什么是AMBA? ---AMBA是一个片内总线规范。
AMBA 协议是用于连接和管理片上系统 (SoC) 中功能块的开放标准和芯片上互连规范。使用它,可以帮助开发带有大量控制器和外设的多处理器设计。AMBA 通过使用 ACE、AXI、AHB、APB 和 ATB 的规范对 SoC 模块的共同主干进行定义,这有助于设计的重复使用。
看一则新闻:
ARM公司日前宣布推出用于嵌入式系统设计的下一代ARM PrimeCell AMBA 3 AXI Configurable Interconnect(PL301)和AMBA Designer Ecosystem Edition设计自动化工具。
为什么需要amba_device? ---为了复用驱动
单词解释:
peripheral :外围 [部]设备;[周围的,周边的]
内核中专门定义了一类amba_bustype、amba_device、amba_driver。具体定义在内核的/drivers/amba/bus.c中。
按理说AMBA是一种片内总线,对驱动程序员来说是透明的,为什么还要定义一类amba_device/amba_driver呢?
看看内核源码中的解释:
* linux/include/amba/bus.h
*
* This device type deals with ARM PrimeCells and anything else that
* presents a proper CID (0xB105F00D) at the end of the I/O register
* region or that is derived from a PrimeCell.
也就是说amba_device定义的是ARM的PrimeCells提供的片内外设,当然这些外设都使用AMBA总线。这些外设有一个特征,那就是在自己的IO地址空间的尾部存放了一个固定的CID(0xB105F00D),表明这是一个amba_device。
由于ARM众多的合作伙伴都会或多或少的使用ARM提供的片内外设,所以众多厂商的ARM处理器的一些外设可以使用相同的驱动,只有IO地址空间和中断号的区别,寄存器和操作方式都是类似的。为了管理这类驱动,内核中专门建立了amba子系统。CID正是为了向驱动表明这是一个amba_device。但是仅仅表明这是一个amba_device还是不够的,因为amba_device包括了lcd控制器、ssp、中断控制器等多种设备。为了让ambe驱动识别设备的类型,amba_device在自己IO地址空间的尾部还存放了一个四字节的periphid,内核使用它来确认是否可以使用标准的amba驱动。
关于periphid的定义,网上有人做了总结:http://hi.baidu.com/serial_story/blog/item/8af9a216cdd1495af2de327d.html
先说一下ARM对外设的编号采用PLXXX的形式,比如SSP使用PL022的编号。
下面说一下periphid各位的含义:
PartNumber[11:0] 设备编号,比如ssp(PL022)这部分的编号就是0x022.
DesignerID[19:12] 设计厂商编号,如果是ARM设计的对应0x41(ASCII码是‘A’)
Revision[23:20] 版本号,从0开始编号
Configuration[31:24] 配置选项,一般都是0.
amba_driver
linux/include/amba/bus.h
struct amba_id {
unsigned int id;
unsigned int mask;
void *data; //这个成员好像没用到。内核中看不到使用
};
struct amba_driver {
struct device_driver drv;
int (*probe)(struct amba_device *, struct amba_id *);
int (*remove)(struct amba_device *);
void (*shutdown)(struct amba_device *);
int (*suspend)(struct amba_device *, pm_message_t);
int (*resume)(struct amba_device *);
struct amba_id *id_table;
};
unsigned int mask;
void *data; //这个成员好像没用到。内核中看不到使用
};
struct amba_driver {
struct device_driver drv;
int (*probe)(struct amba_device *, struct amba_id *);
int (*remove)(struct amba_device *);
void (*shutdown)(struct amba_device *);
int (*suspend)(struct amba_device *, pm_message_t);
int (*resume)(struct amba_device *);
struct amba_id *id_table;
};
amba_driver的结构体唯一亮点就是一个id_table指针,这个指针指向一个数组,数组中保存了此驱动可以支持的设备列表。
amba_bustype匹配设备和驱动的算法如下:
ret = (dev->periphid & table->mask) == table->id;
接口:
int amba_driver_register(struct amba_driver *);
void amba_driver_unregister(struct amba_driver *);
void amba_driver_unregister(struct amba_driver *);
amba_device
linux/include/amba/bus.h
#define AMBA_NR_IRQS 2
struct amba_device {
struct device dev;
struct resource res;
u64 dma_mask;
unsigned int periphid;
unsigned int irq[AMBA_NR_IRQS];
};
struct amba_device {
struct device dev;
struct resource res;
u64 dma_mask;
unsigned int periphid;
unsigned int irq[AMBA_NR_IRQS];
};
一般要初始化的成员有:
dev.init_name: 设备名,这个是必须的
dev.coherent_dma_mask:一般初始化为~0
dev.platform_data:这个指针指向设备的数据,具体的内容由驱动决定。
res:这个成员一般是设备本身的IO内存空间地址。
dma_mask:一般初始化为~0
irq:可以初始化为 {IRQ_XXX, NO_IRQ},或者都初始化为NO_IRQ
接口:
int amba_device_register(struct amba_device *, struct resource *); //目前第二个参数必须是&iomem_resource
void amba_device_unregister(struct amba_device *);
void amba_device_unregister(struct amba_device *);
static struct clcd_board lpc32xx_clcd_data = {
.name = "Phytec LCD",
.check = clcdfb_check,
.decode = clcdfb_decode,
.disable = clcd_disable,
.enable = clcd_enable,
.setup = lpc32xx_clcd_setup,
.mmap = lpc32xx_clcd_mmap,
.remove = lpc32xx_clcd_remove,
};
static struct amba_device lpc32xx_clcd_device = {
.dev = {
.coherent_dma_mask = ~0,
.init_name = "dev:clcd",
.platform_data = &lpc32xx_clcd_data,
},
.res = {
.start = LPC32XX_LCD_BASE,
.end = (LPC32XX_LCD_BASE + SZ_4K - 1),
.flags = IORESOURCE_MEM,
},
.dma_mask = ~0,
.irq = {IRQ_LPC32XX_LCD, NO_IRQ},
};
.name = "Phytec LCD",
.check = clcdfb_check,
.decode = clcdfb_decode,
.disable = clcd_disable,
.enable = clcd_enable,
.setup = lpc32xx_clcd_setup,
.mmap = lpc32xx_clcd_mmap,
.remove = lpc32xx_clcd_remove,
};
static struct amba_device lpc32xx_clcd_device = {
.dev = {
.coherent_dma_mask = ~0,
.init_name = "dev:clcd",
.platform_data = &lpc32xx_clcd_data,
},
.res = {
.start = LPC32XX_LCD_BASE,
.end = (LPC32XX_LCD_BASE + SZ_4K - 1),
.flags = IORESOURCE_MEM,
},
.dma_mask = ~0,
.irq = {IRQ_LPC32XX_LCD, NO_IRQ},
};
这个是LCD控制器的amba_device定义,注册方式为:
amba_device_register(&lpc32xx_clcd_device, &iomem_resource);
amba在sysfs中的目录
[root@M3250 sys]# ls bus/amba/devices/
dev:clcd@ dev:mmc0@ dev:ssp0@
[root@M3250 sys]# ls bus/amba/drivers
clcd-pl11x/ mmci-pl18x/ ssp-pl022/
[root@M3250 sys]# ls bus/amba/devices/dev\:clcd
bus@ id power/ subsystem@
driver@ irq0 resource uevent
dev:clcd@ dev:mmc0@ dev:ssp0@
[root@M3250 sys]# ls bus/amba/drivers
clcd-pl11x/ mmci-pl18x/ ssp-pl022/
[root@M3250 sys]# ls bus/amba/devices/dev\:clcd
bus@ id power/ subsystem@
driver@ irq0 resource uevent
[root@M3250 sys]# cat bus/amba/devices/dev\:clcd/id #periphid
00141111
[root@M3250 sys]# cat bus/amba/devices/dev\:clcd/irq0
14
[root@M3250 sys]# cat bus/amba/devices/dev\:clcd/uevent
DRIVER=clcd-pl11x
PHYSDEVBUS=amba
PHYSDEVDRIVER=clcd-pl11x
AMBA_ID=00141111
[root@M3250 sys]# cat bus/amba/devices/dev\:clcd/resource
0000000031040000 0000000031040fff 0000000000000200 #start end size
============================================
作者:yuanlulu
http://blog.csdn.net/yuanlulu
版权没有,但是转载请保留此段声明
作者:yuanlulu
http://blog.csdn.net/yuanlulu
版权没有,但是转载请保留此段声明
============================================