Linux Platform devices Platform device drivers

Publisher:MysticalSoulLatest update time:2024-07-16 Source: elecfansKeywords:Linux  Platform  devices Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The platform device driver is based on the device bus driver model. It just further encapsulates device into platform_device and device_driver into platform_device_driver. The device bus driver model has been analyzed before. The registration process of device and device_driver and their hierarchical relationship in the sysfs file system will not be analyzed. This article focuses on the new additions to the platform device driver compared to the device bus driver model.


In the abstraction of the Linux device model, there is a class of devices called "Platform Devices", which the kernel describes as follows (Documentation/driver-model/platform.txt):

Platform devices are devices that typically appear as autonomous entities in the system. This includes legacy port-based devices and host bridges to peripheral buses, and most controllers integrated into system-on-chip platforms.  What they usually have in common is direct addressing from a CPU bus.  Rarely, a platform_device will be connected through a segment of some other kind of bus; but its registers will still be directly addressable.

In general, Platform devices include: port-based devices (no longer recommended, and are only retained for compatibility with old devices, legacy); bridge devices connected to physical buses; controllers integrated on the SOC platform; devices connected to other buses (rarely seen), and so on.


These devices have a basic feature: they can be directly addressed through the CPU bus (such as the "registers" commonly seen in embedded systems). Therefore, due to this commonality, the kernel further encapsulates these devices based on the device model (device and device_driver), abstracting the paltform bus, platform device and platform driver, so that driver developers can easily develop drivers for such devices.


It can be said that paltform devices are very important to Linux driver engineers, because most of the device drivers we write are to drive plaftom devices.



platform_bus_type

We know that in the device bus driver model, BUS is like a matchmaker. Through its match function, it matches the device registered in the bus with the driver. Then each different bus has its own match function. Let's take a look at platform_bus_type.

struct bus_type platform_bus_type = {

.name       = "platform",

.dev_attrs  = platform_dev_attrs,

.match      = platform_match,

.uevent     = platform_uevent,

.pm     = &platform_dev_pm_ops,

};

static int platform_match(struct device *dev, struct device_driver *drv)

{

struct platform_device *pdev = to_platform_device(dev);

struct platform_driver *pdrv = to_platform_driver(drv);

/* match against the id table first */

if (pdrv->id_table)

return platform_match_id(pdrv->id_table, pdev) != NULL;

/* fall-back to driver name match */

return (strcmp(pdev->name, drv->name) == 0);

}

If id_table is defined in platform_device_driver, platform_match_id is called for matching


For example:


static struct platform_device_id s3c24xx_driver_ids[] = {

{

.name       = "s3c2410-i2c",

.driver_data    = TYPE_S3C2410,

}, {

.name       = "s3c2440-i2c",

.driver_data    = TYPE_S3C2440,

}, { },

};

struct platform_device s3c_device_i2c0 = {

.name         = "s3c2410-i2c",

#ifdef CONFIG_S3C_DEV_I2C1

.id       = 0,

#else

.id       = -1,

#endif

.num_resources    = ARRAY_SIZE(s3c_i2c_resource),

.resource     = s3c_i2c_resource,

};

static const struct platform_device_id *platform_match_id(struct platform_device_id *id, struct platform_device *pdev)

{

while (id->name[0]) {

if (strcmp(pdev->name, id->name) == 0) {

pdev->id_entry = id;

return id;

}

id++;

}

return NULL;

}

Obviously, the role of platform_match_id is to traverse the entire Id_table array to find whether there is a platform_device->name with the same name. If there is, it returns this Platform_device_id. Using Id_table breaks the limitation of the original device bus driver model that a device can only be paired with one device_driver. Now a platform_device_driver can be paired with multiple platform_devices.


If not, it just compares platform_device_driver->name with platform_device->name. This is why teachers often say when writing platform device drivers, "Register the driver with the kernel. If there is a device with the same name, call the driver->probe function...."




The role of id in pletform_device:


if (pdev->id != -1) /* If it is not -1, number the name */

dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);

else /* -1 is the name directly*/

dev_set_name(&pdev->dev, pdev->name);



platform_device encapsulated from device

struct platform_device {

const char  * name;

you hand;

struct device   dev;

u32     num_resources;

struct resource * resource;

struct platform_device_id   *id_entry;

/* arch specific additions */

struct pdev_archdata    archdata;

};

name, the name of the device. This name will be copied to dev.init_name when the device is registered.

dev, the real device, can find the entire platform_device through container_of and access other members, such as resource mentioned later

num_resources, resource, the resource description of the device, abstracted by the struct resource (include/linux/ioport.h) structure.

In Linux, system resources include I/O, Memory, Register, IRQ, DMA, Bus, etc. Most of these resources are exclusive and do not allow multiple devices to use them at the same time, so the Linux kernel provides some APIs for allocating and managing these resources.

When a device needs to use certain resources, it only needs to use struct resource to organize these resources (such as name, type, start and end address, etc.) and save them in the resource pointer of the device. Then, when probing the device, the device will call the resource management interface to allocate and use these resources. The kernel's resource management logic can determine whether these resources have been used, whether they can be used, etc.

struct resource {

resource_size_t start;

resource_size_t end;

const char *name;

unsigned long flags;

struct resource *parent, *sibling, *child;

};

static struct resource led_resource[] = { // parameters of jz2440, driver not tested

[0] = {

.start = 0x56000010,

.end   = 0x56000010 + 8 - 1,

.flags = IORESOURCE_MEM,

},

[1] = {

.start = 5,

.end   = 5,

.flags = IORESOURCE_IRQ,

},

};

static struct platform_device led_dev = {

.name = "myled", //The device name matches the driver

.id   = -1,

.num_resources = ARRAY_SIZE(led_resource),

.resource = led_resource,

.dev = {

.release = led_release,

//.devt = MKDEV(252, 1),

},

};


platform_device_driver packaged from device_driver

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 (*resume)(struct platform_device *);

struct device_driver driver;

struct platform_device_id *id_table;

};

int platform_driver_register(struct platform_driver *drv)

{

drv->driver.bus = &platform_bus_type;

if (drv->probe)

drv->driver.probe = platform_drv_probe;

if (drv->remove)

drv->driver.remove = platform_drv_remove;

if (drv->shutdown)

drv->driver.shutdown = platform_drv_shutdown;

return driver_register(&drv->driver);

}

The struct platform_driver structure is very similar to the struct device_driver. The platform_drv_probe, platform_drv_remove, and platform_drv_shutdown functions above are just slightly converted to call the probe, remove, and shutdown functions in platform_driver. Let's take a look at an example.

static int platform_drv_probe(struct device *_dev)

{

struct platform_driver *drv = to_platform_driver(_dev->driver);

struct platform_device *dev = to_platform_device(_dev);

return drv->probe(dev);

}


APIs provided by Platform Device

/* include/linux/platform_device.h */

extern int platform_device_register(struct platform_device *);

extern void platform_device_unregister(struct platform_device *);

extern void arch_setup_pdev_archdata(struct platform_device *);

extern struct resource *platform_get_resource(struct platform_device *, unsigned int, unsigned int);

extern int platform_get_irq(struct platform_device *, unsigned int);

extern struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *);

extern int platform_get_irq_byname(struct platform_device *, const char *);

extern int platform_add_devices(struct platform_device **, int);

extern struct platform_device *platform_device_register_full(const struct platform_device_info *pdevinfo);

static inline struct platform_device *platform_device_register_resndata(

struct device *parent, const char *name, int id,

const struct resource *res, unsigned int num,

const void *data, size_t size)

static inline struct platform_device *platform_device_register_simple(

const char *name, int id,

const struct resource *res, unsigned int num)

static inline struct platform_device *platform_device_register_data(

struct device *parent, const char *name, int id,

const void *data, size_t size)

extern struct platform_device *platform_device_alloc(const char *name, int id);

extern int platform_device_add_resources(struct platform_device *pdev,

const struct resource *res,

unsigned int num);

extern int platform_device_add_data(struct platform_device *pdev,

const void *data, size_t size);

extern int platform_device_add(struct platform_device *pdev);

[1] [2]
Keywords:Linux  Platform  devices Reference address:Linux Platform devices Platform device drivers

Previous article:Comprehensive analysis of the spi driver framework, from master driver to device driver
Next article:ALSA sound card 07_Analysis calling process_Study notes

Recommended ReadingLatest update time:2024-11-23 07:32

Simulation and transplantation of MiniGUI based on ARM-Linux
In recent years, with the increasing development of embedded systems and the widespread application of 32-bit embedded processors and graphic display devices, the target products have an increasing demand for GUI (Graphical User Interface). Since embedded systems generally have high real-time requirements, the GUI unde
[Microcontroller]
Simulation and transplantation of MiniGUI based on ARM-Linux
mini2440 u-boot linux kernel boot,Mini2440 uboot,kernel,root file system construction
According to the manual of mini2440, I have learned that the construction process of uboot, kernel and root file system is as follows. The specific details are not considered for the time being, only the entire compilation and burning process is considered. First of all, our host machine must have nfs server and tft
[Microcontroller]
How to develop stc51 microcontroller under Linux
The first time I came into contact with a single-chip microcomputer , I naturally chose the simple 51 single-chip microcomputer. However, my operating system is Linux. It seems easy to get started with 51 under Windows. But it is not very smooth to build a 51 development environment on Linux. So let's talk about how
[Microcontroller]
Design of remote monitoring terminal based on ARM and GPRS
With the development of modern production technology, the requirements for monitoring technology are getting higher and higher, and the forms are becoming more diversified. In unmanned substations, hydrological stations, meteorological stations and other field monitoring or in transportation and other industries, due t
[Microcontroller]
Design of remote monitoring terminal based on ARM and GPRS
Linux Platform devices Platform device drivers
The platform device driver is based on the device bus driver model. It just further encapsulates device into platform_device and device_driver into platform_device_driver. The device bus driver model has been analyzed before. The registration process of device and device_driver and their hierarchical relationship in
[Microcontroller]
4412 Linux delay and time
basic knowledge • The delay function in Linux is very simple, but often used • The operating system and the MCU handle delays in completely different ways. It is impossible to use The for loop wastes system resources. Instead, there is a dedicated interface function • Commonly used delay functions in Linux system prog
[Microcontroller]
OK6410A Development Board (VIII) 8 linux-5.11 OK6410A Detailed analysis of the start_kernel runtime stack
include/asm-generic/vmlinux.lds.h  376 #define INIT_TASK_DATA(align)                                                     377     . = ALIGN(align);                                                             378     __start_init_task = .;                                                        379     init_thread_unio
[Microcontroller]
OK6410A Development Board (VIII) 104 linux-5.11 OK6410A mmap four usage parameters and extensions
Purpose of mmap Shared file mapping One application scenario is that two processes read and write a text file together. For example, you edit and save it with vim, and then view it with the cat command. Private file mapping The most typical application is the use of dynamic link libraries (such as libc.so) by proc
[Microcontroller]
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号