Skip to content

Commit 7d4c57a

Browse files
tlebAndi Shyti
authored andcommitted
i2c: nomadik: support Mobileye EyeQ5 I2C controller
Add compatible for the integration of the same DB8500 IP block into the Mobileye EyeQ5 platform. Two quirks are present: - The memory bus only supports 32-bit accesses. Avoid writeb() and readb() by introducing helper functions that fallback to writel() and readl(). - A register must be configured for the I2C speed mode; it is located in a shared register region called OLB. We access that memory region using a syscon & regmap that gets passed as a phandle (mobileye,olb). A two-bit enum per controller is written into the register; that requires us to know the global index of the I2C controller (cell arg to the mobileye,olb phandle). We add #include <linux/mfd/syscon.h> and <linux/regmap.h>. 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>
1 parent ec189b9 commit 7d4c57a

File tree

1 file changed

+86
-4
lines changed

1 file changed

+86
-4
lines changed

drivers/i2c/busses/i2c-nomadik.c

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
* I2C master mode controller driver, used in Nomadik 8815
77
* and Ux500 platforms.
88
*
9+
* The Mobileye EyeQ5 platform is also supported; it uses
10+
* the same Ux500/DB8500 IP block with two quirks:
11+
* - The memory bus only supports 32-bit accesses.
12+
* - A register must be configured for the I2C speed mode;
13+
* it is located in a shared register region called OLB.
14+
*
915
* Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
1016
* Author: Sachin Verma <sachin.verma@st.com>
1117
*/
@@ -22,6 +28,8 @@
2228
#include <linux/pm_runtime.h>
2329
#include <linux/of.h>
2430
#include <linux/pinctrl/consumer.h>
31+
#include <linux/mfd/syscon.h>
32+
#include <linux/regmap.h>
2533

2634
#define DRIVER_NAME "nmk-i2c"
2735

@@ -110,6 +118,15 @@ enum i2c_freq_mode {
110118
I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */
111119
};
112120

121+
/* Mobileye EyeQ5 offset into a shared register region (called OLB) */
122+
#define NMK_I2C_EYEQ5_OLB_IOCR2 0x0B8
123+
124+
enum i2c_eyeq5_speed {
125+
I2C_EYEQ5_SPEED_FAST,
126+
I2C_EYEQ5_SPEED_FAST_PLUS,
127+
I2C_EYEQ5_SPEED_HIGH_SPEED,
128+
};
129+
113130
/**
114131
* struct i2c_vendor_data - per-vendor variations
115132
* @has_mtdws: variant has the MTDWS bit
@@ -174,6 +191,7 @@ struct i2c_nmk_client {
174191
* @xfer_wq: xfer done wait queue.
175192
* @xfer_done: xfer done boolean.
176193
* @result: controller propogated result.
194+
* @has_32b_bus: controller is on a bus that only supports 32-bit accesses.
177195
*/
178196
struct nmk_i2c_dev {
179197
struct i2c_vendor_data *vendor;
@@ -192,6 +210,7 @@ struct nmk_i2c_dev {
192210
struct wait_queue_head xfer_wq;
193211
bool xfer_done;
194212
int result;
213+
bool has_32b_bus;
195214
};
196215

197216
/* controller's abort causes */
@@ -215,6 +234,24 @@ static inline void i2c_clr_bit(void __iomem *reg, u32 mask)
215234
writel(readl(reg) & ~mask, reg);
216235
}
217236

