Lines Matching +full:mpfs +full:- +full:i2c
1 // SPDX-License-Identifier: GPL-2.0
3 * Microchip CoreI2C I2C controller driver
5 * Copyright (c) 2018-2022 Microchip Corporation. All rights reserved.
13 #include <linux/i2c.h>
91 * struct mchp_corei2c_dev - Microchip CoreI2C device private data
95 * @i2c_clk: clock reference for i2c input clock
99 * @adapter: core i2c abstraction
101 * @bus_clk_rate: current i2c bus clock rate
129 u8 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_core_disable()
132 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_core_disable()
137 u8 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_core_enable()
140 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_core_enable()
151 u8 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_stop()
154 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_stop()
179 return -EINVAL; in mchp_corei2c_set_divisor()
181 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_set_divisor()
184 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_set_divisor()
186 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_set_divisor()
188 return -EIO; in mchp_corei2c_set_divisor()
195 u32 clk_rate = clk_get_rate(idev->i2c_clk); in mchp_corei2c_init()
196 u32 divisor = clk_rate / idev->bus_clk_rate; in mchp_corei2c_init()
212 if (idev->msg_len > 0) { in mchp_corei2c_empty_rx()
213 *idev->buf++ = readb(idev->base + CORE_I2C_DATA); in mchp_corei2c_empty_rx()
214 idev->msg_len--; in mchp_corei2c_empty_rx()
217 if (idev->msg_len <= 1) { in mchp_corei2c_empty_rx()
218 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_empty_rx()
220 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_empty_rx()
226 if (idev->msg_len > 0) in mchp_corei2c_fill_tx()
227 writeb(*idev->buf++, idev->base + CORE_I2C_DATA); in mchp_corei2c_fill_tx()
228 idev->msg_len--; in mchp_corei2c_fill_tx()
238 if (idev->current_num >= idev->total_num) { in mchp_corei2c_next_msg()
239 complete(&idev->msg_complete); in mchp_corei2c_next_msg()
248 if (idev->msg_err) { in mchp_corei2c_next_msg()
249 complete(&idev->msg_complete); in mchp_corei2c_next_msg()
253 this_msg = idev->msg_queue++; in mchp_corei2c_next_msg()
255 if (idev->current_num < (idev->total_num - 1)) { in mchp_corei2c_next_msg()
256 struct i2c_msg *next_msg = idev->msg_queue; in mchp_corei2c_next_msg()
258 idev->restart_needed = next_msg->flags & I2C_M_RD; in mchp_corei2c_next_msg()
260 idev->restart_needed = false; in mchp_corei2c_next_msg()
263 idev->addr = i2c_8bit_addr_from_msg(this_msg); in mchp_corei2c_next_msg()
264 idev->msg_len = this_msg->len; in mchp_corei2c_next_msg()
265 idev->buf = this_msg->buf; in mchp_corei2c_next_msg()
267 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_next_msg()
269 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_next_msg()
271 idev->current_num++; in mchp_corei2c_next_msg()
276 u32 status = idev->isr_status; in mchp_corei2c_handle_isr()
280 if (!idev->buf) in mchp_corei2c_handle_isr()
286 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_handle_isr()
288 writeb(idev->addr, idev->base + CORE_I2C_DATA); in mchp_corei2c_handle_isr()
289 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_handle_isr()
292 idev->msg_err = -EAGAIN; in mchp_corei2c_handle_isr()
297 if (idev->msg_len > 0) { in mchp_corei2c_handle_isr()
300 if (idev->restart_needed) in mchp_corei2c_handle_isr()
309 idev->msg_err = -ENXIO; in mchp_corei2c_handle_isr()
313 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_handle_isr()
314 if (idev->msg_len == 1u) { in mchp_corei2c_handle_isr()
316 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_handle_isr()
319 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_handle_isr()
321 if (idev->msg_len < 1u) in mchp_corei2c_handle_isr()
329 if (idev->msg_len == 0) in mchp_corei2c_handle_isr()
352 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_isr()
354 idev->isr_status = readb(idev->base + CORE_I2C_STATUS); in mchp_corei2c_isr()
358 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_isr()
360 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_isr()
379 idev->restart_needed = false; in mchp_corei2c_xfer()
380 idev->msg_queue = msgs; in mchp_corei2c_xfer()
381 idev->total_num = num; in mchp_corei2c_xfer()
382 idev->current_num = 0; in mchp_corei2c_xfer()
388 idev->addr = i2c_8bit_addr_from_msg(this_msg); in mchp_corei2c_xfer()
389 idev->msg_len = this_msg->len; in mchp_corei2c_xfer()
390 idev->buf = this_msg->buf; in mchp_corei2c_xfer()
391 idev->msg_err = 0; in mchp_corei2c_xfer()
393 if (idev->total_num > 1) { in mchp_corei2c_xfer()
396 idev->restart_needed = next_msg->flags & I2C_M_RD; in mchp_corei2c_xfer()
399 idev->current_num++; in mchp_corei2c_xfer()
400 idev->msg_queue++; in mchp_corei2c_xfer()
402 reinit_completion(&idev->msg_complete); in mchp_corei2c_xfer()
407 ctrl = readb(idev->base + CORE_I2C_CTRL); in mchp_corei2c_xfer()
409 writeb(ctrl, idev->base + CORE_I2C_CTRL); in mchp_corei2c_xfer()
411 time_left = wait_for_completion_timeout(&idev->msg_complete, in mchp_corei2c_xfer()
412 idev->adapter.timeout); in mchp_corei2c_xfer()
414 return -ETIMEDOUT; in mchp_corei2c_xfer()
416 if (idev->msg_err) in mchp_corei2c_xfer()
417 return idev->msg_err; in mchp_corei2c_xfer()
438 idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); in mchp_corei2c_probe()
440 return -ENOMEM; in mchp_corei2c_probe()
442 idev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in mchp_corei2c_probe()
443 if (IS_ERR(idev->base)) in mchp_corei2c_probe()
444 return PTR_ERR(idev->base); in mchp_corei2c_probe()
450 idev->i2c_clk = devm_clk_get(&pdev->dev, NULL); in mchp_corei2c_probe()
451 if (IS_ERR(idev->i2c_clk)) in mchp_corei2c_probe()
452 return dev_err_probe(&pdev->dev, PTR_ERR(idev->i2c_clk), in mchp_corei2c_probe()
455 idev->dev = &pdev->dev; in mchp_corei2c_probe()
456 init_completion(&idev->msg_complete); in mchp_corei2c_probe()
458 ret = device_property_read_u32(idev->dev, "clock-frequency", in mchp_corei2c_probe()
459 &idev->bus_clk_rate); in mchp_corei2c_probe()
460 if (ret || !idev->bus_clk_rate) { in mchp_corei2c_probe()
461 dev_info(&pdev->dev, "default to 100kHz\n"); in mchp_corei2c_probe()
462 idev->bus_clk_rate = 100000; in mchp_corei2c_probe()
465 if (idev->bus_clk_rate > 400000) in mchp_corei2c_probe()
466 return dev_err_probe(&pdev->dev, -EINVAL, in mchp_corei2c_probe()
467 "clock-frequency too high: %d\n", in mchp_corei2c_probe()
468 idev->bus_clk_rate); in mchp_corei2c_probe()
475 ret = devm_request_irq(&pdev->dev, irq, mchp_corei2c_isr, IRQF_SHARED, in mchp_corei2c_probe()
476 pdev->name, idev); in mchp_corei2c_probe()
478 return dev_err_probe(&pdev->dev, ret, in mchp_corei2c_probe()
481 ret = clk_prepare_enable(idev->i2c_clk); in mchp_corei2c_probe()
483 return dev_err_probe(&pdev->dev, ret, in mchp_corei2c_probe()
488 clk_disable_unprepare(idev->i2c_clk); in mchp_corei2c_probe()
489 return dev_err_probe(&pdev->dev, ret, "failed to program clock divider\n"); in mchp_corei2c_probe()
492 i2c_set_adapdata(&idev->adapter, idev); in mchp_corei2c_probe()
493 snprintf(idev->adapter.name, sizeof(idev->adapter.name), in mchp_corei2c_probe()
494 "Microchip I2C hw bus at %08lx", (unsigned long)res->start); in mchp_corei2c_probe()
495 idev->adapter.owner = THIS_MODULE; in mchp_corei2c_probe()
496 idev->adapter.algo = &mchp_corei2c_algo; in mchp_corei2c_probe()
497 idev->adapter.dev.parent = &pdev->dev; in mchp_corei2c_probe()
498 idev->adapter.dev.of_node = pdev->dev.of_node; in mchp_corei2c_probe()
499 idev->adapter.timeout = HZ; in mchp_corei2c_probe()
503 ret = i2c_add_adapter(&idev->adapter); in mchp_corei2c_probe()
505 clk_disable_unprepare(idev->i2c_clk); in mchp_corei2c_probe()
509 dev_info(&pdev->dev, "registered CoreI2C bus driver\n"); in mchp_corei2c_probe()
518 clk_disable_unprepare(idev->i2c_clk); in mchp_corei2c_remove()
519 i2c_del_adapter(&idev->adapter); in mchp_corei2c_remove()
523 { .compatible = "microchip,mpfs-i2c" },
524 { .compatible = "microchip,corei2c-rtl-v7" },
533 .name = "microchip-corei2c",