Merge branch 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Dec 2012 00:51:10 +0000 (16:51 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Dec 2012 00:51:10 +0000 (16:51 -0800)
Pull i2c-embedded changes from Wolfram Sang:
 - CBUS driver (an I2C variant)
 - continued rework of the omap driver
 - s3c2410 gets lots of fixes and gains pinctrl support
 - at91 gains DMA support
 - the GPIO muxer gains devicetree probing
 - typical fixes and additions all over

* 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux: (45 commits)
  i2c: omap: Remove the OMAP_I2C_FLAG_RESET_REGS_POSTIDLE flag
  i2c: at91: add dma support
  i2c: at91: change struct members indentation
  i2c: at91: fix compilation warning
  i2c: mxs: Do not disable the I2C SMBus quick mode
  i2c: mxs: Handle i2c DMA failure properly
  i2c: s3c2410: Remove recently introduced performance overheads
  i2c: ocores: Move grlib set/get functions into #ifdef CONFIG_OF block
  i2c: s3c2410: Add fix for i2c suspend/resume
  i2c: s3c2410: Fix code to free gpios
  i2c: i2c-cbus-gpio: introduce driver
  i2c: ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions
  i2c: ocores: Add irq support for sparc
  i2c: omap: Move the remove constraint
  ARM: dts: cfa10049: Add the i2c muxer buses to the CFA-10049
  i2c: s3c2410: do not special case HDMIPHY stuck bus detection
  i2c: s3c2410: use exponential back off while polling for bus idle
  i2c: s3c2410: do not generate STOP for QUIRK_HDMIPHY
  i2c: s3c2410: grab adapter lock while changing i2c clock
  i2c: s3c2410: Add support for pinctrl
  ...

12 files changed:
1  2 
Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
arch/arm/boot/dts/imx28-cfa10049.dts
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/i2c.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-s3c2410.c

index b6cb5a12c672e9eb430534b3bb15dbb25ca83871,0000000000000000000000000000000000000000..e9611ace87924b8131295831103cb1ba0f3372f7
mode 100644,000000..100644
--- /dev/null
@@@ -1,43 -1,0 +1,55 @@@
-   - gpios: The order of the gpios should be the following: <SDA, SCL>.
-     The gpio specifier depends on the gpio controller. Required in all
-     cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output
-     lines are permanently wired to the respective client
 +* Samsung's I2C controller
 +
 +The Samsung's I2C controller is used to interface with I2C devices.
 +
 +Required properties:
 +  - compatible: value should be either of the following.
 +      (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
 +      (b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
 +      (c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used
 +          inside HDMIPHY block found on several samsung SoCs
 +  - reg: physical base address of the controller and length of memory mapped
 +    region.
 +  - interrupts: interrupt number to the cpu.
 +  - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
 +
++Required for all cases except "samsung,s3c2440-hdmiphy-i2c":
++  - Samsung GPIO variant (deprecated):
++    - gpios: The order of the gpios should be the following: <SDA, SCL>.
++      The gpio specifier depends on the gpio controller. Required in all
++      cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output
++      lines are permanently wired to the respective clienta
++  - Pinctrl variant (preferred, if available):
++    - pinctrl-0: Pin control group to be used for this controller.
++    - pinctrl-names: Should contain only one value - "default".
++
 +Optional properties:
 +  - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
 +    specified, default value is 0.
 +  - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
 +    specified, the default value in Hz is 100000.
 +
 +Example:
 +
 +      i2c@13870000 {
 +              compatible = "samsung,s3c2440-i2c";
 +              reg = <0x13870000 0x100>;
 +              interrupts = <345>;
 +              samsung,i2c-sda-delay = <100>;
 +              samsung,i2c-max-bus-freq = <100000>;
++              /* Samsung GPIO variant begins here */
 +              gpios = <&gpd1 2 0 /* SDA */
 +                       &gpd1 3 0 /* SCL */>;
++              /* Samsung GPIO variant ends here */
++              /* Pinctrl variant begins here */
++              pinctrl-0 = <&i2c3_bus>;
++              pinctrl-names = "default";
++              /* Pinctrl variant ends here */
 +              #address-cells = <1>;
 +              #size-cells = <0>;
 +
 +              wm8994@1a {
 +                      compatible = "wlf,wm8994";
 +                      reg = <0x1a>;
 +              };
 +      };
index b222614ac9e0d3ac2dac19b330f23bed7db02380,319a6dbd934333197e737f4b7ddbca8f6aab7574..bdc80a4453ddbc4ef2996dc3d952ed409b956f19
        apb@80000000 {
                apbh@80000000 {
                        pinctrl@80018000 {
 +                              pinctrl-names = "default", "default";
 +                              pinctrl-1 = <&hog_pins_cfa10049>;
 +
 +                              hog_pins_cfa10049: hog-10049@0 {
 +                                      reg = <0>;
 +                                      fsl,pinmux-ids = <
 +                                              0x0073 /* MX28_PAD_GPMI_D7__GPIO_0_7 */
 +                                              0x1163 /* MX28_PAD_LCD_D22__GPIO_1_22 */
 +                                              0x1173 /* MX28_PAD_LCD_D22__GPIO_1_23 */
 +                                              0x2153 /* MX28_PAD_SSP2_D5__GPIO_2_21 */
 +                                      >;
 +                                      fsl,drive-strength = <0>;
 +                                      fsl,voltage = <1>;
 +                                      fsl,pull-up = <0>;
 +                              };
 +
                                spi3_pins_cfa10049: spi3-cfa10049@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
@@@ -45,7 -29,6 +45,7 @@@
                                                0x01c1 /* MX28_PAD_GPMI_RESETN__SSP3_CMD */
                                                0x0111 /* MX28_PAD_GPMI_CE1N__SSP3_D3 */
                                                0x01a2 /* MX28_PAD_GPMI_ALE__SSP3_D4 */
 +                                              0x01b2 /* MX28_PAD_GPMI_CLE__SSP3_D5 */
                                        >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        spi-max-frequency = <100000>;
                                };
  
 +                              dac0: dh2228@2 {
 +                                      compatible = "rohm,dh2228fv";
 +                                      reg = <2>;
 +                                      spi-max-frequency = <100000>;
 +                              };
                        };
                };
  
                                status = "okay";
                        };
  
+                       i2cmux {
+                               compatible = "i2c-mux-gpio";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               mux-gpios = <&gpio1 22 0 &gpio1 23 0>;
+                               i2c-parent = <&i2c1>;
+                               i2c@0 {
+                                       reg = <0>;
+                               };
+                               i2c@1 {
+                                       reg = <1>;
+                               };
+                               i2c@2 {
+                                       reg = <2>;
+                               };
+                               i2c@3 {
+                                       reg = <3>;
+                               };
+                       };
                        usbphy1: usbphy@8007e000 {
                                status = "okay";
                        };
                        gpio = <&gpio0 7 1>;
                };
        };
 +
 +      ahb@80080000 {
 +              mac0: ethernet@800f0000 {
 +                      phy-mode = "rmii";
 +                      pinctrl-names = "default";
 +                      pinctrl-0 = <&mac0_pins_a>;
 +                      phy-reset-gpios = <&gpio2 21 0>;
 +                      phy-reset-duration = <100>;
 +                      status = "okay";
 +              };
 +      };
  };
