Merge tag 'i2c-host-6.20' of git://git.kernel.org/pub/scm/linux/kernel/git/andi.shyti/linux into i2c/for-mergewindow

i2c-host for v6.20

- amd-mp2, designware, mlxbf, rtl9300, spacemit, tegra: cleanups
- designware: use a dedicated algorithm for AMD Navi
- designware: replace magic numbers with named constants
- designware: replace min_t() with min() to avoid u8 truncation
- designware: refactor core to enable mode switching
- imx-lpi2c: add runtime PM support for IRQ and clock handling
- lan9691-i2c: add new driver
- rtl9300: use OF helpers directly and avoid fwnode handling
- spacemit: add bus reset support
- units: add HZ_PER_GHZ and use it in several i2c drivers
This commit is contained in:
Wolfram Sang
2026-02-03 21:53:38 +01:00
22 changed files with 425 additions and 454 deletions

View File

@@ -26,6 +26,7 @@ properties:
- microchip,sam9x60-i2c
- items:
- enum:
- microchip,lan9691-i2c
- microchip,sama7d65-i2c
- microchip,sama7g5-i2c
- microchip,sam9x7-i2c

View File

@@ -41,6 +41,9 @@ properties:
default: 400000
maximum: 3300000
resets:
maxItems: 1
required:
- compatible
- reg

View File

@@ -569,24 +569,17 @@ config I2C_DESIGNWARE_CORE
help
This option enables support for the Synopsys DesignWare I2C adapter.
This driver includes support for the I2C host on the Synopsys
Designware I2C adapter.
Designware I2C adapter, and the I2C slave when enabled (select
I2C_SLAVE).
To compile the driver as a module, choose M here: the module will be
called i2c-designware-core.
if I2C_DESIGNWARE_CORE
config I2C_DESIGNWARE_SLAVE
bool "Synopsys DesignWare Slave"
select I2C_SLAVE
help
If you say yes to this option, support will be included for the
Synopsys DesignWare I2C slave adapter.
config I2C_DESIGNWARE_PLATFORM
tristate "Synopsys DesignWare Platform driver"
depends on (ACPI && COMMON_CLK) || !ACPI
select MFD_SYSCON if MIPS_BAIKAL_T1
default I2C_DESIGNWARE_CORE
help
If you say yes to this option, support will be included for the

View File

@@ -53,7 +53,7 @@ obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o
i2c-designware-core-y := i2c-designware-common.o
i2c-designware-core-y += i2c-designware-master.o
i2c-designware-core-$(CONFIG_I2C_DESIGNWARE_SLAVE) += i2c-designware-slave.o
i2c-designware-core-$(CONFIG_I2C_SLAVE) += i2c-designware-slave.o
obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o
i2c-designware-platform-y := i2c-designware-platdrv.o
i2c-designware-platform-$(CONFIG_I2C_DESIGNWARE_AMDPSP) += i2c-designware-amdpsp.o

View File

@@ -456,18 +456,20 @@ module_pci_driver(amd_mp2_pci_driver);
struct amd_mp2_dev *amd_mp2_find_device(void)
{
struct amd_mp2_dev *privdata;
struct device *dev;
struct pci_dev *pci_dev;
struct amd_mp2_dev *mp2_dev;
dev = driver_find_next_device(&amd_mp2_pci_driver.driver, NULL);
if (!dev)
return NULL;
pci_dev = to_pci_dev(dev);
mp2_dev = (struct amd_mp2_dev *)pci_get_drvdata(pci_dev);
privdata = pci_get_drvdata(pci_dev);
put_device(dev);
return mp2_dev;
return privdata;
}
EXPORT_SYMBOL_GPL(amd_mp2_find_device);

View File

@@ -163,8 +163,8 @@ static int amd_isp_dw_i2c_plat_runtime_resume(struct device *dev)
if (!i_dev->shared_with_punit)
i2c_dw_prepare_clk(i_dev, true);
if (i_dev->init)
i_dev->init(i_dev);
i2c_dw_init(i_dev);
return 0;
}

View File

