drivers\base\platform.c

 

小结:

 

1、通过文件名可以看出,这个文件是和平台有关的函数

2、声明了结构体struct       platform_object,作为platform_device平台设备的载体

 

 

 

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

函数列表:

 

@@@@@ 平台资源的操作模块

struct resource       *platform_get_resource(struct platform_device *dev, unsigned int type,

                    unsigned int num)

获取平台资源,根据资源类型和索引号,获取指定平台设备的资源

 

int   platform_get_irq(struct platform_device *dev,    unsigned int num)

获取平台设备的中断资源,实际操作是以IORESOURCE_IRQ为资源类型获取资源

 

struct resource       *platform_get_resource_byname(struct platform_device *dev, unsigned int type, char *name)

根据平台设备的设备名获取指定类型的资源

 

int   platform_get_irq_byname(struct platform_device *dev, char *name)

根据设备名获取平台设备的中断资源,同platform_get_irq操作

 

@@@@@     平台设备的操作模块

int   platform_add_devices(struct platform_device     **devs,   int num)

添加一组平台设备,**devs为平台设备数组,核心操作是platform_device_register

 

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

申请平台设备platform_object,并初始化其平台设备成员,最后返回平台设备

 

int   platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num)

将资源res添加到平台设备pdev中

 

int   platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)

将平台数据data添加到平台设备pdev中(pdev->dev.platform_data)

 

int   platform_device_add(struct platform_device *pdev)

//平台设备添加,主要操作如下:

//1、设置设备的父设备(父设备不存在则指定到平台总线上)

//2、设置平台总线的操作函数

//3、设置设备总线的ID

//4、检查资源的设置,如果没设置则设置默认值

//5、调用core.c的device_add函数添加设备

 

void       platform_device_del(struct platform_device *pdev)

平台设备的删除,先device_del删除设备,然后释放资源

由于添加资源的时候只有MEM和IO型的资源是加进资源树中的,所以这里只释放这两种类型的资源

 

int   platform_device_register(struct platform_device * pdev)

平台设备的注册,先执行core.c文件中的device_initialize初始化设备,然后platform_device_add

 

void       platform_device_unregister(struct platform_device * pdev)

平台设备的反注册,实际操作是platform_device_del删除设备,然后释放(put)设备引用

 

struct platform_device   *platform_device_register_simple(char *name, int id,

                                                 struct resource *res, unsigned int num)

//创建并注册一个平台设备,并返回新注册的设备,具体操作如下:

//1、申请一个新的平台设备并初始化

//2、添加资源到平台设备中

//3、调用platform_device_add函数添加平台设备

 

@@@@@     平台的驱动操作模块

int   platform_driver_register(struct platform_driver *drv)

平台驱动的注册,具体操作是将驱动的总线设置为平台总线,关联驱动的函数,最后调用driver.c中的driver_register函数对驱动进行注册

这里要关注一下平台驱动函数的调用,实际就是直接调用drv上对应的函数,所以在关联函数的时候要先判断drv->probe是否指定

 

void       platform_driver_unregister(struct platform_driver *drv)

平台驱动的反注册,直接调用驱动的反注册

 

int __init_or_module    platform_driver_probe(struct platform_driver *drv,

              int (*probe)(struct platform_device *))

用指定的probe探测函数指定平台驱动

 

@@@@@

int   __init     platform_bus_init(void)

平台总线的初始化,系统初始化的时候自动调用,具体操作是先device_register注册平台设备platform_bus,然后在注册总线platform_bus_type

 

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//根据驱动获取平台驱动结构体

#define   to_platform_driver(drv)        (container_of((drv), struct platform_driver, driver))

//platform_driver结构体定义的是一些函数,和设备驱动driver

 

//声明平台总线

struct device   platform_bus = {

       .bus_id           = "platform",

};

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//获取平台设备的资源

struct resource       *platform_get_resource(

       struct platform_device   *dev,              //平台设备

       unsigned int                 type,                     //资源类型

       unsigned int                 num)              //资源索引

