mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 15:12:13 +02:00
i2c: nomadik: use bitops helpers
Constant register bit fields are declared using hardcoded hex values; replace them by calls to BIT() and GENMASK(). Replace custom GEN_MASK() macro by the generic FIELD_PREP(). Replace manual bit manipulations by the generic FIELD_GET() macro. Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com> Reviewed-by: Andi Shyti <andi.shyti@kernel.org> Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
This commit is contained in:
parent
d4f4a361c4
commit
a9f5cd8923
|
|
@ -9,6 +9,7 @@
|
|||
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
|
||||
* Author: Sachin Verma <sachin.verma@st.com>
|
||||
*/
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/amba/bus.h>
|
||||
|
|
@ -42,54 +43,59 @@
|
|||
#define I2C_ICR (0x038)
|
||||
|
||||
/* Control registers */
|
||||
#define I2C_CR_PE (0x1 << 0) /* Peripheral Enable */
|
||||
#define I2C_CR_OM (0x3 << 1) /* Operating mode */
|
||||
#define I2C_CR_SAM (0x1 << 3) /* Slave addressing mode */
|
||||
#define I2C_CR_SM (0x3 << 4) /* Speed mode */
|
||||
#define I2C_CR_SGCM (0x1 << 6) /* Slave general call mode */
|
||||
#define I2C_CR_FTX (0x1 << 7) /* Flush Transmit */
|
||||
#define I2C_CR_FRX (0x1 << 8) /* Flush Receive */
|
||||
#define I2C_CR_DMA_TX_EN (0x1 << 9) /* DMA Tx enable */
|
||||
#define I2C_CR_DMA_RX_EN (0x1 << 10) /* DMA Rx Enable */
|
||||
#define I2C_CR_DMA_SLE (0x1 << 11) /* DMA sync. logic enable */
|
||||
#define I2C_CR_LM (0x1 << 12) /* Loopback mode */
|
||||
#define I2C_CR_FON (0x3 << 13) /* Filtering on */
|
||||
#define I2C_CR_FS (0x3 << 15) /* Force stop enable */
|
||||
#define I2C_CR_PE BIT(0) /* Peripheral Enable */
|
||||
#define I2C_CR_OM GENMASK(2, 1) /* Operating mode */
|
||||
#define I2C_CR_SAM BIT(3) /* Slave addressing mode */
|
||||
#define I2C_CR_SM GENMASK(5, 4) /* Speed mode */
|
||||
#define I2C_CR_SGCM BIT(6) /* Slave general call mode */
|
||||
#define I2C_CR_FTX BIT(7) /* Flush Transmit */
|
||||
#define I2C_CR_FRX BIT(8) /* Flush Receive */
|
||||
#define I2C_CR_DMA_TX_EN BIT(9) /* DMA Tx enable */
|
||||
#define I2C_CR_DMA_RX_EN BIT(10) /* DMA Rx Enable */
|
||||
#define I2C_CR_DMA_SLE BIT(11) /* DMA sync. logic enable */
|
||||
#define I2C_CR_LM BIT(12) /* Loopback mode */
|
||||
#define I2C_CR_FON GENMASK(14, 13) /* Filtering on */
|
||||
#define I2C_CR_FS GENMASK(16, 15) /* Force stop enable */
|
||||
|
||||
/* Slave control register (SCR) */
|
||||
#define I2C_SCR_SLSU GENMASK(31, 16) /* Slave data setup time */
|
||||
|
||||
/* Master controller (MCR) register */
|
||||
#define I2C_MCR_OP (0x1 << 0) /* Operation */
|
||||
#define I2C_MCR_A7 (0x7f << 1) /* 7-bit address */
|
||||
#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */
|
||||
#define I2C_MCR_SB (0x1 << 11) /* Extended address */
|
||||
#define I2C_MCR_AM (0x3 << 12) /* Address type */
|
||||
#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */
|
||||
#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */
|
||||
#define I2C_MCR_OP BIT(0) /* Operation */
|
||||
#define I2C_MCR_A7 GENMASK(7, 1) /* 7-bit address */
|
||||
#define I2C_MCR_EA10 GENMASK(10, 8) /* 10-bit Extended address */
|
||||
#define I2C_MCR_SB BIT(11) /* Extended address */
|
||||
#define I2C_MCR_AM GENMASK(13, 12) /* Address type */
|
||||
#define I2C_MCR_STOP BIT(14) /* Stop condition */
|
||||
#define I2C_MCR_LENGTH GENMASK(25, 15) /* Transaction length */
|
||||
|
||||
/* Status register (SR) */
|
||||
#define I2C_SR_OP (0x3 << 0) /* Operation */
|
||||
#define I2C_SR_STATUS (0x3 << 2) /* controller status */
|
||||
#define I2C_SR_CAUSE (0x7 << 4) /* Abort cause */
|
||||
#define I2C_SR_TYPE (0x3 << 7) /* Receive type */
|
||||
#define I2C_SR_LENGTH (0x7ff << 9) /* Transfer length */
|
||||
#define I2C_SR_OP GENMASK(1, 0) /* Operation */
|
||||
#define I2C_SR_STATUS GENMASK(3, 2) /* controller status */
|
||||
#define I2C_SR_CAUSE GENMASK(6, 4) /* Abort cause */
|
||||
#define I2C_SR_TYPE GENMASK(8, 7) /* Receive type */
|
||||
#define I2C_SR_LENGTH GENMASK(19, 9) /* Transfer length */
|
||||
|
||||
/* Baud-rate counter register (BRCR) */
|
||||
#define I2C_BRCR_BRCNT1 GENMASK(31, 16) /* Baud-rate counter 1 */
|
||||
#define I2C_BRCR_BRCNT2 GENMASK(15, 0) /* Baud-rate counter 2 */
|
||||
|
||||
/* Interrupt mask set/clear (IMSCR) bits */
|
||||
#define I2C_IT_TXFE (0x1 << 0)
|
||||
#define I2C_IT_TXFNE (0x1 << 1)
|
||||
#define I2C_IT_TXFF (0x1 << 2)
|
||||
#define I2C_IT_TXFOVR (0x1 << 3)
|
||||
#define I2C_IT_RXFE (0x1 << 4)
|
||||
#define I2C_IT_RXFNF (0x1 << 5)
|
||||
#define I2C_IT_RXFF (0x1 << 6)
|
||||
#define I2C_IT_RFSR (0x1 << 16)
|
||||
#define I2C_IT_RFSE (0x1 << 17)
|
||||
#define I2C_IT_WTSR (0x1 << 18)
|
||||
#define I2C_IT_MTD (0x1 << 19)
|
||||
#define I2C_IT_STD (0x1 << 20)
|
||||
#define I2C_IT_MAL (0x1 << 24)
|
||||
#define I2C_IT_BERR (0x1 << 25)
|
||||
#define I2C_IT_MTDWS (0x1 << 28)
|
||||
|
||||
#define GEN_MASK(val, mask, sb) (((val) << (sb)) & (mask))
|
||||
#define I2C_IT_TXFE BIT(0)
|
||||
#define I2C_IT_TXFNE BIT(1)
|
||||
#define I2C_IT_TXFF BIT(2)
|
||||
#define I2C_IT_TXFOVR BIT(3)
|
||||
#define I2C_IT_RXFE BIT(4)
|
||||
#define I2C_IT_RXFNF BIT(5)
|
||||
#define I2C_IT_RXFF BIT(6)
|
||||
#define I2C_IT_RFSR BIT(16)
|
||||
#define I2C_IT_RFSE BIT(17)
|
||||
#define I2C_IT_WTSR BIT(18)
|
||||
#define I2C_IT_MTD BIT(19)
|
||||
#define I2C_IT_STD BIT(20)
|
||||
#define I2C_IT_MAL BIT(24)
|
||||
#define I2C_IT_BERR BIT(25)
|
||||
#define I2C_IT_MTDWS BIT(28)
|
||||
|
||||
/* some bits in ICR are reserved */
|
||||
#define I2C_CLEAR_ALL_INTS 0x131f007f
|
||||
|
|
@ -128,6 +134,12 @@ enum i2c_operation {
|
|||
I2C_READ = 0x01
|
||||
};
|
||||
|
||||
enum i2c_operating_mode {
|
||||
I2C_OM_SLAVE,
|
||||
I2C_OM_MASTER,
|
||||
I2C_OM_MASTER_OR_SLAVE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct i2c_nmk_client - client specific data
|
||||
* @slave_adr: 7-bit slave address
|
||||
|
|
@ -284,7 +296,10 @@ static int init_hw(struct nmk_i2c_dev *priv)
|
|||
}
|
||||
|
||||
/* enable peripheral, master mode operation */
|
||||
#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE)
|
||||
#define DEFAULT_I2C_REG_CR (FIELD_PREP(I2C_CR_OM, I2C_OM_MASTER) | I2C_CR_PE)
|
||||
|
||||
/* grab top three bits from extended I2C addresses */
|
||||
#define ADR_3MSB_BITS GENMASK(9, 7)
|
||||
|
||||
/**
|
||||
* load_i2c_mcr_reg() - load the MCR register
|
||||
|
|
@ -296,41 +311,42 @@ static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *priv, u16 flags)
|
|||
u32 mcr = 0;
|
||||
unsigned short slave_adr_3msb_bits;
|
||||
|
||||
mcr |= GEN_MASK(priv->cli.slave_adr, I2C_MCR_A7, 1);
|
||||
mcr |= FIELD_PREP(I2C_MCR_A7, priv->cli.slave_adr);
|
||||
|
||||
if (unlikely(flags & I2C_M_TEN)) {
|
||||
/* 10-bit address transaction */
|
||||
mcr |= GEN_MASK(2, I2C_MCR_AM, 12);
|
||||
mcr |= FIELD_PREP(I2C_MCR_AM, 2);
|
||||
/*
|
||||
* Get the top 3 bits.
|
||||
* EA10 represents extended address in MCR. This includes
|
||||
* the extension (MSB bits) of the 7 bit address loaded
|
||||
* in A7
|
||||
*/
|
||||
slave_adr_3msb_bits = (priv->cli.slave_adr >> 7) & 0x7;
|
||||
slave_adr_3msb_bits = FIELD_GET(ADR_3MSB_BITS,
|
||||
priv->cli.slave_adr);
|
||||
|
||||
mcr |= GEN_MASK(slave_adr_3msb_bits, I2C_MCR_EA10, 8);
|
||||
mcr |= FIELD_PREP(I2C_MCR_EA10, slave_adr_3msb_bits);
|
||||
} else {
|
||||
/* 7-bit address transaction */
|
||||
mcr |= GEN_MASK(1, I2C_MCR_AM, 12);
|
||||
mcr |= FIELD_PREP(I2C_MCR_AM, 1);
|
||||
}
|
||||
|
||||
/* start byte procedure not applied */
|
||||
mcr |= GEN_MASK(0, I2C_MCR_SB, 11);
|
||||
mcr |= FIELD_PREP(I2C_MCR_SB, 0);
|
||||
|
||||
/* check the operation, master read/write? */
|
||||
if (priv->cli.operation == I2C_WRITE)
|
||||
mcr |= GEN_MASK(I2C_WRITE, I2C_MCR_OP, 0);
|
||||
mcr |= FIELD_PREP(I2C_MCR_OP, I2C_WRITE);
|
||||
else
|
||||
mcr |= GEN_MASK(I2C_READ, I2C_MCR_OP, 0);
|
||||
mcr |= FIELD_PREP(I2C_MCR_OP, I2C_READ);
|
||||
|
||||
/* stop or repeated start? */
|
||||
if (priv->stop)
|
||||
mcr |= GEN_MASK(1, I2C_MCR_STOP, 14);
|
||||
mcr |= FIELD_PREP(I2C_MCR_STOP, 1);
|
||||
else
|
||||
mcr &= ~(GEN_MASK(1, I2C_MCR_STOP, 14));
|
||||
mcr &= ~FIELD_PREP(I2C_MCR_STOP, 1);
|
||||
|
||||
mcr |= GEN_MASK(priv->cli.count, I2C_MCR_LENGTH, 15);
|
||||
mcr |= FIELD_PREP(I2C_MCR_LENGTH, priv->cli.count);
|
||||
|
||||
return mcr;
|
||||
}
|
||||
|
|
@ -383,7 +399,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv)
|
|||
slsu += 1;
|
||||
|
||||
dev_dbg(&priv->adev->dev, "calculated SLSU = %04x\n", slsu);
|
||||
writel(slsu << 16, priv->virtbase + I2C_SCR);
|
||||
writel(FIELD_PREP(I2C_SCR_SLSU, slsu), priv->virtbase + I2C_SCR);
|
||||
|
||||
/*
|
||||
* The spec says, in case of std. mode the divider is
|
||||
|
|
@ -399,8 +415,8 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv)
|
|||
* plus operation. Currently we do not supprt high speed mode
|
||||
* so set brcr1 to 0.
|
||||
*/
|
||||
brcr1 = 0 << 16;
|
||||
brcr2 = (i2c_clk / (priv->clk_freq * div)) & 0xffff;
|
||||
brcr1 = FIELD_PREP(I2C_BRCR_BRCNT1, 0);
|
||||
brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2, i2c_clk / (priv->clk_freq * div));
|
||||
|
||||
/* set the baud rate counter register */
|
||||
writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR);
|
||||
|
|
@ -414,12 +430,13 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv)
|
|||
if (priv->sm > I2C_FREQ_MODE_FAST) {
|
||||
dev_err(&priv->adev->dev,
|
||||
"do not support this mode defaulting to std. mode\n");
|
||||
brcr2 = i2c_clk / (I2C_MAX_STANDARD_MODE_FREQ * 2) & 0xffff;
|
||||
brcr2 = FIELD_PREP(I2C_BRCR_BRCNT2,
|
||||
i2c_clk / (I2C_MAX_STANDARD_MODE_FREQ * 2));
|
||||
writel((brcr1 | brcr2), priv->virtbase + I2C_BRCR);
|
||||
writel(I2C_FREQ_MODE_STANDARD << 4,
|
||||
priv->virtbase + I2C_CR);
|
||||
writel(FIELD_PREP(I2C_CR_SM, I2C_FREQ_MODE_STANDARD),
|
||||
priv->virtbase + I2C_CR);
|
||||
}
|
||||
writel(priv->sm << 4, priv->virtbase + I2C_CR);
|
||||
writel(FIELD_PREP(I2C_CR_SM, priv->sm), priv->virtbase + I2C_CR);
|
||||
|
||||
/* set the Tx and Rx FIFO threshold */
|
||||
writel(priv->tft, priv->virtbase + I2C_TFTR);
|
||||
|
|
@ -583,13 +600,8 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *priv, u16 flags)
|
|||
u32 cause;
|
||||
|
||||
i2c_sr = readl(priv->virtbase + I2C_SR);
|
||||
/*
|
||||
* Check if the controller I2C operation status
|
||||
* is set to ABORT(11b).
|
||||
*/
|
||||
if (((i2c_sr >> 2) & 0x3) == 0x3) {
|
||||
/* get the abort cause */
|
||||
cause = (i2c_sr >> 4) & 0x7;
|
||||
if (FIELD_GET(I2C_SR_STATUS, i2c_sr) == I2C_ABORT) {
|
||||
cause = FIELD_GET(I2C_SR_CAUSE, i2c_sr);
|
||||
dev_err(&priv->adev->dev, "%s\n",
|
||||
cause >= ARRAY_SIZE(abort_causes) ?
|
||||
"unknown reason" :
|
||||
|
|
@ -730,7 +742,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
|
|||
misr = readl(priv->virtbase + I2C_MISR);
|
||||
|
||||
src = __ffs(misr);
|
||||
switch ((1 << src)) {
|
||||
switch (BIT(src)) {
|
||||
|
||||
/* Transmit FIFO nearly empty interrupt */
|
||||
case I2C_IT_TXFNE:
|
||||
|
|
@ -824,15 +836,18 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
|
|||
* during the transaction.
|
||||
*/
|
||||
case I2C_IT_BERR:
|
||||
{
|
||||
u32 sr;
|
||||
|
||||
sr = readl(priv->virtbase + I2C_SR);
|
||||
priv->result = -EIO;
|
||||
/* get the status */
|
||||
if (((readl(priv->virtbase + I2C_SR) >> 2) & 0x3) == I2C_ABORT)
|
||||
if (FIELD_GET(I2C_SR_STATUS, sr) == I2C_ABORT)
|
||||
init_hw(priv);
|
||||
|
||||
i2c_set_bit(priv->virtbase + I2C_ICR, I2C_IT_BERR);
|
||||
complete(&priv->xfer_complete);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
* Tx FIFO overrun interrupt.
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user