Apr 11, 2008

Linux Driver - Platform Device

platform-driver


Driver裡面先定義出platform-driver的名稱

這個名稱是s3c2410-ohci

static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe          = ohci_hcd_s3c2410_drv_probe,
.remove         = ohci_hcd_s3c2410_drv_remove,
.shutdown       = usb_hcd_platform_shutdown,
/*.suspend      = ohci_hcd_s3c2410_drv_suspend, */
/*.resume       = ohci_hcd_s3c2410_drv_resume, */
.driver         = {
.owner  = THIS_MODULE,
.name   = "s3c2410-ohci",
},
};

----

platform_driver的資料結構:

[include/linux/platform_device.h]

struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};

resource


[arch/arm/plat-s3c24xx/devs.c"]
/* USB Host Controller */

static struct resource s3c_usb_resource[] = {
[0] = {
.start = S3C24XX_PA_USBHOST,
.end   = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_USBH,
.end   = IRQ_USBH,
.flags = IORESOURCE_IRQ,
}
};

platform-device (單一)


platporm裡要註冊device

使用的name對應到欲使用的driver

還有resource則是對應到上面

[arch/arm/plat-s3c24xx/devs.c"]
struct platform_device s3c_device_usb = {
.name             = "s3c2410-ohci",
.id               = -1,
.num_resources    = ARRAY_SIZE(s3c_usb_resource),
.resource         = s3c_usb_resource,
.dev              = {
.dma_mask = &s3c_device_usb_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};

EXPORT_SYMBOL(s3c_device_usb)

----

platform_device的資料結構:

[include/linux/platform_device.h]

struct platform_device {
const char      * name;
int             id;
struct device dev;
u32             num_resources;
struct resource * resource;
};

----

device的資料結構:

[include/linux/device.h]

struct device {
struct klist            klist_children;
struct klist_node       knode_parent;           /* node in sibling list */
struct klist_node       knode_driver;
struct klist_node       knode_bus;
struct device           *parent;

struct kobject kobj;
char    bus_id[BUS_ID_SIZE];    /* position on parent bus */
struct device_type      *type;
unsigned                is_registered:1;
unsigned                uevent_suppress:1;

struct semaphore        sem;    /* semaphore to synchronize calls to
* its driver.
*/

struct bus_type * bus;          /* type of bus device is on */
struct device_driver *driver;   /* which driver has allocated this
device */
void            *driver_data;   /* data private to the driver */
void            *platform_data; /* Platform specific data, device
core doesn't touch it */
struct dev_pm_info      power;

#ifdef CONFIG_NUMA
int             numa_node;      /* NUMA node this device is close to */
#endif
u64             *dma_mask;      /* dma mask (if dma'able device) */
u64             coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
not all hardware supports
64 bit addresses for consistent
allocations such descriptors. */

struct list_head        dma_pools;      /* dma pools (if dma'ble) */

struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
/* arch specific additions */
struct dev_archdata     archdata;

spinlock_t              devres_lock;
struct list_head        devres_head;

/* class_device migration path */
struct list_head        node;
struct class            *class;
dev_t                   devt;           /* dev_t, creates the sysfs "dev" */
struct attribute_group  **groups;       /* optional groups */

void    (*release)(struct device * dev);
};

platform-device (全部)


最後把整個platform特有的device放在devices[]裡面

[arch/arm/mach-s3c2440/mach-smdk2440.c]

static struct platform_device *smdk2440_devices[] __initdata = {
&s3c_device_usb,
&s3c_device_lcd,
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
};

machine init


在machine init的時候,把devices加進platform

[arch/arm/mach-s3c2440/mach-smdk2440.c]

static void __init smdk2440_machine_init(void)
{
s3c24xx_fb_set_platdata(&smdk2440_fb_info);

platform_add_devices(smdk2440_devices, ARRAY_SIZE(smdk2440_devices));

printk("smdk2440 machine init\n");
smdk_machine_init();
}

參考資料


帥哥安的 linux kernel 2.6.24.3 platform device driver

2.6.24 Kernel Document :
driver-model/Platform.txt

driver-model/Driver.txt

0 comments:

Post a Comment