{

       int i;

 

       //根据指定的资源类型和资源索引,返回资源

       for (i = 0; i < dev->num_resources; i++) {

              struct resource       *r = &dev->resource[i];

 

              if ((r->flags & (IORESOURCE_IO | IORESOURCE_MEM|

                             IORESOURCE_IRQ |IORESOURCE_DMA)) == type)

                     if (num-- == 0)      return r;

       }

       return NULL;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//获取平台资源的中断资源

int   platform_get_irq(struct platform_device *dev,    unsigned int num)

{

       struct resource       *r = platform_get_resource(dev,   IORESOURCE_IRQ, num);

       return     r ? r->start : -ENXIO;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//根据设备名获取资源

struct resource       *platform_get_resource_byname(

       struct platform_device   *dev,             //平台设备

       unsigned int                 type,                     //资源类型

       char                            *name)           //设备名

{

       int i;

       for (i = 0; i < dev->num_resources; i++) {

              struct resource *r = &dev->resource[i];

 

              if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|

                             IORESOURCE_IRQ|IORESOURCE_DMA)) == type)

                     if (!strcmp(r->name, name))  return r;

       }

       return NULL;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//根据设备名获取中断资源

int   platform_get_irq_byname(struct platform_device *dev,     char *name)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//添加一组平台设备,**devs为平台设备数组,核心操作是平台设备的注册

int   platform_add_devices(struct platform_device     **devs,   int num)

{

       int i, ret = 0;

       for (i = 0; i < num; i++) {

              ret = platform_device_register(devs[i]);              //平台设备注册(实现在后)

              if (ret) {         //注册失败,反注册之前注册的函数

                     while (--i >= 0)      platform_device_unregister(devs[i]);

                     break;

              }

       }

       return ret;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//声明结构体,该结构体是平台设备的载体

struct      platform_object {

       struct platform_device   pdev;      //平台设备

       char name[1];

};

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

void       platform_device_put(struct platform_device       *pdev)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台设备的释放

static void      platform_device_release(struct device *dev)

{

       //根据设备获取平台目标结构体

       struct platform_object   *pa = container_of(dev, struct platform_object, pdev.dev);

 

       kfree(pa->pdev.dev.platform_data);      //释放平台设备的私有数据

       kfree(pa->pdev.resource);                    //释放平台资源

       kfree(pa);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//申请平台设备,并初始化,最后返回平台设备

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

{

       struct platform_object   *pa;

 

       //申请平台目标

       pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);

       if (pa) {         //设置成员变量

              strcpy(pa->name, name);                     //复制平台目标名

              pa->pdev.name = pa->name;                //设置平台设备的设备名

              pa->pdev.id = id;                                //平台设备的id号

              device_initialize(&pa->pdev.dev);        //平台设备的初始化

              pa->pdev.dev.release = platform_device_release;  //设置平台设备的释放函数

       }

       return     pa ? &pa->pdev : NULL;             //返回平台设备

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台设备添加资源,成功返回0

int   platform_device_add_resources(

       struct platform_device   *pdev,           //平台设备

       struct resource              *res,              //要添加的资源

       unsigned int                 num)              //资源数量

{

       struct resource *r;

 

       //申请内存

       r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL);

       if (r) {    //申请成功,复制资源

              memcpy(r, res, sizeof(struct resource) * num);

              pdev->resource = r;

              pdev->num_resources = num;

       }

       return     r ? 0 : -ENOMEM;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//为平台设备添加数据,操作同上,只是关联的位置是pdev->dev.platform_data

int   platform_device_add_data(

       struct platform_device   *pdev,

       const void                    *data,

       size_t                          size)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台设备添加,主要操作如下:

//1、设置设备的父设备(父设备不存在则指定到平台总线上)

//2、设置平台总线的操作函数

//3、设置设备总线的ID

//4、检查资源的设置,如果没设置则设置默认值

//5、调用core.c的device_add函数添加设备

int   platform_device_add(struct platform_device *pdev)

{

       int i, ret = 0;

 

       //参数为NULL,出错

       if (!pdev)              return -EINVAL;

       //设备的父设备没设置,将父设备指定到平台总线上

       if (!pdev->dev.parent)    pdev->dev.parent = &platform_bus;

       //设置平台总线的操作函数

       pdev->dev.bus = &platform_bus_type;

 

       //设备ID不是-1,将设备的总线ID设置为“设备名.设备ID”

       //否则,总线ID为设备名

       if (pdev->id != -1)

              snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%d", pdev->name,

                      pdev->id);

       else

              strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);

 

       //资源的默认设置

       for (i = 0; i < pdev->num_resources; i++) {

              struct resource       *p, *r = &pdev->resource[i];

 

              //资源名为空,重设资源名为总线名

              if (r->name == NULL)         r->name = pdev->dev.bus_id;

              p = r->parent;

              //资源没有指定父资源,根据资源的类型设置默认的父资源

              if (!p) {

                     if (r->flags & IORESOURCE_MEM)  //MEM资源

                            p = &iomem_resource;

                     else if (r->flags & IORESOURCE_IO) //IO资源

                            p = &ioport_resource;

              }

 

              //关联上了父资源,将资源插入到资源树中

              //如果父资源不存在,则资源将不插入到资源树中

              if (p && insert_resource(p, r)) {

                     ret = -EBUSY;

                     goto failed;

              }

       }

 

       //设备的添加(core.c中实现)

       ret = device_add(&pdev->dev);

       if (ret == 0)    return ret;

 

       //操作失败,释放资源

 failed:

       while (--i >= 0)

              if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))

                     release_resource(&pdev->resource[i]);

       return ret;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台设备的删除,先调用core.c中的device_del函数删除设备,然后再依次释放资源

