This patch adds regmap support for the at86rf2xx driver and drop the
lowlevel spi access functions and use the regmap ones.

Signed-off-by: Alexander Aring <alex.ar...@gmail.com>
---
 drivers/net/ieee802154/Kconfig     |   1 +
 drivers/net/ieee802154/at86rf2xx.c | 272 +++++++++++++++++++++++--------------
 2 files changed, 168 insertions(+), 105 deletions(-)

diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
index cb75717..ae27de2 100644
--- a/drivers/net/ieee802154/Kconfig
+++ b/drivers/net/ieee802154/Kconfig
@@ -34,6 +34,7 @@ config IEEE802154_AT86RF2XX
        depends on IEEE802154_DRIVERS && MAC802154
        tristate "AT86RF231/233/212 transceiver driver"
        depends on SPI
+       select REGMAP_SPI
        ---help---
          Say Y here to enable the at86rf231/233/212 SPI 802.15.4 wireless
          controller.
diff --git a/drivers/net/ieee802154/at86rf2xx.c 
b/drivers/net/ieee802154/at86rf2xx.c
index d86c067..d022adf 100644
--- a/drivers/net/ieee802154/at86rf2xx.c
+++ b/drivers/net/ieee802154/at86rf2xx.c
@@ -31,6 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/at86rf2xx.h>
+#include <linux/regmap.h>
 #include <linux/skbuff.h>
 #include <linux/of_gpio.h>
 
@@ -50,6 +51,7 @@ struct at86rf2xx_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 at86rf2xx_local *local)
 #define STATE_BUSY_RX_AACK_NOCLK 0x1E
 #define STATE_TRANSITION_IN_PROGRESS 0x1F
 
+#define AT86RF2XX_NUMREGS 0x3F
+
+static inline int
+__at86rf2xx_write(struct at86rf2xx_local *lp,
+                 unsigned int addr, unsigned int data)
+{
+       return regmap_write(lp->regmap, addr, data);
+}
+
+static inline int
+__at86rf2xx_read(struct at86rf2xx_local *lp,
+                unsigned int addr, unsigned int *data)
+{
+       return regmap_read(lp->regmap, addr, data);
+}
+
+static inline int
+at86rf2xx_read_subreg(struct at86rf2xx_local *lp,
+                     unsigned int addr, unsigned int mask,
+                     unsigned int shift, unsigned int *data)
+{
+       int rc;
+
+       rc = __at86rf2xx_read(lp, addr, data);
+       if (rc > 0)
+               *data = (*data & mask) >> shift;
+
+       return rc;
+}
+
+static inline int
+at86rf2xx_write_subreg(struct at86rf2xx_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
+at86rf2xx_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
+at86rf2xx_reg_readable(struct device *dev, unsigned int reg)
+{
+       bool rc;
+
+       /* all writeable are also readable */
+       rc = at86rf2xx_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
+at86rf2xx_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
+at86rf2xx_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 at86rf2xx_regmap_spi_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .write_flag_mask = CMD_REG | CMD_WRITE,
+       .read_flag_mask = CMD_REG,
+       .cache_type = REGCACHE_NONE,
+       .max_register = AT86RF2XX_NUMREGS,
+       .writeable_reg = at86rf2xx_reg_writeable,
+       .readable_reg = at86rf2xx_reg_readable,
+       .volatile_reg = at86rf2xx_reg_volatile,
+       .precious_reg = at86rf2xx_reg_precious,
+};
+
 static int
 __at86rf2xx_detect_device(struct spi_device *spi, u16 *man_id, u8 *part,
                u8 *version)
@@ -308,105 +461,6 @@ __at86rf2xx_detect_device(struct spi_device *spi, u16 
*man_id, u8 *part,
 }
 
 static int
-__at86rf2xx_write(struct at86rf2xx_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
-__at86rf2xx_read_subreg(struct at86rf2xx_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
-at86rf2xx_read_subreg(struct at86rf2xx_local *lp,
-                     u8 addr, u8 mask, int shift, u8 *data)
-{
-       int status;
-
-       mutex_lock(&lp->bmux);
-       status = __at86rf2xx_read_subreg(lp, addr, mask, shift, data);
-       mutex_unlock(&lp->bmux);
-
-       return status;
-}
-
-static int
-at86rf2xx_write_subreg(struct at86rf2xx_local *lp,
-                      u8 addr, u8 mask, int shift, u8 data)
-{
-       int status;
-       u8 val;
-
-       mutex_lock(&lp->bmux);
-       status = __at86rf2xx_read_subreg(lp, addr, 0xff, 0, &val);
-       if (status)
-               goto out;
-
-       val &= ~mask;
-       val |= (data << shift) & mask;
-
-       status = __at86rf2xx_write(lp, addr, val);
-out:
-       mutex_unlock(&lp->bmux);
-
-       return status;
-}
-
-static int
 at86rf2xx_write_fbuf(struct at86rf2xx_local *lp, u8 *data, u8 len)
 {
        u8 *buf = lp->buf;
@@ -520,7 +574,7 @@ at86rf2xx_state(struct ieee802154_dev *dev, int state)
 {
        struct at86rf2xx_local *lp = dev->priv;
        int rc;
-       u8 val;
+       unsigned int val;
        u8 desired_status;
 
        might_sleep();
@@ -890,12 +944,11 @@ static void at86rf2xx_irqwork(struct work_struct *work)
 {
        struct at86rf2xx_local *lp =
                container_of(work, struct at86rf2xx_local, irqwork);
-       u8 status = 0, val;
+       unsigned int status;
        int rc;
        unsigned long flags;
 
-       rc = at86rf2xx_read_subreg(lp, RG_IRQ_STATUS, 0xff, 0, &val);
-       status |= val;
+       rc = at86rf2xx_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 at86rf2xx_isr_level(int irq, void *data)
 static int at86rf2xx_hw_init(struct at86rf2xx_local *lp)
 {
        int rc, irq_pol, irq_type;
-       u8 dvdd;
+       unsigned int dvdd;
        u8 csma_seed[2];
 
        rc = at86rf2xx_write_subreg(lp, SR_TRX_CMD, STATE_FORCE_TRX_OFF);
@@ -1033,7 +1086,8 @@ static int at86rf2xx_probe(struct spi_device *spi)
        struct ieee802154_dev *dev;
        struct at86rf2xx_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 at86rf2xx_probe(struct spi_device *spi)
        if (rc < 0)
                goto free_dev;
 
+       lp->regmap = devm_regmap_init_spi(spi, &at86rf2xx_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 & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
                irq_worker = at86rf2xx_irqwork;
-- 
2.0.0


------------------------------------------------------------------------------
HPCC Systems Open Source Big Data Platform from LexisNexis Risk Solutions
Find What Matters Most in Your Big Data with HPCC Systems
Open Source. Fast. Scalable. Simple. Ideal for Dirty Data.
Leverages Graph Analysis for Fast Processing & Easy Data Exploration
http://p.sf.net/sfu/hpccsystems
_______________________________________________
Linux-zigbee-devel mailing list
Linux-zigbee-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-zigbee-devel

Reply via email to