Commit | Line | Data |
---|---|---|
3731a334 AO |
1 | /* |
2 | * Driver for Microchip MRF24J40 802.15.4 Wireless-PAN Networking controller | |
3 | * | |
4 | * Copyright (C) 2012 Alan Ott <alan@signal11.us> | |
5 | * Signal 11 Software | |
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 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
3731a334 AO |
16 | */ |
17 | ||
18 | #include <linux/spi/spi.h> | |
19 | #include <linux/interrupt.h> | |
20 | #include <linux/module.h> | |
4ca24aca | 21 | #include <linux/ieee802154.h> |
5ad60d36 | 22 | #include <net/cfg802154.h> |
3731a334 AO |
23 | #include <net/mac802154.h> |
24 | ||
25 | /* MRF24J40 Short Address Registers */ | |
c9f883f6 AA |
26 | #define REG_RXMCR 0x00 /* Receive MAC control */ |
27 | #define REG_PANIDL 0x01 /* PAN ID (low) */ | |
28 | #define REG_PANIDH 0x02 /* PAN ID (high) */ | |
29 | #define REG_SADRL 0x03 /* Short address (low) */ | |
30 | #define REG_SADRH 0x04 /* Short address (high) */ | |
31 | #define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */ | |
32 | #define REG_TXMCR 0x11 /* Transmit MAC control */ | |
33 | #define REG_PACON0 0x16 /* Power Amplifier Control */ | |
34 | #define REG_PACON1 0x17 /* Power Amplifier Control */ | |
35 | #define REG_PACON2 0x18 /* Power Amplifier Control */ | |
36 | #define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */ | |
37 | #define REG_TXSTAT 0x24 /* TX MAC Status Register */ | |
38 | #define REG_SOFTRST 0x2A /* Soft Reset */ | |
39 | #define REG_TXSTBL 0x2E /* TX Stabilization */ | |
40 | #define REG_INTSTAT 0x31 /* Interrupt Status */ | |
41 | #define REG_INTCON 0x32 /* Interrupt Control */ | |
42 | #define REG_GPIO 0x33 /* GPIO */ | |
43 | #define REG_TRISGPIO 0x34 /* GPIO direction */ | |
44 | #define REG_RFCTL 0x36 /* RF Control Mode Register */ | |
45 | #define REG_BBREG1 0x39 /* Baseband Registers */ | |
46 | #define REG_BBREG2 0x3A /* */ | |
47 | #define REG_BBREG6 0x3E /* */ | |
48 | #define REG_CCAEDTH 0x3F /* Energy Detection Threshold */ | |
3731a334 AO |
49 | |
50 | /* MRF24J40 Long Address Registers */ | |
c9f883f6 AA |
51 | #define REG_RFCON0 0x200 /* RF Control Registers */ |
52 | #define REG_RFCON1 0x201 | |
53 | #define REG_RFCON2 0x202 | |
54 | #define REG_RFCON3 0x203 | |
55 | #define REG_RFCON5 0x205 | |
56 | #define REG_RFCON6 0x206 | |
57 | #define REG_RFCON7 0x207 | |
58 | #define REG_RFCON8 0x208 | |
59 | #define REG_RSSI 0x210 | |
60 | #define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */ | |
61 | #define REG_SLPCON1 0x220 | |
62 | #define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */ | |
63 | #define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */ | |
64 | #define REG_TESTMODE 0x22F /* Test mode */ | |
65 | #define REG_RX_FIFO 0x300 /* Receive FIFO */ | |
3731a334 AO |
66 | |
67 | /* Device configuration: Only channels 11-26 on page 0 are supported. */ | |
68 | #define MRF24J40_CHAN_MIN 11 | |
69 | #define MRF24J40_CHAN_MAX 26 | |
70 | #define CHANNEL_MASK (((u32)1 << (MRF24J40_CHAN_MAX + 1)) \ | |
71 | - ((u32)1 << MRF24J40_CHAN_MIN)) | |
72 | ||
73 | #define TX_FIFO_SIZE 128 /* From datasheet */ | |
74 | #define RX_FIFO_SIZE 144 /* From datasheet */ | |
75 | #define SET_CHANNEL_DELAY_US 192 /* From datasheet */ | |
76 | ||
db9e0ee8 SV |
77 | enum mrf24j40_modules { MRF24J40, MRF24J40MA, MRF24J40MC }; |
78 | ||
3731a334 AO |
79 | /* Device Private Data */ |
80 | struct mrf24j40 { | |
81 | struct spi_device *spi; | |
5a504397 | 82 | struct ieee802154_hw *hw; |
3731a334 AO |
83 | |
84 | struct mutex buffer_mutex; /* only used to protect buf */ | |
85 | struct completion tx_complete; | |
3731a334 AO |
86 | u8 *buf; /* 3 bytes. Used for SPI single-register transfers. */ |
87 | }; | |
88 | ||
89 | /* Read/Write SPI Commands for Short and Long Address registers. */ | |
90 | #define MRF24J40_READSHORT(reg) ((reg) << 1) | |
91 | #define MRF24J40_WRITESHORT(reg) ((reg) << 1 | 1) | |
92 | #define MRF24J40_READLONG(reg) (1 << 15 | (reg) << 5) | |
93 | #define MRF24J40_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4) | |
94 | ||
cf82dabd AO |
95 | /* The datasheet indicates the theoretical maximum for SCK to be 10MHz */ |
96 | #define MAX_SPI_SPEED_HZ 10000000 | |
3731a334 AO |
97 | |
98 | #define printdev(X) (&X->spi->dev) | |
99 | ||
100 | static int write_short_reg(struct mrf24j40 *devrec, u8 reg, u8 value) | |
101 | { | |
102 | int ret; | |
103 | struct spi_message msg; | |
104 | struct spi_transfer xfer = { | |
105 | .len = 2, | |
106 | .tx_buf = devrec->buf, | |
107 | .rx_buf = devrec->buf, | |
108 | }; | |
109 | ||
110 | spi_message_init(&msg); | |
111 | spi_message_add_tail(&xfer, &msg); | |
112 | ||
113 | mutex_lock(&devrec->buffer_mutex); | |
114 | devrec->buf[0] = MRF24J40_WRITESHORT(reg); | |
115 | devrec->buf[1] = value; | |
116 | ||
117 | ret = spi_sync(devrec->spi, &msg); | |
118 | if (ret) | |
119 | dev_err(printdev(devrec), | |
120 | "SPI write Failed for short register 0x%hhx\n", reg); | |
121 | ||
122 | mutex_unlock(&devrec->buffer_mutex); | |
123 | return ret; | |
124 | } | |
125 | ||
126 | static int read_short_reg(struct mrf24j40 *devrec, u8 reg, u8 *val) | |
127 | { | |
128 | int ret = -1; | |
129 | struct spi_message msg; | |
130 | struct spi_transfer xfer = { | |
131 | .len = 2, | |
132 | .tx_buf = devrec->buf, | |
133 | .rx_buf = devrec->buf, | |
134 | }; | |
135 | ||
136 | spi_message_init(&msg); | |
137 | spi_message_add_tail(&xfer, &msg); | |
138 | ||
139 | mutex_lock(&devrec->buffer_mutex); | |
140 | devrec->buf[0] = MRF24J40_READSHORT(reg); | |
141 | devrec->buf[1] = 0; | |
142 | ||
143 | ret = spi_sync(devrec->spi, &msg); | |
144 | if (ret) | |
145 | dev_err(printdev(devrec), | |
146 | "SPI read Failed for short register 0x%hhx\n", reg); | |
147 | else | |
148 | *val = devrec->buf[1]; | |
149 | ||
150 | mutex_unlock(&devrec->buffer_mutex); | |
151 | return ret; | |
152 | } | |
153 | ||
154 | static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value) | |
155 | { | |
156 | int ret; | |
157 | u16 cmd; | |
158 | struct spi_message msg; | |
159 | struct spi_transfer xfer = { | |
160 | .len = 3, | |
161 | .tx_buf = devrec->buf, | |
162 | .rx_buf = devrec->buf, | |
163 | }; | |
164 | ||
165 | spi_message_init(&msg); | |
166 | spi_message_add_tail(&xfer, &msg); | |
167 | ||
168 | cmd = MRF24J40_READLONG(reg); | |
169 | mutex_lock(&devrec->buffer_mutex); | |
170 | devrec->buf[0] = cmd >> 8 & 0xff; | |
171 | devrec->buf[1] = cmd & 0xff; | |
172 | devrec->buf[2] = 0; | |
173 | ||
174 | ret = spi_sync(devrec->spi, &msg); | |
175 | if (ret) | |
176 | dev_err(printdev(devrec), | |
177 | "SPI read Failed for long register 0x%hx\n", reg); | |
178 | else | |
179 | *value = devrec->buf[2]; | |
180 | ||
181 | mutex_unlock(&devrec->buffer_mutex); | |
182 | return ret; | |
183 | } | |
184 | ||
185 | static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val) | |
186 | { | |
187 | int ret; | |
188 | u16 cmd; | |
189 | struct spi_message msg; | |
190 | struct spi_transfer xfer = { | |
191 | .len = 3, | |
192 | .tx_buf = devrec->buf, | |
193 | .rx_buf = devrec->buf, | |
194 | }; | |
195 | ||
196 | spi_message_init(&msg); | |
197 | spi_message_add_tail(&xfer, &msg); | |
198 | ||
199 | cmd = MRF24J40_WRITELONG(reg); | |
200 | mutex_lock(&devrec->buffer_mutex); | |
201 | devrec->buf[0] = cmd >> 8 & 0xff; | |
202 | devrec->buf[1] = cmd & 0xff; | |
203 | devrec->buf[2] = val; | |
204 | ||
205 | ret = spi_sync(devrec->spi, &msg); | |
206 | if (ret) | |
207 | dev_err(printdev(devrec), | |
208 | "SPI write Failed for long register 0x%hx\n", reg); | |
209 | ||
210 | mutex_unlock(&devrec->buffer_mutex); | |
211 | return ret; | |
212 | } | |
213 | ||
214 | /* This function relies on an undocumented write method. Once a write command | |
215 | and address is set, as many bytes of data as desired can be clocked into | |
216 | the device. The datasheet only shows setting one byte at a time. */ | |
217 | static int write_tx_buf(struct mrf24j40 *devrec, u16 reg, | |
218 | const u8 *data, size_t length) | |
219 | { | |
220 | int ret; | |
221 | u16 cmd; | |
222 | u8 lengths[2]; | |
223 | struct spi_message msg; | |
224 | struct spi_transfer addr_xfer = { | |
225 | .len = 2, | |
226 | .tx_buf = devrec->buf, | |
227 | }; | |
228 | struct spi_transfer lengths_xfer = { | |
229 | .len = 2, | |
230 | .tx_buf = &lengths, /* TODO: Is DMA really required for SPI? */ | |
231 | }; | |
232 | struct spi_transfer data_xfer = { | |
233 | .len = length, | |
234 | .tx_buf = data, | |
235 | }; | |
236 | ||
237 | /* Range check the length. 2 bytes are used for the length fields.*/ | |
238 | if (length > TX_FIFO_SIZE-2) { | |
239 | dev_err(printdev(devrec), "write_tx_buf() was passed too large a buffer. Performing short write.\n"); | |
240 | length = TX_FIFO_SIZE-2; | |
241 | } | |
242 | ||
243 | spi_message_init(&msg); | |
244 | spi_message_add_tail(&addr_xfer, &msg); | |
245 | spi_message_add_tail(&lengths_xfer, &msg); | |
246 | spi_message_add_tail(&data_xfer, &msg); | |
247 | ||
248 | cmd = MRF24J40_WRITELONG(reg); | |
249 | mutex_lock(&devrec->buffer_mutex); | |
250 | devrec->buf[0] = cmd >> 8 & 0xff; | |
251 | devrec->buf[1] = cmd & 0xff; | |
252 | lengths[0] = 0x0; /* Header Length. Set to 0 for now. TODO */ | |
253 | lengths[1] = length; /* Total length */ | |
254 | ||
255 | ret = spi_sync(devrec->spi, &msg); | |
256 | if (ret) | |
257 | dev_err(printdev(devrec), "SPI write Failed for TX buf\n"); | |
258 | ||
259 | mutex_unlock(&devrec->buffer_mutex); | |
260 | return ret; | |
261 | } | |
262 | ||
263 | static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec, | |
264 | u8 *data, u8 *len, u8 *lqi) | |
265 | { | |
266 | u8 rx_len; | |
267 | u8 addr[2]; | |
268 | u8 lqi_rssi[2]; | |
269 | u16 cmd; | |
270 | int ret; | |
271 | struct spi_message msg; | |
272 | struct spi_transfer addr_xfer = { | |
273 | .len = 2, | |
274 | .tx_buf = &addr, | |
275 | }; | |
276 | struct spi_transfer data_xfer = { | |
277 | .len = 0x0, /* set below */ | |
278 | .rx_buf = data, | |
279 | }; | |
280 | struct spi_transfer status_xfer = { | |
281 | .len = 2, | |
282 | .rx_buf = &lqi_rssi, | |
283 | }; | |
284 | ||
285 | /* Get the length of the data in the RX FIFO. The length in this | |
286 | * register exclues the 1-byte length field at the beginning. */ | |
287 | ret = read_long_reg(devrec, REG_RX_FIFO, &rx_len); | |
288 | if (ret) | |
289 | goto out; | |
290 | ||
291 | /* Range check the RX FIFO length, accounting for the one-byte | |
5c1be06a | 292 | * length field at the beginning. */ |
3731a334 AO |
293 | if (rx_len > RX_FIFO_SIZE-1) { |
294 | dev_err(printdev(devrec), "Invalid length read from device. Performing short read.\n"); | |
295 | rx_len = RX_FIFO_SIZE-1; | |
296 | } | |
297 | ||
298 | if (rx_len > *len) { | |
299 | /* Passed in buffer wasn't big enough. Should never happen. */ | |
300 | dev_err(printdev(devrec), "Buffer not big enough. Performing short read\n"); | |
301 | rx_len = *len; | |
302 | } | |
303 | ||
304 | /* Set up the commands to read the data. */ | |
305 | cmd = MRF24J40_READLONG(REG_RX_FIFO+1); | |
306 | addr[0] = cmd >> 8 & 0xff; | |
307 | addr[1] = cmd & 0xff; | |
308 | data_xfer.len = rx_len; | |
309 | ||
310 | spi_message_init(&msg); | |
311 | spi_message_add_tail(&addr_xfer, &msg); | |
312 | spi_message_add_tail(&data_xfer, &msg); | |
313 | spi_message_add_tail(&status_xfer, &msg); | |
314 | ||
315 | ret = spi_sync(devrec->spi, &msg); | |
316 | if (ret) { | |
317 | dev_err(printdev(devrec), "SPI RX Buffer Read Failed.\n"); | |
318 | goto out; | |
319 | } | |
320 | ||
321 | *lqi = lqi_rssi[0]; | |
322 | *len = rx_len; | |
323 | ||
324 | #ifdef DEBUG | |
325 | print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", | |
ce261bc3 | 326 | DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0); |
ca079ad6 VB |
327 | pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n", |
328 | lqi_rssi[0], lqi_rssi[1]); | |
3731a334 AO |
329 | #endif |
330 | ||
331 | out: | |
332 | return ret; | |
333 | } | |
334 | ||
5a504397 | 335 | static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb) |
3731a334 | 336 | { |
5a504397 | 337 | struct mrf24j40 *devrec = hw->priv; |
3731a334 AO |
338 | u8 val; |
339 | int ret = 0; | |
340 | ||
341 | dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len); | |
342 | ||
343 | ret = write_tx_buf(devrec, 0x000, skb->data, skb->len); | |
344 | if (ret) | |
345 | goto err; | |
346 | ||
16735d02 | 347 | reinit_completion(&devrec->tx_complete); |
9757f1d2 | 348 | |
3731a334 AO |
349 | /* Set TXNTRIG bit of TXNCON to send packet */ |
350 | ret = read_short_reg(devrec, REG_TXNCON, &val); | |
351 | if (ret) | |
352 | goto err; | |
353 | val |= 0x1; | |
cbde8123 AO |
354 | /* Set TXNACKREQ if the ACK bit is set in the packet. */ |
355 | if (skb->data[0] & IEEE802154_FC_ACK_REQ) | |
356 | val |= 0x4; | |
3731a334 AO |
357 | write_short_reg(devrec, REG_TXNCON, val); |
358 | ||
3731a334 AO |
359 | /* Wait for the device to send the TX complete interrupt. */ |
360 | ret = wait_for_completion_interruptible_timeout( | |
361 | &devrec->tx_complete, | |
362 | 5 * HZ); | |
363 | if (ret == -ERESTARTSYS) | |
364 | goto err; | |
365 | if (ret == 0) { | |
7a1c2318 | 366 | dev_warn(printdev(devrec), "Timeout waiting for TX interrupt\n"); |
3731a334 AO |
367 | ret = -ETIMEDOUT; |
368 | goto err; | |
369 | } | |
370 | ||
371 | /* Check for send error from the device. */ | |
372 | ret = read_short_reg(devrec, REG_TXSTAT, &val); | |
373 | if (ret) | |
374 | goto err; | |
375 | if (val & 0x1) { | |
cbde8123 | 376 | dev_dbg(printdev(devrec), "Error Sending. Retry count exceeded\n"); |
3731a334 AO |
377 | ret = -ECOMM; /* TODO: Better error code ? */ |
378 | } else | |
379 | dev_dbg(printdev(devrec), "Packet Sent\n"); | |
380 | ||
381 | err: | |
382 | ||
383 | return ret; | |
384 | } | |
385 | ||
5a504397 | 386 | static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level) |
3731a334 AO |
387 | { |
388 | /* TODO: */ | |
ca079ad6 | 389 | pr_warn("mrf24j40: ed not implemented\n"); |
3731a334 AO |
390 | *level = 0; |
391 | return 0; | |
392 | } | |
393 | ||
5a504397 | 394 | static int mrf24j40_start(struct ieee802154_hw *hw) |
3731a334 | 395 | { |
5a504397 | 396 | struct mrf24j40 *devrec = hw->priv; |
3731a334 AO |
397 | u8 val; |
398 | int ret; | |
399 | ||
400 | dev_dbg(printdev(devrec), "start\n"); | |
401 | ||
402 | ret = read_short_reg(devrec, REG_INTCON, &val); | |
403 | if (ret) | |
404 | return ret; | |
405 | val &= ~(0x1|0x8); /* Clear TXNIE and RXIE. Enable interrupts */ | |
406 | write_short_reg(devrec, REG_INTCON, val); | |
407 | ||
408 | return 0; | |
409 | } | |
410 | ||
5a504397 | 411 | static void mrf24j40_stop(struct ieee802154_hw *hw) |
3731a334 | 412 | { |
5a504397 | 413 | struct mrf24j40 *devrec = hw->priv; |
3731a334 AO |
414 | u8 val; |
415 | int ret; | |
529160dc | 416 | |
3731a334 AO |
417 | dev_dbg(printdev(devrec), "stop\n"); |
418 | ||
419 | ret = read_short_reg(devrec, REG_INTCON, &val); | |
420 | if (ret) | |
421 | return; | |
422 | val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */ | |
423 | write_short_reg(devrec, REG_INTCON, val); | |
3731a334 AO |
424 | } |
425 | ||
e37d2ec8 | 426 | static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) |
3731a334 | 427 | { |
5a504397 | 428 | struct mrf24j40 *devrec = hw->priv; |
3731a334 AO |
429 | u8 val; |
430 | int ret; | |
431 | ||
432 | dev_dbg(printdev(devrec), "Set Channel %d\n", channel); | |
433 | ||
434 | WARN_ON(page != 0); | |
435 | WARN_ON(channel < MRF24J40_CHAN_MIN); | |
436 | WARN_ON(channel > MRF24J40_CHAN_MAX); | |
437 | ||
438 | /* Set Channel TODO */ | |
439 | val = (channel-11) << 4 | 0x03; | |
440 | write_long_reg(devrec, REG_RFCON0, val); | |
441 | ||
442 | /* RF Reset */ | |
443 | ret = read_short_reg(devrec, REG_RFCTL, &val); | |
444 | if (ret) | |
445 | return ret; | |
446 | val |= 0x04; | |
447 | write_short_reg(devrec, REG_RFCTL, val); | |
448 | val &= ~0x04; | |
449 | write_short_reg(devrec, REG_RFCTL, val); | |
450 | ||
451 | udelay(SET_CHANNEL_DELAY_US); /* per datasheet */ | |
452 | ||
453 | return 0; | |
454 | } | |
455 | ||
5a504397 | 456 | static int mrf24j40_filter(struct ieee802154_hw *hw, |
3731a334 AO |
457 | struct ieee802154_hw_addr_filt *filt, |
458 | unsigned long changed) | |
459 | { | |
5a504397 | 460 | struct mrf24j40 *devrec = hw->priv; |
3731a334 AO |
461 | |
462 | dev_dbg(printdev(devrec), "filter\n"); | |
463 | ||
57205c14 | 464 | if (changed & IEEE802154_AFILT_SADDR_CHANGED) { |
3731a334 AO |
465 | /* Short Addr */ |
466 | u8 addrh, addrl; | |
529160dc | 467 | |
b70ab2e8 PB |
468 | addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff; |
469 | addrl = le16_to_cpu(filt->short_addr) & 0xff; | |
3731a334 AO |
470 | |
471 | write_short_reg(devrec, REG_SADRH, addrh); | |
472 | write_short_reg(devrec, REG_SADRL, addrl); | |
473 | dev_dbg(printdev(devrec), | |
474 | "Set short addr to %04hx\n", filt->short_addr); | |
475 | } | |
476 | ||
57205c14 | 477 | if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) { |
3731a334 | 478 | /* Device Address */ |
b70ab2e8 PB |
479 | u8 i, addr[8]; |
480 | ||
481 | memcpy(addr, &filt->ieee_addr, 8); | |
3731a334 | 482 | for (i = 0; i < 8; i++) |
b70ab2e8 | 483 | write_short_reg(devrec, REG_EADR0 + i, addr[i]); |
3731a334 AO |
484 | |
485 | #ifdef DEBUG | |
ca079ad6 | 486 | pr_debug("Set long addr to: "); |
3731a334 | 487 | for (i = 0; i < 8; i++) |
ca079ad6 VB |
488 | pr_debug("%02hhx ", addr[7 - i]); |
489 | pr_debug("\n"); | |
3731a334 AO |
490 | #endif |
491 | } | |
492 | ||
57205c14 | 493 | if (changed & IEEE802154_AFILT_PANID_CHANGED) { |
3731a334 AO |
494 | /* PAN ID */ |
495 | u8 panidl, panidh; | |
529160dc | 496 | |
b70ab2e8 PB |
497 | panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff; |
498 | panidl = le16_to_cpu(filt->pan_id) & 0xff; | |
3731a334 AO |
499 | write_short_reg(devrec, REG_PANIDH, panidh); |
500 | write_short_reg(devrec, REG_PANIDL, panidl); | |
501 | ||
502 | dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id); | |
503 | } | |
504 | ||
57205c14 | 505 | if (changed & IEEE802154_AFILT_PANC_CHANGED) { |
3731a334 AO |
506 | /* Pan Coordinator */ |
507 | u8 val; | |
508 | int ret; | |
509 | ||
510 | ret = read_short_reg(devrec, REG_RXMCR, &val); | |
511 | if (ret) | |
512 | return ret; | |
513 | if (filt->pan_coord) | |
514 | val |= 0x8; | |
515 | else | |
516 | val &= ~0x8; | |
517 | write_short_reg(devrec, REG_RXMCR, val); | |
518 | ||
519 | /* REG_SLOTTED is maintained as default (unslotted/CSMA-CA). | |
520 | * REG_ORDER is maintained as default (no beacon/superframe). | |
521 | */ | |
522 | ||
523 | dev_dbg(printdev(devrec), "Set Pan Coord to %s\n", | |
ce261bc3 | 524 | filt->pan_coord ? "on" : "off"); |
3731a334 AO |
525 | } |
526 | ||
527 | return 0; | |
528 | } | |
529 | ||
530 | static int mrf24j40_handle_rx(struct mrf24j40 *devrec) | |
531 | { | |
532 | u8 len = RX_FIFO_SIZE; | |
533 | u8 lqi = 0; | |
534 | u8 val; | |
535 | int ret = 0; | |
e5719b66 | 536 | int ret2; |
3731a334 AO |
537 | struct sk_buff *skb; |
538 | ||
539 | /* Turn off reception of packets off the air. This prevents the | |
540 | * device from overwriting the buffer while we're reading it. */ | |
541 | ret = read_short_reg(devrec, REG_BBREG1, &val); | |
542 | if (ret) | |
543 | goto out; | |
544 | val |= 4; /* SET RXDECINV */ | |
545 | write_short_reg(devrec, REG_BBREG1, val); | |
546 | ||
61a22814 | 547 | skb = dev_alloc_skb(len); |
3731a334 AO |
548 | if (!skb) { |
549 | ret = -ENOMEM; | |
550 | goto out; | |
551 | } | |
552 | ||
553 | ret = mrf24j40_read_rx_buf(devrec, skb_put(skb, len), &len, &lqi); | |
554 | if (ret < 0) { | |
555 | dev_err(printdev(devrec), "Failure reading RX FIFO\n"); | |
556 | kfree_skb(skb); | |
557 | ret = -EINVAL; | |
558 | goto out; | |
559 | } | |
560 | ||
561 | /* Cut off the checksum */ | |
562 | skb_trim(skb, len-2); | |
563 | ||
564 | /* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040, | |
565 | * also from a workqueue). I think irqsafe is not necessary here. | |
566 | * Can someone confirm? */ | |
5a504397 | 567 | ieee802154_rx_irqsafe(devrec->hw, skb, lqi); |
3731a334 AO |
568 | |
569 | dev_dbg(printdev(devrec), "RX Handled\n"); | |
570 | ||
571 | out: | |
572 | /* Turn back on reception of packets off the air. */ | |
e5719b66 SS |
573 | ret2 = read_short_reg(devrec, REG_BBREG1, &val); |
574 | if (ret2) | |
575 | return ret2; | |
3731a334 AO |
576 | val &= ~0x4; /* Clear RXDECINV */ |
577 | write_short_reg(devrec, REG_BBREG1, val); | |
578 | ||
579 | return ret; | |
580 | } | |
581 | ||
16301861 | 582 | static const struct ieee802154_ops mrf24j40_ops = { |
3731a334 | 583 | .owner = THIS_MODULE, |
ed0a5dce | 584 | .xmit_sync = mrf24j40_tx, |
3731a334 AO |
585 | .ed = mrf24j40_ed, |
586 | .start = mrf24j40_start, | |
587 | .stop = mrf24j40_stop, | |
588 | .set_channel = mrf24j40_set_channel, | |
589 | .set_hw_addr_filt = mrf24j40_filter, | |
590 | }; | |
591 | ||
592 | static irqreturn_t mrf24j40_isr(int irq, void *data) | |
593 | { | |
594 | struct mrf24j40 *devrec = data; | |
3731a334 AO |
595 | u8 intstat; |
596 | int ret; | |
597 | ||
598 | /* Read the interrupt status */ | |
599 | ret = read_short_reg(devrec, REG_INTSTAT, &intstat); | |
600 | if (ret) | |
601 | goto out; | |
602 | ||
603 | /* Check for TX complete */ | |
604 | if (intstat & 0x1) | |
605 | complete(&devrec->tx_complete); | |
606 | ||
607 | /* Check for Rx */ | |
608 | if (intstat & 0x8) | |
609 | mrf24j40_handle_rx(devrec); | |
610 | ||
611 | out: | |
4a4e1da8 | 612 | return IRQ_HANDLED; |
3731a334 AO |
613 | } |
614 | ||
3dac9a79 VB |
615 | static int mrf24j40_hw_init(struct mrf24j40 *devrec) |
616 | { | |
617 | int ret; | |
618 | u8 val; | |
619 | ||
620 | /* Initialize the device. | |
621 | From datasheet section 3.2: Initialization. */ | |
622 | ret = write_short_reg(devrec, REG_SOFTRST, 0x07); | |
623 | if (ret) | |
624 | goto err_ret; | |
625 | ||
626 | ret = write_short_reg(devrec, REG_PACON2, 0x98); | |
627 | if (ret) | |
628 | goto err_ret; | |
629 | ||
630 | ret = write_short_reg(devrec, REG_TXSTBL, 0x95); | |
631 | if (ret) | |
632 | goto err_ret; | |
633 | ||
634 | ret = write_long_reg(devrec, REG_RFCON0, 0x03); | |
635 | if (ret) | |
636 | goto err_ret; | |
637 | ||
638 | ret = write_long_reg(devrec, REG_RFCON1, 0x01); | |
639 | if (ret) | |
640 | goto err_ret; | |
641 | ||
642 | ret = write_long_reg(devrec, REG_RFCON2, 0x80); | |
643 | if (ret) | |
644 | goto err_ret; | |
645 | ||
646 | ret = write_long_reg(devrec, REG_RFCON6, 0x90); | |
647 | if (ret) | |
648 | goto err_ret; | |
649 | ||
650 | ret = write_long_reg(devrec, REG_RFCON7, 0x80); | |
651 | if (ret) | |
652 | goto err_ret; | |
653 | ||
654 | ret = write_long_reg(devrec, REG_RFCON8, 0x10); | |
655 | if (ret) | |
656 | goto err_ret; | |
657 | ||
658 | ret = write_long_reg(devrec, REG_SLPCON1, 0x21); | |
659 | if (ret) | |
660 | goto err_ret; | |
661 | ||
662 | ret = write_short_reg(devrec, REG_BBREG2, 0x80); | |
663 | if (ret) | |
664 | goto err_ret; | |
665 | ||
666 | ret = write_short_reg(devrec, REG_CCAEDTH, 0x60); | |
667 | if (ret) | |
668 | goto err_ret; | |
669 | ||
670 | ret = write_short_reg(devrec, REG_BBREG6, 0x40); | |
671 | if (ret) | |
672 | goto err_ret; | |
673 | ||
674 | ret = write_short_reg(devrec, REG_RFCTL, 0x04); | |
675 | if (ret) | |
676 | goto err_ret; | |
677 | ||
678 | ret = write_short_reg(devrec, REG_RFCTL, 0x0); | |
679 | if (ret) | |
680 | goto err_ret; | |
681 | ||
682 | udelay(192); | |
683 | ||
684 | /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */ | |
685 | ret = read_short_reg(devrec, REG_RXMCR, &val); | |
686 | if (ret) | |
687 | goto err_ret; | |
688 | ||
689 | val &= ~0x3; /* Clear RX mode (normal) */ | |
690 | ||
691 | ret = write_short_reg(devrec, REG_RXMCR, val); | |
692 | if (ret) | |
693 | goto err_ret; | |
694 | ||
db9e0ee8 SV |
695 | if (spi_get_device_id(devrec->spi)->driver_data == MRF24J40MC) { |
696 | /* Enable external amplifier. | |
697 | * From MRF24J40MC datasheet section 1.3: Operation. | |
698 | */ | |
699 | read_long_reg(devrec, REG_TESTMODE, &val); | |
700 | val |= 0x7; /* Configure GPIO 0-2 to control amplifier */ | |
701 | write_long_reg(devrec, REG_TESTMODE, val); | |
702 | ||
703 | read_short_reg(devrec, REG_TRISGPIO, &val); | |
704 | val |= 0x8; /* Set GPIO3 as output. */ | |
705 | write_short_reg(devrec, REG_TRISGPIO, val); | |
706 | ||
707 | read_short_reg(devrec, REG_GPIO, &val); | |
708 | val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */ | |
709 | write_short_reg(devrec, REG_GPIO, val); | |
710 | ||
711 | /* Reduce TX pwr to meet FCC requirements. | |
712 | * From MRF24J40MC datasheet section 3.1.1 | |
713 | */ | |
714 | write_long_reg(devrec, REG_RFCON3, 0x28); | |
715 | } | |
716 | ||
3dac9a79 VB |
717 | return 0; |
718 | ||
719 | err_ret: | |
720 | return ret; | |
721 | } | |
722 | ||
766928fb AA |
723 | static void mrf24j40_phy_setup(struct mrf24j40 *devrec) |
724 | { | |
d344c912 | 725 | ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr); |
766928fb AA |
726 | devrec->hw->phy->current_channel = 11; |
727 | } | |
728 | ||
bb1f4606 | 729 | static int mrf24j40_probe(struct spi_device *spi) |
3731a334 AO |
730 | { |
731 | int ret = -ENOMEM; | |
b2cfdf3c | 732 | struct ieee802154_hw *hw; |
3731a334 AO |
733 | struct mrf24j40 *devrec; |
734 | ||
ca079ad6 | 735 | dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq); |
3731a334 | 736 | |
b2cfdf3c AA |
737 | /* Register with the 802154 subsystem */ |
738 | ||
739 | hw = ieee802154_alloc_hw(sizeof(*devrec), &mrf24j40_ops); | |
740 | if (!hw) | |
0aaf43f5 | 741 | goto err_ret; |
b2cfdf3c AA |
742 | |
743 | devrec = hw->priv; | |
744 | devrec->spi = spi; | |
745 | spi_set_drvdata(spi, devrec); | |
746 | devrec->hw = hw; | |
747 | devrec->hw->parent = &spi->dev; | |
748 | devrec->hw->phy->supported.channels[0] = CHANNEL_MASK; | |
749 | devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AFILT; | |
750 | ||
0aaf43f5 | 751 | devrec->buf = devm_kzalloc(&spi->dev, 3, GFP_KERNEL); |
3731a334 | 752 | if (!devrec->buf) |
b2cfdf3c | 753 | goto err_register_device; |
3731a334 | 754 | |
78aedb6b AA |
755 | if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) { |
756 | dev_warn(&spi->dev, "spi clock above possible maximum: %d", | |
757 | MAX_SPI_SPEED_HZ); | |
758 | return -EINVAL; | |
759 | } | |
3731a334 AO |
760 | |
761 | mutex_init(&devrec->buffer_mutex); | |
762 | init_completion(&devrec->tx_complete); | |
3731a334 | 763 | |
3dac9a79 | 764 | ret = mrf24j40_hw_init(devrec); |
3731a334 | 765 | if (ret) |
a339e184 | 766 | goto err_register_device; |
3731a334 | 767 | |
766928fb AA |
768 | mrf24j40_phy_setup(devrec); |
769 | ||
0aaf43f5 VB |
770 | ret = devm_request_threaded_irq(&spi->dev, |
771 | spi->irq, | |
772 | NULL, | |
773 | mrf24j40_isr, | |
774 | IRQF_TRIGGER_LOW|IRQF_ONESHOT, | |
775 | dev_name(&spi->dev), | |
776 | devrec); | |
3731a334 AO |
777 | |
778 | if (ret) { | |
779 | dev_err(printdev(devrec), "Unable to get IRQ"); | |
a339e184 | 780 | goto err_register_device; |
3731a334 AO |
781 | } |
782 | ||
a339e184 AA |
783 | dev_dbg(printdev(devrec), "registered mrf24j40\n"); |
784 | ret = ieee802154_register_hw(devrec->hw); | |
785 | if (ret) | |
786 | goto err_register_device; | |
787 | ||
3731a334 AO |
788 | return 0; |
789 | ||
3731a334 | 790 | err_register_device: |
5a504397 | 791 | ieee802154_free_hw(devrec->hw); |
0aaf43f5 | 792 | err_ret: |
3731a334 AO |
793 | return ret; |
794 | } | |
795 | ||
bb1f4606 | 796 | static int mrf24j40_remove(struct spi_device *spi) |
3731a334 | 797 | { |
4fa0a0ef | 798 | struct mrf24j40 *devrec = spi_get_drvdata(spi); |
3731a334 AO |
799 | |
800 | dev_dbg(printdev(devrec), "remove\n"); | |
801 | ||
5a504397 AA |
802 | ieee802154_unregister_hw(devrec->hw); |
803 | ieee802154_free_hw(devrec->hw); | |
3731a334 AO |
804 | /* TODO: Will ieee802154_free_device() wait until ->xmit() is |
805 | * complete? */ | |
806 | ||
3731a334 AO |
807 | return 0; |
808 | } | |
809 | ||
2e6fd648 AA |
810 | static const struct of_device_id mrf24j40_of_match[] = { |
811 | { .compatible = "microchip,mrf24j40", .data = (void *)MRF24J40 }, | |
812 | { .compatible = "microchip,mrf24j40ma", .data = (void *)MRF24J40MA }, | |
813 | { .compatible = "microchip,mrf24j40mc", .data = (void *)MRF24J40MC }, | |
814 | { }, | |
815 | }; | |
816 | MODULE_DEVICE_TABLE(of, mrf24j40_of_match); | |
817 | ||
3731a334 | 818 | static const struct spi_device_id mrf24j40_ids[] = { |
db9e0ee8 SV |
819 | { "mrf24j40", MRF24J40 }, |
820 | { "mrf24j40ma", MRF24J40MA }, | |
821 | { "mrf24j40mc", MRF24J40MC }, | |
3731a334 AO |
822 | { }, |
823 | }; | |
824 | MODULE_DEVICE_TABLE(spi, mrf24j40_ids); | |
825 | ||
826 | static struct spi_driver mrf24j40_driver = { | |
827 | .driver = { | |
2e6fd648 | 828 | .of_match_table = of_match_ptr(mrf24j40_of_match), |
3731a334 | 829 | .name = "mrf24j40", |
3731a334 AO |
830 | .owner = THIS_MODULE, |
831 | }, | |
832 | .id_table = mrf24j40_ids, | |
833 | .probe = mrf24j40_probe, | |
bb1f4606 | 834 | .remove = mrf24j40_remove, |
3731a334 AO |
835 | }; |
836 | ||
3d4a1316 | 837 | module_spi_driver(mrf24j40_driver); |
3731a334 AO |
838 | |
839 | MODULE_LICENSE("GPL"); | |
840 | MODULE_AUTHOR("Alan Ott"); | |
841 | MODULE_DESCRIPTION("MRF24J40 SPI 802.15.4 Controller Driver"); |