@@ -12,6 +12,7 @@
#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW_COMMON"
#include <linux/acpi.h>
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
@@ -34,6 +35,10 @@
#include "i2c-designware-core.h"
#define DW_IC_DEFAULT_BUS_CAPACITANCE_pF 100
#define DW_IC_ABORT_TIMEOUT_US 10
#define DW_IC_BUSY_POLL_TIMEOUT_US (1 * USEC_PER_MSEC)
static const char *const abort_sources[] = {
[ABRT_7B_ADDR_NOACK] =
"slave address not acknowledged (7bit mode)",
@@ -106,7 +111,7 @@ static int dw_reg_read_word(void *context, unsigned int reg, unsigned int *val)
struct dw_i2c_dev *dev = context;
*val = readw(dev->base + reg) |
(readw(dev->base + reg + 2) << 16);
(readw(dev->base + reg + DW_IC_REG_STEP_BYTES) << DW_IC_REG_WORD_SHIFT);
return 0;
}
@@ -116,7 +121,7 @@ static int dw_reg_write_word(void *context, unsigned int reg, unsigned int val)
struct dw_i2c_dev *dev = context;
writew(val, dev->base + reg);
writew(val >> 16, dev->base + reg + 2);
writew(val >> DW_IC_REG_WORD_SHIFT, dev->base + reg + DW_IC_REG_STEP_BYTES);
return 0;
}
@@ -131,7 +136,7 @@ static int dw_reg_write_word(void *context, unsigned int reg, unsigned int val)
*
* Return: 0 on success, or negative errno otherwise.
*/
int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
static int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
{
struct regmap_config map_cfg = {
.reg_bits = 32,
@@ -165,7 +170,7 @@ int i2c_dw_init_regmap(struct dw_i2c_dev *dev)
if (reg == swab32(DW_IC_COMP_TYPE_VALUE)) {
map_cfg.reg_read = dw_reg_read_swab;
map_cfg.reg_write = dw_reg_write_swab;
} else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
} else if (reg == lower_16_bits(DW_IC_COMP_TYPE_VALUE)) {
map_cfg.reg_read = dw_reg_read_word;
map_cfg.reg_write = dw_reg_write_word;
} else if (reg != DW_IC_COMP_TYPE_VALUE) {
@@ -238,14 +243,10 @@ static void i2c_dw_of_configure(struct device *device)
struct platform_device *pdev = to_platform_device(device);
struct dw_i2c_dev *dev = dev_get_drvdata(device);
switch (dev->flags & MODEL_MASK) {
case MODEL_MSCC_OCELOT:
if (device_is_compatible(dev->dev, "mscc,ocelot-i2c")) {
dev->ext = devm_platform_ioremap_resource(pdev, 1);
if (!IS_ERR(dev->ext))
dev->set_sda_hold_time = mscc_twi_set_sda_hold_time;
break;
default:
break;
}
}
@@ -358,6 +359,109 @@ static inline u32 i2c_dw_acpi_round_bus_speed(struct device *device) { return 0;
#endif /* CONFIG_ACPI */
static void i2c_dw_configure_mode(struct dw_i2c_dev *dev, int mode)
{
switch (mode) {
case DW_IC_MASTER:
regmap_write(dev->map, DW_IC_TX_TL, dev->tx_fifo_depth / 2);
regmap_write(dev->map, DW_IC_RX_TL, 0);
regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
break;
case DW_IC_SLAVE:
dev->status = 0;
regmap_write(dev->map, DW_IC_TX_TL, 0);
regmap_write(dev->map, DW_IC_RX_TL, 0);
regmap_write(dev->map, DW_IC_CON, dev->slave_cfg);
regmap_write(dev->map, DW_IC_SAR, dev->slave->addr);
regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_SLAVE_MASK);
__i2c_dw_enable(dev);
break;
default:
WARN(1, "Invalid mode %d\n", mode);
return;
}
}
static void i2c_dw_write_timings(struct dw_i2c_dev *dev)
{
/* Write standard speed timing parameters */
regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);
/* Write fast mode/fast mode plus timing parameters */
regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt);
regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt);
/* Write high speed timing parameters */
regmap_write(dev->map, DW_IC_HS_SCL_HCNT, dev->hs_hcnt);
regmap_write(dev->map, DW_IC_HS_SCL_LCNT, dev->hs_lcnt);
}
/**
* i2c_dw_set_mode() - Select the controller mode of operation - master or slave
* @dev: device private data
* @mode: I2C mode of operation
*
* Configures the controller to operate in @mode. This function needs to be
* called when ever a mode swap is required.
*
* Setting the slave mode does not have an effect before a slave device is
* registered. So before the slave device is registered, the controller is kept
* in master mode regardless of @mode.
*
* The controller must be disabled before this function is called.
*/
void i2c_dw_set_mode(struct dw_i2c_dev *dev, int mode)
{
if (mode == DW_IC_SLAVE && !dev->slave)
mode = DW_IC_MASTER;
if (dev->mode == mode)
return;
i2c_dw_configure_mode(dev, mode);
dev->mode = mode;
}
/**
* i2c_dw_init() - Initialize the DesignWare I2C hardware
* @dev: device private data
*
* This functions configures and enables the DesigWare I2C hardware.
*
* Return: 0 on success, or negative errno otherwise.
*/
int i2c_dw_init(struct dw_i2c_dev *dev)
{
int ret;
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
/* Disable the adapter */
__i2c_dw_disable(dev);
/*
* Mask SMBus interrupts to block storms from broken
* firmware that leaves IC_SMBUS=1; the handler never
* services them.
*/
regmap_write(dev->map, DW_IC_SMBUS_INTR_MASK, 0);
i2c_dw_write_timings(dev);
/* Write SDA hold time if supported */
if (dev->sda_hold_time)
regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
i2c_dw_configure_mode(dev, dev->mode);
i2c_dw_release_lock(dev);
return 0;
}
EXPORT_SYMBOL_GPL(i2c_dw_init);
static void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev)
{
u32 acpi_speed = i2c_dw_acpi_round_bus_speed(dev->dev);
@@ -384,7 +488,7 @@ int i2c_dw_fw_parse_and_configure(struct dw_i2c_dev *dev)
i2c_parse_fw_timings(device, t, false);
if (device_property_read_u32(device, "snps,bus-capacitance-pf", &dev->bus_capacitance_pF))
dev->bus_capacitance_pF = 100;
dev->bus_capacitance_pF = DW_IC_DEFAULT_BUS_CAPACITANCE_pF;
dev->clk_freq_optimized = device_property_read_bool(device, "snps,clk-freq-optimized");
@@ -457,7 +561,7 @@ u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
return DIV_ROUND_CLOSEST_ULL((u64)ic_clk * (tLOW + tf), MICRO) - 1 + offset;
}
int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
static int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev)
{
unsigned int reg;
int ret;
@@ -539,8 +643,9 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);
ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable,
!(enable & DW_IC_ENABLE_ABORT), 10,
100);
!(enable & DW_IC_ENABLE_ABORT),
DW_IC_ABORT_TIMEOUT_US,
10 * DW_IC_ABORT_TIMEOUT_US);
if (ret)
dev_err(dev->dev, "timeout while trying to abort current transfer\n");
}
@@ -552,7 +657,7 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
* in that case this test reads zero and exits the loop.
*/
regmap_read(dev->map, DW_IC_ENABLE_STATUS, &status);
if ((status & 1) == 0)
if (!(status & 1))
return;
/*
@@ -635,7 +740,8 @@ int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev)
ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
!(status & DW_IC_STATUS_ACTIVITY),
1100, 20000);
DW_IC_BUSY_POLL_TIMEOUT_US,
20 * DW_IC_BUSY_POLL_TIMEOUT_US);
if (ret) {
dev_warn(dev->dev, "timeout waiting for bus ready\n");
@@ -672,7 +778,7 @@ int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
return -EIO;
}
int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
static int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
{
u32 tx_fifo_depth, rx_fifo_depth;
unsigned int param;
@@ -699,12 +805,12 @@ int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev)
if (ret)
return ret;
tx_fifo_depth = ((param >> 16) & 0xff) + 1;
rx_fifo_depth = ((param >> 8) & 0xff) + 1;
tx_fifo_depth = FIELD_GET(DW_IC_FIFO_TX_FIELD, param) + 1;
rx_fifo_depth = FIELD_GET(DW_IC_FIFO_RX_FIELD, param) + 1;
if (!dev->tx_fifo_depth) {
dev->tx_fifo_depth = tx_fifo_depth;
dev->rx_fifo_depth = rx_fifo_depth;
} else if (tx_fifo_depth >= 2) {
} else if (tx_fifo_depth >= DW_IC_FIFO_MIN_DEPTH) {
dev->tx_fifo_depth = min_t(u32, dev->tx_fifo_depth,
tx_fifo_depth);
dev->rx_fifo_depth = min_t(u32, dev->rx_fifo_depth,
@@ -741,19 +847,103 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
}
EXPORT_SYMBOL_GPL(i2c_dw_disable);
static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
{
struct dw_i2c_dev *dev = dev_id;
if (dev->mode == DW_IC_SLAVE)
return i2c_dw_isr_slave(dev);
return i2c_dw_isr_master(dev);
}
static const struct i2c_algorithm i2c_dw_algo = {
.xfer = i2c_dw_xfer,
.functionality = i2c_dw_func,
#if IS_ENABLED(CONFIG_I2C_SLAVE)
.reg_slave = i2c_dw_reg_slave,
.unreg_slave = i2c_dw_unreg_slave,
#endif
};
static const struct i2c_adapter_quirks i2c_dw_quirks = {
.flags = I2C_AQ_NO_ZERO_LEN,
};
int i2c_dw_probe(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
unsigned long irq_flags;
int ret;
device_set_node(&dev->adapter.dev, dev_fwnode(dev->dev));
switch (dev->mode) {
case DW_IC_SLAVE:
return i2c_dw_probe_slave(dev);
case DW_IC_MASTER:
return i2c_dw_probe_master(dev);
default:
dev_err(dev->dev, "Wrong operation mode: %d\n", dev->mode);
return -EINVAL;
ret = i2c_dw_init_regmap(dev);
if (ret)
return ret;
ret = i2c_dw_set_sda_hold(dev);
if (ret)
return ret;
ret = i2c_dw_set_fifo_size(dev);
if (ret)
return ret;
ret = i2c_dw_probe_master(dev);
if (ret)
return ret;
ret = i2c_dw_init(dev);
if (ret)
return ret;
if (!adap->name[0])
strscpy(adap->name, "Synopsys DesignWare I2C adapter");
adap->retries = 3;
adap->algo = &i2c_dw_algo;
adap->quirks = &i2c_dw_quirks;
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);
/*
* REVISIT: The mode check may not be necessary.
* For now keeping the flags as they were originally.
*/
if (dev->mode == DW_IC_SLAVE)
irq_flags = IRQF_SHARED;
else if (dev->flags & ACCESS_NO_IRQ_SUSPEND)
irq_flags = IRQF_NO_SUSPEND;
else
irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND;
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
__i2c_dw_write_intr_mask(dev, 0);
i2c_dw_release_lock(dev);
if (!(dev->flags & ACCESS_POLLING)) {
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr,
irq_flags, dev_name(dev->dev), dev);
if (ret)
return ret;
}
/*
* Increment PM usage count during adapter registration in order to
* avoid possible spurious runtime suspend when adapter device is
* registered to the device core and immediate resume in case bus has
* registered I2C slaves that do I2C transfers in their probe.
*/
ACQUIRE(pm_runtime_noresume, pm)(dev->dev);
ret = ACQUIRE_ERR(pm_runtime_noresume, &pm);
if (ret)
return ret;
return i2c_add_numbered_adapter(adap);
}
EXPORT_SYMBOL_GPL(i2c_dw_probe);
@@ -797,7 +987,7 @@ static int i2c_dw_runtime_resume(struct device *device)
if (!dev->shared_with_punit)
i2c_dw_prepare_clk(dev, true);
dev->init(dev);
i2c_dw_init(dev);
return 0;
}

