1*d211e62aSManivannan Sadhasivam // SPDX-License-Identifier: GPL-2.0-or-later 2*d211e62aSManivannan Sadhasivam /* 3*d211e62aSManivannan Sadhasivam * Actions Semiconductor Owl SoC's I2C driver 4*d211e62aSManivannan Sadhasivam * 5*d211e62aSManivannan Sadhasivam * Copyright (c) 2014 Actions Semi Inc. 6*d211e62aSManivannan Sadhasivam * Author: David Liu <liuwei@actions-semi.com> 7*d211e62aSManivannan Sadhasivam * 8*d211e62aSManivannan Sadhasivam * Copyright (c) 2018 Linaro Ltd. 9*d211e62aSManivannan Sadhasivam * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 10*d211e62aSManivannan Sadhasivam */ 11*d211e62aSManivannan Sadhasivam 12*d211e62aSManivannan Sadhasivam #include <linux/clk.h> 13*d211e62aSManivannan Sadhasivam #include <linux/delay.h> 14*d211e62aSManivannan Sadhasivam #include <linux/i2c.h> 15*d211e62aSManivannan Sadhasivam #include <linux/interrupt.h> 16*d211e62aSManivannan Sadhasivam #include <linux/io.h> 17*d211e62aSManivannan Sadhasivam #include <linux/module.h> 18*d211e62aSManivannan Sadhasivam #include <linux/of_device.h> 19*d211e62aSManivannan Sadhasivam 20*d211e62aSManivannan Sadhasivam /* I2C registers */ 21*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_CTL 0x0000 22*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_CLKDIV 0x0004 23*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_STAT 0x0008 24*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_ADDR 0x000C 25*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_TXDAT 0x0010 26*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_RXDAT 0x0014 27*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_CMD 0x0018 28*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_FIFOCTL 0x001C 29*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_FIFOSTAT 0x0020 30*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_DATCNT 0x0024 31*d211e62aSManivannan Sadhasivam #define OWL_I2C_REG_RCNT 0x0028 32*d211e62aSManivannan Sadhasivam 33*d211e62aSManivannan Sadhasivam /* I2Cx_CTL Bit Mask */ 34*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_RB BIT(1) 35*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_GBCC(x) (((x) & 0x3) << 2) 36*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_GBCC_NONE OWL_I2C_CTL_GBCC(0) 37*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_GBCC_START OWL_I2C_CTL_GBCC(1) 38*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_GBCC_STOP OWL_I2C_CTL_GBCC(2) 39*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_GBCC_RSTART OWL_I2C_CTL_GBCC(3) 40*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_IRQE BIT(5) 41*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_EN BIT(7) 42*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_AE BIT(8) 43*d211e62aSManivannan Sadhasivam #define OWL_I2C_CTL_SHSM BIT(10) 44*d211e62aSManivannan Sadhasivam 45*d211e62aSManivannan Sadhasivam #define OWL_I2C_DIV_FACTOR(x) ((x) & 0xff) 46*d211e62aSManivannan Sadhasivam 47*d211e62aSManivannan Sadhasivam /* I2Cx_STAT Bit Mask */ 48*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_RACK BIT(0) 49*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_BEB BIT(1) 50*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_IRQP BIT(2) 51*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_LAB BIT(3) 52*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_STPD BIT(4) 53*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_STAD BIT(5) 54*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_BBB BIT(6) 55*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_TCB BIT(7) 56*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_LBST BIT(8) 57*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_SAMB BIT(9) 58*d211e62aSManivannan Sadhasivam #define OWL_I2C_STAT_SRGC BIT(10) 59*d211e62aSManivannan Sadhasivam 60*d211e62aSManivannan Sadhasivam /* I2Cx_CMD Bit Mask */ 61*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SBE BIT(0) 62*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_RBE BIT(4) 63*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_DE BIT(8) 64*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_NS BIT(9) 65*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SE BIT(10) 66*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_MSS BIT(11) 67*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_WRS BIT(12) 68*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SECL BIT(15) 69*d211e62aSManivannan Sadhasivam 70*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_AS(x) (((x) & 0x7) << 1) 71*d211e62aSManivannan Sadhasivam #define OWL_I2C_CMD_SAS(x) (((x) & 0x7) << 5) 72*d211e62aSManivannan Sadhasivam 73*d211e62aSManivannan Sadhasivam /* I2Cx_FIFOCTL Bit Mask */ 74*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOCTL_NIB BIT(0) 75*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOCTL_RFR BIT(1) 76*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOCTL_TFR BIT(2) 77*d211e62aSManivannan Sadhasivam 78*d211e62aSManivannan Sadhasivam /* I2Cc_FIFOSTAT Bit Mask */ 79*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_RNB BIT(1) 80*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_RFE BIT(2) 81*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_TFF BIT(5) 82*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_TFD GENMASK(23, 16) 83*d211e62aSManivannan Sadhasivam #define OWL_I2C_FIFOSTAT_RFD GENMASK(15, 8) 84*d211e62aSManivannan Sadhasivam 85*d211e62aSManivannan Sadhasivam /* I2C bus timeout */ 86*d211e62aSManivannan Sadhasivam #define OWL_I2C_TIMEOUT msecs_to_jiffies(4 * 1000) 87*d211e62aSManivannan Sadhasivam 88*d211e62aSManivannan Sadhasivam #define OWL_I2C_MAX_RETRIES 50 89*d211e62aSManivannan Sadhasivam 90*d211e62aSManivannan Sadhasivam #define OWL_I2C_DEF_SPEED_HZ 100000 91*d211e62aSManivannan Sadhasivam #define OWL_I2C_MAX_SPEED_HZ 400000 92*d211e62aSManivannan Sadhasivam 93*d211e62aSManivannan Sadhasivam struct owl_i2c_dev { 94*d211e62aSManivannan Sadhasivam struct i2c_adapter adap; 95*d211e62aSManivannan Sadhasivam struct i2c_msg *msg; 96*d211e62aSManivannan Sadhasivam struct completion msg_complete; 97*d211e62aSManivannan Sadhasivam struct clk *clk; 98*d211e62aSManivannan Sadhasivam spinlock_t lock; 99*d211e62aSManivannan Sadhasivam void __iomem *base; 100*d211e62aSManivannan Sadhasivam unsigned long clk_rate; 101*d211e62aSManivannan Sadhasivam u32 bus_freq; 102*d211e62aSManivannan Sadhasivam u32 msg_ptr; 103*d211e62aSManivannan Sadhasivam int err; 104*d211e62aSManivannan Sadhasivam }; 105*d211e62aSManivannan Sadhasivam 106*d211e62aSManivannan Sadhasivam static void owl_i2c_update_reg(void __iomem *reg, unsigned int val, bool state) 107*d211e62aSManivannan Sadhasivam { 108*d211e62aSManivannan Sadhasivam unsigned int regval; 109*d211e62aSManivannan Sadhasivam 110*d211e62aSManivannan Sadhasivam regval = readl(reg); 111*d211e62aSManivannan Sadhasivam 112*d211e62aSManivannan Sadhasivam if (state) 113*d211e62aSManivannan Sadhasivam regval |= val; 114*d211e62aSManivannan Sadhasivam else 115*d211e62aSManivannan Sadhasivam regval &= ~val; 116*d211e62aSManivannan Sadhasivam 117*d211e62aSManivannan Sadhasivam writel(regval, reg); 118*d211e62aSManivannan Sadhasivam } 119*d211e62aSManivannan Sadhasivam 120*d211e62aSManivannan Sadhasivam static void owl_i2c_reset(struct owl_i2c_dev *i2c_dev) 121*d211e62aSManivannan Sadhasivam { 122*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, 123*d211e62aSManivannan Sadhasivam OWL_I2C_CTL_EN, false); 124*d211e62aSManivannan Sadhasivam mdelay(1); 125*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, 126*d211e62aSManivannan Sadhasivam OWL_I2C_CTL_EN, true); 127*d211e62aSManivannan Sadhasivam 128*d211e62aSManivannan Sadhasivam /* Clear status registers */ 129*d211e62aSManivannan Sadhasivam writel(0, i2c_dev->base + OWL_I2C_REG_STAT); 130*d211e62aSManivannan Sadhasivam } 131*d211e62aSManivannan Sadhasivam 132*d211e62aSManivannan Sadhasivam static int owl_i2c_reset_fifo(struct owl_i2c_dev *i2c_dev) 133*d211e62aSManivannan Sadhasivam { 134*d211e62aSManivannan Sadhasivam unsigned int val, timeout = 0; 135*d211e62aSManivannan Sadhasivam 136*d211e62aSManivannan Sadhasivam /* Reset FIFO */ 137*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL, 138*d211e62aSManivannan Sadhasivam OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR, 139*d211e62aSManivannan Sadhasivam true); 140*d211e62aSManivannan Sadhasivam 141*d211e62aSManivannan Sadhasivam /* Wait 50ms for FIFO reset complete */ 142*d211e62aSManivannan Sadhasivam do { 143*d211e62aSManivannan Sadhasivam val = readl(i2c_dev->base + OWL_I2C_REG_FIFOCTL); 144*d211e62aSManivannan Sadhasivam if (!(val & (OWL_I2C_FIFOCTL_RFR | OWL_I2C_FIFOCTL_TFR))) 145*d211e62aSManivannan Sadhasivam break; 146*d211e62aSManivannan Sadhasivam usleep_range(500, 1000); 147*d211e62aSManivannan Sadhasivam } while (timeout++ < OWL_I2C_MAX_RETRIES); 148*d211e62aSManivannan Sadhasivam 149*d211e62aSManivannan Sadhasivam if (timeout > OWL_I2C_MAX_RETRIES) { 150*d211e62aSManivannan Sadhasivam dev_err(&i2c_dev->adap.dev, "FIFO reset timeout\n"); 151*d211e62aSManivannan Sadhasivam return -ETIMEDOUT; 152*d211e62aSManivannan Sadhasivam } 153*d211e62aSManivannan Sadhasivam 154*d211e62aSManivannan Sadhasivam return 0; 155*d211e62aSManivannan Sadhasivam } 156*d211e62aSManivannan Sadhasivam 157*d211e62aSManivannan Sadhasivam static void owl_i2c_set_freq(struct owl_i2c_dev *i2c_dev) 158*d211e62aSManivannan Sadhasivam { 159*d211e62aSManivannan Sadhasivam unsigned int val; 160*d211e62aSManivannan Sadhasivam 161*d211e62aSManivannan Sadhasivam val = DIV_ROUND_UP(i2c_dev->clk_rate, i2c_dev->bus_freq * 16); 162*d211e62aSManivannan Sadhasivam 163*d211e62aSManivannan Sadhasivam /* Set clock divider factor */ 164*d211e62aSManivannan Sadhasivam writel(OWL_I2C_DIV_FACTOR(val), i2c_dev->base + OWL_I2C_REG_CLKDIV); 165*d211e62aSManivannan Sadhasivam } 166*d211e62aSManivannan Sadhasivam 167*d211e62aSManivannan Sadhasivam static irqreturn_t owl_i2c_interrupt(int irq, void *_dev) 168*d211e62aSManivannan Sadhasivam { 169*d211e62aSManivannan Sadhasivam struct owl_i2c_dev *i2c_dev = _dev; 170*d211e62aSManivannan Sadhasivam struct i2c_msg *msg = i2c_dev->msg; 171*d211e62aSManivannan Sadhasivam unsigned long flags; 172*d211e62aSManivannan Sadhasivam unsigned int stat, fifostat; 173*d211e62aSManivannan Sadhasivam 174*d211e62aSManivannan Sadhasivam spin_lock_irqsave(&i2c_dev->lock, flags); 175*d211e62aSManivannan Sadhasivam 176*d211e62aSManivannan Sadhasivam i2c_dev->err = 0; 177*d211e62aSManivannan Sadhasivam 178*d211e62aSManivannan Sadhasivam /* Handle NACK from slave */ 179*d211e62aSManivannan Sadhasivam fifostat = readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT); 180*d211e62aSManivannan Sadhasivam if (fifostat & OWL_I2C_FIFOSTAT_RNB) { 181*d211e62aSManivannan Sadhasivam i2c_dev->err = -ENXIO; 182*d211e62aSManivannan Sadhasivam goto stop; 183*d211e62aSManivannan Sadhasivam } 184*d211e62aSManivannan Sadhasivam 185*d211e62aSManivannan Sadhasivam /* Handle bus error */ 186*d211e62aSManivannan Sadhasivam stat = readl(i2c_dev->base + OWL_I2C_REG_STAT); 187*d211e62aSManivannan Sadhasivam if (stat & OWL_I2C_STAT_BEB) { 188*d211e62aSManivannan Sadhasivam i2c_dev->err = -EIO; 189*d211e62aSManivannan Sadhasivam goto stop; 190*d211e62aSManivannan Sadhasivam } 191*d211e62aSManivannan Sadhasivam 192*d211e62aSManivannan Sadhasivam /* Handle FIFO read */ 193*d211e62aSManivannan Sadhasivam if (msg->flags & I2C_M_RD) { 194*d211e62aSManivannan Sadhasivam while ((readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) & 195*d211e62aSManivannan Sadhasivam OWL_I2C_FIFOSTAT_RFE) && i2c_dev->msg_ptr < msg->len) { 196*d211e62aSManivannan Sadhasivam msg->buf[i2c_dev->msg_ptr++] = readl(i2c_dev->base + 197*d211e62aSManivannan Sadhasivam OWL_I2C_REG_RXDAT); 198*d211e62aSManivannan Sadhasivam } 199*d211e62aSManivannan Sadhasivam } else { 200*d211e62aSManivannan Sadhasivam /* Handle the remaining bytes which were not sent */ 201*d211e62aSManivannan Sadhasivam while (!(readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) & 202*d211e62aSManivannan Sadhasivam OWL_I2C_FIFOSTAT_TFF) && i2c_dev->msg_ptr < msg->len) { 203*d211e62aSManivannan Sadhasivam writel(msg->buf[i2c_dev->msg_ptr++], 204*d211e62aSManivannan Sadhasivam i2c_dev->base + OWL_I2C_REG_TXDAT); 205*d211e62aSManivannan Sadhasivam } 206*d211e62aSManivannan Sadhasivam } 207*d211e62aSManivannan Sadhasivam 208*d211e62aSManivannan Sadhasivam stop: 209*d211e62aSManivannan Sadhasivam /* Clear pending interrupts */ 210*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_STAT, 211*d211e62aSManivannan Sadhasivam OWL_I2C_STAT_IRQP, true); 212*d211e62aSManivannan Sadhasivam 213*d211e62aSManivannan Sadhasivam complete_all(&i2c_dev->msg_complete); 214*d211e62aSManivannan Sadhasivam spin_unlock_irqrestore(&i2c_dev->lock, flags); 215*d211e62aSManivannan Sadhasivam 216*d211e62aSManivannan Sadhasivam return IRQ_HANDLED; 217*d211e62aSManivannan Sadhasivam } 218*d211e62aSManivannan Sadhasivam 219*d211e62aSManivannan Sadhasivam static u32 owl_i2c_func(struct i2c_adapter *adap) 220*d211e62aSManivannan Sadhasivam { 221*d211e62aSManivannan Sadhasivam return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 222*d211e62aSManivannan Sadhasivam } 223*d211e62aSManivannan Sadhasivam 224*d211e62aSManivannan Sadhasivam static int owl_i2c_check_bus_busy(struct i2c_adapter *adap) 225*d211e62aSManivannan Sadhasivam { 226*d211e62aSManivannan Sadhasivam struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap); 227*d211e62aSManivannan Sadhasivam unsigned long timeout; 228*d211e62aSManivannan Sadhasivam 229*d211e62aSManivannan Sadhasivam /* Check for Bus busy */ 230*d211e62aSManivannan Sadhasivam timeout = jiffies + OWL_I2C_TIMEOUT; 231*d211e62aSManivannan Sadhasivam while (readl(i2c_dev->base + OWL_I2C_REG_STAT) & OWL_I2C_STAT_BBB) { 232*d211e62aSManivannan Sadhasivam if (time_after(jiffies, timeout)) { 233*d211e62aSManivannan Sadhasivam dev_err(&adap->dev, "Bus busy timeout\n"); 234*d211e62aSManivannan Sadhasivam return -ETIMEDOUT; 235*d211e62aSManivannan Sadhasivam } 236*d211e62aSManivannan Sadhasivam } 237*d211e62aSManivannan Sadhasivam 238*d211e62aSManivannan Sadhasivam return 0; 239*d211e62aSManivannan Sadhasivam } 240*d211e62aSManivannan Sadhasivam 241*d211e62aSManivannan Sadhasivam static int owl_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 242*d211e62aSManivannan Sadhasivam int num) 243*d211e62aSManivannan Sadhasivam { 244*d211e62aSManivannan Sadhasivam struct owl_i2c_dev *i2c_dev = i2c_get_adapdata(adap); 245*d211e62aSManivannan Sadhasivam struct i2c_msg *msg; 246*d211e62aSManivannan Sadhasivam unsigned long time_left, flags; 247*d211e62aSManivannan Sadhasivam unsigned int i2c_cmd, val; 248*d211e62aSManivannan Sadhasivam unsigned int addr; 249*d211e62aSManivannan Sadhasivam int ret, idx; 250*d211e62aSManivannan Sadhasivam 251*d211e62aSManivannan Sadhasivam spin_lock_irqsave(&i2c_dev->lock, flags); 252*d211e62aSManivannan Sadhasivam 253*d211e62aSManivannan Sadhasivam /* Reset I2C controller */ 254*d211e62aSManivannan Sadhasivam owl_i2c_reset(i2c_dev); 255*d211e62aSManivannan Sadhasivam 256*d211e62aSManivannan Sadhasivam /* Set bus frequency */ 257*d211e62aSManivannan Sadhasivam owl_i2c_set_freq(i2c_dev); 258*d211e62aSManivannan Sadhasivam 259*d211e62aSManivannan Sadhasivam /* 260*d211e62aSManivannan Sadhasivam * Spinlock should be released before calling reset FIFO and 261*d211e62aSManivannan Sadhasivam * bus busy check since those functions may sleep 262*d211e62aSManivannan Sadhasivam */ 263*d211e62aSManivannan Sadhasivam spin_unlock_irqrestore(&i2c_dev->lock, flags); 264*d211e62aSManivannan Sadhasivam 265*d211e62aSManivannan Sadhasivam /* Reset FIFO */ 266*d211e62aSManivannan Sadhasivam ret = owl_i2c_reset_fifo(i2c_dev); 267*d211e62aSManivannan Sadhasivam if (ret) 268*d211e62aSManivannan Sadhasivam goto unlocked_err_exit; 269*d211e62aSManivannan Sadhasivam 270*d211e62aSManivannan Sadhasivam /* Check for bus busy */ 271*d211e62aSManivannan Sadhasivam ret = owl_i2c_check_bus_busy(adap); 272*d211e62aSManivannan Sadhasivam if (ret) 273*d211e62aSManivannan Sadhasivam goto unlocked_err_exit; 274*d211e62aSManivannan Sadhasivam 275*d211e62aSManivannan Sadhasivam spin_lock_irqsave(&i2c_dev->lock, flags); 276*d211e62aSManivannan Sadhasivam 277*d211e62aSManivannan Sadhasivam /* Check for Arbitration lost */ 278*d211e62aSManivannan Sadhasivam val = readl(i2c_dev->base + OWL_I2C_REG_STAT); 279*d211e62aSManivannan Sadhasivam if (val & OWL_I2C_STAT_LAB) { 280*d211e62aSManivannan Sadhasivam val &= ~OWL_I2C_STAT_LAB; 281*d211e62aSManivannan Sadhasivam writel(val, i2c_dev->base + OWL_I2C_REG_STAT); 282*d211e62aSManivannan Sadhasivam ret = -EAGAIN; 283*d211e62aSManivannan Sadhasivam goto err_exit; 284*d211e62aSManivannan Sadhasivam } 285*d211e62aSManivannan Sadhasivam 286*d211e62aSManivannan Sadhasivam reinit_completion(&i2c_dev->msg_complete); 287*d211e62aSManivannan Sadhasivam 288*d211e62aSManivannan Sadhasivam /* Enable I2C controller interrupt */ 289*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, 290*d211e62aSManivannan Sadhasivam OWL_I2C_CTL_IRQE, true); 291*d211e62aSManivannan Sadhasivam 292*d211e62aSManivannan Sadhasivam /* 293*d211e62aSManivannan Sadhasivam * Select: FIFO enable, Master mode, Stop enable, Data count enable, 294*d211e62aSManivannan Sadhasivam * Send start bit 295*d211e62aSManivannan Sadhasivam */ 296*d211e62aSManivannan Sadhasivam i2c_cmd = OWL_I2C_CMD_SECL | OWL_I2C_CMD_MSS | OWL_I2C_CMD_SE | 297*d211e62aSManivannan Sadhasivam OWL_I2C_CMD_NS | OWL_I2C_CMD_DE | OWL_I2C_CMD_SBE; 298*d211e62aSManivannan Sadhasivam 299*d211e62aSManivannan Sadhasivam /* Handle repeated start condition */ 300*d211e62aSManivannan Sadhasivam if (num > 1) { 301*d211e62aSManivannan Sadhasivam /* Set internal address length and enable repeated start */ 302*d211e62aSManivannan Sadhasivam i2c_cmd |= OWL_I2C_CMD_AS(msgs[0].len + 1) | 303*d211e62aSManivannan Sadhasivam OWL_I2C_CMD_SAS(1) | OWL_I2C_CMD_RBE; 304*d211e62aSManivannan Sadhasivam 305*d211e62aSManivannan Sadhasivam /* Write slave address */ 306*d211e62aSManivannan Sadhasivam addr = i2c_8bit_addr_from_msg(&msgs[0]); 307*d211e62aSManivannan Sadhasivam writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT); 308*d211e62aSManivannan Sadhasivam 309*d211e62aSManivannan Sadhasivam /* Write internal register address */ 310*d211e62aSManivannan Sadhasivam for (idx = 0; idx < msgs[0].len; idx++) 311*d211e62aSManivannan Sadhasivam writel(msgs[0].buf[idx], 312*d211e62aSManivannan Sadhasivam i2c_dev->base + OWL_I2C_REG_TXDAT); 313*d211e62aSManivannan Sadhasivam 314*d211e62aSManivannan Sadhasivam msg = &msgs[1]; 315*d211e62aSManivannan Sadhasivam } else { 316*d211e62aSManivannan Sadhasivam /* Set address length */ 317*d211e62aSManivannan Sadhasivam i2c_cmd |= OWL_I2C_CMD_AS(1); 318*d211e62aSManivannan Sadhasivam msg = &msgs[0]; 319*d211e62aSManivannan Sadhasivam } 320*d211e62aSManivannan Sadhasivam 321*d211e62aSManivannan Sadhasivam i2c_dev->msg = msg; 322*d211e62aSManivannan Sadhasivam i2c_dev->msg_ptr = 0; 323*d211e62aSManivannan Sadhasivam 324*d211e62aSManivannan Sadhasivam /* Set data count for the message */ 325*d211e62aSManivannan Sadhasivam writel(msg->len, i2c_dev->base + OWL_I2C_REG_DATCNT); 326*d211e62aSManivannan Sadhasivam 327*d211e62aSManivannan Sadhasivam addr = i2c_8bit_addr_from_msg(msg); 328*d211e62aSManivannan Sadhasivam writel(addr, i2c_dev->base + OWL_I2C_REG_TXDAT); 329*d211e62aSManivannan Sadhasivam 330*d211e62aSManivannan Sadhasivam if (!(msg->flags & I2C_M_RD)) { 331*d211e62aSManivannan Sadhasivam /* Write data to FIFO */ 332*d211e62aSManivannan Sadhasivam for (idx = 0; idx < msg->len; idx++) { 333*d211e62aSManivannan Sadhasivam /* Check for FIFO full */ 334*d211e62aSManivannan Sadhasivam if (readl(i2c_dev->base + OWL_I2C_REG_FIFOSTAT) & 335*d211e62aSManivannan Sadhasivam OWL_I2C_FIFOSTAT_TFF) 336*d211e62aSManivannan Sadhasivam break; 337*d211e62aSManivannan Sadhasivam 338*d211e62aSManivannan Sadhasivam writel(msg->buf[idx], 339*d211e62aSManivannan Sadhasivam i2c_dev->base + OWL_I2C_REG_TXDAT); 340*d211e62aSManivannan Sadhasivam } 341*d211e62aSManivannan Sadhasivam 342*d211e62aSManivannan Sadhasivam i2c_dev->msg_ptr = idx; 343*d211e62aSManivannan Sadhasivam } 344*d211e62aSManivannan Sadhasivam 345*d211e62aSManivannan Sadhasivam /* Ignore the NACK if needed */ 346*d211e62aSManivannan Sadhasivam if (msg->flags & I2C_M_IGNORE_NAK) 347*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL, 348*d211e62aSManivannan Sadhasivam OWL_I2C_FIFOCTL_NIB, true); 349*d211e62aSManivannan Sadhasivam else 350*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_FIFOCTL, 351*d211e62aSManivannan Sadhasivam OWL_I2C_FIFOCTL_NIB, false); 352*d211e62aSManivannan Sadhasivam 353*d211e62aSManivannan Sadhasivam /* Start the transfer */ 354*d211e62aSManivannan Sadhasivam writel(i2c_cmd, i2c_dev->base + OWL_I2C_REG_CMD); 355*d211e62aSManivannan Sadhasivam 356*d211e62aSManivannan Sadhasivam spin_unlock_irqrestore(&i2c_dev->lock, flags); 357*d211e62aSManivannan Sadhasivam 358*d211e62aSManivannan Sadhasivam time_left = wait_for_completion_timeout(&i2c_dev->msg_complete, 359*d211e62aSManivannan Sadhasivam adap->timeout); 360*d211e62aSManivannan Sadhasivam 361*d211e62aSManivannan Sadhasivam spin_lock_irqsave(&i2c_dev->lock, flags); 362*d211e62aSManivannan Sadhasivam if (time_left == 0) { 363*d211e62aSManivannan Sadhasivam dev_err(&adap->dev, "Transaction timed out\n"); 364*d211e62aSManivannan Sadhasivam /* Send stop condition and release the bus */ 365*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, 366*d211e62aSManivannan Sadhasivam OWL_I2C_CTL_GBCC_STOP | OWL_I2C_CTL_RB, 367*d211e62aSManivannan Sadhasivam true); 368*d211e62aSManivannan Sadhasivam ret = -ETIMEDOUT; 369*d211e62aSManivannan Sadhasivam goto err_exit; 370*d211e62aSManivannan Sadhasivam } 371*d211e62aSManivannan Sadhasivam 372*d211e62aSManivannan Sadhasivam ret = i2c_dev->err < 0 ? i2c_dev->err : num; 373*d211e62aSManivannan Sadhasivam 374*d211e62aSManivannan Sadhasivam err_exit: 375*d211e62aSManivannan Sadhasivam spin_unlock_irqrestore(&i2c_dev->lock, flags); 376*d211e62aSManivannan Sadhasivam 377*d211e62aSManivannan Sadhasivam unlocked_err_exit: 378*d211e62aSManivannan Sadhasivam /* Disable I2C controller */ 379*d211e62aSManivannan Sadhasivam owl_i2c_update_reg(i2c_dev->base + OWL_I2C_REG_CTL, 380*d211e62aSManivannan Sadhasivam OWL_I2C_CTL_EN, false); 381*d211e62aSManivannan Sadhasivam 382*d211e62aSManivannan Sadhasivam return ret; 383*d211e62aSManivannan Sadhasivam } 384*d211e62aSManivannan Sadhasivam 385*d211e62aSManivannan Sadhasivam static const struct i2c_algorithm owl_i2c_algorithm = { 386*d211e62aSManivannan Sadhasivam .master_xfer = owl_i2c_master_xfer, 387*d211e62aSManivannan Sadhasivam .functionality = owl_i2c_func, 388*d211e62aSManivannan Sadhasivam }; 389*d211e62aSManivannan Sadhasivam 390*d211e62aSManivannan Sadhasivam static const struct i2c_adapter_quirks owl_i2c_quirks = { 391*d211e62aSManivannan Sadhasivam .flags = I2C_AQ_COMB | I2C_AQ_COMB_WRITE_FIRST, 392*d211e62aSManivannan Sadhasivam .max_read_len = 240, 393*d211e62aSManivannan Sadhasivam .max_write_len = 240, 394*d211e62aSManivannan Sadhasivam .max_comb_1st_msg_len = 6, 395*d211e62aSManivannan Sadhasivam .max_comb_2nd_msg_len = 240, 396*d211e62aSManivannan Sadhasivam }; 397*d211e62aSManivannan Sadhasivam 398*d211e62aSManivannan Sadhasivam static int owl_i2c_probe(struct platform_device *pdev) 399*d211e62aSManivannan Sadhasivam { 400*d211e62aSManivannan Sadhasivam struct device *dev = &pdev->dev; 401*d211e62aSManivannan Sadhasivam struct owl_i2c_dev *i2c_dev; 402*d211e62aSManivannan Sadhasivam struct resource *res; 403*d211e62aSManivannan Sadhasivam int ret, irq; 404*d211e62aSManivannan Sadhasivam 405*d211e62aSManivannan Sadhasivam i2c_dev = devm_kzalloc(dev, sizeof(*i2c_dev), GFP_KERNEL); 406*d211e62aSManivannan Sadhasivam if (!i2c_dev) 407*d211e62aSManivannan Sadhasivam return -ENOMEM; 408*d211e62aSManivannan Sadhasivam 409*d211e62aSManivannan Sadhasivam res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 410*d211e62aSManivannan Sadhasivam i2c_dev->base = devm_ioremap_resource(dev, res); 411*d211e62aSManivannan Sadhasivam if (IS_ERR(i2c_dev->base)) 412*d211e62aSManivannan Sadhasivam return PTR_ERR(i2c_dev->base); 413*d211e62aSManivannan Sadhasivam 414*d211e62aSManivannan Sadhasivam irq = platform_get_irq(pdev, 0); 415*d211e62aSManivannan Sadhasivam if (irq < 0) { 416*d211e62aSManivannan Sadhasivam dev_err(dev, "failed to get IRQ number\n"); 417*d211e62aSManivannan Sadhasivam return irq; 418*d211e62aSManivannan Sadhasivam } 419*d211e62aSManivannan Sadhasivam 420*d211e62aSManivannan Sadhasivam if (of_property_read_u32(dev->of_node, "clock-frequency", 421*d211e62aSManivannan Sadhasivam &i2c_dev->bus_freq)) 422*d211e62aSManivannan Sadhasivam i2c_dev->bus_freq = OWL_I2C_DEF_SPEED_HZ; 423*d211e62aSManivannan Sadhasivam 424*d211e62aSManivannan Sadhasivam /* We support only frequencies of 100k and 400k for now */ 425*d211e62aSManivannan Sadhasivam if (i2c_dev->bus_freq != OWL_I2C_DEF_SPEED_HZ && 426*d211e62aSManivannan Sadhasivam i2c_dev->bus_freq != OWL_I2C_MAX_SPEED_HZ) { 427*d211e62aSManivannan Sadhasivam dev_err(dev, "invalid clock-frequency %d\n", i2c_dev->bus_freq); 428*d211e62aSManivannan Sadhasivam return -EINVAL; 429*d211e62aSManivannan Sadhasivam } 430*d211e62aSManivannan Sadhasivam 431*d211e62aSManivannan Sadhasivam i2c_dev->clk = devm_clk_get(dev, NULL); 432*d211e62aSManivannan Sadhasivam if (IS_ERR(i2c_dev->clk)) { 433*d211e62aSManivannan Sadhasivam dev_err(dev, "failed to get clock\n"); 434*d211e62aSManivannan Sadhasivam return PTR_ERR(i2c_dev->clk); 435*d211e62aSManivannan Sadhasivam } 436*d211e62aSManivannan Sadhasivam 437*d211e62aSManivannan Sadhasivam ret = clk_prepare_enable(i2c_dev->clk); 438*d211e62aSManivannan Sadhasivam if (ret) 439*d211e62aSManivannan Sadhasivam return ret; 440*d211e62aSManivannan Sadhasivam 441*d211e62aSManivannan Sadhasivam i2c_dev->clk_rate = clk_get_rate(i2c_dev->clk); 442*d211e62aSManivannan Sadhasivam if (!i2c_dev->clk_rate) { 443*d211e62aSManivannan Sadhasivam dev_err(dev, "input clock rate should not be zero\n"); 444*d211e62aSManivannan Sadhasivam ret = -EINVAL; 445*d211e62aSManivannan Sadhasivam goto disable_clk; 446*d211e62aSManivannan Sadhasivam } 447*d211e62aSManivannan Sadhasivam 448*d211e62aSManivannan Sadhasivam init_completion(&i2c_dev->msg_complete); 449*d211e62aSManivannan Sadhasivam spin_lock_init(&i2c_dev->lock); 450*d211e62aSManivannan Sadhasivam i2c_dev->adap.owner = THIS_MODULE; 451*d211e62aSManivannan Sadhasivam i2c_dev->adap.algo = &owl_i2c_algorithm; 452*d211e62aSManivannan Sadhasivam i2c_dev->adap.timeout = OWL_I2C_TIMEOUT; 453*d211e62aSManivannan Sadhasivam i2c_dev->adap.quirks = &owl_i2c_quirks; 454*d211e62aSManivannan Sadhasivam i2c_dev->adap.dev.parent = dev; 455*d211e62aSManivannan Sadhasivam i2c_dev->adap.dev.of_node = dev->of_node; 456*d211e62aSManivannan Sadhasivam snprintf(i2c_dev->adap.name, sizeof(i2c_dev->adap.name), 457*d211e62aSManivannan Sadhasivam "%s", "OWL I2C adapter"); 458*d211e62aSManivannan Sadhasivam i2c_set_adapdata(&i2c_dev->adap, i2c_dev); 459*d211e62aSManivannan Sadhasivam 460*d211e62aSManivannan Sadhasivam platform_set_drvdata(pdev, i2c_dev); 461*d211e62aSManivannan Sadhasivam 462*d211e62aSManivannan Sadhasivam ret = devm_request_irq(dev, irq, owl_i2c_interrupt, 0, pdev->name, 463*d211e62aSManivannan Sadhasivam i2c_dev); 464*d211e62aSManivannan Sadhasivam if (ret) { 465*d211e62aSManivannan Sadhasivam dev_err(dev, "failed to request irq %d\n", irq); 466*d211e62aSManivannan Sadhasivam goto disable_clk; 467*d211e62aSManivannan Sadhasivam } 468*d211e62aSManivannan Sadhasivam 469*d211e62aSManivannan Sadhasivam return i2c_add_adapter(&i2c_dev->adap); 470*d211e62aSManivannan Sadhasivam 471*d211e62aSManivannan Sadhasivam disable_clk: 472*d211e62aSManivannan Sadhasivam clk_disable_unprepare(i2c_dev->clk); 473*d211e62aSManivannan Sadhasivam 474*d211e62aSManivannan Sadhasivam return ret; 475*d211e62aSManivannan Sadhasivam } 476*d211e62aSManivannan Sadhasivam 477*d211e62aSManivannan Sadhasivam static const struct of_device_id owl_i2c_of_match[] = { 478*d211e62aSManivannan Sadhasivam { .compatible = "actions,s900-i2c" }, 479*d211e62aSManivannan Sadhasivam { /* sentinel */ } 480*d211e62aSManivannan Sadhasivam }; 481*d211e62aSManivannan Sadhasivam MODULE_DEVICE_TABLE(of, owl_i2c_of_match); 482*d211e62aSManivannan Sadhasivam 483*d211e62aSManivannan Sadhasivam static struct platform_driver owl_i2c_driver = { 484*d211e62aSManivannan Sadhasivam .probe = owl_i2c_probe, 485*d211e62aSManivannan Sadhasivam .driver = { 486*d211e62aSManivannan Sadhasivam .name = "owl-i2c", 487*d211e62aSManivannan Sadhasivam .of_match_table = of_match_ptr(owl_i2c_of_match), 488*d211e62aSManivannan Sadhasivam }, 489*d211e62aSManivannan Sadhasivam }; 490*d211e62aSManivannan Sadhasivam module_platform_driver(owl_i2c_driver); 491*d211e62aSManivannan Sadhasivam 492*d211e62aSManivannan Sadhasivam MODULE_AUTHOR("David Liu <liuwei@actions-semi.com>"); 493*d211e62aSManivannan Sadhasivam MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>"); 494*d211e62aSManivannan Sadhasivam MODULE_DESCRIPTION("Actions Semiconductor Owl SoC's I2C driver"); 495*d211e62aSManivannan Sadhasivam MODULE_LICENSE("GPL"); 496