君正X系列开发5---GPIO在用户空间使用&platform_device驱动&g
可以通过导出gpio sys节点到用户空间,在用户空间操作。
内核的gpio驱动基于gpio子系统的实现,所以其他驱动程序可以通过内核提供的
libgpio
接口很方面的控制,例如,gpio_request_one,gpio_get_value,gpio_set_value
如果用gpio的方式控制led,需要改哪些呢?
驱动中选中gpioled,板级里找到LED_GPIO的宏,改成您自己用的gpio
X1000 的gpio 控制器有五组,A,B,C,D,Z。
支持输入输出和设备复用功能。内核的gpio 驱动程序是基于gpio 子系统架构编写的。应用
程序可以使用gpio_demo 进行测试。内核驱动可以在内核空间使用,也可以通过导出gpio sys 节点到用户空间,在用户空间进行操作
内核空间
文件介绍
gpio 一般在进行开发板设计的时候就已经固定好了,有的gpio 只能作为设备复用功能管脚,有的gpio 作为普通的输入输出和中断检测功能,对于固定设备复用的功能管脚在以下文件中定义:
arch/mips/xburst/soc-x1000/include/mach/platform.h
在arch/mips/xburst/soc-x1000/common/platform.c 会根据驱动配置,选中相应的设备功能管脚。
内核的gpio 驱动基于gpio 子系统实现,所以其它驱动程序可以通过内核提供的libgpio 接口,很方便的进行gpio 控制
例如gpio_request_one, gpio_get_value,gpio_set_value 等。
gpio 驱动文件所在位置:
arch/mips/xburst/soc-x1000/common/gpio.c
编译配置
内核通过配置CONFIG_GPIOLIB 选项可以使用gpio 功能,默认必须选上。
CONFIG_GPIOLIB:
Symbol: GPIOLIB [=y]
Type : boolean
Prompt: GPIO Support
Location:
-> Device Drivers
Defined at drivers/gpio/Kconfig:38
Depends on: ARCH_WANT_OPTIONAL_GPIOLIB [=n] || ARCH_REQUIRE_GPIOLIB [=y]
通过配置CONFIG_GPIO_SYSFS 选项,可以将gpio 导出到用户节点/sys/class/gpio 下,对该节点下的文件操作,可以控制gpio 输入输出。
Symbol: GPIO_SYSFS [=y]
Type : boolean
Prompt: /sys/class/gpio/... (sysfs interface)
Location:
-> Device Drivers
-> GPIO Support (GPIOLIB [=y])
Defined at drivers/gpio/Kconfig:69
Depends on: GPIOLIB [=y] && SYSFS [=y]
用户空间
在内核导出gpio 节点的前提下,可以操作/sys/class/gpio 节点,控制gpio 输入输出。
/sys/class/gpio/"export" ... 用户空间可以通过写其编号到这个文件,要求内核导出一个GPIO 的控制到用户空间。
例如: 如果内核代码没有申请GPIO #19,"echo 19 > export"
将会为GPIO #19 创建一个"gpio19" 节点。
"unexport" ... 导出到用户空间的逆操作。
例如: "echo 19 > unexport" 将会移除使用"export"文件导出的"gpio19" 节点。
GPIO 信号的路径类似/sys/class/gpio/gpio42/ (对于GPIO #42 来说),并有如下的读/写属性:
/sys/class/gpio/gpioN/
"direction" ... 读取得到"in" 或"out"。这个值通常运行写入。
写入"out" 时,其引脚的默认输出为低电平。为了确保无故障运行,"low" 或"high" 的电平值应该写入GPIO 的配置,作为初始输出值。
注意:如果内核不支持改变GPIO 的方向,或者在导出时内核代码没有明确允许用户空间可以重新配置GPIO 方向,那么这个属性将不存在。
"value" ... 读取得到0 (低电平) 或1 (高电平)。如果GPIO 配置为输出,这个值允许写操作。任何非零值都以高电平看待。
如果引脚可以配置为中断信号,且如果已经配置了产生中断的模式(见"edge"的描述),你可以对这个文件使用轮询操作(poll(2)),且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2)),请在events 中设置POLLPRI 和POLLERR。如果你使用轮询操作
(select(2)),请在exceptfds 设置你期望的文件描述符。在轮询操作(poll(2))返回之后,既可以通过lseek(2)操作读取sysfs 文件的开始部分,也可以关闭这个文件并重新打开它来读取数据。
"edge" ... 读取得到“none”、“rising”、“falling”或者“both”。
将这些字符串写入这个文件可以选择沿触发模式,会使得轮询操作(select(2))在"value"文件中返回。
这个文件仅有在这个引脚可以配置为可产生中断输入引脚时,才存在。
"active_low" ... 读取得到0 (假) 或1 (真)。写入任何非零值可以翻转这个属性的(读写)值。已存在或之后通过"edge"属性设置了"rising"
gpio操作 查看Documentation/gpio.txt文档
GPIO 模块
X1000的gpio 控制器有五组,A,B,C,D,Z。
支持输入输出和设备复用功能。内核的gpio 驱动程序是基于gpio 子系统架构编写的。应用程序可以使用gpio_demo 进行测试。内核驱动可以在内核空间使用,也可以通过导gpiosys 节点到用户空间,在用户空间进行操作。
内核空间
对于固定设备复用的功能管脚在以下文件中定义:
arch/mips/xburst/soc-x1000/include/mach/platform.h
在arch/mips/xburst/soc-x1000/common/platform.c 会根据驱动配置,选中相应的设备功能管脚。Platform.h中
/*
* Copyright (C) 2010 Ingenic Semiconductor Inc.
*
* Inthis file, here are some macro/device/function to
* to help the board special file to organizeresources
* on the chip.
*/
#ifndef __SOC_x1000_H__
#define __SOC_x1000_H__
/* devio define list */
/****************************************************************************************/
#define I2S_PORTB \
{.name = "i2s", .port = GPIO_PORT_B, .func =GPIO_FUNC_1, .pins = 0x1f, }
/****************************************************************************************/
#define UART0_PORTC \
{.name = "uart0", .port = GPIO_PORT_C, .func =GPIO_FUNC_0, .pins = 0x0f << 10, }
#define UART1_PORTA \
{.name = "uart1-pa", .port = GPIO_PORT_A, .func =GPIO_FUNC_2, .pins = 0x3 << 4, }
#ifndef CONFIG_PRODUCT_X1000_BEETHOVEN
#define UART1_PORTD
{.name = "uart1-pd", .port = GPIO_PORT_D, .func =GPIO_FUNC_1, .pins = 0xf << 2, }
#else
#define UART1_PORTD \
{ .name = "uart1-pd", .port =GPIO_PORT_D, .func = GPIO_FUNC_1, .pins = 0x3 << 2, }
#endif
#define UART2_PORTA \
{.name = "uart2-pa", .port = GPIO_PORT_A, .func =GPIO_FUNC_2, .pins = 0x3 << 2, }
#define UART2_PORTD \
{.name = "uart2-pd", .port = GPIO_PORT_D, .func =GPIO_FUNC_0, .pins = 0x3 << 4 }
#define UART2_PORTC \
{.name = "uart2-pc", .port = GPIO_PORT_C, .func =GPIO_FUNC_1, .pins = 0x1 << 31 }
/****************************************************************************************/
/* JZ SoC on Chip devices list*/
extern struct platform_device jz_codec_device;
extern struct platform_device jz_fb_device;
extern struct platform_device jz_uart0_device;
extern struct platform_device jz_uart1_device;
extern struct platform_device jz_uart2_device;
int jz_device_register(structplatform_device *pdev,void *pdata);
#endif
http://blog.csdn.net/ghostyu/article/details/6908805
在kernel/include/linux/platform.h中定义结构体
struct platform_device {
const char *name;
int id;
bool id_auto;
struct device dev;
u32 num_resources;
struct resource *resource;
const struct platform_device_id *id_entry;
/* MFD cell pointer */
struct mfd_cell *mfd_cell;
/* arch specific additions */
struct pdev_archdata archdata;
};
函数extern intplatform_device_register(struct platform_device *);在文件kernel/drivers/base/platform.c中
/**
* platform_device_register - add aplatform-level device
* @pdev: platform device we're adding
*/
int platform_device_register(structplatform_device *pdev)
{
device_initialize(&pdev->dev);
arch_setup_pdev_archdata(pdev);
return platform_device_add(pdev);
}
EXPORT_SYMBOL_GPL(platform_device_register);
文件arch/mips/xburst/soc-x1000/common/platform.c根据配置选项选中相应的设备功能引脚
#ifdef CONFIG_SERIAL_JZ47XX_UART2 //如果定义该选项
//在该板级配置文档中kernel/arch/mips/configs/halley2_nor_v10_linux_defconfig
static struct resource jz_uart2_resources[] = {
[0] = {
.start = UART2_IOBASE,//基地址arch/mips/xburst/soc-x1000/include/soc
//#defineUART0_IOBASE 0x10030000
.end = UART2_IOBASE + 0x1000 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_UART2,
.end = IRQ_UART2,
.flags = IORESOURCE_IRQ,
},
#ifdef CONFIG_SERIAL_JZ47XX_UART2_DMA
[2] = {
.start = JZDMA_REQ_UART2,
.flags = IORESOURCE_DMA,
},
#endif
};
struct platform_device jz_uart2_device = {
.name = "jz-uart",
.id = 2,
.num_resources =ARRAY_SIZE(jz_uart2_resources),
.resource = jz_uart2_resources,
};
#endif
platform_device和platform_driver(一)
首先介绍一下注册一个驱动的步骤:
1、定义一个platform_driver结构
2、初始化这个结构,指定其probe、remove等函数,并初始化其中的driver变量
3、实现其probe、remove等函数
看platform_driver结构,定义于include/Linux/platform_device.h文件中:
struct platform_driver {
int (*probe)(structplatform_device *);
int (*remove)(structplatform_device *);
void (*shutdown)(structplatform_device *);
int (*suspend)(structplatform_device *, pm_message_t state);
int (*resume)(structplatform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
- 分享
- 举报
-
浏览量:2298次2020-07-28 11:05:08
-
浏览量:2530次2020-07-28 10:56:05
-
浏览量:815次2023-11-15 11:24:03
-
浏览量:2712次2020-07-28 10:58:45
-
浏览量:2389次2020-07-29 18:20:36
-
浏览量:1670次2022-01-07 09:00:13
-
浏览量:512次2024-02-21 17:08:25
-
浏览量:2090次2022-02-19 09:00:28
-
浏览量:2184次2021-12-30 13:59:29
-
浏览量:2350次2022-02-22 09:00:25
-
浏览量:4431次2020-11-14 14:33:28
-
浏览量:3522次2022-03-23 11:50:53
-
浏览量:1044次2023-11-29 12:31:57
-
浏览量:2068次2022-03-02 09:00:12
-
浏览量:4051次2022-03-11 09:00:18
-
浏览量:659次2023-12-11 16:42:16
-
浏览量:1990次2024-01-15 16:17:45
-
浏览量:6542次2020-08-10 19:44:10
-
浏览量:3330次2022-08-16 19:28:15
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
夜墨11111
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明