index a4e167c55c1d45b516c54c0cf4531353be0568df,bbfd74263c426d0a0207d33d3346f1af65d0625a..0abb30fe399cfd5923785c37e7a995c29d90eb58
  #include <linux/gpio.h>
  #include <linux/init.h>
  #include <linux/io.h>
+ #include <linux/irq.h>
  #include <linux/stddef.h>
  #include <linux/i2c.h>
  #include <linux/spi/spi.h>
  #include <linux/usb/musb.h>
+ #include <linux/platform_data/i2c-cbus-gpio.h>
  #include <linux/platform_data/spi-omap2-mcspi.h>
  #include <linux/platform_data/mtd-onenand-omap2.h>
 +#include <linux/mfd/menelaus.h>
  #include <sound/tlv320aic3x.h>
  
  #include <asm/mach/arch.h>
  #include <asm/mach-types.h>
  
  #include "common.h"
 -#include <plat/menelaus.h>
 -#include <plat/mmc.h>
 +#include "mmc.h"
  
  #include "mux.h"
 +#include "gpmc-onenand.h"
  
  #define TUSB6010_ASYNC_CS     1
  #define TUSB6010_SYNC_CS      4
  #define TUSB6010_GPIO_ENABLE  0
  #define TUSB6010_DMACHAN      0x3f
  
+ #if defined(CONFIG_I2C_CBUS_GPIO) || defined(CONFIG_I2C_CBUS_GPIO_MODULE)
+ static struct i2c_cbus_platform_data n8x0_cbus_data = {
+       .clk_gpio = 66,
+       .dat_gpio = 65,
+       .sel_gpio = 64,
+ };
+ static struct platform_device n8x0_cbus_device = {
+       .name   = "i2c-cbus-gpio",
+       .id     = 3,
+       .dev    = {
+               .platform_data = &n8x0_cbus_data,
+       },
+ };
+ static struct i2c_board_info n8x0_i2c_board_info_3[] __initdata = {
+       {
+               I2C_BOARD_INFO("retu-mfd", 0x01),
+       },
+ };
+ static void __init n8x0_cbus_init(void)
+ {
+       const int retu_irq_gpio = 108;
+       if (gpio_request_one(retu_irq_gpio, GPIOF_IN, "Retu IRQ"))
+               return;
+       irq_set_irq_type(gpio_to_irq(retu_irq_gpio), IRQ_TYPE_EDGE_RISING);
+       n8x0_i2c_board_info_3[0].irq = gpio_to_irq(retu_irq_gpio);
+       i2c_register_board_info(3, n8x0_i2c_board_info_3,
+                               ARRAY_SIZE(n8x0_i2c_board_info_3));
+       platform_device_register(&n8x0_cbus_device);
+ }
+ #else /* CONFIG_I2C_CBUS_GPIO */
+ static void __init n8x0_cbus_init(void)
+ {
+ }
+ #endif /* CONFIG_I2C_CBUS_GPIO */
  #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
  /*
   * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@@@ -678,6 -718,7 +719,7 @@@ static void __init n8x0_init_machine(vo
        gpmc_onenand_init(board_onenand_data);
        n8x0_mmc_init();
        n8x0_usb_init();
+       n8x0_cbus_init();
  }
  
  MACHINE_START(NOKIA_N800, "Nokia N800")
        .init_machine   = n8x0_init_machine,
        .init_late      = omap2420_init_late,
        .timer          = &omap2_timer,
 -      .restart        = omap_prcm_restart,
 +      .restart        = omap2xxx_restart,
  MACHINE_END
  
  MACHINE_START(NOKIA_N810, "Nokia N810")
        .init_machine   = n8x0_init_machine,
        .init_late      = omap2420_init_late,
        .timer          = &omap2_timer,
 -      .restart        = omap_prcm_restart,
 +      .restart        = omap2xxx_restart,
  MACHINE_END
  
  MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
        .init_machine   = n8x0_init_machine,
        .init_late      = omap2420_init_late,
        .timer          = &omap2_timer,
 -      .restart        = omap_prcm_restart,
 +      .restart        = omap2xxx_restart,
  MACHINE_END
index fbb9b152cd5e7d555e12c71de3c31c469f0617b2,fc57e67b321f3900b38f95df939f796eac8ef33b..df6d6acbc9edad84fe830a40b59cc90c48fcec7f
   *
   */
  
 -#include <plat/i2c.h>
 -#include "common.h"
 -#include <plat/omap_hwmod.h>
 +#include "soc.h"
 +#include "omap_hwmod.h"
 +#include "omap_device.h"
  
 +#include "prm.h"
 +#include "common.h"
  #include "mux.h"
 +#include "i2c.h"
  
  /* In register I2C_CON, Bit 15 is the I2C enable bit */
  #define I2C_EN                                        BIT(15)
  #define OMAP2_I2C_CON_OFFSET                  0x24
  #define OMAP4_I2C_CON_OFFSET                  0xA4
  
 -/* Maximum microseconds to wait for OMAP module to softreset */
 -#define MAX_MODULE_SOFTRESET_WAIT     10000
 +#define MAX_OMAP_I2C_HWMOD_NAME_LEN   16
  
 -void __init omap2_i2c_mux_pins(int bus_id)
 +static void __init omap2_i2c_mux_pins(int bus_id)
  {
        char mux_name[sizeof("i2c2_scl.i2c2_scl")];
  
@@@ -106,62 -104,3 +106,81 @@@ int omap_i2c_reset(struct omap_hwmod *o
  
        return 0;
  }
 +
 +static int __init omap_i2c_nr_ports(void)
 +{
 +      int ports = 0;
 +
 +      if (cpu_is_omap24xx())
 +              ports = 2;
 +      else if (cpu_is_omap34xx())
 +              ports = 3;
 +      else if (cpu_is_omap44xx())
 +              ports = 4;
 +      return ports;
 +}
 +
++/*
++ * XXX This function is a temporary compatibility wrapper - only
++ * needed until the I2C driver can be converted to call
++ * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
++ */
++static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
++{
++      omap_pm_set_max_mpu_wakeup_lat(dev, t);
++}
++
 +static const char name[] = "omap_i2c";
 +
 +int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
 +                              int bus_id)
 +{
 +      int l;
 +      struct omap_hwmod *oh;
 +      struct platform_device *pdev;
 +      char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN];
 +      struct omap_i2c_bus_platform_data *pdata;
 +      struct omap_i2c_dev_attr *dev_attr;
 +
 +      if (bus_id > omap_i2c_nr_ports())
 +              return -EINVAL;
 +
 +      omap2_i2c_mux_pins(bus_id);
 +
 +      l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id);
 +      WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN,
 +              "String buffer overflow in I2C%d device setup\n", bus_id);
 +      oh = omap_hwmod_lookup(oh_name);
 +      if (!oh) {
 +                      pr_err("Could not look up %s\n", oh_name);
 +                      return -EEXIST;
 +      }
 +
 +      pdata = i2c_pdata;
 +      /*
 +       * pass the hwmod class's CPU-specific knowledge of I2C IP revision in
 +       * use, and functionality implementation flags, up to the OMAP I2C
 +       * driver via platform data
 +       */
 +      pdata->rev = oh->class->rev;
 +
 +      dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
 +      pdata->flags = dev_attr->flags;
 +
