1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Loongson-2K/Loongson LS7A I2C master mode driver |
4 | * |
5 | * Copyright (C) 2013 Loongson Technology Corporation Limited. |
6 | * Copyright (C) 2014-2017 Lemote, Inc. |
7 | * Copyright (C) 2018-2022 Loongson Technology Corporation Limited. |
8 | * |
9 | * Originally written by liushaozong |
10 | * Rewritten for mainline by Binbin Zhou <zhoubinbin@loongson.cn> |
11 | */ |
12 | |
13 | #include <linux/bits.h> |
14 | #include <linux/completion.h> |
15 | #include <linux/device.h> |
16 | #include <linux/iopoll.h> |
17 | #include <linux/i2c.h> |
18 | #include <linux/init.h> |
19 | #include <linux/interrupt.h> |
20 | #include <linux/io.h> |
21 | #include <linux/kernel.h> |
22 | #include <linux/module.h> |
23 | #include <linux/pm_runtime.h> |
24 | #include <linux/platform_device.h> |
25 | #include <linux/property.h> |
26 | #include <linux/units.h> |
27 | |
28 | /* I2C Registers */ |
29 | #define I2C_LS2X_PRER 0x0 /* Freq Division Register(16 bits) */ |
30 | #define I2C_LS2X_CTR 0x2 /* Control Register */ |
31 | #define I2C_LS2X_TXR 0x3 /* Transport Data Register */ |
32 | #define I2C_LS2X_RXR 0x3 /* Receive Data Register */ |
33 | #define I2C_LS2X_CR 0x4 /* Command Control Register */ |
34 | #define I2C_LS2X_SR 0x4 /* State Register */ |
35 | |
36 | /* Command Control Register Bit */ |
37 | #define LS2X_CR_START BIT(7) /* Start signal */ |
38 | #define LS2X_CR_STOP BIT(6) /* Stop signal */ |
39 | #define LS2X_CR_READ BIT(5) /* Read signal */ |
40 | #define LS2X_CR_WRITE BIT(4) /* Write signal */ |
41 | #define LS2X_CR_ACK BIT(3) /* Response signal */ |
42 | #define LS2X_CR_IACK BIT(0) /* Interrupt response signal */ |
43 | |
44 | /* State Register Bit */ |
45 | #define LS2X_SR_NOACK BIT(7) /* Receive NACK */ |
46 | #define LS2X_SR_BUSY BIT(6) /* Bus busy state */ |
47 | #define LS2X_SR_AL BIT(5) /* Arbitration lost */ |
48 | #define LS2X_SR_TIP BIT(1) /* Transmission state */ |
49 | #define LS2X_SR_IF BIT(0) /* Interrupt flag */ |
50 | |
51 | /* Control Register Bit */ |
52 | #define LS2X_CTR_EN BIT(7) /* 0: I2c frequency setting 1: Normal */ |
53 | #define LS2X_CTR_IEN BIT(6) /* Enable i2c interrupt */ |
54 | #define LS2X_CTR_MST BIT(5) /* 0: Slave mode 1: Master mode */ |
55 | #define CTR_FREQ_MASK GENMASK(7, 6) |
56 | #define CTR_READY_MASK GENMASK(7, 5) |
57 | |
58 | /* The PCLK frequency from LPB */ |
59 | #define LS2X_I2C_PCLK_FREQ (50 * HZ_PER_MHZ) |
60 | |
61 | /* The default bus frequency, which is an empirical value */ |
62 | #define LS2X_I2C_FREQ_STD (33 * HZ_PER_KHZ) |
63 | |
64 | struct ls2x_i2c_priv { |
65 | struct i2c_adapter adapter; |
66 | void __iomem *base; |
67 | struct i2c_timings i2c_t; |
68 | struct completion cmd_complete; |
69 | }; |
70 | |
71 | /* |
72 | * Interrupt service routine. |
73 | * This gets called whenever an I2C interrupt occurs. |
74 | */ |
75 | static irqreturn_t ls2x_i2c_isr(int this_irq, void *dev_id) |
76 | { |
77 | struct ls2x_i2c_priv *priv = dev_id; |
78 | |
79 | if (!(readb(addr: priv->base + I2C_LS2X_SR) & LS2X_SR_IF)) |
80 | return IRQ_NONE; |
81 | |
82 | writeb(LS2X_CR_IACK, addr: priv->base + I2C_LS2X_CR); |
83 | complete(&priv->cmd_complete); |
84 | return IRQ_HANDLED; |
85 | } |
86 | |
87 | /* |
88 | * The ls2x i2c controller supports standard mode and fast mode, so the |
89 | * maximum bus frequency is '400kHz'. |
90 | * The bus frequency is set to the empirical value of '33KHz' by default, |
91 | * but it can also be taken from ACPI or FDT for compatibility with more |
92 | * devices. |
93 | */ |
94 | static void ls2x_i2c_adjust_bus_speed(struct ls2x_i2c_priv *priv) |
95 | { |
96 | struct i2c_timings *t = &priv->i2c_t; |
97 | struct device *dev = priv->adapter.dev.parent; |
98 | u32 acpi_speed = i2c_acpi_find_bus_speed(dev); |
99 | |
100 | i2c_parse_fw_timings(dev, t, use_defaults: false); |
101 | |
102 | if (acpi_speed || t->bus_freq_hz) |
103 | t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed); |
104 | else |
105 | t->bus_freq_hz = LS2X_I2C_FREQ_STD; |
106 | |
107 | /* Calculate and set i2c frequency. */ |
108 | writew(LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1, |
109 | addr: priv->base + I2C_LS2X_PRER); |
110 | } |
111 | |
112 | static void ls2x_i2c_init(struct ls2x_i2c_priv *priv) |
113 | { |
114 | /* Set i2c frequency setting mode and disable interrupts. */ |
115 | writeb(readb(addr: priv->base + I2C_LS2X_CTR) & ~CTR_FREQ_MASK, |
116 | addr: priv->base + I2C_LS2X_CTR); |
117 | |
118 | ls2x_i2c_adjust_bus_speed(priv); |
119 | |
120 | /* Set i2c normal operating mode and enable interrupts. */ |
121 | writeb(readb(addr: priv->base + I2C_LS2X_CTR) | CTR_READY_MASK, |
122 | addr: priv->base + I2C_LS2X_CTR); |
123 | } |
124 | |
125 | static int ls2x_i2c_xfer_byte(struct ls2x_i2c_priv *priv, u8 txdata, u8 *rxdatap) |
126 | { |
127 | u8 rxdata; |
128 | unsigned long time_left; |
129 | |
130 | writeb(val: txdata, addr: priv->base + I2C_LS2X_CR); |
131 | |
132 | time_left = wait_for_completion_timeout(x: &priv->cmd_complete, |
133 | timeout: priv->adapter.timeout); |
134 | if (!time_left) |
135 | return -ETIMEDOUT; |
136 | |
137 | rxdata = readb(addr: priv->base + I2C_LS2X_SR); |
138 | if (rxdatap) |
139 | *rxdatap = rxdata; |
140 | |
141 | return 0; |
142 | } |
143 | |
144 | static int ls2x_i2c_send_byte(struct ls2x_i2c_priv *priv, u8 txdata) |
145 | { |
146 | int ret; |
147 | u8 rxdata; |
148 | |
149 | ret = ls2x_i2c_xfer_byte(priv, txdata, rxdatap: &rxdata); |
150 | if (ret) |
151 | return ret; |
152 | |
153 | if (rxdata & LS2X_SR_AL) |
154 | return -EAGAIN; |
155 | |
156 | if (rxdata & LS2X_SR_NOACK) |
157 | return -ENXIO; |
158 | |
159 | return 0; |
160 | } |
161 | |
162 | static int ls2x_i2c_stop(struct ls2x_i2c_priv *priv) |
163 | { |
164 | u8 value; |
165 | |
166 | writeb(LS2X_CR_STOP, addr: priv->base + I2C_LS2X_CR); |
167 | return readb_poll_timeout(priv->base + I2C_LS2X_SR, value, |
168 | !(value & LS2X_SR_BUSY), 100, |
169 | jiffies_to_usecs(priv->adapter.timeout)); |
170 | } |
171 | |
172 | static int ls2x_i2c_start(struct ls2x_i2c_priv *priv, struct i2c_msg *msgs) |
173 | { |
174 | reinit_completion(x: &priv->cmd_complete); |
175 | |
176 | writeb(val: i2c_8bit_addr_from_msg(msg: msgs), addr: priv->base + I2C_LS2X_TXR); |
177 | return ls2x_i2c_send_byte(priv, LS2X_CR_START | LS2X_CR_WRITE); |
178 | } |
179 | |
180 | static int ls2x_i2c_rx(struct ls2x_i2c_priv *priv, struct i2c_msg *msg) |
181 | { |
182 | int ret; |
183 | u8 rxdata, *buf = msg->buf; |
184 | u16 len = msg->len; |
185 | |
186 | /* Contains steps to send start condition and address. */ |
187 | ret = ls2x_i2c_start(priv, msgs: msg); |
188 | if (ret) |
189 | return ret; |
190 | |
191 | while (len--) { |
192 | ret = ls2x_i2c_xfer_byte(priv, |
193 | LS2X_CR_READ | (len ? 0 : LS2X_CR_ACK), |
194 | rxdatap: &rxdata); |
195 | if (ret) |
196 | return ret; |
197 | |
198 | *buf++ = readb(addr: priv->base + I2C_LS2X_RXR); |
199 | } |
200 | |
201 | return 0; |
202 | } |
203 | |
204 | static int ls2x_i2c_tx(struct ls2x_i2c_priv *priv, struct i2c_msg *msg) |
205 | { |
206 | int ret; |
207 | u8 *buf = msg->buf; |
208 | u16 len = msg->len; |
209 | |
210 | /* Contains steps to send start condition and address. */ |
211 | ret = ls2x_i2c_start(priv, msgs: msg); |
212 | if (ret) |
213 | return ret; |
214 | |
215 | while (len--) { |
216 | writeb(val: *buf++, addr: priv->base + I2C_LS2X_TXR); |
217 | |
218 | ret = ls2x_i2c_send_byte(priv, LS2X_CR_WRITE); |
219 | if (ret) |
220 | return ret; |
221 | } |
222 | |
223 | return 0; |
224 | } |
225 | |
226 | static int ls2x_i2c_xfer_one(struct ls2x_i2c_priv *priv, |
227 | struct i2c_msg *msg, bool stop) |
228 | { |
229 | int ret; |
230 | |
231 | if (msg->flags & I2C_M_RD) |
232 | ret = ls2x_i2c_rx(priv, msg); |
233 | else |
234 | ret = ls2x_i2c_tx(priv, msg); |
235 | |
236 | if (ret < 0) { |
237 | /* Fatel error. Needs reinit. */ |
238 | if (ret == -ETIMEDOUT) |
239 | ls2x_i2c_init(priv); |
240 | |
241 | return ret; |
242 | } |
243 | |
244 | if (stop) { |
245 | /* Failed to issue STOP. Needs reinit. */ |
246 | ret = ls2x_i2c_stop(priv); |
247 | if (ret) |
248 | ls2x_i2c_init(priv); |
249 | } |
250 | |
251 | return ret; |
252 | } |
253 | |
254 | static int ls2x_i2c_master_xfer(struct i2c_adapter *adap, |
255 | struct i2c_msg *msgs, int num) |
256 | { |
257 | int ret; |
258 | struct i2c_msg *msg, *emsg = msgs + num; |
259 | struct ls2x_i2c_priv *priv = i2c_get_adapdata(adap); |
260 | |
261 | for (msg = msgs; msg < emsg; msg++) { |
262 | ret = ls2x_i2c_xfer_one(priv, msg, stop: msg == emsg - 1); |
263 | if (ret) |
264 | return ret; |
265 | } |
266 | |
267 | return num; |
268 | } |
269 | |
270 | static unsigned int ls2x_i2c_func(struct i2c_adapter *adap) |
271 | { |
272 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
273 | } |
274 | |
275 | static const struct i2c_algorithm ls2x_i2c_algo = { |
276 | .master_xfer = ls2x_i2c_master_xfer, |
277 | .functionality = ls2x_i2c_func, |
278 | }; |
279 | |
280 | static int ls2x_i2c_probe(struct platform_device *pdev) |
281 | { |
282 | int ret, irq; |
283 | struct i2c_adapter *adap; |
284 | struct ls2x_i2c_priv *priv; |
285 | struct device *dev = &pdev->dev; |
286 | |
287 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
288 | if (!priv) |
289 | return -ENOMEM; |
290 | |
291 | /* Map hardware registers */ |
292 | priv->base = devm_platform_ioremap_resource(pdev, index: 0); |
293 | if (IS_ERR(ptr: priv->base)) |
294 | return PTR_ERR(ptr: priv->base); |
295 | |
296 | irq = platform_get_irq(pdev, 0); |
297 | if (irq < 0) |
298 | return irq; |
299 | |
300 | /* Add the i2c adapter */ |
301 | adap = &priv->adapter; |
302 | adap->retries = 5; |
303 | adap->nr = pdev->id; |
304 | adap->dev.parent = dev; |
305 | adap->owner = THIS_MODULE; |
306 | adap->algo = &ls2x_i2c_algo; |
307 | adap->timeout = msecs_to_jiffies(m: 100); |
308 | device_set_node(dev: &adap->dev, dev_fwnode(dev)); |
309 | i2c_set_adapdata(adap, data: priv); |
310 | strscpy(adap->name, pdev->name, sizeof(adap->name)); |
311 | init_completion(x: &priv->cmd_complete); |
312 | platform_set_drvdata(pdev, data: priv); |
313 | |
314 | ls2x_i2c_init(priv); |
315 | |
316 | ret = devm_request_irq(dev, irq, handler: ls2x_i2c_isr, IRQF_SHARED, devname: "ls2x-i2c" , |
317 | dev_id: priv); |
318 | if (ret < 0) |
319 | return dev_err_probe(dev, err: ret, fmt: "Unable to request irq %d\n" , irq); |
320 | |
321 | return devm_i2c_add_adapter(dev, adapter: adap); |
322 | } |
323 | |
324 | static int ls2x_i2c_suspend(struct device *dev) |
325 | { |
326 | struct ls2x_i2c_priv *priv = dev_get_drvdata(dev); |
327 | |
328 | /* Disable interrupts */ |
329 | writeb(readb(addr: priv->base + I2C_LS2X_CTR) & ~LS2X_CTR_IEN, |
330 | addr: priv->base + I2C_LS2X_CTR); |
331 | |
332 | return 0; |
333 | } |
334 | |
335 | static int ls2x_i2c_resume(struct device *dev) |
336 | { |
337 | ls2x_i2c_init(priv: dev_get_drvdata(dev)); |
338 | return 0; |
339 | } |
340 | |
341 | static DEFINE_RUNTIME_DEV_PM_OPS(ls2x_i2c_pm_ops, |
342 | ls2x_i2c_suspend, ls2x_i2c_resume, NULL); |
343 | |
344 | static const struct of_device_id ls2x_i2c_id_table[] = { |
345 | { .compatible = "loongson,ls2k-i2c" }, |
346 | { .compatible = "loongson,ls7a-i2c" }, |
347 | { /* sentinel */ } |
348 | }; |
349 | MODULE_DEVICE_TABLE(of, ls2x_i2c_id_table); |
350 | |
351 | static const struct acpi_device_id ls2x_i2c_acpi_match[] = { |
352 | { "LOON0004" }, /* Loongson LS7A */ |
353 | { } |
354 | }; |
355 | MODULE_DEVICE_TABLE(acpi, ls2x_i2c_acpi_match); |
356 | |
357 | static struct platform_driver ls2x_i2c_driver = { |
358 | .probe = ls2x_i2c_probe, |
359 | .driver = { |
360 | .name = "ls2x-i2c" , |
361 | .pm = pm_sleep_ptr(&ls2x_i2c_pm_ops), |
362 | .of_match_table = ls2x_i2c_id_table, |
363 | .acpi_match_table = ls2x_i2c_acpi_match, |
364 | }, |
365 | }; |
366 | module_platform_driver(ls2x_i2c_driver); |
367 | |
368 | MODULE_DESCRIPTION("Loongson LS2X I2C Bus driver" ); |
369 | MODULE_AUTHOR("Loongson Technology Corporation Limited" ); |
370 | MODULE_LICENSE("GPL" ); |
371 | |