当前位置:   article > 正文

EC20(4g模块)移植到RK3588\rk3399\rk3288\A64\MTK等linux平台教程_rk3288调试ec20

rk3288调试ec20

一、硬件原理:

 这里用是的E20贴片模块,主板使用的是RK3588平台。模块有3个关键IO分别用于控制电源、开机键、reset键,需配置到dts中。(注:若您的平台是用的PCIE模块,则不用关心DTS配置和驱动移植问题)。

二、DTS配置

  1.      rk_modem {
  2.                   compatible="4g-modem-platdata";
  3.                   pinctrl-names = "default";
  4.                   pinctrl-0 = <&lte_vbat &lte_power_en &lte_reset>;
  5.                   4G,vbat-gpio =  <&gpio1 RK_PC3 GPIO_ACTIVE_HIGH>;
  6.                   4G,power-gpio = <&gpio1 RK_PC7 GPIO_ACTIVE_HIGH>;
  7.                   4G,reset-gpio = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
  8.                   status = "okay";
  9.     };

三、驱动源码,代码功能介绍:

1.给上层提供一个虚拟文件/sys/class/rk_modem。

2.用户层对文件进行写0/1则会控制dts配置的gpio电平完成关闭/启动模块的功能。

  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2019, Fuzhou Rockchip Electronics Co., Ltd.
  4. *
  5. * Rockchip rm310 driver for 4g modem
  6. */
  7. #include <linux/module.h>
  8. #include <linux/kernel.h>
  9. #include <linux/kthread.h>
  10. #include <linux/i2c.h>
  11. #include <linux/irq.h>
  12. #include <linux/gpio.h>
  13. #include <linux/input.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/fs.h>
  16. #include <linux/uaccess.h>
  17. #include <linux/miscdevice.h>
  18. #include <linux/circ_buf.h>
  19. #include <linux/miscdevice.h>
  20. #include <linux/gpio.h>
  21. #include <dt-bindings/gpio/gpio.h>
  22. #include <linux/delay.h>
  23. #include <linux/poll.h>
  24. #include <linux/wait.h>
  25. #include <linux/wakelock.h>
  26. #include <linux/workqueue.h>
  27. #include <linux/lte.h>
  28. #include <linux/slab.h>
  29. #include <linux/of.h>
  30. #include <linux/of_device.h>
  31. #include <linux/of_gpio.h>
  32. #define LOG(x...) pr_info("[4g_modem]: " x)
  33. static struct lte_data *gpdata;
  34. static struct class *modem_class;
  35. static int modem_status = 1;
  36. static int modem_poweron_off(int on_off)
  37. {
  38. struct lte_data *pdata = gpdata;
  39. if (pdata) {
  40. if (on_off) {
  41. LOG("%s: 4g modem power up.\n", __func__);
  42. if (pdata->vbat_gpio) {
  43. gpiod_direction_output(pdata->vbat_gpio, 1);
  44. msleep(2000);
  45. }
  46. if (pdata->power_gpio) {
  47. gpiod_direction_output(pdata->power_gpio, 0);
  48. msleep(50);
  49. gpiod_direction_output(pdata->power_gpio, 1);
  50. msleep(400);
  51. gpiod_direction_output(pdata->power_gpio, 0);
  52. }
  53. } else {
  54. LOG("%s: 4g modem power down.\n", __func__);
  55. if (pdata->power_gpio) {
  56. gpiod_direction_output(pdata->power_gpio, 0);
  57. msleep(100);
  58. gpiod_direction_output(pdata->power_gpio, 1);
  59. msleep(1000);
  60. gpiod_direction_output(pdata->power_gpio, 0);
  61. msleep(400);
  62. }
  63. if (pdata->vbat_gpio)
  64. gpiod_direction_output(pdata->vbat_gpio, 0);
  65. }
  66. }
  67. return 0;
  68. }
  69. static ssize_t modem_status_store(struct class *cls,
  70. struct class_attribute *attr,
  71. const char *buf, size_t count)
  72. {
  73. int new_state, ret;
  74. ret = kstrtoint(buf, 10, &new_state);
  75. if (ret) {
  76. LOG("%s: kstrtoint error return %d\n", __func__, ret);
  77. return ret;
  78. }
  79. if (new_state == modem_status)
  80. return count;
  81. if (new_state == 1) {
  82. LOG("%s, c(%d), open modem.\n", __func__, new_state);
  83. modem_poweron_off(1);
  84. } else if (new_state == 0) {
  85. LOG("%s, c(%d), close modem.\n", __func__, new_state);
  86. modem_poweron_off(0);
  87. } else {
  88. LOG("%s, invalid parameter.\n", __func__);
  89. }
  90. modem_status = new_state;
  91. return count;
  92. }
  93. static ssize_t modem_status_show(struct class *cls,
  94. struct class_attribute *attr,
  95. char *buf)
  96. {
  97. return sprintf(buf, "%d\n", modem_status);
  98. }
  99. static CLASS_ATTR_RW(modem_status);
  100. static int modem_platdata_parse_dt(struct device *dev,
  101. struct lte_data *data)
  102. {
  103. struct device_node *node = dev->of_node;
  104. int ret;
  105. if (!node)
  106. return -ENODEV;
  107. memset(data, 0, sizeof(*data));
  108. LOG("%s: LTE modem power controlled by gpio.\n", __func__);
  109. data->vbat_gpio = devm_gpiod_get_optional(dev, "4G,vbat",
  110. GPIOD_OUT_HIGH);
  111. if (IS_ERR(data->vbat_gpio)) {
  112. ret = PTR_ERR(data->vbat_gpio);
  113. dev_err(dev, "failed to request 4G,vbat GPIO: %d\n", ret);
  114. return ret;
  115. }
  116. data->power_gpio = devm_gpiod_get_optional(dev, "4G,power",
  117. GPIOD_OUT_HIGH);
  118. if (IS_ERR(data->power_gpio)) {
  119. ret = PTR_ERR(data->power_gpio);
  120. dev_err(dev, "failed to request 4G,power GPIO: %d\n", ret);
  121. return ret;
  122. }
  123. data->reset_gpio = devm_gpiod_get_optional(dev, "4G,reset",
  124. GPIOD_OUT_LOW);
  125. if (IS_ERR(data->reset_gpio)) {
  126. ret = PTR_ERR(data->reset_gpio);
  127. dev_err(dev, "failed to request 4G,reset GPIO: %d\n", ret);
  128. return ret;
  129. }
  130. return 0;
  131. }
  132. static int modem_power_on_thread(void *data)
  133. {
  134. modem_poweron_off(1);
  135. return 0;
  136. }
  137. static int lte_probe(struct platform_device *pdev)
  138. {
  139. struct lte_data *pdata;
  140. struct task_struct *kthread;
  141. int ret = -1;
  142. LOG("%s\n",__func__);
  143. pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
  144. if (!pdata)
  145. return -ENOMEM;
  146. ret = modem_platdata_parse_dt(&pdev->dev, pdata);
  147. if (ret < 0) {
  148. LOG("%s: No lte platform data specified\n", __func__);
  149. goto err;
  150. }
  151. gpdata = pdata;
  152. pdata->dev = &pdev->dev;
  153. if (pdata->reset_gpio)
  154. gpiod_direction_output(pdata->reset_gpio, 0);
  155. kthread = kthread_run(modem_power_on_thread, NULL,
  156. "modem_power_on_thread");
  157. if (IS_ERR(kthread)) {
  158. LOG("%s: create modem_power_on_thread failed.\n", __func__);
  159. ret = PTR_ERR(kthread);
  160. goto err;
  161. }
  162. return 0;
  163. err:
  164. gpdata = NULL;
  165. return ret;
  166. }
  167. static int lte_suspend(struct platform_device *pdev, pm_message_t state)
  168. {
  169. modem_poweron_off(0);
  170. return 0;
  171. }
  172. static int lte_resume(struct platform_device *pdev)
  173. {
  174. modem_poweron_off(1);
  175. return 0;
  176. }
  177. static int lte_remove(struct platform_device *pdev)
  178. {
  179. struct lte_data *pdata = gpdata;
  180. if (pdata->power_gpio) {
  181. msleep(100);
  182. gpiod_direction_output(pdata->power_gpio, 1);
  183. msleep(750);
  184. gpiod_direction_output(pdata->power_gpio, 0);
  185. }
  186. if (pdata->vbat_gpio)
  187. gpiod_direction_output(pdata->vbat_gpio, 0);
  188. gpdata = NULL;
  189. return 0;
  190. }
  191. static const struct of_device_id modem_platdata_of_match[] = {
  192. { .compatible = "4g-modem-platdata" },
  193. { }
  194. };
  195. MODULE_DEVICE_TABLE(of, modem_platdata_of_match);
  196. static struct platform_driver rm310_driver = {
  197. .probe = lte_probe,
  198. .remove = lte_remove,
  199. .suspend = lte_suspend,
  200. .resume = lte_resume,
  201. .driver = {
  202. .name = "4g-modem-platdata",
  203. .of_match_table = of_match_ptr(modem_platdata_of_match),
  204. },
  205. };
  206. static int __init rm310_init(void)
  207. {
  208. int ret;
  209. printk("%s\n",__func__);
  210. modem_class = class_create(THIS_MODULE, "rk_modem");
  211. ret = class_create_file(modem_class, &class_attr_modem_status);
  212. if (ret)
  213. LOG("Fail to create class modem_status.\n");
  214. return platform_driver_register(&rm310_driver);
  215. }
  216. static void __exit rm310_exit(void)
  217. {
  218. platform_driver_unregister(&rm310_driver);
  219. }
  220. late_initcall(rm310_init);
  221. module_exit(rm310_exit);
  222. MODULE_AUTHOR("xuxuehui <xxh@rock-chips.com>");
  223. MODULE_AUTHOR("Alex Zhao <zzc@rock-chips.com>");
  224. MODULE_DESCRIPTION("RM310 lte modem driver");
  225. MODULE_LICENSE("GPL");

  三、内核配置

        CONFIG_USB_SERIAL=y
        CONFIG_USB_SERIAL_WWAN=y
        CONFIG_USB_SERIAL_OPTION=y
        CONFIG_USBNET=y  

        CONFIG_PPP=y
        CONFIG_PPP_BSDCOMP=y
        CONFIG_PPP_DEFLATE=y
        CONFIG_PPP_FILTER=y
        CONFIG_PPP_MPPE=y
        CONFIG_PPP_MULTILINK=y
        CONFIG_PPPOE=y
        CONFIG_PPP_ASYNC=y
        CONFIG_PPP_SYNC_TTY=y
        CONFIG_SLIP=y
        CONFIG_SLHC=y   

四、应用程序配置

        1.平台端移植pppd程序,下载地址,使用configure配置编译器,编译完成后将编译好的执行程序pppd拷贝到板子/bin目录。

        2.配置包,下载地址,将包解压后放入板子的/etc/ppp/peers/中

五、测试

        

  1. 一、启动模块
  2. echo 1 >/sys/class/rk_modem
  3. 等待5S后,输入lsusb,查询pid/vid是否有枚举到,如果枚举上了,则继续接下来的操作,否则检查硬件。
  4. 二、查询网卡
  5. ifconfig -a
  6. 看看有没wwan0节点产生,如果没有则检查驱动配置。
  7. 三、拨号
  8. pppd call quectel-ppp &
  9. 四、ping 114.114.114.114 测试网络

六、遇到问题可加我微信交流。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/275299
推荐阅读
相关标签
  

闽ICP备14008679号