237+
static inline u8 nmk_i2c_readb(const struct nmk_i2c_dev *priv,
238+
unsigned long reg)
239+
{
240+
if (priv->has_32b_bus)
241+
return readl(priv->virtbase + reg);
242+
else
243+
return readb(priv->virtbase + reg);
244+
}
245+
246+
static inline void nmk_i2c_writeb(const struct nmk_i2c_dev *priv, u32 val,
247+
unsigned long reg)
248+
{
249+
if (priv->has_32b_bus)
250+
writel(val, priv->virtbase + reg);
251+
else
252+
writeb(val, priv->virtbase + reg);
253+
}
254+
218255
/**
219256
* flush_i2c_fifo() - This function flushes the I2C FIFO
220257
* @priv: private data of I2C Driver
@@ -523,7 +560,7 @@ static void fill_tx_fifo(struct nmk_i2c_dev *priv, int no_bytes)
523560
(priv->cli.count != 0);
524561
count--) {
525562
/* write to the Tx FIFO */
526-
writeb(*priv->cli.buffer, priv->virtbase + I2C_TFR);
563+
nmk_i2c_writeb(priv, *priv->cli.buffer, I2C_TFR);
527564
priv->cli.buffer++;
528565
priv->cli.count--;
529566
priv->cli.xfer_bytes++;
@@ -792,7 +829,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
792829
case I2C_IT_RXFNF:
793830
for (count = rft; count > 0; count--) {
794831
/* Read the Rx FIFO */
795-
*priv->cli.buffer = readb(priv->virtbase + I2C_RFR);
832+
*priv->cli.buffer = nmk_i2c_readb(priv, I2C_RFR);
796833
priv->cli.buffer++;
797834
}
798835
priv->cli.count -= rft;
@@ -802,7 +839,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
802839
/* Rx FIFO full */
803840
case I2C_IT_RXFF:
804841
for (count = MAX_I2C_FIFO_THRESHOLD; count > 0; count--) {
805-
*priv->cli.buffer = readb(priv->virtbase + I2C_RFR);
842+
*priv->cli.buffer = nmk_i2c_readb(priv, I2C_RFR);
806843
priv->cli.buffer++;
807844
}
808845
priv->cli.count -= MAX_I2C_FIFO_THRESHOLD;
@@ -818,7 +855,7 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg)
818855
if (priv->cli.count == 0)
819856
break;
820857
*priv->cli.buffer =
821-
readb(priv->virtbase + I2C_RFR);
858+
nmk_i2c_readb(priv, I2C_RFR);
822859
priv->cli.buffer++;
823860
priv->cli.count--;
824861
priv->cli.xfer_bytes++;
@@ -996,6 +1033,44 @@ static void nmk_i2c_of_probe(struct device_node *np,
9961033
priv->timeout_usecs = 200 * USEC_PER_MSEC;
9971034
}
9981035

1036+
static const unsigned int nmk_i2c_eyeq5_masks[] = {
1037+
GENMASK(5, 4),
1038+
GENMASK(7, 6),
1039+
GENMASK(9, 8),
1040+
GENMASK(11, 10),
1041+
GENMASK(13, 12),
1042+
};
1043+
1044+
static int nmk_i2c_eyeq5_probe(struct nmk_i2c_dev *priv)
1045+
{
1046+
struct device *dev = &priv->adev->dev;
1047+
struct device_node *np = dev->of_node;
1048+
unsigned int mask, speed_mode;
1049+
struct regmap *olb;
1050+
unsigned int id;
1051+
1052+
priv->has_32b_bus = true;
1053+
1054+
olb = syscon_regmap_lookup_by_phandle_args(np, "mobileye,olb", 1, &id);
1055+
if (IS_ERR(olb))
1056+
return PTR_ERR(olb);
1057+
if (id >= ARRAY_SIZE(nmk_i2c_eyeq5_masks))
1058+
return -ENOENT;
1059+
1060+
if (priv->clk_freq <= 400000)
1061+
speed_mode = I2C_EYEQ5_SPEED_FAST;
1062+
else if (priv->clk_freq <= 1000000)
1063+
speed_mode = I2C_EYEQ5_SPEED_FAST_PLUS;
1064+
else
1065+
speed_mode = I2C_EYEQ5_SPEED_HIGH_SPEED;
1066+
1067+
mask = nmk_i2c_eyeq5_masks[id];
1068+
regmap_update_bits(olb, NMK_I2C_EYEQ5_OLB_IOCR2,
1069+
mask, speed_mode << __fls(mask));
1070+
1071+
return 0;
1072+
}
1073+
9991074
static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
10001075
{
10011076
int ret = 0;
@@ -1012,8 +1087,15 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
10121087

10131088
priv->vendor = vendor;
10141089
priv->adev = adev;
1090+
priv->has_32b_bus = false;
10151091
nmk_i2c_of_probe(np, priv);
10161092

1093+
if (of_device_is_compatible(np, "mobileye,eyeq5-i2c")) {
1094+
ret = nmk_i2c_eyeq5_probe(priv);
1095+
if (ret)
1096+
return dev_err_probe(dev, ret, "failed OLB lookup\n");
1097+
}
1098+
10171099
if (priv->tft > max_fifo_threshold) {
10181100
dev_warn(dev, "requested TX FIFO threshold %u, adjusted down to %u\n",
10191101
priv->tft, max_fifo_threshold);

0 commit comments

Comments
 (0)