Merge branch 'i2c/for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Aug 2014 16:15:07 +0000 (09:15 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 9 Aug 2014 16:15:07 +0000 (09:15 -0700)
Pull i2c updates from Wolfram Sang:
 "Highlights:

   - class based instantiation finally dropped for most embedded drivers
     bringing boot up performance gains
   - removed two drivers (one outdated, one a duplicate)
   - ACPI has now operation region support (thanks to Lan Tianyu)
   - the i2c-stub driver got overhauled and gained new features to
     become more useful when writing i2c client drivers (thanks to
     Guenter Roeck and Jean Delvare)

  The rest is driver bugfixes, added bindings/ids, cleanups..."

* 'i2c/for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (43 commits)
  i2c: mpc: delete unneeded test before of_node_put
  i2c: rk3x: fix interrupt handling issue
  i2c: imx: Fix format warning for dev_dbg
  i2c: qup: disable clks and return instead of just returning error
  i2c: exynos5: always enable HSI2C
  i2c: designware: add new bindings
  i2c: gpio: Drop dead code in i2c_gpio_remove
  i2c: pca954x: put the mux to disconnected state after resume
  i2c: st: Update i2c timings
  drivers/i2c/busses: use correct type for dma_map/unmap
  i2c: i2c-st: Use %pa to print 'resource_size_t' type
  i2c: s3c2410: resume the I2C controller earlier
  i2c: stub: Avoid an array overrun on I2C block transfers
  i2c: i801: Add device ID for Intel Wildcat Point PCH
  i2c: i801: Fix the alignment of the device table
  i2c: stub: Add support for banked register ranges
  i2c: stub: Remember the number of emulated chips
  i2c: stub: Add support for SMBus block commands
  i2c: efm32: correct namespacing of location property
  i2c: exynos5: remove extra line and fix an assignment
  ...

43 files changed:
Documentation/devicetree/bindings/i2c/i2c-efm32.txt
Documentation/i2c/busses/i2c-i801
Documentation/i2c/i2c-stub
drivers/i2c/Kconfig
drivers/i2c/Makefile
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-bfin-twi.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-pcidrv.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-efm32.c
drivers/i2c/busses/i2c-exynos5.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-qup.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-rk3x.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-s6000.c [deleted file]
drivers/i2c/busses/i2c-s6000.h [deleted file]
drivers/i2c/busses/i2c-sirf.c
drivers/i2c/busses/i2c-st.c
drivers/i2c/busses/i2c-stu300.c
drivers/i2c/busses/i2c-taos-evm.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/busses/i2c-xiic.c
drivers/i2c/busses/scx200_i2c.c [deleted file]
drivers/i2c/i2c-acpi.c [new file with mode: 0644]
drivers/i2c/i2c-core.c
drivers/i2c/i2c-stub.c
drivers/i2c/muxes/i2c-mux-pca954x.c
include/linux/acpi.h
include/linux/i2c.h
include/linux/i2c/s6000.h [deleted file]

index fc15ac5..50b25c3 100644 (file)
@@ -10,7 +10,7 @@ Required properties :
 Recommended properties :
 
  - clock-frequency : maximal I2C bus clock frequency in Hz.
- - efm32,location : Decides the location of the USART I/O pins.
+ - energymicro,location : Decides the location of the USART I/O pins.
    Allowed range : [0 .. 6]
 
 Example:
@@ -23,7 +23,7 @@ Example:
                clocks = <&cmu clk_HFPERCLKI2C0>;
                clock-frequency = <100000>;
                status = "ok";
-               efm32,location = <3>;
+               energymicro,location = <3>;
 
                eeprom@50 {
                        compatible = "microchip,24c02";
index adf5e33..e9c803e 100644 (file)
@@ -25,6 +25,7 @@ Supported adapters:
   * Intel Avoton (SOC)
   * Intel Wellsburg (PCH)
   * Intel Coleto Creek (PCH)
+  * Intel Wildcat Point (PCH)
   * Intel Wildcat Point-LP (PCH)
   * Intel BayTrail (SOC)
    Datasheets: Publicly available at the Intel website
index fa4b669..a16924f 100644 (file)
@@ -2,9 +2,9 @@ MODULE: i2c-stub
 
 DESCRIPTION:
 
-This module is a very simple fake I2C/SMBus driver.  It implements five
+This module is a very simple fake I2C/SMBus driver.  It implements six
 types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, (r/w)
-word data, and (r/w) I2C block data.
+word data, (r/w) I2C block data, and (r/w) SMBus block data.
 
 You need to provide chip addresses as a module parameter when loading this
 driver, which will then only react to SMBus commands to these addresses.
@@ -19,6 +19,14 @@ A pointer register with auto-increment is implemented for all byte
 operations.  This allows for continuous byte reads like those supported by
 EEPROMs, among others.
 
+SMBus block command support is disabled by default, and must be enabled
+explicitly by setting the respective bits (0x03000000) in the functionality
+module parameter.
+
+SMBus block commands must be written to configure an SMBus command for
+SMBus block operations. Writes can be partial. Block read commands always
+return the number of bytes selected with the largest write so far.
+
 The typical use-case is like this:
        1. load this module
        2. use i2cset (from the i2c-tools project) to pre-load some data
@@ -39,15 +47,18 @@ unsigned long functionality:
        value 0x1f0000 would only enable the quick, byte and byte data
        commands.
 
+u8 bank_reg[10]
+u8 bank_mask[10]
+u8 bank_start[10]
+u8 bank_end[10]:
+       Optional bank settings. They tell which bits in which register
+       select the active bank, as well as the range of banked registers.
+
 CAVEATS:
 
 If your target driver polls some byte or word waiting for it to change, the
 stub could lock it up.  Use i2cset to unlock it.
 
-If the hardware for your driver has banked registers (e.g. Winbond sensors
-chips) this module will not work well - although it could be extended to
-support that pretty easily.
-
 If you spam it hard enough, printk can be lossy.  This module really wants
 something like relayfs.
 
index 7b7ea32..3e3b680 100644 (file)
@@ -2,7 +2,9 @@
 # I2C subsystem configuration
 #
 
-menuconfig I2C
+menu "I2C support"
+
+config I2C
        tristate "I2C support"
        select RT_MUTEXES
        ---help---
@@ -21,6 +23,18 @@ menuconfig I2C
          This I2C support can also be built as a module.  If so, the module
          will be called i2c-core.
 
+config I2C_ACPI
+       bool "I2C ACPI support"
+       select I2C
+       depends on ACPI
+       default y
+       help
+         Say Y here if you want to enable ACPI I2C support. This includes support
+         for automatic enumeration of I2C slave devices and support for ACPI I2C
+         Operation Regions. Operation Regions allow firmware (BIOS) code to
+         access I2C slave devices, such as smart batteries through an I2C host
+         controller driver.
+
 if I2C
 
 config I2C_BOARDINFO
@@ -124,3 +138,5 @@ config I2C_DEBUG_BUS
          on.
 
 endif # I2C
+
+endmenu
index 1722f50..a1f590c 100644 (file)
@@ -2,8 +2,11 @@
 # Makefile for the i2c core.
 #
 
+i2ccore-y := i2c-core.o
+i2ccore-$(CONFIG_I2C_ACPI)     += i2c-acpi.o
+
 obj-$(CONFIG_I2C_BOARDINFO)    += i2c-boardinfo.o
-obj-$(CONFIG_I2C)              += i2c-core.o
+obj-$(CONFIG_I2C)              += i2ccore.o
 obj-$(CONFIG_I2C_SMBUS)                += i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-$(CONFIG_I2C_MUX)          += i2c-mux.o
index 9f7d585..2ac87fa 100644 (file)
@@ -109,6 +109,7 @@ config I2C_I801
            Avoton (SOC)
            Wellsburg (PCH)
            Coleto Creek (PCH)
+           Wildcat Point (PCH)
            Wildcat Point-LP (PCH)
            BayTrail (SOC)
 
@@ -465,9 +466,9 @@ config I2C_EG20T
 config I2C_EXYNOS5
        tristate "Exynos5 high-speed I2C driver"
        depends on ARCH_EXYNOS5 && OF
+       default y
        help
-         Say Y here to include support for high-speed I2C controller in the
-         Exynos5 based Samsung SoCs.
+         High-speed I2C controller on Exynos5 based Samsung SoCs.
 
 config I2C_GPIO
        tristate "GPIO-based bitbanging I2C"
@@ -700,16 +701,6 @@ config I2C_S3C2410
          Say Y here to include support for I2C controller in the
          Samsung SoCs.
 
-config I2C_S6000
-       tristate "S6000 I2C support"
-       depends on XTENSA_VARIANT_S6000
-       help
-         This driver supports the on chip I2C device on the
-         S6000 xtensa processor family.
-
-         To compile this driver as a module, choose M here. The module
-         will be called i2c-s6000.
-
 config I2C_SH7760
        tristate "Renesas SH7760 I2C Controller"
        depends on CPU_SUBTYPE_SH7760
@@ -1018,37 +1009,6 @@ config I2C_CROS_EC_TUNNEL
          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
-       select I2C_ALGOBIT
-       help
-         Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
-
-         If you don't know what to do here, say N.
-
-         This support is also available as a module.  If so, the module
-         will be called scx200_i2c.
-
-         This driver is deprecated and will be dropped soon. Use i2c-gpio
-         (or scx200_acb) instead.
-
-config SCx200_I2C_SCL
-       int "GPIO pin used for SCL"
-       depends on SCx200_I2C
-       default "12"
-       help
-         Enter the GPIO pin number used for the SCL signal.  This value can
-         also be specified with a module parameter.
-
-config SCx200_I2C_SDA
-       int "GPIO pin used for SDA"
-       depends on SCx200_I2C
-       default "13"
-       help
-         Enter the GPIO pin number used for the SSA signal.  This value can
-         also be specified with a module parameter.
-
 config SCx200_ACB
        tristate "Geode ACCESS.bus support"
        depends on X86_32 && PCI
index dd9a7f8..49bf07e 100644 (file)
@@ -68,7 +68,6 @@ 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
@@ -101,6 +100,5 @@ obj-$(CONFIG_I2C_ELEKTOR)   += i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
-obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
 
 ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
index e95f9ba..79a6899 100644 (file)
@@ -210,7 +210,7 @@ static void at91_twi_write_data_dma_callback(void *data)
        struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
 
        dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
-                        dev->buf_len, DMA_MEM_TO_DEV);
+                        dev->buf_len, DMA_TO_DEVICE);
 
        at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
 }
