1 // SPDX-License-Identifier: GPL-2.0-or-later 2 #include <linux/of_irq.h> 3 #include "i2c-viai2c-common.h" 4 5 int viai2c_wait_bus_not_busy(struct viai2c *i2c) 6 { 7 unsigned long timeout; 8 9 timeout = jiffies + VIAI2C_TIMEOUT; 10 while (!(readw(i2c->base + VIAI2C_REG_CSR) & VIAI2C_CSR_READY_MASK)) { 11 if (time_after(jiffies, timeout)) { 12 dev_warn(i2c->dev, "timeout waiting for bus ready\n"); 13 return -EBUSY; 14 } 15 msleep(20); 16 } 17 18 return 0; 19 } 20 21 static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, int last) 22 { 23 u16 val, tcr_val = i2c->tcr; 24 25 i2c->last = last; 26 27 if (pmsg->len == 0) { 28 /* 29 * We still need to run through the while (..) once, so 30 * start at -1 and break out early from the loop 31 */ 32 i2c->xfered_len = -1; 33 writew(0, i2c->base + VIAI2C_REG_CDR); 34 } else { 35 writew(pmsg->buf[0] & 0xFF, i2c->base + VIAI2C_REG_CDR); 36 } 37 38 if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) { 39 val = readw(i2c->base + VIAI2C_REG_CR); 40 val &= ~VIAI2C_CR_TX_END; 41 val |= VIAI2C_CR_CPU_RDY; 42 writew(val, i2c->base + VIAI2C_REG_CR); 43 } 44 45 reinit_completion(&i2c->complete); 46 47 tcr_val |= pmsg->addr & VIAI2C_TCR_ADDR_MASK; 48 49 writew(tcr_val, i2c->base + VIAI2C_REG_TCR); 50 51 if (i2c->platform == VIAI2C_PLAT_WMT && pmsg->flags & I2C_M_NOSTART) { 52 val = readw(i2c->base + VIAI2C_REG_CR); 53 val |= VIAI2C_CR_CPU_RDY; 54 writew(val, i2c->base + VIAI2C_REG_CR); 55 } 56 57 if (!wait_for_completion_timeout(&i2c->complete, VIAI2C_TIMEOUT)) 58 return -ETIMEDOUT; 59 60 return i2c->ret; 61 } 62 63 static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg, bool first) 64 { 65 u16 val, tcr_val = i2c->tcr; 66 67 val = readw(i2c->base + VIAI2C_REG_CR); 68 val &= ~(VIAI2C_CR_TX_END | VIAI2C_CR_RX_END); 69 70 if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) 71 val |= VIAI2C_CR_CPU_RDY; 72 73 if (pmsg->len == 1) 74 val |= VIAI2C_CR_RX_END; 75 76 writew(val, i2c->base + VIAI2C_REG_CR); 77 78 reinit_completion(&i2c->complete); 79 80 tcr_val |= VIAI2C_TCR_READ | (pmsg->addr & VIAI2C_TCR_ADDR_MASK); 81 82 writew(tcr_val, i2c->base + VIAI2C_REG_TCR); 83 84 if ((i2c->platform == VIAI2C_PLAT_WMT && (pmsg->flags & I2C_M_NOSTART)) || 85 (i2c->platform == VIAI2C_PLAT_ZHAOXIN && !first)) { 86 val = readw(i2c->base + VIAI2C_REG_CR); 87 val |= VIAI2C_CR_CPU_RDY; 88 writew(val, i2c->base + VIAI2C_REG_CR); 89 } 90 91 if (!wait_for_completion_timeout(&i2c->complete, VIAI2C_TIMEOUT)) 92 return -ETIMEDOUT; 93 94 return i2c->ret; 95 } 96 97 int viai2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) 98 { 99 struct i2c_msg *pmsg; 100 int i; 101 int ret = 0; 102 struct viai2c *i2c = i2c_get_adapdata(adap); 103 104 i2c->mode = VIAI2C_BYTE_MODE; 105 for (i = 0; ret >= 0 && i < num; i++) { 106 pmsg = &msgs[i]; 107 if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) { 108 ret = viai2c_wait_bus_not_busy(i2c); 109 if (ret < 0) 110 return ret; 111 } 112 113 i2c->msg = pmsg; 114 i2c->xfered_len = 0; 115 116 if (pmsg->flags & I2C_M_RD) 117 ret = viai2c_read(i2c, pmsg, i == 0); 118 else 119 ret = viai2c_write(i2c, pmsg, (i + 1) == num); 120 } 121 122 return (ret < 0) ? ret : i; 123 } 124 125 /* 126 * Main process of the byte mode xfer 127 * 128 * Return value indicates whether the transfer is complete 129 * 1: all the data has been successfully transferred 130 * 0: there is still data that needs to be transferred 131 * -EIO: error occurred 132 */ 133 static int viai2c_irq_xfer(struct viai2c *i2c) 134 { 135 u16 val; 136 struct i2c_msg *msg = i2c->msg; 137 u8 read = msg->flags & I2C_M_RD; 138 void __iomem *base = i2c->base; 139 140 if (read) { 141 msg->buf[i2c->xfered_len] = readw(base + VIAI2C_REG_CDR) >> 8; 142 143 val = readw(base + VIAI2C_REG_CR) | VIAI2C_CR_CPU_RDY; 144 if (i2c->xfered_len == msg->len - 2) 145 val |= VIAI2C_CR_RX_END; 146 writew(val, base + VIAI2C_REG_CR); 147 } else { 148 val = readw(base + VIAI2C_REG_CSR); 149 if (val & VIAI2C_CSR_RCV_NOT_ACK) 150 return -EIO; 151 152 /* I2C_SMBUS_QUICK */ 153 if (msg->len == 0) { 154 val = VIAI2C_CR_TX_END | VIAI2C_CR_CPU_RDY | VIAI2C_CR_ENABLE; 155 writew(val, base + VIAI2C_REG_CR); 156 return 1; 157 } 158 159 if ((i2c->xfered_len + 1) == msg->len) { 160 if (i2c->platform == VIAI2C_PLAT_WMT && !i2c->last) 161 writew(VIAI2C_CR_ENABLE, base + VIAI2C_REG_CR); 162 else if (i2c->platform == VIAI2C_PLAT_ZHAOXIN && i2c->last) 163 writeb(VIAI2C_CR_TX_END, base + VIAI2C_REG_CR); 164 } else { 165 writew(msg->buf[i2c->xfered_len + 1] & 0xFF, base + VIAI2C_REG_CDR); 166 writew(VIAI2C_CR_CPU_RDY | VIAI2C_CR_ENABLE, base + VIAI2C_REG_CR); 167 } 168 } 169 170 i2c->xfered_len++; 171 172 return i2c->xfered_len == msg->len; 173 } 174 175 int __weak viai2c_fifo_irq_xfer(struct viai2c *i2c, bool irq) 176 { 177 return 0; 178 } 179 180 static irqreturn_t viai2c_isr(int irq, void *data) 181 { 182 struct viai2c *i2c = data; 183 u8 status; 184 185 /* save the status and write-clear it */ 186 status = readw(i2c->base + VIAI2C_REG_ISR); 187 if (!status && i2c->platform == VIAI2C_PLAT_ZHAOXIN) 188 return IRQ_NONE; 189 190 writew(status, i2c->base + VIAI2C_REG_ISR); 191 192 i2c->ret = 0; 193 if (status & VIAI2C_ISR_NACK_ADDR) 194 i2c->ret = -EIO; 195 196 if (i2c->platform == VIAI2C_PLAT_WMT && (status & VIAI2C_ISR_SCL_TIMEOUT)) 197 i2c->ret = -ETIMEDOUT; 198 199 if (!i2c->ret) { 200 if (i2c->mode == VIAI2C_BYTE_MODE) 201 i2c->ret = viai2c_irq_xfer(i2c); 202 else 203 i2c->ret = viai2c_fifo_irq_xfer(i2c, true); 204 } 205 206 /* All the data has been successfully transferred or error occurred */ 207 if (i2c->ret) 208 complete(&i2c->complete); 209 210 return IRQ_HANDLED; 211 } 212 213 int viai2c_init(struct platform_device *pdev, struct viai2c **pi2c, int plat) 214 { 215 int err; 216 int irq_flags; 217 struct viai2c *i2c; 218 struct device_node *np = pdev->dev.of_node; 219 220 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); 221 if (!i2c) 222 return -ENOMEM; 223 224 i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 225 if (IS_ERR(i2c->base)) 226 return PTR_ERR(i2c->base); 227 228 if (plat == VIAI2C_PLAT_WMT) { 229 irq_flags = 0; 230 i2c->irq = irq_of_parse_and_map(np, 0); 231 if (!i2c->irq) 232 return -EINVAL; 233 } else if (plat == VIAI2C_PLAT_ZHAOXIN) { 234 irq_flags = IRQF_SHARED; 235 i2c->irq = platform_get_irq(pdev, 0); 236 if (i2c->irq < 0) 237 return i2c->irq; 238 } else { 239 return dev_err_probe(&pdev->dev, -EINVAL, "wrong platform type\n"); 240 } 241 242 i2c->platform = plat; 243 244 err = devm_request_irq(&pdev->dev, i2c->irq, viai2c_isr, 245 irq_flags, pdev->name, i2c); 246 if (err) 247 return dev_err_probe(&pdev->dev, err, 248 "failed to request irq %i\n", i2c->irq); 249 250 i2c->dev = &pdev->dev; 251 init_completion(&i2c->complete); 252 platform_set_drvdata(pdev, i2c); 253 254 *pi2c = i2c; 255 return 0; 256 } 257