View File

@@ -13,6 +13,7 @@
#include <linux/completion.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/irqreturn.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/types.h>
@@ -41,6 +42,19 @@
#define DW_IC_DATA_CMD_DAT GENMASK(7, 0)
#define DW_IC_DATA_CMD_FIRST_DATA_BYTE BIT(11)
/*
* Register access parameters
*/
#define DW_IC_REG_STEP_BYTES 2
#define DW_IC_REG_WORD_SHIFT 16
/*
* FIFO depth configuration
*/
#define DW_IC_FIFO_TX_FIELD GENMASK(23, 16)
#define DW_IC_FIFO_RX_FIELD GENMASK(15, 8)
#define DW_IC_FIFO_MIN_DEPTH 2
/*
* Registers offset
*/
@@ -239,7 +253,6 @@ struct reset_control;
* @semaphore_idx: Index of table with semaphore type attached to the bus. It's
* -1 if there is no semaphore.
* @shared_with_punit: true if this bus is shared with the SoC's PUNIT
* @init: function to initialize the I2C hardware
* @set_sda_hold_time: callback to retrieve IP specific SDA hold timing
* @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE
* @rinfo: I²C GPIO recovery information
@@ -300,7 +313,6 @@ struct dw_i2c_dev {
void (*release_lock)(void);
int semaphore_idx;
bool shared_with_punit;
int (*init)(struct dw_i2c_dev *dev);
int (*set_sda_hold_time)(struct dw_i2c_dev *dev);
int mode;
struct i2c_bus_recovery_info rinfo;
@@ -313,8 +325,6 @@ struct dw_i2c_dev {
#define ARBITRATION_SEMAPHORE BIT(2)
#define ACCESS_POLLING BIT(3)
#define MODEL_MSCC_OCELOT BIT(8)
#define MODEL_BAIKAL_BT1 BIT(9)
#define MODEL_AMD_NAVI_GPU BIT(10)
#define MODEL_WANGXUN_SP BIT(11)
#define MODEL_MASK GENMASK(11, 8)
@@ -333,20 +343,18 @@ struct i2c_dw_semaphore_callbacks {
int (*probe)(struct dw_i2c_dev *dev);
};
int i2c_dw_init_regmap(struct dw_i2c_dev *dev);
u32 i2c_dw_scl_hcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
u32 tSYMBOL, u32 tf, int offset);
u32 i2c_dw_scl_lcnt(struct dw_i2c_dev *dev, unsigned int reg, u32 ic_clk,
u32 tLOW, u32 tf, int offset);
int i2c_dw_set_sda_hold(struct dw_i2c_dev *dev);
u32 i2c_dw_clk_rate(struct dw_i2c_dev *dev);
int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
void i2c_dw_release_lock(struct dw_i2c_dev *dev);
int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev);
int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev);
int i2c_dw_set_fifo_size(struct dw_i2c_dev *dev);
u32 i2c_dw_func(struct i2c_adapter *adap);
irqreturn_t i2c_dw_isr_master(struct dw_i2c_dev *dev);
extern const struct dev_pm_ops i2c_dw_dev_pm_ops;
@@ -386,23 +394,27 @@ void i2c_dw_disable(struct dw_i2c_dev *dev);
extern void i2c_dw_configure_master(struct dw_i2c_dev *dev);
extern int i2c_dw_probe_master(struct dw_i2c_dev *dev);
#if IS_ENABLED(CONFIG_I2C_DESIGNWARE_SLAVE)
int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
#if IS_ENABLED(CONFIG_I2C_SLAVE)
extern void i2c_dw_configure_slave(struct dw_i2c_dev *dev);
extern int i2c_dw_probe_slave(struct dw_i2c_dev *dev);
irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev);
int i2c_dw_reg_slave(struct i2c_client *client);
int i2c_dw_unreg_slave(struct i2c_client *client);
#else
static inline void i2c_dw_configure_slave(struct dw_i2c_dev *dev) { }
static inline int i2c_dw_probe_slave(struct dw_i2c_dev *dev) { return -EINVAL; }
static inline irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev) { return IRQ_NONE; }
#endif
static inline void i2c_dw_configure(struct dw_i2c_dev *dev)
{
if (i2c_detect_slave_mode(dev->dev))
i2c_dw_configure_slave(dev);
else
i2c_dw_configure_master(dev);
i2c_dw_configure_slave(dev);
i2c_dw_configure_master(dev);
}
int i2c_dw_probe(struct dw_i2c_dev *dev);
int i2c_dw_init(struct dw_i2c_dev *dev);
void i2c_dw_set_mode(struct dw_i2c_dev *dev, int mode);
#if IS_ENABLED(CONFIG_I2C_DESIGNWARE_BAYTRAIL)
int i2c_dw_baytrail_probe_lock_support(struct dw_i2c_dev *dev);

View File