@@ -289,7 +289,7 @@ static void at91_twi_read_data_dma_callback(void *data)
        struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
 
        dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
-                        dev->buf_len, DMA_DEV_TO_MEM);
+                        dev->buf_len, DMA_FROM_DEVICE);
 
        /* The last two bytes have to be read without using dma */
        dev->buf += dev->buf_len - 2;
@@ -768,7 +768,7 @@ static int at91_twi_probe(struct platform_device *pdev)
        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 | I2C_CLASS_DEPRECATED;
+       dev->adapter.class = I2C_CLASS_DEPRECATED;
        dev->adapter.algo = &at91_twi_algorithm;
        dev->adapter.dev.parent = dev->dev;
        dev->adapter.nr = pdev->id;
index 214ff97..4b8ecd0 100644 (file)
@@ -277,7 +277,7 @@ 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 | I2C_CLASS_DEPRECATED;
+       adap->class = I2C_CLASS_DEPRECATED;
        strlcpy(adap->name, "bcm2835 I2C adapter", sizeof(adap->name));
        adap->algo = &bcm2835_i2c_algo;
        adap->dev.parent = &pdev->dev;
index 3e271e7..067c161 100644 (file)
@@ -648,7 +648,7 @@ 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 | I2C_CLASS_DEPRECATED;
+       p_adap->class = I2C_CLASS_DEPRECATED;
        p_adap->dev.parent = &pdev->dev;
        p_adap->timeout = 5 * HZ;
        p_adap->retries = 3;
index 389bc68..4d96147 100644 (file)
@@ -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 | I2C_CLASS_DEPRECATED;
+       adap->class = I2C_CLASS_DEPRECATED;
        strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
        adap->algo = &i2c_davinci_algo;
        adap->dev.parent = &pdev->dev;
index 3356f7a..d31d313 100644 (file)
@@ -188,6 +188,7 @@ static struct  dw_pci_controller  dw_pci_controllers[] = {
                .scl_sda_cfg = &hsw_config,
        },
 };
+
 static struct i2c_algorithm i2c_dw_algo = {
        .master_xfer    = i2c_dw_xfer,
        .functionality  = i2c_dw_func,
@@ -350,6 +351,14 @@ static const struct pci_device_id i2_designware_pci_ids[] = {
        /* Haswell */
        { PCI_VDEVICE(INTEL, 0x9c61), haswell },
        { PCI_VDEVICE(INTEL, 0x9c62), haswell },
+       /* Braswell / Cherrytrail */
+       { PCI_VDEVICE(INTEL, 0x22C1), baytrail,},
+       { PCI_VDEVICE(INTEL, 0x22C2), baytrail },
+       { PCI_VDEVICE(INTEL, 0x22C3), baytrail },
+       { PCI_VDEVICE(INTEL, 0x22C4), baytrail },
+       { PCI_VDEVICE(INTEL, 0x22C5), baytrail },
+       { PCI_VDEVICE(INTEL, 0x22C6), baytrail },
+       { PCI_VDEVICE(INTEL, 0x22C7), baytrail },
        { 0,}
 };
 MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
index 402ec39..bc87733 100644 (file)
@@ -106,6 +106,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
        { "INT3432", 0 },
        { "INT3433", 0 },
        { "80860F41", 0 },
+       { "808622C1", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -202,7 +203,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 | I2C_CLASS_DEPRECATED;
+       adap->class = I2C_CLASS_DEPRECATED;
        strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
                        sizeof(adap->name));
        adap->algo = &i2c_dw_algo;
index f7eccd6..10b8323 100644 (file)
@@ -370,7 +370,13 @@ static int efm32_i2c_probe(struct platform_device *pdev)
                return ret;
        }
 
-       ret = of_property_read_u32(np, "efm32,location", &location);
+
+       ret = of_property_read_u32(np, "energymicro,location", &location);
+
+       if (ret)
+               /* fall back to wrongly namespaced property */
+               ret = of_property_read_u32(np, "efm32,location", &location);
+
        if (!ret) {
                dev_dbg(&pdev->dev, "using location %u\n", location);
        } else {
index 63d2292..28073f1 100644 (file)
@@ -405,7 +405,6 @@ static irqreturn_t exynos5_i2c_irq(int irqno, void *dev_id)
 
        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) {
@@ -526,7 +525,7 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
        if (i2c->msg->flags & I2C_M_RD) {
                i2c_ctl |= HSI2C_RXCHON;
 
-               i2c_auto_conf = HSI2C_READ_WRITE;
+               i2c_auto_conf |= HSI2C_READ_WRITE;
 
                trig_lvl = (i2c->msg->len > i2c->variant->fifo_depth) ?
                        (i2c->variant->fifo_depth * 3 / 4) : i2c->msg->len;
@@ -549,7 +548,6 @@ static void exynos5_i2c_message_start(struct exynos5_i2c *i2c, int stop)
        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.
@@ -789,8 +787,16 @@ static int exynos5_i2c_resume_noirq(struct device *dev)
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(exynos5_i2c_dev_pm_ops, exynos5_i2c_suspend_noirq,
-                        exynos5_i2c_resume_noirq);
+static const struct dev_pm_ops exynos5_i2c_dev_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+       .suspend_noirq = exynos5_i2c_suspend_noirq,
+       .resume_noirq = exynos5_i2c_resume_noirq,
+       .freeze_noirq = exynos5_i2c_suspend_noirq,
+       .thaw_noirq = exynos5_i2c_resume_noirq,
+       .poweroff_noirq = exynos5_i2c_suspend_noirq,
+       .restore_noirq = exynos5_i2c_resume_noirq,
+#endif
+};
 
 static struct platform_driver exynos5_i2c_driver = {
        .probe          = exynos5_i2c_probe,
index 71a45b2..933f1e4 100644 (file)
@@ -238,12 +238,10 @@ static int i2c_gpio_probe(struct platform_device *pdev)
 static int i2c_gpio_remove(struct platform_device *pdev)
 {
        struct i2c_gpio_private_data *priv;
-       struct i2c_gpio_platform_data *pdata;
        struct i2c_adapter *adap;
 
        priv = platform_get_drvdata(pdev);
        adap = &priv->adap;
-       pdata = &priv->pdata;
 
        i2c_del_adapter(adap);
 
index 6777cd6..2994690 100644 (file)
 */
 
 /*
-  Supports the following Intel I/O Controller Hubs (ICH):
-
-                                  I/O                     Block   I2C
-                                  region  SMBus   Block   proc.   block
-  Chip name             PCI ID    size    PEC     buffer  call    read
-  ----------------------------------------------------------------------
-  82801AA  (ICH)        0x2413     16      no      no      no      no
-  82801AB  (ICH0)       0x2423     16      no      no      no      no
-  82801BA  (ICH2)       0x2443     16      no      no      no      no
-  82801CA  (ICH3)       0x2483     32     soft     no      no      no
-  82801DB  (ICH4)       0x24c3     32     hard     yes     no      no
-  82801E   (ICH5)       0x24d3     32     hard     yes     yes     yes
-  6300ESB               0x25a4     32     hard     yes     yes     yes
-  82801F   (ICH6)       0x266a     32     hard     yes     yes     yes
-  6310ESB/6320ESB       0x269b     32     hard     yes     yes     yes
-  82801G   (ICH7)       0x27da     32     hard     yes     yes     yes
-  82801H   (ICH8)       0x283e     32     hard     yes     yes     yes
-  82801I   (ICH9)       0x2930     32     hard     yes     yes     yes
-  EP80579 (Tolapai)     0x5032     32     hard     yes     yes     yes
-  ICH10                 0x3a30     32     hard     yes     yes     yes
-  ICH10                 0x3a60     32     hard     yes     yes     yes
-  5/3400 Series (PCH)   0x3b30     32     hard     yes     yes     yes
-  6 Series (PCH)        0x1c22     32     hard     yes     yes     yes
-  Patsburg (PCH)        0x1d22     32     hard     yes     yes     yes
-  Patsburg (PCH) IDF    0x1d70     32     hard     yes     yes     yes
-  Patsburg (PCH) IDF    0x1d71     32     hard     yes     yes     yes
-  Patsburg (PCH) IDF    0x1d72     32     hard     yes     yes     yes
-  DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
-  Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
-  Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
-  Lynx Point-LP (PCH)   0x9c22     32     hard     yes     yes     yes
-  Avoton (SOC)          0x1f3c     32     hard     yes     yes     yes
-  Wellsburg (PCH)       0x8d22     32     hard     yes     yes     yes
-  Wellsburg (PCH) MS    0x8d7d     32     hard     yes     yes     yes
-  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
-  Hardware PEC                     yes
-  Block buffer                     yes
-  Block process call transaction   no
-  I2C block read transaction       yes  (doesn't use the block buffer)
-  Slave mode                       no
-  Interrupt processing             yes
-
-  See the file Documentation/i2c/busses/i2c-i801 for details.
-*/
+ * Supports the following Intel I/O Controller Hubs (ICH):
+ *
+ *                                     I/O                     Block   I2C
+ *                                     region  SMBus   Block   proc.   block
+ * Chip name                   PCI ID  size    PEC     buffer  call    read
+ * ---------------------------------------------------------------------------
+ * 82801AA (ICH)               0x2413  16      no      no      no      no
+ * 82801AB (ICH0)              0x2423  16      no      no      no      no
+ * 82801BA (ICH2)              0x2443  16      no      no      no      no
+ * 82801CA (ICH3)              0x2483  32      soft    no      no      no
+ * 82801DB (ICH4)              0x24c3  32      hard    yes     no      no
+ * 82801E (ICH5)               0x24d3  32      hard    yes     yes     yes
+ * 6300ESB                     0x25a4  32      hard    yes     yes     yes
+ * 82801F (ICH6)               0x266a  32      hard    yes     yes     yes
+ * 6310ESB/6320ESB             0x269b  32      hard    yes     yes     yes
+ * 82801G (ICH7)               0x27da  32      hard    yes     yes     yes
+ * 82801H (ICH8)               0x283e  32      hard    yes     yes     yes
+ * 82801I (ICH9)               0x2930  32      hard    yes     yes     yes
+ * EP80579 (Tolapai)           0x5032  32      hard    yes     yes     yes
+ * ICH10                       0x3a30  32      hard    yes     yes     yes
+ * ICH10                       0x3a60  32      hard    yes     yes     yes
+ * 5/3400 Series (PCH)         0x3b30  32      hard    yes     yes     yes
+ * 6 Series (PCH)              0x1c22  32      hard    yes     yes     yes
+ * Patsburg (PCH)              0x1d22  32      hard    yes     yes     yes
+ * Patsburg (PCH) IDF          0x1d70  32      hard    yes     yes     yes
+ * Patsburg (PCH) IDF          0x1d71  32      hard    yes     yes     yes
+ * Patsburg (PCH) IDF          0x1d72  32      hard    yes     yes     yes
+ * DH89xxCC (PCH)              0x2330  32      hard    yes     yes     yes
+ * Panther Point (PCH)         0x1e22  32      hard    yes     yes     yes
+ * Lynx Point (PCH)            0x8c22  32      hard    yes     yes     yes
+ * Lynx Point-LP (PCH)         0x9c22  32      hard    yes     yes     yes
+ * Avoton (SOC)                        0x1f3c  32      hard    yes     yes     yes
+ * Wellsburg (PCH)             0x8d22  32      hard    yes     yes     yes
+ * Wellsburg (PCH) MS          0x8d7d  32      hard    yes     yes     yes
+ * 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 (PCH)         0x8ca2  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
+ * Hardware PEC                                yes
+ * Block buffer                                yes
+ * Block process call transaction      no
+ * I2C block read transaction          yes (doesn't use the block buffer)
+ * Slave mode                          no
+ * Interrupt processing                        yes
+ *
+ * See the file Documentation/i2c/busses/i2c-i801 for details.
+ */
 
 #include <linux/interrupt.h>
 #include <linux/module.h>
                                 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
+#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 */
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0        0x1d70
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1        0x1d71
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2        0x1d72
-#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22
-#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS       0x1f3c
-#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
-#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS  0x23b0
-#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS    0x8c22
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS    0x8d22
-#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0        0x8d7d
-#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_PATSBURG_SMBUS_IDF0                0x1d70
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1                0x1d71
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2                0x1d72
+#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS         0x1e22
+#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS               0x1f3c
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS             0x2330
+#define PCI_DEVICE_ID_INTEL_COLETOCREEK_SMBUS          0x23b0
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS                0x3b30
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS            0x8c22
+#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_SMBUS         0x8ca2
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS            0x8d22
+#define PCI_DEVICE_ID_INTEL_WELLSBURG_SMBUS_MS0                0x8d7d
+#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 {
@@ -823,6 +825,7 @@ static const struct pci_device_id 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_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, }
index aa8bc14..613069b 100644 (file)
@@ -735,10 +735,7 @@ static int i2c_imx_probe(struct platform_device *pdev)
        clk_disable_unprepare(i2c_imx->clk);
 
        dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", irq);
-       dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n",
-               res->start, res->end);
-       dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x\n",
-               resource_size(res), res->start);
+       dev_dbg(&i2c_imx->adapter.dev, "device resources: %pR\n", res);
        dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n",
                i2c_imx->adapter.name);
        dev_info(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n");
index 6a32aa0..0edf630 100644 (file)
@@ -341,8 +341,7 @@ static u32 mpc_i2c_get_sec_cfg_8xxx(void)
                        iounmap(reg);
                }
        }
