cc2520.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  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. WARN_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. WARN_ON(page != 0);
  553. WARN_ON(channel < CC2520_MINCHANNEL);
  554. WARN_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, "%s called for pan id\n", __func__);
  568. ret = cc2520_write_ram(priv, CC2520RAM_PANID,
  569. sizeof(panid), (u8 *)&panid);
  570. }
  571. if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
  572. dev_vdbg(&priv->spi->dev,
  573. "%s called for IEEE addr\n", __func__);
  574. ret = cc2520_write_ram(priv, CC2520RAM_IEEEADDR,
  575. sizeof(filt->ieee_addr),
  576. (u8 *)&filt->ieee_addr);
  577. }
  578. if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
  579. u16 addr = le16_to_cpu(filt->short_addr);
  580. dev_vdbg(&priv->spi->dev, "%s called for saddr\n", __func__);
  581. ret = cc2520_write_ram(priv, CC2520RAM_SHORTADDR,
  582. sizeof(addr), (u8 *)&addr);
  583. }
  584. if (changed & IEEE802154_AFILT_PANC_CHANGED) {
  585. u8 frmfilt0;
  586. dev_vdbg(&priv->spi->dev,
  587. "%s called for panc change\n", __func__);
  588. cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
  589. if (filt->pan_coord)
  590. frmfilt0 |= FRMFILT0_PAN_COORDINATOR;
  591. else
  592. frmfilt0 &= ~FRMFILT0_PAN_COORDINATOR;
  593. ret = cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
  594. }
  595. return ret;
  596. }
  597. static inline int cc2520_set_tx_power(struct cc2520_private *priv, s32 mbm)
  598. {
  599. u8 power;
  600. switch (mbm) {
  601. case 500:
  602. power = 0xF7;
  603. break;
  604. case 300:
  605. power = 0xF2;
  606. break;
  607. case 200:
  608. power = 0xAB;
  609. break;
  610. case 100:
  611. power = 0x13;
  612. break;
  613. case 0:
  614. power = 0x32;
  615. break;
  616. case -200:
  617. power = 0x81;
  618. break;
  619. case -400:
  620. power = 0x88;
  621. break;
  622. case -700:
  623. power = 0x2C;
  624. break;
  625. case -1800:
  626. power = 0x03;
  627. break;
  628. default:
  629. return -EINVAL;
  630. }
  631. return cc2520_write_register(priv, CC2520_TXPOWER, power);
  632. }
  633. static inline int cc2520_cc2591_set_tx_power(struct cc2520_private *priv,
  634. s32 mbm)
  635. {
  636. u8 power;
  637. switch (mbm) {
  638. case 1700:
  639. power = 0xF9;
  640. break;
  641. case 1600:
  642. power = 0xF0;
  643. break;
  644. case 1400:
  645. power = 0xA0;
  646. break;
  647. case 1100:
  648. power = 0x2C;
  649. break;
  650. case -100:
  651. power = 0x03;
  652. break;
  653. case -800:
  654. power = 0x01;
  655. break;
  656. default:
  657. return -EINVAL;
  658. }
  659. return cc2520_write_register(priv, CC2520_TXPOWER, power);
  660. }
  661. #define CC2520_MAX_TX_POWERS 0x8
  662. static const s32 cc2520_powers[CC2520_MAX_TX_POWERS + 1] = {
  663. 500, 300, 200, 100, 0, -200, -400, -700, -1800,
  664. };
  665. #define CC2520_CC2591_MAX_TX_POWERS 0x5
  666. static const s32 cc2520_cc2591_powers[CC2520_CC2591_MAX_TX_POWERS + 1] = {
  667. 1700, 1600, 1400, 1100, -100, -800,
  668. };
  669. static int
  670. cc2520_set_txpower(struct ieee802154_hw *hw, s32 mbm)
  671. {
  672. struct cc2520_private *priv = hw->priv;
  673. if (!priv->amplified)
  674. return cc2520_set_tx_power(priv, mbm);
  675. return cc2520_cc2591_set_tx_power(priv, mbm);
  676. }
  677. static int
  678. cc2520_set_promiscuous_mode(struct ieee802154_hw *hw, bool on)
  679. {
  680. struct cc2520_private *priv = hw->priv;
  681. u8 frmfilt0;
  682. dev_dbg(&priv->spi->dev, "%s : mode %d\n", __func__, on);
  683. priv->promiscuous = on;
  684. cc2520_read_register(priv, CC2520_FRMFILT0, &frmfilt0);
  685. if (on) {
  686. /* Disable automatic ACK, automatic CRC, and frame filtering. */
  687. cc2520_write_register(priv, CC2520_FRMCTRL0, 0);
  688. frmfilt0 &= ~FRMFILT0_FRAME_FILTER_EN;
  689. } else {
  690. cc2520_write_register(priv, CC2520_FRMCTRL0, FRMCTRL0_AUTOACK |
  691. FRMCTRL0_AUTOCRC);
  692. frmfilt0 |= FRMFILT0_FRAME_FILTER_EN;
  693. }
  694. return cc2520_write_register(priv, CC2520_FRMFILT0, frmfilt0);
  695. }
  696. static const struct ieee802154_ops cc2520_ops = {
  697. .owner = THIS_MODULE,
  698. .start = cc2520_start,
  699. .stop = cc2520_stop,
  700. .xmit_sync = cc2520_tx,
  701. .ed = cc2520_ed,
  702. .set_channel = cc2520_set_channel,
  703. .set_hw_addr_filt = cc2520_filter,
  704. .set_txpower = cc2520_set_txpower,
  705. .set_promiscuous_mode = cc2520_set_promiscuous_mode,
  706. };
  707. static int cc2520_register(struct cc2520_private *priv)
  708. {
  709. int ret = -ENOMEM;
  710. priv->hw = ieee802154_alloc_hw(sizeof(*priv), &cc2520_ops);
  711. if (!priv->hw)
  712. goto err_ret;
  713. priv->hw->priv = priv;
  714. priv->hw->parent = &priv->spi->dev;
  715. priv->hw->extra_tx_headroom = 0;
  716. ieee802154_random_extended_addr(&priv->hw->phy->perm_extended_addr);
  717. /* We do support only 2.4 Ghz */
  718. priv->hw->phy->supported.channels[0] = 0x7FFF800;
  719. priv->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
  720. IEEE802154_HW_PROMISCUOUS;
  721. priv->hw->phy->flags = WPAN_PHY_FLAG_TXPOWER;
  722. if (!priv->amplified) {
  723. priv->hw->phy->supported.tx_powers = cc2520_powers;
  724. priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_powers);
  725. priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[4];
  726. } else {
  727. priv->hw->phy->supported.tx_powers = cc2520_cc2591_powers;
  728. priv->hw->phy->supported.tx_powers_size = ARRAY_SIZE(cc2520_cc2591_powers);
  729. priv->hw->phy->transmit_power = priv->hw->phy->supported.tx_powers[0];
  730. }
  731. priv->hw->phy->current_channel = 11;
  732. dev_vdbg(&priv->spi->dev, "registered cc2520\n");
  733. ret = ieee802154_register_hw(priv->hw);
  734. if (ret)
  735. goto err_free_device;
  736. return 0;
  737. err_free_device:
  738. ieee802154_free_hw(priv->hw);
  739. err_ret:
  740. return ret;
  741. }
  742. static void cc2520_fifop_irqwork(struct work_struct *work)
  743. {
  744. struct cc2520_private *priv
  745. = container_of(work, struct cc2520_private, fifop_irqwork);
  746. dev_dbg(&priv->spi->dev, "fifop interrupt received\n");
  747. if (gpio_get_value(priv->fifo_pin))
  748. cc2520_rx(priv);
  749. else
  750. dev_dbg(&priv->spi->dev, "rxfifo overflow\n");
  751. cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
  752. cc2520_cmd_strobe(priv, CC2520_CMD_SFLUSHRX);
  753. }
  754. static irqreturn_t cc2520_fifop_isr(int irq, void *data)
  755. {
  756. struct cc2520_private *priv = data;
  757. schedule_work(&priv->fifop_irqwork);
  758. return IRQ_HANDLED;
  759. }
  760. static irqreturn_t cc2520_sfd_isr(int irq, void *data)
  761. {
  762. struct cc2520_private *priv = data;
  763. unsigned long flags;
  764. spin_lock_irqsave(&priv->lock, flags);
  765. if (priv->is_tx) {
  766. priv->is_tx = 0;
  767. spin_unlock_irqrestore(&priv->lock, flags);
  768. dev_dbg(&priv->spi->dev, "SFD for TX\n");
  769. complete(&priv->tx_complete);
  770. } else {
  771. spin_unlock_irqrestore(&priv->lock, flags);
  772. dev_dbg(&priv->spi->dev, "SFD for RX\n");
  773. }
  774. return IRQ_HANDLED;
  775. }
  776. static int cc2520_get_platform_data(struct spi_device *spi,
  777. struct cc2520_platform_data *pdata)
  778. {
  779. struct device_node *np = spi->dev.of_node;
  780. struct cc2520_private *priv = spi_get_drvdata(spi);
  781. if (!np) {
  782. struct cc2520_platform_data *spi_pdata = spi->dev.platform_data;
  783. if (!spi_pdata)
  784. return -ENOENT;
  785. *pdata = *spi_pdata;
  786. priv->fifo_pin = pdata->fifo;
  787. return 0;
  788. }
  789. pdata->fifo = of_get_named_gpio(np, "fifo-gpio", 0);
  790. priv->fifo_pin = pdata->fifo;
  791. pdata->fifop = of_get_named_gpio(np, "fifop-gpio", 0);
  792. pdata->sfd = of_get_named_gpio(np, "sfd-gpio", 0);
  793. pdata->cca = of_get_named_gpio(np, "cca-gpio", 0);
  794. pdata->vreg = of_get_named_gpio(np, "vreg-gpio", 0);
  795. pdata->reset = of_get_named_gpio(np, "reset-gpio", 0);
  796. /* CC2591 front end for CC2520 */
  797. if (of_property_read_bool(np, "amplified"))
  798. priv->amplified = true;
  799. return 0;
  800. }
  801. static int cc2520_hw_init(struct cc2520_private *priv)
  802. {
  803. u8 status = 0, state = 0xff;
  804. int ret;
  805. int timeout = 100;
  806. struct cc2520_platform_data pdata;
  807. ret = cc2520_get_platform_data(priv->spi, &pdata);
  808. if (ret)
  809. goto err_ret;
  810. ret = cc2520_read_register(priv, CC2520_FSMSTAT1, &state);
  811. if (ret)
  812. goto err_ret;
  813. if (state != STATE_IDLE)
  814. return -EINVAL;
  815. do {
  816. ret = cc2520_get_status(priv, &status);
  817. if (ret)
  818. goto err_ret;
  819. if (timeout-- <= 0) {
  820. dev_err(&priv->spi->dev, "oscillator start failed!\n");
  821. return ret;
  822. }
  823. udelay(1);
  824. } while (!(status & CC2520_STATUS_XOSC32M_STABLE));
  825. dev_vdbg(&priv->spi->dev, "oscillator brought up\n");
  826. /* If the CC2520 is connected to a CC2591 amplifier, we must both
  827. * configure GPIOs on the CC2520 to correctly configure the CC2591
  828. * and change a couple settings of the CC2520 to work with the
  829. * amplifier. See section 8 page 17 of TI application note AN065.
  830. * http://www.ti.com/lit/an/swra229a/swra229a.pdf
  831. */
  832. if (priv->amplified) {
  833. ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x16);
  834. if (ret)
  835. goto err_ret;
  836. ret = cc2520_write_register(priv, CC2520_GPIOCTRL0, 0x46);
  837. if (ret)
  838. goto err_ret;
  839. ret = cc2520_write_register(priv, CC2520_GPIOCTRL5, 0x47);
  840. if (ret)
  841. goto err_ret;
  842. ret = cc2520_write_register(priv, CC2520_GPIOPOLARITY, 0x1e);
  843. if (ret)
  844. goto err_ret;
  845. ret = cc2520_write_register(priv, CC2520_TXCTRL, 0xc1);
  846. if (ret)
  847. goto err_ret;
  848. } else {
  849. ret = cc2520_write_register(priv, CC2520_AGCCTRL1, 0x11);
  850. if (ret)
  851. goto err_ret;
  852. }
  853. /* Registers default value: section 28.1 in Datasheet */
  854. /* Set the CCA threshold to -50 dBm. This seems to have been copied
  855. * from the TinyOS CC2520 driver and is much higher than the -84 dBm
  856. * threshold suggested in the datasheet.
  857. */
  858. ret = cc2520_write_register(priv, CC2520_CCACTRL0, 0x1A);
  859. if (ret)
  860. goto err_ret;
  861. ret = cc2520_write_register(priv, CC2520_MDMCTRL0, 0x85);
  862. if (ret)
  863. goto err_ret;
  864. ret = cc2520_write_register(priv, CC2520_MDMCTRL1, 0x14);
  865. if (ret)
  866. goto err_ret;
  867. ret = cc2520_write_register(priv, CC2520_RXCTRL, 0x3f);
  868. if (ret)
  869. goto err_ret;
  870. ret = cc2520_write_register(priv, CC2520_FSCTRL, 0x5a);
  871. if (ret)
  872. goto err_ret;
  873. ret = cc2520_write_register(priv, CC2520_FSCAL1, 0x2b);
  874. if (ret)
  875. goto err_ret;
  876. ret = cc2520_write_register(priv, CC2520_ADCTEST0, 0x10);
  877. if (ret)
  878. goto err_ret;
  879. ret = cc2520_write_register(priv, CC2520_ADCTEST1, 0x0e);
  880. if (ret)
  881. goto err_ret;
  882. ret = cc2520_write_register(priv, CC2520_ADCTEST2, 0x03);
  883. if (ret)
  884. goto err_ret;
  885. /* Configure registers correctly for this driver. */
  886. ret = cc2520_write_register(priv, CC2520_FRMCTRL1,
  887. FRMCTRL1_SET_RXENMASK_ON_TX |
  888. FRMCTRL1_IGNORE_TX_UNDERF);
  889. if (ret)
  890. goto err_ret;
  891. ret = cc2520_write_register(priv, CC2520_FIFOPCTRL, 127);
  892. if (ret)
  893. goto err_ret;
  894. return 0;
  895. err_ret:
  896. return ret;
  897. }
  898. static int cc2520_probe(struct spi_device *spi)
  899. {
  900. struct cc2520_private *priv;
  901. struct cc2520_platform_data pdata;
  902. int ret;
  903. priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
  904. if (!priv)
  905. return -ENOMEM;
  906. spi_set_drvdata(spi, priv);
  907. ret = cc2520_get_platform_data(spi, &pdata);
  908. if (ret < 0) {
  909. dev_err(&spi->dev, "no platform data\n");
  910. return -EINVAL;
  911. }
  912. priv->spi = spi;
  913. priv->buf = devm_kzalloc(&spi->dev,
  914. SPI_COMMAND_BUFFER, GFP_KERNEL);
  915. if (!priv->buf)
  916. return -ENOMEM;
  917. mutex_init(&priv->buffer_mutex);
  918. INIT_WORK(&priv->fifop_irqwork, cc2520_fifop_irqwork);
  919. spin_lock_init(&priv->lock);
  920. init_completion(&priv->tx_complete);
  921. /* Assumption that CC2591 is not connected */
  922. priv->amplified = false;
  923. /* Request all the gpio's */
  924. if (!gpio_is_valid(pdata.fifo)) {
  925. dev_err(&spi->dev, "fifo gpio is not valid\n");
  926. ret = -EINVAL;
  927. goto err_hw_init;
  928. }
  929. ret = devm_gpio_request_one(&spi->dev, pdata.fifo,
  930. GPIOF_IN, "fifo");
  931. if (ret)
  932. goto err_hw_init;
  933. if (!gpio_is_valid(pdata.cca)) {
  934. dev_err(&spi->dev, "cca gpio is not valid\n");
  935. ret = -EINVAL;
  936. goto err_hw_init;
  937. }
  938. ret = devm_gpio_request_one(&spi->dev, pdata.cca,
  939. GPIOF_IN, "cca");
  940. if (ret)
  941. goto err_hw_init;
  942. if (!gpio_is_valid(pdata.fifop)) {
  943. dev_err(&spi->dev, "fifop gpio is not valid\n");
  944. ret = -EINVAL;
  945. goto err_hw_init;
  946. }
  947. ret = devm_gpio_request_one(&spi->dev, pdata.fifop,
  948. GPIOF_IN, "fifop");
  949. if (ret)
  950. goto err_hw_init;
  951. if (!gpio_is_valid(pdata.sfd)) {
  952. dev_err(&spi->dev, "sfd gpio is not valid\n");
  953. ret = -EINVAL;
  954. goto err_hw_init;
  955. }
  956. ret = devm_gpio_request_one(&spi->dev, pdata.sfd,
  957. GPIOF_IN, "sfd");
  958. if (ret)
  959. goto err_hw_init;
  960. if (!gpio_is_valid(pdata.reset)) {
  961. dev_err(&spi->dev, "reset gpio is not valid\n");
  962. ret = -EINVAL;
  963. goto err_hw_init;
  964. }
  965. ret = devm_gpio_request_one(&spi->dev, pdata.reset,
  966. GPIOF_OUT_INIT_LOW, "reset");
  967. if (ret)
  968. goto err_hw_init;
  969. if (!gpio_is_valid(pdata.vreg)) {
  970. dev_err(&spi->dev, "vreg gpio is not valid\n");
  971. ret = -EINVAL;
  972. goto err_hw_init;
  973. }
  974. ret = devm_gpio_request_one(&spi->dev, pdata.vreg,
  975. GPIOF_OUT_INIT_LOW, "vreg");
  976. if (ret)
  977. goto err_hw_init;
  978. gpio_set_value(pdata.vreg, HIGH);
  979. usleep_range(100, 150);
  980. gpio_set_value(pdata.reset, HIGH);
  981. usleep_range(200, 250);
  982. ret = cc2520_hw_init(priv);
  983. if (ret)
  984. goto err_hw_init;
  985. /* Set up fifop interrupt */
  986. ret = devm_request_irq(&spi->dev,
  987. gpio_to_irq(pdata.fifop),
  988. cc2520_fifop_isr,
  989. IRQF_TRIGGER_RISING,
  990. dev_name(&spi->dev),
  991. priv);
  992. if (ret) {
  993. dev_err(&spi->dev, "could not get fifop irq\n");
  994. goto err_hw_init;
  995. }
  996. /* Set up sfd interrupt */
  997. ret = devm_request_irq(&spi->dev,
  998. gpio_to_irq(pdata.sfd),
  999. cc2520_sfd_isr,
  1000. IRQF_TRIGGER_FALLING,
  1001. dev_name(&spi->dev),
  1002. priv);
  1003. if (ret) {
  1004. dev_err(&spi->dev, "could not get sfd irq\n");
  1005. goto err_hw_init;
  1006. }
  1007. ret = cc2520_register(priv);
  1008. if (ret)
  1009. goto err_hw_init;
  1010. return 0;
  1011. err_hw_init:
  1012. mutex_destroy(&priv->buffer_mutex);
  1013. flush_work(&priv->fifop_irqwork);
  1014. return ret;
  1015. }
  1016. static int cc2520_remove(struct spi_device *spi)
  1017. {
  1018. struct cc2520_private *priv = spi_get_drvdata(spi);
  1019. mutex_destroy(&priv->buffer_mutex);
  1020. flush_work(&priv->fifop_irqwork);
  1021. ieee802154_unregister_hw(priv->hw);
  1022. ieee802154_free_hw(priv->hw);
  1023. return 0;
  1024. }
  1025. static const struct spi_device_id cc2520_ids[] = {
  1026. {"cc2520", },
  1027. {},
  1028. };
  1029. MODULE_DEVICE_TABLE(spi, cc2520_ids);
  1030. static const struct of_device_id cc2520_of_ids[] = {
  1031. {.compatible = "ti,cc2520", },
  1032. {},
  1033. };
  1034. MODULE_DEVICE_TABLE(of, cc2520_of_ids);
  1035. /* SPI driver structure */
  1036. static struct spi_driver cc2520_driver = {
  1037. .driver = {
  1038. .name = "cc2520",
  1039. .of_match_table = of_match_ptr(cc2520_of_ids),
  1040. },
  1041. .id_table = cc2520_ids,
  1042. .probe = cc2520_probe,
  1043. .remove = cc2520_remove,
  1044. };
  1045. module_spi_driver(cc2520_driver);
  1046. MODULE_AUTHOR("Varka Bhadram <varkab@cdac.in>");
  1047. MODULE_DESCRIPTION("CC2520 Transceiver Driver");
  1048. MODULE_LICENSE("GPL v2");