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相关推荐
- 内核添加dts后,device和device_driver的match匹配的变动:通过compatible属性进行匹配【转】...
本文转载自:http://blog.csdn.net/ruanjianruanjianruan/article/details/61622053 内核添加dts后,device和device_driv ...
- linux设备驱动归纳总结(八):2.match.probe.remove
CU首页 ┊ fh265>>博客 微博 相册 个人中心 好友 消息 [退出] ┊ 随便看看 公告:缅怀Dennis Ritchie活动开赛啦! 小白的博客--提升自已,分享别人 xiaob ...
- Linux usb 4. Device 详解
文章目录 1. 简介 2. Platform Layer 2.1 Platform Device 2.2 Platform Driver 3. UDC/Gadget Layer 3.1 Gadget ...
- Linux Driver 和Device匹配过程分析
Linux Driver 和Device匹配过程分析 1,总线注册匹配过程 1.1 struct platform_driver 1.2 struct device_driver 1.3 PCIe总线 ...
- Linux设备模型(4) — bus 与 device 和 driver
前面说了 device 和 device_driver,这两者是通过一个叫 bus 的东西联系在一起,不管这个 bus 是否是真实的存在(虚拟的也算). 1.Bus Linux 中,对 bus 是由一 ...
- linux驱动开发音频设备驱动,linux驱动开发—基于Device tree机制的驱动编写
摘要:媒介 Device Tree是一种用去描绘硬件的数据布局,类似板级描绘说话,发源于OpenFirmware(OF).正在现在遍及应用的kernel 2.6.x版本中,对分歧仄台.分歧硬件,往] ...
- Android 驱动(12)---Linux DTS(Device Tree Source)设备树详解
Linux DTS(Device Tree Source)设备树详解 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇) Linux DTS(Device Tr ...
- LINUX IIO子系统分析之六 iio device的驱动开发流程说明
前面五章我们基本上把IIO 子系统的内部设计实现均作了说明,本章我们将说明iio device的驱动开发流程,本章的主要内容大致安排如下: 一.IIO子系统的关键技术点总结 二.IIO DEVICE的 ...
- 高通平台msm8953 Linux DTS(Device Tree Source)设备树详解之二(DTS设备树匹配过程)
本系列导航: 高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇) 高通平台8953 Linux DTS(Device Tree Source ...
最新文章
- 莱芜市公安局交警支队智能交通项目集成及容灾公开招标公告
- java word模板占位符_word模板导出的几种方式:第一种:占位符替换模板导出(只适用于word中含有表格形式的)...
- python3--装饰器
- 数据库acid简介(一)
- MIT自然语言处理第一讲:简介和概述(第三部分)
- 理解Floyd-Warshall算法
- .Net高级技术——对象序列化
- web.py开发web 第一章 Hello World
- 基于matlab的prony方法实现,基于MATLAB的Prony方法实现
- 【推荐实践】Bandit算法在携程推荐系统中的应用与实践
- ----------------------------------------spring 整合jdbc---------------------
- python编程语言_Python编程语言的历史
- 目前流行的源程序版本管理软件和项目管理的软件优缺点
- SQL Server高可用——日志传送(4-3)——使用
- python自动登录网银_网银自动充值-登陆联通网站沃支付
- 计算机网络实验指导书 pdf,计算机网络实验指导书(新版).pdf
- codevs 5294 挖地雷
- 为什么不要用苹果的@icloud.com邮箱申请你的APP ID
- kafka集群开启sasl认证
- 计算机系学生thinkbook,设计师笔记本电脑推荐 ThinkBook 15p视觉系创造本你值得拥有...
热门文章
- pku 1486 求出二分匹配图中的必须边
- head first html with css with xhtml 学习小笔记
- spring+hibernate的配置
- Windows核心编程 第25章 未处理异常和C ++异常(下)
- 【Linux 内核】编译 Linux 内核 ⑤ ( 查看 .config 编译配置文件 | 正式编译内核 )
- 【EventBus】事件通信框架 ( 订阅类-订阅方法缓存集合 | 事件类型-订阅者集合 | 订阅对象-事件类型集合 )
- 【Java 并发编程】线程简介 ( 原子操作 | volatile 关键字使用场景 )
- Sun公司的产品AnswerBook存在多种漏洞
- 网页瀑布流效果实现的几种方式
- Prism框架研究(一)