diff options
author | Alexander Aring <alex.aring@gmail.com> | 2014-07-02 18:20:44 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-07-08 00:29:24 -0400 |
commit | f76014f770ff2d4e26c82e4e3a5b0928dee1969b (patch) | |
tree | be98d1e0274701e2f6c9194c1f86217c6b31556f /drivers/net/ieee802154 | |
parent | 640985ec2ffd2a81f34dc5004f0951d2c6cb3d5e (diff) |
at86rf230: add regmap support
This patch adds regmap support for the at86rf230 driver and drop the
lowlevel spi access functions and use the regmap access functions.
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ieee802154')
-rw-r--r-- | drivers/net/ieee802154/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/ieee802154/at86rf230.c | 272 |
2 files changed, 168 insertions, 105 deletions
diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig index 8b7ae51f30f5..391a916622a9 100644 --- a/drivers/net/ieee802154/Kconfig +++ b/drivers/net/ieee802154/Kconfig | |||
@@ -34,6 +34,7 @@ config IEEE802154_AT86RF230 | |||
34 | depends on IEEE802154_DRIVERS && MAC802154 | 34 | depends on IEEE802154_DRIVERS && MAC802154 |
35 | tristate "AT86RF230/231/233/212 transceiver driver" | 35 | tristate "AT86RF230/231/233/212 transceiver driver" |
36 | depends on SPI | 36 | depends on SPI |
37 | select REGMAP_SPI | ||
37 | ---help--- | 38 | ---help--- |
38 | Say Y here to enable the at86rf230/231/233/212 SPI 802.15.4 wireless | 39 | Say Y here to enable the at86rf230/231/233/212 SPI 802.15.4 wireless |
39 | controller. | 40 | controller. |
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index dca6bae1402c..e3697038bd6d 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/spi/spi.h> | 32 | #include <linux/spi/spi.h> |
33 | #include <linux/spi/at86rf230.h> | 33 | #include <linux/spi/at86rf230.h> |
34 | #include <linux/regmap.h> | ||
34 | #include <linux/skbuff.h> | 35 | #include <linux/skbuff.h> |
35 | #include <linux/of_gpio.h> | 36 | #include <linux/of_gpio.h> |
36 | 37 | ||
@@ -50,6 +51,7 @@ struct at86rf230_local { | |||
50 | struct completion tx_complete; | 51 | struct completion tx_complete; |
51 | 52 | ||
52 | struct ieee802154_dev *dev; | 53 | struct ieee802154_dev *dev; |
54 | struct regmap *regmap; | ||
53 | 55 | ||
54 | spinlock_t lock; | 56 | spinlock_t lock; |
55 | bool irq_busy; | 57 | bool irq_busy; |
@@ -256,6 +258,157 @@ static bool is_rf212(struct at86rf230_local *local) | |||
256 | #define STATE_BUSY_RX_AACK_NOCLK 0x1E | 258 | #define STATE_BUSY_RX_AACK_NOCLK 0x1E |
257 | #define STATE_TRANSITION_IN_PROGRESS 0x1F | 259 | #define STATE_TRANSITION_IN_PROGRESS 0x1F |
258 | 260 | ||
261 | #define AT86RF2XX_NUMREGS 0x3F | ||
262 | |||
263 | static inline int | ||
264 | __at86rf230_write(struct at86rf230_local *lp, | ||
265 | unsigned int addr, unsigned int data) | ||
266 | { | ||
267 | return regmap_write(lp->regmap, addr, data); | ||
268 | } | ||
269 | |||
270 | static inline int | ||
271 | __at86rf230_read(struct at86rf230_local *lp, | ||
272 | unsigned int addr, unsigned int *data) | ||
273 | { | ||
274 | return regmap_read(lp->regmap, addr, data); | ||
275 | } | ||
276 | |||
277 | static inline int | ||
278 | at86rf230_read_subreg(struct at86rf230_local *lp, | ||
279 | unsigned int addr, unsigned int mask, | ||
280 | unsigned int shift, unsigned int *data) | ||
281 | { | ||
282 | int rc; | ||
283 | |||
284 | rc = __at86rf230_read(lp, addr, data); | ||
285 | if (rc > 0) | ||
286 | *data = (*data & mask) >> shift; | ||
287 | |||
288 | return rc; | ||
289 | } | ||
290 | |||
291 | static inline int | ||
292 | at86rf230_write_subreg(struct at86rf230_local *lp, | ||
293 | unsigned int addr, unsigned int mask, | ||
294 | unsigned int shift, unsigned int data) | ||
295 | { | ||
296 | return regmap_update_bits(lp->regmap, addr, mask, data << shift); | ||
297 | } | ||
298 | |||
299 | static bool | ||
300 | at86rf230_reg_writeable(struct device *dev, unsigned int reg) | ||
301 | { | ||
302 | switch (reg) { | ||
303 | case RG_TRX_STATE: | ||
304 | case RG_TRX_CTRL_0: | ||
305 | case RG_TRX_CTRL_1: | ||
306 | case RG_PHY_TX_PWR: | ||
307 | case RG_PHY_ED_LEVEL: | ||
308 | case RG_PHY_CC_CCA: | ||
309 | case RG_CCA_THRES: | ||
310 | case RG_RX_CTRL: | ||
311 | case RG_SFD_VALUE: | ||
312 | case RG_TRX_CTRL_2: | ||
313 | case RG_ANT_DIV: | ||
314 | case RG_IRQ_MASK: | ||
315 | case RG_VREG_CTRL: | ||
316 | case RG_BATMON: | ||
317 | case RG_XOSC_CTRL: | ||
318 | case RG_RX_SYN: | ||
319 | case RG_XAH_CTRL_1: | ||
320 | case RG_FTN_CTRL: | ||
321 | case RG_PLL_CF: | ||
322 | case RG_PLL_DCU: | ||
323 | case RG_SHORT_ADDR_0: | ||
324 | case RG_SHORT_ADDR_1: | ||
325 | case RG_PAN_ID_0: | ||
326 | case RG_PAN_ID_1: | ||
327 | case RG_IEEE_ADDR_0: | ||
328 | case RG_IEEE_ADDR_1: | ||
329 | case RG_IEEE_ADDR_2: | ||
330 | case RG_IEEE_ADDR_3: | ||
331 | case RG_IEEE_ADDR_4: | ||
332 | case RG_IEEE_ADDR_5: | ||
333 | case RG_IEEE_ADDR_6: | ||
334 | case RG_IEEE_ADDR_7: | ||
335 | case RG_XAH_CTRL_0: | ||
336 | case RG_CSMA_SEED_0: | ||
337 | case RG_CSMA_SEED_1: | ||
338 | case RG_CSMA_BE: | ||
339 | return true; | ||
340 | default: | ||
341 | return false; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | static bool | ||
346 | at86rf230_reg_readable(struct device *dev, unsigned int reg) | ||
347 | { | ||
348 | bool rc; | ||
349 | |||
350 | /* all writeable are also readable */ | ||
351 | rc = at86rf230_reg_writeable(dev, reg); | ||
352 | if (rc) | ||
353 | return rc; | ||
354 | |||
355 | /* readonly regs */ | ||
356 | switch (reg) { | ||
357 | case RG_TRX_STATUS: | ||
358 | case RG_PHY_RSSI: | ||
359 | case RG_IRQ_STATUS: | ||
360 | case RG_PART_NUM: | ||
361 | case RG_VERSION_NUM: | ||
362 | case RG_MAN_ID_1: | ||
363 | case RG_MAN_ID_0: | ||
364 | return true; | ||
365 | default: | ||
366 | return false; | ||
367 | } | ||
368 | } | ||
369 | |||
370 | static bool | ||
371 | at86rf230_reg_volatile(struct device *dev, unsigned int reg) | ||
372 | { | ||
373 | /* can be changed during runtime */ | ||
374 | switch (reg) { | ||
375 | case RG_TRX_STATUS: | ||
376 | case RG_TRX_STATE: | ||
377 | case RG_PHY_RSSI: | ||
378 | case RG_PHY_ED_LEVEL: | ||
379 | case RG_IRQ_STATUS: | ||
380 | case RG_VREG_CTRL: | ||
381 | return true; | ||
382 | default: | ||
383 | return false; | ||
384 | } | ||
385 | } | ||
386 | |||
387 | static bool | ||
388 | at86rf230_reg_precious(struct device *dev, unsigned int reg) | ||
389 | { | ||
390 | /* don't clear irq line on read */ | ||
391 | switch (reg) { | ||
392 | case RG_IRQ_STATUS: | ||
393 | return true; | ||
394 | default: | ||
395 | return false; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | static struct regmap_config at86rf230_regmap_spi_config = { | ||
400 | .reg_bits = 8, | ||
401 | .val_bits = 8, | ||
402 | .write_flag_mask = CMD_REG | CMD_WRITE, | ||
403 | .read_flag_mask = CMD_REG, | ||
404 | .cache_type = REGCACHE_RBTREE, | ||
405 | .max_register = AT86RF2XX_NUMREGS, | ||
406 | .writeable_reg = at86rf230_reg_writeable, | ||
407 | .readable_reg = at86rf230_reg_readable, | ||
408 | .volatile_reg = at86rf230_reg_volatile, | ||
409 | .precious_reg = at86rf230_reg_precious, | ||
410 | }; | ||
411 | |||
259 | static int | 412 | static int |
260 | __at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part, | 413 | __at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part, |
261 | u8 *version) | 414 | u8 *version) |
@@ -308,105 +461,6 @@ __at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part, | |||
308 | } | 461 | } |
309 | 462 | ||
310 | static int | 463 | static int |
311 | __at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data) | ||
312 | { | ||
313 | u8 *buf = lp->buf; | ||
314 | int status; | ||
315 | struct spi_message msg; | ||
316 | struct spi_transfer xfer = { | ||
317 | .len = 2, | ||
318 | .tx_buf = buf, | ||
319 | }; | ||
320 | |||
321 | buf[0] = (addr & CMD_REG_MASK) | CMD_REG | CMD_WRITE; | ||
322 | buf[1] = data; | ||
323 | dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]); | ||
324 | dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]); | ||
325 | spi_message_init(&msg); | ||
326 | spi_message_add_tail(&xfer, &msg); | ||
327 | |||
328 | status = spi_sync(lp->spi, &msg); | ||
329 | dev_vdbg(&lp->spi->dev, "status = %d\n", status); | ||
330 | if (msg.status) | ||
331 | status = msg.status; | ||
332 | |||
333 | dev_vdbg(&lp->spi->dev, "status = %d\n", status); | ||
334 | dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]); | ||
335 | dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]); | ||
336 | |||
337 | return status; | ||
338 | } | ||
339 | |||
340 | static int | ||
341 | __at86rf230_read_subreg(struct at86rf230_local *lp, | ||
342 | u8 addr, u8 mask, int shift, u8 *data) | ||
343 | { | ||
344 | u8 *buf = lp->buf; | ||
345 | int status; | ||
346 | struct spi_message msg; | ||
347 | struct spi_transfer xfer = { | ||
348 | .len = 2, | ||
349 | .tx_buf = buf, | ||
350 | .rx_buf = buf, | ||
351 | }; | ||
352 | |||
353 | buf[0] = (addr & CMD_REG_MASK) | CMD_REG; | ||
354 | buf[1] = 0xff; | ||
355 | dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]); | ||
356 | spi_message_init(&msg); | ||
357 | spi_message_add_tail(&xfer, &msg); | ||
358 | |||
359 | status = spi_sync(lp->spi, &msg); | ||
360 | dev_vdbg(&lp->spi->dev, "status = %d\n", status); | ||
361 | if (msg.status) | ||
362 | status = msg.status; | ||
363 | |||
364 | dev_vdbg(&lp->spi->dev, "status = %d\n", status); | ||
365 | dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]); | ||
366 | dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]); | ||
367 | |||
368 | if (status == 0) | ||
369 | *data = (buf[1] & mask) >> shift; | ||
370 | |||
371 | return status; | ||
372 | } | ||
373 | |||
374 | static int | ||
375 | at86rf230_read_subreg(struct at86rf230_local *lp, | ||
376 | u8 addr, u8 mask, int shift, u8 *data) | ||
377 | { | ||
378 | int status; | ||
379 | |||
380 | mutex_lock(&lp->bmux); | ||
381 | status = __at86rf230_read_subreg(lp, addr, mask, shift, data); | ||
382 | mutex_unlock(&lp->bmux); | ||
383 | |||
384 | return status; | ||
385 | } | ||
386 | |||
387 | static int | ||
388 | at86rf230_write_subreg(struct at86rf230_local *lp, | ||
389 | u8 addr, u8 mask, int shift, u8 data) | ||
390 | { | ||
391 | int status; | ||
392 | u8 val; | ||
393 | |||
394 | mutex_lock(&lp->bmux); | ||
395 | status = __at86rf230_read_subreg(lp, addr, 0xff, 0, &val); | ||
396 | if (status) | ||
397 | goto out; | ||
398 | |||
399 | val &= ~mask; | ||
400 | val |= (data << shift) & mask; | ||
401 | |||
402 | status = __at86rf230_write(lp, addr, val); | ||
403 | out: | ||
404 | mutex_unlock(&lp->bmux); | ||
405 | |||
406 | return status; | ||
407 | } | ||
408 | |||
409 | static int | ||
410 | at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len) | 464 | at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len) |
411 | { | 465 | { |
412 | u8 *buf = lp->buf; | 466 | u8 *buf = lp->buf; |
@@ -520,7 +574,7 @@ at86rf230_state(struct ieee802154_dev *dev, int state) | |||
520 | { | 574 | { |
521 | struct at86rf230_local *lp = dev->priv; | 575 | struct at86rf230_local *lp = dev->priv; |
522 | int rc; | 576 | int rc; |
523 | u8 val; | 577 | unsigned int val; |
524 | u8 desired_status; | 578 | u8 desired_status; |
525 | 579 | ||
526 | might_sleep(); | 580 | might_sleep(); |
@@ -890,12 +944,11 @@ static void at86rf230_irqwork(struct work_struct *work) | |||
890 | { | 944 | { |
891 | struct at86rf230_local *lp = | 945 | struct at86rf230_local *lp = |
892 | container_of(work, struct at86rf230_local, irqwork); | 946 | container_of(work, struct at86rf230_local, irqwork); |
893 | u8 status = 0, val; | 947 | unsigned int status; |
894 | int rc; | 948 | int rc; |
895 | unsigned long flags; | 949 | unsigned long flags; |
896 | 950 | ||
897 | rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val); | 951 | rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status); |
898 | status |= val; | ||
899 | 952 | ||
900 | status &= ~IRQ_PLL_LOCK; /* ignore */ | 953 | status &= ~IRQ_PLL_LOCK; /* ignore */ |
901 | status &= ~IRQ_RX_START; /* ignore */ | 954 | status &= ~IRQ_RX_START; /* ignore */ |
@@ -954,7 +1007,7 @@ static irqreturn_t at86rf230_isr_level(int irq, void *data) | |||
954 | static int at86rf230_hw_init(struct at86rf230_local *lp) | 1007 | static int at86rf230_hw_init(struct at86rf230_local *lp) |
955 | { | 1008 | { |
956 | int rc, irq_pol, irq_type; | 1009 | int rc, irq_pol, irq_type; |
957 | u8 dvdd; | 1010 | unsigned int dvdd; |
958 | u8 csma_seed[2]; | 1011 | u8 csma_seed[2]; |
959 | 1012 | ||
960 | rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF); | 1013 | rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF); |
@@ -1033,7 +1086,8 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1033 | struct ieee802154_dev *dev; | 1086 | struct ieee802154_dev *dev; |
1034 | struct at86rf230_local *lp; | 1087 | struct at86rf230_local *lp; |
1035 | u16 man_id = 0; | 1088 | u16 man_id = 0; |
1036 | u8 part = 0, version = 0, status; | 1089 | u8 part = 0, version = 0; |
1090 | unsigned int status; | ||
1037 | irq_handler_t irq_handler; | 1091 | irq_handler_t irq_handler; |
1038 | work_func_t irq_worker; | 1092 | work_func_t irq_worker; |
1039 | int rc, irq_type; | 1093 | int rc, irq_type; |
@@ -1128,6 +1182,14 @@ static int at86rf230_probe(struct spi_device *spi) | |||
1128 | if (rc < 0) | 1182 | if (rc < 0) |
1129 | goto free_dev; | 1183 | goto free_dev; |
1130 | 1184 | ||
1185 | lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config); | ||
1186 | if (IS_ERR(lp->regmap)) { | ||
1187 | rc = PTR_ERR(lp->regmap); | ||
1188 | dev_err(&spi->dev, "Failed to allocate register map: %d\n", | ||
1189 | rc); | ||
1190 | goto free_dev; | ||
1191 | } | ||
1192 | |||
1131 | irq_type = irq_get_trigger_type(spi->irq); | 1193 | irq_type = irq_get_trigger_type(spi->irq); |
1132 | if (!irq_type) | 1194 | if (!irq_type) |
1133 | irq_type = IRQF_TRIGGER_RISING; | 1195 | irq_type = IRQF_TRIGGER_RISING; |