基于高通MSM 8x60的I2C驱动终极讲解(1)
2014-01-16 19:48
363 查看
网上的I2C驱动讲解已经很多啦,我不想画蛇添足,我想写一个完整的I2C驱动,包括系统启动,总线注册,驱动注册,设备注册,里面会贯穿Linux设备驱动模型,platform机制等等,基于高通MSM 8x60,I2C控制器为qup,下面开始进入正题:
首先是平台设备的注册:源码位置:(msm/arch/arm/mach-msm/devices-msm8x60.c)
首先说下平台设备,因为Linux所有的设备都是通过总线控制器连接到CPU的,但是还有一些设备不是通过总线控制器连接到CPU,所以就有了platform总线虚拟总线,把那些不是真正通过总线控制器相连的设备,比如:SOC的片内设备,片内控制器,这些都归为平台设备.把这些平台设备通过虚拟总线连接到cpu上,以便维护Linux设备模型中的,总线,设备,驱动之间的关系。
首先注册BSP的平台设备驱动,其中I2C控制器的平台设备如下:
先看下高通的8x60,靠,有6个控制器,所有接下来的事情就是淡定。
下面的是6个控制器在I2C控制器的ID编号
#define MSM_GSBI3_QUP_I2C_BUS_ID 0
#define MSM_GSBI4_QUP_I2C_BUS_ID 1
#define MSM_GSBI9_QUP_I2C_BUS_ID 2
#define MSM_GSBI8_QUP_I2C_BUS_ID 3
#define MSM_GSBI7_QUP_I2C_BUS_ID 4
#define MSM_GSBI12_QUP_I2C_BUS_ID 5
下面是六个控制器所用到的资源
static struct resource gsbi3_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI3_QUP_PHYS,
.end = MSM_GSBI3_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI3_PHYS,
.end = MSM_GSBI3_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI3_QUP_IRQ,
.end = GSBI3_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi4_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI4_QUP_PHYS,
.end = MSM_GSBI4_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI4_PHYS,
.end = MSM_GSBI4_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI4_QUP_IRQ,
.end = GSBI4_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi7_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI7_QUP_PHYS,
.end = MSM_GSBI7_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI7_PHYS,
.end = MSM_GSBI7_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI7_QUP_IRQ,
.end = GSBI7_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi8_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI8_QUP_PHYS,
.end = MSM_GSBI8_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI8_PHYS,
.end = MSM_GSBI8_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI8_QUP_IRQ,
.end = GSBI8_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi9_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI9_QUP_PHYS,
.end = MSM_GSBI9_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI9_PHYS,
.end = MSM_GSBI9_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI9_QUP_IRQ,
.end = GSBI9_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi12_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI12_QUP_PHYS,
.end = MSM_GSBI12_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI12_PHYS,
.end = MSM_GSBI12_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI12_QUP_IRQ,
.end = GSBI12_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
下面是为6个I2C控制器所注册平台设备驱动需要的结构体
/* Use GSBI3 QUP for /dev/i2c-0 */
struct platform_device msm_gsbi3_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI3_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi3_qup_i2c_resources),
.resource = gsbi3_qup_i2c_resources,
};
/* Use GSBI4 QUP for /dev/i2c-1 */
struct platform_device msm_gsbi4_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI4_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi4_qup_i2c_resources),
.resource = gsbi4_qup_i2c_resources,
};
/* Use GSBI8 QUP for /dev/i2c-3 */
struct platform_device msm_gsbi8_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI8_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi8_qup_i2c_resources),
.resource = gsbi8_qup_i2c_resources,
};
/* Use GSBI9 QUP for /dev/i2c-2 */
struct platform_device msm_gsbi9_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI9_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi9_qup_i2c_resources),
.resource = gsbi9_qup_i2c_resources,
};
/* Use GSBI7 QUP for /dev/i2c-4 (Marimba) */
struct platform_device msm_gsbi7_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI7_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi7_qup_i2c_resources),
.resource = gsbi7_qup_i2c_resources,
};
/* Use GSBI12 QUP for /dev/i2c-5 (Sensors) */
struct platform_device msm_gsbi12_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI12_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi12_qup_i2c_resources),
.resource = gsbi12_qup_i2c_resources,
};
注意该6个平台设备结构体的name都是"qup_i2c",下面这些平台设备将在BSP资源注册的时候给添加到系统。
首先是平台设备的注册:源码位置:(msm/arch/arm/mach-msm/devices-msm8x60.c)
首先说下平台设备,因为Linux所有的设备都是通过总线控制器连接到CPU的,但是还有一些设备不是通过总线控制器连接到CPU,所以就有了platform总线虚拟总线,把那些不是真正通过总线控制器相连的设备,比如:SOC的片内设备,片内控制器,这些都归为平台设备.把这些平台设备通过虚拟总线连接到cpu上,以便维护Linux设备模型中的,总线,设备,驱动之间的关系。
首先注册BSP的平台设备驱动,其中I2C控制器的平台设备如下:
先看下高通的8x60,靠,有6个控制器,所有接下来的事情就是淡定。
下面的是6个控制器在I2C控制器的ID编号
#define MSM_GSBI3_QUP_I2C_BUS_ID 0
#define MSM_GSBI4_QUP_I2C_BUS_ID 1
#define MSM_GSBI9_QUP_I2C_BUS_ID 2
#define MSM_GSBI8_QUP_I2C_BUS_ID 3
#define MSM_GSBI7_QUP_I2C_BUS_ID 4
#define MSM_GSBI12_QUP_I2C_BUS_ID 5
下面是六个控制器所用到的资源
static struct resource gsbi3_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI3_QUP_PHYS,
.end = MSM_GSBI3_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI3_PHYS,
.end = MSM_GSBI3_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI3_QUP_IRQ,
.end = GSBI3_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi4_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI4_QUP_PHYS,
.end = MSM_GSBI4_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI4_PHYS,
.end = MSM_GSBI4_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI4_QUP_IRQ,
.end = GSBI4_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi7_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI7_QUP_PHYS,
.end = MSM_GSBI7_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI7_PHYS,
.end = MSM_GSBI7_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI7_QUP_IRQ,
.end = GSBI7_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi8_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI8_QUP_PHYS,
.end = MSM_GSBI8_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI8_PHYS,
.end = MSM_GSBI8_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI8_QUP_IRQ,
.end = GSBI8_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi9_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI9_QUP_PHYS,
.end = MSM_GSBI9_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI9_PHYS,
.end = MSM_GSBI9_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI9_QUP_IRQ,
.end = GSBI9_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct resource gsbi12_qup_i2c_resources[] = {
{
.name = "qup_phys_addr",
.start = MSM_GSBI12_QUP_PHYS,
.end = MSM_GSBI12_QUP_PHYS + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "gsbi_qup_i2c_addr",
.start = MSM_GSBI12_PHYS,
.end = MSM_GSBI12_PHYS + 4 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "qup_err_intr",
.start = GSBI12_QUP_IRQ,
.end = GSBI12_QUP_IRQ,
.flags = IORESOURCE_IRQ,
},
};
下面是为6个I2C控制器所注册平台设备驱动需要的结构体
/* Use GSBI3 QUP for /dev/i2c-0 */
struct platform_device msm_gsbi3_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI3_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi3_qup_i2c_resources),
.resource = gsbi3_qup_i2c_resources,
};
/* Use GSBI4 QUP for /dev/i2c-1 */
struct platform_device msm_gsbi4_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI4_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi4_qup_i2c_resources),
.resource = gsbi4_qup_i2c_resources,
};
/* Use GSBI8 QUP for /dev/i2c-3 */
struct platform_device msm_gsbi8_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI8_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi8_qup_i2c_resources),
.resource = gsbi8_qup_i2c_resources,
};
/* Use GSBI9 QUP for /dev/i2c-2 */
struct platform_device msm_gsbi9_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI9_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi9_qup_i2c_resources),
.resource = gsbi9_qup_i2c_resources,
};
/* Use GSBI7 QUP for /dev/i2c-4 (Marimba) */
struct platform_device msm_gsbi7_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI7_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi7_qup_i2c_resources),
.resource = gsbi7_qup_i2c_resources,
};
/* Use GSBI12 QUP for /dev/i2c-5 (Sensors) */
struct platform_device msm_gsbi12_qup_i2c_device = {
.name = "qup_i2c",
.id = MSM_GSBI12_QUP_I2C_BUS_ID,
.num_resources = ARRAY_SIZE(gsbi12_qup_i2c_resources),
.resource = gsbi12_qup_i2c_resources,
};
注意该6个平台设备结构体的name都是"qup_i2c",下面这些平台设备将在BSP资源注册的时候给添加到系统。
相关文章推荐
- Bourbaki集合论(3)引论
- MFC 动态曲线 支持缩放 显示图例(CStatic派生类)(续) .
- 进制转换
- 将Linux下的Android签名对pk8和pem转换为Eclipse下的签名(keystore)
- Bourbaki集合论(2)本书的写作方式
- 用Properties补充hibernate.cfg.xml配置
- MFC 动态曲线 支持缩放 显示图例(CStatic派生类) .
- 好友圈
- Bourbaki集合论(1)译者序与作者简介
- 用sql合并列,两句话合为一句
- 传说中的数据结构
- windows消息处理(强烈推荐,收藏)
- MAC OSX上搭建Android开发环境
- 结构体
- poj 2479 Maximum sum
- vim 编码方式的设置
- 希腊人11
- magento性能优化系列一:.htaccess调整及其他
- uva 10549 Russian Dolls (DP)
- CodeSmith 使用教程(17) Merge策略