mrf24j40: use regmap for register access

This patch uses the regmap functions for transceiver register settings
where it's possible. This means everything except the hotpaths like
receive/transmit handling.

Reviewed-by: Stefan Schmidt <stefan@osg.samsung.com>
Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
Alexander Aring 2015-09-21 11:24:31 +02:00 committed by Marcel Holtmann
parent b015679200
commit 42c7148e06
1 changed files with 52 additions and 99 deletions

View File

@ -543,35 +543,6 @@ static int read_long_reg(struct mrf24j40 *devrec, u16 reg, u8 *value)
return ret;
}
static int write_long_reg(struct mrf24j40 *devrec, u16 reg, u8 val)
{
int ret;
u16 cmd;
struct spi_message msg;
struct spi_transfer xfer = {
.len = 3,
.tx_buf = devrec->buf,
.rx_buf = devrec->buf,
};
spi_message_init(&msg);
spi_message_add_tail(&xfer, &msg);
cmd = MRF24J40_WRITELONG(reg);
mutex_lock(&devrec->buffer_mutex);
devrec->buf[0] = cmd >> 8 & 0xff;
devrec->buf[1] = cmd & 0xff;
devrec->buf[2] = val;
ret = spi_sync(devrec->spi, &msg);
if (ret)
dev_err(printdev(devrec),
"SPI write Failed for long register 0x%hx\n", reg);
mutex_unlock(&devrec->buffer_mutex);
return ret;
}
/* This function relies on an undocumented write method. Once a write command
and address is set, as many bytes of data as desired can be clocked into
the device. The datasheet only shows setting one byte at a time. */
@ -755,33 +726,23 @@ static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
static int mrf24j40_start(struct ieee802154_hw *hw)
{
struct mrf24j40 *devrec = hw->priv;
u8 val;
int ret;
dev_dbg(printdev(devrec), "start\n");
ret = read_short_reg(devrec, REG_INTCON, &val);
if (ret)
return ret;
val &= ~(0x1|0x8); /* Clear TXNIE and RXIE. Enable interrupts */
write_short_reg(devrec, REG_INTCON, val);
return 0;
/* Clear TXNIE and RXIE. Enable interrupts */
return regmap_update_bits(devrec->regmap_short, REG_INTCON,
0x01 | 0x08, 0x00);
}
static void mrf24j40_stop(struct ieee802154_hw *hw)
{
struct mrf24j40 *devrec = hw->priv;
u8 val;
int ret;
dev_dbg(printdev(devrec), "stop\n");
ret = read_short_reg(devrec, REG_INTCON, &val);
if (ret)
return;
val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */
write_short_reg(devrec, REG_INTCON, val);
/* Set TXNIE and RXIE. Disable Interrupts */
regmap_update_bits(devrec->regmap_short, REG_INTCON, 0x01 | 0x08,
0x01 | 0x08);
}
static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
@ -798,20 +759,20 @@ static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
/* Set Channel TODO */
val = (channel-11) << 4 | 0x03;
write_long_reg(devrec, REG_RFCON0, val);
/* RF Reset */
ret = read_short_reg(devrec, REG_RFCTL, &val);
ret = regmap_update_bits(devrec->regmap_long, REG_RFCON0, 0xf0, val);
if (ret)
return ret;
val |= 0x04;
write_short_reg(devrec, REG_RFCTL, val);
val &= ~0x04;
write_short_reg(devrec, REG_RFCTL, val);
udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
/* RF Reset */
ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, 0x04, 0x04);
if (ret)
return ret;
return 0;
ret = regmap_update_bits(devrec->regmap_short, REG_RFCTL, 0x04, 0x00);
if (!ret)
udelay(SET_CHANNEL_DELAY_US); /* per datasheet */
return ret;
}
static int mrf24j40_filter(struct ieee802154_hw *hw,
@ -829,8 +790,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff;
addrl = le16_to_cpu(filt->short_addr) & 0xff;
write_short_reg(devrec, REG_SADRH, addrh);
write_short_reg(devrec, REG_SADRL, addrl);
regmap_write(devrec->regmap_short, REG_SADRH, addrh);
regmap_write(devrec->regmap_short, REG_SADRL, addrl);
dev_dbg(printdev(devrec),
"Set short addr to %04hx\n", filt->short_addr);
}
@ -841,7 +802,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
memcpy(addr, &filt->ieee_addr, 8);
for (i = 0; i < 8; i++)
write_short_reg(devrec, REG_EADR0 + i, addr[i]);
regmap_write(devrec->regmap_short, REG_EADR0 + i,
addr[i]);
#ifdef DEBUG
pr_debug("Set long addr to: ");
@ -857,8 +819,8 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff;
panidl = le16_to_cpu(filt->pan_id) & 0xff;
write_short_reg(devrec, REG_PANIDH, panidh);
write_short_reg(devrec, REG_PANIDL, panidl);
regmap_write(devrec->regmap_short, REG_PANIDH, panidh);
regmap_write(devrec->regmap_short, REG_PANIDL, panidl);
dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
}
@ -868,14 +830,14 @@ static int mrf24j40_filter(struct ieee802154_hw *hw,
u8 val;
int ret;
ret = read_short_reg(devrec, REG_RXMCR, &val);
if (filt->pan_coord)
val = 0x8;
else
val = 0x0;
ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x8,
val);
if (ret)
return ret;
if (filt->pan_coord)
val |= 0x8;
else
val &= ~0x8;
write_short_reg(devrec, REG_RXMCR, val);
/* REG_SLOTTED is maintained as default (unslotted/CSMA-CA).
* REG_ORDER is maintained as default (no beacon/superframe).
@ -976,80 +938,73 @@ static irqreturn_t mrf24j40_isr(int irq, void *data)
static int mrf24j40_hw_init(struct mrf24j40 *devrec)
{
int ret;
u8 val;
/* Initialize the device.
From datasheet section 3.2: Initialization. */
ret = write_short_reg(devrec, REG_SOFTRST, 0x07);
ret = regmap_write(devrec->regmap_short, REG_SOFTRST, 0x07);
if (ret)
goto err_ret;
ret = write_short_reg(devrec, REG_PACON2, 0x98);
ret = regmap_write(devrec->regmap_short, REG_PACON2, 0x98);
if (ret)
goto err_ret;
ret = write_short_reg(devrec, REG_TXSTBL, 0x95);
ret = regmap_write(devrec->regmap_short, REG_TXSTBL, 0x95);
if (ret)
goto err_ret;
ret = write_long_reg(devrec, REG_RFCON0, 0x03);
ret = regmap_write(devrec->regmap_long, REG_RFCON0, 0x03);
if (ret)
goto err_ret;
ret = write_long_reg(devrec, REG_RFCON1, 0x01);
ret = regmap_write(devrec->regmap_long, REG_RFCON1, 0x01);
if (ret)
goto err_ret;
ret = write_long_reg(devrec, REG_RFCON2, 0x80);
ret = regmap_write(devrec->regmap_long, REG_RFCON2, 0x80);
if (ret)
goto err_ret;
ret = write_long_reg(devrec, REG_RFCON6, 0x90);
ret = regmap_write(devrec->regmap_long, REG_RFCON6, 0x90);
if (ret)
goto err_ret;
ret = write_long_reg(devrec, REG_RFCON7, 0x80);
ret = regmap_write(devrec->regmap_long, REG_RFCON7, 0x80);
if (ret)
goto err_ret;
ret = write_long_reg(devrec, REG_RFCON8, 0x10);
ret = regmap_write(devrec->regmap_long, REG_RFCON8, 0x10);
if (ret)
goto err_ret;
ret = write_long_reg(devrec, REG_SLPCON1, 0x21);
ret = regmap_write(devrec->regmap_long, REG_SLPCON1, 0x21);
if (ret)
goto err_ret;
ret = write_short_reg(devrec, REG_BBREG2, 0x80);
ret = regmap_write(devrec->regmap_short, REG_BBREG2, 0x80);
if (ret)
goto err_ret;
ret = write_short_reg(devrec, REG_CCAEDTH, 0x60);
ret = regmap_write(devrec->regmap_short, REG_CCAEDTH, 0x60);
if (ret)
goto err_ret;
ret = write_short_reg(devrec, REG_BBREG6, 0x40);
ret = regmap_write(devrec->regmap_short, REG_BBREG6, 0x40);
if (ret)
goto err_ret;
ret = write_short_reg(devrec, REG_RFCTL, 0x04);
ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x04);
if (ret)
goto err_ret;
ret = write_short_reg(devrec, REG_RFCTL, 0x0);
ret = regmap_write(devrec->regmap_short, REG_RFCTL, 0x0);
if (ret)
goto err_ret;
udelay(192);
/* Set RX Mode. RXMCR<1:0>: 0x0 normal, 0x1 promisc, 0x2 error */
ret = read_short_reg(devrec, REG_RXMCR, &val);
if (ret)
goto err_ret;
val &= ~0x3; /* Clear RX mode (normal) */
ret = write_short_reg(devrec, REG_RXMCR, val);
ret = regmap_update_bits(devrec->regmap_short, REG_RXMCR, 0x03, 0x00);
if (ret)
goto err_ret;
@ -1057,22 +1012,20 @@ static int mrf24j40_hw_init(struct mrf24j40 *devrec)
/* Enable external amplifier.
* From MRF24J40MC datasheet section 1.3: Operation.
*/
read_long_reg(devrec, REG_TESTMODE, &val);
val |= 0x7; /* Configure GPIO 0-2 to control amplifier */
write_long_reg(devrec, REG_TESTMODE, val);
regmap_update_bits(devrec->regmap_long, REG_TESTMODE, 0x07,
0x07);
read_short_reg(devrec, REG_TRISGPIO, &val);
val |= 0x8; /* Set GPIO3 as output. */
write_short_reg(devrec, REG_TRISGPIO, val);
/* Set GPIO3 as output. */
regmap_update_bits(devrec->regmap_short, REG_TRISGPIO, 0x08,
0x08);
read_short_reg(devrec, REG_GPIO, &val);
val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */
write_short_reg(devrec, REG_GPIO, val);
/* Set GPIO3 HIGH to enable U5 voltage regulator */
regmap_update_bits(devrec->regmap_short, REG_GPIO, 0x08, 0x08);
/* Reduce TX pwr to meet FCC requirements.
* From MRF24J40MC datasheet section 3.1.1
*/
write_long_reg(devrec, REG_RFCON3, 0x28);
regmap_write(devrec->regmap_long, REG_RFCON3, 0x28);
}
return 0;