-       if (node)
-               of_node_put(node);
+       of_node_put(node);
 
        return val;
 }
index 9f4b775..6dc5ded 100644 (file)
@@ -863,7 +863,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
        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 | I2C_CLASS_DEPRECATED;
+       drv_data->adapter.class = 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);
index 0e55d85..9ad038d 100644 (file)
@@ -1032,10 +1032,10 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
        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 | I2C_CLASS_DEPRECATED;
-       adap->algo      = &nmk_i2c_algo;
-       adap->timeout   = msecs_to_jiffies(dev->timeout);
+       adap->owner = THIS_MODULE;
+       adap->class = I2C_CLASS_DEPRECATED;
+       adap->algo = &nmk_i2c_algo;
+       adap->timeout = msecs_to_jiffies(dev->timeout);
        snprintf(adap->name, sizeof(adap->name),
                 "Nomadik I2C at %pR", &adev->res);
 
index 0e10cc6..2a4fe0b 100644 (file)
@@ -239,15 +239,15 @@ static u32 ocores_func(struct i2c_adapter *adap)
 }
 
 static const struct i2c_algorithm ocores_algorithm = {
-       .master_xfer    = ocores_xfer,
-       .functionality  = ocores_func,
+       .master_xfer = ocores_xfer,
+       .functionality = ocores_func,
 };
 
 static struct i2c_adapter ocores_adapter = {
-       .owner          = THIS_MODULE,
-       .name           = "i2c-ocores",
-       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED,
-       .algo           = &ocores_algorithm,
+       .owner = THIS_MODULE,
+       .name = "i2c-ocores",
+       .class = I2C_CLASS_DEPRECATED,
+       .algo = &ocores_algorithm,
 };
 
 static const struct of_device_id ocores_i2c_match[] = {
index b182793..0dffb0e 100644 (file)
@@ -1236,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 | I2C_CLASS_DEPRECATED;
+       adap->class = I2C_CLASS_DEPRECATED;
        strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
        adap->algo = &omap_i2c_algo;
        adap->dev.parent = &pdev->dev;
index 2a5efb5..3a4d64e 100644 (file)
@@ -633,13 +633,17 @@ static int qup_i2c_probe(struct platform_device *pdev)
         * associated with each byte written/received
         */
        size = QUP_OUTPUT_BLOCK_SIZE(io_mode);
-       if (size >= ARRAY_SIZE(blk_sizes))
-               return -EIO;
+       if (size >= ARRAY_SIZE(blk_sizes)) {
+               ret = -EIO;
+               goto fail;
+       }
        qup->out_blk_sz = blk_sizes[size] / 2;
 
        size = QUP_INPUT_BLOCK_SIZE(io_mode);
-       if (size >= ARRAY_SIZE(blk_sizes))
-               return -EIO;
+       if (size >= ARRAY_SIZE(blk_sizes)) {
+               ret = -EIO;
+               goto fail;
+       }
        qup->in_blk_sz = blk_sizes[size] / 2;
 
        size = QUP_OUTPUT_FIFO_SIZE(io_mode);
index 8994059..f3c7139 100644 (file)
@@ -541,13 +541,13 @@ static int rcar_i2c_probe(struct platform_device *pdev)
        irq = platform_get_irq(pdev, 0);
        init_waitqueue_head(&priv->wait);
 
-       adap                    = &priv->adap;
-       adap->nr                = pdev->id;
-       adap->algo              = &rcar_i2c_algo;
-       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;
+       adap = &priv->adap;
+       adap->nr = pdev->id;
+       adap->algo = &rcar_i2c_algo;
+       adap->class = 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));
 
index a979150..69e1185 100644 (file)
@@ -399,7 +399,7 @@ static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id)
        }
 
        /* is there anything left to handle? */
-       if (unlikely(ipd == 0))
+       if (unlikely((ipd & REG_INT_ALL) == 0))
                goto out;
 
        switch (i2c->state) {
index e828a1d..e086fb0 100644 (file)
@@ -1128,11 +1128,11 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
                s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c);
 
        strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name));
-       i2c->adap.owner   = THIS_MODULE;
-       i2c->adap.algo    = &s3c24xx_i2c_algorithm;
+       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_CLASS_DEPRECATED;
-       i2c->tx_setup     = 50;
+       i2c->adap.class = I2C_CLASS_DEPRECATED;
+       i2c->tx_setup = 50;
 
        init_waitqueue_head(&i2c->wait);
 
@@ -1267,7 +1267,7 @@ static int s3c24xx_i2c_suspend_noirq(struct device *dev)
        return 0;
 }
 
-static int s3c24xx_i2c_resume(struct device *dev)
+static int s3c24xx_i2c_resume_noirq(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
        struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
@@ -1285,7 +1285,11 @@ static int s3c24xx_i2c_resume(struct device *dev)
 static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
 #ifdef CONFIG_PM_SLEEP
        .suspend_noirq = s3c24xx_i2c_suspend_noirq,
-       .resume = s3c24xx_i2c_resume,
+       .resume_noirq = s3c24xx_i2c_resume_noirq,
+       .freeze_noirq = s3c24xx_i2c_suspend_noirq,
+       .thaw_noirq = s3c24xx_i2c_resume_noirq,
+       .poweroff_noirq = s3c24xx_i2c_suspend_noirq,
+       .restore_noirq = s3c24xx_i2c_resume_noirq,
 #endif
 };
 
diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c
deleted file mode 100644 (file)
index dd186a0..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-s6000.c
- *
- * Description: Driver for S6000 Family I2C Interface
- * Copyright (c) 2008 emlix GmbH
- * Author:     Oskar Schirmer <oskar@scara.com>
- *
- * Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com>
- * Copyright (c) 2005-2007 Analog Devices, 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.
- *
- * 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/i2c/s6000.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/completion.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include "i2c-s6000.h"
-
-#define DRV_NAME "i2c-s6000"
-
-#define POLL_TIMEOUT   (2 * HZ)
-
-struct s6i2c_if {
-       u8 __iomem              *reg; /* memory mapped registers */
-       int                     irq;
-       spinlock_t              lock;
-       struct i2c_msg          *msgs; /* messages currently handled */
-       int                     msgs_num; /* nb of msgs to do */
-       int                     msgs_push; /* nb of msgs read/written */
-       int                     msgs_done; /* nb of msgs finally handled */
-       unsigned                push; /* nb of bytes read/written in msg */
-       unsigned                done; /* nb of bytes finally handled */
-       int                     timeout_count; /* timeout retries left */
-       struct timer_list       timeout_timer;
-       struct i2c_adapter      adap;
-       struct completion       complete;
-       struct clk              *clk;
-       struct resource         *res;
-};
-
-static inline u16 i2c_rd16(struct s6i2c_if *iface, unsigned n)
-{
-       return readw(iface->reg + (n));
-}
-
-static inline void i2c_wr16(struct s6i2c_if *iface, unsigned n, u16 v)
-{
-       writew(v, iface->reg + (n));
-}
-
-static inline u32 i2c_rd32(struct s6i2c_if *iface, unsigned n)
-{
-       return readl(iface->reg + (n));
-}
-
-static inline void i2c_wr32(struct s6i2c_if *iface, unsigned n, u32 v)
-{
-       writel(v, iface->reg + (n));
-}
-
-static struct s6i2c_if s6i2c_if;
-
-static void s6i2c_handle_interrupt(struct s6i2c_if *iface)
-{
-       if (i2c_rd16(iface, S6_I2C_INTRSTAT) & (1 << S6_I2C_INTR_TXABRT)) {
-               i2c_rd16(iface, S6_I2C_CLRTXABRT);
-               i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-               complete(&iface->complete);
-               return;
-       }
-       if (iface->msgs_done >= iface->msgs_num) {
-               dev_err(&iface->adap.dev, "s6i2c: spurious I2C irq: %04x\n",
-                       i2c_rd16(iface, S6_I2C_INTRSTAT));
-               i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-               return;
-       }
-       while ((iface->msgs_push < iface->msgs_num)
-           && (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_TFNF))) {
-               struct i2c_msg *m = &iface->msgs[iface->msgs_push];
-               if (!(m->flags & I2C_M_RD))
-                       i2c_wr16(iface, S6_I2C_DATACMD, m->buf[iface->push]);
-               else
-                       i2c_wr16(iface, S6_I2C_DATACMD,
-                                1 << S6_I2C_DATACMD_READ);
-               if (++iface->push >= m->len) {
-                       iface->push = 0;
-                       iface->msgs_push += 1;
-               }
-       }
-       do {
-               struct i2c_msg *m = &iface->msgs[iface->msgs_done];
-               if (!(m->flags & I2C_M_RD)) {
-                       if (iface->msgs_done < iface->msgs_push)
-                               iface->msgs_done += 1;
-                       else
-                               break;
-               } else if (i2c_rd16(iface, S6_I2C_STATUS)
-                               & (1 << S6_I2C_STATUS_RFNE)) {
-                       m->buf[iface->done] = i2c_rd16(iface, S6_I2C_DATACMD);
-                       if (++iface->done >= m->len) {
-                               iface->done = 0;
-                               iface->msgs_done += 1;
-                       }
-               } else{
-                       break;
-               }
-       } while (iface->msgs_done < iface->msgs_num);
-       if (iface->msgs_done >= iface->msgs_num) {
-               i2c_wr16(iface, S6_I2C_INTRMASK, 1 << S6_I2C_INTR_TXABRT);
-               complete(&iface->complete);
-       } else if (iface->msgs_push >= iface->msgs_num) {
-               i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
-                                                (1 << S6_I2C_INTR_RXFULL));
-       } else {
-               i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) |
-                                                (1 << S6_I2C_INTR_TXEMPTY) |
-                                                (1 << S6_I2C_INTR_RXFULL));
-       }
-}
-
-static irqreturn_t s6i2c_interrupt_entry(int irq, void *dev_id)
-{
-       struct s6i2c_if *iface = dev_id;
-       if (!(i2c_rd16(iface, S6_I2C_STATUS) & ((1 << S6_I2C_INTR_RXUNDER)
-                                             | (1 << S6_I2C_INTR_RXOVER)
-                                             | (1 << S6_I2C_INTR_RXFULL)
-                                             | (1 << S6_I2C_INTR_TXOVER)
-                                             | (1 << S6_I2C_INTR_TXEMPTY)
-                                             | (1 << S6_I2C_INTR_RDREQ)
-                                             | (1 << S6_I2C_INTR_TXABRT)
-                                             | (1 << S6_I2C_INTR_RXDONE)
-                                             | (1 << S6_I2C_INTR_ACTIVITY)
-                                             | (1 << S6_I2C_INTR_STOPDET)
-                                             | (1 << S6_I2C_INTR_STARTDET)
-                                             | (1 << S6_I2C_INTR_GENCALL))))
-               return IRQ_NONE;
-
-       spin_lock(&iface->lock);
-       del_timer(&iface->timeout_timer);
-       s6i2c_handle_interrupt(iface);
-       spin_unlock(&iface->lock);
-       return IRQ_HANDLED;
-}
-
-static void s6i2c_timeout(unsigned long data)
-{
-       struct s6i2c_if *iface = (struct s6i2c_if *)data;
-       unsigned long flags;
-
-       spin_lock_irqsave(&iface->lock, flags);
-       s6i2c_handle_interrupt(iface);
-       if (--iface->timeout_count > 0) {
-               iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
-               add_timer(&iface->timeout_timer);
-       } else {
-               complete(&iface->complete);
-               i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-       }
-       spin_unlock_irqrestore(&iface->lock, flags);
-}
-
-static int s6i2c_master_xfer(struct i2c_adapter *adap,
-                               struct i2c_msg *msgs, int num)
-{
-       struct s6i2c_if *iface = adap->algo_data;
-       int i;
-       if (num == 0)
-               return 0;
-       if (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
-               yield();
-       i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-       i2c_rd16(iface, S6_I2C_CLRINTR);
-       for (i = 0; i < num; i++) {
-               if (msgs[i].flags & I2C_M_TEN) {
-                       dev_err(&adap->dev,
-                               "s6i2c: 10 bits addr not supported\n");
-                       return -EINVAL;
-               }
-               if (msgs[i].len == 0) {
-                       dev_err(&adap->dev,
-                               "s6i2c: zero length message not supported\n");
-                       return -EINVAL;
-               }
-               if (msgs[i].addr != msgs[0].addr) {
-                       dev_err(&adap->dev,
-                               "s6i2c: multiple xfer cannot change target\n");
-                       return -EINVAL;
-               }
-       }
-
-       iface->msgs = msgs;
-       iface->msgs_num = num;
-       iface->msgs_push = 0;
-       iface->msgs_done = 0;
-       iface->push = 0;
-       iface->done = 0;
-       iface->timeout_count = 10;
-       i2c_wr16(iface, S6_I2C_TAR, msgs[0].addr);
-       i2c_wr16(iface, S6_I2C_ENABLE, 1);
-       i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXEMPTY) |
-                                        (1 << S6_I2C_INTR_TXABRT));
-
-       iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
-       add_timer(&iface->timeout_timer);
-       wait_for_completion(&iface->complete);
-       del_timer_sync(&iface->timeout_timer);
-       while (i2c_rd32(iface, S6_I2C_TXFLR) > 0)
-               schedule();
-       while (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY))
-               schedule();
-
-       i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-       i2c_wr16(iface, S6_I2C_ENABLE, 0);
-       return iface->msgs_done;
-}
-
-static u32 s6i2c_functionality(struct i2c_adapter *adap)
-{
-       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
-}
-
-static struct i2c_algorithm s6i2c_algorithm = {
-       .master_xfer   = s6i2c_master_xfer,
-       .functionality = s6i2c_functionality,
-};
-
-static u16 nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns)
-{
-       u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000;
-       if (dividend > 0xffff)
-               return 0xffff;
-       return dividend;
-}
-
-static int s6i2c_probe(struct platform_device *dev)
-{
-       struct s6i2c_if *iface = &s6i2c_if;
-       struct i2c_adapter *p_adap;
-       const char *clock;
-       int bus_num, rc;
-       spin_lock_init(&iface->lock);
-       init_completion(&iface->complete);
-       iface->irq = platform_get_irq(dev, 0);
-       if (iface->irq < 0) {
-               rc = iface->irq;
-               goto err_out;
-       }
-       iface->res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-       if (!iface->res) {
-               rc = -ENXIO;
-               goto err_out;
-       }
-       iface->res = request_mem_region(iface->res->start,
-                                       resource_size(iface->res),
-                                       dev->dev.bus_id);
-       if (!iface->res) {
-               rc = -EBUSY;
-               goto err_out;
-       }
-       iface->reg = ioremap_nocache(iface->res->start,
-                                    resource_size(iface->res));
-       if (!iface->reg) {
-               rc = -ENOMEM;
-               goto err_reg;
-       }
-
-       clock = 0;
-       bus_num = -1;
-       if (dev_get_platdata(&dev->dev)) {
-               struct s6_i2c_platform_data *pdata =
-                       dev_get_platdata(&dev->dev);
-               bus_num = pdata->bus_num;
-               clock = pdata->clock;
-       }
-       iface->clk = clk_get(&dev->dev, clock);
-       if (IS_ERR(iface->clk)) {
-               rc = PTR_ERR(iface->clk);
-               goto err_map;
-       }
-       rc = clk_enable(iface->clk);
-       if (rc < 0)
-               goto err_clk_put;
-       init_timer(&iface->timeout_timer);
-       iface->timeout_timer.function = s6i2c_timeout;
-       iface->timeout_timer.data = (unsigned long)iface;
-
-       p_adap = &iface->adap;
-       strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
-       p_adap->algo = &s6i2c_algorithm;
-       p_adap->algo_data = iface;
-       p_adap->nr = bus_num;
-       p_adap->class = 0;
-       p_adap->dev.parent = &dev->dev;
-       i2c_wr16(iface, S6_I2C_INTRMASK, 0);
-       rc = request_irq(iface->irq, s6i2c_interrupt_entry,
-                        IRQF_SHARED, dev->name, iface);
-       if (rc) {
-               dev_err(&p_adap->dev, "s6i2c: can't get IRQ %d\n", iface->irq);
-               goto err_clk_dis;
-       }
-
-       i2c_wr16(iface, S6_I2C_ENABLE, 0);
-       udelay(1);
-       i2c_wr32(iface, S6_I2C_SRESET, 1 << S6_I2C_SRESET_IC_SRST);
-       i2c_wr16(iface, S6_I2C_CLRTXABRT, 1);
-       i2c_wr16(iface, S6_I2C_CON,
-                       (1 << S6_I2C_CON_MASTER) |
-                       (S6_I2C_CON_SPEED_NORMAL << S6_I2C_CON_SPEED) |
-                       (0 << S6_I2C_CON_10BITSLAVE) |
-                       (0 << S6_I2C_CON_10BITMASTER) |
-                       (1 << S6_I2C_CON_RESTARTENA) |
-                       (1 << S6_I2C_CON_SLAVEDISABLE));
-       i2c_wr16(iface, S6_I2C_SSHCNT, nanoseconds_on_clk(iface, 4000));
-       i2c_wr16(iface, S6_I2C_SSLCNT, nanoseconds_on_clk(iface, 4700));
-       i2c_wr16(iface, S6_I2C_FSHCNT, nanoseconds_on_clk(iface, 600));
-       i2c_wr16(iface, S6_I2C_FSLCNT, nanoseconds_on_clk(iface, 1300));
-       i2c_wr16(iface, S6_I2C_RXTL, 0);
-       i2c_wr16(iface, S6_I2C_TXTL, 0);
-
-       platform_set_drvdata(dev, iface);
-       rc = i2c_add_numbered_adapter(p_adap);
-       if (rc)
-               goto err_irq_free;
-       return 0;
-
-err_irq_free:
-       free_irq(iface->irq, iface);
-err_clk_dis:
-       clk_disable(iface->clk);
-err_clk_put:
-       clk_put(iface->clk);
-err_map:
-       iounmap(iface->reg);
-err_reg:
-       release_mem_region(iface->res->start,
-                          resource_size(iface->res));
-err_out:
-       return rc;
-}
-
-static int s6i2c_remove(struct platform_device *pdev)
-{
-       struct s6i2c_if *iface = platform_get_drvdata(pdev);
-       i2c_wr16(iface, S6_I2C_ENABLE, 0);
-       i2c_del_adapter(&iface->adap);
-       free_irq(iface->irq, iface);
-       clk_disable(iface->clk);
-       clk_put(iface->clk);
-       iounmap(iface->reg);
-       release_mem_region(iface->res->start,
-                          resource_size(iface->res));
-       return 0;
-}
-
-static struct platform_driver s6i2c_driver = {
-       .probe          = s6i2c_probe,
-       .remove         = s6i2c_remove,
-       .driver         = {
-               .name   = DRV_NAME,
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init s6i2c_init(void)
-{
-       pr_info("I2C: S6000 I2C driver\n");
-       return platform_driver_register(&s6i2c_driver);
-}
-
-static void __exit s6i2c_exit(void)
-{
-       platform_driver_unregister(&s6i2c_driver);
-}
-
-MODULE_DESCRIPTION("I2C-Bus adapter routines for S6000 I2C");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRV_NAME);
-
-subsys_initcall(s6i2c_init);
-module_exit(s6i2c_exit);
diff --git a/drivers/i2c/busses/i2c-s6000.h b/drivers/i2c/busses/i2c-s6000.h
deleted file mode 100644 (file)
index 4936f9f..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * drivers/i2c/busses/i2c-s6000.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2008 Emlix GmbH <info@emlix.com>
- * Author:     Oskar Schirmer <oskar@scara.com>
- */
-
-#ifndef __DRIVERS_I2C_BUSSES_I2C_S6000_H
-#define __DRIVERS_I2C_BUSSES_I2C_S6000_H
-
-#define S6_I2C_CON             0x000
-#define S6_I2C_CON_MASTER              0
-#define S6_I2C_CON_SPEED               1
-#define S6_I2C_CON_SPEED_NORMAL                        1
-#define S6_I2C_CON_SPEED_FAST                  2
-#define S6_I2C_CON_SPEED_MASK                  3
-#define S6_I2C_CON_10BITSLAVE          3
-#define S6_I2C_CON_10BITMASTER         4
-#define S6_I2C_CON_RESTARTENA          5
-#define S6_I2C_CON_SLAVEDISABLE                6
-#define S6_I2C_TAR             0x004
-#define S6_I2C_TAR_GCORSTART           10
-#define S6_I2C_TAR_SPECIAL             11
-#define S6_I2C_SAR             0x008
-#define S6_I2C_HSMADDR         0x00C
-#define S6_I2C_DATACMD         0x010
-#define S6_I2C_DATACMD_READ            8
-#define S6_I2C_SSHCNT          0x014
-#define S6_I2C_SSLCNT          0x018
-#define S6_I2C_FSHCNT          0x01C
-#define S6_I2C_FSLCNT          0x020
-#define S6_I2C_INTRSTAT                0x02C
-#define S6_I2C_INTRMASK                0x030
-#define S6_I2C_RAWINTR         0x034
-#define S6_I2C_INTR_RXUNDER            0
-#define S6_I2C_INTR_RXOVER             1
-#define S6_I2C_INTR_RXFULL             2
-#define S6_I2C_INTR_TXOVER             3
-#define S6_I2C_INTR_TXEMPTY            4
-#define S6_I2C_INTR_RDREQ              5
-#define S6_I2C_INTR_TXABRT             6
-#define S6_I2C_INTR_RXDONE             7
-#define S6_I2C_INTR_ACTIVITY           8
-#define S6_I2C_INTR_STOPDET            9
-#define S6_I2C_INTR_STARTDET           10
-#define S6_I2C_INTR_GENCALL            11
-#define S6_I2C_RXTL            0x038
-#define S6_I2C_TXTL            0x03C
-#define S6_I2C_CLRINTR         0x040
-#define S6_I2C_CLRRXUNDER      0x044
-#define S6_I2C_CLRRXOVER       0x048
-#define S6_I2C_CLRTXOVER       0x04C
-#define S6_I2C_CLRRDREQ                0x050
-#define S6_I2C_CLRTXABRT       0x054
-#define S6_I2C_CLRRXDONE       0x058
-#define S6_I2C_CLRACTIVITY     0x05C
-#define S6_I2C_CLRSTOPDET      0x060
-#define S6_I2C_CLRSTARTDET     0x064
-#define S6_I2C_CLRGENCALL      0x068
-#define S6_I2C_ENABLE          0x06C
-#define S6_I2C_STATUS          0x070
-#define S6_I2C_STATUS_ACTIVITY         0
-#define S6_I2C_STATUS_TFNF             1
-#define S6_I2C_STATUS_TFE              2
-#define S6_I2C_STATUS_RFNE             3
-#define S6_I2C_STATUS_RFF              4
-#define S6_I2C_TXFLR           0x074
-#define S6_I2C_RXFLR           0x078
-#define S6_I2C_SRESET          0x07C
-#define S6_I2C_SRESET_IC_SRST          0
-#define S6_I2C_SRESET_IC_MASTER_SRST   1
-#define S6_I2C_SRESET_IC_SLAVE_SRST    2
-#define S6_I2C_TXABRTSOURCE    0x080
-
-#endif
index a3216de..b1336d5 100644 (file)
@@ -311,7 +311,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
                goto out;
        }
        adap = &siic->adapter;