++      /*
++       * When waiting for completion of a i2c transfer, we need to
++       * set a wake up latency constraint for the MPU. This is to
++       * ensure quick enough wakeup from idle, when transfer
++       * completes.
++       * Only omap3 has support for constraints
++       */
++      if (cpu_is_omap34xx())
++              pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
 +      pdev = omap_device_build(name, bus_id, oh, pdata,
 +                      sizeof(struct omap_i2c_bus_platform_data),
 +                      NULL, 0, 0);
 +      WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
 +
 +      return PTR_RET(pdev);
 +}
 +
index 6c8fa70ddaddad333545bb10a9e5d5bfe4204950,b79ccf6efbe8f27f372b3d6f39d4df32e1b3d187..d2d3840557c392b2033e3b3cbf65d1eb985e9833
   * XXX handle crossbar/shared link difference for L3?
   * XXX these should be marked initdata for multi-OMAP kernels
   */
 +
 +#include <linux/i2c-omap.h>
  #include <linux/platform_data/asoc-ti-mcbsp.h>
  #include <linux/platform_data/spi-omap2-mcspi.h>
 -
 -#include <plat/omap_hwmod.h>
 -#include <plat/dma.h>
 -#include <plat/serial.h>
 -#include <plat/i2c.h>
 +#include <linux/omap-dma.h>
  #include <plat/dmtimer.h>
 -#include <plat/mmc.h>
 +
 +#include "omap_hwmod.h"
 +#include "mmc.h"
  #include "l3_2xxx.h"
  
  #include "soc.h"
  #include "omap_hwmod_common_data.h"
  #include "prm-regbits-24xx.h"
  #include "cm-regbits-24xx.h"
 +#include "i2c.h"
  #include "wd_timer.h"
  
  /*
@@@ -77,8 -76,7 +77,7 @@@ static struct omap_hwmod_class i2c_clas
  
  static struct omap_i2c_dev_attr i2c_dev_attr = {
        .fifo_depth     = 8, /* bytes */
-       .flags          = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-                         OMAP_I2C_FLAG_BUS_SHIFT_2 |
+       .flags          = OMAP_I2C_FLAG_BUS_SHIFT_2 |
                          OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
  };
  
index 32820d89f5b41f917ab270273a5a0a0df7266c5d,c9a186bc6d40ab05d99c81115799a9cc71d357a1..081c71edddf4562797c632fc8f19bb86a8bac07d
   * GNU General Public License for more details.
   */
  
 -#include <plat/omap_hwmod.h>
 -#include <plat/cpu.h>
 +#include <linux/i2c-omap.h>
 +
 +#include "omap_hwmod.h"
  #include <linux/platform_data/gpio-omap.h>
  #include <linux/platform_data/spi-omap2-mcspi.h>
 -#include <plat/dma.h>
 -#include <plat/mmc.h>
 -#include <plat/i2c.h>
  
  #include "omap_hwmod_common_data.h"
  
@@@ -26,8 -28,6 +26,8 @@@
  #include "cm33xx.h"
  #include "prm33xx.h"
  #include "prm-regbits-33xx.h"
 +#include "i2c.h"
 +#include "mmc.h"
  
  /*
   * IP blocks
@@@ -674,7 -674,6 +674,7 @@@ static struct omap_hwmod am33xx_cpgmac0
        .name           = "cpgmac0",
        .class          = &am33xx_cpgmac0_hwmod_class,
        .clkdm_name     = "cpsw_125mhz_clkdm",
 +      .flags          = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
        .mpu_irqs       = am33xx_cpgmac0_irqs,
        .main_clk       = "cpsw_125mhz_gclk",
        .prcm           = {
        },
  };
  
 +/*
 + * mdio class
 + */
 +static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
 +      .name           = "davinci_mdio",
 +};
 +
 +static struct omap_hwmod am33xx_mdio_hwmod = {
 +      .name           = "davinci_mdio",
 +      .class          = &am33xx_mdio_hwmod_class,
 +      .clkdm_name     = "cpsw_125mhz_clkdm",
 +      .main_clk       = "cpsw_125mhz_gclk",
 +};
 +
  /*
   * dcan class
   */
@@@ -1118,8 -1103,7 +1118,7 @@@ static struct omap_hwmod_class i2c_clas
  };
  
  static struct omap_i2c_dev_attr i2c_dev_attr = {
-       .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE |
-                 OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
+       .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
  };
  
  /* i2c1 */
@@@ -2516,21 -2500,6 +2515,21 @@@ static struct omap_hwmod_ocp_if am33xx_
        .user           = OCP_USER_MPU,
  };
  
 +struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
 +      {
 +              .pa_start       = 0x4A101000,
 +              .pa_end         = 0x4A101000 + SZ_256 - 1,
 +      },
 +      { }
 +};
 +
 +struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
 +      .master         = &am33xx_cpgmac0_hwmod,
 +      .slave          = &am33xx_mdio_hwmod,
 +      .addr           = am33xx_mdio_addr_space,
 +      .user           = OCP_USER_MPU,
 +};
 +
  static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
        {
                .pa_start       = 0x48080000,
@@@ -3401,7 -3370,6 +3400,7 @@@ static struct omap_hwmod_ocp_if *am33xx
        &am33xx_l3_main__tptc2,
        &am33xx_l3_s__usbss,
        &am33xx_l4_hs__cpgmac0,
 +      &am33xx_cpgmac0__mdio,
        NULL,
  };
  
