Platform bus Architecture (RPM) driven by Linux

Source: Internet
Author: User
Tags goto

Platform is a virtual address bus, which is primarily used to describe on-chip resources on the SOC compared to PCI, USB.    such as the integrated controller on the s3c2410 (LCD, Watchdog, RTC, etc.), the resources described by platform have one thing in common: the direct access on the CPU bus. The platform device is divided into a name (used in the driver bindings) and a series of resources such as address and interrupt request number (IRQ).
struct Platform_device {//Include/linux/platform_device.h
const char * name;
int id;
struct device dev;
U32 num_resources;
struct resource * resource;
};
***************************************************************************
/*
* Mainly used to define the hardware resources (such as address space, interrupt number, etc.) that the specific device occupies.
*/
struct Resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
***************************************************************************
The development steps of the platform bus drive are:
1. Equipment
Device registration, the body that needs to be implemented is: Platform_device.
1) Initialize the resource structure variable
2) Initialize the PLATFORM_DEVICE structure variable
3) Register the device with the system: Platform_device_register. (above three steps, must be completed before the device driver is loaded, so, under the at91rm9200 kernel, the three steps are placed in the ARCH/ARM/MACH-AT91/BOARD-DK.C)
2. Drive
In the driver registration, the structure that needs to be implemented is: Platform_driver.
struct Platform_driver {//Include/linux/platform_device.h
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 Pm_ext_ops *pm;
struct Device_driver driver;
};
In the driver initialization function, the Platform_driver_register () registration platform_driver is called.
It is important to note that the value of the name variable in Platform_driver and Platform_device must be the same. This in
When Platform_driver_register () is registered, the value of the name variable in the currently registered Platform_driver is compared to the value of the name variable in all registered Platform_device, only if the same name is found Platform_device to register successfully. When the registration succeeds, the PLATFORM_DRIVER structure element probe function pointer is called. In rtc-ds1302.c, the driver performs first:
********************************************************************
static int __init ds1302_rtc_init (void)
{
Return Platform_driver_register (&ds1302_platform_driver);
}
********************************************************************
Then, enter: Drivers/base/platform.c:platform_driver_register ()
********************************************************************
/**
* Platform_driver_register
* @drv: Platform driver structure
*/
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;
if (drv->suspend)
Drv->driver.suspend = Platform_drv_suspend;
if (Drv->resume)
Drv->driver.resume = Platform_drv_resume;
if (DRV->PM)
DRV->DRIVER.PM = &drv->pm->base;
Return Driver_register (&drv->driver);
}
Here, several function pointers in the drv->driver struct are initialized. Finally, call Driver_register to register the driver member.
The types of Drv->driver are:
struct Platform_driver {//Include/linux/platform_device.h
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 Pm_ext_ops *pm;
struct Device_driver driver; Drv->driver
};struct Device_driver {//Include/linux/device.h
const char *name;
struct Bus_type *bus; struct module *owner;
const char *mod_name; /* Used for built-in modules */INT (*probe) (struct device *dev);
Int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
Int (*suspend) (struct device *dev, pm_message_t State);
Int (*resume) (struct device *dev);
struct Attribute_group **groups;    struct Pm_ops *pm; struct Driver_private *p;
};
********************************************************************
Then, enter: Drivers/base/driver.c:driver_register
********************************************************************
/**
* Driver_register-register driver with bus
* @drv: Driver to register
*
* We pass off most of the work to the Bus_add_driver () call,
* Since most of the things we had to does deal with the bus
* Structures.
*/
int Driver_register (struct device_driver *drv)
{
int ret;
struct Device_driver *other; if ((drv->bus->probe && drv->probe) | |
(Drv->bus->remove && drv->remove) | |
(Drv->bus->shutdown && Drv->shutdown))
PRINTK (kern_warning "Driver '%s ' needs updating-please use"
"Bus_type methods\n", drv->name); other = Driver_find (Drv->name, Drv->bus);
if (other) {
Put_driver (other);
PRINTK (kern_err "Error:driver '%s ' is already registered,"
"Aborting...\n
", Drv->name);
Return-eexist;
} ret = Bus_add_driver (DRV); Call: Bus_add_driver (), executed here, Drv->bus points to the global variable Platform_bus_type.
if (ret)
return ret;
ret = driver_add_groups (DRV, drv->groups);
if (ret)
Bus_remove_driver (DRV);
return ret;
}
********************************************************************
Then, enter: Drivers/base/bus.c:bus_add_driver
********************************************************************
/**
* Bus_add_driver-add A driver to the bus.
* @drv: Driver.
*/
int bus_add_driver (struct device_driver *drv)
{
struct Bus_type *bus;
struct Driver_private *priv;
int error = 0; Bus = Bus_get (Drv->bus);
if (!bus)
Return-einval;    Pr_debug ("Bus: '%s ': Add driver%s\n", Bus->name, Drv->name); Priv = Kzalloc (sizeof (*PRIV), Gfp_kernel);
if (!priv) {
Error =-enomem;
Goto Out_put_bus;
}
Klist_init (&priv->klist_devices, NULL, NULL);
Priv->driver = DRV;
Drv->p = Priv;
Priv->kobj.kset = bus->p->drivers_kset;
Error = Kobject_init_and_add (&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (Error)
Goto Out_unregister; if (drv->bus->p->drivers_autoprobe) {
Error = Driver_attach (DRV);
if (Error)
Goto Out_unregister;
}
Klist_add_tail (&priv->knode_bus, &bus->p->klist_drivers);
Module_add_driver (Drv->owner, DRV); Error = Driver_create_file (DRV, &driver_attr_uevent);
if (Error) {
PRINTK (kern_err "%s:uevent attr (%s) failed\n",
__func__, Drv->name);
}
Error = Driver_add_attrs (bus, DRV);
if (Error) {
/* How the hell does we get out of this pickle? Give up */
PRINTK (Kern_err "%s:driver_add_attrs (%s) failed\n",
__func__, Drv->name);
}
Error = Add_bind_files (DRV);
if (Error) {
/* Ditto */
PRINTK (Kern_err "%s:add_bind_files (%s) failed\n",
__func__, Drv->name);
} kobject_uevent (&priv->kobj, Kobj_add);
return error;
Out_unregister:
Kobject_put (&priv->kobj);
Out_put_bus:
Bus_put (bus);
return error;

Platform bus Architecture (RPM) driven by Linux

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.