diff options
Diffstat (limited to 'drivers/i2c/busses')
59 files changed, 929 insertions, 242 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 3b26129f605..f5ed03164d8 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -152,6 +152,7 @@ config I2C_PIIX4 ATI SB700/SP5100 ATI SB800 AMD Hudson-2 + AMD ML AMD CZ Serverworks OSB4 Serverworks CSB5 @@ -412,7 +413,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 @@ -648,6 +648,16 @@ config I2C_PXA_SLAVE is necessary for systems where the PXA may be a target on the I2C bus. +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 HAVE_S3C2410_I2C bool help @@ -683,7 +693,7 @@ config I2C_SH7760 config I2C_SH_MOBILE tristate "SuperH Mobile I2C Controller" - depends on SUPERH || ARM || COMPILE_TEST + 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. @@ -796,7 +806,7 @@ config I2C_XLR config I2C_RCAR tristate "Renesas R-Car I2C Controller" - depends on ARM || COMPILE_TEST + depends on ARCH_SHMOBILE || COMPILE_TEST help If you say yes to this option, support will be included for the R-Car I2C controller. @@ -865,6 +875,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 diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index c73eb0ea788..a08931fe73e 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o +obj-$(CONFIG_I2C_RIIC) += i2c-riic.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_S6000) += i2c-s6000.o obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o @@ -83,6 +84,7 @@ 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 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..7d60d3a1f62 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> diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c index 84ccd9496a5..4611e4754a6 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 diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 26bcc6127ce..4823206a487 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> 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..819d3c1062a 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> diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index a44e6e77c5a..f3d4d79855b 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> diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index 8edba9de76d..843d01268ae 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -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, } , { 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-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c index ce7ffba2b02..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> diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 3e5ea2c87a6..be7f0a20d63 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c @@ -33,7 +33,6 @@ #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> diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index e89e3e2145e..14c4b30d4cc 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> diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c index ff15ae90aaf..e08e458bab0 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> diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index c1ef228095b..9fd711c03dd 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/i2c.h> -#include <linux/init.h> #include <linux/time.h> #include <linux/interrupt.h> #include <linux/delay.h> @@ -571,7 +570,7 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap, int i = 0, ret = 0, stop = 0; if (i2c->suspended) { - dev_err(i2c->dev, "HS-I2C is not initialzed.\n"); + dev_err(i2c->dev, "HS-I2C is not initialized.\n"); return -EIO; } 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..e248257fe51 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> diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 737e2986688..349c2d35e79 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> @@ -1312,8 +1312,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 f7444100f39..274312c96b1 100644 --- a/drivers/i2c/busses/i2c-ibm_iic.c +++ b/drivers/i2c/busses/i2c-ibm_iic.c @@ -36,7 +36,6 @@ #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> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index d0cfbb4cb96..db895fb22e6 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -607,7 +607,7 @@ static int i2c_imx_probe(struct platform_device *pdev) 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); 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 0043ede234c..8ce4f517fc5 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> @@ -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; @@ -509,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); @@ -582,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 b6a741caf4f..f5391633b53 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c @@ -16,7 +16,6 @@ #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> diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 8be7e42aa4d..b8c5187b9ee 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -692,6 +692,7 @@ static const struct of_device_id mv64xxx_i2c_of_match_table[] = { { .compatible = "allwinner,sun4i-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); @@ -783,6 +784,10 @@ 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; + } out: return rc; #endif 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..0038c451095 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> diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 8bf9ac01301..4443613514e 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,29 @@ /* 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 nmk_i2c_controller - client specific controller configuration + * @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 + */ +struct nmk_i2c_controller { + u32 clk_freq; + unsigned char tft; + unsigned char rft; + int timeout; + enum i2c_freq_mode sm; +}; + /** * struct i2c_vendor_data - per-vendor variations * @has_mtdws: variant has the MTDWS bit @@ -340,6 +362,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,18 +371,38 @@ 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->cfg.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 @@ -915,11 +959,6 @@ static const struct i2c_algorithm nmk_i2c_algo = { }; 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 */ @@ -1027,7 +1066,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id) /* 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; diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c index c61f37a10a0..80e06fa4572 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> 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-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-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..39dd8ec60df 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", 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 c9a352f0a9a..dc7ff829ad7 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -628,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); @@ -657,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; @@ -672,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); @@ -730,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; @@ -739,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", @@ -747,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; } @@ -767,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 8c87f4a9793..01e967763c2 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -24,7 +24,6 @@ #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> 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-rcar.c b/drivers/i2c/busses/i2c-rcar.c index 2c2fd7c2b11..0282d4d4280 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -26,7 +26,6 @@ #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> @@ -111,6 +110,7 @@ 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; @@ -227,18 +227,12 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, u32 bus_speed, struct device *dev) { - struct clk *clkp = clk_get(dev, NULL); u32 scgd, cdf; u32 round, ick; u32 scl; u32 cdf_width; unsigned long rate; - if (IS_ERR(clkp)) { - dev_err(dev, "couldn't get clock\n"); - return PTR_ERR(clkp); - } - switch (priv->devtype) { case I2C_RCAR_GEN1: cdf_width = 2; @@ -266,7 +260,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, * clkp : peripheral_clk * F[] : integer up-valuation */ - rate = clk_get_rate(clkp); + rate = clk_get_rate(priv->clk); cdf = rate / 20000000; if (cdf >= 1 << cdf_width) { dev_err(dev, "Input clock %lu too high\n", rate); @@ -308,7 +302,7 @@ static int rcar_i2c_clock_calculate(struct rcar_i2c_priv *priv, 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 @@ -604,7 +598,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, * error handling */ if (rcar_i2c_flags_has(priv, ID_NACK)) { - ret = -EREMOTEIO; + ret = -ENXIO; break; } @@ -623,7 +617,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap, pm_runtime_put(dev); - if (ret < 0) + if (ret < 0 && ret != -ENXIO) dev_err(dev, "error %d : %x\n", ret, priv->flags); return ret; @@ -664,6 +658,12 @@ static int rcar_i2c_probe(struct platform_device *pdev) 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 */ ret = of_property_read_u32(dev->of_node, "clock-frequency", &bus_speed); if (ret < 0 && pdata && pdata->bus_speed) diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c new file mode 100644 index 00000000000..9e1f8bacfb3 --- /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 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-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 bf8fb94ebc5..684d21e71e4 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -86,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 @@ -101,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; @@ -123,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 }; @@ -142,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 }, @@ -150,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); @@ -160,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; @@ -188,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) @@ -225,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 * @@ -269,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) @@ -676,6 +708,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; @@ -821,6 +862,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) { @@ -843,7 +887,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) @@ -1118,18 +1162,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); diff --git a/drivers/i2c/busses/i2c-scmi.c b/drivers/i2c/busses/i2c-scmi.c index 59923551413..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> 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-simtec.c b/drivers/i2c/busses/i2c-simtec.c index 4fc87e7c94c..294c80f21d6 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> diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c index 36a9556d7cf..19b8505d0cd 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> diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c index b9faf9b6002..f8aa0c29f02 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> diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c index 04a17b9b38b..5b80ef31084 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; } 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 e661edee4d0..9704537aee3 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); @@ -743,6 +744,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) 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..49d7f14b9d2 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> diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c index b2d90e105f4..40d36df678d 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 @@ -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-xiic.c b/drivers/i2c/busses/i2c-xiic.c index fc2716afdfd..28107502517 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> @@ -69,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; @@ -272,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)); @@ -340,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 @@ -542,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)) { @@ -695,33 +697,21 @@ 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; + return irq; pdata = 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; - } - - 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; - } - /* hook up driver to tree */ platform_set_drvdata(pdev, i2c); i2c->adap = xiic_adapter; @@ -729,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) { @@ -753,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_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> |