index ec4499e5a4c931f0869fc7bee317d4d171a7739e,36270bb637e429cbfd4e37326ff68b96b004a5f0..8bb2628df34ed26522b30560f5eafc2c6a8c459c
   *
   * XXX these should be marked initdata for multi-OMAP kernels
   */
 +
 +#include <linux/i2c-omap.h>
  #include <linux/power/smartreflex.h>
  #include <linux/platform_data/gpio-omap.h>
  
 -#include <plat/omap_hwmod.h>
 -#include <plat/dma.h>
 -#include <plat/serial.h>
 +#include <linux/omap-dma.h>
  #include "l3_3xxx.h"
  #include "l4_3xxx.h"
 -#include <plat/i2c.h>
 -#include <plat/mmc.h>
  #include <linux/platform_data/asoc-ti-mcbsp.h>
  #include <linux/platform_data/spi-omap2-mcspi.h>
 +#include <linux/platform_data/iommu-omap.h>
  #include <plat/dmtimer.h>
 -#include <plat/iommu.h>
  
  #include "am35xx.h"
  
  #include "soc.h"
 +#include "omap_hwmod.h"
  #include "omap_hwmod_common_data.h"
  #include "prm-regbits-34xx.h"
  #include "cm-regbits-34xx.h"
 +
 +#include "dma.h"
 +#include "i2c.h"
 +#include "mmc.h"
  #include "wd_timer.h"
 +#include "serial.h"
  
  /*
   * OMAP3xxx hardware module integration data
@@@ -153,16 -149,29 +153,16 @@@ static struct omap_hwmod omap3xxx_debug
  };
  
  /* timer class */
 -static struct omap_hwmod_class_sysconfig omap3xxx_timer_1ms_sysc = {
 -      .rev_offs       = 0x0000,
 -      .sysc_offs      = 0x0010,
 -      .syss_offs      = 0x0014,
 -      .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
 -                              SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
 -                              SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
 -      .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 -      .sysc_fields    = &omap_hwmod_sysc_type1,
 -};
 -
 -static struct omap_hwmod_class omap3xxx_timer_1ms_hwmod_class = {
 -      .name = "timer",
 -      .sysc = &omap3xxx_timer_1ms_sysc,
 -};
 -
  static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
        .syss_offs      = 0x0014,
 -      .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
 -                         SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
 +      .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
 +                         SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
 +                         SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE |
 +                         SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 +      .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
  };
  
@@@ -211,8 -220,7 +211,8 @@@ static struct omap_hwmod omap3xxx_timer
                },
        },
        .dev_attr       = &capability_alwon_dev_attr,
 -      .class          = &omap3xxx_timer_1ms_hwmod_class,
 +      .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer2 */
@@@ -229,8 -237,7 +229,8 @@@ static struct omap_hwmod omap3xxx_timer
                        .idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
                },
        },
 -      .class          = &omap3xxx_timer_1ms_hwmod_class,
 +      .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer3 */
@@@ -248,7 -255,6 +248,7 @@@ static struct omap_hwmod omap3xxx_timer
                },
        },
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer4 */
@@@ -266,7 -272,6 +266,7 @@@ static struct omap_hwmod omap3xxx_timer
                },
        },
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer5 */
@@@ -285,7 -290,6 +285,7 @@@ static struct omap_hwmod omap3xxx_timer
        },
        .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer6 */
@@@ -304,7 -308,6 +304,7 @@@ static struct omap_hwmod omap3xxx_timer
        },
        .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer7 */
@@@ -323,7 -326,6 +323,7 @@@ static struct omap_hwmod omap3xxx_timer
        },
        .dev_attr       = &capability_dsp_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer8 */
@@@ -342,7 -344,6 +342,7 @@@ static struct omap_hwmod omap3xxx_timer
        },
        .dev_attr       = &capability_dsp_pwm_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer9 */
@@@ -361,7 -362,6 +361,7 @@@ static struct omap_hwmod omap3xxx_timer
        },
        .dev_attr       = &capability_pwm_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer10 */
@@@ -379,8 -379,7 +379,8 @@@ static struct omap_hwmod omap3xxx_timer
                },
        },
        .dev_attr       = &capability_pwm_dev_attr,
 -      .class          = &omap3xxx_timer_1ms_hwmod_class,
 +      .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer11 */
@@@ -399,7 -398,6 +399,7 @@@ static struct omap_hwmod omap3xxx_timer
        },
        .dev_attr       = &capability_pwm_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /* timer12 */
