Skip to content

Commit 5acd48f

Browse files
Hans HuAndi Shyti
authored andcommitted
i2c: wmt: split out common files
Since the I2C IP of both wmt and zhaoxin originates from VIA, it is better to separate the common code first. The common driver is named as i2c-viai2c-common.c. Old i2c-wmt.c renamed to i2c-viai2c-wmt.c. The MAINTAINERS file will be updated accordingly in upcoming commits. Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Signed-off-by: Hans Hu <hanshu-oc@zhaoxin.com> Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
1 parent 8525205 commit 5acd48f

6 files changed

Lines changed: 442 additions & 431 deletions

File tree

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3017,7 +3017,7 @@ S: Orphan
30173017
F: Documentation/devicetree/bindings/i2c/i2c-wmt.txt
30183018
F: arch/arm/mach-vt8500/
30193019
F: drivers/clocksource/timer-vt8500.c
3020-
F: drivers/i2c/busses/i2c-wmt.c
3020+
F: drivers/i2c/busses/i2c-viai2c-wmt.c
30213021
F: drivers/mmc/host/wmt-sdmmc.c
30223022
F: drivers/pwm/pwm-vt8500.c
30233023
F: drivers/rtc/rtc-vt8500.c

drivers/i2c/busses/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ obj-$(CONFIG_I2C_TEGRA_BPMP) += i2c-tegra-bpmp.o
118118
obj-$(CONFIG_I2C_UNIPHIER) += i2c-uniphier.o
119119
obj-$(CONFIG_I2C_UNIPHIER_F) += i2c-uniphier-f.o
120120
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
121+
i2c-wmt-objs := i2c-viai2c-wmt.o i2c-viai2c-common.o
121122
obj-$(CONFIG_I2C_WMT) += i2c-wmt.o
122123
i2c-octeon-objs := i2c-octeon-core.o i2c-octeon-platdrv.o
123124
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
#include <linux/of_irq.h>
3+
#include "i2c-viai2c-common.h"
4+
5+
int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev)
6+
{
7+
unsigned long timeout;
8+
9+
timeout = jiffies + WMT_I2C_TIMEOUT;
10+
while (!(readw(i2c_dev->base + REG_CSR) & CSR_READY_MASK)) {
11+
if (time_after(jiffies, timeout)) {
12+
dev_warn(i2c_dev->dev, "timeout waiting for bus ready\n");
13+
return -EBUSY;
14+
}
15+
msleep(20);
16+
}
17+
18+
return 0;
19+
}
20+
21+
int wmt_check_status(struct wmt_i2c_dev *i2c_dev)
22+
{
23+
int ret = 0;
24+
unsigned long wait_result;
25+
26+
wait_result = wait_for_completion_timeout(&i2c_dev->complete,
27+
msecs_to_jiffies(500));
28+
if (!wait_result)
29+
return -ETIMEDOUT;
30+
31+
if (i2c_dev->cmd_status & ISR_NACK_ADDR)
32+
ret = -EIO;
33+
34+
if (i2c_dev->cmd_status & ISR_SCL_TIMEOUT)
35+
ret = -ETIMEDOUT;
36+
37+
return ret;
38+
}
39+
40+
static int wmt_i2c_write(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg, int last)
41+
{
42+
u16 val, tcr_val = i2c_dev->tcr;
43+
int ret;
44+
int xfer_len = 0;
45+
46+
if (pmsg->len == 0) {
47+
/*
48+
* We still need to run through the while (..) once, so
49+
* start at -1 and break out early from the loop
50+
*/
51+
xfer_len = -1;
52+
writew(0, i2c_dev->base + REG_CDR);
53+
} else {
54+
writew(pmsg->buf[0] & 0xFF, i2c_dev->base + REG_CDR);
55+
}
56+
57+
if (!(pmsg->flags & I2C_M_NOSTART)) {
58+
val = readw(i2c_dev->base + REG_CR);
59+
val &= ~CR_TX_END;
60+
val |= CR_CPU_RDY;
61+
writew(val, i2c_dev->base + REG_CR);
62+
}
63+
64+
reinit_completion(&i2c_dev->complete);
65+
66+
tcr_val |= (TCR_MASTER_WRITE | (pmsg->addr & TCR_SLAVE_ADDR_MASK));
67+
68+
writew(tcr_val, i2c_dev->base + REG_TCR);
69+
70+
if (pmsg->flags & I2C_M_NOSTART) {
71+
val = readw(i2c_dev->base + REG_CR);
72+
val |= CR_CPU_RDY;
73+
writew(val, i2c_dev->base + REG_CR);
74+
}
75+
76+
while (xfer_len < pmsg->len) {
77+
ret = wmt_check_status(i2c_dev);
78+
if (ret)
79+
return ret;
80+
81+
xfer_len++;
82+
83+
val = readw(i2c_dev->base + REG_CSR);
84+
if ((val & CSR_RCV_ACK_MASK) == CSR_RCV_NOT_ACK) {
85+
dev_dbg(i2c_dev->dev, "write RCV NACK error\n");
86+
return -EIO;
87+
}
88+
89+
if (pmsg->len == 0) {
90+
val = CR_TX_END | CR_CPU_RDY | CR_ENABLE;
91+
writew(val, i2c_dev->base + REG_CR);
92+
break;
93+
}
94+
95+
if (xfer_len == pmsg->len) {
96+
if (last != 1)
97+
writew(CR_ENABLE, i2c_dev->base + REG_CR);
98+
} else {
99+
writew(pmsg->buf[xfer_len] & 0xFF, i2c_dev->base +
100+
REG_CDR);
101+
writew(CR_CPU_RDY | CR_ENABLE, i2c_dev->base + REG_CR);
102+
}
103+
}
104+
105+
return 0;
106+
}
107+
108+
static int wmt_i2c_read(struct wmt_i2c_dev *i2c_dev, struct i2c_msg *pmsg)
109+
{
110+
u16 val, tcr_val = i2c_dev->tcr;
111+
int ret;
112+
u32 xfer_len = 0;
113+
114+
val = readw(i2c_dev->base + REG_CR);
115+
val &= ~(CR_TX_END | CR_TX_NEXT_NO_ACK);
116+
117+
if (!(pmsg->flags & I2C_M_NOSTART))
118+
val |= CR_CPU_RDY;
119+
120+
if (pmsg->len == 1)
121+
val |= CR_TX_NEXT_NO_ACK;
122+
123+
writew(val, i2c_dev->base + REG_CR);
124+
125+
reinit_completion(&i2c_dev->complete);
126+
127+
tcr_val |= TCR_MASTER_READ | (pmsg->addr & TCR_SLAVE_ADDR_MASK);
128+
129+
writew(tcr_val, i2c_dev->base + REG_TCR);
130+
131+
if (pmsg->flags & I2C_M_NOSTART) {
132+
val = readw(i2c_dev->base + REG_CR);
133+
val |= CR_CPU_RDY;
134+
writew(val, i2c_dev->base + REG_CR);
135+
}
136+
137+
while (xfer_len < pmsg->len) {
138+
ret = wmt_check_status(i2c_dev);
139+
if (ret)
140+
return ret;
141+
142+
pmsg->buf[xfer_len] = readw(i2c_dev->base + REG_CDR) >> 8;
143+
xfer_len++;
144+
145+
val = readw(i2c_dev->base + REG_CR) | CR_CPU_RDY;
146+
if (xfer_len == pmsg->len - 1)
147+
val |= CR_TX_NEXT_NO_ACK;
148+
writew(val, i2c_dev->base + REG_CR);
149+
}
150+
151+
return 0;
152+
}
153+
154+
int wmt_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
155+
{
156+
struct i2c_msg *pmsg;
157+
int i;
158+
int ret = 0;
159+
struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
160+
161+
for (i = 0; ret >= 0 && i < num; i++) {
162+
pmsg = &msgs[i];
163+
if (!(pmsg->flags & I2C_M_NOSTART)) {
164+
ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
165+
if (ret < 0)
166+
return ret;
167+
}
168+
169+
if (pmsg->flags & I2C_M_RD)
170+
ret = wmt_i2c_read(i2c_dev, pmsg);
171+
else
172+
ret = wmt_i2c_write(i2c_dev, pmsg, (i + 1) == num);
173+
}
174+
175+
return (ret < 0) ? ret : i;
176+
}
177+
178+
static irqreturn_t wmt_i2c_isr(int irq, void *data)
179+
{
180+
struct wmt_i2c_dev *i2c_dev = data;
181+
182+
/* save the status and write-clear it */
183+
i2c_dev->cmd_status = readw(i2c_dev->base + REG_ISR);
184+
writew(i2c_dev->cmd_status, i2c_dev->base + REG_ISR);
185+
186+
complete(&i2c_dev->complete);
187+
188+
return IRQ_HANDLED;
189+
}
190+
191+
int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c_dev **pi2c_dev)
192+
{
193+
int err;
194+
struct wmt_i2c_dev *i2c_dev;
195+
struct device_node *np = pdev->dev.of_node;
196+
197+
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
198+
if (!i2c_dev)
199+
return -ENOMEM;
200+
201+
i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
202+
if (IS_ERR(i2c_dev->base))
203+
return PTR_ERR(i2c_dev->base);
204+
205+
i2c_dev->irq = irq_of_parse_and_map(np, 0);
206+
if (!i2c_dev->irq)
207+
return -EINVAL;
208+
209+
err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr,
210+
0, pdev->name, i2c_dev);
211+
if (err)
212+
return dev_err_probe(&pdev->dev, err,
213+
"failed to request irq %i\n", i2c_dev->irq);
214+
215+
i2c_dev->dev = &pdev->dev;
216+
init_completion(&i2c_dev->complete);
217+
platform_set_drvdata(pdev, i2c_dev);
218+
219+
*pi2c_dev = i2c_dev;
220+
return 0;
221+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
#ifndef __I2C_VIAI2C_COMMON_H_
3+
#define __I2C_VIAI2C_COMMON_H_
4+
5+
#include <linux/delay.h>
6+
#include <linux/err.h>
7+
#include <linux/i2c.h>
8+
#include <linux/interrupt.h>
9+
#include <linux/io.h>
10+
#include <linux/module.h>
11+
#include <linux/of_irq.h>
12+
#include <linux/platform_device.h>
13+
14+
#define REG_CR 0x00
15+
#define REG_TCR 0x02
16+
#define REG_CSR 0x04
17+
#define REG_ISR 0x06
18+
#define REG_IMR 0x08
19+
#define REG_CDR 0x0A
20+
#define REG_TR 0x0C
21+
#define REG_MCR 0x0E
22+
23+
/* REG_CR Bit fields */
24+
#define CR_TX_NEXT_ACK 0x0000
25+
#define CR_ENABLE 0x0001
26+
#define CR_TX_NEXT_NO_ACK 0x0002
27+
#define CR_TX_END 0x0004
28+
#define CR_CPU_RDY 0x0008
29+
#define SLAV_MODE_SEL 0x8000
30+
31+
/* REG_TCR Bit fields */
32+
#define TCR_STANDARD_MODE 0x0000
33+
#define TCR_MASTER_WRITE 0x0000
34+
#define TCR_HS_MODE 0x2000
35+
#define TCR_MASTER_READ 0x4000
36+
#define TCR_FAST_MODE 0x8000
37+
#define TCR_SLAVE_ADDR_MASK 0x007F
38+
39+
/* REG_ISR Bit fields */
40+
#define ISR_NACK_ADDR 0x0001
41+
#define ISR_BYTE_END 0x0002
42+
#define ISR_SCL_TIMEOUT 0x0004
43+
#define ISR_WRITE_ALL 0x0007
44+
45+
/* REG_IMR Bit fields */
46+
#define IMR_ENABLE_ALL 0x0007
47+
48+
/* REG_CSR Bit fields */
49+
#define CSR_RCV_NOT_ACK 0x0001
50+
#define CSR_RCV_ACK_MASK 0x0001
51+
#define CSR_READY_MASK 0x0002
52+
53+
#define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000))
54+
55+
struct wmt_i2c_dev {
56+
struct i2c_adapter adapter;
57+
struct completion complete;
58+
struct device *dev;
59+
void __iomem *base;
60+
struct clk *clk;
61+
u16 tcr;
62+
int irq;
63+
u16 cmd_status;
64+
};
65+
66+
int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev);
67+
int wmt_check_status(struct wmt_i2c_dev *i2c_dev);
68+
int wmt_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num);
69+
int wmt_i2c_init(struct platform_device *pdev, struct wmt_i2c_dev **pi2c_dev);
70+
71+
#endif

0 commit comments

Comments
 (0)