Commit e764a1e3 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'i2c/for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c updates from Wolfram Sang:

 - bus recovery can now be given a pinctrl handle and the I2C core will
   do all the steps to switch to/from GPIO which can save quite some
   boilerplate code from drivers

 - "fallthrough" conversion

 - driver updates, mostly ID additions

* 'i2c/for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (32 commits)
  i2c: iproc: fix race between client unreg and isr
  i2c: eg20t: use generic power management
  i2c: eg20t: Drop PCI wakeup calls from .suspend/.resume
  i2c: mediatek: Fix i2c_spec_values description
  i2c: mediatek: Add i2c compatible for MediaTek MT8192
  dt-bindings: i2c: update bindings for MT8192 SoC
  i2c: mediatek: Add access to more than 8GB dram in i2c driver
  i2c: mediatek: Add apdma sync in i2c driver
  i2c: i801: Add support for Intel Tiger Lake PCH-H
  i2c: i801: Add support for Intel Emmitsburg PCH
  i2c: bcm2835: Replace HTTP links with HTTPS ones
  Documentation: i2c: dev: 'block process call' is supported
  i2c: at91: Move to generic GPIO bus recovery
  i2c: core: treat EPROBE_DEFER when acquiring SCL/SDA GPIOs
  i2c: core: add generic I2C GPIO recovery
  dt-bindings: i2c: add generic properties for GPIO bus recovery
  i2c: rcar: avoid race when unregistering slave
  i2c: tegra: Avoid tegra_i2c_init_dma() for Tegra210 vi i2c
  i2c: tegra: Fix runtime resume to re-init VI I2C
  i2c: tegra: Fix the error path in tegra_i2c_runtime_resume
  ...
