1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Microchip CoreI2C I2C controller driver |
4 | * |
5 | * Copyright (c) 2018-2022 Microchip Corporation. All rights reserved. |
6 | * |
7 | * Author: Daire McNamara <daire.mcnamara@microchip.com> |
8 | * Author: Conor Dooley <conor.dooley@microchip.com> |
9 | */ |
10 | #include <linux/clk.h> |
11 | #include <linux/clkdev.h> |
12 | #include <linux/err.h> |
13 | #include <linux/i2c.h> |
14 | #include <linux/interrupt.h> |
15 | #include <linux/io.h> |
16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> |
18 | #include <linux/platform_device.h> |
19 | |
20 | #define CORE_I2C_CTRL (0x00) |
21 | #define CTRL_CR0 BIT(0) |
22 | #define CTRL_CR1 BIT(1) |
23 | #define CTRL_AA BIT(2) |
24 | #define CTRL_SI BIT(3) |
25 | #define CTRL_STO BIT(4) |
26 | #define CTRL_STA BIT(5) |
27 | #define CTRL_ENS1 BIT(6) |
28 | #define CTRL_CR2 BIT(7) |
29 | |
30 | #define STATUS_BUS_ERROR (0x00) |
31 | #define STATUS_M_START_SENT (0x08) |
32 | #define STATUS_M_REPEATED_START_SENT (0x10) |
33 | #define STATUS_M_SLAW_ACK (0x18) |
34 | #define STATUS_M_SLAW_NACK (0x20) |
35 | #define STATUS_M_TX_DATA_ACK (0x28) |
36 | #define STATUS_M_TX_DATA_NACK (0x30) |
37 | #define STATUS_M_ARB_LOST (0x38) |
38 | #define STATUS_M_SLAR_ACK (0x40) |
39 | #define STATUS_M_SLAR_NACK (0x48) |
40 | #define STATUS_M_RX_DATA_ACKED (0x50) |
41 | #define STATUS_M_RX_DATA_NACKED (0x58) |
42 | #define STATUS_S_SLAW_ACKED (0x60) |
43 | #define STATUS_S_ARB_LOST_SLAW_ACKED (0x68) |
44 | #define STATUS_S_GENERAL_CALL_ACKED (0x70) |
45 | #define STATUS_S_ARB_LOST_GENERAL_CALL_ACKED (0x78) |
46 | #define STATUS_S_RX_DATA_ACKED (0x80) |
47 | #define STATUS_S_RX_DATA_NACKED (0x88) |
48 | #define STATUS_S_GENERAL_CALL_RX_DATA_ACKED (0x90) |
49 | #define STATUS_S_GENERAL_CALL_RX_DATA_NACKED (0x98) |
50 | #define STATUS_S_RX_STOP (0xA0) |
51 | #define STATUS_S_SLAR_ACKED (0xA8) |
52 | #define STATUS_S_ARB_LOST_SLAR_ACKED (0xB0) |
53 | #define STATUS_S_TX_DATA_ACK (0xB8) |
54 | #define STATUS_S_TX_DATA_NACK (0xC0) |
55 | #define STATUS_LAST_DATA_ACK (0xC8) |
56 | #define STATUS_M_SMB_MASTER_RESET (0xD0) |
57 | #define STATUS_S_SCL_LOW_TIMEOUT (0xD8) /* 25 ms */ |
58 | #define STATUS_NO_STATE_INFO (0xF8) |
59 | |
60 | #define CORE_I2C_STATUS (0x04) |
61 | #define CORE_I2C_DATA (0x08) |
62 | #define WRITE_BIT (0x0) |
63 | #define READ_BIT (0x1) |
64 | #define SLAVE_ADDR_SHIFT (1) |
65 | #define CORE_I2C_SLAVE0_ADDR (0x0c) |
66 | #define GENERAL_CALL_BIT (0x0) |
67 | #define CORE_I2C_SMBUS (0x10) |
68 | #define SMBALERT_INT_ENB (0x0) |
69 | #define SMBSUS_INT_ENB (0x1) |
70 | #define SMBUS_ENB (0x2) |
71 | #define SMBALERT_NI_STATUS (0x3) |
72 | #define SMBALERT_NO_CTRL (0x4) |
73 | #define SMBSUS_NI_STATUS (0x5) |
74 | #define SMBSUS_NO_CTRL (0x6) |
75 | #define SMBUS_RESET (0x7) |
76 | #define CORE_I2C_FREQ (0x14) |
77 | #define CORE_I2C_GLITCHREG (0x18) |
78 | #define CORE_I2C_SLAVE1_ADDR (0x1c) |
79 | |
80 | #define PCLK_DIV_960 (CTRL_CR2) |
81 | #define PCLK_DIV_256 (0) |
82 | #define PCLK_DIV_224 (CTRL_CR0) |
83 | #define PCLK_DIV_192 (CTRL_CR1) |
84 | #define PCLK_DIV_160 (CTRL_CR0 | CTRL_CR1) |
85 | #define PCLK_DIV_120 (CTRL_CR0 | CTRL_CR2) |
86 | #define PCLK_DIV_60 (CTRL_CR1 | CTRL_CR2) |
87 | #define BCLK_DIV_8 (CTRL_CR0 | CTRL_CR1 | CTRL_CR2) |
88 | #define CLK_MASK (CTRL_CR0 | CTRL_CR1 | CTRL_CR2) |
89 | |
90 | /** |
91 | * struct mchp_corei2c_dev - Microchip CoreI2C device private data |
92 | * |
93 | * @base: pointer to register struct |
94 | * @dev: device reference |
95 | * @i2c_clk: clock reference for i2c input clock |
96 | * @buf: pointer to msg buffer for easier use |
97 | * @msg_complete: xfer completion object |
98 | * @adapter: core i2c abstraction |
99 | * @msg_err: error code for completed message |
100 | * @bus_clk_rate: current i2c bus clock rate |
101 | * @isr_status: cached copy of local ISR status |
102 | * @msg_len: number of bytes transferred in msg |
103 | * @addr: address of the current slave |
104 | */ |
105 | struct mchp_corei2c_dev { |
106 | void __iomem *base; |
107 | struct device *dev; |
108 | struct clk *i2c_clk; |
109 | u8 *buf; |
110 | struct completion msg_complete; |
111 | struct i2c_adapter adapter; |
112 | int msg_err; |
113 | u32 bus_clk_rate; |
114 | u32 isr_status; |
115 | u16 msg_len; |
116 | u8 addr; |
117 | }; |
118 | |
119 | static void mchp_corei2c_core_disable(struct mchp_corei2c_dev *idev) |
120 | { |
121 | u8 ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
122 | |
123 | ctrl &= ~CTRL_ENS1; |
124 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
125 | } |
126 | |
127 | static void mchp_corei2c_core_enable(struct mchp_corei2c_dev *idev) |
128 | { |
129 | u8 ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
130 | |
131 | ctrl |= CTRL_ENS1; |
132 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
133 | } |
134 | |
135 | static void mchp_corei2c_reset(struct mchp_corei2c_dev *idev) |
136 | { |
137 | mchp_corei2c_core_disable(idev); |
138 | mchp_corei2c_core_enable(idev); |
139 | } |
140 | |
141 | static inline void mchp_corei2c_stop(struct mchp_corei2c_dev *idev) |
142 | { |
143 | u8 ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
144 | |
145 | ctrl |= CTRL_STO; |
146 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
147 | } |
148 | |
149 | static inline int mchp_corei2c_set_divisor(u32 rate, |
150 | struct mchp_corei2c_dev *idev) |
151 | { |
152 | u8 clkval, ctrl; |
153 | |
154 | if (rate >= 960) |
155 | clkval = PCLK_DIV_960; |
156 | else if (rate >= 256) |
157 | clkval = PCLK_DIV_256; |
158 | else if (rate >= 224) |
159 | clkval = PCLK_DIV_224; |
160 | else if (rate >= 192) |
161 | clkval = PCLK_DIV_192; |
162 | else if (rate >= 160) |
163 | clkval = PCLK_DIV_160; |
164 | else if (rate >= 120) |
165 | clkval = PCLK_DIV_120; |
166 | else if (rate >= 60) |
167 | clkval = PCLK_DIV_60; |
168 | else if (rate >= 8) |
169 | clkval = BCLK_DIV_8; |
170 | else |
171 | return -EINVAL; |
172 | |
173 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
174 | ctrl &= ~CLK_MASK; |
175 | ctrl |= clkval; |
176 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
177 | |
178 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
179 | if ((ctrl & CLK_MASK) != clkval) |
180 | return -EIO; |
181 | |
182 | return 0; |
183 | } |
184 | |
185 | static int mchp_corei2c_init(struct mchp_corei2c_dev *idev) |
186 | { |
187 | u32 clk_rate = clk_get_rate(clk: idev->i2c_clk); |
188 | u32 divisor = clk_rate / idev->bus_clk_rate; |
189 | int ret; |
190 | |
191 | ret = mchp_corei2c_set_divisor(rate: divisor, idev); |
192 | if (ret) |
193 | return ret; |
194 | |
195 | mchp_corei2c_reset(idev); |
196 | |
197 | return 0; |
198 | } |
199 | |
200 | static void mchp_corei2c_empty_rx(struct mchp_corei2c_dev *idev) |
201 | { |
202 | u8 ctrl; |
203 | |
204 | if (idev->msg_len > 0) { |
205 | *idev->buf++ = readb(addr: idev->base + CORE_I2C_DATA); |
206 | idev->msg_len--; |
207 | } |
208 | |
209 | if (idev->msg_len <= 1) { |
210 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
211 | ctrl &= ~CTRL_AA; |
212 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
213 | } |
214 | } |
215 | |
216 | static int mchp_corei2c_fill_tx(struct mchp_corei2c_dev *idev) |
217 | { |
218 | if (idev->msg_len > 0) |
219 | writeb(val: *idev->buf++, addr: idev->base + CORE_I2C_DATA); |
220 | idev->msg_len--; |
221 | |
222 | return 0; |
223 | } |
224 | |
225 | static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev) |
226 | { |
227 | u32 status = idev->isr_status; |
228 | u8 ctrl; |
229 | bool last_byte = false, finished = false; |
230 | |
231 | if (!idev->buf) |
232 | return IRQ_NONE; |
233 | |
234 | switch (status) { |
235 | case STATUS_M_START_SENT: |
236 | case STATUS_M_REPEATED_START_SENT: |
237 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
238 | ctrl &= ~CTRL_STA; |
239 | writeb(val: idev->addr, addr: idev->base + CORE_I2C_DATA); |
240 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
241 | if (idev->msg_len == 0) |
242 | finished = true; |
243 | break; |
244 | case STATUS_M_ARB_LOST: |
245 | idev->msg_err = -EAGAIN; |
246 | finished = true; |
247 | break; |
248 | case STATUS_M_SLAW_ACK: |
249 | case STATUS_M_TX_DATA_ACK: |
250 | if (idev->msg_len > 0) |
251 | mchp_corei2c_fill_tx(idev); |
252 | else |
253 | last_byte = true; |
254 | break; |
255 | case STATUS_M_TX_DATA_NACK: |
256 | case STATUS_M_SLAR_NACK: |
257 | case STATUS_M_SLAW_NACK: |
258 | idev->msg_err = -ENXIO; |
259 | last_byte = true; |
260 | break; |
261 | case STATUS_M_SLAR_ACK: |
262 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
263 | if (idev->msg_len == 1u) { |
264 | ctrl &= ~CTRL_AA; |
265 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
266 | } else { |
267 | ctrl |= CTRL_AA; |
268 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
269 | } |
270 | if (idev->msg_len < 1u) |
271 | last_byte = true; |
272 | break; |
273 | case STATUS_M_RX_DATA_ACKED: |
274 | mchp_corei2c_empty_rx(idev); |
275 | break; |
276 | case STATUS_M_RX_DATA_NACKED: |
277 | mchp_corei2c_empty_rx(idev); |
278 | if (idev->msg_len == 0) |
279 | last_byte = true; |
280 | break; |
281 | default: |
282 | break; |
283 | } |
284 | |
285 | /* On the last byte to be transmitted, send STOP */ |
286 | if (last_byte) |
287 | mchp_corei2c_stop(idev); |
288 | |
289 | if (last_byte || finished) |
290 | complete(&idev->msg_complete); |
291 | |
292 | return IRQ_HANDLED; |
293 | } |
294 | |
295 | static irqreturn_t mchp_corei2c_isr(int irq, void *_dev) |
296 | { |
297 | struct mchp_corei2c_dev *idev = _dev; |
298 | irqreturn_t ret = IRQ_NONE; |
299 | u8 ctrl; |
300 | |
301 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
302 | if (ctrl & CTRL_SI) { |
303 | idev->isr_status = readb(addr: idev->base + CORE_I2C_STATUS); |
304 | ret = mchp_corei2c_handle_isr(idev); |
305 | } |
306 | |
307 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
308 | ctrl &= ~CTRL_SI; |
309 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
310 | |
311 | return ret; |
312 | } |
313 | |
314 | static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev, |
315 | struct i2c_msg *msg) |
316 | { |
317 | u8 ctrl; |
318 | unsigned long time_left; |
319 | |
320 | idev->addr = i2c_8bit_addr_from_msg(msg); |
321 | idev->msg_len = msg->len; |
322 | idev->buf = msg->buf; |
323 | idev->msg_err = 0; |
324 | |
325 | reinit_completion(x: &idev->msg_complete); |
326 | |
327 | mchp_corei2c_core_enable(idev); |
328 | |
329 | ctrl = readb(addr: idev->base + CORE_I2C_CTRL); |
330 | ctrl |= CTRL_STA; |
331 | writeb(val: ctrl, addr: idev->base + CORE_I2C_CTRL); |
332 | |
333 | time_left = wait_for_completion_timeout(x: &idev->msg_complete, |
334 | timeout: idev->adapter.timeout); |
335 | if (!time_left) |
336 | return -ETIMEDOUT; |
337 | |
338 | return idev->msg_err; |
339 | } |
340 | |
341 | static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, |
342 | int num) |
343 | { |
344 | struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap); |
345 | int i, ret; |
346 | |
347 | for (i = 0; i < num; i++) { |
348 | ret = mchp_corei2c_xfer_msg(idev, msg: msgs++); |
349 | if (ret) |
350 | return ret; |
351 | } |
352 | |
353 | return num; |
354 | } |
355 | |
356 | static u32 mchp_corei2c_func(struct i2c_adapter *adap) |
357 | { |
358 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
359 | } |
360 | |
361 | static const struct i2c_algorithm mchp_corei2c_algo = { |
362 | .master_xfer = mchp_corei2c_xfer, |
363 | .functionality = mchp_corei2c_func, |
364 | }; |
365 | |
366 | static int mchp_corei2c_probe(struct platform_device *pdev) |
367 | { |
368 | struct mchp_corei2c_dev *idev; |
369 | struct resource *res; |
370 | int irq, ret; |
371 | |
372 | idev = devm_kzalloc(dev: &pdev->dev, size: sizeof(*idev), GFP_KERNEL); |
373 | if (!idev) |
374 | return -ENOMEM; |
375 | |
376 | idev->base = devm_platform_get_and_ioremap_resource(pdev, index: 0, res: &res); |
377 | if (IS_ERR(ptr: idev->base)) |
378 | return PTR_ERR(ptr: idev->base); |
379 | |
380 | irq = platform_get_irq(pdev, 0); |
381 | if (irq < 0) |
382 | return irq; |
383 | |
384 | idev->i2c_clk = devm_clk_get(dev: &pdev->dev, NULL); |
385 | if (IS_ERR(ptr: idev->i2c_clk)) |
386 | return dev_err_probe(dev: &pdev->dev, err: PTR_ERR(ptr: idev->i2c_clk), |
387 | fmt: "missing clock\n" ); |
388 | |
389 | idev->dev = &pdev->dev; |
390 | init_completion(x: &idev->msg_complete); |
391 | |
392 | ret = device_property_read_u32(dev: idev->dev, propname: "clock-frequency" , |
393 | val: &idev->bus_clk_rate); |
394 | if (ret || !idev->bus_clk_rate) { |
395 | dev_info(&pdev->dev, "default to 100kHz\n" ); |
396 | idev->bus_clk_rate = 100000; |
397 | } |
398 | |
399 | if (idev->bus_clk_rate > 400000) |
400 | return dev_err_probe(dev: &pdev->dev, err: -EINVAL, |
401 | fmt: "clock-frequency too high: %d\n" , |
402 | idev->bus_clk_rate); |
403 | |
404 | /* |
405 | * This driver supports both the hard peripherals & soft FPGA cores. |
406 | * The hard peripherals do not have shared IRQs, but we don't have |
407 | * control over what way the interrupts are wired for the soft cores. |
408 | */ |
409 | ret = devm_request_irq(dev: &pdev->dev, irq, handler: mchp_corei2c_isr, IRQF_SHARED, |
410 | devname: pdev->name, dev_id: idev); |
411 | if (ret) |
412 | return dev_err_probe(dev: &pdev->dev, err: ret, |
413 | fmt: "failed to claim irq %d\n" , irq); |
414 | |
415 | ret = clk_prepare_enable(clk: idev->i2c_clk); |
416 | if (ret) |
417 | return dev_err_probe(dev: &pdev->dev, err: ret, |
418 | fmt: "failed to enable clock\n" ); |
419 | |
420 | ret = mchp_corei2c_init(idev); |
421 | if (ret) { |
422 | clk_disable_unprepare(clk: idev->i2c_clk); |
423 | return dev_err_probe(dev: &pdev->dev, err: ret, fmt: "failed to program clock divider\n" ); |
424 | } |
425 | |
426 | i2c_set_adapdata(adap: &idev->adapter, data: idev); |
427 | snprintf(buf: idev->adapter.name, size: sizeof(idev->adapter.name), |
428 | fmt: "Microchip I2C hw bus at %08lx" , (unsigned long)res->start); |
429 | idev->adapter.owner = THIS_MODULE; |
430 | idev->adapter.algo = &mchp_corei2c_algo; |
431 | idev->adapter.dev.parent = &pdev->dev; |
432 | idev->adapter.dev.of_node = pdev->dev.of_node; |
433 | idev->adapter.timeout = HZ; |
434 | |
435 | platform_set_drvdata(pdev, data: idev); |
436 | |
437 | ret = i2c_add_adapter(adap: &idev->adapter); |
438 | if (ret) { |
439 | clk_disable_unprepare(clk: idev->i2c_clk); |
440 | return ret; |
441 | } |
442 | |
443 | dev_info(&pdev->dev, "registered CoreI2C bus driver\n" ); |
444 | |
445 | return 0; |
446 | } |
447 | |
448 | static void mchp_corei2c_remove(struct platform_device *pdev) |
449 | { |
450 | struct mchp_corei2c_dev *idev = platform_get_drvdata(pdev); |
451 | |
452 | clk_disable_unprepare(clk: idev->i2c_clk); |
453 | i2c_del_adapter(adap: &idev->adapter); |
454 | } |
455 | |
456 | static const struct of_device_id mchp_corei2c_of_match[] = { |
457 | { .compatible = "microchip,mpfs-i2c" }, |
458 | { .compatible = "microchip,corei2c-rtl-v7" }, |
459 | {}, |
460 | }; |
461 | MODULE_DEVICE_TABLE(of, mchp_corei2c_of_match); |
462 | |
463 | static struct platform_driver mchp_corei2c_driver = { |
464 | .probe = mchp_corei2c_probe, |
465 | .remove_new = mchp_corei2c_remove, |
466 | .driver = { |
467 | .name = "microchip-corei2c" , |
468 | .of_match_table = mchp_corei2c_of_match, |
469 | }, |
470 | }; |
471 | |
472 | module_platform_driver(mchp_corei2c_driver); |
473 | |
474 | MODULE_DESCRIPTION("Microchip CoreI2C bus driver" ); |
475 | MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>" ); |
476 | MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>" ); |
477 | MODULE_LICENSE("GPL" ); |
478 | |