Commit a9f5cd89 authored by Théo Lebrun's avatar Théo Lebrun Committed by Andi Shyti
Browse files

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarThéo Lebrun <theo.lebrun@bootlin.com>
Reviewed-by: default avatarAndi Shyti <andi.shyti@kernel.org>
Signed-off-by: default avatarAndi Shyti <andi.shyti@kernel.org>
parent d4f4a361
Loading
Loading
Loading
Loading
+88 −73
Original line number Diff line number Diff line
@@ -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,
		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,14 +836,17 @@ 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;

	/*