diff options
Diffstat (limited to 'drivers')
60 files changed, 2216 insertions, 777 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 2ddca08f8a76..6bf68d52a65a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -475,8 +475,8 @@ config I2C_BCM_KONA config I2C_BRCMSTB tristate "BRCM Settop/DSL I2C controller" - depends on ARCH_BRCMSTB || BMIPS_GENERIC || ARCH_BCM_63XX || \ - COMPILE_TEST + depends on ARCH_BCM2835 || ARCH_BRCMSTB || BMIPS_GENERIC || \ + ARCH_BCM_63XX || COMPILE_TEST default y help If you say yes to this option, support will be included for the @@ -527,6 +527,16 @@ config I2C_DAVINCI config I2C_DESIGNWARE_CORE tristate +config I2C_DESIGNWARE_SLAVE + bool "Synopsys DesignWare Slave" + select I2C_SLAVE + help + If you say yes to this option, support will be included for the + Synopsys DesignWare I2C slave adapter. + + This is not a standalone module, this module compiles together with + i2c-designware-core. + config I2C_DESIGNWARE_PLATFORM tristate "Synopsys DesignWare Platform" select I2C_DESIGNWARE_CORE @@ -538,17 +548,6 @@ config I2C_DESIGNWARE_PLATFORM This driver can also be built as a module. If so, the module will be called i2c-designware-platform. -config I2C_DESIGNWARE_SLAVE - bool "Synopsys DesignWare Slave" - select I2C_SLAVE - depends on I2C_DESIGNWARE_PLATFORM - help - If you say yes to this option, support will be included for the - Synopsys DesignWare I2C slave adapter. - - This is not a standalone module, this module compiles together with - i2c-designware-core. - config I2C_DESIGNWARE_PCI tristate "Synopsys DesignWare PCI" depends on PCI @@ -885,6 +884,16 @@ config I2C_PXA_SLAVE is necessary for systems where the PXA may be a target on the I2C bus. +config I2C_QCOM_CCI + tristate "Qualcomm Camera Control Interface" + depends on ARCH_QCOM || COMPILE_TEST + help + If you say yes to this option, support will be included for the + built-in camera control interface on the Qualcomm SoCs. + + This driver can also be built as a module. If so, the module + will be called i2c-qcom-cci. + config I2C_QCOM_GENI tristate "Qualcomm Technologies Inc.'s GENI based I2C controller" depends on ARCH_QCOM || COMPILE_TEST diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 25d60889713c..d5f56e6179a4 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -49,7 +49,8 @@ obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o -i2c-designware-core-objs := i2c-designware-common.o i2c-designware-master.o +i2c-designware-core-objs := i2c-designware-common.o +i2c-designware-core-objs += i2c-designware-master.o ifeq ($(CONFIG_I2C_DESIGNWARE_SLAVE),y) i2c-designware-core-objs += i2c-designware-slave.o endif @@ -91,6 +92,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o +obj-$(CONFIG_I2C_QCOM_CCI) += i2c-qcom-cci.o obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-geni.o obj-$(CONFIG_I2C_QUP) += i2c-qup.o obj-$(CONFIG_I2C_RIIC) += i2c-riic.o diff --git a/drivers/i2c/busses/i2c-altera.c b/drivers/i2c/busses/i2c-altera.c index 16ddc26c00e6..70c81f88b293 100644 --- a/drivers/i2c/busses/i2c-altera.c +++ b/drivers/i2c/busses/i2c-altera.c @@ -389,23 +389,19 @@ static const struct i2c_algorithm altr_i2c_algo = { static int altr_i2c_probe(struct platform_device *pdev) { struct altr_i2c_dev *idev = NULL; - struct resource *res; int irq, ret; idev = devm_kzalloc(&pdev->dev, sizeof(*idev), GFP_KERNEL); if (!idev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - idev->base = devm_ioremap_resource(&pdev->dev, res); + idev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(idev->base)) return PTR_ERR(idev->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "missing interrupt resource\n"); + if (irq < 0) return irq; - } idev->i2c_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(idev->i2c_clk)) { diff --git a/drivers/i2c/busses/i2c-at91-core.c b/drivers/i2c/busses/i2c-at91-core.c index 3da1a8acecb5..e14edd236108 100644 --- a/drivers/i2c/busses/i2c-at91-core.c +++ b/drivers/i2c/busses/i2c-at91-core.c @@ -131,6 +131,7 @@ static struct at91_twi_pdata sama5d2_config = { .has_dig_filtr = true, .has_adv_dig_filtr = true, .has_ana_filtr = true, + .has_clear_cmd = false, /* due to errata, CLEAR cmd is not working */ }; static struct at91_twi_pdata sam9x60_config = { @@ -142,6 +143,7 @@ static struct at91_twi_pdata sam9x60_config = { .has_dig_filtr = true, .has_adv_dig_filtr = true, .has_ana_filtr = true, + .has_clear_cmd = true, }; static const struct of_device_id atmel_twi_dt_ids[] = { diff --git a/drivers/i2c/busses/i2c-at91-master.c b/drivers/i2c/busses/i2c-at91-master.c index 37b96ac9dfae..363d540a8345 100644 --- a/drivers/i2c/busses/i2c-at91-master.c +++ b/drivers/i2c/busses/i2c-at91-master.c @@ -480,7 +480,6 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) unsigned long time_left; bool has_unre_flag = dev->pdata->has_unre_flag; bool has_alt_cmd = dev->pdata->has_alt_cmd; - struct i2c_bus_recovery_info *rinfo = &dev->rinfo; /* * WARNING: the TXCOMP bit in the Status Register is NOT a clear on @@ -641,11 +640,12 @@ error: AT91_TWI_THRCLR | AT91_TWI_LOCKCLR); } - if (rinfo->get_sda && !(rinfo->get_sda(&dev->adapter))) { - dev_dbg(dev->dev, - "SDA is down; clear bus using gpio\n"); - i2c_recover_bus(&dev->adapter); - } + /* + * some faulty I2C slave devices might hold SDA down; + * we can send a bus clear command, hoping that the pins will be + * released + */ + i2c_recover_bus(&dev->adapter); return ret; } @@ -830,7 +830,7 @@ static void at91_unprepare_twi_recovery(struct i2c_adapter *adap) pinctrl_select_state(dev->pinctrl, dev->pinctrl_pins_default); } -static int at91_init_twi_recovery_info(struct platform_device *pdev, +static int at91_init_twi_recovery_gpio(struct platform_device *pdev, struct at91_twi_dev *dev) { struct i2c_bus_recovery_info *rinfo = &dev->rinfo; @@ -894,6 +894,41 @@ static int at91_init_twi_recovery_info(struct platform_device *pdev, return 0; } +static int at91_twi_recover_bus_cmd(struct i2c_adapter *adap) +{ + struct at91_twi_dev *dev = i2c_get_adapdata(adap); + + dev->transfer_status |= at91_twi_read(dev, AT91_TWI_SR); + if (!(dev->transfer_status & AT91_TWI_SDA)) { + dev_dbg(dev->dev, "SDA is down; sending bus clear command\n"); + if (dev->use_alt_cmd) { + unsigned int acr; + + acr = at91_twi_read(dev, AT91_TWI_ACR); + acr &= ~AT91_TWI_ACR_DATAL_MASK; + at91_twi_write(dev, AT91_TWI_ACR, acr); + } + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_CLEAR); + } + + return 0; +} + +static int at91_init_twi_recovery_info(struct platform_device *pdev, + struct at91_twi_dev *dev) +{ + struct i2c_bus_recovery_info *rinfo = &dev->rinfo; + bool has_clear_cmd = dev->pdata->has_clear_cmd; + + if (!has_clear_cmd) + return at91_init_twi_recovery_gpio(pdev, dev); + + rinfo->recover_bus = at91_twi_recover_bus_cmd; + dev->adapter.bus_recovery_info = rinfo; + + return 0; +} + int at91_twi_probe_master(struct platform_device *pdev, u32 phy_addr, struct at91_twi_dev *dev) { diff --git a/drivers/i2c/busses/i2c-at91.h b/drivers/i2c/busses/i2c-at91.h index f57a6cab96b4..7e7b4955ca7f 100644 --- a/drivers/i2c/busses/i2c-at91.h +++ b/drivers/i2c/busses/i2c-at91.h @@ -36,6 +36,7 @@ #define AT91_TWI_SVDIS BIT(5) /* Slave Transfer Disable */ #define AT91_TWI_QUICK BIT(6) /* SMBus quick command */ #define AT91_TWI_SWRST BIT(7) /* Software Reset */ +#define AT91_TWI_CLEAR BIT(15) /* Bus clear command */ #define AT91_TWI_ACMEN BIT(16) /* Alternative Command Mode Enable */ #define AT91_TWI_ACMDIS BIT(17) /* Alternative Command Mode Disable */ #define AT91_TWI_THRCLR BIT(24) /* Transmit Holding Register Clear */ @@ -69,6 +70,8 @@ #define AT91_TWI_NACK BIT(8) /* Not Acknowledged */ #define AT91_TWI_EOSACC BIT(11) /* End Of Slave Access */ #define AT91_TWI_LOCK BIT(23) /* TWI Lock due to Frame Errors */ +#define AT91_TWI_SCL BIT(24) /* TWI SCL status */ +#define AT91_TWI_SDA BIT(25) /* TWI SDA status */ #define AT91_TWI_INT_MASK \ (AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY | AT91_TWI_NACK \ @@ -81,7 +84,8 @@ #define AT91_TWI_THR 0x0034 /* Transmit Holding Register */ #define AT91_TWI_ACR 0x0040 /* Alternative Command Register */ -#define AT91_TWI_ACR_DATAL(len) ((len) & 0xff) +#define AT91_TWI_ACR_DATAL_MASK GENMASK(15, 0) +#define AT91_TWI_ACR_DATAL(len) ((len) & AT91_TWI_ACR_DATAL_MASK) #define AT91_TWI_ACR_DIR BIT(8) #define AT91_TWI_FILTR 0x0044 @@ -118,6 +122,7 @@ struct at91_twi_pdata { bool has_dig_filtr; bool has_adv_dig_filtr; bool has_ana_filtr; + bool has_clear_cmd; struct at_dma_slave dma_slave; }; diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c index be3681d08a8d..5294b73beca8 100644 --- a/drivers/i2c/busses/i2c-axxia.c +++ b/drivers/i2c/busses/i2c-axxia.c @@ -734,7 +734,6 @@ static int axxia_i2c_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct axxia_i2c_dev *idev = NULL; - struct resource *res; void __iomem *base; int ret = 0; @@ -742,16 +741,13 @@ static int axxia_i2c_probe(struct platform_device *pdev) if (!idev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) return PTR_ERR(base); idev->irq = platform_get_irq(pdev, 0); - if (idev->irq < 0) { - dev_err(&pdev->dev, "missing interrupt resource\n"); + if (idev->irq < 0) return idev->irq; - } idev->i2c_clk = devm_clk_get(&pdev->dev, "i2c"); if (IS_ERR(idev->i2c_clk)) { diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c index d091a12596ad..8a3c98866fb7 100644 --- a/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/drivers/i2c/busses/i2c-bcm-iproc.c @@ -79,6 +79,7 @@ #define M_CMD_STATUS_RX_FIFO_FULL 0x6 #define M_CMD_PROTOCOL_SHIFT 9 #define M_CMD_PROTOCOL_MASK 0xf +#define M_CMD_PROTOCOL_QUICK 0x0 #define M_CMD_PROTOCOL_BLK_WR 0x7 #define M_CMD_PROTOCOL_BLK_RD 0x8 #define M_CMD_PROTOCOL_PROCESS 0xa @@ -768,7 +769,11 @@ static int bcm_iproc_i2c_xfer_internal(struct bcm_iproc_i2c_dev *iproc_i2c, * number of bytes to read */ val = BIT(M_CMD_START_BUSY_SHIFT); - if (msg->flags & I2C_M_RD) { + + if (msg->len == 0) { + /* SMBUS QUICK Command (Read/Write) */ + val |= (M_CMD_PROTOCOL_QUICK << M_CMD_PROTOCOL_SHIFT); + } else if (msg->flags & I2C_M_RD) { u32 protocol; iproc_i2c->rx_bytes = 0; @@ -830,8 +835,7 @@ static uint32_t bcm_iproc_i2c_functionality(struct i2c_adapter *adap) { u32 val; - /* We do not support the SMBUS Quick command */ - val = I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); + val = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; if (adap->algo->reg_slave) val |= I2C_FUNC_SLAVE; diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index 572aebbb254e..ed5e1275ae46 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -750,7 +750,6 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev) int rc = 0; struct bcm_kona_i2c_dev *dev; struct i2c_adapter *adap; - struct resource *iomem; /* Allocate memory for private data structure */ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); @@ -762,8 +761,7 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev) init_completion(&dev->done); /* Map hardware registers */ - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->base = devm_ioremap_resource(dev->device, iomem); + dev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dev->base)) return -ENOMEM; @@ -823,8 +821,7 @@ static int bcm_kona_i2c_probe(struct platform_device *pdev) /* Get the interrupt number */ dev->irq = platform_get_irq(pdev, 0); if (dev->irq < 0) { - dev_err(dev->device, "no irq resource\n"); - rc = -ENODEV; + rc = dev->irq; goto probe_disable_clk; } diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 169a2836922d..d4e0a0f6732a 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -647,20 +647,22 @@ static int brcmstb_i2c_probe(struct platform_device *pdev) int_name = NULL; /* Get the interrupt number */ - dev->irq = platform_get_irq(pdev, 0); + dev->irq = platform_get_irq_optional(pdev, 0); /* disable the bsc interrupt line */ brcmstb_i2c_enable_disable_irq(dev, INT_DISABLE); /* register the ISR handler */ - rc = devm_request_irq(&pdev->dev, dev->irq, brcmstb_i2c_isr, - IRQF_SHARED, - int_name ? int_name : pdev->name, - dev); - - if (rc) { - dev_dbg(dev->device, "falling back to polling mode"); - dev->irq = -1; + if (dev->irq >= 0) { + rc = devm_request_irq(&pdev->dev, dev->irq, brcmstb_i2c_isr, + IRQF_SHARED, + int_name ? int_name : pdev->name, + dev); + + if (rc) { + dev_dbg(dev->device, "falling back to polling mode"); + dev->irq = -1; + } } if (of_property_read_u32(dev->device->of_node, diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 89d58f7d2a25..4b72398af505 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -23,6 +23,7 @@ #define CDNS_I2C_ISR_OFFSET 0x10 /* IRQ Status Register, RW */ #define CDNS_I2C_XFER_SIZE_OFFSET 0x14 /* Transfer Size Register, RW */ #define CDNS_I2C_TIME_OUT_OFFSET 0x1C /* Time Out Register, RW */ +#define CDNS_I2C_IMR_OFFSET 0x20 /* IRQ Mask Register, RO */ #define CDNS_I2C_IER_OFFSET 0x24 /* IRQ Enable Register, WO */ #define CDNS_I2C_IDR_OFFSET 0x28 /* IRQ Disable Register, WO */ @@ -40,9 +41,17 @@ #define CDNS_I2C_CR_DIVB_SHIFT 8 #define CDNS_I2C_CR_DIVB_MASK (0x3f << CDNS_I2C_CR_DIVB_SHIFT) +#define CDNS_I2C_CR_MASTER_EN_MASK (CDNS_I2C_CR_NEA | \ + CDNS_I2C_CR_ACK_EN | \ + CDNS_I2C_CR_MS) + +#define CDNS_I2C_CR_SLAVE_EN_MASK ~CDNS_I2C_CR_MASTER_EN_MASK + /* Status Register Bit mask definitions */ #define CDNS_I2C_SR_BA BIT(8) +#define CDNS_I2C_SR_TXDV BIT(6) #define CDNS_I2C_SR_RXDV BIT(5) +#define CDNS_I2C_SR_RXRW BIT(3) /* * I2C Address Register Bit mask definitions @@ -91,6 +100,14 @@ CDNS_I2C_IXR_DATA | \ CDNS_I2C_IXR_COMP) +#define CDNS_I2C_IXR_SLAVE_INTR_MASK (CDNS_I2C_IXR_RX_UNF | \ + CDNS_I2C_IXR_TX_OVF | \ + CDNS_I2C_IXR_RX_OVF | \ + CDNS_I2C_IXR_TO | \ + CDNS_I2C_IXR_NACK | \ + CDNS_I2C_IXR_DATA | \ + CDNS_I2C_IXR_COMP) + #define CDNS_I2C_TIMEOUT msecs_to_jiffies(1000) /* timeout for pm runtime autosuspend */ #define CNDS_I2C_PM_TIMEOUT 1000 /* ms */ @@ -114,6 +131,32 @@ #define cdns_i2c_readreg(offset) readl_relaxed(id->membase + offset) #define cdns_i2c_writereg(val, offset) writel_relaxed(val, id->membase + offset) +#if IS_ENABLED(CONFIG_I2C_SLAVE) +/** + * enum cdns_i2c_mode - I2C Controller current operating mode + * + * @CDNS_I2C_MODE_SLAVE: I2C controller operating in slave mode + * @CDNS_I2C_MODE_MASTER: I2C Controller operating in master mode + */ +enum cdns_i2c_mode { + CDNS_I2C_MODE_SLAVE, + CDNS_I2C_MODE_MASTER, +}; + +/** + * enum cdns_i2c_slave_mode - Slave state when I2C is operating in slave mode + * + * @CDNS_I2C_SLAVE_STATE_IDLE: I2C slave idle + * @CDNS_I2C_SLAVE_STATE_SEND: I2C slave sending data to master + * @CDNS_I2C_SLAVE_STATE_RECV: I2C slave receiving data from master + */ +enum cdns_i2c_slave_state { + CDNS_I2C_SLAVE_STATE_IDLE, + CDNS_I2C_SLAVE_STATE_SEND, + CDNS_I2C_SLAVE_STATE_RECV, +}; +#endif + /** * struct cdns_i2c - I2C device private data structure * @@ -135,6 +178,10 @@ * @clk: Pointer to struct clk * @clk_rate_change_nb: Notifier block for clock rate changes * @quirks: flag for broken hold bit usage in r1p10 + * @ctrl_reg_diva_divb: value of fields DIV_A and DIV_B from CR register + * @slave: Registered slave instance. + * @dev_mode: I2C operating role(master/slave). + * @slave_state: I2C Slave state(idle/read/write). */ struct cdns_i2c { struct device *dev; @@ -155,6 +202,12 @@ struct cdns_i2c { struct clk *clk; struct notifier_block clk_rate_change_nb; u32 quirks; +#if IS_ENABLED(CONFIG_I2C_SLAVE) + u16 ctrl_reg_diva_divb; + struct i2c_client *slave; + enum cdns_i2c_mode dev_mode; + enum cdns_i2c_slave_state slave_state; +#endif }; struct cdns_platform_data { @@ -183,17 +236,155 @@ static inline bool cdns_is_holdquirk(struct cdns_i2c *id, bool hold_wrkaround) (id->curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1)); } +#if IS_ENABLED(CONFIG_I2C_SLAVE) +static void cdns_i2c_set_mode(enum cdns_i2c_mode mode, struct cdns_i2c *id) +{ + /* Disable all interrupts */ + cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, CDNS_I2C_IDR_OFFSET); + + /* Clear FIFO and transfer size */ + cdns_i2c_writereg(CDNS_I2C_CR_CLR_FIFO, CDNS_I2C_CR_OFFSET); + + /* Update device mode and state */ + id->dev_mode = mode; + id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE; + + switch (mode) { + case CDNS_I2C_MODE_MASTER: + /* Enable i2c master */ + cdns_i2c_writereg(id->ctrl_reg_diva_divb | + CDNS_I2C_CR_MASTER_EN_MASK, + CDNS_I2C_CR_OFFSET); + /* + * This delay is needed to give the IP some time to switch to + * the master mode. With lower values(like 110 us) i2cdetect + * will not detect any slave and without this delay, the IP will + * trigger a timeout interrupt. + */ + usleep_range(115, 125); + break; + case CDNS_I2C_MODE_SLAVE: + /* Enable i2c slave */ + cdns_i2c_writereg(id->ctrl_reg_diva_divb & + CDNS_I2C_CR_SLAVE_EN_MASK, + CDNS_I2C_CR_OFFSET); + + /* Setting slave address */ + cdns_i2c_writereg(id->slave->addr & CDNS_I2C_ADDR_MASK, + CDNS_I2C_ADDR_OFFSET); + + /* Enable slave send/receive interrupts */ + cdns_i2c_writereg(CDNS_I2C_IXR_SLAVE_INTR_MASK, + CDNS_I2C_IER_OFFSET); + break; + } +} + +static void cdns_i2c_slave_rcv_data(struct cdns_i2c *id) +{ + u8 bytes; + unsigned char data; + + /* Prepare backend for data reception */ + if (id->slave_state == CDNS_I2C_SLAVE_STATE_IDLE) { + id->slave_state = CDNS_I2C_SLAVE_STATE_RECV; + i2c_slave_event(id->slave, I2C_SLAVE_WRITE_REQUESTED, NULL); + } + + /* Fetch number of bytes to receive */ + bytes = cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET); + + /* Read data and send to backend */ + while (bytes--) { + data = cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); + i2c_slave_event(id->slave, I2C_SLAVE_WRITE_RECEIVED, &data); + } +} + +static void cdns_i2c_slave_send_data(struct cdns_i2c *id) +{ + u8 data; + + /* Prepare backend for data transmission */ + if (id->slave_state == CDNS_I2C_SLAVE_STATE_IDLE) { + id->slave_state = CDNS_I2C_SLAVE_STATE_SEND; + i2c_slave_event(id->slave, I2C_SLAVE_READ_REQUESTED, &data); + } else { + i2c_slave_event(id->slave, I2C_SLAVE_READ_PROCESSED, &data); + } + + /* Send data over bus */ + cdns_i2c_writereg(data, CDNS_I2C_DATA_OFFSET); +} + /** - * cdns_i2c_isr - Interrupt handler for the I2C device - * @irq: irq number for the I2C device - * @ptr: void pointer to cdns_i2c structure + * cdns_i2c_slave_isr - Interrupt handler for the I2C device in slave role + * @ptr: Pointer to I2C device private data + * + * This function handles the data interrupt and transfer complete interrupt of + * the I2C device in slave role. + * + * Return: IRQ_HANDLED always + */ +static irqreturn_t cdns_i2c_slave_isr(void *ptr) +{ + struct cdns_i2c *id = ptr; + unsigned int isr_status, i2c_status; + + /* Fetch the interrupt status */ + isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET); + cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET); + + /* Ignore masked interrupts */ + isr_status &= ~cdns_i2c_readreg(CDNS_I2C_IMR_OFFSET); + + /* Fetch transfer mode (send/receive) */ + i2c_status = cdns_i2c_readreg(CDNS_I2C_SR_OFFSET); + + /* Handle data send/receive */ + if (i2c_status & CDNS_I2C_SR_RXRW) { + /* Send data to master */ + if (isr_status & CDNS_I2C_IXR_DATA) + cdns_i2c_slave_send_data(id); + + if (isr_status & CDNS_I2C_IXR_COMP) { + id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE; + i2c_slave_event(id->slave, I2C_SLAVE_STOP, NULL); + } + } else { + /* Receive data from master */ + if (isr_status & CDNS_I2C_IXR_DATA) + cdns_i2c_slave_rcv_data(id); + + if (isr_status & CDNS_I2C_IXR_COMP) { + cdns_i2c_slave_rcv_data(id); + id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE; + i2c_slave_event(id->slave, I2C_SLAVE_STOP, NULL); + } + } + + /* Master indicated xfer stop or fifo underflow/overflow */ + if (isr_status & (CDNS_I2C_IXR_NACK | CDNS_I2C_IXR_RX_OVF | + CDNS_I2C_IXR_RX_UNF | CDNS_I2C_IXR_TX_OVF)) { + id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE; + i2c_slave_event(id->slave, I2C_SLAVE_STOP, NULL); + cdns_i2c_writereg(CDNS_I2C_CR_CLR_FIFO, CDNS_I2C_CR_OFFSET); + } + + return IRQ_HANDLED; +} +#endif + +/** + * cdns_i2c_master_isr - Interrupt handler for the I2C device in master role + * @ptr: Pointer to I2C device private data * * This function handles the data interrupt, transfer complete interrupt and - * the error interrupts of the I2C device. + * the error interrupts of the I2C device in master role. * * Return: IRQ_HANDLED always */ -static irqreturn_t cdns_i2c_isr(int irq, void *ptr) +static irqreturn_t cdns_i2c_master_isr(void *ptr) { unsigned int isr_status, avail_bytes, updatetx; unsigned int bytes_to_send; @@ -358,6 +549,27 @@ static irqreturn_t cdns_i2c_isr(int irq, void *ptr) } /** + * cdns_i2c_isr - Interrupt handler for the I2C device + * @irq: irq number for the I2C device + * @ptr: void pointer to cdns_i2c structure + * + * This function passes the control to slave/master based on current role of + * i2c controller. + * + * Return: IRQ_HANDLED always + */ +static irqreturn_t cdns_i2c_isr(int irq, void *ptr) +{ +#if IS_ENABLED(CONFIG_I2C_SLAVE) + struct cdns_i2c *id = ptr; + + if (id->dev_mode == CDNS_I2C_MODE_SLAVE) + return cdns_i2c_slave_isr(ptr); +#endif + return cdns_i2c_master_isr(ptr); +} + +/** * cdns_i2c_mrecv - Prepare and start a master receive operation * @id: pointer to the i2c device structure */ @@ -577,10 +789,28 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, u32 reg; struct cdns_i2c *id = adap->algo_data; bool hold_quirk; +#if IS_ENABLED(CONFIG_I2C_SLAVE) + bool change_role = false; +#endif ret = pm_runtime_get_sync(id->dev); if (ret < 0) return ret; + +#if IS_ENABLED(CONFIG_I2C_SLAVE) + /* Check i2c operating mode and switch if possible */ + if (id->dev_mode == CDNS_I2C_MODE_SLAVE) { + if (id->slave_state != CDNS_I2C_SLAVE_STATE_IDLE) + return -EAGAIN; + + /* Set mode to master */ + cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id); + + /* Mark flag to change role once xfer is completed */ + change_role = true; + } +#endif + /* Check if the bus is free */ if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) { ret = -EAGAIN; @@ -639,7 +869,15 @@ static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, } ret = num; + out: + +#if IS_ENABLED(CONFIG_I2C_SLAVE) + /* Switch i2c mode to slave */ + if (change_role) + cdns_i2c_set_mode(CDNS_I2C_MODE_SLAVE, id); +#endif + pm_runtime_mark_last_busy(id->dev); pm_runtime_put_autosuspend(id->dev); return ret; @@ -653,14 +891,67 @@ out: */ static u32 cdns_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | - (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | - I2C_FUNC_SMBUS_BLOCK_DATA; + u32 func = I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | + (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | + I2C_FUNC_SMBUS_BLOCK_DATA; + +#if IS_ENABLED(CONFIG_I2C_SLAVE) + func |= I2C_FUNC_SLAVE; +#endif + + return func; } +#if IS_ENABLED(CONFIG_I2C_SLAVE) +static int cdns_reg_slave(struct i2c_client *slave) +{ + int ret; + struct cdns_i2c *id = container_of(slave->adapter, struct cdns_i2c, + adap); + + if (id->slave) + return -EBUSY; + + if (slave->flags & I2C_CLIENT_TEN) + return -EAFNOSUPPORT; + + ret = pm_runtime_get_sync(id->dev); + if (ret < 0) + return ret; + + /* Store slave information */ + id->slave = slave; + + /* Enable I2C slave */ + cdns_i2c_set_mode(CDNS_I2C_MODE_SLAVE, id); + + return 0; +} + +static int cdns_unreg_slave(struct i2c_client *slave) +{ + struct cdns_i2c *id = container_of(slave->adapter, struct cdns_i2c, + adap); + + pm_runtime_put(id->dev); + + /* Remove slave information */ + id->slave = NULL; + + /* Enable I2C master */ + cdns_i2c_set_mode(CDNS_I2C_MODE_MASTER, id); + + return 0; +} +#endif + static const struct i2c_algorithm cdns_i2c_algo = { .master_xfer = cdns_i2c_master_xfer, .functionality = cdns_i2c_func, +#if IS_ENABLED(CONFIG_I2C_SLAVE) + .reg_slave = cdns_reg_slave, + .unreg_slave = cdns_unreg_slave, +#endif }; /** @@ -755,7 +1046,10 @@ static int cdns_i2c_setclk(unsigned long clk_in, struct cdns_i2c *id) ctrl_reg |= ((div_a << CDNS_I2C_CR_DIVA_SHIFT) | (div_b << CDNS_I2C_CR_DIVB_SHIFT)); cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); - +#if IS_ENABLED(CONFIG_I2C_SLAVE) + id->ctrl_reg_diva_divb = ctrl_reg & (CDNS_I2C_CR_DIVA_MASK | + CDNS_I2C_CR_DIVB_MASK); +#endif return 0; } @@ -906,8 +1200,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) id->quirks = data->quirks; } - r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - id->membase = devm_ioremap_resource(&pdev->dev, r_mem); + id->membase = devm_platform_get_and_ioremap_resource(pdev, 0, &r_mem); if (IS_ERR(id->membase)) return PTR_ERR(id->membase); @@ -949,8 +1242,12 @@ static int cdns_i2c_probe(struct platform_device *pdev) if (ret || (id->i2c_clk > I2C_MAX_FAST_MODE_FREQ)) id->i2c_clk = I2C_MAX_STANDARD_MODE_FREQ; - cdns_i2c_writereg(CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS, - CDNS_I2C_CR_OFFSET); +#if IS_ENABLED(CONFIG_I2C_SLAVE) + /* Set initial mode to master */ + id->dev_mode = CDNS_I2C_MODE_MASTER; + id->slave_state = CDNS_I2C_SLAVE_STATE_IDLE; +#endif + cdns_i2c_writereg(CDNS_I2C_CR_MASTER_EN_MASK, CDNS_I2C_CR_OFFSET); ret = cdns_i2c_setclk(id->input_clk, id); if (ret) { diff --git a/drivers/i2c/busses/i2c-cht-wc.c b/drivers/i2c/busses/i2c-cht-wc.c index 35e55feda763..f80d79e973cd 100644 --- a/drivers/i2c/busses/i2c-cht-wc.c +++ b/drivers/i2c/busses/i2c-cht-wc.c @@ -314,10 +314,8 @@ static int cht_wc_i2c_adap_i2c_probe(struct platform_device *pdev) int ret, reg, irq; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "Error missing irq resource\n"); - return -EINVAL; - } + if (irq < 0) + return irq; adap = devm_kzalloc(&pdev->dev, sizeof(*adap), GFP_KERNEL); if (!adap) diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index e3ceb256a380..232a7679b69b 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -761,7 +761,6 @@ static int davinci_i2c_probe(struct platform_device *pdev) { struct davinci_i2c_dev *dev; struct i2c_adapter *adap; - struct resource *mem; struct i2c_bus_recovery_info *rinfo; int r, irq; @@ -814,8 +813,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) if (IS_ERR(dev->clk)) return PTR_ERR(dev->clk); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->base = devm_ioremap_resource(&pdev->dev, mem); + dev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dev->base)) { return PTR_ERR(dev->base); } diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index b220ad64c38d..1674caf27745 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -314,13 +314,38 @@ static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev) void __i2c_dw_disable(struct dw_i2c_dev *dev); -extern int i2c_dw_probe(struct dw_i2c_dev *dev); +extern void i2c_dw_configure_master(struct dw_i2c_dev *dev); +extern int i2c_dw_probe_master(struct dw_i2c_dev *dev); + #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_SLAVE) +extern void i2c_dw_configure_slave(struct dw_i2c_dev *dev); extern int i2c_dw_probe_slave(struct dw_i2c_dev *dev); #else +static inline void i2c_dw_configure_slave(struct dw_i2c_dev *dev) { } static inline int i2c_dw_probe_slave(struct dw_i2c_dev *dev) { return -EINVAL; } #endif +static inline int i2c_dw_probe(struct dw_i2c_dev *dev) +{ + switch (dev->mode) { + case DW_IC_SLAVE: + return i2c_dw_probe_slave(dev); + case DW_IC_MASTER: + return i2c_dw_probe_master(dev); + default: + dev_err(dev->dev, "Wrong operation mode: %d\n", dev->mode); + return -EINVAL; + } +} + +static inline void i2c_dw_configure(struct dw_i2c_dev *dev) +{ + if (i2c_detect_slave_mode(dev->dev)) + i2c_dw_configure_slave(dev); + else + i2c_dw_configure_master(dev); +} + #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_BAYTRAIL) extern int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev); #else diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index 3a58eef20936..95eeec53c744 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -76,14 +76,27 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev) */ if (t->bus_freq_hz == 1000000) { /* - * Check are fast mode plus parameters available and use - * fast mode if not. + * Check are Fast Mode Plus parameters available. Calculate + * SCL timing parameters for Fast Mode Plus if not set. */ if (dev->fp_hcnt && dev->fp_lcnt) { dev->fs_hcnt = dev->fp_hcnt; dev->fs_lcnt = dev->fp_lcnt; - fp_str = " Plus"; + } else { + ic_clk = i2c_dw_clk_rate(dev); + dev->fs_hcnt = + i2c_dw_scl_hcnt(ic_clk, + 260, /* tHIGH = 260 ns */ + sda_falling_time, + 0, /* DW default */ + 0); /* No offset */ + dev->fs_lcnt = + i2c_dw_scl_lcnt(ic_clk, + 500, /* tLOW = 500 ns */ + scl_falling_time, + 0); /* No offset */ } + fp_str = " Plus"; } /* * Calculate SCL timing parameters for fast mode if not set. They are @@ -116,10 +129,22 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev) dev->master_cfg |= DW_IC_CON_SPEED_FAST; dev->hs_hcnt = 0; dev->hs_lcnt = 0; - } else if (dev->hs_hcnt && dev->hs_lcnt) { - dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n", - dev->hs_hcnt, dev->hs_lcnt); + } else if (!dev->hs_hcnt || !dev->hs_lcnt) { + ic_clk = i2c_dw_clk_rate(dev); + dev->hs_hcnt = + i2c_dw_scl_hcnt(ic_clk, + 160, /* tHIGH = 160 ns */ + sda_falling_time, + 0, /* DW default */ + 0); /* No offset */ + dev->hs_lcnt = + i2c_dw_scl_lcnt(ic_clk, + 320, /* tLOW = 320 ns */ + scl_falling_time, + 0); /* No offset */ } + dev_dbg(dev->dev, "High Speed Mode HCNT:LCNT = %d:%d\n", + dev->hs_hcnt, dev->hs_lcnt); } ret = i2c_dw_set_sda_hold(dev); @@ -632,6 +657,30 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) return IRQ_HANDLED; } +void i2c_dw_configure_master(struct dw_i2c_dev *dev) +{ + struct i2c_timings *t = &dev->timings; + + dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY; + + dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | + DW_IC_CON_RESTART_EN; + + dev->mode = DW_IC_MASTER; + + switch (t->bus_freq_hz) { + case I2C_MAX_STANDARD_MODE_FREQ: + dev->master_cfg |= DW_IC_CON_SPEED_STD; + break; + case I2C_MAX_HIGH_SPEED_MODE_FREQ: + dev->master_cfg |= DW_IC_CON_SPEED_HIGH; + break; + default: + dev->master_cfg |= DW_IC_CON_SPEED_FAST; + } +} +EXPORT_SYMBOL_GPL(i2c_dw_configure_master); + static void i2c_dw_prepare_recovery(struct i2c_adapter *adap) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); @@ -678,7 +727,7 @@ static int i2c_dw_init_recovery_info(struct dw_i2c_dev *dev) return 0; } -int i2c_dw_probe(struct dw_i2c_dev *dev) +int i2c_dw_probe_master(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; unsigned long irq_flags; @@ -745,7 +794,7 @@ int i2c_dw_probe(struct dw_i2c_dev *dev) return ret; } -EXPORT_SYMBOL_GPL(i2c_dw_probe); +EXPORT_SYMBOL_GPL(i2c_dw_probe_master); MODULE_DESCRIPTION("Synopsys DesignWare I2C bus master adapter"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 7a0b65b5b5b5..c762e5a11e44 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -46,20 +46,14 @@ struct dw_scl_sda_cfg { struct dw_pci_controller { u32 bus_num; - u32 bus_cfg; u32 tx_fifo_depth; u32 rx_fifo_depth; u32 clk_khz; - u32 functionality; u32 flags; struct dw_scl_sda_cfg *scl_sda_cfg; int (*setup)(struct pci_dev *pdev, struct dw_pci_controller *c); }; -#define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \ - DW_IC_CON_SLAVE_DISABLE | \ - DW_IC_CON_RESTART_EN) - /* Merrifield HCNT/LCNT/SDA hold time */ static struct dw_scl_sda_cfg mrfld_config = { .ss_hcnt = 0x2f8, @@ -88,10 +82,11 @@ static struct dw_scl_sda_cfg hsw_config = { static int mfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c) { + struct dw_i2c_dev *dev = dev_get_drvdata(&pdev->dev); + switch (pdev->device) { case 0x0817: - c->bus_cfg &= ~DW_IC_CON_SPEED_MASK; - c->bus_cfg |= DW_IC_CON_SPEED_STD; + dev->timings.bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ; /* fall through */ case 0x0818: case 0x0819: @@ -128,53 +123,41 @@ static int mrfld_setup(struct pci_dev *pdev, struct dw_pci_controller *c) static struct dw_pci_controller dw_pci_controllers[] = { [medfield] = { .bus_num = -1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, .tx_fifo_depth = 32, .rx_fifo_depth = 32, - .functionality = I2C_FUNC_10BIT_ADDR, .clk_khz = 25000, .setup = mfld_setup, }, [merrifield] = { .bus_num = -1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, .tx_fifo_depth = 64, .rx_fifo_depth = 64, - .functionality = I2C_FUNC_10BIT_ADDR, .scl_sda_cfg = &mrfld_config, .setup = mrfld_setup, }, [baytrail] = { .bus_num = -1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, .tx_fifo_depth = 32, .rx_fifo_depth = 32, - .functionality = I2C_FUNC_10BIT_ADDR, .scl_sda_cfg = &byt_config, }, [haswell] = { .bus_num = -1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, .tx_fifo_depth = 32, .rx_fifo_depth = 32, - .functionality = I2C_FUNC_10BIT_ADDR, .scl_sda_cfg = &hsw_config, }, [cherrytrail] = { .bus_num = -1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, .tx_fifo_depth = 32, .rx_fifo_depth = 32, - .functionality = I2C_FUNC_10BIT_ADDR, .flags = MODEL_CHERRYTRAIL, .scl_sda_cfg = &byt_config, }, [elkhartlake] = { .bus_num = -1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, .tx_fifo_depth = 32, .rx_fifo_depth = 32, - .functionality = I2C_FUNC_10BIT_ADDR, .clk_khz = 100000, }, }; @@ -250,14 +233,16 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, if (r < 0) return r; - dev->clk = NULL; dev->controller = controller; dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; + dev->timings.bus_freq_hz = I2C_MAX_FAST_MODE_FREQ; dev->base = pcim_iomap_table(pdev)[0]; dev->dev = &pdev->dev; dev->irq = pci_irq_vector(pdev, 0); dev->flags |= controller->flags; + pci_set_drvdata(pdev, dev); + if (controller->setup) { r = controller->setup(pdev, controller); if (r) { @@ -266,10 +251,8 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, } } - dev->functionality = controller->functionality | - DW_IC_DEFAULT_FUNCTIONALITY; + i2c_dw_configure(dev); - dev->master_cfg = controller->bus_cfg; if (controller->scl_sda_cfg) { cfg = controller->scl_sda_cfg; dev->ss_hcnt = cfg->ss_hcnt; @@ -279,8 +262,6 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, dev->sda_hold_time = cfg->sda_hold; } - pci_set_drvdata(pdev, dev); - dev->tx_fifo_depth = controller->tx_fifo_depth; dev->rx_fifo_depth = controller->rx_fifo_depth; diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 5536673060cc..01db634461b6 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -157,12 +157,10 @@ static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev) static int dw_i2c_of_configure(struct platform_device *pdev) { struct dw_i2c_dev *dev = platform_get_drvdata(pdev); - struct resource *mem; switch (dev->flags & MODEL_MASK) { case MODEL_MSCC_OCELOT: - mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); - dev->ext = devm_ioremap_resource(&pdev->dev, mem); + dev->ext = devm_platform_ioremap_resource(pdev, 1); if (!IS_ERR(dev->ext)) dev->set_sda_hold_time = mscc_twi_set_sda_hold_time; break; @@ -186,39 +184,6 @@ static inline int dw_i2c_of_configure(struct platform_device *pdev) } #endif -static void i2c_dw_configure_master(struct dw_i2c_dev *dev) -{ - struct i2c_timings *t = &dev->timings; - - dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY; - - dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | - DW_IC_CON_RESTART_EN; - - dev->mode = DW_IC_MASTER; - - switch (t->bus_freq_hz) { - case I2C_MAX_STANDARD_MODE_FREQ: - dev->master_cfg |= DW_IC_CON_SPEED_STD; - break; - case I2C_MAX_HIGH_SPEED_MODE_FREQ: - dev->master_cfg |= DW_IC_CON_SPEED_HIGH; - break; - default: - dev->master_cfg |= DW_IC_CON_SPEED_FAST; - } -} - -static void i2c_dw_configure_slave(struct dw_i2c_dev *dev) -{ - dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY; - - dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL | - DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED; - - dev->mode = DW_IC_SLAVE; -} - static void dw_i2c_plat_pm_cleanup(struct dw_i2c_dev *dev) { pm_runtime_disable(dev->dev); @@ -241,7 +206,6 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) struct dw_i2c_dev *dev; struct i2c_timings *t; u32 acpi_speed; - struct resource *mem; int i, irq, ret; irq = platform_get_irq(pdev, 0); @@ -252,8 +216,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) if (!dev) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->base = devm_ioremap_resource(&pdev->dev, mem); + dev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(dev->base)) return PTR_ERR(dev->base); @@ -323,10 +286,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) if (ret) goto exit_reset; - if (i2c_detect_slave_mode(&pdev->dev)) - i2c_dw_configure_slave(dev); - else - i2c_dw_configure_master(dev); + i2c_dw_configure(dev); /* Optional interface clock */ dev->pclk = devm_clk_get_optional(&pdev->dev, "pclk"); @@ -377,11 +337,7 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - if (dev->mode == DW_IC_SLAVE) - ret = i2c_dw_probe_slave(dev); - else - ret = i2c_dw_probe(dev); - + ret = i2c_dw_probe(dev); if (ret) goto exit_probe; diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c index f5ecf76c0d02..576e7af4e94b 100644 --- a/drivers/i2c/busses/i2c-designware-slave.c +++ b/drivers/i2c/busses/i2c-designware-slave.c @@ -241,6 +241,17 @@ static const struct i2c_algorithm i2c_dw_algo = { .unreg_slave = i2c_dw_unreg_slave, }; +void i2c_dw_configure_slave(struct dw_i2c_dev *dev) +{ + dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY; + + dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL | + DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED; + + dev->mode = DW_IC_SLAVE; +} +EXPORT_SYMBOL_GPL(i2c_dw_configure_slave); + int i2c_dw_probe_slave(struct dw_i2c_dev *dev) { struct i2c_adapter *adap = &dev->adapter; diff --git a/drivers/i2c/busses/i2c-digicolor.c b/drivers/i2c/busses/i2c-digicolor.c index 056a5c4f0833..332f00437479 100644 --- a/drivers/i2c/busses/i2c-digicolor.c +++ b/drivers/i2c/busses/i2c-digicolor.c @@ -290,7 +290,6 @@ static int dc_i2c_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct dc_i2c *i2c; - struct resource *r; int ret = 0, irq; i2c = devm_kzalloc(&pdev->dev, sizeof(struct dc_i2c), GFP_KERNEL); @@ -311,8 +310,7 @@ static int dc_i2c_probe(struct platform_device *pdev) if (IS_ERR(i2c->clk)) return PTR_ERR(i2c->clk); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->regs = devm_ioremap_resource(&pdev->dev, r); + i2c->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->regs)) return PTR_ERR(i2c->regs); diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c index 959d4912ec0d..1a319352e51b 100644 --- a/drivers/i2c/busses/i2c-emev2.c +++ b/drivers/i2c/busses/i2c-emev2.c @@ -361,15 +361,13 @@ static const struct i2c_algorithm em_i2c_algo = { static int em_i2c_probe(struct platform_device *pdev) { struct em_i2c_device *priv; - struct resource *r; int ret; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, r); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 527030953ba1..ba7033c9e157 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -736,7 +736,6 @@ static int exynos5_i2c_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct exynos5_i2c *i2c; - struct resource *mem; int ret; i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL); @@ -762,8 +761,7 @@ static int exynos5_i2c_probe(struct platform_device *pdev) if (ret) return ret; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + i2c->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->regs)) { ret = PTR_ERR(i2c->regs); goto err_clk; diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 6610304b6dc6..ab15b1ec2ab3 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -388,7 +388,6 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct hix5hd2_i2c_priv *priv; - struct resource *mem; unsigned int freq; int irq, ret; @@ -409,8 +408,7 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev) } } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->regs = devm_ioremap_resource(&pdev->dev, mem); + priv->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->regs)) return PTR_ERR(priv->regs); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index a9c03f5c3482..4f333889489c 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -1439,9 +1439,9 @@ static int i801_add_mux(struct i801_priv *priv) return -ENOMEM; lookup->dev_id = "i2c-mux-gpio"; for (i = 0; i < mux_config->n_gpios; i++) { - lookup->table[i].chip_label = mux_config->gpio_chip; - lookup->table[i].chip_hwnum = mux_config->gpios[i]; - lookup->table[i].con_id = "mux"; + lookup->table[i] = (struct gpiod_lookup) + GPIO_LOOKUP(mux_config->gpio_chip, + mux_config->gpios[i], "mux", 0); } gpiod_add_lookup_table(lookup); priv->lookup = lookup; diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 422097a31c95..98a89301ed2a 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -1330,7 +1330,6 @@ static int img_i2c_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct img_i2c *i2c; - struct resource *res; int irq, ret; u32 val; @@ -1338,16 +1337,13 @@ static int img_i2c_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->base = devm_ioremap_resource(&pdev->dev, res); + i2c->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "can't get irq number\n"); + if (irq < 0) return irq; - } i2c->sys_clk = devm_clk_get(&pdev->dev, "sys"); if (IS_ERR(i2c->sys_clk)) { diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c index 94743ba581fe..9db6ccded5e9 100644 --- a/drivers/i2c/busses/i2c-imx-lpi2c.c +++ b/drivers/i2c/busses/i2c-imx-lpi2c.c @@ -551,10 +551,8 @@ static int lpi2c_imx_probe(struct platform_device *pdev) return PTR_ERR(lpi2c_imx->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "can't get irq number\n"); + if (irq < 0) return irq; - } lpi2c_imx->adapter.owner = THIS_MODULE; lpi2c_imx->adapter.algo = &lpi2c_imx_algo; diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index b426fc956938..ba831df6661e 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -763,7 +763,6 @@ static int jz4780_i2c_probe(struct platform_device *pdev) int ret = 0; unsigned int clk_freq = 0; unsigned short tmp; - struct resource *r; struct jz4780_i2c *i2c; i2c = devm_kzalloc(&pdev->dev, sizeof(struct jz4780_i2c), GFP_KERNEL); @@ -787,8 +786,7 @@ static int jz4780_i2c_probe(struct platform_device *pdev) init_completion(&i2c->trans_waitq); spin_lock_init(&i2c->lock); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->iomem = devm_ioremap_resource(&pdev->dev, r); + i2c->iomem = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->iomem)) return PTR_ERR(i2c->iomem); diff --git a/drivers/i2c/busses/i2c-lpc2k.c b/drivers/i2c/busses/i2c-lpc2k.c index 13b0c12e2dba..4e30c5267142 100644 --- a/drivers/i2c/busses/i2c-lpc2k.c +++ b/drivers/i2c/busses/i2c-lpc2k.c @@ -346,7 +346,6 @@ static const struct i2c_algorithm i2c_lpc2k_algorithm = { static int i2c_lpc2k_probe(struct platform_device *pdev) { struct lpc2k_i2c *i2c; - struct resource *res; u32 bus_clk_rate; u32 scl_high; u32 clkrate; @@ -356,16 +355,13 @@ static int i2c_lpc2k_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->base = devm_ioremap_resource(&pdev->dev, res); + i2c->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); i2c->irq = platform_get_irq(pdev, 0); - if (i2c->irq < 0) { - dev_err(&pdev->dev, "can't get interrupt resource\n"); + if (i2c->irq < 0) return i2c->irq; - } init_waitqueue_head(&i2c->wait); diff --git a/drivers/i2c/busses/i2c-meson.c b/drivers/i2c/busses/i2c-meson.c index 06b3bed78421..c5dec572fc48 100644 --- a/drivers/i2c/busses/i2c-meson.c +++ b/drivers/i2c/busses/i2c-meson.c @@ -397,7 +397,6 @@ static int meson_i2c_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct meson_i2c *i2c; - struct resource *mem; struct i2c_timings timings; int irq, ret = 0; @@ -422,16 +421,13 @@ static int meson_i2c_probe(struct platform_device *pdev) return PTR_ERR(i2c->clk); } - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + i2c->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->regs)) return PTR_ERR(i2c->regs); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "can't find IRQ\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, meson_i2c_irq, 0, NULL, i2c); if (ret < 0) { diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c index 0ca6c38a15eb..deef69e56906 100644 --- a/drivers/i2c/busses/i2c-mt65xx.c +++ b/drivers/i2c/busses/i2c-mt65xx.c @@ -40,12 +40,11 @@ #define I2C_SOFT_RST 0x0001 #define I2C_FIFO_ADDR_CLR 0x0001 #define I2C_DELAY_LEN 0x0002 -#define I2C_ST_START_CON 0x8001 -#define I2C_FS_START_CON 0x1800 #define I2C_TIME_CLR_VALUE 0x0000 #define I2C_TIME_DEFAULT_VALUE 0x0003 #define I2C_WRRD_TRANAC_VALUE 0x0002 #define I2C_RD_TRANAC_VALUE 0x0001 +#define I2C_SCL_MIS_COMP_VALUE 0x0000 #define I2C_DMA_CON_TX 0x0000 #define I2C_DMA_CON_RX 0x0001 @@ -55,10 +54,13 @@ #define I2C_DMA_HARD_RST 0x0002 #define I2C_DMA_4G_MODE 0x0001 -#define I2C_DEFAULT_CLK_DIV 5 #define MAX_SAMPLE_CNT_DIV 8 #define MAX_STEP_CNT_DIV 64 +#define MAX_CLOCK_DIV 256 #define MAX_HS_STEP_CNT_DIV 8 +#define I2C_STANDARD_MODE_BUFFER (1000 / 2) +#define I2C_FAST_MODE_BUFFER (300 / 2) +#define I2C_FAST_MODE_PLUS_BUFFER (20 / 2) #define I2C_CONTROL_RS (0x1 << 1) #define I2C_CONTROL_DMA_EN (0x1 << 2) @@ -123,6 +125,12 @@ enum I2C_REGS_OFFSET { OFFSET_TRANSFER_LEN_AUX, OFFSET_CLOCK_DIV, OFFSET_LTIMING, + OFFSET_SCL_HIGH_LOW_RATIO, + OFFSET_HS_SCL_HIGH_LOW_RATIO, + OFFSET_SCL_MIS_COMP_POINT, + OFFSET_STA_STO_AC_TIMING, + OFFSET_HS_STA_STO_AC_TIMING, + OFFSET_SDA_TIMING, }; static const u16 mt_i2c_regs_v1[] = { @@ -150,6 +158,12 @@ static const u16 mt_i2c_regs_v1[] = { [OFFSET_DEBUGCTRL] = 0x68, [OFFSET_TRANSFER_LEN_AUX] = 0x6c, [OFFSET_CLOCK_DIV] = 0x70, + [OFFSET_SCL_HIGH_LOW_RATIO] = 0x74, + [OFFSET_HS_SCL_HIGH_LOW_RATIO] = 0x78, + [OFFSET_SCL_MIS_COMP_POINT] = 0x7C, + [OFFSET_STA_STO_AC_TIMING] = 0x80, + [OFFSET_HS_STA_STO_AC_TIMING] = 0x84, + [OFFSET_SDA_TIMING] = 0x88, }; static const u16 mt_i2c_regs_v2[] = { @@ -168,9 +182,11 @@ static const u16 mt_i2c_regs_v2[] = { [OFFSET_HS] = 0x30, [OFFSET_IO_CONFIG] = 0x34, [OFFSET_FIFO_ADDR_CLR] = 0x38, + [OFFSET_SDA_TIMING] = 0x3c, [OFFSET_TRANSFER_LEN_AUX] = 0x44, [OFFSET_CLOCK_DIV] = 0x48, [OFFSET_SOFTRESET] = 0x50, + [OFFSET_SCL_MIS_COMP_POINT] = 0x90, [OFFSET_DEBUGSTAT] = 0xe0, [OFFSET_DEBUGCTRL] = 0xe8, [OFFSET_FIFO_STAT] = 0xf4, @@ -191,6 +207,19 @@ struct mtk_i2c_compatible { unsigned char ltiming_adjust: 1; }; +struct mtk_i2c_ac_timing { + u16 htiming; + u16 ltiming; + u16 hs; + u16 ext; + u16 inter_clk_div; + u16 scl_hl_ratio; + u16 hs_scl_hl_ratio; + u16 sta_stop; + u16 hs_sta_stop; + u16 sda_timing; +}; + struct mtk_i2c { struct i2c_adapter adap; /* i2c host adapter */ struct device *dev; @@ -215,9 +244,46 @@ struct mtk_i2c { u16 ltiming_reg; unsigned char auto_restart; bool ignore_restart_irq; + struct mtk_i2c_ac_timing ac_timing; const struct mtk_i2c_compatible *dev_comp; }; +/** + * struct i2c_spec_values: + * min_low_ns: min LOW period of the SCL clock + * min_su_sta_ns: min set-up time for a repeated START condition + * max_hd_dat_ns: max data hold time + * min_su_dat_ns: min data set-up time + */ +struct i2c_spec_values { + unsigned int min_low_ns; + unsigned int min_high_ns; + unsigned int min_su_sta_ns; + unsigned int max_hd_dat_ns; + unsigned int min_su_dat_ns; +}; + +static const struct i2c_spec_values standard_mode_spec = { + .min_low_ns = 4700 + I2C_STANDARD_MODE_BUFFER, + .min_su_sta_ns = 4700 + I2C_STANDARD_MODE_BUFFER, + .max_hd_dat_ns = 3450 - I2C_STANDARD_MODE_BUFFER, + .min_su_dat_ns = 250 + I2C_STANDARD_MODE_BUFFER, +}; + +static const struct i2c_spec_values fast_mode_spec = { + .min_low_ns = 1300 + I2C_FAST_MODE_BUFFER, + .min_su_sta_ns = 600 + I2C_FAST_MODE_BUFFER, + .max_hd_dat_ns = 900 - I2C_FAST_MODE_BUFFER, + .min_su_dat_ns = 100 + I2C_FAST_MODE_BUFFER, +}; + +static const struct i2c_spec_values fast_mode_plus_spec = { + .min_low_ns = 500 + I2C_FAST_MODE_PLUS_BUFFER, + .min_su_sta_ns = 260 + I2C_FAST_MODE_PLUS_BUFFER, + .max_hd_dat_ns = 400 - I2C_FAST_MODE_PLUS_BUFFER, + .min_su_dat_ns = 50 + I2C_FAST_MODE_PLUS_BUFFER, +}; + static const struct i2c_adapter_quirks mt6577_i2c_quirks = { .flags = I2C_AQ_COMB_WRITE_THEN_READ, .max_num_msgs = 1, @@ -397,14 +463,38 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c) if (i2c->dev_comp->dcm) mtk_i2c_writew(i2c, I2C_DCM_DISABLE, OFFSET_DCM_EN); - if (i2c->dev_comp->timing_adjust) - mtk_i2c_writew(i2c, I2C_DEFAULT_CLK_DIV - 1, OFFSET_CLOCK_DIV); - mtk_i2c_writew(i2c, i2c->timing_reg, OFFSET_TIMING); mtk_i2c_writew(i2c, i2c->high_speed_reg, OFFSET_HS); if (i2c->dev_comp->ltiming_adjust) mtk_i2c_writew(i2c, i2c->ltiming_reg, OFFSET_LTIMING); + if (i2c->dev_comp->timing_adjust) { + mtk_i2c_writew(i2c, i2c->ac_timing.ext, OFFSET_EXT_CONF); + mtk_i2c_writew(i2c, i2c->ac_timing.inter_clk_div, + OFFSET_CLOCK_DIV); + mtk_i2c_writew(i2c, I2C_SCL_MIS_COMP_VALUE, + OFFSET_SCL_MIS_COMP_POINT); + mtk_i2c_writew(i2c, i2c->ac_timing.sda_timing, + OFFSET_SDA_TIMING); + + if (i2c->dev_comp->ltiming_adjust) { + mtk_i2c_writew(i2c, i2c->ac_timing.htiming, + OFFSET_TIMING); + mtk_i2c_writew(i2c, i2c->ac_timing.hs, OFFSET_HS); + mtk_i2c_writew(i2c, i2c->ac_timing.ltiming, + OFFSET_LTIMING); + } else { + mtk_i2c_writew(i2c, i2c->ac_timing.scl_hl_ratio, + OFFSET_SCL_HIGH_LOW_RATIO); + mtk_i2c_writew(i2c, i2c->ac_timing.hs_scl_hl_ratio, + OFFSET_HS_SCL_HIGH_LOW_RATIO); + mtk_i2c_writew(i2c, i2c->ac_timing.sta_stop, + OFFSET_STA_STO_AC_TIMING); + mtk_i2c_writew(i2c, i2c->ac_timing.hs_sta_stop, + OFFSET_HS_STA_STO_AC_TIMING); + } + } + /* If use i2c pin from PMIC mt6397 side, need set PATH_DIR first */ if (i2c->have_pmic) mtk_i2c_writew(i2c, I2C_CONTROL_WRAPPER, OFFSET_PATH_DIR); @@ -422,6 +512,126 @@ static void mtk_i2c_init_hw(struct mtk_i2c *i2c) writel(I2C_DMA_CLR_FLAG, i2c->pdmabase + OFFSET_RST); } +static const struct i2c_spec_values *mtk_i2c_get_spec(unsigned int speed) +{ + if (speed <= I2C_MAX_STANDARD_MODE_FREQ) + return &standard_mode_spec; + else if (speed <= I2C_MAX_FAST_MODE_FREQ) + return &fast_mode_spec; + else + return &fast_mode_plus_spec; +} + +static int mtk_i2c_max_step_cnt(unsigned int target_speed) +{ + if (target_speed > I2C_MAX_FAST_MODE_FREQ) + return MAX_HS_STEP_CNT_DIV; + else + return MAX_STEP_CNT_DIV; +} + +/* + * Check and Calculate i2c ac-timing + * + * Hardware design: + * sample_ns = (1000000000 * (sample_cnt + 1)) / clk_src + * xxx_cnt_div = spec->min_xxx_ns / sample_ns + * + * Sample_ns is rounded down for xxx_cnt_div would be greater + * than the smallest spec. + * The sda_timing is chosen as the middle value between + * the largest and smallest. + */ +static int mtk_i2c_check_ac_timing(struct mtk_i2c *i2c, + unsigned int clk_src, + unsigned int check_speed, + unsigned int step_cnt, + unsigned int sample_cnt) +{ + const struct i2c_spec_values *spec; + unsigned int su_sta_cnt, low_cnt, high_cnt, max_step_cnt; + unsigned int sda_max, sda_min, clk_ns, max_sta_cnt = 0x3f; + unsigned int sample_ns = div_u64(1000000000ULL * (sample_cnt + 1), + clk_src); + + if (!i2c->dev_comp->timing_adjust) + return 0; + + if (i2c->dev_comp->ltiming_adjust) + max_sta_cnt = 0x100; + + spec = mtk_i2c_get_spec(check_speed); + + if (i2c->dev_comp->ltiming_adjust) + clk_ns = 1000000000 / clk_src; + else + clk_ns = sample_ns / 2; + + su_sta_cnt = DIV_ROUND_UP(spec->min_su_sta_ns, clk_ns); + if (su_sta_cnt > max_sta_cnt) + return -1; + + low_cnt = DIV_ROUND_UP(spec->min_low_ns, sample_ns); + max_step_cnt = mtk_i2c_max_step_cnt(check_speed); + if ((2 * step_cnt) > low_cnt && low_cnt < max_step_cnt) { + if (low_cnt > step_cnt) { + high_cnt = 2 * step_cnt - low_cnt; + } else { + high_cnt = step_cnt; + low_cnt = step_cnt; + } + } else { + return -2; + } + + sda_max = spec->max_hd_dat_ns / sample_ns; + if (sda_max > low_cnt) + sda_max = 0; + + sda_min = DIV_ROUND_UP(spec->min_su_dat_ns, sample_ns); + if (sda_min < low_cnt) + sda_min = 0; + + if (sda_min > sda_max) + return -3; + + if (check_speed > I2C_MAX_FAST_MODE_FREQ) { + if (i2c->dev_comp->ltiming_adjust) { + i2c->ac_timing.hs = I2C_TIME_DEFAULT_VALUE | + (sample_cnt << 12) | (high_cnt << 8); + i2c->ac_timing.ltiming &= ~GENMASK(15, 9); + i2c->ac_timing.ltiming |= (sample_cnt << 12) | + (low_cnt << 9); + i2c->ac_timing.ext &= ~GENMASK(7, 1); + i2c->ac_timing.ext |= (su_sta_cnt << 1) | (1 << 0); + } else { + i2c->ac_timing.hs_scl_hl_ratio = (1 << 12) | + (high_cnt << 6) | low_cnt; + i2c->ac_timing.hs_sta_stop = (su_sta_cnt << 8) | + su_sta_cnt; + } + i2c->ac_timing.sda_timing &= ~GENMASK(11, 6); + i2c->ac_timing.sda_timing |= (1 << 12) | + ((sda_max + sda_min) / 2) << 6; + } else { + if (i2c->dev_comp->ltiming_adjust) { + i2c->ac_timing.htiming = (sample_cnt << 8) | (high_cnt); + i2c->ac_timing.ltiming = (sample_cnt << 6) | (low_cnt); + i2c->ac_timing.ext = (su_sta_cnt << 8) | (1 << 0); + } else { + i2c->ac_timing.scl_hl_ratio = (1 << 12) | + (high_cnt << 6) | low_cnt; + i2c->ac_timing.sta_stop = (su_sta_cnt << 8) | + su_sta_cnt; + } + + i2c->ac_timing.sda_timing = (1 << 12) | + (sda_max + sda_min) / 2; + } + + return 0; +} + /* * Calculate i2c port speed * @@ -446,15 +656,12 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, unsigned int opt_div; unsigned int best_mul; unsigned int cnt_mul; + int ret = -EINVAL; if (target_speed > I2C_MAX_FAST_MODE_PLUS_FREQ) target_speed = I2C_MAX_FAST_MODE_PLUS_FREQ; - if (target_speed > I2C_MAX_FAST_MODE_FREQ) - max_step_cnt = MAX_HS_STEP_CNT_DIV; - else - max_step_cnt = MAX_STEP_CNT_DIV; - + max_step_cnt = mtk_i2c_max_step_cnt(target_speed); base_step_cnt = max_step_cnt; /* Find the best combination */ opt_div = DIV_ROUND_UP(clk_src >> 1, target_speed); @@ -473,6 +680,11 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, continue; if (cnt_mul < best_mul) { + ret = mtk_i2c_check_ac_timing(i2c, clk_src, + target_speed, step_cnt - 1, sample_cnt - 1); + if (ret) + continue; + best_mul = cnt_mul; base_sample_cnt = sample_cnt; base_step_cnt = step_cnt; @@ -481,6 +693,9 @@ static int mtk_i2c_calculate_speed(struct mtk_i2c *i2c, unsigned int clk_src, } } + if (ret) + return -EINVAL; + sample_cnt = base_sample_cnt; step_cnt = base_step_cnt; @@ -506,47 +721,68 @@ static int mtk_i2c_set_speed(struct mtk_i2c *i2c, unsigned int parent_clk) unsigned int l_step_cnt; unsigned int l_sample_cnt; unsigned int target_speed; + unsigned int clk_div; + unsigned int max_clk_div; int ret; - clk_src = parent_clk / i2c->clk_src_div; target_speed = i2c->speed_hz; + parent_clk /= i2c->clk_src_div; - if (target_speed > I2C_MAX_FAST_MODE_FREQ) { - /* Set master code speed register */ - ret = mtk_i2c_calculate_speed(i2c, clk_src, I2C_MAX_FAST_MODE_FREQ, - &l_step_cnt, &l_sample_cnt); - if (ret < 0) - return ret; - - i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt; - - /* Set the high speed mode register */ - ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, - &step_cnt, &sample_cnt); - if (ret < 0) - return ret; - - i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE | - (sample_cnt << 12) | (step_cnt << 8); + if (i2c->dev_comp->timing_adjust) + max_clk_div = MAX_CLOCK_DIV; + else + max_clk_div = 1; + + for (clk_div = 1; clk_div <= max_clk_div; clk_div++) { + clk_src = parent_clk / clk_div; + + if (target_speed > I2C_MAX_FAST_MODE_FREQ) { + /* Set master code speed register */ + ret = mtk_i2c_calculate_speed(i2c, clk_src, + I2C_MAX_FAST_MODE_FREQ, + &l_step_cnt, + &l_sample_cnt); + if (ret < 0) + continue; + + i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt; + + /* Set the high speed mode register */ + ret = mtk_i2c_calculate_speed(i2c, clk_src, + target_speed, &step_cnt, + &sample_cnt); + if (ret < 0) + continue; + + i2c->high_speed_reg = I2C_TIME_DEFAULT_VALUE | + (sample_cnt << 12) | (step_cnt << 8); + + if (i2c->dev_comp->ltiming_adjust) + i2c->ltiming_reg = + (l_sample_cnt << 6) | l_step_cnt | + (sample_cnt << 12) | (step_cnt << 9); + } else { + ret = mtk_i2c_calculate_speed(i2c, clk_src, + target_speed, &l_step_cnt, + &l_sample_cnt); + if (ret < 0) + continue; - if (i2c->dev_comp->ltiming_adjust) - i2c->ltiming_reg = (l_sample_cnt << 6) | l_step_cnt | - (sample_cnt << 12) | (step_cnt << 9); - } else { - ret = mtk_i2c_calculate_speed(i2c, clk_src, target_speed, - &step_cnt, &sample_cnt); - if (ret < 0) - return ret; + i2c->timing_reg = (l_sample_cnt << 8) | l_step_cnt; - i2c->timing_reg = (sample_cnt << 8) | step_cnt; + /* Disable the high speed transaction */ + i2c->high_speed_reg = I2C_TIME_CLR_VALUE; - /* Disable the high speed transaction */ - i2c->high_speed_reg = I2C_TIME_CLR_VALUE; + if (i2c->dev_comp->ltiming_adjust) + i2c->ltiming_reg = + (l_sample_cnt << 6) | l_step_cnt; + } - if (i2c->dev_comp->ltiming_adjust) - i2c->ltiming_reg = (sample_cnt << 6) | step_cnt; + break; } + i2c->ac_timing.inter_clk_div = clk_div - 1; + return 0; } @@ -586,12 +822,6 @@ static int mtk_i2c_do_transfer(struct mtk_i2c *i2c, struct i2c_msg *msgs, mtk_i2c_writew(i2c, control_reg, OFFSET_CONTROL); - /* set start condition */ - if (i2c->speed_hz <= I2C_MAX_STANDARD_MODE_FREQ) - mtk_i2c_writew(i2c, I2C_ST_START_CON, OFFSET_EXT_CONF); - else - mtk_i2c_writew(i2c, I2C_FS_START_CON, OFFSET_EXT_CONF); - addr_reg = i2c_8bit_addr_from_msg(msgs); mtk_i2c_writew(i2c, addr_reg, OFFSET_SLAVE_ADDR); @@ -948,9 +1178,6 @@ static int mtk_i2c_probe(struct platform_device *pdev) if (ret) return -EINVAL; - if (i2c->dev_comp->timing_adjust) - i2c->clk_src_div *= I2C_DEFAULT_CLK_DIV; - if (i2c->have_pmic && !i2c->dev_comp->pmic_i2c) return -EINVAL; diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 9b8f1d8552ea..829b8c98ae51 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -877,7 +877,6 @@ mv64xxx_i2c_probe(struct platform_device *pd) { struct mv64xxx_i2c_data *drv_data; struct mv64xxx_i2c_pdata *pdata = dev_get_platdata(&pd->dev); - struct resource *r; int rc; if ((!pdata && !pd->dev.of_node)) @@ -888,8 +887,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) if (!drv_data) return -ENOMEM; - r = platform_get_resource(pd, IORESOURCE_MEM, 0); - drv_data->reg_base = devm_ioremap_resource(&pd->dev, r); + drv_data->reg_base = devm_platform_ioremap_resource(pd, 0); if (IS_ERR(drv_data->reg_base)) return PTR_ERR(drv_data->reg_base); diff --git a/drivers/i2c/busses/i2c-octeon-platdrv.c b/drivers/i2c/busses/i2c-octeon-platdrv.c index 64bda83e65ac..0c227963c8d6 100644 --- a/drivers/i2c/busses/i2c-octeon-platdrv.c +++ b/drivers/i2c/busses/i2c-octeon-platdrv.c @@ -136,7 +136,6 @@ static int octeon_i2c_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; int irq, result = 0, hlc_irq = 0; - struct resource *res_mem; struct octeon_i2c *i2c; bool cn78xx_style; @@ -167,8 +166,7 @@ static int octeon_i2c_probe(struct platform_device *pdev) i2c->roff.twsi_int = 0x10; i2c->roff.sw_twsi_ext = 0x18; - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->twsi_base = devm_ioremap_resource(&pdev->dev, res_mem); + i2c->twsi_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->twsi_base)) { result = PTR_ERR(i2c->twsi_base); goto out; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 71b4637c86b7..175c590b93b7 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1365,10 +1365,8 @@ omap_i2c_probe(struct platform_device *pdev) u16 minor, major; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); + if (irq < 0) return irq; - } omap = devm_kzalloc(&pdev->dev, sizeof(struct omap_i2c_dev), GFP_KERNEL); if (!omap) diff --git a/drivers/i2c/busses/i2c-owl.c b/drivers/i2c/busses/i2c-owl.c index 3ab8be62c581..672f1f239bd6 100644 --- a/drivers/i2c/busses/i2c-owl.c +++ b/drivers/i2c/busses/i2c-owl.c @@ -396,23 +396,19 @@ static int owl_i2c_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct owl_i2c_dev *i2c_dev; - struct resource *res; int ret, irq; i2c_dev = devm_kzalloc(dev, sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c_dev->base = devm_ioremap_resource(dev, res); + i2c_dev->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c_dev->base)) return PTR_ERR(i2c_dev->base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to get IRQ number\n"); + if (irq < 0) return irq; - } if (of_property_read_u32(dev->of_node, "clock-frequency", &i2c_dev->bus_freq)) diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 635dd697ac0b..546426a470cc 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -149,8 +149,7 @@ static int i2c_pca_pf_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->reg_base = devm_ioremap_resource(&pdev->dev, res); + i2c->reg_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(i2c->reg_base)) return PTR_ERR(i2c->reg_base); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 30ded6422e7b..69740a4ff1db 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -977,7 +977,8 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) } if (dev->vendor == PCI_VENDOR_ID_AMD && - dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) { + (dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS || + dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS)) { retval = piix4_setup_sb800(dev, id, 1); } diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 686c06f31625..5d7207c10f1d 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -720,7 +720,6 @@ static int i2c_pnx_probe(struct platform_device *pdev) alg_data->irq = platform_get_irq(pdev, 0); if (alg_data->irq < 0) { - dev_err(&pdev->dev, "Failed to get IRQ from platform resource\n"); ret = alg_data->irq; goto out_clock; } diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index d565714c1f13..3e38e114948b 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -207,18 +207,18 @@ static u32 i2c_powermac_get_addr(struct i2c_adapter *adap, struct pmac_i2c_bus *bus, struct device_node *node) { - const __be32 *prop; - int len; + u32 prop; + int ret; /* First check for valid "reg" */ - prop = of_get_property(node, "reg", &len); - if (prop && (len >= sizeof(int))) - return (be32_to_cpup(prop) & 0xff) >> 1; + ret = of_property_read_u32(node, "reg", &prop); + if (ret == 0) + return (prop & 0xff) >> 1; /* Then check old-style "i2c-address" */ - prop = of_get_property(node, "i2c-address", &len); - if (prop && (len >= sizeof(int))) - return (be32_to_cpup(prop) & 0xff) >> 1; + ret = of_property_read_u32(node, "i2c-address", &prop); + if (ret == 0) + return (prop & 0xff) >> 1; /* Now handle some devices with missing "reg" properties */ if (of_node_name_eq(node, "cereal")) @@ -315,7 +315,7 @@ static void i2c_powermac_register_devices(struct i2c_adapter *adap, { struct i2c_client *newdev; struct device_node *node; - bool found_onyx = 0; + bool found_onyx = false; /* * In some cases we end up with the via-pmu node itself, in this diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 466e4f681d7a..0e194d6cd1b5 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -16,25 +16,118 @@ * Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood] * Feb 2005: Rework slave mode handling [RMK] */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/sched.h> +#include <linux/clk.h> #include <linux/delay.h> +#include <linux/err.h> #include <linux/errno.h> +#include <linux/i2c.h> +#include <linux/init.h> #include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/slab.h> -#include <linux/io.h> #include <linux/platform_data/i2c-pxa.h> +#include <linux/slab.h> + +/* I2C register field definitions */ +#define IBMR_SDAS (1 << 0) +#define IBMR_SCLS (1 << 1) + +#define ICR_START (1 << 0) /* start bit */ +#define ICR_STOP (1 << 1) /* stop bit */ +#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */ +#define ICR_TB (1 << 3) /* transfer byte bit */ +#define ICR_MA (1 << 4) /* master abort */ +#define ICR_SCLE (1 << 5) /* master clock enable */ +#define ICR_IUE (1 << 6) /* unit enable */ +#define ICR_GCD (1 << 7) /* general call disable */ +#define ICR_ITEIE (1 << 8) /* enable tx interrupts */ +#define ICR_IRFIE (1 << 9) /* enable rx interrupts */ +#define ICR_BEIE (1 << 10) /* enable bus error ints */ +#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */ +#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */ +#define ICR_SADIE (1 << 13) /* slave address detected int enable */ +#define ICR_UR (1 << 14) /* unit reset */ +#define ICR_FM (1 << 15) /* fast mode */ +#define ICR_HS (1 << 16) /* High Speed mode */ +#define ICR_A3700_FM (1 << 16) /* fast mode for armada-3700 */ +#define ICR_A3700_HS (1 << 17) /* high speed mode for armada-3700 */ +#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */ -#include <asm/irq.h> +#define ISR_RWM (1 << 0) /* read/write mode */ +#define ISR_ACKNAK (1 << 1) /* ack/nak status */ +#define ISR_UB (1 << 2) /* unit busy */ +#define ISR_IBB (1 << 3) /* bus busy */ +#define ISR_SSD (1 << 4) /* slave stop detected */ +#define ISR_ALD (1 << 5) /* arbitration loss detected */ +#define ISR_ITE (1 << 6) /* tx buffer empty */ +#define ISR_IRF (1 << 7) /* rx buffer full */ +#define ISR_GCAD (1 << 8) /* general call address detected */ +#define ISR_SAD (1 << 9) /* slave address detected */ +#define ISR_BED (1 << 10) /* bus error no ACK/NAK */ + +#define ILCR_SLV_SHIFT 0 +#define ILCR_SLV_MASK (0x1FF << ILCR_SLV_SHIFT) +#define ILCR_FLV_SHIFT 9 +#define ILCR_FLV_MASK (0x1FF << ILCR_FLV_SHIFT) +#define ILCR_HLVL_SHIFT 18 +#define ILCR_HLVL_MASK (0x1FF << ILCR_HLVL_SHIFT) +#define ILCR_HLVH_SHIFT 27 +#define ILCR_HLVH_MASK (0x1F << ILCR_HLVH_SHIFT) + +#define IWCR_CNT_SHIFT 0 +#define IWCR_CNT_MASK (0x1F << IWCR_CNT_SHIFT) +#define IWCR_HS_CNT1_SHIFT 5 +#define IWCR_HS_CNT1_MASK (0x1F << IWCR_HS_CNT1_SHIFT) +#define IWCR_HS_CNT2_SHIFT 10 +#define IWCR_HS_CNT2_MASK (0x1F << IWCR_HS_CNT2_SHIFT) + +/* need a longer timeout if we're dealing with the fact we may well be + * looking at a multi-master environment + */ +#define DEF_TIMEOUT 32 + +#define NO_SLAVE (-ENXIO) +#define BUS_ERROR (-EREMOTEIO) +#define XFER_NAKED (-ECONNREFUSED) +#define I2C_RETRY (-2000) /* an error has occurred retry transmit */ + +/* ICR initialize bit values + * + * 15 FM 0 (100 kHz operation) + * 14 UR 0 (No unit reset) + * 13 SADIE 0 (Disables the unit from interrupting on slave addresses + * matching its slave address) + * 12 ALDIE 0 (Disables the unit from interrupt when it loses arbitration + * in master mode) + * 11 SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode) + * 10 BEIE 1 (Enable interrupts from detected bus errors, no ACK sent) + * 9 IRFIE 1 (Enable interrupts from full buffer received) + * 8 ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty) + * 7 GCD 1 (Disables i2c unit response to general call messages as a slave) + * 6 IUE 0 (Disable unit until we change settings) + * 5 SCLE 1 (Enables the i2c clock output for master mode (drives SCL) + * 4 MA 0 (Only send stop with the ICR stop bit) + * 3 TB 0 (We are not transmitting a byte initially) + * 2 ACKNAK 0 (Send an ACK after the unit receives a byte) + * 1 STOP 0 (Do not send a STOP) + * 0 START 0 (Do not send a START) + */ +#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) + +/* I2C status register init values + * + * 10 BED 1 (Clear bus error detected) + * 9 SAD 1 (Clear slave address detected) + * 7 IRF 1 (Clear IDBR Receive Full) + * 6 ITE 1 (Clear IDBR Transmit Empty) + * 5 ALD 1 (Clear Arbitration Loss Detected) + * 4 SSD 1 (Clear Slave Stop Detected) + */ +#define I2C_ISR_INIT 0x7FF /* status register init */ struct pxa_reg_layout { u32 ibmr; @@ -56,12 +149,7 @@ enum pxa_i2c_types { REGS_A3700, }; -#define ICR_BUSMODE_FM (1 << 16) /* shifted fast mode for armada-3700 */ -#define ICR_BUSMODE_HS (1 << 17) /* shifted high speed mode for armada-3700 */ - -/* - * I2C registers definitions - */ +/* I2C register layout definitions */ static struct pxa_reg_layout pxa_reg_layout[] = { [REGS_PXA2XX] = { .ibmr = 0x00, @@ -69,6 +157,8 @@ static struct pxa_reg_layout pxa_reg_layout[] = { .icr = 0x10, .isr = 0x18, .isar = 0x20, + .fm = ICR_FM, + .hs = ICR_HS, }, [REGS_PXA3XX] = { .ibmr = 0x00, @@ -76,6 +166,8 @@ static struct pxa_reg_layout pxa_reg_layout[] = { .icr = 0x08, .isr = 0x0c, .isar = 0x10, + .fm = ICR_FM, + .hs = ICR_HS, }, [REGS_CE4100] = { .ibmr = 0x14, @@ -83,6 +175,8 @@ static struct pxa_reg_layout pxa_reg_layout[] = { .icr = 0x00, .isr = 0x04, /* no isar register */ + .fm = ICR_FM, + .hs = ICR_HS, }, [REGS_PXA910] = { .ibmr = 0x00, @@ -92,6 +186,8 @@ static struct pxa_reg_layout pxa_reg_layout[] = { .isar = 0x20, .ilcr = 0x28, .iwcr = 0x30, + .fm = ICR_FM, + .hs = ICR_HS, }, [REGS_A3700] = { .ibmr = 0x00, @@ -99,11 +195,20 @@ static struct pxa_reg_layout pxa_reg_layout[] = { .icr = 0x08, .isr = 0x0c, .isar = 0x10, - .fm = ICR_BUSMODE_FM, - .hs = ICR_BUSMODE_HS, + .fm = ICR_A3700_FM, + .hs = ICR_A3700_HS, }, }; +static const struct of_device_id i2c_pxa_dt_ids[] = { + { .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX }, + { .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX }, + { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 }, + { .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 }, + {} +}; +MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); + static const struct platform_device_id i2c_pxa_id_table[] = { { "pxa2xx-i2c", REGS_PXA2XX }, { "pxa3xx-pwri2c", REGS_PXA3XX }, @@ -114,58 +219,6 @@ static const struct platform_device_id i2c_pxa_id_table[] = { }; MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); -/* - * I2C bit definitions - */ - -#define ICR_START (1 << 0) /* start bit */ -#define ICR_STOP (1 << 1) /* stop bit */ -#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */ -#define ICR_TB (1 << 3) /* transfer byte bit */ -#define ICR_MA (1 << 4) /* master abort */ -#define ICR_SCLE (1 << 5) /* master clock enable */ -#define ICR_IUE (1 << 6) /* unit enable */ -#define ICR_GCD (1 << 7) /* general call disable */ -#define ICR_ITEIE (1 << 8) /* enable tx interrupts */ -#define ICR_IRFIE (1 << 9) /* enable rx interrupts */ -#define ICR_BEIE (1 << 10) /* enable bus error ints */ -#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */ -#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */ -#define ICR_SADIE (1 << 13) /* slave address detected int enable */ -#define ICR_UR (1 << 14) /* unit reset */ -#define ICR_FM (1 << 15) /* fast mode */ -#define ICR_HS (1 << 16) /* High Speed mode */ -#define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */ - -#define ISR_RWM (1 << 0) /* read/write mode */ -#define ISR_ACKNAK (1 << 1) /* ack/nak status */ -#define ISR_UB (1 << 2) /* unit busy */ -#define ISR_IBB (1 << 3) /* bus busy */ -#define ISR_SSD (1 << 4) /* slave stop detected */ -#define ISR_ALD (1 << 5) /* arbitration loss detected */ -#define ISR_ITE (1 << 6) /* tx buffer empty */ -#define ISR_IRF (1 << 7) /* rx buffer full */ -#define ISR_GCAD (1 << 8) /* general call address detected */ -#define ISR_SAD (1 << 9) /* slave address detected */ -#define ISR_BED (1 << 10) /* bus error no ACK/NAK */ - -/* bit field shift & mask */ -#define ILCR_SLV_SHIFT 0 -#define ILCR_SLV_MASK (0x1FF << ILCR_SLV_SHIFT) -#define ILCR_FLV_SHIFT 9 -#define ILCR_FLV_MASK (0x1FF << ILCR_FLV_SHIFT) -#define ILCR_HLVL_SHIFT 18 -#define ILCR_HLVL_MASK (0x1FF << ILCR_HLVL_SHIFT) -#define ILCR_HLVH_SHIFT 27 -#define ILCR_HLVH_MASK (0x1F << ILCR_HLVH_SHIFT) - -#define IWCR_CNT_SHIFT 0 -#define IWCR_CNT_MASK (0x1F << IWCR_CNT_SHIFT) -#define IWCR_HS_CNT1_SHIFT 5 -#define IWCR_HS_CNT1_MASK (0x1F << IWCR_HS_CNT1_SHIFT) -#define IWCR_HS_CNT2_SHIFT 10 -#define IWCR_HS_CNT2_MASK (0x1F << IWCR_HS_CNT2_SHIFT) - struct pxa_i2c { spinlock_t lock; wait_queue_head_t wait; @@ -234,13 +287,14 @@ struct bits { static inline void decode_bits(const char *prefix, const struct bits *bits, int num, u32 val) { - printk("%s %08x: ", prefix, val); + printk("%s %08x:", prefix, val); while (num--) { const char *str = val & bits->mask ? bits->set : bits->unset; if (str) - printk("%s ", str); + pr_cont(" %s", str); bits++; } + pr_cont("\n"); } static const struct bits isr_bits[] = { @@ -260,7 +314,6 @@ static const struct bits isr_bits[] = { static void decode_ISR(unsigned int val) { decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val); - printk("\n"); } static const struct bits icr_bits[] = { @@ -285,7 +338,6 @@ static const struct bits icr_bits[] = { static void decode_ICR(unsigned int val) { decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val); - printk("\n"); } #endif @@ -311,11 +363,10 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) dev_err(dev, "IBMR: %08x IDBR: %08x ICR: %08x ISR: %08x\n", readl(_IBMR(i2c)), readl(_IDBR(i2c)), readl(_ICR(i2c)), readl(_ISR(i2c))); - dev_dbg(dev, "log: "); + dev_err(dev, "log:"); for (i = 0; i < i2c->irqlogidx; i++) - pr_debug("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]); - - pr_debug("\n"); + pr_cont(" [%03x:%05x]", i2c->isrlog[i], i2c->icrlog[i]); + pr_cont("\n"); } #else /* ifdef DEBUG */ @@ -330,7 +381,6 @@ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) #endif /* ifdef DEBUG / else */ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret); -static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id); static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) { @@ -346,7 +396,7 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c) return; } - while ((i > 0) && (readl(_IBMR(i2c)) & 0x1) == 0) { + while ((i > 0) && (readl(_IBMR(i2c)) & IBMR_SDAS) == 0) { unsigned long icr = readl(_ICR(i2c)); icr &= ~ICR_START; @@ -367,19 +417,26 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c) static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) { int timeout = DEF_TIMEOUT; + u32 isr; + + while (1) { + isr = readl(_ISR(i2c)); + if (!(isr & (ISR_IBB | ISR_UB))) + return 0; - while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) { - if ((readl(_ISR(i2c)) & ISR_SAD) != 0) + if (isr & ISR_SAD) timeout += 4; + if (!timeout--) + break; + msleep(2); show_state(i2c); } - if (timeout < 0) - show_state(i2c); + show_state(i2c); - return timeout < 0 ? I2C_RETRY : 0; + return I2C_RETRY; } static int i2c_pxa_wait_master(struct pxa_i2c *i2c) @@ -401,7 +458,8 @@ static int i2c_pxa_wait_master(struct pxa_i2c *i2c) * quick check of the i2c lines themselves to ensure they've * gone high... */ - if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && readl(_IBMR(i2c)) == 3) { + if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && + readl(_IBMR(i2c)) == (IBMR_SCLS | IBMR_SDAS)) { if (i2c_debug > 0) dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); return 1; @@ -596,7 +654,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) timeout = 0x10000; while (1) { - if ((readl(_IBMR(i2c)) & 2) == 2) + if ((readl(_IBMR(i2c)) & IBMR_SCLS) == IBMR_SCLS) break; timeout--; @@ -691,7 +749,7 @@ static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) timeout = 0x10000; while (1) { - if ((readl(_IBMR(i2c)) & 2) == 2) + if ((readl(_IBMR(i2c)) & IBMR_SCLS) == IBMR_SCLS) break; timeout--; @@ -716,16 +774,6 @@ static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) * PXA I2C Master mode */ -static inline unsigned int i2c_pxa_addr_byte(struct i2c_msg *msg) -{ - unsigned int addr = (msg->addr & 0x7f) << 1; - - if (msg->flags & I2C_M_RD) - addr |= 1; - - return addr; -} - static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) { u32 icr; @@ -733,8 +781,8 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) /* * Step 1: target slave address into IDBR */ - writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c)); - i2c->req_slave_addr = i2c_pxa_addr_byte(i2c->msg); + i2c->req_slave_addr = i2c_8bit_addr_from_msg(i2c->msg); + writel(i2c->req_slave_addr, _IDBR(i2c)); /* * Step 2: initiate the write. @@ -747,42 +795,12 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c) { u32 icr; - /* - * Clear the STOP and ACK flags - */ + /* Clear the START, STOP, ACK, TB and MA flags */ icr = readl(_ICR(i2c)); - icr &= ~(ICR_STOP | ICR_ACKNAK); + icr &= ~(ICR_START | ICR_STOP | ICR_ACKNAK | ICR_TB | ICR_MA); writel(icr, _ICR(i2c)); } -static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) -{ - /* make timeout the same as for interrupt based functions */ - long timeout = 2 * DEF_TIMEOUT; - - /* - * Wait for the bus to become free. - */ - while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) { - udelay(1000); - show_state(i2c); - } - - if (timeout < 0) { - show_state(i2c); - dev_err(&i2c->adap.dev, - "i2c_pxa: timeout waiting for bus free\n"); - return I2C_RETRY; - } - - /* - * Set master mode. - */ - writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c)); - - return 0; -} - /* * PXA I2C send master code * 1. Load master code to IDBR and send it. @@ -811,140 +829,6 @@ static int i2c_pxa_send_mastercode(struct pxa_i2c *i2c) return (timeout == 0) ? I2C_RETRY : 0; } -static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, - struct i2c_msg *msg, int num) -{ - unsigned long timeout = 500000; /* 5 seconds */ - int ret = 0; - - ret = i2c_pxa_pio_set_master(i2c); - if (ret) - goto out; - - i2c->msg = msg; - i2c->msg_num = num; - i2c->msg_idx = 0; - i2c->msg_ptr = 0; - i2c->irqlogidx = 0; - - i2c_pxa_start_message(i2c); - - while (i2c->msg_num > 0 && --timeout) { - i2c_pxa_handler(0, i2c); - udelay(10); - } - - i2c_pxa_stop_message(i2c); - - /* - * We place the return code in i2c->msg_idx. - */ - ret = i2c->msg_idx; - -out: - if (timeout == 0) { - i2c_pxa_scream_blue_murder(i2c, "timeout"); - ret = I2C_RETRY; - } - - return ret; -} - -/* - * We are protected by the adapter bus mutex. - */ -static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) -{ - long timeout; - int ret; - - /* - * Wait for the bus to become free. - */ - ret = i2c_pxa_wait_bus_not_busy(i2c); - if (ret) { - dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n"); - goto out; - } - - /* - * Set master mode. - */ - ret = i2c_pxa_set_master(i2c); - if (ret) { - dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret); - goto out; - } - - if (i2c->high_mode) { - ret = i2c_pxa_send_mastercode(i2c); - if (ret) { - dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n"); - goto out; - } - } - - spin_lock_irq(&i2c->lock); - - i2c->msg = msg; - i2c->msg_num = num; - i2c->msg_idx = 0; - i2c->msg_ptr = 0; - i2c->irqlogidx = 0; - - i2c_pxa_start_message(i2c); - - spin_unlock_irq(&i2c->lock); - - /* - * The rest of the processing occurs in the interrupt handler. - */ - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); - i2c_pxa_stop_message(i2c); - - /* - * We place the return code in i2c->msg_idx. - */ - ret = i2c->msg_idx; - - if (!timeout && i2c->msg_num) { - i2c_pxa_scream_blue_murder(i2c, "timeout"); - ret = I2C_RETRY; - } - - out: - return ret; -} - -static int i2c_pxa_pio_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], int num) -{ - struct pxa_i2c *i2c = adap->algo_data; - int ret, i; - - /* If the I2C controller is disabled we need to reset it - (probably due to a suspend/resume destroying state). We do - this here as we can then avoid worrying about resuming the - controller before its users. */ - if (!(readl(_ICR(i2c)) & ICR_IUE)) - i2c_pxa_reset(i2c); - - for (i = adap->retries; i >= 0; i--) { - ret = i2c_pxa_do_pio_xfer(i2c, msgs, num); - if (ret != I2C_RETRY) - goto out; - - if (i2c_debug) - dev_dbg(&adap->dev, "Retrying transmission\n"); - udelay(100); - } - i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); - ret = -EREMOTEIO; - out: - i2c_pxa_set_slave(i2c, ret); - return ret; -} - /* * i2c_pxa_master_complete - complete the message and wake up. */ @@ -996,7 +880,7 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) */ if (isr & ISR_ACKNAK) { if (i2c->msg_ptr == 0 && i2c->msg_idx == 0) - ret = I2C_RETRY; + ret = NO_SLAVE; else ret = XFER_NAKED; } @@ -1047,8 +931,8 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) /* * Write the next address. */ - writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c)); - i2c->req_slave_addr = i2c_pxa_addr_byte(i2c->msg); + i2c->req_slave_addr = i2c_8bit_addr_from_msg(i2c->msg); + writel(i2c->req_slave_addr, _IDBR(i2c)); /* * And trigger a repeated start, and send the byte. @@ -1056,14 +940,8 @@ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) icr &= ~ICR_ALDIE; icr |= ICR_START | ICR_TB; } else { - if (i2c->msg->len == 0) { - /* - * Device probes have a message length of zero - * and need the bus to be reset before it can - * be used again. - */ - i2c_pxa_reset(i2c); - } + if (i2c->msg->len == 0) + icr |= ICR_MA; i2c_pxa_master_complete(i2c, 0); } @@ -1151,28 +1029,106 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id) return IRQ_HANDLED; } +/* + * We are protected by the adapter bus mutex. + */ +static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) +{ + long timeout; + int ret; + + /* + * Wait for the bus to become free. + */ + ret = i2c_pxa_wait_bus_not_busy(i2c); + if (ret) { + dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n"); + goto out; + } + + /* + * Set master mode. + */ + ret = i2c_pxa_set_master(i2c); + if (ret) { + dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret); + goto out; + } + + if (i2c->high_mode) { + ret = i2c_pxa_send_mastercode(i2c); + if (ret) { + dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n"); + goto out; + } + } + + spin_lock_irq(&i2c->lock); + + i2c->msg = msg; + i2c->msg_num = num; + i2c->msg_idx = 0; + i2c->msg_ptr = 0; + i2c->irqlogidx = 0; + + i2c_pxa_start_message(i2c); + + spin_unlock_irq(&i2c->lock); -static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) + /* + * The rest of the processing occurs in the interrupt handler. + */ + timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); + i2c_pxa_stop_message(i2c); + + /* + * We place the return code in i2c->msg_idx. + */ + ret = i2c->msg_idx; + + if (!timeout && i2c->msg_num) { + i2c_pxa_scream_blue_murder(i2c, "timeout with active message"); + ret = I2C_RETRY; + } + + out: + return ret; +} + +static int i2c_pxa_internal_xfer(struct pxa_i2c *i2c, + struct i2c_msg *msgs, int num, + int (*xfer)(struct pxa_i2c *, + struct i2c_msg *, int num)) { - struct pxa_i2c *i2c = adap->algo_data; int ret, i; - for (i = adap->retries; i >= 0; i--) { - ret = i2c_pxa_do_xfer(i2c, msgs, num); - if (ret != I2C_RETRY) + for (i = 0; ; ) { + ret = xfer(i2c, msgs, num); + if (ret != I2C_RETRY && ret != NO_SLAVE) goto out; + if (++i >= i2c->adap.retries) + break; if (i2c_debug) - dev_dbg(&adap->dev, "Retrying transmission\n"); + dev_dbg(&i2c->adap.dev, "Retrying transmission\n"); udelay(100); } - i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); + if (ret != NO_SLAVE) + i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); ret = -EREMOTEIO; out: i2c_pxa_set_slave(i2c, ret); return ret; } +static int i2c_pxa_xfer(struct i2c_adapter *adap, + struct i2c_msg msgs[], int num) +{ + struct pxa_i2c *i2c = adap->algo_data; + + return i2c_pxa_internal_xfer(i2c, msgs, num, i2c_pxa_do_xfer); +} + static u32 i2c_pxa_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | @@ -1188,6 +1144,87 @@ static const struct i2c_algorithm i2c_pxa_algorithm = { #endif }; +/* Non-interrupt mode support */ +static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) +{ + /* make timeout the same as for interrupt based functions */ + long timeout = 2 * DEF_TIMEOUT; + + /* + * Wait for the bus to become free. + */ + while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) + udelay(1000); + + if (timeout < 0) { + show_state(i2c); + dev_err(&i2c->adap.dev, + "i2c_pxa: timeout waiting for bus free (set_master)\n"); + return I2C_RETRY; + } + + /* + * Set master mode. + */ + writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c)); + + return 0; +} + +static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, + struct i2c_msg *msg, int num) +{ + unsigned long timeout = 500000; /* 5 seconds */ + int ret = 0; + + ret = i2c_pxa_pio_set_master(i2c); + if (ret) + goto out; + + i2c->msg = msg; + i2c->msg_num = num; + i2c->msg_idx = 0; + i2c->msg_ptr = 0; + i2c->irqlogidx = 0; + + i2c_pxa_start_message(i2c); + + while (i2c->msg_num > 0 && --timeout) { + i2c_pxa_handler(0, i2c); + udelay(10); + } + + i2c_pxa_stop_message(i2c); + + /* + * We place the return code in i2c->msg_idx. + */ + ret = i2c->msg_idx; + +out: + if (timeout == 0) { + i2c_pxa_scream_blue_murder(i2c, "timeout (do_pio_xfer)"); + ret = I2C_RETRY; + } + + return ret; +} + +static int i2c_pxa_pio_xfer(struct i2c_adapter *adap, + struct i2c_msg msgs[], int num) +{ + struct pxa_i2c *i2c = adap->algo_data; + + /* If the I2C controller is disabled we need to reset it + (probably due to a suspend/resume destroying state). We do + this here as we can then avoid worrying about resuming the + controller before its users. */ + if (!(readl(_ICR(i2c)) & ICR_IUE)) + i2c_pxa_reset(i2c); + + return i2c_pxa_internal_xfer(i2c, msgs, num, i2c_pxa_do_pio_xfer); +} + static const struct i2c_algorithm i2c_pxa_pio_algorithm = { .master_xfer = i2c_pxa_pio_xfer, .functionality = i2c_pxa_functionality, @@ -1197,15 +1234,6 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = { #endif }; -static const struct of_device_id i2c_pxa_dt_ids[] = { - { .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX }, - { .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX }, - { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA910 }, - { .compatible = "marvell,armada-3700-i2c", .data = (void *)REGS_A3700 }, - {} -}; -MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); - static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c, enum pxa_i2c_types *i2c_types) { @@ -1267,10 +1295,8 @@ static int i2c_pxa_probe(struct platform_device *dev) return PTR_ERR(i2c->reg_base); irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "no irq resource: %d\n", irq); + if (irq < 0) return irq; - } /* Default adapter num to device id; i2c_pxa_probe_dt can override. */ i2c->adap.nr = dev->id; @@ -1299,8 +1325,8 @@ static int i2c_pxa_probe(struct platform_device *dev) i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr; i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr; i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr; - i2c->fm_mask = pxa_reg_layout[i2c_type].fm ? : ICR_FM; - i2c->hs_mask = pxa_reg_layout[i2c_type].hs ? : ICR_HS; + i2c->fm_mask = pxa_reg_layout[i2c_type].fm; + i2c->hs_mask = pxa_reg_layout[i2c_type].hs; if (i2c_type != REGS_CE4100) i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar; diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c new file mode 100644 index 000000000000..f13735beca58 --- /dev/null +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -0,0 +1,791 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +// Copyright (c) 2017-20 Linaro Limited. + +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/i2c.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + +#define CCI_HW_VERSION 0x0 +#define CCI_RESET_CMD 0x004 +#define CCI_RESET_CMD_MASK 0x0f73f3f7 +#define CCI_RESET_CMD_M0_MASK 0x000003f1 +#define CCI_RESET_CMD_M1_MASK 0x0003f001 +#define CCI_QUEUE_START 0x008 +#define CCI_HALT_REQ 0x034 +#define CCI_HALT_REQ_I2C_M0_Q0Q1 BIT(0) +#define CCI_HALT_REQ_I2C_M1_Q0Q1 BIT(1) + +#define CCI_I2C_Mm_SCL_CTL(m) (0x100 + 0x100 * (m)) +#define CCI_I2C_Mm_SDA_CTL_0(m) (0x104 + 0x100 * (m)) +#define CCI_I2C_Mm_SDA_CTL_1(m) (0x108 + 0x100 * (m)) +#define CCI_I2C_Mm_SDA_CTL_2(m) (0x10c + 0x100 * (m)) +#define CCI_I2C_Mm_MISC_CTL(m) (0x110 + 0x100 * (m)) + +#define CCI_I2C_Mm_READ_DATA(m) (0x118 + 0x100 * (m)) +#define CCI_I2C_Mm_READ_BUF_LEVEL(m) (0x11c + 0x100 * (m)) +#define CCI_I2C_Mm_Qn_EXEC_WORD_CNT(m, n) (0x300 + 0x200 * (m) + 0x100 * (n)) +#define CCI_I2C_Mm_Qn_CUR_WORD_CNT(m, n) (0x304 + 0x200 * (m) + 0x100 * (n)) +#define CCI_I2C_Mm_Qn_CUR_CMD(m, n) (0x308 + 0x200 * (m) + 0x100 * (n)) +#define CCI_I2C_Mm_Qn_REPORT_STATUS(m, n) (0x30c + 0x200 * (m) + 0x100 * (n)) +#define CCI_I2C_Mm_Qn_LOAD_DATA(m, n) (0x310 + 0x200 * (m) + 0x100 * (n)) + +#define CCI_IRQ_GLOBAL_CLEAR_CMD 0xc00 +#define CCI_IRQ_MASK_0 0xc04 +#define CCI_IRQ_MASK_0_I2C_M0_RD_DONE BIT(0) +#define CCI_IRQ_MASK_0_I2C_M0_Q0_REPORT BIT(4) +#define CCI_IRQ_MASK_0_I2C_M0_Q1_REPORT BIT(8) +#define CCI_IRQ_MASK_0_I2C_M1_RD_DONE BIT(12) +#define CCI_IRQ_MASK_0_I2C_M1_Q0_REPORT BIT(16) +#define CCI_IRQ_MASK_0_I2C_M1_Q1_REPORT BIT(20) +#define CCI_IRQ_MASK_0_RST_DONE_ACK BIT(24) +#define CCI_IRQ_MASK_0_I2C_M0_Q0Q1_HALT_ACK BIT(25) +#define CCI_IRQ_MASK_0_I2C_M1_Q0Q1_HALT_ACK BIT(26) +#define CCI_IRQ_MASK_0_I2C_M0_ERROR 0x18000ee6 +#define CCI_IRQ_MASK_0_I2C_M1_ERROR 0x60ee6000 +#define CCI_IRQ_CLEAR_0 0xc08 +#define CCI_IRQ_STATUS_0 0xc0c +#define CCI_IRQ_STATUS_0_I2C_M0_RD_DONE BIT(0) +#define CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT BIT(4) +#define CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT BIT(8) +#define CCI_IRQ_STATUS_0_I2C_M1_RD_DONE BIT(12) +#define CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT BIT(16) +#define CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT BIT(20) +#define CCI_IRQ_STATUS_0_RST_DONE_ACK BIT(24) +#define CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK BIT(25) +#define CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK BIT(26) +#define CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERR BIT(27) +#define CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERR BIT(28) +#define CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR BIT(29) +#define CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR BIT(30) +#define CCI_IRQ_STATUS_0_I2C_M0_ERROR 0x18000ee6 +#define CCI_IRQ_STATUS_0_I2C_M1_ERROR 0x60ee6000 + +#define CCI_TIMEOUT (msecs_to_jiffies(100)) +#define NUM_MASTERS 2 +#define NUM_QUEUES 2 + +/* Max number of resources + 1 for a NULL terminator */ +#define CCI_RES_MAX 6 + +#define CCI_I2C_SET_PARAM 1 +#define CCI_I2C_REPORT 8 +#define CCI_I2C_WRITE 9 +#define CCI_I2C_READ 10 + +#define CCI_I2C_REPORT_IRQ_EN BIT(8) + +enum { + I2C_MODE_STANDARD, + I2C_MODE_FAST, + I2C_MODE_FAST_PLUS, +}; + +enum cci_i2c_queue_t { + QUEUE_0, + QUEUE_1 +}; + +struct hw_params { + u16 thigh; /* HIGH period of the SCL clock in clock ticks */ + u16 tlow; /* LOW period of the SCL clock */ + u16 tsu_sto; /* set-up time for STOP condition */ + u16 tsu_sta; /* set-up time for a repeated START condition */ + u16 thd_dat; /* data hold time */ + u16 thd_sta; /* hold time (repeated) START condition */ + u16 tbuf; /* bus free time between a STOP and START condition */ + u8 scl_stretch_en; + u16 trdhld; + u16 tsp; /* pulse width of spikes suppressed by the input filter */ +}; + +struct cci; + +struct cci_master { + struct i2c_adapter adap; + u16 master; + u8 mode; + int status; + struct completion irq_complete; + struct cci *cci; +}; + +struct cci_data { + unsigned int num_masters; + struct i2c_adapter_quirks quirks; + u16 queue_size[NUM_QUEUES]; + unsigned long cci_clk_rate; + struct hw_params params[3]; +}; + +struct cci { + struct device *dev; + void __iomem *base; + unsigned int irq; + const struct cci_data *data; + struct clk_bulk_data *clocks; + int nclocks; + struct cci_master master[NUM_MASTERS]; +}; + +static irqreturn_t cci_isr(int irq, void *dev) +{ + struct cci *cci = dev; + u32 val, reset = 0; + int ret = IRQ_NONE; + + val = readl(cci->base + CCI_IRQ_STATUS_0); + writel(val, cci->base + CCI_IRQ_CLEAR_0); + writel(0x1, cci->base + CCI_IRQ_GLOBAL_CLEAR_CMD); + + if (val & CCI_IRQ_STATUS_0_RST_DONE_ACK) { + complete(&cci->master[0].irq_complete); + if (cci->master[1].master) + complete(&cci->master[1].irq_complete); + ret = IRQ_HANDLED; + } + + if (val & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE || + val & CCI_IRQ_STATUS_0_I2C_M0_Q0_REPORT || + val & CCI_IRQ_STATUS_0_I2C_M0_Q1_REPORT) { + cci->master[0].status = 0; + complete(&cci->master[0].irq_complete); + ret = IRQ_HANDLED; + } + + if (val & CCI_IRQ_STATUS_0_I2C_M1_RD_DONE || + val & CCI_IRQ_STATUS_0_I2C_M1_Q0_REPORT || + val & CCI_IRQ_STATUS_0_I2C_M1_Q1_REPORT) { + cci->master[1].status = 0; + complete(&cci->master[1].irq_complete); + ret = IRQ_HANDLED; + } + + if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M0_Q0Q1_HALT_ACK)) { + reset = CCI_RESET_CMD_M0_MASK; + ret = IRQ_HANDLED; + } + + if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M1_Q0Q1_HALT_ACK)) { + reset = CCI_RESET_CMD_M1_MASK; + ret = IRQ_HANDLED; + } + + if (unlikely(reset)) + writel(reset, cci->base + CCI_RESET_CMD); + + if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M0_ERROR)) { + if (val & CCI_IRQ_STATUS_0_I2C_M0_Q0_NACK_ERR || + val & CCI_IRQ_STATUS_0_I2C_M0_Q1_NACK_ERR) + cci->master[0].status = -ENXIO; + else + cci->master[0].status = -EIO; + + writel(CCI_HALT_REQ_I2C_M0_Q0Q1, cci->base + CCI_HALT_REQ); + ret = IRQ_HANDLED; + } + + if (unlikely(val & CCI_IRQ_STATUS_0_I2C_M1_ERROR)) { + if (val & CCI_IRQ_STATUS_0_I2C_M1_Q0_NACK_ERR || + val & CCI_IRQ_STATUS_0_I2C_M1_Q1_NACK_ERR) + cci->master[0].status = -ENXIO; + else + cci->master[0].status = -EIO; + + writel(CCI_HALT_REQ_I2C_M1_Q0Q1, cci->base + CCI_HALT_REQ); + ret = IRQ_HANDLED; + } + + return ret; +} + +static int cci_halt(struct cci *cci, u8 master_num) +{ + struct cci_master *master; + u32 val; + + if (master_num >= cci->data->num_masters) { + dev_err(cci->dev, "Unsupported master idx (%u)\n", master_num); + return -EINVAL; + } + + val = BIT(master_num); + master = &cci->master[master_num]; + + reinit_completion(&master->irq_complete); + writel(val, cci->base + CCI_HALT_REQ); + + if (!wait_for_completion_timeout(&master->irq_complete, CCI_TIMEOUT)) { + dev_err(cci->dev, "CCI halt timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int cci_reset(struct cci *cci) +{ + /* + * we reset the whole controller, here and for implicity use + * master[0].xxx for waiting on it. + */ + reinit_completion(&cci->master[0].irq_complete); + writel(CCI_RESET_CMD_MASK, cci->base + CCI_RESET_CMD); + + if (!wait_for_completion_timeout(&cci->master[0].irq_complete, + CCI_TIMEOUT)) { + dev_err(cci->dev, "CCI reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static int cci_init(struct cci *cci) +{ + u32 val = CCI_IRQ_MASK_0_I2C_M0_RD_DONE | + CCI_IRQ_MASK_0_I2C_M0_Q0_REPORT | + CCI_IRQ_MASK_0_I2C_M0_Q1_REPORT | + CCI_IRQ_MASK_0_I2C_M1_RD_DONE | + CCI_IRQ_MASK_0_I2C_M1_Q0_REPORT | + CCI_IRQ_MASK_0_I2C_M1_Q1_REPORT | + CCI_IRQ_MASK_0_RST_DONE_ACK | + CCI_IRQ_MASK_0_I2C_M0_Q0Q1_HALT_ACK | + CCI_IRQ_MASK_0_I2C_M1_Q0Q1_HALT_ACK | + CCI_IRQ_MASK_0_I2C_M0_ERROR | + CCI_IRQ_MASK_0_I2C_M1_ERROR; + int i; + + writel(val, cci->base + CCI_IRQ_MASK_0); + + for (i = 0; i < cci->data->num_masters; i++) { + int mode = cci->master[i].mode; + const struct hw_params *hw; + + if (!cci->master[i].cci) + continue; + + hw = &cci->data->params[mode]; + + val = hw->thigh << 16 | hw->tlow; + writel(val, cci->base + CCI_I2C_Mm_SCL_CTL(i)); + + val = hw->tsu_sto << 16 | hw->tsu_sta; + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_0(i)); + + val = hw->thd_dat << 16 | hw->thd_sta; + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_1(i)); + + val = hw->tbuf; + writel(val, cci->base + CCI_I2C_Mm_SDA_CTL_2(i)); + + val = hw->scl_stretch_en << 8 | hw->trdhld << 4 | hw->tsp; + writel(val, cci->base + CCI_I2C_Mm_MISC_CTL(i)); + } + + return 0; +} + +static int cci_run_queue(struct cci *cci, u8 master, u8 queue) +{ + u32 val; + + val = readl(cci->base + CCI_I2C_Mm_Qn_CUR_WORD_CNT(master, queue)); + writel(val, cci->base + CCI_I2C_Mm_Qn_EXEC_WORD_CNT(master, queue)); + + reinit_completion(&cci->master[master].irq_complete); + val = BIT(master * 2 + queue); + writel(val, cci->base + CCI_QUEUE_START); + + if (!wait_for_completion_timeout(&cci->master[master].irq_complete, + CCI_TIMEOUT)) { + dev_err(cci->dev, "master %d queue %d timeout\n", + master, queue); + cci_reset(cci); + cci_init(cci); + return -ETIMEDOUT; + } + + return cci->master[master].status; +} + +static int cci_validate_queue(struct cci *cci, u8 master, u8 queue) +{ + u32 val; + + val = readl(cci->base + CCI_I2C_Mm_Qn_CUR_WORD_CNT(master, queue)); + if (val == cci->data->queue_size[queue]) + return -EINVAL; + + if (!val) + return 0; + + val = CCI_I2C_REPORT | CCI_I2C_REPORT_IRQ_EN; + writel(val, cci->base + CCI_I2C_Mm_Qn_LOAD_DATA(master, queue)); + + return cci_run_queue(cci, master, queue); +} + +static int cci_i2c_read(struct cci *cci, u16 master, + u16 addr, u8 *buf, u16 len) +{ + u32 val, words_read, words_exp; + u8 queue = QUEUE_1; + int i, index = 0, ret; + bool first = true; + + /* + * Call validate queue to make sure queue is empty before starting. + * This is to avoid overflow / underflow of queue. + */ + ret = cci_validate_queue(cci, master, queue); + if (ret < 0) + return ret; + + val = CCI_I2C_SET_PARAM | (addr & 0x7f) << 4; + writel(val, cci->base + CCI_I2C_Mm_Qn_LOAD_DATA(master, queue)); + + val = CCI_I2C_READ | len << 4; + writel(val, cci->base + CCI_I2C_Mm_Qn_LOAD_DATA(master, queue)); + + ret = cci_run_queue(cci, master, queue); + if (ret < 0) + return ret; + + words_read = readl(cci->base + CCI_I2C_Mm_READ_BUF_LEVEL(master)); + words_exp = len / 4 + 1; + if (words_read != words_exp) { + dev_err(cci->dev, "words read = %d, words expected = %d\n", + words_read, words_exp); + return -EIO; + } + + do { + val = readl(cci->base + CCI_I2C_Mm_READ_DATA(master)); + + for (i = 0; i < 4 && index < len; i++) { + if (first) { + /* The LS byte of this register represents the + * first byte read from the slave during a read + * access. + */ + first = false; + continue; + } + buf[index++] = (val >> (i * 8)) & 0xff; + } + } while (--words_read); + + return 0; +} + +static int cci_i2c_write(struct cci *cci, u16 master, + u16 addr, u8 *buf, u16 len) +{ + u8 queue = QUEUE_0; + u8 load[12] = { 0 }; + int i = 0, j, ret; + u32 val; + + /* + * Call validate queue to make sure queue is empty before starting. + * This is to avoid overflow / underflow of queue. + */ + ret = cci_validate_queue(cci, master, queue); + if (ret < 0) + return ret; + + val = CCI_I2C_SET_PARAM | (addr & 0x7f) << 4; + writel(val, cci->base + CCI_I2C_Mm_Qn_LOAD_DATA(master, queue)); + + load[i++] = CCI_I2C_WRITE | len << 4; + + for (j = 0; j < len; j++) + load[i++] = buf[j]; + + for (j = 0; j < i; j += 4) { + val = load[j]; + val |= load[j + 1] << 8; + val |= load[j + 2] << 16; + val |= load[j + 3] << 24; + writel(val, cci->base + CCI_I2C_Mm_Qn_LOAD_DATA(master, queue)); + } + + val = CCI_I2C_REPORT | CCI_I2C_REPORT_IRQ_EN; + writel(val, cci->base + CCI_I2C_Mm_Qn_LOAD_DATA(master, queue)); + + return cci_run_queue(cci, master, queue); +} + +static int cci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct cci_master *cci_master = i2c_get_adapdata(adap); + struct cci *cci = cci_master->cci; + int i, ret; + + ret = pm_runtime_get_sync(cci->dev); + if (ret < 0) + goto err; + + for (i = 0; i < num; i++) { + if (msgs[i].flags & I2C_M_RD) + ret = cci_i2c_read(cci, cci_master->master, + msgs[i].addr, msgs[i].buf, + msgs[i].len); + else + ret = cci_i2c_write(cci, cci_master->master, + msgs[i].addr, msgs[i].buf, + msgs[i].len); + + if (ret < 0) + break; + } + + if (!ret) + ret = num; + +err: + pm_runtime_mark_last_busy(cci->dev); + pm_runtime_put_autosuspend(cci->dev); + + return ret; +} + +static u32 cci_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm cci_algo = { + .master_xfer = cci_xfer, + .functionality = cci_func, +}; + +static int cci_enable_clocks(struct cci *cci) +{ + return clk_bulk_prepare_enable(cci->nclocks, cci->clocks); +} + +static void cci_disable_clocks(struct cci *cci) +{ + clk_bulk_disable_unprepare(cci->nclocks, cci->clocks); +} + +static int __maybe_unused cci_suspend_runtime(struct device *dev) +{ + struct cci *cci = dev_get_drvdata(dev); + + cci_disable_clocks(cci); + return 0; +} + +static int __maybe_unused cci_resume_runtime(struct device *dev) +{ + struct cci *cci = dev_get_drvdata(dev); + int ret; + + ret = cci_enable_clocks(cci); + if (ret) + return ret; + + cci_init(cci); + return 0; +} + +static int __maybe_unused cci_suspend(struct device *dev) +{ + if (!pm_runtime_suspended(dev)) + return cci_suspend_runtime(dev); + + return 0; +} + +static int __maybe_unused cci_resume(struct device *dev) +{ + cci_resume_runtime(dev); + pm_runtime_mark_last_busy(dev); + pm_request_autosuspend(dev); + + return 0; +} + +static const struct dev_pm_ops qcom_cci_pm = { + SET_SYSTEM_SLEEP_PM_OPS(cci_suspend, cci_resume) + SET_RUNTIME_PM_OPS(cci_suspend_runtime, cci_resume_runtime, NULL) +}; + +static int cci_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + unsigned long cci_clk_rate = 0; + struct device_node *child; + struct resource *r; + struct cci *cci; + int ret, i; + u32 val; + + cci = devm_kzalloc(dev, sizeof(*cci), GFP_KERNEL); + if (!cci) + return -ENOMEM; + + cci->dev = dev; + platform_set_drvdata(pdev, cci); + cci->data = device_get_match_data(dev); + if (!cci->data) + return -ENOENT; + + for_each_available_child_of_node(dev->of_node, child) { + u32 idx; + + ret = of_property_read_u32(child, "reg", &idx); + if (ret) { + dev_err(dev, "%pOF invalid 'reg' property", child); + continue; + } + + if (idx >= cci->data->num_masters) { + dev_err(dev, "%pOF invalid 'reg' value: %u (max is %u)", + child, idx, cci->data->num_masters - 1); + continue; + } + + cci->master[idx].adap.quirks = &cci->data->quirks; + cci->master[idx].adap.algo = &cci_algo; + cci->master[idx].adap.dev.parent = dev; + cci->master[idx].adap.dev.of_node = child; + cci->master[idx].master = idx; + cci->master[idx].cci = cci; + + i2c_set_adapdata(&cci->master[idx].adap, &cci->master[idx]); + snprintf(cci->master[idx].adap.name, + sizeof(cci->master[idx].adap.name), "Qualcomm-CCI"); + + cci->master[idx].mode = I2C_MODE_STANDARD; + ret = of_property_read_u32(child, "clock-frequency", &val); + if (!ret) { + if (val == 400000) + cci->master[idx].mode = I2C_MODE_FAST; + else if (val == 1000000) + cci->master[idx].mode = I2C_MODE_FAST_PLUS; + } + + init_completion(&cci->master[idx].irq_complete); + } + + /* Memory */ + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + cci->base = devm_ioremap_resource(dev, r); + if (IS_ERR(cci->base)) + return PTR_ERR(cci->base); + + /* Clocks */ + + ret = devm_clk_bulk_get_all(dev, &cci->clocks); + if (ret < 1) { + dev_err(dev, "failed to get clocks %d\n", ret); + return ret; + } + cci->nclocks = ret; + + /* Retrieve CCI clock rate */ + for (i = 0; i < cci->nclocks; i++) { + if (!strcmp(cci->clocks[i].id, "cci")) { + cci_clk_rate = clk_get_rate(cci->clocks[i].clk); + break; + } + } + + if (cci_clk_rate != cci->data->cci_clk_rate) { + /* cci clock set by the bootloader or via assigned clock rate + * in DT. + */ + dev_warn(dev, "Found %lu cci clk rate while %lu was expected\n", + cci_clk_rate, cci->data->cci_clk_rate); + } + + ret = cci_enable_clocks(cci); + if (ret < 0) + return ret; + + /* Interrupt */ + + ret = platform_get_irq(pdev, 0); + if (ret < 0) + goto disable_clocks; + cci->irq = ret; + + ret = devm_request_irq(dev, cci->irq, cci_isr, 0, dev_name(dev), cci); + if (ret < 0) { + dev_err(dev, "request_irq failed, ret: %d\n", ret); + goto disable_clocks; + } + + val = readl(cci->base + CCI_HW_VERSION); + dev_dbg(dev, "CCI HW version = 0x%08x", val); + + ret = cci_reset(cci); + if (ret < 0) + goto error; + + ret = cci_init(cci); + if (ret < 0) + goto error; + + for (i = 0; i < cci->data->num_masters; i++) { + if (!cci->master[i].cci) + continue; + + ret = i2c_add_adapter(&cci->master[i].adap); + if (ret < 0) + goto error_i2c; + } + + pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); + pm_runtime_use_autosuspend(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + return 0; + +error_i2c: + for (; i >= 0; i--) { + if (cci->master[i].cci) + i2c_del_adapter(&cci->master[i].adap); + } +error: + disable_irq(cci->irq); +disable_clocks: + cci_disable_clocks(cci); + + return ret; +} + +static int cci_remove(struct platform_device *pdev) +{ + struct cci *cci = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < cci->data->num_masters; i++) { + if (cci->master[i].cci) + i2c_del_adapter(&cci->master[i].adap); + cci_halt(cci, i); + } + + disable_irq(cci->irq); + pm_runtime_disable(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + + return 0; +} + +static const struct cci_data cci_v1_data = { + .num_masters = 1, + .queue_size = { 64, 16 }, + .quirks = { + .max_write_len = 10, + .max_read_len = 12, + }, + .cci_clk_rate = 19200000, + .params[I2C_MODE_STANDARD] = { + .thigh = 78, + .tlow = 114, + .tsu_sto = 28, + .tsu_sta = 28, + .thd_dat = 10, + .thd_sta = 77, + .tbuf = 118, + .scl_stretch_en = 0, + .trdhld = 6, + .tsp = 1 + }, + .params[I2C_MODE_FAST] = { + .thigh = 20, + .tlow = 28, + .tsu_sto = 21, + .tsu_sta = 21, + .thd_dat = 13, + .thd_sta = 18, + .tbuf = 32, + .scl_stretch_en = 0, + .trdhld = 6, + .tsp = 3 + }, +}; + +static const struct cci_data cci_v2_data = { + .num_masters = 2, + .queue_size = { 64, 16 }, + .quirks = { + .max_write_len = 11, + .max_read_len = 12, + }, + .cci_clk_rate = 37500000, + .params[I2C_MODE_STANDARD] = { + .thigh = 201, + .tlow = 174, + .tsu_sto = 204, + .tsu_sta = 231, + .thd_dat = 22, + .thd_sta = 162, + .tbuf = 227, + .scl_stretch_en = 0, + .trdhld = 6, + .tsp = 3 + }, + .params[I2C_MODE_FAST] = { + .thigh = 38, + .tlow = 56, + .tsu_sto = 40, + .tsu_sta = 40, + .thd_dat = 22, + .thd_sta = 35, + .tbuf = 62, + .scl_stretch_en = 0, + .trdhld = 6, + .tsp = 3 + }, + .params[I2C_MODE_FAST_PLUS] = { + .thigh = 16, + .tlow = 22, + .tsu_sto = 17, + .tsu_sta = 18, + .thd_dat = 16, + .thd_sta = 15, + .tbuf = 24, + .scl_stretch_en = 0, + .trdhld = 3, + .tsp = 3 + }, +}; + +static const struct of_device_id cci_dt_match[] = { + { .compatible = "qcom,msm8916-cci", .data = &cci_v1_data}, + { .compatible = "qcom,msm8996-cci", .data = &cci_v2_data}, + { .compatible = "qcom,sdm845-cci", .data = &cci_v2_data}, + {} +}; +MODULE_DEVICE_TABLE(of, cci_dt_match); + +static struct platform_driver qcom_cci_driver = { + .probe = cci_probe, + .remove = cci_remove, + .driver = { + .name = "i2c-qcom-cci", + .of_match_table = cci_dt_match, + .pm = &qcom_cci_pm, + }, +}; + +module_platform_driver(qcom_cci_driver); + +MODULE_DESCRIPTION("Qualcomm Camera Control Interface driver"); +MODULE_AUTHOR("Todor Tomov <todor.tomov@linaro.org>"); +MODULE_AUTHOR("Loic Poulain <loic.poulain@linaro.org>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index 748872a9b0fc..fbc04b60cfd1 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -956,10 +956,8 @@ static void qup_i2c_conf_v1(struct qup_i2c_dev *qup) u32 qup_config = I2C_MINI_CORE | I2C_N_VAL; u32 io_mode = QUP_REPACK_EN; - blk->is_tx_blk_mode = - blk->total_tx_len > qup->out_fifo_sz ? true : false; - blk->is_rx_blk_mode = - blk->total_rx_len > qup->in_fifo_sz ? true : false; + blk->is_tx_blk_mode = blk->total_tx_len > qup->out_fifo_sz; + blk->is_rx_blk_mode = blk->total_rx_len > qup->in_fifo_sz; if (blk->is_tx_blk_mode) { io_mode |= QUP_OUTPUT_BLK_MODE; @@ -1528,9 +1526,9 @@ qup_i2c_determine_mode_v2(struct qup_i2c_dev *qup, qup->use_dma = true; } else { qup->blk.is_tx_blk_mode = max_tx_len > qup->out_fifo_sz - - QUP_MAX_TAGS_LEN ? true : false; + QUP_MAX_TAGS_LEN; qup->blk.is_rx_blk_mode = max_rx_len > qup->in_fifo_sz - - READ_RX_TAGS_LEN ? true : false; + READ_RX_TAGS_LEN; } return 0; @@ -1660,7 +1658,6 @@ static int qup_i2c_probe(struct platform_device *pdev) static const int blk_sizes[] = {4, 16, 32}; struct qup_i2c_dev *qup; unsigned long one_bit_t; - struct resource *res; u32 io_mode, hw_ver, size; int ret, fs_div, hs_div; u32 src_clk_freq = DEFAULT_SRC_CLK; @@ -1757,16 +1754,13 @@ nodma: return -EINVAL; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - qup->base = devm_ioremap_resource(qup->dev, res); + qup->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(qup->base)) return PTR_ERR(qup->base); qup->irq = platform_get_irq(pdev, 0); - if (qup->irq < 0) { - dev_err(qup->dev, "No IRQ defined\n"); + if (qup->irq < 0) return qup->irq; - } if (has_acpi_companion(qup->dev)) { ret = device_property_read_u32(qup->dev, diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 3b5397aa4ca6..a45c4bf1ec01 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -938,9 +938,7 @@ static int rcar_i2c_probe(struct platform_device *pdev) return PTR_ERR(priv->clk); } - priv->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - priv->io = devm_ioremap_resource(dev, priv->res); + priv->io = devm_platform_get_and_ioremap_resource(pdev, 0, &priv->res); if (IS_ERR(priv->io)) return PTR_ERR(priv->io); diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c index 73272d4296bb..bc698240c4aa 100644 --- a/drivers/i2c/busses/i2c-rk3x.c +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -1193,7 +1193,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev) struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; struct rk3x_i2c *i2c; - struct resource *mem; int ret = 0; int bus_nr; u32 value; @@ -1223,8 +1222,7 @@ static int rk3x_i2c_probe(struct platform_device *pdev) spin_lock_init(&i2c->lock); init_waitqueue_head(&i2c->wait); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + i2c->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->regs)) return PTR_ERR(i2c->regs); @@ -1262,10 +1260,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev) /* IRQ setup */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "cannot find rk3x IRQ\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, rk3x_i2c_irq, 0, dev_name(&pdev->dev), i2c); diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index a459e00c6851..d7f72ec331e8 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -271,7 +271,6 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) { struct sirfsoc_i2c *siic; struct i2c_adapter *adap; - struct resource *mem_res; struct clk *clk; int bitrate; int ctrl_speed; @@ -309,8 +308,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) adap = &siic->adapter; adap->class = I2C_CLASS_DEPRECATED; - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - siic->base = devm_ioremap_resource(&pdev->dev, mem_res); + siic->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(siic->base)) { err = PTR_ERR(siic->base); goto out; diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 123a42bfe3b1..19cda6742423 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -492,10 +492,8 @@ static int sprd_i2c_probe(struct platform_device *pdev) return PTR_ERR(i2c_dev->base); i2c_dev->irq = platform_get_irq(pdev, 0); - if (i2c_dev->irq < 0) { - dev_err(&pdev->dev, "failed to get irq resource\n"); + if (i2c_dev->irq < 0) return i2c_dev->irq; - } i2c_set_adapdata(&i2c_dev->adap, i2c_dev); init_completion(&i2c_dev->complete); diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c index 1da347e6a358..3f69a3bb6119 100644 --- a/drivers/i2c/busses/i2c-stm32.c +++ b/drivers/i2c/busses/i2c-stm32.c @@ -25,8 +25,9 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, /* Request and configure I2C TX dma channel */ dma->chan_tx = dma_request_chan(dev, "tx"); if (IS_ERR(dma->chan_tx)) { - dev_dbg(dev, "can't request DMA tx channel\n"); ret = PTR_ERR(dma->chan_tx); + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't request DMA tx channel\n"); goto fail_al; } @@ -44,8 +45,10 @@ struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev, /* Request and configure I2C RX dma channel */ dma->chan_rx = dma_request_chan(dev, "rx"); if (IS_ERR(dma->chan_rx)) { - dev_err(dev, "can't request DMA rx channel\n"); ret = PTR_ERR(dma->chan_rx); + if (ret != -EPROBE_DEFER) + dev_err(dev, "can't request DMA rx channel\n"); + goto fail_tx; } @@ -73,7 +76,8 @@ fail_tx: dma_release_channel(dma->chan_tx); fail_al: devm_kfree(dev, dma); - dev_info(dev, "can't use DMA\n"); + if (ret != -EPROBE_DEFER) + dev_info(dev, "can't use DMA\n"); return ERR_PTR(ret); } diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index d6a69dfcac3f..48e269284369 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -797,8 +797,10 @@ static int stm32f4_i2c_probe(struct platform_device *pdev) rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (IS_ERR(rst)) { - dev_err(&pdev->dev, "Error: Missing controller reset\n"); ret = PTR_ERR(rst); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Error: Missing reset ctrl\n"); + goto clk_free; } reset_control_assert(rst); diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 330ffed011e0..bff3479fe122 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -189,8 +189,6 @@ struct stm32f7_i2c_regs { /** * struct stm32f7_i2c_spec - private i2c specification timing * @rate: I2C bus speed (Hz) - * @rate_min: 80% of I2C bus speed (Hz) - * @rate_max: 100% of I2C bus speed (Hz) * @fall_max: Max fall time of both SDA and SCL signals (ns) * @rise_max: Max rise time of both SDA and SCL signals (ns) * @hddat_min: Min data hold time (ns) @@ -201,8 +199,6 @@ struct stm32f7_i2c_regs { */ struct stm32f7_i2c_spec { u32 rate; - u32 rate_min; - u32 rate_max; u32 fall_max; u32 rise_max; u32 hddat_min; @@ -214,7 +210,6 @@ struct stm32f7_i2c_spec { /** * struct stm32f7_i2c_setup - private I2C timing setup parameters - * @speed: I2C speed mode (standard, Fast Plus) * @speed_freq: I2C speed frequency (Hz) * @clock_src: I2C clock source frequency (Hz) * @rise_time: Rise time (ns) @@ -224,7 +219,6 @@ struct stm32f7_i2c_spec { * @fmp_clr_offset: Fast Mode Plus clear register offset from set register */ struct stm32f7_i2c_setup { - enum stm32_i2c_speed speed; u32 speed_freq; u32 clock_src; u32 rise_time; @@ -287,7 +281,7 @@ struct stm32f7_i2c_msg { * @base: virtual memory area * @complete: completion of I2C message * @clk: hw i2c clock - * @speed: I2C clock frequency of the controller. Standard, Fast or Fast+ + * @bus_rate: I2C clock frequency of the controller * @msg: Pointer to data to be written * @msg_num: number of I2C messages to be executed * @msg_id: message identifiant @@ -314,7 +308,7 @@ struct stm32f7_i2c_dev { void __iomem *base; struct completion complete; struct clk *clk; - int speed; + unsigned int bus_rate; struct i2c_msg *msg; unsigned int msg_num; unsigned int msg_id; @@ -342,11 +336,9 @@ struct stm32f7_i2c_dev { * Table10. Characteristics of the SDA and SCL bus lines for Standard, Fast, * and Fast-mode Plus I2C-bus devices */ -static struct stm32f7_i2c_spec i2c_specs[] = { - [STM32_I2C_SPEED_STANDARD] = { +static struct stm32f7_i2c_spec stm32f7_i2c_specs[] = { + { .rate = I2C_MAX_STANDARD_MODE_FREQ, - .rate_min = I2C_MAX_STANDARD_MODE_FREQ * 8 / 10, /* 80% */ - .rate_max = I2C_MAX_STANDARD_MODE_FREQ, .fall_max = 300, .rise_max = 1000, .hddat_min = 0, @@ -355,10 +347,8 @@ static struct stm32f7_i2c_spec i2c_specs[] = { .l_min = 4700, .h_min = 4000, }, - [STM32_I2C_SPEED_FAST] = { + { .rate = I2C_MAX_FAST_MODE_FREQ, - .rate_min = I2C_MAX_FAST_MODE_FREQ * 8 / 10, /* 80% */ - .rate_max = I2C_MAX_FAST_MODE_FREQ, .fall_max = 300, .rise_max = 300, .hddat_min = 0, @@ -367,10 +357,8 @@ static struct stm32f7_i2c_spec i2c_specs[] = { .l_min = 1300, .h_min = 600, }, - [STM32_I2C_SPEED_FAST_PLUS] = { + { .rate = I2C_MAX_FAST_MODE_PLUS_FREQ, - .rate_min = I2C_MAX_FAST_MODE_PLUS_FREQ * 8 / 10, /* 80% */ - .rate_max = I2C_MAX_FAST_MODE_PLUS_FREQ, .fall_max = 100, .rise_max = 120, .hddat_min = 0, @@ -411,10 +399,23 @@ static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask) stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask); } +static struct stm32f7_i2c_spec *stm32f7_get_specs(u32 rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(stm32f7_i2c_specs); i++) + if (rate <= stm32f7_i2c_specs[i].rate) + return &stm32f7_i2c_specs[i]; + + return ERR_PTR(-EINVAL); +} + +#define RATE_MIN(rate) ((rate) * 8 / 10) static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, struct stm32f7_i2c_setup *setup, struct stm32f7_i2c_timings *output) { + struct stm32f7_i2c_spec *specs; u32 p_prev = STM32F7_PRESC_MAX; u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->clock_src); @@ -432,18 +433,19 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, u16 p, l, a, h; int ret = 0; - if (setup->speed >= STM32_I2C_SPEED_END) { - dev_err(i2c_dev->dev, "speed out of bound {%d/%d}\n", - setup->speed, STM32_I2C_SPEED_END - 1); + specs = stm32f7_get_specs(setup->speed_freq); + if (specs == ERR_PTR(-EINVAL)) { + dev_err(i2c_dev->dev, "speed out of bound {%d}\n", + setup->speed_freq); return -EINVAL; } - if ((setup->rise_time > i2c_specs[setup->speed].rise_max) || - (setup->fall_time > i2c_specs[setup->speed].fall_max)) { + if ((setup->rise_time > specs->rise_max) || + (setup->fall_time > specs->fall_max)) { dev_err(i2c_dev->dev, "timings out of bound Rise{%d>%d}/Fall{%d>%d}\n", - setup->rise_time, i2c_specs[setup->speed].rise_max, - setup->fall_time, i2c_specs[setup->speed].fall_max); + setup->rise_time, specs->rise_max, + setup->fall_time, specs->fall_max); return -EINVAL; } @@ -454,12 +456,6 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, return -EINVAL; } - if (setup->speed_freq > i2c_specs[setup->speed].rate) { - dev_err(i2c_dev->dev, "ERROR: Freq {%d/%d}\n", - setup->speed_freq, i2c_specs[setup->speed].rate); - return -EINVAL; - } - /* Analog and Digital Filters */ af_delay_min = (setup->analog_filter ? @@ -469,13 +465,13 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, STM32F7_I2C_ANALOG_FILTER_DELAY_MAX : 0); dnf_delay = setup->dnf * i2cclk; - sdadel_min = i2c_specs[setup->speed].hddat_min + setup->fall_time - + sdadel_min = specs->hddat_min + setup->fall_time - af_delay_min - (setup->dnf + 3) * i2cclk; - sdadel_max = i2c_specs[setup->speed].vddat_max - setup->rise_time - + sdadel_max = specs->vddat_max - setup->rise_time - af_delay_max - (setup->dnf + 4) * i2cclk; - scldel_min = setup->rise_time + i2c_specs[setup->speed].sudat_min; + scldel_min = setup->rise_time + specs->sudat_min; if (sdadel_min < 0) sdadel_min = 0; @@ -530,8 +526,8 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, tsync = af_delay_min + dnf_delay + (2 * i2cclk); s = NULL; - clk_max = NSEC_PER_SEC / i2c_specs[setup->speed].rate_min; - clk_min = NSEC_PER_SEC / i2c_specs[setup->speed].rate_max; + clk_max = NSEC_PER_SEC / RATE_MIN(setup->speed_freq); + clk_min = NSEC_PER_SEC / setup->speed_freq; /* * Among Prescaler possibilities discovered above figures out SCL Low @@ -549,7 +545,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, for (l = 0; l < STM32F7_SCLL_MAX; l++) { u32 tscl_l = (l + 1) * prescaler + tsync; - if ((tscl_l < i2c_specs[setup->speed].l_min) || + if ((tscl_l < specs->l_min) || (i2cclk >= ((tscl_l - af_delay_min - dnf_delay) / 4))) { continue; @@ -561,7 +557,7 @@ static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev, setup->rise_time + setup->fall_time; if ((tscl >= clk_min) && (tscl <= clk_max) && - (tscl_h >= i2c_specs[setup->speed].h_min) && + (tscl_h >= specs->h_min) && (i2cclk < tscl_h)) { int clk_error = tscl - i2cbus; @@ -607,6 +603,17 @@ exit: return ret; } +static u32 stm32f7_get_lower_rate(u32 rate) +{ + int i = ARRAY_SIZE(stm32f7_i2c_specs); + + while (--i) + if (stm32f7_i2c_specs[i].rate < rate) + break; + + return stm32f7_i2c_specs[i].rate; +} + static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, struct stm32f7_i2c_setup *setup) { @@ -619,18 +626,15 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, i2c_parse_fw_timings(i2c_dev->dev, t, false); - if (t->bus_freq_hz >= I2C_MAX_FAST_MODE_PLUS_FREQ) - i2c_dev->speed = STM32_I2C_SPEED_FAST_PLUS; - else if (t->bus_freq_hz >= I2C_MAX_FAST_MODE_FREQ) - i2c_dev->speed = STM32_I2C_SPEED_FAST; - else - i2c_dev->speed = STM32_I2C_SPEED_STANDARD; + if (t->bus_freq_hz > I2C_MAX_FAST_MODE_PLUS_FREQ) { + dev_err(i2c_dev->dev, "Invalid bus speed (%i>%i)\n", + t->bus_freq_hz, I2C_MAX_FAST_MODE_PLUS_FREQ); + return -EINVAL; + } + setup->speed_freq = t->bus_freq_hz; i2c_dev->setup.rise_time = t->scl_rise_ns; i2c_dev->setup.fall_time = t->scl_fall_ns; - - setup->speed = i2c_dev->speed; - setup->speed_freq = i2c_specs[setup->speed].rate; setup->clock_src = clk_get_rate(i2c_dev->clk); if (!setup->clock_src) { @@ -644,17 +648,13 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, if (ret) { dev_err(i2c_dev->dev, "failed to compute I2C timings.\n"); - if (i2c_dev->speed > STM32_I2C_SPEED_STANDARD) { - i2c_dev->speed--; - setup->speed = i2c_dev->speed; - setup->speed_freq = - i2c_specs[setup->speed].rate; - dev_warn(i2c_dev->dev, - "downgrade I2C Speed Freq to (%i)\n", - i2c_specs[setup->speed].rate); - } else { + if (setup->speed_freq <= I2C_MAX_STANDARD_MODE_FREQ) break; - } + setup->speed_freq = + stm32f7_get_lower_rate(setup->speed_freq); + dev_warn(i2c_dev->dev, + "downgrade I2C Speed Freq to (%i)\n", + setup->speed_freq); } } while (ret); @@ -663,13 +663,15 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev, return ret; } - dev_dbg(i2c_dev->dev, "I2C Speed(%i), Freq(%i), Clk Source(%i)\n", - setup->speed, setup->speed_freq, setup->clock_src); + dev_dbg(i2c_dev->dev, "I2C Speed(%i), Clk Source(%i)\n", + setup->speed_freq, setup->clock_src); dev_dbg(i2c_dev->dev, "I2C Rise(%i) and Fall(%i) Time\n", setup->rise_time, setup->fall_time); dev_dbg(i2c_dev->dev, "I2C Analog Filter(%s), DNF(%i)\n", (setup->analog_filter ? "On" : "Off"), setup->dnf); + i2c_dev->bus_rate = setup->speed_freq; + return 0; } @@ -1462,7 +1464,8 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data) /* NACK received */ if (status & STM32F7_I2C_ISR_NACKF) { - dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__); + dev_dbg(i2c_dev->dev, "<%s>: Receive NACK (addr %x)\n", + __func__, f7_msg->addr); writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR); f7_msg->result = -ENXIO; } @@ -1866,7 +1869,7 @@ static int stm32f7_i2c_write_fm_plus_bits(struct stm32f7_i2c_dev *i2c_dev, { int ret; - if (i2c_dev->speed != STM32_I2C_SPEED_FAST_PLUS || + if (i2c_dev->bus_rate <= I2C_MAX_FAST_MODE_FREQ || IS_ERR_OR_NULL(i2c_dev->regmap)) /* Optional */ return 0; @@ -1940,8 +1943,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) if (!i2c_dev) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); + i2c_dev->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(i2c_dev->base)) return PTR_ERR(i2c_dev->base); phy_addr = (dma_addr_t)res->start; @@ -1967,7 +1969,8 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c_dev->clk)) { - dev_err(&pdev->dev, "Error: Missing controller clock\n"); + if (PTR_ERR(i2c_dev->clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Failed to get controller clock\n"); return PTR_ERR(i2c_dev->clk); } @@ -1979,8 +1982,10 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) rst = devm_reset_control_get(&pdev->dev, NULL); if (IS_ERR(rst)) { - dev_err(&pdev->dev, "Error: Missing controller reset\n"); ret = PTR_ERR(rst); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "Error: Missing reset ctrl\n"); + goto clk_free; } reset_control_assert(rst); @@ -2020,7 +2025,8 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) if (ret) goto clk_free; - if (i2c_dev->speed == STM32_I2C_SPEED_FAST_PLUS) { + /* Setup Fast mode plus if necessary */ + if (i2c_dev->bus_rate > I2C_MAX_FAST_MODE_FREQ) { ret = stm32f7_i2c_setup_fm_plus_bits(pdev, i2c_dev); if (ret) goto clk_free; diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index ba6b60caa45e..64d739baf480 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -860,7 +860,6 @@ static int stu300_probe(struct platform_device *pdev) { struct stu300_dev *dev; struct i2c_adapter *adap; - struct resource *res; int bus_nr; int ret = 0; @@ -876,8 +875,7 @@ static int stu300_probe(struct platform_device *pdev) } dev->pdev = pdev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dev->virtbase = devm_ioremap_resource(&pdev->dev, res); + dev->virtbase = devm_platform_ioremap_resource(pdev, 0); dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual " "base %p\n", bus_nr, dev->virtbase); if (IS_ERR(dev->virtbase)) diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c index e5293f0b3318..2f6f6468214d 100644 --- a/drivers/i2c/busses/i2c-sun6i-p2wi.c +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -187,7 +187,6 @@ static int p2wi_probe(struct platform_device *pdev) struct device_node *childnp; unsigned long parent_clk_freq; u32 clk_freq = I2C_MAX_STANDARD_MODE_FREQ; - struct resource *r; struct p2wi *p2wi; u32 slave_addr; int clk_div; @@ -231,17 +230,14 @@ static int p2wi_probe(struct platform_device *pdev) p2wi->slave_addr = slave_addr; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - p2wi->regs = devm_ioremap_resource(dev, r); + p2wi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(p2wi->regs)) return PTR_ERR(p2wi->regs); strlcpy(p2wi->adapter.name, pdev->name, sizeof(p2wi->adapter.name)); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to retrieve irq: %d\n", irq); + if (irq < 0) return irq; - } p2wi->clk = devm_clk_get(dev, NULL); if (IS_ERR(p2wi->clk)) { diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c index 9099d0a67ace..c9a3dba6a75d 100644 --- a/drivers/i2c/busses/i2c-synquacer.c +++ b/drivers/i2c/busses/i2c-synquacer.c @@ -536,7 +536,6 @@ static const struct i2c_adapter synquacer_i2c_ops = { static int synquacer_i2c_probe(struct platform_device *pdev) { struct synquacer_i2c *i2c; - struct resource *r; u32 bus_speed; int ret; @@ -574,16 +573,13 @@ static int synquacer_i2c_probe(struct platform_device *pdev) return -EINVAL; } - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->base = devm_ioremap_resource(&pdev->dev, r); + i2c->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(i2c->base)) return PTR_ERR(i2c->base); i2c->irq = platform_get_irq(pdev, 0); - if (i2c->irq < 0) { - dev_err(&pdev->dev, "no IRQ resource found\n"); + if (i2c->irq < 0) return -ENODEV; - } ret = devm_request_irq(&pdev->dev, i2c->irq, synquacer_i2c_isr, 0, dev_name(&pdev->dev), i2c); diff --git a/drivers/i2c/busses/i2c-uniphier-f.c b/drivers/i2c/busses/i2c-uniphier-f.c index 2b258d54d68c..cb4666c54a23 100644 --- a/drivers/i2c/busses/i2c-uniphier-f.c +++ b/drivers/i2c/busses/i2c-uniphier-f.c @@ -529,10 +529,8 @@ static int uniphier_fi2c_probe(struct platform_device *pdev) return PTR_ERR(priv->membase); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to get IRQ number\n"); + if (irq < 0) return irq; - } if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed)) bus_speed = I2C_MAX_STANDARD_MODE_FREQ; diff --git a/drivers/i2c/busses/i2c-uniphier.c b/drivers/i2c/busses/i2c-uniphier.c index 668b1fa2b0ef..ee00a44bf4c7 100644 --- a/drivers/i2c/busses/i2c-uniphier.c +++ b/drivers/i2c/busses/i2c-uniphier.c @@ -324,10 +324,8 @@ static int uniphier_i2c_probe(struct platform_device *pdev) return PTR_ERR(priv->membase); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(dev, "failed to get IRQ number\n"); + if (irq < 0) return irq; - } if (of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed)) bus_speed = I2C_MAX_STANDARD_MODE_FREQ; diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c index 391c878a7cdc..f2241cedf5d3 100644 --- a/drivers/i2c/busses/i2c-xlp9xx.c +++ b/drivers/i2c/busses/i2c-xlp9xx.c @@ -506,23 +506,19 @@ static int xlp9xx_i2c_smbus_setup(struct xlp9xx_i2c_dev *priv, static int xlp9xx_i2c_probe(struct platform_device *pdev) { struct xlp9xx_i2c_dev *priv; - struct resource *res; int err = 0; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->base = devm_ioremap_resource(&pdev->dev, res); + priv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); priv->irq = platform_get_irq(pdev, 0); - if (priv->irq <= 0) { - dev_err(&pdev->dev, "invalid irq!\n"); + if (priv->irq <= 0) return priv->irq; - } /* SMBAlert irq */ priv->alert_data.irq = platform_get_irq(pdev, 1); if (priv->alert_data.irq <= 0) diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c index 282f161a8b08..126d1393e548 100644 --- a/drivers/i2c/busses/i2c-xlr.c +++ b/drivers/i2c/busses/i2c-xlr.c @@ -362,7 +362,6 @@ static int xlr_i2c_probe(struct platform_device *pdev) { const struct of_device_id *match; struct xlr_i2c_private *priv; - struct resource *res; struct clk *clk; unsigned long clk_rate; unsigned long clk_div; @@ -380,8 +379,7 @@ static int xlr_i2c_probe(struct platform_device *pdev) else priv->cfg = &xlr_i2c_config_default; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->iobase = devm_ioremap_resource(&pdev->dev, res); + priv->iobase = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(priv->iobase)) return PTR_ERR(priv->iobase); diff --git a/drivers/i2c/busses/i2c-zx2967.c b/drivers/i2c/busses/i2c-zx2967.c index 5f3318559b8d..8db9519695a6 100644 --- a/drivers/i2c/busses/i2c-zx2967.c +++ b/drivers/i2c/busses/i2c-zx2967.c @@ -502,7 +502,6 @@ static int zx2967_i2c_probe(struct platform_device *pdev) { struct zx2967_i2c *i2c; void __iomem *reg_base; - struct resource *res; struct clk *clk; int ret; @@ -510,8 +509,7 @@ static int zx2967_i2c_probe(struct platform_device *pdev) if (!i2c) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - reg_base = devm_ioremap_resource(&pdev->dev, res); + reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 1f1442dfcad7..ac7edcc1d5ee 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -313,12 +313,14 @@ static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client) static int i2c_device_probe(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap; struct i2c_driver *driver; int status; if (!client) return 0; + adap = client->adapter; driver = to_i2c_driver(dev->driver); client->irq = client->init_irq; @@ -384,6 +386,12 @@ static int i2c_device_probe(struct device *dev) dev_dbg(dev, "probe\n"); + status = regulator_enable(adap->bus_regulator); + if (status < 0) { + dev_err(&adap->dev, "Failed to enable power regulator\n"); + goto err_clear_wakeup_irq; + } + status = of_clk_set_defaults(dev->of_node, false); if (status < 0) goto err_clear_wakeup_irq; @@ -424,12 +432,14 @@ put_sync_adapter: static int i2c_device_remove(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap; struct i2c_driver *driver; int status = 0; if (!client || !dev->driver) return 0; + adap = client->adapter; driver = to_i2c_driver(dev->driver); if (driver->remove) { dev_dbg(dev, "remove\n"); @@ -437,6 +447,8 @@ static int i2c_device_remove(struct device *dev) } dev_pm_domain_detach(&client->dev, true); + if (!pm_runtime_status_suspended(&client->dev)) + regulator_disable(adap->bus_regulator); dev_pm_clear_wake_irq(&client->dev); device_init_wakeup(&client->dev, false); @@ -448,6 +460,72 @@ static int i2c_device_remove(struct device *dev) return status; } +#ifdef CONFIG_PM_SLEEP +static int i2c_resume_early(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap = client->adapter; + int err; + + if (!pm_runtime_status_suspended(&client->dev)) { + err = regulator_enable(adap->bus_regulator); + if (err) + return err; + } + + return pm_generic_resume_early(&client->dev); +} + +static int i2c_suspend_late(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap = client->adapter; + int err; + + err = pm_generic_suspend_late(&client->dev); + if (err) + return err; + + if (!pm_runtime_status_suspended(&client->dev)) + return regulator_disable(adap->bus_regulator); + + return 0; +} +#endif + +#ifdef CONFIG_PM +static int i2c_runtime_resume(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap = client->adapter; + int err; + + err = regulator_enable(adap->bus_regulator); + if (err) + return err; + + return pm_generic_runtime_resume(&client->dev); +} + +static int i2c_runtime_suspend(struct device *dev) +{ + struct i2c_client *client = i2c_verify_client(dev); + struct i2c_adapter *adap = client->adapter; + int err; + + err = pm_generic_runtime_suspend(&client->dev); + if (err) + return err; + + return regulator_disable(adap->bus_regulator); +} +#endif + +static const struct dev_pm_ops i2c_device_pm = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_suspend_late, i2c_resume_early) + SET_RUNTIME_PM_OPS(i2c_runtime_suspend, i2c_runtime_resume, NULL) +}; + static void i2c_device_shutdown(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); @@ -505,6 +583,7 @@ struct bus_type i2c_bus_type = { .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, + .pm = &i2c_device_pm, }; EXPORT_SYMBOL_GPL(i2c_bus_type); @@ -1343,6 +1422,11 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (res) goto out_reg; + adap->bus_regulator = devm_regulator_get(&adap->dev, "bus"); + if (IS_ERR(adap->bus_regulator)) { + res = PTR_ERR(adap->bus_regulator); + goto out_reg; + } dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); pm_runtime_no_callbacks(&adap->dev); @@ -1598,6 +1682,18 @@ void i2c_del_adapter(struct i2c_adapter *adap) } EXPORT_SYMBOL(i2c_del_adapter); +static void i2c_parse_timing(struct device *dev, char *prop_name, u32 *cur_val_p, + u32 def_val, bool use_def) +{ + int ret; + + ret = device_property_read_u32(dev, prop_name, cur_val_p); + if (ret && use_def) + *cur_val_p = def_val; + + dev_dbg(dev, "%s: %u\n", prop_name, *cur_val_p); +} + /** * i2c_parse_fw_timings - get I2C related timing parameters from firmware * @dev: The device to scan for I2C timing properties @@ -1616,49 +1712,28 @@ EXPORT_SYMBOL(i2c_del_adapter); */ void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults) { - int ret; - - ret = device_property_read_u32(dev, "clock-frequency", &t->bus_freq_hz); - if (ret && use_defaults) - t->bus_freq_hz = I2C_MAX_STANDARD_MODE_FREQ; - - ret = device_property_read_u32(dev, "i2c-scl-rising-time-ns", &t->scl_rise_ns); - if (ret && use_defaults) { - if (t->bus_freq_hz <= I2C_MAX_STANDARD_MODE_FREQ) - t->scl_rise_ns = 1000; - else if (t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ) - t->scl_rise_ns = 300; - else - t->scl_rise_ns = 120; - } - - ret = device_property_read_u32(dev, "i2c-scl-falling-time-ns", &t->scl_fall_ns); - if (ret && use_defaults) { - if (t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ) - t->scl_fall_ns = 300; - else - t->scl_fall_ns = 120; - } - - ret = device_property_read_u32(dev, "i2c-scl-internal-delay-ns", &t->scl_int_delay_ns); - if (ret && use_defaults) - t->scl_int_delay_ns = 0; + bool u = use_defaults; + u32 d; - ret = device_property_read_u32(dev, "i2c-sda-falling-time-ns", &t->sda_fall_ns); - if (ret && use_defaults) - t->sda_fall_ns = t->scl_fall_ns; + i2c_parse_timing(dev, "clock-frequency", &t->bus_freq_hz, + I2C_MAX_STANDARD_MODE_FREQ, u); - ret = device_property_read_u32(dev, "i2c-sda-hold-time-ns", &t->sda_hold_ns); - if (ret && use_defaults) - t->sda_hold_ns = 0; + d = t->bus_freq_hz <= I2C_MAX_STANDARD_MODE_FREQ ? 1000 : + t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ ? 300 : 120; + i2c_parse_timing(dev, "i2c-scl-rising-time-ns", &t->scl_rise_ns, d, u); - ret = device_property_read_u32(dev, "i2c-digital-filter-width-ns", &t->digital_filter_width_ns); - if (ret && use_defaults) - t->digital_filter_width_ns = 0; + d = t->bus_freq_hz <= I2C_MAX_FAST_MODE_FREQ ? 300 : 120; + i2c_parse_timing(dev, "i2c-scl-falling-time-ns", &t->scl_fall_ns, d, u); - ret = device_property_read_u32(dev, "i2c-analog-filter-cutoff-frequency", &t->analog_filter_cutoff_freq_hz); - if (ret && use_defaults) - t->analog_filter_cutoff_freq_hz = 0; + i2c_parse_timing(dev, "i2c-scl-internal-delay-ns", + &t->scl_int_delay_ns, 0, u); + i2c_parse_timing(dev, "i2c-sda-falling-time-ns", &t->sda_fall_ns, + t->scl_fall_ns, u); + i2c_parse_timing(dev, "i2c-sda-hold-time-ns", &t->sda_hold_ns, 0, u); + i2c_parse_timing(dev, "i2c-digital-filter-width-ns", + &t->digital_filter_width_ns, 0, u); + i2c_parse_timing(dev, "i2c-analog-filter-cutoff-frequency", + &t->analog_filter_cutoff_freq_hz, 0, u); } EXPORT_SYMBOL_GPL(i2c_parse_fw_timings); diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 517d98be68d2..94ff1693b391 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -23,9 +23,9 @@ int i2c_dev_irq_from_resources(const struct resource *resources, unsigned int num_resources); /* - * We only allow atomic transfers for very late communication, e.g. to send - * the powerdown command to a PMIC. Atomic transfers are a corner case and not - * for generic use! + * We only allow atomic transfers for very late communication, e.g. to access a + * PMIC when powering down. Atomic transfers are a corner case and not for + * generic use! */ static inline bool i2c_in_atomic_xfer_mode(void) { diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c index cb415b10642f..787fdb7f332f 100644 --- a/drivers/i2c/i2c-slave-eeprom.c +++ b/drivers/i2c/i2c-slave-eeprom.c @@ -18,6 +18,7 @@ */ #include <linux/bitfield.h> +#include <linux/firmware.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/module.h> @@ -40,7 +41,7 @@ struct eeprom_data { #define I2C_SLAVE_BYTELEN GENMASK(15, 0) #define I2C_SLAVE_FLAG_ADDR16 BIT(16) #define I2C_SLAVE_FLAG_RO BIT(17) -#define I2C_SLAVE_DEVICE_MAGIC(_len, _flags) ((_flags) | (_len)) +#define I2C_SLAVE_DEVICE_MAGIC(_len, _flags) ((_flags) | ((_len) - 1)) static int i2c_slave_eeprom_slave_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val) @@ -120,11 +121,31 @@ static ssize_t i2c_slave_eeprom_bin_write(struct file *filp, struct kobject *kob return count; } +static int i2c_slave_init_eeprom_data(struct eeprom_data *eeprom, struct i2c_client *client, + unsigned int size) +{ + const struct firmware *fw; + const char *eeprom_data; + int ret = device_property_read_string(&client->dev, "firmware-name", &eeprom_data); + + if (!ret) { + ret = request_firmware_into_buf(&fw, eeprom_data, &client->dev, + eeprom->buffer, size); + if (ret) + return ret; + release_firmware(fw); + } else { + /* An empty eeprom typically has all bits set to 1 */ + memset(eeprom->buffer, 0xff, size); + } + return 0; +} + static int i2c_slave_eeprom_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct eeprom_data *eeprom; int ret; - unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data); + unsigned int size = FIELD_GET(I2C_SLAVE_BYTELEN, id->driver_data) + 1; unsigned int flag_addr16 = FIELD_GET(I2C_SLAVE_FLAG_ADDR16, id->driver_data); eeprom = devm_kzalloc(&client->dev, sizeof(struct eeprom_data) + size, GFP_KERNEL); @@ -138,6 +159,10 @@ static int i2c_slave_eeprom_probe(struct i2c_client *client, const struct i2c_de spin_lock_init(&eeprom->buffer_lock); i2c_set_clientdata(client, eeprom); + ret = i2c_slave_init_eeprom_data(eeprom, client, size); + if (ret) + return ret; + sysfs_bin_attr_init(&eeprom->bin); eeprom->bin.attr.name = "slave-eeprom"; eeprom->bin.attr.mode = S_IRUSR | S_IWUSR; @@ -175,6 +200,8 @@ static const struct i2c_device_id i2c_slave_eeprom_id[] = { { "slave-24c32ro", I2C_SLAVE_DEVICE_MAGIC(32768 / 8, I2C_SLAVE_FLAG_ADDR16 | I2C_SLAVE_FLAG_RO) }, { "slave-24c64", I2C_SLAVE_DEVICE_MAGIC(65536 / 8, I2C_SLAVE_FLAG_ADDR16) }, { "slave-24c64ro", I2C_SLAVE_DEVICE_MAGIC(65536 / 8, I2C_SLAVE_FLAG_ADDR16 | I2C_SLAVE_FLAG_RO) }, + { "slave-24c512", I2C_SLAVE_DEVICE_MAGIC(524288 / 8, I2C_SLAVE_FLAG_ADDR16) }, + { "slave-24c512ro", I2C_SLAVE_DEVICE_MAGIC(524288 / 8, I2C_SLAVE_FLAG_ADDR16 | I2C_SLAVE_FLAG_RO) }, { } }; MODULE_DEVICE_TABLE(i2c, i2c_slave_eeprom_id); diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index a0d926ae3f86..4ad665757dd8 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -1,10 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 /* * I2C multiplexer * * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> * - * This module supports the PCA954x and PCA954x series of I2C multiplexer/switch + * This module supports the PCA954x and PCA984x series of I2C multiplexer/switch * chips made by NXP Semiconductors. * This includes the: * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547, @@ -29,10 +30,6 @@ * i2c-virtual_cb.c from Brian Kuschak <bkuschak@yahoo.com> * and * pca9540.c from Jean Delvare <jdelvare@suse.de>. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. */ #include <linux/device.h> @@ -43,10 +40,8 @@ #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> #include <linux/pm.h> +#include <linux/property.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <dt-bindings/mux/mux.h> @@ -198,7 +193,6 @@ static const struct i2c_device_id pca954x_id[] = { }; MODULE_DEVICE_TABLE(i2c, pca954x_id); -#ifdef CONFIG_OF static const struct of_device_id pca954x_of_match[] = { { .compatible = "nxp,pca9540", .data = &chips[pca_9540] }, { .compatible = "nxp,pca9542", .data = &chips[pca_9542] }, @@ -215,7 +209,6 @@ static const struct of_device_id pca954x_of_match[] = { {} }; MODULE_DEVICE_TABLE(of, pca954x_of_match); -#endif /* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() for this as they will try to lock adapter a second time */ @@ -327,21 +320,18 @@ static DEVICE_ATTR_RW(idle_state); static irqreturn_t pca954x_irq_handler(int irq, void *dev_id) { struct pca954x *data = dev_id; - unsigned int child_irq; - int ret, i, handled = 0; + unsigned long pending; + int ret, i; ret = i2c_smbus_read_byte(data->client); if (ret < 0) return IRQ_NONE; - for (i = 0; i < data->chip->nchans; i++) { - if (ret & BIT(PCA954X_IRQ_OFFSET + i)) { - child_irq = irq_linear_revmap(data->irq, i); - handle_nested_irq(child_irq); - handled++; - } - } - return handled ? IRQ_HANDLED : IRQ_NONE; + pending = (ret >> PCA954X_IRQ_OFFSET) & (BIT(data->chip->nchans) - 1); + for_each_set_bit(i, &pending, data->chip->nchans) + handle_nested_irq(irq_linear_revmap(data->irq, i)); + + return IRQ_RETVAL(pending); } static int pca954x_irq_set_type(struct irq_data *idata, unsigned int type) @@ -390,11 +380,8 @@ static int pca954x_irq_setup(struct i2c_mux_core *muxc) static void pca954x_cleanup(struct i2c_mux_core *muxc) { struct pca954x *data = i2c_mux_priv(muxc); - struct i2c_client *client = data->client; int c, irq; - device_remove_file(&client->dev, &dev_attr_idle_state); - if (data->irq) { for (c = 0; c < data->chip->nchans; c++) { irq = irq_find_mapping(data->irq, c); @@ -429,7 +416,6 @@ static int pca954x_probe(struct i2c_client *client, { struct i2c_adapter *adap = client->adapter; struct device *dev = &client->dev; - struct device_node *np = dev->of_node; struct gpio_desc *gpio; struct i2c_mux_core *muxc; struct pca954x *data; @@ -459,7 +445,7 @@ static int pca954x_probe(struct i2c_client *client, udelay(1); } - data->chip = of_device_get_match_data(dev); + data->chip = device_get_match_data(dev); if (!data->chip) data->chip = &chips[id->driver_data]; @@ -481,8 +467,8 @@ static int pca954x_probe(struct i2c_client *client, } data->idle_state = MUX_IDLE_AS_IS; - if (of_property_read_u32(np, "idle-state", &data->idle_state)) { - if (np && of_property_read_bool(np, "i2c-mux-idle-disconnect")) + if (device_property_read_u32(dev, "idle-state", &data->idle_state)) { + if (device_property_read_bool(dev, "i2c-mux-idle-disconnect")) data->idle_state = MUX_IDLE_DISCONNECT; } @@ -539,6 +525,8 @@ static int pca954x_remove(struct i2c_client *client) { struct i2c_mux_core *muxc = i2c_get_clientdata(client); + device_remove_file(&client->dev, &dev_attr_idle_state); + pca954x_cleanup(muxc); return 0; } @@ -565,7 +553,7 @@ static struct i2c_driver pca954x_driver = { .driver = { .name = "pca954x", .pm = &pca954x_pm, - .of_match_table = of_match_ptr(pca954x_of_match), + .of_match_table = pca954x_of_match, }, .probe = pca954x_probe, .remove = pca954x_remove, diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c index 77be37a1fbcf..ed48917af162 100644 --- a/drivers/platform/mellanox/mlxreg-hotplug.c +++ b/drivers/platform/mellanox/mlxreg-hotplug.c @@ -101,6 +101,7 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, struct mlxreg_core_data *data) { struct mlxreg_core_hotplug_platform_data *pdata; + struct i2c_client *client; /* Notify user by sending hwmon uevent. */ kobject_uevent(&priv->hwmon->kobj, KOBJ_CHANGE); @@ -121,18 +122,20 @@ static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv, return -EFAULT; } - data->hpdev.client = i2c_new_device(data->hpdev.adapter, - data->hpdev.brdinfo); - if (!data->hpdev.client) { + client = i2c_new_client_device(data->hpdev.adapter, + data->hpdev.brdinfo); + if (IS_ERR(client)) { dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n", data->hpdev.brdinfo->type, data->hpdev.nr + pdata->shift_nr, data->hpdev.brdinfo->addr); i2c_put_adapter(data->hpdev.adapter); data->hpdev.adapter = NULL; - return -EFAULT; + return PTR_ERR(client); } + data->hpdev.client = client; + return 0; } |