qca_uart.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
  2. /*
  3. * Copyright (c) 2011, 2012, Qualcomm Atheros Communications Inc.
  4. * Copyright (c) 2017, I2SE GmbH
  5. */
  6. /* This module implements the Qualcomm Atheros UART protocol for
  7. * kernel-based UART device; it is essentially an Ethernet-to-UART
  8. * serial converter;
  9. */
  10. #include <linux/device.h>
  11. #include <linux/errno.h>
  12. #include <linux/etherdevice.h>
  13. #include <linux/if_arp.h>
  14. #include <linux/if_ether.h>
  15. #include <linux/jiffies.h>
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/netdevice.h>
  19. #include <linux/of.h>
  20. #include <linux/of_net.h>
  21. #include <linux/sched.h>
  22. #include <linux/serdev.h>
  23. #include <linux/skbuff.h>
  24. #include <linux/types.h>
  25. #include "qca_7k_common.h"
  26. #define QCAUART_DRV_VERSION "0.1.0"
  27. #define QCAUART_DRV_NAME "qcauart"
  28. #define QCAUART_TX_TIMEOUT (1 * HZ)
  29. struct qcauart {
  30. struct net_device *net_dev;
  31. spinlock_t lock; /* transmit lock */
  32. struct work_struct tx_work; /* Flushes transmit buffer */
  33. struct serdev_device *serdev;
  34. struct qcafrm_handle frm_handle;
  35. struct sk_buff *rx_skb;
  36. unsigned char *tx_head; /* pointer to next XMIT byte */
  37. int tx_left; /* bytes left in XMIT queue */
  38. unsigned char *tx_buffer;
  39. };
  40. static size_t
  41. qca_tty_receive(struct serdev_device *serdev, const u8 *data, size_t count)
  42. {
  43. struct qcauart *qca = serdev_device_get_drvdata(serdev);
  44. struct net_device *netdev = qca->net_dev;
  45. struct net_device_stats *n_stats = &netdev->stats;
  46. size_t i;
  47. if (!qca->rx_skb) {
  48. qca->rx_skb = netdev_alloc_skb_ip_align(netdev,
  49. netdev->mtu +
  50. VLAN_ETH_HLEN);
  51. if (!qca->rx_skb) {
  52. n_stats->rx_errors++;
  53. n_stats->rx_dropped++;
  54. return 0;
  55. }
  56. }
  57. for (i = 0; i < count; i++) {
  58. s32 retcode;
  59. retcode = qcafrm_fsm_decode(&qca->frm_handle,
  60. qca->rx_skb->data,
  61. skb_tailroom(qca->rx_skb),
  62. data[i]);
  63. switch (retcode) {
  64. case QCAFRM_GATHER:
  65. case QCAFRM_NOHEAD:
  66. break;
  67. case QCAFRM_NOTAIL:
  68. netdev_dbg(netdev, "recv: no RX tail\n");
  69. n_stats->rx_errors++;
  70. n_stats->rx_dropped++;
  71. break;
  72. case QCAFRM_INVLEN:
  73. netdev_dbg(netdev, "recv: invalid RX length\n");
  74. n_stats->rx_errors++;
  75. n_stats->rx_dropped++;
  76. break;
  77. default:
  78. n_stats->rx_packets++;
  79. n_stats->rx_bytes += retcode;
  80. skb_put(qca->rx_skb, retcode);
  81. qca->rx_skb->protocol = eth_type_trans(
  82. qca->rx_skb, qca->rx_skb->dev);
  83. skb_checksum_none_assert(qca->rx_skb);
  84. netif_rx(qca->rx_skb);
  85. qca->rx_skb = netdev_alloc_skb_ip_align(netdev,
  86. netdev->mtu +
  87. VLAN_ETH_HLEN);
  88. if (!qca->rx_skb) {
  89. netdev_dbg(netdev, "recv: out of RX resources\n");
  90. n_stats->rx_errors++;
  91. return i + 1;
  92. }
  93. }
  94. }
  95. return i;
  96. }
  97. /* Write out any remaining transmit buffer. Scheduled when tty is writable */
  98. static void qcauart_transmit(struct work_struct *work)
  99. {
  100. struct qcauart *qca = container_of(work, struct qcauart, tx_work);
  101. struct net_device_stats *n_stats = &qca->net_dev->stats;
  102. int written;
  103. spin_lock_bh(&qca->lock);
  104. /* First make sure we're connected. */
  105. if (!netif_running(qca->net_dev)) {
  106. spin_unlock_bh(&qca->lock);
  107. return;
  108. }
  109. if (qca->tx_left <= 0) {
  110. /* Now serial buffer is almost free & we can start
  111. * transmission of another packet
  112. */
  113. n_stats->tx_packets++;
  114. spin_unlock_bh(&qca->lock);
  115. netif_wake_queue(qca->net_dev);
  116. return;
  117. }
  118. written = serdev_device_write_buf(qca->serdev, qca->tx_head,
  119. qca->tx_left);
  120. if (written > 0) {
  121. qca->tx_left -= written;
  122. qca->tx_head += written;
  123. }
  124. spin_unlock_bh(&qca->lock);
  125. }
  126. /* Called by the driver when there's room for more data.
  127. * Schedule the transmit.
  128. */
  129. static void qca_tty_wakeup(struct serdev_device *serdev)
  130. {
  131. struct qcauart *qca = serdev_device_get_drvdata(serdev);
  132. schedule_work(&qca->tx_work);
  133. }
  134. static const struct serdev_device_ops qca_serdev_ops = {
  135. .receive_buf = qca_tty_receive,
  136. .write_wakeup = qca_tty_wakeup,
  137. };
  138. static int qcauart_netdev_open(struct net_device *dev)
  139. {
  140. struct qcauart *qca = netdev_priv(dev);
  141. netif_start_queue(qca->net_dev);
  142. return 0;
  143. }
  144. static int qcauart_netdev_close(struct net_device *dev)
  145. {
  146. struct qcauart *qca = netdev_priv(dev);
  147. netif_stop_queue(dev);
  148. flush_work(&qca->tx_work);
  149. spin_lock_bh(&qca->lock);
  150. qca->tx_left = 0;
  151. spin_unlock_bh(&qca->lock);
  152. return 0;
  153. }
  154. static netdev_tx_t
  155. qcauart_netdev_xmit(struct sk_buff *skb, struct net_device *dev)
  156. {
  157. struct net_device_stats *n_stats = &dev->stats;
  158. struct qcauart *qca = netdev_priv(dev);
  159. u8 pad_len = 0;
  160. int written;
  161. u8 *pos;
  162. spin_lock(&qca->lock);
  163. WARN_ON(qca->tx_left);
  164. if (!netif_running(dev)) {
  165. spin_unlock(&qca->lock);
  166. netdev_warn(qca->net_dev, "xmit: iface is down\n");
  167. goto out;
  168. }
  169. pos = qca->tx_buffer;
  170. if (skb->len < QCAFRM_MIN_LEN)
  171. pad_len = QCAFRM_MIN_LEN - skb->len;
  172. pos += qcafrm_create_header(pos, skb->len + pad_len);
  173. memcpy(pos, skb->data, skb->len);
  174. pos += skb->len;
  175. if (pad_len) {
  176. memset(pos, 0, pad_len);
  177. pos += pad_len;
  178. }
  179. pos += qcafrm_create_footer(pos);
  180. netif_stop_queue(qca->net_dev);
  181. written = serdev_device_write_buf(qca->serdev, qca->tx_buffer,
  182. pos - qca->tx_buffer);
  183. if (written > 0) {
  184. qca->tx_left = (pos - qca->tx_buffer) - written;
  185. qca->tx_head = qca->tx_buffer + written;
  186. n_stats->tx_bytes += written;
  187. }
  188. spin_unlock(&qca->lock);
  189. netif_trans_update(dev);
  190. out:
  191. dev_kfree_skb_any(skb);
  192. return NETDEV_TX_OK;
  193. }
  194. static void qcauart_netdev_tx_timeout(struct net_device *dev, unsigned int txqueue)
  195. {
  196. struct qcauart *qca = netdev_priv(dev);
  197. netdev_info(qca->net_dev, "Transmit timeout at %ld, latency %ld\n",
  198. jiffies, dev_trans_start(dev));
  199. dev->stats.tx_errors++;
  200. dev->stats.tx_dropped++;
  201. }
  202. static int qcauart_netdev_init(struct net_device *dev)
  203. {
  204. struct qcauart *qca = netdev_priv(dev);
  205. size_t len;
  206. /* Finish setting up the device info. */
  207. dev->mtu = QCAFRM_MAX_MTU;
  208. dev->type = ARPHRD_ETHER;
  209. len = QCAFRM_HEADER_LEN + QCAFRM_MAX_LEN + QCAFRM_FOOTER_LEN;
  210. qca->tx_buffer = devm_kmalloc(&qca->serdev->dev, len, GFP_KERNEL);
  211. if (!qca->tx_buffer)
  212. return -ENOMEM;
  213. qca->rx_skb = netdev_alloc_skb_ip_align(qca->net_dev,
  214. qca->net_dev->mtu +
  215. VLAN_ETH_HLEN);
  216. if (!qca->rx_skb)
  217. return -ENOBUFS;
  218. return 0;
  219. }
  220. static void qcauart_netdev_uninit(struct net_device *dev)
  221. {
  222. struct qcauart *qca = netdev_priv(dev);
  223. dev_kfree_skb(qca->rx_skb);
  224. }
  225. static const struct net_device_ops qcauart_netdev_ops = {
  226. .ndo_init = qcauart_netdev_init,
  227. .ndo_uninit = qcauart_netdev_uninit,
  228. .ndo_open = qcauart_netdev_open,
  229. .ndo_stop = qcauart_netdev_close,
  230. .ndo_start_xmit = qcauart_netdev_xmit,
  231. .ndo_set_mac_address = eth_mac_addr,
  232. .ndo_tx_timeout = qcauart_netdev_tx_timeout,
  233. .ndo_validate_addr = eth_validate_addr,
  234. };
  235. static void qcauart_netdev_setup(struct net_device *dev)
  236. {
  237. dev->netdev_ops = &qcauart_netdev_ops;
  238. dev->watchdog_timeo = QCAUART_TX_TIMEOUT;
  239. dev->priv_flags &= ~IFF_TX_SKB_SHARING;
  240. dev->tx_queue_len = 100;
  241. /* MTU range: 46 - 1500 */
  242. dev->min_mtu = QCAFRM_MIN_MTU;
  243. dev->max_mtu = QCAFRM_MAX_MTU;
  244. }
  245. static const struct of_device_id qca_uart_of_match[] = {
  246. {
  247. .compatible = "qca,qca7000",
  248. },
  249. {}
  250. };
  251. MODULE_DEVICE_TABLE(of, qca_uart_of_match);
  252. static int qca_uart_probe(struct serdev_device *serdev)
  253. {
  254. struct net_device *qcauart_dev = alloc_etherdev(sizeof(struct qcauart));
  255. struct qcauart *qca;
  256. u32 speed = 115200;
  257. int ret;
  258. if (!qcauart_dev)
  259. return -ENOMEM;
  260. qcauart_netdev_setup(qcauart_dev);
  261. SET_NETDEV_DEV(qcauart_dev, &serdev->dev);
  262. qca = netdev_priv(qcauart_dev);
  263. if (!qca) {
  264. pr_err("qca_uart: Fail to retrieve private structure\n");
  265. ret = -ENOMEM;
  266. goto free;
  267. }
  268. qca->net_dev = qcauart_dev;
  269. qca->serdev = serdev;
  270. qcafrm_fsm_init_uart(&qca->frm_handle);
  271. spin_lock_init(&qca->lock);
  272. INIT_WORK(&qca->tx_work, qcauart_transmit);
  273. of_property_read_u32(serdev->dev.of_node, "current-speed", &speed);
  274. ret = of_get_ethdev_address(serdev->dev.of_node, qca->net_dev);
  275. if (ret) {
  276. eth_hw_addr_random(qca->net_dev);
  277. dev_info(&serdev->dev, "Using random MAC address: %pM\n",
  278. qca->net_dev->dev_addr);
  279. }
  280. netif_carrier_on(qca->net_dev);
  281. serdev_device_set_drvdata(serdev, qca);
  282. serdev_device_set_client_ops(serdev, &qca_serdev_ops);
  283. ret = serdev_device_open(serdev);
  284. if (ret) {
  285. dev_err(&serdev->dev, "Unable to open device %s\n",
  286. qcauart_dev->name);
  287. goto free;
  288. }
  289. speed = serdev_device_set_baudrate(serdev, speed);
  290. dev_info(&serdev->dev, "Using baudrate: %u\n", speed);
  291. serdev_device_set_flow_control(serdev, false);
  292. ret = register_netdev(qcauart_dev);
  293. if (ret) {
  294. dev_err(&serdev->dev, "Unable to register net device %s\n",
  295. qcauart_dev->name);
  296. serdev_device_close(serdev);
  297. cancel_work_sync(&qca->tx_work);
  298. goto free;
  299. }
  300. return 0;
  301. free:
  302. free_netdev(qcauart_dev);
  303. return ret;
  304. }
  305. static void qca_uart_remove(struct serdev_device *serdev)
  306. {
  307. struct qcauart *qca = serdev_device_get_drvdata(serdev);
  308. unregister_netdev(qca->net_dev);
  309. /* Flush any pending characters in the driver. */
  310. serdev_device_close(serdev);
  311. cancel_work_sync(&qca->tx_work);
  312. free_netdev(qca->net_dev);
  313. }
  314. static struct serdev_device_driver qca_uart_driver = {
  315. .probe = qca_uart_probe,
  316. .remove = qca_uart_remove,
  317. .driver = {
  318. .name = QCAUART_DRV_NAME,
  319. .of_match_table = qca_uart_of_match,
  320. },
  321. };
  322. module_serdev_device_driver(qca_uart_driver);
  323. MODULE_DESCRIPTION("Qualcomm Atheros QCA7000 UART Driver");
  324. MODULE_AUTHOR("Qualcomm Atheros Communications");
  325. MODULE_AUTHOR("Stefan Wahren <wahrenst@gmx.net>");
  326. MODULE_LICENSE("Dual BSD/GPL");
  327. MODULE_VERSION(QCAUART_DRV_VERSION);