1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Driver for Microchip MRF24J40 802.15.4 Wireless-PAN Networking controller
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2012 Alan Ott <alan@signal11.us>
6*4882a593Smuzhiyun * Signal 11 Software
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/spi/spi.h>
10*4882a593Smuzhiyun #include <linux/interrupt.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/of.h>
13*4882a593Smuzhiyun #include <linux/regmap.h>
14*4882a593Smuzhiyun #include <linux/ieee802154.h>
15*4882a593Smuzhiyun #include <linux/irq.h>
16*4882a593Smuzhiyun #include <net/cfg802154.h>
17*4882a593Smuzhiyun #include <net/mac802154.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* MRF24J40 Short Address Registers */
20*4882a593Smuzhiyun #define REG_RXMCR 0x00 /* Receive MAC control */
21*4882a593Smuzhiyun #define BIT_PROMI BIT(0)
22*4882a593Smuzhiyun #define BIT_ERRPKT BIT(1)
23*4882a593Smuzhiyun #define BIT_NOACKRSP BIT(5)
24*4882a593Smuzhiyun #define BIT_PANCOORD BIT(3)
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #define REG_PANIDL 0x01 /* PAN ID (low) */
27*4882a593Smuzhiyun #define REG_PANIDH 0x02 /* PAN ID (high) */
28*4882a593Smuzhiyun #define REG_SADRL 0x03 /* Short address (low) */
29*4882a593Smuzhiyun #define REG_SADRH 0x04 /* Short address (high) */
30*4882a593Smuzhiyun #define REG_EADR0 0x05 /* Long address (low) (high is EADR7) */
31*4882a593Smuzhiyun #define REG_EADR1 0x06
32*4882a593Smuzhiyun #define REG_EADR2 0x07
33*4882a593Smuzhiyun #define REG_EADR3 0x08
34*4882a593Smuzhiyun #define REG_EADR4 0x09
35*4882a593Smuzhiyun #define REG_EADR5 0x0A
36*4882a593Smuzhiyun #define REG_EADR6 0x0B
37*4882a593Smuzhiyun #define REG_EADR7 0x0C
38*4882a593Smuzhiyun #define REG_RXFLUSH 0x0D
39*4882a593Smuzhiyun #define REG_ORDER 0x10
40*4882a593Smuzhiyun #define REG_TXMCR 0x11 /* Transmit MAC control */
41*4882a593Smuzhiyun #define TXMCR_MIN_BE_SHIFT 3
42*4882a593Smuzhiyun #define TXMCR_MIN_BE_MASK 0x18
43*4882a593Smuzhiyun #define TXMCR_CSMA_RETRIES_SHIFT 0
44*4882a593Smuzhiyun #define TXMCR_CSMA_RETRIES_MASK 0x07
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun #define REG_ACKTMOUT 0x12
47*4882a593Smuzhiyun #define REG_ESLOTG1 0x13
48*4882a593Smuzhiyun #define REG_SYMTICKL 0x14
49*4882a593Smuzhiyun #define REG_SYMTICKH 0x15
50*4882a593Smuzhiyun #define REG_PACON0 0x16 /* Power Amplifier Control */
51*4882a593Smuzhiyun #define REG_PACON1 0x17 /* Power Amplifier Control */
52*4882a593Smuzhiyun #define REG_PACON2 0x18 /* Power Amplifier Control */
53*4882a593Smuzhiyun #define REG_TXBCON0 0x1A
54*4882a593Smuzhiyun #define REG_TXNCON 0x1B /* Transmit Normal FIFO Control */
55*4882a593Smuzhiyun #define BIT_TXNTRIG BIT(0)
56*4882a593Smuzhiyun #define BIT_TXNSECEN BIT(1)
57*4882a593Smuzhiyun #define BIT_TXNACKREQ BIT(2)
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #define REG_TXG1CON 0x1C
60*4882a593Smuzhiyun #define REG_TXG2CON 0x1D
61*4882a593Smuzhiyun #define REG_ESLOTG23 0x1E
62*4882a593Smuzhiyun #define REG_ESLOTG45 0x1F
63*4882a593Smuzhiyun #define REG_ESLOTG67 0x20
64*4882a593Smuzhiyun #define REG_TXPEND 0x21
65*4882a593Smuzhiyun #define REG_WAKECON 0x22
66*4882a593Smuzhiyun #define REG_FROMOFFSET 0x23
67*4882a593Smuzhiyun #define REG_TXSTAT 0x24 /* TX MAC Status Register */
68*4882a593Smuzhiyun #define REG_TXBCON1 0x25
69*4882a593Smuzhiyun #define REG_GATECLK 0x26
70*4882a593Smuzhiyun #define REG_TXTIME 0x27
71*4882a593Smuzhiyun #define REG_HSYMTMRL 0x28
72*4882a593Smuzhiyun #define REG_HSYMTMRH 0x29
73*4882a593Smuzhiyun #define REG_SOFTRST 0x2A /* Soft Reset */
74*4882a593Smuzhiyun #define REG_SECCON0 0x2C
75*4882a593Smuzhiyun #define REG_SECCON1 0x2D
76*4882a593Smuzhiyun #define REG_TXSTBL 0x2E /* TX Stabilization */
77*4882a593Smuzhiyun #define REG_RXSR 0x30
78*4882a593Smuzhiyun #define REG_INTSTAT 0x31 /* Interrupt Status */
79*4882a593Smuzhiyun #define BIT_TXNIF BIT(0)
80*4882a593Smuzhiyun #define BIT_RXIF BIT(3)
81*4882a593Smuzhiyun #define BIT_SECIF BIT(4)
82*4882a593Smuzhiyun #define BIT_SECIGNORE BIT(7)
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun #define REG_INTCON 0x32 /* Interrupt Control */
85*4882a593Smuzhiyun #define BIT_TXNIE BIT(0)
86*4882a593Smuzhiyun #define BIT_RXIE BIT(3)
87*4882a593Smuzhiyun #define BIT_SECIE BIT(4)
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun #define REG_GPIO 0x33 /* GPIO */
90*4882a593Smuzhiyun #define REG_TRISGPIO 0x34 /* GPIO direction */
91*4882a593Smuzhiyun #define REG_SLPACK 0x35
92*4882a593Smuzhiyun #define REG_RFCTL 0x36 /* RF Control Mode Register */
93*4882a593Smuzhiyun #define BIT_RFRST BIT(2)
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun #define REG_SECCR2 0x37
96*4882a593Smuzhiyun #define REG_BBREG0 0x38
97*4882a593Smuzhiyun #define REG_BBREG1 0x39 /* Baseband Registers */
98*4882a593Smuzhiyun #define BIT_RXDECINV BIT(2)
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun #define REG_BBREG2 0x3A /* */
101*4882a593Smuzhiyun #define BBREG2_CCA_MODE_SHIFT 6
102*4882a593Smuzhiyun #define BBREG2_CCA_MODE_MASK 0xc0
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun #define REG_BBREG3 0x3B
105*4882a593Smuzhiyun #define REG_BBREG4 0x3C
106*4882a593Smuzhiyun #define REG_BBREG6 0x3E /* */
107*4882a593Smuzhiyun #define REG_CCAEDTH 0x3F /* Energy Detection Threshold */
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun /* MRF24J40 Long Address Registers */
110*4882a593Smuzhiyun #define REG_RFCON0 0x200 /* RF Control Registers */
111*4882a593Smuzhiyun #define RFCON0_CH_SHIFT 4
112*4882a593Smuzhiyun #define RFCON0_CH_MASK 0xf0
113*4882a593Smuzhiyun #define RFOPT_RECOMMEND 3
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun #define REG_RFCON1 0x201
116*4882a593Smuzhiyun #define REG_RFCON2 0x202
117*4882a593Smuzhiyun #define REG_RFCON3 0x203
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun #define TXPWRL_MASK 0xc0
120*4882a593Smuzhiyun #define TXPWRL_SHIFT 6
121*4882a593Smuzhiyun #define TXPWRL_30 0x3
122*4882a593Smuzhiyun #define TXPWRL_20 0x2
123*4882a593Smuzhiyun #define TXPWRL_10 0x1
124*4882a593Smuzhiyun #define TXPWRL_0 0x0
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun #define TXPWRS_MASK 0x38
127*4882a593Smuzhiyun #define TXPWRS_SHIFT 3
128*4882a593Smuzhiyun #define TXPWRS_6_3 0x7
129*4882a593Smuzhiyun #define TXPWRS_4_9 0x6
130*4882a593Smuzhiyun #define TXPWRS_3_7 0x5
131*4882a593Smuzhiyun #define TXPWRS_2_8 0x4
132*4882a593Smuzhiyun #define TXPWRS_1_9 0x3
133*4882a593Smuzhiyun #define TXPWRS_1_2 0x2
134*4882a593Smuzhiyun #define TXPWRS_0_5 0x1
135*4882a593Smuzhiyun #define TXPWRS_0 0x0
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun #define REG_RFCON5 0x205
138*4882a593Smuzhiyun #define REG_RFCON6 0x206
139*4882a593Smuzhiyun #define REG_RFCON7 0x207
140*4882a593Smuzhiyun #define REG_RFCON8 0x208
141*4882a593Smuzhiyun #define REG_SLPCAL0 0x209
142*4882a593Smuzhiyun #define REG_SLPCAL1 0x20A
143*4882a593Smuzhiyun #define REG_SLPCAL2 0x20B
144*4882a593Smuzhiyun #define REG_RFSTATE 0x20F
145*4882a593Smuzhiyun #define REG_RSSI 0x210
146*4882a593Smuzhiyun #define REG_SLPCON0 0x211 /* Sleep Clock Control Registers */
147*4882a593Smuzhiyun #define BIT_INTEDGE BIT(1)
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun #define REG_SLPCON1 0x220
150*4882a593Smuzhiyun #define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */
151*4882a593Smuzhiyun #define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */
152*4882a593Smuzhiyun #define REG_REMCNTL 0x224
153*4882a593Smuzhiyun #define REG_REMCNTH 0x225
154*4882a593Smuzhiyun #define REG_MAINCNT0 0x226
155*4882a593Smuzhiyun #define REG_MAINCNT1 0x227
156*4882a593Smuzhiyun #define REG_MAINCNT2 0x228
157*4882a593Smuzhiyun #define REG_MAINCNT3 0x229
158*4882a593Smuzhiyun #define REG_TESTMODE 0x22F /* Test mode */
159*4882a593Smuzhiyun #define REG_ASSOEAR0 0x230
160*4882a593Smuzhiyun #define REG_ASSOEAR1 0x231
161*4882a593Smuzhiyun #define REG_ASSOEAR2 0x232
162*4882a593Smuzhiyun #define REG_ASSOEAR3 0x233
163*4882a593Smuzhiyun #define REG_ASSOEAR4 0x234
164*4882a593Smuzhiyun #define REG_ASSOEAR5 0x235
165*4882a593Smuzhiyun #define REG_ASSOEAR6 0x236
166*4882a593Smuzhiyun #define REG_ASSOEAR7 0x237
167*4882a593Smuzhiyun #define REG_ASSOSAR0 0x238
168*4882a593Smuzhiyun #define REG_ASSOSAR1 0x239
169*4882a593Smuzhiyun #define REG_UNONCE0 0x240
170*4882a593Smuzhiyun #define REG_UNONCE1 0x241
171*4882a593Smuzhiyun #define REG_UNONCE2 0x242
172*4882a593Smuzhiyun #define REG_UNONCE3 0x243
173*4882a593Smuzhiyun #define REG_UNONCE4 0x244
174*4882a593Smuzhiyun #define REG_UNONCE5 0x245
175*4882a593Smuzhiyun #define REG_UNONCE6 0x246
176*4882a593Smuzhiyun #define REG_UNONCE7 0x247
177*4882a593Smuzhiyun #define REG_UNONCE8 0x248
178*4882a593Smuzhiyun #define REG_UNONCE9 0x249
179*4882a593Smuzhiyun #define REG_UNONCE10 0x24A
180*4882a593Smuzhiyun #define REG_UNONCE11 0x24B
181*4882a593Smuzhiyun #define REG_UNONCE12 0x24C
182*4882a593Smuzhiyun #define REG_RX_FIFO 0x300 /* Receive FIFO */
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /* Device configuration: Only channels 11-26 on page 0 are supported. */
185*4882a593Smuzhiyun #define MRF24J40_CHAN_MIN 11
186*4882a593Smuzhiyun #define MRF24J40_CHAN_MAX 26
187*4882a593Smuzhiyun #define CHANNEL_MASK (((u32)1 << (MRF24J40_CHAN_MAX + 1)) \
188*4882a593Smuzhiyun - ((u32)1 << MRF24J40_CHAN_MIN))
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun #define TX_FIFO_SIZE 128 /* From datasheet */
191*4882a593Smuzhiyun #define RX_FIFO_SIZE 144 /* From datasheet */
192*4882a593Smuzhiyun #define SET_CHANNEL_DELAY_US 192 /* From datasheet */
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun enum mrf24j40_modules { MRF24J40, MRF24J40MA, MRF24J40MC };
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /* Device Private Data */
197*4882a593Smuzhiyun struct mrf24j40 {
198*4882a593Smuzhiyun struct spi_device *spi;
199*4882a593Smuzhiyun struct ieee802154_hw *hw;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun struct regmap *regmap_short;
202*4882a593Smuzhiyun struct regmap *regmap_long;
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /* for writing txfifo */
205*4882a593Smuzhiyun struct spi_message tx_msg;
206*4882a593Smuzhiyun u8 tx_hdr_buf[2];
207*4882a593Smuzhiyun struct spi_transfer tx_hdr_trx;
208*4882a593Smuzhiyun u8 tx_len_buf[2];
209*4882a593Smuzhiyun struct spi_transfer tx_len_trx;
210*4882a593Smuzhiyun struct spi_transfer tx_buf_trx;
211*4882a593Smuzhiyun struct sk_buff *tx_skb;
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun /* post transmit message to send frame out */
214*4882a593Smuzhiyun struct spi_message tx_post_msg;
215*4882a593Smuzhiyun u8 tx_post_buf[2];
216*4882a593Smuzhiyun struct spi_transfer tx_post_trx;
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /* for protect/unprotect/read length rxfifo */
219*4882a593Smuzhiyun struct spi_message rx_msg;
220*4882a593Smuzhiyun u8 rx_buf[3];
221*4882a593Smuzhiyun struct spi_transfer rx_trx;
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* receive handling */
224*4882a593Smuzhiyun struct spi_message rx_buf_msg;
225*4882a593Smuzhiyun u8 rx_addr_buf[2];
226*4882a593Smuzhiyun struct spi_transfer rx_addr_trx;
227*4882a593Smuzhiyun u8 rx_lqi_buf[2];
228*4882a593Smuzhiyun struct spi_transfer rx_lqi_trx;
229*4882a593Smuzhiyun u8 rx_fifo_buf[RX_FIFO_SIZE];
230*4882a593Smuzhiyun struct spi_transfer rx_fifo_buf_trx;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun /* isr handling for reading intstat */
233*4882a593Smuzhiyun struct spi_message irq_msg;
234*4882a593Smuzhiyun u8 irq_buf[2];
235*4882a593Smuzhiyun struct spi_transfer irq_trx;
236*4882a593Smuzhiyun };
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun /* regmap information for short address register access */
239*4882a593Smuzhiyun #define MRF24J40_SHORT_WRITE 0x01
240*4882a593Smuzhiyun #define MRF24J40_SHORT_READ 0x00
241*4882a593Smuzhiyun #define MRF24J40_SHORT_NUMREGS 0x3F
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /* regmap information for long address register access */
244*4882a593Smuzhiyun #define MRF24J40_LONG_ACCESS 0x80
245*4882a593Smuzhiyun #define MRF24J40_LONG_NUMREGS 0x38F
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /* Read/Write SPI Commands for Short and Long Address registers. */
248*4882a593Smuzhiyun #define MRF24J40_READSHORT(reg) ((reg) << 1)
249*4882a593Smuzhiyun #define MRF24J40_WRITESHORT(reg) ((reg) << 1 | 1)
250*4882a593Smuzhiyun #define MRF24J40_READLONG(reg) (1 << 15 | (reg) << 5)
251*4882a593Smuzhiyun #define MRF24J40_WRITELONG(reg) (1 << 15 | (reg) << 5 | 1 << 4)
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /* The datasheet indicates the theoretical maximum for SCK to be 10MHz */
254*4882a593Smuzhiyun #define MAX_SPI_SPEED_HZ 10000000
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun #define printdev(X) (&X->spi->dev)
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun static bool
mrf24j40_short_reg_writeable(struct device * dev,unsigned int reg)259*4882a593Smuzhiyun mrf24j40_short_reg_writeable(struct device *dev, unsigned int reg)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun switch (reg) {
262*4882a593Smuzhiyun case REG_RXMCR:
263*4882a593Smuzhiyun case REG_PANIDL:
264*4882a593Smuzhiyun case REG_PANIDH:
265*4882a593Smuzhiyun case REG_SADRL:
266*4882a593Smuzhiyun case REG_SADRH:
267*4882a593Smuzhiyun case REG_EADR0:
268*4882a593Smuzhiyun case REG_EADR1:
269*4882a593Smuzhiyun case REG_EADR2:
270*4882a593Smuzhiyun case REG_EADR3:
271*4882a593Smuzhiyun case REG_EADR4:
272*4882a593Smuzhiyun case REG_EADR5:
273*4882a593Smuzhiyun case REG_EADR6:
274*4882a593Smuzhiyun case REG_EADR7:
275*4882a593Smuzhiyun case REG_RXFLUSH:
276*4882a593Smuzhiyun case REG_ORDER:
277*4882a593Smuzhiyun case REG_TXMCR:
278*4882a593Smuzhiyun case REG_ACKTMOUT:
279*4882a593Smuzhiyun case REG_ESLOTG1:
280*4882a593Smuzhiyun case REG_SYMTICKL:
281*4882a593Smuzhiyun case REG_SYMTICKH:
282*4882a593Smuzhiyun case REG_PACON0:
283*4882a593Smuzhiyun case REG_PACON1:
284*4882a593Smuzhiyun case REG_PACON2:
285*4882a593Smuzhiyun case REG_TXBCON0:
286*4882a593Smuzhiyun case REG_TXNCON:
287*4882a593Smuzhiyun case REG_TXG1CON:
288*4882a593Smuzhiyun case REG_TXG2CON:
289*4882a593Smuzhiyun case REG_ESLOTG23:
290*4882a593Smuzhiyun case REG_ESLOTG45:
291*4882a593Smuzhiyun case REG_ESLOTG67:
292*4882a593Smuzhiyun case REG_TXPEND:
293*4882a593Smuzhiyun case REG_WAKECON:
294*4882a593Smuzhiyun case REG_FROMOFFSET:
295*4882a593Smuzhiyun case REG_TXBCON1:
296*4882a593Smuzhiyun case REG_GATECLK:
297*4882a593Smuzhiyun case REG_TXTIME:
298*4882a593Smuzhiyun case REG_HSYMTMRL:
299*4882a593Smuzhiyun case REG_HSYMTMRH:
300*4882a593Smuzhiyun case REG_SOFTRST:
301*4882a593Smuzhiyun case REG_SECCON0:
302*4882a593Smuzhiyun case REG_SECCON1:
303*4882a593Smuzhiyun case REG_TXSTBL:
304*4882a593Smuzhiyun case REG_RXSR:
305*4882a593Smuzhiyun case REG_INTCON:
306*4882a593Smuzhiyun case REG_TRISGPIO:
307*4882a593Smuzhiyun case REG_GPIO:
308*4882a593Smuzhiyun case REG_RFCTL:
309*4882a593Smuzhiyun case REG_SECCR2:
310*4882a593Smuzhiyun case REG_SLPACK:
311*4882a593Smuzhiyun case REG_BBREG0:
312*4882a593Smuzhiyun case REG_BBREG1:
313*4882a593Smuzhiyun case REG_BBREG2:
314*4882a593Smuzhiyun case REG_BBREG3:
315*4882a593Smuzhiyun case REG_BBREG4:
316*4882a593Smuzhiyun case REG_BBREG6:
317*4882a593Smuzhiyun case REG_CCAEDTH:
318*4882a593Smuzhiyun return true;
319*4882a593Smuzhiyun default:
320*4882a593Smuzhiyun return false;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun static bool
mrf24j40_short_reg_readable(struct device * dev,unsigned int reg)325*4882a593Smuzhiyun mrf24j40_short_reg_readable(struct device *dev, unsigned int reg)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun bool rc;
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /* all writeable are also readable */
330*4882a593Smuzhiyun rc = mrf24j40_short_reg_writeable(dev, reg);
331*4882a593Smuzhiyun if (rc)
332*4882a593Smuzhiyun return rc;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun /* readonly regs */
335*4882a593Smuzhiyun switch (reg) {
336*4882a593Smuzhiyun case REG_TXSTAT:
337*4882a593Smuzhiyun case REG_INTSTAT:
338*4882a593Smuzhiyun return true;
339*4882a593Smuzhiyun default:
340*4882a593Smuzhiyun return false;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun static bool
mrf24j40_short_reg_volatile(struct device * dev,unsigned int reg)345*4882a593Smuzhiyun mrf24j40_short_reg_volatile(struct device *dev, unsigned int reg)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun /* can be changed during runtime */
348*4882a593Smuzhiyun switch (reg) {
349*4882a593Smuzhiyun case REG_TXSTAT:
350*4882a593Smuzhiyun case REG_INTSTAT:
351*4882a593Smuzhiyun case REG_RXFLUSH:
352*4882a593Smuzhiyun case REG_TXNCON:
353*4882a593Smuzhiyun case REG_SOFTRST:
354*4882a593Smuzhiyun case REG_RFCTL:
355*4882a593Smuzhiyun case REG_TXBCON0:
356*4882a593Smuzhiyun case REG_TXG1CON:
357*4882a593Smuzhiyun case REG_TXG2CON:
358*4882a593Smuzhiyun case REG_TXBCON1:
359*4882a593Smuzhiyun case REG_SECCON0:
360*4882a593Smuzhiyun case REG_RXSR:
361*4882a593Smuzhiyun case REG_SLPACK:
362*4882a593Smuzhiyun case REG_SECCR2:
363*4882a593Smuzhiyun case REG_BBREG6:
364*4882a593Smuzhiyun /* use them in spi_async and regmap so it's volatile */
365*4882a593Smuzhiyun case REG_BBREG1:
366*4882a593Smuzhiyun return true;
367*4882a593Smuzhiyun default:
368*4882a593Smuzhiyun return false;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun static bool
mrf24j40_short_reg_precious(struct device * dev,unsigned int reg)373*4882a593Smuzhiyun mrf24j40_short_reg_precious(struct device *dev, unsigned int reg)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun /* don't clear irq line on read */
376*4882a593Smuzhiyun switch (reg) {
377*4882a593Smuzhiyun case REG_INTSTAT:
378*4882a593Smuzhiyun return true;
379*4882a593Smuzhiyun default:
380*4882a593Smuzhiyun return false;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun static const struct regmap_config mrf24j40_short_regmap = {
385*4882a593Smuzhiyun .name = "mrf24j40_short",
386*4882a593Smuzhiyun .reg_bits = 7,
387*4882a593Smuzhiyun .val_bits = 8,
388*4882a593Smuzhiyun .pad_bits = 1,
389*4882a593Smuzhiyun .write_flag_mask = MRF24J40_SHORT_WRITE,
390*4882a593Smuzhiyun .read_flag_mask = MRF24J40_SHORT_READ,
391*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
392*4882a593Smuzhiyun .max_register = MRF24J40_SHORT_NUMREGS,
393*4882a593Smuzhiyun .writeable_reg = mrf24j40_short_reg_writeable,
394*4882a593Smuzhiyun .readable_reg = mrf24j40_short_reg_readable,
395*4882a593Smuzhiyun .volatile_reg = mrf24j40_short_reg_volatile,
396*4882a593Smuzhiyun .precious_reg = mrf24j40_short_reg_precious,
397*4882a593Smuzhiyun };
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun static bool
mrf24j40_long_reg_writeable(struct device * dev,unsigned int reg)400*4882a593Smuzhiyun mrf24j40_long_reg_writeable(struct device *dev, unsigned int reg)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun switch (reg) {
403*4882a593Smuzhiyun case REG_RFCON0:
404*4882a593Smuzhiyun case REG_RFCON1:
405*4882a593Smuzhiyun case REG_RFCON2:
406*4882a593Smuzhiyun case REG_RFCON3:
407*4882a593Smuzhiyun case REG_RFCON5:
408*4882a593Smuzhiyun case REG_RFCON6:
409*4882a593Smuzhiyun case REG_RFCON7:
410*4882a593Smuzhiyun case REG_RFCON8:
411*4882a593Smuzhiyun case REG_SLPCAL2:
412*4882a593Smuzhiyun case REG_SLPCON0:
413*4882a593Smuzhiyun case REG_SLPCON1:
414*4882a593Smuzhiyun case REG_WAKETIMEL:
415*4882a593Smuzhiyun case REG_WAKETIMEH:
416*4882a593Smuzhiyun case REG_REMCNTL:
417*4882a593Smuzhiyun case REG_REMCNTH:
418*4882a593Smuzhiyun case REG_MAINCNT0:
419*4882a593Smuzhiyun case REG_MAINCNT1:
420*4882a593Smuzhiyun case REG_MAINCNT2:
421*4882a593Smuzhiyun case REG_MAINCNT3:
422*4882a593Smuzhiyun case REG_TESTMODE:
423*4882a593Smuzhiyun case REG_ASSOEAR0:
424*4882a593Smuzhiyun case REG_ASSOEAR1:
425*4882a593Smuzhiyun case REG_ASSOEAR2:
426*4882a593Smuzhiyun case REG_ASSOEAR3:
427*4882a593Smuzhiyun case REG_ASSOEAR4:
428*4882a593Smuzhiyun case REG_ASSOEAR5:
429*4882a593Smuzhiyun case REG_ASSOEAR6:
430*4882a593Smuzhiyun case REG_ASSOEAR7:
431*4882a593Smuzhiyun case REG_ASSOSAR0:
432*4882a593Smuzhiyun case REG_ASSOSAR1:
433*4882a593Smuzhiyun case REG_UNONCE0:
434*4882a593Smuzhiyun case REG_UNONCE1:
435*4882a593Smuzhiyun case REG_UNONCE2:
436*4882a593Smuzhiyun case REG_UNONCE3:
437*4882a593Smuzhiyun case REG_UNONCE4:
438*4882a593Smuzhiyun case REG_UNONCE5:
439*4882a593Smuzhiyun case REG_UNONCE6:
440*4882a593Smuzhiyun case REG_UNONCE7:
441*4882a593Smuzhiyun case REG_UNONCE8:
442*4882a593Smuzhiyun case REG_UNONCE9:
443*4882a593Smuzhiyun case REG_UNONCE10:
444*4882a593Smuzhiyun case REG_UNONCE11:
445*4882a593Smuzhiyun case REG_UNONCE12:
446*4882a593Smuzhiyun return true;
447*4882a593Smuzhiyun default:
448*4882a593Smuzhiyun return false;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun }
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun static bool
mrf24j40_long_reg_readable(struct device * dev,unsigned int reg)453*4882a593Smuzhiyun mrf24j40_long_reg_readable(struct device *dev, unsigned int reg)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun bool rc;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun /* all writeable are also readable */
458*4882a593Smuzhiyun rc = mrf24j40_long_reg_writeable(dev, reg);
459*4882a593Smuzhiyun if (rc)
460*4882a593Smuzhiyun return rc;
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun /* readonly regs */
463*4882a593Smuzhiyun switch (reg) {
464*4882a593Smuzhiyun case REG_SLPCAL0:
465*4882a593Smuzhiyun case REG_SLPCAL1:
466*4882a593Smuzhiyun case REG_RFSTATE:
467*4882a593Smuzhiyun case REG_RSSI:
468*4882a593Smuzhiyun return true;
469*4882a593Smuzhiyun default:
470*4882a593Smuzhiyun return false;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun static bool
mrf24j40_long_reg_volatile(struct device * dev,unsigned int reg)475*4882a593Smuzhiyun mrf24j40_long_reg_volatile(struct device *dev, unsigned int reg)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun /* can be changed during runtime */
478*4882a593Smuzhiyun switch (reg) {
479*4882a593Smuzhiyun case REG_SLPCAL0:
480*4882a593Smuzhiyun case REG_SLPCAL1:
481*4882a593Smuzhiyun case REG_SLPCAL2:
482*4882a593Smuzhiyun case REG_RFSTATE:
483*4882a593Smuzhiyun case REG_RSSI:
484*4882a593Smuzhiyun case REG_MAINCNT3:
485*4882a593Smuzhiyun return true;
486*4882a593Smuzhiyun default:
487*4882a593Smuzhiyun return false;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun static const struct regmap_config mrf24j40_long_regmap = {
492*4882a593Smuzhiyun .name = "mrf24j40_long",
493*4882a593Smuzhiyun .reg_bits = 11,
494*4882a593Smuzhiyun .val_bits = 8,
495*4882a593Smuzhiyun .pad_bits = 5,
496*4882a593Smuzhiyun .write_flag_mask = MRF24J40_LONG_ACCESS,
497*4882a593Smuzhiyun .read_flag_mask = MRF24J40_LONG_ACCESS,
498*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
499*4882a593Smuzhiyun .max_register = MRF24J40_LONG_NUMREGS,
500*4882a593Smuzhiyun .writeable_reg = mrf24j40_long_reg_writeable,
501*4882a593Smuzhiyun .readable_reg = mrf24j40_long_reg_readable,
502*4882a593Smuzhiyun .volatile_reg = mrf24j40_long_reg_volatile,
503*4882a593Smuzhiyun };
504*4882a593Smuzhiyun
mrf24j40_long_regmap_write(void * context,const void * data,size_t count)505*4882a593Smuzhiyun static int mrf24j40_long_regmap_write(void *context, const void *data,
506*4882a593Smuzhiyun size_t count)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun struct spi_device *spi = context;
509*4882a593Smuzhiyun u8 buf[3];
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun if (count > 3)
512*4882a593Smuzhiyun return -EINVAL;
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun /* regmap supports read/write mask only in frist byte
515*4882a593Smuzhiyun * long write access need to set the 12th bit, so we
516*4882a593Smuzhiyun * make special handling for write.
517*4882a593Smuzhiyun */
518*4882a593Smuzhiyun memcpy(buf, data, count);
519*4882a593Smuzhiyun buf[1] |= (1 << 4);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun return spi_write(spi, buf, count);
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun static int
mrf24j40_long_regmap_read(void * context,const void * reg,size_t reg_size,void * val,size_t val_size)525*4882a593Smuzhiyun mrf24j40_long_regmap_read(void *context, const void *reg, size_t reg_size,
526*4882a593Smuzhiyun void *val, size_t val_size)
527*4882a593Smuzhiyun {
528*4882a593Smuzhiyun struct spi_device *spi = context;
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun return spi_write_then_read(spi, reg, reg_size, val, val_size);
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun static const struct regmap_bus mrf24j40_long_regmap_bus = {
534*4882a593Smuzhiyun .write = mrf24j40_long_regmap_write,
535*4882a593Smuzhiyun .read = mrf24j40_long_regmap_read,
536*4882a593Smuzhiyun .reg_format_endian_default = REGMAP_ENDIAN_BIG,
537*4882a593Smuzhiyun .val_format_endian_default = REGMAP_ENDIAN_BIG,
538*4882a593Smuzhiyun };
539*4882a593Smuzhiyun
write_tx_buf_complete(void * context)540*4882a593Smuzhiyun static void write_tx_buf_complete(void *context)
541*4882a593Smuzhiyun {
542*4882a593Smuzhiyun struct mrf24j40 *devrec = context;
543*4882a593Smuzhiyun __le16 fc = ieee802154_get_fc_from_skb(devrec->tx_skb);
544*4882a593Smuzhiyun u8 val = BIT_TXNTRIG;
545*4882a593Smuzhiyun int ret;
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun if (ieee802154_is_secen(fc))
548*4882a593Smuzhiyun val |= BIT_TXNSECEN;
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun if (ieee802154_is_ackreq(fc))
551*4882a593Smuzhiyun val |= BIT_TXNACKREQ;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun devrec->tx_post_msg.complete = NULL;
554*4882a593Smuzhiyun devrec->tx_post_buf[0] = MRF24J40_WRITESHORT(REG_TXNCON);
555*4882a593Smuzhiyun devrec->tx_post_buf[1] = val;
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun ret = spi_async(devrec->spi, &devrec->tx_post_msg);
558*4882a593Smuzhiyun if (ret)
559*4882a593Smuzhiyun dev_err(printdev(devrec), "SPI write Failed for transmit buf\n");
560*4882a593Smuzhiyun }
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun /* This function relies on an undocumented write method. Once a write command
563*4882a593Smuzhiyun and address is set, as many bytes of data as desired can be clocked into
564*4882a593Smuzhiyun the device. The datasheet only shows setting one byte at a time. */
write_tx_buf(struct mrf24j40 * devrec,u16 reg,const u8 * data,size_t length)565*4882a593Smuzhiyun static int write_tx_buf(struct mrf24j40 *devrec, u16 reg,
566*4882a593Smuzhiyun const u8 *data, size_t length)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun u16 cmd;
569*4882a593Smuzhiyun int ret;
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun /* Range check the length. 2 bytes are used for the length fields.*/
572*4882a593Smuzhiyun if (length > TX_FIFO_SIZE-2) {
573*4882a593Smuzhiyun dev_err(printdev(devrec), "write_tx_buf() was passed too large a buffer. Performing short write.\n");
574*4882a593Smuzhiyun length = TX_FIFO_SIZE-2;
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun cmd = MRF24J40_WRITELONG(reg);
578*4882a593Smuzhiyun devrec->tx_hdr_buf[0] = cmd >> 8 & 0xff;
579*4882a593Smuzhiyun devrec->tx_hdr_buf[1] = cmd & 0xff;
580*4882a593Smuzhiyun devrec->tx_len_buf[0] = 0x0; /* Header Length. Set to 0 for now. TODO */
581*4882a593Smuzhiyun devrec->tx_len_buf[1] = length; /* Total length */
582*4882a593Smuzhiyun devrec->tx_buf_trx.tx_buf = data;
583*4882a593Smuzhiyun devrec->tx_buf_trx.len = length;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun ret = spi_async(devrec->spi, &devrec->tx_msg);
586*4882a593Smuzhiyun if (ret)
587*4882a593Smuzhiyun dev_err(printdev(devrec), "SPI write Failed for TX buf\n");
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun return ret;
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun
mrf24j40_tx(struct ieee802154_hw * hw,struct sk_buff * skb)592*4882a593Smuzhiyun static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun dev_dbg(printdev(devrec), "tx packet of %d bytes\n", skb->len);
597*4882a593Smuzhiyun devrec->tx_skb = skb;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun return write_tx_buf(devrec, 0x000, skb->data, skb->len);
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
mrf24j40_ed(struct ieee802154_hw * hw,u8 * level)602*4882a593Smuzhiyun static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun /* TODO: */
605*4882a593Smuzhiyun pr_warn("mrf24j40: ed not implemented\n");
606*4882a593Smuzhiyun *level = 0;
607*4882a593Smuzhiyun return 0;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
mrf24j40_start(struct ieee802154_hw * hw)610*4882a593Smuzhiyun static int mrf24j40_start(struct ieee802154_hw *hw)
611*4882a593Smuzhiyun {
612*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun dev_dbg(printdev(devrec), "start\n");
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun /* Clear TXNIE and RXIE. Enable interrupts */
617*4882a593Smuzhiyun return regmap_update_bits(devrec->regmap_short, REG_INTCON,
618*4882a593Smuzhiyun BIT_TXNIE | BIT_RXIE | BIT_SECIE, 0);
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun
mrf24j40_stop(struct ieee802154_hw * hw)621*4882a593Smuzhiyun static void mrf24j40_stop(struct ieee802154_hw *hw)
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun dev_dbg(printdev(devrec), "stop\n");
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun /* Set TXNIE and RXIE. Disable Interrupts */
628*4882a593Smuzhiyun regmap_update_bits(devrec->regmap_short, REG_INTCON,
629*4882a593Smuzhiyun BIT_TXNIE | BIT_RXIE, BIT_TXNIE | BIT_RXIE);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
mrf24j40_set_channel(struct ieee802154_hw * hw,u8 page,u8 channel)632*4882a593Smuzhiyun static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
633*4882a593Smuzhiyun {
634*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
635*4882a593Smuzhiyun u8 val;
636*4882a593Smuzhiyun int ret;
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun dev_dbg(printdev(devrec), "Set Channel %d\n", channel);
639*4882a593Smuzhiyun
640*4882a593Smuzhiyun WARN_ON(page != 0);
641*4882a593Smuzhiyun WARN_ON(channel < MRF24J40_CHAN_MIN);
642*4882a593Smuzhiyun WARN_ON(channel > MRF24J40_CHAN_MAX);
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun /* Set Channel TODO */
645*4882a593Smuzhiyun val = (channel - 11) << RFCON0_CH_SHIFT | RFOPT_RECOMMEND;
646*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0,
647*4882a593Smuzhiyun RFCON0_CH_MASK, val);
648*4882a593Smuzhiyun if (ret)
649*4882a593Smuzhiyun return ret;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun /* RF Reset */
652*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST,
653*4882a593Smuzhiyun BIT_RFRST);
654*4882a593Smuzhiyun if (ret)
655*4882a593Smuzhiyun return ret;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, BIT_RFRST, 0);
658*4882a593Smuzhiyun if (!ret)
659*4882a593Smuzhiyun udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun return ret;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
mrf24j40_filter(struct ieee802154_hw * hw,struct ieee802154_hw_addr_filt * filt,unsigned long changed)664*4882a593Smuzhiyun static int mrf24j40_filter(struct ieee802154_hw *hw,
665*4882a593Smuzhiyun struct ieee802154_hw_addr_filt *filt,
666*4882a593Smuzhiyun unsigned long changed)
667*4882a593Smuzhiyun {
668*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun dev_dbg(printdev(devrec), "filter\n");
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
673*4882a593Smuzhiyun /* Short Addr */
674*4882a593Smuzhiyun u8 addrh, addrl;
675*4882a593Smuzhiyun
676*4882a593Smuzhiyun addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff;
677*4882a593Smuzhiyun addrl = le16_to_cpu(filt->short_addr) & 0xff;
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun regmap_write(devrec->regmap_short, REG_SADRH, addrh);
680*4882a593Smuzhiyun regmap_write(devrec->regmap_short, REG_SADRL, addrl);
681*4882a593Smuzhiyun dev_dbg(printdev(devrec),
682*4882a593Smuzhiyun "Set short addr to %04hx\n", filt->short_addr);
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun
685*4882a593Smuzhiyun if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
686*4882a593Smuzhiyun /* Device Address */
687*4882a593Smuzhiyun u8 i, addr[8];
688*4882a593Smuzhiyun
689*4882a593Smuzhiyun memcpy(addr, &filt->ieee_addr, 8);
690*4882a593Smuzhiyun for (i = 0; i < 8; i++)
691*4882a593Smuzhiyun regmap_write(devrec->regmap_short, REG_EADR0 + i,
692*4882a593Smuzhiyun addr[i]);
693*4882a593Smuzhiyun
694*4882a593Smuzhiyun #ifdef DEBUG
695*4882a593Smuzhiyun pr_debug("Set long addr to: ");
696*4882a593Smuzhiyun for (i = 0; i < 8; i++)
697*4882a593Smuzhiyun pr_debug("%02hhx ", addr[7 - i]);
698*4882a593Smuzhiyun pr_debug("\n");
699*4882a593Smuzhiyun #endif
700*4882a593Smuzhiyun }
701*4882a593Smuzhiyun
702*4882a593Smuzhiyun if (changed & IEEE802154_AFILT_PANID_CHANGED) {
703*4882a593Smuzhiyun /* PAN ID */
704*4882a593Smuzhiyun u8 panidl, panidh;
705*4882a593Smuzhiyun
706*4882a593Smuzhiyun panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff;
707*4882a593Smuzhiyun panidl = le16_to_cpu(filt->pan_id) & 0xff;
708*4882a593Smuzhiyun regmap_write(devrec->regmap_short, REG_PANIDH, panidh);
709*4882a593Smuzhiyun regmap_write(devrec->regmap_short, REG_PANIDL, panidl);
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun if (changed & IEEE802154_AFILT_PANC_CHANGED) {
715*4882a593Smuzhiyun /* Pan Coordinator */
716*4882a593Smuzhiyun u8 val;
717*4882a593Smuzhiyun int ret;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun if (filt->pan_coord)
720*4882a593Smuzhiyun val = BIT_PANCOORD;
721*4882a593Smuzhiyun else
722*4882a593Smuzhiyun val = 0;
723*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
724*4882a593Smuzhiyun BIT_PANCOORD, val);
725*4882a593Smuzhiyun if (ret)
726*4882a593Smuzhiyun return ret;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun /* REG_SLOTTED is maintained as default (unslotted/CSMA-CA).
729*4882a593Smuzhiyun * REG_ORDER is maintained as default (no beacon/superframe).
730*4882a593Smuzhiyun */
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun dev_dbg(printdev(devrec), "Set Pan Coord to %s\n",
733*4882a593Smuzhiyun filt->pan_coord ? "on" : "off");
734*4882a593Smuzhiyun }
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun return 0;
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun
mrf24j40_handle_rx_read_buf_unlock(struct mrf24j40 * devrec)739*4882a593Smuzhiyun static void mrf24j40_handle_rx_read_buf_unlock(struct mrf24j40 *devrec)
740*4882a593Smuzhiyun {
741*4882a593Smuzhiyun int ret;
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun /* Turn back on reception of packets off the air. */
744*4882a593Smuzhiyun devrec->rx_msg.complete = NULL;
745*4882a593Smuzhiyun devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
746*4882a593Smuzhiyun devrec->rx_buf[1] = 0x00; /* CLR RXDECINV */
747*4882a593Smuzhiyun ret = spi_async(devrec->spi, &devrec->rx_msg);
748*4882a593Smuzhiyun if (ret)
749*4882a593Smuzhiyun dev_err(printdev(devrec), "failed to unlock rx buffer\n");
750*4882a593Smuzhiyun }
751*4882a593Smuzhiyun
mrf24j40_handle_rx_read_buf_complete(void * context)752*4882a593Smuzhiyun static void mrf24j40_handle_rx_read_buf_complete(void *context)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun struct mrf24j40 *devrec = context;
755*4882a593Smuzhiyun u8 len = devrec->rx_buf[2];
756*4882a593Smuzhiyun u8 rx_local_buf[RX_FIFO_SIZE];
757*4882a593Smuzhiyun struct sk_buff *skb;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun memcpy(rx_local_buf, devrec->rx_fifo_buf, len);
760*4882a593Smuzhiyun mrf24j40_handle_rx_read_buf_unlock(devrec);
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun skb = dev_alloc_skb(IEEE802154_MTU);
763*4882a593Smuzhiyun if (!skb) {
764*4882a593Smuzhiyun dev_err(printdev(devrec), "failed to allocate skb\n");
765*4882a593Smuzhiyun return;
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun
768*4882a593Smuzhiyun skb_put_data(skb, rx_local_buf, len);
769*4882a593Smuzhiyun ieee802154_rx_irqsafe(devrec->hw, skb, 0);
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun #ifdef DEBUG
772*4882a593Smuzhiyun print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", DUMP_PREFIX_OFFSET, 16, 1,
773*4882a593Smuzhiyun rx_local_buf, len, 0);
774*4882a593Smuzhiyun pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
775*4882a593Smuzhiyun devrec->rx_lqi_buf[0], devrec->rx_lqi_buf[1]);
776*4882a593Smuzhiyun #endif
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
mrf24j40_handle_rx_read_buf(void * context)779*4882a593Smuzhiyun static void mrf24j40_handle_rx_read_buf(void *context)
780*4882a593Smuzhiyun {
781*4882a593Smuzhiyun struct mrf24j40 *devrec = context;
782*4882a593Smuzhiyun u16 cmd;
783*4882a593Smuzhiyun int ret;
784*4882a593Smuzhiyun
785*4882a593Smuzhiyun /* if length is invalid read the full MTU */
786*4882a593Smuzhiyun if (!ieee802154_is_valid_psdu_len(devrec->rx_buf[2]))
787*4882a593Smuzhiyun devrec->rx_buf[2] = IEEE802154_MTU;
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun cmd = MRF24J40_READLONG(REG_RX_FIFO + 1);
790*4882a593Smuzhiyun devrec->rx_addr_buf[0] = cmd >> 8 & 0xff;
791*4882a593Smuzhiyun devrec->rx_addr_buf[1] = cmd & 0xff;
792*4882a593Smuzhiyun devrec->rx_fifo_buf_trx.len = devrec->rx_buf[2];
793*4882a593Smuzhiyun ret = spi_async(devrec->spi, &devrec->rx_buf_msg);
794*4882a593Smuzhiyun if (ret) {
795*4882a593Smuzhiyun dev_err(printdev(devrec), "failed to read rx buffer\n");
796*4882a593Smuzhiyun mrf24j40_handle_rx_read_buf_unlock(devrec);
797*4882a593Smuzhiyun }
798*4882a593Smuzhiyun }
799*4882a593Smuzhiyun
mrf24j40_handle_rx_read_len(void * context)800*4882a593Smuzhiyun static void mrf24j40_handle_rx_read_len(void *context)
801*4882a593Smuzhiyun {
802*4882a593Smuzhiyun struct mrf24j40 *devrec = context;
803*4882a593Smuzhiyun u16 cmd;
804*4882a593Smuzhiyun int ret;
805*4882a593Smuzhiyun
806*4882a593Smuzhiyun /* read the length of received frame */
807*4882a593Smuzhiyun devrec->rx_msg.complete = mrf24j40_handle_rx_read_buf;
808*4882a593Smuzhiyun devrec->rx_trx.len = 3;
809*4882a593Smuzhiyun cmd = MRF24J40_READLONG(REG_RX_FIFO);
810*4882a593Smuzhiyun devrec->rx_buf[0] = cmd >> 8 & 0xff;
811*4882a593Smuzhiyun devrec->rx_buf[1] = cmd & 0xff;
812*4882a593Smuzhiyun
813*4882a593Smuzhiyun ret = spi_async(devrec->spi, &devrec->rx_msg);
814*4882a593Smuzhiyun if (ret) {
815*4882a593Smuzhiyun dev_err(printdev(devrec), "failed to read rx buffer length\n");
816*4882a593Smuzhiyun mrf24j40_handle_rx_read_buf_unlock(devrec);
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun
mrf24j40_handle_rx(struct mrf24j40 * devrec)820*4882a593Smuzhiyun static int mrf24j40_handle_rx(struct mrf24j40 *devrec)
821*4882a593Smuzhiyun {
822*4882a593Smuzhiyun /* Turn off reception of packets off the air. This prevents the
823*4882a593Smuzhiyun * device from overwriting the buffer while we're reading it.
824*4882a593Smuzhiyun */
825*4882a593Smuzhiyun devrec->rx_msg.complete = mrf24j40_handle_rx_read_len;
826*4882a593Smuzhiyun devrec->rx_trx.len = 2;
827*4882a593Smuzhiyun devrec->rx_buf[0] = MRF24J40_WRITESHORT(REG_BBREG1);
828*4882a593Smuzhiyun devrec->rx_buf[1] = BIT_RXDECINV; /* SET RXDECINV */
829*4882a593Smuzhiyun
830*4882a593Smuzhiyun return spi_async(devrec->spi, &devrec->rx_msg);
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun static int
mrf24j40_csma_params(struct ieee802154_hw * hw,u8 min_be,u8 max_be,u8 retries)834*4882a593Smuzhiyun mrf24j40_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be,
835*4882a593Smuzhiyun u8 retries)
836*4882a593Smuzhiyun {
837*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
838*4882a593Smuzhiyun u8 val;
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun /* min_be */
841*4882a593Smuzhiyun val = min_be << TXMCR_MIN_BE_SHIFT;
842*4882a593Smuzhiyun /* csma backoffs */
843*4882a593Smuzhiyun val |= retries << TXMCR_CSMA_RETRIES_SHIFT;
844*4882a593Smuzhiyun
845*4882a593Smuzhiyun return regmap_update_bits(devrec->regmap_short, REG_TXMCR,
846*4882a593Smuzhiyun TXMCR_MIN_BE_MASK | TXMCR_CSMA_RETRIES_MASK,
847*4882a593Smuzhiyun val);
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun
mrf24j40_set_cca_mode(struct ieee802154_hw * hw,const struct wpan_phy_cca * cca)850*4882a593Smuzhiyun static int mrf24j40_set_cca_mode(struct ieee802154_hw *hw,
851*4882a593Smuzhiyun const struct wpan_phy_cca *cca)
852*4882a593Smuzhiyun {
853*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
854*4882a593Smuzhiyun u8 val;
855*4882a593Smuzhiyun
856*4882a593Smuzhiyun /* mapping 802.15.4 to driver spec */
857*4882a593Smuzhiyun switch (cca->mode) {
858*4882a593Smuzhiyun case NL802154_CCA_ENERGY:
859*4882a593Smuzhiyun val = 2;
860*4882a593Smuzhiyun break;
861*4882a593Smuzhiyun case NL802154_CCA_CARRIER:
862*4882a593Smuzhiyun val = 1;
863*4882a593Smuzhiyun break;
864*4882a593Smuzhiyun case NL802154_CCA_ENERGY_CARRIER:
865*4882a593Smuzhiyun switch (cca->opt) {
866*4882a593Smuzhiyun case NL802154_CCA_OPT_ENERGY_CARRIER_AND:
867*4882a593Smuzhiyun val = 3;
868*4882a593Smuzhiyun break;
869*4882a593Smuzhiyun default:
870*4882a593Smuzhiyun return -EINVAL;
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun break;
873*4882a593Smuzhiyun default:
874*4882a593Smuzhiyun return -EINVAL;
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
877*4882a593Smuzhiyun return regmap_update_bits(devrec->regmap_short, REG_BBREG2,
878*4882a593Smuzhiyun BBREG2_CCA_MODE_MASK,
879*4882a593Smuzhiyun val << BBREG2_CCA_MODE_SHIFT);
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun
882*4882a593Smuzhiyun /* array for representing ed levels */
883*4882a593Smuzhiyun static const s32 mrf24j40_ed_levels[] = {
884*4882a593Smuzhiyun -9000, -8900, -8800, -8700, -8600, -8500, -8400, -8300, -8200, -8100,
885*4882a593Smuzhiyun -8000, -7900, -7800, -7700, -7600, -7500, -7400, -7300, -7200, -7100,
886*4882a593Smuzhiyun -7000, -6900, -6800, -6700, -6600, -6500, -6400, -6300, -6200, -6100,
887*4882a593Smuzhiyun -6000, -5900, -5800, -5700, -5600, -5500, -5400, -5300, -5200, -5100,
888*4882a593Smuzhiyun -5000, -4900, -4800, -4700, -4600, -4500, -4400, -4300, -4200, -4100,
889*4882a593Smuzhiyun -4000, -3900, -3800, -3700, -3600, -3500
890*4882a593Smuzhiyun };
891*4882a593Smuzhiyun
892*4882a593Smuzhiyun /* map ed levels to register value */
893*4882a593Smuzhiyun static const s32 mrf24j40_ed_levels_map[][2] = {
894*4882a593Smuzhiyun { -9000, 0 }, { -8900, 1 }, { -8800, 2 }, { -8700, 5 }, { -8600, 9 },
895*4882a593Smuzhiyun { -8500, 13 }, { -8400, 18 }, { -8300, 23 }, { -8200, 27 },
896*4882a593Smuzhiyun { -8100, 32 }, { -8000, 37 }, { -7900, 43 }, { -7800, 48 },
897*4882a593Smuzhiyun { -7700, 53 }, { -7600, 58 }, { -7500, 63 }, { -7400, 68 },
898*4882a593Smuzhiyun { -7300, 73 }, { -7200, 78 }, { -7100, 83 }, { -7000, 89 },
899*4882a593Smuzhiyun { -6900, 95 }, { -6800, 100 }, { -6700, 107 }, { -6600, 111 },
900*4882a593Smuzhiyun { -6500, 117 }, { -6400, 121 }, { -6300, 125 }, { -6200, 129 },
901*4882a593Smuzhiyun { -6100, 133 }, { -6000, 138 }, { -5900, 143 }, { -5800, 148 },
902*4882a593Smuzhiyun { -5700, 153 }, { -5600, 159 }, { -5500, 165 }, { -5400, 170 },
903*4882a593Smuzhiyun { -5300, 176 }, { -5200, 183 }, { -5100, 188 }, { -5000, 193 },
904*4882a593Smuzhiyun { -4900, 198 }, { -4800, 203 }, { -4700, 207 }, { -4600, 212 },
905*4882a593Smuzhiyun { -4500, 216 }, { -4400, 221 }, { -4300, 225 }, { -4200, 228 },
906*4882a593Smuzhiyun { -4100, 233 }, { -4000, 239 }, { -3900, 245 }, { -3800, 250 },
907*4882a593Smuzhiyun { -3700, 253 }, { -3600, 254 }, { -3500, 255 },
908*4882a593Smuzhiyun };
909*4882a593Smuzhiyun
mrf24j40_set_cca_ed_level(struct ieee802154_hw * hw,s32 mbm)910*4882a593Smuzhiyun static int mrf24j40_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
911*4882a593Smuzhiyun {
912*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
913*4882a593Smuzhiyun int i;
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(mrf24j40_ed_levels_map); i++) {
916*4882a593Smuzhiyun if (mrf24j40_ed_levels_map[i][0] == mbm)
917*4882a593Smuzhiyun return regmap_write(devrec->regmap_short, REG_CCAEDTH,
918*4882a593Smuzhiyun mrf24j40_ed_levels_map[i][1]);
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun return -EINVAL;
922*4882a593Smuzhiyun }
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun static const s32 mrf24j40ma_powers[] = {
925*4882a593Smuzhiyun 0, -50, -120, -190, -280, -370, -490, -630, -1000, -1050, -1120, -1190,
926*4882a593Smuzhiyun -1280, -1370, -1490, -1630, -2000, -2050, -2120, -2190, -2280, -2370,
927*4882a593Smuzhiyun -2490, -2630, -3000, -3050, -3120, -3190, -3280, -3370, -3490, -3630,
928*4882a593Smuzhiyun };
929*4882a593Smuzhiyun
mrf24j40_set_txpower(struct ieee802154_hw * hw,s32 mbm)930*4882a593Smuzhiyun static int mrf24j40_set_txpower(struct ieee802154_hw *hw, s32 mbm)
931*4882a593Smuzhiyun {
932*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
933*4882a593Smuzhiyun s32 small_scale;
934*4882a593Smuzhiyun u8 val;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun if (0 >= mbm && mbm > -1000) {
937*4882a593Smuzhiyun val = TXPWRL_0 << TXPWRL_SHIFT;
938*4882a593Smuzhiyun small_scale = mbm;
939*4882a593Smuzhiyun } else if (-1000 >= mbm && mbm > -2000) {
940*4882a593Smuzhiyun val = TXPWRL_10 << TXPWRL_SHIFT;
941*4882a593Smuzhiyun small_scale = mbm + 1000;
942*4882a593Smuzhiyun } else if (-2000 >= mbm && mbm > -3000) {
943*4882a593Smuzhiyun val = TXPWRL_20 << TXPWRL_SHIFT;
944*4882a593Smuzhiyun small_scale = mbm + 2000;
945*4882a593Smuzhiyun } else if (-3000 >= mbm && mbm > -4000) {
946*4882a593Smuzhiyun val = TXPWRL_30 << TXPWRL_SHIFT;
947*4882a593Smuzhiyun small_scale = mbm + 3000;
948*4882a593Smuzhiyun } else {
949*4882a593Smuzhiyun return -EINVAL;
950*4882a593Smuzhiyun }
951*4882a593Smuzhiyun
952*4882a593Smuzhiyun switch (small_scale) {
953*4882a593Smuzhiyun case 0:
954*4882a593Smuzhiyun val |= (TXPWRS_0 << TXPWRS_SHIFT);
955*4882a593Smuzhiyun break;
956*4882a593Smuzhiyun case -50:
957*4882a593Smuzhiyun val |= (TXPWRS_0_5 << TXPWRS_SHIFT);
958*4882a593Smuzhiyun break;
959*4882a593Smuzhiyun case -120:
960*4882a593Smuzhiyun val |= (TXPWRS_1_2 << TXPWRS_SHIFT);
961*4882a593Smuzhiyun break;
962*4882a593Smuzhiyun case -190:
963*4882a593Smuzhiyun val |= (TXPWRS_1_9 << TXPWRS_SHIFT);
964*4882a593Smuzhiyun break;
965*4882a593Smuzhiyun case -280:
966*4882a593Smuzhiyun val |= (TXPWRS_2_8 << TXPWRS_SHIFT);
967*4882a593Smuzhiyun break;
968*4882a593Smuzhiyun case -370:
969*4882a593Smuzhiyun val |= (TXPWRS_3_7 << TXPWRS_SHIFT);
970*4882a593Smuzhiyun break;
971*4882a593Smuzhiyun case -490:
972*4882a593Smuzhiyun val |= (TXPWRS_4_9 << TXPWRS_SHIFT);
973*4882a593Smuzhiyun break;
974*4882a593Smuzhiyun case -630:
975*4882a593Smuzhiyun val |= (TXPWRS_6_3 << TXPWRS_SHIFT);
976*4882a593Smuzhiyun break;
977*4882a593Smuzhiyun default:
978*4882a593Smuzhiyun return -EINVAL;
979*4882a593Smuzhiyun }
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun return regmap_update_bits(devrec->regmap_long, REG_RFCON3,
982*4882a593Smuzhiyun TXPWRL_MASK | TXPWRS_MASK, val);
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun
mrf24j40_set_promiscuous_mode(struct ieee802154_hw * hw,bool on)985*4882a593Smuzhiyun static int mrf24j40_set_promiscuous_mode(struct ieee802154_hw *hw, bool on)
986*4882a593Smuzhiyun {
987*4882a593Smuzhiyun struct mrf24j40 *devrec = hw->priv;
988*4882a593Smuzhiyun int ret;
989*4882a593Smuzhiyun
990*4882a593Smuzhiyun if (on) {
991*4882a593Smuzhiyun /* set PROMI, ERRPKT and NOACKRSP */
992*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
993*4882a593Smuzhiyun BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP,
994*4882a593Smuzhiyun BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP);
995*4882a593Smuzhiyun } else {
996*4882a593Smuzhiyun /* clear PROMI, ERRPKT and NOACKRSP */
997*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR,
998*4882a593Smuzhiyun BIT_PROMI | BIT_ERRPKT | BIT_NOACKRSP,
999*4882a593Smuzhiyun 0);
1000*4882a593Smuzhiyun }
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun return ret;
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun
1005*4882a593Smuzhiyun static const struct ieee802154_ops mrf24j40_ops = {
1006*4882a593Smuzhiyun .owner = THIS_MODULE,
1007*4882a593Smuzhiyun .xmit_async = mrf24j40_tx,
1008*4882a593Smuzhiyun .ed = mrf24j40_ed,
1009*4882a593Smuzhiyun .start = mrf24j40_start,
1010*4882a593Smuzhiyun .stop = mrf24j40_stop,
1011*4882a593Smuzhiyun .set_channel = mrf24j40_set_channel,
1012*4882a593Smuzhiyun .set_hw_addr_filt = mrf24j40_filter,
1013*4882a593Smuzhiyun .set_csma_params = mrf24j40_csma_params,
1014*4882a593Smuzhiyun .set_cca_mode = mrf24j40_set_cca_mode,
1015*4882a593Smuzhiyun .set_cca_ed_level = mrf24j40_set_cca_ed_level,
1016*4882a593Smuzhiyun .set_txpower = mrf24j40_set_txpower,
1017*4882a593Smuzhiyun .set_promiscuous_mode = mrf24j40_set_promiscuous_mode,
1018*4882a593Smuzhiyun };
1019*4882a593Smuzhiyun
mrf24j40_intstat_complete(void * context)1020*4882a593Smuzhiyun static void mrf24j40_intstat_complete(void *context)
1021*4882a593Smuzhiyun {
1022*4882a593Smuzhiyun struct mrf24j40 *devrec = context;
1023*4882a593Smuzhiyun u8 intstat = devrec->irq_buf[1];
1024*4882a593Smuzhiyun
1025*4882a593Smuzhiyun enable_irq(devrec->spi->irq);
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun /* Ignore Rx security decryption */
1028*4882a593Smuzhiyun if (intstat & BIT_SECIF)
1029*4882a593Smuzhiyun regmap_write_async(devrec->regmap_short, REG_SECCON0,
1030*4882a593Smuzhiyun BIT_SECIGNORE);
1031*4882a593Smuzhiyun
1032*4882a593Smuzhiyun /* Check for TX complete */
1033*4882a593Smuzhiyun if (intstat & BIT_TXNIF)
1034*4882a593Smuzhiyun ieee802154_xmit_complete(devrec->hw, devrec->tx_skb, false);
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun /* Check for Rx */
1037*4882a593Smuzhiyun if (intstat & BIT_RXIF)
1038*4882a593Smuzhiyun mrf24j40_handle_rx(devrec);
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun
mrf24j40_isr(int irq,void * data)1041*4882a593Smuzhiyun static irqreturn_t mrf24j40_isr(int irq, void *data)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun struct mrf24j40 *devrec = data;
1044*4882a593Smuzhiyun int ret;
1045*4882a593Smuzhiyun
1046*4882a593Smuzhiyun disable_irq_nosync(irq);
1047*4882a593Smuzhiyun
1048*4882a593Smuzhiyun devrec->irq_buf[0] = MRF24J40_READSHORT(REG_INTSTAT);
1049*4882a593Smuzhiyun devrec->irq_buf[1] = 0;
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun /* Read the interrupt status */
1052*4882a593Smuzhiyun ret = spi_async(devrec->spi, &devrec->irq_msg);
1053*4882a593Smuzhiyun if (ret) {
1054*4882a593Smuzhiyun enable_irq(irq);
1055*4882a593Smuzhiyun return IRQ_NONE;
1056*4882a593Smuzhiyun }
1057*4882a593Smuzhiyun
1058*4882a593Smuzhiyun return IRQ_HANDLED;
1059*4882a593Smuzhiyun }
1060*4882a593Smuzhiyun
mrf24j40_hw_init(struct mrf24j40 * devrec)1061*4882a593Smuzhiyun static int mrf24j40_hw_init(struct mrf24j40 *devrec)
1062*4882a593Smuzhiyun {
1063*4882a593Smuzhiyun u32 irq_type;
1064*4882a593Smuzhiyun int ret;
1065*4882a593Smuzhiyun
1066*4882a593Smuzhiyun /* Initialize the device.
1067*4882a593Smuzhiyun From datasheet section 3.2: Initialization. */
1068*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_SOFTRST, 0x07);
1069*4882a593Smuzhiyun if (ret)
1070*4882a593Smuzhiyun goto err_ret;
1071*4882a593Smuzhiyun
1072*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_PACON2, 0x98);
1073*4882a593Smuzhiyun if (ret)
1074*4882a593Smuzhiyun goto err_ret;
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_TXSTBL, 0x95);
1077*4882a593Smuzhiyun if (ret)
1078*4882a593Smuzhiyun goto err_ret;
1079*4882a593Smuzhiyun
1080*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_long, REG_RFCON0, 0x03);
1081*4882a593Smuzhiyun if (ret)
1082*4882a593Smuzhiyun goto err_ret;
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_long, REG_RFCON1, 0x01);
1085*4882a593Smuzhiyun if (ret)
1086*4882a593Smuzhiyun goto err_ret;
1087*4882a593Smuzhiyun
1088*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_long, REG_RFCON2, 0x80);
1089*4882a593Smuzhiyun if (ret)
1090*4882a593Smuzhiyun goto err_ret;
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_long, REG_RFCON6, 0x90);
1093*4882a593Smuzhiyun if (ret)
1094*4882a593Smuzhiyun goto err_ret;
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_long, REG_RFCON7, 0x80);
1097*4882a593Smuzhiyun if (ret)
1098*4882a593Smuzhiyun goto err_ret;
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_long, REG_RFCON8, 0x10);
1101*4882a593Smuzhiyun if (ret)
1102*4882a593Smuzhiyun goto err_ret;
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_long, REG_SLPCON1, 0x21);
1105*4882a593Smuzhiyun if (ret)
1106*4882a593Smuzhiyun goto err_ret;
1107*4882a593Smuzhiyun
1108*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_BBREG2, 0x80);
1109*4882a593Smuzhiyun if (ret)
1110*4882a593Smuzhiyun goto err_ret;
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_CCAEDTH, 0x60);
1113*4882a593Smuzhiyun if (ret)
1114*4882a593Smuzhiyun goto err_ret;
1115*4882a593Smuzhiyun
1116*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_BBREG6, 0x40);
1117*4882a593Smuzhiyun if (ret)
1118*4882a593Smuzhiyun goto err_ret;
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x04);
1121*4882a593Smuzhiyun if (ret)
1122*4882a593Smuzhiyun goto err_ret;
1123*4882a593Smuzhiyun
1124*4882a593Smuzhiyun ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x0);
1125*4882a593Smuzhiyun if (ret)
1126*4882a593Smuzhiyun goto err_ret;
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun udelay(192);
1129*4882a593Smuzhiyun
1130*4882a593Smuzhiyun /* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
1131*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x03, 0x00);
1132*4882a593Smuzhiyun if (ret)
1133*4882a593Smuzhiyun goto err_ret;
1134*4882a593Smuzhiyun
1135*4882a593Smuzhiyun if (spi_get_device_id(devrec->spi)->driver_data == MRF24J40MC) {
1136*4882a593Smuzhiyun /* Enable external amplifier.
1137*4882a593Smuzhiyun * From MRF24J40MC datasheet section 1.3: Operation.
1138*4882a593Smuzhiyun */
1139*4882a593Smuzhiyun regmap_update_bits(devrec->regmap_long, REG_TESTMODE, 0x07,
1140*4882a593Smuzhiyun 0x07);
1141*4882a593Smuzhiyun
1142*4882a593Smuzhiyun /* Set GPIO3 as output. */
1143*4882a593Smuzhiyun regmap_update_bits(devrec->regmap_short, REG_TRISGPIO, 0x08,
1144*4882a593Smuzhiyun 0x08);
1145*4882a593Smuzhiyun
1146*4882a593Smuzhiyun /* Set GPIO3 HIGH to enable U5 voltage regulator */
1147*4882a593Smuzhiyun regmap_update_bits(devrec->regmap_short, REG_GPIO, 0x08, 0x08);
1148*4882a593Smuzhiyun
1149*4882a593Smuzhiyun /* Reduce TX pwr to meet FCC requirements.
1150*4882a593Smuzhiyun * From MRF24J40MC datasheet section 3.1.1
1151*4882a593Smuzhiyun */
1152*4882a593Smuzhiyun regmap_write(devrec->regmap_long, REG_RFCON3, 0x28);
1153*4882a593Smuzhiyun }
1154*4882a593Smuzhiyun
1155*4882a593Smuzhiyun irq_type = irq_get_trigger_type(devrec->spi->irq);
1156*4882a593Smuzhiyun if (irq_type == IRQ_TYPE_EDGE_RISING ||
1157*4882a593Smuzhiyun irq_type == IRQ_TYPE_EDGE_FALLING)
1158*4882a593Smuzhiyun dev_warn(&devrec->spi->dev,
1159*4882a593Smuzhiyun "Using edge triggered irq's are not recommended, because it can cause races and result in a non-functional driver!\n");
1160*4882a593Smuzhiyun switch (irq_type) {
1161*4882a593Smuzhiyun case IRQ_TYPE_EDGE_RISING:
1162*4882a593Smuzhiyun case IRQ_TYPE_LEVEL_HIGH:
1163*4882a593Smuzhiyun /* set interrupt polarity to rising */
1164*4882a593Smuzhiyun ret = regmap_update_bits(devrec->regmap_long, REG_SLPCON0,
1165*4882a593Smuzhiyun BIT_INTEDGE, BIT_INTEDGE);
1166*4882a593Smuzhiyun if (ret)
1167*4882a593Smuzhiyun goto err_ret;
1168*4882a593Smuzhiyun break;
1169*4882a593Smuzhiyun default:
1170*4882a593Smuzhiyun /* default is falling edge */
1171*4882a593Smuzhiyun break;
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun
1174*4882a593Smuzhiyun return 0;
1175*4882a593Smuzhiyun
1176*4882a593Smuzhiyun err_ret:
1177*4882a593Smuzhiyun return ret;
1178*4882a593Smuzhiyun }
1179*4882a593Smuzhiyun
1180*4882a593Smuzhiyun static void
mrf24j40_setup_tx_spi_messages(struct mrf24j40 * devrec)1181*4882a593Smuzhiyun mrf24j40_setup_tx_spi_messages(struct mrf24j40 *devrec)
1182*4882a593Smuzhiyun {
1183*4882a593Smuzhiyun spi_message_init(&devrec->tx_msg);
1184*4882a593Smuzhiyun devrec->tx_msg.context = devrec;
1185*4882a593Smuzhiyun devrec->tx_msg.complete = write_tx_buf_complete;
1186*4882a593Smuzhiyun devrec->tx_hdr_trx.len = 2;
1187*4882a593Smuzhiyun devrec->tx_hdr_trx.tx_buf = devrec->tx_hdr_buf;
1188*4882a593Smuzhiyun spi_message_add_tail(&devrec->tx_hdr_trx, &devrec->tx_msg);
1189*4882a593Smuzhiyun devrec->tx_len_trx.len = 2;
1190*4882a593Smuzhiyun devrec->tx_len_trx.tx_buf = devrec->tx_len_buf;
1191*4882a593Smuzhiyun spi_message_add_tail(&devrec->tx_len_trx, &devrec->tx_msg);
1192*4882a593Smuzhiyun spi_message_add_tail(&devrec->tx_buf_trx, &devrec->tx_msg);
1193*4882a593Smuzhiyun
1194*4882a593Smuzhiyun spi_message_init(&devrec->tx_post_msg);
1195*4882a593Smuzhiyun devrec->tx_post_msg.context = devrec;
1196*4882a593Smuzhiyun devrec->tx_post_trx.len = 2;
1197*4882a593Smuzhiyun devrec->tx_post_trx.tx_buf = devrec->tx_post_buf;
1198*4882a593Smuzhiyun spi_message_add_tail(&devrec->tx_post_trx, &devrec->tx_post_msg);
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun static void
mrf24j40_setup_rx_spi_messages(struct mrf24j40 * devrec)1202*4882a593Smuzhiyun mrf24j40_setup_rx_spi_messages(struct mrf24j40 *devrec)
1203*4882a593Smuzhiyun {
1204*4882a593Smuzhiyun spi_message_init(&devrec->rx_msg);
1205*4882a593Smuzhiyun devrec->rx_msg.context = devrec;
1206*4882a593Smuzhiyun devrec->rx_trx.len = 2;
1207*4882a593Smuzhiyun devrec->rx_trx.tx_buf = devrec->rx_buf;
1208*4882a593Smuzhiyun devrec->rx_trx.rx_buf = devrec->rx_buf;
1209*4882a593Smuzhiyun spi_message_add_tail(&devrec->rx_trx, &devrec->rx_msg);
1210*4882a593Smuzhiyun
1211*4882a593Smuzhiyun spi_message_init(&devrec->rx_buf_msg);
1212*4882a593Smuzhiyun devrec->rx_buf_msg.context = devrec;
1213*4882a593Smuzhiyun devrec->rx_buf_msg.complete = mrf24j40_handle_rx_read_buf_complete;
1214*4882a593Smuzhiyun devrec->rx_addr_trx.len = 2;
1215*4882a593Smuzhiyun devrec->rx_addr_trx.tx_buf = devrec->rx_addr_buf;
1216*4882a593Smuzhiyun spi_message_add_tail(&devrec->rx_addr_trx, &devrec->rx_buf_msg);
1217*4882a593Smuzhiyun devrec->rx_fifo_buf_trx.rx_buf = devrec->rx_fifo_buf;
1218*4882a593Smuzhiyun spi_message_add_tail(&devrec->rx_fifo_buf_trx, &devrec->rx_buf_msg);
1219*4882a593Smuzhiyun devrec->rx_lqi_trx.len = 2;
1220*4882a593Smuzhiyun devrec->rx_lqi_trx.rx_buf = devrec->rx_lqi_buf;
1221*4882a593Smuzhiyun spi_message_add_tail(&devrec->rx_lqi_trx, &devrec->rx_buf_msg);
1222*4882a593Smuzhiyun }
1223*4882a593Smuzhiyun
1224*4882a593Smuzhiyun static void
mrf24j40_setup_irq_spi_messages(struct mrf24j40 * devrec)1225*4882a593Smuzhiyun mrf24j40_setup_irq_spi_messages(struct mrf24j40 *devrec)
1226*4882a593Smuzhiyun {
1227*4882a593Smuzhiyun spi_message_init(&devrec->irq_msg);
1228*4882a593Smuzhiyun devrec->irq_msg.context = devrec;
1229*4882a593Smuzhiyun devrec->irq_msg.complete = mrf24j40_intstat_complete;
1230*4882a593Smuzhiyun devrec->irq_trx.len = 2;
1231*4882a593Smuzhiyun devrec->irq_trx.tx_buf = devrec->irq_buf;
1232*4882a593Smuzhiyun devrec->irq_trx.rx_buf = devrec->irq_buf;
1233*4882a593Smuzhiyun spi_message_add_tail(&devrec->irq_trx, &devrec->irq_msg);
1234*4882a593Smuzhiyun }
1235*4882a593Smuzhiyun
mrf24j40_phy_setup(struct mrf24j40 * devrec)1236*4882a593Smuzhiyun static void mrf24j40_phy_setup(struct mrf24j40 *devrec)
1237*4882a593Smuzhiyun {
1238*4882a593Smuzhiyun ieee802154_random_extended_addr(&devrec->hw->phy->perm_extended_addr);
1239*4882a593Smuzhiyun devrec->hw->phy->current_channel = 11;
1240*4882a593Smuzhiyun
1241*4882a593Smuzhiyun /* mrf24j40 supports max_minbe 0 - 3 */
1242*4882a593Smuzhiyun devrec->hw->phy->supported.max_minbe = 3;
1243*4882a593Smuzhiyun /* datasheet doesn't say anything about max_be, but we have min_be
1244*4882a593Smuzhiyun * So we assume the max_be default.
1245*4882a593Smuzhiyun */
1246*4882a593Smuzhiyun devrec->hw->phy->supported.min_maxbe = 5;
1247*4882a593Smuzhiyun devrec->hw->phy->supported.max_maxbe = 5;
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun devrec->hw->phy->cca.mode = NL802154_CCA_CARRIER;
1250*4882a593Smuzhiyun devrec->hw->phy->supported.cca_modes = BIT(NL802154_CCA_ENERGY) |
1251*4882a593Smuzhiyun BIT(NL802154_CCA_CARRIER) |
1252*4882a593Smuzhiyun BIT(NL802154_CCA_ENERGY_CARRIER);
1253*4882a593Smuzhiyun devrec->hw->phy->supported.cca_opts = BIT(NL802154_CCA_OPT_ENERGY_CARRIER_AND);
1254*4882a593Smuzhiyun
1255*4882a593Smuzhiyun devrec->hw->phy->cca_ed_level = -6900;
1256*4882a593Smuzhiyun devrec->hw->phy->supported.cca_ed_levels = mrf24j40_ed_levels;
1257*4882a593Smuzhiyun devrec->hw->phy->supported.cca_ed_levels_size = ARRAY_SIZE(mrf24j40_ed_levels);
1258*4882a593Smuzhiyun
1259*4882a593Smuzhiyun switch (spi_get_device_id(devrec->spi)->driver_data) {
1260*4882a593Smuzhiyun case MRF24J40:
1261*4882a593Smuzhiyun case MRF24J40MA:
1262*4882a593Smuzhiyun devrec->hw->phy->supported.tx_powers = mrf24j40ma_powers;
1263*4882a593Smuzhiyun devrec->hw->phy->supported.tx_powers_size = ARRAY_SIZE(mrf24j40ma_powers);
1264*4882a593Smuzhiyun devrec->hw->phy->flags |= WPAN_PHY_FLAG_TXPOWER;
1265*4882a593Smuzhiyun break;
1266*4882a593Smuzhiyun default:
1267*4882a593Smuzhiyun break;
1268*4882a593Smuzhiyun }
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun
mrf24j40_probe(struct spi_device * spi)1271*4882a593Smuzhiyun static int mrf24j40_probe(struct spi_device *spi)
1272*4882a593Smuzhiyun {
1273*4882a593Smuzhiyun int ret = -ENOMEM, irq_type;
1274*4882a593Smuzhiyun struct ieee802154_hw *hw;
1275*4882a593Smuzhiyun struct mrf24j40 *devrec;
1276*4882a593Smuzhiyun
1277*4882a593Smuzhiyun dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq);
1278*4882a593Smuzhiyun
1279*4882a593Smuzhiyun /* Register with the 802154 subsystem */
1280*4882a593Smuzhiyun
1281*4882a593Smuzhiyun hw = ieee802154_alloc_hw(sizeof(*devrec), &mrf24j40_ops);
1282*4882a593Smuzhiyun if (!hw)
1283*4882a593Smuzhiyun goto err_ret;
1284*4882a593Smuzhiyun
1285*4882a593Smuzhiyun devrec = hw->priv;
1286*4882a593Smuzhiyun devrec->spi = spi;
1287*4882a593Smuzhiyun spi_set_drvdata(spi, devrec);
1288*4882a593Smuzhiyun devrec->hw = hw;
1289*4882a593Smuzhiyun devrec->hw->parent = &spi->dev;
1290*4882a593Smuzhiyun devrec->hw->phy->supported.channels[0] = CHANNEL_MASK;
1291*4882a593Smuzhiyun devrec->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT |
1292*4882a593Smuzhiyun IEEE802154_HW_CSMA_PARAMS |
1293*4882a593Smuzhiyun IEEE802154_HW_PROMISCUOUS;
1294*4882a593Smuzhiyun
1295*4882a593Smuzhiyun devrec->hw->phy->flags = WPAN_PHY_FLAG_CCA_MODE |
1296*4882a593Smuzhiyun WPAN_PHY_FLAG_CCA_ED_LEVEL;
1297*4882a593Smuzhiyun
1298*4882a593Smuzhiyun mrf24j40_setup_tx_spi_messages(devrec);
1299*4882a593Smuzhiyun mrf24j40_setup_rx_spi_messages(devrec);
1300*4882a593Smuzhiyun mrf24j40_setup_irq_spi_messages(devrec);
1301*4882a593Smuzhiyun
1302*4882a593Smuzhiyun devrec->regmap_short = devm_regmap_init_spi(spi,
1303*4882a593Smuzhiyun &mrf24j40_short_regmap);
1304*4882a593Smuzhiyun if (IS_ERR(devrec->regmap_short)) {
1305*4882a593Smuzhiyun ret = PTR_ERR(devrec->regmap_short);
1306*4882a593Smuzhiyun dev_err(&spi->dev, "Failed to allocate short register map: %d\n",
1307*4882a593Smuzhiyun ret);
1308*4882a593Smuzhiyun goto err_register_device;
1309*4882a593Smuzhiyun }
1310*4882a593Smuzhiyun
1311*4882a593Smuzhiyun devrec->regmap_long = devm_regmap_init(&spi->dev,
1312*4882a593Smuzhiyun &mrf24j40_long_regmap_bus,
1313*4882a593Smuzhiyun spi, &mrf24j40_long_regmap);
1314*4882a593Smuzhiyun if (IS_ERR(devrec->regmap_long)) {
1315*4882a593Smuzhiyun ret = PTR_ERR(devrec->regmap_long);
1316*4882a593Smuzhiyun dev_err(&spi->dev, "Failed to allocate long register map: %d\n",
1317*4882a593Smuzhiyun ret);
1318*4882a593Smuzhiyun goto err_register_device;
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun if (spi->max_speed_hz > MAX_SPI_SPEED_HZ) {
1322*4882a593Smuzhiyun dev_warn(&spi->dev, "spi clock above possible maximum: %d",
1323*4882a593Smuzhiyun MAX_SPI_SPEED_HZ);
1324*4882a593Smuzhiyun ret = -EINVAL;
1325*4882a593Smuzhiyun goto err_register_device;
1326*4882a593Smuzhiyun }
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun ret = mrf24j40_hw_init(devrec);
1329*4882a593Smuzhiyun if (ret)
1330*4882a593Smuzhiyun goto err_register_device;
1331*4882a593Smuzhiyun
1332*4882a593Smuzhiyun mrf24j40_phy_setup(devrec);
1333*4882a593Smuzhiyun
1334*4882a593Smuzhiyun /* request IRQF_TRIGGER_LOW as fallback default */
1335*4882a593Smuzhiyun irq_type = irq_get_trigger_type(spi->irq);
1336*4882a593Smuzhiyun if (!irq_type)
1337*4882a593Smuzhiyun irq_type = IRQF_TRIGGER_LOW;
1338*4882a593Smuzhiyun
1339*4882a593Smuzhiyun ret = devm_request_irq(&spi->dev, spi->irq, mrf24j40_isr,
1340*4882a593Smuzhiyun irq_type, dev_name(&spi->dev), devrec);
1341*4882a593Smuzhiyun if (ret) {
1342*4882a593Smuzhiyun dev_err(printdev(devrec), "Unable to get IRQ");
1343*4882a593Smuzhiyun goto err_register_device;
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun
1346*4882a593Smuzhiyun dev_dbg(printdev(devrec), "registered mrf24j40\n");
1347*4882a593Smuzhiyun ret = ieee802154_register_hw(devrec->hw);
1348*4882a593Smuzhiyun if (ret)
1349*4882a593Smuzhiyun goto err_register_device;
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun return 0;
1352*4882a593Smuzhiyun
1353*4882a593Smuzhiyun err_register_device:
1354*4882a593Smuzhiyun ieee802154_free_hw(devrec->hw);
1355*4882a593Smuzhiyun err_ret:
1356*4882a593Smuzhiyun return ret;
1357*4882a593Smuzhiyun }
1358*4882a593Smuzhiyun
mrf24j40_remove(struct spi_device * spi)1359*4882a593Smuzhiyun static int mrf24j40_remove(struct spi_device *spi)
1360*4882a593Smuzhiyun {
1361*4882a593Smuzhiyun struct mrf24j40 *devrec = spi_get_drvdata(spi);
1362*4882a593Smuzhiyun
1363*4882a593Smuzhiyun dev_dbg(printdev(devrec), "remove\n");
1364*4882a593Smuzhiyun
1365*4882a593Smuzhiyun ieee802154_unregister_hw(devrec->hw);
1366*4882a593Smuzhiyun ieee802154_free_hw(devrec->hw);
1367*4882a593Smuzhiyun /* TODO: Will ieee802154_free_device() wait until ->xmit() is
1368*4882a593Smuzhiyun * complete? */
1369*4882a593Smuzhiyun
1370*4882a593Smuzhiyun return 0;
1371*4882a593Smuzhiyun }
1372*4882a593Smuzhiyun
1373*4882a593Smuzhiyun static const struct of_device_id mrf24j40_of_match[] = {
1374*4882a593Smuzhiyun { .compatible = "microchip,mrf24j40", .data = (void *)MRF24J40 },
1375*4882a593Smuzhiyun { .compatible = "microchip,mrf24j40ma", .data = (void *)MRF24J40MA },
1376*4882a593Smuzhiyun { .compatible = "microchip,mrf24j40mc", .data = (void *)MRF24J40MC },
1377*4882a593Smuzhiyun { },
1378*4882a593Smuzhiyun };
1379*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, mrf24j40_of_match);
1380*4882a593Smuzhiyun
1381*4882a593Smuzhiyun static const struct spi_device_id mrf24j40_ids[] = {
1382*4882a593Smuzhiyun { "mrf24j40", MRF24J40 },
1383*4882a593Smuzhiyun { "mrf24j40ma", MRF24J40MA },
1384*4882a593Smuzhiyun { "mrf24j40mc", MRF24J40MC },
1385*4882a593Smuzhiyun { },
1386*4882a593Smuzhiyun };
1387*4882a593Smuzhiyun MODULE_DEVICE_TABLE(spi, mrf24j40_ids);
1388*4882a593Smuzhiyun
1389*4882a593Smuzhiyun static struct spi_driver mrf24j40_driver = {
1390*4882a593Smuzhiyun .driver = {
1391*4882a593Smuzhiyun .of_match_table = of_match_ptr(mrf24j40_of_match),
1392*4882a593Smuzhiyun .name = "mrf24j40",
1393*4882a593Smuzhiyun },
1394*4882a593Smuzhiyun .id_table = mrf24j40_ids,
1395*4882a593Smuzhiyun .probe = mrf24j40_probe,
1396*4882a593Smuzhiyun .remove = mrf24j40_remove,
1397*4882a593Smuzhiyun };
1398*4882a593Smuzhiyun
1399*4882a593Smuzhiyun module_spi_driver(mrf24j40_driver);
1400*4882a593Smuzhiyun
1401*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1402*4882a593Smuzhiyun MODULE_AUTHOR("Alan Ott");
1403*4882a593Smuzhiyun MODULE_DESCRIPTION("MRF24J40 SPI 802.15.4 Controller Driver");
1404