@@ -31,16 +31,6 @@
#define AMD_TIMEOUT_MAX_US 250
#define AMD_MASTERCFG_MASK GENMASK(15, 0)
static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
{
/* Configure Tx/Rx FIFO threshold levels */
regmap_write(dev->map, DW_IC_TX_TL, dev->tx_fifo_depth / 2);
regmap_write(dev->map, DW_IC_RX_TL, 0);
/* Configure the I2C master */
regmap_write(dev->map, DW_IC_CON, dev->master_cfg);
}
static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
{
unsigned int comp_param1;
@@ -191,66 +181,10 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
dev->hs_hcnt, dev->hs_lcnt);
}
ret = i2c_dw_set_sda_hold(dev);
if (ret)
return ret;
dev_dbg(dev->dev, "Bus speed: %s\n", i2c_freq_mode_string(t->bus_freq_hz));
return 0;
}
/**
* i2c_dw_init_master() - Initialize the DesignWare I2C master hardware
* @dev: device private data
*
* This functions configures and enables the I2C master.
* This function is called during I2C init function, and in case of timeout at
* run time.
*
* Return: 0 on success, or negative errno otherwise.
*/
static int i2c_dw_init_master(struct dw_i2c_dev *dev)
{
int ret;
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
/* Disable the adapter */
__i2c_dw_disable(dev);
/*
* Mask SMBus interrupts to block storms from broken
* firmware that leaves IC_SMBUS=1; the handler never
* services them.
*/
regmap_write(dev->map, DW_IC_SMBUS_INTR_MASK, 0);
/* Write standard speed timing parameters */
regmap_write(dev->map, DW_IC_SS_SCL_HCNT, dev->ss_hcnt);
regmap_write(dev->map, DW_IC_SS_SCL_LCNT, dev->ss_lcnt);
/* Write fast mode/fast mode plus timing parameters */
regmap_write(dev->map, DW_IC_FS_SCL_HCNT, dev->fs_hcnt);
regmap_write(dev->map, DW_IC_FS_SCL_LCNT, dev->fs_lcnt);
/* Write high speed timing parameters if supported */
if (dev->hs_hcnt && dev->hs_lcnt) {
regmap_write(dev->map, DW_IC_HS_SCL_HCNT, dev->hs_hcnt);
regmap_write(dev->map, DW_IC_HS_SCL_LCNT, dev->hs_lcnt);
}
/* Write SDA hold time if supported */
if (dev->sda_hold_time)
regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
i2c_dw_configure_fifo_master(dev);
i2c_dw_release_lock(dev);
return 0;
}
static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
{
struct i2c_msg *msgs = dev->msgs;
@@ -260,6 +194,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
/* Disable the adapter */
__i2c_dw_disable(dev);
i2c_dw_set_mode(dev, DW_IC_MASTER);
/* If the slave address is ten bit address, enable 10BITADDR */
if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) {
ic_con = DW_IC_CON_10BITADDR_MASTER;
@@ -353,14 +289,17 @@ static int i2c_dw_status(struct dw_i2c_dev *dev)
* Initiate and continue master read/write transaction with polling
* based transfer routine afterward write messages into the Tx buffer.
*/
static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, int num_msgs)
static int amd_i2c_dw_xfer_quirk(struct dw_i2c_dev *dev, struct i2c_msg *msgs, int num_msgs)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
int msg_wrt_idx, msg_itr_lmt, buf_len, data_idx;
int cmd = 0, status;
u8 *tx_buf;
unsigned int val;
ACQUIRE(pm_runtime_active_auto_try, pm)(dev->dev);
if (ACQUIRE_ERR(pm_runtime_active_auto_try, &pm))
return -ENXIO;
/*
* In order to enable the interrupt for UCSI i.e. AMD NAVI GPU card,
* it is mandatory to set the right value in specific register
@@ -571,7 +510,7 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
* after receiving the first byte.
*/
len += (flags & I2C_CLIENT_PEC) ? 2 : 1;
dev->tx_buf_len = len - min_t(u8, len, dev->rx_outstanding);
dev->tx_buf_len = len - min(len, dev->rx_outstanding);
msgs[dev->msg_read_idx].len = len;
msgs[dev->msg_read_idx].flags &= ~I2C_M_RECV_LEN;
@@ -593,11 +532,12 @@ i2c_dw_read(struct dw_i2c_dev *dev)
unsigned int rx_valid;
for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) {
u32 flags = msgs[dev->msg_read_idx].flags;
unsigned int tmp;
u32 len;
u8 *buf;
if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD))
if (!(flags & I2C_M_RD))
continue;
if (!(dev->status & STATUS_READ_IN_PROGRESS)) {
@@ -611,8 +551,6 @@ i2c_dw_read(struct dw_i2c_dev *dev)
regmap_read(dev->map, DW_IC_RXFLR, &rx_valid);
for (; len > 0 && rx_valid > 0; len--, rx_valid--) {
u32 flags = msgs[dev->msg_read_idx].flags;
regmap_read(dev->map, DW_IC_DATA_CMD, &tmp);
tmp &= DW_IC_DATA_CMD_DAT;
/* Ensure length byte is a valid value */
@@ -749,9 +687,8 @@ tx_aborted:
* Interrupt service routine. This gets called whenever an I2C master interrupt
* occurs.
*/
static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
irqreturn_t i2c_dw_isr_master(struct dw_i2c_dev *dev)
{
struct dw_i2c_dev *dev = dev_id;
unsigned int stat, enabled;
regmap_read(dev->map, DW_IC_ENABLE, &enabled);
@@ -812,23 +749,14 @@ static int i2c_dw_wait_transfer(struct dw_i2c_dev *dev)
* Prepare controller for a transaction and call i2c_dw_xfer_msg.
*/
static int
i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
i2c_dw_xfer_common(struct dw_i2c_dev *dev, struct i2c_msg msgs[], int num)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
int ret;
dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
pm_runtime_get_sync(dev->dev);
switch (dev->flags & MODEL_MASK) {
case MODEL_AMD_NAVI_GPU:
ret = amd_i2c_dw_xfer_quirk(adap, msgs, num);
goto done_nolock;
default:
break;
}
reinit_completion(&dev->cmd_complete);
dev->msgs = msgs;
dev->msgs_num = num;
@@ -855,9 +783,9 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
ret = i2c_dw_wait_transfer(dev);
if (ret) {
dev_err(dev->dev, "controller timed out\n");
/* i2c_dw_init_master() implicitly disables the adapter */
/* i2c_dw_init() implicitly disables the adapter */
i2c_recover_bus(&dev->adapter);
i2c_dw_init_master(dev);
i2c_dw_init(dev);
goto done;
}
@@ -905,6 +833,8 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
ret = -EIO;
done:
i2c_dw_set_mode(dev, DW_IC_SLAVE);
i2c_dw_release_lock(dev);
done_nolock:
@@ -913,20 +843,21 @@ done_nolock:
return ret;
}
static const struct i2c_algorithm i2c_dw_algo = {
.xfer = i2c_dw_xfer,
.functionality = i2c_dw_func,
};
int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
static const struct i2c_adapter_quirks i2c_dw_quirks = {
.flags = I2C_AQ_NO_ZERO_LEN,
};
if ((dev->flags & MODEL_MASK) == MODEL_AMD_NAVI_GPU)
return amd_i2c_dw_xfer_quirk(dev, msgs, num);
return i2c_dw_xfer_common(dev, msgs, num);
}
void i2c_dw_configure_master(struct dw_i2c_dev *dev)
{
struct i2c_timings *t = &dev->timings;
dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
dev->functionality |= I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
DW_IC_CON_RESTART_EN;
@@ -961,7 +892,7 @@ static void i2c_dw_unprepare_recovery(struct i2c_adapter *adap)
i2c_dw_prepare_clk(dev, true);
reset_control_deassert(dev->rst);
i2c_dw_init_master(dev);
i2c_dw_init(dev);
}
static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
@@ -1005,27 +936,15 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
int i2c_dw_probe_master(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
unsigned long irq_flags;
unsigned int ic_con;
int ret;
init_completion(&dev->cmd_complete);
dev->init = i2c_dw_init_master;
ret = i2c_dw_init_regmap(dev);
if (ret)
return ret;
ret = i2c_dw_set_timings_master(dev);
if (ret)
return ret;
ret = i2c_dw_set_fifo_size(dev);
if (ret)
return ret;
/* Lock the bus for accessing DW_IC_CON */
ret = i2c_dw_acquire_lock(dev);
if (ret)
@@ -1045,60 +964,8 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
if (ic_con & DW_IC_CON_BUS_CLEAR_CTRL)
dev->master_cfg |= DW_IC_CON_BUS_CLEAR_CTRL;
ret = dev->init(dev);
if (ret)
return ret;
if (!adap->name[0])
scnprintf(adap->name, sizeof(adap->name),
"Synopsys DesignWare I2C adapter");
adap->retries = 3;
adap->algo = &i2c_dw_algo;
adap->quirks = &i2c_dw_quirks;
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);
if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
irq_flags = IRQF_NO_SUSPEND;
} else {
irq_flags = IRQF_SHARED | IRQF_COND_SUSPEND;
}
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
__i2c_dw_write_intr_mask(dev, 0);
i2c_dw_release_lock(dev);
if (!(dev->flags & ACCESS_POLLING)) {
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr,
irq_flags, dev_name(dev->dev), dev);
if (ret)
return dev_err_probe(dev->dev, ret,
"failure requesting irq %i: %d\n",
dev->irq, ret);
}
ret = i2c_dw_init_recovery_info(dev);
if (ret)
return ret;
/*
* Increment PM usage count during adapter registration in order to
* avoid possible spurious runtime suspend when adapter device is
* registered to the device core and immediate resume in case bus has
* registered I2C slaves that do I2C transfers in their probe.
*/
pm_runtime_get_noresume(dev->dev);
ret = i2c_add_numbered_adapter(adap);
if (ret)
dev_err(dev->dev, "failure adding adapter: %d\n", ret);
pm_runtime_put_noidle(dev->dev);
return ret;
return i2c_dw_init_recovery_info(dev);
}
EXPORT_SYMBOL_GPL(i2c_dw_probe_master);
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus master adapter");
MODULE_LICENSE("GPL");

