Lines Matching +full:i2c +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 #include "i2c-viai2c-common.h"
5 int viai2c_wait_bus_not_busy(struct viai2c *i2c) in viai2c_wait_bus_not_busy() argument
10 while (!(readw(i2c->base + VIAI2C_REG_CSR) & VIAI2C_CSR_READY_MASK)) { in viai2c_wait_bus_not_busy()
12 dev_warn(i2c->dev, "timeout waiting for bus ready\n"); in viai2c_wait_bus_not_busy()
13 return -EBUSY; in viai2c_wait_bus_not_busy()
18 return 0; in viai2c_wait_bus_not_busy()
22 static int viai2c_write(struct viai2c *i2c, struct i2c_msg *pmsg, int last) in viai2c_write() argument
24 u16 val, tcr_val = i2c->tcr; in viai2c_write()
26 i2c->last = last; in viai2c_write()
28 if (pmsg->len == 0) { in viai2c_write()
31 * start at -1 and break out early from the loop in viai2c_write()
33 i2c->xfered_len = -1; in viai2c_write()
34 writew(0, i2c->base + VIAI2C_REG_CDR); in viai2c_write()
36 writew(pmsg->buf[0] & 0xFF, i2c->base + VIAI2C_REG_CDR); in viai2c_write()
39 if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) { in viai2c_write()
40 val = readw(i2c->base + VIAI2C_REG_CR); in viai2c_write()
43 writew(val, i2c->base + VIAI2C_REG_CR); in viai2c_write()
46 reinit_completion(&i2c->complete); in viai2c_write()
48 tcr_val |= pmsg->addr & VIAI2C_TCR_ADDR_MASK; in viai2c_write()
50 writew(tcr_val, i2c->base + VIAI2C_REG_TCR); in viai2c_write()
52 if (i2c->platform == VIAI2C_PLAT_WMT && pmsg->flags & I2C_M_NOSTART) { in viai2c_write()
53 val = readw(i2c->base + VIAI2C_REG_CR); in viai2c_write()
55 writew(val, i2c->base + VIAI2C_REG_CR); in viai2c_write()
58 if (!wait_for_completion_timeout(&i2c->complete, VIAI2C_TIMEOUT)) in viai2c_write()
59 return -ETIMEDOUT; in viai2c_write()
61 return i2c->ret; in viai2c_write()
64 static int viai2c_read(struct viai2c *i2c, struct i2c_msg *pmsg, bool first) in viai2c_read() argument
66 u16 val, tcr_val = i2c->tcr; in viai2c_read()
68 val = readw(i2c->base + VIAI2C_REG_CR); in viai2c_read()
71 if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) in viai2c_read()
74 if (pmsg->len == 1) in viai2c_read()
77 writew(val, i2c->base + VIAI2C_REG_CR); in viai2c_read()
79 reinit_completion(&i2c->complete); in viai2c_read()
81 tcr_val |= VIAI2C_TCR_READ | (pmsg->addr & VIAI2C_TCR_ADDR_MASK); in viai2c_read()
83 writew(tcr_val, i2c->base + VIAI2C_REG_TCR); in viai2c_read()
85 if ((i2c->platform == VIAI2C_PLAT_WMT && (pmsg->flags & I2C_M_NOSTART)) || in viai2c_read()
86 (i2c->platform == VIAI2C_PLAT_ZHAOXIN && !first)) { in viai2c_read()
87 val = readw(i2c->base + VIAI2C_REG_CR); in viai2c_read()
89 writew(val, i2c->base + VIAI2C_REG_CR); in viai2c_read()
92 if (!wait_for_completion_timeout(&i2c->complete, VIAI2C_TIMEOUT)) in viai2c_read()
93 return -ETIMEDOUT; in viai2c_read()
95 return i2c->ret; in viai2c_read()
102 int ret = 0; in viai2c_xfer()
103 struct viai2c *i2c = i2c_get_adapdata(adap); in viai2c_xfer() local
105 i2c->mode = VIAI2C_BYTE_MODE; in viai2c_xfer()
106 for (i = 0; ret >= 0 && i < num; i++) { in viai2c_xfer()
108 if (i2c->platform == VIAI2C_PLAT_WMT && !(pmsg->flags & I2C_M_NOSTART)) { in viai2c_xfer()
109 ret = viai2c_wait_bus_not_busy(i2c); in viai2c_xfer()
110 if (ret < 0) in viai2c_xfer()
114 i2c->msg = pmsg; in viai2c_xfer()
115 i2c->xfered_len = 0; in viai2c_xfer()
117 if (pmsg->flags & I2C_M_RD) in viai2c_xfer()
118 ret = viai2c_read(i2c, pmsg, i == 0); in viai2c_xfer()
120 ret = viai2c_write(i2c, pmsg, (i + 1) == num); in viai2c_xfer()
123 return (ret < 0) ? ret : i; in viai2c_xfer()
132 * 0: there is still data that needs to be transferred
133 * -EIO: error occurred
135 int viai2c_irq_xfer(struct viai2c *i2c) in viai2c_irq_xfer() argument
138 struct i2c_msg *msg = i2c->msg; in viai2c_irq_xfer()
139 u8 read = msg->flags & I2C_M_RD; in viai2c_irq_xfer()
140 void __iomem *base = i2c->base; in viai2c_irq_xfer()
143 msg->buf[i2c->xfered_len] = readw(base + VIAI2C_REG_CDR) >> 8; in viai2c_irq_xfer()
146 if (i2c->xfered_len == msg->len - 2) in viai2c_irq_xfer()
152 return -EIO; in viai2c_irq_xfer()
155 if (msg->len == 0) { in viai2c_irq_xfer()
161 if ((i2c->xfered_len + 1) == msg->len) { in viai2c_irq_xfer()
162 if (i2c->platform == VIAI2C_PLAT_WMT && !i2c->last) in viai2c_irq_xfer()
164 else if (i2c->platform == VIAI2C_PLAT_ZHAOXIN && i2c->last) in viai2c_irq_xfer()
167 writew(msg->buf[i2c->xfered_len + 1] & 0xFF, base + VIAI2C_REG_CDR); in viai2c_irq_xfer()
172 i2c->xfered_len++; in viai2c_irq_xfer()
174 return i2c->xfered_len == msg->len; in viai2c_irq_xfer()
180 struct viai2c *i2c; in viai2c_init() local
182 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); in viai2c_init()
183 if (!i2c) in viai2c_init()
184 return -ENOMEM; in viai2c_init()
186 i2c->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); in viai2c_init()
187 if (IS_ERR(i2c->base)) in viai2c_init()
188 return PTR_ERR(i2c->base); in viai2c_init()
190 i2c->platform = plat; in viai2c_init()
192 i2c->dev = &pdev->dev; in viai2c_init()
193 init_completion(&i2c->complete); in viai2c_init()
194 platform_set_drvdata(pdev, i2c); in viai2c_init()
196 *pi2c = i2c; in viai2c_init()
197 return 0; in viai2c_init()
201 MODULE_DESCRIPTION("Via/Wondermedia/Zhaoxin I2C controller core");