OK335xS CAN device register and deiver match hacking
生活随笔
收集整理的這篇文章主要介紹了
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);elsedev_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);elseret = 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;
}
?
轉載于:https://www.cnblogs.com/zengjfgit/p/4788923.html
總結
以上是生活随笔為你收集整理的OK335xS CAN device register and deiver match hacking的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Shell】fix 1032报错信息的
- 下一篇: hdu 5011(博弈)