View File

@@ -37,70 +37,6 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
return clk_get_rate(dev->clk) / HZ_PER_KHZ;
}
#ifdef CONFIG_OF
#define BT1_I2C_CTL 0x100
#define BT1_I2C_CTL_ADDR_MASK GENMASK(7, 0)
#define BT1_I2C_CTL_WR BIT(8)
#define BT1_I2C_CTL_GO BIT(31)
#define BT1_I2C_DI 0x104
#define BT1_I2C_DO 0x108
static int bt1_i2c_read(void *context, unsigned int reg, unsigned int *val)
{
struct dw_i2c_dev *dev = context;
int ret;
/*
* Note these methods shouldn't ever fail because the system controller
* registers are memory mapped. We check the return value just in case.
*/
ret = regmap_write(dev->sysmap, BT1_I2C_CTL,
BT1_I2C_CTL_GO | (reg & BT1_I2C_CTL_ADDR_MASK));
if (ret)
return ret;
return regmap_read(dev->sysmap, BT1_I2C_DO, val);
}
static int bt1_i2c_write(void *context, unsigned int reg, unsigned int val)
{
struct dw_i2c_dev *dev = context;
int ret;
ret = regmap_write(dev->sysmap, BT1_I2C_DI, val);
if (ret)
return ret;
return regmap_write(dev->sysmap, BT1_I2C_CTL,
BT1_I2C_CTL_GO | BT1_I2C_CTL_WR | (reg & BT1_I2C_CTL_ADDR_MASK));
}
static const struct regmap_config bt1_i2c_cfg = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.fast_io = true,
.reg_read = bt1_i2c_read,
.reg_write = bt1_i2c_write,
.max_register = DW_IC_COMP_TYPE,
};
static int bt1_i2c_request_regs(struct dw_i2c_dev *dev)
{
dev->sysmap = syscon_node_to_regmap(dev->dev->of_node->parent);
if (IS_ERR(dev->sysmap))
return PTR_ERR(dev->sysmap);
dev->map = devm_regmap_init(dev->dev, NULL, dev, &bt1_i2c_cfg);
return PTR_ERR_OR_ZERO(dev->map);
}
#else
static int bt1_i2c_request_regs(struct dw_i2c_dev *dev)
{
return -ENODEV;
}
#endif
static int dw_i2c_get_parent_regmap(struct dw_i2c_dev *dev)
{
dev->map = dev_get_regmap(dev->dev->parent, NULL);
@@ -127,9 +63,6 @@ static int dw_i2c_plat_request_regs(struct dw_i2c_dev *dev)
return dw_i2c_get_parent_regmap(dev);
switch (dev->flags & MODEL_MASK) {
case MODEL_BAIKAL_BT1:
ret = bt1_i2c_request_regs(dev);
break;
case MODEL_WANGXUN_SP:
ret = dw_i2c_get_parent_regmap(dev);
break;
@@ -334,9 +267,8 @@ static void dw_i2c_plat_remove(struct platform_device *pdev)
}
static const struct of_device_id dw_i2c_of_match[] = {
{ .compatible = "snps,designware-i2c", },
{ .compatible = "mscc,ocelot-i2c", .data = (void *)MODEL_MSCC_OCELOT },
{ .compatible = "baikal,bt1-sys-i2c", .data = (void *)MODEL_BAIKAL_BT1 },
{ .compatible = "mscc,ocelot-i2c" },
{ .compatible = "snps,designware-i2c" },
{}
};
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);

View File

