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.\n");

    /* 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\n",                  |
             __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\n", 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\n", 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)\n", pdev_name, ret);    |
                                                                       |
    return ERR_PTR(ret);                                               |
}                                                                      |
                                                                       |
int omap_device_register(struct platform_device *pdev)     <-----------+
{
    pr_debug("omap_device: %s: registering\n", pdev->name);
    printk("omap_device: %s: registering\n", 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\n",             |
                   dev_name(&pdev->dev), i);                        |
            ret = -EBUSY;                                           |
            goto failed;                                            |
        }                                                           |
    }                                                               |
                                                                    |
    pr_debug("Registering platform device '%s'. Parent at %s\n",    |
         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 "\n");                | | |     |
    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\n");           |     |
    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.\n");
    pdata = pdev->dev.platform_data;
    if (!pdata) {
        dev_err(&pdev->dev, "No platform data\n");
        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\n");
        goto exit;
    }

    priv = netdev_priv(ndev);
    fck = clk_get(&pdev->dev, "fck");
    if (IS_ERR(fck)) {
        dev_err(&pdev->dev, "fck is not found\n");
        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\n");
        goto exit_clk_put;
    }

    if (!request_mem_region(mem->start, resource_size(mem),
                D_CAN_DRV_NAME)) {
        dev_err(&pdev->dev, "resource unavailable\n");
        ret = -EBUSY;
        goto exit_clk_put;
    }

    addr = ioremap(mem->start, resource_size(mem));
    if (!addr) {
        dev_err(&pdev->dev, "ioremap failed\n");
        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\n");
        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\n");
        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)\n",
                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)\n",
                        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\n");

    return ret;
}

 

时间: 2024-07-29 14:45:30

OK335xS CAN device register and deiver match hacking的相关文章

OK335xS pwm device register hacking

/************************************************************************* * OK335xS pwm device register hacking * 声明: * 本文是对OK335xS pwm设备注册进行代码跟踪,其中有些部分是由于本人自己 * 添加的,但都是经过测试. * * 2015-8-25 晴 深圳 南山平山村 曾剑锋 *********************************************

OK335xS GPMC nand device register hacking

/********************************************************************************* * OK335xS GPMC nand device register hacking * 说明: * 由于最近遇到No NAND device found这个内核错误,在网络上也没找到很好的 * 解决办法,于是只能自己去跟踪整个设备.驱动的注册流程,试着去理解整个系统 * 的运作流程. * * 2015-9-2 雨 深圳 南山平山

OK335xS UART device registe hacking

/************************************************************************* * OK335xS UART device registe hacking * 声明: * 1. 本文是对OK335xS Linux内核中UART设备注册代码进行跟踪: * 2. 本人在文中采用函数调用线路图进行标记,方便阅读: * 3. 代码跟踪的用的是vim+ctags: * * 2015-6-30 晴 深圳 南山平山村 曾剑锋 *******

I.MX6 Ar8031 device register hacking

/***************************************************************************** * I.MX6 Ar8031 device register hacking * 声明: * 主要是为了知道网卡的注册流程,如果需要对网卡中的一些需求进行修改时,能够 * 能够快速的对需求进行分析.修改. * * 2015-8-15 雨 深圳 南山区平山村 曾剑锋 **************************************

OK335xS 256M 512M nand flash make ubifs hacking

/********************************************************************************* * OK335xs 256M 512M nand flash make ubifs hacking * 声明: * 本文主要是记录分析如何生成ubifs文件系统. * * 2015-11-14 晴 深圳 南山平山村 曾剑锋 *******************************************************

Node Joining Process in 6LoWPAN - ND, RPL

https://ez.analog.com/docs/DOC-12488 In typical 6LoWPAN networks, the registration is normally referred to as the node joining process. The complete flow is as outlined below. The first step in the network registration is Neighbor Discovery (ND). Thi

Cardboard Unity SDK Reference

Plugin Reference Package Contents The Unity plugin package contains the following: Scripts Cardboard.cs - Singleton connection to the native code VR device. CardboardEye.cs - Applies an eye view/projection to a stereo camera. CardboardHead.cs - Appli

Linux PXE无人值守安装出现 PXE-E32:TFTP OPen timeout的解决办法

用Linux中做pxe 安装系统的时候 出现 PXE-E32:TFTP OPen timeout 查找PXE启动芯片出错代码表,是说tftp没有运行 PXE-E32:TFTP open timeout TFTP"Open"请求没有应答,验证TFTP服务是否正在运行. 重启xinetd服务,并确定端口以内监听,还是有这个问题 [root@localhost /]# service xinetd restart 停止 xinetd: [确定] 启动 xinetd: [确定] [root@l

I.MX6 Linux I2C device&amp; driver hacking

/******************************************************************************************* * I.MX6 Linux I2C device& driver hacking * 声明: * 1. 本文主要是对Linux I2C驱动进行代码跟踪,主要是为了能够对I2C驱动框架有个全面的了解: * 2. 本文源代码来自myzr_android4_2_2_1_1_0.tar.bz2: * 3. 如果你有兴趣,