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>
28 #include "i2c-designware-core.h"
32 "slave address not acknowledged (7bit mode)",
34 "first address byte not acknowledged (10bit mode)",
36 "second address byte not acknowledged (10bit mode)",
48 "trying to read when restart is disabled (10bit mode)",
58 "incorrect slave-transmitter mode configuration",
65 *val = readl_relaxed(dev->base + reg); in dw_reg_read()
74 writel_relaxed(val, dev->base + reg); in dw_reg_write()
83 *val = swab32(readl_relaxed(dev->base + reg)); in dw_reg_read_swab()
92 writel_relaxed(swab32(val), dev->base + reg); in dw_reg_write_swab()
101 *val = readw_relaxed(dev->base + reg) | in dw_reg_read_word()
102 (readw_relaxed(dev->base + reg + 2) << 16); in dw_reg_read_word()
111 writew_relaxed(val, dev->base + reg); in dw_reg_write_word()
112 writew_relaxed(val >> 16, dev->base + reg + 2); in dw_reg_write_word()
118 * i2c_dw_init_regmap() - Initialize registers map
121 * Autodetects needed register access mode and creates the regmap with
143 if (dev->map) in i2c_dw_init_regmap()
150 reg = readl(dev->base + DW_IC_COMP_TYPE); in i2c_dw_init_regmap()
160 dev_err(dev->dev, in i2c_dw_init_regmap()
162 return -ENODEV; in i2c_dw_init_regmap()
168 * basically we have MMIO-based regmap so non of the read/write methods in i2c_dw_init_regmap()
171 dev->map = devm_regmap_init(dev->dev, NULL, dev, &map_cfg); in i2c_dw_init_regmap()
172 if (IS_ERR(dev->map)) { in i2c_dw_init_regmap()
173 dev_err(dev->dev, "Failed to init the registers map\n"); in i2c_dw_init_regmap()
174 return PTR_ERR(dev->map); in i2c_dw_init_regmap()
189 struct i2c_timings *t = &dev->timings; in i2c_dw_validate_speed()
193 * Only standard mode at 100kHz, fast mode at 400kHz, in i2c_dw_validate_speed()
194 * fast mode plus at 1MHz and high speed mode at 3.4MHz are supported. in i2c_dw_validate_speed()
197 if (t->bus_freq_hz == supported_speeds[i]) in i2c_dw_validate_speed()
201 dev_err(dev->dev, in i2c_dw_validate_speed()
203 t->bus_freq_hz); in i2c_dw_validate_speed()
205 return -EINVAL; in i2c_dw_validate_speed()
243 if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) { in i2c_dw_acpi_params()
244 const union acpi_object *objs = obj->package.elements; in i2c_dw_acpi_params()
257 struct i2c_timings *t = &dev->timings; in i2c_dw_acpi_configure()
264 i2c_dw_acpi_params(device, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht); in i2c_dw_acpi_configure()
265 i2c_dw_acpi_params(device, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht); in i2c_dw_acpi_configure()
266 i2c_dw_acpi_params(device, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht); in i2c_dw_acpi_configure()
267 i2c_dw_acpi_params(device, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht); in i2c_dw_acpi_configure()
269 switch (t->bus_freq_hz) { in i2c_dw_acpi_configure()
271 dev->sda_hold_time = ss_ht; in i2c_dw_acpi_configure()
274 dev->sda_hold_time = fp_ht; in i2c_dw_acpi_configure()
277 dev->sda_hold_time = hs_ht; in i2c_dw_acpi_configure()
281 dev->sda_hold_time = fs_ht; in i2c_dw_acpi_configure()
315 u32 acpi_speed = i2c_dw_acpi_round_bus_speed(dev->dev); in i2c_dw_adjust_bus_speed()
316 struct i2c_timings *t = &dev->timings; in i2c_dw_adjust_bus_speed()
319 * Find bus speed from the "clock-frequency" device property, ACPI in i2c_dw_adjust_bus_speed()
320 * or by using fast mode if neither is set. in i2c_dw_adjust_bus_speed()
322 if (acpi_speed && t->bus_freq_hz) in i2c_dw_adjust_bus_speed()
323 t->bus_freq_hz = min(t->bus_freq_hz, acpi_speed); in i2c_dw_adjust_bus_speed()
324 else if (acpi_speed || t->bus_freq_hz) in i2c_dw_adjust_bus_speed()
325 t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed); in i2c_dw_adjust_bus_speed()
327 t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ; in i2c_dw_adjust_bus_speed()
334 * DesignWare I2C core doesn't seem to have solid strategy to meet in i2c_dw_scl_hcnt()
345 * configuration. The resulting I2C bus speed will be in i2c_dw_scl_hcnt()
350 return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset; in i2c_dw_scl_hcnt()
367 - 3 + offset; in i2c_dw_scl_hcnt()
377 * DW I2C core starts counting the SCL CNTs for the LOW period in i2c_dw_scl_lcnt()
383 return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset; in i2c_dw_scl_lcnt()
396 ret = regmap_read(dev->map, DW_IC_COMP_VERSION, ®); in i2c_dw_set_sda_hold()
401 if (!dev->sda_hold_time) { in i2c_dw_set_sda_hold()
403 ret = regmap_read(dev->map, DW_IC_SDA_HOLD, in i2c_dw_set_sda_hold()
404 &dev->sda_hold_time); in i2c_dw_set_sda_hold()
410 * Workaround for avoiding TX arbitration lost in case I2C in i2c_dw_set_sda_hold()
412 * SCL by enabling non-zero SDA RX hold. Specification says it in i2c_dw_set_sda_hold()
416 if (!(dev->sda_hold_time & DW_IC_SDA_HOLD_RX_MASK)) in i2c_dw_set_sda_hold()
417 dev->sda_hold_time |= 1 << DW_IC_SDA_HOLD_RX_SHIFT; in i2c_dw_set_sda_hold()
419 dev_dbg(dev->dev, "SDA Hold Time TX:RX = %d:%d\n", in i2c_dw_set_sda_hold()
420 dev->sda_hold_time & ~(u32)DW_IC_SDA_HOLD_RX_MASK, in i2c_dw_set_sda_hold()
421 dev->sda_hold_time >> DW_IC_SDA_HOLD_RX_SHIFT); in i2c_dw_set_sda_hold()
422 } else if (dev->set_sda_hold_time) { in i2c_dw_set_sda_hold()
423 dev->set_sda_hold_time(dev); in i2c_dw_set_sda_hold()
424 } else if (dev->sda_hold_time) { in i2c_dw_set_sda_hold()
425 dev_warn(dev->dev, in i2c_dw_set_sda_hold()
427 dev->sda_hold_time = 0; in i2c_dw_set_sda_hold()
447 regmap_read(dev->map, DW_IC_ENABLE_STATUS, &status); in __i2c_dw_disable()
452 * Wait 10 times the signaling period of the highest I2C in __i2c_dw_disable()
454 * 25us) as described in the DesignWare I2C databook. in __i2c_dw_disable()
457 } while (timeout--); in __i2c_dw_disable()
459 dev_warn(dev->dev, "timeout in disabling adapter\n"); in __i2c_dw_disable()
468 if (WARN_ON_ONCE(!dev->get_clk_rate_khz)) in i2c_dw_clk_rate()
470 return dev->get_clk_rate_khz(dev); in i2c_dw_clk_rate()
477 if (IS_ERR(dev->clk)) in i2c_dw_prepare_clk()
478 return PTR_ERR(dev->clk); in i2c_dw_prepare_clk()
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()
578 ret = regmap_read(dev->map, DW_IC_COMP_PARAM_1, ¶m); in i2c_dw_set_fifo_size()
584 if (!dev->tx_fifo_depth) { in i2c_dw_set_fifo_size()
585 dev->tx_fifo_depth = tx_fifo_depth; in i2c_dw_set_fifo_size()
586 dev->rx_fifo_depth = rx_fifo_depth; in i2c_dw_set_fifo_size()
588 dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth, in i2c_dw_set_fifo_size()
590 dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth, in i2c_dw_set_fifo_size()
601 return dev->functionality; in i2c_dw_func()
612 regmap_write(dev->map, DW_IC_INTR_MASK, 0); in i2c_dw_disable()
613 regmap_read(dev->map, DW_IC_CLR_INTR, &dummy); in i2c_dw_disable()
618 regmap_write(dev->map, DW_IC_INTR_MASK, 0); in i2c_dw_disable_int()
621 MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");