Lines Matching +full:i2c +full:- +full:fast +full:- +full:mode

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Synopsys DesignWare I2C adapter driver.
5 * Based on the TI DAVINCI I2C adapter driver.
18 #include <linux/i2c.h>
29 #include "i2c-designware-core.h"
33 "slave address not acknowledged (7bit mode)",
35 "first address byte not acknowledged (10bit mode)",
37 "second address byte not acknowledged (10bit mode)",
49 "trying to read when restart is disabled (10bit mode)",
59 "incorrect slave-transmitter mode configuration",
66 *val = readl_relaxed(dev->base + reg); in dw_reg_read()
75 writel_relaxed(val, dev->base + reg); in dw_reg_write()
84 *val = swab32(readl_relaxed(dev->base + reg)); in dw_reg_read_swab()
93 writel_relaxed(swab32(val), dev->base + reg); in dw_reg_write_swab()
102 *val = readw_relaxed(dev->base + reg) | in dw_reg_read_word()
103 (readw_relaxed(dev->base + reg + 2) << 16); in dw_reg_read_word()
112 writew_relaxed(val, dev->base + reg); in dw_reg_write_word()
113 writew_relaxed(val >> 16, dev->base + reg + 2); in dw_reg_write_word()
119 * i2c_dw_init_regmap() - Initialize registers map
122 * Autodetects needed register access mode and creates the regmap with
144 if (dev->map) in i2c_dw_init_regmap()
151 reg = readl(dev->base + DW_IC_COMP_TYPE); in i2c_dw_init_regmap()
154 if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU) in i2c_dw_init_regmap()
164 dev_err(dev->dev, in i2c_dw_init_regmap()
166 return -ENODEV; in i2c_dw_init_regmap()
172 * basically we have MMIO-based regmap so non of the read/write methods in i2c_dw_init_regmap()
175 dev->map = devm_regmap_init(dev->dev, NULL, dev, &map_cfg); in i2c_dw_init_regmap()
176 if (IS_ERR(dev->map)) { in i2c_dw_init_regmap()
177 dev_err(dev->dev, "Failed to init the registers map\n"); in i2c_dw_init_regmap()
178 return PTR_ERR(dev->map); in i2c_dw_init_regmap()
193 struct i2c_timings *t = &dev->timings; in i2c_dw_validate_speed()
197 * Only standard mode at 100kHz, fast mode at 400kHz, in i2c_dw_validate_speed()
198 * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported. in i2c_dw_validate_speed()
201 if (t->bus_freq_hz == supported_speeds[i]) in i2c_dw_validate_speed()
205 dev_err(dev->dev, in i2c_dw_validate_speed()
207 t->bus_freq_hz); in i2c_dw_validate_speed()
209 return -EINVAL; in i2c_dw_validate_speed()
247 if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) { in i2c_dw_acpi_params()
248 const union acpi_object *objs = obj->package.elements; in i2c_dw_acpi_params()
261 struct i2c_timings *t = &dev->timings; in i2c_dw_acpi_configure()
268 i2c_dw_acpi_params(device, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht); in i2c_dw_acpi_configure()
269 i2c_dw_acpi_params(device, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht); in i2c_dw_acpi_configure()
270 i2c_dw_acpi_params(device, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht); in i2c_dw_acpi_configure()
271 i2c_dw_acpi_params(device, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht); in i2c_dw_acpi_configure()
273 switch (t->bus_freq_hz) { in i2c_dw_acpi_configure()
275 dev->sda_hold_time = ss_ht; in i2c_dw_acpi_configure()
278 dev->sda_hold_time = fp_ht; in i2c_dw_acpi_configure()
281 dev->sda_hold_time = hs_ht; in i2c_dw_acpi_configure()
285 dev->sda_hold_time = fs_ht; in i2c_dw_acpi_configure()
319 u32 acpi_speed = i2c_dw_acpi_round_bus_speed(dev->dev); in i2c_dw_adjust_bus_speed()
320 struct i2c_timings *t = &dev->timings; in i2c_dw_adjust_bus_speed()
323 * Find bus speed from the "clock-frequency" device property, ACPI in i2c_dw_adjust_bus_speed()
324 * or by using fast mode if neither is set. in i2c_dw_adjust_bus_speed()
326 if (acpi_speed && t->bus_freq_hz) in i2c_dw_adjust_bus_speed()
327 t->bus_freq_hz = min(t->bus_freq_hz, acpi_speed); in i2c_dw_adjust_bus_speed()
328 else if (acpi_speed || t->bus_freq_hz) in i2c_dw_adjust_bus_speed()
329 t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed); in i2c_dw_adjust_bus_speed()
331 t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ; in i2c_dw_adjust_bus_speed()
338 * DesignWare I2C core doesn't seem to have solid strategy to meet in i2c_dw_scl_hcnt()
349 * configuration. The resulting I2C bus speed will be in i2c_dw_scl_hcnt()
354 return DIV_ROUND_CLOSEST(ic_clk * tSYMBOL, MICRO) - 8 + offset; in i2c_dw_scl_hcnt()
370 return DIV_ROUND_CLOSEST(ic_clk * (tSYMBOL + tf), MICRO) - 3 + offset; in i2c_dw_scl_hcnt()
380 * DW I2C core starts counting the SCL CNTs for the LOW period in i2c_dw_scl_lcnt()
386 return DIV_ROUND_CLOSEST(ic_clk * (tLOW + tf), MICRO) - 1 + offset; in i2c_dw_scl_lcnt()
399 ret = regmap_read(dev->map, DW_IC_COMP_VERSION, &reg); in i2c_dw_set_sda_hold()
404 if (!dev->sda_hold_time) { in i2c_dw_set_sda_hold()
406 ret = regmap_read(dev->map, DW_IC_SDA_HOLD, in i2c_dw_set_sda_hold()
407 &dev->sda_hold_time); in i2c_dw_set_sda_hold()
413 * Workaround for avoiding TX arbitration lost in case I2C in i2c_dw_set_sda_hold()
415 * SCL by enabling non-zero SDA RX hold. Specification says it in i2c_dw_set_sda_hold()
419 if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK)) in i2c_dw_set_sda_hold()
420 dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT; in i2c_dw_set_sda_hold()
422 dev_dbg(dev->dev, "SDA Hold Time TX:RX = %d:%d\n", in i2c_dw_set_sda_hold()
423 dev->sda_hold_time & ~(u32)DW_IC_SDA_HOLD_RX_MASK, in i2c_dw_set_sda_hold()
424 dev->sda_hold_time >> DW_IC_SDA_HOLD_RX_SHIFT); in i2c_dw_set_sda_hold()
425 } else if (dev->set_sda_hold_time) { in i2c_dw_set_sda_hold()
426 dev->set_sda_hold_time(dev); in i2c_dw_set_sda_hold()
427 } else if (dev->sda_hold_time) { in i2c_dw_set_sda_hold()
428 dev_warn(dev->dev, in i2c_dw_set_sda_hold()
430 dev->sda_hold_time = 0; in i2c_dw_set_sda_hold()
450 regmap_read(dev->map, DW_IC_ENABLE_STATUS, &status); in __i2c_dw_disable()
455 * Wait 10 times the signaling period of the highest I2C in __i2c_dw_disable()
457 * 25us) as described in the DesignWare I2C databook. in __i2c_dw_disable()
460 } while (timeout--); in __i2c_dw_disable()
462 dev_warn(dev->dev, "timeout in disabling adapter\n"); in __i2c_dw_disable()
471 if (WARN_ON_ONCE(!dev->get_clk_rate_khz)) in i2c_dw_clk_rate()
473 return dev->get_clk_rate_khz(dev); in i2c_dw_clk_rate()
482 ret = clk_prepare_enable(dev->pclk); in i2c_dw_prepare_clk()
486 ret = clk_prepare_enable(dev->clk); in i2c_dw_prepare_clk()
488 clk_disable_unprepare(dev->pclk); in i2c_dw_prepare_clk()
493 clk_disable_unprepare(dev->clk); in i2c_dw_prepare_clk()
494 clk_disable_unprepare(dev->pclk); in i2c_dw_prepare_clk()
504 if (!dev->acquire_lock) in i2c_dw_acquire_lock()
507 ret = dev->acquire_lock(); in i2c_dw_acquire_lock()
511 dev_err(dev->dev, "couldn't acquire bus ownership\n"); in i2c_dw_acquire_lock()
518 if (dev->release_lock) in i2c_dw_release_lock()
519 dev->release_lock(); in i2c_dw_release_lock()
530 ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status, in i2c_dw_wait_bus_not_busy()
534 dev_warn(dev->dev, "timeout waiting for bus ready\n"); in i2c_dw_wait_bus_not_busy()
536 i2c_recover_bus(&dev->adapter); in i2c_dw_wait_bus_not_busy()
538 regmap_read(dev->map, DW_IC_STATUS, &status); in i2c_dw_wait_bus_not_busy()
548 unsigned long abort_source = dev->abort_source; in i2c_dw_handle_tx_abort()
553 dev_dbg(dev->dev, in i2c_dw_handle_tx_abort()
555 return -EREMOTEIO; in i2c_dw_handle_tx_abort()
559 dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); in i2c_dw_handle_tx_abort()
562 return -EAGAIN; in i2c_dw_handle_tx_abort()
564 return -EINVAL; /* wrong msgs[] data */ in i2c_dw_handle_tx_abort()
566 return -EIO; in i2c_dw_handle_tx_abort()
582 ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, &param); in i2c_dw_set_fifo_size()
589 if (!dev->tx_fifo_depth) { in i2c_dw_set_fifo_size()
590 dev->tx_fifo_depth = tx_fifo_depth; in i2c_dw_set_fifo_size()
591 dev->rx_fifo_depth = rx_fifo_depth; in i2c_dw_set_fifo_size()
593 dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth, in i2c_dw_set_fifo_size()
595 dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth, in i2c_dw_set_fifo_size()
606 return dev->functionality; in i2c_dw_func()
622 regmap_write(dev->map, DW_IC_INTR_MASK, 0); in i2c_dw_disable()
623 regmap_read(dev->map, DW_IC_CLR_INTR, &dummy); in i2c_dw_disable()
630 regmap_write(dev->map, DW_IC_INTR_MASK, 0); in i2c_dw_disable_int()
633 MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");