at86rf230: add regmap support
authorAlexander Aring <alex.aring@gmail.com>
Wed, 2 Jul 2014 22:20:44 +0000 (00:20 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 8 Jul 2014 04:29:24 +0000 (21:29 -0700)
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>
drivers/net/ieee802154/Kconfig
drivers/net/ieee802154/at86rf230.c

index 8b7ae51..391a916 100644 (file)
@@ -34,6 +34,7 @@ config IEEE802154_AT86RF230
        depends on IEEE802154_DRIVERS && MAC802154
        tristate "AT86RF230/231/233/212 transceiver driver"
        depends on SPI
+       select REGMAP_SPI
        ---help---
          Say Y here to enable the at86rf230/231/233/212 SPI 802.15.4 wireless
          controller.
index dca6bae..e369703 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/at86rf230.h>
+#include <linux/regmap.h>
 #include <linux/skbuff.h>
 #include <linux/of_gpio.h>
 
@@ -50,6 +51,7 @@ struct at86rf230_local {
        struct completion tx_complete;
 
        struct ieee802154_dev *dev;
+       struct regmap *regmap;
 
        spinlock_t lock;
        bool irq_busy;
@@ -256,6 +258,157 @@ static bool is_rf212(struct at86rf230_local *local)
 #define STATE_BUSY_RX_AACK_NOCLK 0x1E
 #define STATE_TRANSITION_IN_PROGRESS 0x1F
 
+#define AT86RF2XX_NUMREGS 0x3F
+
+static inline int
+__at86rf230_write(struct at86rf230_local *lp,
+                 unsigned int addr, unsigned int data)
+{
+       return regmap_write(lp->regmap, addr, data);
+}
+
+static inline int
+__at86rf230_read(struct at86rf230_local *lp,
+                unsigned int addr, unsigned int *data)
+{
+       return regmap_read(lp->regmap, addr, data);
+}
+
+static inline int
+at86rf230_read_subreg(struct at86rf230_local *lp,
+                     unsigned int addr, unsigned int mask,
+                     unsigned int shift, unsigned int *data)
+{
+       int rc;
+
+       rc = __at86rf230_read(lp, addr, data);
+       if (rc > 0)
+               *data = (*data & mask) >> shift;
+
+       return rc;
+}
+
+static inline int
+at86rf230_write_subreg(struct at86rf230_local *lp,
+                      unsigned int addr, unsigned int mask,
+                      unsigned int shift, unsigned int data)
+{
+       return regmap_update_bits(lp->regmap, addr, mask, data << shift);
+}
+
+static bool
+at86rf230_reg_writeable(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case RG_TRX_STATE:
+       case RG_TRX_CTRL_0:
+       case RG_TRX_CTRL_1:
+       case RG_PHY_TX_PWR:
+       case RG_PHY_ED_LEVEL:
+       case RG_PHY_CC_CCA:
+       case RG_CCA_THRES:
+       case RG_RX_CTRL:
+       case RG_SFD_VALUE:
+       case RG_TRX_CTRL_2:
+       case RG_ANT_DIV:
+       case RG_IRQ_MASK:
+       case RG_VREG_CTRL:
+       case RG_BATMON:
+       case RG_XOSC_CTRL:
+       case RG_RX_SYN:
+       case RG_XAH_CTRL_1:
+       case RG_FTN_CTRL:
+       case RG_PLL_CF:
+       case RG_PLL_DCU:
+       case RG_SHORT_ADDR_0:
+       case RG_SHORT_ADDR_1:
+       case RG_PAN_ID_0:
+       case RG_PAN_ID_1:
+       case RG_IEEE_ADDR_0:
+       case RG_IEEE_ADDR_1:
+       case RG_IEEE_ADDR_2:
+       case RG_IEEE_ADDR_3:
+       case RG_IEEE_ADDR_4:
+       case RG_IEEE_ADDR_5:
+       case RG_IEEE_ADDR_6:
+       case RG_IEEE_ADDR_7:
+       case RG_XAH_CTRL_0:
+       case RG_CSMA_SEED_0:
+       case RG_CSMA_SEED_1:
+       case RG_CSMA_BE:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool
+at86rf230_reg_readable(struct device *dev, unsigned int reg)
+{
+       bool rc;
+
+       /* all writeable are also readable */
+       rc = at86rf230_reg_writeable(dev, reg);
+       if (rc)
+               return rc;
+
+       /* readonly regs */
+       switch (reg) {
+       case RG_TRX_STATUS:
+       case RG_PHY_RSSI:
+       case RG_IRQ_STATUS:
+       case RG_PART_NUM:
+       case RG_VERSION_NUM:
+       case RG_MAN_ID_1:
+       case RG_MAN_ID_0:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool
+at86rf230_reg_volatile(struct device *dev, unsigned int reg)
+{
+       /* can be changed during runtime */
+       switch (reg) {
+       case RG_TRX_STATUS:
+       case RG_TRX_STATE:
+       case RG_PHY_RSSI:
+       case RG_PHY_ED_LEVEL:
+       case RG_IRQ_STATUS:
+       case RG_VREG_CTRL:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool
+at86rf230_reg_precious(struct device *dev, unsigned int reg)
+{
+       /* don't clear irq line on read */
+       switch (reg) {
+       case RG_IRQ_STATUS:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static struct regmap_config at86rf230_regmap_spi_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .write_flag_mask = CMD_REG | CMD_WRITE,
+       .read_flag_mask = CMD_REG,
+       .cache_type = REGCACHE_RBTREE,
+       .max_register = AT86RF2XX_NUMREGS,
+       .writeable_reg = at86rf230_reg_writeable,
+       .readable_reg = at86rf230_reg_readable,
+       .volatile_reg = at86rf230_reg_volatile,
+       .precious_reg = at86rf230_reg_precious,
+};
+
 static int
 __at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
                u8 *version)
@@ -307,105 +460,6 @@ __at86rf230_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
        return status;
 }
 
-static int
-__at86rf230_write(struct at86rf230_local *lp, u8 addr, u8 data)
-{
-       u8 *buf = lp->buf;
-       int status;
-       struct spi_message msg;
-       struct spi_transfer xfer = {
-               .len    = 2,
-               .tx_buf = buf,
-       };
-
-       buf[0] = (addr & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
-       buf[1] = data;
-       dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-       dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfer, &msg);
-
-       status = spi_sync(lp->spi, &msg);
-       dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-       if (msg.status)
-               status = msg.status;
-
-       dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-       dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-       dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
-       return status;
-}
-
-static int
-__at86rf230_read_subreg(struct at86rf230_local *lp,
-                       u8 addr, u8 mask, int shift, u8 *data)
-{
-       u8 *buf = lp->buf;
-       int status;
-       struct spi_message msg;
-       struct spi_transfer xfer = {
-               .len    = 2,
-               .tx_buf = buf,
-               .rx_buf = buf,
-       };
-
-       buf[0] = (addr & CMD_REG_MASK) | CMD_REG;
-       buf[1] = 0xff;
-       dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-       spi_message_init(&msg);
-       spi_message_add_tail(&xfer, &msg);
-
-       status = spi_sync(lp->spi, &msg);
-       dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-       if (msg.status)
-               status = msg.status;
-
-       dev_vdbg(&lp->spi->dev, "status = %d\n", status);
-       dev_vdbg(&lp->spi->dev, "buf[0] = %02x\n", buf[0]);
-       dev_vdbg(&lp->spi->dev, "buf[1] = %02x\n", buf[1]);
-
-       if (status == 0)
-               *data = (buf[1] & mask) >> shift;
-
-       return status;
-}
-
-static int
-at86rf230_read_subreg(struct at86rf230_local *lp,
-                     u8 addr, u8 mask, int shift, u8 *data)
-{
-       int status;
-
-       mutex_lock(&lp->bmux);
-       status = __at86rf230_read_subreg(lp, addr, mask, shift, data);
-       mutex_unlock(&lp->bmux);
-
-       return status;
-}
-
-static int
-at86rf230_write_subreg(struct at86rf230_local *lp,
-                      u8 addr, u8 mask, int shift, u8 data)
-{
-       int status;
-       u8 val;
-
-       mutex_lock(&lp->bmux);
-       status = __at86rf230_read_subreg(lp, addr, 0xff, 0, &val);
-       if (status)
-               goto out;
-
-       val &= ~mask;
-       val |= (data << shift) & mask;
-
-       status = __at86rf230_write(lp, addr, val);
-out:
-       mutex_unlock(&lp->bmux);
-
-       return status;
-}
-
 static int
 at86rf230_write_fbuf(struct at86rf230_local *lp, u8 *data, u8 len)
 {
@@ -520,7 +574,7 @@ at86rf230_state(struct ieee802154_dev *dev, int state)
 {
        struct at86rf230_local *lp = dev->priv;
        int rc;
-       u8 val;
+       unsigned int val;
        u8 desired_status;
 
        might_sleep();
@@ -890,12 +944,11 @@ static void at86rf230_irqwork(struct work_struct *work)
 {
        struct at86rf230_local *lp =
                container_of(work, struct at86rf230_local, irqwork);
-       u8 status = 0, val;
+       unsigned int status;
        int rc;
        unsigned long flags;
 
-       rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val);
-       status |= val;
+       rc = at86rf230_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &status);
 
        status &= ~IRQ_PLL_LOCK; /* ignore */
        status &= ~IRQ_RX_START; /* ignore */
@@ -954,7 +1007,7 @@ static irqreturn_t at86rf230_isr_level(int irq, void *data)
 static int at86rf230_hw_init(struct at86rf230_local *lp)
 {
        int rc, irq_pol, irq_type;
-       u8 dvdd;
+       unsigned int dvdd;
        u8 csma_seed[2];
 
        rc = at86rf230_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
@@ -1033,7 +1086,8 @@ static int at86rf230_probe(struct spi_device *spi)
        struct ieee802154_dev *dev;
        struct at86rf230_local *lp;
        u16 man_id = 0;
-       u8 part = 0, version = 0, status;
+       u8 part = 0, version = 0;
+       unsigned int status;
        irq_handler_t irq_handler;
        work_func_t irq_worker;
        int rc, irq_type;
@@ -1128,6 +1182,14 @@ static int at86rf230_probe(struct spi_device *spi)
        if (rc < 0)
                goto free_dev;
 
+       lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config);
+       if (IS_ERR(lp->regmap)) {
+               rc = PTR_ERR(lp->regmap);
+               dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+                       rc);
+               goto free_dev;
+       }
+
        irq_type = irq_get_trigger_type(spi->irq);
        if (!irq_type)
                irq_type = IRQF_TRIGGER_RISING;