-       adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
+       adap->class = I2C_CLASS_DEPRECATED;
 
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        siic->base = devm_ioremap_resource(&pdev->dev, mem_res);
index 95b9476..2e4eccd 100644 (file)
@@ -206,25 +206,31 @@ static inline void st_i2c_clr_bits(void __iomem *reg, u32 mask)
        writel_relaxed(readl_relaxed(reg) & ~mask, reg);
 }
 
-/* From I2C Specifications v0.5 */
+/*
+ * From I2C Specifications v0.5.
+ *
+ * All the values below have +10% margin added to be
+ * compatible with some out-of-spec devices,
+ * like HDMI link of the Toshiba 19AV600 TV.
+ */
 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,
+               .rep_start_hold         = 4400,
+               .rep_start_setup        = 5170,
+               .start_hold             = 4400,
+               .data_setup_time        = 275,
+               .stop_setup_time        = 4400,
+               .bus_free_time          = 5170,
        },
        [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,
+               .rep_start_hold         = 660,
+               .rep_start_setup        = 660,
+               .start_hold             = 660,
+               .data_setup_time        = 110,
+               .stop_setup_time        = 660,
+               .bus_free_time          = 1430,
        },
 };
 
@@ -815,7 +821,7 @@ static int st_i2c_probe(struct platform_device *pdev)
 
        adap = &i2c_dev->adap;
        i2c_set_adapdata(adap, i2c_dev);
-       snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%x)", res->start);
+       snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%pa)", &res->start);
        adap->owner = THIS_MODULE;
        adap->timeout = 2 * HZ;
        adap->retries = 0;
index fefb1c1..6a44f37 100644 (file)
@@ -909,7 +909,7 @@ static int 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 | I2C_CLASS_DEPRECATED;
+       adap->class = I2C_CLASS_DEPRECATED;
        strlcpy(adap->name, "ST Microelectronics DDC I2C adapter",
                sizeof(adap->name));
        adap->nr = bus_nr;
index 0576026..10855a0 100644 (file)
@@ -311,19 +311,8 @@ static struct serio_driver taos_drv = {
        .interrupt      = taos_interrupt,
 };
 
-static int __init taos_init(void)
-{
-       return serio_register_driver(&taos_drv);
-}
-
-static void __exit taos_exit(void)
-{
-       serio_unregister_driver(&taos_drv);
-}
+module_serio_driver(taos_drv);
 
 MODULE_AUTHOR("Jean Delvare <jdelvare@suse.de>");
 MODULE_DESCRIPTION("TAOS evaluation module driver");
 MODULE_LICENSE("GPL");
-
-module_init(taos_init);
-module_exit(taos_exit);
index f1bb2fc..87d0371 100644 (file)
@@ -792,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_CLASS_DEPRECATED;
+       i2c_dev->adapter.class = I2C_CLASS_DEPRECATED;
        strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
                sizeof(i2c_dev->adapter.name));
        i2c_dev->adapter.algo = &tegra_i2c_algo;
index 7731f17..ade9223 100644 (file)
@@ -677,15 +677,15 @@ static u32 xiic_func(struct i2c_adapter *adap)
 }
 
 static const struct i2c_algorithm xiic_algorithm = {
-       .master_xfer    = xiic_xfer,
-       .functionality  = xiic_func,
+       .master_xfer = xiic_xfer,
+       .functionality = xiic_func,
 };
 
 static struct i2c_adapter xiic_adapter = {
-       .owner          = THIS_MODULE,
-       .name           = DRIVER_NAME,
-       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED,
-       .algo           = &xiic_algorithm,
+       .owner = THIS_MODULE,
+       .name = DRIVER_NAME,
+       .class = I2C_CLASS_DEPRECATED,
+       .algo = &xiic_algorithm,
 };
 
 
diff --git a/drivers/i2c/busses/scx200_i2c.c b/drivers/i2c/busses/scx200_i2c.c
deleted file mode 100644 (file)
index 8eadf0f..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* linux/drivers/i2c/busses/scx200_i2c.c
-
-   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
-
-   National Semiconductor SCx200 I2C bus on GPIO pins
-
-   Based on i2c-velleman.c Copyright (C) 1995-96, 2000 Simon G. Vogl
-
-   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.
-   
-   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., 675 Mass Ave, Cambridge, MA 02139, USA.                
-*/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/io.h>
-
-#include <linux/scx200_gpio.h>
-
-MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
-MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver");
-MODULE_LICENSE("GPL");
-
-static int scl = CONFIG_SCx200_I2C_SCL;
-static int sda = CONFIG_SCx200_I2C_SDA;
-
-module_param(scl, int, 0);
-MODULE_PARM_DESC(scl, "GPIO line for SCL");
-module_param(sda, int, 0);
-MODULE_PARM_DESC(sda, "GPIO line for SDA");
-
-static void scx200_i2c_setscl(void *data, int state)
-{
-       scx200_gpio_set(scl, state);
-}
-
-static void scx200_i2c_setsda(void *data, int state)
-{
-       scx200_gpio_set(sda, state);
-} 
-
-static int scx200_i2c_getscl(void *data)
-{
-       return scx200_gpio_get(scl);
-}
-
-static int scx200_i2c_getsda(void *data)
-{
-       return scx200_gpio_get(sda);
-}
-
-/* ------------------------------------------------------------------------
- * Encapsulate the above functions in the correct operations structure.
- * This is only done when more than one hardware adapter is supported.
- */
-
-static struct i2c_algo_bit_data scx200_i2c_data = {
-       .setsda         = scx200_i2c_setsda,
-       .setscl         = scx200_i2c_setscl,
-       .getsda         = scx200_i2c_getsda,
-       .getscl         = scx200_i2c_getscl,
-       .udelay         = 10,
-       .timeout        = HZ,
-};
-
-static struct i2c_adapter scx200_i2c_ops = {
-       .owner             = THIS_MODULE,
-       .class             = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-       .algo_data         = &scx200_i2c_data,
-       .name   = "NatSemi SCx200 I2C",
-};
-
-static int scx200_i2c_init(void)
-{
-       pr_debug("NatSemi SCx200 I2C Driver\n");
-
-       if (!scx200_gpio_present()) {
-               pr_err("no SCx200 gpio pins available\n");
-               return -ENODEV;
-       }
-
-       pr_debug("SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda);
-
-       if (scl == -1 || sda == -1 || scl == sda) {
-               pr_err("scl and sda must be specified\n");
-               return -EINVAL;
-       }
-
-       /* Configure GPIOs as open collector outputs */
-       scx200_gpio_configure(scl, ~2, 5);
-       scx200_gpio_configure(sda, ~2, 5);
-
-       if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) {
-               pr_err("adapter %s registration failed\n", scx200_i2c_ops.name);
-               return -ENODEV;
-       }
-       
-       return 0;
-}
-
-static void scx200_i2c_cleanup(void)
-{
-       i2c_del_adapter(&scx200_i2c_ops);
-}
-
-module_init(scx200_i2c_init);
-module_exit(scx200_i2c_cleanup);
-
-/*
-    Local variables:
-        compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules"
-        c-basic-offset: 8
-    End:
-*/
diff --git a/drivers/i2c/i2c-acpi.c b/drivers/i2c/i2c-acpi.c
new file mode 100644 (file)
index 0000000..e8b6196
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * I2C ACPI code
+ *
+ * Copyright (C) 2014 Intel Corp
+ *
+ * Author: Lan Tianyu <tianyu.lan@intel.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.
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "I2C/ACPI : " fmt
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/acpi.h>
+
+struct acpi_i2c_handler_data {
+       struct acpi_connection_info info;
+       struct i2c_adapter *adapter;
+};
+
+struct gsb_buffer {
+       u8      status;
+       u8      len;
+       union {
+               u16     wdata;
+               u8      bdata;
+               u8      data[0];
+       };
+} __packed;
+
+static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
+{
+       struct i2c_board_info *info = data;
+
+       if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+               struct acpi_resource_i2c_serialbus *sb;
+
+               sb = &ares->data.i2c_serial_bus;
+               if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+                       info->addr = sb->slave_address;
+                       if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+                               info->flags |= I2C_CLIENT_TEN;
+               }
+       } else if (info->irq < 0) {
+               struct resource r;
+
+               if (acpi_dev_resource_interrupt(ares, 0, &r))
+                       info->irq = r.start;
+       }
+
+       /* Tell the ACPI core to skip this resource */
+       return 1;
+}
+
+static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
+                                      void *data, void **return_value)
+{
+       struct i2c_adapter *adapter = data;
+       struct list_head resource_list;
+       struct i2c_board_info info;
+       struct acpi_device *adev;
+       int ret;
+
+       if (acpi_bus_get_device(handle, &adev))
+               return AE_OK;
+       if (acpi_bus_get_status(adev) || !adev->status.present)
+               return AE_OK;
+
+       memset(&info, 0, sizeof(info));
+       info.acpi_node.companion = adev;
+       info.irq = -1;
+
+       INIT_LIST_HEAD(&resource_list);
+       ret = acpi_dev_get_resources(adev, &resource_list,
+                                    acpi_i2c_add_resource, &info);
+       acpi_dev_free_resource_list(&resource_list);
+
+       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));
+       }
+
+       return AE_OK;
+}
+
+/**
+ * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
+ * @adap: pointer to adapter
+ *
+ * Enumerate all I2C slave devices behind this adapter by walking the ACPI
+ * namespace. When a device is found it will be added to the Linux device
+ * model and bound to the corresponding ACPI handle.
+ */
+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;
+
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+                                    acpi_i2c_add_device, NULL,
+                                    adap, NULL);
+       if (ACPI_FAILURE(status))
+               dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
+}
+
+static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
+               u8 cmd, u8 *data, u8 data_len)
+{
+
+       struct i2c_msg msgs[2];
+       int ret;
+       u8 *buffer;
+
+       buffer = kzalloc(data_len, GFP_KERNEL);
+       if (!buffer)
+               return AE_NO_MEMORY;
+
+       msgs[0].addr = client->addr;
+       msgs[0].flags = client->flags;
+       msgs[0].len = 1;
+       msgs[0].buf = &cmd;
+
+       msgs[1].addr = client->addr;
+       msgs[1].flags = client->flags | I2C_M_RD;
+       msgs[1].len = data_len;
+       msgs[1].buf = buffer;
+
+       ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (ret < 0)
+               dev_err(&client->adapter->dev, "i2c read failed\n");
+       else
+               memcpy(data, buffer, data_len);
+
+       kfree(buffer);
+       return ret;
+}
+
+static int acpi_gsb_i2c_write_bytes(struct i2c_client *client,
+               u8 cmd, u8 *data, u8 data_len)
+{
+
+       struct i2c_msg msgs[1];
+       u8 *buffer;
+       int ret = AE_OK;
+
+       buffer = kzalloc(data_len + 1, GFP_KERNEL);
+       if (!buffer)
+               return AE_NO_MEMORY;
+
+       buffer[0] = cmd;
+       memcpy(buffer + 1, data, data_len);
+
+       msgs[0].addr = client->addr;
+       msgs[0].flags = client->flags;
+       msgs[0].len = data_len + 1;
+       msgs[0].buf = buffer;
+
+       ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+       if (ret < 0)
+               dev_err(&client->adapter->dev, "i2c write failed\n");
+
+       kfree(buffer);
+       return ret;
+}
+
+static acpi_status
+acpi_i2c_space_handler(u32 function, acpi_physical_address command,
+                       u32 bits, u64 *value64,
+                       void *handler_context, void *region_context)
+{
+       struct gsb_buffer *gsb = (struct gsb_buffer *)value64;
+       struct acpi_i2c_handler_data *data = handler_context;
+       struct acpi_connection_info *info = &data->info;
+       struct acpi_resource_i2c_serialbus *sb;
+       struct i2c_adapter *adapter = data->adapter;
+       struct i2c_client client;
+       struct acpi_resource *ares;
+       u32 accessor_type = function >> 16;
+       u8 action = function & ACPI_IO_MASK;
+       acpi_status ret = AE_OK;
+       int status;
+
+       ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
+       if (ACPI_FAILURE(ret))
+               return ret;
+
+       if (!value64 || ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) {
+               ret = AE_BAD_PARAMETER;
+               goto err;
+       }
+
+       sb = &ares->data.i2c_serial_bus;
+       if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_I2C) {
+               ret = AE_BAD_PARAMETER;
+               goto err;
+       }
+
+       memset(&client, 0, sizeof(client));
+       client.adapter = adapter;
+       client.addr = sb->slave_address;
+       client.flags = 0;
+
+       if (sb->access_mode == ACPI_I2C_10BIT_MODE)
+               client.flags |= I2C_CLIENT_TEN;
+
+       switch (accessor_type) {
+       case ACPI_GSB_ACCESS_ATTRIB_SEND_RCV:
+               if (action == ACPI_READ) {
+                       status = i2c_smbus_read_byte(&client);
+                       if (status >= 0) {
+                               gsb->bdata = status;
+                               status = 0;
+                       }
+               } else {
+                       status = i2c_smbus_write_byte(&client, gsb->bdata);
+               }
+               break;
+
+       case ACPI_GSB_ACCESS_ATTRIB_BYTE:
+               if (action == ACPI_READ) {
+                       status = i2c_smbus_read_byte_data(&client, command);
+                       if (status >= 0) {
+                               gsb->bdata = status;
+                               status = 0;
+                       }
+               } else {
+                       status = i2c_smbus_write_byte_data(&client, command,
+                                       gsb->bdata);
+               }
+               break;
+
+       case ACPI_GSB_ACCESS_ATTRIB_WORD:
+               if (action == ACPI_READ) {
+                       status = i2c_smbus_read_word_data(&client, command);
+                       if (status >= 0) {
+                               gsb->wdata = status;
+                               status = 0;
+                       }
+               } else {
+                       status = i2c_smbus_write_word_data(&client, command,
+                                       gsb->wdata);
+               }
+               break;
+
+       case ACPI_GSB_ACCESS_ATTRIB_BLOCK:
+               if (action == ACPI_READ) {
+                       status = i2c_smbus_read_block_data(&client, command,
+                                       gsb->data);
+                       if (status >= 0) {
+                               gsb->len = status;
+                               status = 0;
+                       }
+               } else {
+                       status = i2c_smbus_write_block_data(&client, command,
+                                       gsb->len, gsb->data);
+               }
+               break;
+
+       case ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE:
+               if (action == ACPI_READ) {
+                       status = acpi_gsb_i2c_read_bytes(&client, command,
+                                       gsb->data, info->access_length);
+                       if (status > 0)
+                               status = 0;
+               } else {
+                       status = acpi_gsb_i2c_write_bytes(&client, command,
+                                       gsb->data, info->access_length);
+               }
+               break;
+
+       default:
+               pr_info("protocol(0x%02x) is not supported.\n", accessor_type);
+               ret = AE_BAD_PARAMETER;
+               goto err;
+       }
+
+       gsb->status = status;
+
+ err:
+       ACPI_FREE(ares);
+       return ret;
+}
+
+
+int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+{
+       acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+       struct acpi_i2c_handler_data *data;
+       acpi_status status;
+
+       if (!handle)
+               return -ENODEV;
+
+       data = kzalloc(sizeof(struct acpi_i2c_handler_data),
+                           GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->adapter = adapter;
+       status = acpi_bus_attach_private_data(handle, (void *)data);
+       if (ACPI_FAILURE(status)) {
+               kfree(data);
+               return -ENOMEM;
+       }
+
+       status = acpi_install_address_space_handler(handle,
+                               ACPI_ADR_SPACE_GSBUS,
+                               &acpi_i2c_space_handler,
+                               NULL,
+                               data);
+       if (ACPI_FAILURE(status)) {
+               dev_err(&adapter->dev, "Error installing i2c space handler\n");
+               acpi_bus_detach_private_data(handle);
+               kfree(data);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+{
+       acpi_handle handle = ACPI_HANDLE(adapter->dev.parent);
+       struct acpi_i2c_handler_data *data;
+       acpi_status status;
+
+       if (!handle)
+               return;
+
+       acpi_remove_address_space_handler(handle,
+                               ACPI_ADR_SPACE_GSBUS,
+                               &acpi_i2c_space_handler);
+
+       status = acpi_bus_get_private_data(handle, (void **)&data);
+       if (ACPI_SUCCESS(status))
+               kfree(data);
+
+       acpi_bus_detach_private_data(handle);
+}
index 66aa83b..632057a 100644 (file)
@@ -1097,101 +1097,6 @@ EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
 static void of_i2c_register_devices(struct i2c_adapter *adap) { }
 #endif /* CONFIG_OF */
 
-/* ACPI support code */
-
-#if IS_ENABLED(CONFIG_ACPI)
-static int acpi_i2c_add_resource(struct acpi_resource *ares, void *data)
-{
-       struct i2c_board_info *info = data;
-
-       if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
-               struct acpi_resource_i2c_serialbus *sb;
-
-               sb = &ares->data.i2c_serial_bus;
-               if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_I2C) {
-                       info->addr = sb->slave_address;
-                       if (sb->access_mode == ACPI_I2C_10BIT_MODE)
-                               info->flags |= I2C_CLIENT_TEN;
-               }
-       } else if (info->irq < 0) {
-               struct resource r;
-
-               if (acpi_dev_resource_interrupt(ares, 0, &r))
-                       info->irq = r.start;
-       }
-
-       /* Tell the ACPI core to skip this resource */
-       return 1;
-}
-
-static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
-                                      void *data, void **return_value)
-{
-       struct i2c_adapter *adapter = data;
-       struct list_head resource_list;
-       struct i2c_board_info info;
-       struct acpi_device *adev;
-       int ret;
-
-       if (acpi_bus_get_device(handle, &adev))
-               return AE_OK;
-       if (acpi_bus_get_status(adev) || !adev->status.present)
-               return AE_OK;
-
-       memset(&info, 0, sizeof(info));
-       info.acpi_node.companion = adev;
-       info.irq = -1;
-
-       INIT_LIST_HEAD(&resource_list);
-       ret = acpi_dev_get_resources(adev, &resource_list,
-                                    acpi_i2c_add_resource, &info);
-       acpi_dev_free_resource_list(&resource_list);
-
-       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));
-       }
-
-       return AE_OK;
-}
-
-/**
- * acpi_i2c_register_devices - enumerate I2C slave devices behind adapter
- * @adap: pointer to adapter
- *
- * Enumerate all I2C slave devices behind this adapter by walking the ACPI
- * namespace. When a device is found it will be added to the Linux device
- * model and bound to the corresponding ACPI handle.
- */
-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;
-
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
-                                    acpi_i2c_add_device, NULL,
-                                    adap, NULL);
-       if (ACPI_FAILURE(status))
-               dev_warn(&adap->dev, "failed to enumerate I2C slaves\n");
-}
-#else
-static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) {}
-#endif /* CONFIG_ACPI */
-
 static int i2c_do_add_adapter(struct i2c_driver *driver,
                              struct i2c_adapter *adap)
 {
@@ -1298,6 +1203,7 @@ exit_recovery:
        /* create pre-declared device nodes */
        of_i2c_register_devices(adap);
        acpi_i2c_register_devices(adap);
+       acpi_i2c_install_space_handler(adap);
 
        if (adap->nr < __i2c_first_dynamic_bus_num)
                i2c_scan_static_board_info(adap);
@@ -1471,6 +1377,7 @@ void i2c_del_adapter(struct i2c_adapter *adap)
                return;
        }
 
+       acpi_i2c_remove_space_handler(adap);
        /* Tell drivers about this removal */
        mutex_lock(&core_lock);
        bus_for_each_drv(&i2c_bus_type, NULL, adap,
@@ -2013,6 +1920,16 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
        if (!driver->detect || !address_list)
                return 0;
 
+       /* Warn that the adapter lost class based instantiation */
+       if (adapter->class == I2C_CLASS_DEPRECATED) {
+               dev_dbg(&adapter->dev,
+                       "This adapter dropped support for I2C classes and "
+                       "won't auto-detect %s devices anymore. If you need it, check "
+                       "'Documentation/i2c/instantiating-devices' for alternatives.\n",
+                       driver->driver.name);
+               return 0;
+       }
+
        /* Stop here if the classes do not match */
        if (!(adapter->class & driver->class))
                return 0;
index 77e4849..d241aa2 100644 (file)
@@ -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 <jdelvare@suse.de>
+    Copyright (C) 2007-2014 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
 #include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
+#include <linux/list.h>
 
 #define MAX_CHIPS 10
-#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
-                  I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
-                  I2C_FUNC_SMBUS_I2C_BLOCK)
+
+/*
+ * Support for I2C_FUNC_SMBUS_BLOCK_DATA is disabled by default and must
+ * be enabled explicitly by setting the I2C_FUNC_SMBUS_BLOCK_DATA bits
+ * in the 'functionality' module parameter.
+ */
+#define STUB_FUNC_DEFAULT \
+               (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
+                I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
+                I2C_FUNC_SMBUS_I2C_BLOCK)
+
+#define STUB_FUNC_ALL \
+               (STUB_FUNC_DEFAULT | I2C_FUNC_SMBUS_BLOCK_DATA)
 
 static unsigned short chip_addr[MAX_CHIPS];
 module_param_array(chip_addr, ushort, NULL, S_IRUGO);
 MODULE_PARM_DESC(chip_addr,
                 "Chip addresses (up to 10, between 0x03 and 0x77)");
 
-static unsigned long functionality = STUB_FUNC;
+static unsigned long functionality = STUB_FUNC_DEFAULT;
 module_param(functionality, ulong, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(functionality, "Override functionality bitfield");
 
+/* Some chips have banked register ranges */
+
+static u8 bank_reg[MAX_CHIPS];
+module_param_array(bank_reg, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_reg, "Bank register");
+
+static u8 bank_mask[MAX_CHIPS];
+module_param_array(bank_mask, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_mask, "Bank value mask");
+
+static u8 bank_start[MAX_CHIPS];
+module_param_array(bank_start, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_start, "First banked register");
+
+static u8 bank_end[MAX_CHIPS];
+module_param_array(bank_end, byte, NULL, S_IRUGO);
+MODULE_PARM_DESC(bank_end, "Last banked register");
+
+struct smbus_block_data {
+       struct list_head node;
+       u8 command;
+       u8 len;
+       u8 block[I2C_SMBUS_BLOCK_MAX];
+};
+
 struct stub_chip {
        u8 pointer;
        u16 words[256];         /* Byte operations use the LSB as per SMBus
                                   specification */
+       struct list_head smbus_blocks;
+
+       /* For chips with banks, extra registers are allocated dynamically */
+       u8 bank_reg;
+       u8 bank_shift;
+       u8 bank_mask;
+       u8 bank_sel;            /* Currently selected bank */
+       u8 bank_start;
+       u8 bank_end;
+       u16 bank_size;
+       u16 *bank_words;        /* Room for bank_mask * bank_size registers */
 };
 
 static struct stub_chip *stub_chips;
+static int stub_chips_nr;
+
+static struct smbus_block_data *stub_find_block(struct device *dev,
+                                               struct stub_chip *chip,
+                                               u8 command, bool create)
+{
+       struct smbus_block_data *b, *rb = NULL;
+
+       list_for_each_entry(b, &chip->smbus_blocks, node) {
+               if (b->command == command) {
+                       rb = b;
+                       break;
+               }
+       }
+       if (rb == NULL && create) {
+               rb = devm_kzalloc(dev, sizeof(*rb), GFP_KERNEL);
+               if (rb == NULL)
+                       return rb;
+               rb->command = command;
+               list_add(&rb->node, &chip->smbus_blocks);
+       }
+       return rb;
+}
+
+static u16 *stub_get_wordp(struct stub_chip *chip, u8 offset)
+{
+       if (chip->bank_sel &&
+           offset >= chip->bank_start && offset <= chip->bank_end)
+               return chip->bank_words +
+                      (chip->bank_sel - 1) * chip->bank_size +
+                      offset - chip->bank_start;
+       else
+               return chip->words + offset;
+}
 
 /* Return negative errno on error. */
 static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
@@ -57,9 +138,11 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
        s32 ret;
        int i, len;
        struct stub_chip *chip = NULL;
+       struct smbus_block_data *b;
+       u16 *wordp;
 
        /* Search for the right chip */
-       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
+       for (i = 0; i < stub_chips_nr; i++) {
                if (addr == chip_addr[i]) {
                        chip = stub_chips + i;
                        break;
@@ -82,7 +165,8 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
                                "smbus byte - addr 0x%02x, wrote 0x%02x.\n",
                                addr, command);
                } else {
-                       data->byte = chip->words[chip->pointer++] & 0xff;
+                       wordp = stub_get_wordp(chip, chip->pointer++);
+                       data->byte = *wordp & 0xff;
                        dev_dbg(&adap->dev,
                                "smbus byte - addr 0x%02x, read  0x%02x.\n",
                                addr, data->byte);
@@ -92,14 +176,25 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
                break;
 
        case I2C_SMBUS_BYTE_DATA:
+               wordp = stub_get_wordp(chip, command);
                if (read_write == I2C_SMBUS_WRITE) {
-                       chip->words[command] &= 0xff00;
-                       chip->words[command] |= data->byte;
+                       *wordp &= 0xff00;
+                       *wordp |= data->byte;
                        dev_dbg(&adap->dev,
                                "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
                                addr, data->byte, command);
+
+                       /* Set the bank as needed */
+                       if (chip->bank_words && command == chip->bank_reg) {
+                               chip->bank_sel =
+                                       (data->byte >> chip->bank_shift)
+                                       & chip->bank_mask;
+                               dev_dbg(&adap->dev,
+                                       "switching to bank %u.\n",
+                                       chip->bank_sel);
+                       }
                } else {
-                       data->byte = chip->words[command] & 0xff;
+                       data->byte = *wordp & 0xff;
                        dev_dbg(&adap->dev,
                                "smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n",
                                addr, data->byte, command);
@@ -110,13 +205,14 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
                break;
 
        case I2C_SMBUS_WORD_DATA:
+               wordp = stub_get_wordp(chip, command);
                if (read_write == I2C_SMBUS_WRITE) {
-                       chip->words[command] = data->word;
+                       *wordp = data->word;
                        dev_dbg(&adap->dev,
                                "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
                                addr, data->word, command);
                } else {
-                       data->word = chip->words[command];
+                       data->word = *wordp;
                        dev_dbg(&adap->dev,
                                "smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n",
                                addr, data->word, command);
@@ -126,6 +222,12 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
                break;
 
        case I2C_SMBUS_I2C_BLOCK_DATA:
+               /*
+                * We ignore banks here, because banked chips don't use I2C
+                * block transfers
+                */
+               if (data->block[0] > 256 - command)     /* Avoid overrun */
+                       data->block[0] = 256 - command;
                len = data->block[0];
                if (read_write == I2C_SMBUS_WRITE) {
                        for (i = 0; i < len; i++) {
@@ -148,6 +250,55 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
                ret = 0;
                break;
 
+       case I2C_SMBUS_BLOCK_DATA:
+               /*
+                * We ignore banks here, because chips typically don't use both
+                * banks and SMBus block transfers
+                */
+               b = stub_find_block(&adap->dev, chip, command, false);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       len = data->block[0];
+                       if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) {
+                               ret = -EINVAL;
+                               break;
+                       }
+                       if (b == NULL) {
+                               b = stub_find_block(&adap->dev, chip, command,
+                                                   true);
+                               if (b == NULL) {
+                                       ret = -ENOMEM;
+                                       break;
+                               }
+                       }
+                       /* Largest write sets read block length */
+                       if (len > b->len)
+                               b->len = len;
+                       for (i = 0; i < len; i++)
+                               b->block[i] = data->block[i + 1];
+                       /* update for byte and word commands */
+                       chip->words[command] = (b->block[0] << 8) | b->len;
+                       dev_dbg(&adap->dev,
+                               "smbus block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+                               addr, len, command);
+               } else {
+                       if (b == NULL) {
+                               dev_dbg(&adap->dev,
+                                       "SMBus block read command without prior block write not supported\n");
+                               ret = -EOPNOTSUPP;
+                               break;
+                       }
+                       len = b->len;
+                       data->block[0] = len;
+                       for (i = 0; i < len; i++)
+                               data->block[i + 1] = b->block[i];
+                       dev_dbg(&adap->dev,
+                               "smbus block data - addr 0x%02x, read  %d bytes at 0x%02x.\n",
+                               addr, len, command);
+               }
+
+               ret = 0;
+               break;
+
        default:
                dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
                ret = -EOPNOTSUPP;
@@ -159,7 +310,7 @@ static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
 
 static u32 stub_func(struct i2c_adapter *adapter)
 {
-       return STUB_FUNC & functionality;
+       return STUB_FUNC_ALL & functionality;
 }
 
 static const struct i2c_algorithm smbus_algorithm = {
@@ -174,6 +325,43 @@ static struct i2c_adapter stub_adapter = {
        .name           = "SMBus stub driver",
 };
 
+static int __init i2c_stub_allocate_banks(int i)
+{
+       struct stub_chip *chip = stub_chips + i;
+
+       chip->bank_reg = bank_reg[i];
+       chip->bank_start = bank_start[i];
+       chip->bank_end = bank_end[i];
+       chip->bank_size = bank_end[i] - bank_start[i] + 1;
+
+       /* We assume that all bits in the mask are contiguous */
+       chip->bank_mask = bank_mask[i];
+       while (!(chip->bank_mask & 1)) {
+               chip->bank_shift++;
+               chip->bank_mask >>= 1;
+       }
+
+       chip->bank_words = kzalloc(chip->bank_mask * chip->bank_size *
+                                  sizeof(u16), GFP_KERNEL);
+       if (!chip->bank_words)
+               return -ENOMEM;
+
+       pr_debug("i2c-stub: Allocated %u banks of %u words each (registers 0x%02x to 0x%02x)\n",
+                chip->bank_mask, chip->bank_size, chip->bank_start,
+                chip->bank_end);
+
+       return 0;
+}
+
+static void i2c_stub_free(void)
+{
+       int i;
+
+       for (i = 0; i < stub_chips_nr; i++)
+               kfree(stub_chips[i].bank_words);
+       kfree(stub_chips);
+}
+
 static int __init i2c_stub_init(void)
 {
        int i, ret;
@@ -194,22 +382,39 @@ static int __init i2c_stub_init(void)
        }
 
        /* Allocate memory for all chips at once */
-       stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
+       stub_chips_nr = i;
+       stub_chips = kcalloc(stub_chips_nr, sizeof(struct stub_chip),
+                            GFP_KERNEL);
        if (!stub_chips) {
                pr_err("i2c-stub: Out of memory\n");
                return -ENOMEM;
        }
+       for (i = 0; i < stub_chips_nr; i++) {
+               INIT_LIST_HEAD(&stub_chips[i].smbus_blocks);
+
+               /* Allocate extra memory for banked register ranges */
+               if (bank_mask[i]) {
+                       ret = i2c_stub_allocate_banks(i);
+                       if (ret)
+                               goto fail_free;
+               }
+       }
 
        ret = i2c_add_adapter(&stub_adapter);
        if (ret)
-               kfree(stub_chips);
+               goto fail_free;
+
+       return 0;
+
+ fail_free:
+       i2c_stub_free();
        return ret;
 }
 
 static void __exit i2c_stub_exit(void)
 {
        i2c_del_adapter(&stub_adapter);
-       kfree(stub_chips);
+       i2c_stub_free();
 }
 
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
index 9bd4212..ec11b40 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/i2c-mux.h>
 #include <linux/i2c/pca954x.h>
 #include <linux/module.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 
 #define PCA954X_MAX_NCHANS 8
@@ -273,9 +274,23 @@ static int pca954x_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int pca954x_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct pca954x *data = i2c_get_clientdata(client);
+
+       data->last_chan = 0;
+       return i2c_smbus_write_byte(client, 0);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(pca954x_pm, NULL, pca954x_resume);
+
 static struct i2c_driver pca954x_driver = {
        .driver         = {
                .name   = "pca954x",
+               .pm     = &pca954x_pm,
                .owner  = THIS_MODULE,
        },
        .probe          = pca954x_probe,
index 5320153..807cbc4 100644 (file)
@@ -364,6 +364,17 @@ extern bool osc_sb_apei_support_acked;
 #define OSC_PCI_EXPRESS_CAPABILITY_CONTROL     0x00000010
 #define OSC_PCI_CONTROL_MASKS                  0x0000001f
 
+#define ACPI_GSB_ACCESS_ATTRIB_QUICK           0x00000002
+#define ACPI_GSB_ACCESS_ATTRIB_SEND_RCV         0x00000004
+#define ACPI_GSB_ACCESS_ATTRIB_BYTE            0x00000006
+#define ACPI_GSB_ACCESS_ATTRIB_WORD            0x00000008
+#define ACPI_GSB_ACCESS_ATTRIB_BLOCK           0x0000000A
+#define ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE       0x0000000B
+#define ACPI_GSB_ACCESS_ATTRIB_WORD_CALL       0x0000000C
+#define ACPI_GSB_ACCESS_ATTRIB_BLOCK_CALL      0x0000000D
+#define ACPI_GSB_ACCESS_ATTRIB_RAW_BYTES       0x0000000E
+#define ACPI_GSB_ACCESS_ATTRIB_RAW_PROCESS     0x0000000F
+
 extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
                                             u32 *mask, u32 req);
 
index b556e0a..ea50766 100644 (file)
@@ -577,4 +577,16 @@ static inline struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node
 }
 #endif /* CONFIG_OF */
 
+#ifdef CONFIG_I2C_ACPI
+int acpi_i2c_install_space_handler(struct i2c_adapter *adapter);
+void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter);
+void acpi_i2c_register_devices(struct i2c_adapter *adap);
+#else
+static inline void acpi_i2c_register_devices(struct i2c_adapter *adap) { }
+static inline void acpi_i2c_remove_space_handler(struct i2c_adapter *adapter)
+{ }
+static inline int acpi_i2c_install_space_handler(struct i2c_adapter *adapter)
+{ return 0; }
+#endif
+
 #endif /* _LINUX_I2C_H */
diff --git a/include/linux/i2c/s6000.h b/include/linux/i2c/s6000.h
deleted file mode 100644 (file)
index d9b34bf..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __LINUX_I2C_S6000_H
-#define __LINUX_I2C_S6000_H
-
-struct s6_i2c_platform_data {
-       const char *clock; /* the clock to use */
-       int bus_num; /* the bus number to register */
-};
-
-#endif
-