cc2520.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264
  1. /* Driver for TI CC2520 802.15.4 Wireless-PAN Networking controller
  2. *
  3. * Copyright (C) 2014 Varka Bhadram <varkab@cdac.in>
  4. * Md.Jamal Mohiuddin <mjmohiuddin@cdac.in>
  5. * P Sowjanya <sowjanyap@cdac.in>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/gpio.h>
  16. #include <linux/delay.h>
  17. #include <linux/spi/spi.h>
  18. #include <linux/spi/cc2520.h>
  19. #include <linux/workqueue.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/skbuff.h>
  22. #include <linux/of_gpio.h>
  23. #include <linux/ieee802154.h>
  24. #include <linux/crc-ccitt.h>
  25. #include <asm/unaligned.h>
  26. #include <net/mac802154.h>
  27. #include <net/cfg802154.h>
  28. #define SPI_COMMAND_BUFFER 3
  29. #define HIGH 1
  30. #define LOW 0
  31. #define STATE_IDLE 0
  32. #define RSSI_VALID 0
  33. #define RSSI_OFFSET 78
  34. #define CC2520_RAM_SIZE 640
  35. #define CC2520_FIFO_SIZE 128
  36. #define CC2520RAM_TXFIFO 0x100
  37. #define CC2520RAM_RXFIFO 0x180
  38. #define CC2520RAM_IEEEADDR 0x3EA
  39. #define CC2520RAM_PANID 0x3F2
  40. #define CC2520RAM_SHORTADDR 0x3F4
  41. #define CC2520_FREG_MASK 0x3F
  42. /* status byte values */
  43. #define CC2520_STATUS_XOSC32M_STABLE BIT(7)
  44. #define CC2520_STATUS_RSSI_VALID BIT(6)
  45. #define CC2520_STATUS_TX_UNDERFLOW BIT(3)
  46. /* IEEE-802.15.4 defined constants (2.4 GHz logical channels) */
  47. #define CC2520_MINCHANNEL 11
  48. #define CC2520_MAXCHANNEL 26
  49. #define CC2520_CHANNEL_SPACING 5
  50. /* command strobes */
  51. #define CC2520_CMD_SNOP 0x00
  52. #define CC2520_CMD_IBUFLD 0x02
  53. #define CC2520_CMD_SIBUFEX 0x03
  54. #define CC2520_CMD_SSAMPLECCA 0x04
  55. #define CC2520_CMD_SRES 0x0f
  56. #define CC2520_CMD_MEMORY_MASK 0x0f
  57. #define CC2520_CMD_MEMORY_READ 0x10
  58. #define CC2520_CMD_MEMORY_WRITE 0x20
  59. #define CC2520_CMD_RXBUF 0x30
  60. #define CC2520_CMD_RXBUFCP 0x38
  61. #define CC2520_CMD_RXBUFMOV 0x32
  62. #define CC2520_CMD_TXBUF 0x3A
  63. #define CC2520_CMD_TXBUFCP 0x3E
  64. #define CC2520_CMD_RANDOM 0x3C
  65. #define CC2520_CMD_SXOSCON 0x40
  66. #define CC2520_CMD_STXCAL 0x41
  67. #define CC2520_CMD_SRXON 0x42
  68. #define CC2520_CMD_STXON 0x43
  69. #define CC2520_CMD_STXONCCA 0x44
  70. #define CC2520_CMD_SRFOFF 0x45
  71. #define CC2520_CMD_SXOSCOFF 0x46
  72. #define CC2520_CMD_SFLUSHRX 0x47
  73. #define CC2520_CMD_SFLUSHTX 0x48
  74. #define CC2520_CMD_SACK 0x49
  75. #define CC2520_CMD_SACKPEND 0x4A
  76. #define CC2520_CMD_SNACK 0x4B
  77. #define CC2520_CMD_SRXMASKBITSET 0x4C
  78. #define CC2520_CMD_SRXMASKBITCLR 0x4D
  79. #define CC2520_CMD_RXMASKAND 0x4E
  80. #define CC2520_CMD_RXMASKOR 0x4F
  81. #define CC2520_CMD_MEMCP 0x50
  82. #define CC2520_CMD_MEMCPR 0x52
  83. #define CC2520_CMD_MEMXCP 0x54
  84. #define CC2520_CMD_MEMXWR 0x56
  85. #define CC2520_CMD_BCLR 0x58
  86. #define CC2520_CMD_BSET 0x59
  87. #define CC2520_CMD_CTR_UCTR 0x60
  88. #define CC2520_CMD_CBCMAC 0x64
  89. #define CC2520_CMD_UCBCMAC 0x66
  90. #define CC2520_CMD_CCM 0x68
  91. #define CC2520_CMD_UCCM 0x6A
  92. #define CC2520_CMD_ECB 0x70
  93. #define CC2520_CMD_ECBO 0x72
  94. #define CC2520_CMD_ECBX 0x74
  95. #define CC2520_CMD_INC 0x78
  96. #define CC2520_CMD_ABORT 0x7F
  97. #define CC2520_CMD_REGISTER_READ 0x80
  98. #define CC2520_CMD_REGISTER_WRITE 0xC0
  99. /* status registers */
  100. #define CC2520_CHIPID 0x40
  101. #define CC2520_VERSION 0x42
  102. #define CC2520_EXTCLOCK 0x44
  103. #define CC2520_MDMCTRL0 0x46
  104. #define CC2520_MDMCTRL1 0x47
  105. #define CC2520_FREQEST 0x48
  106. #define CC2520_RXCTRL 0x4A
  107. #define CC2520_FSCTRL 0x4C
  108. #define CC2520_FSCAL0 0x4E
  109. #define CC2520_FSCAL1 0x4F
  110. #define CC2520_FSCAL2 0x50
  111. #define CC2520_FSCAL3 0x51
  112. #define CC2520_AGCCTRL0 0x52
  113. #define CC2520_AGCCTRL1 0x53
  114. #define CC2520_AGCCTRL2 0x54
  115. #define CC2520_AGCCTRL3 0x55
  116. #define CC2520_ADCTEST0 0x56
  117. #define CC2520_ADCTEST1 0x57
  118. #define CC2520_ADCTEST2 0x58
  119. #define CC2520_MDMTEST0 0x5A
  120. #define CC2520_MDMTEST1 0x5B
  121. #define CC2520_DACTEST0 0x5C
  122. #define CC2520_DACTEST1 0x5D
  123. #define CC2520_ATEST 0x5E
  124. #define CC2520_DACTEST2 0x5F
  125. #define CC2520_PTEST0 0x60
  126. #define CC2520_PTEST1 0x61
  127. #define CC2520_RESERVED 0x62
  128. #define CC2520_DPUBIST 0x7A
  129. #define CC2520_ACTBIST 0x7C
  130. #define CC2520_RAMBIST 0x7E
  131. /* frame registers */
  132. #define CC2520_FRMFILT0 0x00
  133. #define CC2520_FRMFILT1 0x01
  134. #define CC2520_SRCMATCH 0x02
  135. #define CC2520_SRCSHORTEN0 0x04
  136. #define CC2520_SRCSHORTEN1 0x05
  137. #define CC2520_SRCSHORTEN2 0x06
  138. #define CC2520_SRCEXTEN0 0x08
  139. #define CC2520_SRCEXTEN1 0x09
  140. #define CC2520_SRCEXTEN2 0x0A
  141. #define CC2520_FRMCTRL0 0x0C
  142. #define CC2520_FRMCTRL1 0x0D
  143. #define CC2520_RXENABLE0 0x0E
  144. #define CC2520_RXENABLE1 0x0F
  145. #define CC2520_EXCFLAG0 0x10
  146. #define CC2520_EXCFLAG1 0x11
  147. #define CC2520_EXCFLAG2 0x12
  148. #define CC2520_EXCMASKA0 0x14
  149. #define CC2520_EXCMASKA1 0x15
  150. #define CC2520_EXCMASKA2 0x16
  151. #define CC2520_EXCMASKB0 0x18
  152. #define CC2520_EXCMASKB1 0x19
  153. #define CC2520_EXCMASKB2 0x1A
  154. #define CC2520_EXCBINDX0 0x1C
  155. #define CC2520_EXCBINDX1 0x1D
  156. #define CC2520_EXCBINDY0 0x1E
  157. #define CC2520_EXCBINDY1 0x1F
  158. #define CC2520_GPIOCTRL0 0x20
  159. #define CC2520_GPIOCTRL1 0x21
  160. #define CC2520_GPIOCTRL2 0x22
  161. #define CC2520_GPIOCTRL3 0x23
  162. #define CC2520_GPIOCTRL4 0x24
  163. #define CC2520_GPIOCTRL5 0x25
  164. #define CC2520_GPIOPOLARITY 0x26
  165. #define CC2520_GPIOCTRL 0x28
  166. #define CC2520_DPUCON 0x2A
  167. #define CC2520_DPUSTAT 0x2C
  168. #define CC2520_FREQCTRL 0x2E
  169. #define CC2520_FREQTUNE 0x2F
  170. #define CC2520_TXPOWER 0x30
  171. #define CC2520_TXCTRL 0x31
  172. #define CC2520_FSMSTAT0 0x32
  173. #define CC2520_FSMSTAT1 0x33
  174. #define CC2520_FIFOPCTRL 0x34
  175. #define CC2520_FSMCTRL 0x35
  176. #define CC2520_CCACTRL0 0x36
  177. #define CC2520_CCACTRL1 0x37
  178. #define CC2520_RSSI 0x38
  179. #define CC2520_RSSISTAT 0x39
  180. #define CC2520_RXFIRST 0x3C
  181. #define CC2520_RXFIFOCNT 0x3E
  182. #define CC2520_TXFIFOCNT 0x3F
  183. /* CC2520_FRMFILT0 */
  184. #define FRMFILT0_FRAME_FILTER_EN BIT(0)
  185. #define FRMFILT0_PAN_COORDINATOR BIT(1)
  186. /* CC2520_FRMCTRL0 */
  187. #define FRMCTRL0_AUTOACK BIT(5)
  188. #define FRMCTRL0_AUTOCRC BIT(6)
  189. /* CC2520_FRMCTRL1 */
  190. #define FRMCTRL1_SET_RXENMASK_ON_TX BIT(0)
  191. #define FRMCTRL1_IGNORE_TX_UNDERF BIT(1)
  192. /* Driver private information */
  193. struct cc2520_private {
  194. struct spi_device *spi; /* SPI device structure */
  195. struct ieee802154_hw *hw; /* IEEE-802.15.4 device */
  196. u8 *buf; /* SPI TX/Rx data buffer */
  197. struct mutex buffer_mutex; /* SPI buffer mutex */
  198. bool is_tx; /* Flag for sync b/w Tx and Rx */
  199. bool amplified; /* Flag for CC2591 */
  200. int fifo_pin; /* FIFO GPIO pin number */
  201. struct work_struct fifop_irqwork;/* Workqueue for FIFOP */
  202. spinlock_t lock; /* Lock for is_tx*/
  203. struct completion tx_complete; /* Work completion for Tx */
  204. bool promiscuous; /* Flag for promiscuous mode */
  205. };
  206. /* Generic Functions */
  207. static int
  208. cc2520_cmd_strobe(struct cc2520_private *priv, u8 cmd)
  209. {
  210. int ret;
  211. u8 status = 0xff;
  212. struct spi_message msg;
  213. struct spi_transfer xfer = {
  214. .len = 0,
  215. .tx_buf = priv->buf,
  216. .rx_buf = priv->buf,
  217. };
  218. spi_message_init(&msg);
  219. spi_message_add_tail(&xfer, &msg);
  220. mutex_lock(&priv->buffer_mutex);
  221. priv->buf[xfer.len++] = cmd;
  222. dev_vdbg(&priv->spi->dev,
  223. "command strobe buf[0] = %02x\n",
  224. priv->buf[0]);
  225. ret = spi_sync(priv->spi, &msg);
  226. if (!ret)
  227. status = priv->buf[0];
  228. dev_vdbg(&priv->spi->dev,
  229. "buf[0] = %02x\n", priv->buf[0]);
  230. mutex_unlock(&priv->buffer_mutex);
  231. return ret;
  232. }
  233. static int
  234. cc2520_get_status(struct cc2520_private *priv, u8 *status)
  235. {
  236. int ret;
  237. struct spi_message msg;
  238. struct spi_transfer xfer = {
  239. .len = 0,
  240. .tx_buf = priv->buf,
  241. .rx_buf = priv->buf,
  242. };
  243. spi_message_init(&msg);
  244. spi_message_add_tail(&xfer, &msg);
  245. mutex_lock(&priv->buffer_mutex);
  246. priv->buf[xfer.len++] = CC2520_CMD_SNOP;
  247. dev_vdbg(&priv->spi->dev,
  248. "get status command buf[0] = %02x\n", priv->buf[0]);
  249. ret = spi_sync(priv->spi, &msg);
  250. if (!ret)
  251. *status = priv->buf[0];
  252. dev_vdbg(&priv->spi->dev,
  253. "buf[0] = %02x\n", priv->buf[0]);
  254. mutex_unlock(&priv->buffer_mutex);
  255. return ret;
  256. }
  257. static int
  258. cc2520_write_register(struct cc2520_private *priv, u8 reg, u8 value)
  259. {
  260. int status;
  261. struct spi_message msg;
  262. struct spi_transfer xfer = {
  263. .len = 0,
  264. .tx_buf = priv->buf,
  265. .rx_buf = priv->buf,
  266. };
  267. spi_message_init(&msg);
  268. spi_message_add_tail(&xfer, &msg);
  269. mutex_lock(&priv->buffer_mutex);
  270. if (reg <= CC2520_FREG_MASK) {
  271. priv->buf[xfer.len++] = CC2520_CMD_REGISTER_WRITE | reg;
  272. priv->buf[xfer.len++] = value;
  273. } else {
  274. priv->buf[xfer.len++] = CC2520_CMD_MEMORY_WRITE;
  275. priv->buf[xfer.len++] = reg;
  276. priv->buf[xfer.len++] = value;
  277. }
  278. status = spi_sync(priv->spi, &msg);
  279. if (msg.status)
  280. status = msg.status;
  281. mutex_unlock(&priv->buffer_mutex);
  282. return status;
  283. }
  284. static int
  285. cc2520_write_ram(struct cc2520_private *priv, u16 reg, u8 len, u8 *data)
  286. {
  287. int status;
  288. struct spi_message msg;
  289. struct spi_transfer xfer_head = {
  290. .len = 0,
  291. .tx_buf = priv->buf,
  292. .rx_buf = priv->buf,
  293. };
  294. struct spi_transfer xfer_buf = {
  295. .len = len,
  296. .tx_buf = data,
  297. };
  298. mutex_lock(&priv->buffer_mutex);
  299. priv->buf[xfer_head.len++] = (CC2520_CMD_MEMORY_WRITE |
  300. ((reg >> 8) & 0xff));
  301. priv->buf[xfer_head.len++] = reg & 0xff;
  302. spi_message_init(&msg);
  303. spi_message_add_tail(&xfer_head, &msg);
  304. spi_message_add_tail(&xfer_buf, &msg);
  305. status = spi_sync(priv->spi, &msg);
  306. dev_dbg(&priv->spi->dev, "spi status = %d\n", status);
  307. if (msg.status)
  308. status = msg.status;
  309. mutex_unlock(&priv->buffer_mutex);
  310. return status;
  311. }
  312. static int
  313. cc2520_read_register(struct cc2520_private *priv, u8 reg, u8 *data)
  314. {
  315. int status;
  316. struct spi_message msg;
  317. struct spi_transfer xfer1 = {
  318. .len = 0,
  319. .tx_buf = priv->buf,
  320. .rx_buf = priv->buf,
  321. };
  322. struct spi_transfer xfer2 = {
  323. .len = 1,
  324. .rx_buf = data,
  325. };
  326. spi_message_init(&msg);
  327. spi_message_add_tail(&xfer1, &msg);
  328. spi_message_add_tail(&xfer2, &msg);
  329. mutex_lock(&priv->buffer_mutex);
  330. priv->buf[xfer1.len++] = CC2520_CMD_MEMORY_READ;
  331. priv->buf[xfer1.len++] = reg;
  332. status = spi_sync(priv->spi, &msg);
  333. dev_dbg(&priv->spi->dev,
  334. "spi status = %d\n", status);
  335. if (msg.status)
  336. status = msg.status;
  337. mutex_unlock(&priv->buffer_mutex);
  338. return status;
  339. }
  340. static int
  341. cc2520_write_txfifo(struct cc2520_private *priv, u8 pkt_len, u8 *data, u8 len)
  342. {
  343. int status;
  344. /* length byte must include FCS even
  345. * if it is calculated in the hardware
  346. */
  347. int len_byte = pkt_len;
  348. struct spi_message msg;
  349. struct spi_transfer xfer_head = {
  350. .len = 0,
  351. .tx_buf = priv->buf,
  352. .rx_buf = priv->buf,
  353. };
  354. struct spi_transfer xfer_len = {
  355. .len = 1,
  356. .tx_buf = &len_byte,
  357. };
  358. struct spi_transfer xfer_buf = {
  359. .len = len,
  360. .tx_buf = data,
  361. };
  362. spi_message_init(&msg);
  363. spi_message_add_tail(&xfer_head, &msg);
  364. spi_message_add_tail(&xfer_len, &msg);
  365. spi_message_add_tail(&xfer_buf, &msg);
  366. mutex_lock(&priv->buffer_mutex);
  367. priv->buf[xfer_head.len++] = CC2520_CMD_TXBUF;
  368. dev_vdbg(&priv->spi->dev,
  369. "TX_FIFO cmd buf[0] = %02x\n", priv->buf[0]);
  370. status = spi_sync(priv->spi, &msg);
  371. dev_vdbg(&priv->spi->dev, "status = %d\n", status);
  372. if (msg.status)
  373. status = msg.status;
  374. dev_vdbg(&priv->spi->dev, "status = %d\n", status);
  375. dev_vdbg(&priv->spi->dev, "buf[0] = %02x\n", priv->buf[0]);
  376. mutex_unlock(&priv->buffer_mutex);
  377. return status;
  378. }
  379. static int
  380. cc2520_read_rxfifo(struct cc2520_private *priv, u8 *data, u8 len)
  381. {
  382. int status;
  383. struct spi_message msg;
  384. struct spi_transfer xfer_head = {
  385. .len = 0,
  386. .tx_buf = priv->buf,
  387. .rx_buf = priv->buf,
  388. };
  389. struct spi_transfer xfer_buf = {
  390. .len = len,
  391. .rx_buf = data,
  392. };
  393. spi_message_init(&msg);
  394. spi_message_add_tail(&xfer_head, &msg);
  395. spi_message_add_tail(&xfer_buf, &msg);
  396. mutex_lock(&priv->buffer_mutex);
  397. priv->buf[xfer_head.len++] = CC2520_CMD_RXBUF;
  398. dev_vdbg(&priv->spi->dev, "read rxfifo buf[0] = %02x\n", priv->buf[0]);
  399. dev_vdbg(&priv->spi->dev, "buf[1] = %02x\n", priv->buf[1]);
  400. status = spi_sync(priv->spi, &msg);
  401. dev_vdbg(&priv->spi->dev, "status = %d\n", status);
  402. if (msg.status)
  403. status = msg.status;
  404. dev_vdbg(&priv->spi->dev, "status = %d\n", status);
  405. dev_vdbg(&priv->spi->dev,
  406. "return status buf[0] = %02x\n", priv->buf[0]);
  407. dev_vdbg(&priv->spi->dev, "length buf[1] = %02x\n", priv->buf[1]);
  408. mutex_unlock(&priv->buffer_mutex);
  409. return status;
  410. }
  411. static int cc2520_start(struct ieee802154_hw *hw)
  412. {
  413. return cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRXON);
  414. }
  415. static void cc2520_stop(struct ieee802154_hw *hw)
  416. {
  417. cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRFOFF);
  418. }
  419. static int
  420. cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
  421. {
  422. struct cc2520_private *priv = hw->priv;
  423. unsigned long flags;
  424. int rc;
  425. u8 status = 0;
  426. u8 pkt_len;
  427. /* In promiscuous mode we disable AUTOCRC so we can get the raw CRC
  428. * values on RX. This means we need to manually add the CRC on TX.
  429. */
  430. if (priv->promiscuous) {
  431. u16 crc = crc_ccitt(0, skb->data, skb->len);
  432. put_unaligned_le16(crc, skb_put(skb, 2));
  433. pkt_len = skb->len;
  434. } else {
  435. pkt_len = skb->len + 2;
  436. }
  437. rc = cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
  438. if (rc)
  439. goto err_tx;
  440. rc = cc2520_write_txfifo(priv, pkt_len, skb->data, skb->len);
  441. if (rc)
  442. goto err_tx;
  443. rc = cc2520_get_status(priv, &status);
  444. if (rc)
  445. goto err_tx;
  446. if (status & CC2520_STATUS_TX_UNDERFLOW) {
  447. dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n");
  448. goto err_tx;
  449. }
  450. spin_lock_irqsave(&priv->lock, flags);
  451. BUG_ON(priv->is_tx);
  452. priv->is_tx = 1;
  453. spin_unlock_irqrestore(&priv->lock, flags);
  454. rc = cc2520_cmd_strobe(priv, CC2520_CMD_STXONCCA);
  455. if (rc)
  456. goto err;
  457. rc = wait_for_completion_interruptible(&priv->tx_complete);
  458. if (rc < 0)
  459. goto err;
  460. cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHTX);
  461. cc2520_cmd_strobe(priv, CC2520_CMD_SRXON);
  462. return rc;
  463. err:
  464. spin_lock_irqsave(&priv->lock, flags);
  465. priv->is_tx = 0;
  466. spin_unlock_irqrestore(&priv->lock, flags);
  467. err_tx:
  468. return rc;
  469. }
  470. static int cc2520_rx(struct cc2520_private *priv)
  471. {
  472. u8 len = 0, lqi = 0, bytes = 1;
  473. struct sk_buff *skb;
  474. /* Read single length byte from the radio. */
  475. cc2520_read_rxfifo(priv, &len, bytes);
  476. if (!ieee802154_is_valid_psdu_len(len)) {
  477. /* Corrupted frame received, clear frame buffer by
  478. * reading entire buffer.
  479. */
  480. dev_dbg(&priv->spi->dev, "corrupted frame received\n");
  481. len = IEEE802154_MTU;
  482. }
  483. skb = dev_alloc_skb(len);
  484. if (!skb)
  485. return -ENOMEM;
  486. if (cc2520_read_rxfifo(priv, skb_put(skb, len), len)) {
  487. dev_dbg(&priv->spi->dev, "frame reception failed\n");
  488. kfree_skb(skb);
  489. return -EINVAL;
  490. }
  491. /* In promiscuous mode, we configure the radio to include the
  492. * CRC (AUTOCRC==0) and we pass on the packet unconditionally. If not
  493. * in promiscuous mode, we check the CRC here, but leave the
  494. * RSSI/LQI/CRC_OK bytes as they will get removed in the mac layer.
  495. */
  496. if (!priv->promiscuous) {
  497. bool crc_ok;
  498. /* Check if the CRC is valid. With AUTOCRC set, the most
  499. * significant bit of the last byte returned from the CC2520
  500. * is CRC_OK flag. See section 20.3.4 of the datasheet.
  501. */
  502. crc_ok = skb->data[len - 1] & BIT(7);
  503. /* If we failed CRC drop the packet in the driver layer. */
  504. if (!crc_ok) {
  505. dev_dbg(&priv->spi->dev, "CRC check failed\n");
  506. kfree_skb(skb);
  507. return -EINVAL;
  508. }
  509. /* To calculate LQI, the lower 7 bits of the last byte (the
  510. * correlation value provided by the radio) must be scaled to
  511. * the range 0-255. According to section 20.6, the correlation
  512. * value ranges from 50-110. Ideally this would be calibrated
  513. * per hardware design, but we use roughly the datasheet values
  514. * to get close enough while avoiding floating point.
  515. */
  516. lqi = skb->data[len - 1] & 0x7f;
  517. if (lqi < 50)
  518. lqi = 50;
  519. else if (lqi > 113)
  520. lqi = 113;
  521. lqi = (lqi - 50) * 4;
  522. }
  523. ieee802154_rx_irqsafe(priv->hw, skb, lqi);
  524. dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi);
  525. return 0;
  526. }
  527. static int
  528. cc2520_ed(struct ieee802154_hw *hw, u8 *level)
  529. {
  530. struct cc2520_private *priv = hw->priv;
  531. u8 status = 0xff;
  532. u8 rssi;
  533. int ret;
  534. ret = cc2520_read_register(priv, CC2520_RSSISTAT, &status);
  535. if (ret)
  536. return ret;
  537. if (status != RSSI_VALID)
  538. return -EINVAL;
  539. ret = cc2520_read_register(priv, CC2520_RSSI, &rssi);
  540. if (ret)
  541. return ret;
  542. /* level = RSSI(rssi) - OFFSET [dBm] : offset is 76dBm */
  543. *level = rssi - RSSI_OFFSET;
  544. return 0;
  545. }
  546. static int
  547. cc2520_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
  548. {
  549. struct cc2520_private *priv = hw->priv;
  550. int ret;
  551. dev_dbg(&priv->spi->dev, "trying to set channel\n");
  552. BUG_ON(page != 0);
  553. BUG_ON(channel < CC2520_MINCHANNEL);
  554. BUG_ON(channel > CC2520_MAXCHANNEL);
  555. ret = cc2520_write_register(priv, CC2520_FREQCTRL,
  556. 11 + 5*(channel - 11));
  557. return ret;
  558. }
  559. static int
  560. cc2520_filter(struct ieee802154_hw *hw,
  561. struct ieee802154_hw_addr_filt *filt, unsigned long changed)
  562. {
  563. struct cc2520_private *priv = hw->priv;
  564. int ret = 0;
  565. if (changed & IEEE802154_AFILT_PANID_CHANGED) {
  566. u16 panid = le16_to_cpu(filt->pan_id);
  567. dev_vdbg(&priv->spi->dev,
  568. "cc2520_filter called for pan id\n");
  569. ret = cc2520_write_ram(priv, CC2520RAM_PANID,
  570. sizeof(panid), (u8 *)&panid);
  571. }
  572. if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
  573. dev_vdbg(&priv->spi->dev,
  574. "cc2520_filter called for IEEE addr\n");
  575. ret = cc2520_write_ram(priv, CC2520RAM_IEEEADDR,
  576. sizeof(filt->ieee_addr),
  577. (u8 *)&filt->ieee_addr);
  578. }
  579. if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
  580. u16 addr = le16_to_cpu(filt->short_addr);
  581. dev_vdbg(&priv->spi->dev,
  582. "cc2520_filter called for saddr\n");
  583. ret = cc2520_write_ram(priv, CC2520RAM_SHORTADDR,
  584. sizeof(addr), (u8 *)&addr);
  585. }
  586. if (changed & IEEE802154_AFILT_PANC_CHANGED) {
  587. u8 frmfilt0;
  588. dev_vdbg(&priv->spi->dev,
  589. "cc2520_filter called for panc change\n");
  590. cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
  591. if (filt->pan_coord)
  592. frmfilt0 |= FRMFILT0_PAN_COORDINATOR;
  593. else
  594. frmfilt0 &= ~FRMFILT0_PAN_COORDINATOR;
  595. ret = cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
  596. }
  597. return ret;
  598. }
  599. static inline int cc2520_set_tx_power(struct cc2520_private *priv, s32 mbm)
  600. {
  601. u8 power;
  602. switch (mbm) {
  603. case 500:
  604. power = 0xF7;
  605. break;
  606. case 300:
  607. power = 0xF2;
  608. break;
  609. case 200:
  610. power = 0xAB;
  611. break;
  612. case 100:
  613. power = 0x13;
  614. break;
  615. case 0:
  616. power = 0x32;
  617. break;
  618. case -200:
  619. power = 0x81;
  620. break;
  621. case -400:
  622. power = 0x88;
  623. break;
  624. case -700:
  625. power = 0x2C;
  626. break;
  627. case -1800:
  628. power = 0x03;
  629. break;
  630. default:
  631. return -EINVAL;
  632. }
  633. return cc2520_write_register(priv, CC2520_TXPOWER, power);
  634. }
  635. static inline int cc2520_cc2591_set_tx_power(struct cc2520_private *priv,
  636. s32 mbm)
  637. {
  638. u8 power;
  639. switch (mbm) {
  640. case 1700:
  641. power = 0xF9;
  642. break;
  643. case 1600:
  644. power = 0xF0;
  645. break;
  646. case 1400:
  647. power = 0xA0;
  648. break;
  649. case 1100:
  650. power = 0x2C;
  651. break;
  652. case -100:
  653. power = 0x03;
  654. break;
  655. case -800:
  656. power = 0x01;
  657. break;
  658. default:
  659. return -EINVAL;
  660. }
  661. return cc2520_write_register(priv, CC2520_TXPOWER, power);
  662. }
  663. #define CC2520_MAX_TX_POWERS 0x8
  664. static const s32 cc2520_powers[CC2520_MAX_TX_POWERS + 1] = {
  665. 500, 300, 200, 100, 0, -200, -400, -700, -1800,
  666. };
  667. #define CC2520_CC2591_MAX_TX_POWERS 0x5
  668. static const s32 cc2520_cc2591_powers[CC2520_CC2591_MAX_TX_POWERS + 1] = {
  669. 1700, 1600, 1400, 1100, -100, -800,
  670. };
  671. static int
  672. cc2520_set_txpower(struct ieee802154_hw *hw, s32 mbm)
  673. {
  674. struct cc2520_private *priv = hw->priv;
  675. if (!priv->amplified)
  676. return cc2520_set_tx_power(priv, mbm);
  677. return cc2520_cc2591_set_tx_power(priv, mbm);
  678. }
  679. static int
  680. cc2520_set_promiscuous_mode(struct ieee802154_hw *hw, bool on)
  681. {
  682. struct cc2520_private *priv = hw->priv;
  683. u8 frmfilt0;
  684. dev_dbg(&priv->spi->dev, "%s : mode %d\n", __func__, on);
  685. priv->promiscuous = on;
  686. cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
  687. if (on) {
  688. /* Disable automatic ACK, automatic CRC, and frame filtering. */
  689. cc2520_write_register(priv, CC2520_FRMCTRL0, 0);
  690. frmfilt0 &= ~FRMFILT0_FRAME_FILTER_EN;
  691. } else {
  692. cc2520_write_register(priv, CC2520_FRMCTRL0, FRMCTRL0_AUTOACK |
  693. FRMCTRL0_AUTOCRC);
  694. frmfilt0 |= FRMFILT0_FRAME_FILTER_EN;
  695. }
  696. return cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
  697. }
  698. static const struct ieee802154_ops cc2520_ops = {
  699. .owner = THIS_MODULE,
  700. .start = cc2520_start,
  701. .stop = cc2520_stop,
  702. .xmit_sync = cc2520_tx,
  703. .ed = cc2520_ed,
  704. .set_channel = cc2520_set_channel,
  705. .set_hw_addr_filt = cc2520_filter,
  706. .set_txpower = cc2520_set_txpower,
  707. .set_promiscuous_mode = cc2520_set_promiscuous_mode,
  708. };
  709. static int cc2520_register(struct cc2520_private *priv)
  710. {
  711. int ret = -ENOMEM;
  712. priv->hw = ieee802154_alloc_hw(sizeof(*priv), &cc2520_ops);
  713. if (!priv->hw)
  714. goto err_ret;
  715. priv->hw->priv = priv;
  716. priv->hw->parent = &priv->spi->dev;
  717. priv->hw->extra_tx_headroom = 0;
  718. ieee802154_random_extended_addr(&priv->hw->phy->perm_extended_addr);
  719. /* We do support only 2.4 Ghz */
  720. priv->hw->phy->supported.channels[0] = 0x7FFF800;
  721. priv->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
  722. IEEE802154_HW_PROMISCUOUS;
  723. priv->hw->phy->flags = WPAN_PHY_FLAG_TXPOWER;
  724. if (!priv->amplified) {
  725. priv->hw->phy->supported.tx_powers = cc2520_powers;
  726. priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_powers);
  727. priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[4];
  728. } else {
  729. priv->hw->phy->supported.tx_powers = cc2520_cc2591_powers;
  730. priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_cc2591_powers);
  731. priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[0];
  732. }
  733. priv->hw->phy->current_channel = 11;
  734. dev_vdbg(&priv->spi->dev, "registered cc2520\n");
  735. ret = ieee802154_register_hw(priv->hw);
  736. if (ret)
  737. goto err_free_device;
  738. return 0;
  739. err_free_device:
  740. ieee802154_free_hw(priv->hw);
  741. err_ret:
  742. return ret;
  743. }
  744. static void cc2520_fifop_irqwork(struct work_struct *work)
  745. {
  746. struct cc2520_private *priv
  747. = container_of(work, struct cc2520_private, fifop_irqwork);
  748. dev_dbg(&priv->spi->dev, "fifop interrupt received\n");
  749. if (gpio_get_value(priv->fifo_pin))
  750. cc2520_rx(priv);
  751. else
  752. dev_dbg(&priv->spi->dev, "rxfifo overflow\n");
  753. cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
  754. cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
  755. }
  756. static irqreturn_t cc2520_fifop_isr(int irq, void *data)
  757. {
  758. struct cc2520_private *priv = data;
  759. schedule_work(&priv->fifop_irqwork);
  760. return IRQ_HANDLED;
  761. }
  762. static irqreturn_t cc2520_sfd_isr(int irq, void *data)
  763. {
  764. struct cc2520_private *priv = data;
  765. unsigned long flags;
  766. spin_lock_irqsave(&priv->lock, flags);
  767. if (priv->is_tx) {
  768. priv->is_tx = 0;
  769. spin_unlock_irqrestore(&priv->lock, flags);
  770. dev_dbg(&priv->spi->dev, "SFD for TX\n");
  771. complete(&priv->tx_complete);
  772. } else {
  773. spin_unlock_irqrestore(&priv->lock, flags);
  774. dev_dbg(&priv->spi->dev, "SFD for RX\n");
  775. }
  776. return IRQ_HANDLED;
  777. }
  778. static int cc2520_get_platform_data(struct spi_device *spi,
  779. struct cc2520_platform_data *pdata)
  780. {
  781. struct device_node *np = spi->dev.of_node;
  782. struct cc2520_private *priv = spi_get_drvdata(spi);
  783. if (!np) {
  784. struct cc2520_platform_data *spi_pdata = spi->dev.platform_data;
  785. if (!spi_pdata)
  786. return -ENOENT;
  787. *pdata = *spi_pdata;
  788. priv->fifo_pin = pdata->fifo;
  789. return 0;
  790. }
  791. pdata->fifo = of_get_named_gpio(np, "fifo-gpio", 0);
  792. priv->fifo_pin = pdata->fifo;
  793. pdata->fifop = of_get_named_gpio(np, "fifop-gpio", 0);
  794. pdata->sfd = of_get_named_gpio(np, "sfd-gpio", 0);
  795. pdata->cca = of_get_named_gpio(np, "cca-gpio", 0);
  796. pdata->vreg = of_get_named_gpio(np, "vreg-gpio", 0);
  797. pdata->reset = of_get_named_gpio(np, "reset-gpio", 0);
  798. /* CC2591 front end for CC2520 */
  799. if (of_property_read_bool(np, "amplified"))
  800. priv->amplified = true;
  801. return 0;
  802. }
  803. static int cc2520_hw_init(struct cc2520_private *priv)
  804. {
  805. u8 status = 0, state = 0xff;
  806. int ret;
  807. int timeout = 100;
  808. struct cc2520_platform_data pdata;
  809. ret = cc2520_get_platform_data(priv->spi, &pdata);
  810. if (ret)
  811. goto err_ret;
  812. ret = cc2520_read_register(priv, CC2520_FSMSTAT1, &state);
  813. if (ret)
  814. goto err_ret;
  815. if (state != STATE_IDLE)
  816. return -EINVAL;
  817. do {
  818. ret = cc2520_get_status(priv, &status);
  819. if (ret)
  820. goto err_ret;
  821. if (timeout-- <= 0) {
  822. dev_err(&priv->spi->dev, "oscillator start failed!\n");
  823. return ret;
  824. }
  825. udelay(1);
  826. } while (!(status & CC2520_STATUS_XOSC32M_STABLE));
  827. dev_vdbg(&priv->spi->dev, "oscillator brought up\n");
  828. /* If the CC2520 is connected to a CC2591 amplifier, we must both
  829. * configure GPIOs on the CC2520 to correctly configure the CC2591
  830. * and change a couple settings of the CC2520 to work with the
  831. * amplifier. See section 8 page 17 of TI application note AN065.
  832. * http://www.ti.com/lit/an/swra229a/swra229a.pdf
  833. */
  834. if (priv->amplified) {
  835. ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x16);
  836. if (ret)
  837. goto err_ret;
  838. ret = cc2520_write_register(priv, CC2520_GPIOCTRL0, 0x46);
  839. if (ret)
  840. goto err_ret;
  841. ret = cc2520_write_register(priv, CC2520_GPIOCTRL5, 0x47);
  842. if (ret)
  843. goto err_ret;
  844. ret = cc2520_write_register(priv, CC2520_GPIOPOLARITY, 0x1e);
  845. if (ret)
  846. goto err_ret;
  847. ret = cc2520_write_register(priv, CC2520_TXCTRL, 0xc1);
  848. if (ret)
  849. goto err_ret;
  850. } else {
  851. ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11);
  852. if (ret)
  853. goto err_ret;
  854. }
  855. /* Registers default value: section 28.1 in Datasheet */
  856. /* Set the CCA threshold to -50 dBm. This seems to have been copied
  857. * from the TinyOS CC2520 driver and is much higher than the -84 dBm
  858. * threshold suggested in the datasheet.
  859. */
  860. ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A);
  861. if (ret)
  862. goto err_ret;
  863. ret = cc2520_write_register(priv, CC2520_MDMCTRL0, 0x85);
  864. if (ret)
  865. goto err_ret;
  866. ret = cc2520_write_register(priv, CC2520_MDMCTRL1, 0x14);
  867. if (ret)
  868. goto err_ret;
  869. ret = cc2520_write_register(priv, CC2520_RXCTRL, 0x3f);
  870. if (ret)
  871. goto err_ret;
  872. ret = cc2520_write_register(priv, CC2520_FSCTRL, 0x5a);
  873. if (ret)
  874. goto err_ret;
  875. ret = cc2520_write_register(priv, CC2520_FSCAL1, 0x2b);
  876. if (ret)
  877. goto err_ret;
  878. ret = cc2520_write_register(priv, CC2520_ADCTEST0, 0x10);
  879. if (ret)
  880. goto err_ret;
  881. ret = cc2520_write_register(priv, CC2520_ADCTEST1, 0x0e);
  882. if (ret)
  883. goto err_ret;
  884. ret = cc2520_write_register(priv, CC2520_ADCTEST2, 0x03);
  885. if (ret)
  886. goto err_ret;
  887. /* Configure registers correctly for this driver. */
  888. ret = cc2520_write_register(priv, CC2520_FRMCTRL1,
  889. FRMCTRL1_SET_RXENMASK_ON_TX |
  890. FRMCTRL1_IGNORE_TX_UNDERF);
  891. if (ret)
  892. goto err_ret;
  893. ret = cc2520_write_register(priv, CC2520_FIFOPCTRL, 127);
  894. if (ret)
  895. goto err_ret;
  896. return 0;
  897. err_ret:
  898. return ret;
  899. }
  900. static int cc2520_probe(struct spi_device *spi)
  901. {
  902. struct cc2520_private *priv;
  903. struct cc2520_platform_data pdata;
  904. int ret;
  905. priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
  906. if (!priv)
  907. return -ENOMEM;
  908. spi_set_drvdata(spi, priv);
  909. ret = cc2520_get_platform_data(spi, &pdata);
  910. if (ret < 0) {
  911. dev_err(&spi->dev, "no platform data\n");
  912. return -EINVAL;
  913. }
  914. priv->spi = spi;
  915. priv->buf = devm_kzalloc(&spi->dev,
  916. SPI_COMMAND_BUFFER, GFP_KERNEL);
  917. if (!priv->buf)
  918. return -ENOMEM;
  919. mutex_init(&priv->buffer_mutex);
  920. INIT_WORK(&priv->fifop_irqwork, cc2520_fifop_irqwork);
  921. spin_lock_init(&priv->lock);
  922. init_completion(&priv->tx_complete);
  923. /* Assumption that CC2591 is not connected */
  924. priv->amplified = false;
  925. /* Request all the gpio's */
  926. if (!gpio_is_valid(pdata.fifo)) {
  927. dev_err(&spi->dev, "fifo gpio is not valid\n");
  928. ret = -EINVAL;
  929. goto err_hw_init;
  930. }
  931. ret = devm_gpio_request_one(&spi->dev, pdata.fifo,
  932. GPIOF_IN, "fifo");
  933. if (ret)
  934. goto err_hw_init;
  935. if (!gpio_is_valid(pdata.cca)) {
  936. dev_err(&spi->dev, "cca gpio is not valid\n");
  937. ret = -EINVAL;
  938. goto err_hw_init;
  939. }
  940. ret = devm_gpio_request_one(&spi->dev, pdata.cca,
  941. GPIOF_IN, "cca");
  942. if (ret)
  943. goto err_hw_init;
  944. if (!gpio_is_valid(pdata.fifop)) {
  945. dev_err(&spi->dev, "fifop gpio is not valid\n");
  946. ret = -EINVAL;
  947. goto err_hw_init;
  948. }
  949. ret = devm_gpio_request_one(&spi->dev, pdata.fifop,
  950. GPIOF_IN, "fifop");
  951. if (ret)
  952. goto err_hw_init;
  953. if (!gpio_is_valid(pdata.sfd)) {
  954. dev_err(&spi->dev, "sfd gpio is not valid\n");
  955. ret = -EINVAL;
  956. goto err_hw_init;
  957. }
  958. ret = devm_gpio_request_one(&spi->dev, pdata.sfd,
  959. GPIOF_IN, "sfd");
  960. if (ret)
  961. goto err_hw_init;
  962. if (!gpio_is_valid(pdata.reset)) {
  963. dev_err(&spi->dev, "reset gpio is not valid\n");
  964. ret = -EINVAL;
  965. goto err_hw_init;
  966. }
  967. ret = devm_gpio_request_one(&spi->dev, pdata.reset,
  968. GPIOF_OUT_INIT_LOW, "reset");
  969. if (ret)
  970. goto err_hw_init;
  971. if (!gpio_is_valid(pdata.vreg)) {
  972. dev_err(&spi->dev, "vreg gpio is not valid\n");
  973. ret = -EINVAL;
  974. goto err_hw_init;
  975. }
  976. ret = devm_gpio_request_one(&spi->dev, pdata.vreg,
  977. GPIOF_OUT_INIT_LOW, "vreg");
  978. if (ret)
  979. goto err_hw_init;
  980. gpio_set_value(pdata.vreg, HIGH);
  981. usleep_range(100, 150);
  982. gpio_set_value(pdata.reset, HIGH);
  983. usleep_range(200, 250);
  984. ret = cc2520_hw_init(priv);
  985. if (ret)
  986. goto err_hw_init;
  987. /* Set up fifop interrupt */
  988. ret = devm_request_irq(&spi->dev,
  989. gpio_to_irq(pdata.fifop),
  990. cc2520_fifop_isr,
  991. IRQF_TRIGGER_RISING,
  992. dev_name(&spi->dev),
  993. priv);
  994. if (ret) {
  995. dev_err(&spi->dev, "could not get fifop irq\n");
  996. goto err_hw_init;
  997. }
  998. /* Set up sfd interrupt */
  999. ret = devm_request_irq(&spi->dev,
  1000. gpio_to_irq(pdata.sfd),
  1001. cc2520_sfd_isr,
  1002. IRQF_TRIGGER_FALLING,
  1003. dev_name(&spi->dev),
  1004. priv);
  1005. if (ret) {
  1006. dev_err(&spi->dev, "could not get sfd irq\n");
  1007. goto err_hw_init;
  1008. }
  1009. ret = cc2520_register(priv);
  1010. if (ret)
  1011. goto err_hw_init;
  1012. return 0;
  1013. err_hw_init:
  1014. mutex_destroy(&priv->buffer_mutex);
  1015. flush_work(&priv->fifop_irqwork);
  1016. return ret;
  1017. }
  1018. static int cc2520_remove(struct spi_device *spi)
  1019. {
  1020. struct cc2520_private *priv = spi_get_drvdata(spi);
  1021. mutex_destroy(&priv->buffer_mutex);
  1022. flush_work(&priv->fifop_irqwork);
  1023. ieee802154_unregister_hw(priv->hw);
  1024. ieee802154_free_hw(priv->hw);
  1025. return 0;
  1026. }
  1027. static const struct spi_device_id cc2520_ids[] = {
  1028. {"cc2520", },
  1029. {},
  1030. };
  1031. MODULE_DEVICE_TABLE(spi, cc2520_ids);
  1032. static const struct of_device_id cc2520_of_ids[] = {
  1033. {.compatible = "ti,cc2520", },
  1034. {},
  1035. };
  1036. MODULE_DEVICE_TABLE(of, cc2520_of_ids);
  1037. /* SPI driver structure */
  1038. static struct spi_driver cc2520_driver = {
  1039. .driver = {
  1040. .name = "cc2520",
  1041. .of_match_table = of_match_ptr(cc2520_of_ids),
  1042. },
  1043. .id_table = cc2520_ids,
  1044. .probe = cc2520_probe,
  1045. .remove = cc2520_remove,
  1046. };
  1047. module_spi_driver(cc2520_driver);
  1048. MODULE_AUTHOR("Varka Bhadram <varkab@cdac.in>");
  1049. MODULE_DESCRIPTION("CC2520 Transceiver Driver");
  1050. MODULE_LICENSE("GPL v2");