diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-05 08:41:14 -1000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-11-05 08:41:14 -1000 |
commit | 3d05e493e461c4469a9b73e00e59ea16e1d8a416 (patch) | |
tree | a23450428a4153bebce9bc11a92d1ea8803dca82 /drivers/i2c/busses | |
parent | 2153fc3d68170bb67be8e389c2f6e0f4a9eb7cd3 (diff) | |
parent | 10e806d39d304f837ed2921f36499f17a774a220 (diff) |
Merge tag 'i2c-for-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"I2C has largely driver updates for 6.7, i.e. feature additions (like
adding transfers while in atomic mode), using new helpers (like
devm_clk_get_enabled), new IDs, documentation fixes and additions...
you name it.
The core got a memleak fix and better support for nested muxes"
* tag 'i2c-for-6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (53 commits)
i2c: s3c2410: make i2c_s3c_irq_nextbyte() void
i2c: qcom-geni: add ACPI device id for sc8180x
Documentation: i2c: add fault code for not supporting 10 bit addresses
i2c: sun6i-p2wi: Prevent potential division by zero
i2c: mux: demux-pinctrl: Convert to use sysfs_emit_at() API
i2c: i801: Use new helper acpi_use_parent_companion
ACPI: Add helper acpi_use_parent_companion
MAINTAINERS: add YAML file for i2c-demux-pinctrl
i2c: core: fix lockdep warning for sparsely nested adapter chain
i2c: axxia: eliminate kernel-doc warnings
dt-bindings: i2c: i2c-demux-pinctrl: Convert to json-schema
i2c: stm32f7: Use devm_clk_get_enabled()
i2c: stm32f4: Use devm_clk_get_enabled()
i2c: stm32f7: add description of atomic in struct stm32f7_i2c_dev
i2c: fix memleak in i2c_new_client_device()
i2c: exynos5: Calculate t_scl_l, t_scl_h according to i2c spec
i2c: i801: Simplify class-based client device instantiation
i2c: exynos5: add support for atomic transfers
i2c: at91-core: Use devm_clk_get_enabled()
eeprom: at24: add ST M24C64-D Additional Write lockable page support
...
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-at91-core.c | 10 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-axxia.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-brcmstb.c | 23 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-cp2615.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-exynos5.c | 80 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-gpio.c | 7 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 110 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mt65xx.c | 12 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mv64xxx.c | 11 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-powermac.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 7 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-qcom-geni.c | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-rcar.c | 180 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-riic.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 7 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stm32f4.c | 32 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-stm32f7.c | 89 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-sun6i-p2wi.c | 5 |
20 files changed, 362 insertions, 235 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index fd887f767675..28eb48dd5b32 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -158,6 +158,7 @@ config I2C_I801 Alder Lake (PCH) Raptor Lake (PCH) Meteor Lake (SOC and PCH) + Birch Stream (SOC) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c index db45554327ae..dc52b3530725 100644 --- a/drivers/i2c/busses/i2c-at91-core.c +++ b/drivers/i2c/busses/i2c-at91-core.c @@ -221,11 +221,10 @@ static int at91_twi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); - dev->clk = devm_clk_get(dev->dev, NULL); + dev->clk = devm_clk_get_enabled(dev->dev, NULL); if (IS_ERR(dev->clk)) - return dev_err_probe(dev->dev, PTR_ERR(dev->clk), "no clock defined\n"); - - clk_prepare_enable(dev->clk); + return dev_err_probe(dev->dev, PTR_ERR(dev->clk), + "failed to enable clock\n"); snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91"); i2c_set_adapdata(&dev->adapter, dev); @@ -254,8 +253,6 @@ static int at91_twi_probe(struct platform_device *pdev) rc = i2c_add_numbered_adapter(&dev->adapter); if (rc) { - clk_disable_unprepare(dev->clk); - pm_runtime_disable(dev->dev); pm_runtime_set_suspended(dev->dev); @@ -272,7 +269,6 @@ static void at91_twi_remove(struct platform_device *pdev) struct at91_twi_dev *dev = platform_get_drvdata(pdev); i2c_del_adapter(&dev->adapter); - clk_disable_unprepare(dev->clk); pm_runtime_disable(dev->dev); pm_runtime_set_suspended(dev->dev); diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index d7f1e98777ac..a66f7f67b3b8 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -131,6 +131,8 @@ * @i2c_clk: clock reference for i2c input clock * @bus_clk_rate: current i2c bus clock rate * @last: a flag indicating is this is last message in transfer + * @slave: associated &i2c_client + * @irq: platform device IRQ number */ struct axxia_i2c_dev { void __iomem *base; @@ -165,7 +167,7 @@ static void i2c_int_enable(struct axxia_i2c_dev *idev, u32 mask) writel(int_en | mask, idev->base + MST_INT_ENABLE); } -/** +/* * ns_to_clk - Convert time (ns) to clock cycles for the given clock frequency. */ static u32 ns_to_clk(u64 ns, u32 clk_mhz) @@ -263,7 +265,7 @@ static int i2c_m_recv_len(const struct i2c_msg *msg) return (msg->flags & I2C_M_RECV_LEN) != 0; } -/** +/* * axxia_i2c_empty_rx_fifo - Fetch data from RX FIFO and update SMBus block * transfer length if this is the first byte of such a transfer. */ @@ -295,7 +297,7 @@ static int axxia_i2c_empty_rx_fifo(struct axxia_i2c_dev *idev) return 0; } -/** +/* * axxia_i2c_fill_tx_fifo - Fill TX FIFO from current message buffer. * @return: Number of bytes left to transfer. */ diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index acee76732544..38f276c99193 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -160,6 +160,7 @@ struct brcmstb_i2c_dev { struct completion done; u32 clk_freq_hz; int data_regsz; + bool atomic; }; /* register accessors for both be and le cpu arch */ @@ -240,7 +241,7 @@ static int brcmstb_i2c_wait_for_completion(struct brcmstb_i2c_dev *dev) int ret = 0; unsigned long timeout = msecs_to_jiffies(I2C_TIMEOUT); - if (dev->irq >= 0) { + if (dev->irq >= 0 && !dev->atomic) { if (!wait_for_completion_timeout(&dev->done, timeout)) ret = -ETIMEDOUT; } else { @@ -287,7 +288,7 @@ static int brcmstb_send_i2c_cmd(struct brcmstb_i2c_dev *dev, return rc; /* only if we are in interrupt mode */ - if (dev->irq >= 0) + if (dev->irq >= 0 && !dev->atomic) reinit_completion(&dev->done); /* enable BSC CTL interrupt line */ @@ -520,6 +521,23 @@ out: } +static int brcmstb_i2c_xfer_atomic(struct i2c_adapter *adapter, + struct i2c_msg msgs[], int num) +{ + struct brcmstb_i2c_dev *dev = i2c_get_adapdata(adapter); + int ret; + + if (dev->irq >= 0) + disable_irq(dev->irq); + dev->atomic = true; + ret = brcmstb_i2c_xfer(adapter, msgs, num); + dev->atomic = false; + if (dev->irq >= 0) + enable_irq(dev->irq); + + return ret; +} + static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR @@ -528,6 +546,7 @@ static u32 brcmstb_i2c_functionality(struct i2c_adapter *adap) static const struct i2c_algorithm brcmstb_i2c_algo = { .master_xfer = brcmstb_i2c_xfer, + .master_xfer_atomic = brcmstb_i2c_xfer_atomic, .functionality = brcmstb_i2c_functionality, }; diff --git a/drivers/i2c/busses/i2c-cp2615.c b/drivers/i2c/busses/i2c-cp2615.c index 3ded28632e4c..20f8f7c9a8cd 100644 --- a/drivers/i2c/busses/i2c-cp2615.c +++ b/drivers/i2c/busses/i2c-cp2615.c @@ -298,7 +298,7 @@ cp2615_i2c_probe(struct usb_interface *usbif, const struct usb_device_id *id) if (!adap) return -ENOMEM; - strncpy(adap->name, usbdev->serial, sizeof(adap->name) - 1); + strscpy(adap->name, usbdev->serial, sizeof(adap->name)); adap->owner = THIS_MODULE; adap->dev.parent = &usbif->dev; adap->dev.of_node = usbif->dev.of_node; diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 2b0b9cdffa86..385ef9d9e4d4 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -194,6 +194,11 @@ struct exynos5_i2c { */ int trans_done; + /* + * Called from atomic context, don't use interrupts. + */ + unsigned int atomic; + /* Controller operating frequency */ unsigned int op_clock; @@ -265,7 +270,7 @@ static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c) * exynos5_i2c_set_timing: updates the registers with appropriate * timing values calculated * - * Timing values for operation are calculated against either 100kHz + * Timing values for operation are calculated against 100kHz, 400kHz * or 1MHz controller operating frequency. * * Returns 0 on success, -EINVAL if the cycle length cannot @@ -328,6 +333,23 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings) * * Constraints: 4 <= temp, 0 <= CLK_DIV < 256, 2 <= clk_cycle <= 510 * + * To split SCL clock into low, high periods appropriately, one + * proportion factor for each I2C mode is used, which is calculated + * using this formula. + * ``` + * ((t_low_min + (scl_clock - t_low_min - t_high_min) / 2) / scl_clock) + * ``` + * where: + * t_low_min is the minimal value of low period of the SCL clock in us; + * t_high_min is the minimal value of high period of the SCL clock in us; + * scl_clock is converted from SCL clock frequency into us. + * + * Below are the proportion factors for these I2C modes: + * t_low_min, t_high_min, scl_clock, proportion + * Standard Mode: 4.7us, 4.0us, 10us, 0.535 + * Fast Mode: 1.3us, 0.6us, 2.5us, 0.64 + * Fast-Plus Mode: 0.5us, 0.26us, 1us, 0.62 + * */ t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7; temp = clkin / op_clk - 8 - t_ftl_cycle; @@ -341,8 +363,19 @@ static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, bool hs_timings) return -EINVAL; } - t_scl_l = clk_cycle / 2; - t_scl_h = clk_cycle / 2; + /* + * Scale clk_cycle to get t_scl_l using the proption factors for individual I2C modes. + */ + if (op_clk <= I2C_MAX_STANDARD_MODE_FREQ) + t_scl_l = clk_cycle * 535 / 1000; + else if (op_clk <= I2C_MAX_FAST_MODE_FREQ) + t_scl_l = clk_cycle * 64 / 100; + else + t_scl_l = clk_cycle * 62 / 100; + + if (t_scl_l > 0xFF) + t_scl_l = 0xFF; + t_scl_h = clk_cycle - t_scl_l; t_start_su = t_scl_l; t_start_hd = t_scl_l; t_stop_su = t_scl_l; @@ -711,6 +744,22 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) spin_unlock_irqrestore(&i2c->lock, flags); } +static bool exynos5_i2c_poll_irqs_timeout(struct exynos5_i2c *i2c, + unsigned long timeout) +{ + unsigned long time_left = jiffies + timeout; + + while (time_before(jiffies, time_left) && + !((i2c->trans_done && (i2c->msg->len == i2c->msg_ptr)) || + (i2c->state < 0))) { + while (readl(i2c->regs + HSI2C_INT_ENABLE) & + readl(i2c->regs + HSI2C_INT_STATUS)) + exynos5_i2c_irq(i2c->irq, i2c); + usleep_range(100, 200); + } + return time_before(jiffies, time_left); +} + static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, struct i2c_msg *msgs, int stop) { @@ -725,8 +774,13 @@ static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, exynos5_i2c_message_start(i2c, stop); - timeout = wait_for_completion_timeout(&i2c->msg_complete, - EXYNOS5_I2C_TIMEOUT); + if (!i2c->atomic) + timeout = wait_for_completion_timeout(&i2c->msg_complete, + EXYNOS5_I2C_TIMEOUT); + else + timeout = exynos5_i2c_poll_irqs_timeout(i2c, + EXYNOS5_I2C_TIMEOUT); + if (timeout == 0) ret = -ETIMEDOUT; else @@ -777,6 +831,21 @@ err_pclk: return ret ?: num; } +static int exynos5_i2c_xfer_atomic(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct exynos5_i2c *i2c = adap->algo_data; + int ret; + + disable_irq(i2c->irq); + i2c->atomic = true; + ret = exynos5_i2c_xfer(adap, msgs, num); + i2c->atomic = false; + enable_irq(i2c->irq); + + return ret; +} + static u32 exynos5_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); @@ -784,6 +853,7 @@ static u32 exynos5_i2c_func(struct i2c_adapter *adap) static const struct i2c_algorithm exynos5_i2c_algorithm = { .master_xfer = exynos5_i2c_xfer, + .master_xfer_atomic = exynos5_i2c_xfer_atomic, .functionality = exynos5_i2c_func, }; diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index e5a5b9e8bf2c..fb35a75fe0e3 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -263,15 +263,10 @@ static void i2c_gpio_fault_injector_init(struct platform_device *pdev) * 'fault-injector' dir there. Until then, we have a global dir with * all adapters as subdirs. */ - if (!i2c_gpio_debug_dir) { + if (!i2c_gpio_debug_dir) i2c_gpio_debug_dir = debugfs_create_dir("i2c-fault-injector", NULL); - if (!i2c_gpio_debug_dir) - return; - } priv->debug_dir = debugfs_create_dir(pdev->name, i2c_gpio_debug_dir); - if (!priv->debug_dir) - return; init_completion(&priv->scl_irq_completion); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 1d855258a45d..070999139c6d 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -79,6 +79,7 @@ * Meteor Lake-P (SOC) 0x7e22 32 hard yes yes yes * Meteor Lake SoC-S (SOC) 0xae22 32 hard yes yes yes * Meteor Lake PCH-S (PCH) 0x7f23 32 hard yes yes yes + * Birch Stream (SOC) 0x5796 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -231,6 +232,7 @@ #define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_P_SMBUS 0x51a3 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_M_SMBUS 0x54a3 +#define PCI_DEVICE_ID_INTEL_BIRCH_STREAM_SMBUS 0x5796 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 #define PCI_DEVICE_ID_INTEL_RAPTOR_LAKE_S_SMBUS 0x7a23 #define PCI_DEVICE_ID_INTEL_ALDER_LAKE_S_SMBUS 0x7aa3 @@ -285,7 +287,6 @@ struct i801_priv { u8 *data; #if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI - const struct i801_mux_config *mux_drvdata; struct platform_device *mux_pdev; struct gpiod_lookup_table *lookup; #endif @@ -293,10 +294,9 @@ struct i801_priv { /* * If set to true the host controller registers are reserved for - * ACPI AML use. Protected by acpi_lock. + * ACPI AML use. */ bool acpi_reserved; - struct mutex acpi_lock; }; #define FEATURE_SMBUS_PEC BIT(0) @@ -679,15 +679,11 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, return result ? priv->status : -ETIMEDOUT; } - for (i = 1; i <= len; i++) { - if (i == len && read_write == I2C_SMBUS_READ) - smbcmd |= SMBHSTCNT_LAST_BYTE; - outb_p(smbcmd, SMBHSTCNT(priv)); - - if (i == 1) - outb_p(inb(SMBHSTCNT(priv)) | SMBHSTCNT_START, - SMBHSTCNT(priv)); + if (len == 1 && read_write == I2C_SMBUS_READ) + smbcmd |= SMBHSTCNT_LAST_BYTE; + outb_p(smbcmd | SMBHSTCNT_START, SMBHSTCNT(priv)); + for (i = 1; i <= len; i++) { status = i801_wait_byte_done(priv); if (status) return status; @@ -710,9 +706,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, data->block[0] = len; } - /* Retrieve/store value in SMBBLKDAT */ - if (read_write == I2C_SMBUS_READ) + if (read_write == I2C_SMBUS_READ) { data->block[i] = inb_p(SMBBLKDAT(priv)); + if (i == len - 1) + outb_p(smbcmd | SMBHSTCNT_LAST_BYTE, SMBHSTCNT(priv)); + } + if (read_write == I2C_SMBUS_WRITE && i+1 <= len) outb_p(data->block[i+1], SMBBLKDAT(priv)); @@ -875,11 +874,8 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, int hwpec, ret; struct i801_priv *priv = i2c_get_adapdata(adap); - mutex_lock(&priv->acpi_lock); - if (priv->acpi_reserved) { - mutex_unlock(&priv->acpi_lock); + if (priv->acpi_reserved) return -EBUSY; - } pm_runtime_get_sync(&priv->pci_dev->dev); @@ -920,7 +916,6 @@ out: pm_runtime_mark_last_busy(&priv->pci_dev->dev); pm_runtime_put_autosuspend(&priv->pci_dev->dev); - mutex_unlock(&priv->acpi_lock); return ret; } @@ -1044,6 +1039,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_P_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_SOC_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { PCI_DEVICE_DATA(INTEL, METEOR_LAKE_PCH_S_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, + { PCI_DEVICE_DATA(INTEL, BIRCH_STREAM_SMBUS, FEATURES_ICH5 | FEATURE_TCO_CNL) }, { 0, } }; @@ -1288,7 +1284,7 @@ static void i801_probe_optional_slaves(struct i801_priv *priv) /* Instantiate SPD EEPROMs unless the SMBus is multiplexed */ #if IS_ENABLED(CONFIG_I2C_MUX_GPIO) - if (!priv->mux_drvdata) + if (!priv->mux_pdev) #endif i2c_register_spd(&priv->adapter); } @@ -1390,11 +1386,14 @@ static void i801_add_mux(struct i801_priv *priv) const struct i801_mux_config *mux_config; struct i2c_mux_gpio_platform_data gpio_data; struct gpiod_lookup_table *lookup; + const struct dmi_system_id *id; int i; - if (!priv->mux_drvdata) + id = dmi_first_match(mux_dmi_table); + if (!id) return; - mux_config = priv->mux_drvdata; + + mux_config = id->driver_data; /* Prepare the platform data */ memset(&gpio_data, 0, sizeof(struct i2c_mux_gpio_platform_data)); @@ -1438,35 +1437,9 @@ static void i801_del_mux(struct i801_priv *priv) platform_device_unregister(priv->mux_pdev); gpiod_remove_lookup_table(priv->lookup); } - -static unsigned int i801_get_adapter_class(struct i801_priv *priv) -{ - const struct dmi_system_id *id; - const struct i801_mux_config *mux_config; - unsigned int class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - int i; - - id = dmi_first_match(mux_dmi_table); - if (id) { - /* Remove branch classes from trunk */ - mux_config = id->driver_data; - for (i = 0; i < mux_config->n_values; i++) - class &= ~mux_config->classes[i]; - - /* Remember for later */ - priv->mux_drvdata = mux_config; - } - - return class; -} #else static inline void i801_add_mux(struct i801_priv *priv) { } static inline void i801_del_mux(struct i801_priv *priv) { } - -static inline unsigned int i801_get_adapter_class(struct i801_priv *priv) -{ - return I2C_CLASS_HWMON | I2C_CLASS_SPD; -} #endif static struct platform_device * @@ -1572,7 +1545,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, * further access from the driver itself. This device is now owned * by the system firmware. */ - mutex_lock(&priv->acpi_lock); + i2c_lock_bus(&priv->adapter, I2C_LOCK_SEGMENT); if (!priv->acpi_reserved && i801_acpi_is_smbus_ioport(priv, address)) { priv->acpi_reserved = true; @@ -1592,7 +1565,7 @@ i801_acpi_io_handler(u32 function, acpi_physical_address address, u32 bits, else status = acpi_os_write_port(address, (u32)*value, bits); - mutex_unlock(&priv->acpi_lock); + i2c_unlock_bus(&priv->adapter, I2C_LOCK_SEGMENT); return status; } @@ -1630,6 +1603,12 @@ static void i801_setup_hstcfg(struct i801_priv *priv) pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hstcfg); } +static void i801_restore_regs(struct i801_priv *priv) +{ + outb_p(priv->original_hstcnt, SMBHSTCNT(priv)); + pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg); +} + static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { int err, i; @@ -1641,12 +1620,11 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) i2c_set_adapdata(&priv->adapter, priv); priv->adapter.owner = THIS_MODULE; - priv->adapter.class = i801_get_adapter_class(priv); + priv->adapter.class = I2C_CLASS_HWMON; priv->adapter.algo = &smbus_algorithm; priv->adapter.dev.parent = &dev->dev; - ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&dev->dev)); + acpi_use_parent_companion(&priv->adapter.dev); priv->adapter.retries = 3; - mutex_init(&priv->acpi_lock); priv->pci_dev = dev; priv->features = id->driver_data; @@ -1756,6 +1734,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) if (err) { platform_device_unregister(priv->tco_pdev); i801_acpi_remove(priv); + i801_restore_regs(priv); return err; } @@ -1780,12 +1759,10 @@ static void i801_remove(struct pci_dev *dev) { struct i801_priv *priv = pci_get_drvdata(dev); - outb_p(priv->original_hstcnt, SMBHSTCNT(priv)); i801_disable_host_notify(priv); i801_del_mux(priv); i2c_del_adapter(&priv->adapter); i801_acpi_remove(priv); - pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); platform_device_unregister(priv->tco_pdev); @@ -1793,6 +1770,8 @@ static void i801_remove(struct pci_dev *dev) if (!priv->acpi_reserved) pm_runtime_get_noresume(&dev->dev); + i801_restore_regs(priv); + /* * do not call pci_disable_device(dev) since it can cause hard hangs on * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010) @@ -1803,18 +1782,18 @@ static void i801_shutdown(struct pci_dev *dev) { struct i801_priv *priv = pci_get_drvdata(dev); - /* Restore config registers to avoid hard hang on some systems */ - outb_p(priv->original_hstcnt, SMBHSTCNT(priv)); i801_disable_host_notify(priv); - pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); + /* Restore config registers to avoid hard hang on some systems */ + i801_restore_regs(priv); } static int i801_suspend(struct device *dev) { struct i801_priv *priv = dev_get_drvdata(dev); - outb_p(priv->original_hstcnt, SMBHSTCNT(priv)); - pci_write_config_byte(priv->pci_dev, SMBHSTCFG, priv->original_hstcfg); + i2c_mark_adapter_suspended(&priv->adapter); + i801_restore_regs(priv); + return 0; } @@ -1824,6 +1803,7 @@ static int i801_resume(struct device *dev) i801_setup_hstcfg(priv); i801_enable_host_notify(&priv->adapter); + i2c_mark_adapter_resumed(&priv->adapter); return 0; } @@ -1842,16 +1822,11 @@ static struct pci_driver i801_driver = { }, }; -static int __init i2c_i801_init(void) +static int __init i2c_i801_init(struct pci_driver *drv) { if (dmi_name_in_vendors("FUJITSU")) input_apanel_init(); - return pci_register_driver(&i801_driver); -} - -static void __exit i2c_i801_exit(void) -{ - pci_unregister_driver(&i801_driver); + return pci_register_driver(drv); } MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>"); @@ -1859,5 +1834,4 @@ MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("I801 SMBus driver"); MODULE_LICENSE("GPL"); -module_init(i2c_i801_init); -module_exit(i2c_i801_exit); +module_driver(i801_driver, i2c_i801_init, pci_unregister_driver); diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 1a9b5a068ef1..a8b5719c3372 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -1442,15 +1442,19 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk)) return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_ARB].clk); + i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get_optional(&pdev->dev, "pmic"); + if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) { + dev_err(&pdev->dev, "cannot get pmic clock\n"); + return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk); + } + if (i2c->have_pmic) { - i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = devm_clk_get(&pdev->dev, "pmic"); - if (IS_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk)) { + if (!i2c->clocks[I2C_MT65XX_CLK_PMIC].clk) { dev_err(&pdev->dev, "cannot get pmic clock\n"); - return PTR_ERR(i2c->clocks[I2C_MT65XX_CLK_PMIC].clk); + return -ENODEV; } speed_clk = I2C_MT65XX_CLK_PMIC; } else { - i2c->clocks[I2C_MT65XX_CLK_PMIC].clk = NULL; speed_clk = I2C_MT65XX_CLK_MAIN; } diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index fd8403b07fa6..dc160cbc3155 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -19,11 +19,10 @@ #include <linux/platform_device.h> #include <linux/pinctrl/consumer.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/reset.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/delay.h> @@ -859,7 +858,7 @@ static int mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, struct device *dev) { - const struct of_device_id *device; + const struct mv64xxx_i2c_regs *data; struct device_node *np = dev->of_node; u32 bus_freq, tclk; int rc = 0; @@ -897,11 +896,11 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, */ drv_data->adapter.timeout = HZ; - device = of_match_device(mv64xxx_i2c_of_match_table, dev); - if (!device) + data = device_get_match_data(dev); + if (!data) return -ENODEV; - memcpy(&drv_data->reg_offsets, device->data, sizeof(drv_data->reg_offsets)); + memcpy(&drv_data->reg_offsets, data, sizeof(drv_data->reg_offsets)); /* * For controllers embedded in new SoCs activate the diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 58fd6fa3edf1..42165ef57946 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -25,11 +25,11 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_device.h> #include <linux/slab.h> #include <linux/platform_data/i2c-omap.h> #include <linux/pm_runtime.h> #include <linux/pinctrl/consumer.h> +#include <linux/property.h> /* I2C controller revisions */ #define OMAP_I2C_OMAP1_REV_2 0x20 @@ -1358,7 +1358,6 @@ omap_i2c_probe(struct platform_device *pdev) const struct omap_i2c_bus_platform_data *pdata = dev_get_platdata(&pdev->dev); struct device_node *node = pdev->dev.of_node; - const struct of_device_id *match; int irq; int r; u32 rev; @@ -1376,11 +1375,10 @@ omap_i2c_probe(struct platform_device *pdev) if (IS_ERR(omap->base)) return PTR_ERR(omap->base); - match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev); - if (match) { + if (pdev->dev.of_node) { u32 freq = I2C_MAX_STANDARD_MODE_FREQ; - pdata = match->data; + pdata = device_get_match_data(&pdev->dev); omap->flags = pdata->flags; of_property_read_u32(node, "clock-frequency", &freq); diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 4996a628fdae..8e57ebe595be 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -231,7 +231,7 @@ static void i2c_powermac_create_one(struct i2c_adapter *adap, struct i2c_board_info info = {}; struct i2c_client *newdev; - strncpy(info.type, type, sizeof(info.type)); + strscpy(info.type, type, sizeof(info.type)); info.addr = addr; newdev = i2c_new_client_device(adap, &info); if (IS_ERR(newdev)) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 29be05af826b..1d7648242749 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -32,6 +32,7 @@ #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> #include <linux/platform_data/i2c-pxa.h> +#include <linux/property.h> #include <linux/slab.h> /* I2C register field definitions */ @@ -1252,10 +1253,8 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c, enum pxa_i2c_types *i2c_types) { struct device_node *np = pdev->dev.of_node; - const struct of_device_id *of_id = - of_match_device(i2c_pxa_dt_ids, &pdev->dev); - if (!of_id) + if (!pdev->dev.of_node) return 1; /* For device tree we always use the dynamic or alias-assigned ID */ @@ -1264,7 +1263,7 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c, i2c->use_pio = of_property_read_bool(np, "mrvl,i2c-polling"); i2c->fast_mode = of_property_read_bool(np, "mrvl,i2c-fast-mode"); - *i2c_types = (enum pxa_i2c_types)(of_id->data); + *i2c_types = (enum pxa_i2c_types)device_get_match_data(&pdev->dev); return 0; } diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 229353e96e09..6d829ed2f868 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -722,6 +722,7 @@ static const struct i2c_algorithm geni_i2c_algo = { #ifdef CONFIG_ACPI static const struct acpi_device_id geni_i2c_acpi_match[] = { { "QCOM0220"}, + { "QCOM0411" }, { }, }; MODULE_DEVICE_TABLE(acpi, geni_i2c_acpi_match); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index a32a93f9a60d..829ac053bbb7 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -41,6 +41,10 @@ #define ICSAR 0x1C /* slave address */ #define ICMAR 0x20 /* master address */ #define ICRXTX 0x24 /* data port */ +#define ICCCR2 0x28 /* Clock control 2 */ +#define ICMPR 0x2C /* SCL mask control */ +#define ICHPR 0x30 /* SCL HIGH control */ +#define ICLPR 0x34 /* SCL LOW control */ #define ICFBSCR 0x38 /* first bit setup cycle (Gen3) */ #define ICDMAER 0x3c /* DMA enable (Gen3) */ @@ -84,11 +88,25 @@ #define RMDMAE BIT(1) /* DMA Master Received Enable */ #define TMDMAE BIT(0) /* DMA Master Transmitted Enable */ +/* ICCCR2 */ +#define CDFD BIT(2) /* CDF Disable */ +#define HLSE BIT(1) /* HIGH/LOW Separate Control Enable */ +#define SME BIT(0) /* SCL Mask Enable */ + /* ICFBSCR */ #define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */ #define RCAR_MIN_DMA_LEN 8 +/* SCL low/high ratio 5:4 to meet all I2C timing specs (incl safety margin) */ +#define RCAR_SCLD_RATIO 5 +#define RCAR_SCHD_RATIO 4 +/* + * SMD should be smaller than SCLD/SCHD and is always around 20 in the docs. + * Thus, we simply use 20 which works for low and high speeds. + */ +#define RCAR_DEFAULT_SMD 20 + #define RCAR_BUS_PHASE_START (MDBS | MIE | ESG) #define RCAR_BUS_PHASE_DATA (MDBS | MIE) #define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB) @@ -128,6 +146,8 @@ struct rcar_i2c_priv { int pos; u32 icccr; + u16 schd; + u16 scld; u8 recovery_icmcr; /* protected by adapter lock */ enum rcar_i2c_type devtype; struct i2c_client *slave; @@ -216,11 +236,16 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv) rcar_i2c_write(priv, ICMCR, MDBS); rcar_i2c_write(priv, ICMSR, 0); /* start clock */ - rcar_i2c_write(priv, ICCCR, priv->icccr); - - if (priv->devtype == I2C_RCAR_GEN3) + if (priv->devtype < I2C_RCAR_GEN3) { + rcar_i2c_write(priv, ICCCR, priv->icccr); + } else { + rcar_i2c_write(priv, ICCCR2, CDFD | HLSE | SME); + rcar_i2c_write(priv, ICCCR, priv->icccr); + rcar_i2c_write(priv, ICMPR, RCAR_DEFAULT_SMD); + rcar_i2c_write(priv, ICHPR, priv->schd); + rcar_i2c_write(priv, ICLPR, priv->scld); rcar_i2c_write(priv, ICFBSCR, TCYC17); - + } } static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) @@ -241,7 +266,7 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv) { - u32 scgd, cdf, round, ick, sum, scl, cdf_width; + u32 cdf, round, ick, sum, scl, cdf_width; unsigned long rate; struct device *dev = rcar_i2c_priv_to_dev(priv); struct i2c_timings t = { @@ -254,27 +279,17 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv) /* Fall back to previously used values if not supplied */ i2c_parse_fw_timings(dev, &t, false); - switch (priv->devtype) { - case I2C_RCAR_GEN1: - cdf_width = 2; - break; - case I2C_RCAR_GEN2: - case I2C_RCAR_GEN3: - cdf_width = 3; - break; - default: - dev_err(dev, "device type error\n"); - return -EIO; - } - /* * calculate SCL clock * see - * ICCCR + * ICCCR (and ICCCR2 for Gen3+) * * ick = clkp / (1 + CDF) * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick]) * + * for Gen3+: + * SCL = clkp / (8 + SMD * 2 + SCLD + SCHD +F[(ticf + tr + intd) * clkp]) + * * ick : I2C internal clock < 20 MHz * ticf : I2C SCL falling time * tr : I2C SCL rising time @@ -284,52 +299,82 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv) */ rate = clk_get_rate(priv->clk); cdf = rate / 20000000; - if (cdf >= 1U << cdf_width) { - dev_err(dev, "Input clock %lu too high\n", rate); - return -EIO; - } - ick = rate / (cdf + 1); + cdf_width = (priv->devtype == I2C_RCAR_GEN1) ? 2 : 3; + if (cdf >= 1U << cdf_width) + goto err_no_val; + + /* On Gen3+, we use cdf only for the filters, not as a SCL divider */ + ick = rate / (priv->devtype < I2C_RCAR_GEN3 ? (cdf + 1) : 1); /* - * it is impossible to calculate large scale - * number on u32. separate it + * It is impossible to calculate a large scale number on u32. Separate it. * * F[(ticf + tr + intd) * ick] with sum = (ticf + tr + intd) * = F[sum * ick / 1000000000] * = F[(ick / 1000000) * sum / 1000] */ sum = t.scl_fall_ns + t.scl_rise_ns + t.scl_int_delay_ns; - round = (ick + 500000) / 1000000 * sum; - round = (round + 500) / 1000; + round = DIV_ROUND_CLOSEST(ick, 1000000); + round = DIV_ROUND_CLOSEST(round * sum, 1000); - /* - * SCL = ick / (20 + SCGD * 8 + F[(ticf + tr + intd) * ick]) - * - * Calculation result (= SCL) should be less than - * bus_speed for hardware safety - * - * We could use something along the lines of - * div = ick / (bus_speed + 1) + 1; - * scgd = (div - 20 - round + 7) / 8; - * scl = ick / (20 + (scgd * 8) + round); - * (not fully verified) but that would get pretty involved - */ - for (scgd = 0; scgd < 0x40; scgd++) { - scl = ick / (20 + (scgd * 8) + round); - if (scl <= t.bus_freq_hz) - goto scgd_find; - } - dev_err(dev, "it is impossible to calculate best SCL\n"); - return -EIO; + if (priv->devtype < I2C_RCAR_GEN3) { + u32 scgd; + /* + * SCL = ick / (20 + 8 * SCGD + F[(ticf + tr + intd) * ick]) + * 20 + 8 * SCGD + F[...] = ick / SCL + * SCGD = ((ick / SCL) - 20 - F[...]) / 8 + * Result (= SCL) should be less than bus_speed for hardware safety + */ + scgd = DIV_ROUND_UP(ick, t.bus_freq_hz ?: 1); + scgd = DIV_ROUND_UP(scgd - 20 - round, 8); + scl = ick / (20 + 8 * scgd + round); + + if (scgd > 0x3f) + goto err_no_val; -scgd_find: - dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n", - scl, t.bus_freq_hz, rate, round, cdf, scgd); + dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u, SCGD: %u\n", + scl, t.bus_freq_hz, rate, round, cdf, scgd); - /* keep icccr value */ - priv->icccr = scgd << cdf_width | cdf; + priv->icccr = scgd << cdf_width | cdf; + } else { + u32 x, sum_ratio = RCAR_SCHD_RATIO + RCAR_SCLD_RATIO; + /* + * SCLD/SCHD ratio and SMD default value are explained above + * where they are defined. With these definitions, we can compute + * x as a base value for the SCLD/SCHD ratio: + * + * SCL = clkp / (8 + 2 * SMD + SCLD + SCHD + F[(ticf + tr + intd) * clkp]) + * SCL = clkp / (8 + 2 * RCAR_DEFAULT_SMD + RCAR_SCLD_RATIO * x + * + RCAR_SCHD_RATIO * x + F[...]) + * + * with: sum_ratio = RCAR_SCLD_RATIO + RCAR_SCHD_RATIO + * and: smd = RCAR_DEFAULT_SMD + * + * SCL = clkp / (8 + 2 * smd + sum_ratio * x + F[...]) + * 8 + 2 * smd + sum_ratio * x + F[...] = clkp / SCL + * x = ((clkp / SCL) - 8 - 2 * smd - F[...]) / sum_ratio + */ + x = DIV_ROUND_UP(rate, t.bus_freq_hz ?: 1); + x = DIV_ROUND_UP(x - 8 - 2 * RCAR_DEFAULT_SMD - round, sum_ratio); + scl = rate / (8 + 2 * RCAR_DEFAULT_SMD + sum_ratio * x + round); + + /* Bail out if values don't fit into 16 bit or SMD became too large */ + if (x * RCAR_SCLD_RATIO > 0xffff || RCAR_DEFAULT_SMD > x * RCAR_SCHD_RATIO) + goto err_no_val; + + priv->icccr = cdf; + priv->schd = RCAR_SCHD_RATIO * x; + priv->scld = RCAR_SCLD_RATIO * x; + + dev_dbg(dev, "clk %u/%u(%lu), round %u, CDF: %u SCHD %u SCLD %u\n", + scl, t.bus_freq_hz, rate, round, cdf, priv->schd, priv->scld); + } return 0; + +err_no_val: + dev_err(dev, "it is impossible to calculate best SCL\n"); + return -EINVAL; } /* @@ -843,12 +888,10 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, /* Gen3 needs a reset before allowing RXDMA once */ if (priv->devtype == I2C_RCAR_GEN3) { - priv->flags |= ID_P_NO_RXDMA; - if (!IS_ERR(priv->rstc)) { - ret = rcar_i2c_do_reset(priv); - if (ret == 0) - priv->flags &= ~ID_P_NO_RXDMA; - } + priv->flags &= ~ID_P_NO_RXDMA; + ret = rcar_i2c_do_reset(priv); + if (ret) + goto out; } rcar_i2c_init(priv); @@ -1099,15 +1142,6 @@ static int rcar_i2c_probe(struct platform_device *pdev) irqhandler = rcar_i2c_gen2_irq; } - if (priv->devtype == I2C_RCAR_GEN3) { - priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (!IS_ERR(priv->rstc)) { - ret = reset_control_status(priv->rstc); - if (ret < 0) - priv->rstc = ERR_PTR(-ENOTSUPP); - } - } - /* Stay always active when multi-master to keep arbitration working */ if (of_property_read_bool(dev->of_node, "multi-master")) priv->flags |= ID_P_PM_BLOCKED; @@ -1117,6 +1151,18 @@ static int rcar_i2c_probe(struct platform_device *pdev) if (of_property_read_bool(dev->of_node, "smbus")) priv->flags |= ID_P_HOST_NOTIFY; + if (priv->devtype == I2C_RCAR_GEN3) { + priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(priv->rstc)) { + ret = PTR_ERR(priv->rstc); + goto out_pm_put; + } + + ret = reset_control_status(priv->rstc); + if (ret < 0) + goto out_pm_put; + } + ret = platform_get_irq(pdev, 0); if (ret < 0) goto out_pm_put; diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index f0ee8871d5ae..e43ff483c56e 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -313,7 +313,7 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t) * frequency with only 62 clock ticks max (31 high, 31 low). * Aim for a duty of 60% LOW, 40% HIGH. */ - total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz); + total_ticks = DIV_ROUND_UP(rate, t->bus_freq_hz ?: 1); for (cks = 0; cks < 7; cks++) { /* diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 127eb3805fac..c56886af724e 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -133,7 +133,7 @@ static const struct platform_device_id s3c24xx_driver_ids[] = { }; MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); -static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat); +static void i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat); #ifdef CONFIG_OF static const struct of_device_id s3c24xx_i2c_match[] = { @@ -377,11 +377,10 @@ static inline int is_msgend(struct s3c24xx_i2c *i2c) /* * process an interrupt and work out what to do */ -static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) +static void i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) { unsigned long tmp; unsigned char byte; - int ret = 0; switch (i2c->state) { @@ -544,7 +543,7 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) tmp &= ~S3C2410_IICCON_IRQPEND; writel(tmp, i2c->regs + S3C2410_IICCON); out: - return ret; + return; } /* diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index ecc54792a66f..859ac0cf7f6c 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -783,23 +783,17 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) return -EINVAL; } - i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); + i2c_dev->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c_dev->clk)) { - dev_err(&pdev->dev, "Error: Missing controller clock\n"); + dev_err(&pdev->dev, "Failed to enable clock\n"); return PTR_ERR(i2c_dev->clk); } - ret = clk_prepare_enable(i2c_dev->clk); - if (ret) { - dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n"); - return ret; - } rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); - if (IS_ERR(rst)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rst), - "Error: Missing reset ctrl\n"); - goto clk_free; - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), + "Error: Missing reset ctrl\n"); + reset_control_assert(rst); udelay(2); reset_control_deassert(rst); @@ -816,7 +810,7 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Failed to request irq event %i\n", irq_event); - goto clk_free; + return ret; } ret = devm_request_irq(&pdev->dev, irq_error, stm32f4_i2c_isr_error, 0, @@ -824,12 +818,12 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Failed to request irq error %i\n", irq_error); - goto clk_free; + return ret; } ret = stm32f4_i2c_hw_config(i2c_dev); if (ret) - goto clk_free; + return ret; adap = &i2c_dev->adap; i2c_set_adapdata(adap, i2c_dev); @@ -845,7 +839,7 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) ret = i2c_add_adapter(adap); if (ret) - goto clk_free; + return ret; platform_set_drvdata(pdev, i2c_dev); @@ -854,10 +848,6 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) dev_info(i2c_dev->dev, "STM32F4 I2C driver registered\n"); return 0; - -clk_free: - clk_disable_unprepare(i2c_dev->clk); - return ret; } static void stm32f4_i2c_remove(struct platform_device *pdev) @@ -865,8 +855,6 @@ static void stm32f4_i2c_remove(struct platform_device *pdev) struct stm32f4_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(&i2c_dev->adap); - - clk_unprepare(i2c_dev->clk); } static const struct of_device_id stm32f4_i2c_match[] = { diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 0d3c9a041b56..983509936727 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -325,6 +325,7 @@ struct stm32f7_i2c_alert { * @dnf_dt: value of digital filter requested via dt * @dnf: value of digital filter to apply * @alert: SMBus alert specific data + * @atomic: boolean indicating that current transfer is atomic */ struct stm32f7_i2c_dev { struct i2c_adapter adap; @@ -357,6 +358,7 @@ struct stm32f7_i2c_dev { u32 dnf_dt; u32 dnf; struct stm32f7_i2c_alert *alert; + bool atomic; }; /* @@ -915,7 +917,8 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, /* Configure DMA or enable RX/TX interrupt */ i2c_dev->use_dma = false; - if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) { + if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN + && !i2c_dev->atomic) { ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma, msg->flags & I2C_M_RD, f7_msg->count, f7_msg->buf, @@ -939,6 +942,9 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev, cr1 |= STM32F7_I2C_CR1_TXDMAEN; } + if (i2c_dev->atomic) + cr1 &= ~STM32F7_I2C_ALL_IRQ_MASK; /* Disable all interrupts */ + /* Configure Start/Repeated Start */ cr2 |= STM32F7_I2C_CR2_START; @@ -1673,7 +1679,22 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data) return IRQ_HANDLED; } -static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, +static int stm32f7_i2c_wait_polling(struct stm32f7_i2c_dev *i2c_dev) +{ + ktime_t timeout = ktime_add_ms(ktime_get(), i2c_dev->adap.timeout); + + while (ktime_compare(ktime_get(), timeout) < 0) { + udelay(5); + stm32f7_i2c_isr_event(0, i2c_dev); + + if (completion_done(&i2c_dev->complete)) + return 1; + } + + return 0; +} + +static int stm32f7_i2c_xfer_core(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); @@ -1697,8 +1718,12 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, stm32f7_i2c_xfer_msg(i2c_dev, msgs); - time_left = wait_for_completion_timeout(&i2c_dev->complete, - i2c_dev->adap.timeout); + if (!i2c_dev->atomic) + time_left = wait_for_completion_timeout(&i2c_dev->complete, + i2c_dev->adap.timeout); + else + time_left = stm32f7_i2c_wait_polling(i2c_dev); + ret = f7_msg->result; if (ret) { if (i2c_dev->use_dma) @@ -1730,6 +1755,24 @@ pm_free: return (ret < 0) ? ret : num; } +static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], int num) +{ + struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); + + i2c_dev->atomic = false; + return stm32f7_i2c_xfer_core(i2c_adap, msgs, num); +} + +static int stm32f7_i2c_xfer_atomic(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], int num) +{ + struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); + + i2c_dev->atomic = true; + return stm32f7_i2c_xfer_core(i2c_adap, msgs, num); +} + static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, @@ -2098,6 +2141,7 @@ static u32 stm32f7_i2c_func(struct i2c_adapter *adap) static const struct i2c_algorithm stm32f7_i2c_algo = { .master_xfer = stm32f7_i2c_xfer, + .master_xfer_atomic = stm32f7_i2c_xfer_atomic, .smbus_xfer = stm32f7_i2c_smbus_xfer, .functionality = stm32f7_i2c_func, .reg_slave = stm32f7_i2c_reg_slave, @@ -2134,23 +2178,16 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) i2c_dev->wakeup_src = of_property_read_bool(pdev->dev.of_node, "wakeup-source"); - i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); + i2c_dev->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(i2c_dev->clk)) return dev_err_probe(&pdev->dev, PTR_ERR(i2c_dev->clk), - "Failed to get controller clock\n"); - - ret = clk_prepare_enable(i2c_dev->clk); - if (ret) { - dev_err(&pdev->dev, "Failed to prepare_enable clock\n"); - return ret; - } + "Failed to enable controller clock\n"); rst = devm_reset_control_get(&pdev->dev, NULL); - if (IS_ERR(rst)) { - ret = dev_err_probe(&pdev->dev, PTR_ERR(rst), - "Error: Missing reset ctrl\n"); - goto clk_free; - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), + "Error: Missing reset ctrl\n"); + reset_control_assert(rst); udelay(2); reset_control_deassert(rst); @@ -2165,7 +2202,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Failed to request irq event %i\n", irq_event); - goto clk_free; + return ret; } ret = devm_request_irq(&pdev->dev, irq_error, stm32f7_i2c_isr_error, 0, @@ -2173,29 +2210,28 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "Failed to request irq error %i\n", irq_error); - goto clk_free; + return ret; } setup = of_device_get_match_data(&pdev->dev); if (!setup) { dev_err(&pdev->dev, "Can't get device data\n"); - ret = -ENODEV; - goto clk_free; + return -ENODEV; } i2c_dev->setup = *setup; ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup); if (ret) - goto clk_free; + return ret; /* Setup Fast mode plus if necessary */ if (i2c_dev->bus_rate > I2C_MAX_FAST_MODE_FREQ) { ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev); if (ret) - goto clk_free; + return ret; ret = stm32f7_i2c_write_fm_plus_bits(i2c_dev, true); if (ret) - goto clk_free; + return ret; } adap = &i2c_dev->adap; @@ -2306,9 +2342,6 @@ clr_wakeup_capable: fmp_clear: stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); -clk_free: - clk_disable_unprepare(i2c_dev->clk); - return ret; } @@ -2342,8 +2375,6 @@ static void stm32f7_i2c_remove(struct platform_device *pdev) } stm32f7_i2c_write_fm_plus_bits(i2c_dev, false); - - clk_disable_unprepare(i2c_dev->clk); } static int __maybe_unused stm32f7_i2c_runtime_suspend(struct device *dev) diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index fa6020dced59..85e035e7a1d7 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -201,6 +201,11 @@ static int p2wi_probe(struct platform_device *pdev) return -EINVAL; } + if (clk_freq == 0) { + dev_err(dev, "clock-frequency is set to 0 in DT\n"); + return -EINVAL; + } + if (of_get_child_count(np) > 1) { dev_err(dev, "P2WI only supports one slave device\n"); return -EINVAL; |