Commit c77756d3 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'i2c-for-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:
 "Minor changes to the I2C core. Most changes are in drivers:

  The i801 and designware drivers received most of the changes,
  including refactorings and some additions.

  Recovery changes for the iMX and iMX-LPI2C are now utilizing the
  generic i2c support.

  The Cadence driver now supports system suspend and resume.

  The hisi, mpc, sh_mobile, and npcm drivers have undergone some
  cleanups and improvements. Meanwhile, Uwe continues his work on
  converting the "remove" callback to become a void function.

  The pca954x mux driver now supports additional configurations, such as
  isolating faulty channels and flushing stuck buses, among others.

  Support has been added for Renesas r8a779h0, i.MX95 LPI2C, and
  Microchip sam9x7. Meanwhile, Geert lays the groundwork for the
  upcoming R-Car Gen4"

* tag 'i2c-for-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (34 commits)
  i2c: sprd: Convert to platform remove callback returning void
  Documentation: i2c: Document that client auto-detection is a legacy mechanism
  i2c: remove redundant condition
  i2c: rcar: Prepare for the advent of ARCH_RCAR_GEN4
  i2c: imx-lpi2c: add generic GPIO recovery for LPI2C
  i2c: cadence: Add system suspend and resume PM support
  i2c: mpc: remove outdated macro
  i2c: mpc: use proper binding for transfer timeouts
  dt-bindings: i2c: mpc: use proper binding for transfer timeouts
  i2c: smbus: Prepare i2c_register_spd for usage on muxed segments
  i2c: constify the struct device_type usage
  i2c: designware: Implement generic polling mode code for Wangxun 10Gb NIC
  i2c: designware: Fix RX FIFO depth define on Wangxun 10Gb NIC
  i2c: designware: Move interrupt handling functions before i2c_dw_xfer()
  i2c: designware: Use accessors to DW_IC_INTR_MASK register
  i2c: designware: Do not enable interrupts shortly in polling mode
  i2c: designware: Uniform initialization flow for polling mode
  dt-bindings: i2c: at91: Add sam9x7 compatible string
  dt-bindings: i2c: imx-lpi2c: add i.MX95 LPI2C
  i2c: Remove redundant comparison in npcm_i2c_reg_slave
  ...