parents dddcbc13 b1eef236
...@@ -14,6 +14,7 @@ Required properties: ...@@ -14,6 +14,7 @@ Required properties:
"mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629 "mediatek,mt7629-i2c", "mediatek,mt2712-i2c": for MediaTek MT7629
"mediatek,mt8173-i2c": for MediaTek MT8173 "mediatek,mt8173-i2c": for MediaTek MT8173
"mediatek,mt8183-i2c": for MediaTek MT8183 "mediatek,mt8183-i2c": for MediaTek MT8183
"mediatek,mt8192-i2c": for MediaTek MT8192
"mediatek,mt8516-i2c", "mediatek,mt2712-i2c": for MediaTek MT8516 "mediatek,mt8516-i2c", "mediatek,mt2712-i2c": for MediaTek MT8516
- reg: physical base address of the controller and dma base, length of memory - reg: physical base address of the controller and dma base, length of memory
mapped region. mapped region.
......
...@@ -72,6 +72,16 @@ wants to support one of the below features, it should adapt these bindings. ...@@ -72,6 +72,16 @@ wants to support one of the below features, it should adapt these bindings.
this information to adapt power management to keep the arbitration awake this information to adapt power management to keep the arbitration awake
all the time, for example. Can not be combined with 'single-master'. all the time, for example. Can not be combined with 'single-master'.
- pinctrl
add extra pinctrl to configure SCL/SDA pins to GPIO function for bus
recovery, call it "gpio" or "recovery" (deprecated) state
- scl-gpios
specify the gpio related to SCL pin. Used for GPIO bus recovery.
- sda-gpios
specify the gpio related to SDA pin. Optional for GPIO bus recovery.
- single-master - single-master
states that there is no other master active on this bus. The OS can use states that there is no other master active on this bus. The OS can use
this information to detect a stalled bus more reliably, for example. this information to detect a stalled bus more reliably, for example.
......
...@@ -26,6 +26,9 @@ properties: ...@@ -26,6 +26,9 @@ properties:
- items: - items:
- const: allwinner,sun50i-a64-i2c - const: allwinner,sun50i-a64-i2c
- const: allwinner,sun6i-a31-i2c - const: allwinner,sun6i-a31-i2c
- items:
- const: allwinner,sun50i-a100-i2c
- const: allwinner,sun6i-a31-i2c
- items: - items:
- const: allwinner,sun50i-h6-i2c - const: allwinner,sun50i-h6-i2c
- const: allwinner,sun6i-a31-i2c - const: allwinner,sun6i-a31-i2c
......
...@@ -10,6 +10,7 @@ Required properties: ...@@ -10,6 +10,7 @@ Required properties:
"renesas,i2c-r8a774a1" if the device is a part of a R8A774A1 SoC. "renesas,i2c-r8a774a1" if the device is a part of a R8A774A1 SoC.
"renesas,i2c-r8a774b1" if the device is a part of a R8A774B1 SoC. "renesas,i2c-r8a774b1" if the device is a part of a R8A774B1 SoC.
"renesas,i2c-r8a774c0" if the device is a part of a R8A774C0 SoC. "renesas,i2c-r8a774c0" if the device is a part of a R8A774C0 SoC.
"renesas,i2c-r8a774e1" if the device is a part of a R8A774E1 SoC.
"renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC. "renesas,i2c-r8a7778" if the device is a part of a R8A7778 SoC.
"renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC. "renesas,i2c-r8a7779" if the device is a part of a R8A7779 SoC.
"renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC. "renesas,i2c-r8a7790" if the device is a part of a R8A7790 SoC.
......
...@@ -11,6 +11,7 @@ Required properties: ...@@ -11,6 +11,7 @@ Required properties:
- "renesas,iic-r8a774a1" (RZ/G2M) - "renesas,iic-r8a774a1" (RZ/G2M)
- "renesas,iic-r8a774b1" (RZ/G2N) - "renesas,iic-r8a774b1" (RZ/G2N)
- "renesas,iic-r8a774c0" (RZ/G2E) - "renesas,iic-r8a774c0" (RZ/G2E)
- "renesas,iic-r8a774e1" (RZ/G2H)
- "renesas,iic-r8a7790" (R-Car H2) - "renesas,iic-r8a7790" (R-Car H2)
- "renesas,iic-r8a7791" (R-Car M2-W) - "renesas,iic-r8a7791" (R-Car M2-W)
- "renesas,iic-r8a7792" (R-Car V2H) - "renesas,iic-r8a7792" (R-Car V2H)
......
...@@ -43,6 +43,7 @@ Supported adapters: ...@@ -43,6 +43,7 @@ Supported adapters:
* Intel Elkhart Lake (PCH) * Intel Elkhart Lake (PCH)
* Intel Tiger Lake (PCH) * Intel Tiger Lake (PCH)
* Intel Jasper Lake (SOC) * Intel Jasper Lake (SOC)
* Intel Emmitsburg (PCH)
Datasheets: Publicly available at the Intel website Datasheets: Publicly available at the Intel website
......
...@@ -159,6 +159,8 @@ for details) through the following functions:: ...@@ -159,6 +159,8 @@ for details) through the following functions::
__s32 i2c_smbus_read_word_data(int file, __u8 command); __s32 i2c_smbus_read_word_data(int file, __u8 command);
__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value); __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
__s32 i2c_smbus_process_call(int file, __u8 command, __u16 value); __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
__s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
__u8 *values);
__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values); __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
__u8 *values); __u8 *values);
......
...@@ -542,8 +542,8 @@ int i2c_pca_add_numbered_bus(struct i2c_adapter *adap) ...@@ -542,8 +542,8 @@ int i2c_pca_add_numbered_bus(struct i2c_adapter *adap)
} }
EXPORT_SYMBOL(i2c_pca_add_numbered_bus); EXPORT_SYMBOL(i2c_pca_add_numbered_bus);
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>, " MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
"Wolfram Sang <kernel@pengutronix.de>"); MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm"); MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -146,6 +146,7 @@ config I2C_I801 ...@@ -146,6 +146,7 @@ config I2C_I801
Elkhart Lake (PCH) Elkhart Lake (PCH)
Tiger Lake (PCH) Tiger Lake (PCH)
Jasper Lake (SOC) Jasper Lake (SOC)
Emmitsburg (PCH)
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-i801. will be called i2c-i801.
......
...@@ -519,9 +519,9 @@ static struct pci_driver ali1535_driver = { ...@@ -519,9 +519,9 @@ static struct pci_driver ali1535_driver = {
module_pci_driver(ali1535_driver); module_pci_driver(ali1535_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
"Philip Edelbrock <phil@netroedge.com>, " MODULE_AUTHOR("Philip Edelbrock <phil@netroedge.com>");
"Mark D. Studebaker <mdsxyz123@yahoo.com> " MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
"and Dan Eaton <dan.eaton@rocketlogix.com>"); MODULE_AUTHOR("Dan Eaton <dan.eaton@rocketlogix.com>");
MODULE_DESCRIPTION("ALI1535 SMBus driver"); MODULE_DESCRIPTION("ALI1535 SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -502,8 +502,8 @@ static struct pci_driver ali15x3_driver = { ...@@ -502,8 +502,8 @@ static struct pci_driver ali15x3_driver = {
module_pci_driver(ali15x3_driver); module_pci_driver(ali15x3_driver);
MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, " MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
"Philip Edelbrock <phil@netroedge.com>, " MODULE_AUTHOR("Philip Edelbrock <phil@netroedge.com>");
"and Mark D. Studebaker <mdsxyz123@yahoo.com>"); MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_DESCRIPTION("ALI15X3 SMBus driver"); MODULE_DESCRIPTION("ALI15X3 SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -381,7 +381,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, ...@@ -381,7 +381,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
if (status) if (status)
return status; return status;
len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
/* fall through */ fallthrough;
case I2C_SMBUS_I2C_BLOCK_DATA: case I2C_SMBUS_I2C_BLOCK_DATA:
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
status = amd_ec_read(smbus, AMD_SMB_DATA + i, status = amd_ec_read(smbus, AMD_SMB_DATA + i,
......
...@@ -504,7 +504,7 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) ...@@ -504,7 +504,7 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
goto error_and_stop; goto error_and_stop;
} }
irq_handled |= ASPEED_I2CD_INTR_TX_ACK; irq_handled |= ASPEED_I2CD_INTR_TX_ACK;
/* fall through */ fallthrough;
case ASPEED_I2C_MASTER_TX_FIRST: case ASPEED_I2C_MASTER_TX_FIRST:
if (bus->buf_index < msg->len) { if (bus->buf_index < msg->len) {
bus->master_state = ASPEED_I2C_MASTER_TX; bus->master_state = ASPEED_I2C_MASTER_TX;
...@@ -520,7 +520,7 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status) ...@@ -520,7 +520,7 @@ static u32 aspeed_i2c_master_irq(struct aspeed_i2c_bus *bus, u32 irq_status)
/* RX may not have completed yet (only address cycle) */ /* RX may not have completed yet (only address cycle) */
if (!(irq_status & ASPEED_I2CD_INTR_RX_DONE)) if (!(irq_status & ASPEED_I2CD_INTR_RX_DONE))
goto out_no_complete; goto out_no_complete;
/* fall through */ fallthrough;
case ASPEED_I2C_MASTER_RX: case ASPEED_I2C_MASTER_RX:
if (unlikely(!(irq_status & ASPEED_I2CD_INTR_RX_DONE))) { if (unlikely(!(irq_status & ASPEED_I2CD_INTR_RX_DONE))) {
dev_err(bus->dev, "master failed to RX\n"); dev_err(bus->dev, "master failed to RX\n");
......
...@@ -816,79 +816,16 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr) ...@@ -816,79 +816,16 @@ static int at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
return ret; return ret;
} }
static void at91_prepare_twi_recovery(struct i2c_adapter *adap)
{
struct at91_twi_dev *dev = i2c_get_adapdata(adap);
pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
}
static void at91_unprepare_twi_recovery(struct i2c_adapter *adap)
{
struct at91_twi_dev *dev = i2c_get_adapdata(adap);
pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
}
static int at91_init_twi_recovery_gpio(struct platform_device *pdev, static int at91_init_twi_recovery_gpio(struct platform_device *pdev,
struct at91_twi_dev *dev) struct at91_twi_dev *dev)
{ {
struct i2c_bus_recovery_info *rinfo = &dev->rinfo; struct i2c_bus_recovery_info *rinfo = &dev->rinfo;
dev->pinctrl = devm_pinctrl_get(&pdev->dev); rinfo->pinctrl = devm_pinctrl_get(&pdev->dev);
if (!dev->pinctrl || IS_ERR(dev->pinctrl)) { if (!rinfo->pinctrl || IS_ERR(rinfo->pinctrl)) {
dev_info(dev->dev, "can't get pinctrl, bus recovery not supported\n"); dev_info(dev->dev, "can't get pinctrl, bus recovery not supported\n");
return PTR_ERR(dev->pinctrl); return PTR_ERR(rinfo->pinctrl);
}
dev->pinctrl_pins_default = pinctrl_lookup_state(dev->pinctrl,
PINCTRL_STATE_DEFAULT);
dev->pinctrl_pins_gpio = pinctrl_lookup_state(dev->pinctrl,
"gpio");
if (IS_ERR(dev->pinctrl_pins_default) ||
IS_ERR(dev->pinctrl_pins_gpio)) {
dev_info(&pdev->dev, "pinctrl states incomplete for recovery\n");
return -EINVAL;
} }
/*
* pins will be taken as GPIO, so we might as well inform pinctrl about
* this and move the state to GPIO
*/
pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_gpio);
rinfo->sda_gpiod = devm_gpiod_get(&pdev->dev, "sda", GPIOD_IN);
if (PTR_ERR(rinfo->sda_gpiod) == -EPROBE_DEFER)
return -EPROBE_DEFER;
rinfo->scl_gpiod = devm_gpiod_get(&pdev->dev, "scl",
GPIOD_OUT_HIGH_OPEN_DRAIN);
if (PTR_ERR(rinfo->scl_gpiod) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (IS_ERR(rinfo->sda_gpiod) ||
IS_ERR(rinfo->scl_gpiod)) {
dev_info(&pdev->dev, "recovery information incomplete\n");
if (!IS_ERR(rinfo->sda_gpiod)) {
gpiod_put(rinfo->sda_gpiod);
rinfo->sda_gpiod = NULL;
}
if (!IS_ERR(rinfo->scl_gpiod)) {
gpiod_put(rinfo->scl_gpiod);
rinfo->scl_gpiod = NULL;
}
pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
return -EINVAL;
}
/* change the state of the pins back to their default state */
pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default);
dev_info(&pdev->dev, "using scl, sda for recovery\n");
rinfo->prepare_recovery = at91_prepare_twi_recovery;
rinfo->unprepare_recovery = at91_unprepare_twi_recovery;
rinfo->recover_bus = i2c_generic_scl_recovery;
dev->adapter.bus_recovery_info = rinfo; dev->adapter.bus_recovery_info = rinfo;
return 0; return 0;
......
...@@ -157,9 +157,6 @@ struct at91_twi_dev { ...@@ -157,9 +157,6 @@ struct at91_twi_dev {
struct at91_twi_dma dma; struct at91_twi_dma dma;
bool slave_detected; bool slave_detected;
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;
#ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL #ifdef CONFIG_I2C_AT91_SLAVE_EXPERIMENTAL
unsigned smr; unsigned smr;
struct i2c_client *slave; struct i2c_client *slave;
......
...@@ -1078,7 +1078,7 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave) ...@@ -1078,7 +1078,7 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave)
if (!iproc_i2c->slave) if (!iproc_i2c->slave)
return -EINVAL; return -EINVAL;
iproc_i2c->slave = NULL; disable_irq(iproc_i2c->irq);
/* disable all slave interrupts */ /* disable all slave interrupts */
tmp = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET); tmp = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
...@@ -1091,6 +1091,17 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave) ...@@ -1091,6 +1091,17 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave)
tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT); tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET, tmp); iproc_i2c_wr_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET, tmp);
/* flush TX/RX FIFOs */
tmp = (BIT(S_FIFO_RX_FLUSH_SHIFT) | BIT(S_FIFO_TX_FLUSH_SHIFT));
iproc_i2c_wr_reg(iproc_i2c, S_FIFO_CTRL_OFFSET, tmp);
/* clear all pending slave interrupts */
iproc_i2c_wr_reg(iproc_i2c, IS_OFFSET, ISR_MASK_SLAVE);
iproc_i2c->slave = NULL;
enable_irq(iproc_i2c->irq);
return 0; return 0;
} }
......
...@@ -392,7 +392,7 @@ static const struct i2c_algorithm bcm2835_i2c_algo = { ...@@ -392,7 +392,7 @@ static const struct i2c_algorithm bcm2835_i2c_algo = {
/* /*
* The BCM2835 was reported to have problems with clock stretching: * The BCM2835 was reported to have problems with clock stretching:
* http://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html * https://www.advamation.com/knowhow/raspberrypi/rpi-i2c-bug.html
* https://www.raspberrypi.org/forums/viewtopic.php?p=146272 * https://www.raspberrypi.org/forums/viewtopic.php?p=146272
*/ */
static const struct i2c_adapter_quirks bcm2835_i2c_quirks = { static const struct i2c_adapter_quirks bcm2835_i2c_quirks = {
......
...@@ -90,7 +90,7 @@ static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c) ...@@ -90,7 +90,7 @@ static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c)
switch (pdev->device) { switch (pdev->device) {
case 0x0817: case 0x0817:
dev->timings.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ; dev->timings.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ;
/* fall through */ fallthrough;
case 0x0818: case 0x0818:
case 0x0819: case 0x0819:
c->bus_num = pdev->device - 0x817 + 3; c->bus_num = pdev->device - 0x817 + 3;
......
...@@ -187,7 +187,7 @@ static irqreturn_t dc_i2c_irq(int irq, void *dev_id) ...@@ -187,7 +187,7 @@ static irqreturn_t dc_i2c_irq(int irq, void *dev_id)
break; break;
} }
i2c->state = STATE_WRITE; i2c->state = STATE_WRITE;
/* fall through */ fallthrough;
case STATE_WRITE: case STATE_WRITE:
if (i2c->msgbuf_ptr < i2c->msg->len) if (i2c->msgbuf_ptr < i2c->msg->len)
dc_i2c_write_buf(i2c); dc_i2c_write_buf(i2c);
......
...@@ -846,11 +846,10 @@ static void pch_i2c_remove(struct pci_dev *pdev) ...@@ -846,11 +846,10 @@ static void pch_i2c_remove(struct pci_dev *pdev)
kfree(adap_info); kfree(adap_info);
} }
#ifdef CONFIG_PM static int __maybe_unused pch_i2c_suspend(struct device *dev)
static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
int ret;
int i; int i;
struct pci_dev *pdev = to_pci_dev(dev);
struct adapter_info *adap_info = pci_get_drvdata(pdev); struct adapter_info *adap_info = pci_get_drvdata(pdev);
void __iomem *p = adap_info->pch_data[0].pch_base_address; void __iomem *p = adap_info->pch_data[0].pch_base_address;
...@@ -872,34 +871,13 @@ static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -872,34 +871,13 @@ static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
ioread32(p + PCH_I2CSR), ioread32(p + PCH_I2CBUFSTA), ioread32(p + PCH_I2CSR), ioread32(p + PCH_I2CBUFSTA),
ioread32(p + PCH_I2CESRSTA)); ioread32(p + PCH_I2CESRSTA));
ret = pci_save_state(pdev);
if (ret) {
pch_pci_err(pdev, "pci_save_state\n");
return ret;
}
pci_enable_wake(pdev, PCI_D3hot, 0);
pci_disable_device(pdev);
pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0; return 0;
} }
static int pch_i2c_resume(struct pci_dev *pdev) static int __maybe_unused pch_i2c_resume(struct device *dev)
{ {
int i; int i;
struct adapter_info *adap_info = pci_get_drvdata(pdev); struct adapter_info *adap_info = dev_get_drvdata(dev);
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
if (pci_enable_device(pdev) < 0) {
pch_pci_err(pdev, "pch_i2c_resume:pci_enable_device FAILED\n");
return -EIO;
}
pci_enable_wake(pdev, PCI_D3hot, 0);
for (i = 0; i < adap_info->ch_num; i++) for (i = 0; i < adap_info->ch_num; i++)
pch_i2c_init(&adap_info->pch_data[i]); pch_i2c_init(&adap_info->pch_data[i]);
...@@ -908,18 +886,15 @@ static int pch_i2c_resume(struct pci_dev *pdev) ...@@ -908,18 +886,15 @@ static int pch_i2c_resume(struct pci_dev *pdev)
return 0; return 0;
} }
#else
#define pch_i2c_suspend NULL static SIMPLE_DEV_PM_OPS(pch_i2c_pm_ops, pch_i2c_suspend, pch_i2c_resume);
#define pch_i2c_resume NULL
#endif
static struct pci_driver pch_pcidriver = { static struct pci_driver pch_pcidriver = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
.id_table = pch_pcidev_id, .id_table = pch_pcidev_id,
.probe = pch_i2c_probe, .probe = pch_i2c_probe,
.remove = pch_i2c_remove, .remove = pch_i2c_remove,
.suspend = pch_i2c_suspend, .driver.pm = &pch_i2c_pm_ops,
.resume = pch_i2c_resume
}; };
module_pci_driver(pch_pcidriver); module_pci_driver(pch_pcidriver);
......
...@@ -442,6 +442,7 @@ static struct platform_driver em_i2c_driver = { ...@@ -442,6 +442,7 @@ static struct platform_driver em_i2c_driver = {
module_platform_driver(em_i2c_driver); module_platform_driver(em_i2c_driver);
MODULE_DESCRIPTION("EMEV2 I2C bus driver"); MODULE_DESCRIPTION("EMEV2 I2C bus driver");
MODULE_AUTHOR("Ian Molton and Wolfram Sang <wsa@sang-engineering.com>"); MODULE_AUTHOR("Ian Molton");
MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_DEVICE_TABLE(of, em_i2c_ids); MODULE_DEVICE_TABLE(of, em_i2c_ids);
...@@ -703,7 +703,7 @@ static int fsi_i2c_probe(struct device *dev) ...@@ -703,7 +703,7 @@ static int fsi_i2c_probe(struct device *dev)
for (port_no = 0; port_no < ports; port_no++) { for (port_no = 0; port_no < ports; port_no++) {
np = fsi_i2c_find_port_of_node(dev->of_node, port_no); np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
if (np && !of_device_is_available(np)) if (!of_device_is_available(np))
continue; continue;
port = kzalloc(sizeof(*port), GFP_KERNEL); port = kzalloc(sizeof(*port), GFP_KERNEL);
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
* Sunrise Point-H (PCH) 0xa123 32 hard yes yes yes * Sunrise Point-H (PCH) 0xa123 32 hard yes yes yes
* Sunrise Point-LP (PCH) 0x9d23 32 hard yes yes yes * Sunrise Point-LP (PCH) 0x9d23 32 hard yes yes yes
* DNV (SOC) 0x19df 32 hard yes yes yes * DNV (SOC) 0x19df 32 hard yes yes yes
* Emmitsburg (PCH) 0x1bc9 32 hard yes yes yes
* Broxton (SOC) 0x5ad4 32 hard yes yes yes * Broxton (SOC) 0x5ad4 32 hard yes yes yes
* Lewisburg (PCH) 0xa1a3 32 hard yes yes yes * Lewisburg (PCH) 0xa1a3 32 hard yes yes yes
* Lewisburg Supersku (PCH) 0xa223 32 hard yes yes yes * Lewisburg Supersku (PCH) 0xa223 32 hard yes yes yes
...@@ -67,6 +68,7 @@ ...@@ -67,6 +68,7 @@
* Comet Lake-H (PCH) 0x06a3 32 hard yes yes yes * Comet Lake-H (PCH) 0x06a3 32 hard yes yes yes
* Elkhart Lake (PCH) 0x4b23 32 hard yes yes yes * Elkhart Lake (PCH) 0x4b23 32 hard yes yes yes
* Tiger Lake-LP (PCH) 0xa0a3 32 hard yes yes yes * Tiger Lake-LP (PCH) 0xa0a3 32 hard yes yes yes
* Tiger Lake-H (PCH) 0x43a3 32 hard yes yes yes
* Jasper Lake (SOC) 0x4da3 32 hard yes yes yes * Jasper Lake (SOC) 0x4da3 32 hard yes yes yes
* Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes * Comet Lake-V (PCH) 0xa3a3 32 hard yes yes yes
* *
...@@ -207,6 +209,7 @@ ...@@ -207,6 +209,7 @@
#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 #define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12
#define PCI_DEVICE_ID_INTEL_CDF_SMBUS 0x18df #define PCI_DEVICE_ID_INTEL_CDF_SMBUS 0x18df
#define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df #define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df
#define PCI_DEVICE_ID_INTEL_EBG_SMBUS 0x1bc9
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22
#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22
/* Patsburg also has three 'Integrated Device Function' SMBus controllers */ /* Patsburg also has three 'Integrated Device Function' SMBus controllers */
...@@ -221,6 +224,7 @@ ...@@ -221,6 +224,7 @@
#define PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS 0x31d4 #define PCI_DEVICE_ID_INTEL_GEMINILAKE_SMBUS 0x31d4
#define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS 0x34a3 #define PCI_DEVICE_ID_INTEL_ICELAKE_LP_SMBUS 0x34a3
#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30
#define PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS 0x43a3
#define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23 #define PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS 0x4b23
#define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3 #define PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS 0x4da3
#define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4 #define PCI_DEVICE_ID_INTEL_BROXTON_SMBUS 0x5ad4
...@@ -1062,6 +1066,7 @@ static const struct pci_device_id i801_ids[] = { ...@@ -1062,6 +1066,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EBG_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS) },
...@@ -1074,6 +1079,7 @@ static const struct pci_device_id i801_ids[] = { ...@@ -1074,6 +1079,7 @@ static const struct pci_device_id i801_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COMETLAKE_V_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS) },
{ 0, } { 0, }
}; };
...@@ -1748,7 +1754,9 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1748,7 +1754,9 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
case PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS: case PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS:
case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS: case PCI_DEVICE_ID_INTEL_ELKHART_LAKE_SMBUS:
case PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_TIGERLAKE_LP_SMBUS:
case PCI_DEVICE_ID_INTEL_TIGERLAKE_H_SMBUS:
case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS: case PCI_DEVICE_ID_INTEL_JASPER_LAKE_SMBUS:
case PCI_DEVICE_ID_INTEL_EBG_SMBUS:
priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_BLOCK_PROC;
priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ; priv->features |= FEATURE_IRQ;
...@@ -1765,19 +1773,19 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) ...@@ -1765,19 +1773,19 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1: case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1:
case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2: case PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2:
priv->features |= FEATURE_IDF; priv->features |= FEATURE_IDF;
/* fall through */ fallthrough;
default: default:
priv->features |= FEATURE_BLOCK_PROC; priv->features |= FEATURE_BLOCK_PROC;
priv->features |= FEATURE_I2C_BLOCK_READ; priv->features |= FEATURE_I2C_BLOCK_READ;
priv->features |= FEATURE_IRQ; priv->features |= FEATURE_IRQ;
/* fall through */ fallthrough;
case PCI_DEVICE_ID_INTEL_82801DB_3: case PCI_DEVICE_ID_INTEL_82801DB_3:
priv->features |= FEATURE_SMBUS_PEC; priv->features |= FEATURE_SMBUS_PEC;
priv->features |= FEATURE_BLOCK_BUFFER; priv->features |= FEATURE_BLOCK_BUFFER;
/* fall through */ fallthrough;
case PCI_DEVICE_ID_INTEL_82801CA_3: case PCI_DEVICE_ID_INTEL_82801CA_3:
priv->features |= FEATURE_HOST_NOTIFY; priv->features |= FEATURE_HOST_NOTIFY;
/* fall through */ fallthrough;
case PCI_DEVICE_ID_INTEL_82801BA_2: case PCI_DEVICE_ID_INTEL_82801BA_2:
case PCI_DEVICE_ID_INTEL_82801AB_3: case PCI_DEVICE_ID_INTEL_82801AB_3:
case PCI_DEVICE_ID_INTEL_82801AA_3: case PCI_DEVICE_ID_INTEL_82801AA_3:
...@@ -1986,7 +1994,8 @@ static void __exit i2c_i801_exit(void) ...@@ -1986,7 +1994,8 @@ static void __exit i2c_i801_exit(void)
pci_unregister_driver(&i801_driver); pci_unregister_driver(&i801_driver);
} }
MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, Jean Delvare <jdelvare@suse.de>"); MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
MODULE_DESCRIPTION("I801 SMBus driver"); MODULE_DESCRIPTION("I801 SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -48,11 +48,13 @@ ...@@ -48,11 +48,13 @@
#define I2C_DMA_CON_TX 0x0000 #define I2C_DMA_CON_TX 0x0000
#define I2C_DMA_CON_RX 0x0001 #define I2C_DMA_CON_RX 0x0001
#define I2C_DMA_ASYNC_MODE 0x0004
#define I2C_DMA_SKIP_CONFIG 0x0010
#define I2C_DMA_DIR_CHANGE 0x0200
#define I2C_DMA_START_EN 0x0001 #define I2C_DMA_START_EN 0x0001
#define I2C_DMA_INT_FLAG_NONE 0x0000 #define I2C_DMA_INT_FLAG_NONE 0x0000
#define I2C_DMA_CLR_FLAG 0x0000 #define I2C_DMA_CLR_FLAG 0x0000
#define I2C_DMA_HARD_RST 0x0002 #define I2C_DMA_HARD_RST 0x0002
#define I2C_DMA_4G_MODE 0x0001
#define MAX_SAMPLE_CNT_DIV 8 #define MAX_SAMPLE_CNT_DIV 8
#define MAX_STEP_CNT_DIV 64 #define MAX_STEP_CNT_DIV 64
...@@ -201,10 +203,11 @@ struct mtk_i2c_compatible { ...@@ -201,10 +203,11 @@ struct mtk_i2c_compatible {
unsigned char dcm: 1; unsigned char dcm: 1;
unsigned char auto_restart: 1; unsigned char auto_restart: 1;
unsigned char aux_len_reg: 1; unsigned char aux_len_reg: 1;
unsigned char support_33bits: 1;
unsigned char timing_adjust: 1; unsigned char timing_adjust: 1;
unsigned char dma_sync: 1; unsigned char dma_sync: 1;
unsigned char ltiming_adjust: 1; unsigned char ltiming_adjust: 1;
unsigned char apdma_sync: 1;
unsigned char max_dma_support;
}; };
struct mtk_i2c_ac_timing { struct mtk_i2c_ac_timing {
...@@ -250,14 +253,13 @@ struct mtk_i2c { ...@@ -250,14 +253,13 @@ struct mtk_i2c {
/** /**
* struct i2c_spec_values: * struct i2c_spec_values:
* min_low_ns: min LOW period of the SCL clock * @min_low_ns: min LOW period of the SCL clock
* min_su_sta_ns: min set-up time for a repeated START condition * @min_su_sta_ns: min set-up time for a repeated START condition
* max_hd_dat_ns: max data hold time * @max_hd_dat_ns: max data hold time
* min_su_dat_ns: min data set-up time * @min_su_dat_ns: min data set-up time
*/ */
struct i2c_spec_values { struct i2c_spec_values {
unsigned int min_low_ns; unsigned int min_low_ns;
unsigned int min_high_ns;
unsigned int min_su_sta_ns; unsigned int min_su_sta_ns;
unsigned int max_hd_dat_ns; unsigned int max_hd_dat_ns;
unsigned int min_su_dat_ns; unsigned int min_su_dat_ns;
...@@ -307,10 +309,11 @@ static const struct mtk_i2c_compatible mt2712_compat = { ...@@ -307,10 +309,11 @@ static const struct mtk_i2c_compatible mt2712_compat = {
.dcm = 1, .dcm = 1,
.auto_restart = 1, .auto_restart = 1,
.aux_len_reg = 1, .aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 1, .timing_adjust = 1,
.dma_sync = 0, .dma_sync = 0,
.ltiming_adjust = 0, .ltiming_adjust = 0,
.apdma_sync = 0,
.max_dma_support = 33,
}; };
static const struct mtk_i2c_compatible mt6577_compat = { static const struct mtk_i2c_compatible mt6577_compat = {
...@@ -320,10 +323,11 @@ static const struct mtk_i2c_compatible mt6577_compat = { ...@@ -320,10 +323,11 @@ static const struct mtk_i2c_compatible mt6577_compat = {
.dcm = 1, .dcm = 1,
.auto_restart = 0, .auto_restart = 0,
.aux_len_reg = 0, .aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0, .timing_adjust = 0,
.dma_sync = 0, .dma_sync = 0,
.ltiming_adjust = 0, .ltiming_adjust = 0,
.apdma_sync = 0,
.max_dma_support = 32,
}; };
static const struct mtk_i2c_compatible mt6589_compat = { static const struct mtk_i2c_compatible mt6589_compat = {
...@@ -333,10 +337,11 @@ static const struct mtk_i2c_compatible mt6589_compat = { ...@@ -333,10 +337,11 @@ static const struct mtk_i2c_compatible mt6589_compat = {
.dcm = 0, .dcm = 0,
.auto_restart = 0, .auto_restart = 0,
.aux_len_reg = 0, .aux_len_reg = 0,
.support_33bits = 0,
.timing_adjust = 0, .timing_adjust = 0,
.dma_sync = 0, .dma_sync = 0,
.ltiming_adjust = 0, .ltiming_adjust = 0,
.apdma_sync = 0,
.max_dma_support = 32,
}; };
static const struct mtk_i2c_compatible mt7622_compat = { static const struct mtk_i2c_compatible mt7622_compat = {
...@@ -346,10 +351,11 @@ static const struct mtk_i2c_compatible mt7622_compat = { ...@@ -346,10 +351,11 @@ static const struct mtk_i2c_compatible mt7622_compat = {
.dcm = 1, .dcm = 1,
.auto_restart = 1, .auto_restart = 1,
.aux_len_reg = 1, .aux_len_reg = 1,
.support_33bits = 0,
.timing_adjust = 0, .timing_adjust = 0,
.dma_sync = 0, .dma_sync = 0,
.ltiming_adjust = 0, .ltiming_adjust = 0,
.apdma_sync = 0,
.max_dma_support = 32,
}; };
static const struct mtk_i2c_compatible mt8173_compat = { static const struct mtk_i2c_compatible mt8173_compat = {
...@@ -358,10 +364,11 @@ static const struct mtk_i2c_compatible mt8173_compat = { ...@@ -358,10 +364,11 @@ static const struct mtk_i2c_compatible mt8173_compat = {
.dcm = 1, .dcm = 1,
.auto_restart = 1, .auto_restart = 1,
.aux_len_reg = 1, .aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 0, .timing_adjust = 0,
.dma_sync = 0, .dma_sync = 0,
.ltiming_adjust = 0, .ltiming_adjust = 0,
.apdma_sync = 0,
.max_dma_support = 33,
}; };
static const struct mtk_i2c_compatible mt8183_compat = { static const struct mtk_i2c_compatible mt8183_compat = {
...@@ -371,10 +378,25 @@ static const struct mtk_i2c_compatible mt8183_compat = { ...@@ -371,10 +378,25 @@ static const struct mtk_i2c_compatible mt8183_compat = {
.dcm = 0, .dcm = 0,
.auto_restart = 1, .auto_restart = 1,
.aux_len_reg = 1, .aux_len_reg = 1,
.support_33bits = 1,
.timing_adjust = 1, .timing_adjust = 1,
.dma_sync = 1, .dma_sync = 1,
.ltiming_adjust = 1, .ltiming_adjust = 1,
.apdma_sync = 0,
.max_dma_support = 33,
};
static const struct mtk_i2c_compatible mt8192_compat = {
.quirks = &mt8183_i2c_quirks,
.regs = mt_i2c_regs_v2,
.pmic_i2c = 0,
.dcm = 0,
.auto_restart = 1,
.aux_len_reg = 1,
.timing_adjust = 1,
.dma_sync = 1,
.ltiming_adjust = 1,
.apdma_sync = 1,
.max_dma_support = 36,
}; };
static const struct of_device_id mtk_i2c_of_match[] = { static const struct of_device_id mtk_i2c_of_match[] = {
...@@ -384,6 +406,7 @@ static const struct of_device_id mtk_i2c_of_match[] = { ...@@ -384,6 +406,7 @@ static const struct of_device_id mtk_i2c_of_match[] = {
{ .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat }, { .compatible = "mediatek,mt7622-i2c", .data = &mt7622_compat },
{ .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat }, { .compatible = "mediatek,mt8173-i2c", .data = &mt8173_compat },
{ .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat }, { .compatible = "mediatek,mt8183-i2c", .data = &mt8183_compat },
{ .compatible = "mediatek,mt8192-i2c", .data = &mt8192_compat },
{} {}
}; };
MODULE_DEVICE_TABLE(of, mtk_i2c_of_match); MODULE_DEVICE_TABLE(of, mtk_i2c_of_match);
...@@ -786,11 +809,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk) ...@@ -786,11 +809,6 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk)
return 0; return 0;
} }
static inline u32 mtk_i2c_set_4g_mode(dma_addr_t addr)
{
return (addr & BIT_ULL(32)) ? I2C_DMA_4G_MODE : I2C_DMA_CLR_FLAG;
}
static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
int num, int left_num) int num, int left_num)
{ {
...@@ -798,6 +816,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, ...@@ -798,6 +816,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
u16 start_reg; u16 start_reg;
u16 control_reg; u16 control_reg;
u16 restart_flag = 0; u16 restart_flag = 0;
u16 dma_sync = 0;
u32 reg_4g_mode; u32 reg_4g_mode;
u8 *dma_rd_buf = NULL; u8 *dma_rd_buf = NULL;
u8 *dma_wr_buf = NULL; u8 *dma_wr_buf = NULL;
...@@ -851,10 +870,16 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, ...@@ -851,10 +870,16 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN); mtk_i2c_writew(i2c, num, OFFSET_TRANSAC_LEN);
} }
if (i2c->dev_comp->apdma_sync) {
dma_sync = I2C_DMA_SKIP_CONFIG | I2C_DMA_ASYNC_MODE;
if (i2c->op == I2C_MASTER_WRRD)
dma_sync |= I2C_DMA_DIR_CHANGE;
}
/* Prepare buffer data to start transfer */ /* Prepare buffer data to start transfer */
if (i2c->op == I2C_MASTER_RD) { if (i2c->op == I2C_MASTER_RD) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG); writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
writel(I2C_DMA_CON_RX, i2c->pdmabase + OFFSET_CON); writel(I2C_DMA_CON_RX | dma_sync, i2c->pdmabase + OFFSET_CON);
dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1); dma_rd_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_rd_buf) if (!dma_rd_buf)
...@@ -868,8 +893,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, ...@@ -868,8 +893,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
return -ENOMEM; return -ENOMEM;
} }
if (i2c->dev_comp->support_33bits) { if (i2c->dev_comp->max_dma_support > 32) {
reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr); reg_4g_mode = upper_32_bits(rpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE); writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);
} }
...@@ -877,7 +902,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, ...@@ -877,7 +902,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN); writel(msgs->len, i2c->pdmabase + OFFSET_RX_LEN);
} else if (i2c->op == I2C_MASTER_WR) { } else if (i2c->op == I2C_MASTER_WR) {
writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG); writel(I2C_DMA_INT_FLAG_NONE, i2c->pdmabase + OFFSET_INT_FLAG);
writel(I2C_DMA_CON_TX, i2c->pdmabase + OFFSET_CON); writel(I2C_DMA_CON_TX | dma_sync, i2c->pdmabase + OFFSET_CON);
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1); dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf) if (!dma_wr_buf)
...@@ -891,8 +916,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, ...@@ -891,8 +916,8 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
return -ENOMEM; return -ENOMEM;
} }
if (i2c->dev_comp->support_33bits) { if (i2c->dev_comp->max_dma_support > 32) {
reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr); reg_4g_mode = upper_32_bits(wpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE); writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
} }
...@@ -900,7 +925,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, ...@@ -900,7 +925,7 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN); writel(msgs->len, i2c->pdmabase + OFFSET_TX_LEN);
} else { } else {
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG); writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_INT_FLAG);
writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_CON); writel(I2C_DMA_CLR_FLAG | dma_sync, i2c->pdmabase + OFFSET_CON);
dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1); dma_wr_buf = i2c_get_dma_safe_msg_buf(msgs, 1);
if (!dma_wr_buf) if (!dma_wr_buf)
...@@ -937,11 +962,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, ...@@ -937,11 +962,11 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs,
return -ENOMEM; return -ENOMEM;
} }
if (i2c->dev_comp->support_33bits) { if (i2c->dev_comp->max_dma_support > 32) {
reg_4g_mode = mtk_i2c_set_4g_mode(wpaddr); reg_4g_mode = upper_32_bits(wpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE); writel(reg_4g_mode, i2c->pdmabase + OFFSET_TX_4G_MODE);
reg_4g_mode = mtk_i2c_set_4g_mode(rpaddr); reg_4g_mode = upper_32_bits(rpaddr);
writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE); writel(reg_4g_mode, i2c->pdmabase + OFFSET_RX_4G_MODE);
} }
...@@ -1215,8 +1240,9 @@ static int mtk_i2c_probe(struct platform_device *pdev) ...@@ -1215,8 +1240,9 @@ static int mtk_i2c_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
if (i2c->dev_comp->support_33bits) { if (i2c->dev_comp->max_dma_support > 32) {
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(33)); ret = dma_set_mask(&pdev->dev,
DMA_BIT_MASK(i2c->dev_comp->max_dma_support));
if (ret) { if (ret) {
dev_err(&pdev->dev, "dma_set_mask return error.\n"); dev_err(&pdev->dev, "dma_set_mask return error.\n");
return ret; return ret;
......
...@@ -251,7 +251,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) ...@@ -251,7 +251,7 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
break; break;
} }
/* FALLTHRU */ fallthrough;
case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */
case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */ case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */
if ((drv_data->bytes_left == 0) if ((drv_data->bytes_left == 0)
...@@ -282,14 +282,14 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) ...@@ -282,14 +282,14 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
break; break;
} }
/* FALLTHRU */ fallthrough;
case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */ case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */
if (drv_data->bytes_left == 0) { if (drv_data->bytes_left == 0) {
drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
drv_data->state = MV64XXX_I2C_STATE_IDLE; drv_data->state = MV64XXX_I2C_STATE_IDLE;
break; break;
} }
/* FALLTHRU */ fallthrough;
case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */ case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */
if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK) if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK)
drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;
...@@ -417,8 +417,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) ...@@ -417,8 +417,7 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
"mv64xxx_i2c_do_action: Invalid action: %d\n", "mv64xxx_i2c_do_action: Invalid action: %d\n",
drv_data->action); drv_data->action);
drv_data->rc = -EIO; drv_data->rc = -EIO;
fallthrough;
/* FALLTHRU */
case MV64XXX_I2C_ACTION_SEND_STOP: case MV64XXX_I2C_ACTION_SEND_STOP:
drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
......
...@@ -1122,6 +1122,7 @@ static void __exit nmk_i2c_exit(void) ...@@ -1122,6 +1122,7 @@ static void __exit nmk_i2c_exit(void)
subsys_initcall(nmk_i2c_init); subsys_initcall(nmk_i2c_init);
module_exit(nmk_i2c_exit); module_exit(nmk_i2c_exit);
MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR"); MODULE_AUTHOR("Sachin Verma");
MODULE_AUTHOR("Srinidhi KASAGAR");
MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver"); MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -1032,7 +1032,7 @@ static struct pci_driver piix4_driver = { ...@@ -1032,7 +1032,7 @@ static struct pci_driver piix4_driver = {
module_pci_driver(piix4_driver); module_pci_driver(piix4_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
"Philip Edelbrock <phil@netroedge.com>"); MODULE_AUTHOR("Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("PIIX4 SMBus driver"); MODULE_DESCRIPTION("PIIX4 SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -781,7 +781,8 @@ static void __exit i2c_adap_pnx_exit(void) ...@@ -781,7 +781,8 @@ static void __exit i2c_adap_pnx_exit(void)
platform_driver_unregister(&i2c_pnx_driver); platform_driver_unregister(&i2c_pnx_driver);
} }
MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>"); MODULE_AUTHOR("Vitaly Wool");
MODULE_AUTHOR("Dennis Kovalev <source@mvista.com>");
MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses"); MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pnx-i2c"); MODULE_ALIAS("platform:pnx-i2c");
......
...@@ -583,13 +583,14 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) ...@@ -583,13 +583,14 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR); rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR);
} }
rcar_i2c_write(priv, ICSSR, ~SAR & 0xff); /* Clear SSR, too, because of old STOPs to other clients than us */
rcar_i2c_write(priv, ICSSR, ~(SAR | SSR) & 0xff);
} }
/* master sent stop */ /* master sent stop */
if (ssr_filtered & SSR) { if (ssr_filtered & SSR) {
i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value); i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
rcar_i2c_write(priv, ICSIER, SAR | SSR); rcar_i2c_write(priv, ICSIER, SAR);
rcar_i2c_write(priv, ICSSR, ~SSR & 0xff); rcar_i2c_write(priv, ICSSR, ~SSR & 0xff);
} }
...@@ -853,7 +854,7 @@ static int rcar_reg_slave(struct i2c_client *slave) ...@@ -853,7 +854,7 @@ static int rcar_reg_slave(struct i2c_client *slave)
priv->slave = slave; priv->slave = slave;
rcar_i2c_write(priv, ICSAR, slave->addr); rcar_i2c_write(priv, ICSAR, slave->addr);
rcar_i2c_write(priv, ICSSR, 0); rcar_i2c_write(priv, ICSSR, 0);
rcar_i2c_write(priv, ICSIER, SAR | SSR); rcar_i2c_write(priv, ICSIER, SAR);
rcar_i2c_write(priv, ICSCR, SIE | SDBS); rcar_i2c_write(priv, ICSCR, SIE | SDBS);
return 0; return 0;
...@@ -865,12 +866,14 @@ static int rcar_unreg_slave(struct i2c_client *slave) ...@@ -865,12 +866,14 @@ static int rcar_unreg_slave(struct i2c_client *slave)
WARN_ON(!priv->slave); WARN_ON(!priv->slave);
/* disable irqs and ensure none is running before clearing ptr */ /* ensure no irq is running before clearing ptr */
disable_irq(priv->irq);
rcar_i2c_write(priv, ICSIER, 0); rcar_i2c_write(priv, ICSIER, 0);
rcar_i2c_write(priv, ICSCR, 0); rcar_i2c_write(priv, ICSSR, 0);
enable_irq(priv->irq);
rcar_i2c_write(priv, ICSCR, SDBS);
rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */ rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
synchronize_irq(priv->irq);
priv->slave = NULL; priv->slave = NULL;
pm_runtime_put(rcar_i2c_priv_to_dev(priv)); pm_runtime_put(rcar_i2c_priv_to_dev(priv));
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -1040,8 +1041,21 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) ...@@ -1040,8 +1041,21 @@ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num)
return ret; return ret;
} }
static int rk3x_i2c_xfer(struct i2c_adapter *adap, static int rk3x_i2c_wait_xfer_poll(struct rk3x_i2c *i2c)
struct i2c_msg *msgs, int num) {
ktime_t timeout = ktime_add_ms(ktime_get(), WAIT_TIMEOUT);
while (READ_ONCE(i2c->busy) &&
ktime_compare(ktime_get(), timeout) < 0) {
udelay(5);
rk3x_i2c_irq(0, i2c);
}
return !i2c->busy;
}
static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num, bool polling)
{ {
struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data; struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data;
unsigned long timeout, flags; unsigned long timeout, flags;
...@@ -1075,8 +1089,12 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, ...@@ -1075,8 +1089,12 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
rk3x_i2c_start(i2c); rk3x_i2c_start(i2c);
if (!polling) {
timeout = wait_event_timeout(i2c->wait, !i2c->busy, timeout = wait_event_timeout(i2c->wait, !i2c->busy,
msecs_to_jiffies(WAIT_TIMEOUT)); msecs_to_jiffies(WAIT_TIMEOUT));
} else {
timeout = rk3x_i2c_wait_xfer_poll(i2c);
}
spin_lock_irqsave(&i2c->lock, flags); spin_lock_irqsave(&i2c->lock, flags);
...@@ -1110,6 +1128,18 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap, ...@@ -1110,6 +1128,18 @@ static int rk3x_i2c_xfer(struct i2c_adapter *adap,
return ret < 0 ? ret : num; return ret < 0 ? ret : num;
} }
static int rk3x_i2c_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
return rk3x_i2c_xfer_common(adap, msgs, num, false);
}
static int rk3x_i2c_xfer_polling(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
return rk3x_i2c_xfer_common(adap, msgs, num, true);
}
static __maybe_unused int rk3x_i2c_resume(struct device *dev) static __maybe_unused int rk3x_i2c_resume(struct device *dev)
{ {
struct rk3x_i2c *i2c = dev_get_drvdata(dev); struct rk3x_i2c *i2c = dev_get_drvdata(dev);
...@@ -1126,6 +1156,7 @@ static u32 rk3x_i2c_func(struct i2c_adapter *adap) ...@@ -1126,6 +1156,7 @@ static u32 rk3x_i2c_func(struct i2c_adapter *adap)
static const struct i2c_algorithm rk3x_i2c_algorithm = { static const struct i2c_algorithm rk3x_i2c_algorithm = {
.master_xfer = rk3x_i2c_xfer, .master_xfer = rk3x_i2c_xfer,
.master_xfer_atomic = rk3x_i2c_xfer_polling,
.functionality = rk3x_i2c_func, .functionality = rk3x_i2c_func,
}; };
......
...@@ -932,6 +932,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) ...@@ -932,6 +932,7 @@ static void __exit sh_mobile_i2c_adap_exit(void)
module_exit(sh_mobile_i2c_adap_exit); module_exit(sh_mobile_i2c_adap_exit);
MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
MODULE_AUTHOR("Magnus Damm and Wolfram Sang"); MODULE_AUTHOR("Magnus Damm");
MODULE_AUTHOR("Wolfram Sang");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:i2c-sh_mobile"); MODULE_ALIAS("platform:i2c-sh_mobile");
...@@ -180,6 +180,7 @@ static void __exit i2c_sibyte_exit(void) ...@@ -180,6 +180,7 @@ static void __exit i2c_sibyte_exit(void)
module_init(i2c_sibyte_init); module_init(i2c_sibyte_init);
module_exit(i2c_sibyte_exit); module_exit(i2c_sibyte_exit);
MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>"); MODULE_AUTHOR("Kip Walker (Broadcom Corp.)");
MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards"); MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -470,6 +470,6 @@ static struct platform_driver i2c_sirfsoc_driver = { ...@@ -470,6 +470,6 @@ static struct platform_driver i2c_sirfsoc_driver = {
module_platform_driver(i2c_sirfsoc_driver); module_platform_driver(i2c_sirfsoc_driver);
MODULE_DESCRIPTION("SiRF SoC I2C master controller driver"); MODULE_DESCRIPTION("SiRF SoC I2C master controller driver");
MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>, " MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>");
"Xiangzhen Ye <Xiangzhen.Ye@csr.com>"); MODULE_AUTHOR("Xiangzhen Ye <Xiangzhen.Ye@csr.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -398,8 +398,7 @@ static irqreturn_t synquacer_i2c_isr(int irq, void *dev_id) ...@@ -398,8 +398,7 @@ static irqreturn_t synquacer_i2c_isr(int irq, void *dev_id)
if (i2c->state == STATE_READ) if (i2c->state == STATE_READ)
goto prepare_read; goto prepare_read;
fallthrough;
/* fall through */
case STATE_WRITE: case STATE_WRITE:
if (bsr & SYNQUACER_I2C_BSR_LRB) { if (bsr & SYNQUACER_I2C_BSR_LRB) {
......
...@@ -293,6 +293,8 @@ struct tegra_i2c_dev { ...@@ -293,6 +293,8 @@ struct tegra_i2c_dev {
bool is_curr_atomic_xfer; bool is_curr_atomic_xfer;
}; };
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev, bool clk_reinit);
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
unsigned long reg) unsigned long reg)
{ {
...@@ -419,7 +421,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev) ...@@ -419,7 +421,7 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
dma_addr_t dma_phys; dma_addr_t dma_phys;
int err; int err;
if (!i2c_dev->hw->has_apb_dma) if (!i2c_dev->hw->has_apb_dma || i2c_dev->is_vi)
return 0; return 0;
if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) { if (!IS_ENABLED(CONFIG_TEGRA20_APB_DMA)) {
...@@ -655,32 +657,47 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev) ...@@ -655,32 +657,47 @@ static int __maybe_unused tegra_i2c_runtime_resume(struct device *dev)
if (ret) if (ret)
return ret; return ret;
if (!i2c_dev->hw->has_single_clk_source) {
ret = clk_enable(i2c_dev->fast_clk); ret = clk_enable(i2c_dev->fast_clk);
if (ret < 0) { if (ret < 0) {
dev_err(i2c_dev->dev, dev_err(i2c_dev->dev,
"Enabling fast clk failed, err %d\n", ret); "Enabling fast clk failed, err %d\n", ret);
return ret; return ret;
} }
}
if (i2c_dev->slow_clk) {
ret = clk_enable(i2c_dev->slow_clk); ret = clk_enable(i2c_dev->slow_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to enable slow clock: %d\n", ret); dev_err(dev, "failed to enable slow clock: %d\n", ret);
return ret; goto disable_fast_clk;
}
} }
ret = clk_enable(i2c_dev->div_clk); ret = clk_enable(i2c_dev->div_clk);
if (ret < 0) { if (ret < 0) {
dev_err(i2c_dev->dev, dev_err(i2c_dev->dev,
"Enabling div clk failed, err %d\n", ret); "Enabling div clk failed, err %d\n", ret);
clk_disable(i2c_dev->fast_clk); goto disable_slow_clk;
return ret; }
/*
* VI I2C device is attached to VE power domain which goes through
* power ON/OFF during PM runtime resume/suspend. So, controller
* should go through reset and need to re-initialize after power
* domain ON.
*/
if (i2c_dev->is_vi) {
ret = tegra_i2c_init(i2c_dev, true);
if (ret)
goto disable_div_clk;
} }
return 0; return 0;
disable_div_clk:
clk_disable(i2c_dev->div_clk);
disable_slow_clk:
clk_disable(i2c_dev->slow_clk);
disable_fast_clk:
clk_disable(i2c_dev->fast_clk);
return ret;
} }
static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev) static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
...@@ -688,11 +705,7 @@ static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev) ...@@ -688,11 +705,7 @@ static int __maybe_unused tegra_i2c_runtime_suspend(struct device *dev)
struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
clk_disable(i2c_dev->div_clk); clk_disable(i2c_dev->div_clk);
if (i2c_dev->slow_clk)
clk_disable(i2c_dev->slow_clk); clk_disable(i2c_dev->slow_clk);
if (!i2c_dev->hw->has_single_clk_source)
clk_disable(i2c_dev->fast_clk); clk_disable(i2c_dev->fast_clk);
return pinctrl_pm_select_idle_state(i2c_dev->dev); return pinctrl_pm_select_idle_state(i2c_dev->dev);
...@@ -1716,21 +1729,17 @@ static int tegra_i2c_probe(struct platform_device *pdev) ...@@ -1716,21 +1729,17 @@ static int tegra_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, i2c_dev); platform_set_drvdata(pdev, i2c_dev);
if (!i2c_dev->hw->has_single_clk_source) {
ret = clk_prepare(i2c_dev->fast_clk); ret = clk_prepare(i2c_dev->fast_clk);
if (ret < 0) { if (ret < 0) {
dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret); dev_err(i2c_dev->dev, "Clock prepare failed %d\n", ret);
return ret; return ret;
} }
}
if (i2c_dev->slow_clk) {
ret = clk_prepare(i2c_dev->slow_clk); ret = clk_prepare(i2c_dev->slow_clk);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "failed to prepare slow clock: %d\n", ret); dev_err(dev, "failed to prepare slow clock: %d\n", ret);
goto unprepare_fast_clk; goto unprepare_fast_clk;
} }
}
if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ && if (i2c_dev->bus_clk_rate > I2C_MAX_FAST_MODE_FREQ &&
i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ) i2c_dev->bus_clk_rate <= I2C_MAX_FAST_MODE_PLUS_FREQ)
...@@ -1750,6 +1759,14 @@ static int tegra_i2c_probe(struct platform_device *pdev) ...@@ -1750,6 +1759,14 @@ static int tegra_i2c_probe(struct platform_device *pdev)
goto unprepare_slow_clk; goto unprepare_slow_clk;
} }
/*
* VI I2C is in VE power domain which is not always on and not
* an IRQ safe. So, IRQ safe device can't be attached to a non-IRQ
* safe domain as it prevents powering off the PM domain.
* Also, VI I2C device don't need to use runtime IRQ safe as it will
* not be used for atomic transfers.
*/
if (!i2c_dev->is_vi)
pm_runtime_irq_safe(&pdev->dev); pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
if (!pm_runtime_enabled(&pdev->dev)) { if (!pm_runtime_enabled(&pdev->dev)) {
...@@ -1835,11 +1852,9 @@ static int tegra_i2c_probe(struct platform_device *pdev) ...@@ -1835,11 +1852,9 @@ static int tegra_i2c_probe(struct platform_device *pdev)
clk_unprepare(i2c_dev->div_clk); clk_unprepare(i2c_dev->div_clk);
unprepare_slow_clk: unprepare_slow_clk:
if (i2c_dev->is_vi)
clk_unprepare(i2c_dev->slow_clk); clk_unprepare(i2c_dev->slow_clk);
unprepare_fast_clk: unprepare_fast_clk:
if (!i2c_dev->hw->has_single_clk_source)
clk_unprepare(i2c_dev->fast_clk); clk_unprepare(i2c_dev->fast_clk);
return ret; return ret;
...@@ -1859,11 +1874,7 @@ static int tegra_i2c_remove(struct platform_device *pdev) ...@@ -1859,11 +1874,7 @@ static int tegra_i2c_remove(struct platform_device *pdev)
tegra_i2c_runtime_suspend(&pdev->dev); tegra_i2c_runtime_suspend(&pdev->dev);
clk_unprepare(i2c_dev->div_clk); clk_unprepare(i2c_dev->div_clk);
if (i2c_dev->slow_clk)
clk_unprepare(i2c_dev->slow_clk); clk_unprepare(i2c_dev->slow_clk);
if (!i2c_dev->hw->has_single_clk_source)
clk_unprepare(i2c_dev->fast_clk); clk_unprepare(i2c_dev->fast_clk);
tegra_i2c_release_dma(i2c_dev); tegra_i2c_release_dma(i2c_dev);
......
...@@ -228,7 +228,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr, ...@@ -228,7 +228,7 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
goto exit_unsupported; goto exit_unsupported;
if (read_write == I2C_SMBUS_READ) if (read_write == I2C_SMBUS_READ)
outb_p(data->block[0], SMBHSTDAT0); outb_p(data->block[0], SMBHSTDAT0);
/* Fall through */ fallthrough;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
outb_p(command, SMBHSTCMD); outb_p(command, SMBHSTCMD);
if (read_write == I2C_SMBUS_WRITE) { if (read_write == I2C_SMBUS_WRITE) {
...@@ -489,9 +489,9 @@ static void __exit i2c_vt596_exit(void) ...@@ -489,9 +489,9 @@ static void __exit i2c_vt596_exit(void)
} }
} }
MODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>, " MODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>");
"Mark D. Studebaker <mdsxyz123@yahoo.com> and " MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
"Jean Delvare <jdelvare@suse.de>"); MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
MODULE_DESCRIPTION("vt82c596 SMBus driver"); MODULE_DESCRIPTION("vt82c596 SMBus driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -151,7 +151,7 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) ...@@ -151,7 +151,7 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status)
case state_repeat_start: case state_repeat_start:
outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1);
/* fallthrough */ fallthrough;
case state_quick: case state_quick:
if (iface->address_byte & 1) { if (iface->address_byte & 1) {
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_domain.h> #include <linux/pm_domain.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pm_wakeirq.h> #include <linux/pm_wakeirq.h>
...@@ -181,6 +182,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap) ...@@ -181,6 +182,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
if (bri->prepare_recovery) if (bri->prepare_recovery)
bri->prepare_recovery(adap); bri->prepare_recovery(adap);
if (bri->pinctrl)
pinctrl_select_state(bri->pinctrl, bri->pins_gpio);
/* /*
* If we can set SDA, we will always create a STOP to ensure additional * If we can set SDA, we will always create a STOP to ensure additional
...@@ -236,6 +239,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap) ...@@ -236,6 +239,8 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
if (bri->unprepare_recovery) if (bri->unprepare_recovery)
bri->unprepare_recovery(adap); bri->unprepare_recovery(adap);
if (bri->pinctrl)
pinctrl_select_state(bri->pinctrl, bri->pins_default);
return ret; return ret;
} }
...@@ -251,13 +256,135 @@ int i2c_recover_bus(struct i2c_adapter *adap) ...@@ -251,13 +256,135 @@ int i2c_recover_bus(struct i2c_adapter *adap)
} }
EXPORT_SYMBOL_GPL(i2c_recover_bus); EXPORT_SYMBOL_GPL(i2c_recover_bus);
static void i2c_init_recovery(struct i2c_adapter *adap) static void i2c_gpio_init_pinctrl_recovery(struct i2c_adapter *adap)
{
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
struct device *dev = &adap->dev;
struct pinctrl *p = bri->pinctrl;
/*
* we can't change states without pinctrl, so remove the states if
* populated
*/
if (!p) {
bri->pins_default = NULL;
bri->pins_gpio = NULL;
return;
}
if (!bri->pins_default) {
bri->pins_default = pinctrl_lookup_state(p,
PINCTRL_STATE_DEFAULT);
if (IS_ERR(bri->pins_default)) {
dev_dbg(dev, PINCTRL_STATE_DEFAULT " state not found for GPIO recovery\n");
bri->pins_default = NULL;
}
}
if (!bri->pins_gpio) {
bri->pins_gpio = pinctrl_lookup_state(p, "gpio");
if (IS_ERR(bri->pins_gpio))
bri->pins_gpio = pinctrl_lookup_state(p, "recovery");
if (IS_ERR(bri->pins_gpio)) {
dev_dbg(dev, "no gpio or recovery state found for GPIO recovery\n");
bri->pins_gpio = NULL;
}
}
/* for pinctrl state changes, we need all the information */
if (bri->pins_default && bri->pins_gpio) {
dev_info(dev, "using pinctrl states for GPIO recovery");
} else {
bri->pinctrl = NULL;
bri->pins_default = NULL;
bri->pins_gpio = NULL;
}
}
static int i2c_gpio_init_generic_recovery(struct i2c_adapter *adap)
{
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
struct device *dev = &adap->dev;
struct gpio_desc *gpiod;
int ret = 0;
/*
* don't touch the recovery information if the driver is not using
* generic SCL recovery
*/
if (bri->recover_bus && bri->recover_bus != i2c_generic_scl_recovery)
return 0;
/*
* pins might be taken as GPIO, so we should inform pinctrl about
* this and move the state to GPIO
*/
if (bri->pinctrl)
pinctrl_select_state(bri->pinctrl, bri->pins_gpio);
/*
* if there is incomplete or no recovery information, see if generic
* GPIO recovery is available
*/
if (!bri->scl_gpiod) {
gpiod = devm_gpiod_get(dev, "scl", GPIOD_OUT_HIGH_OPEN_DRAIN);
if (PTR_ERR(gpiod) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto cleanup_pinctrl_state;
}
if (!IS_ERR(gpiod)) {
bri->scl_gpiod = gpiod;
bri->recover_bus = i2c_generic_scl_recovery;
dev_info(dev, "using generic GPIOs for recovery\n");
}
}
/* SDA GPIOD line is optional, so we care about DEFER only */
if (!bri->sda_gpiod) {
/*
* We have SCL. Pull SCL low and wait a bit so that SDA glitches
* have no effect.
*/
gpiod_direction_output(bri->scl_gpiod, 0);
udelay(10);
gpiod = devm_gpiod_get(dev, "sda", GPIOD_IN);
/* Wait a bit in case of a SDA glitch, and then release SCL. */
udelay(10);
gpiod_direction_output(bri->scl_gpiod, 1);
if (PTR_ERR(gpiod) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto cleanup_pinctrl_state;
}
if (!IS_ERR(gpiod))
bri->sda_gpiod = gpiod;
}
cleanup_pinctrl_state:
/* change the state of the pins back to their default state */
if (bri->pinctrl)
pinctrl_select_state(bri->pinctrl, bri->pins_default);
return ret;
}
static int i2c_gpio_init_recovery(struct i2c_adapter *adap)
{
i2c_gpio_init_pinctrl_recovery(adap);
return i2c_gpio_init_generic_recovery(adap);
}
static int i2c_init_recovery(struct i2c_adapter *adap)
{ {
struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; struct i2c_bus_recovery_info *bri = adap->bus_recovery_info;
char *err_str; char *err_str;
if (!bri) if (!bri)
return; return 0;
if (i2c_gpio_init_recovery(adap) == -EPROBE_DEFER)
return -EPROBE_DEFER;
if (!bri->recover_bus) { if (!bri->recover_bus) {
err_str = "no recover_bus() found"; err_str = "no recover_bus() found";
...@@ -273,10 +400,7 @@ static void i2c_init_recovery(struct i2c_adapter *adap) ...@@ -273,10 +400,7 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
if (gpiod_get_direction(bri->sda_gpiod) == 0) if (gpiod_get_direction(bri->sda_gpiod) == 0)
bri->set_sda = set_sda_gpio_value; bri->set_sda = set_sda_gpio_value;
} }
return; } else if (bri->recover_bus == i2c_generic_scl_recovery) {
}
if (bri->recover_bus == i2c_generic_scl_recovery) {
/* Generic SCL recovery */ /* Generic SCL recovery */
if (!bri->set_scl || !bri->get_scl) { if (!bri->set_scl || !bri->get_scl) {
err_str = "no {get|set}_scl() found"; err_str = "no {get|set}_scl() found";
...@@ -288,10 +412,12 @@ static void i2c_init_recovery(struct i2c_adapter *adap) ...@@ -288,10 +412,12 @@ static void i2c_init_recovery(struct i2c_adapter *adap)
} }
} }
return; return 0;
err: err:
dev_err(&adap->dev, "Not using recovery: %s\n", err_str); dev_err(&adap->dev, "Not using recovery: %s\n", err_str);
adap->bus_recovery_info = NULL; adap->bus_recovery_info = NULL;
return -EINVAL;
} }
static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client) static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client)
...@@ -319,11 +445,9 @@ static int i2c_device_probe(struct device *dev) ...@@ -319,11 +445,9 @@ static int i2c_device_probe(struct device *dev)
if (!client) if (!client)
return 0; return 0;
driver = to_i2c_driver(dev->driver);
client->irq = client->init_irq; client->irq = client->init_irq;
if (!client->irq && !driver->disable_i2c_core_irq_mapping) { if (!client->irq) {
int irq = -ENOENT; int irq = -ENOENT;
if (client->flags & I2C_CLIENT_HOST_NOTIFY) { if (client->flags & I2C_CLIENT_HOST_NOTIFY) {
...@@ -349,6 +473,8 @@ static int i2c_device_probe(struct device *dev) ...@@ -349,6 +473,8 @@ static int i2c_device_probe(struct device *dev)
client->irq = irq; client->irq = irq;
} }
driver = to_i2c_driver(dev->driver);
/* /*
* An I2C ID table is not mandatory, if and only if, a suitable OF * An I2C ID table is not mandatory, if and only if, a suitable OF
* or ACPI ID table is supplied for the probing device. * or ACPI ID table is supplied for the probing device.
...@@ -1227,7 +1353,7 @@ static int i2c_setup_host_notify_irq_domain(struct i2c_adapter *adap) ...@@ -1227,7 +1353,7 @@ static int i2c_setup_host_notify_irq_domain(struct i2c_adapter *adap)
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_HOST_NOTIFY)) if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_HOST_NOTIFY))
return 0; return 0;
domain = irq_domain_create_linear(adap->dev.fwnode, domain = irq_domain_create_linear(adap->dev.parent->fwnode,
I2C_ADDR_7BITS_COUNT, I2C_ADDR_7BITS_COUNT,
&i2c_host_notify_irq_ops, adap); &i2c_host_notify_irq_ops, adap);
if (!domain) if (!domain)
...@@ -1318,12 +1444,16 @@ static int i2c_register_adapter(struct i2c_adapter *adap) ...@@ -1318,12 +1444,16 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
if (res) if (res)
goto out_reg; goto out_reg;
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
pm_runtime_no_callbacks(&adap->dev); pm_runtime_no_callbacks(&adap->dev);
pm_suspend_ignore_children(&adap->dev, true); pm_suspend_ignore_children(&adap->dev, true);
pm_runtime_enable(&adap->dev); pm_runtime_enable(&adap->dev);
res = i2c_init_recovery(adap);
if (res == -EPROBE_DEFER)
goto out_reg;
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
#ifdef CONFIG_I2C_COMPAT #ifdef CONFIG_I2C_COMPAT
res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev, res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,
adap->dev.parent); adap->dev.parent);
...@@ -1332,8 +1462,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap) ...@@ -1332,8 +1462,6 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
"Failed to create compatibility class link\n"); "Failed to create compatibility class link\n");
#endif #endif
i2c_init_recovery(adap);
/* create pre-declared device nodes */ /* create pre-declared device nodes */
of_i2c_register_devices(adap); of_i2c_register_devices(adap);
i2c_acpi_register_devices(adap); i2c_acpi_register_devices(adap);
......
...@@ -761,8 +761,8 @@ static void __exit i2c_dev_exit(void) ...@@ -761,8 +761,8 @@ static void __exit i2c_dev_exit(void)
unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS); unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS);
} }
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
"Simon G. Vogl <simon@tk.uni-linz.ac.at>"); MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C /dev entries driver"); MODULE_DESCRIPTION("I2C /dev entries driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -66,7 +66,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, ...@@ -66,7 +66,7 @@ static int i2c_slave_eeprom_slave_cb(struct i2c_client *client,
case I2C_SLAVE_READ_PROCESSED: case I2C_SLAVE_READ_PROCESSED:
/* The previous byte made it to the bus, get next one */ /* The previous byte made it to the bus, get next one */
eeprom->buffer_idx++; eeprom->buffer_idx++;
/* fallthrough */ fallthrough;
case I2C_SLAVE_READ_REQUESTED: case I2C_SLAVE_READ_REQUESTED:
spin_lock(&eeprom->buffer_lock); spin_lock(&eeprom->buffer_lock);
*val = eeprom->buffer[eeprom->buffer_idx & eeprom->address_mask]; *val = eeprom->buffer[eeprom->buffer_idx & eeprom->address_mask];
......
...@@ -231,7 +231,6 @@ enum i2c_alert_protocol { ...@@ -231,7 +231,6 @@ enum i2c_alert_protocol {
* @detect: Callback for device detection * @detect: Callback for device detection
* @address_list: The I2C addresses to probe (for detect) * @address_list: The I2C addresses to probe (for detect)
* @clients: List of detected clients we created (for i2c-core use only) * @clients: List of detected clients we created (for i2c-core use only)
* @disable_i2c_core_irq_mapping: Tell the i2c-core to not do irq-mapping
* *
* The driver.owner field should be set to the module owner of this driver. * The driver.owner field should be set to the module owner of this driver.
* The driver.name field should be set to the name of this driver. * The driver.name field should be set to the name of this driver.
...@@ -290,8 +289,6 @@ struct i2c_driver { ...@@ -290,8 +289,6 @@ struct i2c_driver {
int (*detect)(struct i2c_client *client, struct i2c_board_info *info); int (*detect)(struct i2c_client *client, struct i2c_board_info *info);
const unsigned short *address_list; const unsigned short *address_list;
struct list_head clients; struct list_head clients;
bool disable_i2c_core_irq_mapping;
}; };
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
...@@ -609,6 +606,14 @@ struct i2c_timings { ...@@ -609,6 +606,14 @@ struct i2c_timings {
* may configure padmux here for SDA/SCL line or something else they want. * may configure padmux here for SDA/SCL line or something else they want.
* @scl_gpiod: gpiod of the SCL line. Only required for GPIO recovery. * @scl_gpiod: gpiod of the SCL line. Only required for GPIO recovery.
* @sda_gpiod: gpiod of the SDA line. Only required for GPIO recovery. * @sda_gpiod: gpiod of the SDA line. Only required for GPIO recovery.
* @pinctrl: pinctrl used by GPIO recovery to change the state of the I2C pins.
* Optional.
* @pins_default: default pinctrl state of SCL/SDA lines, when they are assigned
* to the I2C bus. Optional. Populated internally for GPIO recovery, if
* state with the name PINCTRL_STATE_DEFAULT is found and pinctrl is valid.
* @pins_gpio: recovery pinctrl state of SCL/SDA lines, when they are used as
* GPIOs. Optional. Populated internally for GPIO recovery, if this state
* is called "gpio" or "recovery" and pinctrl is valid.
*/ */
struct i2c_bus_recovery_info { struct i2c_bus_recovery_info {
int (*recover_bus)(struct i2c_adapter *adap); int (*recover_bus)(struct i2c_adapter *adap);
...@@ -625,6 +630,9 @@ struct i2c_bus_recovery_info { ...@@ -625,6 +630,9 @@ struct i2c_bus_recovery_info {
/* gpio recovery */ /* gpio recovery */
struct gpio_desc *scl_gpiod; struct gpio_desc *scl_gpiod;
struct gpio_desc *sda_gpiod; struct gpio_desc *sda_gpiod;
struct pinctrl *pinctrl;
struct pinctrl_state *pins_default;
struct pinctrl_state *pins_gpio;
}; };
int i2c_recover_bus(struct i2c_adapter *adap); int i2c_recover_bus(struct i2c_adapter *adap);
......
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