@@@ -423,7 -421,6 +423,7 @@@ static struct omap_hwmod omap3xxx_timer
        },
        .dev_attr       = &capability_secure_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
  };
  
  /*
@@@ -794,9 -791,7 +794,7 @@@ static struct omap_hwmod omap3xxx_dss_v
  /* I2C1 */
  static struct omap_i2c_dev_attr i2c1_dev_attr = {
        .fifo_depth     = 8, /* bytes */
-       .flags          = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-                         OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
-                         OMAP_I2C_FLAG_BUS_SHIFT_2,
+       .flags          = OMAP_I2C_FLAG_BUS_SHIFT_2,
  };
  
  static struct omap_hwmod omap3xxx_i2c1_hwmod = {
  /* I2C2 */
  static struct omap_i2c_dev_attr i2c2_dev_attr = {
        .fifo_depth     = 8, /* bytes */
-       .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-                OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
-                OMAP_I2C_FLAG_BUS_SHIFT_2,
+       .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
  };
  
  static struct omap_hwmod omap3xxx_i2c2_hwmod = {
  /* I2C3 */
  static struct omap_i2c_dev_attr i2c3_dev_attr = {
        .fifo_depth     = 64, /* bytes */
-       .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
-                OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
-                OMAP_I2C_FLAG_BUS_SHIFT_2,
+       .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
  };
  
  static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
index eb61cfd9452b57e3d6ffaf98ba02c795a533aebb,eb40dbc6688e8a1883f31550c916369341685235..272b0178dba6495f087cf63f184eb1c185316a06
  #include <linux/io.h>
  #include <linux/platform_data/gpio-omap.h>
  #include <linux/power/smartreflex.h>
 +#include <linux/platform_data/omap_ocp2scp.h>
 +#include <linux/i2c-omap.h>
  
 -#include <plat/omap_hwmod.h>
 -#include <plat/i2c.h>
 -#include <plat/dma.h>
 +#include <linux/omap-dma.h>
 +
 +#include <linux/platform_data/omap_ocp2scp.h>
  #include <linux/platform_data/spi-omap2-mcspi.h>
  #include <linux/platform_data/asoc-ti-mcbsp.h>
 -#include <plat/mmc.h>
 +#include <linux/platform_data/iommu-omap.h>
  #include <plat/dmtimer.h>
 -#include <plat/common.h>
 -#include <plat/iommu.h>
  
 +#include "omap_hwmod.h"
  #include "omap_hwmod_common_data.h"
  #include "cm1_44xx.h"
  #include "cm2_44xx.h"
  #include "prm44xx.h"
  #include "prm-regbits-44xx.h"
 +#include "i2c.h"
 +#include "mmc.h"
  #include "wd_timer.h"
  
  /* Base offset for all OMAP4 interrupts external to MPUSS */
@@@ -1529,8 -1526,7 +1529,7 @@@ static struct omap_hwmod_class omap44xx
  };
  
  static struct omap_i2c_dev_attr i2c_dev_attr = {
-       .flags  = OMAP_I2C_FLAG_BUS_SHIFT_NONE |
-                       OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
+       .flags  = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
  };
  
  /* i2c1 */
@@@ -2128,14 -2124,6 +2127,14 @@@ static struct omap_hwmod omap44xx_mcpdm
        .name           = "mcpdm",
        .class          = &omap44xx_mcpdm_hwmod_class,
        .clkdm_name     = "abe_clkdm",
 +      /*
 +       * It's suspected that the McPDM requires an off-chip main
 +       * functional clock, controlled via I2C.  This IP block is
 +       * currently reset very early during boot, before I2C is
 +       * available, so it doesn't seem that we have any choice in
 +       * the kernel other than to avoid resetting it.
 +       */
 +      .flags          = HWMOD_EXT_OPT_MAIN_CLK,
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
@@@ -2692,32 -2680,6 +2691,32 @@@ static struct omap_hwmod_class omap44xx
        .sysc   = &omap44xx_ocp2scp_sysc,
  };
  
 +/* ocp2scp dev_attr */
 +static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
 +      {
 +              .name           = "usb_phy",
 +              .start          = 0x4a0ad080,
 +              .end            = 0x4a0ae000,
 +              .flags          = IORESOURCE_MEM,
 +      },
 +      {
 +              /* XXX: Remove this once control module driver is in place */
 +              .name           = "ctrl_dev",
 +              .start          = 0x4a002300,
 +              .end            = 0x4a002303,
 +              .flags          = IORESOURCE_MEM,
 +      },
 +      { }
 +};
 +
 +static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
 +      {
 +              .drv_name       = "omap-usb2",
 +              .res            = omap44xx_usb_phy_and_pll_addrs,
 +      },
 +      { }
 +};
 +
  /* ocp2scp_usb_phy */
  static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
                        .modulemode   = MODULEMODE_HWCTRL,
                },
        },
 +      .dev_attr       = ocp2scp_dev_attr,
  };
  
  /*
@@@ -3104,7 -3065,6 +3103,7 @@@ static struct omap_hwmod_class_sysconfi
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
                           SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 +      .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
  };
  
@@@ -3158,7 -3118,6 +3157,7 @@@ static struct omap_hwmod omap44xx_timer
        .name           = "timer1",
        .class          = &omap44xx_timer_1ms_hwmod_class,
        .clkdm_name     = "l4_wkup_clkdm",
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
        .mpu_irqs       = omap44xx_timer1_irqs,
        .main_clk       = "timer1_fck",
        .prcm = {
@@@ -3181,7 -3140,6 +3180,7 @@@ static struct omap_hwmod omap44xx_timer
        .name           = "timer2",
        .class          = &omap44xx_timer_1ms_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
        .mpu_irqs       = omap44xx_timer2_irqs,
        .main_clk       = "timer2_fck",
        .prcm = {
@@@ -3356,7 -3314,6 +3355,7 @@@ static struct omap_hwmod omap44xx_timer
        .name           = "timer10",
        .class          = &omap44xx_timer_1ms_hwmod_class,
        .clkdm_name     = "l4_per_clkdm",
 +      .flags          = HWMOD_SET_DEFAULT_CLOCKACT,
        .mpu_irqs       = omap44xx_timer10_irqs,
        .main_clk       = "timer10_fck",
        .prcm = {
index c7bff51fe524788d65c4c4e150405f0affa0c0ad,e949edf644d4a49af85a7fc9248fa6315deab5bf..bdca5111eb9de406e685c62315fb67a59bf5cecc
@@@ -337,6 -337,16 +337,16 @@@ config I2C_BLACKFIN_TWI_CLK_KH
        help
          The unit of the TWI clock is kHz.
  
+ config I2C_CBUS_GPIO
+       tristate "CBUS I2C driver"
+       depends on GENERIC_GPIO
+       help
+         Support for CBUS access using I2C API. Mostly relevant for Nokia
+         Internet Tablets (770, N800 and N810).
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-cbus-gpio.
  config I2C_CPM
        tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
        depends on (CPM1 || CPM2) && OF_I2C
@@@ -818,16 -828,6 +828,16 @@@ config I2C_TINY_US
          This driver can also be built as a module.  If so, the module
          will be called i2c-tiny-usb.
  
 +config I2C_VIPERBOARD
 +      tristate "Viperboard I2C master support"
 +      depends on MFD_VIPERBOARD && USB
 +      help
 +        Say yes here to access the I2C part of the Nano River
 +        Technologies Viperboard as I2C master.
 +          See viperboard API specification and Nano
 +          River Tech's viperboard.h for detailed meaning
 +          of the module parameters.
 +
  comment "Other I2C/SMBus bus drivers"
  
  config I2C_ACORN
index e5cb209d276c8aae007cbac8cc307f590cd37732,f9e3e0b5c827a9e3d5a60da9060c92f26dfbe80e..6181f3ff263fde9c0aa6d5b25e20ead42bb44e2a
@@@ -31,6 -31,7 +31,7 @@@ obj-$(CONFIG_I2C_POWERMAC)    += i2c-power
  obj-$(CONFIG_I2C_AT91)                += i2c-at91.o
  obj-$(CONFIG_I2C_AU1550)      += i2c-au1550.o
  obj-$(CONFIG_I2C_BLACKFIN_TWI)        += i2c-bfin-twi.o
+ obj-$(CONFIG_I2C_CBUS_GPIO)   += i2c-cbus-gpio.o
  obj-$(CONFIG_I2C_CPM)         += i2c-cpm.o
  obj-$(CONFIG_I2C_DAVINCI)     += i2c-davinci.o
  obj-$(CONFIG_I2C_DESIGNWARE_CORE)     += i2c-designware-core.o
@@@ -79,7 -80,6 +80,7 @@@ obj-$(CONFIG_I2C_PARPORT)     += i2c-parpor
  obj-$(CONFIG_I2C_PARPORT_LIGHT)       += i2c-parport-light.o
  obj-$(CONFIG_I2C_TAOS_EVM)    += i2c-taos-evm.o
  obj-$(CONFIG_I2C_TINY_USB)    += i2c-tiny-usb.o
 +obj-$(CONFIG_I2C_VIPERBOARD)  += i2c-viperboard.o
  
  # Other I2C/SMBus bus drivers
  obj-$(CONFIG_I2C_ACORN)               += i2c-acorn.o
index 15da1ac7cf9e05983a8a8db08907023e435d2325,df69598ed28e4ce80ae28bbd862277d3b7c2f2fc..9b35c9fbb2fea12859a178c3146e478c32861180
@@@ -4,11 -4,18 +4,14 @@@
   *
   * Peter Korsgaard <jacmet@sunsite.dk>
   *
+  * Support for the GRLIB port of the controller by
+  * Andreas Larsson <andreas@gaisler.com>
+  *
   * This file is licensed under the terms of the GNU General Public License
   * version 2.  This program is licensed "as is" without any warranty of any
   * kind, whether express or implied.
   */
  
 -/*
 - * This driver can be used from the device tree, see
 - *     Documentation/devicetree/bindings/i2c/ocore-i2c.txt
 - */
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
@@@ -34,6 -41,8 +37,8 @@@ struct ocores_i2c 
        int nmsgs;
        int state; /* see STATE_ */
        int clock_khz;
+       void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value);
+       u8 (*getreg)(struct ocores_i2c *i2c, int reg);
  };
  
  /* registers */
  #define STATE_READ            3
  #define STATE_ERROR           4
  
+ #define TYPE_OCORES           0
+ #define TYPE_GRLIB            1
+ static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value)
+ {
+       iowrite8(value, i2c->base + (reg << i2c->reg_shift));
+ }
+ static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value)
+ {
+       iowrite16(value, i2c->base + (reg << i2c->reg_shift));
+ }
+ static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value)
+ {
+       iowrite32(value, i2c->base + (reg << i2c->reg_shift));
+ }
+ static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg)
+ {
+       return ioread8(i2c->base + (reg << i2c->reg_shift));
+ }
+ static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg)
+ {
+       return ioread16(i2c->base + (reg << i2c->reg_shift));
+ }
+ static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg)
+ {
+       return ioread32(i2c->base + (reg << i2c->reg_shift));
+ }
  static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
  {
-       if (i2c->reg_io_width == 4)
-               iowrite32(value, i2c->base + (reg << i2c->reg_shift));
-       else if (i2c->reg_io_width == 2)
-               iowrite16(value, i2c->base + (reg << i2c->reg_shift));
-       else
-               iowrite8(value, i2c->base + (reg << i2c->reg_shift));
+       i2c->setreg(i2c, reg, value);
  }
  
  static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
  {
-       if (i2c->reg_io_width == 4)
-               return ioread32(i2c->base + (reg << i2c->reg_shift));
-       else if (i2c->reg_io_width == 2)
-               return ioread16(i2c->base + (reg << i2c->reg_shift));
-       else
-               return ioread8(i2c->base + (reg << i2c->reg_shift));
+       return i2c->getreg(i2c, reg);
  }
  
  static void ocores_process(struct ocores_i2c *i2c)
@@@ -223,11 -255,59 +251,59 @@@ static struct i2c_adapter ocores_adapte
        .algo           = &ocores_algorithm,
  };
  
+ static struct of_device_id ocores_i2c_match[] = {
+       {
+               .compatible = "opencores,i2c-ocores",
+               .data = (void *)TYPE_OCORES,
+       },
+       {
+               .compatible = "aeroflexgaisler,i2cmst",
+               .data = (void *)TYPE_GRLIB,
+       },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, ocores_i2c_match);
  #ifdef CONFIG_OF
+ /* Read and write functions for the GRLIB port of the controller. Registers are
+  * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one
+  * register. The subsequent registers has their offset decreased accordingly. */
+ static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg)
+ {
+       u32 rd;
+       int rreg = reg;
+       if (reg != OCI2C_PRELOW)
+               rreg--;
+       rd = ioread32be(i2c->base + (rreg << i2c->reg_shift));
+       if (reg == OCI2C_PREHIGH)
+               return (u8)(rd >> 8);
+       else
+               return (u8)rd;
+ }
+ static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value)
+ {
+       u32 curr, wr;
+       int rreg = reg;
+       if (reg != OCI2C_PRELOW)
+               rreg--;
+       if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) {
+               curr = ioread32be(i2c->base + (rreg << i2c->reg_shift));
+               if (reg == OCI2C_PRELOW)
+                       wr = (curr & 0xff00) | value;
+               else
+                       wr = (((u32)value) << 8) | (curr & 0xff);
+       } else {
+               wr = value;
+       }
+       iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift));
+ }
  static int ocores_i2c_of_probe(struct platform_device *pdev,
                                struct ocores_i2c *i2c)
  {
        struct device_node *np = pdev->dev.of_node;
+       const struct of_device_id *match;
        u32 val;
  
        if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
  
        of_property_read_u32(pdev->dev.of_node, "reg-io-width",
                                &i2c->reg_io_width);
+       match = of_match_node(ocores_i2c_match, pdev->dev.of_node);
+       if (match && (int)match->data == TYPE_GRLIB) {
+               dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n");
+               i2c->setreg = oc_setreg_grlib;
+               i2c->getreg = oc_getreg_grlib;
+       }
        return 0;
  }
  #else
@@@ -263,7 -351,8 +347,8 @@@ static int __devinit ocores_i2c_probe(s
  {
        struct ocores_i2c *i2c;
        struct ocores_i2c_platform_data *pdata;
-       struct resource *res, *res2;
+       struct resource *res;
+       int irq;
        int ret;
        int i;
  
        if (!res)
                return -ENODEV;
  
-       res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res2)
-               return -ENODEV;
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0)
+               return irq;
  
        i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
        if (!i2c)
                return -ENOMEM;
  
-       if (!devm_request_mem_region(&pdev->dev, res->start,
-                                    resource_size(res), pdev->name)) {
-               dev_err(&pdev->dev, "Memory region busy\n");
-               return -EBUSY;
-       }
-       i2c->base = devm_ioremap_nocache(&pdev->dev, res->start,
-                                        resource_size(res));
-       if (!i2c->base) {
-               dev_err(&pdev->dev, "Unable to map registers\n");
-               return -EIO;
-       }
+       i2c->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!i2c->base)
+               return -EADDRNOTAVAIL;
  
        pdata = pdev->dev.platform_data;
        if (pdata) {
        if (i2c->reg_io_width == 0)
                i2c->reg_io_width = 1; /* Set to default value */
  
+       if (!i2c->setreg || !i2c->getreg) {
+               switch (i2c->reg_io_width) {
+               case 1:
+                       i2c->setreg = oc_setreg_8;
+                       i2c->getreg = oc_getreg_8;
+                       break;
+               case 2:
+                       i2c->setreg = oc_setreg_16;
+                       i2c->getreg = oc_getreg_16;
+                       break;
+               case 4:
+                       i2c->setreg = oc_setreg_32;
+                       i2c->getreg = oc_getreg_32;
+                       break;
+               default:
+                       dev_err(&pdev->dev, "Unsupported I/O width (%d)\n",
+                               i2c->reg_io_width);
+                       return -EINVAL;
+               }
+       }
        ocores_init(i2c);
  
        init_waitqueue_head(&i2c->wait);
-       ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0,
+       ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0,
                               pdev->name, i2c);
        if (ret) {
                dev_err(&pdev->dev, "Cannot claim IRQ\n");
@@@ -383,12 -487,6 +483,6 @@@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm
  #define OCORES_I2C_PM NULL
  #endif
  
- static struct of_device_id ocores_i2c_match[] = {
-       { .compatible = "opencores,i2c-ocores", },
-       {},
- };
- MODULE_DEVICE_TABLE(of, ocores_i2c_match);
  static struct platform_driver ocores_i2c_driver = {
        .probe   = ocores_i2c_probe,
        .remove  = __devexit_p(ocores_i2c_remove),
index b33d95ebc890aa9667d64f01a66fb961244fbe88,e93e7d672773c6f16a0fd438eaaaa8fe0158690e..a290d089ceaf084702530af3ebce4fe458e9132c
@@@ -38,6 -38,7 +38,7 @@@
  #include <linux/io.h>
  #include <linux/of_i2c.h>
  #include <linux/of_gpio.h>
+ #include <linux/pinctrl/consumer.h>
  
  #include <asm/irq.h>
  
@@@ -49,6 -50,9 +50,9 @@@
  #define QUIRK_HDMIPHY         (1 << 1)
  #define QUIRK_NO_GPIO         (1 << 2)
  
+ /* Max time to wait for bus to become idle after a xfer (in us) */
+ #define S3C2410_IDLE_TIMEOUT  5000
  /* i2c controller state */
  enum s3c24xx_i2c_state {
        STATE_IDLE,
@@@ -59,7 -63,6 +63,6 @@@
  };
  
  struct s3c24xx_i2c {
-       spinlock_t              lock;
        wait_queue_head_t       wait;
        unsigned int            quirks;
        unsigned int            suspended:1;
        void __iomem            *regs;
        struct clk              *clk;
        struct device           *dev;
-       struct resource         *ioarea;
        struct i2c_adapter      adap;
  
        struct s3c2410_platform_i2c     *pdata;
        int                     gpios[2];
+       struct pinctrl          *pctrl;
  #ifdef CONFIG_CPU_FREQ
        struct notifier_block   freq_transition;
  #endif
@@@ -208,7 -211,7 +211,7 @@@ static void s3c24xx_i2c_message_start(s
        if (msg->flags & I2C_M_REV_DIR_ADDR)
                addr ^= 1;
  
 -      /* todo - check for wether ack wanted or not */
 +      /* todo - check for whether ack wanted or not */
        s3c24xx_i2c_enable_ack(i2c);
  
        iiccon = readl(i2c->regs + S3C2410_IICCON);
@@@ -235,8 -238,47 +238,47 @@@ static inline void s3c24xx_i2c_stop(str
  
        dev_dbg(i2c->dev, "STOP\n");
  
-       /* stop the transfer */
-       iicstat &= ~S3C2410_IICSTAT_START;
+       /*
+        * The datasheet says that the STOP sequence should be:
+        *  1) I2CSTAT.5 = 0    - Clear BUSY (or 'generate STOP')
+        *  2) I2CCON.4 = 0     - Clear IRQPEND
+        *  3) Wait until the stop condition takes effect.
+        *  4*) I2CSTAT.4 = 0   - Clear TXRXEN
+        *
+        * Where, step "4*" is only for buses with the "HDMIPHY" quirk.
+        *
+        * However, after much experimentation, it appears that:
+        * a) normal buses automatically clear BUSY and transition from
+        *    Master->Slave when they complete generating a STOP condition.
+        *    Therefore, step (3) can be done in doxfer() by polling I2CCON.4
+        *    after starting the STOP generation here.
+        * b) HDMIPHY bus does neither, so there is no way to do step 3.
+        *    There is no indication when this bus has finished generating
+        *    STOP.
+        *
+        * In fact, we have found that as soon as the IRQPEND bit is cleared in
+        * step 2, the HDMIPHY bus generates the STOP condition, and then
+        * immediately starts transferring another data byte, even though the
+        * bus is supposedly stopped.  This is presumably because the bus is
+        * still in "Master" mode, and its BUSY bit is still set.
+        *
+        * To avoid these extra post-STOP transactions on HDMI phy devices, we
+        * just disable Serial Output on the bus (I2CSTAT.4 = 0) directly,
+        * instead of first generating a proper STOP condition.  This should
+        * float SDA & SCK terminating the transfer.  Subsequent transfers
+        *  start with a proper START condition, and proceed normally.
+        *
+        * The HDMIPHY bus is an internal bus that always has exactly two
+        * devices, the host as Master and the HDMIPHY device as the slave.
+        * Skipping the STOP condition has been tested on this bus and works.
+        */
+       if (i2c->quirks & QUIRK_HDMIPHY) {
+               /* Stop driving the I2C pins */
+               iicstat &= ~S3C2410_IICSTAT_TXRXEN;
+       } else {
+               /* stop the transfer */
+               iicstat &= ~S3C2410_IICSTAT_START;
+       }
        writel(iicstat, i2c->regs + S3C2410_IICSTAT);
  
        i2c->state = STATE_STOP;
@@@ -397,7 -439,7 +439,7 @@@ static int i2c_s3c_irq_nextbyte(struct 
  
        case STATE_READ:
                /* we have a byte of data in the data register, do
 -               * something with it, and then work out wether we are
 +               * something with it, and then work out whether we are
                 * going to do any more read/write
                 */
  
@@@ -490,13 -532,6 +532,6 @@@ static int s3c24xx_i2c_set_master(struc
        unsigned long iicstat;
        int timeout = 400;
  
-       /* the timeout for HDMIPHY is reduced to 10 ms because
-        * the hangup is expected to happen, so waiting 400 ms
-        * causes only unnecessary system hangup
-        */
-       if (i2c->quirks & QUIRK_HDMIPHY)
-               timeout = 10;
        while (timeout-- > 0) {
                iicstat = readl(i2c->regs + S3C2410_IICSTAT);
  
                msleep(1);
        }
  
-       /* hang-up of bus dedicated for HDMIPHY occurred, resetting */
-       if (i2c->quirks & QUIRK_HDMIPHY) {
-               writel(0, i2c->regs + S3C2410_IICCON);
-               writel(0, i2c->regs + S3C2410_IICSTAT);
-               writel(0, i2c->regs + S3C2410_IICDS);
+       return -ETIMEDOUT;
+ }
  
-               return 0;
+ /* s3c24xx_i2c_wait_idle
+  *
+  * wait for the i2c bus to become idle.
+ */
+ static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
+ {
+       unsigned long iicstat;
+       ktime_t start, now;
+       unsigned long delay;
+       int spins;
+       /* ensure the stop has been through the bus */
+       dev_dbg(i2c->dev, "waiting for bus idle\n");
+       start = now = ktime_get();
+       /*
+        * Most of the time, the bus is already idle within a few usec of the
+        * end of a transaction.  However, really slow i2c devices can stretch
+        * the clock, delaying STOP generation.
+        *
+        * On slower SoCs this typically happens within a very small number of
+        * instructions so busy wait briefly to avoid scheduling overhead.
+        */
+       spins = 3;
+       iicstat = readl(i2c->regs + S3C2410_IICSTAT);
+       while ((iicstat & S3C2410_IICSTAT_START) && --spins) {
+               cpu_relax();
+               iicstat = readl(i2c->regs + S3C2410_IICSTAT);
        }
  
-       return -ETIMEDOUT;
+       /*
+        * If we do get an appreciable delay as a compromise between idle
+        * detection latency for the normal, fast case, and system load in the
+        * slow device case, use an exponential back off in the polling loop,
+        * up to 1/10th of the total timeout, then continue to poll at a
+        * constant rate up to the timeout.
+        */
+       delay = 1;
+       while ((iicstat & S3C2410_IICSTAT_START) &&
+              ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) {
+               usleep_range(delay, 2 * delay);
+               if (delay < S3C2410_IDLE_TIMEOUT / 10)
+                       delay <<= 1;
+               now = ktime_get();
+               iicstat = readl(i2c->regs + S3C2410_IICSTAT);
+       }
+       if (iicstat & S3C2410_IICSTAT_START)
+               dev_warn(i2c->dev, "timeout waiting for bus idle\n");
  }
  
  /* s3c24xx_i2c_doxfer
  static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
                              struct i2c_msg *msgs, int num)
  {
-       unsigned long iicstat, timeout;
-       int spins = 20;
+       unsigned long timeout;
        int ret;
  
        if (i2c->suspended)
                goto out;
        }
  
-       spin_lock_irq(&i2c->lock);
        i2c->msg     = msgs;
        i2c->msg_num = num;
        i2c->msg_ptr = 0;
  
        s3c24xx_i2c_enable_irq(i2c);
        s3c24xx_i2c_message_start(i2c, msgs);
-       spin_unlock_irq(&i2c->lock);
  
        timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
  
        else if (ret != num)
                dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
  
-       /* ensure the stop has been through the bus */
-       dev_dbg(i2c->dev, "waiting for bus idle\n");
-       /* first, try busy waiting briefly */
-       do {
-               cpu_relax();
-               iicstat = readl(i2c->regs + S3C2410_IICSTAT);
-       } while ((iicstat & S3C2410_IICSTAT_START) && --spins);
-       /* if that timed out sleep */
-       if (!spins) {
-               msleep(1);
-               iicstat = readl(i2c->regs + S3C2410_IICSTAT);
-       }
+       /* For QUIRK_HDMIPHY, bus is already disabled */
+       if (i2c->quirks & QUIRK_HDMIPHY)
+               goto out;
  
-       if (iicstat & S3C2410_IICSTAT_START)
-               dev_warn(i2c->dev, "timeout waiting for bus idle\n");
+       s3c24xx_i2c_wait_idle(i2c);
  
   out:
        return ret;
@@@ -740,7 -803,6 +803,6 @@@ static int s3c24xx_i2c_cpufreq_transiti
                                          unsigned long val, void *data)
  {
        struct s3c24xx_i2c *i2c = freq_to_i2c(nb);
-       unsigned long flags;
        unsigned int got;
        int delta_f;
        int ret;
  
        if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
            (val == CPUFREQ_PRECHANGE && delta_f > 0)) {
-               spin_lock_irqsave(&i2c->lock, flags);
+               i2c_lock_adapter(&i2c->adap);
                ret = s3c24xx_i2c_clockrate(i2c, &got);
-               spin_unlock_irqrestore(&i2c->lock, flags);
+               i2c_unlock_adapter(&i2c->adap);
  
                if (ret < 0)
                        dev_err(i2c->dev, "cannot find frequency\n");
@@@ -858,14 -920,6 +920,6 @@@ static int s3c24xx_i2c_init(struct s3c2
  
        pdata = i2c->pdata;
  
-       /* inititalise the gpio */
-       if (pdata->cfg_gpio)
-               pdata->cfg_gpio(to_platform_device(i2c->dev));
-       else
-               if (s3c24xx_i2c_parse_dt_gpio(i2c))
-                       return -EINVAL;
        /* write slave address */
  
        writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
@@@ -963,7 -1017,6 +1017,6 @@@ static int s3c24xx_i2c_probe(struct pla
        i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        i2c->tx_setup     = 50;
  
-       spin_lock_init(&i2c->lock);
        init_waitqueue_head(&i2c->wait);
  
        /* find the clock and enable it */
                goto err_clk;
        }
  
-       i2c->ioarea = request_mem_region(res->start, resource_size(res),
-                                        pdev->name);
-       if (i2c->ioarea == NULL) {
-               dev_err(&pdev->dev, "cannot request IO\n");
-               ret = -ENXIO;
-               goto err_clk;
-       }
-       i2c->regs = ioremap(res->start, resource_size(res));
+       i2c->regs = devm_request_and_ioremap(&pdev->dev, res);
  
        if (i2c->regs == NULL) {
                dev_err(&pdev->dev, "cannot map IO\n");
                ret = -ENXIO;
-               goto err_ioarea;
+               goto err_clk;
        }
  
-       dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
-               i2c->regs, i2c->ioarea, res);
+       dev_dbg(&pdev->dev, "registers %p (%p)\n",
+               i2c->regs, res);
  
        /* setup info block for the i2c core */
  
        i2c->adap.algo_data = i2c;
        i2c->adap.dev.parent = &pdev->dev;
  
+       i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev);
+       /* inititalise the i2c gpio lines */
+       if (i2c->pdata->cfg_gpio) {
+               i2c->pdata->cfg_gpio(to_platform_device(i2c->dev));
+       } else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) {
+               ret = -EINVAL;
+               goto err_clk;
+       }
        /* initialise the i2c controller */
  
        ret = s3c24xx_i2c_init(i2c);
        if (ret != 0)
-               goto err_iomap;
+               goto err_clk;
  
        /* find the IRQ for this unit (note, this relies on the init call to
         * ensure no current IRQs pending
        i2c->irq = ret = platform_get_irq(pdev, 0);
        if (ret <= 0) {
                dev_err(&pdev->dev, "cannot find IRQ\n");
-               goto err_iomap;
+               goto err_clk;
        }
  
        ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
  
        if (ret != 0) {
                dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
-               goto err_iomap;
+               goto err_clk;
        }
  
        ret = s3c24xx_i2c_register_cpufreq(i2c);
   err_irq:
        free_irq(i2c->irq, i2c);
  
-  err_iomap:
-       iounmap(i2c->regs);
-  err_ioarea:
-       release_resource(i2c->ioarea);
-       kfree(i2c->ioarea);
   err_clk:
        clk_disable_unprepare(i2c->clk);
        clk_put(i2c->clk);
@@@ -1110,16 -1158,13 +1158,13 @@@ static int s3c24xx_i2c_remove(struct pl
        clk_disable_unprepare(i2c->clk);
        clk_put(i2c->clk);
  
-       iounmap(i2c->regs);
-       release_resource(i2c->ioarea);
-       s3c24xx_i2c_dt_gpio_free(i2c);
-       kfree(i2c->ioarea);
+       if (pdev->dev.of_node && IS_ERR(i2c->pctrl))
+               s3c24xx_i2c_dt_gpio_free(i2c);
  
        return 0;
  }
  
- #ifdef CONFIG_PM
+ #ifdef CONFIG_PM_SLEEP
  static int s3c24xx_i2c_suspend_noirq(struct device *dev)
  {
        struct platform_device *pdev = to_platform_device(dev);
@@@ -1142,10 -1187,14 +1187,14 @@@ static int s3c24xx_i2c_resume(struct de
  
        return 0;
  }
+ #endif
  
+ #ifdef CONFIG_PM
  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,
+ #endif
  };
  
  #define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)