parents 4757c3c6 91962feb
...@@ -25,7 +25,9 @@ properties: ...@@ -25,7 +25,9 @@ properties:
- atmel,sama5d2-i2c - atmel,sama5d2-i2c
- microchip,sam9x60-i2c - microchip,sam9x60-i2c
- items: - items:
- const: microchip,sama7g5-i2c - enum:
- microchip,sama7g5-i2c
- microchip,sam9x7-i2c
- const: microchip,sam9x60-i2c - const: microchip,sam9x60-i2c
reg: reg:
......
...@@ -24,6 +24,7 @@ properties: ...@@ -24,6 +24,7 @@ properties:
- fsl,imx8qm-lpi2c - fsl,imx8qm-lpi2c
- fsl,imx8ulp-lpi2c - fsl,imx8ulp-lpi2c
- fsl,imx93-lpi2c - fsl,imx93-lpi2c
- fsl,imx95-lpi2c
- const: fsl,imx7ulp-lpi2c - const: fsl,imx7ulp-lpi2c
reg: reg:
......
...@@ -96,6 +96,6 @@ examples: ...@@ -96,6 +96,6 @@ examples:
interrupts = <43 2>; interrupts = <43 2>;
interrupt-parent = <&mpic>; interrupt-parent = <&mpic>;
clock-frequency = <400000>; clock-frequency = <400000>;
i2c-scl-clk-low-timeout-us = <10000>; i2c-transfer-timeout-us = <10000>;
}; };
... ...
...@@ -71,6 +71,23 @@ properties: ...@@ -71,6 +71,23 @@ properties:
description: A voltage regulator supplying power to the chip. On PCA9846 description: A voltage regulator supplying power to the chip. On PCA9846
the regulator supplies power to VDD2 (core logic) and optionally to VDD1. the regulator supplies power to VDD2 (core logic) and optionally to VDD1.
maxim,isolate-stuck-channel:
type: boolean
description: Allows to use non faulty channels while a stuck channel is
isolated from the upstream bus. If not set all channels are isolated from
the upstream bus until the fault is cleared.
maxim,send-flush-out-sequence:
type: boolean
description: Send a flush-out sequence to stuck auxiliary buses
automatically after a stuck channel is being detected.
maxim,preconnection-wiggle-test-enable:
type: boolean
description: Send a STOP condition to the auxiliary buses when the switch
register activates a channel to detect a stuck high fault. On fault the
channel is isolated from the upstream bus.
required: required:
- compatible - compatible
- reg - reg
...@@ -95,6 +112,19 @@ allOf: ...@@ -95,6 +112,19 @@ allOf:
"#interrupt-cells": false "#interrupt-cells": false
interrupt-controller: false interrupt-controller: false
- if:
not:
properties:
compatible:
contains:
enum:
- maxim,max7357
then:
properties:
maxim,isolate-stuck-channel: false
maxim,send-flush-out-sequence: false
maxim,preconnection-wiggle-test-enable: false
unevaluatedProperties: false unevaluatedProperties: false
examples: examples:
......
...@@ -53,6 +53,7 @@ properties: ...@@ -53,6 +53,7 @@ properties:
- renesas,i2c-r8a779a0 # R-Car V3U - renesas,i2c-r8a779a0 # R-Car V3U
- renesas,i2c-r8a779f0 # R-Car S4-8 - renesas,i2c-r8a779f0 # R-Car S4-8
- renesas,i2c-r8a779g0 # R-Car V4H - renesas,i2c-r8a779g0 # R-Car V4H
- renesas,i2c-r8a779h0 # R-Car V4M
- const: renesas,rcar-gen4-i2c # R-Car Gen4 - const: renesas,rcar-gen4-i2c # R-Car Gen4
reg: reg:
......
...@@ -48,10 +48,6 @@ driver model device node, and its I2C address. ...@@ -48,10 +48,6 @@ driver model device node, and its I2C address.
.id_table = foo_idtable, .id_table = foo_idtable,
.probe = foo_probe, .probe = foo_probe,
.remove = foo_remove, .remove = foo_remove,
/* if device autodetection is needed: */
.class = I2C_CLASS_SOMETHING,
.detect = foo_detect,
.address_list = normal_i2c,
.shutdown = foo_shutdown, /* optional */ .shutdown = foo_shutdown, /* optional */
.command = foo_command, /* optional, deprecated */ .command = foo_command, /* optional, deprecated */
...@@ -203,27 +199,8 @@ reference for later use. ...@@ -203,27 +199,8 @@ reference for later use.
Device Detection Device Detection
---------------- ----------------
Sometimes you do not know in advance which I2C devices are connected to The device detection mechanism comes with a number of disadvantages.
a given I2C bus. This is for example the case of hardware monitoring You need some reliable way to identify the supported devices
devices on a PC's SMBus. In that case, you may want to let your driver
detect supported devices automatically. This is how the legacy model
was working, and is now available as an extension to the standard
driver model.
You simply have to define a detect callback which will attempt to
identify supported devices (returning 0 for supported ones and -ENODEV
for unsupported ones), a list of addresses to probe, and a device type
(or class) so that only I2C buses which may have that type of device
connected (and not otherwise enumerated) will be probed. For example,
a driver for a hardware monitoring chip for which auto-detection is
needed would set its class to I2C_CLASS_HWMON, and only I2C adapters
with a class including I2C_CLASS_HWMON would be probed by this driver.
Note that the absence of matching classes does not prevent the use of
a device of that type on the given I2C adapter. All it prevents is
auto-detection; explicit instantiation of devices is still possible.
Note that this mechanism is purely optional and not suitable for all
devices. You need some reliable way to identify the supported devices
(typically using device-specific, dedicated identification registers), (typically using device-specific, dedicated identification registers),
otherwise misdetections are likely to occur and things can get wrong otherwise misdetections are likely to occur and things can get wrong
quickly. Keep in mind that the I2C protocol doesn't include any quickly. Keep in mind that the I2C protocol doesn't include any
...@@ -231,9 +208,8 @@ standard way to detect the presence of a chip at a given address, let ...@@ -231,9 +208,8 @@ standard way to detect the presence of a chip at a given address, let
alone a standard way to identify devices. Even worse is the lack of alone a standard way to identify devices. Even worse is the lack of
semantics associated to bus transfers, which means that the same semantics associated to bus transfers, which means that the same
transfer can be seen as a read operation by a chip and as a write transfer can be seen as a read operation by a chip and as a write
operation by another chip. For these reasons, explicit device operation by another chip. For these reasons, device detection is
instantiation should always be preferred to auto-detection where considered a legacy mechanism and shouldn't be used in new code.
possible.
Device Deletion Device Deletion
......
...@@ -1235,7 +1235,7 @@ config I2C_RCAR ...@@ -1235,7 +1235,7 @@ config I2C_RCAR
depends on ARCH_RENESAS || COMPILE_TEST depends on ARCH_RENESAS || COMPILE_TEST
select I2C_SLAVE select I2C_SLAVE
select I2C_SMBUS select I2C_SMBUS
select RESET_CONTROLLER if ARCH_RCAR_GEN3 select RESET_CONTROLLER if ARCH_RCAR_GEN3 || ARCH_RCAR_GEN4
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
R-Car I2C controller. R-Car I2C controller.
......
...@@ -1176,6 +1176,18 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) ...@@ -1176,6 +1176,18 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev)
return 0; return 0;
} }
static int __maybe_unused cdns_i2c_suspend(struct device *dev)
{
struct cdns_i2c *xi2c = dev_get_drvdata(dev);
i2c_mark_adapter_suspended(&xi2c->adap);
if (!pm_runtime_status_suspended(dev))
return cdns_i2c_runtime_suspend(dev);
return 0;
}
/** /**
* cdns_i2c_init - Controller initialisation * cdns_i2c_init - Controller initialisation
* @id: Device private data structure * @id: Device private data structure
...@@ -1219,7 +1231,28 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) ...@@ -1219,7 +1231,28 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev)
return 0; return 0;
} }
static int __maybe_unused cdns_i2c_resume(struct device *dev)
{
struct cdns_i2c *xi2c = dev_get_drvdata(dev);
int err;
err = cdns_i2c_runtime_resume(dev);
if (err)
return err;
if (pm_runtime_status_suspended(dev)) {
err = cdns_i2c_runtime_suspend(dev);
if (err)
return err;
}
i2c_mark_adapter_resumed(&xi2c->adap);
return 0;
}
static const struct dev_pm_ops cdns_i2c_dev_pm_ops = { static const struct dev_pm_ops cdns_i2c_dev_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(cdns_i2c_suspend, cdns_i2c_resume)
SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend, SET_RUNTIME_PM_OPS(cdns_i2c_runtime_suspend,
cdns_i2c_runtime_resume, NULL) cdns_i2c_runtime_resume, NULL)
}; };
......
...@@ -648,7 +648,7 @@ void i2c_dw_disable(struct dw_i2c_dev *dev) ...@@ -648,7 +648,7 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
__i2c_dw_disable(dev); __i2c_dw_disable(dev);
/* Disable all interrupts */ /* Disable all interrupts */
regmap_write(dev->map, DW_IC_INTR_MASK, 0); __i2c_dw_write_intr_mask(dev, 0);
regmap_read(dev->map, DW_IC_CLR_INTR, &dummy); regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
i2c_dw_release_lock(dev); i2c_dw_release_lock(dev);
......
...@@ -212,6 +212,7 @@ struct reset_control; ...@@ -212,6 +212,7 @@ struct reset_control;
* @msg_err: error status of the current transfer * @msg_err: error status of the current transfer
* @status: i2c master status, one of STATUS_* * @status: i2c master status, one of STATUS_*
* @abort_source: copy of the TX_ABRT_SOURCE register * @abort_source: copy of the TX_ABRT_SOURCE register
* @sw_mask: SW mask of DW_IC_INTR_MASK used in polling mode
* @irq: interrupt number for the i2c master * @irq: interrupt number for the i2c master
* @flags: platform specific flags like type of IO accessors or model * @flags: platform specific flags like type of IO accessors or model
* @adapter: i2c subsystem adapter node * @adapter: i2c subsystem adapter node
...@@ -270,6 +271,7 @@ struct dw_i2c_dev { ...@@ -270,6 +271,7 @@ struct dw_i2c_dev {
int msg_err; int msg_err;
unsigned int status; unsigned int status;
unsigned int abort_source; unsigned int abort_source;
unsigned int sw_mask;
int irq; int irq;
u32 flags; u32 flags;
struct i2c_adapter adapter; struct i2c_adapter adapter;
...@@ -303,6 +305,7 @@ struct dw_i2c_dev { ...@@ -303,6 +305,7 @@ struct dw_i2c_dev {
#define ACCESS_INTR_MASK BIT(0) #define ACCESS_INTR_MASK BIT(0)
#define ACCESS_NO_IRQ_SUSPEND BIT(1) #define ACCESS_NO_IRQ_SUSPEND BIT(1)
#define ARBITRATION_SEMAPHORE BIT(2) #define ARBITRATION_SEMAPHORE BIT(2)
#define ACCESS_POLLING BIT(3)
#define MODEL_MSCC_OCELOT BIT(8) #define MODEL_MSCC_OCELOT BIT(8)
#define MODEL_BAIKAL_BT1 BIT(9) #define MODEL_BAIKAL_BT1 BIT(9)
...@@ -318,7 +321,7 @@ struct dw_i2c_dev { ...@@ -318,7 +321,7 @@ struct dw_i2c_dev {
#define AMD_UCSI_INTR_EN 0xd #define AMD_UCSI_INTR_EN 0xd
#define TXGBE_TX_FIFO_DEPTH 4 #define TXGBE_TX_FIFO_DEPTH 4
#define TXGBE_RX_FIFO_DEPTH 0 #define TXGBE_RX_FIFO_DEPTH 1
struct i2c_dw_semaphore_callbacks { struct i2c_dw_semaphore_callbacks {
int (*probe)(struct dw_i2c_dev *dev); int (*probe)(struct dw_i2c_dev *dev);
...@@ -351,6 +354,24 @@ static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev) ...@@ -351,6 +354,24 @@ static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
dev->status &= ~STATUS_ACTIVE; dev->status &= ~STATUS_ACTIVE;
} }
static inline void __i2c_dw_write_intr_mask(struct dw_i2c_dev *dev,
unsigned int intr_mask)
{
unsigned int val = dev->flags & ACCESS_POLLING ? 0 : intr_mask;
regmap_write(dev->map, DW_IC_INTR_MASK, val);
dev->sw_mask = intr_mask;
}
static inline void __i2c_dw_read_intr_mask(struct dw_i2c_dev *dev,
unsigned int *intr_mask)
{
if (!(dev->flags & ACCESS_POLLING))
regmap_read(dev->map, DW_IC_INTR_MASK, intr_mask);
else
*intr_mask = dev->sw_mask;
}
void __i2c_dw_disable(struct dw_i2c_dev *dev); void __i2c_dw_disable(struct dw_i2c_dev *dev);
extern void i2c_dw_configure_master(struct dw_i2c_dev *dev); extern void i2c_dw_configure_master(struct dw_i2c_dev *dev);
......
...@@ -240,7 +240,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) ...@@ -240,7 +240,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
msgs[dev->msg_write_idx].addr | ic_tar); msgs[dev->msg_write_idx].addr | ic_tar);
/* Enforce disabled interrupts (due to HW issues) */ /* Enforce disabled interrupts (due to HW issues) */
regmap_write(dev->map, DW_IC_INTR_MASK, 0); __i2c_dw_write_intr_mask(dev, 0);
/* Enable the adapter */ /* Enable the adapter */
__i2c_dw_enable(dev); __i2c_dw_enable(dev);
...@@ -250,7 +250,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) ...@@ -250,7 +250,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
/* Clear and enable interrupts */ /* Clear and enable interrupts */
regmap_read(dev->map, DW_IC_CLR_INTR, &dummy); regmap_read(dev->map, DW_IC_CLR_INTR, &dummy);
regmap_write(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_MASTER_MASK); __i2c_dw_write_intr_mask(dev, DW_IC_INTR_MASTER_MASK);
} }
static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev) static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev)
...@@ -300,7 +300,6 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -300,7 +300,6 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
dev->msgs = msgs; dev->msgs = msgs;
dev->msgs_num = num_msgs; dev->msgs_num = num_msgs;
i2c_dw_xfer_init(dev); i2c_dw_xfer_init(dev);
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
/* Initiate messages read/write transaction */ /* Initiate messages read/write transaction */
for (msg_wrt_idx = 0; msg_wrt_idx < num_msgs; msg_wrt_idx++) { for (msg_wrt_idx = 0; msg_wrt_idx < num_msgs; msg_wrt_idx++) {
...@@ -355,68 +354,6 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs, ...@@ -355,68 +354,6 @@ static int amd_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
return 0; return 0;
} }
static int i2c_dw_poll_tx_empty(struct dw_i2c_dev *dev)
{
u32 val;
return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val,
val & DW_IC_INTR_TX_EMPTY,
100, 1000);
}
static int i2c_dw_poll_rx_full(struct dw_i2c_dev *dev)
{
u32 val;
return regmap_read_poll_timeout(dev->map, DW_IC_RAW_INTR_STAT, val,
val & DW_IC_INTR_RX_FULL,
100, 1000);
}
static int txgbe_i2c_dw_xfer_quirk(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num_msgs)
{
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
int msg_idx, buf_len, data_idx, ret;
unsigned int val, stop = 0;
u8 *buf;
dev->msgs = msgs;
dev->msgs_num = num_msgs;
i2c_dw_xfer_init(dev);
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
for (msg_idx = 0; msg_idx < num_msgs; msg_idx++) {
buf = msgs[msg_idx].buf;
buf_len = msgs[msg_idx].len;
for (data_idx = 0; data_idx < buf_len; data_idx++) {
if (msg_idx == num_msgs - 1 && data_idx == buf_len - 1)
stop |= BIT(9);
if (msgs[msg_idx].flags & I2C_M_RD) {
regmap_write(dev->map, DW_IC_DATA_CMD, 0x100 | stop);
ret = i2c_dw_poll_rx_full(dev);
if (ret)
return ret;
regmap_read(dev->map, DW_IC_DATA_CMD, &val);
buf[data_idx] = val;
} else {
ret = i2c_dw_poll_tx_empty(dev);
if (ret)
return ret;
regmap_write(dev->map, DW_IC_DATA_CMD,
buf[data_idx] | stop);
}
}
}
return num_msgs;
}
/* /*
* Initiate (and continue) low level master read/write transaction. * Initiate (and continue) low level master read/write transaction.
* This function is only called from i2c_dw_isr, and pumping i2c_msg * This function is only called from i2c_dw_isr, and pumping i2c_msg
...@@ -546,7 +483,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev) ...@@ -546,7 +483,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
if (dev->msg_err) if (dev->msg_err)
intr_mask = 0; intr_mask = 0;
regmap_write(dev->map, DW_IC_INTR_MASK, intr_mask); __i2c_dw_write_intr_mask(dev, intr_mask);
} }
static u8 static u8
...@@ -554,6 +491,7 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len) ...@@ -554,6 +491,7 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
{ {
struct i2c_msg *msgs = dev->msgs; struct i2c_msg *msgs = dev->msgs;
u32 flags = msgs[dev->msg_read_idx].flags; u32 flags = msgs[dev->msg_read_idx].flags;
unsigned int intr_mask;
/* /*
* Adjust the buffer length and mask the flag * Adjust the buffer length and mask the flag
...@@ -568,8 +506,9 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len) ...@@ -568,8 +506,9 @@ i2c_dw_recv_len(struct dw_i2c_dev *dev, u8 len)
* Received buffer length, re-enable TX_EMPTY interrupt * Received buffer length, re-enable TX_EMPTY interrupt
* to resume the SMBUS transaction. * to resume the SMBUS transaction.
*/ */
regmap_update_bits(dev->map, DW_IC_INTR_MASK, DW_IC_INTR_TX_EMPTY, __i2c_dw_read_intr_mask(dev, &intr_mask);
DW_IC_INTR_TX_EMPTY); intr_mask |= DW_IC_INTR_TX_EMPTY;
__i2c_dw_write_intr_mask(dev, intr_mask);
return len; return len;
} }
...@@ -633,6 +572,169 @@ i2c_dw_read(struct dw_i2c_dev *dev) ...@@ -633,6 +572,169 @@ i2c_dw_read(struct dw_i2c_dev *dev)
} }
} }
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
{
unsigned int stat, dummy;
/*
* The IC_INTR_STAT register just indicates "enabled" interrupts.
* The unmasked raw version of interrupt status bits is available
* in the IC_RAW_INTR_STAT register.
*
* That is,
* stat = readl(IC_INTR_STAT);
* equals to,
* stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
*
* The raw version might be useful for debugging purposes.
*/
if (!(dev->flags & ACCESS_POLLING)) {
regmap_read(dev->map, DW_IC_INTR_STAT, &stat);
} else {
regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
stat &= dev->sw_mask;
}
/*
* Do not use the IC_CLR_INTR register to clear interrupts, or
* you'll miss some interrupts, triggered during the period from
* readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
*
* Instead, use the separately-prepared IC_CLR_* registers.
*/
if (stat & DW_IC_INTR_RX_UNDER)
regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &dummy);
if (stat & DW_IC_INTR_RX_OVER)
regmap_read(dev->map, DW_IC_CLR_RX_OVER, &dummy);
if (stat & DW_IC_INTR_TX_OVER)
regmap_read(dev->map, DW_IC_CLR_TX_OVER, &dummy);
if (stat & DW_IC_INTR_RD_REQ)
regmap_read(dev->map, DW_IC_CLR_RD_REQ, &dummy);
if (stat & DW_IC_INTR_TX_ABRT) {
/*
* The IC_TX_ABRT_SOURCE register is cleared whenever
* the IC_CLR_TX_ABRT is read. Preserve it beforehand.
*/
regmap_read(dev->map, DW_IC_TX_ABRT_SOURCE, &dev->abort_source);
regmap_read(dev->map, DW_IC_CLR_TX_ABRT, &dummy);
}
if (stat & DW_IC_INTR_RX_DONE)
regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy);
if (stat & DW_IC_INTR_ACTIVITY)
regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy);
if ((stat & DW_IC_INTR_STOP_DET) &&
((dev->rx_outstanding == 0) || (stat & DW_IC_INTR_RX_FULL)))
regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy);
if (stat & DW_IC_INTR_START_DET)
regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy);
if (stat & DW_IC_INTR_GEN_CALL)
regmap_read(dev->map, DW_IC_CLR_GEN_CALL, &dummy);
return stat;
}
static void i2c_dw_process_transfer(struct dw_i2c_dev *dev, unsigned int stat)
{
if (stat & DW_IC_INTR_TX_ABRT) {
dev->cmd_err |= DW_IC_ERR_TX_ABRT;
dev->status &= ~STATUS_MASK;
dev->rx_outstanding = 0;
/*
* Anytime TX_ABRT is set, the contents of the tx/rx
* buffers are flushed. Make sure to skip them.
*/
__i2c_dw_write_intr_mask(dev, 0);
goto tx_aborted;
}
if (stat & DW_IC_INTR_RX_FULL)
i2c_dw_read(dev);
if (stat & DW_IC_INTR_TX_EMPTY)
i2c_dw_xfer_msg(dev);
/*
* No need to modify or disable the interrupt mask here.
* i2c_dw_xfer_msg() will take care of it according to
* the current transmit status.
*/
tx_aborted:
if (((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) &&
(dev->rx_outstanding == 0))
complete(&dev->cmd_complete);
else if (unlikely(dev->flags & ACCESS_INTR_MASK)) {
/* Workaround to trigger pending interrupt */
__i2c_dw_read_intr_mask(dev, &stat);
__i2c_dw_write_intr_mask(dev, 0);
__i2c_dw_write_intr_mask(dev, stat);
}
}
/*
* Interrupt service routine. This gets called whenever an I2C master interrupt
* occurs.
*/
static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
{
struct dw_i2c_dev *dev = dev_id;
unsigned int stat, enabled;
regmap_read(dev->map, DW_IC_ENABLE, &enabled);
regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
return IRQ_NONE;
if (pm_runtime_suspended(dev->dev) || stat == GENMASK(31, 0))
return IRQ_NONE;
dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat);
stat = i2c_dw_read_clear_intrbits(dev);
if (!(dev->status & STATUS_ACTIVE)) {
/*
* Unexpected interrupt in driver point of view. State
* variables are either unset or stale so acknowledge and
* disable interrupts for suppressing further interrupts if
* interrupt really came from this HW (E.g. firmware has left
* the HW active).
*/
__i2c_dw_write_intr_mask(dev, 0);
return IRQ_HANDLED;
}
i2c_dw_process_transfer(dev, stat);
return IRQ_HANDLED;
}
static int i2c_dw_wait_transfer(struct dw_i2c_dev *dev)
{
unsigned long timeout = dev->adapter.timeout;
unsigned int stat;
int ret;
if (!(dev->flags & ACCESS_POLLING)) {
ret = wait_for_completion_timeout(&dev->cmd_complete, timeout);
} else {
timeout += jiffies;
do {
ret = try_wait_for_completion(&dev->cmd_complete);
if (ret)
break;
stat = i2c_dw_read_clear_intrbits(dev);
if (stat)
i2c_dw_process_transfer(dev, stat);
else
/* Try save some power */
usleep_range(3, 25);
} while (time_before(jiffies, timeout));
}
return ret ? 0 : -ETIMEDOUT;
}
/* /*
* Prepare controller for a transaction and call i2c_dw_xfer_msg. * Prepare controller for a transaction and call i2c_dw_xfer_msg.
*/ */
...@@ -646,18 +748,10 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -646,18 +748,10 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
pm_runtime_get_sync(dev->dev); pm_runtime_get_sync(dev->dev);
/*
* Initiate I2C message transfer when polling mode is enabled,
* As it is polling based transfer mechanism, which does not support
* interrupt based functionalities of existing DesignWare driver.
*/
switch (dev->flags & MODEL_MASK) { switch (dev->flags & MODEL_MASK) {
case MODEL_AMD_NAVI_GPU: case MODEL_AMD_NAVI_GPU:
ret = amd_i2c_dw_xfer_quirk(adap, msgs, num); ret = amd_i2c_dw_xfer_quirk(adap, msgs, num);
goto done_nolock; goto done_nolock;
case MODEL_WANGXUN_SP:
ret = txgbe_i2c_dw_xfer_quirk(adap, msgs, num);
goto done_nolock;
default: default:
break; break;
} }
...@@ -685,12 +779,12 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -685,12 +779,12 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
i2c_dw_xfer_init(dev); i2c_dw_xfer_init(dev);
/* Wait for tx to complete */ /* Wait for tx to complete */
if (!wait_for_completion_timeout(&dev->cmd_complete, adap->timeout)) { ret = i2c_dw_wait_transfer(dev);
if (ret) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
/* i2c_dw_init implicitly disables the adapter */ /* i2c_dw_init_master() implicitly disables the adapter */
i2c_recover_bus(&dev->adapter); i2c_recover_bus(&dev->adapter);
i2c_dw_init_master(dev); i2c_dw_init_master(dev);
ret = -ETIMEDOUT;
goto done; goto done;
} }
...@@ -698,7 +792,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) ...@@ -698,7 +792,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
* We must disable the adapter before returning and signaling the end * We must disable the adapter before returning and signaling the end
* of the current transfer. Otherwise the hardware might continue * of the current transfer. Otherwise the hardware might continue
* generating interrupts which in turn causes a race condition with * generating interrupts which in turn causes a race condition with
* the following transfer. Needs some more investigation if the * the following transfer. Needs some more investigation if the
* additional interrupts are a hardware bug or this driver doesn't * additional interrupts are a hardware bug or this driver doesn't
* handle them correctly yet. * handle them correctly yet.
*/ */
...@@ -746,132 +840,6 @@ static const struct i2c_adapter_quirks i2c_dw_quirks = { ...@@ -746,132 +840,6 @@ static const struct i2c_adapter_quirks i2c_dw_quirks = {
.flags = I2C_AQ_NO_ZERO_LEN, .flags = I2C_AQ_NO_ZERO_LEN,
}; };
static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
{
unsigned int stat, dummy;
/*
* The IC_INTR_STAT register just indicates "enabled" interrupts.
* The unmasked raw version of interrupt status bits is available
* in the IC_RAW_INTR_STAT register.
*
* That is,
* stat = readl(IC_INTR_STAT);
* equals to,
* stat = readl(IC_RAW_INTR_STAT) & readl(IC_INTR_MASK);
*
* The raw version might be useful for debugging purposes.
*/
regmap_read(dev->map, DW_IC_INTR_STAT, &stat);
/*
* Do not use the IC_CLR_INTR register to clear interrupts, or
* you'll miss some interrupts, triggered during the period from
* readl(IC_INTR_STAT) to readl(IC_CLR_INTR).
*
* Instead, use the separately-prepared IC_CLR_* registers.
*/
if (stat & DW_IC_INTR_RX_UNDER)
regmap_read(dev->map, DW_IC_CLR_RX_UNDER, &dummy);
if (stat & DW_IC_INTR_RX_OVER)
regmap_read(dev->map, DW_IC_CLR_RX_OVER, &dummy);
if (stat & DW_IC_INTR_TX_OVER)
regmap_read(dev->map, DW_IC_CLR_TX_OVER, &dummy);
if (stat & DW_IC_INTR_RD_REQ)
regmap_read(dev->map, DW_IC_CLR_RD_REQ, &dummy);
if (stat & DW_IC_INTR_TX_ABRT) {
/*
* The IC_TX_ABRT_SOURCE register is cleared whenever
* the IC_CLR_TX_ABRT is read. Preserve it beforehand.
*/
regmap_read(dev->map, DW_IC_TX_ABRT_SOURCE, &dev->abort_source);
regmap_read(dev->map, DW_IC_CLR_TX_ABRT, &dummy);
}
if (stat & DW_IC_INTR_RX_DONE)
regmap_read(dev->map, DW_IC_CLR_RX_DONE, &dummy);
if (stat & DW_IC_INTR_ACTIVITY)
regmap_read(dev->map, DW_IC_CLR_ACTIVITY, &dummy);
if ((stat & DW_IC_INTR_STOP_DET) &&
((dev->rx_outstanding == 0) || (stat & DW_IC_INTR_RX_FULL)))
regmap_read(dev->map, DW_IC_CLR_STOP_DET, &dummy);
if (stat & DW_IC_INTR_START_DET)
regmap_read(dev->map, DW_IC_CLR_START_DET, &dummy);
if (stat & DW_IC_INTR_GEN_CALL)
regmap_read(dev->map, DW_IC_CLR_GEN_CALL, &dummy);
return stat;
}
/*
* Interrupt service routine. This gets called whenever an I2C master interrupt
* occurs.
*/
static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
{
struct dw_i2c_dev *dev = dev_id;
unsigned int stat, enabled;
regmap_read(dev->map, DW_IC_ENABLE, &enabled);
regmap_read(dev->map, DW_IC_RAW_INTR_STAT, &stat);
if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
return IRQ_NONE;
if (pm_runtime_suspended(dev->dev) || stat == GENMASK(31, 0))
return IRQ_NONE;
dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat);
stat = i2c_dw_read_clear_intrbits(dev);
if (!(dev->status & STATUS_ACTIVE)) {
/*
* Unexpected interrupt in driver point of view. State
* variables are either unset or stale so acknowledge and
* disable interrupts for suppressing further interrupts if
* interrupt really came from this HW (E.g. firmware has left
* the HW active).
*/
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
return IRQ_HANDLED;
}
if (stat & DW_IC_INTR_TX_ABRT) {
dev->cmd_err |= DW_IC_ERR_TX_ABRT;
dev->status &= ~STATUS_MASK;
dev->rx_outstanding = 0;
/*
* Anytime TX_ABRT is set, the contents of the tx/rx
* buffers are flushed. Make sure to skip them.
*/
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
goto tx_aborted;
}
if (stat & DW_IC_INTR_RX_FULL)
i2c_dw_read(dev);
if (stat & DW_IC_INTR_TX_EMPTY)
i2c_dw_xfer_msg(dev);
/*
* No need to modify or disable the interrupt mask here.
* i2c_dw_xfer_msg() will take care of it according to
* the current transmit status.
*/
tx_aborted:
if (((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) &&
(dev->rx_outstanding == 0))
complete(&dev->cmd_complete);
else if (unlikely(dev->flags & ACCESS_INTR_MASK)) {
/* Workaround to trigger pending interrupt */
regmap_read(dev->map, DW_IC_INTR_MASK, &stat);
regmap_write(dev->map, DW_IC_INTR_MASK, 0);
regmap_write(dev->map, DW_IC_INTR_MASK, stat);
}
return IRQ_HANDLED;
}
void i2c_dw_configure_master(struct dw_i2c_dev *dev) void i2c_dw_configure_master(struct dw_i2c_dev *dev)
{ {
struct i2c_timings *t = &dev->timings; struct i2c_timings *t = &dev->timings;
...@@ -953,31 +921,6 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) ...@@ -953,31 +921,6 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev)
return 0; return 0;
} }
static int i2c_dw_poll_adap_quirk(struct dw_i2c_dev *dev)
{
struct i2c_adapter *adap = &dev->adapter;
int ret;
pm_runtime_get_noresume(dev->dev);
ret = i2c_add_numbered_adapter(adap);
if (ret)
dev_err(dev->dev, "Failed to add adapter: %d\n", ret);
pm_runtime_put_noidle(dev->dev);
return ret;
}
static bool i2c_dw_is_model_poll(struct dw_i2c_dev *dev)
{
switch (dev->flags & MODEL_MASK) {
case MODEL_AMD_NAVI_GPU:
case MODEL_WANGXUN_SP:
return true;
default:
return false;
}
}
int i2c_dw_probe_master(struct dw_i2c_dev *dev) int i2c_dw_probe_master(struct dw_i2c_dev *dev)
{ {
struct i2c_adapter *adap = &dev->adapter; struct i2c_adapter *adap = &dev->adapter;
...@@ -1033,9 +976,6 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) ...@@ -1033,9 +976,6 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
adap->dev.parent = dev->dev; adap->dev.parent = dev->dev;
i2c_set_adapdata(adap, dev); i2c_set_adapdata(adap, dev);
if (i2c_dw_is_model_poll(dev))
return i2c_dw_poll_adap_quirk(dev);
if (dev->flags & ACCESS_NO_IRQ_SUSPEND) { if (dev->flags & ACCESS_NO_IRQ_SUSPEND) {
irq_flags = IRQF_NO_SUSPEND; irq_flags = IRQF_NO_SUSPEND;
} else { } else {
...@@ -1046,15 +986,17 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev) ...@@ -1046,15 +986,17 @@ int i2c_dw_probe_master(struct dw_i2c_dev *dev)
if (ret) if (ret)
return ret; return ret;
regmap_write(dev->map, DW_IC_INTR_MASK, 0); __i2c_dw_write_intr_mask(dev, 0);
i2c_dw_release_lock(dev); i2c_dw_release_lock(dev);
ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, irq_flags, if (!(dev->flags & ACCESS_POLLING)) {
dev_name(dev->dev), dev); ret = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr,
if (ret) { irq_flags, dev_name(dev->dev), dev);
dev_err(dev->dev, "failure requesting irq %i: %d\n", if (ret) {
dev->irq, ret); dev_err(dev->dev, "failure requesting irq %i: %d\n",
return ret; dev->irq, ret);
return ret;
}
} }
ret = i2c_dw_init_recovery_info(dev); ret = i2c_dw_init_recovery_info(dev);
......
...@@ -154,7 +154,7 @@ static int navi_amd_setup(struct pci_dev *pdev, struct dw_pci_controller *c) ...@@ -154,7 +154,7 @@ static int navi_amd_setup(struct pci_dev *pdev, struct dw_pci_controller *c)
{ {
struct dw_i2c_dev *dev = dev_get_drvdata(&pdev->dev); struct dw_i2c_dev *dev = dev_get_drvdata(&pdev->dev);
dev->flags |= MODEL_AMD_NAVI_GPU; dev->flags |= MODEL_AMD_NAVI_GPU | ACCESS_POLLING;
dev->timings.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ; dev->timings.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ;
return 0; return 0;
} }
......
...@@ -290,7 +290,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) ...@@ -290,7 +290,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
dev->flags = (uintptr_t)device_get_match_data(&pdev->dev); dev->flags = (uintptr_t)device_get_match_data(&pdev->dev);
if (device_property_present(&pdev->dev, "wx,i2c-snps-model")) if (device_property_present(&pdev->dev, "wx,i2c-snps-model"))
dev->flags = MODEL_WANGXUN_SP; dev->flags = MODEL_WANGXUN_SP | ACCESS_POLLING;
dev->dev = &pdev->dev; dev->dev = &pdev->dev;
dev->irq = irq; dev->irq = irq;
......
...@@ -57,6 +57,8 @@ ...@@ -57,6 +57,8 @@
#define HISI_I2C_FS_SPK_LEN_CNT GENMASK(7, 0) #define HISI_I2C_FS_SPK_LEN_CNT GENMASK(7, 0)
#define HISI_I2C_HS_SPK_LEN 0x003c #define HISI_I2C_HS_SPK_LEN 0x003c
#define HISI_I2C_HS_SPK_LEN_CNT GENMASK(7, 0) #define HISI_I2C_HS_SPK_LEN_CNT GENMASK(7, 0)
#define HISI_I2C_TX_INT_CLR 0x0040
#define HISI_I2C_TX_AEMPTY_INT BIT(0)
#define HISI_I2C_INT_MSTAT 0x0044 #define HISI_I2C_INT_MSTAT 0x0044
#define HISI_I2C_INT_CLR 0x0048 #define HISI_I2C_INT_CLR 0x0048
#define HISI_I2C_INT_MASK 0x004C #define HISI_I2C_INT_MASK 0x004C
...@@ -124,6 +126,11 @@ static void hisi_i2c_clear_int(struct hisi_i2c_controller *ctlr, u32 mask) ...@@ -124,6 +126,11 @@ static void hisi_i2c_clear_int(struct hisi_i2c_controller *ctlr, u32 mask)
writel_relaxed(mask, ctlr->iobase + HISI_I2C_INT_CLR); writel_relaxed(mask, ctlr->iobase + HISI_I2C_INT_CLR);
} }
static void hisi_i2c_clear_tx_int(struct hisi_i2c_controller *ctlr, u32 mask)
{
writel_relaxed(mask, ctlr->iobase + HISI_I2C_TX_INT_CLR);
}
static void hisi_i2c_handle_errors(struct hisi_i2c_controller *ctlr) static void hisi_i2c_handle_errors(struct hisi_i2c_controller *ctlr)
{ {
u32 int_err = ctlr->xfer_err, reg; u32 int_err = ctlr->xfer_err, reg;
...@@ -168,6 +175,7 @@ static int hisi_i2c_start_xfer(struct hisi_i2c_controller *ctlr) ...@@ -168,6 +175,7 @@ static int hisi_i2c_start_xfer(struct hisi_i2c_controller *ctlr)
writel(reg, ctlr->iobase + HISI_I2C_FIFO_CTRL); writel(reg, ctlr->iobase + HISI_I2C_FIFO_CTRL);
hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL); hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
hisi_i2c_clear_tx_int(ctlr, HISI_I2C_TX_AEMPTY_INT);
hisi_i2c_enable_int(ctlr, HISI_I2C_INT_ALL); hisi_i2c_enable_int(ctlr, HISI_I2C_INT_ALL);
return 0; return 0;
...@@ -266,7 +274,7 @@ static int hisi_i2c_read_rx_fifo(struct hisi_i2c_controller *ctlr) ...@@ -266,7 +274,7 @@ static int hisi_i2c_read_rx_fifo(struct hisi_i2c_controller *ctlr)
static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr) static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
{ {
int max_write = HISI_I2C_TX_FIFO_DEPTH; int max_write = HISI_I2C_TX_FIFO_DEPTH - HISI_I2C_TX_F_AE_THRESH;
bool need_restart = false, last_msg; bool need_restart = false, last_msg;
struct i2c_msg *cur_msg; struct i2c_msg *cur_msg;
u32 cmd, fifo_state; u32 cmd, fifo_state;
...@@ -323,6 +331,8 @@ static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr) ...@@ -323,6 +331,8 @@ static void hisi_i2c_xfer_msg(struct hisi_i2c_controller *ctlr)
*/ */
if (ctlr->msg_tx_idx == ctlr->msg_num) if (ctlr->msg_tx_idx == ctlr->msg_num)
hisi_i2c_disable_int(ctlr, HISI_I2C_INT_TX_EMPTY); hisi_i2c_disable_int(ctlr, HISI_I2C_INT_TX_EMPTY);
hisi_i2c_clear_tx_int(ctlr, HISI_I2C_TX_AEMPTY_INT);
} }
static irqreturn_t hisi_i2c_irq(int irq, void *context) static irqreturn_t hisi_i2c_irq(int irq, void *context)
...@@ -363,6 +373,7 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context) ...@@ -363,6 +373,7 @@ static irqreturn_t hisi_i2c_irq(int irq, void *context)
if (int_stat & HISI_I2C_INT_TRANS_CPLT) { if (int_stat & HISI_I2C_INT_TRANS_CPLT) {
hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL); hisi_i2c_disable_int(ctlr, HISI_I2C_INT_ALL);
hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL); hisi_i2c_clear_int(ctlr, HISI_I2C_INT_ALL);
hisi_i2c_clear_tx_int(ctlr, HISI_I2C_TX_AEMPTY_INT);
complete(ctlr->completion); complete(ctlr->completion);
} }
......
...@@ -205,6 +205,8 @@ ...@@ -205,6 +205,8 @@
#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \ #define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \
STATUS_ERROR_FLAGS) STATUS_ERROR_FLAGS)
#define SMBUS_LEN_SENTINEL (I2C_SMBUS_BLOCK_MAX + 1)
/* Older devices have their ID defined in <linux/pci_ids.h> */ /* Older devices have their ID defined in <linux/pci_ids.h> */
#define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3 #define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS 0x02a3
#define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS 0x06a3 #define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS 0x06a3
...@@ -328,11 +330,39 @@ MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n" ...@@ -328,11 +330,39 @@ MODULE_PARM_DESC(disable_features, "Disable selected driver features:\n"
"\t\t 0x10 don't use interrupts\n" "\t\t 0x10 don't use interrupts\n"
"\t\t 0x20 disable SMBus Host Notify "); "\t\t 0x20 disable SMBus Host Notify ");
static int i801_get_block_len(struct i801_priv *priv)
{
u8 len = inb_p(SMBHSTDAT0(priv));
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
pci_err(priv->pci_dev, "Illegal SMBus block read size %u\n", len);
return -EPROTO;
}
return len;
}
static int i801_check_and_clear_pec_error(struct i801_priv *priv)
{
u8 status;
if (!(priv->features & FEATURE_SMBUS_PEC))
return 0;
status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE;
if (status) {
outb_p(status, SMBAUXSTS(priv));
return -EBADMSG;
}
return 0;
}
/* Make sure the SMBus host is ready to start transmitting. /* Make sure the SMBus host is ready to start transmitting.
Return 0 if it is, -EBUSY if it is not. */ Return 0 if it is, -EBUSY if it is not. */
static int i801_check_pre(struct i801_priv *priv) static int i801_check_pre(struct i801_priv *priv)
{ {
int status; int status, result;
status = inb_p(SMBHSTSTS(priv)); status = inb_p(SMBHSTSTS(priv));
if (status & SMBHSTSTS_HOST_BUSY) { if (status & SMBHSTSTS_HOST_BUSY) {
...@@ -353,13 +383,9 @@ static int i801_check_pre(struct i801_priv *priv) ...@@ -353,13 +383,9 @@ static int i801_check_pre(struct i801_priv *priv)
* the hardware was already in this state when the driver * the hardware was already in this state when the driver
* started. * started.
*/ */
if (priv->features & FEATURE_SMBUS_PEC) { result = i801_check_and_clear_pec_error(priv);
status = inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE; if (result)
if (status) { pci_dbg(priv->pci_dev, "Clearing aux status flag CRCE\n");
pci_dbg(priv->pci_dev, "Clearing aux status flags (%02x)\n", status);
outb_p(status, SMBAUXSTS(priv));
}
}
return 0; return 0;
} }
...@@ -408,14 +434,12 @@ static int i801_check_post(struct i801_priv *priv, int status) ...@@ -408,14 +434,12 @@ static int i801_check_post(struct i801_priv *priv, int status)
* bit is harmless as long as it's cleared before * bit is harmless as long as it's cleared before
* the next operation. * the next operation.
*/ */
if ((priv->features & FEATURE_SMBUS_PEC) && result = i801_check_and_clear_pec_error(priv);
(inb_p(SMBAUXSTS(priv)) & SMBAUXSTS_CRCE)) { if (result) {
outb_p(SMBAUXSTS_CRCE, SMBAUXSTS(priv)); pci_dbg(priv->pci_dev, "PEC error\n");
result = -EBADMSG;
dev_dbg(&priv->pci_dev->dev, "PEC error\n");
} else { } else {
result = -ENXIO; result = -ENXIO;
dev_dbg(&priv->pci_dev->dev, "No response\n"); pci_dbg(priv->pci_dev, "No response\n");
} }
} }
if (status & SMBHSTSTS_BUS_ERR) { if (status & SMBHSTSTS_BUS_ERR) {
...@@ -512,12 +536,11 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, ...@@ -512,12 +536,11 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
if (read_write == I2C_SMBUS_READ || if (read_write == I2C_SMBUS_READ ||
command == I2C_SMBUS_BLOCK_PROC_CALL) { command == I2C_SMBUS_BLOCK_PROC_CALL) {
len = inb_p(SMBHSTDAT0(priv)); status = i801_get_block_len(priv);
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { if (status < 0)
status = -EPROTO;
goto out; goto out;
}
len = status;
data->block[0] = len; data->block[0] = len;
inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
...@@ -531,17 +554,17 @@ static int i801_block_transaction_by_block(struct i801_priv *priv, ...@@ -531,17 +554,17 @@ static int i801_block_transaction_by_block(struct i801_priv *priv,
static void i801_isr_byte_done(struct i801_priv *priv) static void i801_isr_byte_done(struct i801_priv *priv)
{ {
if (priv->is_read) { if (priv->is_read) {
/* For SMBus block reads, length is received with first byte */ /*
if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) && * At transfer start i801_smbus_block_transaction() marks
(priv->count == 0)) { * the block length as invalid. Check for this sentinel value
priv->len = inb_p(SMBHSTDAT0(priv)); * and read the block length from SMBHSTDAT0.
if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) { */
dev_err(&priv->pci_dev->dev, if (priv->len == SMBUS_LEN_SENTINEL) {
"Illegal SMBus block read size %d\n", priv->len = i801_get_block_len(priv);
priv->len); if (priv->len < 0)
/* FIXME: Recover */ /* FIXME: Recover */
priv->len = I2C_SMBUS_BLOCK_MAX; priv->len = I2C_SMBUS_BLOCK_MAX;
}
priv->data[-1] = priv->len; priv->data[-1] = priv->len;
} }
...@@ -688,13 +711,14 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, ...@@ -688,13 +711,14 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
if (status) if (status)
return status; return status;
if (i == 1 && read_write == I2C_SMBUS_READ /*
&& command != I2C_SMBUS_I2C_BLOCK_DATA) { * At transfer start i801_smbus_block_transaction() marks
len = inb_p(SMBHSTDAT0(priv)); * the block length as invalid. Check for this sentinel value
if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { * and read the block length from SMBHSTDAT0.
dev_err(&priv->pci_dev->dev, */
"Illegal SMBus block read size %d\n", if (len == SMBUS_LEN_SENTINEL) {
len); len = i801_get_block_len(priv);
if (len < 0) {
/* Recover */ /* Recover */
while (inb_p(SMBHSTSTS(priv)) & while (inb_p(SMBHSTSTS(priv)) &
SMBHSTSTS_HOST_BUSY) SMBHSTSTS_HOST_BUSY)
...@@ -792,77 +816,66 @@ static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data ...@@ -792,77 +816,66 @@ static int i801_simple_transaction(struct i801_priv *priv, union i2c_smbus_data
return 0; return 0;
} }
/* Block transaction function */ static int i801_smbus_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
static int i801_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data, u8 addr, u8 hstcmd, char read_write, int command)
u8 addr, u8 hstcmd, char read_write, int command)
{ {
int result = 0;
unsigned char hostc;
if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA) if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA)
data->block[0] = I2C_SMBUS_BLOCK_MAX; /* Mark block length as invalid */
data->block[0] = SMBUS_LEN_SENTINEL;
else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX) else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO; return -EPROTO;
switch (command) { if (command == I2C_SMBUS_BLOCK_PROC_CALL)
case I2C_SMBUS_BLOCK_DATA:
i801_set_hstadd(priv, addr, read_write);
outb_p(hstcmd, SMBHSTCMD(priv));
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/*
* NB: page 240 of ICH5 datasheet shows that the R/#W
* bit should be cleared here, even when reading.
* However if SPD Write Disable is set (Lynx Point and later),
* the read will fail if we don't set the R/#W bit.
*/
i801_set_hstadd(priv, addr,
priv->original_hstcfg & SMBHSTCFG_SPD_WD ?
read_write : I2C_SMBUS_WRITE);
if (read_write == I2C_SMBUS_READ) {
/* NB: page 240 of ICH5 datasheet also shows
* that DATA1 is the cmd field when reading
*/
outb_p(hstcmd, SMBHSTDAT1(priv));
} else
outb_p(hstcmd, SMBHSTCMD(priv));
if (read_write == I2C_SMBUS_WRITE) {
/* set I2C_EN bit in configuration register */
pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(priv->pci_dev, SMBHSTCFG,
hostc | SMBHSTCFG_I2C_EN);
} else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
dev_err(&priv->pci_dev->dev,
"I2C block read is unsupported!\n");
return -EOPNOTSUPP;
}
break;
case I2C_SMBUS_BLOCK_PROC_CALL:
/* Needs to be flagged as write transaction */ /* Needs to be flagged as write transaction */
i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE); i801_set_hstadd(priv, addr, I2C_SMBUS_WRITE);
else
i801_set_hstadd(priv, addr, read_write);
outb_p(hstcmd, SMBHSTCMD(priv));
if (priv->features & FEATURE_BLOCK_BUFFER)
return i801_block_transaction_by_block(priv, data, read_write, command);
else
return i801_block_transaction_byte_by_byte(priv, data, read_write, command);
}
static int i801_i2c_block_transaction(struct i801_priv *priv, union i2c_smbus_data *data,
u8 addr, u8 hstcmd, char read_write, int command)
{
int result;
u8 hostc;
if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
/*
* NB: page 240 of ICH5 datasheet shows that the R/#W bit should be cleared here,
* even when reading. However if SPD Write Disable is set (Lynx Point and later),
* the read will fail if we don't set the R/#W bit.
*/
i801_set_hstadd(priv, addr,
priv->original_hstcfg & SMBHSTCFG_SPD_WD ? read_write : I2C_SMBUS_WRITE);
/* NB: page 240 of ICH5 datasheet shows that DATA1 is the cmd field when reading */
if (read_write == I2C_SMBUS_READ)
outb_p(hstcmd, SMBHSTDAT1(priv));
else
outb_p(hstcmd, SMBHSTCMD(priv)); outb_p(hstcmd, SMBHSTCMD(priv));
break;
if (read_write == I2C_SMBUS_WRITE) {
/* set I2C_EN bit in configuration register */
pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc);
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN);
} else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) {
pci_err(priv->pci_dev, "I2C block read is unsupported!\n");
return -EOPNOTSUPP;
} }
/* Experience has shown that the block buffer can only be used for /* Block buffer isn't supported for I2C block transactions */
SMBus (not I2C) block transactions, even though the datasheet result = i801_block_transaction_byte_by_byte(priv, data, read_write, command);
doesn't mention this limitation. */
if ((priv->features & FEATURE_BLOCK_BUFFER) &&
command != I2C_SMBUS_I2C_BLOCK_DATA)
result = i801_block_transaction_by_block(priv, data,
read_write,
command);
else
result = i801_block_transaction_byte_by_byte(priv, data,
read_write,
command);
if (command == I2C_SMBUS_I2C_BLOCK_DATA /* restore saved configuration register value */
&& read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE)
/* restore saved configuration register value */
pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc); pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc);
}
return result; return result;
} }
...@@ -893,10 +906,10 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, ...@@ -893,10 +906,10 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC),
SMBAUXCTL(priv)); SMBAUXCTL(priv));
if (size == I2C_SMBUS_BLOCK_DATA || if (size == I2C_SMBUS_BLOCK_DATA || size == I2C_SMBUS_BLOCK_PROC_CALL)
size == I2C_SMBUS_I2C_BLOCK_DATA || ret = i801_smbus_block_transaction(priv, data, addr, command, read_write, size);
size == I2C_SMBUS_BLOCK_PROC_CALL) else if (size == I2C_SMBUS_I2C_BLOCK_DATA)
ret = i801_block_transaction(priv, data, addr, command, read_write, size); ret = i801_i2c_block_transaction(priv, data, addr, command, read_write, size);
else else
ret = i801_simple_transaction(priv, data, addr, command, read_write, size); ret = i801_simple_transaction(priv, data, addr, command, read_write, size);
...@@ -969,11 +982,10 @@ static const struct i2c_algorithm smbus_algorithm = { ...@@ -969,11 +982,10 @@ static const struct i2c_algorithm smbus_algorithm = {
.functionality = i801_func, .functionality = i801_func,
}; };
#define FEATURES_ICH5 (FEATURE_BLOCK_PROC | FEATURE_I2C_BLOCK_READ | \
FEATURE_IRQ | FEATURE_SMBUS_PEC | \
FEATURE_BLOCK_BUFFER | FEATURE_HOST_NOTIFY)
#define FEATURES_ICH4 (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER | \ #define FEATURES_ICH4 (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER | \
FEATURE_HOST_NOTIFY) FEATURE_HOST_NOTIFY)
#define FEATURES_ICH5 (FEATURES_ICH4 | FEATURE_BLOCK_PROC | \
FEATURE_I2C_BLOCK_READ | FEATURE_IRQ)
static const struct pci_device_id i801_ids[] = { static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) }, { PCI_DEVICE_DATA(INTEL, 82801AA_3, 0) },
...@@ -1117,7 +1129,7 @@ static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap) ...@@ -1117,7 +1129,7 @@ static void dmi_check_onboard_devices(const struct dmi_header *dm, void *adap)
{ {
int i, count; int i, count;
if (dm->type != 10) if (dm->type != DMI_ENTRY_ONBOARD_DEVICE)
return; return;
count = (dm->length - sizeof(struct dmi_header)) / 2; count = (dm->length - sizeof(struct dmi_header)) / 2;
...@@ -1447,8 +1459,7 @@ static inline void i801_del_mux(struct i801_priv *priv) { } ...@@ -1447,8 +1459,7 @@ static inline void i801_del_mux(struct i801_priv *priv) { }
#endif #endif
static struct platform_device * static struct platform_device *
i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, i801_add_tco_spt(struct pci_dev *pci_dev, struct resource *tco_res)
struct resource *tco_res)
{ {
static const struct itco_wdt_platform_data pldata = { static const struct itco_wdt_platform_data pldata = {
.name = "Intel PCH", .name = "Intel PCH",
...@@ -1479,8 +1490,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev, ...@@ -1479,8 +1490,7 @@ i801_add_tco_spt(struct i801_priv *priv, struct pci_dev *pci_dev,
} }
static struct platform_device * static struct platform_device *
i801_add_tco_cnl(struct i801_priv *priv, struct pci_dev *pci_dev, i801_add_tco_cnl(struct pci_dev *pci_dev, struct resource *tco_res)
struct resource *tco_res)
{ {
static const struct itco_wdt_platform_data pldata = { static const struct itco_wdt_platform_data pldata = {
.name = "Intel PCH", .name = "Intel PCH",
...@@ -1520,9 +1530,9 @@ static void i801_add_tco(struct i801_priv *priv) ...@@ -1520,9 +1530,9 @@ static void i801_add_tco(struct i801_priv *priv)
res->flags = IORESOURCE_IO; res->flags = IORESOURCE_IO;
if (priv->features & FEATURE_TCO_CNL) if (priv->features & FEATURE_TCO_CNL)
priv->tco_pdev = i801_add_tco_cnl(priv, pci_dev, tco_res); priv->tco_pdev = i801_add_tco_cnl(pci_dev, tco_res);
else else
priv->tco_pdev = i801_add_tco_spt(priv, pci_dev, tco_res); priv->tco_pdev = i801_add_tco_spt(pci_dev, tco_res);
if (IS_ERR(priv->tco_pdev)) if (IS_ERR(priv->tco_pdev))
dev_warn(&pci_dev->dev, "failed to create iTCO device\n"); dev_warn(&pci_dev->dev, "failed to create iTCO device\n");
......
...@@ -106,6 +106,7 @@ struct lpi2c_imx_struct { ...@@ -106,6 +106,7 @@ struct lpi2c_imx_struct {
unsigned int txfifosize; unsigned int txfifosize;
unsigned int rxfifosize; unsigned int rxfifosize;
enum lpi2c_imx_mode mode; enum lpi2c_imx_mode mode;
struct i2c_bus_recovery_info rinfo;
}; };
static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx, static void lpi2c_imx_intctrl(struct lpi2c_imx_struct *lpi2c_imx,
...@@ -133,6 +134,8 @@ static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx) ...@@ -133,6 +134,8 @@ static int lpi2c_imx_bus_busy(struct lpi2c_imx_struct *lpi2c_imx)
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n"); dev_dbg(&lpi2c_imx->adapter.dev, "bus not work\n");
if (lpi2c_imx->adapter.bus_recovery_info)
i2c_recover_bus(&lpi2c_imx->adapter);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
schedule(); schedule();
...@@ -190,6 +193,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx) ...@@ -190,6 +193,8 @@ static void lpi2c_imx_stop(struct lpi2c_imx_struct *lpi2c_imx)
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n"); dev_dbg(&lpi2c_imx->adapter.dev, "stop timeout\n");
if (lpi2c_imx->adapter.bus_recovery_info)
i2c_recover_bus(&lpi2c_imx->adapter);
break; break;
} }
schedule(); schedule();
...@@ -325,6 +330,8 @@ static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx) ...@@ -325,6 +330,8 @@ static int lpi2c_imx_txfifo_empty(struct lpi2c_imx_struct *lpi2c_imx)
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n"); dev_dbg(&lpi2c_imx->adapter.dev, "txfifo empty timeout\n");
if (lpi2c_imx->adapter.bus_recovery_info)
i2c_recover_bus(&lpi2c_imx->adapter);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
schedule(); schedule();
...@@ -526,6 +533,20 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id) ...@@ -526,6 +533,20 @@ static irqreturn_t lpi2c_imx_isr(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static int lpi2c_imx_init_recovery_info(struct lpi2c_imx_struct *lpi2c_imx,
struct platform_device *pdev)
{
struct i2c_bus_recovery_info *bri = &lpi2c_imx->rinfo;
bri->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(bri->pinctrl))
return PTR_ERR(bri->pinctrl);
lpi2c_imx->adapter.bus_recovery_info = bri;
return 0;
}
static u32 lpi2c_imx_func(struct i2c_adapter *adapter) static u32 lpi2c_imx_func(struct i2c_adapter *adapter)
{ {
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
...@@ -600,6 +621,12 @@ static int lpi2c_imx_probe(struct platform_device *pdev) ...@@ -600,6 +621,12 @@ static int lpi2c_imx_probe(struct platform_device *pdev)
lpi2c_imx->txfifosize = 1 << (temp & 0x0f); lpi2c_imx->txfifosize = 1 << (temp & 0x0f);
lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f); lpi2c_imx->rxfifosize = 1 << ((temp >> 8) & 0x0f);
/* Init optional bus recovery function */
ret = lpi2c_imx_init_recovery_info(lpi2c_imx, pdev);
/* Give it another chance if pinctrl used is not ready yet */
if (ret == -EPROBE_DEFER)
goto rpm_disable;
ret = i2c_add_adapter(&lpi2c_imx->adapter); ret = i2c_add_adapter(&lpi2c_imx->adapter);
if (ret) if (ret)
goto rpm_disable; goto rpm_disable;
......
...@@ -212,10 +212,6 @@ struct imx_i2c_struct { ...@@ -212,10 +212,6 @@ struct imx_i2c_struct {
const struct imx_i2c_hwdata *hwdata; const struct imx_i2c_hwdata *hwdata;
struct i2c_bus_recovery_info rinfo; struct i2c_bus_recovery_info rinfo;
struct pinctrl *pinctrl;
struct pinctrl_state *pinctrl_pins_default;
struct pinctrl_state *pinctrl_pins_gpio;
struct imx_i2c_dma *dma; struct imx_i2c_dma *dma;
struct i2c_client *slave; struct i2c_client *slave;
enum i2c_slave_event last_slave_event; enum i2c_slave_event last_slave_event;
...@@ -1362,24 +1358,6 @@ static int i2c_imx_xfer_atomic(struct i2c_adapter *adapter, ...@@ -1362,24 +1358,6 @@ static int i2c_imx_xfer_atomic(struct i2c_adapter *adapter,
return result; return result;
} }
static void i2c_imx_prepare_recovery(struct i2c_adapter *adap)
{
struct imx_i2c_struct *i2c_imx;
i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_gpio);
}
static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
{
struct imx_i2c_struct *i2c_imx;
i2c_imx = container_of(adap, struct imx_i2c_struct, adapter);
pinctrl_select_state(i2c_imx->pinctrl, i2c_imx->pinctrl_pins_default);
}
/* /*
* We switch SCL and SDA to their GPIO function and do some bitbanging * We switch SCL and SDA to their GPIO function and do some bitbanging
* for bus recovery. These alternative pinmux settings can be * for bus recovery. These alternative pinmux settings can be
...@@ -1390,43 +1368,13 @@ static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap) ...@@ -1390,43 +1368,13 @@ static void i2c_imx_unprepare_recovery(struct i2c_adapter *adap)
static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx,
struct platform_device *pdev) struct platform_device *pdev)
{ {
struct i2c_bus_recovery_info *rinfo = &i2c_imx->rinfo; struct i2c_bus_recovery_info *bri = &i2c_imx->rinfo;
i2c_imx->pinctrl = devm_pinctrl_get(&pdev->dev);
if (!i2c_imx->pinctrl) {
dev_info(&pdev->dev, "pinctrl unavailable, bus recovery not supported\n");
return 0;
}
if (IS_ERR(i2c_imx->pinctrl)) {
dev_info(&pdev->dev, "can't get pinctrl, bus recovery not supported\n");
return PTR_ERR(i2c_imx->pinctrl);
}
i2c_imx->pinctrl_pins_default = pinctrl_lookup_state(i2c_imx->pinctrl,
PINCTRL_STATE_DEFAULT);
i2c_imx->pinctrl_pins_gpio = pinctrl_lookup_state(i2c_imx->pinctrl,
"gpio");
rinfo->sda_gpiod = devm_gpiod_get_optional(&pdev->dev, "sda", GPIOD_IN);
rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER ||
PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else if (IS_ERR(rinfo->sda_gpiod) ||
IS_ERR(rinfo->scl_gpiod) ||
IS_ERR(i2c_imx->pinctrl_pins_default) ||
IS_ERR(i2c_imx->pinctrl_pins_gpio)) {
dev_dbg(&pdev->dev, "recovery information incomplete\n");
return 0;
}
dev_dbg(&pdev->dev, "using scl%s for recovery\n", bri->pinctrl = devm_pinctrl_get(&pdev->dev);
rinfo->sda_gpiod ? ",sda" : ""); if (IS_ERR(bri->pinctrl))
return PTR_ERR(bri->pinctrl);
rinfo->prepare_recovery = i2c_imx_prepare_recovery; i2c_imx->adapter.bus_recovery_info = bri;
rinfo->unprepare_recovery = i2c_imx_unprepare_recovery;
rinfo->recover_bus = i2c_generic_scl_recovery;
i2c_imx->adapter.bus_recovery_info = rinfo;
return 0; return 0;
} }
......
...@@ -30,8 +30,6 @@ ...@@ -30,8 +30,6 @@
#include <asm/mpc85xx.h> #include <asm/mpc85xx.h>
#include <sysdev/fsl_soc.h> #include <sysdev/fsl_soc.h>
#define DRV_NAME "mpc-i2c"
#define MPC_I2C_CLOCK_LEGACY 0 #define MPC_I2C_CLOCK_LEGACY 0
#define MPC_I2C_CLOCK_PRESERVE (~0U) #define MPC_I2C_CLOCK_PRESERVE (~0U)
...@@ -844,14 +842,14 @@ static int fsl_i2c_probe(struct platform_device *op) ...@@ -844,14 +842,14 @@ static int fsl_i2c_probe(struct platform_device *op)
mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock); mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock);
} }
/* /* Sadly, we have to support two deprecated bindings here */
* "fsl,timeout" has been marked as deprecated and, to maintain
* backward compatibility, we will only look for it if
* "i2c-scl-clk-low-timeout-us" is not present.
*/
result = of_property_read_u32(op->dev.of_node, result = of_property_read_u32(op->dev.of_node,
"i2c-scl-clk-low-timeout-us", "i2c-transfer-timeout-us",
&mpc_ops.timeout); &mpc_ops.timeout);
if (result == -EINVAL)
result = of_property_read_u32(op->dev.of_node,
"i2c-scl-clk-low-timeout-us",
&mpc_ops.timeout);
if (result == -EINVAL) if (result == -EINVAL)
result = of_property_read_u32(op->dev.of_node, result = of_property_read_u32(op->dev.of_node,
"fsl,timeout", &mpc_ops.timeout); "fsl,timeout", &mpc_ops.timeout);
...@@ -960,7 +958,7 @@ static struct platform_driver mpc_i2c_driver = { ...@@ -960,7 +958,7 @@ static struct platform_driver mpc_i2c_driver = {
.probe = fsl_i2c_probe, .probe = fsl_i2c_probe,
.remove_new = fsl_i2c_remove, .remove_new = fsl_i2c_remove,
.driver = { .driver = {
.name = DRV_NAME, .name = "mpc-i2c",
.of_match_table = mpc_i2c_of_match, .of_match_table = mpc_i2c_of_match,
.pm = &mpc_i2c_pm_ops, .pm = &mpc_i2c_pm_ops,
}, },
......
...@@ -1264,9 +1264,6 @@ static int npcm_i2c_reg_slave(struct i2c_client *client) ...@@ -1264,9 +1264,6 @@ static int npcm_i2c_reg_slave(struct i2c_client *client)
bus->slave = client; bus->slave = client;
if (!bus->slave)
return -EINVAL;
if (client->flags & I2C_CLIENT_TEN) if (client->flags & I2C_CLIENT_TEN)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
......
...@@ -773,7 +773,7 @@ static int sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd) ...@@ -773,7 +773,7 @@ static int sh_mobile_i2c_r8a7740_workaround(struct sh_mobile_i2c_data *pd)
iic_wr(pd, ICCR, ICCR_TRS); iic_wr(pd, ICCR, ICCR_TRS);
udelay(10); udelay(10);
return sh_mobile_i2c_init(pd); return sh_mobile_i2c_v2_init(pd);
} }
static const struct sh_mobile_dt_config default_dt_config = { static const struct sh_mobile_dt_config default_dt_config = {
...@@ -782,11 +782,6 @@ static const struct sh_mobile_dt_config default_dt_config = { ...@@ -782,11 +782,6 @@ static const struct sh_mobile_dt_config default_dt_config = {
}; };
static const struct sh_mobile_dt_config fast_clock_dt_config = { static const struct sh_mobile_dt_config fast_clock_dt_config = {
.clks_per_count = 2,
.setup = sh_mobile_i2c_init,
};
static const struct sh_mobile_dt_config v2_freq_calc_dt_config = {
.clks_per_count = 2, .clks_per_count = 2,
.setup = sh_mobile_i2c_v2_init, .setup = sh_mobile_i2c_v2_init,
}; };
...@@ -799,17 +794,17 @@ static const struct sh_mobile_dt_config r8a7740_dt_config = { ...@@ -799,17 +794,17 @@ static const struct sh_mobile_dt_config r8a7740_dt_config = {
static const struct of_device_id sh_mobile_i2c_dt_ids[] = { static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
{ .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config }, { .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config }, { .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config },
{ .compatible = "renesas,iic-r8a774c0", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a774c0", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7790", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a7790", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7791", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a7791", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7792", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a7792", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7793", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a7793", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7794", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a7794", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a7795", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a7795", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-r8a77990", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,iic-r8a77990", .data = &fast_clock_dt_config },
{ .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config }, { .compatible = "renesas,iic-sh73a0", .data = &fast_clock_dt_config },
{ .compatible = "renesas,rcar-gen2-iic", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,rcar-gen2-iic", .data = &fast_clock_dt_config },
{ .compatible = "renesas,rcar-gen3-iic", .data = &v2_freq_calc_dt_config }, { .compatible = "renesas,rcar-gen3-iic", .data = &fast_clock_dt_config },
{ .compatible = "renesas,rmobile-iic", .data = &default_dt_config }, { .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
{}, {},
}; };
......
...@@ -570,7 +570,7 @@ static int sprd_i2c_probe(struct platform_device *pdev) ...@@ -570,7 +570,7 @@ static int sprd_i2c_probe(struct platform_device *pdev)
return ret; return ret;
} }
static int sprd_i2c_remove(struct platform_device *pdev) static void sprd_i2c_remove(struct platform_device *pdev)
{ {
struct sprd_i2c *i2c_dev = platform_get_drvdata(pdev); struct sprd_i2c *i2c_dev = platform_get_drvdata(pdev);
int ret; int ret;
...@@ -586,8 +586,6 @@ static int sprd_i2c_remove(struct platform_device *pdev) ...@@ -586,8 +586,6 @@ static int sprd_i2c_remove(struct platform_device *pdev)
pm_runtime_put_noidle(i2c_dev->dev); pm_runtime_put_noidle(i2c_dev->dev);
pm_runtime_disable(i2c_dev->dev); pm_runtime_disable(i2c_dev->dev);
return 0;
} }
static int __maybe_unused sprd_i2c_suspend_noirq(struct device *dev) static int __maybe_unused sprd_i2c_suspend_noirq(struct device *dev)
...@@ -645,7 +643,7 @@ MODULE_DEVICE_TABLE(of, sprd_i2c_of_match); ...@@ -645,7 +643,7 @@ MODULE_DEVICE_TABLE(of, sprd_i2c_of_match);
static struct platform_driver sprd_i2c_driver = { static struct platform_driver sprd_i2c_driver = {
.probe = sprd_i2c_probe, .probe = sprd_i2c_probe,
.remove = sprd_i2c_remove, .remove_new = sprd_i2c_remove,
.driver = { .driver = {
.name = "sprd-i2c", .name = "sprd-i2c",
.of_match_table = sprd_i2c_of_match, .of_match_table = sprd_i2c_of_match,
......
...@@ -701,7 +701,7 @@ const struct bus_type i2c_bus_type = { ...@@ -701,7 +701,7 @@ const struct bus_type i2c_bus_type = {
}; };
EXPORT_SYMBOL_GPL(i2c_bus_type); EXPORT_SYMBOL_GPL(i2c_bus_type);
struct device_type i2c_client_type = { const struct device_type i2c_client_type = {
.groups = i2c_dev_groups, .groups = i2c_dev_groups,
.uevent = i2c_device_uevent, .uevent = i2c_device_uevent,
.release = i2c_client_dev_release, .release = i2c_client_dev_release,
...@@ -1343,7 +1343,7 @@ static struct attribute *i2c_adapter_attrs[] = { ...@@ -1343,7 +1343,7 @@ static struct attribute *i2c_adapter_attrs[] = {
}; };
ATTRIBUTE_GROUPS(i2c_adapter); ATTRIBUTE_GROUPS(i2c_adapter);
struct device_type i2c_adapter_type = { const struct device_type i2c_adapter_type = {
.groups = i2c_adapter_groups, .groups = i2c_adapter_groups,
.release = i2c_adapter_dev_release, .release = i2c_adapter_dev_release,
}; };
......
...@@ -351,13 +351,18 @@ void i2c_register_spd(struct i2c_adapter *adap) ...@@ -351,13 +351,18 @@ void i2c_register_spd(struct i2c_adapter *adap)
if (!dimm_count) if (!dimm_count)
return; return;
dev_info(&adap->dev, "%d/%d memory slots populated (from DMI)\n", /*
dimm_count, slot_count); * If we're a child adapter on a muxed segment, then limit slots to 8,
* as this is the max number of SPD EEPROMs that can be addressed per bus.
if (slot_count > 8) { */
dev_warn(&adap->dev, if (i2c_parent_is_i2c_adapter(adap)) {
"Systems with more than 8 memory slots not supported yet, not instantiating SPD\n"); slot_count = 8;
return; } else {
if (slot_count > 8) {
dev_warn(&adap->dev,
"More than 8 memory slots on a single bus, contact i801 maintainer to add missing mux config\n");
return;
}
} }
/* /*
......
...@@ -57,6 +57,20 @@ ...@@ -57,6 +57,20 @@
#define PCA954X_IRQ_OFFSET 4 #define PCA954X_IRQ_OFFSET 4
/*
* MAX7357's configuration register is writeable after POR, but
* can be locked by setting the basic mode bit. MAX7358 configuration
* register is locked by default and needs to be unlocked first.
* The configuration register holds the following settings:
*/
#define MAX7357_CONF_INT_ENABLE BIT(0)
#define MAX7357_CONF_FLUSH_OUT BIT(1)
#define MAX7357_CONF_RELEASE_INT BIT(2)
#define MAX7357_CONF_DISCON_SINGLE_CHAN BIT(4)
#define MAX7357_CONF_PRECONNECT_TEST BIT(7)
#define MAX7357_POR_DEFAULT_CONF MAX7357_CONF_INT_ENABLE
enum pca_type { enum pca_type {
max_7356, max_7356,
max_7357, max_7357,
...@@ -470,7 +484,34 @@ static int pca954x_init(struct i2c_client *client, struct pca954x *data) ...@@ -470,7 +484,34 @@ static int pca954x_init(struct i2c_client *client, struct pca954x *data)
else else
data->last_chan = 0; /* Disconnect multiplexer */ data->last_chan = 0; /* Disconnect multiplexer */
ret = i2c_smbus_write_byte(client, data->last_chan); if (device_is_compatible(&client->dev, "maxim,max7357")) {
if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) {
u8 conf = MAX7357_POR_DEFAULT_CONF;
/*
* The interrupt signal is shared with the reset pin. Release the
* interrupt after 1.6 seconds to allow using the pin as reset.
*/
conf |= MAX7357_CONF_RELEASE_INT;
if (device_property_read_bool(&client->dev, "maxim,isolate-stuck-channel"))
conf |= MAX7357_CONF_DISCON_SINGLE_CHAN;
if (device_property_read_bool(&client->dev,
"maxim,send-flush-out-sequence"))
conf |= MAX7357_CONF_FLUSH_OUT;
if (device_property_read_bool(&client->dev,
"maxim,preconnection-wiggle-test-enable"))
conf |= MAX7357_CONF_PRECONNECT_TEST;
ret = i2c_smbus_write_byte_data(client, data->last_chan, conf);
} else {
dev_warn(&client->dev, "Write byte data not supported."
"Cannot enable enhanced mode features\n");
ret = i2c_smbus_write_byte(client, data->last_chan);
}
} else {
ret = i2c_smbus_write_byte(client, data->last_chan);
}
if (ret < 0) if (ret < 0)
data->last_chan = 0; data->last_chan = 0;
......
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
#include <uapi/linux/i2c.h> #include <uapi/linux/i2c.h>
extern const struct bus_type i2c_bus_type; extern const struct bus_type i2c_bus_type;
extern struct device_type i2c_adapter_type; extern const struct device_type i2c_adapter_type;
extern struct device_type i2c_client_type; extern const struct device_type i2c_client_type;
/* --- General options ------------------------------------------------ */ /* --- General options ------------------------------------------------ */
...@@ -931,7 +931,7 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap) ...@@ -931,7 +931,7 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg) static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
{ {
return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0); return (msg->addr << 1) | (msg->flags & I2C_M_RD);
} }
u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold); u8 *i2c_get_dma_safe_msg_buf(struct i2c_msg *msg, unsigned int threshold);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment