目录
设备端资源定义
上一篇文章(https://blog.csdn.net/qq_37600027/article/details/100802337)中,我们定义了一个platform_device设备结构体,其中有一变量resource,他描述了platform的资源数据,资源本身由resource结构体描述。结构体原型如下所示:
struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
结构体重主要的参数为三个,start、end、flags
start:资源的起始值
end:资源的终止值
flags:资源类型
flags | 资源类型 | start | end |
IORESOURCE_IO | IO地址空间 | IO起始地址 | IO终止地址 |
IORESOURCE_MEM | 内存 | 内存起始地址 | 内存终止地址 |
IORESOURCE_IRQ | 中断 | 起始中断号 | 终止中断号 |
IORESOURCE_DMA | DMA内存 | 内存起始地址 | 内存终止地址 |
IORESOURCE_BUS | 总线 |
上篇文章中定义的platform_device如下所示:
#define PIN_BASE 32
#define CHIPSELECT_2 0x30000000
#define PIN_PC11 (PIN_BASE + 0x40 + 11)
#define GPIO_PF9 9
#define CH_SPI 5
#define DATA_FLAG 5
static struct resource globalmem_resoure[] = {
[0] = {
.start = CHIPSELECT_2,
.end = CHIPSELECT_2 + 3,
.flags = IORESOURCE_MEM
},
[1] = {
.start = CHIPSELECT_2 + 0x44,
.end = CHIPSELECT_2 + 0xFF,
.flags = IORESOURCE_MEM
},
[2] = {
.start = PIN_PC11,
.end = PIN_PC11,
.flags = IORESOURCE_IRQ
| IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE,
},
[3] = {
.start = GPIO_PF9,
.end = GPIO_PF9,
.flags = IORESOURCE_IO,
},
};
struct plat_platform {
unsigned long iobase; /* io base address */
unsigned int irq; /* interrupt number */
unsigned int clk; /* UART clock rate */
int flags; /* UPF_* flags */
};
#define PORT(base, int) \
{ \
.iobase = base, \
.irq = int, \
.clk = 1843200, \
.flags = DATA_FLAG, \
}
static struct plat_platform platform_data[] = {
PORT(0x3F8, 4),
PORT(0x2F8, 3),
PORT(0x3E8, 4),
PORT(0x2E8, 3),
{ },
};
static struct platform_device platform_uart_device2 = {
.name = "globalfifo",
.id = -1,
.resource = globalmem_resoure,
.num_resources = ARRAY_SIZE(globalmem_resoure),
.dev = {
.platform_data = platform_data,
}
};
#define PA_IIC1 0xEC20F000
#define IRQ_IIC1 ((5) + 32)
static struct resource i2c_resource[] = {
[0] = {
.start = PA_IIC1,
.end = PA_IIC1 + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_IIC1,
.end = IRQ_IIC1,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device device_i2c1 = {
.name = "s3c2410-i2c",
.id = -1,
.num_resources = ARRAY_SIZE(i2c_resource),
.resource = i2c_resource,
};
#define PA_USBDEV (0x15200140)
#define SZ_USBDEV SZ_1M
#define IRQ_USBD 18
static struct resource usbgadget_resource[] = {
[0] = {
.start = PA_USBDEV,
.end = PA_USBDEV + SZ_USBDEV - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_USBD,
.end = IRQ_USBD,
.flags = IORESOURCE_IRQ,
}
};
struct platform_device device_usbgadget = {
.name = "s3c2410-usbgadget",
.id = -1,
.num_resources = ARRAY_SIZE(usbgadget_resource),
.resource = usbgadget_resource,
};
struct platform_device *globaofifo_device[3] = {
&platform_uart_device2,
&device_i2c1,
&device_usbgadget,
};
EXPORT_SYMBOL(globaofifo_device);
其中globalmem_resoure中定义了三种资源:IORESOURCE_IRQ、IORESOURCE_MEM、IORESOURCE_IO
IORESOURCE_IRQ:中断号是32 + 0x40 + 11
IORESOURCE_MEM:内存起始地址0x30000000为,第一块mem长度为3,第二块长度为0xff-0x44
IORESOURCE_IO:io地址为9
驱动端资源获取
这个是设备端定义的资源,那么我们如何在驱动端获取到这些数据呢
struct resource *res_mem[2];
struct resource *res_irq;
struct resource *res_io;
res_mem[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if(!res_mem[0]){
printk("%s %d \n",__func__,__LINE__);
} else{
printk("%s %d start=0x%x end=0x%x\n",__func__,__LINE__,res_mem[0]->start,res_mem[0]->end);
}
res_mem[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if(!res_mem[1]){
printk("%s %d \n",__func__,__LINE__);
} else{
printk("%s %d start=0x%x end=0x%x\n",__func__,__LINE__,res_mem[1]->start,res_mem[1]->end);
}
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if(!res_irq){
printk("%s %d \n",__func__,__LINE__);
} else{
printk("%s %d start=0x%x end=0x%x\n",__func__,__LINE__,res_irq->start,res_irq->end);
}
res_io = platform_get_resource(pdev, IORESOURCE_IO, 0);
if(!res_io){
printk("%s %d \n",__func__,__LINE__);
} else{
printk("%s %d start=0x%x end=0x%x\n",__func__,__LINE__,res_io->start,res_io->end);
}
驱动端使用函数platform_get_resource来获取资源,函数的原型如下所示:
struct resource *platform_get_resource(struct platform_device *dev,
unsigned int type, unsigned int num)
第一个变量为platform的设备结构体,第二个变量为资源类型,第三个变量为资源对用的编号,比如说,想要获取mem的第一个资源,函数platform_get_resource的最后一个参数为0,想要获取mem的第二个资源,函数platform_get_resource的最后一个参数为1.
res_mem[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0);
res_mem[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1);
设备端数据定义
在设备端我们除了可以定义资源以外,还可以附加一些自定义数据,作为设备的私有数据,数据的类型我们可以自行定义
上述模块中,我们定义了自定义数据为:
struct plat_platform {
unsigned long iobase; /* io base address */
unsigned int irq; /* interrupt number */
unsigned int clk; /* UART clock rate */
int flags; /* UPF_* flags */
};
#define PORT(base, int) \
{ \
.iobase = base, \
.irq = int, \
.clk = 1843200, \
.flags = DATA_FLAG, \
}
static struct plat_platform platform_data[] = {
PORT(0x3F8, 4),
PORT(0x2F8, 3),
PORT(0x3E8, 4),
PORT(0x2E8, 3),
{ },
};
驱动端数据获取
数据段使用函数dev_get_platdata来获取私有数据,函数原型为
static inline void *dev_get_platdata(const struct device *dev)
函数,参数为&pdev->dev,pdev为platform_device的指针
驱动端示例代码如下所示
static struct plat_platform {
unsigned long iobase; /* io base address */
unsigned int irq; /* interrupt number */
unsigned int clk; /* UART clock rate */
int flags; /* UPF_* flags */
};
struct plat_platform *platform_data;
platform_data = dev_get_platdata(&pdev->dev);
if(!platform_data){
printk("%s %d \n",__func__,__LINE__);
} else{
printk("%s %d iobase=0x%x irq=0x%x\n",__func__,__LINE__,platform_data->iobase,platform_data->irq);
printk("%s %d clk=0x%x flags=0x%x\n",__func__,__LINE__,platform_data->clk,platform_data->flags);
}
上一篇:platform总线设备与驱动:https://blog.csdn.net/qq_37600027/article/details/100802337