void       platform_device_del(struct platform_device *pdev)

{

       int i;

 

       if (pdev) {

              device_del(&pdev->dev);

 

              for (i = 0; i < pdev->num_resources; i++) {

                     struct resource *r = &pdev->resource[i];

                     if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))

                            release_resource(r);

              }

       }

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台设备的注册,先设备初始化,然后执行平台设备的添加函数

int   platform_device_register(struct platform_device * pdev)

{

       device_initialize(&pdev->dev);

       return     platform_device_add(pdev);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台设备的反注册,实际操作是平台设备的删除函数,然后释放平台设备计数

void       platform_device_unregister(struct platform_device * pdev)

{

       platform_device_del(pdev);

       platform_device_put(pdev);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//创建并注册一个平台设备,并返回新注册的设备,具体操作如下:

//1、申请一个新的平台设备并初始化

//2、添加资源到平台设备中

//3、调用platform_device_add函数添加平台设备

struct platform_device   *platform_device_register_simple(      

       char                     *name,          //平台设备名

       int                        id,                 //平台设备的ID

       struct resource       *res,              //平台设备资源

       unsigned int          num)              //资源数量

{

       struct platform_device *pdev;

       int retval;

 

       //申请一个新的平台设备并初始化

       pdev = platform_device_alloc(name, id);

      

       //资源存在,添加资源到平台设备中

       if (num) {

              retval = platform_device_add_resources(pdev, res, num);

              if (retval)              goto error;

       }

 

       //添加这个平台设备

       retval = platform_device_add(pdev);

       if (retval)                     goto error;

 

       return pdev;           //返回平台设备

 

error:

       platform_device_put(pdev);

       return     ERR_PTR(retval);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//设备驱动的探测函数,根据输入的设备获取设备对应的驱动,并调用驱动的probe

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);

}

 

//探测失败

static int        platform_drv_probe_fail(struct device *_dev)

{

       return -ENXIO;

}

 

//设备驱动的remove,shutdown,suspend,resume函数的调用

static int        platform_drv_remove(struct device *_dev)

static void platform_drv_shutdown(struct device *_dev)

static int platform_drv_suspend(struct device *_dev, pm_message_t state)

static int platform_drv_resume(struct device *_dev)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台驱动的注册,具体操作是将驱动的总线设置为平台总线,关联驱动的函数,最后调用driver.c中的driver_register函数对驱动进行注册

//这里要关注一下平台驱动函数的调用,实际就是直接调用drv上对应的函数,所以在关联函数的时候要先判断drv->probe是否镇定

//注册成功

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;

       return     driver_register(&drv->driver);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台驱动的反注册函数,直接调用驱动的反注册

void       platform_driver_unregister(struct platform_driver *drv)

{

       driver_unregister(&drv->driver);

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//用指定的probe探测函数注册平台驱动

//__init_or_module在模块的时候为空,非模块的时候为init

int   __init_or_module platform_driver_probe(

       struct platform_driver   *drv,

       int (*probe)(struct platform_device *))

{

       int retval, code;

 

       //设置驱动的probe函数为指定函数,对drv进行注册

       //指定probe,这样注册驱动的时候,设备驱动的probe就会指定

       drv->probe = probe;

       retval = code = platform_driver_register(drv);

 

       //将probe函数挂空(可能是注册的使用用完就不用了)

       //如果注册失败,且驱动的设备链表为空,返回错误

       //探测函数指定为错误返回的函数

       spin_lock(&platform_bus_type.klist_drivers.k_lock);

       drv->probe = NULL;

       if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))

              retval = -ENODEV;

       drv->driver.probe = platform_drv_probe_fail;

       spin_unlock(&platform_bus_type.klist_drivers.k_lock);

 

       //如果有错误,反注册

       if (code != retval)          platform_driver_unregister(drv);

       return retval;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//获取平台设备的设备名

static      ssize_t     modalias_show(struct device *dev, struct device_attribute *a, char *buf)

{

       //获取平台设备,将平台设备的设备名打印到buf中

       struct platform_device   *pdev = to_platform_device(dev);

       int   len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);

 

       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//声明平台设备的属性,初始只有两个

static struct device_attribute         platform_dev_attrs[] = {

       __ATTR_RO(modalias),        //只读属性

       __ATTR_NULL,                   //空属性

};

 

#define __ATTR_RO(_name) { \

       .attr = { .name = __stringify(_name), .mode = 0444 },      \             //只读

       .show      = _name##_show,                               \

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台设备的uevent操作

static int        platform_uevent(struct device *dev,     struct kobj_uevent_env *env)

{

       struct platform_device   *pdev = to_platform_device(dev);

       add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);

       return 0;

}

 

//match匹配函数

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

{

       struct platform_device *pdev = container_of(dev, struct platform_device, dev);

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

}

 

//suspend挂起函数,实际是执行驱动的挂起函数

static int platform_suspend(struct device *dev, pm_message_t mesg)

{

       int ret = 0;

       if (dev->driver      &&        dev->driver->suspend)

              ret = dev->driver->suspend(dev, mesg);

       return ret;

}

 

//挂起之后,恢复之前,恢复,实际都是直接调用设备驱动的对应的函数

static int        platform_suspend_late(struct device *dev, pm_message_t mesg)

static int        platform_resume_early(struct device *dev)

static int        platform_resume(struct device * dev)

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//声明平台总线的操作函数

struct bus_type      platform_bus_type = {

       .name             = "platform",                       //总线名

       .dev_attrs              = platform_dev_attrs,           //属性(show,store)

       .match            = platform_match,

       .uevent           = platform_uevent,

       .suspend         = platform_suspend,

       .suspend_late  = platform_suspend_late,

       .resume_early = platform_resume_early,

       .resume          = platform_resume,

};

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//平台总线的初始化,系统自动调用

int   __init     platform_bus_init(void)

{

       int error;

 

       //总线设备注册

       error = device_register(&platform_bus);

       if (error) return error;

       //平台总线注册

       error =  bus_register(&platform_bus_type);

       if (error) device_unregister(&platform_bus);

       return error;

}

 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//通过网上搜索到的资料说明,这个函数是驱动用来寻找最佳DMA掩码的方法

u64        dma_get_required_mask(struct device *dev)

{

       u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);

       u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));

       u64 mask;

 

       if (!high_totalram) {

              low_totalram = (1 << (fls(low_totalram) - 1));

              low_totalram += low_totalram - 1;

              mask = low_totalram;

       } else {

              high_totalram = (1 << (fls(high_totalram) - 1));

              high_totalram += high_totalram - 1;

              mask = (((u64)high_totalram) << 32) + 0xffffffff;

       }

       return mask;

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值