diff options
Diffstat (limited to 'drivers/i2c')
100 files changed, 8489 insertions, 2101 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index fad22b0bb5b..65ef9664d5d 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -20,12 +20,11 @@ * ------------------------------------------------------------------------- */ /* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki - <kmalkki@cc.hut.fi> and Jean Delvare <khali@linux-fr.org> */ + <kmalkki@cc.hut.fi> and Jean Delvare <jdelvare@suse.de> */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/i2c.h> diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c index f892a424009..8b10f88b13d 100644 --- a/drivers/i2c/algos/i2c-algo-pca.c +++ b/drivers/i2c/algos/i2c-algo-pca.c @@ -24,7 +24,6 @@ #include <linux/moduleparam.h> #include <linux/delay.h> #include <linux/jiffies.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/i2c.h> #include <linux/i2c-algo-pca.h> diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c index 5c2379522aa..34370090b75 100644 --- a/drivers/i2c/algos/i2c-algo-pcf.c +++ b/drivers/i2c/algos/i2c-algo-pcf.c @@ -30,7 +30,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/i2c.h> #include <linux/i2c-algo-pcf.h> diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index cdcbd8368ed..9f7d5859cf6 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -109,6 +109,8 @@ config I2C_I801 Avoton (SOC) Wellsburg (PCH) Coleto Creek (PCH) + Wildcat Point-LP (PCH) + BayTrail (SOC) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -151,6 +153,7 @@ config I2C_PIIX4 ATI SB700/SP5100 ATI SB800 AMD Hudson-2 + AMD ML AMD CZ Serverworks OSB4 Serverworks CSB5 @@ -345,6 +348,16 @@ config I2C_BCM2835 This support is also available as a module. If so, the module will be called i2c-bcm2835. +config I2C_BCM_KONA + tristate "BCM Kona I2C adapter" + depends on ARCH_BCM_MOBILE + default y + help + If you say yes to this option, support will be included for the + I2C interface on the Broadcom Kona family of processors. + + If you do not need KONA I2C inteface, say N. + config I2C_BLACKFIN_TWI tristate "Blackfin TWI I2C support" depends on BLACKFIN @@ -363,6 +376,13 @@ config I2C_BLACKFIN_TWI_CLK_KHZ help The unit of the TWI clock is kHz. +config I2C_CADENCE + tristate "Cadence I2C Controller" + depends on ARCH_ZYNQ + help + Say yes here to select Cadence I2C Host Controller. This controller is + e.g. used by Xilinx Zynq. + config I2C_CBUS_GPIO tristate "CBUS I2C driver" depends on GPIOLIB @@ -375,7 +395,7 @@ config I2C_CBUS_GPIO config I2C_CPM tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" - depends on (CPM1 || CPM2) && OF_I2C + depends on CPM1 || CPM2 help This supports the use of the I2C interface on Freescale processors with CPM1 or CPM2. @@ -401,7 +421,6 @@ config I2C_DESIGNWARE_CORE config I2C_DESIGNWARE_PLATFORM tristate "Synopsys DesignWare Platform" - depends on HAVE_CLK select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the @@ -421,9 +440,16 @@ config I2C_DESIGNWARE_PCI This driver can also be built as a module. If so, the module will be called i2c-designware-pci. +config I2C_EFM32 + tristate "EFM32 I2C controller" + depends on ARCH_EFM32 || COMPILE_TEST + help + This driver supports the i2c block found in Energy Micro's EFM32 + SoCs. + config I2C_EG20T tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C" - depends on PCI + depends on PCI && (X86_32 || COMPILE_TEST) help This driver is for PCH(Platform controller Hub) I2C of EG20T which is an IOH(Input/Output Hub) for x86 embedded processor. @@ -436,6 +462,13 @@ config I2C_EG20T ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. +config I2C_EXYNOS5 + tristate "Exynos5 high-speed I2C driver" + depends on ARCH_EXYNOS5 && OF + help + Say Y here to include support for high-speed I2C controller in the + Exynos5 based Samsung SoCs. + config I2C_GPIO tristate "GPIO-based bitbanging I2C" depends on GPIOLIB @@ -509,7 +542,7 @@ config I2C_MPC config I2C_MV64XXX tristate "Marvell mv64xxx I2C Controller" - depends on (MV64X60 || PLAT_ORION || ARCH_SUNXI) + depends on MV64X60 || PLAT_ORION || ARCH_SUNXI help If you say yes to this option, support will be included for the built-in I2C interface on the Marvell 64xxx line of host bridges. @@ -537,13 +570,6 @@ config I2C_NOMADIK I2C interface from ST-Ericsson's Nomadik and Ux500 architectures, as well as the STA2X11 PCIe I/O HUB. -config I2C_NUC900 - tristate "NUC900 I2C Driver" - depends on ARCH_W90X900 - help - Say Y here to include support for I2C controller in the - Winbond/Nuvoton NUC900 based System-on-Chip devices. - config I2C_OCORES tristate "OpenCores I2C Controller" help @@ -630,6 +656,36 @@ config I2C_PXA_SLAVE is necessary for systems where the PXA may be a target on the I2C bus. +config I2C_QUP + tristate "Qualcomm QUP based I2C controller" + depends on ARCH_QCOM + help + If you say yes to this option, support will be included for the + built-in I2C interface on the Qualcomm SoCs. + + This driver can also be built as a module. If so, the module + will be called i2c-qup. + +config I2C_RIIC + tristate "Renesas RIIC adapter" + depends on ARCH_SHMOBILE || COMPILE_TEST + help + If you say yes to this option, support will be included for the + Renesas RIIC I2C interface. + + This driver can also be built as a module. If so, the module + will be called i2c-riic. + +config I2C_RK3X + tristate "Rockchip RK3xxx I2C adapter" + depends on OF + help + Say Y here to include support for the I2C adapter in Rockchip RK3xxx + SoCs. + + This driver can also be built as a module. If so, the module will + be called i2c-rk3x. + config HAVE_S3C2410_I2C bool help @@ -665,7 +721,7 @@ config I2C_SH7760 config I2C_SH_MOBILE tristate "SuperH Mobile I2C Controller" - depends on SUPERH || ARCH_SHMOBILE + depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST help If you say yes to this option, support will be included for the built-in I2C interface on the Renesas SH-Mobile processor. @@ -695,6 +751,16 @@ config I2C_SIRF This driver can also be built as a module. If so, the module will be called i2c-sirf. +config I2C_ST + tristate "STMicroelectronics SSC I2C support" + depends on ARCH_STI + help + Enable this option to add support for STMicroelectronics SoCs + hardware SSC (Synchronous Serial Controller) as an I2C controller. + + This driver can also be built as module. If so, the module + will be called i2c-st. + config I2C_STU300 tristate "ST Microelectronics DDC I2C interface" depends on MACH_U300 @@ -708,6 +774,19 @@ config I2C_STU300 This driver can also be built as a module. If so, the module will be called i2c-stu300. +config I2C_SUN6I_P2WI + tristate "Allwinner sun6i internal P2WI controller" + depends on RESET_CONTROLLER + depends on MACH_SUN6I || COMPILE_TEST + help + If you say yes to this option, support will be included for the + P2WI (Push/Pull 2 Wire Interface) controller embedded in some sunxi + SOCs. + The P2WI looks like an SMBus controller (which supports only byte + accesses), except that it only supports one slave device. + This interface is used to connect to specific PMIC devices (like the + AXP221). + config I2C_TEGRA tristate "NVIDIA Tegra internal I2C controller" depends on ARCH_TEGRA @@ -768,7 +847,7 @@ config I2C_XLR config I2C_RCAR tristate "Renesas R-Car I2C Controller" - depends on ARCH_SHMOBILE && I2C + depends on ARCH_SHMOBILE || COMPILE_TEST help If you say yes to this option, support will be included for the R-Car I2C controller. @@ -837,6 +916,16 @@ config I2C_PARPORT_LIGHT This support is also available as a module. If so, the module will be called i2c-parport-light. +config I2C_ROBOTFUZZ_OSIF + tristate "RobotFuzz Open Source InterFace USB adapter" + depends on USB + help + If you say yes to this option, support will be included for the + RobotFuzz Open Source InterFace USB to I2C interface. + + This driver can also be built as a module. If so, the module + will be called i2c-osif. + config I2C_TAOS_EVM tristate "TAOS evaluation module" depends on TTY @@ -888,7 +977,7 @@ config I2C_ACORN config I2C_ELEKTOR tristate "Elektor ISA card" - depends on ISA && HAS_IOPORT && BROKEN_ON_SMP + depends on ISA && HAS_IOPORT_MAP && BROKEN_ON_SMP select I2C_ALGOPCF help This supports the PCF8584 ISA bus I2C adapter. Say Y if you own @@ -920,6 +1009,15 @@ config I2C_SIBYTE help Supports the SiByte SOC on-chip I2C interfaces (2 channels). +config I2C_CROS_EC_TUNNEL + tristate "ChromeOS EC tunnel I2C bus" + depends on MFD_CROS_EC + help + If you say yes here you get an I2C bus that will tunnel i2c commands + through to the other side of the ChromeOS EC to the i2c bus + connected there. This will work whatever the interface used to + talk to the EC (SPI, I2C or LPC). + config SCx200_I2C tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)" depends on SCx200_GPIO diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index d00997f3eb3..dd9a7f8e873 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -33,6 +33,7 @@ obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o +obj-$(CONFIG_I2C_CADENCE) += i2c-cadence.o obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o @@ -41,7 +42,9 @@ obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o i2c-designware-platform-objs := i2c-designware-platdrv.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o i2c-designware-pci-objs := i2c-designware-pcidrv.o +obj-$(CONFIG_I2C_EFM32) += i2c-efm32.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o +obj-$(CONFIG_I2C_EXYNOS5) += i2c-exynos5.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o @@ -52,7 +55,6 @@ obj-$(CONFIG_I2C_MPC) += i2c-mpc.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_MXS) += i2c-mxs.o obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o -obj-$(CONFIG_I2C_NUC900) += i2c-nuc900.o obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o @@ -62,13 +64,18 @@ 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_QUP) += i2c-qup.o +obj-$(CONFIG_I2C_RIIC) += i2c-riic.o +obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_S6000) += i2c-s6000.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o +obj-$(CONFIG_I2C_ST) += i2c-st.o obj-$(CONFIG_I2C_STU300) += i2c-stu300.o +obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_WMT) += i2c-wmt.o @@ -81,12 +88,15 @@ obj-$(CONFIG_I2C_RCAR) += i2c-rcar.o obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o +obj-$(CONFIG_I2C_ROBOTFUZZ_OSIF) += i2c-robotfuzz-osif.o obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o obj-$(CONFIG_I2C_VIPERBOARD) += i2c-viperboard.o # Other I2C/SMBus bus drivers obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o +obj-$(CONFIG_I2C_BCM_KONA) += i2c-bcm-kona.o +obj-$(CONFIG_I2C_CROS_EC_TUNNEL) += i2c-cros-ec-tunnel.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c index ed9f48d566d..9d7be5af2bf 100644 --- a/drivers/i2c/busses/i2c-acorn.c +++ b/drivers/i2c/busses/i2c-acorn.c @@ -12,7 +12,7 @@ * On Acorn machines, the following i2c devices are on the bus: * - PCF8583 real time clock & static RAM */ -#include <linux/init.h> +#include <linux/module.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/io.h> diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c index 3f491815e2c..451e305f797 100644 --- a/drivers/i2c/busses/i2c-ali1535.c +++ b/drivers/i2c/busses/i2c-ali1535.c @@ -58,7 +58,6 @@ #include <linux/delay.h> #include <linux/ioport.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/acpi.h> #include <linux/io.h> @@ -495,7 +494,7 @@ static struct i2c_adapter ali1535_adapter = { .algo = &smbus_algorithm, }; -static DEFINE_PCI_DEVICE_TABLE(ali1535_ids) = { +static const struct pci_device_id ali1535_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { }, }; diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index 84ccd9496a5..15517d78d5f 100644 --- a/drivers/i2c/busses/i2c-ali1563.c +++ b/drivers/i2c/busses/i2c-ali1563.c @@ -20,7 +20,6 @@ #include <linux/delay.h> #include <linux/i2c.h> #include <linux/pci.h> -#include <linux/init.h> #include <linux/acpi.h> #define ALI1563_MAX_TIMEOUT 500 @@ -64,7 +63,7 @@ static struct pci_driver ali1563_pci_driver; static unsigned short ali1563_smba; -static int ali1563_transaction(struct i2c_adapter * a, int size) +static int ali1563_transaction(struct i2c_adapter *a, int size) { u32 data; int timeout; @@ -79,7 +78,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) data = inb_p(SMB_HST_STS); if (data & HST_STS_BAD) { dev_err(&a->dev, "ali1563: Trying to reset busy device\n"); - outb_p(data | HST_STS_BAD,SMB_HST_STS); + outb_p(data | HST_STS_BAD, SMB_HST_STS); data = inb_p(SMB_HST_STS); if (data & HST_STS_BAD) return -EBUSY; @@ -103,10 +102,10 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) if (!timeout) { dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n"); /* Issue 'kill' to host controller */ - outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); + outb_p(HST_CNTL2_KILL, SMB_HST_CNTL2); data = inb_p(SMB_HST_STS); status = -ETIMEDOUT; - } + } /* device error - no response, ignore the autodetection case */ if (data & HST_STS_DEVERR) { @@ -118,18 +117,18 @@ static int ali1563_transaction(struct i2c_adapter * a, int size) if (data & HST_STS_BUSERR) { dev_err(&a->dev, "Bus collision!\n"); /* Issue timeout, hoping it helps */ - outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1); + outb_p(HST_CNTL1_TIMEOUT, SMB_HST_CNTL1); } if (data & HST_STS_FAIL) { dev_err(&a->dev, "Cleaning fail after KILL!\n"); - outb_p(0x0,SMB_HST_CNTL2); + outb_p(0x0, SMB_HST_CNTL2); } return status; } -static int ali1563_block_start(struct i2c_adapter * a) +static int ali1563_block_start(struct i2c_adapter *a) { u32 data; int timeout; @@ -143,8 +142,8 @@ static int ali1563_block_start(struct i2c_adapter * a) data = inb_p(SMB_HST_STS); if (data & HST_STS_BAD) { - dev_warn(&a->dev,"ali1563: Trying to reset busy device\n"); - outb_p(data | HST_STS_BAD,SMB_HST_STS); + dev_warn(&a->dev, "ali1563: Trying to reset busy device\n"); + outb_p(data | HST_STS_BAD, SMB_HST_STS); data = inb_p(SMB_HST_STS); if (data & HST_STS_BAD) return -EBUSY; @@ -185,13 +184,14 @@ static int ali1563_block_start(struct i2c_adapter * a) return status; } -static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) +static int ali1563_block(struct i2c_adapter *a, + union i2c_smbus_data *data, u8 rw) { int i, len; int error = 0; /* Do we need this? */ - outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); + outb_p(HST_CNTL1_LAST, SMB_HST_CNTL1); if (rw == I2C_SMBUS_WRITE) { len = data->block[0]; @@ -199,8 +199,8 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 len = 1; else if (len > 32) len = 32; - outb_p(len,SMB_HST_DAT0); - outb_p(data->block[1],SMB_BLK_DAT); + outb_p(len, SMB_HST_DAT0); + outb_p(data->block[1], SMB_BLK_DAT); } else len = 32; @@ -209,10 +209,12 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 for (i = 0; i < len; i++) { if (rw == I2C_SMBUS_WRITE) { outb_p(data->block[i + 1], SMB_BLK_DAT); - if ((error = ali1563_block_start(a))) + error = ali1563_block_start(a); + if (error) break; } else { - if ((error = ali1563_block_start(a))) + error = ali1563_block_start(a); + if (error) break; if (i == 0) { len = inb_p(SMB_HST_DAT0); @@ -225,25 +227,26 @@ static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 } } /* Do we need this? */ - outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); + outb_p(HST_CNTL1_LAST, SMB_HST_CNTL1); return error; } -static s32 ali1563_access(struct i2c_adapter * a, u16 addr, +static s32 ali1563_access(struct i2c_adapter *a, u16 addr, unsigned short flags, char rw, u8 cmd, - int size, union i2c_smbus_data * data) + int size, union i2c_smbus_data *data) { int error = 0; int timeout; u32 reg; for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) { - if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY)) + reg = inb_p(SMB_HST_STS); + if (!(reg & HST_STS_BUSY)) break; } if (!timeout) - dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg); - outb_p(0xff,SMB_HST_STS); + dev_warn(&a->dev, "SMBus not idle. HST_STS = %02x\n", reg); + outb_p(0xff, SMB_HST_STS); /* Map the size to what the chip understands */ switch (size) { @@ -269,13 +272,14 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, } outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); - outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2); + outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | + (size << 3), SMB_HST_CNTL2); /* Write the command register */ - switch(size) { + switch (size) { case HST_CNTL2_BYTE: - if (rw== I2C_SMBUS_WRITE) + if (rw == I2C_SMBUS_WRITE) /* Beware it uses DAT0 register and not CMD! */ outb_p(cmd, SMB_HST_DAT0); break; @@ -293,11 +297,12 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr, break; case HST_CNTL2_BLOCK: outb_p(cmd, SMB_HST_CMD); - error = ali1563_block(a,data,rw); + error = ali1563_block(a, data, rw); goto Done; } - if ((error = ali1563_transaction(a, size))) + error = ali1563_transaction(a, size); + if (error) goto Done; if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK)) @@ -318,7 +323,7 @@ Done: return error; } -static u32 ali1563_func(struct i2c_adapter * a) +static u32 ali1563_func(struct i2c_adapter *a) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | @@ -330,13 +335,13 @@ static int ali1563_setup(struct pci_dev *dev) { u16 ctrl; - pci_read_config_word(dev,ALI1563_SMBBA,&ctrl); + pci_read_config_word(dev, ALI1563_SMBBA, &ctrl); /* SMB I/O Base in high 12 bits and must be aligned with the * size of the I/O space. */ ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1); if (!ali1563_smba) { - dev_warn(&dev->dev,"ali1563_smba Uninitialized\n"); + dev_warn(&dev->dev, "ali1563_smba Uninitialized\n"); goto Err; } @@ -351,8 +356,8 @@ static int ali1563_setup(struct pci_dev *dev) ctrl | ALI1563_SMB_IOEN); pci_read_config_word(dev, ALI1563_SMBBA, &ctrl); if (!(ctrl & ALI1563_SMB_IOEN)) { - dev_err(&dev->dev, "I/O space still not enabled, " - "giving up\n"); + dev_err(&dev->dev, + "I/O space still not enabled, giving up\n"); goto Err; } } @@ -376,7 +381,7 @@ Err: static void ali1563_shutdown(struct pci_dev *dev) { - release_region(ali1563_smba,ALI1563_SMB_IOSIZE); + release_region(ali1563_smba, ALI1563_SMB_IOSIZE); } static const struct i2c_algorithm ali1563_algorithm = { @@ -395,12 +400,14 @@ static int ali1563_probe(struct pci_dev *dev, { int error; - if ((error = ali1563_setup(dev))) + error = ali1563_setup(dev); + if (error) goto exit; ali1563_adapter.dev.parent = &dev->dev; snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name), "SMBus ALi 1563 Adapter @ %04x", ali1563_smba); - if ((error = i2c_add_adapter(&ali1563_adapter))) + error = i2c_add_adapter(&ali1563_adapter); + if (error) goto exit_shutdown; return 0; @@ -417,17 +424,17 @@ static void ali1563_remove(struct pci_dev *dev) ali1563_shutdown(dev); } -static DEFINE_PCI_DEVICE_TABLE(ali1563_id_table) = { +static const struct pci_device_id ali1563_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) }, {}, }; -MODULE_DEVICE_TABLE (pci, ali1563_id_table); +MODULE_DEVICE_TABLE(pci, ali1563_id_table); static struct pci_driver ali1563_pci_driver = { - .name = "ali1563_smbus", + .name = "ali1563_smbus", .id_table = ali1563_id_table, - .probe = ali1563_probe, + .probe = ali1563_probe, .remove = ali1563_remove, }; diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 26bcc6127ce..2fa21ce9682 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -65,7 +65,6 @@ #include <linux/ioport.h> #include <linux/delay.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/acpi.h> #include <linux/io.h> @@ -477,7 +476,7 @@ static struct i2c_adapter ali15x3_adapter = { .algo = &smbus_algorithm, }; -static DEFINE_PCI_DEVICE_TABLE(ali15x3_ids) = { +static const struct pci_device_id ali15x3_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c index 07f01ac853f..41fc6837fb8 100644 --- a/drivers/i2c/busses/i2c-amd756-s4882.c +++ b/drivers/i2c/busses/i2c-amd756-s4882.c @@ -1,7 +1,7 @@ /* * i2c-amd756-s4882.c - i2c-amd756 extras for the Tyan S4882 motherboard * - * Copyright (C) 2004, 2008 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2004, 2008 Jean Delvare <jdelvare@suse.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -250,7 +250,7 @@ static void __exit amd756_s4882_exit(void) "Physical bus restoration failed\n"); } -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("S4882 SMBus multiplexing"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index e13e2aa2d05..a16f7289135 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -41,7 +41,6 @@ #include <linux/stddef.h> #include <linux/ioport.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/acpi.h> #include <linux/io.h> @@ -308,7 +307,7 @@ static const char* chipname[] = { "nVidia nForce", "AMD8111", }; -static DEFINE_PCI_DEVICE_TABLE(amd756_ids) = { +static const struct pci_device_id amd756_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B), .driver_data = AMD756 }, { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413), diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index a44e6e77c5a..95a80a8f81b 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -13,7 +13,6 @@ #include <linux/kernel.h> #include <linux/stddef.h> #include <linux/ioport.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> #include <linux/acpi.h> @@ -415,7 +414,7 @@ static const struct i2c_algorithm smbus_algorithm = { }; -static DEFINE_PCI_DEVICE_TABLE(amd8111_ids) = { +static const struct pci_device_id amd8111_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index fd059308aff..e95f9ba9679 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -32,7 +32,7 @@ #include <linux/slab.h> #include <linux/platform_data/dma-atmel.h> -#define TWI_CLK_HZ 100000 /* max 400 Kbits/s */ +#define DEFAULT_TWI_CLK_HZ 100000 /* max 400 Kbits/s */ #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ #define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */ @@ -371,7 +371,7 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) dev_dbg(dev->dev, "transfer: %s %d bytes.\n", (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len); - INIT_COMPLETION(dev->cmd_complete); + reinit_completion(&dev->cmd_complete); dev->transfer_status = 0; if (!dev->buf_len) { @@ -589,6 +589,9 @@ static const struct of_device_id atmel_twi_dt_ids[] = { .compatible = "atmel,at91sam9260-i2c", .data = &at91sam9260_config, } , { + .compatible = "atmel,at91sam9261-i2c", + .data = &at91sam9261_config, + } , { .compatible = "atmel,at91sam9g20-i2c", .data = &at91sam9g20_config, } , { @@ -708,6 +711,7 @@ static int at91_twi_probe(struct platform_device *pdev) struct resource *mem; int rc; u32 phy_addr; + u32 bus_clk_rate; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); if (!dev) @@ -753,13 +757,18 @@ static int at91_twi_probe(struct platform_device *pdev) dev->use_dma = true; } - at91_calc_twi_clock(dev, TWI_CLK_HZ); + rc = of_property_read_u32(dev->dev->of_node, "clock-frequency", + &bus_clk_rate); + if (rc) + bus_clk_rate = DEFAULT_TWI_CLK_HZ; + + at91_calc_twi_clock(dev, bus_clk_rate); at91_init_twi_bus(dev); snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91"); i2c_set_adapdata(&dev->adapter, dev); dev->adapter.owner = THIS_MODULE; - dev->adapter.class = I2C_CLASS_HWMON; + dev->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED; dev->adapter.algo = &at91_twi_algorithm; dev->adapter.dev.parent = dev->dev; dev->adapter.nr = pdev->id; diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c index b5b89239d62..8762458ca7d 100644 --- a/drivers/i2c/busses/i2c-au1550.c +++ b/drivers/i2c/busses/i2c-au1550.c @@ -31,7 +31,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/i2c.h> #include <linux/slab.h> diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c new file mode 100644 index 00000000000..18a74a6751a --- /dev/null +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -0,0 +1,908 @@ +/* + * Copyright (C) 2013 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/slab.h> + +/* Hardware register offsets and field defintions */ +#define CS_OFFSET 0x00000020 +#define CS_ACK_SHIFT 3 +#define CS_ACK_MASK 0x00000008 +#define CS_ACK_CMD_GEN_START 0x00000000 +#define CS_ACK_CMD_GEN_RESTART 0x00000001 +#define CS_CMD_SHIFT 1 +#define CS_CMD_CMD_NO_ACTION 0x00000000 +#define CS_CMD_CMD_START_RESTART 0x00000001 +#define CS_CMD_CMD_STOP 0x00000002 +#define CS_EN_SHIFT 0 +#define CS_EN_CMD_ENABLE_BSC 0x00000001 + +#define TIM_OFFSET 0x00000024 +#define TIM_PRESCALE_SHIFT 6 +#define TIM_P_SHIFT 3 +#define TIM_NO_DIV_SHIFT 2 +#define TIM_DIV_SHIFT 0 + +#define DAT_OFFSET 0x00000028 + +#define TOUT_OFFSET 0x0000002c + +#define TXFCR_OFFSET 0x0000003c +#define TXFCR_FIFO_FLUSH_MASK 0x00000080 +#define TXFCR_FIFO_EN_MASK 0x00000040 + +#define IER_OFFSET 0x00000044 +#define IER_READ_COMPLETE_INT_MASK 0x00000010 +#define IER_I2C_INT_EN_MASK 0x00000008 +#define IER_FIFO_INT_EN_MASK 0x00000002 +#define IER_NOACK_EN_MASK 0x00000001 + +#define ISR_OFFSET 0x00000048 +#define ISR_RESERVED_MASK 0xffffff60 +#define ISR_CMDBUSY_MASK 0x00000080 +#define ISR_READ_COMPLETE_MASK 0x00000010 +#define ISR_SES_DONE_MASK 0x00000008 +#define ISR_ERR_MASK 0x00000004 +#define ISR_TXFIFOEMPTY_MASK 0x00000002 +#define ISR_NOACK_MASK 0x00000001 + +#define CLKEN_OFFSET 0x0000004C +#define CLKEN_AUTOSENSE_OFF_MASK 0x00000080 +#define CLKEN_M_SHIFT 4 +#define CLKEN_N_SHIFT 1 +#define CLKEN_CLKEN_MASK 0x00000001 + +#define FIFO_STATUS_OFFSET 0x00000054 +#define FIFO_STATUS_RXFIFO_EMPTY_MASK 0x00000004 +#define FIFO_STATUS_TXFIFO_EMPTY_MASK 0x00000010 + +#define HSTIM_OFFSET 0x00000058 +#define HSTIM_HS_MODE_MASK 0x00008000 +#define HSTIM_HS_HOLD_SHIFT 10 +#define HSTIM_HS_HIGH_PHASE_SHIFT 5 +#define HSTIM_HS_SETUP_SHIFT 0 + +#define PADCTL_OFFSET 0x0000005c +#define PADCTL_PAD_OUT_EN_MASK 0x00000004 + +#define RXFCR_OFFSET 0x00000068 +#define RXFCR_NACK_EN_SHIFT 7 +#define RXFCR_READ_COUNT_SHIFT 0 +#define RXFIFORDOUT_OFFSET 0x0000006c + +/* Locally used constants */ +#define MAX_RX_FIFO_SIZE 64U /* bytes */ +#define MAX_TX_FIFO_SIZE 64U /* bytes */ + +#define STD_EXT_CLK_FREQ 13000000UL +#define HS_EXT_CLK_FREQ 104000000UL + +#define MASTERCODE 0x08 /* Mastercodes are 0000_1xxxb */ + +#define I2C_TIMEOUT 100 /* msecs */ + +/* Operations that can be commanded to the controller */ +enum bcm_kona_cmd_t { + BCM_CMD_NOACTION = 0, + BCM_CMD_START, + BCM_CMD_RESTART, + BCM_CMD_STOP, +}; + +enum bus_speed_index { + BCM_SPD_100K = 0, + BCM_SPD_400K, + BCM_SPD_1MHZ, +}; + +enum hs_bus_speed_index { + BCM_SPD_3P4MHZ = 0, +}; + +/* Internal divider settings for standard mode, fast mode and fast mode plus */ +struct bus_speed_cfg { + uint8_t time_m; /* Number of cycles for setup time */ + uint8_t time_n; /* Number of cycles for hold time */ + uint8_t prescale; /* Prescale divider */ + uint8_t time_p; /* Timing coefficient */ + uint8_t no_div; /* Disable clock divider */ + uint8_t time_div; /* Post-prescale divider */ +}; + +/* Internal divider settings for high-speed mode */ +struct hs_bus_speed_cfg { + uint8_t hs_hold; /* Number of clock cycles SCL stays low until + the end of bit period */ + uint8_t hs_high_phase; /* Number of clock cycles SCL stays high + before it falls */ + uint8_t hs_setup; /* Number of clock cycles SCL stays low + before it rises */ + uint8_t prescale; /* Prescale divider */ + uint8_t time_p; /* Timing coefficient */ + uint8_t no_div; /* Disable clock divider */ + uint8_t time_div; /* Post-prescale divider */ +}; + +static const struct bus_speed_cfg std_cfg_table[] = { + [BCM_SPD_100K] = {0x01, 0x01, 0x03, 0x06, 0x00, 0x02}, + [BCM_SPD_400K] = {0x05, 0x01, 0x03, 0x05, 0x01, 0x02}, + [BCM_SPD_1MHZ] = {0x01, 0x01, 0x03, 0x01, 0x01, 0x03}, +}; + +static const struct hs_bus_speed_cfg hs_cfg_table[] = { + [BCM_SPD_3P4MHZ] = {0x01, 0x08, 0x14, 0x00, 0x06, 0x01, 0x00}, +}; + +struct bcm_kona_i2c_dev { + struct device *device; + + void __iomem *base; + int irq; + struct clk *external_clk; + + struct i2c_adapter adapter; + + struct completion done; + + const struct bus_speed_cfg *std_cfg; + const struct hs_bus_speed_cfg *hs_cfg; +}; + +static void bcm_kona_i2c_send_cmd_to_ctrl(struct bcm_kona_i2c_dev *dev, + enum bcm_kona_cmd_t cmd) +{ + dev_dbg(dev->device, "%s, %d\n", __func__, cmd); + + switch (cmd) { + case BCM_CMD_NOACTION: + writel((CS_CMD_CMD_NO_ACTION << CS_CMD_SHIFT) | + (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT), + dev->base + CS_OFFSET); + break; + + case BCM_CMD_START: + writel((CS_ACK_CMD_GEN_START << CS_ACK_SHIFT) | + (CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) | + (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT), + dev->base + CS_OFFSET); + break; + + case BCM_CMD_RESTART: + writel((CS_ACK_CMD_GEN_RESTART << CS_ACK_SHIFT) | + (CS_CMD_CMD_START_RESTART << CS_CMD_SHIFT) | + (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT), + dev->base + CS_OFFSET); + break; + + case BCM_CMD_STOP: + writel((CS_CMD_CMD_STOP << CS_CMD_SHIFT) | + (CS_EN_CMD_ENABLE_BSC << CS_EN_SHIFT), + dev->base + CS_OFFSET); + break; + + default: + dev_err(dev->device, "Unknown command %d\n", cmd); + } +} + +static void bcm_kona_i2c_enable_clock(struct bcm_kona_i2c_dev *dev) +{ + writel(readl(dev->base + CLKEN_OFFSET) | CLKEN_CLKEN_MASK, + dev->base + CLKEN_OFFSET); +} + +static void bcm_kona_i2c_disable_clock(struct bcm_kona_i2c_dev *dev) +{ + writel(readl(dev->base + CLKEN_OFFSET) & ~CLKEN_CLKEN_MASK, + dev->base + CLKEN_OFFSET); +} + +static irqreturn_t bcm_kona_i2c_isr(int irq, void *devid) +{ + struct bcm_kona_i2c_dev *dev = devid; + uint32_t status = readl(dev->base + ISR_OFFSET); + + if ((status & ~ISR_RESERVED_MASK) == 0) + return IRQ_NONE; + + /* Must flush the TX FIFO when NAK detected */ + if (status & ISR_NOACK_MASK) + writel(TXFCR_FIFO_FLUSH_MASK | TXFCR_FIFO_EN_MASK, + dev->base + TXFCR_OFFSET); + + writel(status & ~ISR_RESERVED_MASK, dev->base + ISR_OFFSET); + complete_all(&dev->done); + + return IRQ_HANDLED; +} + +/* Wait for ISR_CMDBUSY_MASK to go low before writing to CS, DAT, or RCD */ +static int bcm_kona_i2c_wait_if_busy(struct bcm_kona_i2c_dev *dev) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(I2C_TIMEOUT); + + while (readl(dev->base + ISR_OFFSET) & ISR_CMDBUSY_MASK) + if (time_after(jiffies, timeout)) { + dev_err(dev->device, "CMDBUSY timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +/* Send command to I2C bus */ +static int bcm_kona_send_i2c_cmd(struct bcm_kona_i2c_dev *dev, + enum bcm_kona_cmd_t cmd) +{ + int rc; + unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT); + + /* Make sure the hardware is ready */ + rc = bcm_kona_i2c_wait_if_busy(dev); + if (rc < 0) + return rc; + + /* Unmask the session done interrupt */ + writel(IER_I2C_INT_EN_MASK, dev->base + IER_OFFSET); + + /* Mark as incomplete before sending the command */ + reinit_completion(&dev->done); + + /* Send the command */ + bcm_kona_i2c_send_cmd_to_ctrl(dev, cmd); + + /* Wait for transaction to finish or timeout */ + time_left = wait_for_completion_timeout(&dev->done, time_left); + + /* Mask all interrupts */ + writel(0, dev->base + IER_OFFSET); + + if (!time_left) { + dev_err(dev->device, "controller timed out\n"); + rc = -ETIMEDOUT; + } + + /* Clear command */ + bcm_kona_i2c_send_cmd_to_ctrl(dev, BCM_CMD_NOACTION); + + return rc; +} + +/* Read a single RX FIFO worth of data from the i2c bus */ +static int bcm_kona_i2c_read_fifo_single(struct bcm_kona_i2c_dev *dev, + uint8_t *buf, unsigned int len, + unsigned int last_byte_nak) +{ + unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT); + + /* Mark as incomplete before starting the RX FIFO */ + reinit_completion(&dev->done); + + /* Unmask the read complete interrupt */ + writel(IER_READ_COMPLETE_INT_MASK, dev->base + IER_OFFSET); + + /* Start the RX FIFO */ + writel((last_byte_nak << RXFCR_NACK_EN_SHIFT) | + (len << RXFCR_READ_COUNT_SHIFT), + dev->base + RXFCR_OFFSET); + + /* Wait for FIFO read to complete */ + time_left = wait_for_completion_timeout(&dev->done, time_left); + + /* Mask all interrupts */ + writel(0, dev->base + IER_OFFSET); + + if (!time_left) { + dev_err(dev->device, "RX FIFO time out\n"); + return -EREMOTEIO; + } + + /* Read data from FIFO */ + for (; len > 0; len--, buf++) + *buf = readl(dev->base + RXFIFORDOUT_OFFSET); + + return 0; +} + +/* Read any amount of data using the RX FIFO from the i2c bus */ +static int bcm_kona_i2c_read_fifo(struct bcm_kona_i2c_dev *dev, + struct i2c_msg *msg) +{ + unsigned int bytes_to_read = MAX_RX_FIFO_SIZE; + unsigned int last_byte_nak = 0; + unsigned int bytes_read = 0; + int rc; + + uint8_t *tmp_buf = msg->buf; + + while (bytes_read < msg->len) { + if (msg->len - bytes_read <= MAX_RX_FIFO_SIZE) { + last_byte_nak = 1; /* NAK last byte of transfer */ + bytes_to_read = msg->len - bytes_read; + } + + rc = bcm_kona_i2c_read_fifo_single(dev, tmp_buf, bytes_to_read, + last_byte_nak); + if (rc < 0) + return -EREMOTEIO; + + bytes_read += bytes_to_read; + tmp_buf += bytes_to_read; + } + + return 0; +} + +/* Write a single byte of data to the i2c bus */ +static int bcm_kona_i2c_write_byte(struct bcm_kona_i2c_dev *dev, uint8_t data, + unsigned int nak_expected) +{ + int rc; + unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT); + unsigned int nak_received; + + /* Make sure the hardware is ready */ + rc = bcm_kona_i2c_wait_if_busy(dev); + if (rc < 0) + return rc; + + /* Clear pending session done interrupt */ + writel(ISR_SES_DONE_MASK, dev->base + ISR_OFFSET); + + /* Unmask the session done interrupt */ + writel(IER_I2C_INT_EN_MASK, dev->base + IER_OFFSET); + + /* Mark as incomplete before sending the data */ + reinit_completion(&dev->done); + + /* Send one byte of data */ + writel(data, dev->base + DAT_OFFSET); + + /* Wait for byte to be written */ + time_left = wait_for_completion_timeout(&dev->done, time_left); + + /* Mask all interrupts */ + writel(0, dev->base + IER_OFFSET); + + if (!time_left) { + dev_dbg(dev->device, "controller timed out\n"); + return -ETIMEDOUT; + } + + nak_received = readl(dev->base + CS_OFFSET) & CS_ACK_MASK ? 1 : 0; + + if (nak_received ^ nak_expected) { + dev_dbg(dev->device, "unexpected NAK/ACK\n"); + return -EREMOTEIO; + } + + return 0; +} + +/* Write a single TX FIFO worth of data to the i2c bus */ +static int bcm_kona_i2c_write_fifo_single(struct bcm_kona_i2c_dev *dev, + uint8_t *buf, unsigned int len) +{ + int k; + unsigned long time_left = msecs_to_jiffies(I2C_TIMEOUT); + unsigned int fifo_status; + + /* Mark as incomplete before sending data to the TX FIFO */ + reinit_completion(&dev->done); + + /* Unmask the fifo empty and nak interrupt */ + writel(IER_FIFO_INT_EN_MASK | IER_NOACK_EN_MASK, + dev->base + IER_OFFSET); + + /* Disable IRQ to load a FIFO worth of data without interruption */ + disable_irq(dev->irq); + + /* Write data into FIFO */ + for (k = 0; k < len; k++) + writel(buf[k], (dev->base + DAT_OFFSET)); + + /* Enable IRQ now that data has been loaded */ + enable_irq(dev->irq); + + /* Wait for FIFO to empty */ + do { + time_left = wait_for_completion_timeout(&dev->done, time_left); + fifo_status = readl(dev->base + FIFO_STATUS_OFFSET); + } while (time_left && !(fifo_status & FIFO_STATUS_TXFIFO_EMPTY_MASK)); + + /* Mask all interrupts */ + writel(0, dev->base + IER_OFFSET); + + /* Check if there was a NAK */ + if (readl(dev->base + CS_OFFSET) & CS_ACK_MASK) { + dev_err(dev->device, "unexpected NAK\n"); + return -EREMOTEIO; + } + + /* Check if a timeout occured */ + if (!time_left) { + dev_err(dev->device, "completion timed out\n"); + return -EREMOTEIO; + } + + return 0; +} + + +/* Write any amount of data using TX FIFO to the i2c bus */ +static int bcm_kona_i2c_write_fifo(struct bcm_kona_i2c_dev *dev, + struct i2c_msg *msg) +{ + unsigned int bytes_to_write = MAX_TX_FIFO_SIZE; + unsigned int bytes_written = 0; + int rc; + + uint8_t *tmp_buf = msg->buf; + + while (bytes_written < msg->len) { + if (msg->len - bytes_written <= MAX_TX_FIFO_SIZE) + bytes_to_write = msg->len - bytes_written; + + rc = bcm_kona_i2c_write_fifo_single(dev, tmp_buf, + bytes_to_write); + if (rc < 0) + return -EREMOTEIO; + + bytes_written += bytes_to_write; + tmp_buf += bytes_to_write; + } + + return 0; +} + +/* Send i2c address */ +static int bcm_kona_i2c_do_addr(struct bcm_kona_i2c_dev *dev, + struct i2c_msg *msg) +{ + unsigned char addr; + + if (msg->flags & I2C_M_TEN) { + /* First byte is 11110XX0 where XX is upper 2 bits */ + addr = 0xF0 | ((msg->addr & 0x300) >> 7); + if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) + return -EREMOTEIO; + + /* Second byte is the remaining 8 bits */ + addr = msg->addr & 0xFF; + if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) + return -EREMOTEIO; + + if (msg->flags & I2C_M_RD) { + /* For read, send restart command */ + if (bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART) < 0) + return -EREMOTEIO; + + /* Then re-send the first byte with the read bit set */ + addr = 0xF0 | ((msg->addr & 0x300) >> 7) | 0x01; + if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) + return -EREMOTEIO; + } + } else { + addr = msg->addr << 1; + + if (msg->flags & I2C_M_RD) + addr |= 1; + + if (bcm_kona_i2c_write_byte(dev, addr, 0) < 0) + return -EREMOTEIO; + } + + return 0; +} + +static void bcm_kona_i2c_enable_autosense(struct bcm_kona_i2c_dev *dev) +{ + writel(readl(dev->base + CLKEN_OFFSET) & ~CLKEN_AUTOSENSE_OFF_MASK, + dev->base + CLKEN_OFFSET); +} + +static void bcm_kona_i2c_config_timing(struct bcm_kona_i2c_dev *dev) +{ + writel(readl(dev->base + HSTIM_OFFSET) & ~HSTIM_HS_MODE_MASK, + dev->base + HSTIM_OFFSET); + + writel((dev->std_cfg->prescale << TIM_PRESCALE_SHIFT) | + (dev->std_cfg->time_p << TIM_P_SHIFT) | + (dev->std_cfg->no_div << TIM_NO_DIV_SHIFT) | + (dev->std_cfg->time_div << TIM_DIV_SHIFT), + dev->base + TIM_OFFSET); + + writel((dev->std_cfg->time_m << CLKEN_M_SHIFT) | + (dev->std_cfg->time_n << CLKEN_N_SHIFT) | + CLKEN_CLKEN_MASK, + dev->base + CLKEN_OFFSET); +} + +static void bcm_kona_i2c_config_timing_hs(struct bcm_kona_i2c_dev *dev) +{ + writel((dev->hs_cfg->prescale << TIM_PRESCALE_SHIFT) | + (dev->hs_cfg->time_p << TIM_P_SHIFT) | + (dev->hs_cfg->no_div << TIM_NO_DIV_SHIFT) | + (dev->hs_cfg->time_div << TIM_DIV_SHIFT), + dev->base + TIM_OFFSET); + + writel((dev->hs_cfg->hs_hold << HSTIM_HS_HOLD_SHIFT) | + (dev->hs_cfg->hs_high_phase << HSTIM_HS_HIGH_PHASE_SHIFT) | + (dev->hs_cfg->hs_setup << HSTIM_HS_SETUP_SHIFT), + dev->base + HSTIM_OFFSET); + + writel(readl(dev->base + HSTIM_OFFSET) | HSTIM_HS_MODE_MASK, + dev->base + HSTIM_OFFSET); +} + +static int bcm_kona_i2c_switch_to_hs(struct bcm_kona_i2c_dev *dev) +{ + int rc; + + /* Send mastercode at standard speed */ + rc = bcm_kona_i2c_write_byte(dev, MASTERCODE, 1); + if (rc < 0) { + pr_err("High speed handshake failed\n"); + return rc; + } + + /* Configure external clock to higher frequency */ + rc = clk_set_rate(dev->external_clk, HS_EXT_CLK_FREQ); + if (rc) { + dev_err(dev->device, "%s: clk_set_rate returned %d\n", + __func__, rc); + return rc; + } + + /* Reconfigure internal dividers */ + bcm_kona_i2c_config_timing_hs(dev); + + /* Send a restart command */ + rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART); + if (rc < 0) + dev_err(dev->device, "High speed restart command failed\n"); + + return rc; +} + +static int bcm_kona_i2c_switch_to_std(struct bcm_kona_i2c_dev *dev) +{ + int rc; + + /* Reconfigure internal dividers */ + bcm_kona_i2c_config_timing(dev); + + /* Configure external clock to lower frequency */ + rc = clk_set_rate(dev->external_clk, STD_EXT_CLK_FREQ); + if (rc) { + dev_err(dev->device, "%s: clk_set_rate returned %d\n", + __func__, rc); + } + + return rc; +} + +/* Master transfer function */ +static int bcm_kona_i2c_xfer(struct i2c_adapter *adapter, + struct i2c_msg msgs[], int num) +{ + struct bcm_kona_i2c_dev *dev = i2c_get_adapdata(adapter); + struct i2c_msg *pmsg; + int rc = 0; + int i; + + rc = clk_prepare_enable(dev->external_clk); + if (rc) { + dev_err(dev->device, "%s: peri clock enable failed. err %d\n", + __func__, rc); + return rc; + } + + /* Enable pad output */ + writel(0, dev->base + PADCTL_OFFSET); + + /* Enable internal clocks */ + bcm_kona_i2c_enable_clock(dev); + + /* Send start command */ + rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_START); + if (rc < 0) { + dev_err(dev->device, "Start command failed rc = %d\n", rc); + goto xfer_disable_pad; + } + + /* Switch to high speed if applicable */ + if (dev->hs_cfg) { + rc = bcm_kona_i2c_switch_to_hs(dev); + if (rc < 0) + goto xfer_send_stop; + } + + /* Loop through all messages */ + for (i = 0; i < num; i++) { + pmsg = &msgs[i]; + + /* Send restart for subsequent messages */ + if ((i != 0) && ((pmsg->flags & I2C_M_NOSTART) == 0)) { + rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART); + if (rc < 0) { + dev_err(dev->device, + "restart cmd failed rc = %d\n", rc); + goto xfer_send_stop; + } + } + + /* Send slave address */ + if (!(pmsg->flags & I2C_M_NOSTART)) { + rc = bcm_kona_i2c_do_addr(dev, pmsg); + if (rc < 0) { + dev_err(dev->device, + "NAK from addr %2.2x msg#%d rc = %d\n", + pmsg->addr, i, rc); + goto xfer_send_stop; + } + } + + /* Perform data transfer */ + if (pmsg->flags & I2C_M_RD) { + rc = bcm_kona_i2c_read_fifo(dev, pmsg); + if (rc < 0) { + dev_err(dev->device, "read failure\n"); + goto xfer_send_stop; + } + } else { + rc = bcm_kona_i2c_write_fifo(dev, pmsg); + if (rc < 0) { + dev_err(dev->device, "write failure"); + goto xfer_send_stop; + } + } + } + + rc = num; + +xfer_send_stop: + /* Send a STOP command */ + bcm_kona_send_i2c_cmd(dev, BCM_CMD_STOP); + + /* Return from high speed if applicable */ + if (dev->hs_cfg) { + int hs_rc = bcm_kona_i2c_switch_to_std(dev); + + if (hs_rc) + rc = hs_rc; + } + +xfer_disable_pad: + /* Disable pad output */ + writel(PADCTL_PAD_OUT_EN_MASK, dev->base + PADCTL_OFFSET); + + /* Stop internal clock */ + bcm_kona_i2c_disable_clock(dev); + + clk_disable_unprepare(dev->external_clk); + + return rc; +} + +static uint32_t bcm_kona_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_NOSTART; +} + +static const struct i2c_algorithm bcm_algo = { + .master_xfer = bcm_kona_i2c_xfer, + .functionality = bcm_kona_i2c_functionality, +}; + +static int bcm_kona_i2c_assign_bus_speed(struct bcm_kona_i2c_dev *dev) +{ + unsigned int bus_speed; + int ret = of_property_read_u32(dev->device->of_node, "clock-frequency", + &bus_speed); + if (ret < 0) { + dev_err(dev->device, "missing clock-frequency property\n"); + return -ENODEV; + } + + switch (bus_speed) { + case 100000: + dev->std_cfg = &std_cfg_table[BCM_SPD_100K]; + break; + case 400000: + dev->std_cfg = &std_cfg_table[BCM_SPD_400K]; + break; + case 1000000: + dev->std_cfg = &std_cfg_table[BCM_SPD_1MHZ]; + break; + case 3400000: + /* Send mastercode at 100k */ + dev->std_cfg = &std_cfg_table[BCM_SPD_100K]; + dev->hs_cfg = &hs_cfg_table[BCM_SPD_3P4MHZ]; + break; + default: + pr_err("%d hz bus speed not supported\n", bus_speed); + pr_err("Valid speeds are 100khz, 400khz, 1mhz, and 3.4mhz\n"); + return -EINVAL; + } + + return 0; +} + +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); + if (!dev) + return -ENOMEM; + + platform_set_drvdata(pdev, dev); + dev->device = &pdev->dev; + init_completion(&dev->done); + + /* Map hardware registers */ + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dev->base = devm_ioremap_resource(dev->device, iomem); + if (IS_ERR(dev->base)) + return -ENOMEM; + + /* Get and enable external clock */ + dev->external_clk = devm_clk_get(dev->device, NULL); + if (IS_ERR(dev->external_clk)) { + dev_err(dev->device, "couldn't get clock\n"); + return -ENODEV; + } + + rc = clk_set_rate(dev->external_clk, STD_EXT_CLK_FREQ); + if (rc) { + dev_err(dev->device, "%s: clk_set_rate returned %d\n", + __func__, rc); + return rc; + } + + rc = clk_prepare_enable(dev->external_clk); + if (rc) { + dev_err(dev->device, "couldn't enable clock\n"); + return rc; + } + + /* Parse bus speed */ + rc = bcm_kona_i2c_assign_bus_speed(dev); + if (rc) + goto probe_disable_clk; + + /* Enable internal clocks */ + bcm_kona_i2c_enable_clock(dev); + + /* Configure internal dividers */ + bcm_kona_i2c_config_timing(dev); + + /* Disable timeout */ + writel(0, dev->base + TOUT_OFFSET); + + /* Enable autosense */ + bcm_kona_i2c_enable_autosense(dev); + + /* Enable TX FIFO */ + writel(TXFCR_FIFO_FLUSH_MASK | TXFCR_FIFO_EN_MASK, + dev->base + TXFCR_OFFSET); + + /* Mask all interrupts */ + writel(0, dev->base + IER_OFFSET); + + /* Clear all pending interrupts */ + writel(ISR_CMDBUSY_MASK | + ISR_READ_COMPLETE_MASK | + ISR_SES_DONE_MASK | + ISR_ERR_MASK | + ISR_TXFIFOEMPTY_MASK | + ISR_NOACK_MASK, + dev->base + ISR_OFFSET); + + /* 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; + goto probe_disable_clk; + } + + /* register the ISR handler */ + rc = devm_request_irq(&pdev->dev, dev->irq, bcm_kona_i2c_isr, + IRQF_SHARED, pdev->name, dev); + if (rc) { + dev_err(dev->device, "failed to request irq %i\n", dev->irq); + goto probe_disable_clk; + } + + /* Enable the controller but leave it idle */ + bcm_kona_i2c_send_cmd_to_ctrl(dev, BCM_CMD_NOACTION); + + /* Disable pad output */ + writel(PADCTL_PAD_OUT_EN_MASK, dev->base + PADCTL_OFFSET); + + /* Disable internal clock */ + bcm_kona_i2c_disable_clock(dev); + + /* Disable external clock */ + clk_disable_unprepare(dev->external_clk); + + /* Add the i2c adapter */ + adap = &dev->adapter; + i2c_set_adapdata(adap, dev); + adap->owner = THIS_MODULE; + strlcpy(adap->name, "Broadcom I2C adapter", sizeof(adap->name)); + adap->algo = &bcm_algo; + adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; + + rc = i2c_add_adapter(adap); + if (rc) { + dev_err(dev->device, "failed to add adapter\n"); + return rc; + } + + dev_info(dev->device, "device registered successfully\n"); + + return 0; + +probe_disable_clk: + bcm_kona_i2c_disable_clock(dev); + clk_disable_unprepare(dev->external_clk); + + return rc; +} + +static int bcm_kona_i2c_remove(struct platform_device *pdev) +{ + struct bcm_kona_i2c_dev *dev = platform_get_drvdata(pdev); + + i2c_del_adapter(&dev->adapter); + + return 0; +} + +static const struct of_device_id bcm_kona_i2c_of_match[] = { + {.compatible = "brcm,kona-i2c",}, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm_kona_i2c_of_match); + +static struct platform_driver bcm_kona_i2c_driver = { + .driver = { + .name = "bcm-kona-i2c", + .owner = THIS_MODULE, + .of_match_table = bcm_kona_i2c_of_match, + }, + .probe = bcm_kona_i2c_probe, + .remove = bcm_kona_i2c_remove, +}; +module_platform_driver(bcm_kona_i2c_driver); + +MODULE_AUTHOR("Tim Kryger <tkryger@broadcom.com>"); +MODULE_DESCRIPTION("Broadcom Kona I2C Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c index ea4b08fc335..214ff9700ef 100644 --- a/drivers/i2c/busses/i2c-bcm2835.c +++ b/drivers/i2c/busses/i2c-bcm2835.c @@ -151,7 +151,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev, i2c_dev->msg_buf = msg->buf; i2c_dev->msg_buf_remaining = msg->len; - INIT_COMPLETION(i2c_dev->completion); + reinit_completion(&i2c_dev->completion); bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR); @@ -219,40 +219,22 @@ static const struct i2c_algorithm bcm2835_i2c_algo = { static int bcm2835_i2c_probe(struct platform_device *pdev) { struct bcm2835_i2c_dev *i2c_dev; - struct resource *mem, *requested, *irq; + struct resource *mem, *irq; u32 bus_clk_rate, divider; int ret; struct i2c_adapter *adap; i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); - if (!i2c_dev) { - dev_err(&pdev->dev, "Cannot allocate i2c_dev\n"); + if (!i2c_dev) return -ENOMEM; - } platform_set_drvdata(pdev, i2c_dev); i2c_dev->dev = &pdev->dev; init_completion(&i2c_dev->completion); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "No mem resource\n"); - return -ENODEV; - } - - requested = devm_request_mem_region(&pdev->dev, mem->start, - resource_size(mem), - dev_name(&pdev->dev)); - if (!requested) { - dev_err(&pdev->dev, "Could not claim register region\n"); - return -EBUSY; - } - - i2c_dev->regs = devm_ioremap(&pdev->dev, mem->start, - resource_size(mem)); - if (!i2c_dev->regs) { - dev_err(&pdev->dev, "Could not map registers\n"); - return -ENOMEM; - } + i2c_dev->regs = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(i2c_dev->regs)) + return PTR_ERR(i2c_dev->regs); i2c_dev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2c_dev->clk)) { @@ -295,10 +277,11 @@ static int bcm2835_i2c_probe(struct platform_device *pdev) adap = &i2c_dev->adapter; i2c_set_adapdata(adap, i2c_dev); adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED; strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name)); adap->algo = &bcm2835_i2c_algo; adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0); diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index 35a473ba3d8..3e271e7558d 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -21,10 +21,10 @@ #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/delay.h> +#include <linux/i2c/bfin_twi.h> -#include <asm/blackfin.h> -#include <asm/portmux.h> #include <asm/irq.h> +#include <asm/portmux.h> #include <asm/bfin_twi.h> /* SMBus mode*/ @@ -65,7 +65,6 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, /* Transmit next data */ while (iface->writeNum > 0 && (read_FIFO_STAT(iface) & XMTSTAT) != XMT_FULL) { - SSYNC(); write_XMT_DATA8(iface, *(iface->transPtr++)); iface->writeNum--; } @@ -248,7 +247,6 @@ static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) /* Clear interrupt status */ write_INT_STAT(iface, twi_int_status); bfin_twi_handle_interrupt(iface, twi_int_status); - SSYNC(); } spin_unlock_irqrestore(&iface->lock, flags); return IRQ_HANDLED; @@ -294,9 +292,7 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, * discarded before start a new operation. */ write_FIFO_CTL(iface, 0x3); - SSYNC(); write_FIFO_CTL(iface, 0); - SSYNC(); if (pmsg->flags & I2C_M_RD) iface->read_write = I2C_SMBUS_READ; @@ -306,7 +302,6 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, if (iface->writeNum > 0) { write_XMT_DATA8(iface, *(iface->transPtr++)); iface->writeNum--; - SSYNC(); } } @@ -315,7 +310,6 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, /* Interrupt mask . Enable XMT, RCV interrupt */ write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV); - SSYNC(); if (pmsg->len <= 255) write_MASTER_CTL(iface, pmsg->len << 6); @@ -329,7 +323,6 @@ static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, (iface->msg_num > 1 ? RSTART : 0) | ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); - SSYNC(); while (!iface->result) { if (!wait_for_completion_timeout(&iface->complete, @@ -453,7 +446,6 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, * start a new operation. */ write_FIFO_CTL(iface, 0x3); - SSYNC(); write_FIFO_CTL(iface, 0); /* clear int stat */ @@ -461,7 +453,6 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, /* Set Transmit device address */ write_MASTER_ADDR(iface, addr); - SSYNC(); switch (iface->cur_mode) { case TWI_I2C_MODE_STANDARDSUB: @@ -469,7 +460,6 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, write_INT_MASK(iface, MCOMP | MERR | ((iface->read_write == I2C_SMBUS_READ) ? RCVSERV : XMTSERV)); - SSYNC(); if (iface->writeNum + 1 <= 255) write_MASTER_CTL(iface, (iface->writeNum + 1) << 6); @@ -484,7 +474,6 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, case TWI_I2C_MODE_COMBINED: write_XMT_DATA8(iface, iface->command); write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV); - SSYNC(); if (iface->writeNum > 0) write_MASTER_CTL(iface, (iface->writeNum + 1) << 6); @@ -531,7 +520,6 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, write_INT_MASK(iface, MCOMP | MERR | ((iface->read_write == I2C_SMBUS_READ) ? RCVSERV : XMTSERV)); - SSYNC(); /* Master enable */ write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | @@ -539,7 +527,6 @@ int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); break; } - SSYNC(); while (!iface->result) { if (!wait_for_completion_timeout(&iface->complete, @@ -633,35 +620,27 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) int rc; unsigned int clkhilow; - iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL); + iface = devm_kzalloc(&pdev->dev, sizeof(struct bfin_twi_iface), + GFP_KERNEL); if (!iface) { dev_err(&pdev->dev, "Cannot allocate memory\n"); - rc = -ENOMEM; - goto out_error_nomem; + return -ENOMEM; } spin_lock_init(&(iface->lock)); /* Find and map our resources */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); - rc = -ENOENT; - goto out_error_get_res; - } - - iface->regs_base = ioremap(res->start, resource_size(res)); - if (iface->regs_base == NULL) { + iface->regs_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(iface->regs_base)) { dev_err(&pdev->dev, "Cannot map IO\n"); - rc = -ENXIO; - goto out_error_ioremap; + return PTR_ERR(iface->regs_base); } iface->irq = platform_get_irq(pdev, 0); if (iface->irq < 0) { dev_err(&pdev->dev, "No IRQ specified\n"); - rc = -ENOENT; - goto out_error_no_irq; + return -ENOENT; } p_adap = &iface->adap; @@ -669,25 +648,25 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); p_adap->algo = &bfin_twi_algorithm; p_adap->algo_data = iface; - p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED; p_adap->dev.parent = &pdev->dev; p_adap->timeout = 5 * HZ; p_adap->retries = 3; rc = peripheral_request_list( - (unsigned short *)dev_get_platdata(&pdev->dev), + dev_get_platdata(&pdev->dev), "i2c-bfin-twi"); if (rc) { dev_err(&pdev->dev, "Can't setup pin mux!\n"); - goto out_error_pin_mux; + return -EBUSY; } - rc = request_irq(iface->irq, bfin_twi_interrupt_entry, + rc = devm_request_irq(&pdev->dev, iface->irq, bfin_twi_interrupt_entry, 0, pdev->name, iface); if (rc) { dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); rc = -ENODEV; - goto out_error_req_irq; + goto out_error; } /* Set TWI internal clock as 10MHz */ @@ -704,12 +683,11 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) /* Enable TWI */ write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); - SSYNC(); rc = i2c_add_numbered_adapter(p_adap); if (rc < 0) { dev_err(&pdev->dev, "Can't add i2c adapter!\n"); - goto out_error_add_adapter; + goto out_error; } platform_set_drvdata(pdev, iface); @@ -719,17 +697,8 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) return 0; -out_error_add_adapter: - free_irq(iface->irq, iface); -out_error_req_irq: -out_error_no_irq: - peripheral_free_list((unsigned short *)dev_get_platdata(&pdev->dev)); -out_error_pin_mux: - iounmap(iface->regs_base); -out_error_ioremap: -out_error_get_res: - kfree(iface); -out_error_nomem: +out_error: + peripheral_free_list(dev_get_platdata(&pdev->dev)); return rc; } @@ -738,10 +707,7 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev) struct bfin_twi_iface *iface = platform_get_drvdata(pdev); i2c_del_adapter(&(iface->adap)); - free_irq(iface->irq, iface); - peripheral_free_list((unsigned short *)dev_get_platdata(&pdev->dev)); - iounmap(iface->regs_base); - kfree(iface); + peripheral_free_list(dev_get_platdata(&pdev->dev)); return 0; } diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c new file mode 100644 index 00000000000..63f3f03ecc9 --- /dev/null +++ b/drivers/i2c/busses/i2c-cadence.c @@ -0,0 +1,905 @@ +/* + * I2C bus driver for the Cadence I2C controller. + * + * Copyright (C) 2009 - 2014 Xilinx, Inc. + * + * This program is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any + * later version. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +/* Register offsets for the I2C device. */ +#define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */ +#define CDNS_I2C_SR_OFFSET 0x04 /* Status Register, RO */ +#define CDNS_I2C_ADDR_OFFSET 0x08 /* I2C Address Register, RW */ +#define CDNS_I2C_DATA_OFFSET 0x0C /* I2C Data Register, RW */ +#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_IER_OFFSET 0x24 /* IRQ Enable Register, WO */ +#define CDNS_I2C_IDR_OFFSET 0x28 /* IRQ Disable Register, WO */ + +/* Control Register Bit mask definitions */ +#define CDNS_I2C_CR_HOLD BIT(4) /* Hold Bus bit */ +#define CDNS_I2C_CR_ACK_EN BIT(3) +#define CDNS_I2C_CR_NEA BIT(2) +#define CDNS_I2C_CR_MS BIT(1) +/* Read or Write Master transfer 0 = Transmitter, 1 = Receiver */ +#define CDNS_I2C_CR_RW BIT(0) +/* 1 = Auto init FIFO to zeroes */ +#define CDNS_I2C_CR_CLR_FIFO BIT(6) +#define CDNS_I2C_CR_DIVA_SHIFT 14 +#define CDNS_I2C_CR_DIVA_MASK (3 << CDNS_I2C_CR_DIVA_SHIFT) +#define CDNS_I2C_CR_DIVB_SHIFT 8 +#define CDNS_I2C_CR_DIVB_MASK (0x3f << CDNS_I2C_CR_DIVB_SHIFT) + +/* Status Register Bit mask definitions */ +#define CDNS_I2C_SR_BA BIT(8) +#define CDNS_I2C_SR_RXDV BIT(5) + +/* + * I2C Address Register Bit mask definitions + * Normal addressing mode uses [6:0] bits. Extended addressing mode uses [9:0] + * bits. A write access to this register always initiates a transfer if the I2C + * is in master mode. + */ +#define CDNS_I2C_ADDR_MASK 0x000003FF /* I2C Address Mask */ + +/* + * I2C Interrupt Registers Bit mask definitions + * All the four interrupt registers (Status/Mask/Enable/Disable) have the same + * bit definitions. + */ +#define CDNS_I2C_IXR_ARB_LOST BIT(9) +#define CDNS_I2C_IXR_RX_UNF BIT(7) +#define CDNS_I2C_IXR_TX_OVF BIT(6) +#define CDNS_I2C_IXR_RX_OVF BIT(5) +#define CDNS_I2C_IXR_SLV_RDY BIT(4) +#define CDNS_I2C_IXR_TO BIT(3) +#define CDNS_I2C_IXR_NACK BIT(2) +#define CDNS_I2C_IXR_DATA BIT(1) +#define CDNS_I2C_IXR_COMP BIT(0) + +#define CDNS_I2C_IXR_ALL_INTR_MASK (CDNS_I2C_IXR_ARB_LOST | \ + CDNS_I2C_IXR_RX_UNF | \ + CDNS_I2C_IXR_TX_OVF | \ + CDNS_I2C_IXR_RX_OVF | \ + CDNS_I2C_IXR_SLV_RDY | \ + CDNS_I2C_IXR_TO | \ + CDNS_I2C_IXR_NACK | \ + CDNS_I2C_IXR_DATA | \ + CDNS_I2C_IXR_COMP) + +#define CDNS_I2C_IXR_ERR_INTR_MASK (CDNS_I2C_IXR_ARB_LOST | \ + CDNS_I2C_IXR_RX_UNF | \ + CDNS_I2C_IXR_TX_OVF | \ + CDNS_I2C_IXR_RX_OVF | \ + CDNS_I2C_IXR_NACK) + +#define CDNS_I2C_ENABLED_INTR_MASK (CDNS_I2C_IXR_ARB_LOST | \ + CDNS_I2C_IXR_RX_UNF | \ + CDNS_I2C_IXR_TX_OVF | \ + CDNS_I2C_IXR_RX_OVF | \ + CDNS_I2C_IXR_NACK | \ + CDNS_I2C_IXR_DATA | \ + CDNS_I2C_IXR_COMP) + +#define CDNS_I2C_TIMEOUT msecs_to_jiffies(1000) + +#define CDNS_I2C_FIFO_DEPTH 16 +/* FIFO depth at which the DATA interrupt occurs */ +#define CDNS_I2C_DATA_INTR_DEPTH (CDNS_I2C_FIFO_DEPTH - 2) +#define CDNS_I2C_MAX_TRANSFER_SIZE 255 +/* Transfer size in multiples of data interrupt depth */ +#define CDNS_I2C_TRANSFER_SIZE (CDNS_I2C_MAX_TRANSFER_SIZE - 3) + +#define DRIVER_NAME "cdns-i2c" + +#define CDNS_I2C_SPEED_MAX 400000 +#define CDNS_I2C_SPEED_DEFAULT 100000 + +#define CDNS_I2C_DIVA_MAX 4 +#define CDNS_I2C_DIVB_MAX 64 + +#define cdns_i2c_readreg(offset) readl_relaxed(id->membase + offset) +#define cdns_i2c_writereg(val, offset) writel_relaxed(val, id->membase + offset) + +/** + * struct cdns_i2c - I2C device private data structure + * @membase: Base address of the I2C device + * @adap: I2C adapter instance + * @p_msg: Message pointer + * @err_status: Error status in Interrupt Status Register + * @xfer_done: Transfer complete status + * @p_send_buf: Pointer to transmit buffer + * @p_recv_buf: Pointer to receive buffer + * @suspended: Flag holding the device's PM status + * @send_count: Number of bytes still expected to send + * @recv_count: Number of bytes still expected to receive + * @irq: IRQ number + * @input_clk: Input clock to I2C controller + * @i2c_clk: Maximum I2C clock speed + * @bus_hold_flag: Flag used in repeated start for clearing HOLD bit + * @clk: Pointer to struct clk + * @clk_rate_change_nb: Notifier block for clock rate changes + */ +struct cdns_i2c { + void __iomem *membase; + struct i2c_adapter adap; + struct i2c_msg *p_msg; + int err_status; + struct completion xfer_done; + unsigned char *p_send_buf; + unsigned char *p_recv_buf; + u8 suspended; + unsigned int send_count; + unsigned int recv_count; + int irq; + unsigned long input_clk; + unsigned int i2c_clk; + unsigned int bus_hold_flag; + struct clk *clk; + struct notifier_block clk_rate_change_nb; +}; + +#define to_cdns_i2c(_nb) container_of(_nb, struct cdns_i2c, \ + clk_rate_change_nb) + +/** + * cdns_i2c_clear_bus_hold() - Clear bus hold bit + * @id: Pointer to driver data struct + * + * Helper to clear the controller's bus hold bit. + */ +static void cdns_i2c_clear_bus_hold(struct cdns_i2c *id) +{ + u32 reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + if (reg & CDNS_I2C_CR_HOLD) + cdns_i2c_writereg(reg & ~CDNS_I2C_CR_HOLD, CDNS_I2C_CR_OFFSET); +} + +/** + * 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 handles the data interrupt, transfer complete interrupt and + * the error interrupts of the I2C device. + * + * Return: IRQ_HANDLED always + */ +static irqreturn_t cdns_i2c_isr(int irq, void *ptr) +{ + unsigned int isr_status, avail_bytes; + unsigned int bytes_to_recv, bytes_to_send; + struct cdns_i2c *id = ptr; + /* Signal completion only after everything is updated */ + int done_flag = 0; + irqreturn_t status = IRQ_NONE; + + isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET); + + /* Handling nack and arbitration lost interrupt */ + if (isr_status & (CDNS_I2C_IXR_NACK | CDNS_I2C_IXR_ARB_LOST)) { + done_flag = 1; + status = IRQ_HANDLED; + } + + /* Handling Data interrupt */ + if ((isr_status & CDNS_I2C_IXR_DATA) && + (id->recv_count >= CDNS_I2C_DATA_INTR_DEPTH)) { + /* Always read data interrupt threshold bytes */ + bytes_to_recv = CDNS_I2C_DATA_INTR_DEPTH; + id->recv_count -= CDNS_I2C_DATA_INTR_DEPTH; + avail_bytes = cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET); + + /* + * if the tranfer size register value is zero, then + * check for the remaining bytes and update the + * transfer size register. + */ + if (!avail_bytes) { + if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) + cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE, + CDNS_I2C_XFER_SIZE_OFFSET); + else + cdns_i2c_writereg(id->recv_count, + CDNS_I2C_XFER_SIZE_OFFSET); + } + + /* Process the data received */ + while (bytes_to_recv--) + *(id->p_recv_buf)++ = + cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); + + if (!id->bus_hold_flag && + (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) + cdns_i2c_clear_bus_hold(id); + + status = IRQ_HANDLED; + } + + /* Handling Transfer Complete interrupt */ + if (isr_status & CDNS_I2C_IXR_COMP) { + if (!id->p_recv_buf) { + /* + * If the device is sending data If there is further + * data to be sent. Calculate the available space + * in FIFO and fill the FIFO with that many bytes. + */ + if (id->send_count) { + avail_bytes = CDNS_I2C_FIFO_DEPTH - + cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET); + if (id->send_count > avail_bytes) + bytes_to_send = avail_bytes; + else + bytes_to_send = id->send_count; + + while (bytes_to_send--) { + cdns_i2c_writereg( + (*(id->p_send_buf)++), + CDNS_I2C_DATA_OFFSET); + id->send_count--; + } + } else { + /* + * Signal the completion of transaction and + * clear the hold bus bit if there are no + * further messages to be processed. + */ + done_flag = 1; + } + if (!id->send_count && !id->bus_hold_flag) + cdns_i2c_clear_bus_hold(id); + } else { + if (!id->bus_hold_flag) + cdns_i2c_clear_bus_hold(id); + /* + * If the device is receiving data, then signal + * the completion of transaction and read the data + * present in the FIFO. Signal the completion of + * transaction. + */ + while (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & + CDNS_I2C_SR_RXDV) { + *(id->p_recv_buf)++ = + cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); + id->recv_count--; + } + done_flag = 1; + } + + status = IRQ_HANDLED; + } + + /* Update the status for errors */ + id->err_status = isr_status & CDNS_I2C_IXR_ERR_INTR_MASK; + if (id->err_status) + status = IRQ_HANDLED; + + cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET); + + if (done_flag) + complete(&id->xfer_done); + + return status; +} + +/** + * cdns_i2c_mrecv - Prepare and start a master receive operation + * @id: pointer to the i2c device structure + */ +static void cdns_i2c_mrecv(struct cdns_i2c *id) +{ + unsigned int ctrl_reg; + unsigned int isr_status; + + id->p_recv_buf = id->p_msg->buf; + id->recv_count = id->p_msg->len; + + /* Put the controller in master receive mode and clear the FIFO */ + ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + ctrl_reg |= CDNS_I2C_CR_RW | CDNS_I2C_CR_CLR_FIFO; + + if (id->p_msg->flags & I2C_M_RECV_LEN) + id->recv_count = I2C_SMBUS_BLOCK_MAX + 1; + + /* + * Check for the message size against FIFO depth and set the + * 'hold bus' bit if it is greater than FIFO depth. + */ + if (id->recv_count > CDNS_I2C_FIFO_DEPTH) + ctrl_reg |= CDNS_I2C_CR_HOLD; + + cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); + + /* Clear the interrupts in interrupt status register */ + isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET); + cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET); + + /* + * The no. of bytes to receive is checked against the limit of + * max transfer size. Set transfer size register with no of bytes + * receive if it is less than transfer size and transfer size if + * it is more. Enable the interrupts. + */ + if (id->recv_count > CDNS_I2C_TRANSFER_SIZE) + cdns_i2c_writereg(CDNS_I2C_TRANSFER_SIZE, + CDNS_I2C_XFER_SIZE_OFFSET); + else + cdns_i2c_writereg(id->recv_count, CDNS_I2C_XFER_SIZE_OFFSET); + /* Clear the bus hold flag if bytes to receive is less than FIFO size */ + if (!id->bus_hold_flag && + ((id->p_msg->flags & I2C_M_RECV_LEN) != I2C_M_RECV_LEN) && + (id->recv_count <= CDNS_I2C_FIFO_DEPTH)) + cdns_i2c_clear_bus_hold(id); + /* Set the slave address in address register - triggers operation */ + cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, + CDNS_I2C_ADDR_OFFSET); + cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET); +} + +/** + * cdns_i2c_msend - Prepare and start a master send operation + * @id: pointer to the i2c device + */ +static void cdns_i2c_msend(struct cdns_i2c *id) +{ + unsigned int avail_bytes; + unsigned int bytes_to_send; + unsigned int ctrl_reg; + unsigned int isr_status; + + id->p_recv_buf = NULL; + id->p_send_buf = id->p_msg->buf; + id->send_count = id->p_msg->len; + + /* Set the controller in Master transmit mode and clear the FIFO. */ + ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + ctrl_reg &= ~CDNS_I2C_CR_RW; + ctrl_reg |= CDNS_I2C_CR_CLR_FIFO; + + /* + * Check for the message size against FIFO depth and set the + * 'hold bus' bit if it is greater than FIFO depth. + */ + if (id->send_count > CDNS_I2C_FIFO_DEPTH) + ctrl_reg |= CDNS_I2C_CR_HOLD; + cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); + + /* Clear the interrupts in interrupt status register. */ + isr_status = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET); + cdns_i2c_writereg(isr_status, CDNS_I2C_ISR_OFFSET); + + /* + * Calculate the space available in FIFO. Check the message length + * against the space available, and fill the FIFO accordingly. + * Enable the interrupts. + */ + avail_bytes = CDNS_I2C_FIFO_DEPTH - + cdns_i2c_readreg(CDNS_I2C_XFER_SIZE_OFFSET); + + if (id->send_count > avail_bytes) + bytes_to_send = avail_bytes; + else + bytes_to_send = id->send_count; + + while (bytes_to_send--) { + cdns_i2c_writereg((*(id->p_send_buf)++), CDNS_I2C_DATA_OFFSET); + id->send_count--; + } + + /* + * Clear the bus hold flag if there is no more data + * and if it is the last message. + */ + if (!id->bus_hold_flag && !id->send_count) + cdns_i2c_clear_bus_hold(id); + /* Set the slave address in address register - triggers operation. */ + cdns_i2c_writereg(id->p_msg->addr & CDNS_I2C_ADDR_MASK, + CDNS_I2C_ADDR_OFFSET); + + cdns_i2c_writereg(CDNS_I2C_ENABLED_INTR_MASK, CDNS_I2C_IER_OFFSET); +} + +/** + * cdns_i2c_master_reset - Reset the interface + * @adap: pointer to the i2c adapter driver instance + * + * This function cleanup the fifos, clear the hold bit and status + * and disable the interrupts. + */ +static void cdns_i2c_master_reset(struct i2c_adapter *adap) +{ + struct cdns_i2c *id = adap->algo_data; + u32 regval; + + /* Disable the interrupts */ + cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, CDNS_I2C_IDR_OFFSET); + /* Clear the hold bit and fifos */ + regval = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + regval &= ~CDNS_I2C_CR_HOLD; + regval |= CDNS_I2C_CR_CLR_FIFO; + cdns_i2c_writereg(regval, CDNS_I2C_CR_OFFSET); + /* Update the transfercount register to zero */ + cdns_i2c_writereg(0, CDNS_I2C_XFER_SIZE_OFFSET); + /* Clear the interupt status register */ + regval = cdns_i2c_readreg(CDNS_I2C_ISR_OFFSET); + cdns_i2c_writereg(regval, CDNS_I2C_ISR_OFFSET); + /* Clear the status register */ + regval = cdns_i2c_readreg(CDNS_I2C_SR_OFFSET); + cdns_i2c_writereg(regval, CDNS_I2C_SR_OFFSET); +} + +static int cdns_i2c_process_msg(struct cdns_i2c *id, struct i2c_msg *msg, + struct i2c_adapter *adap) +{ + int ret; + u32 reg; + + id->p_msg = msg; + id->err_status = 0; + reinit_completion(&id->xfer_done); + + /* Check for the TEN Bit mode on each msg */ + reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + if (msg->flags & I2C_M_TEN) { + if (reg & CDNS_I2C_CR_NEA) + cdns_i2c_writereg(reg & ~CDNS_I2C_CR_NEA, + CDNS_I2C_CR_OFFSET); + } else { + if (!(reg & CDNS_I2C_CR_NEA)) + cdns_i2c_writereg(reg | CDNS_I2C_CR_NEA, + CDNS_I2C_CR_OFFSET); + } + + /* Check for the R/W flag on each msg */ + if (msg->flags & I2C_M_RD) + cdns_i2c_mrecv(id); + else + cdns_i2c_msend(id); + + /* Wait for the signal of completion */ + ret = wait_for_completion_timeout(&id->xfer_done, adap->timeout); + if (!ret) { + cdns_i2c_master_reset(adap); + dev_err(id->adap.dev.parent, + "timeout waiting on completion\n"); + return -ETIMEDOUT; + } + + cdns_i2c_writereg(CDNS_I2C_IXR_ALL_INTR_MASK, + CDNS_I2C_IDR_OFFSET); + + /* If it is bus arbitration error, try again */ + if (id->err_status & CDNS_I2C_IXR_ARB_LOST) + return -EAGAIN; + + return 0; +} + +/** + * cdns_i2c_master_xfer - The main i2c transfer function + * @adap: pointer to the i2c adapter driver instance + * @msgs: pointer to the i2c message structure + * @num: the number of messages to transfer + * + * Initiates the send/recv activity based on the transfer message received. + * + * Return: number of msgs processed on success, negative error otherwise + */ +static int cdns_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, + int num) +{ + int ret, count; + u32 reg; + struct cdns_i2c *id = adap->algo_data; + + /* Check if the bus is free */ + if (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_BA) + return -EAGAIN; + + /* + * Set the flag to one when multiple messages are to be + * processed with a repeated start. + */ + if (num > 1) { + id->bus_hold_flag = 1; + reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + reg |= CDNS_I2C_CR_HOLD; + cdns_i2c_writereg(reg, CDNS_I2C_CR_OFFSET); + } else { + id->bus_hold_flag = 0; + } + + /* Process the msg one by one */ + for (count = 0; count < num; count++, msgs++) { + if (count == (num - 1)) + id->bus_hold_flag = 0; + + ret = cdns_i2c_process_msg(id, msgs, adap); + if (ret) + return ret; + + /* Report the other error interrupts to application */ + if (id->err_status) { + cdns_i2c_master_reset(adap); + + if (id->err_status & CDNS_I2C_IXR_NACK) + return -ENXIO; + + return -EIO; + } + } + + return num; +} + +/** + * cdns_i2c_func - Returns the supported features of the I2C driver + * @adap: pointer to the i2c adapter structure + * + * Return: 32 bit value, each bit corresponding to a feature + */ +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; +} + +static const struct i2c_algorithm cdns_i2c_algo = { + .master_xfer = cdns_i2c_master_xfer, + .functionality = cdns_i2c_func, +}; + +/** + * cdns_i2c_calc_divs - Calculate clock dividers + * @f: I2C clock frequency + * @input_clk: Input clock frequency + * @a: First divider (return value) + * @b: Second divider (return value) + * + * f is used as input and output variable. As input it is used as target I2C + * frequency. On function exit f holds the actually resulting I2C frequency. + * + * Return: 0 on success, negative errno otherwise. + */ +static int cdns_i2c_calc_divs(unsigned long *f, unsigned long input_clk, + unsigned int *a, unsigned int *b) +{ + unsigned long fscl = *f, best_fscl = *f, actual_fscl, temp; + unsigned int div_a, div_b, calc_div_a = 0, calc_div_b = 0; + unsigned int last_error, current_error; + + /* calculate (divisor_a+1) x (divisor_b+1) */ + temp = input_clk / (22 * fscl); + + /* + * If the calculated value is negative or 0, the fscl input is out of + * range. Return error. + */ + if (!temp || (temp > (CDNS_I2C_DIVA_MAX * CDNS_I2C_DIVB_MAX))) + return -EINVAL; + + last_error = -1; + for (div_a = 0; div_a < CDNS_I2C_DIVA_MAX; div_a++) { + div_b = DIV_ROUND_UP(input_clk, 22 * fscl * (div_a + 1)); + + if ((div_b < 1) || (div_b > CDNS_I2C_DIVB_MAX)) + continue; + div_b--; + + actual_fscl = input_clk / (22 * (div_a + 1) * (div_b + 1)); + + if (actual_fscl > fscl) + continue; + + current_error = ((actual_fscl > fscl) ? (actual_fscl - fscl) : + (fscl - actual_fscl)); + + if (last_error > current_error) { + calc_div_a = div_a; + calc_div_b = div_b; + best_fscl = actual_fscl; + last_error = current_error; + } + } + + *a = calc_div_a; + *b = calc_div_b; + *f = best_fscl; + + return 0; +} + +/** + * cdns_i2c_setclk - This function sets the serial clock rate for the I2C device + * @clk_in: I2C clock input frequency in Hz + * @id: Pointer to the I2C device structure + * + * The device must be idle rather than busy transferring data before setting + * these device options. + * The data rate is set by values in the control register. + * The formula for determining the correct register values is + * Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1)) + * See the hardware data sheet for a full explanation of setting the serial + * clock rate. The clock can not be faster than the input clock divide by 22. + * The two most common clock rates are 100KHz and 400KHz. + * + * Return: 0 on success, negative error otherwise + */ +static int cdns_i2c_setclk(unsigned long clk_in, struct cdns_i2c *id) +{ + unsigned int div_a, div_b; + unsigned int ctrl_reg; + int ret = 0; + unsigned long fscl = id->i2c_clk; + + ret = cdns_i2c_calc_divs(&fscl, clk_in, &div_a, &div_b); + if (ret) + return ret; + + ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + ctrl_reg &= ~(CDNS_I2C_CR_DIVA_MASK | CDNS_I2C_CR_DIVB_MASK); + 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); + + return 0; +} + +/** + * cdns_i2c_clk_notifier_cb - Clock rate change callback + * @nb: Pointer to notifier block + * @event: Notification reason + * @data: Pointer to notification data object + * + * This function is called when the cdns_i2c input clock frequency changes. + * The callback checks whether a valid bus frequency can be generated after the + * change. If so, the change is acknowledged, otherwise the change is aborted. + * New dividers are written to the HW in the pre- or post change notification + * depending on the scaling direction. + * + * Return: NOTIFY_STOP if the rate change should be aborted, NOTIFY_OK + * to acknowedge the change, NOTIFY_DONE if the notification is + * considered irrelevant. + */ +static int cdns_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long + event, void *data) +{ + struct clk_notifier_data *ndata = data; + struct cdns_i2c *id = to_cdns_i2c(nb); + + if (id->suspended) + return NOTIFY_OK; + + switch (event) { + case PRE_RATE_CHANGE: + { + unsigned long input_clk = ndata->new_rate; + unsigned long fscl = id->i2c_clk; + unsigned int div_a, div_b; + int ret; + + ret = cdns_i2c_calc_divs(&fscl, input_clk, &div_a, &div_b); + if (ret) { + dev_warn(id->adap.dev.parent, + "clock rate change rejected\n"); + return NOTIFY_STOP; + } + + /* scale up */ + if (ndata->new_rate > ndata->old_rate) + cdns_i2c_setclk(ndata->new_rate, id); + + return NOTIFY_OK; + } + case POST_RATE_CHANGE: + id->input_clk = ndata->new_rate; + /* scale down */ + if (ndata->new_rate < ndata->old_rate) + cdns_i2c_setclk(ndata->new_rate, id); + return NOTIFY_OK; + case ABORT_RATE_CHANGE: + /* scale up */ + if (ndata->new_rate > ndata->old_rate) + cdns_i2c_setclk(ndata->old_rate, id); + return NOTIFY_OK; + default: + return NOTIFY_DONE; + } +} + +/** + * cdns_i2c_suspend - Suspend method for the driver + * @_dev: Address of the platform_device structure + * + * Put the driver into low power mode. + * + * Return: 0 always + */ +static int __maybe_unused cdns_i2c_suspend(struct device *_dev) +{ + struct platform_device *pdev = container_of(_dev, + struct platform_device, dev); + struct cdns_i2c *xi2c = platform_get_drvdata(pdev); + + clk_disable(xi2c->clk); + xi2c->suspended = 1; + + return 0; +} + +/** + * cdns_i2c_resume - Resume from suspend + * @_dev: Address of the platform_device structure + * + * Resume operation after suspend. + * + * Return: 0 on success and error value on error + */ +static int __maybe_unused cdns_i2c_resume(struct device *_dev) +{ + struct platform_device *pdev = container_of(_dev, + struct platform_device, dev); + struct cdns_i2c *xi2c = platform_get_drvdata(pdev); + int ret; + + ret = clk_enable(xi2c->clk); + if (ret) { + dev_err(_dev, "Cannot enable clock.\n"); + return ret; + } + + xi2c->suspended = 0; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(cdns_i2c_dev_pm_ops, cdns_i2c_suspend, + cdns_i2c_resume); + +/** + * cdns_i2c_probe - Platform registration call + * @pdev: Handle to the platform device structure + * + * This function does all the memory allocation and registration for the i2c + * device. User can modify the address mode to 10 bit address mode using the + * ioctl call with option I2C_TENBIT. + * + * Return: 0 on success, negative error otherwise + */ +static int cdns_i2c_probe(struct platform_device *pdev) +{ + struct resource *r_mem; + struct cdns_i2c *id; + int ret; + + id = devm_kzalloc(&pdev->dev, sizeof(*id), GFP_KERNEL); + if (!id) + return -ENOMEM; + + platform_set_drvdata(pdev, id); + + r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + id->membase = devm_ioremap_resource(&pdev->dev, r_mem); + if (IS_ERR(id->membase)) + return PTR_ERR(id->membase); + + id->irq = platform_get_irq(pdev, 0); + + id->adap.dev.of_node = pdev->dev.of_node; + id->adap.algo = &cdns_i2c_algo; + id->adap.timeout = CDNS_I2C_TIMEOUT; + id->adap.retries = 3; /* Default retry value. */ + id->adap.algo_data = id; + id->adap.dev.parent = &pdev->dev; + init_completion(&id->xfer_done); + snprintf(id->adap.name, sizeof(id->adap.name), + "Cadence I2C at %08lx", (unsigned long)r_mem->start); + + id->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(id->clk)) { + dev_err(&pdev->dev, "input clock not found.\n"); + return PTR_ERR(id->clk); + } + ret = clk_prepare_enable(id->clk); + if (ret) { + dev_err(&pdev->dev, "Unable to enable clock.\n"); + return ret; + } + id->clk_rate_change_nb.notifier_call = cdns_i2c_clk_notifier_cb; + if (clk_notifier_register(id->clk, &id->clk_rate_change_nb)) + dev_warn(&pdev->dev, "Unable to register clock notifier.\n"); + id->input_clk = clk_get_rate(id->clk); + + ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &id->i2c_clk); + if (ret || (id->i2c_clk > CDNS_I2C_SPEED_MAX)) + id->i2c_clk = CDNS_I2C_SPEED_DEFAULT; + + cdns_i2c_writereg(CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS, + CDNS_I2C_CR_OFFSET); + + ret = cdns_i2c_setclk(id->input_clk, id); + if (ret) { + dev_err(&pdev->dev, "invalid SCL clock: %u Hz\n", id->i2c_clk); + ret = -EINVAL; + goto err_clk_dis; + } + + ret = devm_request_irq(&pdev->dev, id->irq, cdns_i2c_isr, 0, + DRIVER_NAME, id); + if (ret) { + dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); + goto err_clk_dis; + } + + ret = i2c_add_adapter(&id->adap); + if (ret < 0) { + dev_err(&pdev->dev, "reg adap failed: %d\n", ret); + goto err_clk_dis; + } + + dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n", + id->i2c_clk / 1000, (unsigned long)r_mem->start, id->irq); + + return 0; + +err_clk_dis: + clk_disable_unprepare(id->clk); + return ret; +} + +/** + * cdns_i2c_remove - Unregister the device after releasing the resources + * @pdev: Handle to the platform device structure + * + * This function frees all the resources allocated to the device. + * + * Return: 0 always + */ +static int cdns_i2c_remove(struct platform_device *pdev) +{ + struct cdns_i2c *id = platform_get_drvdata(pdev); + + i2c_del_adapter(&id->adap); + clk_notifier_unregister(id->clk, &id->clk_rate_change_nb); + clk_disable_unprepare(id->clk); + + return 0; +} + +static const struct of_device_id cdns_i2c_of_match[] = { + { .compatible = "cdns,i2c-r1p10", }, + { /* end of table */ } +}; +MODULE_DEVICE_TABLE(of, cdns_i2c_of_match); + +static struct platform_driver cdns_i2c_drv = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = cdns_i2c_of_match, + .pm = &cdns_i2c_dev_pm_ops, + }, + .probe = cdns_i2c_probe, + .remove = cdns_i2c_remove, +}; + +module_platform_driver(cdns_i2c_drv); + +MODULE_AUTHOR("Xilinx Inc."); +MODULE_DESCRIPTION("Cadence I2C bus driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c index 2d46f13adfd..bdf040fd867 100644 --- a/drivers/i2c/busses/i2c-cbus-gpio.c +++ b/drivers/i2c/busses/i2c-cbus-gpio.c @@ -19,7 +19,6 @@ #include <linux/io.h> #include <linux/i2c.h> #include <linux/gpio.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/errno.h> @@ -246,6 +245,7 @@ static int cbus_i2c_probe(struct platform_device *pdev) adapter->owner = THIS_MODULE; adapter->class = I2C_CLASS_HWMON; adapter->dev.parent = &pdev->dev; + adapter->dev.of_node = pdev->dev.of_node; adapter->nr = pdev->id; adapter->timeout = HZ; adapter->algo = &cbus_i2c_algo; @@ -289,6 +289,7 @@ static struct platform_driver cbus_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = "i2c-cbus-gpio", + .of_match_table = of_match_ptr(i2c_cbus_dt_ids), }, }; module_platform_driver(cbus_i2c_driver); diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index b2b8aa9adc0..f3b89a4698b 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -33,14 +33,15 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/errno.h> #include <linux/stddef.h> #include <linux/i2c.h> #include <linux/io.h> #include <linux/dma-mapping.h> +#include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> #include <sysdev/fsl_soc.h> #include <asm/cpm.h> @@ -447,7 +448,7 @@ static int cpm_i2c_setup(struct cpm_i2c *cpm) init_waitqueue_head(&cpm->i2c_wait); - cpm->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); + cpm->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0); if (!cpm->irq) return -EINVAL; diff --git a/drivers/i2c/busses/i2c-cros-ec-tunnel.c b/drivers/i2c/busses/i2c-cros-ec-tunnel.c new file mode 100644 index 00000000000..8e7a71487bb --- /dev/null +++ b/drivers/i2c/busses/i2c-cros-ec-tunnel.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2013 Google, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Expose an I2C passthrough to the ChromeOS EC. + */ + +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/mfd/cros_ec.h> +#include <linux/mfd/cros_ec_commands.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +/** + * struct ec_i2c_device - Driver data for I2C tunnel + * + * @dev: Device node + * @adap: I2C adapter + * @ec: Pointer to EC device + * @remote_bus: The EC bus number we tunnel to on the other side. + * @request_buf: Buffer for transmitting data; we expect most transfers to fit. + * @response_buf: Buffer for receiving data; we expect most transfers to fit. + */ + +struct ec_i2c_device { + struct device *dev; + struct i2c_adapter adap; + struct cros_ec_device *ec; + + u16 remote_bus; + + u8 request_buf[256]; + u8 response_buf[256]; +}; + +/** + * ec_i2c_count_message - Count bytes needed for ec_i2c_construct_message + * + * @i2c_msgs: The i2c messages to read + * @num: The number of i2c messages. + * + * Returns the number of bytes the messages will take up. + */ +static int ec_i2c_count_message(const struct i2c_msg i2c_msgs[], int num) +{ + int i; + int size; + + size = sizeof(struct ec_params_i2c_passthru); + size += num * sizeof(struct ec_params_i2c_passthru_msg); + for (i = 0; i < num; i++) + if (!(i2c_msgs[i].flags & I2C_M_RD)) + size += i2c_msgs[i].len; + + return size; +} + +/** + * ec_i2c_construct_message - construct a message to go to the EC + * + * This function effectively stuffs the standard i2c_msg format of Linux into + * a format that the EC understands. + * + * @buf: The buffer to fill. We assume that the buffer is big enough. + * @i2c_msgs: The i2c messages to read. + * @num: The number of i2c messages. + * @bus_num: The remote bus number we want to talk to. + * + * Returns 0 or a negative error number. + */ +static int ec_i2c_construct_message(u8 *buf, const struct i2c_msg i2c_msgs[], + int num, u16 bus_num) +{ + struct ec_params_i2c_passthru *params; + u8 *out_data; + int i; + + out_data = buf + sizeof(struct ec_params_i2c_passthru) + + num * sizeof(struct ec_params_i2c_passthru_msg); + + params = (struct ec_params_i2c_passthru *)buf; + params->port = bus_num; + params->num_msgs = num; + for (i = 0; i < num; i++) { + const struct i2c_msg *i2c_msg = &i2c_msgs[i]; + struct ec_params_i2c_passthru_msg *msg = ¶ms->msg[i]; + + msg->len = i2c_msg->len; + msg->addr_flags = i2c_msg->addr; + + if (i2c_msg->flags & I2C_M_TEN) + msg->addr_flags |= EC_I2C_FLAG_10BIT; + + if (i2c_msg->flags & I2C_M_RD) { + msg->addr_flags |= EC_I2C_FLAG_READ; + } else { + memcpy(out_data, i2c_msg->buf, msg->len); + out_data += msg->len; + } + } + + return 0; +} + +/** + * ec_i2c_count_response - Count bytes needed for ec_i2c_parse_response + * + * @i2c_msgs: The i2c messages to to fill up. + * @num: The number of i2c messages expected. + * + * Returns the number of response bytes expeced. + */ +static int ec_i2c_count_response(struct i2c_msg i2c_msgs[], int num) +{ + int size; + int i; + + size = sizeof(struct ec_response_i2c_passthru); + for (i = 0; i < num; i++) + if (i2c_msgs[i].flags & I2C_M_RD) + size += i2c_msgs[i].len; + + return size; +} + +/** + * ec_i2c_parse_response - Parse a response from the EC + * + * We'll take the EC's response and copy it back into msgs. + * + * @buf: The buffer to parse. + * @i2c_msgs: The i2c messages to to fill up. + * @num: The number of i2c messages; will be modified to include the actual + * number received. + * + * Returns 0 or a negative error number. + */ +static int ec_i2c_parse_response(const u8 *buf, struct i2c_msg i2c_msgs[], + int *num) +{ + const struct ec_response_i2c_passthru *resp; + const u8 *in_data; + int i; + + in_data = buf + sizeof(struct ec_response_i2c_passthru); + + resp = (const struct ec_response_i2c_passthru *)buf; + if (resp->i2c_status & EC_I2C_STATUS_TIMEOUT) + return -ETIMEDOUT; + else if (resp->i2c_status & EC_I2C_STATUS_ERROR) + return -EREMOTEIO; + + /* Other side could send us back fewer messages, but not more */ + if (resp->num_msgs > *num) + return -EPROTO; + *num = resp->num_msgs; + + for (i = 0; i < *num; i++) { + struct i2c_msg *i2c_msg = &i2c_msgs[i]; + + if (i2c_msgs[i].flags & I2C_M_RD) { + memcpy(i2c_msg->buf, in_data, i2c_msg->len); + in_data += i2c_msg->len; + } + } + + return 0; +} + +static int ec_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg i2c_msgs[], + int num) +{ + struct ec_i2c_device *bus = adap->algo_data; + struct device *dev = bus->dev; + const u16 bus_num = bus->remote_bus; + int request_len; + int response_len; + u8 *request = NULL; + u8 *response = NULL; + int result; + + request_len = ec_i2c_count_message(i2c_msgs, num); + if (request_len < 0) { + dev_warn(dev, "Error constructing message %d\n", request_len); + result = request_len; + goto exit; + } + response_len = ec_i2c_count_response(i2c_msgs, num); + if (response_len < 0) { + /* Unexpected; no errors should come when NULL response */ + dev_warn(dev, "Error preparing response %d\n", response_len); + result = response_len; + goto exit; + } + + if (request_len <= ARRAY_SIZE(bus->request_buf)) { + request = bus->request_buf; + } else { + request = kzalloc(request_len, GFP_KERNEL); + if (request == NULL) { + result = -ENOMEM; + goto exit; + } + } + if (response_len <= ARRAY_SIZE(bus->response_buf)) { + response = bus->response_buf; + } else { + response = kzalloc(response_len, GFP_KERNEL); + if (response == NULL) { + result = -ENOMEM; + goto exit; + } + } + + ec_i2c_construct_message(request, i2c_msgs, num, bus_num); + result = bus->ec->command_sendrecv(bus->ec, EC_CMD_I2C_PASSTHRU, + request, request_len, + response, response_len); + if (result) + goto exit; + + result = ec_i2c_parse_response(response, i2c_msgs, &num); + if (result < 0) + goto exit; + + /* Indicate success by saying how many messages were sent */ + result = num; +exit: + if (request != bus->request_buf) + kfree(request); + if (response != bus->response_buf) + kfree(response); + + return result; +} + +static u32 ec_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm ec_i2c_algorithm = { + .master_xfer = ec_i2c_xfer, + .functionality = ec_i2c_functionality, +}; + +static int ec_i2c_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent); + struct device *dev = &pdev->dev; + struct ec_i2c_device *bus = NULL; + u32 remote_bus; + int err; + + if (!ec->command_sendrecv) { + dev_err(dev, "Missing sendrecv\n"); + return -EINVAL; + } + + bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL); + if (bus == NULL) + return -ENOMEM; + + err = of_property_read_u32(np, "google,remote-bus", &remote_bus); + if (err) { + dev_err(dev, "Couldn't read remote-bus property\n"); + return err; + } + bus->remote_bus = remote_bus; + + bus->ec = ec; + bus->dev = dev; + + bus->adap.owner = THIS_MODULE; + strlcpy(bus->adap.name, "cros-ec-i2c-tunnel", sizeof(bus->adap.name)); + bus->adap.algo = &ec_i2c_algorithm; + bus->adap.algo_data = bus; + bus->adap.dev.parent = &pdev->dev; + bus->adap.dev.of_node = np; + + err = i2c_add_adapter(&bus->adap); + if (err) { + dev_err(dev, "cannot register i2c adapter\n"); + return err; + } + platform_set_drvdata(pdev, bus); + + return err; +} + +static int ec_i2c_remove(struct platform_device *dev) +{ + struct ec_i2c_device *bus = platform_get_drvdata(dev); + + i2c_del_adapter(&bus->adap); + + return 0; +} + +static struct platform_driver ec_i2c_tunnel_driver = { + .probe = ec_i2c_probe, + .remove = ec_i2c_remove, + .driver = { + .name = "cros-ec-i2c-tunnel", + }, +}; + +module_platform_driver(ec_i2c_tunnel_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("EC I2C tunnel driver"); +MODULE_ALIAS("platform:cros-ec-i2c-tunnel"); diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 132369fad4e..389bc68c55a 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -125,12 +125,12 @@ static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = { static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev, int reg, u16 val) { - __raw_writew(val, i2c_dev->base + reg); + writew_relaxed(val, i2c_dev->base + reg); } static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg) { - return __raw_readw(i2c_dev->base + reg); + return readw_relaxed(i2c_dev->base + reg); } /* Generate a pulse on the i2c clock pin. */ @@ -323,7 +323,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); - INIT_COMPLETION(dev->cmd_complete); + reinit_completion(&dev->cmd_complete); dev->cmd_err = 0; /* Take I2C out of reset and configure it as master */ @@ -712,7 +712,7 @@ static int davinci_i2c_probe(struct platform_device *pdev) adap = &dev->adapter; i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED; strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name)); adap->algo = &i2c_davinci_algo; adap->dev.parent = &pdev->dev; @@ -795,7 +795,7 @@ static struct platform_driver davinci_i2c_driver = { .name = "i2c_davinci", .owner = THIS_MODULE, .pm = davinci_i2c_pm_ops, - .of_match_table = of_match_ptr(davinci_i2c_of_match), + .of_match_table = davinci_i2c_of_match, }, }; diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index dbecf08399f..3c20e4bd6dd 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -26,7 +26,6 @@ * */ #include <linux/export.h> -#include <linux/clk.h> #include <linux/errno.h> #include <linux/err.h> #include <linux/i2c.h> @@ -98,6 +97,8 @@ #define DW_IC_ERR_TX_ABRT 0x1 +#define DW_IC_TAR_10BITADDR_MASTER BIT(12) + /* * status codes */ @@ -217,7 +218,7 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) * * If your hardware is free from tHD;STA issue, try this one. */ - return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset; + return (ic_clk * tSYMBOL + 500000) / 1000000 - 8 + offset; else /* * Conditional expression: @@ -233,7 +234,8 @@ i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) * The reason why we need to take into account "tf" here, * is the same as described in i2c_dw_scl_lcnt(). */ - return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset; + return (ic_clk * (tSYMBOL + tf) + 500000) / 1000000 + - 3 + offset; } static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) @@ -249,7 +251,7 @@ static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) * account the fall time of SCL signal (tf). Default tf value * should be 0.3 us, for safety. */ - return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset; + return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset; } static void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable) @@ -286,6 +288,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) u32 input_clock_khz; u32 hcnt, lcnt; u32 reg; + u32 sda_falling_time, scl_falling_time; input_clock_khz = dev->get_clk_rate_khz(dev); @@ -307,15 +310,18 @@ int i2c_dw_init(struct dw_i2c_dev *dev) /* set standard and fast speed deviders for high/low periods */ + sda_falling_time = dev->sda_falling_time ?: 300; /* ns */ + scl_falling_time = dev->scl_falling_time ?: 300; /* ns */ + /* Standard-mode */ hcnt = i2c_dw_scl_hcnt(input_clock_khz, - 40, /* tHD;STA = tHIGH = 4.0 us */ - 3, /* tf = 0.3 us */ + 4000, /* tHD;STA = tHIGH = 4.0 us */ + sda_falling_time, 0, /* 0: DW default, 1: Ideal */ 0); /* No offset */ lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 47, /* tLOW = 4.7 us */ - 3, /* tf = 0.3 us */ + 4700, /* tLOW = 4.7 us */ + scl_falling_time, 0); /* No offset */ /* Allow platforms to specify the ideal HCNT and LCNT values */ @@ -329,13 +335,13 @@ int i2c_dw_init(struct dw_i2c_dev *dev) /* Fast-mode */ hcnt = i2c_dw_scl_hcnt(input_clock_khz, - 6, /* tHD;STA = tHIGH = 0.6 us */ - 3, /* tf = 0.3 us */ + 600, /* tHD;STA = tHIGH = 0.6 us */ + sda_falling_time, 0, /* 0: DW default, 1: Ideal */ 0); /* No offset */ lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 13, /* tLOW = 1.3 us */ - 3, /* tf = 0.3 us */ + 1300, /* tLOW = 1.3 us */ + scl_falling_time, 0); /* No offset */ if (dev->fs_hcnt && dev->fs_lcnt) { @@ -388,22 +394,37 @@ static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) { struct i2c_msg *msgs = dev->msgs; - u32 ic_con; + u32 ic_con, ic_tar = 0; /* Disable the adapter */ __i2c_dw_enable(dev, false); - /* set the slave (target) address */ - dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR); - /* if the slave address is ten bit address, enable 10BITADDR */ ic_con = dw_readl(dev, DW_IC_CON); - if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) + if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) { ic_con |= DW_IC_CON_10BITADDR_MASTER; - else + /* + * If I2C_DYNAMIC_TAR_UPDATE is set, the 10-bit addressing + * mode has to be enabled via bit 12 of IC_TAR register. + * We set it always as I2C_DYNAMIC_TAR_UPDATE can't be + * detected from registers. + */ + ic_tar = DW_IC_TAR_10BITADDR_MASTER; + } else { ic_con &= ~DW_IC_CON_10BITADDR_MASTER; + } + dw_writel(dev, ic_con, DW_IC_CON); + /* + * Set the slave (target) address and enable 10-bit addressing mode + * if applicable. + */ + dw_writel(dev, msgs[dev->msg_write_idx].addr | ic_tar, DW_IC_TAR); + + /* enforce disabled interrupts (due to HW issues) */ + i2c_dw_disable_int(dev); + /* Enable the adapter */ __i2c_dw_enable(dev, true); @@ -599,7 +620,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) mutex_lock(&dev->lock); pm_runtime_get_sync(dev->dev); - INIT_COMPLETION(dev->cmd_complete); + reinit_completion(&dev->cmd_complete); dev->msgs = msgs; dev->msgs_num = num; dev->cmd_err = 0; diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index e8a756537ed..d66b6cbc9ed 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -99,6 +99,8 @@ struct dw_i2c_dev { unsigned int rx_fifo_depth; int rx_outstanding; u32 sda_hold_time; + u32 sda_falling_time; + u32 scl_falling_time; u16 ss_hcnt; u16 ss_lcnt; u16 fs_hcnt; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index f6ed06c966e..3356f7ab9f7 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -54,6 +54,17 @@ enum dw_pci_ctl_id_t { medfield_3, medfield_4, medfield_5, + + baytrail, + haswell, +}; + +struct dw_scl_sda_cfg { + u32 ss_hcnt; + u32 fs_hcnt; + u32 ss_lcnt; + u32 fs_lcnt; + u32 sda_hold; }; struct dw_pci_controller { @@ -62,12 +73,38 @@ struct dw_pci_controller { u32 tx_fifo_depth; u32 rx_fifo_depth; u32 clk_khz; + u32 functionality; + struct dw_scl_sda_cfg *scl_sda_cfg; }; #define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \ DW_IC_CON_SLAVE_DISABLE | \ DW_IC_CON_RESTART_EN) +#define DW_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \ + I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_BYTE_DATA | \ + I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_I2C_BLOCK) + +/* BayTrail HCNT/LCNT/SDA hold time */ +static struct dw_scl_sda_cfg byt_config = { + .ss_hcnt = 0x200, + .fs_hcnt = 0x55, + .ss_lcnt = 0x200, + .fs_lcnt = 0x99, + .sda_hold = 0x6, +}; + +/* Haswell HCNT/LCNT/SDA hold time */ +static struct dw_scl_sda_cfg hsw_config = { + .ss_hcnt = 0x01b0, + .fs_hcnt = 0x48, + .ss_lcnt = 0x01fb, + .fs_lcnt = 0xa0, + .sda_hold = 0x9, +}; + static struct dw_pci_controller dw_pci_controllers[] = { [moorestown_0] = { .bus_num = 0, @@ -132,75 +169,49 @@ static struct dw_pci_controller dw_pci_controllers[] = { .rx_fifo_depth = 32, .clk_khz = 25000, }, + [baytrail] = { + .bus_num = -1, + .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, + .tx_fifo_depth = 32, + .rx_fifo_depth = 32, + .clk_khz = 100000, + .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, + .clk_khz = 100000, + .functionality = I2C_FUNC_10BIT_ADDR, + .scl_sda_cfg = &hsw_config, + }, }; static struct i2c_algorithm i2c_dw_algo = { .master_xfer = i2c_dw_xfer, .functionality = i2c_dw_func, }; +#ifdef CONFIG_PM static int i2c_dw_pci_suspend(struct device *dev) { struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); - struct dw_i2c_dev *i2c = pci_get_drvdata(pdev); - int err; - - - i2c_dw_disable(i2c); - - err = pci_save_state(pdev); - if (err) { - dev_err(&pdev->dev, "pci_save_state failed\n"); - return err; - } - - err = pci_set_power_state(pdev, PCI_D3hot); - if (err) { - dev_err(&pdev->dev, "pci_set_power_state failed\n"); - return err; - } + i2c_dw_disable(pci_get_drvdata(pdev)); return 0; } static int i2c_dw_pci_resume(struct device *dev) { struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); - struct dw_i2c_dev *i2c = pci_get_drvdata(pdev); - int err; - u32 enabled; - - enabled = i2c_dw_is_enabled(i2c); - if (enabled) - return 0; - - err = pci_set_power_state(pdev, PCI_D0); - if (err) { - dev_err(&pdev->dev, "pci_set_power_state() failed\n"); - return err; - } - - pci_restore_state(pdev); - i2c_dw_init(i2c); - return 0; + return i2c_dw_init(pci_get_drvdata(pdev)); } +#endif -static int i2c_dw_pci_runtime_idle(struct device *dev) -{ - int err = pm_schedule_suspend(dev, 500); - dev_dbg(dev, "runtime_idle called\n"); - - if (err != 0) - return 0; - return -EBUSY; -} - -static const struct dev_pm_ops i2c_dw_pm_ops = { - .resume = i2c_dw_pci_resume, - .suspend = i2c_dw_pci_suspend, - SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume, - i2c_dw_pci_runtime_idle) -}; +static UNIVERSAL_DEV_PM_OPS(i2c_dw_pm_ops, i2c_dw_pci_suspend, + i2c_dw_pci_resume, NULL); static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) { @@ -214,6 +225,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, struct i2c_adapter *adap; int r; struct dw_pci_controller *controller; + struct dw_scl_sda_cfg *cfg; if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { dev_err(&pdev->dev, "%s: invalid driver data %ld\n", __func__, @@ -247,13 +259,18 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; dev->base = pcim_iomap_table(pdev)[0]; dev->dev = &pdev->dev; - dev->functionality = - I2C_FUNC_I2C | - I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_I2C_BLOCK; + dev->functionality = controller->functionality | + DW_DEFAULT_FUNCTIONALITY; + dev->master_cfg = controller->bus_cfg; + if (controller->scl_sda_cfg) { + cfg = controller->scl_sda_cfg; + dev->ss_hcnt = cfg->ss_hcnt; + dev->fs_hcnt = cfg->fs_hcnt; + dev->ss_lcnt = cfg->ss_lcnt; + dev->fs_lcnt = cfg->fs_lcnt; + dev->sda_hold_time = cfg->sda_hold; + } pci_set_drvdata(pdev, dev); @@ -270,8 +287,8 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, adap->algo = &i2c_dw_algo; adap->dev.parent = &pdev->dev; adap->nr = controller->bus_num; - snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d", - adap->nr); + + snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci"); r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev); @@ -290,6 +307,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev, pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_put_autosuspend(&pdev->dev); pm_runtime_allow(&pdev->dev); return 0; @@ -309,7 +327,7 @@ static void i2c_dw_pci_remove(struct pci_dev *pdev) /* work with hotplug and coldplug */ MODULE_ALIAS("i2c_designware-pci"); -static DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = { +static const struct pci_device_id i2_designware_pci_ids[] = { /* Moorestown */ { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 }, { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 }, @@ -321,6 +339,17 @@ static DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = { { PCI_VDEVICE(INTEL, 0x082C), medfield_0 }, { PCI_VDEVICE(INTEL, 0x082D), medfield_1 }, { PCI_VDEVICE(INTEL, 0x082E), medfield_2 }, + /* Baytrail */ + { PCI_VDEVICE(INTEL, 0x0F41), baytrail }, + { PCI_VDEVICE(INTEL, 0x0F42), baytrail }, + { PCI_VDEVICE(INTEL, 0x0F43), baytrail }, + { PCI_VDEVICE(INTEL, 0x0F44), baytrail }, + { PCI_VDEVICE(INTEL, 0x0F45), baytrail }, + { PCI_VDEVICE(INTEL, 0x0F46), baytrail }, + { PCI_VDEVICE(INTEL, 0x0F47), baytrail }, + /* Haswell */ + { PCI_VDEVICE(INTEL, 0x9c61), haswell }, + { PCI_VDEVICE(INTEL, 0x9c62), haswell }, { 0,} }; MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 4c1b60539a2..402ec3970fe 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -103,6 +103,8 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev) static const struct acpi_device_id dw_i2c_acpi_match[] = { { "INT33C2", 0 }, { "INT33C3", 0 }, + { "INT3432", 0 }, + { "INT3433", 0 }, { "80860F41", 0 }, { } }; @@ -157,6 +159,13 @@ static int dw_i2c_probe(struct platform_device *pdev) "i2c-sda-hold-time-ns", &ht); dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000, 1000000); + + of_property_read_u32(pdev->dev.of_node, + "i2c-sda-falling-time-ns", + &dev->sda_falling_time); + of_property_read_u32(pdev->dev.of_node, + "i2c-scl-falling-time-ns", + &dev->scl_falling_time); } dev->functionality = @@ -193,7 +202,7 @@ static int dw_i2c_probe(struct platform_device *pdev) adap = &dev->adapter; i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED; strlcpy(adap->name, "Synopsys DesignWare I2C adapter", sizeof(adap->name)); adap->algo = &i2c_dw_algo; @@ -238,12 +247,13 @@ static const struct of_device_id dw_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, dw_i2c_of_match); #endif -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM static int dw_i2c_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); + i2c_dw_disable(i_dev); clk_disable_unprepare(i_dev->clk); return 0; @@ -259,30 +269,29 @@ static int dw_i2c_resume(struct device *dev) return 0; } - -static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume); -#define DW_I2C_DEV_PM_OPS (&dw_i2c_dev_pm_ops) -#else -#define DW_I2C_DEV_PM_OPS NULL #endif +static UNIVERSAL_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, + dw_i2c_resume, NULL); + /* work with hotplug and coldplug */ MODULE_ALIAS("platform:i2c_designware"); static struct platform_driver dw_i2c_driver = { - .remove = dw_i2c_remove, + .probe = dw_i2c_probe, + .remove = dw_i2c_remove, .driver = { .name = "i2c_designware", .owner = THIS_MODULE, .of_match_table = of_match_ptr(dw_i2c_of_match), .acpi_match_table = ACPI_PTR(dw_i2c_acpi_match), - .pm = DW_I2C_DEV_PM_OPS, + .pm = &dw_i2c_dev_pm_ops, }, }; static int __init dw_i2c_init_driver(void) { - return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe); + return platform_driver_register(&dw_i2c_driver); } subsys_initcall(dw_i2c_init_driver); diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c index dae3ddfe761..b19a310bf9b 100644 --- a/drivers/i2c/busses/i2c-diolan-u2c.c +++ b/drivers/i2c/busses/i2c-diolan-u2c.c @@ -25,8 +25,6 @@ #define USB_VENDOR_ID_DIOLAN 0x0abf #define USB_DEVICE_ID_DIOLAN_U2C 0x3370 -#define DIOLAN_OUT_EP 0x02 -#define DIOLAN_IN_EP 0x84 /* commands via USB, must match command ids in the firmware */ #define CMD_I2C_READ 0x01 @@ -84,6 +82,7 @@ struct i2c_diolan_u2c { u8 obuffer[DIOLAN_OUTBUF_LEN]; /* output buffer */ u8 ibuffer[DIOLAN_INBUF_LEN]; /* input buffer */ + int ep_in, ep_out; /* Endpoints */ struct usb_device *usb_dev; /* the usb device for this device */ struct usb_interface *interface;/* the interface for this device */ struct i2c_adapter adapter; /* i2c related things */ @@ -109,7 +108,7 @@ static int diolan_usb_transfer(struct i2c_diolan_u2c *dev) return -EINVAL; ret = usb_bulk_msg(dev->usb_dev, - usb_sndbulkpipe(dev->usb_dev, DIOLAN_OUT_EP), + usb_sndbulkpipe(dev->usb_dev, dev->ep_out), dev->obuffer, dev->olen, &actual, DIOLAN_USB_TIMEOUT); if (!ret) { @@ -118,7 +117,7 @@ static int diolan_usb_transfer(struct i2c_diolan_u2c *dev) tmpret = usb_bulk_msg(dev->usb_dev, usb_rcvbulkpipe(dev->usb_dev, - DIOLAN_IN_EP), + dev->ep_in), dev->ibuffer, sizeof(dev->ibuffer), &actual, DIOLAN_USB_TIMEOUT); @@ -210,7 +209,7 @@ static void diolan_flush_input(struct i2c_diolan_u2c *dev) int ret; ret = usb_bulk_msg(dev->usb_dev, - usb_rcvbulkpipe(dev->usb_dev, DIOLAN_IN_EP), + usb_rcvbulkpipe(dev->usb_dev, dev->ep_in), dev->ibuffer, sizeof(dev->ibuffer), &actual, DIOLAN_USB_TIMEOUT); if (ret < 0 || actual == 0) @@ -445,16 +444,22 @@ static void diolan_u2c_free(struct i2c_diolan_u2c *dev) static int diolan_u2c_probe(struct usb_interface *interface, const struct usb_device_id *id) { + struct usb_host_interface *hostif = interface->cur_altsetting; struct i2c_diolan_u2c *dev; int ret; + if (hostif->desc.bInterfaceNumber != 0 + || hostif->desc.bNumEndpoints < 2) + return -ENODEV; + /* allocate memory for our device state and initialize it */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (dev == NULL) { - dev_err(&interface->dev, "no memory for device state\n"); ret = -ENOMEM; goto error; } + dev->ep_out = hostif->endpoint[0].desc.bEndpointAddress; + dev->ep_in = hostif->endpoint[1].desc.bEndpointAddress; dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c new file mode 100644 index 00000000000..f7eccd682de --- /dev/null +++ b/drivers/i2c/busses/i2c-efm32.c @@ -0,0 +1,479 @@ +/* + * Copyright (C) 2014 Uwe Kleine-Koenig for Pengutronix + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/clk.h> + +#define DRIVER_NAME "efm32-i2c" + +#define MASK_VAL(mask, val) ((val << __ffs(mask)) & mask) + +#define REG_CTRL 0x00 +#define REG_CTRL_EN 0x00001 +#define REG_CTRL_SLAVE 0x00002 +#define REG_CTRL_AUTOACK 0x00004 +#define REG_CTRL_AUTOSE 0x00008 +#define REG_CTRL_AUTOSN 0x00010 +#define REG_CTRL_ARBDIS 0x00020 +#define REG_CTRL_GCAMEN 0x00040 +#define REG_CTRL_CLHR__MASK 0x00300 +#define REG_CTRL_BITO__MASK 0x03000 +#define REG_CTRL_BITO_OFF 0x00000 +#define REG_CTRL_BITO_40PCC 0x01000 +#define REG_CTRL_BITO_80PCC 0x02000 +#define REG_CTRL_BITO_160PCC 0x03000 +#define REG_CTRL_GIBITO 0x08000 +#define REG_CTRL_CLTO__MASK 0x70000 +#define REG_CTRL_CLTO_OFF 0x00000 + +#define REG_CMD 0x04 +#define REG_CMD_START 0x00001 +#define REG_CMD_STOP 0x00002 +#define REG_CMD_ACK 0x00004 +#define REG_CMD_NACK 0x00008 +#define REG_CMD_CONT 0x00010 +#define REG_CMD_ABORT 0x00020 +#define REG_CMD_CLEARTX 0x00040 +#define REG_CMD_CLEARPC 0x00080 + +#define REG_STATE 0x08 +#define REG_STATE_BUSY 0x00001 +#define REG_STATE_MASTER 0x00002 +#define REG_STATE_TRANSMITTER 0x00004 +#define REG_STATE_NACKED 0x00008 +#define REG_STATE_BUSHOLD 0x00010 +#define REG_STATE_STATE__MASK 0x000e0 +#define REG_STATE_STATE_IDLE 0x00000 +#define REG_STATE_STATE_WAIT 0x00020 +#define REG_STATE_STATE_START 0x00040 +#define REG_STATE_STATE_ADDR 0x00060 +#define REG_STATE_STATE_ADDRACK 0x00080 +#define REG_STATE_STATE_DATA 0x000a0 +#define REG_STATE_STATE_DATAACK 0x000c0 + +#define REG_STATUS 0x0c +#define REG_STATUS_PSTART 0x00001 +#define REG_STATUS_PSTOP 0x00002 +#define REG_STATUS_PACK 0x00004 +#define REG_STATUS_PNACK 0x00008 +#define REG_STATUS_PCONT 0x00010 +#define REG_STATUS_PABORT 0x00020 +#define REG_STATUS_TXC 0x00040 +#define REG_STATUS_TXBL 0x00080 +#define REG_STATUS_RXDATAV 0x00100 + +#define REG_CLKDIV 0x10 +#define REG_CLKDIV_DIV__MASK 0x001ff +#define REG_CLKDIV_DIV(div) MASK_VAL(REG_CLKDIV_DIV__MASK, (div)) + +#define REG_SADDR 0x14 +#define REG_SADDRMASK 0x18 +#define REG_RXDATA 0x1c +#define REG_RXDATAP 0x20 +#define REG_TXDATA 0x24 +#define REG_IF 0x28 +#define REG_IF_START 0x00001 +#define REG_IF_RSTART 0x00002 +#define REG_IF_ADDR 0x00004 +#define REG_IF_TXC 0x00008 +#define REG_IF_TXBL 0x00010 +#define REG_IF_RXDATAV 0x00020 +#define REG_IF_ACK 0x00040 +#define REG_IF_NACK 0x00080 +#define REG_IF_MSTOP 0x00100 +#define REG_IF_ARBLOST 0x00200 +#define REG_IF_BUSERR 0x00400 +#define REG_IF_BUSHOLD 0x00800 +#define REG_IF_TXOF 0x01000 +#define REG_IF_RXUF 0x02000 +#define REG_IF_BITO 0x04000 +#define REG_IF_CLTO 0x08000 +#define REG_IF_SSTOP 0x10000 + +#define REG_IFS 0x2c +#define REG_IFC 0x30 +#define REG_IFC__MASK 0x1ffcf + +#define REG_IEN 0x34 + +#define REG_ROUTE 0x38 +#define REG_ROUTE_SDAPEN 0x00001 +#define REG_ROUTE_SCLPEN 0x00002 +#define REG_ROUTE_LOCATION__MASK 0x00700 +#define REG_ROUTE_LOCATION(n) MASK_VAL(REG_ROUTE_LOCATION__MASK, (n)) + +struct efm32_i2c_ddata { + struct i2c_adapter adapter; + + struct clk *clk; + void __iomem *base; + unsigned int irq; + u8 location; + unsigned long frequency; + + /* transfer data */ + struct completion done; + struct i2c_msg *msgs; + size_t num_msgs; + size_t current_word, current_msg; + int retval; +}; + +static u32 efm32_i2c_read32(struct efm32_i2c_ddata *ddata, unsigned offset) +{ + return readl(ddata->base + offset); +} + +static void efm32_i2c_write32(struct efm32_i2c_ddata *ddata, + unsigned offset, u32 value) +{ + writel(value, ddata->base + offset); +} + +static void efm32_i2c_send_next_msg(struct efm32_i2c_ddata *ddata) +{ + struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; + + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_START); + efm32_i2c_write32(ddata, REG_TXDATA, cur_msg->addr << 1 | + (cur_msg->flags & I2C_M_RD ? 1 : 0)); +} + +static void efm32_i2c_send_next_byte(struct efm32_i2c_ddata *ddata) +{ + struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; + + if (ddata->current_word >= cur_msg->len) { + /* cur_msg completely transferred */ + ddata->current_word = 0; + ddata->current_msg += 1; + + if (ddata->current_msg >= ddata->num_msgs) { + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); + complete(&ddata->done); + } else { + efm32_i2c_send_next_msg(ddata); + } + } else { + efm32_i2c_write32(ddata, REG_TXDATA, + cur_msg->buf[ddata->current_word++]); + } +} + +static void efm32_i2c_recv_next_byte(struct efm32_i2c_ddata *ddata) +{ + struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; + + cur_msg->buf[ddata->current_word] = efm32_i2c_read32(ddata, REG_RXDATA); + ddata->current_word += 1; + if (ddata->current_word >= cur_msg->len) { + /* cur_msg completely transferred */ + ddata->current_word = 0; + ddata->current_msg += 1; + + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_NACK); + + if (ddata->current_msg >= ddata->num_msgs) { + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); + complete(&ddata->done); + } else { + efm32_i2c_send_next_msg(ddata); + } + } else { + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ACK); + } +} + +static irqreturn_t efm32_i2c_irq(int irq, void *dev_id) +{ + struct efm32_i2c_ddata *ddata = dev_id; + struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg]; + u32 irqflag = efm32_i2c_read32(ddata, REG_IF); + u32 state = efm32_i2c_read32(ddata, REG_STATE); + + efm32_i2c_write32(ddata, REG_IFC, irqflag & REG_IFC__MASK); + + switch (state & REG_STATE_STATE__MASK) { + case REG_STATE_STATE_IDLE: + /* arbitration lost? */ + ddata->retval = -EAGAIN; + complete(&ddata->done); + break; + case REG_STATE_STATE_WAIT: + /* + * huh, this shouldn't happen. + * Reset hardware state and get out + */ + ddata->retval = -EIO; + efm32_i2c_write32(ddata, REG_CMD, + REG_CMD_STOP | REG_CMD_ABORT | + REG_CMD_CLEARTX | REG_CMD_CLEARPC); + complete(&ddata->done); + break; + case REG_STATE_STATE_START: + /* "caller" is expected to send an address */ + break; + case REG_STATE_STATE_ADDR: + /* wait for Ack or NAck of slave */ + break; + case REG_STATE_STATE_ADDRACK: + if (state & REG_STATE_NACKED) { + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); + ddata->retval = -ENXIO; + complete(&ddata->done); + } else if (cur_msg->flags & I2C_M_RD) { + /* wait for slave to send first data byte */ + } else { + efm32_i2c_send_next_byte(ddata); + } + break; + case REG_STATE_STATE_DATA: + if (cur_msg->flags & I2C_M_RD) { + efm32_i2c_recv_next_byte(ddata); + } else { + /* wait for Ack or Nack of slave */ + } + break; + case REG_STATE_STATE_DATAACK: + if (state & REG_STATE_NACKED) { + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP); + complete(&ddata->done); + } else { + efm32_i2c_send_next_byte(ddata); + } + } + + return IRQ_HANDLED; +} + +static int efm32_i2c_master_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct efm32_i2c_ddata *ddata = i2c_get_adapdata(adap); + int ret; + + if (ddata->msgs) + return -EBUSY; + + ddata->msgs = msgs; + ddata->num_msgs = num; + ddata->current_word = 0; + ddata->current_msg = 0; + ddata->retval = -EIO; + + reinit_completion(&ddata->done); + + dev_dbg(&ddata->adapter.dev, "state: %08x, status: %08x\n", + efm32_i2c_read32(ddata, REG_STATE), + efm32_i2c_read32(ddata, REG_STATUS)); + + efm32_i2c_send_next_msg(ddata); + + wait_for_completion(&ddata->done); + + if (ddata->current_msg >= ddata->num_msgs) + ret = ddata->num_msgs; + else + ret = ddata->retval; + + return ret; +} + +static u32 efm32_i2c_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm efm32_i2c_algo = { + .master_xfer = efm32_i2c_master_xfer, + .functionality = efm32_i2c_functionality, +}; + +static u32 efm32_i2c_get_configured_location(struct efm32_i2c_ddata *ddata) +{ + u32 reg = efm32_i2c_read32(ddata, REG_ROUTE); + + return (reg & REG_ROUTE_LOCATION__MASK) >> + __ffs(REG_ROUTE_LOCATION__MASK); +} + +static int efm32_i2c_probe(struct platform_device *pdev) +{ + struct efm32_i2c_ddata *ddata; + struct resource *res; + unsigned long rate; + struct device_node *np = pdev->dev.of_node; + u32 location, frequency; + int ret; + u32 clkdiv; + + if (!np) + return -EINVAL; + + ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + platform_set_drvdata(pdev, ddata); + + init_completion(&ddata->done); + strlcpy(ddata->adapter.name, pdev->name, sizeof(ddata->adapter.name)); + ddata->adapter.owner = THIS_MODULE; + ddata->adapter.algo = &efm32_i2c_algo; + ddata->adapter.dev.parent = &pdev->dev; + ddata->adapter.dev.of_node = pdev->dev.of_node; + i2c_set_adapdata(&ddata->adapter, ddata); + + ddata->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(ddata->clk)) { + ret = PTR_ERR(ddata->clk); + dev_err(&pdev->dev, "failed to get clock: %d\n", ret); + return ret; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "failed to determine base address\n"); + return -ENODEV; + } + + if (resource_size(res) < 0x42) { + dev_err(&pdev->dev, "memory resource too small\n"); + return -EINVAL; + } + + ddata->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(ddata->base)) + return PTR_ERR(ddata->base); + + ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "failed to get irq (%d)\n", ret); + if (!ret) + ret = -EINVAL; + return ret; + } + + ddata->irq = ret; + + ret = clk_prepare_enable(ddata->clk); + if (ret < 0) { + dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret); + return ret; + } + + ret = of_property_read_u32(np, "efm32,location", &location); + if (!ret) { + dev_dbg(&pdev->dev, "using location %u\n", location); + } else { + /* default to location configured in hardware */ + location = efm32_i2c_get_configured_location(ddata); + + dev_info(&pdev->dev, "fall back to location %u\n", location); + } + + ddata->location = location; + + ret = of_property_read_u32(np, "clock-frequency", &frequency); + if (!ret) { + dev_dbg(&pdev->dev, "using frequency %u\n", frequency); + } else { + frequency = 100000; + dev_info(&pdev->dev, "defaulting to 100 kHz\n"); + } + ddata->frequency = frequency; + + rate = clk_get_rate(ddata->clk); + if (!rate) { + dev_err(&pdev->dev, "there is no input clock available\n"); + ret = -EINVAL; + goto err_disable_clk; + } + clkdiv = DIV_ROUND_UP(rate, 8 * ddata->frequency) - 1; + if (clkdiv >= 0x200) { + dev_err(&pdev->dev, + "input clock too fast (%lu) to divide down to bus freq (%lu)", + rate, ddata->frequency); + ret = -EINVAL; + goto err_disable_clk; + } + + dev_dbg(&pdev->dev, "input clock = %lu, bus freq = %lu, clkdiv = %lu\n", + rate, ddata->frequency, (unsigned long)clkdiv); + efm32_i2c_write32(ddata, REG_CLKDIV, REG_CLKDIV_DIV(clkdiv)); + + efm32_i2c_write32(ddata, REG_ROUTE, REG_ROUTE_SDAPEN | + REG_ROUTE_SCLPEN | + REG_ROUTE_LOCATION(ddata->location)); + + efm32_i2c_write32(ddata, REG_CTRL, REG_CTRL_EN | + REG_CTRL_BITO_160PCC | 0 * REG_CTRL_GIBITO); + + efm32_i2c_write32(ddata, REG_IFC, REG_IFC__MASK); + efm32_i2c_write32(ddata, REG_IEN, REG_IF_TXC | REG_IF_ACK | REG_IF_NACK + | REG_IF_ARBLOST | REG_IF_BUSERR | REG_IF_RXDATAV); + + /* to make bus idle */ + efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ABORT); + + ret = request_irq(ddata->irq, efm32_i2c_irq, 0, DRIVER_NAME, ddata); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request irq (%d)\n", ret); + return ret; + } + + ret = i2c_add_adapter(&ddata->adapter); + if (ret) { + dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret); + free_irq(ddata->irq, ddata); + +err_disable_clk: + clk_disable_unprepare(ddata->clk); + } + return ret; +} + +static int efm32_i2c_remove(struct platform_device *pdev) +{ + struct efm32_i2c_ddata *ddata = platform_get_drvdata(pdev); + + i2c_del_adapter(&ddata->adapter); + free_irq(ddata->irq, ddata); + clk_disable_unprepare(ddata->clk); + + return 0; +} + +static const struct of_device_id efm32_i2c_dt_ids[] = { + { + .compatible = "energymicro,efm32-i2c", + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(of, efm32_i2c_dt_ids); + +static struct platform_driver efm32_i2c_driver = { + .probe = efm32_i2c_probe, + .remove = efm32_i2c_remove, + + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = efm32_i2c_dt_ids, + }, +}; +module_platform_driver(efm32_i2c_driver); + +MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>"); +MODULE_DESCRIPTION("EFM32 i2c driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index 0f3752967c4..a44ea13d143 100644 --- a/drivers/i2c/busses/i2c-eg20t.c +++ b/drivers/i2c/busses/i2c-eg20t.c @@ -18,7 +18,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/i2c.h> #include <linux/fs.h> @@ -187,7 +186,7 @@ static DEFINE_MUTEX(pch_mutex); #define PCI_DEVICE_ID_ML7223_I2C 0x8010 #define PCI_DEVICE_ID_ML7831_I2C 0x8817 -static DEFINE_PCI_DEVICE_TABLE(pch_pcidev_id) = { +static const struct pci_device_id pch_pcidev_id[] = { { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C), 1, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, }, { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_I2C), 1, }, @@ -312,24 +311,6 @@ static void pch_i2c_start(struct i2c_algo_pch_data *adap) } /** - * pch_i2c_getack() - to confirm ACK/NACK - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static s32 pch_i2c_getack(struct i2c_algo_pch_data *adap) -{ - u32 reg_val; - void __iomem *p = adap->pch_base_address; - reg_val = ioread32(p + PCH_I2CSR) & PCH_GETACK; - - if (reg_val != 0) { - pch_err(adap, "return%d\n", -EPROTO); - return -EPROTO; - } - - return 0; -} - -/** * pch_i2c_stop() - generate stop condition in normal mode. * @adap: Pointer to struct i2c_algo_pch_data. */ @@ -344,6 +325,7 @@ static void pch_i2c_stop(struct i2c_algo_pch_data *adap) static int pch_i2c_wait_for_check_xfer(struct i2c_algo_pch_data *adap) { long ret; + void __iomem *p = adap->pch_base_address; ret = wait_event_timeout(pch_event, (adap->pch_event_flag != 0), msecs_to_jiffies(1000)); @@ -366,10 +348,9 @@ static int pch_i2c_wait_for_check_xfer(struct i2c_algo_pch_data *adap) adap->pch_event_flag = 0; - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave address" - "setting\n"); - return -EIO; + if (ioread32(p + PCH_I2CSR) & PCH_GETACK) { + pch_dbg(adap, "Receive NACK for slave address setting\n"); + return -ENXIO; } return 0; @@ -770,10 +751,8 @@ static int pch_i2c_probe(struct pci_dev *pdev, pch_pci_dbg(pdev, "Entered.\n"); adap_info = kzalloc((sizeof(struct adapter_info)), GFP_KERNEL); - if (adap_info == NULL) { - pch_pci_err(pdev, "Memory allocation FAILED\n"); + if (adap_info == NULL) return -ENOMEM; - } ret = pci_enable_device(pdev); if (ret) { diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c new file mode 100644 index 00000000000..63d22920285 --- /dev/null +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -0,0 +1,811 @@ +/** + * i2c-exynos5.c - Samsung Exynos5 I2C Controller Driver + * + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include <linux/kernel.h> +#include <linux/module.h> + +#include <linux/i2c.h> +#include <linux/time.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/spinlock.h> + +/* + * HSI2C controller from Samsung supports 2 modes of operation + * 1. Auto mode: Where in master automatically controls the whole transaction + * 2. Manual mode: Software controls the transaction by issuing commands + * START, READ, WRITE, STOP, RESTART in I2C_MANUAL_CMD register. + * + * Operation mode can be selected by setting AUTO_MODE bit in I2C_CONF register + * + * Special bits are available for both modes of operation to set commands + * and for checking transfer status + */ + +/* Register Map */ +#define HSI2C_CTL 0x00 +#define HSI2C_FIFO_CTL 0x04 +#define HSI2C_TRAILIG_CTL 0x08 +#define HSI2C_CLK_CTL 0x0C +#define HSI2C_CLK_SLOT 0x10 +#define HSI2C_INT_ENABLE 0x20 +#define HSI2C_INT_STATUS 0x24 +#define HSI2C_ERR_STATUS 0x2C +#define HSI2C_FIFO_STATUS 0x30 +#define HSI2C_TX_DATA 0x34 +#define HSI2C_RX_DATA 0x38 +#define HSI2C_CONF 0x40 +#define HSI2C_AUTO_CONF 0x44 +#define HSI2C_TIMEOUT 0x48 +#define HSI2C_MANUAL_CMD 0x4C +#define HSI2C_TRANS_STATUS 0x50 +#define HSI2C_TIMING_HS1 0x54 +#define HSI2C_TIMING_HS2 0x58 +#define HSI2C_TIMING_HS3 0x5C +#define HSI2C_TIMING_FS1 0x60 +#define HSI2C_TIMING_FS2 0x64 +#define HSI2C_TIMING_FS3 0x68 +#define HSI2C_TIMING_SLA 0x6C +#define HSI2C_ADDR 0x70 + +/* I2C_CTL Register bits */ +#define HSI2C_FUNC_MODE_I2C (1u << 0) +#define HSI2C_MASTER (1u << 3) +#define HSI2C_RXCHON (1u << 6) +#define HSI2C_TXCHON (1u << 7) +#define HSI2C_SW_RST (1u << 31) + +/* I2C_FIFO_CTL Register bits */ +#define HSI2C_RXFIFO_EN (1u << 0) +#define HSI2C_TXFIFO_EN (1u << 1) +#define HSI2C_RXFIFO_TRIGGER_LEVEL(x) ((x) << 4) +#define HSI2C_TXFIFO_TRIGGER_LEVEL(x) ((x) << 16) + +/* I2C_TRAILING_CTL Register bits */ +#define HSI2C_TRAILING_COUNT (0xf) + +/* I2C_INT_EN Register bits */ +#define HSI2C_INT_TX_ALMOSTEMPTY_EN (1u << 0) +#define HSI2C_INT_RX_ALMOSTFULL_EN (1u << 1) +#define HSI2C_INT_TRAILING_EN (1u << 6) +#define HSI2C_INT_I2C_EN (1u << 9) + +/* I2C_INT_STAT Register bits */ +#define HSI2C_INT_TX_ALMOSTEMPTY (1u << 0) +#define HSI2C_INT_RX_ALMOSTFULL (1u << 1) +#define HSI2C_INT_TX_UNDERRUN (1u << 2) +#define HSI2C_INT_TX_OVERRUN (1u << 3) +#define HSI2C_INT_RX_UNDERRUN (1u << 4) +#define HSI2C_INT_RX_OVERRUN (1u << 5) +#define HSI2C_INT_TRAILING (1u << 6) +#define HSI2C_INT_I2C (1u << 9) + +/* I2C_FIFO_STAT Register bits */ +#define HSI2C_RX_FIFO_EMPTY (1u << 24) +#define HSI2C_RX_FIFO_FULL (1u << 23) +#define HSI2C_RX_FIFO_LVL(x) ((x >> 16) & 0x7f) +#define HSI2C_TX_FIFO_EMPTY (1u << 8) +#define HSI2C_TX_FIFO_FULL (1u << 7) +#define HSI2C_TX_FIFO_LVL(x) ((x >> 0) & 0x7f) + +/* I2C_CONF Register bits */ +#define HSI2C_AUTO_MODE (1u << 31) +#define HSI2C_10BIT_ADDR_MODE (1u << 30) +#define HSI2C_HS_MODE (1u << 29) + +/* I2C_AUTO_CONF Register bits */ +#define HSI2C_READ_WRITE (1u << 16) +#define HSI2C_STOP_AFTER_TRANS (1u << 17) +#define HSI2C_MASTER_RUN (1u << 31) + +/* I2C_TIMEOUT Register bits */ +#define HSI2C_TIMEOUT_EN (1u << 31) +#define HSI2C_TIMEOUT_MASK 0xff + +/* I2C_TRANS_STATUS register bits */ +#define HSI2C_MASTER_BUSY (1u << 17) +#define HSI2C_SLAVE_BUSY (1u << 16) +#define HSI2C_TIMEOUT_AUTO (1u << 4) +#define HSI2C_NO_DEV (1u << 3) +#define HSI2C_NO_DEV_ACK (1u << 2) +#define HSI2C_TRANS_ABORT (1u << 1) +#define HSI2C_TRANS_DONE (1u << 0) + +/* I2C_ADDR register bits */ +#define HSI2C_SLV_ADDR_SLV(x) ((x & 0x3ff) << 0) +#define HSI2C_SLV_ADDR_MAS(x) ((x & 0x3ff) << 10) +#define HSI2C_MASTER_ID(x) ((x & 0xff) << 24) +#define MASTER_ID(x) ((x & 0x7) + 0x08) + +/* + * Controller operating frequency, timing values for operation + * are calculated against this frequency + */ +#define HSI2C_HS_TX_CLOCK 1000000 +#define HSI2C_FS_TX_CLOCK 100000 +#define HSI2C_HIGH_SPD 1 +#define HSI2C_FAST_SPD 0 + +#define EXYNOS5_I2C_TIMEOUT (msecs_to_jiffies(1000)) + +struct exynos5_i2c { + struct i2c_adapter adap; + unsigned int suspended:1; + + struct i2c_msg *msg; + struct completion msg_complete; + unsigned int msg_ptr; + + unsigned int irq; + + void __iomem *regs; + struct clk *clk; + struct device *dev; + int state; + + spinlock_t lock; /* IRQ synchronization */ + + /* + * Since the TRANS_DONE bit is cleared on read, and we may read it + * either during an IRQ or after a transaction, keep track of its + * state here. + */ + int trans_done; + + /* Controller operating frequency */ + unsigned int fs_clock; + unsigned int hs_clock; + + /* + * HSI2C Controller can operate in + * 1. High speed upto 3.4Mbps + * 2. Fast speed upto 1Mbps + */ + int speed_mode; + + /* Version of HS-I2C Hardware */ + struct exynos_hsi2c_variant *variant; +}; + +/** + * struct exynos_hsi2c_variant - platform specific HSI2C driver data + * @fifo_depth: the fifo depth supported by the HSI2C module + * + * Specifies platform specific configuration of HSI2C module. + * Note: A structure for driver specific platform data is used for future + * expansion of its usage. + */ +struct exynos_hsi2c_variant { + unsigned int fifo_depth; +}; + +static const struct exynos_hsi2c_variant exynos5250_hsi2c_data = { + .fifo_depth = 64, +}; + +static const struct exynos_hsi2c_variant exynos5260_hsi2c_data = { + .fifo_depth = 16, +}; + +static const struct of_device_id exynos5_i2c_match[] = { + { + .compatible = "samsung,exynos5-hsi2c", + .data = &exynos5250_hsi2c_data + }, { + .compatible = "samsung,exynos5250-hsi2c", + .data = &exynos5250_hsi2c_data + }, { + .compatible = "samsung,exynos5260-hsi2c", + .data = &exynos5260_hsi2c_data + }, {}, +}; +MODULE_DEVICE_TABLE(of, exynos5_i2c_match); + +static inline struct exynos_hsi2c_variant *exynos5_i2c_get_variant + (struct platform_device *pdev) +{ + const struct of_device_id *match; + + match = of_match_node(exynos5_i2c_match, pdev->dev.of_node); + return (struct exynos_hsi2c_variant *)match->data; +} + +static void exynos5_i2c_clr_pend_irq(struct exynos5_i2c *i2c) +{ + writel(readl(i2c->regs + HSI2C_INT_STATUS), + i2c->regs + HSI2C_INT_STATUS); +} + +/* + * exynos5_i2c_set_timing: updates the registers with appropriate + * timing values calculated + * + * Returns 0 on success, -EINVAL if the cycle length cannot + * be calculated. + */ +static int exynos5_i2c_set_timing(struct exynos5_i2c *i2c, int mode) +{ + u32 i2c_timing_s1; + u32 i2c_timing_s2; + u32 i2c_timing_s3; + u32 i2c_timing_sla; + unsigned int t_start_su, t_start_hd; + unsigned int t_stop_su; + unsigned int t_data_su, t_data_hd; + unsigned int t_scl_l, t_scl_h; + unsigned int t_sr_release; + unsigned int t_ftl_cycle; + unsigned int clkin = clk_get_rate(i2c->clk); + unsigned int div, utemp0 = 0, utemp1 = 0, clk_cycle; + unsigned int op_clk = (mode == HSI2C_HIGH_SPD) ? + i2c->hs_clock : i2c->fs_clock; + + /* + * FPCLK / FI2C = + * (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + 8 + 2 * FLT_CYCLE + * utemp0 = (CLK_DIV + 1) * (TSCLK_L + TSCLK_H + 2) + * utemp1 = (TSCLK_L + TSCLK_H + 2) + */ + t_ftl_cycle = (readl(i2c->regs + HSI2C_CONF) >> 16) & 0x7; + utemp0 = (clkin / op_clk) - 8 - 2 * t_ftl_cycle; + + /* CLK_DIV max is 256 */ + for (div = 0; div < 256; div++) { + utemp1 = utemp0 / (div + 1); + + /* + * SCL_L and SCL_H each has max value of 255 + * Hence, For the clk_cycle to the have right value + * utemp1 has to be less then 512 and more than 4. + */ + if ((utemp1 < 512) && (utemp1 > 4)) { + clk_cycle = utemp1 - 2; + break; + } else if (div == 255) { + dev_warn(i2c->dev, "Failed to calculate divisor"); + return -EINVAL; + } + } + + t_scl_l = clk_cycle / 2; + t_scl_h = clk_cycle / 2; + t_start_su = t_scl_l; + t_start_hd = t_scl_l; + t_stop_su = t_scl_l; + t_data_su = t_scl_l / 2; + t_data_hd = t_scl_l / 2; + t_sr_release = clk_cycle; + + i2c_timing_s1 = t_start_su << 24 | t_start_hd << 16 | t_stop_su << 8; + i2c_timing_s2 = t_data_su << 24 | t_scl_l << 8 | t_scl_h << 0; + i2c_timing_s3 = div << 16 | t_sr_release << 0; + i2c_timing_sla = t_data_hd << 0; + + dev_dbg(i2c->dev, "tSTART_SU: %X, tSTART_HD: %X, tSTOP_SU: %X\n", + t_start_su, t_start_hd, t_stop_su); + dev_dbg(i2c->dev, "tDATA_SU: %X, tSCL_L: %X, tSCL_H: %X\n", + t_data_su, t_scl_l, t_scl_h); + dev_dbg(i2c->dev, "nClkDiv: %X, tSR_RELEASE: %X\n", + div, t_sr_release); + dev_dbg(i2c->dev, "tDATA_HD: %X\n", t_data_hd); + + if (mode == HSI2C_HIGH_SPD) { + writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_HS1); + writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_HS2); + writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_HS3); + } else { + writel(i2c_timing_s1, i2c->regs + HSI2C_TIMING_FS1); + writel(i2c_timing_s2, i2c->regs + HSI2C_TIMING_FS2); + writel(i2c_timing_s3, i2c->regs + HSI2C_TIMING_FS3); + } + writel(i2c_timing_sla, i2c->regs + HSI2C_TIMING_SLA); + + return 0; +} + +static int exynos5_hsi2c_clock_setup(struct exynos5_i2c *i2c) +{ + /* + * Configure the Fast speed timing values + * Even the High Speed mode initially starts with Fast mode + */ + if (exynos5_i2c_set_timing(i2c, HSI2C_FAST_SPD)) { + dev_err(i2c->dev, "HSI2C FS Clock set up failed\n"); + return -EINVAL; + } + + /* configure the High speed timing values */ + if (i2c->speed_mode == HSI2C_HIGH_SPD) { + if (exynos5_i2c_set_timing(i2c, HSI2C_HIGH_SPD)) { + dev_err(i2c->dev, "HSI2C HS Clock set up failed\n"); + return -EINVAL; + } + } + + return 0; +} + +/* + * exynos5_i2c_init: configures the controller for I2C functionality + * Programs I2C controller for Master mode operation + */ +static void exynos5_i2c_init(struct exynos5_i2c *i2c) +{ + u32 i2c_conf = readl(i2c->regs + HSI2C_CONF); + u32 i2c_timeout = readl(i2c->regs + HSI2C_TIMEOUT); + + /* Clear to disable Timeout */ + i2c_timeout &= ~HSI2C_TIMEOUT_EN; + writel(i2c_timeout, i2c->regs + HSI2C_TIMEOUT); + + writel((HSI2C_FUNC_MODE_I2C | HSI2C_MASTER), + i2c->regs + HSI2C_CTL); + writel(HSI2C_TRAILING_COUNT, i2c->regs + HSI2C_TRAILIG_CTL); + + if (i2c->speed_mode == HSI2C_HIGH_SPD) { + writel(HSI2C_MASTER_ID(MASTER_ID(i2c->adap.nr)), + i2c->regs + HSI2C_ADDR); + i2c_conf |= HSI2C_HS_MODE; + } + + writel(i2c_conf | HSI2C_AUTO_MODE, i2c->regs + HSI2C_CONF); +} + +static void exynos5_i2c_reset(struct exynos5_i2c *i2c) +{ + u32 i2c_ctl; + + /* Set and clear the bit for reset */ + i2c_ctl = readl(i2c->regs + HSI2C_CTL); + i2c_ctl |= HSI2C_SW_RST; + writel(i2c_ctl, i2c->regs + HSI2C_CTL); + + i2c_ctl = readl(i2c->regs + HSI2C_CTL); + i2c_ctl &= ~HSI2C_SW_RST; + writel(i2c_ctl, i2c->regs + HSI2C_CTL); + + /* We don't expect calculations to fail during the run */ + exynos5_hsi2c_clock_setup(i2c); + /* Initialize the configure registers */ + exynos5_i2c_init(i2c); +} + +/* + * exynos5_i2c_irq: top level IRQ servicing routine + * + * INT_STATUS registers gives the interrupt details. Further, + * FIFO_STATUS or TRANS_STATUS registers are to be check for detailed + * state of the bus. + */ +static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id) +{ + struct exynos5_i2c *i2c = dev_id; + u32 fifo_level, int_status, fifo_status, trans_status; + unsigned char byte; + int len = 0; + + i2c->state = -EINVAL; + + spin_lock(&i2c->lock); + + int_status = readl(i2c->regs + HSI2C_INT_STATUS); + writel(int_status, i2c->regs + HSI2C_INT_STATUS); + fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS); + + /* handle interrupt related to the transfer status */ + if (int_status & HSI2C_INT_I2C) { + trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); + if (trans_status & HSI2C_NO_DEV_ACK) { + dev_dbg(i2c->dev, "No ACK from device\n"); + i2c->state = -ENXIO; + goto stop; + } else if (trans_status & HSI2C_NO_DEV) { + dev_dbg(i2c->dev, "No device\n"); + i2c->state = -ENXIO; + goto stop; + } else if (trans_status & HSI2C_TRANS_ABORT) { + dev_dbg(i2c->dev, "Deal with arbitration lose\n"); + i2c->state = -EAGAIN; + goto stop; + } else if (trans_status & HSI2C_TIMEOUT_AUTO) { + dev_dbg(i2c->dev, "Accessing device timed out\n"); + i2c->state = -EAGAIN; + goto stop; + } else if (trans_status & HSI2C_TRANS_DONE) { + i2c->trans_done = 1; + i2c->state = 0; + } + } + + if ((i2c->msg->flags & I2C_M_RD) && (int_status & + (HSI2C_INT_TRAILING | HSI2C_INT_RX_ALMOSTFULL))) { + fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS); + fifo_level = HSI2C_RX_FIFO_LVL(fifo_status); + len = min(fifo_level, i2c->msg->len - i2c->msg_ptr); + + while (len > 0) { + byte = (unsigned char) + readl(i2c->regs + HSI2C_RX_DATA); + i2c->msg->buf[i2c->msg_ptr++] = byte; + len--; + } + i2c->state = 0; + } else if (int_status & HSI2C_INT_TX_ALMOSTEMPTY) { + fifo_status = readl(i2c->regs + HSI2C_FIFO_STATUS); + fifo_level = HSI2C_TX_FIFO_LVL(fifo_status); + + len = i2c->variant->fifo_depth - fifo_level; + if (len > (i2c->msg->len - i2c->msg_ptr)) + len = i2c->msg->len - i2c->msg_ptr; + + while (len > 0) { + byte = i2c->msg->buf[i2c->msg_ptr++]; + writel(byte, i2c->regs + HSI2C_TX_DATA); + len--; + } + i2c->state = 0; + } + + stop: + if ((i2c->trans_done && (i2c->msg->len == i2c->msg_ptr)) || + (i2c->state < 0)) { + writel(0, i2c->regs + HSI2C_INT_ENABLE); + exynos5_i2c_clr_pend_irq(i2c); + complete(&i2c->msg_complete); + } + + spin_unlock(&i2c->lock); + + return IRQ_HANDLED; +} + +/* + * exynos5_i2c_wait_bus_idle + * + * Wait for the bus to go idle, indicated by the MASTER_BUSY bit being + * cleared. + * + * Returns -EBUSY if the bus cannot be bought to idle + */ +static int exynos5_i2c_wait_bus_idle(struct exynos5_i2c *i2c) +{ + unsigned long stop_time; + u32 trans_status; + + /* wait for 100 milli seconds for the bus to be idle */ + stop_time = jiffies + msecs_to_jiffies(100) + 1; + do { + trans_status = readl(i2c->regs + HSI2C_TRANS_STATUS); + if (!(trans_status & HSI2C_MASTER_BUSY)) + return 0; + + usleep_range(50, 200); + } while (time_before(jiffies, stop_time)); + + return -EBUSY; +} + +/* + * exynos5_i2c_message_start: Configures the bus and starts the xfer + * i2c: struct exynos5_i2c pointer for the current bus + * stop: Enables stop after transfer if set. Set for last transfer of + * in the list of messages. + * + * Configures the bus for read/write function + * Sets chip address to talk to, message length to be sent. + * Enables appropriate interrupts and sends start xfer command. + */ +static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop) +{ + u32 i2c_ctl; + u32 int_en = HSI2C_INT_I2C_EN; + u32 i2c_auto_conf = 0; + u32 fifo_ctl; + unsigned long flags; + unsigned short trig_lvl; + + i2c_ctl = readl(i2c->regs + HSI2C_CTL); + i2c_ctl &= ~(HSI2C_TXCHON | HSI2C_RXCHON); + fifo_ctl = HSI2C_RXFIFO_EN | HSI2C_TXFIFO_EN; + + if (i2c->msg->flags & I2C_M_RD) { + i2c_ctl |= HSI2C_RXCHON; + + i2c_auto_conf = HSI2C_READ_WRITE; + + trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ? + (i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len; + fifo_ctl |= HSI2C_RXFIFO_TRIGGER_LEVEL(trig_lvl); + + int_en |= (HSI2C_INT_RX_ALMOSTFULL_EN | + HSI2C_INT_TRAILING_EN); + } else { + i2c_ctl |= HSI2C_TXCHON; + + trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ? + (i2c->variant->fifo_depth * 1 / 4) : i2c->msg->len; + fifo_ctl |= HSI2C_TXFIFO_TRIGGER_LEVEL(trig_lvl); + + int_en |= HSI2C_INT_TX_ALMOSTEMPTY_EN; + } + + writel(HSI2C_SLV_ADDR_MAS(i2c->msg->addr), i2c->regs + HSI2C_ADDR); + + writel(fifo_ctl, i2c->regs + HSI2C_FIFO_CTL); + writel(i2c_ctl, i2c->regs + HSI2C_CTL); + + + /* + * Enable interrupts before starting the transfer so that we don't + * miss any INT_I2C interrupts. + */ + spin_lock_irqsave(&i2c->lock, flags); + writel(int_en, i2c->regs + HSI2C_INT_ENABLE); + + if (stop == 1) + i2c_auto_conf |= HSI2C_STOP_AFTER_TRANS; + i2c_auto_conf |= i2c->msg->len; + i2c_auto_conf |= HSI2C_MASTER_RUN; + writel(i2c_auto_conf, i2c->regs + HSI2C_AUTO_CONF); + spin_unlock_irqrestore(&i2c->lock, flags); +} + +static int exynos5_i2c_xfer_msg(struct exynos5_i2c *i2c, + struct i2c_msg *msgs, int stop) +{ + unsigned long timeout; + int ret; + + i2c->msg = msgs; + i2c->msg_ptr = 0; + i2c->trans_done = 0; + + reinit_completion(&i2c->msg_complete); + + exynos5_i2c_message_start(i2c, stop); + + timeout = wait_for_completion_timeout(&i2c->msg_complete, + EXYNOS5_I2C_TIMEOUT); + if (timeout == 0) + ret = -ETIMEDOUT; + else + ret = i2c->state; + + /* + * If this is the last message to be transfered (stop == 1) + * Then check if the bus can be brought back to idle. + */ + if (ret == 0 && stop) + ret = exynos5_i2c_wait_bus_idle(i2c); + + if (ret < 0) { + exynos5_i2c_reset(i2c); + if (ret == -ETIMEDOUT) + dev_warn(i2c->dev, "%s timeout\n", + (msgs->flags & I2C_M_RD) ? "rx" : "tx"); + } + + /* Return the state as in interrupt routine */ + return ret; +} + +static int exynos5_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct exynos5_i2c *i2c = adap->algo_data; + int i = 0, ret = 0, stop = 0; + + if (i2c->suspended) { + dev_err(i2c->dev, "HS-I2C is not initialized.\n"); + return -EIO; + } + + clk_prepare_enable(i2c->clk); + + for (i = 0; i < num; i++, msgs++) { + stop = (i == num - 1); + + ret = exynos5_i2c_xfer_msg(i2c, msgs, stop); + + if (ret < 0) + goto out; + } + + if (i == num) { + ret = num; + } else { + /* Only one message, cannot access the device */ + if (i == 1) + ret = -EREMOTEIO; + else + ret = i; + + dev_warn(i2c->dev, "xfer message failed\n"); + } + + out: + clk_disable_unprepare(i2c->clk); + return ret; +} + +static u32 exynos5_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); +} + +static const struct i2c_algorithm exynos5_i2c_algorithm = { + .master_xfer = exynos5_i2c_xfer, + .functionality = exynos5_i2c_func, +}; + +static int exynos5_i2c_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct exynos5_i2c *i2c; + struct resource *mem; + unsigned int op_clock; + int ret; + + i2c = devm_kzalloc(&pdev->dev, sizeof(struct exynos5_i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + if (of_property_read_u32(np, "clock-frequency", &op_clock)) { + i2c->speed_mode = HSI2C_FAST_SPD; + i2c->fs_clock = HSI2C_FS_TX_CLOCK; + } else { + if (op_clock >= HSI2C_HS_TX_CLOCK) { + i2c->speed_mode = HSI2C_HIGH_SPD; + i2c->fs_clock = HSI2C_FS_TX_CLOCK; + i2c->hs_clock = op_clock; + } else { + i2c->speed_mode = HSI2C_FAST_SPD; + i2c->fs_clock = op_clock; + } + } + + strlcpy(i2c->adap.name, "exynos5-i2c", sizeof(i2c->adap.name)); + i2c->adap.owner = THIS_MODULE; + i2c->adap.algo = &exynos5_i2c_algorithm; + i2c->adap.retries = 3; + + i2c->dev = &pdev->dev; + i2c->clk = devm_clk_get(&pdev->dev, "hsi2c"); + if (IS_ERR(i2c->clk)) { + dev_err(&pdev->dev, "cannot get clock\n"); + return -ENOENT; + } + + clk_prepare_enable(i2c->clk); + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(i2c->regs)) { + ret = PTR_ERR(i2c->regs); + goto err_clk; + } + + i2c->adap.dev.of_node = np; + i2c->adap.algo_data = i2c; + i2c->adap.dev.parent = &pdev->dev; + + /* Clear pending interrupts from u-boot or misc causes */ + exynos5_i2c_clr_pend_irq(i2c); + + spin_lock_init(&i2c->lock); + init_completion(&i2c->msg_complete); + + i2c->irq = ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "cannot find HS-I2C IRQ\n"); + ret = -EINVAL; + goto err_clk; + } + + ret = devm_request_irq(&pdev->dev, i2c->irq, exynos5_i2c_irq, + IRQF_NO_SUSPEND | IRQF_ONESHOT, + dev_name(&pdev->dev), i2c); + + if (ret != 0) { + dev_err(&pdev->dev, "cannot request HS-I2C IRQ %d\n", i2c->irq); + goto err_clk; + } + + ret = exynos5_hsi2c_clock_setup(i2c); + if (ret) + goto err_clk; + + i2c->variant = exynos5_i2c_get_variant(pdev); + + exynos5_i2c_reset(i2c); + + ret = i2c_add_adapter(&i2c->adap); + if (ret < 0) { + dev_err(&pdev->dev, "failed to add bus to i2c core\n"); + goto err_clk; + } + + platform_set_drvdata(pdev, i2c); + + err_clk: + clk_disable_unprepare(i2c->clk); + return ret; +} + +static int exynos5_i2c_remove(struct platform_device *pdev) +{ + struct exynos5_i2c *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adap); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int exynos5_i2c_suspend_noirq(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos5_i2c *i2c = platform_get_drvdata(pdev); + + i2c->suspended = 1; + + return 0; +} + +static int exynos5_i2c_resume_noirq(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct exynos5_i2c *i2c = platform_get_drvdata(pdev); + int ret = 0; + + clk_prepare_enable(i2c->clk); + + ret = exynos5_hsi2c_clock_setup(i2c); + if (ret) { + clk_disable_unprepare(i2c->clk); + return ret; + } + + exynos5_i2c_init(i2c); + clk_disable_unprepare(i2c->clk); + i2c->suspended = 0; + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(exynos5_i2c_dev_pm_ops, exynos5_i2c_suspend_noirq, + exynos5_i2c_resume_noirq); + +static struct platform_driver exynos5_i2c_driver = { + .probe = exynos5_i2c_probe, + .remove = exynos5_i2c_remove, + .driver = { + .owner = THIS_MODULE, + .name = "exynos5-hsi2c", + .pm = &exynos5_i2c_dev_pm_ops, + .of_match_table = exynos5_i2c_match, + }, +}; + +module_platform_driver(exynos5_i2c_driver); + +MODULE_DESCRIPTION("Exynos5 HS-I2C Bus driver"); +MODULE_AUTHOR("Naveen Krishna Chatradhi, <ch.naveen@samsung.com>"); +MODULE_AUTHOR("Taekgyun Ko, <taeggyun.ko@samsung.com>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index bfa02c6c2dd..71a45b210a2 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/gpio.h> +#include <linux/of.h> #include <linux/of_gpio.h> struct i2c_gpio_private_data { @@ -93,6 +94,9 @@ static int of_i2c_gpio_get_pins(struct device_node *np, *sda_pin = of_get_gpio(np, 0); *scl_pin = of_get_gpio(np, 1); + if (*sda_pin == -EPROBE_DEFER || *scl_pin == -EPROBE_DEFER) + return -EPROBE_DEFER; + if (!gpio_is_valid(*sda_pin) || !gpio_is_valid(*scl_pin)) { pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", np->full_name, *sda_pin, *scl_pin); @@ -143,24 +147,22 @@ static int i2c_gpio_probe(struct platform_device *pdev) scl_pin = pdata->scl_pin; } - ret = gpio_request(sda_pin, "sda"); + ret = devm_gpio_request(&pdev->dev, sda_pin, "sda"); if (ret) { if (ret == -EINVAL) ret = -EPROBE_DEFER; /* Try again later */ - goto err_request_sda; + return ret; } - ret = gpio_request(scl_pin, "scl"); + ret = devm_gpio_request(&pdev->dev, scl_pin, "scl"); if (ret) { if (ret == -EINVAL) ret = -EPROBE_DEFER; /* Try again later */ - goto err_request_scl; + return ret; } priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto err_add_bus; - } + if (!priv) + return -ENOMEM; adap = &priv->adap; bit_data = &priv->bit_data; pdata = &priv->pdata; @@ -221,7 +223,7 @@ static int i2c_gpio_probe(struct platform_device *pdev) adap->nr = pdev->id; ret = i2c_bit_add_numbered_bus(adap); if (ret) - goto err_add_bus; + return ret; platform_set_drvdata(pdev, priv); @@ -231,13 +233,6 @@ static int i2c_gpio_probe(struct platform_device *pdev) ? ", no clock stretching" : ""); return 0; - -err_add_bus: - gpio_free(scl_pin); -err_request_scl: - gpio_free(sda_pin); -err_request_sda: - return ret; } static int i2c_gpio_remove(struct platform_device *pdev) @@ -251,8 +246,6 @@ static int i2c_gpio_remove(struct platform_device *pdev) pdata = &priv->pdata; i2c_del_adapter(adap); - gpio_free(pdata->scl_pin); - gpio_free(pdata->sda_pin); return 0; } diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index 436b0f25491..512fcfabc18 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c @@ -12,7 +12,6 @@ * of this archive for more details. */ #include <linux/module.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/i2c.h> #include <linux/platform_device.h> diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c index 79c3d9069a4..14d2b76de25 100644 --- a/drivers/i2c/busses/i2c-hydra.c +++ b/drivers/i2c/busses/i2c-hydra.c @@ -27,7 +27,6 @@ #include <linux/types.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> -#include <linux/init.h> #include <linux/io.h> #include <asm/hydra.h> @@ -105,7 +104,7 @@ static struct i2c_adapter hydra_adap = { .algo_data = &hydra_bit_data, }; -static DEFINE_PCI_DEVICE_TABLE(hydra_ids) = { +static const struct pci_device_id hydra_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 4296d172127..6777cd6f877 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -2,7 +2,7 @@ Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com> - Copyright (C) 2007 - 2012 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2007 - 2012 Jean Delvare <jdelvare@suse.de> Copyright (C) 2010 Intel Corporation, David Woodhouse <dwmw2@infradead.org> @@ -59,6 +59,8 @@ Wellsburg (PCH) MS 0x8d7e 32 hard yes yes yes Wellsburg (PCH) MS 0x8d7f 32 hard yes yes yes Coleto Creek (PCH) 0x23b0 32 hard yes yes yes + Wildcat Point-LP (PCH) 0x9ca2 32 hard yes yes yes + BayTrail (SOC) 0x0f12 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -160,6 +162,7 @@ STATUS_ERROR_FLAGS) /* Older devices have their ID defined in <linux/pci_ids.h> */ +#define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 /* Patsburg also has three 'Integrated Device Function' SMBus controllers */ @@ -177,6 +180,7 @@ #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1 0x8d7e #define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2 0x8d7f #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 +#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS 0x9ca2 struct i801_mux_config { char *gpio_chip; @@ -787,7 +791,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = i801_func, }; -static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { +static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) }, @@ -819,6 +823,8 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS2) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS) }, { 0, } }; @@ -1309,8 +1315,7 @@ static void __exit i2c_i801_exit(void) pci_unregister_driver(&i801_driver); } -MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, " - "Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("I801 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c index ff3caa0c28c..274312c96b1 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -36,11 +36,12 @@ #include <linux/ioport.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <asm/irq.h> #include <linux/io.h> #include <linux/i2c.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> #include "i2c-ibm_iic.h" diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index ccf46656bda..aa8bc146718 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -183,6 +183,8 @@ struct imx_i2c_struct { unsigned int disable_delay; int stopped; unsigned int ifdr; /* IMX_I2C_IFDR */ + unsigned int cur_clk; + unsigned int bitrate; const struct imx_i2c_hwdata *hwdata; }; @@ -305,6 +307,48 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) return 0; } +static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) +{ + struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; + unsigned int i2c_clk_rate; + unsigned int div; + int i; + + /* Divider value calculation */ + i2c_clk_rate = clk_get_rate(i2c_imx->clk); + if (i2c_imx->cur_clk == i2c_clk_rate) + return; + else + i2c_imx->cur_clk = i2c_clk_rate; + + div = (i2c_clk_rate + i2c_imx->bitrate - 1) / i2c_imx->bitrate; + if (div < i2c_clk_div[0].div) + i = 0; + else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div) + i = i2c_imx->hwdata->ndivs - 1; + else + for (i = 0; i2c_clk_div[i].div < div; i++); + + /* Store divider value */ + i2c_imx->ifdr = i2c_clk_div[i].val; + + /* + * There dummy delay is calculated. + * It should be about one I2C clock period long. + * This delay is used in I2C bus disable function + * to fix chip hardware bug. + */ + i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div + + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); + +#ifdef CONFIG_I2C_DEBUG_BUS + dev_dbg(&i2c_imx->adapter.dev, "I2C_CLK=%d, REQ DIV=%d\n", + i2c_clk_rate, div); + dev_dbg(&i2c_imx->adapter.dev, "IFDR[IC]=0x%x, REAL DIV=%d\n", + i2c_clk_div[i].val, i2c_clk_div[i].div); +#endif +} + static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) { unsigned int temp = 0; @@ -312,7 +356,11 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - clk_prepare_enable(i2c_imx->clk); + i2c_imx_set_clk(i2c_imx); + + result = clk_prepare_enable(i2c_imx->clk); + if (result) + return result; imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); /* Enable I2C controller */ imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); @@ -365,45 +413,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) clk_disable_unprepare(i2c_imx->clk); } -static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, - unsigned int rate) -{ - struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; - unsigned int i2c_clk_rate; - unsigned int div; - int i; - - /* Divider value calculation */ - i2c_clk_rate = clk_get_rate(i2c_imx->clk); - div = (i2c_clk_rate + rate - 1) / rate; - if (div < i2c_clk_div[0].div) - i = 0; - else if (div > i2c_clk_div[i2c_imx->hwdata->ndivs - 1].div) - i = i2c_imx->hwdata->ndivs - 1; - else - for (i = 0; i2c_clk_div[i].div < div; i++); - - /* Store divider value */ - i2c_imx->ifdr = i2c_clk_div[i].val; - - /* - * There dummy delay is calculated. - * It should be about one I2C clock period long. - * This delay is used in I2C bus disable function - * to fix chip hardware bug. - */ - i2c_imx->disable_delay = (500000U * i2c_clk_div[i].div - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); - - /* dev_dbg() can't be used, because adapter is not yet registered */ -#ifdef CONFIG_I2C_DEBUG_BUS - dev_dbg(&i2c_imx->adapter.dev, "<%s> I2C_CLK=%d, REQ DIV=%d\n", - __func__, i2c_clk_rate, div); - dev_dbg(&i2c_imx->adapter.dev, "<%s> IFDR[IC]=0x%x, REAL DIV=%d\n", - __func__, i2c_clk_div[i].val, i2c_clk_div[i].div); -#endif -} - static irqreturn_t i2c_imx_isr(int irq, void *dev_id) { struct imx_i2c_struct *i2c_imx = dev_id; @@ -456,10 +465,11 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) return 0; } -static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) +static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bool is_lastmsg) { int i, result; unsigned int temp; + int block_data = msgs->flags & I2C_M_RECV_LEN; dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n", @@ -479,7 +489,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) /* setup bus to read data */ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); temp &= ~I2CR_MTX; - if (msgs->len - 1) + + /* + * Reset the I2CR_TXAK flag initially for SMBus block read since the + * length is unknown + */ + if ((msgs->len - 1) || block_data) temp &= ~I2CR_TXAK; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */ @@ -488,19 +503,49 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) /* read data */ for (i = 0; i < msgs->len; i++) { + u8 len = 0; result = i2c_imx_trx_complete(i2c_imx); if (result) return result; - if (i == (msgs->len - 1)) { - /* It must generate STOP before read I2DR to prevent - controller from generating another clock cycle */ + /* + * First byte is the length of remaining packet + * in the SMBus block data read. Add it to + * msgs->len. + */ + if ((!i) && block_data) { + len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) + return -EPROTO; dev_dbg(&i2c_imx->adapter.dev, - "<%s> clear MSTA\n", __func__); - temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); - temp &= ~(I2CR_MSTA | I2CR_MTX); - imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); - i2c_imx->stopped = 1; + "<%s> read length: 0x%X\n", + __func__, len); + msgs->len += len; + } + if (i == (msgs->len - 1)) { + if (is_lastmsg) { + /* + * It must generate STOP before read I2DR to prevent + * controller from generating another clock cycle + */ + dev_dbg(&i2c_imx->adapter.dev, + "<%s> clear MSTA\n", __func__); + temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + temp &= ~(I2CR_MSTA | I2CR_MTX); + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); + i2c_imx_bus_busy(i2c_imx, 0); + i2c_imx->stopped = 1; + } else { + /* + * For i2c master receiver repeat restart operation like: + * read -> repeat MSTA -> read/write + * The controller must set MTX before read the last byte in + * the first read operation, otherwise the first read cost + * one extra clock cycle. + */ + temp = readb(i2c_imx->base + IMX_I2C_I2CR); + temp |= I2CR_MTX; + writeb(temp, i2c_imx->base + IMX_I2C_I2CR); + } } else if (i == (msgs->len - 2)) { dev_dbg(&i2c_imx->adapter.dev, "<%s> set TXAK\n", __func__); @@ -508,7 +553,10 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) temp |= I2CR_TXAK; imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); } - msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); + if ((!i) && block_data) + msgs->buf[0] = len; + else + msgs->buf[i] = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); dev_dbg(&i2c_imx->adapter.dev, "<%s> read byte: B%d=0x%X\n", __func__, i, msgs->buf[i]); @@ -521,6 +569,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, { unsigned int i, temp; int result; + bool is_lastmsg = false; struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); @@ -532,6 +581,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, /* read/write data */ for (i = 0; i < num; i++) { + if (i == num - 1) + is_lastmsg = true; + if (i) { dev_dbg(&i2c_imx->adapter.dev, "<%s> repeated start\n", __func__); @@ -562,7 +614,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, (temp & I2SR_RXAK ? 1 : 0)); #endif if (msgs[i].flags & I2C_M_RD) - result = i2c_imx_read(i2c_imx, &msgs[i]); + result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg); else result = i2c_imx_write(i2c_imx, &msgs[i]); if (result) @@ -581,7 +633,8 @@ fail0: static u32 i2c_imx_func(struct i2c_adapter *adapter) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL + | I2C_FUNC_SMBUS_READ_BLOCK_DATA; } static struct i2c_algorithm i2c_imx_algo = { @@ -589,7 +642,7 @@ static struct i2c_algorithm i2c_imx_algo = { .functionality = i2c_imx_func, }; -static int __init i2c_imx_probe(struct platform_device *pdev) +static int i2c_imx_probe(struct platform_device *pdev) { const struct of_device_id *of_id = of_match_device(i2c_imx_dt_ids, &pdev->dev); @@ -598,14 +651,13 @@ static int __init i2c_imx_probe(struct platform_device *pdev) struct imxi2c_platform_data *pdata = dev_get_platdata(&pdev->dev); void __iomem *base; int irq, ret; - u32 bitrate; dev_dbg(&pdev->dev, "<%s>\n", __func__); irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "can't get irq number\n"); - return -ENOENT; + return irq; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -615,10 +667,8 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_imx = devm_kzalloc(&pdev->dev, sizeof(struct imx_i2c_struct), GFP_KERNEL); - if (!i2c_imx) { - dev_err(&pdev->dev, "can't allocate interface\n"); + if (!i2c_imx) return -ENOMEM; - } if (of_id) i2c_imx->hwdata = of_id->data; @@ -662,12 +712,11 @@ static int __init i2c_imx_probe(struct platform_device *pdev) i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); /* Set up clock divider */ - bitrate = IMX_I2C_BIT_RATE; + i2c_imx->bitrate = IMX_I2C_BIT_RATE; ret = of_property_read_u32(pdev->dev.of_node, - "clock-frequency", &bitrate); + "clock-frequency", &i2c_imx->bitrate); if (ret < 0 && pdata && pdata->bitrate) - bitrate = pdata->bitrate; - i2c_imx_set_clk(i2c_imx, bitrate); + i2c_imx->bitrate = pdata->bitrate; /* Set up chip registers to defaults */ imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, @@ -697,7 +746,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) return 0; /* Return OK */ } -static int __exit i2c_imx_remove(struct platform_device *pdev) +static int i2c_imx_remove(struct platform_device *pdev) { struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); @@ -715,7 +764,8 @@ static int __exit i2c_imx_remove(struct platform_device *pdev) } static struct platform_driver i2c_imx_driver = { - .remove = __exit_p(i2c_imx_remove), + .probe = i2c_imx_probe, + .remove = i2c_imx_remove, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, @@ -726,7 +776,7 @@ static struct platform_driver i2c_imx_driver = { static int __init i2c_adap_imx_init(void) { - return platform_driver_probe(&i2c_imx_driver, i2c_imx_probe); + return platform_driver_register(&i2c_imx_driver); } subsys_initcall(i2c_adap_imx_init); diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c index dd24aa0424a..3d16c2f60a5 100644 --- a/drivers/i2c/busses/i2c-iop3xx.c +++ b/drivers/i2c/busses/i2c-iop3xx.c @@ -34,7 +34,6 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/platform_device.h> #include <linux/i2c.h> diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c index 8c38aaa7417..cf99dbf21fd 100644 --- a/drivers/i2c/busses/i2c-isch.c +++ b/drivers/i2c/busses/i2c-isch.c @@ -33,7 +33,6 @@ #include <linux/stddef.h> #include <linux/ioport.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/io.h> #include <linux/acpi.h> @@ -275,7 +274,8 @@ static int smbus_sch_probe(struct platform_device *dev) if (!res) return -EBUSY; - if (!request_region(res->start, resource_size(res), dev->name)) { + if (!devm_request_region(&dev->dev, res->start, resource_size(res), + dev->name)) { dev_err(&dev->dev, "SMBus region 0x%x already in use!\n", sch_smba); return -EBUSY; @@ -294,7 +294,6 @@ static int smbus_sch_probe(struct platform_device *dev) retval = i2c_add_adapter(&sch_adapter); if (retval) { dev_err(&dev->dev, "Couldn't register adapter!\n"); - release_region(res->start, resource_size(res)); sch_smba = 0; } @@ -303,11 +302,8 @@ static int smbus_sch_probe(struct platform_device *dev) static int smbus_sch_remove(struct platform_device *pdev) { - struct resource *res; if (sch_smba) { i2c_del_adapter(&sch_adapter); - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, resource_size(res)); sch_smba = 0; } diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index 8ed79a086f8..984492553e9 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -62,7 +62,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/pci.h> #include <linux/kernel.h> #include <linux/stddef.h> @@ -183,7 +182,7 @@ struct ismt_priv { /** * ismt_ids - PCI device IDs supported by this driver */ -static DEFINE_PCI_DEVICE_TABLE(ismt_ids) = { +static const struct pci_device_id ismt_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) }, @@ -344,6 +343,7 @@ static int ismt_process_desc(const struct ismt_desc *desc, data->word = dma_buffer[0] | (dma_buffer[1] << 8); break; case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: memcpy(&data->block[1], dma_buffer, desc->rxbytes); data->block[0] = desc->rxbytes; break; @@ -393,6 +393,9 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, desc = &priv->hw[priv->head]; + /* Initialize the DMA buffer */ + memset(priv->dma_buffer, 0, sizeof(priv->dma_buffer)); + /* Initialize the descriptor */ memset(desc, 0, sizeof(struct ismt_desc)); desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, read_write); @@ -506,6 +509,41 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, } break; + case I2C_SMBUS_I2C_BLOCK_DATA: + /* Make sure the length is valid */ + if (data->block[0] < 1) + data->block[0] = 1; + + if (data->block[0] > I2C_SMBUS_BLOCK_MAX) + data->block[0] = I2C_SMBUS_BLOCK_MAX; + + if (read_write == I2C_SMBUS_WRITE) { + /* i2c Block Write */ + dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: WRITE\n"); + dma_size = data->block[0] + 1; + dma_direction = DMA_TO_DEVICE; + desc->wr_len_cmd = dma_size; + desc->control |= ISMT_DESC_I2C; + priv->dma_buffer[0] = command; + memcpy(&priv->dma_buffer[1], &data->block[1], dma_size); + } else { + /* i2c Block Read */ + dev_dbg(dev, "I2C_SMBUS_I2C_BLOCK_DATA: READ\n"); + dma_size = data->block[0]; + dma_direction = DMA_FROM_DEVICE; + desc->rd_len = dma_size; + desc->wr_len_cmd = command; + desc->control |= (ISMT_DESC_I2C | ISMT_DESC_CWRL); + /* + * Per the "Table 15-15. I2C Commands", + * in the External Design Specification (EDS), + * (Document Number: 508084, Revision: 2.0), + * the _rw bit must be 0 + */ + desc->tgtaddr_rw = ISMT_DESC_ADDR_RW(addr, 0); + } + break; + default: dev_err(dev, "Unsupported transaction %d\n", size); @@ -538,7 +576,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, desc->dptr_high = upper_32_bits(dma_addr); } - INIT_COMPLETION(priv->cmp); + reinit_completion(&priv->cmp); /* Add the descriptor */ ismt_submit_desc(priv); @@ -579,6 +617,7 @@ static u32 ismt_func(struct i2c_adapter *adap) I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA | + I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC; } diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index b80c76888ca..6a32aa095f8 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -16,7 +16,8 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h> -#include <linux/init.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/slab.h> @@ -114,7 +115,7 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c) for (k = 9; k; k--) { writeccr(i2c, 0); writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); - udelay(delay_val); + readb(i2c->base + MPC_I2C_DR); writeccr(i2c, CCR_MEN); udelay(delay_val << 1); } diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 7f3a4744349..9f4b775e2e3 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -17,6 +17,7 @@ #include <linux/interrupt.h> #include <linux/mv643xx_i2c.h> #include <linux/platform_device.h> +#include <linux/reset.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_device.h> @@ -97,8 +98,6 @@ enum { enum { MV64XXX_I2C_ACTION_INVALID, MV64XXX_I2C_ACTION_CONTINUE, - MV64XXX_I2C_ACTION_OFFLOAD_SEND_START, - MV64XXX_I2C_ACTION_SEND_START, MV64XXX_I2C_ACTION_SEND_RESTART, MV64XXX_I2C_ACTION_OFFLOAD_RESTART, MV64XXX_I2C_ACTION_SEND_ADDR_1, @@ -149,6 +148,8 @@ struct mv64xxx_i2c_data { bool offload_enabled; /* 5us delay in order to avoid repeated start timing violation */ bool errata_delay; + struct reset_control *rstc; + bool irq_clear_inverted; }; static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { @@ -177,11 +178,6 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, { u32 dir = 0; - drv_data->msg = msg; - drv_data->byte_posn = 0; - drv_data->bytes_left = msg->len; - drv_data->aborting = 0; - drv_data->rc = 0; drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; @@ -204,11 +200,9 @@ static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data) unsigned long ctrl_reg; struct i2c_msg *msg = drv_data->msgs; - drv_data->msg = msg; - drv_data->byte_posn = 0; - drv_data->bytes_left = msg->len; - drv_data->aborting = 0; - drv_data->rc = 0; + if (!drv_data->offload_enabled) + return -EOPNOTSUPP; + /* Only regular transactions can be offloaded */ if ((msg->flags & ~(I2C_M_TEN | I2C_M_RD)) != 0) return -EINVAL; @@ -234,9 +228,9 @@ static int mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data) ctrl_reg |= MV64XXX_I2C_BRIDGE_CONTROL_WR | (msg->len - 1) << MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT; - writel_relaxed(data_reg_lo, + writel(data_reg_lo, drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_LO); - writel_relaxed(data_reg_hi, + writel(data_reg_hi, drv_data->reg_base + MV64XXX_I2C_REG_TX_DATA_HI); } else { @@ -417,6 +411,23 @@ mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) } } +static void mv64xxx_i2c_send_start(struct mv64xxx_i2c_data *drv_data) +{ + drv_data->msg = drv_data->msgs; + drv_data->byte_posn = 0; + drv_data->bytes_left = drv_data->msg->len; + drv_data->aborting = 0; + drv_data->rc = 0; + + /* Can we offload this msg ? */ + if (mv64xxx_i2c_offload_msg(drv_data) < 0) { + /* No, switch to standard path */ + mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, + drv_data->reg_base + drv_data->reg_offsets.control); + } +} + static void mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) { @@ -433,15 +444,8 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) drv_data->msgs++; drv_data->num_msgs--; - if (!(drv_data->offload_enabled && - mv64xxx_i2c_offload_msg(drv_data))) { - drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; - writel(drv_data->cntl_bits, - drv_data->reg_base + drv_data->reg_offsets.control); + mv64xxx_i2c_send_start(drv_data); - /* Setup for the next message */ - mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); - } if (drv_data->errata_delay) udelay(5); @@ -458,17 +462,6 @@ mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) drv_data->reg_base + drv_data->reg_offsets.control); break; - case MV64XXX_I2C_ACTION_OFFLOAD_SEND_START: - if (!mv64xxx_i2c_offload_msg(drv_data)) - break; - else - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - /* FALLTHRU */ - case MV64XXX_I2C_ACTION_SEND_START: - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, - drv_data->reg_base + drv_data->reg_offsets.control); - break; - case MV64XXX_I2C_ACTION_SEND_ADDR_1: writel(drv_data->addr1, drv_data->reg_base + drv_data->reg_offsets.data); @@ -566,6 +559,11 @@ mv64xxx_i2c_intr(int irq, void *dev_id) status = readl(drv_data->reg_base + drv_data->reg_offsets.status); mv64xxx_i2c_fsm(drv_data, status); mv64xxx_i2c_do_action(drv_data); + + if (drv_data->irq_clear_inverted) + writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_IFLG, + drv_data->reg_base + drv_data->reg_offsets.control); + rc = IRQ_HANDLED; } spin_unlock_irqrestore(&drv_data->lock, flags); @@ -625,18 +623,12 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, unsigned long flags; spin_lock_irqsave(&drv_data->lock, flags); - if (drv_data->offload_enabled) { - drv_data->action = MV64XXX_I2C_ACTION_OFFLOAD_SEND_START; - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; - } else { - mv64xxx_i2c_prepare_for_io(drv_data, msg); - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; - } + drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND; + drv_data->send_stop = is_last; drv_data->block = 1; - mv64xxx_i2c_do_action(drv_data); + mv64xxx_i2c_send_start(drv_data); spin_unlock_irqrestore(&drv_data->lock, flags); mv64xxx_i2c_wait_for_completion(drv_data); @@ -689,14 +681,17 @@ static const struct i2c_algorithm mv64xxx_i2c_algo = { ***************************************************************************** */ static const struct of_device_id mv64xxx_i2c_of_match_table[] = { - { .compatible = "allwinner,sun4i-i2c", .data = &mv64xxx_i2c_regs_sun4i}, + { .compatible = "allwinner,sun4i-a10-i2c", .data = &mv64xxx_i2c_regs_sun4i}, + { .compatible = "allwinner,sun6i-a31-i2c", .data = &mv64xxx_i2c_regs_sun4i}, { .compatible = "marvell,mv64xxx-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, { .compatible = "marvell,mv78230-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, + { .compatible = "marvell,mv78230-a0-i2c", .data = &mv64xxx_i2c_regs_mv64xxx}, {} }; MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table); #ifdef CONFIG_OF +#ifdef CONFIG_HAVE_CLK static int mv64xxx_calc_freq(const int tclk, const int n, const int m) { @@ -726,16 +721,12 @@ mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n, return false; return true; } +#endif /* CONFIG_HAVE_CLK */ static int mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, struct device *dev) { - const struct of_device_id *device; - struct device_node *np = dev->of_node; - u32 bus_freq, tclk; - int rc = 0; - /* CLK is mandatory when using DT to describe the i2c bus. We * need to know tclk in order to calculate bus clock * factors. @@ -744,6 +735,11 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, /* Have OF but no CLK */ return -ENODEV; #else + const struct of_device_id *device; + struct device_node *np = dev->of_node; + u32 bus_freq, tclk; + int rc = 0; + if (IS_ERR(drv_data->clk)) { rc = -ENODEV; goto out; @@ -761,6 +757,16 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, } drv_data->irq = irq_of_parse_and_map(np, 0); + drv_data->rstc = devm_reset_control_get_optional(dev, NULL); + if (IS_ERR(drv_data->rstc)) { + if (PTR_ERR(drv_data->rstc) == -EPROBE_DEFER) { + rc = -EPROBE_DEFER; + goto out; + } + } else { + reset_control_deassert(drv_data->rstc); + } + /* Its not yet defined how timeouts will be specified in device tree. * So hard code the value to 1 second. */ @@ -781,6 +787,14 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, drv_data->errata_delay = true; } + if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) { + drv_data->offload_enabled = false; + drv_data->errata_delay = true; + } + + if (of_device_is_compatible(np, "allwinner,sun6i-a31-i2c")) + drv_data->irq_clear_inverted = true; + out: return rc; #endif @@ -843,13 +857,13 @@ mv64xxx_i2c_probe(struct platform_device *pd) } if (drv_data->irq < 0) { rc = -ENXIO; - goto exit_clk; + goto exit_reset; } drv_data->adapter.dev.parent = &pd->dev; drv_data->adapter.algo = &mv64xxx_i2c_algo; drv_data->adapter.owner = THIS_MODULE; - drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED; drv_data->adapter.nr = pd->id; drv_data->adapter.dev.of_node = pd->dev.of_node; platform_set_drvdata(pd, drv_data); @@ -863,7 +877,7 @@ mv64xxx_i2c_probe(struct platform_device *pd) dev_err(&drv_data->adapter.dev, "mv64xxx: Can't register intr handler irq%d: %d\n", drv_data->irq, rc); - goto exit_clk; + goto exit_reset; } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { dev_err(&drv_data->adapter.dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); @@ -874,6 +888,9 @@ mv64xxx_i2c_probe(struct platform_device *pd) exit_free_irq: free_irq(drv_data->irq, drv_data); +exit_reset: + if (!IS_ERR_OR_NULL(drv_data->rstc)) + reset_control_assert(drv_data->rstc); exit_clk: #if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ @@ -892,6 +909,8 @@ mv64xxx_i2c_remove(struct platform_device *dev) i2c_del_adapter(&drv_data->adapter); free_irq(drv_data->irq, drv_data); + if (!IS_ERR_OR_NULL(drv_data->rstc)) + reset_control_assert(drv_data->rstc); #if defined(CONFIG_HAVE_CLK) /* Not all platforms have a clk */ if (!IS_ERR(drv_data->clk)) { @@ -909,7 +928,7 @@ static struct platform_driver mv64xxx_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = MV64XXX_I2C_CTLR_NAME, - .of_match_table = of_match_ptr(mv64xxx_i2c_of_match_table), + .of_match_table = mv64xxx_i2c_of_match_table, }, }; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index f4a01675fa7..7170fc89282 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -1,6 +1,7 @@ /* * Freescale MXS I2C bus driver * + * Copyright (C) 2012-2013 Marek Vasut <marex@denx.de> * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K. * * based on a (non-working) driver which was: @@ -34,10 +35,12 @@ #define MXS_I2C_CTRL0 (0x00) #define MXS_I2C_CTRL0_SET (0x04) +#define MXS_I2C_CTRL0_CLR (0x08) #define MXS_I2C_CTRL0_SFTRST 0x80000000 #define MXS_I2C_CTRL0_RUN 0x20000000 #define MXS_I2C_CTRL0_SEND_NAK_ON_LAST 0x02000000 +#define MXS_I2C_CTRL0_PIO_MODE 0x01000000 #define MXS_I2C_CTRL0_RETAIN_CLOCK 0x00200000 #define MXS_I2C_CTRL0_POST_SEND_STOP 0x00100000 #define MXS_I2C_CTRL0_PRE_SEND_START 0x00080000 @@ -64,13 +67,13 @@ #define MXS_I2C_CTRL1_SLAVE_IRQ 0x01 #define MXS_I2C_STAT (0x50) +#define MXS_I2C_STAT_GOT_A_NAK 0x10000000 #define MXS_I2C_STAT_BUS_BUSY 0x00000800 #define MXS_I2C_STAT_CLK_GEN_BUSY 0x00000400 -#define MXS_I2C_DATA (0xa0) +#define MXS_I2C_DATA(i2c) ((i2c->dev_type == MXS_I2C_V1) ? 0x60 : 0xa0) -#define MXS_I2C_DEBUG0 (0xb0) -#define MXS_I2C_DEBUG0_CLR (0xb8) +#define MXS_I2C_DEBUG0_CLR(i2c) ((i2c->dev_type == MXS_I2C_V1) ? 0x78 : 0xb8) #define MXS_I2C_DEBUG0_DMAREQ 0x80000000 @@ -95,10 +98,17 @@ #define MXS_CMD_I2C_READ (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \ MXS_I2C_CTRL0_MASTER_MODE) +enum mxs_i2c_devtype { + MXS_I2C_UNKNOWN = 0, + MXS_I2C_V1, + MXS_I2C_V2, +}; + /** * struct mxs_i2c_dev - per device, private MXS-I2C data * * @dev: driver model device node + * @dev_type: distinguish i.MX23/i.MX28 features * @regs: IO registers pointer * @cmd_complete: completion object for transaction wait * @cmd_err: error code for last transaction @@ -106,6 +116,7 @@ */ struct mxs_i2c_dev { struct device *dev; + enum mxs_i2c_devtype dev_type; void __iomem *regs; struct completion cmd_complete; int cmd_err; @@ -291,48 +302,11 @@ write_init_pio_fail: return -EINVAL; } -static int mxs_i2c_pio_wait_dmareq(struct mxs_i2c_dev *i2c) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - - while (!(readl(i2c->regs + MXS_I2C_DEBUG0) & - MXS_I2C_DEBUG0_DMAREQ)) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - cond_resched(); - } - - return 0; -} - -static int mxs_i2c_pio_wait_cplt(struct mxs_i2c_dev *i2c, int last) +static int mxs_i2c_pio_wait_xfer_end(struct mxs_i2c_dev *i2c) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); - /* - * We do not use interrupts in the PIO mode. Due to the - * maximum transfer length being 8 bytes in PIO mode, the - * overhead of interrupt would be too large and this would - * neglect the gain from using the PIO mode. - */ - - while (!(readl(i2c->regs + MXS_I2C_CTRL1) & - MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ)) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - cond_resched(); - } - - writel(MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ, - i2c->regs + MXS_I2C_CTRL1_CLR); - - /* - * When ending a transfer with a stop, we have to wait for the bus to - * go idle before we report the transfer as completed. Otherwise the - * start of the next transfer may race with the end of the current one. - */ - while (last && (readl(i2c->regs + MXS_I2C_STAT) & - (MXS_I2C_STAT_BUS_BUSY | MXS_I2C_STAT_CLK_GEN_BUSY))) { + while (readl(i2c->regs + MXS_I2C_CTRL0) & MXS_I2C_CTRL0_RUN) { if (time_after(jiffies, timeout)) return -ETIMEDOUT; cond_resched(); @@ -370,106 +344,215 @@ static void mxs_i2c_pio_trigger_cmd(struct mxs_i2c_dev *i2c, u32 cmd) writel(reg, i2c->regs + MXS_I2C_CTRL0); } +/* + * Start WRITE transaction on the I2C bus. By studying i.MX23 datasheet, + * CTRL0::PIO_MODE bit description clarifies the order in which the registers + * must be written during PIO mode operation. First, the CTRL0 register has + * to be programmed with all the necessary bits but the RUN bit. Then the + * payload has to be written into the DATA register. Finally, the transmission + * is executed by setting the RUN bit in CTRL0. + */ +static void mxs_i2c_pio_trigger_write_cmd(struct mxs_i2c_dev *i2c, u32 cmd, + u32 data) +{ + writel(cmd, i2c->regs + MXS_I2C_CTRL0); + + if (i2c->dev_type == MXS_I2C_V1) + writel(MXS_I2C_CTRL0_PIO_MODE, i2c->regs + MXS_I2C_CTRL0_SET); + + writel(data, i2c->regs + MXS_I2C_DATA(i2c)); + writel(MXS_I2C_CTRL0_RUN, i2c->regs + MXS_I2C_CTRL0_SET); +} + static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, uint32_t flags) { struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap); uint32_t addr_data = msg->addr << 1; uint32_t data = 0; - int i, shifts_left, ret; + int i, ret, xlen = 0, xmit = 0; + uint32_t start; /* Mute IRQs coming from this block. */ writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_CLR); + /* + * MX23 idea: + * - Enable CTRL0::PIO_MODE (1 << 24) + * - Enable CTRL1::ACK_MODE (1 << 27) + * + * WARNING! The MX23 is broken in some way, even if it claims + * to support PIO, when we try to transfer any amount of data + * that is not aligned to 4 bytes, the DMA engine will have + * bits in DEBUG1::DMA_BYTES_ENABLES still set even after the + * transfer. This in turn will mess up the next transfer as + * the block it emit one byte write onto the bus terminated + * with a NAK+STOP. A possible workaround is to reset the IP + * block after every PIO transmission, which might just work. + * + * NOTE: The CTRL0::PIO_MODE description is important, since + * it outlines how the PIO mode is really supposed to work. + */ if (msg->flags & I2C_M_RD) { + /* + * PIO READ transfer: + * + * This transfer MUST be limited to 4 bytes maximum. It is not + * possible to transfer more than four bytes via PIO, since we + * can not in any way make sure we can read the data from the + * DATA register fast enough. Besides, the RX FIFO is only four + * bytes deep, thus we can only really read up to four bytes at + * time. Finally, there is no bit indicating us that new data + * arrived at the FIFO and can thus be fetched from the DATA + * register. + */ + BUG_ON(msg->len > 4); + addr_data |= I2C_SMBUS_READ; /* SELECT command. */ - mxs_i2c_pio_trigger_cmd(i2c, MXS_CMD_I2C_SELECT); + mxs_i2c_pio_trigger_write_cmd(i2c, MXS_CMD_I2C_SELECT, + addr_data); - ret = mxs_i2c_pio_wait_dmareq(i2c); - if (ret) - return ret; - - writel(addr_data, i2c->regs + MXS_I2C_DATA); - writel(MXS_I2C_DEBUG0_DMAREQ, i2c->regs + MXS_I2C_DEBUG0_CLR); - - ret = mxs_i2c_pio_wait_cplt(i2c, 0); - if (ret) - return ret; - - if (mxs_i2c_pio_check_error_state(i2c)) + ret = mxs_i2c_pio_wait_xfer_end(i2c); + if (ret) { + dev_err(i2c->dev, + "PIO: Failed to send SELECT command!\n"); goto cleanup; + } /* READ command. */ mxs_i2c_pio_trigger_cmd(i2c, MXS_CMD_I2C_READ | flags | MXS_I2C_CTRL0_XFER_COUNT(msg->len)); + ret = mxs_i2c_pio_wait_xfer_end(i2c); + if (ret) { + dev_err(i2c->dev, + "PIO: Failed to send SELECT command!\n"); + goto cleanup; + } + + data = readl(i2c->regs + MXS_I2C_DATA(i2c)); for (i = 0; i < msg->len; i++) { - if ((i & 3) == 0) { - ret = mxs_i2c_pio_wait_dmareq(i2c); - if (ret) - return ret; - data = readl(i2c->regs + MXS_I2C_DATA); - writel(MXS_I2C_DEBUG0_DMAREQ, - i2c->regs + MXS_I2C_DEBUG0_CLR); - } msg->buf[i] = data & 0xff; data >>= 8; } } else { + /* + * PIO WRITE transfer: + * + * The code below implements clock stretching to circumvent + * the possibility of kernel not being able to supply data + * fast enough. It is possible to transfer arbitrary amount + * of data using PIO write. + */ addr_data |= I2C_SMBUS_WRITE; - /* WRITE command. */ - mxs_i2c_pio_trigger_cmd(i2c, - MXS_CMD_I2C_WRITE | flags | - MXS_I2C_CTRL0_XFER_COUNT(msg->len + 1)); - /* * The LSB of data buffer is the first byte blasted across * the bus. Higher order bytes follow. Thus the following * filling schematic. */ + data = addr_data << 24; + + /* Start the transfer with START condition. */ + start = MXS_I2C_CTRL0_PRE_SEND_START; + + /* If the transfer is long, use clock stretching. */ + if (msg->len > 3) + start |= MXS_I2C_CTRL0_RETAIN_CLOCK; + for (i = 0; i < msg->len; i++) { data >>= 8; data |= (msg->buf[i] << 24); - if ((i & 3) == 2) { - ret = mxs_i2c_pio_wait_dmareq(i2c); - if (ret) - return ret; - writel(data, i2c->regs + MXS_I2C_DATA); - writel(MXS_I2C_DEBUG0_DMAREQ, - i2c->regs + MXS_I2C_DEBUG0_CLR); + + xmit = 0; + + /* This is the last transfer of the message. */ + if (i + 1 == msg->len) { + /* Add optional STOP flag. */ + start |= flags; + /* Remove RETAIN_CLOCK bit. */ + start &= ~MXS_I2C_CTRL0_RETAIN_CLOCK; + xmit = 1; } - } - shifts_left = 24 - (i & 3) * 8; - if (shifts_left) { - data >>= shifts_left; - ret = mxs_i2c_pio_wait_dmareq(i2c); - if (ret) - return ret; - writel(data, i2c->regs + MXS_I2C_DATA); + /* Four bytes are ready in the "data" variable. */ + if ((i & 3) == 2) + xmit = 1; + + /* Nothing interesting happened, continue stuffing. */ + if (!xmit) + continue; + + /* + * Compute the size of the transfer and shift the + * data accordingly. + * + * i = (4k + 0) .... xlen = 2 + * i = (4k + 1) .... xlen = 3 + * i = (4k + 2) .... xlen = 4 + * i = (4k + 3) .... xlen = 1 + */ + + if ((i % 4) == 3) + xlen = 1; + else + xlen = (i % 4) + 2; + + data >>= (4 - xlen) * 8; + + dev_dbg(i2c->dev, + "PIO: len=%i pos=%i total=%i [W%s%s%s]\n", + xlen, i, msg->len, + start & MXS_I2C_CTRL0_PRE_SEND_START ? "S" : "", + start & MXS_I2C_CTRL0_POST_SEND_STOP ? "E" : "", + start & MXS_I2C_CTRL0_RETAIN_CLOCK ? "C" : ""); + writel(MXS_I2C_DEBUG0_DMAREQ, - i2c->regs + MXS_I2C_DEBUG0_CLR); + i2c->regs + MXS_I2C_DEBUG0_CLR(i2c)); + + mxs_i2c_pio_trigger_write_cmd(i2c, + start | MXS_I2C_CTRL0_MASTER_MODE | + MXS_I2C_CTRL0_DIRECTION | + MXS_I2C_CTRL0_XFER_COUNT(xlen), data); + + /* The START condition is sent only once. */ + start &= ~MXS_I2C_CTRL0_PRE_SEND_START; + + /* Wait for the end of the transfer. */ + ret = mxs_i2c_pio_wait_xfer_end(i2c); + if (ret) { + dev_err(i2c->dev, + "PIO: Failed to finish WRITE cmd!\n"); + break; + } + + /* Check NAK here. */ + ret = readl(i2c->regs + MXS_I2C_STAT) & + MXS_I2C_STAT_GOT_A_NAK; + if (ret) { + ret = -ENXIO; + goto cleanup; + } } } - ret = mxs_i2c_pio_wait_cplt(i2c, flags & MXS_I2C_CTRL0_POST_SEND_STOP); - if (ret) - return ret; - /* make sure we capture any occurred error into cmd_err */ - mxs_i2c_pio_check_error_state(i2c); + ret = mxs_i2c_pio_check_error_state(i2c); cleanup: /* Clear any dangling IRQs and re-enable interrupts. */ writel(MXS_I2C_IRQ_MASK, i2c->regs + MXS_I2C_CTRL1_CLR); writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); - return 0; + /* Clear the PIO_MODE on i.MX23 */ + if (i2c->dev_type == MXS_I2C_V1) + writel(MXS_I2C_CTRL0_PIO_MODE, i2c->regs + MXS_I2C_CTRL0_CLR); + + return ret; } /* @@ -479,8 +562,9 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) { struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap); - int ret, err; + int ret; int flags; + int use_pio = 0; flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0; @@ -491,21 +575,23 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, return -EINVAL; /* - * The current boundary to select between PIO/DMA transfer method - * is set to 8 bytes, transfers shorter than 8 bytes are transfered - * using PIO mode while longer transfers use DMA. The 8 byte border is - * based on this empirical measurement and a lot of previous frobbing. + * The MX28 I2C IP block can only do PIO READ for transfer of to up + * 4 bytes of length. The write transfer is not limited as it can use + * clock stretching to avoid FIFO underruns. */ + if ((msg->flags & I2C_M_RD) && (msg->len <= 4)) + use_pio = 1; + if (!(msg->flags & I2C_M_RD) && (msg->len < 7)) + use_pio = 1; + i2c->cmd_err = 0; - if (0) { /* disable PIO mode until a proper fix is made */ + if (use_pio) { ret = mxs_i2c_pio_setup_xfer(adap, msg, flags); - if (ret) { - err = mxs_i2c_reset(i2c); - if (err) - return err; - } + /* No need to reset the block if NAK was received. */ + if (ret && (ret != -ENXIO)) + mxs_i2c_reset(i2c); } else { - INIT_COMPLETION(i2c->cmd_complete); + reinit_completion(&i2c->cmd_complete); ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); if (ret) return ret; @@ -514,9 +600,11 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, msecs_to_jiffies(1000)); if (ret == 0) goto timeout; + + ret = i2c->cmd_err; } - if (i2c->cmd_err == -ENXIO) { + if (ret == -ENXIO) { /* * If the transfer fails with a NAK from the slave the * controller halts until it gets told to return to idle state. @@ -525,7 +613,19 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, i2c->regs + MXS_I2C_CTRL1_SET); } - ret = i2c->cmd_err; + /* + * WARNING! + * The i.MX23 is strange. After each and every operation, it's I2C IP + * block must be reset, otherwise the IP block will misbehave. This can + * be observed on the bus by the block sending out one single byte onto + * the bus. In case such an error happens, bit 27 will be set in the + * DEBUG0 register. This bit is not documented in the i.MX23 datasheet + * and is marked as "TBD" instead. To reset this bit to a correct state, + * reset the whole block. Since the block reset does not take long, do + * reset the block after every transfer to play safe. + */ + if (i2c->dev_type == MXS_I2C_V1) + mxs_i2c_reset(i2c); dev_dbg(i2c->dev, "Done with err=%d\n", ret); @@ -680,32 +780,51 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c) return 0; } +static struct platform_device_id mxs_i2c_devtype[] = { + { + .name = "imx23-i2c", + .driver_data = MXS_I2C_V1, + }, { + .name = "imx28-i2c", + .driver_data = MXS_I2C_V2, + }, { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, mxs_i2c_devtype); + +static const struct of_device_id mxs_i2c_dt_ids[] = { + { .compatible = "fsl,imx23-i2c", .data = &mxs_i2c_devtype[0], }, + { .compatible = "fsl,imx28-i2c", .data = &mxs_i2c_devtype[1], }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); + static int mxs_i2c_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = + of_match_device(mxs_i2c_dt_ids, &pdev->dev); struct device *dev = &pdev->dev; struct mxs_i2c_dev *i2c; struct i2c_adapter *adap; struct resource *res; - resource_size_t res_size; int err, irq; i2c = devm_kzalloc(dev, sizeof(struct mxs_i2c_dev), GFP_KERNEL); if (!i2c) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - - if (!res || irq < 0) - return -ENOENT; + if (of_id) { + const struct platform_device_id *device_id = of_id->data; + i2c->dev_type = device_id->driver_data; + } - res_size = resource_size(res); - if (!devm_request_mem_region(dev, res->start, res_size, res->name)) - return -EBUSY; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2c->regs)) + return PTR_ERR(i2c->regs); - i2c->regs = devm_ioremap_nocache(dev, res->start, res_size); - if (!i2c->regs) - return -EBUSY; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c); if (err) @@ -768,24 +887,19 @@ static int mxs_i2c_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id mxs_i2c_dt_ids[] = { - { .compatible = "fsl,imx28-i2c", }, - { /* sentinel */ } -}; -MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); - static struct platform_driver mxs_i2c_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = mxs_i2c_dt_ids, }, + .probe = mxs_i2c_probe, .remove = mxs_i2c_remove, }; static int __init mxs_i2c_init(void) { - return platform_driver_probe(&mxs_i2c_driver, mxs_i2c_probe); + return platform_driver_register(&mxs_i2c_driver); } subsys_initcall(mxs_i2c_init); @@ -795,6 +909,7 @@ static void __exit mxs_i2c_exit(void) } module_exit(mxs_i2c_exit); +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); MODULE_DESCRIPTION("MXS I2C Bus Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c index 2ca268d6140..b170bdffb5d 100644 --- a/drivers/i2c/busses/i2c-nforce2-s4985.c +++ b/drivers/i2c/busses/i2c-nforce2-s4985.c @@ -1,7 +1,7 @@ /* * i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard * - * Copyright (C) 2008 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2008 Jean Delvare <jdelvare@suse.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -245,7 +245,7 @@ static void __exit nforce2_s4985_exit(void) "Physical bus restoration failed\n"); } -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("S4985 SMBus multiplexing"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c index ac88f4000cc..ee3a76c7ae9 100644 --- a/drivers/i2c/busses/i2c-nforce2.c +++ b/drivers/i2c/busses/i2c-nforce2.c @@ -51,7 +51,6 @@ #include <linux/kernel.h> #include <linux/stddef.h> #include <linux/ioport.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/delay.h> #include <linux/dmi.h> @@ -307,7 +306,7 @@ static struct i2c_algorithm smbus_algorithm = { }; -static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = { +static const struct pci_device_id nforce2_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) }, diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 8bf9ac01301..0e55d85fd4e 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -22,7 +22,6 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/pm_runtime.h> -#include <linux/platform_data/i2c-nomadik.h> #include <linux/of.h> #include <linux/pinctrl/consumer.h> @@ -104,6 +103,13 @@ /* maximum threshold value */ #define MAX_I2C_FIFO_THRESHOLD 15 +enum i2c_freq_mode { + I2C_FREQ_MODE_STANDARD, /* up to 100 Kb/s */ + I2C_FREQ_MODE_FAST, /* up to 400 Kb/s */ + I2C_FREQ_MODE_HIGH_SPEED, /* up to 3.4 Mb/s */ + I2C_FREQ_MODE_FAST_PLUS, /* up to 1 Mb/s */ +}; + /** * struct i2c_vendor_data - per-vendor variations * @has_mtdws: variant has the MTDWS bit @@ -152,12 +158,15 @@ struct i2c_nmk_client { * @irq: interrupt line for the controller. * @virtbase: virtual io memory area. * @clk: hardware i2c block clock. - * @cfg: machine provided controller configuration. * @cli: holder of client specific data. + * @clk_freq: clock frequency for the operation mode + * @tft: Tx FIFO Threshold in bytes + * @rft: Rx FIFO Threshold in bytes + * @timeout Slave response timeout (ms) + * @sm: speed mode * @stop: stop condition. * @xfer_complete: acknowledge completion for a I2C message. * @result: controller propogated result. - * @busy: Busy doing transfer. */ struct nmk_i2c_dev { struct i2c_vendor_data *vendor; @@ -166,12 +175,15 @@ struct nmk_i2c_dev { int irq; void __iomem *virtbase; struct clk *clk; - struct nmk_i2c_controller cfg; struct i2c_nmk_client cli; + u32 clk_freq; + unsigned char tft; + unsigned char rft; + int timeout; + enum i2c_freq_mode sm; int stop; struct completion xfer_complete; int result; - bool busy; }; /* controller's abort causes */ @@ -340,6 +352,8 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) { u32 brcr1, brcr2; u32 i2c_clk, div; + u32 ns; + u16 slsu; writel(0x0, dev->virtbase + I2C_CR); writel(0x0, dev->virtbase + I2C_HSMCR); @@ -347,25 +361,45 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) writel(0x0, dev->virtbase + I2C_RFTR); writel(0x0, dev->virtbase + I2C_DMAR); + i2c_clk = clk_get_rate(dev->clk); + /* * set the slsu: * * slsu defines the data setup time after SCL clock - * stretching in terms of i2c clk cycles. The - * needed setup time for the three modes are 250ns, - * 100ns, 10ns respectively thus leading to the values - * of 14, 6, 2 for a 48 MHz i2c clk. + * stretching in terms of i2c clk cycles + 1 (zero means + * "wait one cycle"), the needed setup time for the three + * modes are 250ns, 100ns, 10ns respectively. + * + * As the time for one cycle T in nanoseconds is + * T = (1/f) * 1000000000 => + * slsu = cycles / (1000000000 / f) + 1 */ - writel(dev->cfg.slsu << 16, dev->virtbase + I2C_SCR); + ns = DIV_ROUND_UP_ULL(1000000000ULL, i2c_clk); + switch (dev->sm) { + case I2C_FREQ_MODE_FAST: + case I2C_FREQ_MODE_FAST_PLUS: + slsu = DIV_ROUND_UP(100, ns); /* Fast */ + break; + case I2C_FREQ_MODE_HIGH_SPEED: + slsu = DIV_ROUND_UP(10, ns); /* High */ + break; + case I2C_FREQ_MODE_STANDARD: + default: + slsu = DIV_ROUND_UP(250, ns); /* Standard */ + break; + } + slsu += 1; - i2c_clk = clk_get_rate(dev->clk); + dev_dbg(&dev->adev->dev, "calculated SLSU = %04x\n", slsu); + writel(slsu << 16, dev->virtbase + I2C_SCR); /* * The spec says, in case of std. mode the divider is * 2 whereas it is 3 for fast and fastplus mode of * operation. TODO - high speed support. */ - div = (dev->cfg.clk_freq > 100000) ? 3 : 2; + div = (dev->clk_freq > 100000) ? 3 : 2; /* * generate the mask for baud rate counters. The controller @@ -375,7 +409,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) * so set brcr1 to 0. */ brcr1 = 0 << 16; - brcr2 = (i2c_clk/(dev->cfg.clk_freq * div)) & 0xffff; + brcr2 = (i2c_clk/(dev->clk_freq * div)) & 0xffff; /* set the baud rate counter register */ writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); @@ -386,7 +420,7 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) * TODO - support for fast mode plus (up to 1Mb/s) * and high speed (up to 3.4 Mb/s) */ - if (dev->cfg.sm > I2C_FREQ_MODE_FAST) { + if (dev->sm > I2C_FREQ_MODE_FAST) { dev_err(&dev->adev->dev, "do not support this mode defaulting to std. mode\n"); brcr2 = i2c_clk/(100000 * 2) & 0xffff; @@ -394,11 +428,11 @@ static void setup_i2c_controller(struct nmk_i2c_dev *dev) writel(I2C_FREQ_MODE_STANDARD << 4, dev->virtbase + I2C_CR); } - writel(dev->cfg.sm << 4, dev->virtbase + I2C_CR); + writel(dev->sm << 4, dev->virtbase + I2C_CR); /* set the Tx and Rx FIFO threshold */ - writel(dev->cfg.tft, dev->virtbase + I2C_TFTR); - writel(dev->cfg.rft, dev->virtbase + I2C_RFTR); + writel(dev->tft, dev->virtbase + I2C_TFTR); + writel(dev->rft, dev->virtbase + I2C_RFTR); } /** @@ -630,28 +664,13 @@ static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num_msgs) { - int status; + int status = 0; int i; struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap); int j; - dev->busy = true; - pm_runtime_get_sync(&dev->adev->dev); - status = clk_prepare_enable(dev->clk); - if (status) { - dev_err(&dev->adev->dev, "can't prepare_enable clock\n"); - goto out_clk; - } - - /* Optionaly enable pins to be muxed in and configured */ - pinctrl_pm_select_default_state(&dev->adev->dev); - - status = init_hw(dev); - if (status) - goto out; - /* Attempt three times to send the message queue */ for (j = 0; j < 3; j++) { /* setup the i2c controller */ @@ -672,16 +691,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, break; } -out: - clk_disable_unprepare(dev->clk); -out_clk: - /* Optionally let pins go into idle state */ - pinctrl_pm_select_idle_state(&dev->adev->dev); - pm_runtime_put_sync(&dev->adev->dev); - dev->busy = false; - /* return the no. messages processed */ if (status) return status; @@ -865,43 +876,65 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) return IRQ_HANDLED; } +#ifdef CONFIG_PM_SLEEP +static int nmk_i2c_suspend_late(struct device *dev) +{ + int ret; + + ret = pm_runtime_force_suspend(dev); + if (ret) + return ret; + + pinctrl_pm_select_sleep_state(dev); + return 0; +} + +static int nmk_i2c_resume_early(struct device *dev) +{ + return pm_runtime_force_resume(dev); +} +#endif #ifdef CONFIG_PM -static int nmk_i2c_suspend(struct device *dev) +static int nmk_i2c_runtime_suspend(struct device *dev) { struct amba_device *adev = to_amba_device(dev); struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); - if (nmk_i2c->busy) - return -EBUSY; - - pinctrl_pm_select_sleep_state(dev); - + clk_disable_unprepare(nmk_i2c->clk); + pinctrl_pm_select_idle_state(dev); return 0; } -static int nmk_i2c_resume(struct device *dev) +static int nmk_i2c_runtime_resume(struct device *dev) { - /* First go to the default state */ + struct amba_device *adev = to_amba_device(dev); + struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev); + int ret; + + ret = clk_prepare_enable(nmk_i2c->clk); + if (ret) { + dev_err(dev, "can't prepare_enable clock\n"); + return ret; + } + pinctrl_pm_select_default_state(dev); - /* Then let's idle the pins until the next transfer happens */ - pinctrl_pm_select_idle_state(dev); - return 0; + ret = init_hw(nmk_i2c); + if (ret) { + clk_disable_unprepare(nmk_i2c->clk); + pinctrl_pm_select_idle_state(dev); + } + + return ret; } -#else -#define nmk_i2c_suspend NULL -#define nmk_i2c_resume NULL #endif -/* - * We use noirq so that we suspend late and resume before the wakeup interrupt - * to ensure that we do the !pm_runtime_suspended() check in resume before - * there has been a regular pm runtime resume (via pm_runtime_get_sync()). - */ static const struct dev_pm_ops nmk_i2c_pm = { - .suspend_noirq = nmk_i2c_suspend, - .resume_noirq = nmk_i2c_resume, + SET_LATE_SYSTEM_SLEEP_PM_OPS(nmk_i2c_suspend_late, nmk_i2c_resume_early) + SET_PM_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, + nmk_i2c_runtime_resume, + NULL) }; static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) @@ -914,124 +947,98 @@ static const struct i2c_algorithm nmk_i2c_algo = { .functionality = nmk_i2c_functionality }; -static struct nmk_i2c_controller u8500_i2c = { - /* - * Slave data setup time; 250ns, 100ns, and 10ns, which - * is 14, 6 and 2 respectively for a 48Mhz i2c clock. - */ - .slsu = 0xe, - .tft = 1, /* Tx FIFO threshold */ - .rft = 8, /* Rx FIFO threshold */ - .clk_freq = 400000, /* fast mode operation */ - .timeout = 200, /* Slave response timeout(ms) */ - .sm = I2C_FREQ_MODE_FAST, -}; - static void nmk_i2c_of_probe(struct device_node *np, - struct nmk_i2c_controller *pdata) + struct nmk_i2c_dev *nmk) { - of_property_read_u32(np, "clock-frequency", &pdata->clk_freq); + /* Default to 100 kHz if no frequency is given in the node */ + if (of_property_read_u32(np, "clock-frequency", &nmk->clk_freq)) + nmk->clk_freq = 100000; /* This driver only supports 'standard' and 'fast' modes of operation. */ - if (pdata->clk_freq <= 100000) - pdata->sm = I2C_FREQ_MODE_STANDARD; + if (nmk->clk_freq <= 100000) + nmk->sm = I2C_FREQ_MODE_STANDARD; else - pdata->sm = I2C_FREQ_MODE_FAST; + nmk->sm = I2C_FREQ_MODE_FAST; + nmk->tft = 1; /* Tx FIFO threshold */ + nmk->rft = 8; /* Rx FIFO threshold */ + nmk->timeout = 200; /* Slave response timeout(ms) */ } static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) { int ret = 0; - struct nmk_i2c_controller *pdata = dev_get_platdata(&adev->dev); struct device_node *np = adev->dev.of_node; struct nmk_i2c_dev *dev; struct i2c_adapter *adap; struct i2c_vendor_data *vendor = id->data; u32 max_fifo_threshold = (vendor->fifodepth / 2) - 1; - if (!pdata) { - if (np) { - pdata = devm_kzalloc(&adev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - ret = -ENOMEM; - goto err_no_mem; - } - /* Provide the default configuration as a base. */ - memcpy(pdata, &u8500_i2c, sizeof(struct nmk_i2c_controller)); - nmk_i2c_of_probe(np, pdata); - } else - /* No i2c configuration found, using the default. */ - pdata = &u8500_i2c; + dev = devm_kzalloc(&adev->dev, sizeof(struct nmk_i2c_dev), GFP_KERNEL); + if (!dev) { + dev_err(&adev->dev, "cannot allocate memory\n"); + ret = -ENOMEM; + goto err_no_mem; } + dev->vendor = vendor; + dev->adev = adev; + nmk_i2c_of_probe(np, dev); - if (pdata->tft > max_fifo_threshold) { + if (dev->tft > max_fifo_threshold) { dev_warn(&adev->dev, "requested TX FIFO threshold %u, adjusted down to %u\n", - pdata->tft, max_fifo_threshold); - pdata->tft = max_fifo_threshold; + dev->tft, max_fifo_threshold); + dev->tft = max_fifo_threshold; } - if (pdata->rft > max_fifo_threshold) { + if (dev->rft > max_fifo_threshold) { dev_warn(&adev->dev, "requested RX FIFO threshold %u, adjusted down to %u\n", - pdata->rft, max_fifo_threshold); - pdata->rft = max_fifo_threshold; + dev->rft, max_fifo_threshold); + dev->rft = max_fifo_threshold; } - dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); - if (!dev) { - dev_err(&adev->dev, "cannot allocate memory\n"); - ret = -ENOMEM; - goto err_no_mem; - } - dev->vendor = vendor; - dev->busy = false; - dev->adev = adev; amba_set_drvdata(adev, dev); - /* Select default pin state */ - pinctrl_pm_select_default_state(&adev->dev); - /* If possible, let's go to idle until the first transfer */ - pinctrl_pm_select_idle_state(&adev->dev); - - dev->virtbase = ioremap(adev->res.start, resource_size(&adev->res)); + dev->virtbase = devm_ioremap(&adev->dev, adev->res.start, + resource_size(&adev->res)); if (!dev->virtbase) { ret = -ENOMEM; - goto err_no_ioremap; + goto err_no_mem; } dev->irq = adev->irq[0]; - ret = request_irq(dev->irq, i2c_irq_handler, 0, + ret = devm_request_irq(&adev->dev, dev->irq, i2c_irq_handler, 0, DRIVER_NAME, dev); if (ret) { dev_err(&adev->dev, "cannot claim the irq %d\n", dev->irq); - goto err_irq; + goto err_no_mem; } pm_suspend_ignore_children(&adev->dev, true); - dev->clk = clk_get(&adev->dev, NULL); + dev->clk = devm_clk_get(&adev->dev, NULL); if (IS_ERR(dev->clk)) { dev_err(&adev->dev, "could not get i2c clock\n"); ret = PTR_ERR(dev->clk); - goto err_no_clk; + goto err_no_mem; + } + + ret = clk_prepare_enable(dev->clk); + if (ret) { + dev_err(&adev->dev, "can't prepare_enable clock\n"); + goto err_no_mem; } + init_hw(dev); + adap = &dev->adap; adap->dev.of_node = np; adap->dev.parent = &adev->dev; adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED; adap->algo = &nmk_i2c_algo; - adap->timeout = msecs_to_jiffies(pdata->timeout); + adap->timeout = msecs_to_jiffies(dev->timeout); snprintf(adap->name, sizeof(adap->name), "Nomadik I2C at %pR", &adev->res); - /* fetch the controller configuration from machine */ - dev->cfg.clk_freq = pdata->clk_freq; - dev->cfg.slsu = pdata->slsu; - dev->cfg.tft = pdata->tft; - dev->cfg.rft = pdata->rft; - dev->cfg.sm = pdata->sm; - i2c_set_adapdata(adap, dev); dev_info(&adev->dev, @@ -1041,21 +1048,15 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) ret = i2c_add_adapter(adap); if (ret) { dev_err(&adev->dev, "failed to add adapter\n"); - goto err_add_adap; + goto err_no_adap; } pm_runtime_put(&adev->dev); return 0; - err_add_adap: - clk_put(dev->clk); - err_no_clk: - free_irq(dev->irq, dev); - err_irq: - iounmap(dev->virtbase); - err_no_ioremap: - kfree(dev); + err_no_adap: + clk_disable_unprepare(dev->clk); err_no_mem: return ret; @@ -1072,13 +1073,9 @@ static int nmk_i2c_remove(struct amba_device *adev) clear_all_interrupts(dev); /* disable the controller */ i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); - free_irq(dev->irq, dev); - iounmap(dev->virtbase); + clk_disable_unprepare(dev->clk); if (res) release_mem_region(res->start, resource_size(res)); - clk_put(dev->clk); - pm_runtime_disable(&adev->dev); - kfree(dev); return 0; } diff --git a/drivers/i2c/busses/i2c-nuc900.c b/drivers/i2c/busses/i2c-nuc900.c deleted file mode 100644 index 36394d737fa..00000000000 --- a/drivers/i2c/busses/i2c-nuc900.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * linux/drivers/i2c/busses/i2c-nuc900.c - * - * Copyright (c) 2010 Nuvoton technology corporation. - * - * This driver based on S3C2410 I2C driver of Ben Dooks <ben-Y5A6D6n0/KfQXOPxS62xeg@public.gmane.org>. - * Written by Wan ZongShun <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation;version 2 of the License. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/slab.h> -#include <linux/io.h> - -#include <mach/mfp.h> -#include <linux/platform_data/i2c-nuc900.h> - -/* nuc900 i2c registers offset */ - -#define CSR 0x00 -#define DIVIDER 0x04 -#define CMDR 0x08 -#define SWR 0x0C -#define RXR 0x10 -#define TXR 0x14 - -/* nuc900 i2c CSR register bits */ - -#define IRQEN 0x003 -#define I2CBUSY 0x400 -#define I2CSTART 0x018 -#define IRQFLAG 0x004 -#define ARBIT_LOST 0x200 -#define SLAVE_ACK 0x800 - -/* nuc900 i2c CMDR register bits */ - -#define I2C_CMD_START 0x10 -#define I2C_CMD_STOP 0x08 -#define I2C_CMD_READ 0x04 -#define I2C_CMD_WRITE 0x02 -#define I2C_CMD_NACK 0x01 - -/* i2c controller state */ - -enum nuc900_i2c_state { - STATE_IDLE, - STATE_START, - STATE_READ, - STATE_WRITE, - STATE_STOP -}; - -/* i2c controller private data */ - -struct nuc900_i2c { - spinlock_t lock; - wait_queue_head_t wait; - - struct i2c_msg *msg; - unsigned int msg_num; - unsigned int msg_idx; - unsigned int msg_ptr; - unsigned int irq; - - enum nuc900_i2c_state state; - - void __iomem *regs; - struct clk *clk; - struct device *dev; - struct resource *ioarea; - struct i2c_adapter adap; -}; - -/* nuc900_i2c_master_complete - * - * complete the message and wake up the caller, using the given return code, - * or zero to mean ok. -*/ - -static inline void nuc900_i2c_master_complete(struct nuc900_i2c *i2c, int ret) -{ - dev_dbg(i2c->dev, "master_complete %d\n", ret); - - i2c->msg_ptr = 0; - i2c->msg = NULL; - i2c->msg_idx++; - i2c->msg_num = 0; - if (ret) - i2c->msg_idx = ret; - - wake_up(&i2c->wait); -} - -/* irq enable/disable functions */ - -static inline void nuc900_i2c_disable_irq(struct nuc900_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + CSR); - writel(tmp & ~IRQEN, i2c->regs + CSR); -} - -static inline void nuc900_i2c_enable_irq(struct nuc900_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + CSR); - writel(tmp | IRQEN, i2c->regs + CSR); -} - - -/* nuc900_i2c_message_start - * - * put the start of a message onto the bus -*/ - -static void nuc900_i2c_message_start(struct nuc900_i2c *i2c, - struct i2c_msg *msg) -{ - unsigned int addr = (msg->addr & 0x7f) << 1; - - if (msg->flags & I2C_M_RD) - addr |= 0x1; - writel(addr & 0xff, i2c->regs + TXR); - writel(I2C_CMD_START | I2C_CMD_WRITE, i2c->regs + CMDR); -} - -static inline void nuc900_i2c_stop(struct nuc900_i2c *i2c, int ret) -{ - - dev_dbg(i2c->dev, "STOP\n"); - - /* stop the transfer */ - i2c->state = STATE_STOP; - writel(I2C_CMD_STOP, i2c->regs + CMDR); - - nuc900_i2c_master_complete(i2c, ret); - nuc900_i2c_disable_irq(i2c); -} - -/* helper functions to determine the current state in the set of - * messages we are sending -*/ - -/* is_lastmsg() - * - * returns TRUE if the current message is the last in the set -*/ - -static inline int is_lastmsg(struct nuc900_i2c *i2c) -{ - return i2c->msg_idx >= (i2c->msg_num - 1); -} - -/* is_msglast - * - * returns TRUE if we this is the last byte in the current message -*/ - -static inline int is_msglast(struct nuc900_i2c *i2c) -{ - return i2c->msg_ptr == i2c->msg->len-1; -} - -/* is_msgend - * - * returns TRUE if we reached the end of the current message -*/ - -static inline int is_msgend(struct nuc900_i2c *i2c) -{ - return i2c->msg_ptr >= i2c->msg->len; -} - -/* i2c_nuc900_irq_nextbyte - * - * process an interrupt and work out what to do - */ - -static void i2c_nuc900_irq_nextbyte(struct nuc900_i2c *i2c, - unsigned long iicstat) -{ - unsigned char byte; - - switch (i2c->state) { - - case STATE_IDLE: - dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); - break; - - case STATE_STOP: - dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); - nuc900_i2c_disable_irq(i2c); - break; - - case STATE_START: - /* last thing we did was send a start condition on the - * bus, or started a new i2c message - */ - - if (iicstat & SLAVE_ACK && - !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - /* ack was not received... */ - - dev_dbg(i2c->dev, "ack was not received\n"); - nuc900_i2c_stop(i2c, -ENXIO); - break; - } - - if (i2c->msg->flags & I2C_M_RD) - i2c->state = STATE_READ; - else - i2c->state = STATE_WRITE; - - /* terminate the transfer if there is nothing to do - * as this is used by the i2c probe to find devices. - */ - - if (is_lastmsg(i2c) && i2c->msg->len == 0) { - nuc900_i2c_stop(i2c, 0); - break; - } - - if (i2c->state == STATE_READ) - goto prepare_read; - - /* fall through to the write state, as we will need to - * send a byte as well - */ - - case STATE_WRITE: - /* we are writing data to the device... check for the - * end of the message, and if so, work out what to do - */ - - if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - if (iicstat & SLAVE_ACK) { - dev_dbg(i2c->dev, "WRITE: No Ack\n"); - - nuc900_i2c_stop(i2c, -ECONNREFUSED); - break; - } - } - -retry_write: - - if (!is_msgend(i2c)) { - byte = i2c->msg->buf[i2c->msg_ptr++]; - writeb(byte, i2c->regs + TXR); - writel(I2C_CMD_WRITE, i2c->regs + CMDR); - - } else if (!is_lastmsg(i2c)) { - /* we need to go to the next i2c message */ - - dev_dbg(i2c->dev, "WRITE: Next Message\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - - /* check to see if we need to do another message */ - if (i2c->msg->flags & I2C_M_NOSTART) { - - if (i2c->msg->flags & I2C_M_RD) { - /* cannot do this, the controller - * forces us to send a new START - * when we change direction - */ - - nuc900_i2c_stop(i2c, -EINVAL); - } - - goto retry_write; - } else { - /* send the new start */ - nuc900_i2c_message_start(i2c, i2c->msg); - i2c->state = STATE_START; - } - - } else { - /* send stop */ - - nuc900_i2c_stop(i2c, 0); - } - break; - - case STATE_READ: - /* we have a byte of data in the data register, do - * something with it, and then work out whether we are - * going to do any more read/write - */ - - byte = readb(i2c->regs + RXR); - i2c->msg->buf[i2c->msg_ptr++] = byte; - -prepare_read: - if (is_msglast(i2c)) { - /* last byte of buffer */ - - if (is_lastmsg(i2c)) - writel(I2C_CMD_READ | I2C_CMD_NACK, - i2c->regs + CMDR); - - } else if (is_msgend(i2c)) { - /* ok, we've read the entire buffer, see if there - * is anything else we need to do - */ - - if (is_lastmsg(i2c)) { - /* last message, send stop and complete */ - dev_dbg(i2c->dev, "READ: Send Stop\n"); - - nuc900_i2c_stop(i2c, 0); - } else { - /* go to the next transfer */ - dev_dbg(i2c->dev, "READ: Next Transfer\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - - writel(I2C_CMD_READ, i2c->regs + CMDR); - } - - } else { - writel(I2C_CMD_READ, i2c->regs + CMDR); - } - - break; - } -} - -/* nuc900_i2c_irq - * - * top level IRQ servicing routine -*/ - -static irqreturn_t nuc900_i2c_irq(int irqno, void *dev_id) -{ - struct nuc900_i2c *i2c = dev_id; - unsigned long status; - - status = readl(i2c->regs + CSR); - writel(status | IRQFLAG, i2c->regs + CSR); - - if (status & ARBIT_LOST) { - /* deal with arbitration loss */ - dev_err(i2c->dev, "deal with arbitration loss\n"); - goto out; - } - - if (i2c->state == STATE_IDLE) { - dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); - goto out; - } - - /* pretty much this leaves us with the fact that we've - * transmitted or received whatever byte we last sent - */ - - i2c_nuc900_irq_nextbyte(i2c, status); - - out: - return IRQ_HANDLED; -} - - -/* nuc900_i2c_set_master - * - * get the i2c bus for a master transaction -*/ - -static int nuc900_i2c_set_master(struct nuc900_i2c *i2c) -{ - int timeout = 400; - - while (timeout-- > 0) { - if (((readl(i2c->regs + SWR) & I2CSTART) == I2CSTART) && - ((readl(i2c->regs + CSR) & I2CBUSY) == 0)) { - return 0; - } - - msleep(1); - } - - return -ETIMEDOUT; -} - -/* nuc900_i2c_doxfer - * - * this starts an i2c transfer -*/ - -static int nuc900_i2c_doxfer(struct nuc900_i2c *i2c, - struct i2c_msg *msgs, int num) -{ - unsigned long iicstat, timeout; - int spins = 20; - int ret; - - ret = nuc900_i2c_set_master(i2c); - if (ret != 0) { - dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); - ret = -EAGAIN; - goto out; - } - - spin_lock_irq(&i2c->lock); - - i2c->msg = msgs; - i2c->msg_num = num; - i2c->msg_ptr = 0; - i2c->msg_idx = 0; - i2c->state = STATE_START; - - nuc900_i2c_message_start(i2c, msgs); - spin_unlock_irq(&i2c->lock); - - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); - - ret = i2c->msg_idx; - - /* having these next two as dev_err() makes life very - * noisy when doing an i2cdetect - */ - - if (timeout == 0) - dev_dbg(i2c->dev, "timeout\n"); - else if (ret != num) - dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); - - /* ensure the stop has been through the bus */ - - dev_dbg(i2c->dev, "waiting for bus idle\n"); - - /* first, try busy waiting briefly */ - do { - iicstat = readl(i2c->regs + CSR); - } while ((iicstat & I2CBUSY) && --spins); - - /* if that timed out sleep */ - if (!spins) { - msleep(1); - iicstat = readl(i2c->regs + CSR); - } - - if (iicstat & I2CBUSY) - dev_warn(i2c->dev, "timeout waiting for bus idle\n"); - - out: - return ret; -} - -/* nuc900_i2c_xfer - * - * first port of call from the i2c bus code when an message needs - * transferring across the i2c bus. -*/ - -static int nuc900_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct nuc900_i2c *i2c = (struct nuc900_i2c *)adap->algo_data; - int retry; - int ret; - - nuc900_i2c_enable_irq(i2c); - - for (retry = 0; retry < adap->retries; retry++) { - - ret = nuc900_i2c_doxfer(i2c, msgs, num); - - if (ret != -EAGAIN) - return ret; - - dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); - - udelay(100); - } - - return -EREMOTEIO; -} - -/* declare our i2c functionality */ -static u32 nuc900_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART | - I2C_FUNC_PROTOCOL_MANGLING; -} - -/* i2c bus registration info */ - -static const struct i2c_algorithm nuc900_i2c_algorithm = { - .master_xfer = nuc900_i2c_xfer, - .functionality = nuc900_i2c_func, -}; - -/* nuc900_i2c_probe - * - * called by the bus driver when a suitable device is found -*/ - -static int nuc900_i2c_probe(struct platform_device *pdev) -{ - struct nuc900_i2c *i2c; - struct nuc900_platform_i2c *pdata; - struct resource *res; - int ret; - - pdata = dev_get_platdata(&pdev->dev); - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - - i2c = kzalloc(sizeof(struct nuc900_i2c), GFP_KERNEL); - if (!i2c) { - dev_err(&pdev->dev, "no memory for state\n"); - return -ENOMEM; - } - - strlcpy(i2c->adap.name, "nuc900-i2c0", sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &nuc900_i2c_algorithm; - i2c->adap.retries = 2; - i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - - /* find the clock and enable it */ - - i2c->dev = &pdev->dev; - i2c->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - ret = -ENOENT; - goto err_noclk; - } - - dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); - - clk_enable(i2c->clk); - - /* map the registers */ - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err_clk; - } - - i2c->ioarea = request_mem_region(res->start, resource_size(res), - pdev->name); - - if (i2c->ioarea == NULL) { - dev_err(&pdev->dev, "cannot request IO\n"); - ret = -ENXIO; - goto err_clk; - } - - i2c->regs = ioremap(res->start, resource_size(res)); - - if (i2c->regs == NULL) { - dev_err(&pdev->dev, "cannot map IO\n"); - ret = -ENXIO; - goto err_ioarea; - } - - dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", - i2c->regs, i2c->ioarea, res); - - /* setup info block for the i2c core */ - - i2c->adap.algo_data = i2c; - i2c->adap.dev.parent = &pdev->dev; - - mfp_set_groupg(&pdev->dev, NULL); - - clk_get_rate(i2c->clk); - - ret = (i2c->clk.apbfreq)/(pdata->bus_freq * 5) - 1; - writel(ret & 0xffff, i2c->regs + DIVIDER); - - /* find the IRQ for this unit (note, this relies on the init call to - * ensure no current IRQs pending - */ - - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); - goto err_iomap; - } - - ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED, - dev_name(&pdev->dev), i2c); - - if (ret != 0) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - goto err_iomap; - } - - /* Note, previous versions of the driver used i2c_add_adapter() - * to add the bus at any number. We now pass the bus number via - * the platform data, so if unset it will now default to always - * being bus 0. - */ - - i2c->adap.nr = pdata->bus_num; - - ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add bus to i2c core\n"); - goto err_irq; - } - - platform_set_drvdata(pdev, i2c); - - dev_info(&pdev->dev, "%s: NUC900 I2C adapter\n", - dev_name(&i2c->adap.dev)); - return 0; - - err_irq: - free_irq(i2c->irq, i2c); - - err_iomap: - iounmap(i2c->regs); - - err_ioarea: - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - - err_clk: - clk_disable(i2c->clk); - clk_put(i2c->clk); - - err_noclk: - kfree(i2c); - return ret; -} - -/* nuc900_i2c_remove - * - * called when device is removed from the bus -*/ - -static int nuc900_i2c_remove(struct platform_device *pdev) -{ - struct nuc900_i2c *i2c = platform_get_drvdata(pdev); - - i2c_del_adapter(&i2c->adap); - free_irq(i2c->irq, i2c); - - clk_disable(i2c->clk); - clk_put(i2c->clk); - - iounmap(i2c->regs); - - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - kfree(i2c); - - return 0; -} - -static struct platform_driver nuc900_i2c_driver = { - .probe = nuc900_i2c_probe, - .remove = nuc900_i2c_remove, - .driver = { - .owner = THIS_MODULE, - .name = "nuc900-i2c0", - }, -}; - -static int __init i2c_adap_nuc900_init(void) -{ - return platform_driver_register(&nuc900_i2c_driver); -} - -static void __exit i2c_adap_nuc900_exit(void) -{ - platform_driver_unregister(&nuc900_i2c_driver); -} -subsys_initcall(i2c_adap_nuc900_init); -module_exit(i2c_adap_nuc900_exit); - -MODULE_DESCRIPTION("NUC900 I2C Bus driver"); -MODULE_AUTHOR("Wan ZongShun, <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-i2c0"); diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index c61f37a10a0..0e10cc6182f 100644 --- a/drivers/i2c/busses/i2c-ocores.c +++ b/drivers/i2c/busses/i2c-ocores.c @@ -15,7 +15,6 @@ #include <linux/err.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/errno.h> #include <linux/platform_device.h> #include <linux/i2c.h> @@ -247,11 +246,11 @@ static const struct i2c_algorithm ocores_algorithm = { static struct i2c_adapter ocores_adapter = { .owner = THIS_MODULE, .name = "i2c-ocores", - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED, .algo = &ocores_algorithm, }; -static struct of_device_id ocores_i2c_match[] = { +static const struct of_device_id ocores_i2c_match[] = { { .compatible = "opencores,i2c-ocores", .data = (void *)TYPE_OCORES, diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index b929ba271b4..81042b08a94 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -18,7 +18,6 @@ #include <linux/delay.h> #include <linux/sched.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/io.h> #include <linux/of.h> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 6d8308d5dc4..b182793a405 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -266,13 +266,13 @@ static const u8 reg_map_ip_v2[] = { static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, int reg, u16 val) { - __raw_writew(val, i2c_dev->base + + writew_relaxed(val, i2c_dev->base + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) { - return __raw_readw(i2c_dev->base + + return readw_relaxed(i2c_dev->base + (i2c_dev->regs[reg] << i2c_dev->reg_shift)); } @@ -543,7 +543,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR; omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w); - INIT_COMPLETION(dev->cmd_complete); + reinit_completion(&dev->cmd_complete); dev->cmd_err = 0; w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; @@ -636,7 +636,7 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) int r; r = pm_runtime_get_sync(dev->dev); - if (IS_ERR_VALUE(r)) + if (r < 0) goto out; r = omap_i2c_wait_for_bb(dev); @@ -939,6 +939,9 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) /* * ProDB0017052: Clear ARDY bit twice */ + if (stat & OMAP_I2C_STAT_ARDY) + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ARDY); + if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY | @@ -1034,6 +1037,20 @@ static const struct i2c_algorithm omap_i2c_algo = { }; #ifdef CONFIG_OF +static struct omap_i2c_bus_platform_data omap2420_pdata = { + .rev = OMAP_I2C_IP_VERSION_1, + .flags = OMAP_I2C_FLAG_NO_FIFO | + OMAP_I2C_FLAG_SIMPLE_CLOCK | + OMAP_I2C_FLAG_16BIT_DATA_REG | + OMAP_I2C_FLAG_BUS_SHIFT_2, +}; + +static struct omap_i2c_bus_platform_data omap2430_pdata = { + .rev = OMAP_I2C_IP_VERSION_1, + .flags = OMAP_I2C_FLAG_BUS_SHIFT_2 | + OMAP_I2C_FLAG_FORCE_19200_INT_CLK, +}; + static struct omap_i2c_bus_platform_data omap3_pdata = { .rev = OMAP_I2C_IP_VERSION_1, .flags = OMAP_I2C_FLAG_BUS_SHIFT_2, @@ -1052,6 +1069,14 @@ static const struct of_device_id omap_i2c_of_match[] = { .compatible = "ti,omap3-i2c", .data = &omap3_pdata, }, + { + .compatible = "ti,omap2430-i2c", + .data = &omap2430_pdata, + }, + { + .compatible = "ti,omap2420-i2c", + .data = &omap2420_pdata, + }, { }, }; MODULE_DEVICE_TABLE(of, omap_i2c_of_match); @@ -1089,10 +1114,8 @@ omap_i2c_probe(struct platform_device *pdev) } dev = devm_kzalloc(&pdev->dev, sizeof(struct omap_i2c_dev), GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, "Menory allocation failed\n"); + if (!dev) return -ENOMEM; - } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); dev->base = devm_ioremap_resource(&pdev->dev, mem); @@ -1130,16 +1153,16 @@ omap_i2c_probe(struct platform_device *pdev) pm_runtime_use_autosuspend(dev->dev); r = pm_runtime_get_sync(dev->dev); - if (IS_ERR_VALUE(r)) + if (r < 0) goto err_free_mem; /* * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2. * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset. * Also since the omap_i2c_read_reg uses reg_map_ip_* a - * raw_readw is done. + * readw_relaxed is done. */ - rev = __raw_readw(dev->base + 0x04); + rev = readw_relaxed(dev->base + 0x04); dev->scheme = OMAP_I2C_SCHEME(rev); switch (dev->scheme) { @@ -1213,7 +1236,7 @@ omap_i2c_probe(struct platform_device *pdev) adap = &dev->adapter; i2c_set_adapdata(adap, dev); adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED; strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); adap->algo = &omap_i2c_algo; adap->dev.parent = &pdev->dev; @@ -1251,7 +1274,7 @@ static int omap_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&dev->adapter); ret = pm_runtime_get_sync(&pdev->dev); - if (IS_ERR_VALUE(ret)) + if (ret < 0) return ret; omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c index aa957788192..62f55fe624c 100644 --- a/drivers/i2c/busses/i2c-parport-light.c +++ b/drivers/i2c/busses/i2c-parport-light.c @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------ * * i2c-parport-light.c I2C bus over parallel port * * ------------------------------------------------------------------------ * - Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2003-2010 Jean Delvare <jdelvare@suse.de> Based on older i2c-velleman.c driver Copyright (C) 1995-2000 Simon G. Vogl @@ -273,7 +273,7 @@ static void __exit i2c_parport_exit(void) release_region(base, 3); } -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("I2C bus over parallel port (light)"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c index 81d88786962..a27aae2d675 100644 --- a/drivers/i2c/busses/i2c-parport.c +++ b/drivers/i2c/busses/i2c-parport.c @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------ * * i2c-parport.c I2C bus over parallel port * * ------------------------------------------------------------------------ * - Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2003-2011 Jean Delvare <jdelvare@suse.de> Based on older i2c-philips-par.c driver Copyright (C) 1995-2000 Simon G. Vogl @@ -298,7 +298,7 @@ static void __exit i2c_parport_exit(void) parport_unregister_driver(&i2c_parport_driver); } -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("I2C bus over parallel port"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-parport.h b/drivers/i2c/busses/i2c-parport.h index 3fe652302ea..e572f3aac0f 100644 --- a/drivers/i2c/busses/i2c-parport.h +++ b/drivers/i2c/busses/i2c-parport.h @@ -1,7 +1,7 @@ /* ------------------------------------------------------------------------ * * i2c-parport.h I2C bus over parallel port * * ------------------------------------------------------------------------ * - Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2003-2010 Jean Delvare <jdelvare@suse.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 615f632c846..7a9dce43e11 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -401,7 +401,7 @@ static void pasemi_smb_remove(struct pci_dev *dev) kfree(smbus); } -static DEFINE_PCI_DEVICE_TABLE(pasemi_smb_ids) = { +static const struct pci_device_id pasemi_smb_ids[] = { { PCI_DEVICE(0x1959, 0xa003) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c index 39e2755e3f2..845f12598e7 100644 --- a/drivers/i2c/busses/i2c-pca-platform.c +++ b/drivers/i2c/busses/i2c-pca-platform.c @@ -12,7 +12,6 @@ */ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/jiffies.h> diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index a028617b8f1..a6f54ba27e2 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -22,7 +22,7 @@ Intel PIIX4, 440MX Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100 ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800 - AMD Hudson-2, CZ + AMD Hudson-2, ML, CZ SMSC Victory66 Note: we assume there can only be one device, with one or more @@ -38,7 +38,6 @@ #include <linux/ioport.h> #include <linux/i2c.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/dmi.h> #include <linux/acpi.h> #include <linux/io.h> @@ -208,16 +207,16 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, "WARNING: SMBus interface has been FORCEFULLY ENABLED!\n"); } else { dev_err(&PIIX4_dev->dev, - "Host SMBus controller not enabled!\n"); + "SMBus Host Controller not enabled!\n"); release_region(piix4_smba, SMBIOSIZE); return -ENODEV; } } if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2)) - dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus\n"); else if ((temp & 0x0E) == 0) - dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus\n"); else dev_err(&PIIX4_dev->dev, "Illegal Interrupt configuration " "(or code out of date)!\n"); @@ -235,7 +234,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, { unsigned short piix4_smba; unsigned short smba_idx = 0xcd6; - u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en; + u8 smba_en_lo, smba_en_hi, smb_en, smb_en_status; + u8 i2ccfg, i2ccfg_offset = 0x10; /* SB800 and later SMBus does not support forcing address */ if (force || force_addr) { @@ -245,7 +245,15 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, } /* Determine the address of the SMBus areas */ - smb_en = (aux) ? 0x28 : 0x2c; + if ((PIIX4_dev->vendor == PCI_VENDOR_ID_AMD && + PIIX4_dev->device == PCI_DEVICE_ID_AMD_HUDSON2_SMBUS && + PIIX4_dev->revision >= 0x41) || + (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD && + PIIX4_dev->device == 0x790b && + PIIX4_dev->revision >= 0x49)) + smb_en = 0x00; + else + smb_en = (aux) ? 0x28 : 0x2c; if (!request_region(smba_idx, 2, "smba_idx")) { dev_err(&PIIX4_dev->dev, "SMBus base address index region " @@ -258,13 +266,22 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, smba_en_hi = inb_p(smba_idx + 1); release_region(smba_idx, 2); - if ((smba_en_lo & 1) == 0) { + if (!smb_en) { + smb_en_status = smba_en_lo & 0x10; + piix4_smba = smba_en_hi << 8; + if (aux) + piix4_smba |= 0x20; + } else { + smb_en_status = smba_en_lo & 0x01; + piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0; + } + + if (!smb_en_status) { dev_err(&PIIX4_dev->dev, - "Host SMBus controller not enabled!\n"); + "SMBus Host Controller not enabled!\n"); return -ENODEV; } - piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0; if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) return -ENODEV; @@ -277,7 +294,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, /* Aux SMBus does not support IRQ information */ if (aux) { dev_info(&PIIX4_dev->dev, - "SMBus Host Controller at 0x%x\n", piix4_smba); + "Auxiliary SMBus Host Controller at 0x%x\n", + piix4_smba); return piix4_smba; } @@ -292,9 +310,9 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, release_region(piix4_smba + i2ccfg_offset, 1); if (i2ccfg & 1) - dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus\n"); else - dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus\n"); dev_info(&PIIX4_dev->dev, "SMBus Host Controller at 0x%x, revision %d\n", @@ -522,7 +540,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = piix4_func, }; -static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = { +static const struct pci_device_id piix4_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) }, { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) }, diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index f6389e2c9d0..8564768fee3 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c @@ -26,7 +26,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/interrupt.h> diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index 1a9ea25f231..dc7ff829ad7 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -23,6 +23,7 @@ #include <linux/err.h> #include <linux/clk.h> #include <linux/slab.h> +#include <linux/of.h> #define I2C_PNX_TIMEOUT_DEFAULT 10 /* msec */ #define I2C_PNX_SPEED_KHZ_DEFAULT 100 @@ -627,11 +628,9 @@ static int i2c_pnx_probe(struct platform_device *pdev) struct resource *res; u32 speed = I2C_PNX_SPEED_KHZ_DEFAULT * 1000; - alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); - if (!alg_data) { - ret = -ENOMEM; - goto err_kzalloc; - } + alg_data = devm_kzalloc(&pdev->dev, sizeof(*alg_data), GFP_KERNEL); + if (!alg_data) + return -ENOMEM; platform_set_drvdata(pdev, alg_data); @@ -656,11 +655,9 @@ static int i2c_pnx_probe(struct platform_device *pdev) */ } #endif - alg_data->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(alg_data->clk)) { - ret = PTR_ERR(alg_data->clk); - goto out_drvdata; - } + alg_data->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(alg_data->clk)) + return PTR_ERR(alg_data->clk); init_timer(&alg_data->mif.timer); alg_data->mif.timer.function = i2c_pnx_timeout; @@ -671,31 +668,13 @@ static int i2c_pnx_probe(struct platform_device *pdev) /* Register I/O resource */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "Unable to get mem resource.\n"); - ret = -EBUSY; - goto out_clkget; - } - if (!request_mem_region(res->start, I2C_PNX_REGION_SIZE, - pdev->name)) { - dev_err(&pdev->dev, - "I/O region 0x%08x for I2C already in use.\n", - res->start); - ret = -ENOMEM; - goto out_clkget; - } - - alg_data->base = res->start; - alg_data->ioaddr = ioremap(res->start, I2C_PNX_REGION_SIZE); - if (!alg_data->ioaddr) { - dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n"); - ret = -ENOMEM; - goto out_release; - } + alg_data->ioaddr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(alg_data->ioaddr)) + return PTR_ERR(alg_data->ioaddr); ret = clk_enable(alg_data->clk); if (ret) - goto out_unmap; + return ret; freq = clk_get_rate(alg_data->clk); @@ -729,8 +708,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) ret = alg_data->irq; goto out_clock; } - ret = request_irq(alg_data->irq, i2c_pnx_interrupt, - 0, pdev->name, alg_data); + ret = devm_request_irq(&pdev->dev, alg_data->irq, i2c_pnx_interrupt, + 0, pdev->name, alg_data); if (ret) goto out_clock; @@ -738,7 +717,7 @@ static int i2c_pnx_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(&alg_data->adapter); if (ret < 0) { dev_err(&pdev->dev, "I2C: Failed to add bus\n"); - goto out_irq; + goto out_clock; } dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", @@ -746,19 +725,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) return 0; -out_irq: - free_irq(alg_data->irq, alg_data); out_clock: clk_disable(alg_data->clk); -out_unmap: - iounmap(alg_data->ioaddr); -out_release: - release_mem_region(res->start, I2C_PNX_REGION_SIZE); -out_clkget: - clk_put(alg_data->clk); -out_drvdata: - kfree(alg_data); -err_kzalloc: return ret; } @@ -766,13 +734,8 @@ static int i2c_pnx_remove(struct platform_device *pdev) { struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); - free_irq(alg_data->irq, alg_data); i2c_del_adapter(&alg_data->adapter); clk_disable(alg_data->clk); - iounmap(alg_data->ioaddr); - release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); - clk_put(alg_data->clk); - kfree(alg_data); return 0; } diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 37e8cfad625..01e967763c2 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -24,9 +24,9 @@ #include <linux/kernel.h> #include <linux/types.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/device.h> #include <linux/platform_device.h> +#include <linux/of_irq.h> #include <asm/prom.h> #include <asm/pmac_low_i2c.h> diff --git a/drivers/i2c/busses/i2c-puv3.c b/drivers/i2c/busses/i2c-puv3.c index ac80199885b..c83fc3ccdd2 100644 --- a/drivers/i2c/busses/i2c-puv3.c +++ b/drivers/i2c/busses/i2c-puv3.c @@ -17,7 +17,6 @@ #include <linux/types.h> #include <linux/delay.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/clk.h> #include <linux/platform_device.h> #include <linux/io.h> diff --git a/drivers/i2c/busses/i2c-pxa-pci.c b/drivers/i2c/busses/i2c-pxa-pci.c index 9639be86e53..417464e9ea2 100644 --- a/drivers/i2c/busses/i2c-pxa-pci.c +++ b/drivers/i2c/busses/i2c-pxa-pci.c @@ -148,7 +148,7 @@ static void ce4100_i2c_remove(struct pci_dev *dev) kfree(sds); } -static DEFINE_PCI_DEVICE_TABLE(ce4100_i2c_devices) = { +static const struct pci_device_id ce4100_i2c_devices[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)}, { }, }; diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index bbe6dfbc5c0..be671f7a0e0 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1084,7 +1084,7 @@ static const struct i2c_algorithm i2c_pxa_pio_algorithm = { .functionality = i2c_pxa_functionality, }; -static struct of_device_id i2c_pxa_dt_ids[] = { +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_PXA2XX }, diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c new file mode 100644 index 00000000000..2a5efb5b487 --- /dev/null +++ b/drivers/i2c/busses/i2c-qup.c @@ -0,0 +1,768 @@ +/* + * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, Sony Mobile Communications AB. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + +/* QUP Registers */ +#define QUP_CONFIG 0x000 +#define QUP_STATE 0x004 +#define QUP_IO_MODE 0x008 +#define QUP_SW_RESET 0x00c +#define QUP_OPERATIONAL 0x018 +#define QUP_ERROR_FLAGS 0x01c +#define QUP_ERROR_FLAGS_EN 0x020 +#define QUP_HW_VERSION 0x030 +#define QUP_MX_OUTPUT_CNT 0x100 +#define QUP_OUT_FIFO_BASE 0x110 +#define QUP_MX_WRITE_CNT 0x150 +#define QUP_MX_INPUT_CNT 0x200 +#define QUP_MX_READ_CNT 0x208 +#define QUP_IN_FIFO_BASE 0x218 +#define QUP_I2C_CLK_CTL 0x400 +#define QUP_I2C_STATUS 0x404 + +/* QUP States and reset values */ +#define QUP_RESET_STATE 0 +#define QUP_RUN_STATE 1 +#define QUP_PAUSE_STATE 3 +#define QUP_STATE_MASK 3 + +#define QUP_STATE_VALID BIT(2) +#define QUP_I2C_MAST_GEN BIT(4) + +#define QUP_OPERATIONAL_RESET 0x000ff0 +#define QUP_I2C_STATUS_RESET 0xfffffc + +/* QUP OPERATIONAL FLAGS */ +#define QUP_I2C_NACK_FLAG BIT(3) +#define QUP_OUT_NOT_EMPTY BIT(4) +#define QUP_IN_NOT_EMPTY BIT(5) +#define QUP_OUT_FULL BIT(6) +#define QUP_OUT_SVC_FLAG BIT(8) +#define QUP_IN_SVC_FLAG BIT(9) +#define QUP_MX_OUTPUT_DONE BIT(10) +#define QUP_MX_INPUT_DONE BIT(11) + +/* I2C mini core related values */ +#define QUP_CLOCK_AUTO_GATE BIT(13) +#define I2C_MINI_CORE (2 << 8) +#define I2C_N_VAL 15 +/* Most significant word offset in FIFO port */ +#define QUP_MSW_SHIFT (I2C_N_VAL + 1) + +/* Packing/Unpacking words in FIFOs, and IO modes */ +#define QUP_OUTPUT_BLK_MODE (1 << 10) +#define QUP_INPUT_BLK_MODE (1 << 12) +#define QUP_UNPACK_EN BIT(14) +#define QUP_PACK_EN BIT(15) + +#define QUP_REPACK_EN (QUP_UNPACK_EN | QUP_PACK_EN) + +#define QUP_OUTPUT_BLOCK_SIZE(x)(((x) >> 0) & 0x03) +#define QUP_OUTPUT_FIFO_SIZE(x) (((x) >> 2) & 0x07) +#define QUP_INPUT_BLOCK_SIZE(x) (((x) >> 5) & 0x03) +#define QUP_INPUT_FIFO_SIZE(x) (((x) >> 7) & 0x07) + +/* QUP tags */ +#define QUP_TAG_START (1 << 8) +#define QUP_TAG_DATA (2 << 8) +#define QUP_TAG_STOP (3 << 8) +#define QUP_TAG_REC (4 << 8) + +/* Status, Error flags */ +#define I2C_STATUS_WR_BUFFER_FULL BIT(0) +#define I2C_STATUS_BUS_ACTIVE BIT(8) +#define I2C_STATUS_ERROR_MASK 0x38000fc +#define QUP_STATUS_ERROR_FLAGS 0x7c + +#define QUP_READ_LIMIT 256 + +struct qup_i2c_dev { + struct device *dev; + void __iomem *base; + int irq; + struct clk *clk; + struct clk *pclk; + struct i2c_adapter adap; + + int clk_ctl; + int out_fifo_sz; + int in_fifo_sz; + int out_blk_sz; + int in_blk_sz; + + unsigned long one_byte_t; + + struct i2c_msg *msg; + /* Current posion in user message buffer */ + int pos; + /* I2C protocol errors */ + u32 bus_err; + /* QUP core errors */ + u32 qup_err; + + struct completion xfer; +}; + +static irqreturn_t qup_i2c_interrupt(int irq, void *dev) +{ + struct qup_i2c_dev *qup = dev; + u32 bus_err; + u32 qup_err; + u32 opflags; + + bus_err = readl(qup->base + QUP_I2C_STATUS); + qup_err = readl(qup->base + QUP_ERROR_FLAGS); + opflags = readl(qup->base + QUP_OPERATIONAL); + + if (!qup->msg) { + /* Clear Error interrupt */ + writel(QUP_RESET_STATE, qup->base + QUP_STATE); + return IRQ_HANDLED; + } + + bus_err &= I2C_STATUS_ERROR_MASK; + qup_err &= QUP_STATUS_ERROR_FLAGS; + + if (qup_err) { + /* Clear Error interrupt */ + writel(qup_err, qup->base + QUP_ERROR_FLAGS); + goto done; + } + + if (bus_err) { + /* Clear Error interrupt */ + writel(QUP_RESET_STATE, qup->base + QUP_STATE); + goto done; + } + + if (opflags & QUP_IN_SVC_FLAG) + writel(QUP_IN_SVC_FLAG, qup->base + QUP_OPERATIONAL); + + if (opflags & QUP_OUT_SVC_FLAG) + writel(QUP_OUT_SVC_FLAG, qup->base + QUP_OPERATIONAL); + +done: + qup->qup_err = qup_err; + qup->bus_err = bus_err; + complete(&qup->xfer); + return IRQ_HANDLED; +} + +static int qup_i2c_poll_state_mask(struct qup_i2c_dev *qup, + u32 req_state, u32 req_mask) +{ + int retries = 1; + u32 state; + + /* + * State transition takes 3 AHB clocks cycles + 3 I2C master clock + * cycles. So retry once after a 1uS delay. + */ + do { + state = readl(qup->base + QUP_STATE); + + if (state & QUP_STATE_VALID && + (state & req_mask) == req_state) + return 0; + + udelay(1); + } while (retries--); + + return -ETIMEDOUT; +} + +static int qup_i2c_poll_state(struct qup_i2c_dev *qup, u32 req_state) +{ + return qup_i2c_poll_state_mask(qup, req_state, QUP_STATE_MASK); +} + +static int qup_i2c_poll_state_valid(struct qup_i2c_dev *qup) +{ + return qup_i2c_poll_state_mask(qup, 0, 0); +} + +static int qup_i2c_poll_state_i2c_master(struct qup_i2c_dev *qup) +{ + return qup_i2c_poll_state_mask(qup, QUP_I2C_MAST_GEN, QUP_I2C_MAST_GEN); +} + +static int qup_i2c_change_state(struct qup_i2c_dev *qup, u32 state) +{ + if (qup_i2c_poll_state_valid(qup) != 0) + return -EIO; + + writel(state, qup->base + QUP_STATE); + + if (qup_i2c_poll_state(qup, state) != 0) + return -EIO; + return 0; +} + +static int qup_i2c_wait_writeready(struct qup_i2c_dev *qup) +{ + unsigned long timeout; + u32 opflags; + u32 status; + + timeout = jiffies + HZ; + + for (;;) { + opflags = readl(qup->base + QUP_OPERATIONAL); + status = readl(qup->base + QUP_I2C_STATUS); + + if (!(opflags & QUP_OUT_NOT_EMPTY) && + !(status & I2C_STATUS_BUS_ACTIVE)) + return 0; + + if (time_after(jiffies, timeout)) + return -ETIMEDOUT; + + usleep_range(qup->one_byte_t, qup->one_byte_t * 2); + } +} + +static void qup_i2c_set_write_mode(struct qup_i2c_dev *qup, struct i2c_msg *msg) +{ + /* Number of entries to shift out, including the start */ + int total = msg->len + 1; + + if (total < qup->out_fifo_sz) { + /* FIFO mode */ + writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); + writel(total, qup->base + QUP_MX_WRITE_CNT); + } else { + /* BLOCK mode (transfer data on chunks) */ + writel(QUP_OUTPUT_BLK_MODE | QUP_REPACK_EN, + qup->base + QUP_IO_MODE); + writel(total, qup->base + QUP_MX_OUTPUT_CNT); + } +} + +static void qup_i2c_issue_write(struct qup_i2c_dev *qup, struct i2c_msg *msg) +{ + u32 addr = msg->addr << 1; + u32 qup_tag; + u32 opflags; + int idx; + u32 val; + + if (qup->pos == 0) { + val = QUP_TAG_START | addr; + idx = 1; + } else { + val = 0; + idx = 0; + } + + while (qup->pos < msg->len) { + /* Check that there's space in the FIFO for our pair */ + opflags = readl(qup->base + QUP_OPERATIONAL); + if (opflags & QUP_OUT_FULL) + break; + + if (qup->pos == msg->len - 1) + qup_tag = QUP_TAG_STOP; + else + qup_tag = QUP_TAG_DATA; + + if (idx & 1) + val |= (qup_tag | msg->buf[qup->pos]) << QUP_MSW_SHIFT; + else + val = qup_tag | msg->buf[qup->pos]; + + /* Write out the pair and the last odd value */ + if (idx & 1 || qup->pos == msg->len - 1) + writel(val, qup->base + QUP_OUT_FIFO_BASE); + + qup->pos++; + idx++; + } +} + +static int qup_i2c_write_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) +{ + unsigned long left; + int ret; + + qup->msg = msg; + qup->pos = 0; + + enable_irq(qup->irq); + + qup_i2c_set_write_mode(qup, msg); + + ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + if (ret) + goto err; + + writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); + + do { + ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); + if (ret) + goto err; + + qup_i2c_issue_write(qup, msg); + + ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + if (ret) + goto err; + + left = wait_for_completion_timeout(&qup->xfer, HZ); + if (!left) { + writel(1, qup->base + QUP_SW_RESET); + ret = -ETIMEDOUT; + goto err; + } + + if (qup->bus_err || qup->qup_err) { + if (qup->bus_err & QUP_I2C_NACK_FLAG) + dev_err(qup->dev, "NACK from %x\n", msg->addr); + ret = -EIO; + goto err; + } + } while (qup->pos < msg->len); + + /* Wait for the outstanding data in the fifo to drain */ + ret = qup_i2c_wait_writeready(qup); + +err: + disable_irq(qup->irq); + qup->msg = NULL; + + return ret; +} + +static void qup_i2c_set_read_mode(struct qup_i2c_dev *qup, int len) +{ + if (len < qup->in_fifo_sz) { + /* FIFO mode */ + writel(QUP_REPACK_EN, qup->base + QUP_IO_MODE); + writel(len, qup->base + QUP_MX_READ_CNT); + } else { + /* BLOCK mode (transfer data on chunks) */ + writel(QUP_INPUT_BLK_MODE | QUP_REPACK_EN, + qup->base + QUP_IO_MODE); + writel(len, qup->base + QUP_MX_INPUT_CNT); + } +} + +static void qup_i2c_issue_read(struct qup_i2c_dev *qup, struct i2c_msg *msg) +{ + u32 addr, len, val; + + addr = (msg->addr << 1) | 1; + + /* 0 is used to specify a length 256 (QUP_READ_LIMIT) */ + len = (msg->len == QUP_READ_LIMIT) ? 0 : msg->len; + + val = ((QUP_TAG_REC | len) << QUP_MSW_SHIFT) | QUP_TAG_START | addr; + writel(val, qup->base + QUP_OUT_FIFO_BASE); +} + + +static void qup_i2c_read_fifo(struct qup_i2c_dev *qup, struct i2c_msg *msg) +{ + u32 opflags; + u32 val = 0; + int idx; + + for (idx = 0; qup->pos < msg->len; idx++) { + if ((idx & 1) == 0) { + /* Check that FIFO have data */ + opflags = readl(qup->base + QUP_OPERATIONAL); + if (!(opflags & QUP_IN_NOT_EMPTY)) + break; + + /* Reading 2 words at time */ + val = readl(qup->base + QUP_IN_FIFO_BASE); + + msg->buf[qup->pos++] = val & 0xFF; + } else { + msg->buf[qup->pos++] = val >> QUP_MSW_SHIFT; + } + } +} + +static int qup_i2c_read_one(struct qup_i2c_dev *qup, struct i2c_msg *msg) +{ + unsigned long left; + int ret; + + /* + * The QUP block will issue a NACK and STOP on the bus when reaching + * the end of the read, the length of the read is specified as one byte + * which limits the possible read to 256 (QUP_READ_LIMIT) bytes. + */ + if (msg->len > QUP_READ_LIMIT) { + dev_err(qup->dev, "HW not capable of reads over %d bytes\n", + QUP_READ_LIMIT); + return -EINVAL; + } + + qup->msg = msg; + qup->pos = 0; + + enable_irq(qup->irq); + + qup_i2c_set_read_mode(qup, msg->len); + + ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + if (ret) + goto err; + + writel(qup->clk_ctl, qup->base + QUP_I2C_CLK_CTL); + + ret = qup_i2c_change_state(qup, QUP_PAUSE_STATE); + if (ret) + goto err; + + qup_i2c_issue_read(qup, msg); + + ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + if (ret) + goto err; + + do { + left = wait_for_completion_timeout(&qup->xfer, HZ); + if (!left) { + writel(1, qup->base + QUP_SW_RESET); + ret = -ETIMEDOUT; + goto err; + } + + if (qup->bus_err || qup->qup_err) { + if (qup->bus_err & QUP_I2C_NACK_FLAG) + dev_err(qup->dev, "NACK from %x\n", msg->addr); + ret = -EIO; + goto err; + } + + qup_i2c_read_fifo(qup, msg); + } while (qup->pos < msg->len); + +err: + disable_irq(qup->irq); + qup->msg = NULL; + + return ret; +} + +static int qup_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg msgs[], + int num) +{ + struct qup_i2c_dev *qup = i2c_get_adapdata(adap); + int ret, idx; + + ret = pm_runtime_get_sync(qup->dev); + if (ret < 0) + goto out; + + writel(1, qup->base + QUP_SW_RESET); + ret = qup_i2c_poll_state(qup, QUP_RESET_STATE); + if (ret) + goto out; + + /* Configure QUP as I2C mini core */ + writel(I2C_MINI_CORE | I2C_N_VAL, qup->base + QUP_CONFIG); + + for (idx = 0; idx < num; idx++) { + if (msgs[idx].len == 0) { + ret = -EINVAL; + goto out; + } + + if (qup_i2c_poll_state_i2c_master(qup)) { + ret = -EIO; + goto out; + } + + if (msgs[idx].flags & I2C_M_RD) + ret = qup_i2c_read_one(qup, &msgs[idx]); + else + ret = qup_i2c_write_one(qup, &msgs[idx]); + + if (ret) + break; + + ret = qup_i2c_change_state(qup, QUP_RESET_STATE); + if (ret) + break; + } + + if (ret == 0) + ret = num; +out: + + pm_runtime_mark_last_busy(qup->dev); + pm_runtime_put_autosuspend(qup->dev); + + return ret; +} + +static u32 qup_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); +} + +static const struct i2c_algorithm qup_i2c_algo = { + .master_xfer = qup_i2c_xfer, + .functionality = qup_i2c_func, +}; + +static void qup_i2c_enable_clocks(struct qup_i2c_dev *qup) +{ + clk_prepare_enable(qup->clk); + clk_prepare_enable(qup->pclk); +} + +static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup) +{ + u32 config; + + qup_i2c_change_state(qup, QUP_RESET_STATE); + clk_disable_unprepare(qup->clk); + config = readl(qup->base + QUP_CONFIG); + config |= QUP_CLOCK_AUTO_GATE; + writel(config, qup->base + QUP_CONFIG); + clk_disable_unprepare(qup->pclk); +} + +static int qup_i2c_probe(struct platform_device *pdev) +{ + static const int blk_sizes[] = {4, 16, 32}; + struct device_node *node = pdev->dev.of_node; + 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; + int src_clk_freq; + u32 clk_freq = 100000; + + qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL); + if (!qup) + return -ENOMEM; + + qup->dev = &pdev->dev; + init_completion(&qup->xfer); + platform_set_drvdata(pdev, qup); + + of_property_read_u32(node, "clock-frequency", &clk_freq); + + /* We support frequencies up to FAST Mode (400KHz) */ + if (!clk_freq || clk_freq > 400000) { + dev_err(qup->dev, "clock frequency not supported %d\n", + clk_freq); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + qup->base = devm_ioremap_resource(qup->dev, res); + 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"); + return qup->irq; + } + + qup->clk = devm_clk_get(qup->dev, "core"); + if (IS_ERR(qup->clk)) { + dev_err(qup->dev, "Could not get core clock\n"); + return PTR_ERR(qup->clk); + } + + qup->pclk = devm_clk_get(qup->dev, "iface"); + if (IS_ERR(qup->pclk)) { + dev_err(qup->dev, "Could not get iface clock\n"); + return PTR_ERR(qup->pclk); + } + + qup_i2c_enable_clocks(qup); + + /* + * Bootloaders might leave a pending interrupt on certain QUP's, + * so we reset the core before registering for interrupts. + */ + writel(1, qup->base + QUP_SW_RESET); + ret = qup_i2c_poll_state_valid(qup); + if (ret) + goto fail; + + ret = devm_request_irq(qup->dev, qup->irq, qup_i2c_interrupt, + IRQF_TRIGGER_HIGH, "i2c_qup", qup); + if (ret) { + dev_err(qup->dev, "Request %d IRQ failed\n", qup->irq); + goto fail; + } + disable_irq(qup->irq); + + hw_ver = readl(qup->base + QUP_HW_VERSION); + dev_dbg(qup->dev, "Revision %x\n", hw_ver); + + io_mode = readl(qup->base + QUP_IO_MODE); + + /* + * The block/fifo size w.r.t. 'actual data' is 1/2 due to 'tag' + * associated with each byte written/received + */ + size = QUP_OUTPUT_BLOCK_SIZE(io_mode); + if (size >= ARRAY_SIZE(blk_sizes)) + return -EIO; + qup->out_blk_sz = blk_sizes[size] / 2; + + size = QUP_INPUT_BLOCK_SIZE(io_mode); + if (size >= ARRAY_SIZE(blk_sizes)) + return -EIO; + qup->in_blk_sz = blk_sizes[size] / 2; + + size = QUP_OUTPUT_FIFO_SIZE(io_mode); + qup->out_fifo_sz = qup->out_blk_sz * (2 << size); + + size = QUP_INPUT_FIFO_SIZE(io_mode); + qup->in_fifo_sz = qup->in_blk_sz * (2 << size); + + src_clk_freq = clk_get_rate(qup->clk); + fs_div = ((src_clk_freq / clk_freq) / 2) - 3; + hs_div = 3; + qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff); + + /* + * Time it takes for a byte to be clocked out on the bus. + * Each byte takes 9 clock cycles (8 bits + 1 ack). + */ + one_bit_t = (USEC_PER_SEC / clk_freq) + 1; + qup->one_byte_t = one_bit_t * 9; + + dev_dbg(qup->dev, "IN:block:%d, fifo:%d, OUT:block:%d, fifo:%d\n", + qup->in_blk_sz, qup->in_fifo_sz, + qup->out_blk_sz, qup->out_fifo_sz); + + i2c_set_adapdata(&qup->adap, qup); + qup->adap.algo = &qup_i2c_algo; + qup->adap.dev.parent = qup->dev; + qup->adap.dev.of_node = pdev->dev.of_node; + strlcpy(qup->adap.name, "QUP I2C adapter", sizeof(qup->adap.name)); + + ret = i2c_add_adapter(&qup->adap); + if (ret) + goto fail; + + pm_runtime_set_autosuspend_delay(qup->dev, MSEC_PER_SEC); + pm_runtime_use_autosuspend(qup->dev); + pm_runtime_set_active(qup->dev); + pm_runtime_enable(qup->dev); + return 0; + +fail: + qup_i2c_disable_clocks(qup); + return ret; +} + +static int qup_i2c_remove(struct platform_device *pdev) +{ + struct qup_i2c_dev *qup = platform_get_drvdata(pdev); + + disable_irq(qup->irq); + qup_i2c_disable_clocks(qup); + i2c_del_adapter(&qup->adap); + pm_runtime_disable(qup->dev); + pm_runtime_set_suspended(qup->dev); + return 0; +} + +#ifdef CONFIG_PM +static int qup_i2c_pm_suspend_runtime(struct device *device) +{ + struct qup_i2c_dev *qup = dev_get_drvdata(device); + + dev_dbg(device, "pm_runtime: suspending...\n"); + qup_i2c_disable_clocks(qup); + return 0; +} + +static int qup_i2c_pm_resume_runtime(struct device *device) +{ + struct qup_i2c_dev *qup = dev_get_drvdata(device); + + dev_dbg(device, "pm_runtime: resuming...\n"); + qup_i2c_enable_clocks(qup); + return 0; +} +#endif + +#ifdef CONFIG_PM_SLEEP +static int qup_i2c_suspend(struct device *device) +{ + qup_i2c_pm_suspend_runtime(device); + return 0; +} + +static int qup_i2c_resume(struct device *device) +{ + qup_i2c_pm_resume_runtime(device); + pm_runtime_mark_last_busy(device); + pm_request_autosuspend(device); + return 0; +} +#endif + +static const struct dev_pm_ops qup_i2c_qup_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS( + qup_i2c_suspend, + qup_i2c_resume) + SET_RUNTIME_PM_OPS( + qup_i2c_pm_suspend_runtime, + qup_i2c_pm_resume_runtime, + NULL) +}; + +static const struct of_device_id qup_i2c_dt_match[] = { + { .compatible = "qcom,i2c-qup-v1.1.1" }, + { .compatible = "qcom,i2c-qup-v2.1.1" }, + { .compatible = "qcom,i2c-qup-v2.2.1" }, + {} +}; +MODULE_DEVICE_TABLE(of, qup_i2c_dt_match); + +static struct platform_driver qup_i2c_driver = { + .probe = qup_i2c_probe, + .remove = qup_i2c_remove, + .driver = { + .name = "i2c_qup", + .owner = THIS_MODULE, + .pm = &qup_i2c_qup_pm_ops, + .of_match_table = qup_i2c_dt_match, + }, +}; + +module_platform_driver(qup_i2c_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:i2c_qup"); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index d2fe11da5e8..89940592367 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -1,7 +1,9 @@ /* - * drivers/i2c/busses/i2c-rcar.c + * Driver for the Renesas RCar I2C unit * - * Copyright (C) 2012 Renesas Solutions Corp. + * Copyright (C) 2014 Wolfram Sang <wsa@sang-engineering.com> + * + * Copyright (C) 2012-14 Renesas Solutions Corp. * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> * * This file is based on the drivers/i2c/busses/i2c-sh7760.c @@ -12,31 +14,26 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License + * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/i2c.h> #include <linux/i2c/i2c-rcar.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/slab.h> -#include <linux/spinlock.h> /* register offsets */ #define ICSCR 0x00 /* slave ctrl */ @@ -60,7 +57,7 @@ #define FSB (1 << 1) /* force stop bit */ #define ESG (1 << 0) /* en startbit gen */ -/* ICMSR */ +/* ICMSR (also for ICMIE) */ #define MNR (1 << 6) /* nack received */ #define MAL (1 << 5) /* arbitration lost */ #define MST (1 << 4) /* sent a stop */ @@ -69,32 +66,18 @@ #define MDR (1 << 1) #define MAT (1 << 0) /* slave addr xfer done */ -/* ICMIE */ -#define MNRE (1 << 6) /* nack irq en */ -#define MALE (1 << 5) /* arblos irq en */ -#define MSTE (1 << 4) /* stop irq en */ -#define MDEE (1 << 3) -#define MDTE (1 << 2) -#define MDRE (1 << 1) -#define MATE (1 << 0) /* address sent irq en */ +#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG) +#define RCAR_BUS_PHASE_DATA (MDBS | MIE) +#define RCAR_BUS_PHASE_STOP (MDBS | MIE | FSB) -enum { - RCAR_BUS_PHASE_ADDR, - RCAR_BUS_PHASE_DATA, - RCAR_BUS_PHASE_STOP, -}; +#define RCAR_IRQ_SEND (MNR | MAL | MST | MAT | MDE) +#define RCAR_IRQ_RECV (MNR | MAL | MST | MAT | MDR) +#define RCAR_IRQ_STOP (MST) -enum { - RCAR_IRQ_CLOSE, - RCAR_IRQ_OPEN_FOR_SEND, - RCAR_IRQ_OPEN_FOR_RECV, - RCAR_IRQ_OPEN_FOR_STOP, -}; +#define RCAR_IRQ_ACK_SEND (~(MAT | MDE)) +#define RCAR_IRQ_ACK_RECV (~(MAT | MDR)) -/* - * flags - */ #define ID_LAST_MSG (1 << 0) #define ID_IOERROR (1 << 1) #define ID_DONE (1 << 2) @@ -102,23 +85,22 @@ enum { #define ID_NACK (1 << 4) enum rcar_i2c_type { - I2C_RCAR_H1, - I2C_RCAR_H2, + I2C_RCAR_GEN1, + I2C_RCAR_GEN2, }; struct rcar_i2c_priv { void __iomem *io; struct i2c_adapter adap; struct i2c_msg *msg; + struct clk *clk; - spinlock_t lock; wait_queue_head_t wait; int pos; - int irq; u32 icccr; u32 flags; - enum rcar_i2c_type devtype; + enum rcar_i2c_type devtype; }; #define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent) @@ -129,9 +111,7 @@ struct rcar_i2c_priv { #define LOOP_TIMEOUT 1024 -/* - * basic functions - */ + static void rcar_i2c_write(struct rcar_i2c_priv *priv, int reg, u32 val) { writel(val, priv->io + reg); @@ -160,36 +140,6 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv) rcar_i2c_write(priv, ICMAR, 0); } -static void rcar_i2c_irq_mask(struct rcar_i2c_priv *priv, int open) -{ - u32 val = MNRE | MALE | MSTE | MATE; /* default */ - - switch (open) { - case RCAR_IRQ_OPEN_FOR_SEND: - val |= MDEE; /* default + send */ - break; - case RCAR_IRQ_OPEN_FOR_RECV: - val |= MDRE; /* default + read */ - break; - case RCAR_IRQ_OPEN_FOR_STOP: - val = MSTE; /* stop irq only */ - break; - case RCAR_IRQ_CLOSE: - default: - val = 0; /* all close */ - break; - } - rcar_i2c_write(priv, ICMIER, val); -} - -static void rcar_i2c_set_addr(struct rcar_i2c_priv *priv, u32 recv) -{ - rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | recv); -} - -/* - * bus control functions - */ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) { int i; @@ -204,44 +154,21 @@ static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv) return -EBUSY; } -static void rcar_i2c_bus_phase(struct rcar_i2c_priv *priv, int phase) -{ - switch (phase) { - case RCAR_BUS_PHASE_ADDR: - rcar_i2c_write(priv, ICMCR, MDBS | MIE | ESG); - break; - case RCAR_BUS_PHASE_DATA: - rcar_i2c_write(priv, ICMCR, MDBS | MIE); - break; - case RCAR_BUS_PHASE_STOP: - rcar_i2c_write(priv, ICMCR, MDBS | MIE | FSB); - break; - } -} - -/* - * clock function - */ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, u32 bus_speed, struct device *dev) { - struct clk *clkp = clk_get(NULL, "peripheral_clk"); u32 scgd, cdf; u32 round, ick; u32 scl; u32 cdf_width; - - if (!clkp) { - dev_err(dev, "there is no peripheral_clk\n"); - return -EIO; - } + unsigned long rate; switch (priv->devtype) { - case I2C_RCAR_H1: + case I2C_RCAR_GEN1: cdf_width = 2; break; - case I2C_RCAR_H2: + case I2C_RCAR_GEN2: cdf_width = 3; break; default: @@ -264,15 +191,14 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, * clkp : peripheral_clk * F[] : integer up-valuation */ - for (cdf = 0; cdf < (1 << cdf_width); cdf++) { - ick = clk_get_rate(clkp) / (1 + cdf); - if (ick < 20000000) - goto ick_find; + rate = clk_get_rate(priv->clk); + cdf = rate / 20000000; + if (cdf >= 1 << cdf_width) { + dev_err(dev, "Input clock %lu too high\n", rate); + return -EIO; } - dev_err(dev, "there is no best CDF\n"); - return -EIO; + ick = rate / (cdf + 1); -ick_find: /* * it is impossible to calculate large scale * number on u32. separate it @@ -290,6 +216,12 @@ ick_find: * * Calculation result (= SCL) should be less than * bus_speed for hardware safety + * + * We could use something along the lines of + * div = ick / (bus_speed + 1) + 1; + * scgd = (div - 20 - round + 7) / 8; + * scl = ick / (20 + (scgd * 8) + round); + * (not fully verified) but that would get pretty involved */ for (scgd = 0; scgd < 0x40; scgd++) { scl = ick / (20 + (scgd * 8) + round); @@ -301,70 +233,28 @@ ick_find: scgd_find: dev_dbg(dev, "clk %d/%d(%lu), round %u, CDF:0x%x, SCGD: 0x%x\n", - scl, bus_speed, clk_get_rate(clkp), round, cdf, scgd); + scl, bus_speed, clk_get_rate(priv->clk), round, cdf, scgd); /* * keep icccr value */ - priv->icccr = (scgd << (cdf_width) | cdf); - - return 0; -} - -static void rcar_i2c_clock_start(struct rcar_i2c_priv *priv) -{ - rcar_i2c_write(priv, ICCCR, priv->icccr); -} - -/* - * status functions - */ -static u32 rcar_i2c_status_get(struct rcar_i2c_priv *priv) -{ - return rcar_i2c_read(priv, ICMSR); -} - -#define rcar_i2c_status_clear(priv) rcar_i2c_status_bit_clear(priv, 0xffffffff) -static void rcar_i2c_status_bit_clear(struct rcar_i2c_priv *priv, u32 bit) -{ - rcar_i2c_write(priv, ICMSR, ~bit); -} - -/* - * recv/send functions - */ -static int rcar_i2c_recv(struct rcar_i2c_priv *priv) -{ - rcar_i2c_set_addr(priv, 1); - rcar_i2c_status_clear(priv); - rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR); - rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_RECV); + priv->icccr = scgd << cdf_width | cdf; return 0; } -static int rcar_i2c_send(struct rcar_i2c_priv *priv) +static int rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv) { - int ret; - - /* - * It should check bus status when send case - */ - ret = rcar_i2c_bus_barrier(priv); - if (ret < 0) - return ret; + int read = !!rcar_i2c_is_recv(priv); - rcar_i2c_set_addr(priv, 0); - rcar_i2c_status_clear(priv); - rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_ADDR); - rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_SEND); + rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read); + rcar_i2c_write(priv, ICMSR, 0); + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_START); + rcar_i2c_write(priv, ICMIER, read ? RCAR_IRQ_RECV : RCAR_IRQ_SEND); return 0; } -#define rcar_i2c_send_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDE)) -#define rcar_i2c_recv_restart(priv) rcar_i2c_status_bit_clear(priv, (MAT | MDR)) - /* * interrupt functions */ @@ -385,7 +275,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) * goto data phase. */ if (msr & MAT) - rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA); + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); if (priv->pos < msg->len) { /* @@ -413,7 +303,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) * prepare stop condition here. * ID_DONE will be set on STOP irq. */ - rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP); + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); else /* * If current msg is _NOT_ last msg, @@ -424,7 +314,7 @@ static int rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr) return ID_DONE; } - rcar_i2c_send_restart(priv); + rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_SEND); return 0; } @@ -461,11 +351,11 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) * otherwise, go to DATA phase. */ if (priv->pos + 1 >= msg->len) - rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP); + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); else - rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_DATA); + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_DATA); - rcar_i2c_recv_restart(priv); + rcar_i2c_write(priv, ICMSR, RCAR_IRQ_ACK_RECV); return 0; } @@ -473,53 +363,31 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr) static irqreturn_t rcar_i2c_irq(int irq, void *ptr) { struct rcar_i2c_priv *priv = ptr; - struct device *dev = rcar_i2c_priv_to_dev(priv); u32 msr; - /*-------------- spin lock -----------------*/ - spin_lock(&priv->lock); - - msr = rcar_i2c_status_get(priv); + msr = rcar_i2c_read(priv, ICMSR); - /* - * Arbitration lost - */ + /* Arbitration lost */ if (msr & MAL) { - /* - * CAUTION - * - * When arbitration lost, device become _slave_ mode. - */ - dev_dbg(dev, "Arbitration Lost\n"); rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST)); goto out; } - /* - * Stop - */ + /* Stop */ if (msr & MST) { - dev_dbg(dev, "Stop\n"); rcar_i2c_flags_set(priv, ID_DONE); goto out; } - /* - * Nack - */ + /* Nack */ if (msr & MNR) { - dev_dbg(dev, "Nack\n"); - /* go to stop phase */ - rcar_i2c_bus_phase(priv, RCAR_BUS_PHASE_STOP); - rcar_i2c_irq_mask(priv, RCAR_IRQ_OPEN_FOR_STOP); + rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP); + rcar_i2c_write(priv, ICMIER, RCAR_IRQ_STOP); rcar_i2c_flags_set(priv, ID_NACK); goto out; } - /* - * recv/send - */ if (rcar_i2c_is_recv(priv)) rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr)); else @@ -527,14 +395,11 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr) out: if (rcar_i2c_flags_has(priv, ID_DONE)) { - rcar_i2c_irq_mask(priv, RCAR_IRQ_CLOSE); - rcar_i2c_status_clear(priv); + rcar_i2c_write(priv, ICMIER, 0); + rcar_i2c_write(priv, ICMSR, 0); wake_up(&priv->wait); } - spin_unlock(&priv->lock); - /*-------------- spin unlock -----------------*/ - return IRQ_HANDLED; } @@ -544,24 +409,24 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, { struct rcar_i2c_priv *priv = i2c_get_adapdata(adap); struct device *dev = rcar_i2c_priv_to_dev(priv); - unsigned long flags; int i, ret, timeout; pm_runtime_get_sync(dev); - /*-------------- spin lock -----------------*/ - spin_lock_irqsave(&priv->lock, flags); - rcar_i2c_init(priv); - rcar_i2c_clock_start(priv); + /* start clock */ + rcar_i2c_write(priv, ICCCR, priv->icccr); - spin_unlock_irqrestore(&priv->lock, flags); - /*-------------- spin unlock -----------------*/ + ret = rcar_i2c_bus_barrier(priv); + if (ret < 0) + goto out; - ret = -EINVAL; for (i = 0; i < num; i++) { - /*-------------- spin lock -----------------*/ - spin_lock_irqsave(&priv->lock, flags); + /* This HW can't send STOP after address phase */ + if (msgs[i].len == 0) { + ret = -EOPNOTSUPP; + break; + } /* init each data */ priv->msg = &msgs[i]; @@ -570,21 +435,11 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, if (priv->msg == &msgs[num - 1]) rcar_i2c_flags_set(priv, ID_LAST_MSG); - /* start send/recv */ - if (rcar_i2c_is_recv(priv)) - ret = rcar_i2c_recv(priv); - else - ret = rcar_i2c_send(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - /*-------------- spin unlock -----------------*/ + ret = rcar_i2c_prepare_msg(priv); if (ret < 0) break; - /* - * wait result - */ timeout = wait_event_timeout(priv->wait, rcar_i2c_flags_has(priv, ID_DONE), 5 * HZ); @@ -593,11 +448,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, break; } - /* - * error handling - */ if (rcar_i2c_flags_has(priv, ID_NACK)) { - ret = -EREMOTEIO; + ret = -ENXIO; break; } @@ -613,10 +465,10 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, ret = i + 1; /* The number of transfer */ } - +out: pm_runtime_put(dev); - if (ret < 0) + if (ret < 0 && ret != -ENXIO) dev_err(dev, "error %d : %x\n", ret, priv->flags); return ret; @@ -624,7 +476,8 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, static u32 rcar_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + /* This HW can't do SMBUS_QUICK and NOSTART */ + return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); } static const struct i2c_algorithm rcar_i2c_algo = { @@ -632,6 +485,19 @@ static const struct i2c_algorithm rcar_i2c_algo = { .functionality = rcar_i2c_func, }; +static const struct of_device_id rcar_i2c_dt_ids[] = { + { .compatible = "renesas,i2c-rcar", .data = (void *)I2C_RCAR_GEN1 }, + { .compatible = "renesas,i2c-r8a7778", .data = (void *)I2C_RCAR_GEN1 }, + { .compatible = "renesas,i2c-r8a7779", .data = (void *)I2C_RCAR_GEN1 }, + { .compatible = "renesas,i2c-r8a7790", .data = (void *)I2C_RCAR_GEN2 }, + { .compatible = "renesas,i2c-r8a7791", .data = (void *)I2C_RCAR_GEN2 }, + { .compatible = "renesas,i2c-r8a7792", .data = (void *)I2C_RCAR_GEN2 }, + { .compatible = "renesas,i2c-r8a7793", .data = (void *)I2C_RCAR_GEN2 }, + { .compatible = "renesas,i2c-r8a7794", .data = (void *)I2C_RCAR_GEN2 }, + {}, +}; +MODULE_DEVICE_TABLE(of, rcar_i2c_dt_ids); + static int rcar_i2c_probe(struct platform_device *pdev) { struct i2c_rcar_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -640,19 +506,28 @@ static int rcar_i2c_probe(struct platform_device *pdev) struct resource *res; struct device *dev = &pdev->dev; u32 bus_speed; - int ret; + int irq, ret; priv = devm_kzalloc(dev, sizeof(struct rcar_i2c_priv), GFP_KERNEL); - if (!priv) { - dev_err(dev, "no mem for private data\n"); + if (!priv) return -ENOMEM; + + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + dev_err(dev, "cannot get clock\n"); + return PTR_ERR(priv->clk); } bus_speed = 100000; /* default 100 kHz */ - if (pdata && pdata->bus_speed) + ret = of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed); + if (ret < 0 && pdata && pdata->bus_speed) bus_speed = pdata->bus_speed; - priv->devtype = platform_get_device_id(pdev)->driver_data; + if (pdev->dev.of_node) + priv->devtype = (long)of_match_device(rcar_i2c_dt_ids, + dev)->data; + else + priv->devtype = platform_get_device_id(pdev)->driver_data; ret = rcar_i2c_clock_calculate(priv, bus_speed, dev); if (ret < 0) @@ -663,23 +538,23 @@ static int rcar_i2c_probe(struct platform_device *pdev) if (IS_ERR(priv->io)) return PTR_ERR(priv->io); - priv->irq = platform_get_irq(pdev, 0); + irq = platform_get_irq(pdev, 0); init_waitqueue_head(&priv->wait); - spin_lock_init(&priv->lock); adap = &priv->adap; adap->nr = pdev->id; adap->algo = &rcar_i2c_algo; - adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED; adap->retries = 3; adap->dev.parent = dev; + adap->dev.of_node = dev->of_node; i2c_set_adapdata(adap, priv); strlcpy(adap->name, pdev->name, sizeof(adap->name)); - ret = devm_request_irq(dev, priv->irq, rcar_i2c_irq, 0, + ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0, dev_name(dev), priv); if (ret < 0) { - dev_err(dev, "cannot get irq %d\n", priv->irq); + dev_err(dev, "cannot get irq %d\n", irq); return ret; } @@ -709,9 +584,9 @@ static int rcar_i2c_remove(struct platform_device *pdev) } static struct platform_device_id rcar_i2c_id_table[] = { - { "i2c-rcar", I2C_RCAR_H1 }, - { "i2c-rcar_h1", I2C_RCAR_H1 }, - { "i2c-rcar_h2", I2C_RCAR_H2 }, + { "i2c-rcar", I2C_RCAR_GEN1 }, + { "i2c-rcar_gen1", I2C_RCAR_GEN1 }, + { "i2c-rcar_gen2", I2C_RCAR_GEN2 }, {}, }; MODULE_DEVICE_TABLE(platform, rcar_i2c_id_table); @@ -720,6 +595,7 @@ static struct platform_driver rcar_i2c_driver = { .driver = { .name = "i2c-rcar", .owner = THIS_MODULE, + .of_match_table = rcar_i2c_dt_ids, }, .probe = rcar_i2c_probe, .remove = rcar_i2c_remove, @@ -728,6 +604,6 @@ static struct platform_driver rcar_i2c_driver = { module_platform_driver(rcar_i2c_driver); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Renesas R-Car I2C bus driver"); MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c new file mode 100644 index 00000000000..af3b3d032a9 --- /dev/null +++ b/drivers/i2c/busses/i2c-riic.c @@ -0,0 +1,427 @@ +/* + * Renesas RIIC driver + * + * Copyright (C) 2013 Wolfram Sang <wsa@sang-engineering.com> + * Copyright (C) 2013 Renesas Solutions Corp. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +/* + * This i2c core has a lot of interrupts, namely 8. We use their chaining as + * some kind of state machine. + * + * 1) The main xfer routine kicks off a transmission by putting the start bit + * (or repeated start) on the bus and enabling the transmit interrupt (TIE) + * since we need to send the slave address + RW bit in every case. + * + * 2) TIE sends slave address + RW bit and selects how to continue. + * + * 3a) Write case: We keep utilizing TIE as long as we have data to send. If we + * are done, we switch over to the transmission done interrupt (TEIE) and mark + * the message as completed (includes sending STOP) there. + * + * 3b) Read case: We switch over to receive interrupt (RIE). One dummy read is + * needed to start clocking, then we keep receiving until we are done. Note + * that we use the RDRFS mode all the time, i.e. we ACK/NACK every byte by + * writing to the ACKBT bit. I tried using the RDRFS mode only at the end of a + * message to create the final NACK as sketched in the datasheet. This caused + * some subtle races (when byte n was processed and byte n+1 was already + * waiting), though, and I started with the safe approach. + * + * 4) If we got a NACK somewhere, we flag the error and stop the transmission + * via NAKIE. + * + * Also check the comments in the interrupt routines for some gory details. + */ + +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#define RIIC_ICCR1 0x00 +#define RIIC_ICCR2 0x04 +#define RIIC_ICMR1 0x08 +#define RIIC_ICMR3 0x10 +#define RIIC_ICSER 0x18 +#define RIIC_ICIER 0x1c +#define RIIC_ICSR2 0x24 +#define RIIC_ICBRL 0x34 +#define RIIC_ICBRH 0x38 +#define RIIC_ICDRT 0x3c +#define RIIC_ICDRR 0x40 + +#define ICCR1_ICE 0x80 +#define ICCR1_IICRST 0x40 +#define ICCR1_SOWP 0x10 + +#define ICCR2_BBSY 0x80 +#define ICCR2_SP 0x08 +#define ICCR2_RS 0x04 +#define ICCR2_ST 0x02 + +#define ICMR1_CKS_MASK 0x70 +#define ICMR1_BCWP 0x08 +#define ICMR1_CKS(_x) ((((_x) << 4) & ICMR1_CKS_MASK) | ICMR1_BCWP) + +#define ICMR3_RDRFS 0x20 +#define ICMR3_ACKWP 0x10 +#define ICMR3_ACKBT 0x08 + +#define ICIER_TIE 0x80 +#define ICIER_TEIE 0x40 +#define ICIER_RIE 0x20 +#define ICIER_NAKIE 0x10 + +#define ICSR2_NACKF 0x10 + +/* ICBRx (@ PCLK 33MHz) */ +#define ICBR_RESERVED 0xe0 /* Should be 1 on writes */ +#define ICBRL_SP100K (19 | ICBR_RESERVED) +#define ICBRH_SP100K (16 | ICBR_RESERVED) +#define ICBRL_SP400K (21 | ICBR_RESERVED) +#define ICBRH_SP400K (9 | ICBR_RESERVED) + +#define RIIC_INIT_MSG -1 + +struct riic_dev { + void __iomem *base; + u8 *buf; + struct i2c_msg *msg; + int bytes_left; + int err; + int is_last; + struct completion msg_done; + struct i2c_adapter adapter; + struct clk *clk; +}; + +struct riic_irq_desc { + int res_num; + irq_handler_t isr; + char *name; +}; + +static inline void riic_clear_set_bit(struct riic_dev *riic, u8 clear, u8 set, u8 reg) +{ + writeb((readb(riic->base + reg) & ~clear) | set, riic->base + reg); +} + +static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct riic_dev *riic = i2c_get_adapdata(adap); + unsigned long time_left; + int i, ret; + u8 start_bit; + + ret = clk_prepare_enable(riic->clk); + if (ret) + return ret; + + if (readb(riic->base + RIIC_ICCR2) & ICCR2_BBSY) { + riic->err = -EBUSY; + goto out; + } + + reinit_completion(&riic->msg_done); + riic->err = 0; + + writeb(0, riic->base + RIIC_ICSR2); + + for (i = 0, start_bit = ICCR2_ST; i < num; i++) { + riic->bytes_left = RIIC_INIT_MSG; + riic->buf = msgs[i].buf; + riic->msg = &msgs[i]; + riic->is_last = (i == num - 1); + + writeb(ICIER_NAKIE | ICIER_TIE, riic->base + RIIC_ICIER); + + writeb(start_bit, riic->base + RIIC_ICCR2); + + time_left = wait_for_completion_timeout(&riic->msg_done, riic->adapter.timeout); + if (time_left == 0) + riic->err = -ETIMEDOUT; + + if (riic->err) + break; + + start_bit = ICCR2_RS; + } + + out: + clk_disable_unprepare(riic->clk); + + return riic->err ?: num; +} + +static irqreturn_t riic_tdre_isr(int irq, void *data) +{ + struct riic_dev *riic = data; + u8 val; + + if (!riic->bytes_left) + return IRQ_NONE; + + if (riic->bytes_left == RIIC_INIT_MSG) { + val = !!(riic->msg->flags & I2C_M_RD); + if (val) + /* On read, switch over to receive interrupt */ + riic_clear_set_bit(riic, ICIER_TIE, ICIER_RIE, RIIC_ICIER); + else + /* On write, initialize length */ + riic->bytes_left = riic->msg->len; + + val |= (riic->msg->addr << 1); + } else { + val = *riic->buf; + riic->buf++; + riic->bytes_left--; + } + + /* + * Switch to transmission ended interrupt when done. Do check here + * after bytes_left was initialized to support SMBUS_QUICK (new msg has + * 0 length then) + */ + if (riic->bytes_left == 0) + riic_clear_set_bit(riic, ICIER_TIE, ICIER_TEIE, RIIC_ICIER); + + /* + * This acks the TIE interrupt. We get another TIE immediately if our + * value could be moved to the shadow shift register right away. So + * this must be after updates to ICIER (where we want to disable TIE)! + */ + writeb(val, riic->base + RIIC_ICDRT); + + return IRQ_HANDLED; +} + +static irqreturn_t riic_tend_isr(int irq, void *data) +{ + struct riic_dev *riic = data; + + if (readb(riic->base + RIIC_ICSR2) & ICSR2_NACKF) { + /* We got a NACKIE */ + readb(riic->base + RIIC_ICDRR); /* dummy read */ + riic->err = -ENXIO; + } else if (riic->bytes_left) { + return IRQ_NONE; + } + + if (riic->is_last || riic->err) + writeb(ICCR2_SP, riic->base + RIIC_ICCR2); + + writeb(0, riic->base + RIIC_ICIER); + complete(&riic->msg_done); + + return IRQ_HANDLED; +} + +static irqreturn_t riic_rdrf_isr(int irq, void *data) +{ + struct riic_dev *riic = data; + + if (!riic->bytes_left) + return IRQ_NONE; + + if (riic->bytes_left == RIIC_INIT_MSG) { + riic->bytes_left = riic->msg->len; + readb(riic->base + RIIC_ICDRR); /* dummy read */ + return IRQ_HANDLED; + } + + if (riic->bytes_left == 1) { + /* STOP must come before we set ACKBT! */ + if (riic->is_last) + writeb(ICCR2_SP, riic->base + RIIC_ICCR2); + + riic_clear_set_bit(riic, 0, ICMR3_ACKBT, RIIC_ICMR3); + + writeb(0, riic->base + RIIC_ICIER); + complete(&riic->msg_done); + } else { + riic_clear_set_bit(riic, ICMR3_ACKBT, 0, RIIC_ICMR3); + } + + /* Reading acks the RIE interrupt */ + *riic->buf = readb(riic->base + RIIC_ICDRR); + riic->buf++; + riic->bytes_left--; + + return IRQ_HANDLED; +} + +static u32 riic_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm riic_algo = { + .master_xfer = riic_xfer, + .functionality = riic_func, +}; + +static int riic_init_hw(struct riic_dev *riic, u32 spd) +{ + int ret; + unsigned long rate; + + ret = clk_prepare_enable(riic->clk); + if (ret) + return ret; + + /* + * TODO: Implement formula to calculate the timing values depending on + * variable parent clock rate and arbitrary bus speed + */ + rate = clk_get_rate(riic->clk); + if (rate != 33325000) { + dev_err(&riic->adapter.dev, + "invalid parent clk (%lu). Must be 33325000Hz\n", rate); + clk_disable_unprepare(riic->clk); + return -EINVAL; + } + + /* Changing the order of accessing IICRST and ICE may break things! */ + writeb(ICCR1_IICRST | ICCR1_SOWP, riic->base + RIIC_ICCR1); + riic_clear_set_bit(riic, 0, ICCR1_ICE, RIIC_ICCR1); + + switch (spd) { + case 100000: + writeb(ICMR1_CKS(3), riic->base + RIIC_ICMR1); + writeb(ICBRH_SP100K, riic->base + RIIC_ICBRH); + writeb(ICBRL_SP100K, riic->base + RIIC_ICBRL); + break; + case 400000: + writeb(ICMR1_CKS(1), riic->base + RIIC_ICMR1); + writeb(ICBRH_SP400K, riic->base + RIIC_ICBRH); + writeb(ICBRL_SP400K, riic->base + RIIC_ICBRL); + break; + default: + dev_err(&riic->adapter.dev, + "unsupported bus speed (%dHz). Use 100000 or 400000\n", spd); + clk_disable_unprepare(riic->clk); + return -EINVAL; + } + + writeb(0, riic->base + RIIC_ICSER); + writeb(ICMR3_ACKWP | ICMR3_RDRFS, riic->base + RIIC_ICMR3); + + riic_clear_set_bit(riic, ICCR1_IICRST, 0, RIIC_ICCR1); + + clk_disable_unprepare(riic->clk); + + return 0; +} + +static struct riic_irq_desc riic_irqs[] = { + { .res_num = 0, .isr = riic_tend_isr, .name = "riic-tend" }, + { .res_num = 1, .isr = riic_rdrf_isr, .name = "riic-rdrf" }, + { .res_num = 2, .isr = riic_tdre_isr, .name = "riic-tdre" }, + { .res_num = 5, .isr = riic_tend_isr, .name = "riic-nack" }, +}; + +static int riic_i2c_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct riic_dev *riic; + struct i2c_adapter *adap; + struct resource *res; + u32 bus_rate = 0; + int i, ret; + + riic = devm_kzalloc(&pdev->dev, sizeof(*riic), GFP_KERNEL); + if (!riic) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + riic->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(riic->base)) + return PTR_ERR(riic->base); + + riic->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(riic->clk)) { + dev_err(&pdev->dev, "missing controller clock"); + return PTR_ERR(riic->clk); + } + + for (i = 0; i < ARRAY_SIZE(riic_irqs); i++) { + res = platform_get_resource(pdev, IORESOURCE_IRQ, riic_irqs[i].res_num); + if (!res) + return -ENODEV; + + ret = devm_request_irq(&pdev->dev, res->start, riic_irqs[i].isr, + 0, riic_irqs[i].name, riic); + if (ret) { + dev_err(&pdev->dev, "failed to request irq %s\n", riic_irqs[i].name); + return ret; + } + } + + adap = &riic->adapter; + i2c_set_adapdata(adap, riic); + strlcpy(adap->name, "Renesas RIIC adapter", sizeof(adap->name)); + adap->owner = THIS_MODULE; + adap->algo = &riic_algo; + adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; + + init_completion(&riic->msg_done); + + of_property_read_u32(np, "clock-frequency", &bus_rate); + ret = riic_init_hw(riic, bus_rate); + if (ret) + return ret; + + + ret = i2c_add_adapter(adap); + if (ret) { + dev_err(&pdev->dev, "failed to add adapter\n"); + return ret; + } + + platform_set_drvdata(pdev, riic); + + dev_info(&pdev->dev, "registered with %dHz bus speed\n", bus_rate); + return 0; +} + +static int riic_i2c_remove(struct platform_device *pdev) +{ + struct riic_dev *riic = platform_get_drvdata(pdev); + + writeb(0, riic->base + RIIC_ICIER); + i2c_del_adapter(&riic->adapter); + + return 0; +} + +static const struct of_device_id riic_i2c_dt_ids[] = { + { .compatible = "renesas,riic-rz" }, + { /* Sentinel */ }, +}; + +static struct platform_driver riic_i2c_driver = { + .probe = riic_i2c_probe, + .remove = riic_i2c_remove, + .driver = { + .name = "i2c-riic", + .owner = THIS_MODULE, + .of_match_table = riic_i2c_dt_ids, + }, +}; + +module_platform_driver(riic_i2c_driver); + +MODULE_DESCRIPTION("Renesas RIIC adapter"); +MODULE_AUTHOR("Wolfram Sang <wsa@sang-engineering.com>"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, riic_i2c_dt_ids); diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c new file mode 100644 index 00000000000..a9791509966 --- /dev/null +++ b/drivers/i2c/busses/i2c-rk3x.c @@ -0,0 +1,763 @@ +/* + * Driver for I2C adapter in Rockchip RK3xxx SoC + * + * Max Schwarz <max.schwarz@online.de> + * based on the patches by Rockchip Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/errno.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/spinlock.h> +#include <linux/clk.h> +#include <linux/wait.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> + + +/* Register Map */ +#define REG_CON 0x00 /* control register */ +#define REG_CLKDIV 0x04 /* clock divisor register */ +#define REG_MRXADDR 0x08 /* slave address for REGISTER_TX */ +#define REG_MRXRADDR 0x0c /* slave register address for REGISTER_TX */ +#define REG_MTXCNT 0x10 /* number of bytes to be transmitted */ +#define REG_MRXCNT 0x14 /* number of bytes to be received */ +#define REG_IEN 0x18 /* interrupt enable */ +#define REG_IPD 0x1c /* interrupt pending */ +#define REG_FCNT 0x20 /* finished count */ + +/* Data buffer offsets */ +#define TXBUFFER_BASE 0x100 +#define RXBUFFER_BASE 0x200 + +/* REG_CON bits */ +#define REG_CON_EN BIT(0) +enum { + REG_CON_MOD_TX = 0, /* transmit data */ + REG_CON_MOD_REGISTER_TX, /* select register and restart */ + REG_CON_MOD_RX, /* receive data */ + REG_CON_MOD_REGISTER_RX, /* broken: transmits read addr AND writes + * register addr */ +}; +#define REG_CON_MOD(mod) ((mod) << 1) +#define REG_CON_MOD_MASK (BIT(1) | BIT(2)) +#define REG_CON_START BIT(3) +#define REG_CON_STOP BIT(4) +#define REG_CON_LASTACK BIT(5) /* 1: send NACK after last received byte */ +#define REG_CON_ACTACK BIT(6) /* 1: stop if NACK is received */ + +/* REG_MRXADDR bits */ +#define REG_MRXADDR_VALID(x) BIT(24 + (x)) /* [x*8+7:x*8] of MRX[R]ADDR valid */ + +/* REG_IEN/REG_IPD bits */ +#define REG_INT_BTF BIT(0) /* a byte was transmitted */ +#define REG_INT_BRF BIT(1) /* a byte was received */ +#define REG_INT_MBTF BIT(2) /* master data transmit finished */ +#define REG_INT_MBRF BIT(3) /* master data receive finished */ +#define REG_INT_START BIT(4) /* START condition generated */ +#define REG_INT_STOP BIT(5) /* STOP condition generated */ +#define REG_INT_NAKRCV BIT(6) /* NACK received */ +#define REG_INT_ALL 0x7f + +/* Constants */ +#define WAIT_TIMEOUT 200 /* ms */ +#define DEFAULT_SCL_RATE (100 * 1000) /* Hz */ + +enum rk3x_i2c_state { + STATE_IDLE, + STATE_START, + STATE_READ, + STATE_WRITE, + STATE_STOP +}; + +/** + * @grf_offset: offset inside the grf regmap for setting the i2c type + */ +struct rk3x_i2c_soc_data { + int grf_offset; +}; + +struct rk3x_i2c { + struct i2c_adapter adap; + struct device *dev; + struct rk3x_i2c_soc_data *soc_data; + + /* Hardware resources */ + void __iomem *regs; + struct clk *clk; + + /* Settings */ + unsigned int scl_frequency; + + /* Synchronization & notification */ + spinlock_t lock; + wait_queue_head_t wait; + bool busy; + + /* Current message */ + struct i2c_msg *msg; + u8 addr; + unsigned int mode; + bool is_last_msg; + + /* I2C state machine */ + enum rk3x_i2c_state state; + unsigned int processed; /* sent/received bytes */ + int error; +}; + +static inline void i2c_writel(struct rk3x_i2c *i2c, u32 value, + unsigned int offset) +{ + writel(value, i2c->regs + offset); +} + +static inline u32 i2c_readl(struct rk3x_i2c *i2c, unsigned int offset) +{ + return readl(i2c->regs + offset); +} + +/* Reset all interrupt pending bits */ +static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c) +{ + i2c_writel(i2c, REG_INT_ALL, REG_IPD); +} + +/** + * Generate a START condition, which triggers a REG_INT_START interrupt. + */ +static void rk3x_i2c_start(struct rk3x_i2c *i2c) +{ + u32 val; + + rk3x_i2c_clean_ipd(i2c); + i2c_writel(i2c, REG_INT_START, REG_IEN); + + /* enable adapter with correct mode, send START condition */ + val = REG_CON_EN | REG_CON_MOD(i2c->mode) | REG_CON_START; + + /* if we want to react to NACK, set ACTACK bit */ + if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) + val |= REG_CON_ACTACK; + + i2c_writel(i2c, val, REG_CON); +} + +/** + * Generate a STOP condition, which triggers a REG_INT_STOP interrupt. + * + * @error: Error code to return in rk3x_i2c_xfer + */ +static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error) +{ + unsigned int ctrl; + + i2c->processed = 0; + i2c->msg = NULL; + i2c->error = error; + + if (i2c->is_last_msg) { + /* Enable stop interrupt */ + i2c_writel(i2c, REG_INT_STOP, REG_IEN); + + i2c->state = STATE_STOP; + + ctrl = i2c_readl(i2c, REG_CON); + ctrl |= REG_CON_STOP; + i2c_writel(i2c, ctrl, REG_CON); + } else { + /* Signal rk3x_i2c_xfer to start the next message. */ + i2c->busy = false; + i2c->state = STATE_IDLE; + + /* + * The HW is actually not capable of REPEATED START. But we can + * get the intended effect by resetting its internal state + * and issuing an ordinary START. + */ + i2c_writel(i2c, 0, REG_CON); + + /* signal that we are finished with the current msg */ + wake_up(&i2c->wait); + } +} + +/** + * Setup a read according to i2c->msg + */ +static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c) +{ + unsigned int len = i2c->msg->len - i2c->processed; + u32 con; + + con = i2c_readl(i2c, REG_CON); + + /* + * The hw can read up to 32 bytes at a time. If we need more than one + * chunk, send an ACK after the last byte of the current chunk. + */ + if (unlikely(len > 32)) { + len = 32; + con &= ~REG_CON_LASTACK; + } else { + con |= REG_CON_LASTACK; + } + + /* make sure we are in plain RX mode if we read a second chunk */ + if (i2c->processed != 0) { + con &= ~REG_CON_MOD_MASK; + con |= REG_CON_MOD(REG_CON_MOD_RX); + } + + i2c_writel(i2c, con, REG_CON); + i2c_writel(i2c, len, REG_MRXCNT); +} + +/** + * Fill the transmit buffer with data from i2c->msg + */ +static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c) +{ + unsigned int i, j; + u32 cnt = 0; + u32 val; + u8 byte; + + for (i = 0; i < 8; ++i) { + val = 0; + for (j = 0; j < 4; ++j) { + if (i2c->processed == i2c->msg->len) + break; + + if (i2c->processed == 0 && cnt == 0) + byte = (i2c->addr & 0x7f) << 1; + else + byte = i2c->msg->buf[i2c->processed++]; + + val |= byte << (j * 8); + cnt++; + } + + i2c_writel(i2c, val, TXBUFFER_BASE + 4 * i); + + if (i2c->processed == i2c->msg->len) + break; + } + + i2c_writel(i2c, cnt, REG_MTXCNT); +} + + +/* IRQ handlers for individual states */ + +static void rk3x_i2c_handle_start(struct rk3x_i2c *i2c, unsigned int ipd) +{ + if (!(ipd & REG_INT_START)) { + rk3x_i2c_stop(i2c, -EIO); + dev_warn(i2c->dev, "unexpected irq in START: 0x%x\n", ipd); + rk3x_i2c_clean_ipd(i2c); + return; + } + + /* ack interrupt */ + i2c_writel(i2c, REG_INT_START, REG_IPD); + + /* disable start bit */ + i2c_writel(i2c, i2c_readl(i2c, REG_CON) & ~REG_CON_START, REG_CON); + + /* enable appropriate interrupts and transition */ + if (i2c->mode == REG_CON_MOD_TX) { + i2c_writel(i2c, REG_INT_MBTF | REG_INT_NAKRCV, REG_IEN); + i2c->state = STATE_WRITE; + rk3x_i2c_fill_transmit_buf(i2c); + } else { + /* in any other case, we are going to be reading. */ + i2c_writel(i2c, REG_INT_MBRF | REG_INT_NAKRCV, REG_IEN); + i2c->state = STATE_READ; + rk3x_i2c_prepare_read(i2c); + } +} + +static void rk3x_i2c_handle_write(struct rk3x_i2c *i2c, unsigned int ipd) +{ + if (!(ipd & REG_INT_MBTF)) { + rk3x_i2c_stop(i2c, -EIO); + dev_err(i2c->dev, "unexpected irq in WRITE: 0x%x\n", ipd); + rk3x_i2c_clean_ipd(i2c); + return; + } + + /* ack interrupt */ + i2c_writel(i2c, REG_INT_MBTF, REG_IPD); + + /* are we finished? */ + if (i2c->processed == i2c->msg->len) + rk3x_i2c_stop(i2c, i2c->error); + else + rk3x_i2c_fill_transmit_buf(i2c); +} + +static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) +{ + unsigned int i; + unsigned int len = i2c->msg->len - i2c->processed; + u32 uninitialized_var(val); + u8 byte; + + /* we only care for MBRF here. */ + if (!(ipd & REG_INT_MBRF)) + return; + + /* ack interrupt */ + i2c_writel(i2c, REG_INT_MBRF, REG_IPD); + + /* read the data from receive buffer */ + for (i = 0; i < len; ++i) { + if (i % 4 == 0) + val = i2c_readl(i2c, RXBUFFER_BASE + (i / 4) * 4); + + byte = (val >> ((i % 4) * 8)) & 0xff; + i2c->msg->buf[i2c->processed++] = byte; + } + + /* are we finished? */ + if (i2c->processed == i2c->msg->len) + rk3x_i2c_stop(i2c, i2c->error); + else + rk3x_i2c_prepare_read(i2c); +} + +static void rk3x_i2c_handle_stop(struct rk3x_i2c *i2c, unsigned int ipd) +{ + unsigned int con; + + if (!(ipd & REG_INT_STOP)) { + rk3x_i2c_stop(i2c, -EIO); + dev_err(i2c->dev, "unexpected irq in STOP: 0x%x\n", ipd); + rk3x_i2c_clean_ipd(i2c); + return; + } + + /* ack interrupt */ + i2c_writel(i2c, REG_INT_STOP, REG_IPD); + + /* disable STOP bit */ + con = i2c_readl(i2c, REG_CON); + con &= ~REG_CON_STOP; + i2c_writel(i2c, con, REG_CON); + + i2c->busy = false; + i2c->state = STATE_IDLE; + + /* signal rk3x_i2c_xfer that we are finished */ + wake_up(&i2c->wait); +} + +static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id) +{ + struct rk3x_i2c *i2c = dev_id; + unsigned int ipd; + + spin_lock(&i2c->lock); + + ipd = i2c_readl(i2c, REG_IPD); + if (i2c->state == STATE_IDLE) { + dev_warn(i2c->dev, "irq in STATE_IDLE, ipd = 0x%x\n", ipd); + rk3x_i2c_clean_ipd(i2c); + goto out; + } + + dev_dbg(i2c->dev, "IRQ: state %d, ipd: %x\n", i2c->state, ipd); + + /* Clean interrupt bits we don't care about */ + ipd &= ~(REG_INT_BRF | REG_INT_BTF); + + if (ipd & REG_INT_NAKRCV) { + /* + * We got a NACK in the last operation. Depending on whether + * IGNORE_NAK is set, we have to stop the operation and report + * an error. + */ + i2c_writel(i2c, REG_INT_NAKRCV, REG_IPD); + + ipd &= ~REG_INT_NAKRCV; + + if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) + rk3x_i2c_stop(i2c, -ENXIO); + } + + /* is there anything left to handle? */ + if (unlikely(ipd == 0)) + goto out; + + switch (i2c->state) { + case STATE_START: + rk3x_i2c_handle_start(i2c, ipd); + break; + case STATE_WRITE: + rk3x_i2c_handle_write(i2c, ipd); + break; + case STATE_READ: + rk3x_i2c_handle_read(i2c, ipd); + break; + case STATE_STOP: + rk3x_i2c_handle_stop(i2c, ipd); + break; + case STATE_IDLE: + break; + } + +out: + spin_unlock(&i2c->lock); + return IRQ_HANDLED; +} + +static void rk3x_i2c_set_scl_rate(struct rk3x_i2c *i2c, unsigned long scl_rate) +{ + unsigned long i2c_rate = clk_get_rate(i2c->clk); + unsigned int div; + + /* SCL rate = (clk rate) / (8 * DIV) */ + div = DIV_ROUND_UP(i2c_rate, scl_rate * 8); + + /* The lower and upper half of the CLKDIV reg describe the length of + * SCL low & high periods. */ + div = DIV_ROUND_UP(div, 2); + + i2c_writel(i2c, (div << 16) | (div & 0xffff), REG_CLKDIV); +} + +/** + * Setup I2C registers for an I2C operation specified by msgs, num. + * + * Must be called with i2c->lock held. + * + * @msgs: I2C msgs to process + * @num: Number of msgs + * + * returns: Number of I2C msgs processed or negative in case of error + */ +static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) +{ + u32 addr = (msgs[0].addr & 0x7f) << 1; + int ret = 0; + + /* + * The I2C adapter can issue a small (len < 4) write packet before + * reading. This speeds up SMBus-style register reads. + * The MRXADDR/MRXRADDR hold the slave address and the slave register + * address in this case. + */ + + if (num >= 2 && msgs[0].len < 4 && + !(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { + u32 reg_addr = 0; + int i; + + dev_dbg(i2c->dev, "Combined write/read from addr 0x%x\n", + addr >> 1); + + /* Fill MRXRADDR with the register address(es) */ + for (i = 0; i < msgs[0].len; ++i) { + reg_addr |= msgs[0].buf[i] << (i * 8); + reg_addr |= REG_MRXADDR_VALID(i); + } + + /* msgs[0] is handled by hw. */ + i2c->msg = &msgs[1]; + + i2c->mode = REG_CON_MOD_REGISTER_TX; + + i2c_writel(i2c, addr | REG_MRXADDR_VALID(0), REG_MRXADDR); + i2c_writel(i2c, reg_addr, REG_MRXRADDR); + + ret = 2; + } else { + /* + * We'll have to do it the boring way and process the msgs + * one-by-one. + */ + + if (msgs[0].flags & I2C_M_RD) { + addr |= 1; /* set read bit */ + + /* + * We have to transmit the slave addr first. Use + * MOD_REGISTER_TX for that purpose. + */ + i2c->mode = REG_CON_MOD_REGISTER_TX; + i2c_writel(i2c, addr | REG_MRXADDR_VALID(0), + REG_MRXADDR); + i2c_writel(i2c, 0, REG_MRXRADDR); + } else { + i2c->mode = REG_CON_MOD_TX; + } + + i2c->msg = &msgs[0]; + + ret = 1; + } + + i2c->addr = msgs[0].addr; + i2c->busy = true; + i2c->state = STATE_START; + i2c->processed = 0; + i2c->error = 0; + + rk3x_i2c_clean_ipd(i2c); + + return ret; +} + +static int rk3x_i2c_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + struct rk3x_i2c *i2c = (struct rk3x_i2c *)adap->algo_data; + unsigned long timeout, flags; + int ret = 0; + int i; + + spin_lock_irqsave(&i2c->lock, flags); + + clk_enable(i2c->clk); + + /* The clock rate might have changed, so setup the divider again */ + rk3x_i2c_set_scl_rate(i2c, i2c->scl_frequency); + + i2c->is_last_msg = false; + + /* + * Process msgs. We can handle more than one message at once (see + * rk3x_i2c_setup()). + */ + for (i = 0; i < num; i += ret) { + ret = rk3x_i2c_setup(i2c, msgs + i, num - i); + + if (ret < 0) { + dev_err(i2c->dev, "rk3x_i2c_setup() failed\n"); + break; + } + + if (i + ret >= num) + i2c->is_last_msg = true; + + spin_unlock_irqrestore(&i2c->lock, flags); + + rk3x_i2c_start(i2c); + + timeout = wait_event_timeout(i2c->wait, !i2c->busy, + msecs_to_jiffies(WAIT_TIMEOUT)); + + spin_lock_irqsave(&i2c->lock, flags); + + if (timeout == 0) { + dev_err(i2c->dev, "timeout, ipd: 0x%02x, state: %d\n", + i2c_readl(i2c, REG_IPD), i2c->state); + + /* Force a STOP condition without interrupt */ + i2c_writel(i2c, 0, REG_IEN); + i2c_writel(i2c, REG_CON_EN | REG_CON_STOP, REG_CON); + + i2c->state = STATE_IDLE; + + ret = -ETIMEDOUT; + break; + } + + if (i2c->error) { + ret = i2c->error; + break; + } + } + + clk_disable(i2c->clk); + spin_unlock_irqrestore(&i2c->lock, flags); + + return ret; +} + +static u32 rk3x_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; +} + +static const struct i2c_algorithm rk3x_i2c_algorithm = { + .master_xfer = rk3x_i2c_xfer, + .functionality = rk3x_i2c_func, +}; + +static struct rk3x_i2c_soc_data soc_data[3] = { + { .grf_offset = 0x154 }, /* rk3066 */ + { .grf_offset = 0x0a4 }, /* rk3188 */ + { .grf_offset = -1 }, /* no I2C switching needed */ +}; + +static const struct of_device_id rk3x_i2c_match[] = { + { .compatible = "rockchip,rk3066-i2c", .data = (void *)&soc_data[0] }, + { .compatible = "rockchip,rk3188-i2c", .data = (void *)&soc_data[1] }, + { .compatible = "rockchip,rk3288-i2c", .data = (void *)&soc_data[2] }, + {}, +}; + +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; + int irq; + + i2c = devm_kzalloc(&pdev->dev, sizeof(struct rk3x_i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + + match = of_match_node(rk3x_i2c_match, np); + i2c->soc_data = (struct rk3x_i2c_soc_data *)match->data; + + if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", + &i2c->scl_frequency)) { + dev_info(&pdev->dev, "using default SCL frequency: %d\n", + DEFAULT_SCL_RATE); + i2c->scl_frequency = DEFAULT_SCL_RATE; + } + + if (i2c->scl_frequency == 0 || i2c->scl_frequency > 400 * 1000) { + dev_warn(&pdev->dev, "invalid SCL frequency specified.\n"); + dev_warn(&pdev->dev, "using default SCL frequency: %d\n", + DEFAULT_SCL_RATE); + i2c->scl_frequency = DEFAULT_SCL_RATE; + } + + strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name)); + i2c->adap.owner = THIS_MODULE; + i2c->adap.algo = &rk3x_i2c_algorithm; + i2c->adap.retries = 3; + i2c->adap.dev.of_node = np; + i2c->adap.algo_data = i2c; + i2c->adap.dev.parent = &pdev->dev; + + i2c->dev = &pdev->dev; + + spin_lock_init(&i2c->lock); + init_waitqueue_head(&i2c->wait); + + i2c->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(i2c->clk)) { + dev_err(&pdev->dev, "cannot get clock\n"); + return PTR_ERR(i2c->clk); + } + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + i2c->regs = devm_ioremap_resource(&pdev->dev, mem); + if (IS_ERR(i2c->regs)) + return PTR_ERR(i2c->regs); + + /* Try to set the I2C adapter number from dt */ + bus_nr = of_alias_get_id(np, "i2c"); + + /* + * Switch to new interface if the SoC also offers the old one. + * The control bit is located in the GRF register space. + */ + if (i2c->soc_data->grf_offset >= 0) { + struct regmap *grf; + + grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(grf)) { + dev_err(&pdev->dev, + "rk3x-i2c needs 'rockchip,grf' property\n"); + return PTR_ERR(grf); + } + + if (bus_nr < 0) { + dev_err(&pdev->dev, "rk3x-i2c needs i2cX alias"); + return -EINVAL; + } + + /* 27+i: write mask, 11+i: value */ + value = BIT(27 + bus_nr) | BIT(11 + bus_nr); + + ret = regmap_write(grf, i2c->soc_data->grf_offset, value); + if (ret != 0) { + dev_err(i2c->dev, "Could not write to GRF: %d\n", ret); + return ret; + } + } + + /* IRQ setup */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "cannot find rk3x IRQ\n"); + return irq; + } + + ret = devm_request_irq(&pdev->dev, irq, rk3x_i2c_irq, + 0, dev_name(&pdev->dev), i2c); + if (ret < 0) { + dev_err(&pdev->dev, "cannot request IRQ\n"); + return ret; + } + + platform_set_drvdata(pdev, i2c); + + ret = clk_prepare(i2c->clk); + if (ret < 0) { + dev_err(&pdev->dev, "Could not prepare clock\n"); + return ret; + } + + ret = i2c_add_adapter(&i2c->adap); + if (ret < 0) { + dev_err(&pdev->dev, "Could not register adapter\n"); + goto err_clk; + } + + dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs); + + return 0; + +err_clk: + clk_unprepare(i2c->clk); + return ret; +} + +static int rk3x_i2c_remove(struct platform_device *pdev) +{ + struct rk3x_i2c *i2c = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c->adap); + clk_unprepare(i2c->clk); + + return 0; +} + +static struct platform_driver rk3x_i2c_driver = { + .probe = rk3x_i2c_probe, + .remove = rk3x_i2c_remove, + .driver = { + .owner = THIS_MODULE, + .name = "rk3x-i2c", + .of_match_table = rk3x_i2c_match, + }, +}; + +module_platform_driver(rk3x_i2c_driver); + +MODULE_DESCRIPTION("Rockchip RK3xxx I2C Bus driver"); +MODULE_AUTHOR("Max Schwarz <max.schwarz@online.de>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-robotfuzz-osif.c b/drivers/i2c/busses/i2c-robotfuzz-osif.c new file mode 100644 index 00000000000..ced9c6a308d --- /dev/null +++ b/drivers/i2c/busses/i2c-robotfuzz-osif.c @@ -0,0 +1,202 @@ +/* + * Driver for RobotFuzz OSIF + * + * Copyright (c) 2013 Andrew Lunn <andrew@lunn.ch> + * Copyright (c) 2007 Barry Carter <Barry.Carter@robotfuzz.com> + * + * Based on the i2c-tiny-usb by + * + * Copyright (C) 2006 Til Harbaum (Till@Harbaum.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/errno.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/usb.h> + +#define OSIFI2C_READ 20 +#define OSIFI2C_WRITE 21 +#define OSIFI2C_STOP 22 +#define OSIFI2C_STATUS 23 +#define OSIFI2C_SET_BIT_RATE 24 + +#define STATUS_ADDRESS_ACK 0 +#define STATUS_ADDRESS_NAK 2 + +struct osif_priv { + struct usb_device *usb_dev; + struct usb_interface *interface; + struct i2c_adapter adapter; + unsigned char status; +}; + +static int osif_usb_read(struct i2c_adapter *adapter, int cmd, + int value, int index, void *data, int len) +{ + struct osif_priv *priv = adapter->algo_data; + + return usb_control_msg(priv->usb_dev, usb_rcvctrlpipe(priv->usb_dev, 0), + cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | + USB_DIR_IN, value, index, data, len, 2000); +} + +static int osif_usb_write(struct i2c_adapter *adapter, int cmd, + int value, int index, void *data, int len) +{ + + struct osif_priv *priv = adapter->algo_data; + + return usb_control_msg(priv->usb_dev, usb_sndctrlpipe(priv->usb_dev, 0), + cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, + value, index, data, len, 2000); +} + +static int osif_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, + int num) +{ + struct osif_priv *priv = adapter->algo_data; + struct i2c_msg *pmsg; + int ret = 0; + int i, cmd; + + for (i = 0; ret >= 0 && i < num; i++) { + pmsg = &msgs[i]; + + if (pmsg->flags & I2C_M_RD) { + cmd = OSIFI2C_READ; + + ret = osif_usb_read(adapter, cmd, pmsg->flags, + pmsg->addr, pmsg->buf, + pmsg->len); + if (ret != pmsg->len) { + dev_err(&adapter->dev, "failure reading data\n"); + return -EREMOTEIO; + } + } else { + cmd = OSIFI2C_WRITE; + + ret = osif_usb_write(adapter, cmd, pmsg->flags, + pmsg->addr, pmsg->buf, pmsg->len); + if (ret != pmsg->len) { + dev_err(&adapter->dev, "failure writing data\n"); + return -EREMOTEIO; + } + } + + ret = osif_usb_read(adapter, OSIFI2C_STOP, 0, 0, NULL, 0); + if (ret) { + dev_err(&adapter->dev, "failure sending STOP\n"); + return -EREMOTEIO; + } + + /* read status */ + ret = osif_usb_read(adapter, OSIFI2C_STATUS, 0, 0, + &priv->status, 1); + if (ret != 1) { + dev_err(&adapter->dev, "failure reading status\n"); + return -EREMOTEIO; + } + + if (priv->status != STATUS_ADDRESS_ACK) { + dev_dbg(&adapter->dev, "status = %d\n", priv->status); + return -EREMOTEIO; + } + } + + return i; +} + +static u32 osif_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm osif_algorithm = { + .master_xfer = osif_xfer, + .functionality = osif_func, +}; + +#define USB_OSIF_VENDOR_ID 0x1964 +#define USB_OSIF_PRODUCT_ID 0x0001 + +static struct usb_device_id osif_table[] = { + { USB_DEVICE(USB_OSIF_VENDOR_ID, USB_OSIF_PRODUCT_ID) }, + { } +}; +MODULE_DEVICE_TABLE(usb, osif_table); + +static int osif_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + int ret; + struct osif_priv *priv; + u16 version; + + priv = devm_kzalloc(&interface->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->usb_dev = usb_get_dev(interface_to_usbdev(interface)); + priv->interface = interface; + + usb_set_intfdata(interface, priv); + + priv->adapter.owner = THIS_MODULE; + priv->adapter.class = I2C_CLASS_HWMON; + priv->adapter.algo = &osif_algorithm; + priv->adapter.algo_data = priv; + snprintf(priv->adapter.name, sizeof(priv->adapter.name), + "OSIF at bus %03d device %03d", + priv->usb_dev->bus->busnum, priv->usb_dev->devnum); + + /* + * Set bus frequency. The frequency is: + * 120,000,000 / ( 16 + 2 * div * 4^prescale). + * Using dev = 52, prescale = 0 give 100KHz */ + ret = osif_usb_read(&priv->adapter, OSIFI2C_SET_BIT_RATE, 52, 0, + NULL, 0); + if (ret) { + dev_err(&interface->dev, "failure sending bit rate"); + usb_put_dev(priv->usb_dev); + return ret; + } + + i2c_add_adapter(&(priv->adapter)); + + version = le16_to_cpu(priv->usb_dev->descriptor.bcdDevice); + dev_info(&interface->dev, + "version %x.%02x found at bus %03d address %03d", + version >> 8, version & 0xff, + priv->usb_dev->bus->busnum, priv->usb_dev->devnum); + + return 0; +} + +static void osif_disconnect(struct usb_interface *interface) +{ + struct osif_priv *priv = usb_get_intfdata(interface); + + i2c_del_adapter(&(priv->adapter)); + usb_set_intfdata(interface, NULL); + usb_put_dev(priv->usb_dev); +} + +static struct usb_driver osif_driver = { + .name = "RobotFuzz Open Source InterFace, OSIF", + .probe = osif_probe, + .disconnect = osif_disconnect, + .id_table = osif_table, +}; + +module_usb_driver(osif_driver); + +MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>"); +MODULE_AUTHOR("Barry Carter <barry.carter@robotfuzz.com>"); +MODULE_DESCRIPTION("RobotFuzz OSIF driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 3535f3c0f7b..e828a1dba0e 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -36,6 +36,7 @@ #include <linux/cpufreq.h> #include <linux/slab.h> #include <linux/io.h> +#include <linux/of.h> #include <linux/of_gpio.h> #include <linux/pinctrl/consumer.h> @@ -85,6 +86,7 @@ #define QUIRK_S3C2440 (1 << 0) #define QUIRK_HDMIPHY (1 << 1) #define QUIRK_NO_GPIO (1 << 2) +#define QUIRK_POLL (1 << 3) /* Max time to wait for bus to become idle after a xfer (in us) */ #define S3C2410_IDLE_TIMEOUT 5000 @@ -100,7 +102,7 @@ enum s3c24xx_i2c_state { struct s3c24xx_i2c { wait_queue_head_t wait; - unsigned int quirks; + kernel_ulong_t quirks; unsigned int suspended:1; struct i2c_msg *msg; @@ -122,7 +124,7 @@ struct s3c24xx_i2c { struct s3c2410_platform_i2c *pdata; int gpios[2]; struct pinctrl *pctrl; -#ifdef CONFIG_CPU_FREQ +#if defined(CONFIG_ARM_S3C24XX_CPUFREQ) struct notifier_block freq_transition; #endif }; @@ -141,6 +143,8 @@ static struct platform_device_id s3c24xx_driver_ids[] = { }; MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); +static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat); + #ifdef CONFIG_OF static const struct of_device_id s3c24xx_i2c_match[] = { { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 }, @@ -149,6 +153,8 @@ static const struct of_device_id s3c24xx_i2c_match[] = { .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) }, { .compatible = "samsung,exynos5440-i2c", .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) }, + { .compatible = "samsung,exynos5-sata-phy-i2c", + .data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) }, {}, }; MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); @@ -159,12 +165,12 @@ MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); * Get controller type either from device tree or platform device variant. */ -static inline unsigned int s3c24xx_get_device_quirks(struct platform_device *pdev) +static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *pdev) { if (pdev->dev.of_node) { const struct of_device_id *match; match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node); - return (unsigned int)match->data; + return (kernel_ulong_t)match->data; } return platform_get_device_id(pdev)->driver_data; @@ -187,7 +193,8 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) if (ret) i2c->msg_idx = ret; - wake_up(&i2c->wait); + if (!(i2c->quirks & QUIRK_POLL)) + wake_up(&i2c->wait); } static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) @@ -224,6 +231,22 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); } +static bool is_ack(struct s3c24xx_i2c *i2c) +{ + int tries; + + for (tries = 50; tries; --tries) { + if (readl(i2c->regs + S3C2410_IICCON) + & S3C2410_IICCON_IRQPEND) { + if (!(readl(i2c->regs + S3C2410_IICSTAT) + & S3C2410_IICSTAT_LASTBIT)) + return true; + } + usleep_range(1000, 2000); + } + dev_err(i2c->dev, "ack was not recieved\n"); + return false; +} /* s3c24xx_i2c_message_start * @@ -268,6 +291,16 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, stat |= S3C2410_IICSTAT_START; writel(stat, i2c->regs + S3C2410_IICSTAT); + + if (i2c->quirks & QUIRK_POLL) { + while ((i2c->msg_num != 0) && is_ack(i2c)) { + i2c_s3c_irq_nextbyte(i2c, stat); + stat = readl(i2c->regs + S3C2410_IICSTAT); + + if (stat & S3C2410_IICSTAT_ARBITR) + dev_err(i2c->dev, "deal with arbitration loss\n"); + } + } } static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) @@ -568,6 +601,31 @@ static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id) return IRQ_HANDLED; } +/* + * Disable the bus so that we won't get any interrupts from now on, or try + * to drive any lines. This is the default state when we don't have + * anything to send/receive. + * + * If there is an event on the bus, or we have a pre-existing event at + * kernel boot time, we may not notice the event and the I2C controller + * will lock the bus with the I2C clock line low indefinitely. + */ +static inline void s3c24xx_i2c_disable_bus(struct s3c24xx_i2c *i2c) +{ + unsigned long tmp; + + /* Stop driving the I2C pins */ + tmp = readl(i2c->regs + S3C2410_IICSTAT); + tmp &= ~S3C2410_IICSTAT_TXRXEN; + writel(tmp, i2c->regs + S3C2410_IICSTAT); + + /* We don't expect any interrupts now, and don't want send acks */ + tmp = readl(i2c->regs + S3C2410_IICCON); + tmp &= ~(S3C2410_IICCON_IRQEN | S3C2410_IICCON_IRQPEND | + S3C2410_IICCON_ACKEN); + writel(tmp, i2c->regs + S3C2410_IICCON); +} + /* s3c24xx_i2c_set_master * @@ -675,6 +733,15 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_message_start(i2c, msgs); + if (i2c->quirks & QUIRK_POLL) { + ret = i2c->msg_idx; + + if (ret != num) + dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); + + goto out; + } + timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); ret = i2c->msg_idx; @@ -693,7 +760,11 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, s3c24xx_i2c_wait_idle(i2c); + s3c24xx_i2c_disable_bus(i2c); + out: + i2c->state = STATE_IDLE; + return ret; } @@ -820,6 +891,9 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) if (div1 == 512) iiccon |= S3C2410_IICCON_TXDIV_512; + if (i2c->quirks & QUIRK_POLL) + iiccon |= S3C2410_IICCON_SCALE(2); + writel(iiccon, i2c->regs + S3C2410_IICCON); if (i2c->quirks & QUIRK_S3C2440) { @@ -842,7 +916,7 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) return 0; } -#ifdef CONFIG_CPU_FREQ +#if defined(CONFIG_ARM_S3C24XX_CPUFREQ) #define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition) @@ -959,7 +1033,6 @@ static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) { - unsigned long iicon = S3C2410_IICCON_IRQEN | S3C2410_IICCON_ACKEN; struct s3c2410_platform_i2c *pdata; unsigned int freq; @@ -973,12 +1046,12 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); - writel(iicon, i2c->regs + S3C2410_IICCON); + writel(0, i2c->regs + S3C2410_IICCON); + writel(0, i2c->regs + S3C2410_IICSTAT); /* we need to work out the divisors for the clock... */ if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) { - writel(0, i2c->regs + S3C2410_IICCON); dev_err(i2c->dev, "cannot meet bus frequency required\n"); return -EINVAL; } @@ -986,7 +1059,8 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) /* todo - check that the i2c lines aren't being dragged anywhere */ dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); - dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); + dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02x\n", + readl(i2c->regs + S3C2410_IICCON)); return 0; } @@ -1040,16 +1114,12 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) } i2c = devm_kzalloc(&pdev->dev, sizeof(struct s3c24xx_i2c), GFP_KERNEL); - if (!i2c) { - dev_err(&pdev->dev, "no memory for state\n"); + if (!i2c) return -ENOMEM; - } i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!i2c->pdata) { - dev_err(&pdev->dev, "no memory for platform data\n"); + if (!i2c->pdata) return -ENOMEM; - } i2c->quirks = s3c24xx_get_device_quirks(pdev); if (pdata) @@ -1061,7 +1131,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) i2c->adap.owner = THIS_MODULE; i2c->adap.algo = &s3c24xx_i2c_algorithm; i2c->adap.retries = 2; - i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED; i2c->tx_setup = 50; init_waitqueue_head(&i2c->wait); @@ -1117,18 +1187,20 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) * ensure no current IRQs pending */ - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); - return ret; - } + if (!(i2c->quirks & QUIRK_POLL)) { + i2c->irq = ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "cannot find IRQ\n"); + return ret; + } ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0, - dev_name(&pdev->dev), i2c); + dev_name(&pdev->dev), i2c); - if (ret != 0) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - return ret; + if (ret != 0) { + dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); + return ret; + } } ret = s3c24xx_i2c_register_cpufreq(i2c); @@ -1178,8 +1250,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) i2c_del_adapter(&i2c->adap); - clk_disable_unprepare(i2c->clk); - if (pdev->dev.of_node && IS_ERR(i2c->pctrl)) s3c24xx_i2c_dt_gpio_free(i2c); @@ -1202,10 +1272,10 @@ static int s3c24xx_i2c_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); - i2c->suspended = 0; clk_prepare_enable(i2c->clk); s3c24xx_i2c_init(i2c); clk_disable_unprepare(i2c->clk); + i2c->suspended = 0; return 0; } diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index c447e8d40b7..dfc98df7b1b 100644 --- a/drivers/i2c/busses/i2c-scmi.c +++ b/drivers/i2c/busses/i2c-scmi.c @@ -12,7 +12,6 @@ #include <linux/slab.h> #include <linux/kernel.h> #include <linux/stddef.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/acpi.h> @@ -223,7 +222,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, goto out; obj = pkg->package.elements + 1; - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { + if (obj->type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "Invalid argument type")); result = -EIO; goto out; @@ -235,7 +234,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, case I2C_SMBUS_BYTE: case I2C_SMBUS_BYTE_DATA: case I2C_SMBUS_WORD_DATA: - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { + if (obj->type != ACPI_TYPE_INTEGER) { ACPI_ERROR((AE_INFO, "Invalid argument type")); result = -EIO; goto out; @@ -246,7 +245,7 @@ acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, data->byte = obj->integer.value; break; case I2C_SMBUS_BLOCK_DATA: - if (obj == NULL || obj->type != ACPI_TYPE_BUFFER) { + if (obj->type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "Invalid argument type")); result = -EIO; goto out; diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index 5e8f136e233..d76f3d9737e 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c @@ -11,7 +11,6 @@ #include <linux/delay.h> #include <linux/err.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/platform_device.h> diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 55110ddbed1..8b5e79cb446 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -32,6 +32,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/of_device.h> #include <linux/i2c/i2c-sh_mobile.h> /* Transmit operation: */ @@ -139,6 +140,10 @@ struct sh_mobile_i2c_data { bool send_stop; }; +struct sh_mobile_dt_config { + int clks_per_count; +}; + #define IIC_FLAG_HAS_ICIC67 (1 << 0) #define STANDARD_MODE 100000 @@ -194,7 +199,7 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); } -static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset) +static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf) { /* * Conditional expression: @@ -206,10 +211,10 @@ static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int off * account the fall time of SCL signal (tf). Default tf value * should be 0.3 us, for safety. */ - return (((count_khz * (tLOW + tf)) + 5000) / 10000) + offset; + return (((count_khz * (tLOW + tf)) + 5000) / 10000); } -static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int offset) +static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf) { /* * Conditional expression: @@ -225,59 +230,65 @@ static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int of * to take into account the fall time of SDA signal (tf) at START * condition, in order to meet both tHIGH and tHD;STA specs. */ - return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset; + return (((count_khz * (tHIGH + tf)) + 5000) / 10000); } -static void sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd) +static int sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd) { unsigned long i2c_clk_khz; u32 tHIGH, tLOW, tf; - int offset; + uint16_t max_val; /* Get clock rate after clock is enabled */ - clk_enable(pd->clk); + clk_prepare_enable(pd->clk); i2c_clk_khz = clk_get_rate(pd->clk) / 1000; + clk_disable_unprepare(pd->clk); i2c_clk_khz /= pd->clks_per_count; if (pd->bus_speed == STANDARD_MODE) { tLOW = 47; /* tLOW = 4.7 us */ tHIGH = 40; /* tHD;STA = tHIGH = 4.0 us */ tf = 3; /* tf = 0.3 us */ - offset = 0; /* No offset */ } else if (pd->bus_speed == FAST_MODE) { tLOW = 13; /* tLOW = 1.3 us */ tHIGH = 6; /* tHD;STA = tHIGH = 0.6 us */ tf = 3; /* tf = 0.3 us */ - offset = 0; /* No offset */ } else { dev_err(pd->dev, "unrecognized bus speed %lu Hz\n", pd->bus_speed); - goto out; + return -EINVAL; + } + + pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf); + pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf); + + max_val = pd->flags & IIC_FLAG_HAS_ICIC67 ? 0x1ff : 0xff; + if (pd->iccl > max_val || pd->icch > max_val) { + dev_err(pd->dev, "timing values out of range: L/H=0x%x/0x%x\n", + pd->iccl, pd->icch); + return -EINVAL; } - pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf, offset); /* one more bit of ICCL in ICIC */ - if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67)) + if (pd->iccl & 0x100) pd->icic |= ICIC_ICCLB8; else pd->icic &= ~ICIC_ICCLB8; - pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf, offset); /* one more bit of ICCH in ICIC */ - if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67)) + if (pd->icch & 0x100) pd->icic |= ICIC_ICCHB8; else pd->icic &= ~ICIC_ICCHB8; -out: - clk_disable(pd->clk); + return 0; } static void activate_ch(struct sh_mobile_i2c_data *pd) { /* Wake up device and enable clock */ pm_runtime_get_sync(pd->dev); - clk_enable(pd->clk); + clk_prepare_enable(pd->clk); /* Enable channel and configure rx ack */ iic_set_clr(pd, ICCR, ICCR_ICE, 0); @@ -300,7 +311,7 @@ static void deactivate_ch(struct sh_mobile_i2c_data *pd) iic_set_clr(pd, ICCR, 0, ICCR_ICE); /* Disable clock and mark device as idle */ - clk_disable(pd->clk); + clk_disable_unprepare(pd->clk); pm_runtime_put_sync(pd->dev); } @@ -316,7 +327,7 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, switch (op) { case OP_START: /* issue start and trigger DTE interrupt */ - iic_wr(pd, ICCR, 0x94); + iic_wr(pd, ICCR, ICCR_ICE | ICCR_TRS | ICCR_BBSY); break; case OP_TX_FIRST: /* disable DTE interrupt and write data */ iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); @@ -327,10 +338,11 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, break; case OP_TX_STOP: /* write data and issue a stop afterwards */ iic_wr(pd, ICDR, data); - iic_wr(pd, ICCR, pd->send_stop ? 0x90 : 0x94); + iic_wr(pd, ICCR, pd->send_stop ? ICCR_ICE | ICCR_TRS + : ICCR_ICE | ICCR_TRS | ICCR_BBSY); break; case OP_TX_TO_RX: /* select read mode */ - iic_wr(pd, ICCR, 0x81); + iic_wr(pd, ICCR, ICCR_ICE | ICCR_SCP); break; case OP_RX: /* just read data */ ret = iic_rd(pd, ICDR); @@ -338,13 +350,13 @@ static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, case OP_RX_STOP: /* enable DTE interrupt, issue stop */ iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); - iic_wr(pd, ICCR, 0xc0); + iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK); break; case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); ret = iic_rd(pd, ICDR); - iic_wr(pd, ICCR, 0xc0); + iic_wr(pd, ICCR, ICCR_ICE | ICCR_RACK); break; } @@ -479,7 +491,7 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg, { if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) { dev_err(pd->dev, "Unsupported zero length i2c read\n"); - return -EIO; + return -EOPNOTSUPP; } if (do_init) { @@ -514,17 +526,12 @@ static int poll_dte(struct sh_mobile_i2c_data *pd) break; if (val & ICSR_TACK) - return -EIO; + return -ENXIO; udelay(10); } - if (!i) { - dev_warn(pd->dev, "Timeout polling for DTE!\n"); - return -ETIMEDOUT; - } - - return 0; + return i ? 0 : -ETIMEDOUT; } static int poll_busy(struct sh_mobile_i2c_data *pd) @@ -542,20 +549,18 @@ static int poll_busy(struct sh_mobile_i2c_data *pd) */ if (!(val & ICSR_BUSY)) { /* handle missing acknowledge and arbitration lost */ - if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) - return -EIO; + val |= pd->sr; + if (val & ICSR_TACK) + return -ENXIO; + if (val & ICSR_AL) + return -EAGAIN; break; } udelay(10); } - if (!i) { - dev_err(pd->dev, "Polling timed out\n"); - return -ETIMEDOUT; - } - - return 0; + return i ? 0 : -ETIMEDOUT; } static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, @@ -617,42 +622,44 @@ static struct i2c_algorithm sh_mobile_i2c_algorithm = { .master_xfer = sh_mobile_i2c_xfer, }; -static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) +static const struct sh_mobile_dt_config default_dt_config = { + .clks_per_count = 1, +}; + +static const struct sh_mobile_dt_config rcar_gen2_dt_config = { + .clks_per_count = 2, +}; + +static const struct of_device_id sh_mobile_i2c_dt_ids[] = { + { .compatible = "renesas,rmobile-iic", .data = &default_dt_config }, + { .compatible = "renesas,iic-r8a7790", .data = &rcar_gen2_dt_config }, + { .compatible = "renesas,iic-r8a7791", .data = &rcar_gen2_dt_config }, + { .compatible = "renesas,iic-r8a7792", .data = &rcar_gen2_dt_config }, + { .compatible = "renesas,iic-r8a7793", .data = &rcar_gen2_dt_config }, + { .compatible = "renesas,iic-r8a7794", .data = &rcar_gen2_dt_config }, + {}, +}; +MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids); + +static int sh_mobile_i2c_hook_irqs(struct platform_device *dev) { struct resource *res; - int ret = -ENXIO; - int n, k = 0; + resource_size_t n; + int k = 0, ret; while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { - for (n = res->start; hook && n <= res->end; n++) { - if (request_irq(n, sh_mobile_i2c_isr, 0, - dev_name(&dev->dev), dev)) { - for (n--; n >= res->start; n--) - free_irq(n, dev); - - goto rollback; + for (n = res->start; n <= res->end; n++) { + ret = devm_request_irq(&dev->dev, n, sh_mobile_i2c_isr, + 0, dev_name(&dev->dev), dev); + if (ret) { + dev_err(&dev->dev, "cannot request IRQ %pa\n", &n); + return ret; } } k++; } - if (hook) - return k > 0 ? 0 : -ENOENT; - - ret = 0; - - rollback: - k--; - - while (k >= 0) { - res = platform_get_resource(dev, IORESOURCE_IRQ, k); - for (n = res->start; n <= res->end; n++) - free_irq(n, dev); - - k--; - } - - return ret; + return k > 0 ? 0 : -ENOENT; } static int sh_mobile_i2c_probe(struct platform_device *dev) @@ -661,62 +668,64 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) struct sh_mobile_i2c_data *pd; struct i2c_adapter *adap; struct resource *res; - int size; int ret; + u32 bus_speed; - pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL); - if (pd == NULL) { - dev_err(&dev->dev, "cannot allocate private data\n"); + pd = devm_kzalloc(&dev->dev, sizeof(struct sh_mobile_i2c_data), GFP_KERNEL); + if (!pd) return -ENOMEM; - } - pd->clk = clk_get(&dev->dev, NULL); + pd->clk = devm_clk_get(&dev->dev, NULL); if (IS_ERR(pd->clk)) { dev_err(&dev->dev, "cannot get clock\n"); - ret = PTR_ERR(pd->clk); - goto err; + return PTR_ERR(pd->clk); } - ret = sh_mobile_i2c_hook_irqs(dev, 1); - if (ret) { - dev_err(&dev->dev, "cannot request IRQ\n"); - goto err_clk; - } + ret = sh_mobile_i2c_hook_irqs(dev); + if (ret) + return ret; pd->dev = &dev->dev; platform_set_drvdata(dev, pd); res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&dev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err_irq; - } - - size = resource_size(res); - pd->reg = ioremap(res->start, size); - if (pd->reg == NULL) { - dev_err(&dev->dev, "cannot map IO\n"); - ret = -ENXIO; - goto err_irq; - } + pd->reg = devm_ioremap_resource(&dev->dev, res); + if (IS_ERR(pd->reg)) + return PTR_ERR(pd->reg); /* Use platform data bus speed or STANDARD_MODE */ - pd->bus_speed = STANDARD_MODE; - if (pdata && pdata->bus_speed) - pd->bus_speed = pdata->bus_speed; + ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed); + pd->bus_speed = ret ? STANDARD_MODE : bus_speed; + pd->clks_per_count = 1; - if (pdata && pdata->clks_per_count) - pd->clks_per_count = pdata->clks_per_count; + + if (dev->dev.of_node) { + const struct of_device_id *match; + + match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev); + if (match) { + const struct sh_mobile_dt_config *config; + + config = match->data; + pd->clks_per_count = config->clks_per_count; + } + } else { + if (pdata && pdata->bus_speed) + pd->bus_speed = pdata->bus_speed; + if (pdata && pdata->clks_per_count) + pd->clks_per_count = pdata->clks_per_count; + } /* The IIC blocks on SH-Mobile ARM processors * come with two new bits in ICIC. */ - if (size > 0x17) + if (resource_size(res) > 0x17) pd->flags |= IIC_FLAG_HAS_ICIC67; - sh_mobile_i2c_init(pd); + ret = sh_mobile_i2c_init(pd); + if (ret) + return ret; /* Enable Runtime PM for this device. * @@ -750,24 +759,14 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) ret = i2c_add_numbered_adapter(adap); if (ret < 0) { dev_err(&dev->dev, "cannot add numbered adapter\n"); - goto err_all; + return ret; } dev_info(&dev->dev, - "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n", + "I2C adapter %d with bus speed %lu Hz (L/H=0x%x/0x%x)\n", adap->nr, pd->bus_speed, pd->iccl, pd->icch); return 0; - - err_all: - iounmap(pd->reg); - err_irq: - sh_mobile_i2c_hook_irqs(dev, 0); - err_clk: - clk_put(pd->clk); - err: - kfree(pd); - return ret; } static int sh_mobile_i2c_remove(struct platform_device *dev) @@ -775,11 +774,7 @@ static int sh_mobile_i2c_remove(struct platform_device *dev) struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev); i2c_del_adapter(&pd->adap); - iounmap(pd->reg); - sh_mobile_i2c_hook_irqs(dev, 0); - clk_put(pd->clk); pm_runtime_disable(&dev->dev); - kfree(pd); return 0; } @@ -800,12 +795,6 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = { .runtime_resume = sh_mobile_i2c_runtime_nop, }; -static const struct of_device_id sh_mobile_i2c_dt_ids[] = { - { .compatible = "renesas,rmobile-iic", }, - {}, -}; -MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids); - static struct platform_driver sh_mobile_i2c_driver = { .driver = { .name = "i2c-sh_mobile", diff --git a/drivers/i2c/busses/i2c-simtec.c b/drivers/i2c/busses/i2c-simtec.c index 4fc87e7c94c..964e5c6f84a 100644 --- a/drivers/i2c/busses/i2c-simtec.c +++ b/drivers/i2c/busses/i2c-simtec.c @@ -20,7 +20,6 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -78,10 +77,8 @@ static int simtec_i2c_probe(struct platform_device *dev) int ret; pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL); - if (pd == NULL) { - dev_err(&dev->dev, "cannot allocate private data\n"); + if (pd == NULL) return -ENOMEM; - } platform_set_drvdata(dev, pd); diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 6784f7f527a..a3216defc1d 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c @@ -307,12 +307,11 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL); if (!siic) { - dev_err(&pdev->dev, "Can't allocate driver data\n"); err = -ENOMEM; goto out; } adap = &siic->adapter; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED; mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); siic->base = devm_ioremap_resource(&pdev->dev, mem_res); diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c index 79fd96a0438..ac9bc33acef 100644 --- a/drivers/i2c/busses/i2c-sis5595.c +++ b/drivers/i2c/busses/i2c-sis5595.c @@ -369,7 +369,7 @@ static struct i2c_adapter sis5595_adapter = { .algo = &smbus_algorithm, }; -static DEFINE_PCI_DEVICE_TABLE(sis5595_ids) = { +static const struct pci_device_id sis5595_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 36a9556d7cf..c6366733008 100644 --- a/drivers/i2c/busses/i2c-sis630.c +++ b/drivers/i2c/busses/i2c-sis630.c @@ -45,7 +45,6 @@ #include <linux/delay.h> #include <linux/pci.h> #include <linux/ioport.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/acpi.h> #include <linux/io.h> @@ -511,7 +510,7 @@ static struct i2c_adapter sis630_adapter = { .retries = 3 }; -static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = { +static const struct pci_device_id sis630_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_964) }, diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index b9faf9b6002..8dc2fc5f74f 100644 --- a/drivers/i2c/busses/i2c-sis96x.c +++ b/drivers/i2c/busses/i2c-sis96x.c @@ -36,7 +36,6 @@ #include <linux/stddef.h> #include <linux/ioport.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/acpi.h> #include <linux/io.h> @@ -245,7 +244,7 @@ static struct i2c_adapter sis96x_adapter = { .algo = &smbus_algorithm, }; -static DEFINE_PCI_DEVICE_TABLE(sis96x_ids) = { +static const struct pci_device_id sis96x_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-st.c b/drivers/i2c/busses/i2c-st.c new file mode 100644 index 00000000000..95b94767038 --- /dev/null +++ b/drivers/i2c/busses/i2c-st.c @@ -0,0 +1,872 @@ +/* + * Copyright (C) 2013 STMicroelectronics + * + * I2C master mode controller driver, used in STMicroelectronics devices. + * + * Author: Maxime Coquelin <maxime.coquelin@st.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/i2c.h> +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/err.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> + +/* SSC registers */ +#define SSC_BRG 0x000 +#define SSC_TBUF 0x004 +#define SSC_RBUF 0x008 +#define SSC_CTL 0x00C +#define SSC_IEN 0x010 +#define SSC_STA 0x014 +#define SSC_I2C 0x018 +#define SSC_SLAD 0x01C +#define SSC_REP_START_HOLD 0x020 +#define SSC_START_HOLD 0x024 +#define SSC_REP_START_SETUP 0x028 +#define SSC_DATA_SETUP 0x02C +#define SSC_STOP_SETUP 0x030 +#define SSC_BUS_FREE 0x034 +#define SSC_TX_FSTAT 0x038 +#define SSC_RX_FSTAT 0x03C +#define SSC_PRE_SCALER_BRG 0x040 +#define SSC_CLR 0x080 +#define SSC_NOISE_SUPP_WIDTH 0x100 +#define SSC_PRSCALER 0x104 +#define SSC_NOISE_SUPP_WIDTH_DATAOUT 0x108 +#define SSC_PRSCALER_DATAOUT 0x10c + +/* SSC Control */ +#define SSC_CTL_DATA_WIDTH_9 0x8 +#define SSC_CTL_DATA_WIDTH_MSK 0xf +#define SSC_CTL_BM 0xf +#define SSC_CTL_HB BIT(4) +#define SSC_CTL_PH BIT(5) +#define SSC_CTL_PO BIT(6) +#define SSC_CTL_SR BIT(7) +#define SSC_CTL_MS BIT(8) +#define SSC_CTL_EN BIT(9) +#define SSC_CTL_LPB BIT(10) +#define SSC_CTL_EN_TX_FIFO BIT(11) +#define SSC_CTL_EN_RX_FIFO BIT(12) +#define SSC_CTL_EN_CLST_RX BIT(13) + +/* SSC Interrupt Enable */ +#define SSC_IEN_RIEN BIT(0) +#define SSC_IEN_TIEN BIT(1) +#define SSC_IEN_TEEN BIT(2) +#define SSC_IEN_REEN BIT(3) +#define SSC_IEN_PEEN BIT(4) +#define SSC_IEN_AASEN BIT(6) +#define SSC_IEN_STOPEN BIT(7) +#define SSC_IEN_ARBLEN BIT(8) +#define SSC_IEN_NACKEN BIT(10) +#define SSC_IEN_REPSTRTEN BIT(11) +#define SSC_IEN_TX_FIFO_HALF BIT(12) +#define SSC_IEN_RX_FIFO_HALF_FULL BIT(14) + +/* SSC Status */ +#define SSC_STA_RIR BIT(0) +#define SSC_STA_TIR BIT(1) +#define SSC_STA_TE BIT(2) +#define SSC_STA_RE BIT(3) +#define SSC_STA_PE BIT(4) +#define SSC_STA_CLST BIT(5) +#define SSC_STA_AAS BIT(6) +#define SSC_STA_STOP BIT(7) +#define SSC_STA_ARBL BIT(8) +#define SSC_STA_BUSY BIT(9) +#define SSC_STA_NACK BIT(10) +#define SSC_STA_REPSTRT BIT(11) +#define SSC_STA_TX_FIFO_HALF BIT(12) +#define SSC_STA_TX_FIFO_FULL BIT(13) +#define SSC_STA_RX_FIFO_HALF BIT(14) + +/* SSC I2C Control */ +#define SSC_I2C_I2CM BIT(0) +#define SSC_I2C_STRTG BIT(1) +#define SSC_I2C_STOPG BIT(2) +#define SSC_I2C_ACKG BIT(3) +#define SSC_I2C_AD10 BIT(4) +#define SSC_I2C_TXENB BIT(5) +#define SSC_I2C_REPSTRTG BIT(11) +#define SSC_I2C_SLAVE_DISABLE BIT(12) + +/* SSC Tx FIFO Status */ +#define SSC_TX_FSTAT_STATUS 0x07 + +/* SSC Rx FIFO Status */ +#define SSC_RX_FSTAT_STATUS 0x07 + +/* SSC Clear bit operation */ +#define SSC_CLR_SSCAAS BIT(6) +#define SSC_CLR_SSCSTOP BIT(7) +#define SSC_CLR_SSCARBL BIT(8) +#define SSC_CLR_NACK BIT(10) +#define SSC_CLR_REPSTRT BIT(11) + +/* SSC Clock Prescaler */ +#define SSC_PRSC_VALUE 0x0f + + +#define SSC_TXFIFO_SIZE 0x8 +#define SSC_RXFIFO_SIZE 0x8 + +enum st_i2c_mode { + I2C_MODE_STANDARD, + I2C_MODE_FAST, + I2C_MODE_END, +}; + +/** + * struct st_i2c_timings - per-Mode tuning parameters + * @rate: I2C bus rate + * @rep_start_hold: I2C repeated start hold time requirement + * @rep_start_setup: I2C repeated start set up time requirement + * @start_hold: I2C start hold time requirement + * @data_setup_time: I2C data set up time requirement + * @stop_setup_time: I2C stop set up time requirement + * @bus_free_time: I2C bus free time requirement + * @sda_pulse_min_limit: I2C SDA pulse mini width limit + */ +struct st_i2c_timings { + u32 rate; + u32 rep_start_hold; + u32 rep_start_setup; + u32 start_hold; + u32 data_setup_time; + u32 stop_setup_time; + u32 bus_free_time; + u32 sda_pulse_min_limit; +}; + +/** + * struct st_i2c_client - client specific data + * @addr: 8-bit slave addr, including r/w bit + * @count: number of bytes to be transfered + * @xfered: number of bytes already transferred + * @buf: data buffer + * @result: result of the transfer + * @stop: last I2C msg to be sent, i.e. STOP to be generated + */ +struct st_i2c_client { + u8 addr; + u32 count; + u32 xfered; + u8 *buf; + int result; + bool stop; +}; + +/** + * struct st_i2c_dev - private data of the controller + * @adap: I2C adapter for this controller + * @dev: device for this controller + * @base: virtual memory area + * @complete: completion of I2C message + * @irq: interrupt line for th controller + * @clk: hw ssc block clock + * @mode: I2C mode of the controller. Standard or Fast only supported + * @scl_min_width_us: SCL line minimum pulse width in us + * @sda_min_width_us: SDA line minimum pulse width in us + * @client: I2C transfert information + * @busy: I2C transfer on-going + */ +struct st_i2c_dev { + struct i2c_adapter adap; + struct device *dev; + void __iomem *base; + struct completion complete; + int irq; + struct clk *clk; + int mode; + u32 scl_min_width_us; + u32 sda_min_width_us; + struct st_i2c_client client; + bool busy; +}; + +static inline void st_i2c_set_bits(void __iomem *reg, u32 mask) +{ + writel_relaxed(readl_relaxed(reg) | mask, reg); +} + +static inline void st_i2c_clr_bits(void __iomem *reg, u32 mask) +{ + writel_relaxed(readl_relaxed(reg) & ~mask, reg); +} + +/* From I2C Specifications v0.5 */ +static struct st_i2c_timings i2c_timings[] = { + [I2C_MODE_STANDARD] = { + .rate = 100000, + .rep_start_hold = 4000, + .rep_start_setup = 4700, + .start_hold = 4000, + .data_setup_time = 250, + .stop_setup_time = 4000, + .bus_free_time = 4700, + }, + [I2C_MODE_FAST] = { + .rate = 400000, + .rep_start_hold = 600, + .rep_start_setup = 600, + .start_hold = 600, + .data_setup_time = 100, + .stop_setup_time = 600, + .bus_free_time = 1300, + }, +}; + +static void st_i2c_flush_rx_fifo(struct st_i2c_dev *i2c_dev) +{ + int count, i; + + /* + * Counter only counts up to 7 but fifo size is 8... + * When fifo is full, counter is 0 and RIR bit of status register is + * set + */ + if (readl_relaxed(i2c_dev->base + SSC_STA) & SSC_STA_RIR) + count = SSC_RXFIFO_SIZE; + else + count = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT) & + SSC_RX_FSTAT_STATUS; + + for (i = 0; i < count; i++) + readl_relaxed(i2c_dev->base + SSC_RBUF); +} + +static void st_i2c_soft_reset(struct st_i2c_dev *i2c_dev) +{ + /* + * FIFO needs to be emptied before reseting the IP, + * else the controller raises a BUSY error. + */ + st_i2c_flush_rx_fifo(i2c_dev); + + st_i2c_set_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR); + st_i2c_clr_bits(i2c_dev->base + SSC_CTL, SSC_CTL_SR); +} + +/** + * st_i2c_hw_config() - Prepare SSC block, calculate and apply tuning timings + * @i2c_dev: Controller's private data + */ +static void st_i2c_hw_config(struct st_i2c_dev *i2c_dev) +{ + unsigned long rate; + u32 val, ns_per_clk; + struct st_i2c_timings *t = &i2c_timings[i2c_dev->mode]; + + st_i2c_soft_reset(i2c_dev); + + val = SSC_CLR_REPSTRT | SSC_CLR_NACK | SSC_CLR_SSCARBL | + SSC_CLR_SSCAAS | SSC_CLR_SSCSTOP; + writel_relaxed(val, i2c_dev->base + SSC_CLR); + + /* SSC Control register setup */ + val = SSC_CTL_PO | SSC_CTL_PH | SSC_CTL_HB | SSC_CTL_DATA_WIDTH_9; + writel_relaxed(val, i2c_dev->base + SSC_CTL); + + rate = clk_get_rate(i2c_dev->clk); + ns_per_clk = 1000000000 / rate; + + /* Baudrate */ + val = rate / (2 * t->rate); + writel_relaxed(val, i2c_dev->base + SSC_BRG); + + /* Pre-scaler baudrate */ + writel_relaxed(1, i2c_dev->base + SSC_PRE_SCALER_BRG); + + /* Enable I2C mode */ + writel_relaxed(SSC_I2C_I2CM, i2c_dev->base + SSC_I2C); + + /* Repeated start hold time */ + val = t->rep_start_hold / ns_per_clk; + writel_relaxed(val, i2c_dev->base + SSC_REP_START_HOLD); + + /* Repeated start set up time */ + val = t->rep_start_setup / ns_per_clk; + writel_relaxed(val, i2c_dev->base + SSC_REP_START_SETUP); + + /* Start hold time */ + val = t->start_hold / ns_per_clk; + writel_relaxed(val, i2c_dev->base + SSC_START_HOLD); + + /* Data set up time */ + val = t->data_setup_time / ns_per_clk; + writel_relaxed(val, i2c_dev->base + SSC_DATA_SETUP); + + /* Stop set up time */ + val = t->stop_setup_time / ns_per_clk; + writel_relaxed(val, i2c_dev->base + SSC_STOP_SETUP); + + /* Bus free time */ + val = t->bus_free_time / ns_per_clk; + writel_relaxed(val, i2c_dev->base + SSC_BUS_FREE); + + /* Prescalers set up */ + val = rate / 10000000; + writel_relaxed(val, i2c_dev->base + SSC_PRSCALER); + writel_relaxed(val, i2c_dev->base + SSC_PRSCALER_DATAOUT); + + /* Noise suppression witdh */ + val = i2c_dev->scl_min_width_us * rate / 100000000; + writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH); + + /* Noise suppression max output data delay width */ + val = i2c_dev->sda_min_width_us * rate / 100000000; + writel_relaxed(val, i2c_dev->base + SSC_NOISE_SUPP_WIDTH_DATAOUT); +} + +static int st_i2c_wait_free_bus(struct st_i2c_dev *i2c_dev) +{ + u32 sta; + int i; + + for (i = 0; i < 10; i++) { + sta = readl_relaxed(i2c_dev->base + SSC_STA); + if (!(sta & SSC_STA_BUSY)) + return 0; + + usleep_range(2000, 4000); + } + + dev_err(i2c_dev->dev, "bus not free (status = 0x%08x)\n", sta); + + return -EBUSY; +} + +/** + * st_i2c_write_tx_fifo() - Write a byte in the Tx FIFO + * @i2c_dev: Controller's private data + * @byte: Data to write in the Tx FIFO + */ +static inline void st_i2c_write_tx_fifo(struct st_i2c_dev *i2c_dev, u8 byte) +{ + u16 tbuf = byte << 1; + + writel_relaxed(tbuf | 1, i2c_dev->base + SSC_TBUF); +} + +/** + * st_i2c_wr_fill_tx_fifo() - Fill the Tx FIFO in write mode + * @i2c_dev: Controller's private data + * + * This functions fills the Tx FIFO with I2C transfert buffer when + * in write mode. + */ +static void st_i2c_wr_fill_tx_fifo(struct st_i2c_dev *i2c_dev) +{ + struct st_i2c_client *c = &i2c_dev->client; + u32 tx_fstat, sta; + int i; + + sta = readl_relaxed(i2c_dev->base + SSC_STA); + if (sta & SSC_STA_TX_FIFO_FULL) + return; + + tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); + tx_fstat &= SSC_TX_FSTAT_STATUS; + + if (c->count < (SSC_TXFIFO_SIZE - tx_fstat)) + i = c->count; + else + i = SSC_TXFIFO_SIZE - tx_fstat; + + for (; i > 0; i--, c->count--, c->buf++) + st_i2c_write_tx_fifo(i2c_dev, *c->buf); +} + +/** + * st_i2c_rd_fill_tx_fifo() - Fill the Tx FIFO in read mode + * @i2c_dev: Controller's private data + * + * This functions fills the Tx FIFO with fixed pattern when + * in read mode to trigger clock. + */ +static void st_i2c_rd_fill_tx_fifo(struct st_i2c_dev *i2c_dev, int max) +{ + struct st_i2c_client *c = &i2c_dev->client; + u32 tx_fstat, sta; + int i; + + sta = readl_relaxed(i2c_dev->base + SSC_STA); + if (sta & SSC_STA_TX_FIFO_FULL) + return; + + tx_fstat = readl_relaxed(i2c_dev->base + SSC_TX_FSTAT); + tx_fstat &= SSC_TX_FSTAT_STATUS; + + if (max < (SSC_TXFIFO_SIZE - tx_fstat)) + i = max; + else + i = SSC_TXFIFO_SIZE - tx_fstat; + + for (; i > 0; i--, c->xfered++) + st_i2c_write_tx_fifo(i2c_dev, 0xff); +} + +static void st_i2c_read_rx_fifo(struct st_i2c_dev *i2c_dev) +{ + struct st_i2c_client *c = &i2c_dev->client; + u32 i, sta; + u16 rbuf; + + sta = readl_relaxed(i2c_dev->base + SSC_STA); + if (sta & SSC_STA_RIR) { + i = SSC_RXFIFO_SIZE; + } else { + i = readl_relaxed(i2c_dev->base + SSC_RX_FSTAT); + i &= SSC_RX_FSTAT_STATUS; + } + + for (; (i > 0) && (c->count > 0); i--, c->count--) { + rbuf = readl_relaxed(i2c_dev->base + SSC_RBUF) >> 1; + *c->buf++ = (u8)rbuf & 0xff; + } + + if (i) { + dev_err(i2c_dev->dev, "Unexpected %d bytes in rx fifo\n", i); + st_i2c_flush_rx_fifo(i2c_dev); + } +} + +/** + * st_i2c_terminate_xfer() - Send either STOP or REPSTART condition + * @i2c_dev: Controller's private data + */ +static void st_i2c_terminate_xfer(struct st_i2c_dev *i2c_dev) +{ + struct st_i2c_client *c = &i2c_dev->client; + + st_i2c_clr_bits(i2c_dev->base + SSC_IEN, SSC_IEN_TEEN); + st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG); + + if (c->stop) { + st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_STOPEN); + st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); + } else { + st_i2c_set_bits(i2c_dev->base + SSC_IEN, SSC_IEN_REPSTRTEN); + st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_REPSTRTG); + } +} + +/** + * st_i2c_handle_write() - Handle FIFO empty interrupt in case of write + * @i2c_dev: Controller's private data + */ +static void st_i2c_handle_write(struct st_i2c_dev *i2c_dev) +{ + struct st_i2c_client *c = &i2c_dev->client; + + st_i2c_flush_rx_fifo(i2c_dev); + + if (!c->count) + /* End of xfer, send stop or repstart */ + st_i2c_terminate_xfer(i2c_dev); + else + st_i2c_wr_fill_tx_fifo(i2c_dev); +} + +/** + * st_i2c_handle_write() - Handle FIFO enmpty interrupt in case of read + * @i2c_dev: Controller's private data + */ +static void st_i2c_handle_read(struct st_i2c_dev *i2c_dev) +{ + struct st_i2c_client *c = &i2c_dev->client; + u32 ien; + + /* Trash the address read back */ + if (!c->xfered) { + readl_relaxed(i2c_dev->base + SSC_RBUF); + st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_TXENB); + } else { + st_i2c_read_rx_fifo(i2c_dev); + } + + if (!c->count) { + /* End of xfer, send stop or repstart */ + st_i2c_terminate_xfer(i2c_dev); + } else if (c->count == 1) { + /* Penultimate byte to xfer, disable ACK gen. */ + st_i2c_clr_bits(i2c_dev->base + SSC_I2C, SSC_I2C_ACKG); + + /* Last received byte is to be handled by NACK interrupt */ + ien = SSC_IEN_NACKEN | SSC_IEN_ARBLEN; + writel_relaxed(ien, i2c_dev->base + SSC_IEN); + + st_i2c_rd_fill_tx_fifo(i2c_dev, c->count); + } else { + st_i2c_rd_fill_tx_fifo(i2c_dev, c->count - 1); + } +} + +/** + * st_i2c_isr() - Interrupt routine + * @irq: interrupt number + * @data: Controller's private data + */ +static irqreturn_t st_i2c_isr_thread(int irq, void *data) +{ + struct st_i2c_dev *i2c_dev = data; + struct st_i2c_client *c = &i2c_dev->client; + u32 sta, ien; + int it; + + ien = readl_relaxed(i2c_dev->base + SSC_IEN); + sta = readl_relaxed(i2c_dev->base + SSC_STA); + + /* Use __fls() to check error bits first */ + it = __fls(sta & ien); + if (it < 0) { + dev_dbg(i2c_dev->dev, "spurious it (sta=0x%04x, ien=0x%04x)\n", + sta, ien); + return IRQ_NONE; + } + + switch (1 << it) { + case SSC_STA_TE: + if (c->addr & I2C_M_RD) + st_i2c_handle_read(i2c_dev); + else + st_i2c_handle_write(i2c_dev); + break; + + case SSC_STA_STOP: + case SSC_STA_REPSTRT: + writel_relaxed(0, i2c_dev->base + SSC_IEN); + complete(&i2c_dev->complete); + break; + + case SSC_STA_NACK: + writel_relaxed(SSC_CLR_NACK, i2c_dev->base + SSC_CLR); + + /* Last received byte handled by NACK interrupt */ + if ((c->addr & I2C_M_RD) && (c->count == 1) && (c->xfered)) { + st_i2c_handle_read(i2c_dev); + break; + } + + it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN; + writel_relaxed(it, i2c_dev->base + SSC_IEN); + + st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); + c->result = -EIO; + break; + + case SSC_STA_ARBL: + writel_relaxed(SSC_CLR_SSCARBL, i2c_dev->base + SSC_CLR); + + it = SSC_IEN_STOPEN | SSC_IEN_ARBLEN; + writel_relaxed(it, i2c_dev->base + SSC_IEN); + + st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STOPG); + c->result = -EAGAIN; + break; + + default: + dev_err(i2c_dev->dev, + "it %d unhandled (sta=0x%04x)\n", it, sta); + } + + /* + * Read IEN register to ensure interrupt mask write is effective + * before re-enabling interrupt at GIC level, and thus avoid spurious + * interrupts. + */ + readl(i2c_dev->base + SSC_IEN); + + return IRQ_HANDLED; +} + +/** + * st_i2c_xfer_msg() - Transfer a single I2C message + * @i2c_dev: Controller's private data + * @msg: I2C message to transfer + * @is_first: first message of the sequence + * @is_last: last message of the sequence + */ +static int st_i2c_xfer_msg(struct st_i2c_dev *i2c_dev, struct i2c_msg *msg, + bool is_first, bool is_last) +{ + struct st_i2c_client *c = &i2c_dev->client; + u32 ctl, i2c, it; + unsigned long timeout; + int ret; + + c->addr = (u8)(msg->addr << 1); + c->addr |= (msg->flags & I2C_M_RD); + c->buf = msg->buf; + c->count = msg->len; + c->xfered = 0; + c->result = 0; + c->stop = is_last; + + reinit_completion(&i2c_dev->complete); + + ctl = SSC_CTL_EN | SSC_CTL_MS | SSC_CTL_EN_RX_FIFO | SSC_CTL_EN_TX_FIFO; + st_i2c_set_bits(i2c_dev->base + SSC_CTL, ctl); + + i2c = SSC_I2C_TXENB; + if (c->addr & I2C_M_RD) + i2c |= SSC_I2C_ACKG; + st_i2c_set_bits(i2c_dev->base + SSC_I2C, i2c); + + /* Write slave address */ + st_i2c_write_tx_fifo(i2c_dev, c->addr); + + /* Pre-fill Tx fifo with data in case of write */ + if (!(c->addr & I2C_M_RD)) + st_i2c_wr_fill_tx_fifo(i2c_dev); + + it = SSC_IEN_NACKEN | SSC_IEN_TEEN | SSC_IEN_ARBLEN; + writel_relaxed(it, i2c_dev->base + SSC_IEN); + + if (is_first) { + ret = st_i2c_wait_free_bus(i2c_dev); + if (ret) + return ret; + + st_i2c_set_bits(i2c_dev->base + SSC_I2C, SSC_I2C_STRTG); + } + + timeout = wait_for_completion_timeout(&i2c_dev->complete, + i2c_dev->adap.timeout); + ret = c->result; + + if (!timeout) { + dev_err(i2c_dev->dev, "Write to slave 0x%x timed out\n", + c->addr); + ret = -ETIMEDOUT; + } + + i2c = SSC_I2C_STOPG | SSC_I2C_REPSTRTG; + st_i2c_clr_bits(i2c_dev->base + SSC_I2C, i2c); + + writel_relaxed(SSC_CLR_SSCSTOP | SSC_CLR_REPSTRT, + i2c_dev->base + SSC_CLR); + + return ret; +} + +/** + * st_i2c_xfer() - Transfer a single I2C message + * @i2c_adap: Adapter pointer to the controller + * @msgs: Pointer to data to be written. + * @num: Number of messages to be executed + */ +static int st_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg msgs[], int num) +{ + struct st_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap); + int ret, i; + + i2c_dev->busy = true; + + ret = clk_prepare_enable(i2c_dev->clk); + if (ret) { + dev_err(i2c_dev->dev, "Failed to prepare_enable clock\n"); + return ret; + } + + pinctrl_pm_select_default_state(i2c_dev->dev); + + st_i2c_hw_config(i2c_dev); + + for (i = 0; (i < num) && !ret; i++) + ret = st_i2c_xfer_msg(i2c_dev, &msgs[i], i == 0, i == num - 1); + + pinctrl_pm_select_idle_state(i2c_dev->dev); + + clk_disable_unprepare(i2c_dev->clk); + + i2c_dev->busy = false; + + return (ret < 0) ? ret : i; +} + +#ifdef CONFIG_PM_SLEEP +static int st_i2c_suspend(struct device *dev) +{ + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + + if (i2c_dev->busy) + return -EBUSY; + + pinctrl_pm_select_sleep_state(dev); + + return 0; +} + +static int st_i2c_resume(struct device *dev) +{ + pinctrl_pm_select_default_state(dev); + /* Go in idle state if available */ + pinctrl_pm_select_idle_state(dev); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(st_i2c_pm, st_i2c_suspend, st_i2c_resume); +#define ST_I2C_PM (&st_i2c_pm) +#else +#define ST_I2C_PM NULL +#endif + +static u32 st_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static struct i2c_algorithm st_i2c_algo = { + .master_xfer = st_i2c_xfer, + .functionality = st_i2c_func, +}; + +static int st_i2c_of_get_deglitch(struct device_node *np, + struct st_i2c_dev *i2c_dev) +{ + int ret; + + ret = of_property_read_u32(np, "st,i2c-min-scl-pulse-width-us", + &i2c_dev->scl_min_width_us); + if ((ret == -ENODATA) || (ret == -EOVERFLOW)) { + dev_err(i2c_dev->dev, "st,i2c-min-scl-pulse-width-us invalid\n"); + return ret; + } + + ret = of_property_read_u32(np, "st,i2c-min-sda-pulse-width-us", + &i2c_dev->sda_min_width_us); + if ((ret == -ENODATA) || (ret == -EOVERFLOW)) { + dev_err(i2c_dev->dev, "st,i2c-min-sda-pulse-width-us invalid\n"); + return ret; + } + + return 0; +} + +static int st_i2c_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct st_i2c_dev *i2c_dev; + struct resource *res; + u32 clk_rate; + struct i2c_adapter *adap; + int ret; + + i2c_dev = devm_kzalloc(&pdev->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(&pdev->dev, res); + if (IS_ERR(i2c_dev->base)) + return PTR_ERR(i2c_dev->base); + + i2c_dev->irq = irq_of_parse_and_map(np, 0); + if (!i2c_dev->irq) { + dev_err(&pdev->dev, "IRQ missing or invalid\n"); + return -EINVAL; + } + + i2c_dev->clk = of_clk_get_by_name(np, "ssc"); + if (IS_ERR(i2c_dev->clk)) { + dev_err(&pdev->dev, "Unable to request clock\n"); + return PTR_ERR(i2c_dev->clk); + } + + i2c_dev->mode = I2C_MODE_STANDARD; + ret = of_property_read_u32(np, "clock-frequency", &clk_rate); + if ((!ret) && (clk_rate == 400000)) + i2c_dev->mode = I2C_MODE_FAST; + + i2c_dev->dev = &pdev->dev; + + ret = devm_request_threaded_irq(&pdev->dev, i2c_dev->irq, + NULL, st_i2c_isr_thread, + IRQF_ONESHOT, pdev->name, i2c_dev); + if (ret) { + dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); + return ret; + } + + pinctrl_pm_select_default_state(i2c_dev->dev); + /* In case idle state available, select it */ + pinctrl_pm_select_idle_state(i2c_dev->dev); + + ret = st_i2c_of_get_deglitch(np, i2c_dev); + if (ret) + return ret; + + adap = &i2c_dev->adap; + i2c_set_adapdata(adap, i2c_dev); + snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%x)", res->start); + adap->owner = THIS_MODULE; + adap->timeout = 2 * HZ; + adap->retries = 0; + adap->algo = &st_i2c_algo; + adap->dev.parent = &pdev->dev; + adap->dev.of_node = pdev->dev.of_node; + + init_completion(&i2c_dev->complete); + + ret = i2c_add_adapter(adap); + if (ret) { + dev_err(&pdev->dev, "Failed to add adapter\n"); + return ret; + } + + platform_set_drvdata(pdev, i2c_dev); + + dev_info(i2c_dev->dev, "%s initialized\n", adap->name); + + return 0; +} + +static int st_i2c_remove(struct platform_device *pdev) +{ + struct st_i2c_dev *i2c_dev = platform_get_drvdata(pdev); + + i2c_del_adapter(&i2c_dev->adap); + + return 0; +} + +static const struct of_device_id st_i2c_match[] = { + { .compatible = "st,comms-ssc-i2c", }, + { .compatible = "st,comms-ssc4-i2c", }, + {}, +}; +MODULE_DEVICE_TABLE(of, st_i2c_match); + +static struct platform_driver st_i2c_driver = { + .driver = { + .name = "st-i2c", + .owner = THIS_MODULE, + .of_match_table = st_i2c_match, + .pm = ST_I2C_PM, + }, + .probe = st_i2c_probe, + .remove = st_i2c_remove, +}; + +module_platform_driver(st_i2c_driver); + +MODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics I2C driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index f8f6f2e552d..fefb1c19ec1 100644 --- a/drivers/i2c/busses/i2c-stu300.c +++ b/drivers/i2c/busses/i2c-stu300.c @@ -801,7 +801,7 @@ static int stu300_xfer_msg(struct i2c_adapter *adap, /* Check that the bus is free, or wait until some timeout occurs */ ret = stu300_wait_while_busy(dev); if (ret != 0) { - dev_err(&dev->pdev->dev, "timout waiting for transfer " + dev_err(&dev->pdev->dev, "timeout waiting for transfer " "to commence.\n"); goto exit_disable; } @@ -859,8 +859,7 @@ static const struct i2c_algorithm stu300_algo = { .functionality = stu300_func, }; -static int __init -stu300_probe(struct platform_device *pdev) +static int stu300_probe(struct platform_device *pdev) { struct stu300_dev *dev; struct i2c_adapter *adap; @@ -869,10 +868,8 @@ stu300_probe(struct platform_device *pdev) int ret = 0; dev = devm_kzalloc(&pdev->dev, sizeof(struct stu300_dev), GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, "could not allocate device struct\n"); + if (!dev) return -ENOMEM; - } bus_nr = pdev->id; dev->clk = devm_clk_get(&pdev->dev, NULL); @@ -912,7 +909,7 @@ stu300_probe(struct platform_device *pdev) adap = &dev->adapter; adap->owner = THIS_MODULE; /* DDC class but actually often used for more generic I2C */ - adap->class = I2C_CLASS_DDC; + adap->class = I2C_CLASS_DDC | I2C_CLASS_DEPRECATED; strlcpy(adap->name, "ST Microelectronics DDC I2C adapter", sizeof(adap->name)); adap->nr = bus_nr; @@ -966,8 +963,7 @@ static SIMPLE_DEV_PM_OPS(stu300_pm, stu300_suspend, stu300_resume); #define STU300_I2C_PM NULL #endif -static int __exit -stu300_remove(struct platform_device *pdev) +static int stu300_remove(struct platform_device *pdev) { struct stu300_dev *dev = platform_get_drvdata(pdev); @@ -989,13 +985,14 @@ static struct platform_driver stu300_i2c_driver = { .pm = STU300_I2C_PM, .of_match_table = stu300_dt_match, }, - .remove = __exit_p(stu300_remove), + .probe = stu300_probe, + .remove = stu300_remove, }; static int __init stu300_init(void) { - return platform_driver_probe(&stu300_i2c_driver, stu300_probe); + return platform_driver_register(&stu300_i2c_driver); } static void __exit stu300_exit(void) diff --git a/drivers/i2c/busses/i2c-sun6i-p2wi.c b/drivers/i2c/busses/i2c-sun6i-p2wi.c new file mode 100644 index 00000000000..4d75d475970 --- /dev/null +++ b/drivers/i2c/busses/i2c-sun6i-p2wi.c @@ -0,0 +1,344 @@ +/* + * P2WI (Push-Pull Two Wire Interface) bus driver. + * + * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> + * + * 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. + * + * The P2WI controller looks like an SMBus controller which only supports byte + * data transfers. But, it differs from standard SMBus protocol on several + * aspects: + * - it supports only one slave device, and thus drop the address field + * - it adds a parity bit every 8bits of data + * - only one read access is required to read a byte (instead of a write + * followed by a read access in standard SMBus protocol) + * - there's no Ack bit after each byte transfer + * + * This means this bus cannot be used to interface with standard SMBus + * devices (the only known device to support this interface is the AXP221 + * PMIC). + * + */ +#include <linux/clk.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/reset.h> + + +/* P2WI registers */ +#define P2WI_CTRL 0x0 +#define P2WI_CCR 0x4 +#define P2WI_INTE 0x8 +#define P2WI_INTS 0xc +#define P2WI_DADDR0 0x10 +#define P2WI_DADDR1 0x14 +#define P2WI_DLEN 0x18 +#define P2WI_DATA0 0x1c +#define P2WI_DATA1 0x20 +#define P2WI_LCR 0x24 +#define P2WI_PMCR 0x28 + +/* CTRL fields */ +#define P2WI_CTRL_START_TRANS BIT(7) +#define P2WI_CTRL_ABORT_TRANS BIT(6) +#define P2WI_CTRL_GLOBAL_INT_ENB BIT(1) +#define P2WI_CTRL_SOFT_RST BIT(0) + +/* CLK CTRL fields */ +#define P2WI_CCR_SDA_OUT_DELAY(v) (((v) & 0x7) << 8) +#define P2WI_CCR_MAX_CLK_DIV 0xff +#define P2WI_CCR_CLK_DIV(v) ((v) & P2WI_CCR_MAX_CLK_DIV) + +/* STATUS fields */ +#define P2WI_INTS_TRANS_ERR_ID(v) (((v) >> 8) & 0xff) +#define P2WI_INTS_LOAD_BSY BIT(2) +#define P2WI_INTS_TRANS_ERR BIT(1) +#define P2WI_INTS_TRANS_OVER BIT(0) + +/* DATA LENGTH fields*/ +#define P2WI_DLEN_READ BIT(4) +#define P2WI_DLEN_DATA_LENGTH(v) ((v - 1) & 0x7) + +/* LINE CTRL fields*/ +#define P2WI_LCR_SCL_STATE BIT(5) +#define P2WI_LCR_SDA_STATE BIT(4) +#define P2WI_LCR_SCL_CTL BIT(3) +#define P2WI_LCR_SCL_CTL_EN BIT(2) +#define P2WI_LCR_SDA_CTL BIT(1) +#define P2WI_LCR_SDA_CTL_EN BIT(0) + +/* PMU MODE CTRL fields */ +#define P2WI_PMCR_PMU_INIT_SEND BIT(31) +#define P2WI_PMCR_PMU_INIT_DATA(v) (((v) & 0xff) << 16) +#define P2WI_PMCR_PMU_MODE_REG(v) (((v) & 0xff) << 8) +#define P2WI_PMCR_PMU_DEV_ADDR(v) ((v) & 0xff) + +#define P2WI_MAX_FREQ 6000000 + +struct p2wi { + struct i2c_adapter adapter; + struct completion complete; + unsigned int status; + void __iomem *regs; + struct clk *clk; + struct reset_control *rstc; + int slave_addr; +}; + +static irqreturn_t p2wi_interrupt(int irq, void *dev_id) +{ + struct p2wi *p2wi = dev_id; + unsigned long status; + + status = readl(p2wi->regs + P2WI_INTS); + p2wi->status = status; + + /* Clear interrupts */ + status &= (P2WI_INTS_LOAD_BSY | P2WI_INTS_TRANS_ERR | + P2WI_INTS_TRANS_OVER); + writel(status, p2wi->regs + P2WI_INTS); + + complete(&p2wi->complete); + + return IRQ_HANDLED; +} + +static u32 p2wi_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_BYTE_DATA; +} + +static int p2wi_smbus_xfer(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + struct p2wi *p2wi = i2c_get_adapdata(adap); + unsigned long dlen = P2WI_DLEN_DATA_LENGTH(1); + + if (p2wi->slave_addr >= 0 && addr != p2wi->slave_addr) { + dev_err(&adap->dev, "invalid P2WI address\n"); + return -EINVAL; + } + + if (!data) + return -EINVAL; + + writel(command, p2wi->regs + P2WI_DADDR0); + + if (read_write == I2C_SMBUS_READ) + dlen |= P2WI_DLEN_READ; + else + writel(data->byte, p2wi->regs + P2WI_DATA0); + + writel(dlen, p2wi->regs + P2WI_DLEN); + + if (readl(p2wi->regs + P2WI_CTRL) & P2WI_CTRL_START_TRANS) { + dev_err(&adap->dev, "P2WI bus busy\n"); + return -EBUSY; + } + + reinit_completion(&p2wi->complete); + + writel(P2WI_INTS_LOAD_BSY | P2WI_INTS_TRANS_ERR | P2WI_INTS_TRANS_OVER, + p2wi->regs + P2WI_INTE); + + writel(P2WI_CTRL_START_TRANS | P2WI_CTRL_GLOBAL_INT_ENB, + p2wi->regs + P2WI_CTRL); + + wait_for_completion(&p2wi->complete); + + if (p2wi->status & P2WI_INTS_LOAD_BSY) { + dev_err(&adap->dev, "P2WI bus busy\n"); + return -EBUSY; + } + + if (p2wi->status & P2WI_INTS_TRANS_ERR) { + dev_err(&adap->dev, "P2WI bus xfer error\n"); + return -ENXIO; + } + + if (read_write == I2C_SMBUS_READ) + data->byte = readl(p2wi->regs + P2WI_DATA0); + + return 0; +} + +static const struct i2c_algorithm p2wi_algo = { + .smbus_xfer = p2wi_smbus_xfer, + .functionality = p2wi_functionality, +}; + +static const struct of_device_id p2wi_of_match_table[] = { + { .compatible = "allwinner,sun6i-a31-p2wi" }, + {} +}; +MODULE_DEVICE_TABLE(of, p2wi_of_match_table); + +static int p2wi_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *childnp; + unsigned long parent_clk_freq; + u32 clk_freq = 100000; + struct resource *r; + struct p2wi *p2wi; + u32 slave_addr; + int clk_div; + int irq; + int ret; + + of_property_read_u32(np, "clock-frequency", &clk_freq); + if (clk_freq > P2WI_MAX_FREQ) { + dev_err(dev, + "required clock-frequency (%u Hz) is too high (max = 6MHz)", + clk_freq); + return -EINVAL; + } + + if (of_get_child_count(np) > 1) { + dev_err(dev, "P2WI only supports one slave device\n"); + return -EINVAL; + } + + p2wi = devm_kzalloc(dev, sizeof(struct p2wi), GFP_KERNEL); + if (!p2wi) + return -ENOMEM; + + p2wi->slave_addr = -1; + + /* + * Authorize a p2wi node without any children to be able to use an + * i2c-dev from userpace. + * In this case the slave_addr is set to -1 and won't be checked when + * launching a P2WI transfer. + */ + childnp = of_get_next_available_child(np, NULL); + if (childnp) { + ret = of_property_read_u32(childnp, "reg", &slave_addr); + if (ret) { + dev_err(dev, "invalid slave address on node %s\n", + childnp->full_name); + return -EINVAL; + } + + p2wi->slave_addr = slave_addr; + } + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + p2wi->regs = devm_ioremap_resource(dev, r); + 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); + return irq; + } + + p2wi->clk = devm_clk_get(dev, NULL); + if (IS_ERR(p2wi->clk)) { + ret = PTR_ERR(p2wi->clk); + dev_err(dev, "failed to retrieve clk: %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(p2wi->clk); + if (ret) { + dev_err(dev, "failed to enable clk: %d\n", ret); + return ret; + } + + parent_clk_freq = clk_get_rate(p2wi->clk); + + p2wi->rstc = devm_reset_control_get(dev, NULL); + if (IS_ERR(p2wi->rstc)) { + ret = PTR_ERR(p2wi->rstc); + dev_err(dev, "failed to retrieve reset controller: %d\n", ret); + goto err_clk_disable; + } + + ret = reset_control_deassert(p2wi->rstc); + if (ret) { + dev_err(dev, "failed to deassert reset line: %d\n", ret); + goto err_clk_disable; + } + + init_completion(&p2wi->complete); + p2wi->adapter.dev.parent = dev; + p2wi->adapter.algo = &p2wi_algo; + p2wi->adapter.owner = THIS_MODULE; + p2wi->adapter.dev.of_node = pdev->dev.of_node; + platform_set_drvdata(pdev, p2wi); + i2c_set_adapdata(&p2wi->adapter, p2wi); + + ret = devm_request_irq(dev, irq, p2wi_interrupt, 0, pdev->name, p2wi); + if (ret) { + dev_err(dev, "can't register interrupt handler irq%d: %d\n", + irq, ret); + goto err_reset_assert; + } + + writel(P2WI_CTRL_SOFT_RST, p2wi->regs + P2WI_CTRL); + + clk_div = parent_clk_freq / clk_freq; + if (!clk_div) { + dev_warn(dev, + "clock-frequency is too high, setting it to %lu Hz\n", + parent_clk_freq); + clk_div = 1; + } else if (clk_div > P2WI_CCR_MAX_CLK_DIV) { + dev_warn(dev, + "clock-frequency is too low, setting it to %lu Hz\n", + parent_clk_freq / P2WI_CCR_MAX_CLK_DIV); + clk_div = P2WI_CCR_MAX_CLK_DIV; + } + + writel(P2WI_CCR_SDA_OUT_DELAY(1) | P2WI_CCR_CLK_DIV(clk_div), + p2wi->regs + P2WI_CCR); + + ret = i2c_add_adapter(&p2wi->adapter); + if (!ret) + return 0; + +err_reset_assert: + reset_control_assert(p2wi->rstc); + +err_clk_disable: + clk_disable_unprepare(p2wi->clk); + + return ret; +} + +static int p2wi_remove(struct platform_device *dev) +{ + struct p2wi *p2wi = platform_get_drvdata(dev); + + reset_control_assert(p2wi->rstc); + clk_disable_unprepare(p2wi->clk); + i2c_del_adapter(&p2wi->adapter); + + return 0; +} + +static struct platform_driver p2wi_driver = { + .probe = p2wi_probe, + .remove = p2wi_remove, + .driver = { + .owner = THIS_MODULE, + .name = "i2c-sunxi-p2wi", + .of_match_table = p2wi_of_match_table, + }, +}; +module_platform_driver(p2wi_driver); + +MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>"); +MODULE_DESCRIPTION("Allwinner P2WI driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c index 6ffa56e0851..05760268355 100644 --- a/drivers/i2c/busses/i2c-taos-evm.c +++ b/drivers/i2c/busses/i2c-taos-evm.c @@ -3,7 +3,7 @@ * These devices include an I2C master which can be controlled over the * serial port. * - * Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2007 Jean Delvare <jdelvare@suse.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -321,7 +321,7 @@ static void __exit taos_exit(void) serio_unregister_driver(&taos_drv); } -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("TAOS evaluation module driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c457cb447c6..f1bb2fc0679 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -27,7 +27,7 @@ #include <linux/slab.h> #include <linux/of_device.h> #include <linux/module.h> -#include <linux/clk/tegra.h> +#include <linux/reset.h> #include <asm/unaligned.h> @@ -160,6 +160,7 @@ struct tegra_i2c_dev { struct i2c_adapter adapter; struct clk *div_clk; struct clk *fast_clk; + struct reset_control *rst; void __iomem *base; int cont_id; int irq; @@ -415,9 +416,9 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) return err; } - tegra_periph_reset_assert(i2c_dev->div_clk); + reset_control_assert(i2c_dev->rst); udelay(2); - tegra_periph_reset_deassert(i2c_dev->div_clk); + reset_control_deassert(i2c_dev->rst); if (i2c_dev->is_dvc) tegra_dvc_init(i2c_dev); @@ -544,7 +545,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, i2c_dev->msg_buf_remaining = msg->len; i2c_dev->msg_err = I2C_ERR_NONE; i2c_dev->msg_read = (msg->flags & I2C_M_RD); - INIT_COMPLETION(i2c_dev->msg_complete); + reinit_completion(&i2c_dev->msg_complete); packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) | PACKET_HEADER0_PROTOCOL_I2C | @@ -731,10 +732,8 @@ static int tegra_i2c_probe(struct platform_device *pdev) } i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); - if (!i2c_dev) { - dev_err(&pdev->dev, "Could not allocate struct tegra_i2c_dev"); + if (!i2c_dev) return -ENOMEM; - } i2c_dev->base = base; i2c_dev->div_clk = div_clk; @@ -743,6 +742,12 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_dev->cont_id = pdev->id; i2c_dev->dev = &pdev->dev; + i2c_dev->rst = devm_reset_control_get(&pdev->dev, "i2c"); + if (IS_ERR(i2c_dev->rst)) { + dev_err(&pdev->dev, "missing controller reset"); + return PTR_ERR(i2c_dev->rst); + } + ret = of_property_read_u32(i2c_dev->dev->of_node, "clock-frequency", &i2c_dev->bus_clk_rate); if (ret) @@ -787,7 +792,7 @@ static int tegra_i2c_probe(struct platform_device *pdev) i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); i2c_dev->adapter.owner = THIS_MODULE; - i2c_dev->adapter.class = I2C_CLASS_HWMON; + i2c_dev->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED; strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter", sizeof(i2c_dev->adapter.name)); i2c_dev->adapter.algo = &tegra_i2c_algo; diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c index e7d3b755af3..0ed77eeff31 100644 --- a/drivers/i2c/busses/i2c-tiny-usb.c +++ b/drivers/i2c/busses/i2c-tiny-usb.c @@ -162,7 +162,6 @@ static const struct i2c_algorithm usb_algorithm = { static const struct usb_device_id i2c_tiny_usb_table[] = { { USB_DEVICE(0x0403, 0xc631) }, /* FTDI */ { USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */ - { USB_DEVICE(0x1964, 0x0001) }, /* Robofuzz OSIF */ { } /* Terminating entry */ }; diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c index be662511c58..f4a1ed75761 100644 --- a/drivers/i2c/busses/i2c-via.c +++ b/drivers/i2c/busses/i2c-via.c @@ -22,7 +22,6 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/ioport.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/io.h> @@ -89,7 +88,7 @@ static struct i2c_adapter vt586b_adapter = { }; -static DEFINE_PCI_DEVICE_TABLE(vt586b_ids) = { +static const struct pci_device_id vt586b_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3) }, { 0, } }; diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index b2d90e105f4..6841200b6e5 100644 --- a/drivers/i2c/busses/i2c-viapro.c +++ b/drivers/i2c/busses/i2c-viapro.c @@ -2,7 +2,7 @@ Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>, Mark D. Studebaker <mdsxyz123@yahoo.com> - Copyright (C) 2005 - 2008 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2005 - 2008 Jean Delvare <jdelvare@suse.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -442,7 +442,7 @@ release_region: return error; } -static DEFINE_PCI_DEVICE_TABLE(vt596_ids) = { +static const struct pci_device_id vt596_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3), .driver_data = SMBBA1 }, { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3), @@ -503,7 +503,7 @@ static void __exit i2c_vt596_exit(void) MODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>, " "Mark D. Studebaker <mdsxyz123@yahoo.com> and " - "Jean Delvare <khali@linux-fr.org>"); + "Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("vt82c596 SMBus driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-viperboard.c b/drivers/i2c/busses/i2c-viperboard.c index c68450cd8d5..7533fa34d73 100644 --- a/drivers/i2c/busses/i2c-viperboard.c +++ b/drivers/i2c/busses/i2c-viperboard.c @@ -118,8 +118,7 @@ static int vprbrd_i2c_addr(struct usb_device *usb_dev, static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg) { int ret; - u16 remain_len, bytes_xfer, len1, len2, - start = 0x0000; + u16 remain_len, len1, len2, start = 0x0000; struct vprbrd_i2c_read_msg *rmsg = (struct vprbrd_i2c_read_msg *)vb->buf; @@ -166,7 +165,6 @@ static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg) rmsg->header.len3 = remain_len - 512; rmsg->header.len4 = 0x00; rmsg->header.len5 = 0x00; - bytes_xfer = remain_len; remain_len = 0; } else if (remain_len <= 1022) { len1 = 512; @@ -367,7 +365,7 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) int ret; int pipe; - vb_i2c = kzalloc(sizeof(*vb_i2c), GFP_KERNEL); + vb_i2c = devm_kzalloc(&pdev->dev, sizeof(*vb_i2c), GFP_KERNEL); if (vb_i2c == NULL) return -ENOMEM; @@ -394,14 +392,12 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) if (ret != 1) { dev_err(&pdev->dev, "failure setting i2c_bus_freq to %d\n", i2c_bus_freq); - ret = -EIO; - goto error; + return -EIO; } } else { dev_err(&pdev->dev, "invalid i2c_bus_freq setting:%d\n", i2c_bus_freq); - ret = -EIO; - goto error; + return -EIO; } vb_i2c->i2c.dev.parent = &pdev->dev; @@ -412,10 +408,6 @@ static int vprbrd_i2c_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vb_i2c); return 0; - -error: - kfree(vb_i2c); - return ret; } static int vprbrd_i2c_remove(struct platform_device *pdev) diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c index c65da3d913a..f80a38c2072 100644 --- a/drivers/i2c/busses/i2c-wmt.c +++ b/drivers/i2c/busses/i2c-wmt.c @@ -158,7 +158,7 @@ static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg, writew(val, i2c_dev->base + REG_CR); } - INIT_COMPLETION(i2c_dev->complete); + reinit_completion(&i2c_dev->complete); if (i2c_dev->mode == I2C_MODE_STANDARD) tcr_val = TCR_STANDARD_MODE; @@ -247,7 +247,7 @@ static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg, writew(val, i2c_dev->base + REG_CR); } - INIT_COMPLETION(i2c_dev->complete); + reinit_completion(&i2c_dev->complete); if (i2c_dev->mode == I2C_MODE_STANDARD) tcr_val = TCR_STANDARD_MODE; @@ -349,6 +349,7 @@ static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev) err = clk_set_rate(i2c_dev->clk, 20000000); if (err) { dev_err(i2c_dev->dev, "failed to set clock = 20Mhz\n"); + clk_disable_unprepare(i2c_dev->clk); return err; } @@ -378,10 +379,8 @@ static int wmt_i2c_probe(struct platform_device *pdev) u32 clk_rate; i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL); - if (!i2c_dev) { - dev_err(&pdev->dev, "device memory allocation failed\n"); + if (!i2c_dev) return -ENOMEM; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); i2c_dev->base = devm_ioremap_resource(&pdev->dev, res); @@ -453,7 +452,7 @@ static int wmt_i2c_remove(struct platform_device *pdev) return 0; } -static struct of_device_id wmt_i2c_dt_ids[] = { +static const struct of_device_id wmt_i2c_dt_ids[] = { { .compatible = "wm,wm8505-i2c" }, { /* Sentinel */ }, }; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 4c8b368d463..7731f179586 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -30,8 +30,8 @@ */ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/init.h> #include <linux/errno.h> +#include <linux/err.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/i2c.h> @@ -40,6 +40,7 @@ #include <linux/i2c-xiic.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/of.h> #define DRIVER_NAME "xiic-i2c" @@ -68,7 +69,7 @@ struct xiic_i2c { struct i2c_adapter adap; struct i2c_msg *tx_msg; spinlock_t lock; - unsigned int tx_pos; + unsigned int tx_pos; unsigned int nmsgs; enum xilinx_i2c_state state; struct i2c_msg *rx_msg; @@ -271,8 +272,8 @@ static void xiic_read_rx(struct xiic_i2c *i2c) bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1; - dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d" - ", SR: 0x%x, CR: 0x%x\n", + dev_dbg(i2c->adap.dev.parent, + "%s entry, bytes in fifo: %d, msg: %d, SR: 0x%x, CR: 0x%x\n", __func__, bytes_in_fifo, xiic_rx_space(i2c), xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); @@ -339,9 +340,10 @@ static void xiic_process(struct xiic_i2c *i2c) ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); pend = isr & ier; - dev_dbg(i2c->adap.dev.parent, "%s entry, IER: 0x%x, ISR: 0x%x, " - "pend: 0x%x, SR: 0x%x, msg: %p, nmsgs: %d\n", - __func__, ier, isr, pend, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), + dev_dbg(i2c->adap.dev.parent, "%s: IER: 0x%x, ISR: 0x%x, pend: 0x%x\n", + __func__, ier, isr, pend); + dev_dbg(i2c->adap.dev.parent, "%s: SR: 0x%x, msg: %p, nmsgs: %d\n", + __func__, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), i2c->tx_msg, i2c->nmsgs); /* Do not processes a devices interrupts if the device has no @@ -541,9 +543,10 @@ static void xiic_start_send(struct xiic_i2c *i2c) xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK); - dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d, " - "ISR: 0x%x, CR: 0x%x\n", - __func__, msg, msg->len, xiic_getreg32(i2c, XIIC_IISR_OFFSET), + dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d", + __func__, msg, msg->len); + dev_dbg(i2c->adap.dev.parent, "%s entry, ISR: 0x%x, CR: 0x%x\n", + __func__, xiic_getreg32(i2c, XIIC_IISR_OFFSET), xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); if (!(msg->flags & I2C_M_NOSTART)) { @@ -681,7 +684,7 @@ static const struct i2c_algorithm xiic_algorithm = { static struct i2c_adapter xiic_adapter = { .owner = THIS_MODULE, .name = DRIVER_NAME, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, + .class = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED, .algo = &xiic_algorithm, }; @@ -694,32 +697,20 @@ static int xiic_i2c_probe(struct platform_device *pdev) int ret, irq; u8 i; + i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); + if (!i2c) + return -ENOMEM; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - goto resource_missing; + i2c->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(i2c->base)) + return PTR_ERR(i2c->base); irq = platform_get_irq(pdev, 0); if (irq < 0) - goto resource_missing; - - pdata = (struct xiic_i2c_platform_data *)dev_get_platdata(&pdev->dev); - - i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "Memory region busy\n"); - ret = -EBUSY; - goto request_mem_failed; - } + return irq; - i2c->base = ioremap(res->start, resource_size(res)); - if (!i2c->base) { - dev_err(&pdev->dev, "Unable to map registers\n"); - ret = -EIO; - goto map_failed; - } + pdata = dev_get_platdata(&pdev->dev); /* hook up driver to tree */ platform_set_drvdata(pdev, i2c); @@ -728,21 +719,23 @@ static int xiic_i2c_probe(struct platform_device *pdev) i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.of_node = pdev->dev.of_node; - xiic_reinit(i2c); - spin_lock_init(&i2c->lock); init_waitqueue_head(&i2c->wait); - ret = request_irq(irq, xiic_isr, 0, pdev->name, i2c); - if (ret) { + + ret = devm_request_irq(&pdev->dev, irq, xiic_isr, 0, pdev->name, i2c); + if (ret < 0) { dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto request_irq_failed; + return ret; } + xiic_reinit(i2c); + /* add i2c adapter to i2c tree */ ret = i2c_add_adapter(&i2c->adap); if (ret) { dev_err(&pdev->dev, "Failed to add adapter\n"); - goto add_adapter_failed; + xiic_deinit(i2c); + return ret; } if (pdata) { @@ -752,43 +745,17 @@ static int xiic_i2c_probe(struct platform_device *pdev) } return 0; - -add_adapter_failed: - free_irq(irq, i2c); -request_irq_failed: - xiic_deinit(i2c); - iounmap(i2c->base); -map_failed: - release_mem_region(res->start, resource_size(res)); -request_mem_failed: - kfree(i2c); - - return ret; -resource_missing: - dev_err(&pdev->dev, "IRQ or Memory resource is missing\n"); - return -ENOENT; } static int xiic_i2c_remove(struct platform_device *pdev) { struct xiic_i2c *i2c = platform_get_drvdata(pdev); - struct resource *res; /* remove adapter & data */ i2c_del_adapter(&i2c->adap); xiic_deinit(i2c); - free_irq(platform_get_irq(pdev, 0), i2c); - - iounmap(i2c->base); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) - release_mem_region(res->start, resource_size(res)); - - kfree(i2c); - return 0; } diff --git a/drivers/i2c/busses/i2c-xlr.c b/drivers/i2c/busses/i2c-xlr.c index 7945b05d3ea..17f7352eca6 100644 --- a/drivers/i2c/busses/i2c-xlr.c +++ b/drivers/i2c/busses/i2c-xlr.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> -#include <linux/init.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/errno.h> diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 2d1d2c5653f..ff3f5747e43 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -431,10 +431,8 @@ static struct scx200_acb_iface *scx200_create_iface(const char *text, struct i2c_adapter *adapter; iface = kzalloc(sizeof(*iface), GFP_KERNEL); - if (!iface) { - pr_err("can't allocate memory\n"); + if (!iface) return NULL; - } adapter = &iface->adapter; i2c_set_adapdata(adapter, iface); @@ -556,7 +554,7 @@ static struct platform_driver scx200_pci_driver = { .remove = scx200_remove, }; -static DEFINE_PCI_DEVICE_TABLE(scx200_isa) = { +static const struct pci_device_id scx200_isa[] = { { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, { 0, } diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c index ae1258b95d6..8eadf0f47ad 100644 --- a/drivers/i2c/busses/scx200_i2c.c +++ b/drivers/i2c/busses/scx200_i2c.c @@ -26,7 +26,6 @@ #include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> #include <linux/io.h> diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 29d3f045a2b..7c7f4b856ba 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -21,7 +21,7 @@ /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and - Jean Delvare <khali@linux-fr.org> + Jean Delvare <jdelvare@suse.de> Mux support by Rodolfo Giometti <giometti@enneenne.com> and Michael Lawnick <michael.lawnick.ext@nsn.com> OF support is copyright (c) 2008 Jochen Friedrich <jochen@scram.de> @@ -48,10 +48,13 @@ #include <linux/rwsem.h> #include <linux/pm_runtime.h> #include <linux/acpi.h> +#include <linux/jump_label.h> #include <asm/uaccess.h> #include "i2c-core.h" +#define CREATE_TRACE_POINTS +#include <trace/events/i2c.h> /* core_lock protects i2c_adapter_idr, and guarantees that device detection, deletion of detected devices, and attach_adapter @@ -62,6 +65,18 @@ static DEFINE_IDR(i2c_adapter_idr); static struct device_type i2c_client_type; static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); +static struct static_key i2c_trace_msg = STATIC_KEY_INIT_FALSE; + +void i2c_transfer_trace_reg(void) +{ + static_key_slow_inc(&i2c_trace_msg); +} + +void i2c_transfer_trace_unreg(void) +{ + static_key_slow_dec(&i2c_trace_msg); +} + /* ------------------------------------------------------------------------- */ static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, @@ -104,6 +119,11 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv) static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) { struct i2c_client *client = to_i2c_client(dev); + int rc; + + rc = acpi_device_uevent_modalias(dev, env); + if (rc != -ENODEV) + return rc; if (add_uevent_var(env, "MODALIAS=%s%s", I2C_MODULE_PREFIX, client->name)) @@ -248,17 +268,17 @@ static int i2c_device_probe(struct device *dev) driver = to_i2c_driver(dev->driver); if (!driver->probe || !driver->id_table) return -ENODEV; - client->driver = driver; + if (!device_can_wakeup(&client->dev)) device_init_wakeup(&client->dev, client->flags & I2C_CLIENT_WAKE); dev_dbg(dev, "probe\n"); + acpi_dev_pm_attach(&client->dev, true); status = driver->probe(client, i2c_match_id(driver->id_table, client)); - if (status) { - client->driver = NULL; - i2c_set_clientdata(client, NULL); - } + if (status) + acpi_dev_pm_detach(&client->dev, true); + return status; } @@ -266,7 +286,7 @@ static int i2c_device_remove(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); struct i2c_driver *driver; - int status; + int status = 0; if (!client || !dev->driver) return 0; @@ -275,14 +295,9 @@ static int i2c_device_remove(struct device *dev) if (driver->remove) { dev_dbg(dev, "remove\n"); status = driver->remove(client); - } else { - dev->driver = NULL; - status = 0; - } - if (status == 0) { - client->driver = NULL; - i2c_set_clientdata(client, NULL); } + + acpi_dev_pm_detach(&client->dev, true); return status; } @@ -409,6 +424,12 @@ static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf) { struct i2c_client *client = to_i2c_client(dev); + int len; + + len = acpi_device_modalias(dev, buf, PAGE_SIZE -1); + if (len != -ENODEV) + return len; + return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); } @@ -615,6 +636,22 @@ void i2c_unlock_adapter(struct i2c_adapter *adapter) } EXPORT_SYMBOL_GPL(i2c_unlock_adapter); +static void i2c_dev_set_name(struct i2c_adapter *adap, + struct i2c_client *client) +{ + struct acpi_device *adev = ACPI_COMPANION(&client->dev); + + if (adev) { + dev_set_name(&client->dev, "i2c-%s", acpi_dev_name(adev)); + return; + } + + /* For 10-bit clients, add an arbitrary offset to avoid collisions */ + dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), + client->addr | ((client->flags & I2C_CLIENT_TEN) + ? 0xa000 : 0)); +} + /** * i2c_new_device - instantiate an i2c device * @adap: the adapter managing the device @@ -671,12 +708,9 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.bus = &i2c_bus_type; client->dev.type = &i2c_client_type; client->dev.of_node = info->of_node; - ACPI_HANDLE_SET(&client->dev, info->acpi_node.handle); + ACPI_COMPANION_SET(&client->dev, info->acpi_node.companion); - /* For 10-bit clients, add an arbitrary offset to avoid collisions */ - dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), - client->addr | ((client->flags & I2C_CLIENT_TEN) - ? 0xa000 : 0)); + i2c_dev_set_name(adap, client); status = device_register(&client->dev); if (status) goto out_err; @@ -1100,7 +1134,7 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, return AE_OK; memset(&info, 0, sizeof(info)); - info.acpi_node.handle = handle; + info.acpi_node.companion = adev; info.irq = -1; INIT_LIST_HEAD(&resource_list); @@ -1111,8 +1145,10 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level, if (ret < 0 || !info.addr) return AE_OK; + adev->power.flags.ignore_parent = true; strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); if (!i2c_new_device(adapter, &info)) { + adev->power.flags.ignore_parent = false; dev_err(&adapter->dev, "failed to add I2C device %s from ACPI\n", dev_name(&adev->dev)); @@ -1134,6 +1170,9 @@ static void acpi_i2c_register_devices(struct i2c_adapter *adap) acpi_handle handle; acpi_status status; + if (!adap->dev.parent) + return; + handle = ACPI_HANDLE(adap->dev.parent); if (!handle) return; @@ -1606,9 +1645,14 @@ static int i2c_cmd(struct device *dev, void *_arg) { struct i2c_client *client = i2c_verify_client(dev); struct i2c_cmd_arg *arg = _arg; + struct i2c_driver *driver; + + if (!client || !client->dev.driver) + return 0; - if (client && client->driver && client->driver->command) - client->driver->command(client, arg->cmd, arg->arg); + driver = to_i2c_driver(client->dev.driver); + if (driver->command) + driver->command(client, arg->cmd, arg->arg); return 0; } @@ -1657,6 +1701,7 @@ static void __exit i2c_exit(void) class_compat_unregister(i2c_adapter_compat_class); #endif bus_unregister(&i2c_bus_type); + tracepoint_synchronize_unregister(); } /* We must initialize early, because some subsystems register i2c drivers @@ -1687,6 +1732,19 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) unsigned long orig_jiffies; int ret, try; + /* i2c_trace_msg gets enabled when tracepoint i2c_transfer gets + * enabled. This is an efficient way of keeping the for-loop from + * being executed when not needed. + */ + if (static_key_false(&i2c_trace_msg)) { + int i; + for (i = 0; i < num; i++) + if (msgs[i].flags & I2C_M_RD) + trace_i2c_read(adap, &msgs[i], i); + else + trace_i2c_write(adap, &msgs[i], i); + } + /* Retry automatically on arbitration loss */ orig_jiffies = jiffies; for (ret = 0, try = 0; try <= adap->retries; try++) { @@ -1697,6 +1755,14 @@ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) break; } + if (static_key_false(&i2c_trace_msg)) { + int i; + for (i = 0; i < ret; i++) + if (msgs[i].flags & I2C_M_RD) + trace_i2c_reply(adap, &msgs[i], i); + trace_i2c_result(adap, i, ret); + } + return ret; } EXPORT_SYMBOL(__i2c_transfer); @@ -1912,6 +1978,13 @@ static int i2c_detect_address(struct i2c_client *temp_client, struct i2c_client *client; /* Detection succeeded, instantiate the device */ + if (adapter->class & I2C_CLASS_DEPRECATED) + dev_warn(&adapter->dev, + "This adapter will soon drop class based instantiation of devices. " + "Please make sure client 0x%02x gets instantiated by other means. " + "Check 'Documentation/i2c/instantiating-devices' for details.\n", + info.addr); + dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", info.type, info.addr); client = i2c_new_device(adapter, &info); @@ -2492,6 +2565,14 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, int try; s32 res; + /* If enabled, the following two tracepoints are conditional on + * read_write and protocol. + */ + trace_smbus_write(adapter, addr, flags, read_write, + command, protocol, data); + trace_smbus_read(adapter, addr, flags, read_write, + command, protocol); + flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB; if (adapter->algo->smbus_xfer) { @@ -2512,15 +2593,24 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, i2c_unlock_adapter(adapter); if (res != -EOPNOTSUPP || !adapter->algo->master_xfer) - return res; + goto trace; /* * Fall back to i2c_smbus_xfer_emulated if the adapter doesn't * implement native support for the SMBus operation. */ } - return i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, - command, protocol, data); + res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, + command, protocol, data); + +trace: + /* If enabled, the reply tracepoint is conditional on read_write. */ + trace_smbus_reply(adapter, addr, flags, read_write, + command, protocol, data); + trace_smbus_result(adapter, addr, flags, read_write, + command, protocol, res); + + return res; } EXPORT_SYMBOL(i2c_smbus_xfer); diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index c3ccdea3d18..80b47e8ce03 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -102,8 +102,8 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) kfree(i2c_dev); } -static ssize_t show_adapter_name(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt)); @@ -111,7 +111,13 @@ static ssize_t show_adapter_name(struct device *dev, return -ENODEV; return sprintf(buf, "%s\n", i2c_dev->adap->name); } -static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); +static DEVICE_ATTR_RO(name); + +static struct attribute *i2c_attrs[] = { + &dev_attr_name.attr, + NULL, +}; +ATTRIBUTE_GROUPS(i2c); /* ------------------------------------------------------------------------- */ @@ -562,15 +568,10 @@ static int i2cdev_attach_adapter(struct device *dev, void *dummy) res = PTR_ERR(i2c_dev->dev); goto error; } - res = device_create_file(i2c_dev->dev, &dev_attr_name); - if (res) - goto error_destroy; pr_debug("i2c-dev: adapter [%s] registered as minor %d\n", adap->name, adap->nr); return 0; -error_destroy: - device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); error: return_i2c_dev(i2c_dev); return res; @@ -589,7 +590,6 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy) if (!i2c_dev) /* attach_adapter must have failed */ return 0; - device_remove_file(i2c_dev->dev, &dev_attr_name); return_i2c_dev(i2c_dev); device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); @@ -637,6 +637,7 @@ static int __init i2c_dev_init(void) res = PTR_ERR(i2c_dev_class); goto out_unreg_chrdev; } + i2c_dev_class->dev_groups = i2c_groups; /* Keep track of adapters which will be added or removed later */ res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c index 797e3117bef..2d0847b6be6 100644 --- a/drivers/i2c/i2c-mux.c +++ b/drivers/i2c/i2c-mux.c @@ -139,6 +139,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, priv->adap.algo = &priv->algo; priv->adap.algo_data = priv; priv->adap.dev.parent = &parent->dev; + priv->adap.retries = parent->retries; + priv->adap.timeout = parent->timeout; /* Sanity check on class */ if (i2c_mux_parent_classes(parent) & class) diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 44d4c6071c1..fc99f0d6b4a 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -2,7 +2,7 @@ * i2c-smbus.c - SMBus extensions to the I2C protocol * * Copyright (C) 2008 David Brownell - * Copyright (C) 2010 Jean Delvare <khali@linux-fr.org> + * Copyright (C) 2010 Jean Delvare <jdelvare@suse.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,6 +46,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) { struct i2c_client *client = i2c_verify_client(dev); struct alert_data *data = addrp; + struct i2c_driver *driver; if (!client || client->addr != data->addr) return 0; @@ -54,12 +55,13 @@ static int smbus_do_alert(struct device *dev, void *addrp) /* * Drivers should either disable alerts, or provide at least - * a minimal handler. Lock so client->driver won't change. + * a minimal handler. Lock so the driver won't change. */ device_lock(dev); - if (client->driver) { - if (client->driver->alert) - client->driver->alert(client, data->flag); + if (client->dev.driver) { + driver = to_i2c_driver(client->dev.driver); + if (driver->alert) + driver->alert(client, data->flag); else dev_warn(&client->dev, "no driver alert()!\n"); } else @@ -244,6 +246,6 @@ EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert); module_i2c_driver(smbalert_driver); -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); +MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>"); MODULE_DESCRIPTION("SMBus protocol extensions support"); MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c index d0a9c590c3c..77e4849d2f2 100644 --- a/drivers/i2c/i2c-stub.c +++ b/drivers/i2c/i2c-stub.c @@ -2,7 +2,7 @@ i2c-stub.c - I2C/SMBus chip emulator Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com> - Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org> + Copyright (C) 2007, 2012 Jean Delvare <jdelvare@suse.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index f7f9865b8b8..f6d313e528d 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -40,6 +40,7 @@ config I2C_MUX_PCA9541 config I2C_MUX_PCA954x tristate "Philips PCA954x I2C Mux/switches" + depends on GPIOLIB help If you say yes here you get support for the Philips PCA954x I2C mux/switch devices. diff --git a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c index 74b41ae690f..69afffa8f42 100644 --- a/drivers/i2c/muxes/i2c-arb-gpio-challenge.c +++ b/drivers/i2c/muxes/i2c-arb-gpio-challenge.c @@ -19,7 +19,6 @@ #include <linux/kernel.h> #include <linux/i2c.h> #include <linux/i2c-mux.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/of_gpio.h> #include <linux/platform_device.h> @@ -200,7 +199,7 @@ static int i2c_arbitrator_probe(struct platform_device *pdev) arb->parent = of_find_i2c_adapter_by_node(parent_np); if (!arb->parent) { dev_err(dev, "Cannot find parent bus\n"); - return -EINVAL; + return -EPROBE_DEFER; } /* Actually add the mux adapter */ @@ -238,7 +237,7 @@ static struct platform_driver i2c_arbitrator_driver = { .driver = { .owner = THIS_MODULE, .name = "i2c-arb-gpio-challenge", - .of_match_table = of_match_ptr(i2c_arbitrator_of_match), + .of_match_table = i2c_arbitrator_of_match, }, }; diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c index 5d4a99ba743..d8989c823f5 100644 --- a/drivers/i2c/muxes/i2c-mux-gpio.c +++ b/drivers/i2c/muxes/i2c-mux-gpio.c @@ -12,7 +12,6 @@ #include <linux/i2c-mux.h> #include <linux/i2c-mux-gpio.h> #include <linux/platform_device.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/gpio.h> @@ -30,15 +29,15 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val) int i; for (i = 0; i < mux->data.n_gpios; i++) - gpio_set_value(mux->gpio_base + mux->data.gpios[i], - val & (1 << i)); + gpio_set_value_cansleep(mux->gpio_base + mux->data.gpios[i], + val & (1 << i)); } static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan) { struct gpiomux *mux = data; - i2c_mux_gpio_set(mux, mux->data.values[chan]); + i2c_mux_gpio_set(mux, chan); return 0; } @@ -66,7 +65,7 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, struct device_node *adapter_np, *child; struct i2c_adapter *adapter; unsigned *values, *gpios; - int i = 0; + int i = 0, ret; if (!np) return -ENODEV; @@ -79,7 +78,7 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, adapter = of_find_i2c_adapter_by_node(adapter_np); if (!adapter) { dev_err(&pdev->dev, "Cannot find parent bus\n"); - return -ENODEV; + return -EPROBE_DEFER; } mux->data.parent = i2c_adapter_id(adapter); put_device(&adapter->dev); @@ -116,8 +115,12 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux, return -ENOMEM; } - for (i = 0; i < mux->data.n_gpios; i++) - gpios[i] = of_get_named_gpio(np, "mux-gpios", i); + for (i = 0; i < mux->data.n_gpios; i++) { + ret = of_get_named_gpio(np, "mux-gpios", i); + if (ret < 0) + return ret; + gpios[i] = ret; + } mux->data.gpios = gpios; @@ -177,7 +180,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) if (!parent) { dev_err(&pdev->dev, "Parent adapter (%d) not found\n", mux->data.parent); - return -ENODEV; + return -EPROBE_DEFER; } mux->parent = parent; @@ -224,7 +227,7 @@ static int i2c_mux_gpio_probe(struct platform_device *pdev) unsigned int class = mux->data.classes ? mux->data.classes[i] : 0; mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, - i, class, + mux->data.values[i], class, i2c_mux_gpio_select, deselect); if (!mux->adap[i]) { ret = -ENODEV; @@ -279,7 +282,7 @@ static struct platform_driver i2c_mux_gpio_driver = { .driver = { .owner = THIS_MODULE, .name = "i2c-mux-gpio", - .of_match_table = of_match_ptr(i2c_mux_gpio_of_match), + .of_match_table = i2c_mux_gpio_of_match, }, }; diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index c4f08ad3118..cb772775da4 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -17,7 +17,6 @@ */ #include <linux/module.h> -#include <linux/init.h> #include <linux/jiffies.h> #include <linux/delay.h> #include <linux/slab.h> diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index bad5b84a598..9bd4212782a 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -28,21 +28,20 @@ * Based on: * i2c-virtual_cb.c from Brian Kuschak <bkuschak@yahoo.com> * and - * pca9540.c from Jean Delvare <khali@linux-fr.org>. + * 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/module.h> -#include <linux/init.h> -#include <linux/slab.h> #include <linux/device.h> +#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/i2c-mux.h> - #include <linux/i2c/pca954x.h> +#include <linux/module.h> +#include <linux/slab.h> #define PCA954X_MAX_NCHANS 8 @@ -186,28 +185,32 @@ static int pca954x_probe(struct i2c_client *client, { struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); struct pca954x_platform_data *pdata = dev_get_platdata(&client->dev); + struct gpio_desc *gpio; int num, force, class; struct pca954x *data; - int ret = -ENODEV; + int ret; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) - goto err; + return -ENODEV; - data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } + data = devm_kzalloc(&client->dev, sizeof(struct pca954x), GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); + /* Get the mux out of reset if a reset GPIO is specified. */ + gpio = devm_gpiod_get(&client->dev, "reset"); + if (!IS_ERR(gpio)) + gpiod_direction_output(gpio, 0); + /* Write the mux register at addr to verify * that the mux is in fact present. This also * initializes the mux to disconnected state. */ if (i2c_smbus_write_byte(client, 0) < 0) { dev_warn(&client->dev, "probe failed\n"); - goto exit_free; + return -ENODEV; } data->type = id->driver_data; @@ -252,9 +255,6 @@ static int pca954x_probe(struct i2c_client *client, virt_reg_failed: for (num--; num >= 0; num--) i2c_del_mux_adapter(data->virt_adaps[num]); -exit_free: - kfree(data); -err: return ret; } @@ -270,7 +270,6 @@ static int pca954x_remove(struct i2c_client *client) data->virt_adaps[i] = NULL; } - kfree(data); return 0; } diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 69a91732ae6..4ff0ef3e07a 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -18,12 +18,12 @@ #include <linux/i2c.h> #include <linux/i2c-mux.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/pinctrl/consumer.h> #include <linux/i2c-mux-pinctrl.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/of.h> struct i2c_mux_pinctrl { struct device *dev; @@ -113,7 +113,7 @@ static int i2c_mux_pinctrl_parse_dt(struct i2c_mux_pinctrl *mux, adapter = of_find_i2c_adapter_by_node(adapter_np); if (!adapter) { dev_err(mux->dev, "Cannot find parent bus\n"); - return -ENODEV; + return -EPROBE_DEFER; } mux->pdata->parent_bus_num = i2c_adapter_id(adapter); put_device(&adapter->dev); @@ -211,7 +211,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) if (!mux->parent) { dev_err(&pdev->dev, "Parent adapter (%d) not found\n", mux->pdata->parent_bus_num); - ret = -ENODEV; + ret = -EPROBE_DEFER; goto err; } |
