zoukankan      html  css  js  c++  java
  • OK335xS CAN device register and deiver match hacking

    /*************************************************************************
     *        OK335xS CAN device register and deiver match hacking
     * 声明:
     *     本文主要是跟踪CAN设备的注册、和驱动的匹配方式,了解CAN的注册流程。
     *
     *                                  2015-9-7 晴 深圳 南山平山村 曾剑锋        
     ************************************************************************/
    MACHINE_START(AM335XEVM, "am335xevm")
        /* Maintainer: Texas Instruments */
        .atag_offset    = 0x100,
        .map_io         = am335x_evm_map_io,
        .init_early     = am33xx_init_early,
        .init_irq       = ti81xx_init_irq,
        .handle_irq     = omap3_intc_handle_irq,
        .timer          = &omap3_am33xx_timer,
        .init_machine   = am335x_evm_init,            ------+
    MACHINE_END                                             |
                                                            |
    MACHINE_START(AM335XIAEVM, "am335xiaevm")               |
        /* Maintainer: Texas Instruments */                 |
        .atag_offset    = 0x100,                            |
        .map_io         = am335x_evm_map_io,                |
        .init_irq       = ti81xx_init_irq,                  |
        .init_early     = am33xx_init_early,                |
        .timer          = &omap3_am33xx_timer,              |
        .init_machine   = am335x_evm_init,            ------+
    MACHINE_END                                             |
                                                            |
    static void __init am335x_evm_init(void)          <-----+
    {
        setup_ok335xs();                              ------+
    }                                                       |
                                                            |
    static void setup_ok335xs(void)                   <-----+
    {
        pr_info("The board is a ok335xs.
    ");
    
        /* Starter Kit has Micro-SD slot which doesn't have Write Protect pin */
        am335x_mmc[0].gpio_wp = -EINVAL;
    
        _configure_device(EVM_SK, ok335xs_dev_cfg, PROFILE_NONE);
                                          ^------------------------------------+
        am33xx_cpsw_init(AM33XX_CPSW_MODE_RGMII, NULL, NULL);                  |
        /* Atheros Tx Clk delay Phy fixup */                                   |
        phy_register_fixup_for_uid(AM335X_EVM_PHY_ID, AM335X_EVM_PHY_MASK,     |
                       am33xx_evm_tx_clk_dly_phy_fixup);                       |
    }                                                                          |
                                                                               |
    /*ok335xs*/                                                                |
    static struct evm_dev_cfg ok335xs_dev_cfg[] = {          <-----------------+
        {mmc0_init,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        #if defined(CONFIG_ANDROID)
        {mfd_tscadc_init,         DEV_ON_BASEBOARD, PROFILE_ALL},
        #endif
        {rgmii1_init,    DEV_ON_BASEBOARD, PROFILE_ALL},
        {rgmii2_init,    DEV_ON_BASEBOARD, PROFILE_ALL},
        {lcdc_init,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {i2c1_init,     DEV_ON_BASEBOARD, PROFILE_ALL},
        {buzzer_init,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {enable_ecap2,     DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {usb0_init,     DEV_ON_BASEBOARD, PROFILE_ALL},
        {usb1_init,     DEV_ON_BASEBOARD, PROFILE_ALL},
        {evm_nand_init,DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {mcasp1_init,   DEV_ON_BASEBOARD, PROFILE_NONE},//fixed
        {gpio_keys_init_forlinx_s,  DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {gpio_led_init_s,  DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {uart2_init_s,  DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {spi1_init_s,           DEV_ON_BASEBOARD, PROFILE_ALL},//fixed
        {d_can_init, DEV_ON_BASEBOARD, PROFILE_ALL},//fixed    ------+
        {sgx_init,       DEV_ON_BASEBOARD, PROFILE_ALL},             |
        {NULL, 0, 0},                                                |
    };                                                               |
                                                                     |
    static void d_can_init(int evm_id, int profile)      <-----------+
    {
        //setup_pin_mux(d_can0_pin_mux);
        setup_pin_mux(d_can_gp_pin_mux);   ---------------------------------+
        am33xx_d_can_init(1);       |      ---------------------------------*-+
    }                               |                                       | |
                                    V                                       | |
    static struct pinmux_config d_can_gp_pin_mux[] = {                      | |
        {"uart0_ctsn.d_can1_tx", OMAP_MUX_MODE2 | AM33XX_PULL_ENBL},        | |
        {"uart0_rtsn.d_can1_rx", OMAP_MUX_MODE2 | AM33XX_PIN_INPUT_PULLUP}, | |
        {NULL, 0},                                                          | |
    };                                                                      | |
                                                                            | |
    static void setup_pin_mux(struct pinmux_config *pin_mux)    <-----------+ |
    {                                                                         |
        int i;                                                                |
                                                                              |
        for (i = 0; pin_mux->string_name != NULL; pin_mux++)                  |
            omap_mux_init_signal(pin_mux->string_name, pin_mux->val); ------+ |
                                                                            | |
    }                                                                       | |
                                                                            | |
    int __init omap_mux_init_signal(const char *muxname, int val)     <-----+ |
    {                                                                         |
        struct omap_mux_partition *partition = NULL;                          |
        struct omap_mux *mux = NULL;                                          |
        u16 old_mode;                                                         |
        int mux_mode;                                                         |
                                                                              |
        mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);           |
        if (mux_mode < 0)                                                     |
            return mux_mode;                                                  |
                                                                              |
        old_mode = omap_mux_read(partition, mux->reg_offset);                 |
        mux_mode |= val;                                                      |
        pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x
    ",                  |
                 __func__, muxname, old_mode, mux_mode);                      |
        omap_mux_write(partition, mux_mode, mux->reg_offset);                 |
                                                                              |
        return 0;                                                             |
    }                                                                         |
                                                                              |
    void am33xx_d_can_init(unsigned int instance)        <--------------------+
    {
        struct omap_hwmod *oh;
        struct platform_device *pdev;
        char oh_name[L3_MODULES_MAX_LEN];
    
        /* Copy string name to oh_name buffer */
        snprintf(oh_name, L3_MODULES_MAX_LEN, "d_can%d", instance);
    
        oh = omap_hwmod_lookup(oh_name);
        if (!oh) {
            pr_err("could not find %s hwmod data
    ", oh_name);
            return;
        }
    
        pdev = omap_device_build("d_can", instance, oh, &am33xx_dcan_info,  ----------+
                sizeof(am33xx_dcan_info), NULL, 0, 0);                                |
        if (IS_ERR(pdev))                                                             |
            pr_err("could not build omap_device for %s
    ", oh_name);                  |
    }                                                                                 |
                                                                                      |
    struct platform_device *omap_device_build(const char *pdev_name, int pdev_id, <---+
                          struct omap_hwmod *oh, void *pdata,
                          int pdata_len,
                          struct omap_device_pm_latency *pm_lats,
                          int pm_lats_cnt, int is_early_device)
    {
        struct omap_hwmod *ohs[] = { oh };
    
        if (!oh)
            return ERR_PTR(-EINVAL);
    
        return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,        ----------+
                        pdata_len, pm_lats, pm_lats_cnt,                                |
                        is_early_device);                                               |
    }                                                                                   |
                                                                                        |
    struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id, <--+
                         struct omap_hwmod **ohs, int oh_cnt,
                         void *pdata, int pdata_len,
                         struct omap_device_pm_latency *pm_lats,
                         int pm_lats_cnt, int is_early_device)
    {
        int ret = -ENOMEM;
        struct platform_device *pdev;
        struct omap_device *od;
    
        if (!ohs || oh_cnt == 0 || !pdev_name)
            return ERR_PTR(-EINVAL);
    
        if (!pdata && pdata_len > 0)
            return ERR_PTR(-EINVAL);
    
        pdev = platform_device_alloc(pdev_name, pdev_id);
        if (!pdev) {
            ret = -ENOMEM;
            goto odbs_exit;
        }
    
        /* Set the dev_name early to allow dev_xxx in omap_device_alloc */
        if (pdev->id != -1)
            dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
        else
            dev_set_name(&pdev->dev, "%s", pdev->name);
    
        od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
        if (!od)
            goto odbs_exit1;
    
        ret = platform_device_add_data(pdev, pdata, pdata_len);
        if (ret)
            goto odbs_exit2;
    
        if (is_early_device)
            ret = omap_early_device_register(pdev);
        else
            ret = omap_device_register(pdev);           -------------------+
        if (ret)                                                           |
            goto odbs_exit2;                                               |
                                                                           |
        return pdev;                                                       |
                                                                           |
    odbs_exit2:                                                            |
        omap_device_delete(od);                                            |
    odbs_exit1:                                                            |
        platform_device_put(pdev);                                         |
    odbs_exit:                                                             |
                                                                           |
        pr_err("omap_device: %s: build failed (%d)
    ", pdev_name, ret);    |
                                                                           |
        return ERR_PTR(ret);                                               |
    }                                                                      |
                                                                           |
    int omap_device_register(struct platform_device *pdev)     <-----------+
    {
        pr_debug("omap_device: %s: registering
    ", pdev->name);
        printk("omap_device: %s: registering
    ", pdev->name);
    
        pdev->dev.parent = &omap_device_parent;
        pdev->dev.pm_domain = &omap_device_pm_domain;
        return platform_device_add(pdev);                      ------------+
    }                                                                      |
                                                                           |
    int platform_device_add(struct platform_device *pdev)      <-----------+
    {
        int i, ret = 0;
    
        if (!pdev)
            return -EINVAL;
    
        if (!pdev->dev.parent)
            pdev->dev.parent = &platform_bus;
    
        pdev->dev.bus = &platform_bus_type;          -------------------+
                                                                        |
        if (pdev->id != -1)                                             |
            dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);   |
        else                                                            |
            dev_set_name(&pdev->dev, "%s", pdev->name);                 |
                                                                        |
        for (i = 0; i < pdev->num_resources; i++) {                     |
            struct resource *p, *r = &pdev->resource[i];                |
                                                                        |
            if (r->name == NULL)                                        |
                r->name = dev_name(&pdev->dev);                         |
                                                                        |
            p = r->parent;                                              |
            if (!p) {                                                   |
                if (resource_type(r) == IORESOURCE_MEM)                 |
                    p = &iomem_resource;                                |
                else if (resource_type(r) == IORESOURCE_IO)             |
                    p = &ioport_resource;                               |
            }                                                           |
                                                                        |
            if (p && insert_resource(p, r)) {                           |
                printk(KERN_ERR                                         |
                       "%s: failed to claim resource %d
    ",             |
                       dev_name(&pdev->dev), i);                        |
                ret = -EBUSY;                                           |
                goto failed;                                            |
            }                                                           |
        }                                                               |
                                                                        |
        pr_debug("Registering platform device '%s'. Parent at %s
    ",    |
             dev_name(&pdev->dev), dev_name(pdev->dev.parent));         |
                                                                        |
        ret = device_add(&pdev->dev);                                   |
        if (ret == 0)                                                   |
            return ret;                                                 |
                                                                        |
     failed:                                                            |
        while (--i >= 0) {                                              |
            struct resource *r = &pdev->resource[i];                    |
            unsigned long type = resource_type(r);                      |
                                                                        |
            if (type == IORESOURCE_MEM || type == IORESOURCE_IO)        |
                release_resource(r);                                    |
        }                                                               |
                                                                        |
        return ret;                                                     |
    }                                                                   |
    EXPORT_SYMBOL_GPL(platform_device_add);                             |
                                                                        |
    struct bus_type platform_bus_type = {        <----------------------+
        .name        = "platform",
        .dev_attrs    = platform_dev_attrs,
        .match        = platform_match,          -------------------------------+
        .uevent        = platform_uevent,                                       |
        .pm        = &platform_dev_pm_ops,                                      |
    };                                                                          |
    EXPORT_SYMBOL_GPL(platform_bus_type);                                       |
                                                                                |
    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);
    
        /* Attempt an OF style match first */
        if (of_driver_match_device(dev, drv))           -------------+
            return 1;                                                |
                                                                     |
        /* Then try to match against the id table */                 |
        if (pdrv->id_table)                                          |
            return platform_match_id(pdrv->id_table, pdev) != NULL;  |
                          ^------------------------------------------|-+
        /* fall-back to driver name match */                         | |
        // canbus use this for match                                 | |
        return (strcmp(pdev->name, drv->name) == 0);                 | |
    }                                                                | |
                                                                     | |
    static inline int of_driver_match_device(struct device *dev, <---+ |
                         const struct device_driver *drv)              |
    {                                                                  |
        return of_match_device(drv->of_match_table, dev) != NULL;      |
    }                                                                  |
                                                                       |
    static const struct platform_device_id *platform_match_id(   <-----+
                const 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;
    }
    
    
    
    
    
    cat drivers/net/can/d_can/d_can_platform.c
    static struct platform_driver d_can_plat_driver = {   <-----+
        .driver = {                                             |
            .name   = D_CAN_DRV_NAME,            ---------------*-+
            .owner  = THIS_MODULE,                              | |
        },                                                      | |
        .probe      = d_can_plat_probe,          ---------------*-*-----+
        .remove     = __devexit_p(d_can_plat_remove),           | |     |
        .suspend    = d_can_suspend,                            | |     |
        .resume     = d_can_resume,                             | |     |
    };                                                          | |     |
                                                                | |     |
    static int __init d_can_plat_init(void)      <------------+ | |     |
    {                                                         | | |     |
        printk(KERN_INFO D_CAN_DRV_DESC "
    ");                | | |     |
        return platform_driver_register(&d_can_plat_driver);--*-- |     |
    }                                                         |   |     |
    module_init(d_can_plat_init); ----------------------------+   |     |
                                                                  |     |
    static void __exit d_can_plat_exit(void)                      |     |
    {                                                             |     |
        printk(KERN_INFO D_CAN_DRV_DESC " unloaded
    ");           |     |
        platform_driver_unregister(&d_can_plat_driver);           |     |
    }                                                             |     |
    module_exit(d_can_plat_exit);                                 |     |
                                                                  |     |
    MODULE_AUTHOR("AnilKumar Ch <anilkumar@ti.com>");             |     |
    MODULE_LICENSE("GPL v2");                                     |     |
    MODULE_VERSION(D_CAN_VERSION);                                |     |
    MODULE_DESCRIPTION(D_CAN_DRV_DESC);                           |     |
                                                                  |     |
    #define D_CAN_DRV_NAME    "d_can"            <----------------+     |
                                  v-------------------------------------+
    static int __devinit d_can_plat_probe(struct platform_device *pdev)
    {
        int ret = 0;
        void __iomem *addr;
        struct net_device *ndev;
        struct d_can_priv *priv;
        struct resource *mem;
        struct d_can_platform_data *pdata;
        struct clk *fck;
    
        printk("zengjf check can plat probed.
    ");
        pdata = pdev->dev.platform_data;
        if (!pdata) {
            dev_err(&pdev->dev, "No platform data
    ");
            goto exit;
        }
    
        /* allocate the d_can device */
        ndev = alloc_d_can_dev(pdata->num_of_msg_objs);
        if (!ndev) {
            ret = -ENOMEM;
            dev_err(&pdev->dev, "alloc_d_can_dev failed
    ");
            goto exit;
        }
    
        priv = netdev_priv(ndev);
        fck = clk_get(&pdev->dev, "fck");
        if (IS_ERR(fck)) {
            dev_err(&pdev->dev, "fck is not found
    ");
            ret = -ENODEV;
            goto exit_free_ndev;
        }
    
        /* get the platform data */
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
            ret = -ENODEV;
            dev_err(&pdev->dev, "No mem resource
    ");
            goto exit_clk_put;
        }
    
        if (!request_mem_region(mem->start, resource_size(mem),
                    D_CAN_DRV_NAME)) {
            dev_err(&pdev->dev, "resource unavailable
    ");
            ret = -EBUSY;
            goto exit_clk_put;
        }
    
        addr = ioremap(mem->start, resource_size(mem));
        if (!addr) {
            dev_err(&pdev->dev, "ioremap failed
    ");
            ret = -ENOMEM;
            goto exit_release_mem;
        }
    
        /* IRQ specific to Error and status & can be used for Message Object */
        ndev->irq = platform_get_irq_byname(pdev, "d_can_ms");
        if (!ndev->irq) {
            dev_err(&pdev->dev, "No irq0 resource
    ");
            goto exit_iounmap;
        }
    
        /* IRQ specific for Message Object */
        priv->irq_obj = platform_get_irq_byname(pdev, "d_can_mo");
        if (!priv->irq_obj) {
            dev_err(&pdev->dev, "No irq1 resource
    ");
            goto exit_iounmap;
        }
    
        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
        priv->pdev = pdev;
        priv->base = addr;
        priv->can.clock.freq = clk_get_rate(fck);
        priv->ram_init = pdata->ram_init;
        priv->opened = false;
    
        platform_set_drvdata(pdev, ndev);
        SET_NETDEV_DEV(ndev, &pdev->dev);
    
        ret = register_d_can_dev(ndev);
        if (ret) {
            dev_err(&pdev->dev, "registering %s failed (err=%d)
    ",
                    D_CAN_DRV_NAME, ret);
            goto exit_free_device;
        }
    
        /* Initialize DCAN RAM */
        d_can_reset_ram(priv, pdev->id, 1);
    
        dev_info(&pdev->dev, "device registered (irq=%d, irq_obj=%d)
    ",
                            ndev->irq, priv->irq_obj);
    
        return 0;
    
    exit_free_device:
        platform_set_drvdata(pdev, NULL);
        pm_runtime_disable(&pdev->dev);
    exit_iounmap:
        iounmap(addr);
    exit_release_mem:
        release_mem_region(mem->start, resource_size(mem));
    exit_clk_put:
        clk_put(fck);
    exit_free_ndev:
        free_d_can_dev(ndev);
    exit:
        dev_err(&pdev->dev, "probe failed
    ");
    
        return ret;
    }
  • 相关阅读:
    ASP.NET Web API自身对CORS的支持:从实例开始
    通过扩展让ASP.NET Web API支持W3C的CORS规范
    通过扩展让ASP.NET Web API支持JSONP
    [CORS:跨域资源共享] W3C的CORS Specification
    [CORS:跨域资源共享] 同源策略与JSONP
    如何让ASP.NET Web API的Action方法在希望的Culture下执行
    唐伯虎的垃圾
    Razor Engine,实现代码生成器的又一件利器
    ASP.NET Web API路由系统:Web Host下的URL路由
    How ASP.NET Web API 2.0 Works?[持续更新中…]
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/4788923.html
Copyright © 2011-2022 走看看