@@ -21,74 +21,33 @@
#include "i2c-designware-core.h"
static void i2c_dw_configure_fifo_slave(struct dw_i2c_dev *dev)
{
/* Configure Tx/Rx FIFO threshold levels. */
regmap_write(dev->map, DW_IC_TX_TL, 0);
regmap_write(dev->map, DW_IC_RX_TL, 0);
/* Configure the I2C slave. */
regmap_write(dev->map, DW_IC_CON, dev->slave_cfg);
regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_SLAVE_MASK);
}
/**
* i2c_dw_init_slave() - Initialize the DesignWare i2c slave hardware
* @dev: device private data
*
* This function configures and enables the I2C in slave mode.
* This function is called during I2C init function, and in case of timeout at
* run time.
*
* Return: 0 on success, or negative errno otherwise.
*/
static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
int i2c_dw_reg_slave(struct i2c_client *slave)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter);
int ret;
if (!i2c_check_functionality(slave->adapter, I2C_FUNC_SLAVE))
return -EOPNOTSUPP;
if (dev->slave)
return -EBUSY;
if (slave->flags & I2C_CLIENT_TEN)
return -EAFNOSUPPORT;
ret = i2c_dw_acquire_lock(dev);
if (ret)
return ret;
/* Disable the adapter. */
__i2c_dw_disable(dev);
pm_runtime_get_sync(dev->dev);
__i2c_dw_disable_nowait(dev);
dev->slave = slave;
i2c_dw_set_mode(dev, DW_IC_SLAVE);
/* Write SDA hold time if supported */
if (dev->sda_hold_time)
regmap_write(dev->map, DW_IC_SDA_HOLD, dev->sda_hold_time);
i2c_dw_configure_fifo_slave(dev);
i2c_dw_release_lock(dev);
return 0;
}
static int i2c_dw_reg_slave(struct i2c_client *slave)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter);
if (dev->slave)
return -EBUSY;
if (slave->flags & I2C_CLIENT_TEN)
return -EAFNOSUPPORT;
pm_runtime_get_sync(dev->dev);
/*
* Set slave address in the IC_SAR register,
* the address to which the DW_apb_i2c responds.
*/
__i2c_dw_disable_nowait(dev);
regmap_write(dev->map, DW_IC_SAR, slave->addr);
dev->slave = slave;
__i2c_dw_enable(dev);
dev->status = 0;
return 0;
}
static int i2c_dw_unreg_slave(struct i2c_client *slave)
int i2c_dw_unreg_slave(struct i2c_client *slave)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(slave->adapter);
@@ -96,6 +55,7 @@ static int i2c_dw_unreg_slave(struct i2c_client *slave)
i2c_dw_disable(dev);
synchronize_irq(dev->irq);
dev->slave = NULL;
i2c_dw_set_mode(dev, DW_IC_MASTER);
pm_runtime_put_sync_suspend(dev->dev);
return 0;
@@ -152,9 +112,8 @@ static u32 i2c_dw_read_clear_intrbits_slave(struct dw_i2c_dev *dev)
* Interrupt service routine. This gets called whenever an I2C slave interrupt
* occurs.
*/
static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
irqreturn_t i2c_dw_isr_slave(struct dw_i2c_dev *dev)
{
struct dw_i2c_dev *dev = dev_id;
unsigned int raw_stat, stat, enabled, tmp;
u8 val = 0, slave_activity;
@@ -217,68 +176,18 @@ static irqreturn_t i2c_dw_isr_slave(int this_irq, void *dev_id)
return IRQ_HANDLED;
}
static const struct i2c_algorithm i2c_dw_algo = {
.functionality = i2c_dw_func,
.reg_slave = i2c_dw_reg_slave,
.unreg_slave = i2c_dw_unreg_slave,
};
void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
{
dev->functionality = I2C_FUNC_SLAVE;
if (dev->flags & ACCESS_POLLING)
return;
dev->functionality |= I2C_FUNC_SLAVE;
dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED;
dev->mode = DW_IC_SLAVE;
}
EXPORT_SYMBOL_GPL(i2c_dw_configure_slave);
int i2c_dw_probe_slave(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
int ret;
dev->init = i2c_dw_init_slave;
ret = i2c_dw_init_regmap(dev);
if (ret)
return ret;
ret = i2c_dw_set_sda_hold(dev);
if (ret)
return ret;
ret = i2c_dw_set_fifo_size(dev);
if (ret)
return ret;
ret = dev->init(dev);
if (ret)
return ret;
snprintf(adap->name, sizeof(adap->name),
"Synopsys DesignWare I2C Slave adapter");
adap->retries = 3;
adap->algo = &i2c_dw_algo;
adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev);
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr_slave,
IRQF_SHARED, dev_name(dev->dev), dev);
if (ret)
return dev_err_probe(dev->dev, ret,
"failure requesting IRQ %i: %d\n",
dev->irq, ret);
ret = i2c_add_numbered_adapter(adap);
if (ret)
dev_err(dev->dev, "failure adding adapter: %d\n", ret);
return ret;
}
EXPORT_SYMBOL_GPL(i2c_dw_probe_slave);
MODULE_AUTHOR("Luis Oliveira <lolivei@synopsys.com>");
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus slave adapter");
MODULE_LICENSE("GPL v2");

View File

@@ -131,6 +131,7 @@
#define CHUNK_DATA 256
#define I2C_PM_TIMEOUT 10 /* ms */
#define I2C_PM_LONG_TIMEOUT_MS 1000 /* Avoid dead lock caused by big clock prepare lock */
#define I2C_DMA_THRESHOLD 8 /* bytes */
enum lpi2c_imx_mode {
@@ -148,6 +149,11 @@ enum lpi2c_imx_pincfg {
FOUR_PIN_PP,
};
struct imx_lpi2c_hwdata {
bool need_request_free_irq; /* Needed by irqsteer */
bool need_prepare_unprepare_clk; /* Needed by LPCG */
};
struct lpi2c_imx_dma {
bool using_pio_mode;
u8 rx_cmd_buf_len;
@@ -186,6 +192,21 @@ struct lpi2c_imx_struct {
bool can_use_dma;
struct lpi2c_imx_dma *dma;
struct i2c_client *target;
int irq;
const struct imx_lpi2c_hwdata *hwdata;
};
static const struct imx_lpi2c_hwdata imx7ulp_lpi2c_hwdata = {
};
static const struct imx_lpi2c_hwdata imx8qxp_lpi2c_hwdata = {
.need_request_free_irq = true,
.need_prepare_unprepare_clk = true,
};
static const struct imx_lpi2c_hwdata imx8qm_lpi2c_hwdata = {
.need_request_free_irq = true,
.need_prepare_unprepare_clk = true,
};
#define lpi2c_imx_read_msr_poll_timeout(atomic, val, cond) \
@@ -1363,7 +1384,9 @@ static const struct i2c_algorithm lpi2c_imx_algo = {
};
static const struct of_device_id lpi2c_imx_of_match[] = {
{ .compatible = "fsl,imx7ulp-lpi2c" },
{ .compatible = "fsl,imx7ulp-lpi2c", .data = &imx7ulp_lpi2c_hwdata,},
{ .compatible = "fsl,imx8qxp-lpi2c", .data = &imx8qxp_lpi2c_hwdata,},
{ .compatible = "fsl,imx8qm-lpi2c", .data = &imx8qm_lpi2c_hwdata,},
{ }
};
MODULE_DEVICE_TABLE(of, lpi2c_imx_of_match);
@@ -1374,19 +1397,23 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
struct resource *res;
dma_addr_t phy_addr;
unsigned int temp;
int irq, ret;
int ret;
lpi2c_imx = devm_kzalloc(&pdev->dev, sizeof(*lpi2c_imx), GFP_KERNEL);
if (!lpi2c_imx)
return -ENOMEM;
lpi2c_imx->hwdata = of_device_get_match_data(&pdev->dev);
if (!lpi2c_imx->hwdata)
return -ENODEV;
lpi2c_imx->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(lpi2c_imx->base))
return PTR_ERR(lpi2c_imx->base);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
lpi2c_imx->irq = platform_get_irq(pdev, 0);
if (lpi2c_imx->irq < 0)
return lpi2c_imx->irq;
lpi2c_imx->adapter.owner = THIS_MODULE;
lpi2c_imx->adapter.algo = &lpi2c_imx_algo;
@@ -1406,10 +1433,10 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
if (ret)
lpi2c_imx->bitrate = I2C_MAX_STANDARD_MODE_FREQ;
ret = devm_request_irq(&pdev->dev, irq, lpi2c_imx_isr, IRQF_NO_SUSPEND,
ret = devm_request_irq(&pdev->dev, lpi2c_imx->irq, lpi2c_imx_isr, IRQF_NO_SUSPEND,
pdev->name, lpi2c_imx);
if (ret)
return dev_err_probe(&pdev->dev, ret, "can't claim irq %d\n", irq);
return dev_err_probe(&pdev->dev, ret, "can't claim irq %d\n", lpi2c_imx->irq);
i2c_set_adapdata(&lpi2c_imx->adapter, lpi2c_imx);
platform_set_drvdata(pdev, lpi2c_imx);
@@ -1432,7 +1459,11 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, -EINVAL,
"can't get I2C peripheral clock rate\n");
pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
if (lpi2c_imx->hwdata->need_prepare_unprepare_clk)
pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_LONG_TIMEOUT_MS);
else
pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_get_noresume(&pdev->dev);
pm_runtime_set_active(&pdev->dev);
@@ -1487,8 +1518,16 @@ static void lpi2c_imx_remove(struct platform_device *pdev)
static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
{
struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
bool need_prepare_unprepare_clk = lpi2c_imx->hwdata->need_prepare_unprepare_clk;
bool need_request_free_irq = lpi2c_imx->hwdata->need_request_free_irq;
clk_bulk_disable(lpi2c_imx->num_clks, lpi2c_imx->clks);
if (need_request_free_irq)
devm_free_irq(dev, lpi2c_imx->irq, lpi2c_imx);
if (need_prepare_unprepare_clk)
clk_bulk_disable_unprepare(lpi2c_imx->num_clks, lpi2c_imx->clks);
else
clk_bulk_disable(lpi2c_imx->num_clks, lpi2c_imx->clks);
pinctrl_pm_select_sleep_state(dev);
return 0;
@@ -1497,13 +1536,32 @@ static int __maybe_unused lpi2c_runtime_suspend(struct device *dev)
static int __maybe_unused lpi2c_runtime_resume(struct device *dev)
{
struct lpi2c_imx_struct *lpi2c_imx = dev_get_drvdata(dev);
bool need_prepare_unprepare_clk = lpi2c_imx->hwdata->need_prepare_unprepare_clk;
bool need_request_free_irq = lpi2c_imx->hwdata->need_request_free_irq;
int ret;
pinctrl_pm_select_default_state(dev);
ret = clk_bulk_enable(lpi2c_imx->num_clks, lpi2c_imx->clks);
if (ret) {
dev_err(dev, "failed to enable I2C clock, ret=%d\n", ret);
return ret;
if (need_prepare_unprepare_clk) {
ret = clk_bulk_prepare_enable(lpi2c_imx->num_clks, lpi2c_imx->clks);
if (ret) {
dev_err(dev, "failed to enable I2C clock, ret=%d\n", ret);
return ret;
}
} else {
ret = clk_bulk_enable(lpi2c_imx->num_clks, lpi2c_imx->clks);
if (ret) {
dev_err(dev, "failed to enable clock %d\n", ret);
return ret;
}
}
if (need_request_free_irq) {
ret = devm_request_irq(dev, lpi2c_imx->irq, lpi2c_imx_isr, IRQF_NO_SUSPEND,
dev_name(dev), lpi2c_imx);
if (ret) {
dev_err(dev, "can't claim irq %d\n", lpi2c_imx->irq);
return ret;
}
}
return 0;

View File

@@ -4,12 +4,13 @@
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
/* spacemit i2c registers */
#define SPACEMIT_ICR 0x0 /* Control register */
@@ -534,6 +535,7 @@ static int spacemit_i2c_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *of_node = pdev->dev.of_node;
struct spacemit_i2c_dev *i2c;
struct reset_control *rst;
int ret;
i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
@@ -578,6 +580,11 @@ static int spacemit_i2c_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk), "failed to enable bus clock");
rst = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL);
if (IS_ERR(rst))
return dev_err_probe(dev, PTR_ERR(rst),
"failed to acquire deasserted reset\n");
spacemit_i2c_reset(i2c);
i2c_set_adapdata(&i2c->adapt, i2c);

View File

@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/string_choices.h>
#include <linux/units.h>
/* Defines what functionality is present. */
#define MLXBF_I2C_FUNC_SMBUS_BLOCK \
@@ -65,15 +66,13 @@
* strongly dependent on the core clock frequency of the SMBus
* Master. Default value is set to 400MHz.
*/
#define MLXBF_I2C_TYU_PLL_OUT_FREQ (400 * 1000 * 1000)
#define MLXBF_I2C_TYU_PLL_OUT_FREQ (400 * HZ_PER_MHZ)
/* Reference clock for Bluefield - 156 MHz. */
#define MLXBF_I2C_PLL_IN_FREQ 156250000ULL
/* Constant used to determine the PLL frequency. */
#define MLNXBF_I2C_COREPLL_CONST 16384ULL
#define MLXBF_I2C_FREQUENCY_1GHZ 1000000000ULL
/* PLL registers. */
#define MLXBF_I2C_CORE_PLL_REG1 0x4
#define MLXBF_I2C_CORE_PLL_REG2 0x8
@@ -325,12 +324,6 @@
.name = (str) \
}
enum {
MLXBF_I2C_TIMING_100KHZ = 100000,
MLXBF_I2C_TIMING_400KHZ = 400000,
MLXBF_I2C_TIMING_1000KHZ = 1000000,
};
enum {
MLXBF_I2C_F_READ = BIT(0),
MLXBF_I2C_F_WRITE = BIT(1),
@@ -1083,7 +1076,7 @@ static u32 mlxbf_i2c_get_ticks(struct mlxbf_i2c_priv *priv, u64 nanoseconds,
* Frequency
*/
frequency = priv->frequency;
ticks = div_u64(nanoseconds * frequency, MLXBF_I2C_FREQUENCY_1GHZ);
ticks = div_u64(nanoseconds * frequency, HZ_PER_GHZ);
/*
* The number of ticks is rounded down and if minimum is equal to 1
* then add one tick.

View File

@@ -24,6 +24,7 @@
#include <linux/scatterlist.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/units.h>
#define I2C_RS_TRANSFER (1 << 4)
#define I2C_ARB_LOST (1 << 3)
@@ -685,7 +686,7 @@ static int mtk_i2c_get_clk_div_restri(struct mtk_i2c *i2c,
* Check and Calculate i2c ac-timing
*
* Hardware design:
* sample_ns = (1000000000 * (sample_cnt + 1)) / clk_src
* sample_ns = (HZ_PER_GHZ * (sample_cnt + 1)) / clk_src
* xxx_cnt_div = spec->min_xxx_ns / sample_ns
*
* Sample_ns is rounded down for xxx_cnt_div would be greater
@@ -701,9 +702,8 @@ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
{
const struct i2c_spec_values *spec;
unsigned int su_sta_cnt, low_cnt, high_cnt, max_step_cnt;
unsigned int sda_max, sda_min, clk_ns, max_sta_cnt = 0x3f;
unsigned int sample_ns = div_u64(1000000000ULL * (sample_cnt + 1),
clk_src);
unsigned int sda_max, sda_min, max_sta_cnt = 0x3f;
unsigned int clk_ns, sample_ns;
if (!i2c->dev_comp->timing_adjust)
return 0;
@@ -713,8 +713,9 @@ static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c,
spec = mtk_i2c_get_spec(check_speed);
sample_ns = div_u64(1ULL * HZ_PER_GHZ * (sample_cnt + 1), clk_src);
if (i2c->dev_comp->ltiming_adjust)
clk_ns = 1000000000 / clk_src;
clk_ns = HZ_PER_GHZ / clk_src;
else
clk_ns = sample_ns / 2;

View File

@@ -31,6 +31,7 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/units.h>
#define DRIVER_NAME "nmk-i2c"
@@ -419,10 +420,10 @@ static void setup_i2c_controller(struct nmk_i2c_dev *priv)
* modes are 250ns, 100ns, 10ns respectively.
*
* As the time for one cycle T in nanoseconds is
* T = (1/f) * 1000000000 =>
* slsu = cycles / (1000000000 / f) + 1
* T = (1/f) * HZ_PER_GHZ =>
* slsu = cycles / (HZ_PER_GHZ / f) + 1
*/
ns = DIV_ROUND_UP_ULL(1000000000ULL, i2c_clk);
ns = DIV_ROUND_UP(HZ_PER_GHZ, i2c_clk);
switch (priv->sm) {
case I2C_FREQ_MODE_FAST:
case I2C_FREQ_MODE_FAST_PLUS:

View File

@@ -19,6 +19,7 @@
#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <linux/clk.h>
#include <linux/units.h>
#include <linux/wait.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
@@ -896,13 +897,12 @@ static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate)
clk_disable(i2c->pclk);
t_low_ns = div_u64(((u64)calc.div_low + 1) * 8 * 1000000000, clk_rate);
t_high_ns = div_u64(((u64)calc.div_high + 1) * 8 * 1000000000,
clk_rate);
t_low_ns = div_u64(8ULL * HZ_PER_GHZ * (calc.div_low + 1), clk_rate);
t_high_ns = div_u64(8ULL * HZ_PER_GHZ * (calc.div_high + 1), clk_rate);
dev_dbg(i2c->dev,
"CLK %lukhz, Req %uns, Act low %lluns high %lluns\n",
clk_rate / 1000,
1000000000 / t->bus_freq_hz,
"CLK %lukHz, Req %luns, Act low %lluns high %lluns\n",
clk_rate / HZ_PER_KHZ,
HZ_PER_GHZ / t->bus_freq_hz,
t_low_ns, t_high_ns);
}

View File

@@ -129,7 +129,7 @@ static int rtl9310_i2c_select_scl(struct rtl9300_i2c *i2c, u8 scl)
static int rtl9300_i2c_config_chan(struct rtl9300_i2c *i2c, struct rtl9300_i2c_chan *chan)
{
struct rtl9300_i2c_drv_data *drv_data;
const struct rtl9300_i2c_drv_data *drv_data;
int ret;
if (i2c->sda_num == chan->sda_num)
@@ -139,7 +139,7 @@ static int rtl9300_i2c_config_chan(struct rtl9300_i2c *i2c, struct rtl9300_i2c_c
if (ret)
return ret;
drv_data = (struct rtl9300_i2c_drv_data *)device_get_match_data(i2c->dev);
drv_data = device_get_match_data(i2c->dev);
ret = drv_data->select_scl(i2c, i2c->scl_num);
if (ret)
return ret;
@@ -371,8 +371,7 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct rtl9300_i2c *i2c;
struct fwnode_handle *child;
struct rtl9300_i2c_drv_data *drv_data;
const struct rtl9300_i2c_drv_data *drv_data;
struct reg_field fields[F_NUM_FIELDS];
u32 clock_freq, scl_num, sda_num;
int ret, i = 0;
@@ -399,7 +398,7 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2c);
drv_data = (struct rtl9300_i2c_drv_data *)device_get_match_data(i2c->dev);
drv_data = device_get_match_data(i2c->dev);
if (device_get_child_node_count(dev) > drv_data->max_nchan)
return dev_err_probe(dev, -EINVAL, "Too many channels\n");
@@ -415,15 +414,15 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
return ret;
i = 0;
device_for_each_child_node(dev, child) {
for_each_child_of_node_scoped(dev->of_node, child) {
struct rtl9300_i2c_chan *chan = &i2c->chans[i];
struct i2c_adapter *adap = &chan->adap;
ret = fwnode_property_read_u32(child, "reg", &sda_num);
ret = of_property_read_u32(child, "reg", &sda_num);
if (ret)
return ret;
ret = fwnode_property_read_u32(child, "clock-frequency", &clock_freq);
ret = of_property_read_u32(child, "clock-frequency", &clock_freq);
if (ret)
clock_freq = I2C_MAX_STANDARD_MODE_FREQ;
@@ -449,7 +448,7 @@ static int rtl9300_i2c_probe(struct platform_device *pdev)
adap->retries = 3;
adap->dev.parent = dev;
i2c_set_adapdata(adap, chan);
adap->dev.of_node = to_of_node(child);
adap->dev.of_node = child;
snprintf(adap->name, sizeof(adap->name), "%s SDA%d\n", dev_name(dev), sda_num);
i++;

View File

@@ -20,6 +20,7 @@
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/units.h>
/* SSC registers */
#define SSC_BRG 0x000
@@ -285,7 +286,7 @@ static void st_i2c_hw_config(struct st_i2c_dev *i2c_dev)
writel_relaxed(val, i2c_dev->base + SSC_CTL);
rate = clk_get_rate(i2c_dev->clk);
ns_per_clk = 1000000000 / rate;
ns_per_clk = HZ_PER_GHZ / rate;
/* Baudrate */
val = rate / (2 * t->rate);

View File

@@ -18,9 +18,10 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/units.h>
#define WAIT_PCLK(n, rate) \
ndelay(DIV_ROUND_UP(DIV_ROUND_UP(1000000000, rate), n) + 10)
ndelay(DIV_ROUND_UP(DIV_ROUND_UP(HZ_PER_GHZ, rate), n) + 10)
/* I2C register address definitions */
#define SYNQUACER_I2C_REG_BSR (0x00 << 2) // Bus Status

View File

@@ -264,7 +264,6 @@ struct tegra_i2c_hw_feature {
* @div_clk: clock reference for div clock of I2C controller
* @clocks: array of I2C controller clocks
* @nclocks: number of clocks in the array
* @rst: reset control for the I2C controller
* @base: ioremapped registers cookie
* @base_phys: physical base address of the I2C controller
* @cont_id: I2C controller ID, used for packet header
@@ -293,7 +292,6 @@ struct tegra_i2c_dev {
struct i2c_adapter adapter;
const struct tegra_i2c_hw_feature *hw;
struct reset_control *rst;
unsigned int cont_id;
unsigned int irq;

View File

@@ -25,9 +25,12 @@
#define MICROHZ_PER_HZ 1000000UL
#define MILLIHZ_PER_HZ 1000UL
/* Hz based multipliers */
#define HZ_PER_KHZ 1000UL
#define HZ_PER_MHZ 1000000UL
#define HZ_PER_GHZ 1000000000UL
/* kHz based multipliers */
#define KHZ_PER_MHZ 1000UL
#define KHZ_PER_GHZ 1000000UL