Merge branch 'for-next' of git://git.infradead.org/users/sameo/mfd-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Nov 2011 16:40:51 +0000 (09:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 3 Nov 2011 16:40:51 +0000 (09:40 -0700)
* 'for-next' of git://git.infradead.org/users/sameo/mfd-2.6: (80 commits)
  mfd: Fix missing abx500 header file updates
  mfd: Add missing <linux/io.h> include to intel_msic
  x86, mrst: add platform support for MSIC MFD driver
  mfd: Expose TurnOnStatus in ab8500 sysfs
  mfd: Remove support for early drop ab8500 chip
  mfd: Add support for ab8500 v3.3
  mfd: Add ab8500 interrupt disable hook
  mfd: Convert db8500-prcmu panic() into pr_crit()
  mfd: Refactor db8500-prcmu request_clock() function
  mfd: Rename db8500-prcmu init function
  mfd: Fix db5500-prcmu defines
  mfd: db8500-prcmu voltage domain consumers additions
  mfd: db8500-prcmu reset code retrieval
  mfd: db8500-prcmu tweak for modem wakeup
  mfd: Add db8500-pcmu watchdog accessor functions for watchdog
  mfd: hwacc power state db8500-prcmu accessor
  mfd: Add db8500-prcmu accessors for PLL and SGA clock
  mfd: Move to the new db500 PRCMU API
  mfd: Create a common interface for dbx500 PRCMU drivers
  mfd: Initialize DB8500 PRCMU regs
  ...

Fix up trivial conflicts in
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-u300/include/mach/irqs.h
drivers/mfd/wm831x-spi.c

74 files changed:
arch/arm/mach-imx/mach-mx27_3ds.c
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31lite.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-pcm038.c
arch/arm/mach-mx5/mx51_efika.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-u300/i2c.c
arch/arm/mach-u300/include/mach/irqs.h
arch/arm/mach-ux500/board-u5500.c
arch/arm/mach-ux500/cpu.c
arch/x86/include/asm/intel_scu_ipc.h
arch/x86/platform/mrst/mrst.c
drivers/cpufreq/db8500-cpufreq.c
drivers/gpio/Kconfig
drivers/hwmon/mc13783-adc.c
drivers/i2c/busses/Kconfig
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/mc13783-pwrbutton.c [new file with mode: 0644]
drivers/input/touchscreen/mc13783_ts.c
drivers/leds/leds-asic3.c
drivers/leds/leds-mc13783.c
drivers/media/radio/Kconfig
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/aat2870-core.c
drivers/mfd/ab3100-core.c
drivers/mfd/ab3550-core.c [deleted file]
drivers/mfd/ab5500-core.c [new file with mode: 0644]
drivers/mfd/ab5500-core.h [new file with mode: 0644]
drivers/mfd/ab5500-debugfs.c [new file with mode: 0644]
drivers/mfd/ab5500-debugfs.h [new file with mode: 0644]
drivers/mfd/ab8500-core.c
drivers/mfd/ab8500-gpadc.c
drivers/mfd/asic3.c
drivers/mfd/da903x.c
drivers/mfd/db5500-prcmu.c
drivers/mfd/db8500-prcmu-regs.h [deleted file]
drivers/mfd/db8500-prcmu.c
drivers/mfd/dbx500-prcmu-regs.h [moved from drivers/mfd/db5500-prcmu-regs.h with 51% similarity]
drivers/mfd/intel_msic.c [new file with mode: 0644]
drivers/mfd/jz4740-adc.c
drivers/mfd/max8997.c
drivers/mfd/mc13xxx-core.c
drivers/mfd/menelaus.c
drivers/mfd/pcf50633-core.c
drivers/mfd/tc3589x.c
drivers/mfd/timberdale.c
drivers/mfd/tps65912-core.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-irq.c
drivers/mfd/twl4030-madc.c
drivers/mfd/twl6030-irq.c
drivers/mfd/wm831x-irq.c
drivers/mfd/wm8994-core.c
drivers/regulator/db8500-prcmu.c
drivers/regulator/mc13783-regulator.c
include/linux/i2c/twl4030-madc.h
include/linux/mfd/ab5500/ab5500.h [new file with mode: 0644]
include/linux/mfd/ab8500/gpadc.h
include/linux/mfd/abx500.h
include/linux/mfd/db5500-prcmu.h
include/linux/mfd/db8500-prcmu.h
include/linux/mfd/dbx500-prcmu.h [new file with mode: 0644]
include/linux/mfd/intel_msic.h [new file with mode: 0644]
include/linux/mfd/max8997-private.h
include/linux/mfd/mc13783.h
include/linux/mfd/mc13xxx.h
include/linux/mfd/pcf50633/core.h
include/linux/mfd/wm831x/core.h
include/linux/mfd/wm8994/core.h
include/linux/mfd/wm8994/pdata.h

index cfa8417..ba232d7 100644 (file)
@@ -293,8 +293,7 @@ static struct mc13xxx_platform_data mc13783_pdata = {
                .num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
 
        },
-       .flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN |
-       MC13783_USE_RTC,
+       .flags  = MC13XXX_USE_TOUCHSCREEN | MC13XXX_USE_RTC,
 };
 
 /* SPI */
index 60f1fda..b8c54b8 100644 (file)
@@ -492,7 +492,7 @@ static struct mc13xxx_platform_data mc13783_pdata = {
                .regulators = mx31_3ds_regulators,
                .num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
        },
-       .flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
+       .flags  = MC13XXX_USE_TOUCHSCREEN,
 };
 
 /* SPI */
index c97c26d..05f1c71 100644 (file)
@@ -112,8 +112,7 @@ static const struct spi_imx_master spi1_pdata __initconst = {
 };
 
 static struct mc13xxx_platform_data mc13783_pdata __initdata = {
-       .flags  = MC13XXX_USE_RTC |
-                 MC13XXX_USE_REGULATOR,
+       .flags = MC13XXX_USE_RTC,
 };
 
 static struct spi_board_info mc13783_spi_dev __initdata = {
index fff7791..07034f4 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/input.h>
 
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -225,7 +226,7 @@ static struct mc13xxx_regulator_init_data moboard_regulators[] = {
        },
 };
 
-static struct mc13783_led_platform_data moboard_led[] = {
+static struct mc13xxx_led_platform_data moboard_led[] = {
        {
                .id = MC13783_LED_R1,
                .name = "coreboard-led-4:red",
@@ -258,7 +259,7 @@ static struct mc13783_led_platform_data moboard_led[] = {
        },
 };
 
-static struct mc13783_leds_platform_data moboard_leds = {
+static struct mc13xxx_leds_platform_data moboard_leds = {
        .num_leds = ARRAY_SIZE(moboard_led),
        .led = moboard_led,
        .flags = MC13783_LED_SLEWLIMTC,
@@ -267,14 +268,20 @@ static struct mc13783_leds_platform_data moboard_leds = {
        .tc2_period = MC13783_LED_PERIOD_10MS,
 };
 
+static struct mc13xxx_buttons_platform_data moboard_buttons = {
+       .b1on_flags = MC13783_BUTTON_DBNC_750MS | MC13783_BUTTON_ENABLE |
+                       MC13783_BUTTON_POL_INVERT,
+       .b1on_key = KEY_POWER,
+};
+
 static struct mc13xxx_platform_data moboard_pmic = {
        .regulators = {
                .regulators = moboard_regulators,
                .num_regulators = ARRAY_SIZE(moboard_regulators),
        },
        .leds = &moboard_leds,
-       .flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
-               MC13XXX_USE_ADC | MC13XXX_USE_LED,
+       .buttons = &moboard_buttons,
+       .flags = MC13XXX_USE_RTC | MC13XXX_USE_ADC,
 };
 
 static struct spi_board_info moboard_spi_board_info[] __initdata = {
index 100bc73..a17e9c7 100644 (file)
@@ -268,8 +268,7 @@ static struct mc13xxx_platform_data pcm038_pmic = {
                .regulators = pcm038_regulators,
                .num_regulators = ARRAY_SIZE(pcm038_regulators),
        },
-       .flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
-                MC13783_USE_TOUCHSCREEN,
+       .flags = MC13XXX_USE_ADC | MC13XXX_USE_TOUCHSCREEN,
 };
 
 static struct spi_board_info pcm038_spi_board_info[] __initdata = {
index b004e17..ec6ca91 100644 (file)
@@ -565,7 +565,7 @@ static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
 };
 
 static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
-       .flags = MC13XXX_USE_RTC | MC13XXX_USE_REGULATOR,
+       .flags = MC13XXX_USE_RTC,
        .regulators = {
                .num_regulators = ARRAY_SIZE(mx51_efika_regulators),
                .regulators = mx51_efika_regulators,
index 497e9dc..5034147 100644 (file)
@@ -14,7 +14,6 @@ config ARCH_OMAP2PLUS_TYPICAL
        select SERIAL_OMAP_CONSOLE
        select I2C
        select I2C_OMAP
-       select MFD_SUPPORT
        select MENELAUS if ARCH_OMAP2
        select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
        select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
index 70261bc..4a71cb7 100644 (file)
@@ -378,7 +378,8 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
 static int __init omap3_beagle_i2c_init(void)
 {
        omap3_pmic_get_config(&beagle_twldata,
-                       TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_AUDIO,
+                       TWL_COMMON_PDATA_USB | TWL_COMMON_PDATA_MADC |
+                       TWL_COMMON_PDATA_AUDIO,
                        TWL_COMMON_REGULATOR_VDAC | TWL_COMMON_REGULATOR_VPLL2);
 
        beagle_twldata.vpll2->constraints.name = "VDVI";
@@ -444,9 +445,15 @@ static struct platform_device keys_gpio = {
        },
 };
 
+static struct platform_device madc_hwmon = {
+       .name   = "twl4030_madc_hwmon",
+       .id     = -1,
+};
+
 static struct platform_device *omap3_beagle_devices[] __initdata = {
        &leds_gpio,
        &keys_gpio,
+       &madc_hwmon,
 };
 
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
index f0394ba..5140dee 100644 (file)
@@ -256,57 +256,8 @@ static struct ab3100_platform_data ab3100_plf_data = {
 };
 #endif
 
-#ifdef CONFIG_AB3550_CORE
-static struct abx500_init_settings ab3550_init_settings[] = {
-       {
-               .bank = 0,
-               .reg = AB3550_IMR1,
-               .setting = 0xff
-       },
-       {
-               .bank = 0,
-               .reg = AB3550_IMR2,
-               .setting = 0xff
-       },
-       {
-               .bank = 0,
-               .reg = AB3550_IMR3,
-               .setting = 0xff
-       },
-       {
-               .bank = 0,
-               .reg = AB3550_IMR4,
-               .setting = 0xff
-       },
-       {
-               .bank = 0,
-               .reg = AB3550_IMR5,
-               /* The two most significant bits are not used */
-               .setting = 0x3f
-       },
-};
-
-static struct ab3550_platform_data ab3550_plf_data = {
-       .irq = {
-               .base = IRQ_AB3550_BASE,
-               .count = (IRQ_AB3550_END - IRQ_AB3550_BASE + 1),
-       },
-       .dev_data = {
-       },
-       .init_settings = ab3550_init_settings,
-       .init_settings_sz = ARRAY_SIZE(ab3550_init_settings),
-};
-#endif
-
 static struct i2c_board_info __initdata bus0_i2c_board_info[] = {
-#if defined(CONFIG_AB3550_CORE)
-       {
-               .type = "ab3550",
-               .addr = 0x4A,
-               .irq = IRQ_U300_IRQ0_EXT,
-               .platform_data = &ab3550_plf_data,
-       },
-#elif defined(CONFIG_AB3100_CORE)
+#ifdef CONFIG_AB3100_CORE
        {
                .type = "ab3100",
                .addr = 0x48,
index d270fea..db3fbfa 100644 (file)
 #define IRQ_U300_GPIO_END              (U300_VIC_IRQS_END)
 #endif
 
-/* Optional AB3550 mixsig chip */
-#ifdef CONFIG_AB3550_CORE
-#define IRQ_AB3550_BASE                        (IRQ_U300_GPIO_END)
-#define IRQ_AB3550_END                 (IRQ_AB3550_BASE + 38)
-#else
-#define IRQ_AB3550_END                 (IRQ_U300_GPIO_END)
-#endif
-
-#define NR_IRQS                                (IRQ_AB3550_END)
+#define NR_IRQS                                (IRQ_U300_GPIO_END)
 
 #endif
index e014aa7..82025ba 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/amba/bus.h>
 #include <linux/irq.h>
 #include <linux/i2c.h>
+#include <linux/mfd/ab5500/ab5500.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -87,7 +88,6 @@ static struct lm3530_platform_data u5500_als_platform_data = {
        .brt_val = 0x7F,        /* Max brightness */
 };
 
-
 static struct i2c_board_info __initdata u5500_i2c2_devices[] = {
        {
                /* Backlight */
@@ -101,6 +101,30 @@ static void __init u5500_i2c_init(void)
        db5500_add_i2c2(&u5500_i2c2_data);
        i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices));
 }
+
+static struct ab5500_platform_data ab5500_plf_data = {
+       .irq = {
+               .base = 0,
+               .count = 0,
+       },
+       .init_settings = NULL,
+       .init_settings_sz = 0,
+       .pm_power_off = false,
+};
+
+static struct platform_device ab5500_device = {
+       .name = "ab5500-core",
+       .id = 0,
+       .dev = {
+               .platform_data = &ab5500_plf_data,
+       },
+       .num_resources = 0,
+};
+
+static struct platform_device *u5500_platform_devices[] __initdata = {
+       &ab5500_device,
+};
+
 static void __init u5500_uart_init(void)
 {
        db5500_add_uart0(NULL);
@@ -115,6 +139,9 @@ static void __init u5500_init_machine(void)
        u5500_i2c_init();
        u5500_sdi_init();
        u5500_uart_init();
+
+       platform_add_devices(u5500_platform_devices,
+               ARRAY_SIZE(u5500_platform_devices));
 }
 
 MACHINE_START(U5500, "ST-Ericsson U5500 Platform")
index 1405d0e..f418574 100644 (file)
@@ -47,6 +47,6 @@ void __init ux500_init_irq(void)
        if (cpu_is_u5500())
                db5500_prcmu_early_init();
        if (cpu_is_u8500())
-               prcmu_early_init();
+               db8500_prcmu_early_init();
        clk_init();
 }
index 29f6679..4420993 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _ASM_X86_INTEL_SCU_IPC_H_
 #define  _ASM_X86_INTEL_SCU_IPC_H_
 
+#include <linux/notifier.h>
+
 #define IPCMSG_VRTC    0xFA     /* Set vRTC device */
 
 /* Command id associated with message IPCMSG_VRTC */
@@ -44,4 +46,24 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data);
 /* Update FW version */
 int intel_scu_ipc_fw_update(u8 *buffer, u32 length);
 
+extern struct blocking_notifier_head intel_scu_notifier;
+
+static inline void intel_scu_notifier_add(struct notifier_block *nb)
+{
+       blocking_notifier_chain_register(&intel_scu_notifier, nb);
+}
+
+static inline void intel_scu_notifier_remove(struct notifier_block *nb)
+{
+       blocking_notifier_chain_unregister(&intel_scu_notifier, nb);
+}
+
+static inline int intel_scu_notifier_post(unsigned long v, void *p)
+{
+       return blocking_notifier_call_chain(&intel_scu_notifier, v, p);
+}
+
+#define                SCU_AVAILABLE           1
+#define                SCU_DOWN                2
+
 #endif
index e637952..6ed7afd 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/platform_device.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/mfd/intel_msic.h>
 
 #include <asm/setup.h>
 #include <asm/mpspec_def.h>
@@ -483,6 +485,128 @@ static void __init *no_platform_data(void *info)
        return NULL;
 }
 
+static struct resource msic_resources[] = {
+       {
+               .start  = INTEL_MSIC_IRQ_PHYS_BASE,
+               .end    = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct intel_msic_platform_data msic_pdata;
+
+static struct platform_device msic_device = {
+       .name           = "intel_msic",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &msic_pdata,
+       },
+       .num_resources  = ARRAY_SIZE(msic_resources),
+       .resource       = msic_resources,
+};
+
+static inline bool mrst_has_msic(void)
+{
+       return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
+}
+
+static int msic_scu_status_change(struct notifier_block *nb,
+                                 unsigned long code, void *data)
+{
+       if (code == SCU_DOWN) {
+               platform_device_unregister(&msic_device);
+               return 0;
+       }
+
+       return platform_device_register(&msic_device);
+}
+
+static int __init msic_init(void)
+{
+       static struct notifier_block msic_scu_notifier = {
+               .notifier_call  = msic_scu_status_change,
+       };
+
+       /*
+        * We need to be sure that the SCU IPC is ready before MSIC device
+        * can be registered.
+        */
+       if (mrst_has_msic())
+               intel_scu_notifier_add(&msic_scu_notifier);
+
+       return 0;
+}
+arch_initcall(msic_init);
+
+/*
+ * msic_generic_platform_data - sets generic platform data for the block
+ * @info: pointer to the SFI device table entry for this block
+ * @block: MSIC block
+ *
+ * Function sets IRQ number from the SFI table entry for given device to
+ * the MSIC platform data.
+ */
+static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
+{
+       struct sfi_device_table_entry *entry = info;
+
+       BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
+       msic_pdata.irq[block] = entry->irq;
+
+       return no_platform_data(info);
+}
+
+static void *msic_battery_platform_data(void *info)
+{
+       return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
+}
+
+static void *msic_gpio_platform_data(void *info)
+{
+       static struct intel_msic_gpio_pdata pdata;
+       int gpio = get_gpio_by_name("msic_gpio_base");
+
+       if (gpio < 0)
+               return NULL;
+
+       pdata.gpio_base = gpio;
+       msic_pdata.gpio = &pdata;
+
+       return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
+}
+
+static void *msic_audio_platform_data(void *info)
+{
+       struct platform_device *pdev;
+
+       pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
+       if (IS_ERR(pdev)) {
+               pr_err("failed to create audio platform device\n");
+               return NULL;
+       }
+
+       return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
+}
+
+static void *msic_power_btn_platform_data(void *info)
+{
+       return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
+}
+
+static void *msic_ocd_platform_data(void *info)
+{
+       static struct intel_msic_ocd_pdata pdata;
+       int gpio = get_gpio_by_name("ocd_gpio");
+
+       if (gpio < 0)
+               return NULL;
+
+       pdata.gpio = gpio;
+       msic_pdata.ocd = &pdata;
+
+       return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
+}
+
 static const struct devs_id __initconst device_ids[] = {
        {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
        {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
@@ -491,7 +615,14 @@ static const struct devs_id __initconst device_ids[] = {
        {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
        {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
        {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
-       {"msic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
+
+       /* MSIC subdevices */
+       {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
+       {"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
+       {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
+       {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
+       {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
+
        {},
 };
 
@@ -558,6 +689,9 @@ static void __init intel_scu_i2c_device_register(int bus,
        i2c_devs[i2c_next_dev++] = new_dev;
 }
 
+BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
+EXPORT_SYMBOL_GPL(intel_scu_notifier);
+
 /* Called by IPC driver */
 void intel_scu_devices_create(void)
 {
@@ -582,6 +716,7 @@ void intel_scu_devices_create(void)
                } else
                        i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
        }
+       intel_scu_notifier_post(SCU_AVAILABLE, 0L);
 }
 EXPORT_SYMBOL_GPL(intel_scu_devices_create);
 
@@ -590,6 +725,8 @@ void intel_scu_devices_destroy(void)
 {
        int i;
 
+       intel_scu_notifier_post(SCU_DOWN, 0L);
+
        for (i = 0; i < ipc_next_dev; i++)
                platform_device_del(ipc_devs[i]);
 }
@@ -606,19 +743,37 @@ static void __init install_irq_resource(struct platform_device *pdev, int irq)
        platform_device_add_resources(pdev, &res, 1);
 }
 
-static void __init sfi_handle_ipc_dev(struct platform_device *pdev)
+static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
 {
        const struct devs_id *dev = device_ids;
+       struct platform_device *pdev;
        void *pdata = NULL;
 
        while (dev->name[0]) {
                if (dev->type == SFI_DEV_TYPE_IPC &&
-                       !strncmp(dev->name, pdev->name, SFI_NAME_LEN)) {
-                       pdata = dev->get_platform_data(pdev);
+                       !strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
+                       pdata = dev->get_platform_data(entry);
                        break;
                }
                dev++;
        }
+
+       /*
+        * On Medfield the platform device creation is handled by the MSIC
+        * MFD driver so we don't need to do it here.
+        */
+       if (mrst_has_msic())
+               return;
+
+       /* ID as IRQ is a hack that will go away */
+       pdev = platform_device_alloc(entry->name, entry->irq);
+       if (pdev == NULL) {
+               pr_err("out of memory for SFI platform device '%s'.\n",
+                       entry->name);
+               return;
+       }
+       install_irq_resource(pdev, entry->irq);
+
        pdev->dev.platform_data = pdata;
        intel_scu_device_register(pdev);
 }
@@ -671,7 +826,6 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
        struct sfi_device_table_entry *pentry;
        struct spi_board_info spi_info;
        struct i2c_board_info i2c_info;
-       struct platform_device *pdev;
        int num, i, bus;
        int ioapic;
        struct io_apic_irq_attr irq_attr;
@@ -699,17 +853,9 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
 
                switch (pentry->type) {
                case SFI_DEV_TYPE_IPC:
-                       /* ID as IRQ is a hack that will go away */
-                       pdev = platform_device_alloc(pentry->name, irq);
-                       if (pdev == NULL) {
-                               pr_err("out of memory for SFI platform device '%s'.\n",
-                                                       pentry->name);
-                               continue;
-                       }
-                       install_irq_resource(pdev, irq);
                        pr_debug("info[%2d]: IPC bus, name = %16.16s, "
-                               "irq = 0x%2x\n", i, pentry->name, irq);
-                       sfi_handle_ipc_dev(pdev);
+                               "irq = 0x%2x\n", i, pentry->name, pentry->irq);
+                       sfi_handle_ipc_dev(pentry);
                        break;
                case SFI_DEV_TYPE_SPI:
                        memset(&spi_info, 0, sizeof(spi_info));
index d90456a..8e89dcf 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <mach/id.h>
 
 static struct cpufreq_frequency_table freq_table[] = {
index cb0bd07..8b3c745 100644 (file)
@@ -189,7 +189,7 @@ config GPIO_U300
 
 config GPIO_VX855
        tristate "VIA VX855/VX875 GPIO"
-       depends on MFD_SUPPORT && PCI
+       depends on PCI
        select MFD_CORE
        select MFD_VX855
        help
@@ -428,7 +428,6 @@ config GPIO_TIMBERDALE
 config GPIO_RDC321X
        tristate "RDC R-321x GPIO support"
        depends on PCI
-       select MFD_SUPPORT
        select MFD_CORE
        select MFD_RDC321X
        help
index d5226c9..ef65ab5 100644 (file)
@@ -31,7 +31,7 @@
 #define MC13783_ADC_NAME       "mc13783-adc"
 
 struct mc13783_adc_priv {
-       struct mc13783 *mc13783;
+       struct mc13xxx *mc13xxx;
        struct device *hwmon_dev;
 };
 
@@ -51,8 +51,8 @@ static int mc13783_adc_read(struct device *dev,
        unsigned int sample[4];
        int ret;
 
-       ret = mc13783_adc_do_conversion(priv->mc13783,
-                       MC13783_ADC_MODE_MULT_CHAN,
+       ret = mc13xxx_adc_do_conversion(priv->mc13xxx,
+                       MC13XXX_ADC_MODE_MULT_CHAN,
                        channel, sample);
        if (ret)
                return ret;
@@ -147,9 +147,9 @@ static const struct attribute_group mc13783_group_ts = {
 static int mc13783_adc_use_touchscreen(struct platform_device *pdev)
 {
        struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
-       unsigned flags = mc13783_get_flags(priv->mc13783);
+       unsigned flags = mc13xxx_get_flags(priv->mc13xxx);
 
-       return flags & MC13783_USE_TOUCHSCREEN;
+       return flags & MC13XXX_USE_TOUCHSCREEN;
 }
 
 static int __init mc13783_adc_probe(struct platform_device *pdev)
@@ -161,7 +161,7 @@ static int __init mc13783_adc_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+       priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
 
        platform_set_drvdata(pdev, priv);
 
index b2b8562..76f6531 100644 (file)
@@ -110,7 +110,6 @@ config I2C_I801
 config I2C_ISCH
        tristate "Intel SCH SMBus 1.0"
        depends on PCI
-       select MFD_CORE
        select LPC_SCH
        help
          Say Y here if you want to use SMBus controller on the Intel SCH
index 56aa465..22d875f 100644 (file)
@@ -134,6 +134,16 @@ config INPUT_MAX8925_ONKEY
          To compile this driver as a module, choose M here: the module
          will be called max8925_onkey.
 
+config INPUT_MC13783_PWRBUTTON
+       tristate "MC13783 ON buttons"
+       depends on MFD_MC13783
+       help
+         Support the ON buttons of MC13783 PMIC as an input device
+         reporting power button status.
+
+         To compile this driver as a module, choose M here: the module
+         will be called mc13783-pwrbutton.
+
 config INPUT_MMA8450
        tristate "MMA8450 - Freescale's 3-Axis, 8/12-bit Digital Accelerometer"
        depends on I2C
index 62dcd79..a244fc6 100644 (file)
@@ -28,6 +28,7 @@ obj-$(CONFIG_INPUT_KEYSPAN_REMOTE)    += keyspan_remote.o
 obj-$(CONFIG_INPUT_KXTJ9)              += kxtj9.o
 obj-$(CONFIG_INPUT_M68K_BEEP)          += m68kspkr.o
 obj-$(CONFIG_INPUT_MAX8925_ONKEY)      += max8925_onkey.o
+obj-$(CONFIG_INPUT_MC13783_PWRBUTTON)  += mc13783-pwrbutton.o
 obj-$(CONFIG_INPUT_MMA8450)            += mma8450.o
 obj-$(CONFIG_INPUT_MPU3050)            += mpu3050.o
 obj-$(CONFIG_INPUT_PCAP)               += pcap_keys.o
diff --git a/drivers/input/misc/mc13783-pwrbutton.c b/drivers/input/misc/mc13783-pwrbutton.c
new file mode 100644 (file)
index 0000000..09b0522
--- /dev/null
@@ -0,0 +1,282 @@
+/**
+ * Copyright (C) 2011 Philippe Rétornaz
+ *
+ * Based on twl4030-pwrbutton driver by:
+ *     Peter De Schrijver <peter.de-schrijver@nokia.com>
+ *     Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * 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.
+ *
+ * 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 Street, Suite 500, Boston, MA 02110-1335  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/mc13783.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+struct mc13783_pwrb {
+       struct input_dev *pwr;
+       struct mc13xxx *mc13783;
+#define MC13783_PWRB_B1_POL_INVERT     (1 << 0)
+#define MC13783_PWRB_B2_POL_INVERT     (1 << 1)
+#define MC13783_PWRB_B3_POL_INVERT     (1 << 2)
+       int flags;
+       unsigned short keymap[3];
+};
+
+#define MC13783_REG_INTERRUPT_SENSE_1          5
+#define MC13783_IRQSENSE1_ONOFD1S              (1 << 3)
+#define MC13783_IRQSENSE1_ONOFD2S              (1 << 4)
+#define MC13783_IRQSENSE1_ONOFD3S              (1 << 5)
+
+#define MC13783_REG_POWER_CONTROL_2            15
+#define MC13783_POWER_CONTROL_2_ON1BDBNC       4
+#define MC13783_POWER_CONTROL_2_ON2BDBNC       6
+#define MC13783_POWER_CONTROL_2_ON3BDBNC       8
+#define MC13783_POWER_CONTROL_2_ON1BRSTEN      (1 << 1)
+#define MC13783_POWER_CONTROL_2_ON2BRSTEN      (1 << 2)
+#define MC13783_POWER_CONTROL_2_ON3BRSTEN      (1 << 3)
+
+static irqreturn_t button_irq(int irq, void *_priv)
+{
+       struct mc13783_pwrb *priv = _priv;
+       int val;
+
+       mc13xxx_irq_ack(priv->mc13783, irq);
+       mc13xxx_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_SENSE_1, &val);
+
+       switch (irq) {
+       case MC13783_IRQ_ONOFD1:
+               val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0;
+               if (priv->flags & MC13783_PWRB_B1_POL_INVERT)
+                       val ^= 1;
+               input_report_key(priv->pwr, priv->keymap[0], val);
+               break;
+
+       case MC13783_IRQ_ONOFD2:
+               val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0;
+               if (priv->flags & MC13783_PWRB_B2_POL_INVERT)
+                       val ^= 1;
+               input_report_key(priv->pwr, priv->keymap[1], val);
+               break;
+
+       case MC13783_IRQ_ONOFD3:
+               val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0;
+               if (priv->flags & MC13783_PWRB_B3_POL_INVERT)
+                       val ^= 1;
+               input_report_key(priv->pwr, priv->keymap[2], val);
+               break;
+       }
+
+       input_sync(priv->pwr);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit mc13783_pwrbutton_probe(struct platform_device *pdev)
+{
+       const struct mc13xxx_buttons_platform_data *pdata;
+       struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
+       struct input_dev *pwr;
+       struct mc13783_pwrb *priv;
+       int err = 0;
+       int reg = 0;
+
+       pdata = dev_get_platdata(&pdev->dev);
+       if (!pdata) {
+               dev_err(&pdev->dev, "missing platform data\n");
+               return -ENODEV;
+       }
+
+       pwr = input_allocate_device();
+       if (!pwr) {
+               dev_dbg(&pdev->dev, "Can't allocate power button\n");
+               return -ENOMEM;
+       }
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv) {
+               err = -ENOMEM;
+               dev_dbg(&pdev->dev, "Can't allocate power button\n");
+               goto free_input_dev;
+       }
+
+       reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC;
+       reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC;
+       reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC;
+
+       priv->pwr = pwr;
+       priv->mc13783 = mc13783;
+
+       mc13xxx_lock(mc13783);
+
+       if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) {
+               priv->keymap[0] = pdata->b1on_key;
+               if (pdata->b1on_key != KEY_RESERVED)
+                       __set_bit(pdata->b1on_key, pwr->keybit);
+
+               if (pdata->b1on_flags & MC13783_BUTTON_POL_INVERT)
+                       priv->flags |= MC13783_PWRB_B1_POL_INVERT;
+
+               if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN)
+                       reg |= MC13783_POWER_CONTROL_2_ON1BRSTEN;
+
+               err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD1,
+                                         button_irq, "b1on", priv);
+               if (err) {
+                       dev_dbg(&pdev->dev, "Can't request irq\n");
+                       goto free_priv;
+               }
+       }
+
+       if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) {
+               priv->keymap[1] = pdata->b2on_key;
+               if (pdata->b2on_key != KEY_RESERVED)
+                       __set_bit(pdata->b2on_key, pwr->keybit);
+
+               if (pdata->b2on_flags & MC13783_BUTTON_POL_INVERT)
+                       priv->flags |= MC13783_PWRB_B2_POL_INVERT;
+
+               if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN)
+                       reg |= MC13783_POWER_CONTROL_2_ON2BRSTEN;
+
+               err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD2,
+                                         button_irq, "b2on", priv);
+               if (err) {
+                       dev_dbg(&pdev->dev, "Can't request irq\n");
+                       goto free_irq_b1;
+               }
+       }
+
+       if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) {
+               priv->keymap[2] = pdata->b3on_key;
+               if (pdata->b3on_key != KEY_RESERVED)
+                       __set_bit(pdata->b3on_key, pwr->keybit);
+
+               if (pdata->b3on_flags & MC13783_BUTTON_POL_INVERT)
+                       priv->flags |= MC13783_PWRB_B3_POL_INVERT;
+
+               if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN)
+                       reg |= MC13783_POWER_CONTROL_2_ON3BRSTEN;
+
+               err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD3,
+                                         button_irq, "b3on", priv);
+               if (err) {
+                       dev_dbg(&pdev->dev, "Can't request irq: %d\n", err);
+                       goto free_irq_b2;
+               }
+       }
+
+       mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg);
+
+       mc13xxx_unlock(mc13783);
+
+       pwr->name = "mc13783_pwrbutton";
+       pwr->phys = "mc13783_pwrbutton/input0";
+       pwr->dev.parent = &pdev->dev;
+
+       pwr->keycode = priv->keymap;
+       pwr->keycodemax = ARRAY_SIZE(priv->keymap);
+       pwr->keycodesize = sizeof(priv->keymap[0]);
+       __set_bit(EV_KEY, pwr->evbit);
+
+       err = input_register_device(pwr);
+       if (err) {
+               dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
+               goto free_irq;
+       }
+
+       platform_set_drvdata(pdev, priv);
+
+       return 0;
+
+free_irq:
+       mc13xxx_lock(mc13783);
+
+       if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
+               mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv);
+
+free_irq_b2:
+       if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
+               mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv);
+
+free_irq_b1:
+       if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
+               mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv);
+
+free_priv:
+       mc13xxx_unlock(mc13783);
+       kfree(priv);
+
+free_input_dev:
+       input_free_device(pwr);
+
+       return err;
+}
+
+static int __devexit mc13783_pwrbutton_remove(struct platform_device *pdev)
+{
+       struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
+       const struct mc13xxx_buttons_platform_data *pdata;
+
+       pdata = dev_get_platdata(&pdev->dev);
+
+       mc13xxx_lock(priv->mc13783);
+
+       if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
+               mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD3, priv);
+       if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
+               mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD2, priv);
+       if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
+               mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD1, priv);
+
+       mc13xxx_unlock(priv->mc13783);
+
+       input_unregister_device(priv->pwr);
+       kfree(priv);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+struct platform_driver mc13783_pwrbutton_driver = {
+       .probe          = mc13783_pwrbutton_probe,
+       .remove         = __devexit_p(mc13783_pwrbutton_remove),
+       .driver         = {
+               .name   = "mc13783-pwrbutton",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init mc13783_pwrbutton_init(void)
+{
+       return platform_driver_register(&mc13783_pwrbutton_driver);
+}
+module_init(mc13783_pwrbutton_init);
+
+static void __exit mc13783_pwrbutton_exit(void)
+{
+       platform_driver_unregister(&mc13783_pwrbutton_driver);
+}
+module_exit(mc13783_pwrbutton_exit);
+
+MODULE_ALIAS("platform:mc13783-pwrbutton");
+MODULE_DESCRIPTION("MC13783 Power Button");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Philippe Retornaz");
index c5bc62d..ede0274 100644 (file)
@@ -35,7 +35,7 @@ MODULE_PARM_DESC(sample_tolerance,
 
 struct mc13783_ts_priv {
        struct input_dev *idev;
-       struct mc13783 *mc13783;
+       struct mc13xxx *mc13xxx;
        struct delayed_work work;
        struct workqueue_struct *workq;
        unsigned int sample[4];
@@ -45,7 +45,7 @@ static irqreturn_t mc13783_ts_handler(int irq, void *data)
 {
        struct mc13783_ts_priv *priv = data;
 
-       mc13783_irq_ack(priv->mc13783, irq);
+       mc13xxx_irq_ack(priv->mc13xxx, irq);
 
        /*
         * Kick off reading coordinates. Note that if work happens already
@@ -121,10 +121,10 @@ static void mc13783_ts_work(struct work_struct *work)
 {
        struct mc13783_ts_priv *priv =
                container_of(work, struct mc13783_ts_priv, work.work);
-       unsigned int mode = MC13783_ADC_MODE_TS;
+       unsigned int mode = MC13XXX_ADC_MODE_TS;
        unsigned int channel = 12;
 
-       if (mc13783_adc_do_conversion(priv->mc13783,
+       if (mc13xxx_adc_do_conversion(priv->mc13xxx,
                                mode, channel, priv->sample) == 0)
                mc13783_ts_report_sample(priv);
 }
@@ -134,21 +134,21 @@ static int mc13783_ts_open(struct input_dev *dev)
        struct mc13783_ts_priv *priv = input_get_drvdata(dev);
        int ret;
 
-       mc13783_lock(priv->mc13783);
+       mc13xxx_lock(priv->mc13xxx);
 
-       mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS);
+       mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TS);
 
-       ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
+       ret = mc13xxx_irq_request(priv->mc13xxx, MC13XXX_IRQ_TS,
                mc13783_ts_handler, MC13783_TS_NAME, priv);
        if (ret)
                goto out;
 
-       ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
-                       MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0);
+       ret = mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+                       MC13XXX_ADC0_TSMOD_MASK, MC13XXX_ADC0_TSMOD0);
        if (ret)
-               mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
+               mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
 out:
-       mc13783_unlock(priv->mc13783);
+       mc13xxx_unlock(priv->mc13xxx);
        return ret;
 }
 
@@ -156,11 +156,11 @@ static void mc13783_ts_close(struct input_dev *dev)
 {
        struct mc13783_ts_priv *priv = input_get_drvdata(dev);
 
-       mc13783_lock(priv->mc13783);
-       mc13783_reg_rmw(priv->mc13783, MC13783_ADC0,
-                       MC13783_ADC0_TSMOD_MASK, 0);
-       mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv);
-       mc13783_unlock(priv->mc13783);
+       mc13xxx_lock(priv->mc13xxx);
+       mc13xxx_reg_rmw(priv->mc13xxx, MC13XXX_ADC0,
+                       MC13XXX_ADC0_TSMOD_MASK, 0);
+       mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TS, priv);
+       mc13xxx_unlock(priv->mc13xxx);
 
        cancel_delayed_work_sync(&priv->work);
 }
@@ -177,7 +177,7 @@ static int __init mc13783_ts_probe(struct platform_device *pdev)
                goto err_free_mem;
 
        INIT_DELAYED_WORK(&priv->work, mc13783_ts_work);
-       priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
+       priv->mc13xxx = dev_get_drvdata(pdev->dev.parent);
        priv->idev = idev;
 
        /*
index 22f847c..fbd5d88 100644 (file)
@@ -107,9 +107,10 @@ static int __devinit asic3_led_probe(struct platform_device *pdev)
        }
 
        led->cdev->name = led->name;
-       led->cdev->default_trigger = led->default_trigger;
+       led->cdev->flags = LED_CORE_SUSPENDRESUME;
        led->cdev->brightness_set = brightness_set;
        led->cdev->blink_set = blink_set;
+       led->cdev->default_trigger = led->default_trigger;
 
        ret = led_classdev_register(&pdev->dev, led->cdev);
        if (ret < 0)
@@ -136,12 +137,44 @@ static int __devexit asic3_led_remove(struct platform_device *pdev)
        return mfd_cell_disable(pdev);
 }
 
+static int asic3_led_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       const struct mfd_cell *cell = mfd_get_cell(pdev);
+       int ret;
+
+       ret = 0;
+       if (cell->suspend)
+               ret = (*cell->suspend)(pdev);
+
+       return ret;
+}
+
+static int asic3_led_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       const struct mfd_cell *cell = mfd_get_cell(pdev);
+       int ret;
+
+       ret = 0;
+       if (cell->resume)
+               ret = (*cell->resume)(pdev);
+
+       return ret;
+}
+
+static const struct dev_pm_ops asic3_led_pm_ops = {
+       .suspend        = asic3_led_suspend,
+       .resume         = asic3_led_resume,
+};
+
 static struct platform_driver asic3_led_driver = {
        .probe          = asic3_led_probe,
        .remove         = __devexit_p(asic3_led_remove),
        .driver         = {
                .name   = "leds-asic3",
                .owner  = THIS_MODULE,
+               .pm     = &asic3_led_pm_ops,
        },
 };
 
index f369e56..b3393a9 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <linux/workqueue.h>
-#include <linux/mfd/mc13783.h>
+#include <linux/mfd/mc13xxx.h>
 #include <linux/slab.h>
 
 struct mc13783_led {
        struct led_classdev     cdev;
        struct work_struct      work;
-       struct mc13783          *master;
+       struct mc13xxx          *master;
        enum led_brightness     new_brightness;
        int                     id;
 };
@@ -111,11 +111,11 @@ static void mc13783_led_work(struct work_struct *work)
                break;
        }
 
-       mc13783_lock(led->master);
+       mc13xxx_lock(led->master);
 
-       mc13783_reg_rmw(led->master, reg, mask, value);
+       mc13xxx_reg_rmw(led->master, reg, mask, value);
 
-       mc13783_unlock(led->master);
+       mc13xxx_unlock(led->master);
 }
 
 static void mc13783_led_set(struct led_classdev *led_cdev,
@@ -172,23 +172,23 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current)
                break;
        }
 
-       mc13783_lock(led->master);
+       mc13xxx_lock(led->master);
 
-       ret = mc13783_reg_rmw(led->master, reg, mask << shift,
+       ret = mc13xxx_reg_rmw(led->master, reg, mask << shift,
                                                value << shift);
 
-       mc13783_unlock(led->master);
+       mc13xxx_unlock(led->master);
        return ret;
 }
 
 static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
 {
-       struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
+       struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
        int ret = 0;
        int reg = 0;
 
-       mc13783_lock(dev);
+       mc13xxx_lock(dev);
 
        if (pdata->flags & MC13783_LED_TC1HALF)
                reg |= MC13783_LED_C1_TC1HALF_BIT;
@@ -196,7 +196,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
        if (pdata->flags & MC13783_LED_SLEWLIMTC)
                reg |= MC13783_LED_Cx_SLEWLIM_BIT;
 
-       ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
+       ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg);
        if (ret)
                goto out;
 
@@ -206,7 +206,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
        if (pdata->flags & MC13783_LED_SLEWLIMBL)
                reg |= MC13783_LED_Cx_SLEWLIM_BIT;
 
-       ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
+       ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg);
        if (ret)
                goto out;
 
@@ -216,7 +216,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
        if (pdata->flags & MC13783_LED_TRIODE_TC1)
                reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-       ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
+       ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg);
        if (ret)
                goto out;
 
@@ -226,7 +226,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
        if (pdata->flags & MC13783_LED_TRIODE_TC2)
                reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-       ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
+       ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg);
        if (ret)
                goto out;
 
@@ -236,7 +236,7 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
        if (pdata->flags & MC13783_LED_TRIODE_TC3)
                reg |= MC13783_LED_Cx_TRIODE_TC_BIT;
 
-       ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
+       ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg);
        if (ret)
                goto out;
 
@@ -255,17 +255,17 @@ static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
        reg |= (pdata->abref & MC13783_LED_C0_ABREF_MASK) <<
                                                        MC13783_LED_C0_ABREF;
 
-       ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
+       ret = mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg);
 
 out:
-       mc13783_unlock(dev);
+       mc13xxx_unlock(dev);
        return ret;
 }
 
 static int __devinit mc13783_led_probe(struct platform_device *pdev)
 {
-       struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       struct mc13783_led_platform_data *led_cur;
+       struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       struct mc13xxx_led_platform_data *led_cur;
        struct mc13783_led *led, *led_dat;
        int ret, i;
        int init_led = 0;
@@ -351,9 +351,9 @@ err_free:
 
 static int __devexit mc13783_led_remove(struct platform_device *pdev)
 {
-       struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct mc13783_led *led = platform_get_drvdata(pdev);
-       struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
+       struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent);
        int i;
 
        for (i = 0; i < pdata->num_leds; i++) {
@@ -361,16 +361,16 @@ static int __devexit mc13783_led_remove(struct platform_device *pdev)
                cancel_work_sync(&led[i].work);
        }
 
-       mc13783_lock(dev);
+       mc13xxx_lock(dev);
 
-       mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
-       mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
-       mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
-       mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
-       mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
-       mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
+       mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0);
+       mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0);
+       mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0);
+       mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0);
+       mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0);
+       mc13xxx_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0);
 
-       mc13783_unlock(dev);
+       mc13xxx_unlock(dev);
 
        kfree(led);
        return 0;
index 52798a1..ccd5f0d 100644 (file)
@@ -426,7 +426,6 @@ config RADIO_TIMBERDALE
 config RADIO_WL1273
        tristate "Texas Instruments WL1273 I2C FM Radio"
        depends on I2C && VIDEO_V4L2
-       select MFD_CORE
        select MFD_WL1273_CORE
        select FW_LOADER
        ---help---
index a67adcb..f1391c2 100644 (file)
@@ -2,23 +2,8 @@
 # Multifunction miscellaneous devices
 #
 
-menuconfig MFD_SUPPORT
-       bool "Multifunction device drivers"
-       depends on HAS_IOMEM
-       default y
-       help
-         Multifunction devices embed several functions (e.g. GPIOs,
-         touchscreens, keyboards, current regulators, power management chips,
-         etc...) in one single integrated circuit. They usually talk to the
-         main CPU through one or more IRQ lines and low speed data busses (SPI,
-         I2C, etc..). They appear as one single device to the main system
-         through the data bus and the MFD framework allows for sub devices
-         (a.k.a. functions) to appear as discrete platform devices.
-         MFDs are typically found on embedded platforms.
-
-         This option alone does not add any kernel code.
-
-if MFD_SUPPORT
+if HAS_IOMEM
+menu "Multifunction device drivers"
 
 config MFD_CORE
        tristate
@@ -390,6 +375,7 @@ config MFD_WM8400
        tristate "Support Wolfson Microelectronics WM8400"
        select MFD_CORE
        depends on I2C
+       select REGMAP_I2C
        help
          Support for the Wolfson Microelecronics WM8400 PMIC and audio
          CODEC.  This driver provides common support for accessing
@@ -503,6 +489,7 @@ config MFD_WM8994
 config MFD_PCF50633
        tristate "Support for NXP PCF50633"
        depends on I2C
+       select REGMAP_I2C
        help
          Say yes here if you have NXP PCF50633 chip on your board.
          This core driver provides register access and IRQ handling
@@ -579,6 +566,23 @@ config EZX_PCAP
          This enables the PCAP ASIC present on EZX Phones. This is
          needed for MMC, TouchScreen, Sound, USB, etc..
 
+config AB5500_CORE
+       bool "ST-Ericsson AB5500 Mixed Signal Power Management chip"
+       depends on ABX500_CORE && MFD_DB5500_PRCMU
+       select MFD_CORE
+       help
+         Select this option to enable access to AB5500 power management
+         chip. This connects to the db5500 chip via the I2C bus via PRCMU.
+         This chip embeds various other multimedia funtionalities as well.
+
+config AB5500_DEBUG
+       bool "Enable debug info via debugfs"
+       depends on AB5500_CORE && DEBUG_FS
+       default y if DEBUG_FS
+       help
+         Select this option if you want debug information from the AB5500
+         using the debug filesystem, debugfs.
+
 config AB8500_CORE
        bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
        depends on GENERIC_HARDIRQS && ABX500_CORE
@@ -615,20 +619,6 @@ config AB8500_GPADC
        help
          AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage
 
-config AB3550_CORE
-        bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions"
-       select MFD_CORE
-       depends on I2C=y && GENERIC_HARDIRQS && ABX500_CORE
-       help
-         Select this to enable the AB3550 Mixed Signal IC core
-         functionality. This connects to a AB3550 on the I2C bus
-         and expose a number of symbols needed for dependent devices
-         to read and write registers and subscribe to events from
-         this multi-functional IC. This is needed to use other features
-         of the AB3550 such as battery-backed RTC, charging control,
-         LEDs, vibrator, system power and temperature, power management
-         and ALSA sound.
-
 config MFD_DB8500_PRCMU
        bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
        depends on UX500_SOC_DB8500
@@ -773,7 +763,17 @@ config MFD_AAT2870_CORE
          additional drivers must be enabled in order to use the
          functionality of the device.
 
-endif # MFD_SUPPORT
+config MFD_INTEL_MSIC
+       bool "Support for Intel MSIC"
+       depends on INTEL_SCU_IPC
+       select MFD_CORE
+       help
+         Select this option to enable access to Intel MSIC (Avatele
+         Passage) chip. This chip embeds audio, battery, GPIO, etc.
+         devices used in Intel Medfield platforms.
+
+endmenu
+endif
 
 menu "Multimedia Capabilities Port drivers"
        depends on ARCH_SA1100
index c580203..b2292eb 100644 (file)
@@ -79,7 +79,8 @@ obj-$(CONFIG_PCF50633_GPIO)   += pcf50633-gpio.o
 obj-$(CONFIG_ABX500_CORE)      += abx500-core.o
 obj-$(CONFIG_AB3100_CORE)      += ab3100-core.o
 obj-$(CONFIG_AB3100_OTP)       += ab3100-otp.o
-obj-$(CONFIG_AB3550_CORE)      += ab3550-core.o
+obj-$(CONFIG_AB5500_CORE)      += ab5500-core.o
+obj-$(CONFIG_AB5500_DEBUG)     += ab5500-debugfs.o
 obj-$(CONFIG_AB8500_CORE)      += ab8500-core.o ab8500-sysctrl.o
 obj-$(CONFIG_AB8500_DEBUG)     += ab8500-debugfs.o
 obj-$(CONFIG_AB8500_GPADC)     += ab8500-gpadc.o
@@ -102,3 +103,4 @@ obj-$(CONFIG_MFD_PM8921_CORE)       += pm8921-core.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ)   += pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)      += tps65911-comparator.o
 obj-$(CONFIG_MFD_AAT2870_CORE) += aat2870-core.o
+obj-$(CONFIG_MFD_INTEL_MSIC)   += intel_msic.o
index 345dc65..02c4201 100644 (file)
@@ -295,7 +295,7 @@ static ssize_t aat2870_reg_write_file(struct file *file,
 {
        struct aat2870_data *aat2870 = file->private_data;
        char buf[32];
-       int buf_size;
+       ssize_t buf_size;
        char *start = buf;
        unsigned long addr, val;
        int ret;
index a20e1c4..4f57255 100644 (file)
@@ -809,7 +809,7 @@ struct ab_family_id {
        char    *name;
 };
 
-static const struct ab_family_id ids[] __devinitdata = {
+static const struct ab_family_id ids[] __devinitconst = {
        /* AB3100 */
        {
                .id = 0xc0,
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c
deleted file mode 100644 (file)
index 56ba194..0000000
+++ /dev/null
@@ -1,1380 +0,0 @@
-/*
- * Copyright (C) 2007-2010 ST-Ericsson
- * License terms: GNU General Public License (GPL) version 2
- * Low-level core for exclusive access to the AB3550 IC on the I2C bus
- * and some basic chip-configuration.
- * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
- * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
- * Author: Mattias Wallin <mattias.wallin@stericsson.com>
- * Author: Rickard Andersson <rickard.andersson@stericsson.com>
- */
-
-#include <linux/i2c.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
-#include <linux/random.h>
-#include <linux/workqueue.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/uaccess.h>
-#include <linux/mfd/abx500.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/mfd/core.h>
-
-#define AB3550_NAME_STRING "ab3550"
-#define AB3550_ID_FORMAT_STRING "AB3550 %s"
-#define AB3550_NUM_BANKS 2
-#define AB3550_NUM_EVENT_REG 5
-
-/* These are the only registers inside AB3550 used in this main file */
-
-/* Chip ID register */
-#define AB3550_CID_REG           0x20
-
-/* Interrupt event registers */
-#define AB3550_EVENT_BANK        0
-#define AB3550_EVENT_REG         0x22
-
-/* Read/write operation values. */
-#define AB3550_PERM_RD (0x01)
-#define AB3550_PERM_WR (0x02)
-
-/* Read/write permissions. */
-#define AB3550_PERM_RO (AB3550_PERM_RD)
-#define AB3550_PERM_RW (AB3550_PERM_RD | AB3550_PERM_WR)
-
-/**
- * struct ab3550
- * @access_mutex: lock out concurrent accesses to the AB registers
- * @i2c_client: I2C client for this chip
- * @chip_name: name of this chip variant
- * @chip_id: 8 bit chip ID for this chip variant
- * @mask_work: a worker for writing to mask registers
- * @event_lock: a lock to protect the event_mask
- * @event_mask: a local copy of the mask event registers
- * @startup_events: a copy of the first reading of the event registers
- * @startup_events_read: whether the first events have been read
- */
-struct ab3550 {
-       struct mutex access_mutex;
-       struct i2c_client *i2c_client[AB3550_NUM_BANKS];
-       char chip_name[32];
-       u8 chip_id;
-       struct work_struct mask_work;
-       spinlock_t event_lock;
-       u8 event_mask[AB3550_NUM_EVENT_REG];
-       u8 startup_events[AB3550_NUM_EVENT_REG];
-       bool startup_events_read;
-#ifdef CONFIG_DEBUG_FS
-       unsigned int debug_bank;
-       unsigned int debug_address;
-#endif
-};
-
-/**
- * struct ab3550_reg_range
- * @first: the first address of the range
- * @last: the last address of the range
- * @perm: access permissions for the range
- */
-struct ab3550_reg_range {
-       u8 first;
-       u8 last;
-       u8 perm;
-};
-
-/**
- * struct ab3550_reg_ranges
- * @count: the number of ranges in the list
- * @range: the list of register ranges
- */
-struct ab3550_reg_ranges {
-       u8 count;
-       const struct ab3550_reg_range *range;
-};
-
-/*
- * Permissible register ranges for reading and writing per device and bank.
- *
- * The ranges must be listed in increasing address order, and no overlaps are
- * allowed. It is assumed that write permission implies read permission
- * (i.e. only RO and RW permissions should be used).  Ranges with write
- * permission must not be split up.
- */
-
-#define NO_RANGE {.count = 0, .range = NULL,}
-
-static struct
-ab3550_reg_ranges ab3550_reg_ranges[AB3550_NUM_DEVICES][AB3550_NUM_BANKS] = {
-       [AB3550_DEVID_DAC] = {
-               NO_RANGE,
-               {
-                       .count = 2,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0xb0,
-                                       .last = 0xba,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                               {
-                                       .first = 0xbc,
-                                       .last = 0xc3,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       },
-               },
-       },
-       [AB3550_DEVID_LEDS] = {
-               NO_RANGE,
-               {
-                       .count = 2,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x5a,
-                                       .last = 0x88,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                               {
-                                       .first = 0x8a,
-                                       .last = 0xad,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       }
-               },
-       },
-       [AB3550_DEVID_POWER] = {
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x21,
-                                       .last = 0x21,
-                                       .perm = AB3550_PERM_RO,
-                               },
-                       }
-               },
-               NO_RANGE,
-       },
-       [AB3550_DEVID_REGULATORS] = {
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x69,
-                                       .last = 0xa3,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       }
-               },
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x14,
-                                       .last = 0x16,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       }
-               },
-       },
-       [AB3550_DEVID_SIM] = {
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x21,
-                                       .last = 0x21,
-                                       .perm = AB3550_PERM_RO,
-                               },
-                       }
-               },
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x14,
-                                       .last = 0x17,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       }
-
-               },
-       },
-       [AB3550_DEVID_UART] = {
-               NO_RANGE,
-               NO_RANGE,
-       },
-       [AB3550_DEVID_RTC] = {
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x00,
-                                       .last = 0x0c,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       }
-               },
-               NO_RANGE,
-       },
-       [AB3550_DEVID_CHARGER] = {
-               {
-                       .count = 2,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x10,
-                                       .last = 0x1a,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                               {
-                                       .first = 0x21,
-                                       .last = 0x21,
-                                       .perm = AB3550_PERM_RO,
-                               },
-                       }
-               },
-               NO_RANGE,
-       },
-       [AB3550_DEVID_ADC] = {
-               NO_RANGE,
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x20,
-                                       .last = 0x56,
-                                       .perm = AB3550_PERM_RW,
-                               },
-
-                       }
-               },
-       },
-       [AB3550_DEVID_FUELGAUGE] = {
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x21,
-                                       .last = 0x21,
-                                       .perm = AB3550_PERM_RO,
-                               },
-                       }
-               },
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x00,
-                                       .last = 0x0e,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       }
-               },
-       },
-       [AB3550_DEVID_VIBRATOR] = {
-               NO_RANGE,
-               {
-                       .count = 1,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x10,
-                                       .last = 0x13,
-                                       .perm = AB3550_PERM_RW,
-                               },
-
-                       }
-               },
-       },
-       [AB3550_DEVID_CODEC] = {
-               {
-                       .count = 2,
-                       .range = (struct ab3550_reg_range[]) {
-                               {
-                                       .first = 0x31,
-                                       .last = 0x63,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                               {
-                                       .first = 0x65,
-                                       .last = 0x68,
-                                       .perm = AB3550_PERM_RW,
-                               },
-                       }
-               },
-               NO_RANGE,
-       },
-};
-
-static struct mfd_cell ab3550_devs[AB3550_NUM_DEVICES] = {
-       [AB3550_DEVID_DAC] = {
-               .name = "ab3550-dac",
-               .id = AB3550_DEVID_DAC,
-               .num_resources = 0,
-       },
-       [AB3550_DEVID_LEDS] = {
-               .name = "ab3550-leds",
-               .id = AB3550_DEVID_LEDS,
-       },
-       [AB3550_DEVID_POWER] = {
-               .name = "ab3550-power",
-               .id = AB3550_DEVID_POWER,
-       },
-       [AB3550_DEVID_REGULATORS] = {
-               .name = "ab3550-regulators",
-               .id = AB3550_DEVID_REGULATORS,
-       },
-       [AB3550_DEVID_SIM] = {
-               .name = "ab3550-sim",
-               .id = AB3550_DEVID_SIM,
-       },
-       [AB3550_DEVID_UART] = {
-               .name = "ab3550-uart",
-               .id = AB3550_DEVID_UART,
-       },
-       [AB3550_DEVID_RTC] = {
-               .name = "ab3550-rtc",
-               .id = AB3550_DEVID_RTC,
-       },
-       [AB3550_DEVID_CHARGER] = {
-               .name = "ab3550-charger",
-               .id = AB3550_DEVID_CHARGER,
-       },
-       [AB3550_DEVID_ADC] = {
-               .name = "ab3550-adc",
-               .id = AB3550_DEVID_ADC,
-               .num_resources = 10,
-               .resources = (struct resource[]) {
-                       {
-                               .name = "TRIGGER-0",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 16,
-                               .end = 16,
-                       },
-                       {
-                               .name = "TRIGGER-1",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 17,
-                               .end = 17,
-                       },
-                       {
-                               .name = "TRIGGER-2",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 18,
-                               .end = 18,
-                       },
-                       {
-                               .name = "TRIGGER-3",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 19,
-                               .end = 19,
-                       },
-                       {
-                               .name = "TRIGGER-4",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 20,
-                               .end = 20,
-                       },
-                       {
-                               .name = "TRIGGER-5",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 21,
-                               .end = 21,
-                       },
-                       {
-                               .name = "TRIGGER-6",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 22,
-                               .end = 22,
-                       },
-                       {
-                               .name = "TRIGGER-7",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 23,
-                               .end = 23,
-                       },
-                       {
-                               .name = "TRIGGER-VBAT-TXON",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 13,
-                               .end = 13,
-                       },
-                       {
-                               .name = "TRIGGER-VBAT",
-                               .flags = IORESOURCE_IRQ,
-                               .start = 12,
-                               .end = 12,
-                       },
-               },
-       },
-       [AB3550_DEVID_FUELGAUGE] = {
-               .name = "ab3550-fuelgauge",
-               .id = AB3550_DEVID_FUELGAUGE,
-       },
-       [AB3550_DEVID_VIBRATOR] = {
-               .name = "ab3550-vibrator",
-               .id = AB3550_DEVID_VIBRATOR,
-       },
-       [AB3550_DEVID_CODEC] = {
-               .name = "ab3550-codec",
-               .id = AB3550_DEVID_CODEC,
-       },
-};
-
-/*
- * I2C transactions with error messages.
- */
-static int ab3550_i2c_master_send(struct ab3550 *ab, u8 bank, u8 *data,
-       u8 count)
-{
-       int err;
-
-       err = i2c_master_send(ab->i2c_client[bank], data, count);
-       if (err < 0) {
-               dev_err(&ab->i2c_client[0]->dev, "send error: %d\n", err);
-               return err;
-       }
-       return 0;
-}
-
-static int ab3550_i2c_master_recv(struct ab3550 *ab, u8 bank, u8 *data,
-       u8 count)
-{
-       int err;
-
-       err = i2c_master_recv(ab->i2c_client[bank], data, count);
-       if (err < 0) {
-               dev_err(&ab->i2c_client[0]->dev, "receive error: %d\n", err);
-               return err;
-       }
-       return 0;
-}
-
-/*
- * Functionality for getting/setting register values.
- */
-static int get_register_interruptible(struct ab3550 *ab, u8 bank, u8 reg,
-       u8 *value)
-{
-       int err;
-
-       err = mutex_lock_interruptible(&ab->access_mutex);
-       if (err)
-               return err;
-
-       err = ab3550_i2c_master_send(ab, bank, &reg, 1);
-       if (!err)
-               err = ab3550_i2c_master_recv(ab, bank, value, 1);
-
-       mutex_unlock(&ab->access_mutex);
-       return err;
-}
-
-static int get_register_page_interruptible(struct ab3550 *ab, u8 bank,
-       u8 first_reg, u8 *regvals, u8 numregs)
-{
-       int err;
-
-       err = mutex_lock_interruptible(&ab->access_mutex);
-       if (err)
-               return err;
-
-       err = ab3550_i2c_master_send(ab, bank, &first_reg, 1);
-       if (!err)
-               err = ab3550_i2c_master_recv(ab, bank, regvals, numregs);
-
-       mutex_unlock(&ab->access_mutex);
-       return err;
-}
-
-static int mask_and_set_register_interruptible(struct ab3550 *ab, u8 bank,
-       u8 reg, u8 bitmask, u8 bitvalues)
-{
-       int err = 0;
-
-       if (likely(bitmask)) {
-               u8 reg_bits[2] = {reg, 0};
-
-               err = mutex_lock_interruptible(&ab->access_mutex);
-               if (err)
-                       return err;
-
-               if (bitmask == 0xFF) /* No need to read in this case. */
-                       reg_bits[1] = bitvalues;
-               else { /* Read and modify the register value. */
-                       u8 bits;
-
-                       err = ab3550_i2c_master_send(ab, bank, &reg, 1);
-                       if (err)
-                               goto unlock_and_return;
-                       err = ab3550_i2c_master_recv(ab, bank, &bits, 1);
-                       if (err)
-                               goto unlock_and_return;
-                       reg_bits[1] = ((~bitmask & bits) |
-                               (bitmask & bitvalues));
-               }
-               /* Write the new value. */
-               err = ab3550_i2c_master_send(ab, bank, reg_bits, 2);
-unlock_and_return:
-               mutex_unlock(&ab->access_mutex);
-       }
-       return err;
-}
-
-/*
- * Read/write permission checking functions.
- */
-static bool page_write_allowed(const struct ab3550_reg_ranges *ranges,
-       u8 first_reg, u8 last_reg)
-{
-       u8 i;
-
-       if (last_reg < first_reg)
-               return false;
-
-       for (i = 0; i < ranges->count; i++) {
-               if (first_reg < ranges->range[i].first)
-                       break;
-               if ((last_reg <= ranges->range[i].last) &&
-                       (ranges->range[i].perm & AB3550_PERM_WR))
-                       return true;
-       }
-       return false;
-}
-
-static bool reg_write_allowed(const struct ab3550_reg_ranges *ranges, u8 reg)
-{
-       return page_write_allowed(ranges, reg, reg);
-}
-
-static bool page_read_allowed(const struct ab3550_reg_ranges *ranges,
-       u8 first_reg, u8 last_reg)
-{
-       u8 i;
-
-       if (last_reg < first_reg)
-               return false;
-       /* Find the range (if it exists in the list) that includes first_reg. */
-       for (i = 0; i < ranges->count; i++) {
-               if (first_reg < ranges->range[i].first)
-                       return false;
-               if (first_reg <= ranges->range[i].last)
-                       break;
-       }
-       /* Make sure that the entire range up to and including last_reg is
-        * readable. This may span several of the ranges in the list.
-        */
-       while ((i < ranges->count) &&
-               (ranges->range[i].perm & AB3550_PERM_RD)) {
-               if (last_reg <= ranges->range[i].last)
-                       return true;
-               if ((++i >= ranges->count) ||
-                       (ranges->range[i].first !=
-                        (ranges->range[i - 1].last + 1))) {
-                       break;
-               }
-       }
-       return false;
-}
-
-static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg)
-{
-       return page_read_allowed(ranges, reg, reg);
-}
-
-/*
- * The register access functionality.
- */
-static int ab3550_get_chip_id(struct device *dev)
-{
-       struct ab3550 *ab = dev_get_drvdata(dev->parent);
-       return (int)ab->chip_id;
-}
-
-static int ab3550_mask_and_set_register_interruptible(struct device *dev,
-       u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
-{
-       struct ab3550 *ab;
-       struct platform_device *pdev = to_platform_device(dev);
-
-       if ((AB3550_NUM_BANKS <= bank) ||
-               !reg_write_allowed(&ab3550_reg_ranges[pdev->id][bank], reg))
-               return -EINVAL;
-
-       ab = dev_get_drvdata(dev->parent);
-       return mask_and_set_register_interruptible(ab, bank, reg,
-               bitmask, bitvalues);
-}
-
-static int ab3550_set_register_interruptible(struct device *dev, u8 bank,
-       u8 reg, u8 value)
-{
-       return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF,
-               value);
-}
-
-static int ab3550_get_register_interruptible(struct device *dev, u8 bank,
-       u8 reg, u8 *value)
-{
-       struct ab3550 *ab;
-       struct platform_device *pdev = to_platform_device(dev);
-
-       if ((AB3550_NUM_BANKS <= bank) ||
-               !reg_read_allowed(&ab3550_reg_ranges[pdev->id][bank], reg))
-               return -EINVAL;
-
-       ab = dev_get_drvdata(dev->parent);
-       return get_register_interruptible(ab, bank, reg, value);
-}
-
-static int ab3550_get_register_page_interruptible(struct device *dev, u8 bank,
-       u8 first_reg, u8 *regvals, u8 numregs)
-{
-       struct ab3550 *ab;
-       struct platform_device *pdev = to_platform_device(dev);
-
-       if ((AB3550_NUM_BANKS <= bank) ||
-               !page_read_allowed(&ab3550_reg_ranges[pdev->id][bank],
-                       first_reg, (first_reg + numregs - 1)))
-               return -EINVAL;
-
-       ab = dev_get_drvdata(dev->parent);
-       return get_register_page_interruptible(ab, bank, first_reg, regvals,
-               numregs);
-}
-
-static int ab3550_event_registers_startup_state_get(struct device *dev,
-       u8 *event)
-{
-       struct ab3550 *ab;
-
-       ab = dev_get_drvdata(dev->parent);
-       if (!ab->startup_events_read)
-               return -EAGAIN; /* Try again later */
-
-       memcpy(event, ab->startup_events, AB3550_NUM_EVENT_REG);
-       return 0;
-}
-
-static int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq)
-{
-       struct ab3550 *ab;
-       struct ab3550_platform_data *plf_data;
-       bool val;
-
-       ab = irq_get_chip_data(irq);
-       plf_data = ab->i2c_client[0]->dev.platform_data;
-       irq -= plf_data->irq.base;
-       val = ((ab->startup_events[irq / 8] & BIT(irq % 8)) != 0);
-
-       return val;
-}
-
-static struct abx500_ops ab3550_ops = {
-       .get_chip_id = ab3550_get_chip_id,
-       .get_register = ab3550_get_register_interruptible,
-       .set_register = ab3550_set_register_interruptible,
-       .get_register_page = ab3550_get_register_page_interruptible,
-       .set_register_page = NULL,
-       .mask_and_set_register = ab3550_mask_and_set_register_interruptible,
-       .event_registers_startup_state_get =
-               ab3550_event_registers_startup_state_get,
-       .startup_irq_enabled = ab3550_startup_irq_enabled,
-};
-
-static irqreturn_t ab3550_irq_handler(int irq, void *data)
-{
-       struct ab3550 *ab = data;
-       int err;
-       unsigned int i;
-       u8 e[AB3550_NUM_EVENT_REG];
-       u8 *events;
-       unsigned long flags;
-
-       events = (ab->startup_events_read ? e : ab->startup_events);
-
-       err = get_register_page_interruptible(ab, AB3550_EVENT_BANK,
-               AB3550_EVENT_REG, events, AB3550_NUM_EVENT_REG);
-       if (err)
-               goto err_event_rd;
-
-       if (!ab->startup_events_read) {
-               dev_info(&ab->i2c_client[0]->dev,
-                       "startup events 0x%x,0x%x,0x%x,0x%x,0x%x\n",
-                       ab->startup_events[0], ab->startup_events[1],
-                       ab->startup_events[2], ab->startup_events[3],
-                       ab->startup_events[4]);
-               ab->startup_events_read = true;
-               goto out;
-       }
-
-       /* The two highest bits in event[4] are not used. */
-       events[4] &= 0x3f;
-
-       spin_lock_irqsave(&ab->event_lock, flags);
-       for (i = 0; i < AB3550_NUM_EVENT_REG; i++)
-               events[i] &= ~ab->event_mask[i];
-       spin_unlock_irqrestore(&ab->event_lock, flags);
-
-       for (i = 0; i < AB3550_NUM_EVENT_REG; i++) {
-               u8 bit;
-               u8 event_reg;
-
-               dev_dbg(&ab->i2c_client[0]->dev, "IRQ Event[%d]: 0x%2x\n",
-                       i, events[i]);
-
-               event_reg = events[i];
-               for (bit = 0; event_reg; bit++, event_reg /= 2) {
-                       if (event_reg % 2) {
-                               unsigned int irq;
-                               struct ab3550_platform_data *plf_data;
-
-                               plf_data = ab->i2c_client[0]->dev.platform_data;
-                               irq = plf_data->irq.base + (i * 8) + bit;
-                               handle_nested_irq(irq);
-                       }
-               }
-       }
-out:
-       return IRQ_HANDLED;
-
-err_event_rd:
-       dev_dbg(&ab->i2c_client[0]->dev, "error reading event registers\n");
-       return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_DEBUG_FS
-static struct ab3550_reg_ranges debug_ranges[AB3550_NUM_BANKS] = {
-       {
-               .count = 6,
-               .range = (struct ab3550_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x0e,
-                       },
-                       {
-                               .first = 0x10,
-                               .last = 0x1a,
-                       },
-                       {
-                               .first = 0x1e,
-                               .last = 0x4f,
-                       },
-                       {
-                               .first = 0x51,
-                               .last = 0x63,
-                       },
-                       {
-                               .first = 0x65,
-                               .last = 0xa3,
-                       },
-                       {
-                               .first = 0xa5,
-                               .last = 0xa8,
-                       },
-               }
-       },
-       {
-               .count = 8,
-               .range = (struct ab3550_reg_range[]) {
-                       {
-                               .first = 0x00,
-                               .last = 0x0e,
-                       },
-                       {
-                               .first = 0x10,
-                               .last = 0x17,
-                       },
-                       {
-                               .first = 0x1a,
-                               .last = 0x1c,
-                       },
-                       {
-                               .first = 0x20,
-                               .last = 0x56,
-                       },
-                       {
-                               .first = 0x5a,
-                               .last = 0x88,
-                       },
-                       {
-                               .first = 0x8a,
-                               .last = 0xad,
-                       },
-                       {
-                               .first = 0xb0,
-                               .last = 0xba,
-                       },
-                       {
-                               .first = 0xbc,
-                               .last = 0xc3,
-                       },
-               }
-       },
-};
-
-static int ab3550_registers_print(struct seq_file *s, void *p)
-{
-       struct ab3550 *ab = s->private;
-       int bank;
-
-       seq_printf(s, AB3550_NAME_STRING " register values:\n");
-
-       for (bank = 0; bank < AB3550_NUM_BANKS; bank++) {
-               unsigned int i;
-
-               seq_printf(s, " bank %d:\n", bank);
-               for (i = 0; i < debug_ranges[bank].count; i++) {
-                       u8 reg;
-
-                       for (reg = debug_ranges[bank].range[i].first;
-                               reg <= debug_ranges[bank].range[i].last;
-                               reg++) {
-                               u8 value;
-
-                               get_register_interruptible(ab, bank, reg,
-                                       &value);
-                               seq_printf(s, "  [%d/0x%02X]: 0x%02X\n", bank,
-                                       reg, value);
-                       }
-               }
-       }
-       return 0;
-}
-
-static int ab3550_registers_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, ab3550_registers_print, inode->i_private);
-}
-
-static const struct file_operations ab3550_registers_fops = {
-       .open = ab3550_registers_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static int ab3550_bank_print(struct seq_file *s, void *p)
-{
-       struct ab3550 *ab = s->private;
-
-       seq_printf(s, "%d\n", ab->debug_bank);
-       return 0;
-}
-
-static int ab3550_bank_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, ab3550_bank_print, inode->i_private);
-}
-
-static ssize_t ab3550_bank_write(struct file *file,
-       const char __user *user_buf,
-       size_t count, loff_t *ppos)
-{
-       struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       unsigned long user_bank;
-       int err;
-
-       /* Get userspace string and assure termination */
-       err = kstrtoul_from_user(user_buf, count, 0, &user_bank);
-       if (err)
-               return err;
-
-       if (user_bank >= AB3550_NUM_BANKS) {
-               dev_err(&ab->i2c_client[0]->dev,
-                       "debugfs error input > number of banks\n");
-               return -EINVAL;
-       }
-
-       ab->debug_bank = user_bank;
-
-       return count;
-}
-
-static int ab3550_address_print(struct seq_file *s, void *p)
-{
-       struct ab3550 *ab = s->private;
-
-       seq_printf(s, "0x%02X\n", ab->debug_address);
-       return 0;
-}
-
-static int ab3550_address_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, ab3550_address_print, inode->i_private);
-}
-
-static ssize_t ab3550_address_write(struct file *file,
-       const char __user *user_buf,
-       size_t count, loff_t *ppos)
-{
-       struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       unsigned long user_address;
-       int err;
-
-       /* Get userspace string and assure termination */
-       err = kstrtoul_from_user(user_buf, count, 0, &user_address);
-       if (err)
-               return err;
-
-       if (user_address > 0xff) {
-               dev_err(&ab->i2c_client[0]->dev,
-                       "debugfs error input > 0xff\n");
-               return -EINVAL;
-       }
-       ab->debug_address = user_address;
-       return count;
-}
-
-static int ab3550_val_print(struct seq_file *s, void *p)
-{
-       struct ab3550 *ab = s->private;
-       int err;
-       u8 regvalue;
-
-       err = get_register_interruptible(ab, (u8)ab->debug_bank,
-               (u8)ab->debug_address, &regvalue);
-       if (err)
-               return -EINVAL;
-       seq_printf(s, "0x%02X\n", regvalue);
-
-       return 0;
-}
-
-static int ab3550_val_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, ab3550_val_print, inode->i_private);
-}
-
-static ssize_t ab3550_val_write(struct file *file,
-       const char __user *user_buf,
-       size_t count, loff_t *ppos)
-{
-       struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private;
-       unsigned long user_val;
-       int err;
-       u8 regvalue;
-
-       /* Get userspace string and assure termination */
-       err = kstrtoul_from_user(user_buf, count, 0, &user_val);
-       if (err)
-               return err;
-
-       if (user_val > 0xff) {
-               dev_err(&ab->i2c_client[0]->dev,
-                       "debugfs error input > 0xff\n");
-               return -EINVAL;
-       }
-       err = mask_and_set_register_interruptible(
-               ab, (u8)ab->debug_bank,
-               (u8)ab->debug_address, 0xFF, (u8)user_val);
-       if (err)
-               return -EINVAL;
-
-       get_register_interruptible(ab, (u8)ab->debug_bank,
-               (u8)ab->debug_address, &regvalue);
-       if (err)
-               return -EINVAL;
-
-       return count;
-}
-
-static const struct file_operations ab3550_bank_fops = {
-       .open = ab3550_bank_open,
-       .write = ab3550_bank_write,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static const struct file_operations ab3550_address_fops = {
-       .open = ab3550_address_open,
-       .write = ab3550_address_write,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static const struct file_operations ab3550_val_fops = {
-       .open = ab3550_val_open,
-       .write = ab3550_val_write,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static struct dentry *ab3550_dir;
-static struct dentry *ab3550_reg_file;
-static struct dentry *ab3550_bank_file;
-static struct dentry *ab3550_address_file;
-static struct dentry *ab3550_val_file;
-
-static inline void ab3550_setup_debugfs(struct ab3550 *ab)
-{
-       ab->debug_bank = 0;
-       ab->debug_address = 0x00;
-
-       ab3550_dir = debugfs_create_dir(AB3550_NAME_STRING, NULL);
-       if (!ab3550_dir)
-               goto exit_no_debugfs;
-
-       ab3550_reg_file = debugfs_create_file("all-registers",
-               S_IRUGO, ab3550_dir, ab, &ab3550_registers_fops);
-       if (!ab3550_reg_file)
-               goto exit_destroy_dir;
-
-       ab3550_bank_file = debugfs_create_file("register-bank",
-               (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_bank_fops);
-       if (!ab3550_bank_file)
-               goto exit_destroy_reg;
-
-       ab3550_address_file = debugfs_create_file("register-address",
-               (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_address_fops);
-       if (!ab3550_address_file)
-               goto exit_destroy_bank;
-
-       ab3550_val_file = debugfs_create_file("register-value",
-               (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_val_fops);
-       if (!ab3550_val_file)
-               goto exit_destroy_address;
-
-       return;
-
-exit_destroy_address:
-       debugfs_remove(ab3550_address_file);
-exit_destroy_bank:
-       debugfs_remove(ab3550_bank_file);
-exit_destroy_reg:
-       debugfs_remove(ab3550_reg_file);
-exit_destroy_dir:
-       debugfs_remove(ab3550_dir);
-exit_no_debugfs:
-       dev_err(&ab->i2c_client[0]->dev, "failed to create debugfs entries.\n");
-       return;
-}
-
-static inline void ab3550_remove_debugfs(void)
-{
-       debugfs_remove(ab3550_val_file);
-       debugfs_remove(ab3550_address_file);
-       debugfs_remove(ab3550_bank_file);
-       debugfs_remove(ab3550_reg_file);
-       debugfs_remove(ab3550_dir);
-}
-
-#else /* !CONFIG_DEBUG_FS */
-static inline void ab3550_setup_debugfs(struct ab3550 *ab)
-{
-}
-static inline void ab3550_remove_debugfs(void)
-{
-}
-#endif
-
-/*
- * Basic set-up, datastructure creation/destruction and I2C interface.
- * This sets up a default config in the AB3550 chip so that it
- * will work as expected.
- */
-static int __init ab3550_setup(struct ab3550 *ab)
-{
-       int err = 0;
-       int i;
-       struct ab3550_platform_data *plf_data;
-       struct abx500_init_settings *settings;
-
-       plf_data = ab->i2c_client[0]->dev.platform_data;
-       settings = plf_data->init_settings;
-
-       for (i = 0; i < plf_data->init_settings_sz; i++) {
-               err = mask_and_set_register_interruptible(ab,
-                       settings[i].bank,
-                       settings[i].reg,
-                       0xFF, settings[i].setting);
-               if (err)
-                       goto exit_no_setup;
-
-               /* If event mask register update the event mask in ab3550 */
-               if ((settings[i].bank == 0) &&
-                       (AB3550_IMR1 <= settings[i].reg) &&
-                       (settings[i].reg <= AB3550_IMR5)) {
-                       ab->event_mask[settings[i].reg - AB3550_IMR1] =
-                               settings[i].setting;
-               }
-       }
-exit_no_setup:
-       return err;
-}
-
-static void ab3550_mask_work(struct work_struct *work)
-{
-       struct ab3550 *ab = container_of(work, struct ab3550, mask_work);
-       int i;
-       unsigned long flags;
-       u8 mask[AB3550_NUM_EVENT_REG];
-
-       spin_lock_irqsave(&ab->event_lock, flags);
-       for (i = 0; i < AB3550_NUM_EVENT_REG; i++)
-               mask[i] = ab->event_mask[i];
-       spin_unlock_irqrestore(&ab->event_lock, flags);
-
-       for (i = 0; i < AB3550_NUM_EVENT_REG; i++) {
-               int err;
-
-               err = mask_and_set_register_interruptible(ab, 0,
-                       (AB3550_IMR1 + i), ~0, mask[i]);
-               if (err)
-                       dev_err(&ab->i2c_client[0]->dev,
-                               "ab3550_mask_work failed 0x%x,0x%x\n",
-                               (AB3550_IMR1 + i), mask[i]);
-       }
-}
-
-static void ab3550_mask(struct irq_data *data)
-{
-       unsigned long flags;
-       struct ab3550 *ab;
-       struct ab3550_platform_data *plf_data;
-       int irq;
-
-       ab = irq_data_get_irq_chip_data(data);
-       plf_data = ab->i2c_client[0]->dev.platform_data;
-       irq = data->irq - plf_data->irq.base;
-
-       spin_lock_irqsave(&ab->event_lock, flags);
-       ab->event_mask[irq / 8] |= BIT(irq % 8);
-       spin_unlock_irqrestore(&ab->event_lock, flags);
-
-       schedule_work(&ab->mask_work);
-}
-
-static void ab3550_unmask(struct irq_data *data)
-{
-       unsigned long flags;
-       struct ab3550 *ab;
-       struct ab3550_platform_data *plf_data;
-       int irq;
-
-       ab = irq_data_get_irq_chip_data(data);
-       plf_data = ab->i2c_client[0]->dev.platform_data;
-       irq = data->irq - plf_data->irq.base;
-
-       spin_lock_irqsave(&ab->event_lock, flags);
-       ab->event_mask[irq / 8] &= ~BIT(irq % 8);
-       spin_unlock_irqrestore(&ab->event_lock, flags);
-
-       schedule_work(&ab->mask_work);
-}
-
-static void noop(struct irq_data *data)
-{
-}
-
-static struct irq_chip ab3550_irq_chip = {
-       .name           = "ab3550-core", /* Keep the same name as the request */
-       .irq_disable    = ab3550_mask, /* No default to mask in chip.c */
-       .irq_ack        = noop,
-       .irq_mask       = ab3550_mask,
-       .irq_unmask     = ab3550_unmask,
-};
-
-struct ab_family_id {
-       u8      id;
-       char    *name;
-};
-
-static const struct ab_family_id ids[] __initdata = {
-       /* AB3550 */
-       {
-               .id = AB3550_P1A,
-               .name = "P1A"
-       },
-       /* Terminator */
-       {
-               .id = 0x00,
-       }
-};
-
-static int __init ab3550_probe(struct i2c_client *client,
-       const struct i2c_device_id *id)
-{
-       struct ab3550 *ab;
-       struct ab3550_platform_data *ab3550_plf_data =
-               client->dev.platform_data;
-       int err;
-       int i;
-       int num_i2c_clients = 0;
-
-       ab = kzalloc(sizeof(struct ab3550), GFP_KERNEL);
-       if (!ab) {
-               dev_err(&client->dev,
-                       "could not allocate " AB3550_NAME_STRING " device\n");
-               return -ENOMEM;
-       }
-
-       /* Initialize data structure */
-       mutex_init(&ab->access_mutex);
-       spin_lock_init(&ab->event_lock);
-       ab->i2c_client[0] = client;
-
-       i2c_set_clientdata(client, ab);
-
-       /* Read chip ID register */
-       err = get_register_interruptible(ab, 0, AB3550_CID_REG, &ab->chip_id);
-       if (err) {
-               dev_err(&client->dev, "could not communicate with the analog "
-                       "baseband chip\n");
-               goto exit_no_detect;
-       }
-
-       for (i = 0; ids[i].id != 0x0; i++) {
-               if (ids[i].id == ab->chip_id) {
-                       snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1,
-                               AB3550_ID_FORMAT_STRING, ids[i].name);
-                       break;
-               }
-       }
-
-       if (ids[i].id == 0x0) {
-               dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n",
-                       ab->chip_id);
-               dev_err(&client->dev, "driver not started!\n");
-               goto exit_no_detect;
-       }
-
-       dev_info(&client->dev, "detected AB chip: %s\n", &ab->chip_name[0]);
-
-       /* Attach other dummy I2C clients. */
-       while (++num_i2c_clients < AB3550_NUM_BANKS) {
-               ab->i2c_client[num_i2c_clients] =
-                       i2c_new_dummy(client->adapter,
-                               (client->addr + num_i2c_clients));
-               if (!ab->i2c_client[num_i2c_clients]) {
-                       err = -ENOMEM;
-                       goto exit_no_dummy_client;
-               }
-               strlcpy(ab->i2c_client[num_i2c_clients]->name, id->name,
-                       sizeof(ab->i2c_client[num_i2c_clients]->name));
-       }
-
-       err = ab3550_setup(ab);
-       if (err)
-               goto exit_no_setup;
-
-       INIT_WORK(&ab->mask_work, ab3550_mask_work);
-
-       for (i = 0; i < ab3550_plf_data->irq.count; i++) {
-               unsigned int irq;
-
-               irq = ab3550_plf_data->irq.base + i;
-               irq_set_chip_data(irq, ab);
-               irq_set_chip_and_handler(irq, &ab3550_irq_chip,
-                                        handle_simple_irq);
-               irq_set_nested_thread(irq, 1);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID);
-#else
-               irq_set_noprobe(irq);
-#endif
-       }
-
-       err = request_threaded_irq(client->irq, NULL, ab3550_irq_handler,
-               IRQF_ONESHOT, "ab3550-core", ab);
-       /* This real unpredictable IRQ is of course sampled for entropy */
-       rand_initialize_irq(client->irq);
-
-       if (err)
-               goto exit_no_irq;
-
-       err = abx500_register_ops(&client->dev, &ab3550_ops);
-       if (err)
-               goto exit_no_ops;
-
-       /* Set up and register the platform devices. */
-       for (i = 0; i < AB3550_NUM_DEVICES; i++) {
-               ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i];
-               ab3550_devs[i].pdata_size = ab3550_plf_data->dev_data_sz[i];
-       }
-
-       err = mfd_add_devices(&client->dev, 0, ab3550_devs,
-               ARRAY_SIZE(ab3550_devs), NULL,
-               ab3550_plf_data->irq.base);
-
-       ab3550_setup_debugfs(ab);
-
-       return 0;
-
-exit_no_ops:
-exit_no_irq:
-exit_no_setup:
-exit_no_dummy_client:
-       /* Unregister the dummy i2c clients. */
-       while (--num_i2c_clients)
-               i2c_unregister_device(ab->i2c_client[num_i2c_clients]);
-exit_no_detect:
-       kfree(ab);
-       return err;
-}
-
-static int __exit ab3550_remove(struct i2c_client *client)
-{
-       struct ab3550 *ab = i2c_get_clientdata(client);
-       int num_i2c_clients = AB3550_NUM_BANKS;
-
-       mfd_remove_devices(&client->dev);
-       ab3550_remove_debugfs();
-
-       while (--num_i2c_clients)
-               i2c_unregister_device(ab->i2c_client[num_i2c_clients]);
-
-       /*
-        * At this point, all subscribers should have unregistered
-        * their notifiers so deactivate IRQ
-        */
-       free_irq(client->irq, ab);
-       kfree(ab);
-       return 0;
-}
-
-static const struct i2c_device_id ab3550_id[] = {
-       {AB3550_NAME_STRING, 0},
-       {}
-};
-MODULE_DEVICE_TABLE(i2c, ab3550_id);
-
-static struct i2c_driver ab3550_driver = {
-       .driver = {
-               .name   = AB3550_NAME_STRING,
-               .owner  = THIS_MODULE,
-       },
-       .id_table       = ab3550_id,
-       .probe          = ab3550_probe,
-       .remove         = __exit_p(ab3550_remove),
-};
-
-static int __init ab3550_i2c_init(void)
-{
-       return i2c_add_driver(&ab3550_driver);
-}
-
-static void __exit ab3550_i2c_exit(void)
-{
-       i2c_del_driver(&ab3550_driver);
-}
-
-subsys_initcall(ab3550_i2c_init);
-module_exit(ab3550_i2c_exit);
-
-MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
-MODULE_DESCRIPTION("AB3550 core driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ab5500-core.c b/drivers/mfd/ab5500-core.c
new file mode 100644 (file)
index 0000000..4175544
--- /dev/null
@@ -0,0 +1,1439 @@
+/*
+ * Copyright (C) 2007-2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Low-level core for exclusive access to the AB5500 IC on the I2C bus
+ * and some basic chip-configuration.
+ * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com>
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com>
+ * Author: Rickard Andersson <rickard.andersson@stericsson.com>
+ * Author: Karl Komierowski  <karl.komierowski@stericsson.com>
+ * Author: Bibek Basu <bibek.basu@stericsson.com>
+ *
+ * TODO: Event handling with irq_chip. Waiting for PRCMU fw support.
+ */
+
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/mfd/ab5500/ab5500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/list.h>
+#include <linux/bitops.h>
+#include <linux/spinlock.h>
+#include <linux/mfd/core.h>
+#include <linux/version.h>
+#include <linux/mfd/db5500-prcmu.h>
+
+#include "ab5500-core.h"
+#include "ab5500-debugfs.h"
+
+#define AB5500_NUM_EVENT_REG 23
+#define AB5500_IT_LATCH0_REG 0x40
+#define AB5500_IT_MASK0_REG 0x60
+
+/*
+ * Permissible register ranges for reading and writing per device and bank.
+ *
+ * The ranges must be listed in increasing address order, and no overlaps are
+ * allowed. It is assumed that write permission implies read permission
+ * (i.e. only RO and RW permissions should be used).  Ranges with write
+ * permission must not be split up.
+ */
+
+#define NO_RANGE {.count = 0, .range = NULL,}
+static struct ab5500_i2c_banks ab5500_bank_ranges[AB5500_NUM_DEVICES] = {
+       [AB5500_DEVID_USB] =  {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_USB,
+                               .nranges = 12,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x01,
+                                               .last = 0x01,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x80,
+                                               .last = 0x83,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x87,
+                                               .last = 0x8A,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x8B,
+                                               .last = 0x8B,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x91,
+                                               .last = 0x92,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x93,
+                                               .last = 0x93,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x94,
+                                               .last = 0x94,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0xA8,
+                                               .last = 0xB0,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0xB2,
+                                               .last = 0xB2,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0xB4,
+                                               .last = 0xBC,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0xBF,
+                                               .last = 0xBF,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0xC1,
+                                               .last = 0xC5,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_ADC] =  {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_ADC,
+                               .nranges = 6,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x1F,
+                                               .last = 0x22,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x23,
+                                               .last = 0x24,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x26,
+                                               .last = 0x2D,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x2F,
+                                               .last = 0x34,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x37,
+                                               .last = 0x57,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x58,
+                                               .last = 0x58,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_LEDS] =  {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_LED,
+                               .nranges = 1,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x00,
+                                               .last = 0x0C,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_VIDEO] =   {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_VDENC,
+                               .nranges = 12,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x00,
+                                               .last = 0x08,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x09,
+                                               .last = 0x09,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x0A,
+                                               .last = 0x12,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x15,
+                                               .last = 0x19,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x1B,
+                                               .last = 0x21,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x27,
+                                               .last = 0x2C,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x41,
+                                               .last = 0x41,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x45,
+                                               .last = 0x5B,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x5D,
+                                               .last = 0x5D,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x69,
+                                               .last = 0x69,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x6C,
+                                               .last = 0x6D,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x80,
+                                               .last = 0x81,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_REGULATORS] =   {
+               .nbanks = 2,
+               .bank =  (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_STARTUP,
+                               .nranges = 12,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x00,
+                                               .last = 0x01,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x1F,
+                                               .last = 0x1F,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x2E,
+                                               .last = 0x2E,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x2F,
+                                               .last = 0x30,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x50,
+                                               .last = 0x51,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x60,
+                                               .last = 0x61,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x66,
+                                               .last = 0x8A,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x8C,
+                                               .last = 0x96,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0xAA,
+                                               .last = 0xB4,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0xB7,
+                                               .last = 0xBF,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0xC1,
+                                               .last = 0xCA,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0xD3,
+                                               .last = 0xE0,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+                       {
+                               .bankid = AB5500_BANK_SIM_USBSIM,
+                               .nranges = 1,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x13,
+                                               .last = 0x19,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_SIM] =   {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_SIM_USBSIM,
+                               .nranges = 1,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x13,
+                                               .last = 0x19,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_RTC] =   {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_RTC,
+                               .nranges = 2,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x00,
+                                               .last = 0x04,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0x06,
+                                               .last = 0x0C,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_CHARGER] =   {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_CHG,
+                               .nranges = 2,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x11,
+                                               .last = 0x11,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x12,
+                                               .last = 0x1B,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_FUELGAUGE] =   {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_FG_BATTCOM_ACC,
+                               .nranges = 2,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x00,
+                                               .last = 0x0B,
+                                               .perm = AB5500_PERM_RO,
+                                       },
+                                       {
+                                               .first = 0x0C,
+                                               .last = 0x10,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_VIBRATOR] =   {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_VIBRA,
+                               .nranges = 2,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x10,
+                                               .last = 0x13,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0xFE,
+                                               .last = 0xFE,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_CODEC] =   {
+               .nbanks = 1,
+               .bank = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
+                               .nranges = 2,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x00,
+                                               .last = 0x48,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                                       {
+                                               .first = 0xEB,
+                                               .last = 0xFB,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+       [AB5500_DEVID_POWER] = {
+               .nbanks = 2,
+               .bank   = (struct ab5500_i2c_ranges []) {
+                       {
+                               .bankid = AB5500_BANK_STARTUP,
+                               .nranges = 1,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x30,
+                                               .last = 0x30,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+                       {
+                               .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
+                               .nranges = 1,
+                               .range = (struct ab5500_reg_range[]) {
+                                       {
+                                               .first = 0x01,
+                                               .last = 0x01,
+                                               .perm = AB5500_PERM_RW,
+                                       },
+                               },
+                       },
+               },
+       },
+};
+
+#define AB5500_IRQ(bank, bit)  ((bank) * 8 + (bit))
+
+/* I appologize for the resource names beeing a mix of upper case
+ * and lower case but I want them to be exact as the documentation */
+static struct mfd_cell ab5500_devs[AB5500_NUM_DEVICES] = {
+       [AB5500_DEVID_LEDS] = {
+               .name = "ab5500-leds",
+               .id = AB5500_DEVID_LEDS,
+       },
+       [AB5500_DEVID_POWER] = {
+               .name = "ab5500-power",
+               .id = AB5500_DEVID_POWER,
+       },
+       [AB5500_DEVID_REGULATORS] = {
+               .name = "ab5500-regulator",
+               .id = AB5500_DEVID_REGULATORS,
+       },
+       [AB5500_DEVID_SIM] = {
+               .name = "ab5500-sim",
+               .id = AB5500_DEVID_SIM,
+               .num_resources = 1,
+               .resources = (struct resource[]) {
+                       {
+                               .name = "SIMOFF",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(2, 0), /*rising*/
+                               .end = AB5500_IRQ(2, 1), /*falling*/
+                       },
+               },
+       },
+       [AB5500_DEVID_RTC] = {
+               .name = "ab5500-rtc",
+               .id = AB5500_DEVID_RTC,
+               .num_resources = 1,
+               .resources = (struct resource[]) {
+                       {
+                               .name   = "RTC_Alarm",
+                               .flags  = IORESOURCE_IRQ,
+                               .start  = AB5500_IRQ(1, 7),
+                               .end    = AB5500_IRQ(1, 7),
+                       }
+               },
+       },
+       [AB5500_DEVID_CHARGER] = {
+               .name = "ab5500-charger",
+               .id = AB5500_DEVID_CHARGER,
+       },
+       [AB5500_DEVID_ADC] = {
+               .name = "ab5500-adc",
+               .id = AB5500_DEVID_ADC,
+               .num_resources = 10,
+               .resources = (struct resource[]) {
+                       {
+                               .name = "TRIGGER-0",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 0),
+                               .end = AB5500_IRQ(0, 0),
+                       },
+                       {
+                               .name = "TRIGGER-1",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 1),
+                               .end = AB5500_IRQ(0, 1),
+                       },
+                       {
+                               .name = "TRIGGER-2",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 2),
+                               .end = AB5500_IRQ(0, 2),
+                       },
+                       {
+                               .name = "TRIGGER-3",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 3),
+                               .end = AB5500_IRQ(0, 3),
+                       },
+                       {
+                               .name = "TRIGGER-4",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 4),
+                               .end = AB5500_IRQ(0, 4),
+                       },
+                       {
+                               .name = "TRIGGER-5",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 5),
+                               .end = AB5500_IRQ(0, 5),
+                       },
+                       {
+                               .name = "TRIGGER-6",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 6),
+                               .end = AB5500_IRQ(0, 6),
+                       },
+                       {
+                               .name = "TRIGGER-7",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 7),
+                               .end = AB5500_IRQ(0, 7),
+                       },
+                       {
+                               .name = "TRIGGER-VBAT",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 8),
+                               .end = AB5500_IRQ(0, 8),
+                       },
+                       {
+                               .name = "TRIGGER-VBAT-TXON",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(0, 9),
+                               .end = AB5500_IRQ(0, 9),
+                       },
+               },
+       },
+       [AB5500_DEVID_FUELGAUGE] = {
+               .name = "ab5500-fuelgauge",
+               .id = AB5500_DEVID_FUELGAUGE,
+               .num_resources = 6,
+               .resources = (struct resource[]) {
+                       {
+                               .name = "Batt_attach",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(7, 5),
+                               .end = AB5500_IRQ(7, 5),
+                       },
+                       {
+                               .name = "Batt_removal",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(7, 6),
+                               .end = AB5500_IRQ(7, 6),
+                       },
+                       {
+                               .name = "UART_framing",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(7, 7),
+                               .end = AB5500_IRQ(7, 7),
+                       },
+                       {
+                               .name = "UART_overrun",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(8, 0),
+                               .end = AB5500_IRQ(8, 0),
+                       },
+                       {
+                               .name = "UART_Rdy_RX",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(8, 1),
+                               .end = AB5500_IRQ(8, 1),
+                       },
+                       {
+                               .name = "UART_Rdy_TX",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(8, 2),
+                               .end = AB5500_IRQ(8, 2),
+                       },
+               },
+       },
+       [AB5500_DEVID_VIBRATOR] = {
+               .name = "ab5500-vibrator",
+               .id = AB5500_DEVID_VIBRATOR,
+       },
+       [AB5500_DEVID_CODEC] = {
+               .name = "ab5500-codec",
+               .id = AB5500_DEVID_CODEC,
+               .num_resources = 3,
+               .resources = (struct resource[]) {
+                       {
+                               .name = "audio_spkr1_ovc",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 5),
+                               .end = AB5500_IRQ(9, 5),
+                       },
+                       {
+                               .name = "audio_plllocked",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 6),
+                               .end = AB5500_IRQ(9, 6),
+                       },
+                       {
+                               .name = "audio_spkr2_ovc",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(17, 4),
+                               .end = AB5500_IRQ(17, 4),
+                       },
+               },
+       },
+       [AB5500_DEVID_USB] = {
+               .name = "ab5500-usb",
+               .id = AB5500_DEVID_USB,
+               .num_resources = 36,
+               .resources = (struct resource[]) {
+                       {
+                               .name = "Link_Update",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(22, 1),
+                               .end = AB5500_IRQ(22, 1),
+                       },
+                       {
+                               .name = "DCIO",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(8, 3),
+                               .end = AB5500_IRQ(8, 4),
+                       },
+                       {
+                               .name = "VBUS_R",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(8, 5),
+                               .end = AB5500_IRQ(8, 5),
+                       },
+                       {
+                               .name = "VBUS_F",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(8, 6),
+                               .end = AB5500_IRQ(8, 6),
+                       },
+                       {
+                               .name = "CHGstate_10_PCVBUSchg",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(8, 7),
+                               .end = AB5500_IRQ(8, 7),
+                       },
+                       {
+                               .name = "DCIOreverse_ovc",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 0),
+                               .end = AB5500_IRQ(9, 0),
+                       },
+                       {
+                               .name = "USBCharDetDone",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 1),
+                               .end = AB5500_IRQ(9, 1),
+                       },
+                       {
+                               .name = "DCIO_no_limit",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 2),
+                               .end = AB5500_IRQ(9, 2),
+                       },
+                       {
+                               .name = "USB_suspend",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 3),
+                               .end = AB5500_IRQ(9, 3),
+                       },
+                       {
+                               .name = "DCIOreverse_fwdcurrent",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 4),
+                               .end = AB5500_IRQ(9, 4),
+                       },
+                       {
+                               .name = "Vbus_Imeasmax_change",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(9, 5),
+                               .end = AB5500_IRQ(9, 6),
+                       },
+                       {
+                               .name = "OVV",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 5),
+                               .end = AB5500_IRQ(14, 5),
+                       },
+                       {
+                               .name = "USBcharging_NOTok",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(15, 3),
+                               .end = AB5500_IRQ(15, 3),
+                       },
+                       {
+                               .name = "usb_adp_sensoroff",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(15, 6),
+                               .end = AB5500_IRQ(15, 6),
+                       },
+                       {
+                               .name = "usb_adp_probeplug",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(15, 7),
+                               .end = AB5500_IRQ(15, 7),
+                       },
+                       {
+                               .name = "usb_adp_sinkerror",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(16, 0),
+                               .end = AB5500_IRQ(16, 6),
+                       },
+                       {
+                               .name = "usb_adp_sourceerror",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(16, 1),
+                               .end = AB5500_IRQ(16, 1),
+                       },
+                       {
+                               .name = "usb_idgnd_r",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(16, 2),
+                               .end = AB5500_IRQ(16, 2),
+                       },
+                       {
+                               .name = "usb_idgnd_f",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(16, 3),
+                               .end = AB5500_IRQ(16, 3),
+                       },
+                       {
+                               .name = "usb_iddetR1",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(16, 4),
+                               .end = AB5500_IRQ(16, 5),
+                       },
+                       {
+                               .name = "usb_iddetR2",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(16, 6),
+                               .end = AB5500_IRQ(16, 7),
+                       },
+                       {
+                               .name = "usb_iddetR3",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(17, 0),
+                               .end = AB5500_IRQ(17, 1),
+                       },
+                       {
+                               .name = "usb_iddetR4",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(17, 2),
+                               .end = AB5500_IRQ(17, 3),
+                       },
+                       {
+                               .name = "CharTempWindowOk",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(17, 7),
+                               .end = AB5500_IRQ(18, 0),
+                       },
+                       {
+                               .name = "USB_SprDetect",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(18, 1),
+                               .end = AB5500_IRQ(18, 1),
+                       },
+                       {
+                               .name = "usb_adp_probe_unplug",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(18, 2),
+                               .end = AB5500_IRQ(18, 2),
+                       },
+                       {
+                               .name = "VBUSChDrop",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(18, 3),
+                               .end = AB5500_IRQ(18, 4),
+                       },
+                       {
+                               .name = "dcio_char_rec_done",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(18, 5),
+                               .end = AB5500_IRQ(18, 5),
+                       },
+                       {
+                               .name = "Charging_stopped_by_temp",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(18, 6),
+                               .end = AB5500_IRQ(18, 6),
+                       },
+                       {
+                               .name = "CHGstate_11_SafeModeVBUS",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(21, 1),
+                               .end = AB5500_IRQ(21, 2),
+                       },
+                       {
+                               .name = "CHGstate_12_comletedVBUS",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(21, 2),
+                               .end = AB5500_IRQ(21, 2),
+                       },
+                       {
+                               .name = "CHGstate_13_completedVBUS",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(21, 3),
+                               .end = AB5500_IRQ(21, 3),
+                       },
+                       {
+                               .name = "CHGstate_14_FullChgDCIO",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(21, 4),
+                               .end = AB5500_IRQ(21, 4),
+                       },
+                       {
+                               .name = "CHGstate_15_SafeModeDCIO",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(21, 5),
+                               .end = AB5500_IRQ(21, 5),
+                       },
+                       {
+                               .name = "CHGstate_16_OFFsuspendDCIO",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(21, 6),
+                               .end = AB5500_IRQ(21, 6),
+                       },
+                       {
+                               .name = "CHGstate_17_completedDCIO",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(21, 7),
+                               .end = AB5500_IRQ(21, 7),
+                       },
+               },
+       },
+       [AB5500_DEVID_OTP] = {
+               .name = "ab5500-otp",
+               .id = AB5500_DEVID_OTP,
+       },
+       [AB5500_DEVID_VIDEO] = {
+               .name = "ab5500-video",
+               .id = AB5500_DEVID_VIDEO,
+               .num_resources = 1,
+               .resources = (struct resource[]) {
+                       {
+                               .name = "plugTVdet",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(22, 2),
+                               .end = AB5500_IRQ(22, 2),
+                       },
+               },
+       },
+       [AB5500_DEVID_DBIECI] = {
+               .name = "ab5500-dbieci",
+               .id = AB5500_DEVID_DBIECI,
+               .num_resources = 10,
+               .resources = (struct resource[]) {
+                       {
+                               .name = "COLL",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 0),
+                               .end = AB5500_IRQ(14, 0),
+                       },
+                       {
+                               .name = "RESERR",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 1),
+                               .end = AB5500_IRQ(14, 1),
+                       },
+                       {
+                               .name = "FRAERR",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 2),
+                               .end = AB5500_IRQ(14, 2),
+                       },
+                       {
+                               .name = "COMERR",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 3),
+                               .end = AB5500_IRQ(14, 3),
+                       },
+                       {
+                               .name = "BSI_indicator",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 4),
+                               .end = AB5500_IRQ(14, 4),
+                       },
+                       {
+                               .name = "SPDSET",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 6),
+                               .end = AB5500_IRQ(14, 6),
+                       },
+                       {
+                               .name = "DSENT",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(14, 7),
+                               .end = AB5500_IRQ(14, 7),
+                       },
+                       {
+                               .name = "DREC",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(15, 0),
+                               .end = AB5500_IRQ(15, 0),
+                       },
+                       {
+                               .name = "ACCINT",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(15, 1),
+                               .end = AB5500_IRQ(15, 1),
+                       },
+                       {
+                               .name = "NOPINT",
+                               .flags = IORESOURCE_IRQ,
+                               .start = AB5500_IRQ(15, 2),
+                               .end = AB5500_IRQ(15, 2),
+                       },
+               },
+       },
+       [AB5500_DEVID_ONSWA] = {
+               .name = "ab5500-onswa",
+               .id = AB5500_DEVID_ONSWA,
+               .num_resources = 2,
+               .resources = (struct resource[]) {
+                       {
+                               .name   = "ONSWAn_rising",
+                               .flags  = IORESOURCE_IRQ,
+                               .start  = AB5500_IRQ(1, 3),
+                               .end    = AB5500_IRQ(1, 3),
+                       },
+                       {
+                               .name   = "ONSWAn_falling",
+                               .flags  = IORESOURCE_IRQ,
+                               .start  = AB5500_IRQ(1, 4),
+                               .end    = AB5500_IRQ(1, 4),
+                       },
+               },
+       },
+};
+
+/*
+ * Functionality for getting/setting register values.
+ */
+int ab5500_get_register_interruptible_raw(struct ab5500 *ab,
+                                         u8 bank, u8 reg,
+                                         u8 *value)
+{
+       int err;
+
+       if (bank >= AB5500_NUM_BANKS)
+               return -EINVAL;
+
+       err = mutex_lock_interruptible(&ab->access_mutex);
+       if (err)
+               return err;
+       err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr, reg, value, 1);
+
+       mutex_unlock(&ab->access_mutex);
+       return err;
+}
+
+static int get_register_page_interruptible(struct ab5500 *ab, u8 bank,
+       u8 first_reg, u8 *regvals, u8 numregs)
+{
+       int err;
+
+       if (bank >= AB5500_NUM_BANKS)
+               return -EINVAL;
+
+       err = mutex_lock_interruptible(&ab->access_mutex);
+       if (err)
+               return err;
+
+       while (numregs) {
+               /* The hardware limit for get page is 4 */
+               u8 curnum = min_t(u8, numregs, 4u);
+
+               err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr,
+                                           first_reg, regvals, curnum);
+               if (err)
+                       goto out;
+
+               numregs -= curnum;
+               first_reg += curnum;
+               regvals += curnum;
+       }
+
+out:
+       mutex_unlock(&ab->access_mutex);
+       return err;
+}
+
+int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
+       u8 reg, u8 bitmask, u8 bitvalues)
+{
+       int err = 0;
+
+       if (bank >= AB5500_NUM_BANKS)
+               return -EINVAL;
+
+       if (bitmask) {
+               u8 buf;
+
+               err = mutex_lock_interruptible(&ab->access_mutex);
+               if (err)
+                       return err;
+
+               if (bitmask == 0xFF) /* No need to read in this case. */
+                       buf = bitvalues;
+               else { /* Read and modify the register value. */
+                       err = db5500_prcmu_abb_read(bankinfo[bank].slave_addr,
+                               reg, &buf, 1);
+                       if (err)
+                               return err;
+
+                       buf = ((~bitmask & buf) | (bitmask & bitvalues));
+               }
+               /* Write the new value. */
+               err = db5500_prcmu_abb_write(bankinfo[bank].slave_addr, reg,
+                                            &buf, 1);
+
+               mutex_unlock(&ab->access_mutex);
+       }
+       return err;
+}
+
+static int
+set_register_interruptible(struct ab5500 *ab, u8 bank, u8 reg, u8 value)
+{
+       return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
+                                                             0xff, value);
+}
+
+/*
+ * Read/write permission checking functions.
+ */
+static const struct ab5500_i2c_ranges *get_bankref(u8 devid, u8 bank)
+{
+       u8 i;
+
+       if (devid < AB5500_NUM_DEVICES) {
+               for (i = 0; i < ab5500_bank_ranges[devid].nbanks; i++) {
+                       if (ab5500_bank_ranges[devid].bank[i].bankid == bank)
+                               return &ab5500_bank_ranges[devid].bank[i];
+               }
+       }
+       return NULL;
+}
+
+static bool page_write_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg)
+{
+       u8 i; /* range loop index */
+       const struct ab5500_i2c_ranges *bankref;
+
+       bankref = get_bankref(devid, bank);
+       if (bankref == NULL || last_reg < first_reg)
+               return false;
+
+       for (i = 0; i < bankref->nranges; i++) {
+               if (first_reg < bankref->range[i].first)
+                       break;
+               if ((last_reg <= bankref->range[i].last) &&
+                       (bankref->range[i].perm & AB5500_PERM_WR))
+                       return true;
+       }
+       return false;
+}
+
+static bool reg_write_allowed(u8 devid, u8 bank, u8 reg)
+{
+       return page_write_allowed(devid, bank, reg, reg);
+}
+
+static bool page_read_allowed(u8 devid, u8 bank, u8 first_reg, u8 last_reg)
+{
+       u8 i;
+       const struct ab5500_i2c_ranges *bankref;
+
+       bankref = get_bankref(devid, bank);
+       if (bankref == NULL || last_reg < first_reg)
+               return false;
+
+
+       /* Find the range (if it exists in the list) that includes first_reg. */
+       for (i = 0; i < bankref->nranges; i++) {
+               if (first_reg < bankref->range[i].first)
+                       return false;
+               if (first_reg <= bankref->range[i].last)
+                       break;
+       }
+       /* Make sure that the entire range up to and including last_reg is
+        * readable. This may span several of the ranges in the list.
+        */
+       while ((i < bankref->nranges) &&
+               (bankref->range[i].perm & AB5500_PERM_RD)) {
+               if (last_reg <= bankref->range[i].last)
+                       return true;
+               if ((++i >= bankref->nranges) ||
+                       (bankref->range[i].first !=
+                               (bankref->range[i - 1].last + 1))) {
+                       break;
+               }
+       }
+       return false;
+}
+
+static bool reg_read_allowed(u8 devid, u8 bank, u8 reg)
+{
+       return page_read_allowed(devid, bank, reg, reg);
+}
+
+
+/*
+ * The exported register access functionality.
+ */
+static int ab5500_get_chip_id(struct device *dev)
+{
+       struct ab5500 *ab = dev_get_drvdata(dev->parent);
+
+       return (int)ab->chip_id;
+}
+
+static int ab5500_mask_and_set_register_interruptible(struct device *dev,
+               u8 bank, u8 reg, u8 bitmask, u8 bitvalues)
+{
+       struct ab5500 *ab;
+       struct platform_device *pdev = to_platform_device(dev);
+
+       if ((AB5500_NUM_BANKS <= bank) ||
+               !reg_write_allowed(pdev->id, bank, reg))
+               return -EINVAL;
+
+       ab = dev_get_drvdata(dev->parent);
+       return ab5500_mask_and_set_register_interruptible_raw(ab, bank, reg,
+               bitmask, bitvalues);
+}
+
+static int ab5500_set_register_interruptible(struct device *dev, u8 bank,
+       u8 reg, u8 value)
+{
+       return ab5500_mask_and_set_register_interruptible(dev, bank, reg, 0xFF,
+               value);
+}
+
+static int ab5500_get_register_interruptible(struct device *dev, u8 bank,
+               u8 reg, u8 *value)
+{
+       struct ab5500 *ab;
+       struct platform_device *pdev = to_platform_device(dev);
+
+       if ((AB5500_NUM_BANKS <= bank) ||
+               !reg_read_allowed(pdev->id, bank, reg))
+               return -EINVAL;
+
+       ab = dev_get_drvdata(dev->parent);
+       return ab5500_get_register_interruptible_raw(ab, bank, reg, value);
+}
+
+static int ab5500_get_register_page_interruptible(struct device *dev, u8 bank,
+               u8 first_reg, u8 *regvals, u8 numregs)
+{
+       struct ab5500 *ab;
+       struct platform_device *pdev = to_platform_device(dev);
+
+       if ((AB5500_NUM_BANKS <= bank) ||
+               !page_read_allowed(pdev->id, bank,
+                       first_reg, (first_reg + numregs - 1)))
+               return -EINVAL;
+
+       ab = dev_get_drvdata(dev->parent);
+       return get_register_page_interruptible(ab, bank, first_reg, regvals,
+               numregs);
+}
+
+static int
+ab5500_event_registers_startup_state_get(struct device *dev, u8 *event)
+{
+       struct ab5500 *ab;
+
+       ab = dev_get_drvdata(dev->parent);
+       if (!ab->startup_events_read)
+               return -EAGAIN; /* Try again later */
+
+       memcpy(event, ab->startup_events, AB5500_NUM_EVENT_REG);
+       return 0;
+}
+
+static struct abx500_ops ab5500_ops = {
+       .get_chip_id = ab5500_get_chip_id,
+       .get_register = ab5500_get_register_interruptible,
+       .set_register = ab5500_set_register_interruptible,
+       .get_register_page = ab5500_get_register_page_interruptible,
+       .set_register_page = NULL,
+       .mask_and_set_register = ab5500_mask_and_set_register_interruptible,
+       .event_registers_startup_state_get =
+               ab5500_event_registers_startup_state_get,
+       .startup_irq_enabled = NULL,
+};
+
+/*
+ * ab5500_setup : Basic set-up, datastructure creation/destruction
+ *               and I2C interface.This sets up a default config
+ *               in the AB5500 chip so that it will work as expected.
+ * @ab :         Pointer to ab5500 structure
+ * @settings :    Pointer to struct abx500_init_settings
+ * @size :        Size of init data
+ */
+static int __init ab5500_setup(struct ab5500 *ab,
+       struct abx500_init_settings *settings, unsigned int size)
+{
+       int err = 0;
+       int i;
+
+       for (i = 0; i < size; i++) {
+               err = ab5500_mask_and_set_register_interruptible_raw(ab,
+                       settings[i].bank,
+                       settings[i].reg,
+                       0xFF, settings[i].setting);
+               if (err)
+                       goto exit_no_setup;
+
+               /* If event mask register update the event mask in ab5500 */
+               if ((settings[i].bank == AB5500_BANK_IT) &&
+                       (AB5500_MASK_BASE <= settings[i].reg) &&
+                       (settings[i].reg <= AB5500_MASK_END)) {
+                       ab->mask[settings[i].reg - AB5500_MASK_BASE] =
+                               settings[i].setting;
+               }
+       }
+exit_no_setup:
+       return err;
+}
+
+struct ab_family_id {
+       u8      id;
+       char    *name;
+};
+
+static const struct ab_family_id ids[] __initdata = {
+       /* AB5500 */
+       {
+               .id = AB5500_1_0,
+               .name = "1.0"
+       },
+       {
+               .id = AB5500_1_1,
+               .name = "1.1"
+       },
+       /* Terminator */
+       {
+               .id = 0x00,
+       }
+};
+
+static int __init ab5500_probe(struct platform_device *pdev)
+{
+       struct ab5500 *ab;
+       struct ab5500_platform_data *ab5500_plf_data =
+               pdev->dev.platform_data;
+       int err;
+       int i;
+
+       ab = kzalloc(sizeof(struct ab5500), GFP_KERNEL);
+       if (!ab) {
+               dev_err(&pdev->dev,
+                       "could not allocate ab5500 device\n");
+               return -ENOMEM;
+       }
+
+       /* Initialize data structure */
+       mutex_init(&ab->access_mutex);
+       mutex_init(&ab->irq_lock);
+       ab->dev = &pdev->dev;
+
+       platform_set_drvdata(pdev, ab);
+
+       /* Read chip ID register */
+       err = ab5500_get_register_interruptible_raw(ab,
+                                       AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
+                                       AB5500_CHIP_ID, &ab->chip_id);
+       if (err) {
+               dev_err(&pdev->dev, "could not communicate with the analog "
+                       "baseband chip\n");
+               goto exit_no_detect;
+       }
+
+       for (i = 0; ids[i].id != 0x0; i++) {
+               if (ids[i].id == ab->chip_id) {
+                       snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1,
+                               "AB5500 %s", ids[i].name);
+                       break;
+               }
+       }
+       if (ids[i].id == 0x0) {
+               dev_err(&pdev->dev, "unknown analog baseband chip id: 0x%x\n",
+                       ab->chip_id);
+               dev_err(&pdev->dev, "driver not started!\n");
+               goto exit_no_detect;
+       }
+
+       /* Clear and mask all interrupts */
+       for (i = 0; i < AB5500_NUM_IRQ_REGS; i++) {
+               u8 latchreg = AB5500_IT_LATCH0_REG + i;
+               u8 maskreg = AB5500_IT_MASK0_REG + i;
+               u8 val;
+
+               ab5500_get_register_interruptible_raw(ab, AB5500_BANK_IT,
+                                                     latchreg, &val);
+               set_register_interruptible(ab, AB5500_BANK_IT, maskreg, 0xff);
+               ab->mask[i] = ab->oldmask[i] = 0xff;
+       }
+
+       err = abx500_register_ops(&pdev->dev, &ab5500_ops);
+       if (err) {
+               dev_err(&pdev->dev, "ab5500_register ops error\n");
+               goto exit_no_detect;
+       }
+
+       /* Set up and register the platform devices. */
+       for (i = 0; i < AB5500_NUM_DEVICES; i++) {
+               ab5500_devs[i].platform_data = ab5500_plf_data->dev_data[i];
+               ab5500_devs[i].pdata_size =
+                       sizeof(ab5500_plf_data->dev_data[i]);
+       }
+
+       err = mfd_add_devices(&pdev->dev, 0, ab5500_devs,
+               ARRAY_SIZE(ab5500_devs), NULL,
+               ab5500_plf_data->irq.base);
+       if (err) {
+               dev_err(&pdev->dev, "ab5500_mfd_add_device error\n");
+               goto exit_no_detect;
+       }
+
+       err = ab5500_setup(ab, ab5500_plf_data->init_settings,
+               ab5500_plf_data->init_settings_sz);
+       if (err) {
+               dev_err(&pdev->dev, "ab5500_setup error\n");
+               goto exit_no_detect;
+       }
+
+       ab5500_setup_debugfs(ab);
+
+       dev_info(&pdev->dev, "detected AB chip: %s\n", &ab->chip_name[0]);
+       return 0;
+
+exit_no_detect:
+       kfree(ab);
+       return err;
+}
+
+static int __exit ab5500_remove(struct platform_device *pdev)
+{
+       struct ab5500 *ab = platform_get_drvdata(pdev);
+
+       ab5500_remove_debugfs();
+       mfd_remove_devices(&pdev->dev);
+       kfree(ab);
+       return 0;
+}
+
+static struct platform_driver ab5500_driver = {
+       .driver = {
+               .name = "ab5500-core",
+               .owner = THIS_MODULE,
+       },
+       .remove  = __exit_p(ab5500_remove),
+};
+
+static int __init ab5500_core_init(void)
+{
+       return platform_driver_probe(&ab5500_driver, ab5500_probe);
+}
+
+static void __exit ab5500_core_exit(void)
+{
+       platform_driver_unregister(&ab5500_driver);
+}
+
+subsys_initcall(ab5500_core_init);
+module_exit(ab5500_core_exit);
+
+MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>");
+MODULE_DESCRIPTION("AB5500 core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/ab5500-core.h b/drivers/mfd/ab5500-core.h
new file mode 100644 (file)
index 0000000..63b30b1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Shared definitions and data structures for the AB5500 MFD driver
+ */
+
+/* Read/write operation values. */
+#define AB5500_PERM_RD (0x01)
+#define AB5500_PERM_WR (0x02)
+
+/* Read/write permissions. */
+#define AB5500_PERM_RO (AB5500_PERM_RD)
+#define AB5500_PERM_RW (AB5500_PERM_RD | AB5500_PERM_WR)
+
+#define AB5500_MASK_BASE (0x60)
+#define AB5500_MASK_END (0x79)
+#define AB5500_CHIP_ID (0x20)
+
+/**
+ * struct ab5500_reg_range
+ * @first: the first address of the range
+ * @last: the last address of the range
+ * @perm: access permissions for the range
+ */
+struct ab5500_reg_range {
+       u8 first;
+       u8 last;
+       u8 perm;
+};
+
+/**
+ * struct ab5500_i2c_ranges
+ * @count: the number of ranges in the list
+ * @range: the list of register ranges
+ */
+struct ab5500_i2c_ranges {
+       u8 nranges;
+       u8 bankid;
+       const struct ab5500_reg_range *range;
+};
+
+/**
+ * struct ab5500_i2c_banks
+ * @count: the number of ranges in the list
+ * @range: the list of register ranges
+ */
+struct ab5500_i2c_banks {
+       u8 nbanks;
+       const struct ab5500_i2c_ranges *bank;
+};
+
+/**
+ * struct ab5500_bank
+ * @slave_addr: I2C slave_addr found in AB5500 specification
+ * @name: Documentation name of the bank. For reference
+ */
+struct ab5500_bank {
+       u8 slave_addr;
+       const char *name;
+};
+
+static const struct ab5500_bank bankinfo[AB5500_NUM_BANKS] = {
+       [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
+               AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP, "VIT_IO_I2C_CLK_TST_OTP"},
+       [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
+               AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST, "VDDDIG_IO_I2C_CLK_TST"},
+       [AB5500_BANK_VDENC] = {AB5500_ADDR_VDENC, "VDENC"},
+       [AB5500_BANK_SIM_USBSIM] = {AB5500_ADDR_SIM_USBSIM, "SIM_USBSIM"},
+       [AB5500_BANK_LED] = {AB5500_ADDR_LED, "LED"},
+       [AB5500_BANK_ADC] = {AB5500_ADDR_ADC, "ADC"},
+       [AB5500_BANK_RTC] = {AB5500_ADDR_RTC, "RTC"},
+       [AB5500_BANK_STARTUP] = {AB5500_ADDR_STARTUP, "STARTUP"},
+       [AB5500_BANK_DBI_ECI] = {AB5500_ADDR_DBI_ECI, "DBI-ECI"},
+       [AB5500_BANK_CHG] = {AB5500_ADDR_CHG, "CHG"},
+       [AB5500_BANK_FG_BATTCOM_ACC] = {
+               AB5500_ADDR_FG_BATTCOM_ACC, "FG_BATCOM_ACC"},
+       [AB5500_BANK_USB] = {AB5500_ADDR_USB, "USB"},
+       [AB5500_BANK_IT] = {AB5500_ADDR_IT, "IT"},
+       [AB5500_BANK_VIBRA] = {AB5500_ADDR_VIBRA, "VIBRA"},
+       [AB5500_BANK_AUDIO_HEADSETUSB] = {
+               AB5500_ADDR_AUDIO_HEADSETUSB, "AUDIO_HEADSETUSB"},
+};
+
+int ab5500_get_register_interruptible_raw(struct ab5500 *ab, u8 bank, u8 reg,
+       u8 *value);
+int ab5500_mask_and_set_register_interruptible_raw(struct ab5500 *ab, u8 bank,
+       u8 reg, u8 bitmask, u8 bitvalues);
diff --git a/drivers/mfd/ab5500-debugfs.c b/drivers/mfd/ab5500-debugfs.c
new file mode 100644 (file)
index 0000000..6be1fe6
--- /dev/null
@@ -0,0 +1,806 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Debugfs support for the AB5500 MFD driver
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/mfd/ab5500/ab5500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/uaccess.h>
+
+#include "ab5500-core.h"
+#include "ab5500-debugfs.h"
+
+static struct ab5500_i2c_ranges ab5500_reg_ranges[AB5500_NUM_BANKS] = {
+       [AB5500_BANK_LED] = {
+               .bankid = AB5500_BANK_LED,
+               .nranges = 1,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x0C,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_ADC] = {
+               .bankid = AB5500_BANK_ADC,
+               .nranges = 6,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x1F,
+                               .last = 0x22,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x23,
+                               .last = 0x24,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x26,
+                               .last = 0x2D,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x2F,
+                               .last = 0x34,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x37,
+                               .last = 0x57,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x58,
+                               .last = 0x58,
+                               .perm = AB5500_PERM_RO,
+                       },
+               },
+       },
+       [AB5500_BANK_RTC] = {
+               .bankid = AB5500_BANK_RTC,
+               .nranges = 2,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x04,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x06,
+                               .last = 0x0C,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_STARTUP] = {
+               .bankid = AB5500_BANK_STARTUP,
+               .nranges = 12,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x01,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x1F,
+                               .last = 0x1F,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x2E,
+                               .last = 0x2E,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x2F,
+                               .last = 0x30,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x50,
+                               .last = 0x51,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x60,
+                               .last = 0x61,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x66,
+                               .last = 0x8A,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x8C,
+                               .last = 0x96,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0xAA,
+                               .last = 0xB4,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0xB7,
+                               .last = 0xBF,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0xC1,
+                               .last = 0xCA,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0xD3,
+                               .last = 0xE0,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_DBI_ECI] = {
+               .bankid = AB5500_BANK_DBI_ECI,
+               .nranges = 3,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x07,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x10,
+                               .last = 0x10,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x13,
+                               .last = 0x13,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_CHG] = {
+               .bankid = AB5500_BANK_CHG,
+               .nranges = 2,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x11,
+                               .last = 0x11,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x12,
+                               .last = 0x1B,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_FG_BATTCOM_ACC] = {
+               .bankid = AB5500_BANK_FG_BATTCOM_ACC,
+               .nranges = 2,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x0B,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x0C,
+                               .last = 0x10,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_USB] = {
+               .bankid = AB5500_BANK_USB,
+               .nranges = 12,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x01,
+                               .last = 0x01,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x80,
+                               .last = 0x83,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x87,
+                               .last = 0x8A,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x8B,
+                               .last = 0x8B,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x91,
+                               .last = 0x92,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x93,
+                               .last = 0x93,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x94,
+                               .last = 0x94,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0xA8,
+                               .last = 0xB0,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0xB2,
+                               .last = 0xB2,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0xB4,
+                               .last = 0xBC,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0xBF,
+                               .last = 0xBF,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0xC1,
+                               .last = 0xC5,
+                               .perm = AB5500_PERM_RO,
+                       },
+               },
+       },
+       [AB5500_BANK_IT] = {
+               .bankid = AB5500_BANK_IT,
+               .nranges = 4,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x02,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x20,
+                               .last = 0x36,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x40,
+                               .last = 0x56,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x60,
+                               .last = 0x76,
+                               .perm = AB5500_PERM_RO,
+                       },
+               },
+       },
+       [AB5500_BANK_VDDDIG_IO_I2C_CLK_TST] = {
+               .bankid = AB5500_BANK_VDDDIG_IO_I2C_CLK_TST,
+               .nranges = 7,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x02,
+                               .last = 0x02,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x12,
+                               .last = 0x12,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x30,
+                               .last = 0x34,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x40,
+                               .last = 0x44,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x50,
+                               .last = 0x54,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x60,
+                               .last = 0x64,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x70,
+                               .last = 0x74,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP] = {
+               .bankid = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP,
+               .nranges = 13,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x01,
+                               .last = 0x01,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x02,
+                               .last = 0x02,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x0D,
+                               .last = 0x0F,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x1C,
+                               .last = 0x1C,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x1E,
+                               .last = 0x1E,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x20,
+                               .last = 0x21,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x25,
+                               .last = 0x25,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x28,
+                               .last = 0x2A,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x30,
+                               .last = 0x33,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x40,
+                               .last = 0x43,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x50,
+                               .last = 0x53,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x60,
+                               .last = 0x63,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x70,
+                               .last = 0x73,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_VIBRA] = {
+               .bankid = AB5500_BANK_VIBRA,
+               .nranges = 2,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x10,
+                               .last = 0x13,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0xFE,
+                               .last = 0xFE,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_AUDIO_HEADSETUSB] = {
+               .bankid = AB5500_BANK_AUDIO_HEADSETUSB,
+               .nranges = 2,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x48,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0xEB,
+                               .last = 0xFB,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_SIM_USBSIM] = {
+               .bankid = AB5500_BANK_SIM_USBSIM,
+               .nranges = 1,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x13,
+                               .last = 0x19,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+       [AB5500_BANK_VDENC] = {
+               .bankid = AB5500_BANK_VDENC,
+               .nranges = 12,
+               .range = (struct ab5500_reg_range[]) {
+                       {
+                               .first = 0x00,
+                               .last = 0x08,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x09,
+                               .last = 0x09,
+                               .perm = AB5500_PERM_RO,
+                       },
+                       {
+                               .first = 0x0A,
+                               .last = 0x12,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x15,
+                               .last = 0x19,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x1B,
+                               .last = 0x21,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x27,
+                               .last = 0x2C,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x41,
+                               .last = 0x41,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x45,
+                               .last = 0x5B,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x5D,
+                               .last = 0x5D,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x69,
+                               .last = 0x69,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x6C,
+                               .last = 0x6D,
+                               .perm = AB5500_PERM_RW,
+                       },
+                       {
+                               .first = 0x80,
+                               .last = 0x81,
+                               .perm = AB5500_PERM_RW,
+                       },
+               },
+       },
+};
+
+static int ab5500_registers_print(struct seq_file *s, void *p)
+{
+       struct ab5500 *ab = s->private;
+       unsigned int i;
+       u8 bank = (u8)ab->debug_bank;
+
+       seq_printf(s, "ab5500 register values:\n");
+       for (bank = 0; bank < AB5500_NUM_BANKS; bank++) {
+               seq_printf(s, " bank %u, %s (0x%x):\n", bank,
+                               bankinfo[bank].name,
+                               bankinfo[bank].slave_addr);
+               for (i = 0; i < ab5500_reg_ranges[bank].nranges; i++) {
+                       u8 reg;
+                       int err;
+
+                       for (reg = ab5500_reg_ranges[bank].range[i].first;
+                               reg <= ab5500_reg_ranges[bank].range[i].last;
+                               reg++) {
+                               u8 value;
+
+                               err = ab5500_get_register_interruptible_raw(ab,
+                                                               bank, reg,
+                                                               &value);
+                               if (err < 0) {
+                                       dev_err(ab->dev, "get_reg failed %d"
+                                               "bank 0x%x reg 0x%x\n",
+                                               err, bank, reg);
+                                       return err;
+                               }
+
+                               err = seq_printf(s, "[%d/0x%02X]: 0x%02X\n",
+                                               bank, reg, value);
+                               if (err < 0) {
+                                       dev_err(ab->dev,
+                                               "seq_printf overflow\n");
+                                       /*
+                                        * Error is not returned here since
+                                        * the output is wanted in any case
+                                        */
+                                       return 0;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+static int ab5500_registers_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ab5500_registers_print, inode->i_private);
+}
+
+static const struct file_operations ab5500_registers_fops = {
+       .open = ab5500_registers_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static int ab5500_bank_print(struct seq_file *s, void *p)
+{
+       struct ab5500 *ab = s->private;
+
+       seq_printf(s, "%d\n", ab->debug_bank);
+       return 0;
+}
+
+static int ab5500_bank_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ab5500_bank_print, inode->i_private);
+}
+
+static ssize_t ab5500_bank_write(struct file *file,
+       const char __user *user_buf,
+       size_t count, loff_t *ppos)
+{
+       struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
+       char buf[32];
+       int buf_size;
+       unsigned long user_bank;
+       int err;
+
+       /* Get userspace string and assure termination */
+       buf_size = min(count, (sizeof(buf) - 1));
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       buf[buf_size] = 0;
+
+       err = strict_strtoul(buf, 0, &user_bank);
+       if (err)
+               return -EINVAL;
+
+       if (user_bank >= AB5500_NUM_BANKS) {
+               dev_err(ab->dev,
+                       "debugfs error input > number of banks\n");
+               return -EINVAL;
+       }
+
+       ab->debug_bank = user_bank;
+
+       return buf_size;
+}
+
+static int ab5500_address_print(struct seq_file *s, void *p)
+{
+       struct ab5500 *ab = s->private;
+
+       seq_printf(s, "0x%02X\n", ab->debug_address);
+       return 0;
+}
+
+static int ab5500_address_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ab5500_address_print, inode->i_private);
+}
+
+static ssize_t ab5500_address_write(struct file *file,
+       const char __user *user_buf,
+       size_t count, loff_t *ppos)
+{
+       struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
+       char buf[32];
+       int buf_size;
+       unsigned long user_address;
+       int err;
+
+       /* Get userspace string and assure termination */
+       buf_size = min(count, (sizeof(buf) - 1));
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       buf[buf_size] = 0;
+
+       err = strict_strtoul(buf, 0, &user_address);
+       if (err)
+               return -EINVAL;
+       if (user_address > 0xff) {
+               dev_err(ab->dev,
+                       "debugfs error input > 0xff\n");
+               return -EINVAL;
+       }
+       ab->debug_address = user_address;
+       return buf_size;
+}
+
+static int ab5500_val_print(struct seq_file *s, void *p)
+{
+       struct ab5500 *ab = s->private;
+       int err;
+       u8 regvalue;
+
+       err = ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
+               (u8)ab->debug_address, &regvalue);
+       if (err) {
+               dev_err(ab->dev, "get_reg failed %d, bank 0x%x"
+                       ", reg 0x%x\n", err, ab->debug_bank,
+                       ab->debug_address);
+               return -EINVAL;
+       }
+       seq_printf(s, "0x%02X\n", regvalue);
+
+       return 0;
+}
+
+static int ab5500_val_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ab5500_val_print, inode->i_private);
+}
+
+static ssize_t ab5500_val_write(struct file *file,
+       const char __user *user_buf,
+       size_t count, loff_t *ppos)
+{
+       struct ab5500 *ab = ((struct seq_file *)(file->private_data))->private;
+       char buf[32];
+       int buf_size;
+       unsigned long user_val;
+       int err;
+       u8 regvalue;
+
+       /* Get userspace string and assure termination */
+       buf_size = min(count, (sizeof(buf)-1));
+       if (copy_from_user(buf, user_buf, buf_size))
+               return -EFAULT;
+       buf[buf_size] = 0;
+
+       err = strict_strtoul(buf, 0, &user_val);
+       if (err)
+               return -EINVAL;
+       if (user_val > 0xff) {
+               dev_err(ab->dev,
+                       "debugfs error input > 0xff\n");
+               return -EINVAL;
+       }
+       err = ab5500_mask_and_set_register_interruptible_raw(
+               ab, (u8)ab->debug_bank,
+               (u8)ab->debug_address, 0xFF, (u8)user_val);
+       if (err)
+               return -EINVAL;
+
+       ab5500_get_register_interruptible_raw(ab, (u8)ab->debug_bank,
+               (u8)ab->debug_address, &regvalue);
+       if (err)
+               return -EINVAL;
+
+       return buf_size;
+}
+
+static const struct file_operations ab5500_bank_fops = {
+       .open = ab5500_bank_open,
+       .write = ab5500_bank_write,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static const struct file_operations ab5500_address_fops = {
+       .open = ab5500_address_open,
+       .write = ab5500_address_write,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static const struct file_operations ab5500_val_fops = {
+       .open = ab5500_val_open,
+       .write = ab5500_val_write,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .owner = THIS_MODULE,
+};
+
+static struct dentry *ab5500_dir;
+static struct dentry *ab5500_reg_file;
+static struct dentry *ab5500_bank_file;
+static struct dentry *ab5500_address_file;
+static struct dentry *ab5500_val_file;
+
+void __init ab5500_setup_debugfs(struct ab5500 *ab)
+{
+       ab->debug_bank = AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP;
+       ab->debug_address = AB5500_CHIP_ID;
+
+       ab5500_dir = debugfs_create_dir("ab5500", NULL);
+       if (!ab5500_dir)
+               goto exit_no_debugfs;
+
+       ab5500_reg_file = debugfs_create_file("all-bank-registers",
+               S_IRUGO, ab5500_dir, ab, &ab5500_registers_fops);
+       if (!ab5500_reg_file)
+               goto exit_destroy_dir;
+
+       ab5500_bank_file = debugfs_create_file("register-bank",
+               (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_bank_fops);
+       if (!ab5500_bank_file)
+               goto exit_destroy_reg;
+
+       ab5500_address_file = debugfs_create_file("register-address",
+               (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_address_fops);
+       if (!ab5500_address_file)
+               goto exit_destroy_bank;
+
+       ab5500_val_file = debugfs_create_file("register-value",
+               (S_IRUGO | S_IWUGO), ab5500_dir, ab, &ab5500_val_fops);
+       if (!ab5500_val_file)
+               goto exit_destroy_address;
+
+       return;
+
+exit_destroy_address:
+       debugfs_remove(ab5500_address_file);
+exit_destroy_bank:
+       debugfs_remove(ab5500_bank_file);
+exit_destroy_reg:
+       debugfs_remove(ab5500_reg_file);
+exit_destroy_dir:
+       debugfs_remove(ab5500_dir);
+exit_no_debugfs:
+       dev_err(ab->dev, "failed to create debugfs entries.\n");
+       return;
+}
+
+void __exit ab5500_remove_debugfs(void)
+{
+       debugfs_remove(ab5500_val_file);
+       debugfs_remove(ab5500_address_file);
+       debugfs_remove(ab5500_bank_file);
+       debugfs_remove(ab5500_reg_file);
+       debugfs_remove(ab5500_dir);
+}
diff --git a/drivers/mfd/ab5500-debugfs.h b/drivers/mfd/ab5500-debugfs.h
new file mode 100644 (file)
index 0000000..7330a9b
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson
+ * License terms: GNU General Public License (GPL) version 2
+ * Debugfs interface to the AB5500 core driver
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+void ab5500_setup_debugfs(struct ab5500 *ab);
+void ab5500_remove_debugfs(void);
+
+#else /* !CONFIG_DEBUG_FS */
+
+static inline void ab5500_setup_debugfs(struct ab5500 *ab)
+{
+}
+
+static inline void ab5500_remove_debugfs(void)
+{
+}
+
+#endif
index 387705e..1e91738 100644 (file)
@@ -92,6 +92,8 @@
 #define AB8500_REV_REG                 0x80
 #define AB8500_SWITCH_OFF_STATUS       0x00
 
+#define AB8500_TURN_ON_STATUS          0x00
+
 /*
  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
  * numbers are indexed into this array with (num / 8).
@@ -293,6 +295,7 @@ static struct irq_chip ab8500_irq_chip = {
        .irq_bus_lock           = ab8500_irq_lock,
        .irq_bus_sync_unlock    = ab8500_irq_sync_unlock,
        .irq_mask               = ab8500_irq_mask,
+       .irq_disable            = ab8500_irq_mask,
        .irq_unmask             = ab8500_irq_unmask,
 };
 
@@ -811,12 +814,40 @@ static ssize_t show_switch_off_status(struct device *dev,
        return sprintf(buf, "%#x\n", value);
 }
 
+/*
+ * ab8500 has turned on due to (TURN_ON_STATUS):
+ * 0x01 PORnVbat
+ * 0x02 PonKey1dbF
+ * 0x04 PonKey2dbF
+ * 0x08 RTCAlarm
+ * 0x10 MainChDet
+ * 0x20 VbusDet
+ * 0x40 UsbIDDetect
+ * 0x80 Reserved
+ */
+static ssize_t show_turn_on_status(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       int ret;
+       u8 value;
+       struct ab8500 *ab8500;
+
+       ab8500 = dev_get_drvdata(dev);
+       ret = get_register_interruptible(ab8500, AB8500_SYS_CTRL1_BLOCK,
+               AB8500_TURN_ON_STATUS, &value);
+       if (ret < 0)
+               return ret;
+       return sprintf(buf, "%#x\n", value);
+}
+
 static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
 static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
+static DEVICE_ATTR(turn_on_status, S_IRUGO, show_turn_on_status, NULL);
 
 static struct attribute *ab8500_sysfs_entries[] = {
        &dev_attr_chip_id.attr,
        &dev_attr_switch_off_status.attr,
+       &dev_attr_turn_on_status.attr,
        NULL,
 };
 
@@ -843,11 +874,11 @@ int __devinit ab8500_init(struct ab8500 *ab8500)
                return ret;
 
        switch (value) {
-       case AB8500_CUTEARLY:
        case AB8500_CUT1P0:
        case AB8500_CUT1P1:
        case AB8500_CUT2P0:
        case AB8500_CUT3P0:
+       case AB8500_CUT3P3:
                dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
                break;
        default:
index f16afb2..e985d17 100644 (file)
@@ -143,12 +143,15 @@ struct ab8500_gpadc *ab8500_gpadc_get(char *name)
 }
 EXPORT_SYMBOL(ab8500_gpadc_get);
 
-static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input,
+/**
+ * ab8500_gpadc_ad_to_voltage() - Convert a raw ADC value to a voltage
+ */
+int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 channel,
        int ad_value)
 {
        int res;
 
-       switch (input) {
+       switch (channel) {
        case MAIN_CHARGER_V:
                /* For some reason we don't have calibrated data */
                if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) {
@@ -232,18 +235,46 @@ static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input,
        }
        return res;
 }
+EXPORT_SYMBOL(ab8500_gpadc_ad_to_voltage);
 
 /**
  * ab8500_gpadc_convert() - gpadc conversion
- * @input:     analog input to be converted to digital data
+ * @channel:   analog channel to be converted to digital data
  *
  * This function converts the selected analog i/p to digital
  * data.
  */
-int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
+int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel)
+{
+       int ad_value;
+       int voltage;
+
+       ad_value = ab8500_gpadc_read_raw(gpadc, channel);
+       if (ad_value < 0) {
+               dev_err(gpadc->dev, "GPADC raw value failed ch: %d\n", channel);
+               return ad_value;
+       }
+
+       voltage = ab8500_gpadc_ad_to_voltage(gpadc, channel, ad_value);
+
+       if (voltage < 0)
+               dev_err(gpadc->dev, "GPADC to voltage conversion failed ch:"
+                       " %d AD: 0x%x\n", channel, ad_value);
+
+       return voltage;
+}
+EXPORT_SYMBOL(ab8500_gpadc_convert);
+
+/**
+ * ab8500_gpadc_read_raw() - gpadc read
+ * @channel:   analog channel to be read
+ *
+ * This function obtains the raw ADC value, this then needs
+ * to be converted by calling ab8500_gpadc_ad_to_voltage()
+ */
+int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel)
 {
        int ret;
-       u16 data = 0;
        int looplimit = 0;
        u8 val, low_data, high_data;
 
@@ -278,9 +309,9 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
                goto out;
        }
 
-       /* Select the input source and set average samples to 16 */
+       /* Select the channel source and set average samples to 16 */
        ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
-               AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16));
+               AB8500_GPADC_CTRL2_REG, (channel | SW_AVG_16));
        if (ret < 0) {
                dev_err(gpadc->dev,
                        "gpadc_conversion: set avg samples failed\n");
@@ -292,7 +323,7 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
         * charging current sense if it needed, ABB 3.0 needs some special
         * treatment too.
         */
-       switch (input) {
+       switch (channel) {
        case MAIN_CHARGER_C:
        case USB_CHARGER_C:
                ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
@@ -359,7 +390,6 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
                goto out;
        }
 
-       data = (high_data << 8) | low_data;
        /* Disable GPADC */
        ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
                AB8500_GPADC_CTRL1_REG, DIS_GPADC);
@@ -370,8 +400,8 @@ int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
        /* Disable VTVout LDO this is required for GPADC */
        regulator_disable(gpadc->regu);
        mutex_unlock(&gpadc->ab8500_gpadc_lock);
-       ret = ab8500_gpadc_ad_to_voltage(gpadc, input, data);
-       return ret;
+
+       return (high_data << 8) | low_data;
 
 out:
        /*
@@ -385,10 +415,10 @@ out:
        regulator_disable(gpadc->regu);
        mutex_unlock(&gpadc->ab8500_gpadc_lock);
        dev_err(gpadc->dev,
-               "gpadc_conversion: Failed to AD convert channel %d\n", input);
+               "gpadc_conversion: Failed to AD convert channel %d\n", channel);
        return ret;
 }
-EXPORT_SYMBOL(ab8500_gpadc_convert);
+EXPORT_SYMBOL(ab8500_gpadc_read_raw);
 
 /**
  * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion
index c71ae09..3bd85bd 100644 (file)
@@ -584,7 +584,7 @@ static int asic3_gpio_remove(struct platform_device *pdev)
        return gpiochip_remove(&asic->gpio);
 }
 
-static int asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
+static void asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
 {
        unsigned long flags;
        u32 cdex;
@@ -596,8 +596,6 @@ static int asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
                asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
        }
        spin_unlock_irqrestore(&asic->lock, flags);
-
-       return 0;
 }
 
 static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
@@ -779,6 +777,8 @@ static struct mfd_cell asic3_cell_mmc = {
        .name          = "tmio-mmc",
        .enable        = asic3_mmc_enable,
        .disable       = asic3_mmc_disable,
+       .suspend       = asic3_mmc_disable,
+       .resume        = asic3_mmc_enable,
        .platform_data = &asic3_mmc_data,
        .pdata_size    = sizeof(asic3_mmc_data),
        .num_resources = ARRAY_SIZE(asic3_mmc_resources),
@@ -811,24 +811,43 @@ static int asic3_leds_disable(struct platform_device *pdev)
        return 0;
 }
 
+static int asic3_leds_suspend(struct platform_device *pdev)
+{
+       const struct mfd_cell *cell = mfd_get_cell(pdev);
+       struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
+
+       while (asic3_gpio_get(&asic->gpio, ASIC3_GPIO(C, cell->id)) != 0)
+               msleep(1);
+
+       asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
+
+       return 0;
+}
+
 static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = {
        [0] = {
                .name          = "leds-asic3",
                .id            = 0,
                .enable        = asic3_leds_enable,
                .disable       = asic3_leds_disable,
+               .suspend       = asic3_leds_suspend,
+               .resume        = asic3_leds_enable,
        },
        [1] = {
                .name          = "leds-asic3",
                .id            = 1,
                .enable        = asic3_leds_enable,
                .disable       = asic3_leds_disable,
+               .suspend       = asic3_leds_suspend,
+               .resume        = asic3_leds_enable,
        },
        [2] = {
                .name          = "leds-asic3",
                .id            = 2,
                .enable        = asic3_leds_enable,
                .disable       = asic3_leds_disable,
+               .suspend       = asic3_leds_suspend,
+               .resume        = asic3_leds_enable,
        },
 };
 
@@ -949,6 +968,7 @@ static int __init asic3_probe(struct platform_device *pdev)
                goto out_unmap;
        }
 
+       asic->gpio.label = "asic3";
        asic->gpio.base = pdata->gpio_base;
        asic->gpio.ngpio = ASIC3_NUM_GPIOS;
        asic->gpio.get = asic3_gpio_get;
index 2fadbae..1b79c37 100644 (file)
@@ -523,7 +523,7 @@ static int __devinit da903x_probe(struct i2c_client *client,
        chip->ops->read_events(chip, &tmp);
 
        ret = request_irq(client->irq, da903x_irq_handler,
-                       IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+                       IRQF_TRIGGER_FALLING,
                        "da903x", chip);
        if (ret) {
                dev_err(&client->dev, "failed to request irq %d\n",
index 9dbb3ca..bb115b2 100644 (file)
 #include <linux/jiffies.h>
 #include <linux/bitops.h>
 #include <linux/interrupt.h>
-#include <linux/mfd/db5500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/db5500-regs.h>
-#include "db5500-prcmu-regs.h"
+#include "dbx500-prcmu-regs.h"
 
 #define _PRCM_MB_HEADER (tcdm_base + 0xFE8)
 #define PRCM_REQ_MB0_HEADER (_PRCM_MB_HEADER + 0x0)
@@ -109,15 +109,18 @@ enum mb5_header {
 #define PRCMU_DSI_CLOCK_SETTING                        0x00000128
 /* TVCLK_MGT PLLSW=001 (PLLSOC0) PLLDIV=0x13, = 19.05 MHZ */
 #define PRCMU_DSI_LP_CLOCK_SETTING             0x00000135
-#define PRCMU_PLLDSI_FREQ_SETTING              0x0004013C
+#define PRCMU_PLLDSI_FREQ_SETTING              0x00020121
 #define PRCMU_DSI_PLLOUT_SEL_SETTING           0x00000002
-#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV          0x03000101
+#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV          0x03000201
 #define PRCMU_DISABLE_ESCAPE_CLOCK_DIV         0x00000101
 
 #define PRCMU_ENABLE_PLLDSI                    0x00000001
 #define PRCMU_DISABLE_PLLDSI                   0x00000000
 
 #define PRCMU_DSI_RESET_SW                     0x00000003
+#define PRCMU_RESOUTN0_PIN                     0x00000001
+#define PRCMU_RESOUTN1_PIN                     0x00000002
+#define PRCMU_RESOUTN2_PIN                     0x00000004
 
 #define PRCMU_PLLDSI_LOCKP_LOCKED              0x3
 
@@ -315,31 +318,31 @@ static bool read_mailbox_0(void)
                r = false;
                break;
        }
-       writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
        return r;
 }
 
 static bool read_mailbox_1(void)
 {
-       writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
        return false;
 }
 
 static bool read_mailbox_2(void)
 {
-       writel(MBOX_BIT(2), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
        return false;
 }
 
 static bool read_mailbox_3(void)
 {
-       writel(MBOX_BIT(3), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
        return false;
 }
 
 static bool read_mailbox_4(void)
 {
-       writel(MBOX_BIT(4), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
        return false;
 }
 
@@ -360,19 +363,19 @@ static bool read_mailbox_5(void)
                print_unknown_header_warning(5, header);
                break;
        }
-       writel(MBOX_BIT(5), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
        return false;
 }
 
 static bool read_mailbox_6(void)
 {
-       writel(MBOX_BIT(6), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
        return false;
 }
 
 static bool read_mailbox_7(void)
 {
-       writel(MBOX_BIT(7), PRCM_ARM_IT1_CLEAR);
+       writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
        return false;
 }
 
@@ -434,7 +437,7 @@ int __init db5500_prcmu_init(void)
                return -ENODEV;
 
        /* Clean up the mailbox interrupts after pre-kernel code. */
-       writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLEAR);
+       writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
 
        r = request_threaded_irq(IRQ_DB5500_PRCMU1, prcmu_irq_handler,
                prcmu_irq_thread_fn, 0, "prcmu", NULL);
diff --git a/drivers/mfd/db8500-prcmu-regs.h b/drivers/mfd/db8500-prcmu-regs.h
deleted file mode 100644 (file)
index 3bbf04d..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * Copyright (C) STMicroelectronics 2009
- * Copyright (C) ST-Ericsson SA 2010
- *
- * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com>
- * Author: Sundar Iyer <sundar.iyer@stericsson.com>
- *
- * License Terms: GNU General Public License v2
- *
- * PRCM Unit registers
- */
-#ifndef __DB8500_PRCMU_REGS_H
-#define __DB8500_PRCMU_REGS_H
-
-#include <linux/bitops.h>
-#include <mach/hardware.h>
-
-#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
-
-#define PRCM_ARM_PLLDIVPS 0x118
-#define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE BITS(0, 5)
-#define PRCM_ARM_PLLDIVPS_MAX_MASK     0xF
-
-#define PRCM_PLLARM_LOCKP 0x0A8
-#define PRCM_PLLARM_LOCKP_PRCM_PLLARM_LOCKP3 BIT(1)
-
-#define PRCM_ARM_CHGCLKREQ 0x114
-#define PRCM_ARM_CHGCLKREQ_PRCM_ARM_CHGCLKREQ BIT(0)
-
-#define PRCM_PLLARM_ENABLE 0x98
-#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_ENABLE  BIT(0)
-#define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON BIT(8)
-
-#define PRCM_ARMCLKFIX_MGT     0x0
-#define PRCM_A9_RESETN_CLR     0x1f4
-#define PRCM_A9_RESETN_SET     0x1f0
-#define PRCM_ARM_LS_CLAMP      0x30C
-#define PRCM_SRAM_A9           0x308
-
-/* ARM WFI Standby signal register */
-#define PRCM_ARM_WFI_STANDBY   0x130
-#define PRCM_IOCR              0x310
-#define PRCM_IOCR_IOFORCE BIT(0)
-
-/* CPU mailbox registers */
-#define PRCM_MBOX_CPU_VAL 0x0FC
-#define PRCM_MBOX_CPU_SET 0x100
-
-/* Dual A9 core interrupt management unit registers */
-#define PRCM_A9_MASK_REQ 0x328
-#define PRCM_A9_MASK_REQ_PRCM_A9_MASK_REQ BIT(0)
-
-#define PRCM_A9_MASK_ACK       0x32C
-#define PRCM_ARMITMSK31TO0     0x11C
-#define PRCM_ARMITMSK63TO32    0x120
-#define PRCM_ARMITMSK95TO64    0x124
-#define PRCM_ARMITMSK127TO96   0x128
-#define PRCM_POWER_STATE_VAL   0x25C
-#define PRCM_ARMITVAL31TO0     0x260
-#define PRCM_ARMITVAL63TO32    0x264
-#define PRCM_ARMITVAL95TO64    0x268
-#define PRCM_ARMITVAL127TO96   0x26C
-
-#define PRCM_HOSTACCESS_REQ 0x334
-#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ BIT(0)
-
-#define PRCM_ARM_IT1_CLR 0x48C
-#define PRCM_ARM_IT1_VAL 0x494
-
-#define PRCM_ITSTATUS0         0x148
-#define PRCM_ITSTATUS1         0x150
-#define PRCM_ITSTATUS2         0x158
-#define PRCM_ITSTATUS3         0x160
-#define PRCM_ITSTATUS4         0x168
-#define PRCM_ITSTATUS5         0x484
-#define PRCM_ITCLEAR5          0x488
-#define PRCM_ARMIT_MASKXP70_IT 0x1018
-
-/* System reset register */
-#define PRCM_APE_SOFTRST 0x228
-
-/* Level shifter and clamp control registers */
-#define PRCM_MMIP_LS_CLAMP_SET 0x420
-#define PRCM_MMIP_LS_CLAMP_CLR 0x424
-
-/* PRCMU HW semaphore */
-#define PRCM_SEM 0x400
-#define PRCM_SEM_PRCM_SEM BIT(0)
-
-/* PRCMU clock/PLL/reset registers */
-#define PRCM_PLLDSI_FREQ       0x500
-#define PRCM_PLLDSI_ENABLE     0x504
-#define PRCM_PLLDSI_LOCKP      0x508
-#define PRCM_DSI_PLLOUT_SEL    0x530
-#define PRCM_DSITVCLK_DIV      0x52C
-#define PRCM_APE_RESETN_SET    0x1E4
-#define PRCM_APE_RESETN_CLR    0x1E8
-
-#define PRCM_TCR               0x1C8
-#define PRCM_TCR_TENSEL_MASK   BITS(0, 7)
-#define PRCM_TCR_STOP_TIMERS   BIT(16)
-#define PRCM_TCR_DOZE_MODE     BIT(17)
-
-#define PRCM_CLKOCR                    0x1CC
-#define PRCM_CLKOCR_CLKODIV0_SHIFT     0
-#define PRCM_CLKOCR_CLKODIV0_MASK      BITS(0, 5)
-#define PRCM_CLKOCR_CLKOSEL0_SHIFT     6
-#define PRCM_CLKOCR_CLKOSEL0_MASK      BITS(6, 8)
-#define PRCM_CLKOCR_CLKODIV1_SHIFT     16
-#define PRCM_CLKOCR_CLKODIV1_MASK      BITS(16, 21)
-#define PRCM_CLKOCR_CLKOSEL1_SHIFT     22
-#define PRCM_CLKOCR_CLKOSEL1_MASK      BITS(22, 24)
-#define PRCM_CLKOCR_CLK1TYPE           BIT(28)
-
-#define PRCM_SGACLK_MGT                0x014
-#define PRCM_UARTCLK_MGT       0x018
-#define PRCM_MSP02CLK_MGT      0x01C
-#define PRCM_MSP1CLK_MGT       0x288
-#define PRCM_I2CCLK_MGT                0x020
-#define PRCM_SDMMCCLK_MGT      0x024
-#define PRCM_SLIMCLK_MGT       0x028
-#define PRCM_PER1CLK_MGT       0x02C
-#define PRCM_PER2CLK_MGT       0x030
-#define PRCM_PER3CLK_MGT       0x034
-#define PRCM_PER5CLK_MGT       0x038
-#define PRCM_PER6CLK_MGT       0x03C
-#define PRCM_PER7CLK_MGT       0x040
-#define PRCM_LCDCLK_MGT                0x044
-#define PRCM_BMLCLK_MGT                0x04C
-#define PRCM_HSITXCLK_MGT      0x050
-#define PRCM_HSIRXCLK_MGT      0x054
-#define PRCM_HDMICLK_MGT       0x058
-#define PRCM_APEATCLK_MGT      0x05C
-#define PRCM_APETRACECLK_MGT   0x060
-#define PRCM_MCDECLK_MGT       0x064
-#define PRCM_IPI2CCLK_MGT      0x068
-#define PRCM_DSIALTCLK_MGT     0x06C
-#define PRCM_DMACLK_MGT                0x074
-#define PRCM_B2R2CLK_MGT       0x078
-#define PRCM_TVCLK_MGT         0x07C
-#define PRCM_UNIPROCLK_MGT     0x278
-#define PRCM_SSPCLK_MGT                0x280
-#define PRCM_RNGCLK_MGT                0x284
-#define PRCM_UICCCLK_MGT       0x27C
-
-#define PRCM_CLK_MGT_CLKPLLDIV_MASK    BITS(0, 4)
-#define PRCM_CLK_MGT_CLKPLLSW_MASK     BITS(5, 7)
-#define PRCM_CLK_MGT_CLKEN             BIT(8)
-
-/* ePOD and memory power signal control registers */
-#define PRCM_EPOD_C_SET                0x410
-#define PRCM_SRAM_LS_SLEEP     0x304
-
-/* Debug power control unit registers */
-#define PRCM_POWER_STATE_SET 0x254
-
-/* Miscellaneous unit registers */
-#define PRCM_DSI_SW_RESET 0x324
-#define PRCM_GPIOCR            0x138
-
-/* GPIOCR register */
-#define PRCM_GPIOCR_SPI2_SELECT BIT(23)
-
-#define PRCM_DDR_SUBSYS_APE_MINBW  0x438
-
-#endif /* __DB8500_PRCMU_REGS_H */
index 02a15d7..a25ab9c 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
 #include <linux/mfd/core.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <linux/regulator/db8500-prcmu.h>
 #include <linux/regulator/machine.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/db8500-regs.h>
 #include <mach/id.h>
-#include "db8500-prcmu-regs.h"
+#include "dbx500-prcmu-regs.h"
 
 /* Offset for the firmware version within the TCPM */
 #define PRCMU_FW_VERSION_OFFSET 0xA4
 #define MB1H_REQUEST_APE_OPP_100_VOLT 0x3
 #define MB1H_RELEASE_APE_OPP_100_VOLT 0x4
 #define MB1H_RELEASE_USB_WAKEUP 0x5
+#define MB1H_PLL_ON_OFF 0x6
 
 /* Mailbox 1 Requests */
 #define PRCM_REQ_MB1_ARM_OPP                   (PRCM_REQ_MB1 + 0x0)
 #define PRCM_REQ_MB1_APE_OPP                   (PRCM_REQ_MB1 + 0x1)
-#define PRCM_REQ_MB1_APE_OPP_100_RESTORE       (PRCM_REQ_MB1 + 0x4)
-#define PRCM_REQ_MB1_ARM_OPP_100_RESTORE       (PRCM_REQ_MB1 + 0x8)
+#define PRCM_REQ_MB1_PLL_ON_OFF                        (PRCM_REQ_MB1 + 0x4)
+#define PLL_SOC1_OFF   0x4
+#define PLL_SOC1_ON    0x8
 
 /* Mailbox 1 ACKs */
 #define PRCM_ACK_MB1_CURRENT_ARM_OPP   (PRCM_ACK_MB1 + 0x0)
 #define MB4H_HOTDOG    0x12
 #define MB4H_HOTMON    0x13
 #define MB4H_HOT_PERIOD        0x14
+#define MB4H_A9WDOG_CONF 0x16
+#define MB4H_A9WDOG_EN   0x17
+#define MB4H_A9WDOG_DIS  0x18
+#define MB4H_A9WDOG_LOAD 0x19
+#define MB4H_A9WDOG_KICK 0x20
 
 /* Mailbox 4 Requests */
 #define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE      (PRCM_REQ_MB4 + 0x0)
 #define PRCM_REQ_MB4_HOT_PERIOD                        (PRCM_REQ_MB4 + 0x0)
 #define HOTMON_CONFIG_LOW                      BIT(0)
 #define HOTMON_CONFIG_HIGH                     BIT(1)
+#define PRCM_REQ_MB4_A9WDOG_0                  (PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_A9WDOG_1                  (PRCM_REQ_MB4 + 0x1)
+#define PRCM_REQ_MB4_A9WDOG_2                  (PRCM_REQ_MB4 + 0x2)
+#define PRCM_REQ_MB4_A9WDOG_3                  (PRCM_REQ_MB4 + 0x3)
+#define A9WDOG_AUTO_OFF_EN                     BIT(7)
+#define A9WDOG_AUTO_OFF_DIS                    0
+#define A9WDOG_ID_MASK                         0xf
 
 /* Mailbox 5 Requests */
 #define PRCM_REQ_MB5_I2C_SLAVE_OP      (PRCM_REQ_MB5 + 0x0)
@@ -412,7 +426,7 @@ struct clk_mgt {
 
 static DEFINE_SPINLOCK(clk_mgt_lock);
 
-#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT), 0 }
+#define CLK_MGT_ENTRY(_name)[PRCMU_##_name] = { (PRCM_##_name##_MGT_OFF), 0 }
 struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
        CLK_MGT_ENTRY(SGACLK),
        CLK_MGT_ENTRY(UARTCLK),
@@ -445,6 +459,35 @@ struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
        CLK_MGT_ENTRY(UICCCLK),
 };
 
+static struct regulator *hwacc_regulator[NUM_HW_ACC];
+static struct regulator *hwacc_ret_regulator[NUM_HW_ACC];
+
+static bool hwacc_enabled[NUM_HW_ACC];
+static bool hwacc_ret_enabled[NUM_HW_ACC];
+
+static const char *hwacc_regulator_name[NUM_HW_ACC] = {
+       [HW_ACC_SVAMMDSP]       = "hwacc-sva-mmdsp",
+       [HW_ACC_SVAPIPE]        = "hwacc-sva-pipe",
+       [HW_ACC_SIAMMDSP]       = "hwacc-sia-mmdsp",
+       [HW_ACC_SIAPIPE]        = "hwacc-sia-pipe",
+       [HW_ACC_SGA]            = "hwacc-sga",
+       [HW_ACC_B2R2]           = "hwacc-b2r2",
+       [HW_ACC_MCDE]           = "hwacc-mcde",
+       [HW_ACC_ESRAM1]         = "hwacc-esram1",
+       [HW_ACC_ESRAM2]         = "hwacc-esram2",
+       [HW_ACC_ESRAM3]         = "hwacc-esram3",
+       [HW_ACC_ESRAM4]         = "hwacc-esram4",
+};
+
+static const char *hwacc_ret_regulator_name[NUM_HW_ACC] = {
+       [HW_ACC_SVAMMDSP]       = "hwacc-sva-mmdsp-ret",
+       [HW_ACC_SIAMMDSP]       = "hwacc-sia-mmdsp-ret",
+       [HW_ACC_ESRAM1]         = "hwacc-esram1-ret",
+       [HW_ACC_ESRAM2]         = "hwacc-esram2-ret",
+       [HW_ACC_ESRAM3]         = "hwacc-esram3-ret",
+       [HW_ACC_ESRAM4]         = "hwacc-esram4-ret",
+};
+
 /*
 * Used by MCDE to setup all necessary PRCMU registers
 */
@@ -493,55 +536,51 @@ static struct {
 } prcmu_version;
 
 
-int prcmu_enable_dsipll(void)
+int db8500_prcmu_enable_dsipll(void)
 {
        int i;
        unsigned int plldsifreq;
 
        /* Clear DSIPLL_RESETN */
-       writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_CLR));
+       writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_CLR);
        /* Unclamp DSIPLL in/out */
-       writel(PRCMU_UNCLAMP_DSIPLL, (_PRCMU_BASE + PRCM_MMIP_LS_CLAMP_CLR));
+       writel(PRCMU_UNCLAMP_DSIPLL, PRCM_MMIP_LS_CLAMP_CLR);
 
        if (prcmu_is_u8400())
                plldsifreq = PRCMU_PLLDSI_FREQ_SETTING_U8400;
        else
                plldsifreq = PRCMU_PLLDSI_FREQ_SETTING;
        /* Set DSI PLL FREQ */
-       writel(plldsifreq, (_PRCMU_BASE + PRCM_PLLDSI_FREQ));
-       writel(PRCMU_DSI_PLLOUT_SEL_SETTING,
-               (_PRCMU_BASE + PRCM_DSI_PLLOUT_SEL));
+       writel(plldsifreq, PRCM_PLLDSI_FREQ);
+       writel(PRCMU_DSI_PLLOUT_SEL_SETTING, PRCM_DSI_PLLOUT_SEL);
        /* Enable Escape clocks */
-       writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV,
-                                       (_PRCMU_BASE + PRCM_DSITVCLK_DIV));
+       writel(PRCMU_ENABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
 
        /* Start DSI PLL */
-       writel(PRCMU_ENABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE));
+       writel(PRCMU_ENABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
        /* Reset DSI PLL */
-       writel(PRCMU_DSI_RESET_SW, (_PRCMU_BASE + PRCM_DSI_SW_RESET));
+       writel(PRCMU_DSI_RESET_SW, PRCM_DSI_SW_RESET);
        for (i = 0; i < 10; i++) {
-               if ((readl(_PRCMU_BASE + PRCM_PLLDSI_LOCKP) &
-                       PRCMU_PLLDSI_LOCKP_LOCKED)
+               if ((readl(PRCM_PLLDSI_LOCKP) & PRCMU_PLLDSI_LOCKP_LOCKED)
                                        == PRCMU_PLLDSI_LOCKP_LOCKED)
                        break;
                udelay(100);
        }
        /* Set DSIPLL_RESETN */
-       writel(PRCMU_RESET_DSIPLL, (_PRCMU_BASE + PRCM_APE_RESETN_SET));
+       writel(PRCMU_RESET_DSIPLL, PRCM_APE_RESETN_SET);
        return 0;
 }
 
-int prcmu_disable_dsipll(void)
+int db8500_prcmu_disable_dsipll(void)
 {
        /* Disable dsi pll */
-       writel(PRCMU_DISABLE_PLLDSI, (_PRCMU_BASE + PRCM_PLLDSI_ENABLE));
+       writel(PRCMU_DISABLE_PLLDSI, PRCM_PLLDSI_ENABLE);
        /* Disable  escapeclock */
-       writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV,
-                                       (_PRCMU_BASE + PRCM_DSITVCLK_DIV));
+       writel(PRCMU_DISABLE_ESCAPE_CLOCK_DIV, PRCM_DSITVCLK_DIV);
        return 0;
 }
 
-int prcmu_set_display_clocks(void)
+int db8500_prcmu_set_display_clocks(void)
 {
        unsigned long flags;
        unsigned int dsiclk;
@@ -554,15 +593,15 @@ int prcmu_set_display_clocks(void)
        spin_lock_irqsave(&clk_mgt_lock, flags);
 
        /* Grab the HW semaphore. */
-       while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
                cpu_relax();
 
-       writel(dsiclk, (_PRCMU_BASE + PRCM_HDMICLK_MGT));
-       writel(PRCMU_DSI_LP_CLOCK_SETTING, (_PRCMU_BASE + PRCM_TVCLK_MGT));
-       writel(PRCMU_DPI_CLOCK_SETTING, (_PRCMU_BASE + PRCM_LCDCLK_MGT));
+       writel(dsiclk, PRCM_HDMICLK_MGT);
+       writel(PRCMU_DSI_LP_CLOCK_SETTING, PRCM_TVCLK_MGT);
+       writel(PRCMU_DPI_CLOCK_SETTING, PRCM_LCDCLK_MGT);
 
        /* Release the HW semaphore. */
-       writel(0, (_PRCMU_BASE + PRCM_SEM));
+       writel(0, PRCM_SEM);
 
        spin_unlock_irqrestore(&clk_mgt_lock, flags);
 
@@ -578,8 +617,8 @@ void prcmu_enable_spi2(void)
        unsigned long flags;
 
        spin_lock_irqsave(&gpiocr_lock, flags);
-       reg = readl(_PRCMU_BASE + PRCM_GPIOCR);
-       writel(reg | PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR);
+       reg = readl(PRCM_GPIOCR);
+       writel(reg | PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
        spin_unlock_irqrestore(&gpiocr_lock, flags);
 }
 
@@ -592,8 +631,8 @@ void prcmu_disable_spi2(void)
        unsigned long flags;
 
        spin_lock_irqsave(&gpiocr_lock, flags);
-       reg = readl(_PRCMU_BASE + PRCM_GPIOCR);
-       writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, _PRCMU_BASE + PRCM_GPIOCR);
+       reg = readl(PRCM_GPIOCR);
+       writel(reg & ~PRCM_GPIOCR_SPI2_SELECT, PRCM_GPIOCR);
        spin_unlock_irqrestore(&gpiocr_lock, flags);
 }
 
@@ -701,7 +740,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
 
        spin_lock_irqsave(&clkout_lock, flags);
 
-       val = readl(_PRCMU_BASE + PRCM_CLKOCR);
+       val = readl(PRCM_CLKOCR);
        if (val & div_mask) {
                if (div) {
                        if ((val & mask) != bits) {
@@ -715,7 +754,7 @@ int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
                        }
                }
        }
-       writel((bits | (val & ~mask)), (_PRCMU_BASE + PRCM_CLKOCR));
+       writel((bits | (val & ~mask)), PRCM_CLKOCR);
        requests[clkout] += (div ? 1 : -1);
 
 unlock_and_return:
@@ -724,7 +763,7 @@ unlock_and_return:
        return r;
 }
 
-int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
+int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 {
        unsigned long flags;
 
@@ -732,7 +771,7 @@ int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 
        spin_lock_irqsave(&mb0_transfer.lock, flags);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
                cpu_relax();
 
        writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
@@ -741,7 +780,7 @@ int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
        writeb((keep_ulp_clk ? 1 : 0),
                (tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE));
        writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI));
-       writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
        spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 
@@ -770,18 +809,18 @@ static void config_wakeups(void)
                return;
 
        for (i = 0; i < 2; i++) {
-               while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+               while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
                        cpu_relax();
                writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500));
                writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500));
                writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
-               writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+               writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
        }
        last_dbb_events = dbb_events;
        last_abb_events = abb_events;
 }
 
-void prcmu_enable_wakeups(u32 wakeups)
+void db8500_prcmu_enable_wakeups(u32 wakeups)
 {
        unsigned long flags;
        u32 bits;
@@ -802,7 +841,7 @@ void prcmu_enable_wakeups(u32 wakeups)
        spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
 
-void prcmu_config_abb_event_readout(u32 abb_events)
+void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 {
        unsigned long flags;
 
@@ -814,7 +853,7 @@ void prcmu_config_abb_event_readout(u32 abb_events)
        spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
 
-void prcmu_get_abb_event_buffer(void __iomem **buf)
+void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
 {
        if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
                *buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500);
@@ -823,13 +862,13 @@ void prcmu_get_abb_event_buffer(void __iomem **buf)
 }
 
 /**
- * prcmu_set_arm_opp - set the appropriate ARM OPP
+ * db8500_prcmu_set_arm_opp - set the appropriate ARM OPP
  * @opp: The new ARM operating point to which transition is to be made
  * Returns: 0 on success, non-zero on failure
  *
  * This function sets the the operating point of the ARM.
  */
-int prcmu_set_arm_opp(u8 opp)
+int db8500_prcmu_set_arm_opp(u8 opp)
 {
        int r;
 
@@ -840,14 +879,14 @@ int prcmu_set_arm_opp(u8 opp)
 
        mutex_lock(&mb1_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
                cpu_relax();
 
        writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
        writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
        writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
 
-       writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb1_transfer.work);
 
        if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
@@ -860,11 +899,11 @@ int prcmu_set_arm_opp(u8 opp)
 }
 
 /**
- * prcmu_get_arm_opp - get the current ARM OPP
+ * db8500_prcmu_get_arm_opp - get the current ARM OPP
  *
  * Returns: the current ARM OPP
  */
-int prcmu_get_arm_opp(void)
+int db8500_prcmu_get_arm_opp(void)
 {
        return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
 }
@@ -876,7 +915,7 @@ int prcmu_get_arm_opp(void)
  */
 int prcmu_get_ddr_opp(void)
 {
-       return readb(_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW);
+       return readb(PRCM_DDR_SUBSYS_APE_MINBW);
 }
 
 /**
@@ -892,7 +931,7 @@ int prcmu_set_ddr_opp(u8 opp)
                return -EINVAL;
        /* Changing the DDR OPP can hang the hardware pre-v21 */
        if (cpu_is_u8500v20_or_later() && !cpu_is_u8500v20())
-               writeb(opp, (_PRCMU_BASE + PRCM_DDR_SUBSYS_APE_MINBW));
+               writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW);
 
        return 0;
 }
@@ -909,14 +948,14 @@ int prcmu_set_ape_opp(u8 opp)
 
        mutex_lock(&mb1_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
                cpu_relax();
 
        writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
        writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
        writeb(opp, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
 
-       writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb1_transfer.work);
 
        if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
@@ -966,12 +1005,12 @@ int prcmu_request_ape_opp_100_voltage(bool enable)
                header = MB1H_RELEASE_APE_OPP_100_VOLT;
        }
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
                cpu_relax();
 
        writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
 
-       writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb1_transfer.work);
 
        if ((mb1_transfer.ack.header != header) ||
@@ -995,13 +1034,13 @@ int prcmu_release_usb_wakeup_state(void)
 
        mutex_lock(&mb1_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
                cpu_relax();
 
        writeb(MB1H_RELEASE_USB_WAKEUP,
                (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
 
-       writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb1_transfer.work);
 
        if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
@@ -1013,15 +1052,169 @@ int prcmu_release_usb_wakeup_state(void)
        return r;
 }
 
+static int request_pll(u8 clock, bool enable)
+{
+       int r = 0;
+
+       if (clock == PRCMU_PLLSOC1)
+               clock = (enable ? PLL_SOC1_ON : PLL_SOC1_OFF);
+       else
+               return -EINVAL;
+
+       mutex_lock(&mb1_transfer.lock);
+
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+               cpu_relax();
+
+       writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+       writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF));
+
+       writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
+       wait_for_completion(&mb1_transfer.work);
+
+       if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF)
+               r = -EIO;
+
+       mutex_unlock(&mb1_transfer.lock);
+
+       return r;
+}
+
 /**
- * prcmu_set_epod - set the state of a EPOD (power domain)
+ * prcmu_set_hwacc - set the power state of a h/w accelerator
+ * @hwacc_dev: The hardware accelerator (enum hw_acc_dev).
+ * @state: The new power state (enum hw_acc_state).
+ *
+ * This function sets the power state of a hardware accelerator.
+ * This function should not be called from interrupt context.
+ *
+ * NOTE! Deprecated, to be removed when all users switched over to use the
+ * regulator framework API.
+ */
+int prcmu_set_hwacc(u16 hwacc_dev, u8 state)
+{
+       int r = 0;
+       bool ram_retention = false;
+       bool enable, enable_ret;
+
+       /* check argument */
+       BUG_ON(hwacc_dev >= NUM_HW_ACC);
+
+       /* get state of switches */
+       enable = hwacc_enabled[hwacc_dev];
+       enable_ret = hwacc_ret_enabled[hwacc_dev];
+
+       /* set flag if retention is possible */
+       switch (hwacc_dev) {
+       case HW_ACC_SVAMMDSP:
+       case HW_ACC_SIAMMDSP:
+       case HW_ACC_ESRAM1:
+       case HW_ACC_ESRAM2:
+       case HW_ACC_ESRAM3:
+       case HW_ACC_ESRAM4:
+               ram_retention = true;
+               break;
+       }
+
+       /* check argument */
+       BUG_ON(state > HW_ON);
+       BUG_ON(state == HW_OFF_RAMRET && !ram_retention);
+
+       /* modify enable flags */
+       switch (state) {
+       case HW_OFF:
+               enable_ret = false;
+               enable = false;
+               break;
+       case HW_ON:
+               enable = true;
+               break;
+       case HW_OFF_RAMRET:
+               enable_ret = true;
+               enable = false;
+               break;
+       }
+
+       /* get regulator (lazy) */
+       if (hwacc_regulator[hwacc_dev] == NULL) {
+               hwacc_regulator[hwacc_dev] = regulator_get(NULL,
+                       hwacc_regulator_name[hwacc_dev]);
+               if (IS_ERR(hwacc_regulator[hwacc_dev])) {
+                       pr_err("prcmu: failed to get supply %s\n",
+                               hwacc_regulator_name[hwacc_dev]);
+                       r = PTR_ERR(hwacc_regulator[hwacc_dev]);
+                       goto out;
+               }
+       }
+
+       if (ram_retention) {
+               if (hwacc_ret_regulator[hwacc_dev] == NULL) {
+                       hwacc_ret_regulator[hwacc_dev] = regulator_get(NULL,
+                               hwacc_ret_regulator_name[hwacc_dev]);
+                       if (IS_ERR(hwacc_ret_regulator[hwacc_dev])) {
+                               pr_err("prcmu: failed to get supply %s\n",
+                                       hwacc_ret_regulator_name[hwacc_dev]);
+                               r = PTR_ERR(hwacc_ret_regulator[hwacc_dev]);
+                               goto out;
+                       }
+               }
+       }
+
+       /* set regulators */
+       if (ram_retention) {
+               if (enable_ret && !hwacc_ret_enabled[hwacc_dev]) {
+                       r = regulator_enable(hwacc_ret_regulator[hwacc_dev]);
+                       if (r < 0) {
+                               pr_err("prcmu_set_hwacc: ret enable failed\n");
+                               goto out;
+                       }
+                       hwacc_ret_enabled[hwacc_dev] = true;
+               }
+       }
+
+       if (enable && !hwacc_enabled[hwacc_dev]) {
+               r = regulator_enable(hwacc_regulator[hwacc_dev]);
+               if (r < 0) {
+                       pr_err("prcmu_set_hwacc: enable failed\n");
+                       goto out;
+               }
+               hwacc_enabled[hwacc_dev] = true;
+       }
+
+       if (!enable && hwacc_enabled[hwacc_dev]) {
+               r = regulator_disable(hwacc_regulator[hwacc_dev]);
+               if (r < 0) {
+                       pr_err("prcmu_set_hwacc: disable failed\n");
+                       goto out;
+               }
+               hwacc_enabled[hwacc_dev] = false;
+       }
+
+       if (ram_retention) {
+               if (!enable_ret && hwacc_ret_enabled[hwacc_dev]) {
+                       r = regulator_disable(hwacc_ret_regulator[hwacc_dev]);
+                       if (r < 0) {
+                               pr_err("prcmu_set_hwacc: ret disable failed\n");
+                               goto out;
+                       }
+                       hwacc_ret_enabled[hwacc_dev] = false;
+               }
+       }
+
+out:
+       return r;
+}
+EXPORT_SYMBOL(prcmu_set_hwacc);
+
+/**
+ * db8500_prcmu_set_epod - set the state of a EPOD (power domain)
  * @epod_id: The EPOD to set
  * @epod_state: The new EPOD state
  *
  * This function sets the state of a EPOD (power domain). It may not be called
  * from interrupt context.
  */
-int prcmu_set_epod(u16 epod_id, u8 epod_state)
+int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
        int r = 0;
        bool ram_retention = false;
@@ -1048,7 +1241,7 @@ int prcmu_set_epod(u16 epod_id, u8 epod_state)
        mutex_lock(&mb2_transfer.lock);
 
        /* wait for mailbox */
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
                cpu_relax();
 
        /* fill in mailbox */
@@ -1058,7 +1251,7 @@ int prcmu_set_epod(u16 epod_id, u8 epod_state)
 
        writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2));
 
-       writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET);
 
        /*
         * The current firmware version does not handle errors correctly,
@@ -1145,13 +1338,13 @@ static int request_sysclk(bool enable)
 
        spin_lock_irqsave(&mb3_transfer.lock, flags);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
                cpu_relax();
 
        writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT));
 
        writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3));
-       writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
 
        spin_unlock_irqrestore(&mb3_transfer.lock, flags);
 
@@ -1177,7 +1370,7 @@ static int request_timclk(bool enable)
 
        if (!enable)
                val |= PRCM_TCR_STOP_TIMERS;
-       writel(val, (_PRCMU_BASE + PRCM_TCR));
+       writel(val, PRCM_TCR);
 
        return 0;
 }
@@ -1190,7 +1383,7 @@ static int request_reg_clock(u8 clock, bool enable)
        spin_lock_irqsave(&clk_mgt_lock, flags);
 
        /* Grab the HW semaphore. */
-       while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
                cpu_relax();
 
        val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
@@ -1203,34 +1396,61 @@ static int request_reg_clock(u8 clock, bool enable)
        writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
 
        /* Release the HW semaphore. */
-       writel(0, (_PRCMU_BASE + PRCM_SEM));
+       writel(0, PRCM_SEM);
 
        spin_unlock_irqrestore(&clk_mgt_lock, flags);
 
        return 0;
 }
 
+static int request_sga_clock(u8 clock, bool enable)
+{
+       u32 val;
+       int ret;
+
+       if (enable) {
+               val = readl(PRCM_CGATING_BYPASS);
+               writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
+       }
+
+       ret = request_reg_clock(clock, enable);
+
+       if (!ret && !enable) {
+               val = readl(PRCM_CGATING_BYPASS);
+               writel(val & ~PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
+       }
+
+       return ret;
+}
+
 /**
- * prcmu_request_clock() - Request for a clock to be enabled or disabled.
+ * db8500_prcmu_request_clock() - Request for a clock to be enabled or disabled.
  * @clock:      The clock for which the request is made.
  * @enable:     Whether the clock should be enabled (true) or disabled (false).
  *
  * This function should only be used by the clock implementation.
  * Do not use it from any other place!
  */
-int prcmu_request_clock(u8 clock, bool enable)
+int db8500_prcmu_request_clock(u8 clock, bool enable)
 {
-       if (clock < PRCMU_NUM_REG_CLOCKS)
-               return request_reg_clock(clock, enable);
-       else if (clock == PRCMU_TIMCLK)
+       switch(clock) {
+       case PRCMU_SGACLK:
+               return request_sga_clock(clock, enable);
+       case PRCMU_TIMCLK:
                return request_timclk(enable);
-       else if (clock == PRCMU_SYSCLK)
+       case PRCMU_SYSCLK:
                return request_sysclk(enable);
-       else
-               return -EINVAL;
+       case PRCMU_PLLSOC1:
+               return request_pll(clock, enable);
+       default:
+               break;
+       }
+       if (clock < PRCMU_NUM_REG_CLOCKS)
+               return request_reg_clock(clock, enable);
+       return -EINVAL;
 }
 
-int prcmu_config_esram0_deep_sleep(u8 state)
+int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 {
        if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) ||
            (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
@@ -1238,7 +1458,7 @@ int prcmu_config_esram0_deep_sleep(u8 state)
 
        mutex_lock(&mb4_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
                cpu_relax();
 
        writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
@@ -1248,7 +1468,7 @@ int prcmu_config_esram0_deep_sleep(u8 state)
               (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE));
        writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST));
 
-       writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb4_transfer.work);
 
        mutex_unlock(&mb4_transfer.lock);
@@ -1260,13 +1480,13 @@ int prcmu_config_hotdog(u8 threshold)
 {
        mutex_lock(&mb4_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
                cpu_relax();
 
        writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD));
        writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
 
-       writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb4_transfer.work);
 
        mutex_unlock(&mb4_transfer.lock);
@@ -1278,7 +1498,7 @@ int prcmu_config_hotmon(u8 low, u8 high)
 {
        mutex_lock(&mb4_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
                cpu_relax();
 
        writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW));
@@ -1287,7 +1507,7 @@ int prcmu_config_hotmon(u8 low, u8 high)
                (tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG));
        writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
 
-       writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb4_transfer.work);
 
        mutex_unlock(&mb4_transfer.lock);
@@ -1299,13 +1519,13 @@ static int config_hot_period(u16 val)
 {
        mutex_lock(&mb4_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
                cpu_relax();
 
        writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD));
        writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
 
-       writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb4_transfer.work);
 
        mutex_unlock(&mb4_transfer.lock);
@@ -1326,6 +1546,78 @@ int prcmu_stop_temp_sense(void)
        return config_hot_period(0xFFFF);
 }
 
+static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
+{
+
+       mutex_lock(&mb4_transfer.lock);
+
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
+               cpu_relax();
+
+       writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0));
+       writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1));
+       writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2));
+       writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3));
+
+       writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+
+       writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
+       wait_for_completion(&mb4_transfer.work);
+
+       mutex_unlock(&mb4_transfer.lock);
+
+       return 0;
+
+}
+
+int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+{
+       BUG_ON(num == 0 || num > 0xf);
+       return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0,
+                           sleep_auto_off ? A9WDOG_AUTO_OFF_EN :
+                           A9WDOG_AUTO_OFF_DIS);
+}
+
+int prcmu_enable_a9wdog(u8 id)
+{
+       return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
+}
+
+int prcmu_disable_a9wdog(u8 id)
+{
+       return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
+}
+
+int prcmu_kick_a9wdog(u8 id)
+{
+       return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
+}
+
+/*
+ * timeout is 28 bit, in ms.
+ */
+#define MAX_WATCHDOG_TIMEOUT 131000
+int prcmu_load_a9wdog(u8 id, u32 timeout)
+{
+       if (timeout > MAX_WATCHDOG_TIMEOUT)
+               /*
+                * Due to calculation bug in prcmu fw, timeouts
+                * can't be bigger than 131 seconds.
+                */
+               return -EINVAL;
+
+       return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
+                           (id & A9WDOG_ID_MASK) |
+                           /*
+                            * Put the lowest 28 bits of timeout at
+                            * offset 4. Four first bits are used for id.
+                            */
+                           (u8)((timeout << 4) & 0xf0),
+                           (u8)((timeout >> 4) & 0xff),
+                           (u8)((timeout >> 12) & 0xff),
+                           (u8)((timeout >> 20) & 0xff));
+}
+
 /**
  * prcmu_set_clock_divider() - Configure the clock divider.
  * @clock:     The clock for which the request is made.
@@ -1345,7 +1637,7 @@ int prcmu_set_clock_divider(u8 clock, u8 divider)
        spin_lock_irqsave(&clk_mgt_lock, flags);
 
        /* Grab the HW semaphore. */
-       while ((readl(_PRCMU_BASE + PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+       while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
                cpu_relax();
 
        val = readl(_PRCMU_BASE + clk_mgt[clock].offset);
@@ -1354,7 +1646,7 @@ int prcmu_set_clock_divider(u8 clock, u8 divider)
        writel(val, (_PRCMU_BASE + clk_mgt[clock].offset));
 
        /* Release the HW semaphore. */
-       writel(0, (_PRCMU_BASE + PRCM_SEM));
+       writel(0, PRCM_SEM);
 
        spin_unlock_irqrestore(&clk_mgt_lock, flags);
 
@@ -1380,7 +1672,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 
        mutex_lock(&mb5_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
                cpu_relax();
 
        writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
@@ -1388,7 +1680,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
        writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
        writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
 
-       writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
        if (!wait_for_completion_timeout(&mb5_transfer.work,
                                msecs_to_jiffies(20000))) {
@@ -1426,7 +1718,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
 
        mutex_lock(&mb5_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
                cpu_relax();
 
        writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
@@ -1434,7 +1726,7 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
        writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
        writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
 
-       writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
        if (!wait_for_completion_timeout(&mb5_transfer.work,
                                msecs_to_jiffies(20000))) {
@@ -1456,21 +1748,44 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
 void prcmu_ac_wake_req(void)
 {
        u32 val;
+       u32 status;
 
        mutex_lock(&mb0_transfer.ac_wake_lock);
 
-       val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ);
+       val = readl(PRCM_HOSTACCESS_REQ);
        if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)
                goto unlock_and_return;
 
        atomic_set(&ac_wake_req_state, 1);
 
-       writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
-               (_PRCMU_BASE + PRCM_HOSTACCESS_REQ));
+retry:
+       writel((val | PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ), PRCM_HOSTACCESS_REQ);
 
        if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
-                       msecs_to_jiffies(20000))) {
-               pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+                       msecs_to_jiffies(5000))) {
+               pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
+                       __func__);
+               goto unlock_and_return;
+       }
+
+       /*
+        * The modem can generate an AC_WAKE_ACK, and then still go to sleep.
+        * As a workaround, we wait, and then check that the modem is indeed
+        * awake (in terms of the value of the PRCM_MOD_AWAKE_STATUS
+        * register, which may not be the whole truth).
+        */
+       udelay(400);
+       status = (readl(PRCM_MOD_AWAKE_STATUS) & BITS(0, 2));
+       if (status != (PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE |
+                       PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE)) {
+               pr_err("prcmu: %s received ack, but modem not awake (0x%X).\n",
+                       __func__, status);
+               udelay(1200);
+               writel(val, PRCM_HOSTACCESS_REQ);
+               if (wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
+                               msecs_to_jiffies(5000)))
+                       goto retry;
+               pr_crit("prcmu: %s timed out (5 s) waiting for AC_SLEEP_ACK.\n",
                        __func__);
        }
 
@@ -1487,16 +1802,16 @@ void prcmu_ac_sleep_req()
 
        mutex_lock(&mb0_transfer.ac_wake_lock);
 
-       val = readl(_PRCMU_BASE + PRCM_HOSTACCESS_REQ);
+       val = readl(PRCM_HOSTACCESS_REQ);
        if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ))
                goto unlock_and_return;
 
        writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
-               (_PRCMU_BASE + PRCM_HOSTACCESS_REQ));
+               PRCM_HOSTACCESS_REQ);
 
        if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
-                       msecs_to_jiffies(20000))) {
-               pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+                       msecs_to_jiffies(5000))) {
+               pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
                        __func__);
        }
 
@@ -1506,21 +1821,32 @@ unlock_and_return:
        mutex_unlock(&mb0_transfer.ac_wake_lock);
 }
 
-bool prcmu_is_ac_wake_requested(void)
+bool db8500_prcmu_is_ac_wake_requested(void)
 {
        return (atomic_read(&ac_wake_req_state) != 0);
 }
 
 /**
- * prcmu_system_reset - System reset
+ * db8500_prcmu_system_reset - System reset
  *
- * Saves the reset reason code and then sets the APE_SOFRST register which
+ * Saves the reset reason code and then sets the APE_SOFTRST register which
  * fires interrupt to fw
  */
-void prcmu_system_reset(u16 reset_code)
+void db8500_prcmu_system_reset(u16 reset_code)
 {
        writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON));
-       writel(1, (_PRCMU_BASE + PRCM_APE_SOFTRST));
+       writel(1, PRCM_APE_SOFTRST);
+}
+
+/**
+ * db8500_prcmu_get_reset_code - Retrieve SW reset reason code
+ *
+ * Retrieves the reset reason code stored by prcmu_system_reset() before
+ * last restart.
+ */
+u16 db8500_prcmu_get_reset_code(void)
+{
+       return readw(tcdm_base + PRCM_SW_RST_REASON);
 }
 
 /**
@@ -1530,11 +1856,11 @@ void prcmu_modem_reset(void)
 {
        mutex_lock(&mb1_transfer.lock);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
                cpu_relax();
 
        writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
-       writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
        wait_for_completion(&mb1_transfer.work);
 
        /*
@@ -1551,11 +1877,11 @@ static void ack_dbb_wakeup(void)
 
        spin_lock_irqsave(&mb0_transfer.lock, flags);
 
-       while (readl(_PRCMU_BASE + PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
+       while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
                cpu_relax();
 
        writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
-       writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_MBOX_CPU_SET));
+       writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
        spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
@@ -1600,7 +1926,7 @@ static bool read_mailbox_0(void)
                r = false;
                break;
        }
-       writel(MBOX_BIT(0), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(0), PRCM_ARM_IT1_CLR);
        return r;
 }
 
@@ -1613,7 +1939,7 @@ static bool read_mailbox_1(void)
                PRCM_ACK_MB1_CURRENT_APE_OPP);
        mb1_transfer.ack.ape_voltage_status = readb(tcdm_base +
                PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
-       writel(MBOX_BIT(1), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
        complete(&mb1_transfer.work);
        return false;
 }
@@ -1621,14 +1947,14 @@ static bool read_mailbox_1(void)
 static bool read_mailbox_2(void)
 {
        mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS);
-       writel(MBOX_BIT(2), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
        complete(&mb2_transfer.work);
        return false;
 }
 
 static bool read_mailbox_3(void)
 {
-       writel(MBOX_BIT(3), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
        return false;
 }
 
@@ -1643,6 +1969,11 @@ static bool read_mailbox_4(void)
        case MB4H_HOTDOG:
        case MB4H_HOTMON:
        case MB4H_HOT_PERIOD:
+       case MB4H_A9WDOG_CONF:
+       case MB4H_A9WDOG_EN:
+       case MB4H_A9WDOG_DIS:
+       case MB4H_A9WDOG_LOAD:
+       case MB4H_A9WDOG_KICK:
                break;
        default:
                print_unknown_header_warning(4, header);
@@ -1650,7 +1981,7 @@ static bool read_mailbox_4(void)
                break;
        }
 
-       writel(MBOX_BIT(4), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
 
        if (do_complete)
                complete(&mb4_transfer.work);
@@ -1662,20 +1993,20 @@ static bool read_mailbox_5(void)
 {
        mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS);
        mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL);
-       writel(MBOX_BIT(5), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
        complete(&mb5_transfer.work);
        return false;
 }
 
 static bool read_mailbox_6(void)
 {
-       writel(MBOX_BIT(6), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
        return false;
 }
 
 static bool read_mailbox_7(void)
 {
-       writel(MBOX_BIT(7), (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
        return false;
 }
 
@@ -1696,7 +2027,7 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data)
        u8 n;
        irqreturn_t r;
 
-       bits = (readl(_PRCMU_BASE + PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
+       bits = (readl(PRCM_ARM_IT1_VAL) & ALL_MBOX_BITS);
        if (unlikely(!bits))
                return IRQ_NONE;
 
@@ -1768,7 +2099,7 @@ static struct irq_chip prcmu_irq_chip = {
        .irq_unmask     = prcmu_irq_unmask,
 };
 
-void __init prcmu_early_init(void)
+void __init db8500_prcmu_early_init(void)
 {
        unsigned int i;
 
@@ -1826,6 +2157,16 @@ void __init prcmu_early_init(void)
        }
 }
 
+static void __init db8500_prcmu_init_clkforce(void)
+{
+       u32 val;
+
+       val = readl(PRCM_A9PL_FORCE_CLKEN);
+       val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN |
+               PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN);
+       writel(val, (PRCM_A9PL_FORCE_CLKEN));
+}
+
 /*
  * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC
  */
@@ -1861,7 +2202,42 @@ static struct regulator_consumer_supply db8500_vsmps2_consumers[] = {
 
 static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
        REGULATOR_SUPPLY("vsupply", "b2r2.0"),
-       REGULATOR_SUPPLY("vsupply", "mcde.0"),
+       REGULATOR_SUPPLY("vsupply", "mcde"),
+};
+
+/* SVA MMDSP regulator switch */
+static struct regulator_consumer_supply db8500_svammdsp_consumers[] = {
+       REGULATOR_SUPPLY("sva-mmdsp", "cm_control"),
+};
+
+/* SVA pipe regulator switch */
+static struct regulator_consumer_supply db8500_svapipe_consumers[] = {
+       REGULATOR_SUPPLY("sva-pipe", "cm_control"),
+};
+
+/* SIA MMDSP regulator switch */
+static struct regulator_consumer_supply db8500_siammdsp_consumers[] = {
+       REGULATOR_SUPPLY("sia-mmdsp", "cm_control"),
+};
+
+/* SIA pipe regulator switch */
+static struct regulator_consumer_supply db8500_siapipe_consumers[] = {
+       REGULATOR_SUPPLY("sia-pipe", "cm_control"),
+};
+
+static struct regulator_consumer_supply db8500_sga_consumers[] = {
+       REGULATOR_SUPPLY("v-mali", NULL),
+};
+
+/* ESRAM1 and 2 regulator switch */
+static struct regulator_consumer_supply db8500_esram12_consumers[] = {
+       REGULATOR_SUPPLY("esram12", "cm_control"),
+};
+
+/* ESRAM3 and 4 regulator switch */
+static struct regulator_consumer_supply db8500_esram34_consumers[] = {
+       REGULATOR_SUPPLY("v-esram34", "mcde"),
+       REGULATOR_SUPPLY("esram34", "cm_control"),
 };
 
 static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
@@ -1923,6 +2299,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                        .name = "db8500-sva-mmdsp",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
                },
+               .consumer_supplies = db8500_svammdsp_consumers,
+               .num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers),
        },
        [DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
                .constraints = {
@@ -1937,6 +2315,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                        .name = "db8500-sva-pipe",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
                },
+               .consumer_supplies = db8500_svapipe_consumers,
+               .num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers),
        },
        [DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
                .supply_regulator = "db8500-vape",
@@ -1944,6 +2324,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                        .name = "db8500-sia-mmdsp",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
                },
+               .consumer_supplies = db8500_siammdsp_consumers,
+               .num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers),
        },
        [DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
                .constraints = {
@@ -1957,6 +2339,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                        .name = "db8500-sia-pipe",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
                },
+               .consumer_supplies = db8500_siapipe_consumers,
+               .num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers),
        },
        [DB8500_REGULATOR_SWITCH_SGA] = {
                .supply_regulator = "db8500-vape",
@@ -1964,6 +2348,9 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                        .name = "db8500-sga",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
                },
+               .consumer_supplies = db8500_sga_consumers,
+               .num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers),
+
        },
        [DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
                .supply_regulator = "db8500-vape",
@@ -1980,6 +2367,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                        .name = "db8500-esram12",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
                },
+               .consumer_supplies = db8500_esram12_consumers,
+               .num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers),
        },
        [DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
                .constraints = {
@@ -1993,6 +2382,8 @@ static struct regulator_init_data db8500_regulators[DB8500_NUM_REGULATORS] = {
                        .name = "db8500-esram34",
                        .valid_ops_mask = REGULATOR_CHANGE_STATUS,
                },
+               .consumer_supplies = db8500_esram34_consumers,
+               .num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers),
        },
        [DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
                .constraints = {
@@ -2024,8 +2415,10 @@ static int __init db8500_prcmu_probe(struct platform_device *pdev)
        if (ux500_is_svp())
                return -ENODEV;
 
+       db8500_prcmu_init_clkforce();
+
        /* Clean up the mailbox interrupts after pre-kernel code. */
-       writel(ALL_MBOX_BITS, (_PRCMU_BASE + PRCM_ARM_IT1_CLR));
+       writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
 
        err = request_threaded_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler,
                prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
similarity index 51%
rename from drivers/mfd/db5500-prcmu-regs.h
rename to drivers/mfd/dbx500-prcmu-regs.h
index 9a8e9e4..ec22e9f 100644 (file)
  * PRCM Unit registers
  */
 
-#ifndef __MACH_PRCMU_REGS_H
-#define __MACH_PRCMU_REGS_H
+#ifndef __DB8500_PRCMU_REGS_H
+#define __DB8500_PRCMU_REGS_H
 
 #include <mach/hardware.h>
 
+#define BITS(_start, _end) ((BIT(_end) - BIT(_start)) + BIT(_end))
+
+#define PRCM_SVACLK_MGT_OFF            0x008
+#define PRCM_SIACLK_MGT_OFF            0x00C
+#define PRCM_SGACLK_MGT_OFF            0x014
+#define PRCM_UARTCLK_MGT_OFF           0x018
+#define PRCM_MSP02CLK_MGT_OFF          0x01C
+#define PRCM_I2CCLK_MGT_OFF            0x020
+#define PRCM_SDMMCCLK_MGT_OFF          0x024
+#define PRCM_SLIMCLK_MGT_OFF           0x028
+#define PRCM_PER1CLK_MGT_OFF           0x02C
+#define PRCM_PER2CLK_MGT_OFF           0x030
+#define PRCM_PER3CLK_MGT_OFF           0x034
+#define PRCM_PER5CLK_MGT_OFF           0x038
+#define PRCM_PER6CLK_MGT_OFF           0x03C
+#define PRCM_PER7CLK_MGT_OFF           0x040
+#define PRCM_PWMCLK_MGT_OFF            0x044 /* for DB5500 */
+#define PRCM_IRDACLK_MGT_OFF           0x048 /* for DB5500 */
+#define PRCM_IRRCCLK_MGT_OFF           0x04C /* for DB5500 */
+#define PRCM_LCDCLK_MGT_OFF            0x044
+#define PRCM_BMLCLK_MGT_OFF            0x04C
+#define PRCM_HSITXCLK_MGT_OFF          0x050
+#define PRCM_HSIRXCLK_MGT_OFF          0x054
+#define PRCM_HDMICLK_MGT_OFF           0x058
+#define PRCM_APEATCLK_MGT_OFF          0x05C
+#define PRCM_APETRACECLK_MGT_OFF       0x060
+#define PRCM_MCDECLK_MGT_OFF           0x064
+#define PRCM_IPI2CCLK_MGT_OFF          0x068
+#define PRCM_DSIALTCLK_MGT_OFF         0x06C
+#define PRCM_DMACLK_MGT_OFF            0x074
+#define PRCM_B2R2CLK_MGT_OFF           0x078
+#define PRCM_TVCLK_MGT_OFF             0x07C
+#define PRCM_UNIPROCLK_MGT_OFF         0x278
+#define PRCM_SSPCLK_MGT_OFF            0x280
+#define PRCM_RNGCLK_MGT_OFF            0x284
+#define PRCM_UICCCLK_MGT_OFF           0x27C
+#define PRCM_MSP1CLK_MGT_OFF           0x288
+
 #define PRCM_ARM_PLLDIVPS      (_PRCMU_BASE + 0x118)
 #define PRCM_ARM_PLLDIVPS_ARM_BRM_RATE         0x3f
 #define PRCM_ARM_PLLDIVPS_MAX_MASK             0xf
 #define PRCM_PLLARM_ENABLE_PRCM_PLLARM_COUNTON 0x100
 
 #define PRCM_ARMCLKFIX_MGT     (_PRCMU_BASE + 0x0)
+#define PRCM_A9PL_FORCE_CLKEN  (_PRCMU_BASE + 0x19C)
 #define PRCM_A9_RESETN_CLR     (_PRCMU_BASE + 0x1f4)
 #define PRCM_A9_RESETN_SET     (_PRCMU_BASE + 0x1f0)
 #define PRCM_ARM_LS_CLAMP      (_PRCMU_BASE + 0x30c)
 #define PRCM_SRAM_A9           (_PRCMU_BASE + 0x308)
 
+#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN BIT(0)
+#define PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN BIT(1)
+
 /* ARM WFI Standby signal register */
 #define PRCM_ARM_WFI_STANDBY    (_PRCMU_BASE + 0x130)
 #define PRCM_IOCR              (_PRCMU_BASE + 0x310)
 #define PRCM_ARMITVAL127TO96   (_PRCMU_BASE + 0x26C)
 
 #define PRCM_HOSTACCESS_REQ    (_PRCMU_BASE + 0x334)
+#define PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ 0x1
 #define ARM_WAKEUP_MODEM       0x1
 
-#define PRCM_ARM_IT1_CLEAR     (_PRCMU_BASE + 0x48C)
+#define PRCM_ARM_IT1_CLR       (_PRCMU_BASE + 0x48C)
 #define PRCM_ARM_IT1_VAL       (_PRCMU_BASE + 0x494)
 #define PRCM_HOLD_EVT          (_PRCMU_BASE + 0x174)
 
+#define PRCM_MOD_AWAKE_STATUS  (_PRCMU_BASE + 0x4A0)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_COREPD_AWAKE    BIT(0)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_AAPD_AWAKE      BIT(1)
+#define PRCM_MOD_AWAKE_STATUS_PRCM_MOD_VMODEM_OFF_ISO  BIT(2)
+
 #define PRCM_ITSTATUS0         (_PRCMU_BASE + 0x148)
 #define PRCM_ITSTATUS1         (_PRCMU_BASE + 0x150)
 #define PRCM_ITSTATUS2         (_PRCMU_BASE + 0x158)
 #define PRCM_PLLDSI_FREQ           (_PRCMU_BASE + 0x500)
 #define PRCM_PLLDSI_ENABLE         (_PRCMU_BASE + 0x504)
 #define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
-#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + 0x044)
-#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + 0x064)
-#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + 0x058)
-#define PRCM_TVCLK_MGT             (_PRCMU_BASE + 0x07c)
+#define PRCM_LCDCLK_MGT            (_PRCMU_BASE + PRCM_LCDCLK_MGT_OFF)
+#define PRCM_MCDECLK_MGT           (_PRCMU_BASE + PRCM_MCDECLK_MGT_OFF)
+#define PRCM_HDMICLK_MGT           (_PRCMU_BASE + PRCM_HDMICLK_MGT_OFF)
+#define PRCM_TVCLK_MGT             (_PRCMU_BASE + PRCM_TVCLK_MGT_OFF)
 #define PRCM_DSI_PLLOUT_SEL        (_PRCMU_BASE + 0x530)
 #define PRCM_DSITVCLK_DIV          (_PRCMU_BASE + 0x52C)
 #define PRCM_PLLDSI_LOCKP          (_PRCMU_BASE + 0x508)
 #define PRCM_APE_RESETN_SET        (_PRCMU_BASE + 0x1E4)
 #define PRCM_APE_RESETN_CLR        (_PRCMU_BASE + 0x1E8)
+
 #define PRCM_CLKOCR               (_PRCMU_BASE + 0x1CC)
+#define PRCM_CLKOCR_CLKOUT0_REF_CLK    (1 << 0)
+#define PRCM_CLKOCR_CLKOUT0_MASK       BITS(0, 13)
+#define PRCM_CLKOCR_CLKOUT1_REF_CLK    (1 << 16)
+#define PRCM_CLKOCR_CLKOUT1_MASK       BITS(16, 29)
 
 /* ePOD and memory power signal control registers */
 #define PRCM_EPOD_C_SET            (_PRCMU_BASE + 0x410)
 #define PRCM_GPIOCR_DBG_STM_MOD_CMD1            0x800
 #define PRCM_GPIOCR_DBG_UARTMOD_CMD0            0x1
 
+/* PRCMU HW semaphore */
+#define PRCM_SEM                   (_PRCMU_BASE + 0x400)
+#define PRCM_SEM_PRCM_SEM BIT(0)
+
+#define PRCM_TCR                   (_PRCMU_BASE + 0x1C8)
+#define PRCM_TCR_TENSEL_MASK       BITS(0, 7)
+#define PRCM_TCR_STOP_TIMERS       BIT(16)
+#define PRCM_TCR_DOZE_MODE         BIT(17)
+
+#define PRCM_CLKOCR_CLKODIV0_SHIFT     0
+#define PRCM_CLKOCR_CLKODIV0_MASK      BITS(0, 5)
+#define PRCM_CLKOCR_CLKOSEL0_SHIFT     6
+#define PRCM_CLKOCR_CLKOSEL0_MASK      BITS(6, 8)
+#define PRCM_CLKOCR_CLKODIV1_SHIFT     16
+#define PRCM_CLKOCR_CLKODIV1_MASK      BITS(16, 21)
+#define PRCM_CLKOCR_CLKOSEL1_SHIFT     22
+#define PRCM_CLKOCR_CLKOSEL1_MASK      BITS(22, 24)
+#define PRCM_CLKOCR_CLK1TYPE           BIT(28)
+
+#define PRCM_CLK_MGT_CLKPLLDIV_MASK    BITS(0, 4)
+#define PRCM_CLK_MGT_CLKPLLSW_MASK     BITS(5, 7)
+#define PRCM_CLK_MGT_CLKEN             BIT(8)
+
+/* GPIOCR register */
+#define PRCM_GPIOCR_SPI2_SELECT BIT(23)
+
+#define PRCM_DDR_SUBSYS_APE_MINBW      (_PRCMU_BASE + 0x438)
+#define PRCM_CGATING_BYPASS            (_PRCMU_BASE + 0x134)
+#define PRCM_CGATING_BYPASS_ICN2       BIT(6)
+
+/* Miscellaneous unit registers */
+#define PRCM_RESOUTN_SET               (_PRCMU_BASE + 0x214)
+#define PRCM_RESOUTN_CLR               (_PRCMU_BASE + 0x218)
+
+/* System reset register */
+#define PRCM_APE_SOFTRST               (_PRCMU_BASE + 0x228)
 
-#endif /* __MACH_PRCMU__REGS_H */
+#endif /* __DB8500_PRCMU_REGS_H */
diff --git a/drivers/mfd/intel_msic.c b/drivers/mfd/intel_msic.c
new file mode 100644 (file)
index 0000000..97c2776
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * Driver for Intel MSIC
+ *
+ * Copyright (C) 2011, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.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.
+ */
+
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/intel_msic.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <asm/intel_scu_ipc.h>
+
+#define MSIC_VENDOR(id)                ((id >> 6) & 3)
+#define MSIC_VERSION(id)       (id & 0x3f)
+#define MSIC_MAJOR(id)         ('A' + ((id >> 3) & 7))
+#define MSIC_MINOR(id)         (id & 7)
+
+/*
+ * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
+ * Since IRQ block starts from address 0x002 we need to substract that from
+ * the actual IRQ status register address.
+ */
+#define MSIC_IRQ_STATUS(x)     (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
+#define MSIC_IRQ_STATUS_ACCDET MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET)
+
+/*
+ * The SCU hardware has limitation of 16 bytes per read/write buffer on
+ * Medfield.
+ */
+#define SCU_IPC_RWBUF_LIMIT    16
+
+/**
+ * struct intel_msic - an MSIC MFD instance
+ * @pdev: pointer to the platform device
+ * @vendor: vendor ID
+ * @version: chip version
+ * @irq_base: base address of the mapped MSIC SRAM interrupt tree
+ */
+struct intel_msic {
+       struct platform_device          *pdev;
+       unsigned                        vendor;
+       unsigned                        version;
+       void __iomem                    *irq_base;
+};
+
+static struct resource msic_touch_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msic_adc_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msic_battery_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msic_gpio_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msic_audio_resources[] = {
+       {
+               .name           = "IRQ",
+               .flags          = IORESOURCE_IRQ,
+       },
+       /*
+        * We will pass IRQ_BASE to the driver now but this can be removed
+        * when/if the driver starts to use intel_msic_irq_read().
+        */
+       {
+               .name           = "IRQ_BASE",
+               .flags          = IORESOURCE_MEM,
+               .start          = MSIC_IRQ_STATUS_ACCDET,
+               .end            = MSIC_IRQ_STATUS_ACCDET,
+       },
+};
+
+static struct resource msic_hdmi_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msic_thermal_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msic_power_btn_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct resource msic_ocd_resources[] = {
+       {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+/*
+ * Devices that are part of the MSIC and are available via firmware
+ * populated SFI DEVS table.
+ */
+static struct mfd_cell msic_devs[] = {
+       [INTEL_MSIC_BLOCK_TOUCH]        = {
+               .name                   = "msic_touch",
+               .num_resources          = ARRAY_SIZE(msic_touch_resources),
+               .resources              = msic_touch_resources,
+       },
+       [INTEL_MSIC_BLOCK_ADC]          = {
+               .name                   = "msic_adc",
+               .num_resources          = ARRAY_SIZE(msic_adc_resources),
+               .resources              = msic_adc_resources,
+       },
+       [INTEL_MSIC_BLOCK_BATTERY]      = {
+               .name                   = "msic_battery",
+               .num_resources          = ARRAY_SIZE(msic_battery_resources),
+               .resources              = msic_battery_resources,
+       },
+       [INTEL_MSIC_BLOCK_GPIO]         = {
+               .name                   = "msic_gpio",
+               .num_resources          = ARRAY_SIZE(msic_gpio_resources),
+               .resources              = msic_gpio_resources,
+       },
+       [INTEL_MSIC_BLOCK_AUDIO]        = {
+               .name                   = "msic_audio",
+               .num_resources          = ARRAY_SIZE(msic_audio_resources),
+               .resources              = msic_audio_resources,
+       },
+       [INTEL_MSIC_BLOCK_HDMI]         = {
+               .name                   = "msic_hdmi",
+               .num_resources          = ARRAY_SIZE(msic_hdmi_resources),
+               .resources              = msic_hdmi_resources,
+       },
+       [INTEL_MSIC_BLOCK_THERMAL]      = {
+               .name                   = "msic_thermal",
+               .num_resources          = ARRAY_SIZE(msic_thermal_resources),
+               .resources              = msic_thermal_resources,
+       },
+       [INTEL_MSIC_BLOCK_POWER_BTN]    = {
+               .name                   = "msic_power_btn",
+               .num_resources          = ARRAY_SIZE(msic_power_btn_resources),
+               .resources              = msic_power_btn_resources,
+       },
+       [INTEL_MSIC_BLOCK_OCD]          = {
+               .name                   = "msic_ocd",
+               .num_resources          = ARRAY_SIZE(msic_ocd_resources),
+               .resources              = msic_ocd_resources,
+       },
+};
+
+/*
+ * Other MSIC related devices which are not directly available via SFI DEVS
+ * table. These can be pseudo devices, regulators etc. which are needed for
+ * different purposes.
+ *
+ * These devices appear only after the MSIC driver itself is initialized so
+ * we can guarantee that the SCU IPC interface is ready.
+ */
+static struct mfd_cell msic_other_devs[] = {
+       /* Audio codec in the MSIC */
+       {
+               .id                     = -1,
+               .name                   = "sn95031",
+       },
+};
+
+/**
+ * intel_msic_reg_read - read a single MSIC register
+ * @reg: register to read
+ * @val: register value is placed here
+ *
+ * Read a single register from MSIC. Returns %0 on success and negative
+ * errno in case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_reg_read(unsigned short reg, u8 *val)
+{
+       return intel_scu_ipc_ioread8(reg, val);
+}
+EXPORT_SYMBOL_GPL(intel_msic_reg_read);
+
+/**
+ * intel_msic_reg_write - write a single MSIC register
+ * @reg: register to write
+ * @val: value to write to that register
+ *
+ * Write a single MSIC register. Returns 0 on success and negative
+ * errno in case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_reg_write(unsigned short reg, u8 val)
+{
+       return intel_scu_ipc_iowrite8(reg, val);
+}
+EXPORT_SYMBOL_GPL(intel_msic_reg_write);
+
+/**
+ * intel_msic_reg_update - update a single MSIC register
+ * @reg: register to update
+ * @val: value to write to the register
+ * @mask: specifies which of the bits are updated (%0 = don't update,
+ *        %1 = update)
+ *
+ * Perform an update to a register @reg. @mask is used to specify which
+ * bits are updated. Returns %0 in case of success and negative errno in
+ * case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask)
+{
+       return intel_scu_ipc_update_register(reg, val, mask);
+}
+EXPORT_SYMBOL_GPL(intel_msic_reg_update);
+
+/**
+ * intel_msic_bulk_read - read an array of registers
+ * @reg: array of register addresses to read
+ * @buf: array where the read values are placed
+ * @count: number of registers to read
+ *
+ * Function reads @count registers from the MSIC using addresses passed in
+ * @reg. Read values are placed in @buf. Reads are performed atomically
+ * wrt. MSIC.
+ *
+ * Returns %0 in case of success and negative errno in case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count)
+{
+       if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
+               return -EINVAL;
+
+       return intel_scu_ipc_readv(reg, buf, count);
+}
+EXPORT_SYMBOL_GPL(intel_msic_bulk_read);
+
+/**
+ * intel_msic_bulk_write - write an array of values to the MSIC registers
+ * @reg: array of registers to write
+ * @buf: values to write to each register
+ * @count: number of registers to write
+ *
+ * Function writes @count registers in @buf to MSIC. Writes are performed
+ * atomically wrt MSIC. Returns %0 in case of success and negative errno in
+ * case of failure.
+ *
+ * Function may sleep.
+ */
+int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count)
+{
+       if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
+               return -EINVAL;
+
+       return intel_scu_ipc_writev(reg, buf, count);
+}
+EXPORT_SYMBOL_GPL(intel_msic_bulk_write);
+
+/**
+ * intel_msic_irq_read - read a register from an MSIC interrupt tree
+ * @msic: MSIC instance
+ * @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and
+ *      %INTEL_MSIC_RESETIRQ2)
+ * @val: value of the register is placed here
+ *
+ * This function can be used by an MSIC subdevice interrupt handler to read
+ * a register value from the MSIC interrupt tree. In this way subdevice
+ * drivers don't have to map in the interrupt tree themselves but can just
+ * call this function instead.
+ *
+ * Function doesn't sleep and is callable from interrupt context.
+ *
+ * Returns %-EINVAL if @reg is outside of the allowed register region.
+ */
+int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
+{
+       if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2))
+               return -EINVAL;
+
+       *val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1));
+       return 0;
+}
+EXPORT_SYMBOL_GPL(intel_msic_irq_read);
+
+static int __devinit intel_msic_init_devices(struct intel_msic *msic)
+{
+       struct platform_device *pdev = msic->pdev;
+       struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+       int ret, i;
+
+       if (pdata->gpio) {
+               struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO];
+
+               cell->platform_data = pdata->gpio;
+               cell->pdata_size = sizeof(*pdata->gpio);
+       }
+
+       if (pdata->ocd) {
+               unsigned gpio = pdata->ocd->gpio;
+
+               ret = gpio_request_one(gpio, GPIOF_IN, "ocd_gpio");
+               if (ret) {
+                       dev_err(&pdev->dev, "failed to register OCD GPIO\n");
+                       return ret;
+               }
+
+               ret = gpio_to_irq(gpio);
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n");
+                       gpio_free(gpio);
+                       return ret;
+               }
+
+               /* Update the IRQ number for the OCD */
+               pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(msic_devs); i++) {
+               if (!pdata->irq[i])
+                       continue;
+
+               ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
+                                     pdata->irq[i]);
+               if (ret)
+                       goto fail;
+       }
+
+       ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
+                             ARRAY_SIZE(msic_other_devs), NULL, 0);
+       if (ret)
+               goto fail;
+
+       return 0;
+
+fail:
+       mfd_remove_devices(&pdev->dev);
+       if (pdata->ocd)
+               gpio_free(pdata->ocd->gpio);
+
+       return ret;
+}
+
+static void __devexit intel_msic_remove_devices(struct intel_msic *msic)
+{
+       struct platform_device *pdev = msic->pdev;
+       struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+
+       mfd_remove_devices(&pdev->dev);
+
+       if (pdata->ocd)
+               gpio_free(pdata->ocd->gpio);
+}
+
+static int __devinit intel_msic_probe(struct platform_device *pdev)
+{
+       struct intel_msic_platform_data *pdata = pdev->dev.platform_data;
+       struct intel_msic *msic;
+       struct resource *res;
+       u8 id0, id1;
+       int ret;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data passed\n");
+               return -EINVAL;
+       }
+
+       /* First validate that we have an MSIC in place */
+       ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n");
+               return -ENXIO;
+       }
+
+       ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n");
+               return -ENXIO;
+       }
+
+       if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) {
+               dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1);
+               return -ENXIO;
+       }
+
+       msic = kzalloc(sizeof(*msic), GFP_KERNEL);
+       if (!msic)
+               return -ENOMEM;
+
+       msic->vendor = MSIC_VENDOR(id0);
+       msic->version = MSIC_VERSION(id0);
+       msic->pdev = pdev;
+
+       /*
+        * Map in the MSIC interrupt tree area in SRAM. This is exposed to
+        * the clients via intel_msic_irq_read().
+        */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "failed to get SRAM iomem resource\n");
+               ret = -ENODEV;
+               goto fail_free_msic;
+       }
+
+       res = request_mem_region(res->start, resource_size(res), pdev->name);
+       if (!res) {
+               ret = -EBUSY;
+               goto fail_free_msic;
+       }
+
+       msic->irq_base = ioremap_nocache(res->start, resource_size(res));
+       if (!msic->irq_base) {
+               dev_err(&pdev->dev, "failed to map SRAM memory\n");
+               ret = -ENOMEM;
+               goto fail_release_region;
+       }
+
+       platform_set_drvdata(pdev, msic);
+
+       ret = intel_msic_init_devices(msic);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to initialize MSIC devices\n");
+               goto fail_unmap_mem;
+       }
+
+       dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n",
+                MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version),
+                msic->vendor);
+
+       return 0;
+
+fail_unmap_mem:
+       iounmap(msic->irq_base);
+fail_release_region:
+       release_mem_region(res->start, resource_size(res));
+fail_free_msic:
+       kfree(msic);
+
+       return ret;
+}
+
+static int __devexit intel_msic_remove(struct platform_device *pdev)
+{
+       struct intel_msic *msic = platform_get_drvdata(pdev);
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       intel_msic_remove_devices(msic);
+       platform_set_drvdata(pdev, NULL);
+       iounmap(msic->irq_base);
+       release_mem_region(res->start, resource_size(res));
+       kfree(msic);
+
+       return 0;
+}
+
+static struct platform_driver intel_msic_driver = {
+       .probe          = intel_msic_probe,
+       .remove         = __devexit_p(intel_msic_remove),
+       .driver         = {
+               .name   = "intel_msic",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init intel_msic_init(void)
+{
+       return platform_driver_register(&intel_msic_driver);
+}
+module_init(intel_msic_init);
+
+static void __exit intel_msic_exit(void)
+{
+       platform_driver_unregister(&intel_msic_driver);
+}
+module_exit(intel_msic_exit);
+
+MODULE_DESCRIPTION("Driver for Intel MSIC");
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
+MODULE_LICENSE("GPL");
index 563654c..1e9ee53 100644 (file)
@@ -328,7 +328,7 @@ static int __devexit jz4740_adc_remove(struct platform_device *pdev)
        return 0;
 }
 
-struct platform_driver jz4740_adc_driver = {
+static struct platform_driver jz4740_adc_driver = {
        .probe  = jz4740_adc_probe,
        .remove = __devexit_p(jz4740_adc_remove),
        .driver = {
index f83103b..dc58750 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/mutex.h>
 #include <linux/mfd/core.h>
@@ -142,7 +143,6 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 
        max8997->irq_base = pdata->irq_base;
        max8997->ono = pdata->ono;
-       max8997->wakeup = pdata->wakeup;
 
        mutex_init(&max8997->iolock);
 
@@ -169,6 +169,9 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
        if (ret < 0)
                goto err_mfd;
 
+       /* MAX8997 has a power button input. */
+       device_init_wakeup(max8997->dev, pdata->wakeup);
+
        return ret;
 
 err_mfd:
@@ -398,7 +401,29 @@ static int max8997_restore(struct device *dev)
        return 0;
 }
 
+static int max8997_suspend(struct device *dev)
+{
+       struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+       struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+
+       if (device_may_wakeup(dev))
+               irq_set_irq_wake(max8997->irq, 1);
+       return 0;
+}
+
+static int max8997_resume(struct device *dev)
+{
+       struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+       struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+
+       if (device_may_wakeup(dev))
+               irq_set_irq_wake(max8997->irq, 0);
+       return max8997_irq_resume(max8997);
+}
+
 const struct dev_pm_ops max8997_pm = {
+       .suspend = max8997_suspend,
+       .resume = max8997_resume,
        .freeze = max8997_freeze,
        .restore = max8997_restore,
 };
index 7e4d44b..e9619ac 100644 (file)
@@ -26,20 +26,10 @@ struct mc13xxx {
 
        irq_handler_t irqhandler[MC13XXX_NUM_IRQ];
        void *irqdata[MC13XXX_NUM_IRQ];
-};
-
-struct mc13783 {
-       struct mc13xxx mc13xxx;
 
        int adcflags;
 };
 
-struct mc13xxx *mc13783_to_mc13xxx(struct mc13783 *mc13783)
-{
-       return &mc13783->mc13xxx;
-}
-EXPORT_SYMBOL(mc13783_to_mc13xxx);
-
 #define MC13XXX_IRQSTAT0       0
 #define MC13XXX_IRQSTAT0_ADCDONEI      (1 << 0)
 #define MC13XXX_IRQSTAT0_ADCBISDONEI   (1 << 1)
@@ -136,14 +126,14 @@ EXPORT_SYMBOL(mc13783_to_mc13xxx);
 #define MC13XXX_REVISION_FAB           (0x03 << 11)
 #define MC13XXX_REVISION_ICIDCODE      (0x3f << 13)
 
-#define MC13783_ADC1           44
-#define MC13783_ADC1_ADEN              (1 << 0)
-#define MC13783_ADC1_RAND              (1 << 1)
-#define MC13783_ADC1_ADSEL             (1 << 3)
-#define MC13783_ADC1_ASC               (1 << 20)
-#define MC13783_ADC1_ADTRIGIGN         (1 << 21)
+#define MC13XXX_ADC1           44
+#define MC13XXX_ADC1_ADEN              (1 << 0)
+#define MC13XXX_ADC1_RAND              (1 << 1)
+#define MC13XXX_ADC1_ADSEL             (1 << 3)
+#define MC13XXX_ADC1_ASC               (1 << 20)
+#define MC13XXX_ADC1_ADTRIGIGN         (1 << 21)
 
-#define MC13783_ADC2           45
+#define MC13XXX_ADC2           45
 
 #define MC13XXX_NUMREGS 0x3f
 
@@ -487,7 +477,7 @@ enum mc13xxx_id {
        MC13XXX_ID_INVALID,
 };
 
-const char *mc13xxx_chipname[] = {
+static const char *mc13xxx_chipname[] = {
        [MC13XXX_ID_MC13783] = "mc13783",
        [MC13XXX_ID_MC13892] = "mc13892",
 };
@@ -558,8 +548,6 @@ static const char *mc13xxx_get_chipname(struct mc13xxx *mc13xxx)
        return mc13xxx_chipname[devid->driver_data];
 }
 
-#include <linux/mfd/mc13783.h>
-
 int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
 {
        struct mc13xxx_platform_data *pdata =
@@ -569,15 +557,15 @@ int mc13xxx_get_flags(struct mc13xxx *mc13xxx)
 }
 EXPORT_SYMBOL(mc13xxx_get_flags);
 
-#define MC13783_ADC1_CHAN0_SHIFT       5
-#define MC13783_ADC1_CHAN1_SHIFT       8
+#define MC13XXX_ADC1_CHAN0_SHIFT       5
+#define MC13XXX_ADC1_CHAN1_SHIFT       8
 
 struct mc13xxx_adcdone_data {
        struct mc13xxx *mc13xxx;
        struct completion done;
 };
 
-static irqreturn_t mc13783_handler_adcdone(int irq, void *data)
+static irqreturn_t mc13xxx_handler_adcdone(int irq, void *data)
 {
        struct mc13xxx_adcdone_data *adcdone_data = data;
 
@@ -588,12 +576,11 @@ static irqreturn_t mc13783_handler_adcdone(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-#define MC13783_ADC_WORKING (1 << 0)
+#define MC13XXX_ADC_WORKING (1 << 0)
 
-int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
+int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
                unsigned int channel, unsigned int *sample)
 {
-       struct mc13xxx *mc13xxx = &mc13783->mc13xxx;
        u32 adc0, adc1, old_adc0;
        int i, ret;
        struct mc13xxx_adcdone_data adcdone_data = {
@@ -605,51 +592,51 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
 
        mc13xxx_lock(mc13xxx);
 
-       if (mc13783->adcflags & MC13783_ADC_WORKING) {
+       if (mc13xxx->adcflags & MC13XXX_ADC_WORKING) {
                ret = -EBUSY;
                goto out;
        }
 
-       mc13783->adcflags |= MC13783_ADC_WORKING;
+       mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
 
-       mc13xxx_reg_read(mc13xxx, MC13783_ADC0, &old_adc0);
+       mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
 
-       adc0 = MC13783_ADC0_ADINC1 | MC13783_ADC0_ADINC2;
-       adc1 = MC13783_ADC1_ADEN | MC13783_ADC1_ADTRIGIGN | MC13783_ADC1_ASC;
+       adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2;
+       adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC;
 
        if (channel > 7)
-               adc1 |= MC13783_ADC1_ADSEL;
+               adc1 |= MC13XXX_ADC1_ADSEL;
 
        switch (mode) {
-       case MC13783_ADC_MODE_TS:
-               adc0 |= MC13783_ADC0_ADREFEN | MC13783_ADC0_TSMOD0 |
-                       MC13783_ADC0_TSMOD1;
-               adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT;
+       case MC13XXX_ADC_MODE_TS:
+               adc0 |= MC13XXX_ADC0_ADREFEN | MC13XXX_ADC0_TSMOD0 |
+                       MC13XXX_ADC0_TSMOD1;
+               adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
                break;
 
-       case MC13783_ADC_MODE_SINGLE_CHAN:
-               adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK;
-               adc1 |= (channel & 0x7) << MC13783_ADC1_CHAN0_SHIFT;
-               adc1 |= MC13783_ADC1_RAND;
+       case MC13XXX_ADC_MODE_SINGLE_CHAN:
+               adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
+               adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT;
+               adc1 |= MC13XXX_ADC1_RAND;
                break;
 
-       case MC13783_ADC_MODE_MULT_CHAN:
-               adc0 |= old_adc0 & MC13783_ADC0_TSMOD_MASK;
-               adc1 |= 4 << MC13783_ADC1_CHAN1_SHIFT;
+       case MC13XXX_ADC_MODE_MULT_CHAN:
+               adc0 |= old_adc0 & MC13XXX_ADC0_TSMOD_MASK;
+               adc1 |= 4 << MC13XXX_ADC1_CHAN1_SHIFT;
                break;
 
        default:
-               mc13783_unlock(mc13783);
+               mc13xxx_unlock(mc13xxx);
                return -EINVAL;
        }
 
-       dev_dbg(&mc13783->mc13xxx.spidev->dev, "%s: request irq\n", __func__);
-       mc13xxx_irq_request(mc13xxx, MC13783_IRQ_ADCDONE,
-                       mc13783_handler_adcdone, __func__, &adcdone_data);
-       mc13xxx_irq_ack(mc13xxx, MC13783_IRQ_ADCDONE);
+       dev_dbg(&mc13xxx->spidev->dev, "%s: request irq\n", __func__);
+       mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_ADCDONE,
+                       mc13xxx_handler_adcdone, __func__, &adcdone_data);
+       mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_ADCDONE);
 
-       mc13xxx_reg_write(mc13xxx, MC13783_ADC0, adc0);
-       mc13xxx_reg_write(mc13xxx, MC13783_ADC1, adc1);
+       mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, adc0);
+       mc13xxx_reg_write(mc13xxx, MC13XXX_ADC1, adc1);
 
        mc13xxx_unlock(mc13xxx);
 
@@ -660,27 +647,27 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
 
        mc13xxx_lock(mc13xxx);
 
-       mc13xxx_irq_free(mc13xxx, MC13783_IRQ_ADCDONE, &adcdone_data);
+       mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_ADCDONE, &adcdone_data);
 
        if (ret > 0)
                for (i = 0; i < 4; ++i) {
                        ret = mc13xxx_reg_read(mc13xxx,
-                                       MC13783_ADC2, &sample[i]);
+                                       MC13XXX_ADC2, &sample[i]);
                        if (ret)
                                break;
                }
 
-       if (mode == MC13783_ADC_MODE_TS)
+       if (mode == MC13XXX_ADC_MODE_TS)
                /* restore TSMOD */
-               mc13xxx_reg_write(mc13xxx, MC13783_ADC0, old_adc0);
+               mc13xxx_reg_write(mc13xxx, MC13XXX_ADC0, old_adc0);
 
-       mc13783->adcflags &= ~MC13783_ADC_WORKING;
+       mc13xxx->adcflags &= ~MC13XXX_ADC_WORKING;
 out:
        mc13xxx_unlock(mc13xxx);
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion);
+EXPORT_SYMBOL_GPL(mc13xxx_adc_do_conversion);
 
 static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
                const char *format, void *pdata, size_t pdata_size)
@@ -716,6 +703,11 @@ static int mc13xxx_probe(struct spi_device *spi)
        enum mc13xxx_id id;
        int ret;
 
+       if (!pdata) {
+               dev_err(&spi->dev, "invalid platform data\n");
+               return -EINVAL;
+       }
+
        mc13xxx = kzalloc(sizeof(*mc13xxx), GFP_KERNEL);
        if (!mc13xxx)
                return -ENOMEM;
@@ -763,10 +755,8 @@ err_revision:
        if (pdata->flags & MC13XXX_USE_CODEC)
                mc13xxx_add_subdevice(mc13xxx, "%s-codec");
 
-       if (pdata->flags & MC13XXX_USE_REGULATOR) {
-               mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
-                               &pdata->regulators, sizeof(pdata->regulators));
-       }
+       mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
+               &pdata->regulators, sizeof(pdata->regulators));
 
        if (pdata->flags & MC13XXX_USE_RTC)
                mc13xxx_add_subdevice(mc13xxx, "%s-rtc");
@@ -774,10 +764,14 @@ err_revision:
        if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
                mc13xxx_add_subdevice(mc13xxx, "%s-ts");
 
-       if (pdata->flags & MC13XXX_USE_LED)
+       if (pdata->leds)
                mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
                                pdata->leds, sizeof(*pdata->leds));
 
+       if (pdata->buttons)
+               mc13xxx_add_subdevice_pdata(mc13xxx, "%s-pwrbutton",
+                               pdata->buttons, sizeof(*pdata->buttons));
+
        return 0;
 }
 
index af5d9d0..cb4910a 100644 (file)
@@ -1226,7 +1226,7 @@ static int menelaus_probe(struct i2c_client *client,
        menelaus_write_reg(MENELAUS_MCT_CTRL1, 0x73);
 
        if (client->irq > 0) {
-               err = request_irq(client->irq, menelaus_irq, IRQF_DISABLED,
+               err = request_irq(client->irq, menelaus_irq, 0,
                                  DRIVER_NAME, menelaus);
                if (err) {
                        dev_dbg(&client->dev,  "can't get IRQ %d, err %d\n",
index 5786841..ff1a7e7 100644 (file)
 #include <linux/i2c.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
 
 #include <linux/mfd/pcf50633/core.h>
 
-static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
-{
-       int ret;
-
-       ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg,
-                               num, data);
-       if (ret < 0)
-               dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg);
-
-       return ret;
-}
-
-static int __pcf50633_write(struct pcf50633 *pcf, u8 reg, int num, u8 *data)
-{
-       int ret;
-
-       ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg,
-                               num, data);
-       if (ret < 0)
-               dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg);
-
-       return ret;
-
-}
-
 /* Read a block of up to 32 regs  */
 int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
                                        int nr_regs, u8 *data)
 {
        int ret;
 
-       mutex_lock(&pcf->lock);
-       ret = __pcf50633_read(pcf, reg, nr_regs, data);
-       mutex_unlock(&pcf->lock);
+       ret = regmap_raw_read(pcf->regmap, reg, data, nr_regs);
+       if (ret != 0)
+               return ret;
 
-       return ret;
+       return nr_regs;
 }
 EXPORT_SYMBOL_GPL(pcf50633_read_block);
 
@@ -71,21 +48,22 @@ int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
 {
        int ret;
 
-       mutex_lock(&pcf->lock);
-       ret = __pcf50633_write(pcf, reg, nr_regs, data);
-       mutex_unlock(&pcf->lock);
+       ret = regmap_raw_write(pcf->regmap, reg, data, nr_regs);
+       if (ret != 0)
+               return ret;
 
-       return ret;
+       return nr_regs;
 }
 EXPORT_SYMBOL_GPL(pcf50633_write_block);
 
 u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg)
 {
-       u8 val;
+       unsigned int val;
+       int ret;
 
-       mutex_lock(&pcf->lock);
-       __pcf50633_read(pcf, reg, 1, &val);
-       mutex_unlock(&pcf->lock);
+       ret = regmap_read(pcf->regmap, reg, &val);
+       if (ret < 0)
+               return -1;
 
        return val;
 }
@@ -93,56 +71,19 @@ EXPORT_SYMBOL_GPL(pcf50633_reg_read);
 
 int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val)
 {
-       int ret;
-
-       mutex_lock(&pcf->lock);
-       ret = __pcf50633_write(pcf, reg, 1, &val);
-       mutex_unlock(&pcf->lock);
-
-       return ret;
+       return regmap_write(pcf->regmap, reg, val);
 }
 EXPORT_SYMBOL_GPL(pcf50633_reg_write);
 
 int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val)
 {
-       int ret;
-       u8 tmp;
-
-       val &= mask;
-
-       mutex_lock(&pcf->lock);
-       ret = __pcf50633_read(pcf, reg, 1, &tmp);
-       if (ret < 0)
-               goto out;
-
-       tmp &= ~mask;
-       tmp |= val;
-       ret = __pcf50633_write(pcf, reg, 1, &tmp);
-
-out:
-       mutex_unlock(&pcf->lock);
-
-       return ret;
+       return regmap_update_bits(pcf->regmap, reg, mask, val);
 }
 EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask);
 
 int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val)
 {
-       int ret;
-       u8 tmp;
-
-       mutex_lock(&pcf->lock);
-       ret = __pcf50633_read(pcf, reg, 1, &tmp);
-       if (ret < 0)
-               goto out;
-
-       tmp &= ~val;
-       ret = __pcf50633_write(pcf, reg, 1, &tmp);
-
-out:
-       mutex_unlock(&pcf->lock);
-
-       return ret;
+       return regmap_update_bits(pcf->regmap, reg, val, 0);
 }
 EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits);
 
@@ -251,6 +192,11 @@ static int pcf50633_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
 
+static struct regmap_config pcf50633_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
 static int __devinit pcf50633_probe(struct i2c_client *client,
                                const struct i2c_device_id *ids)
 {
@@ -272,16 +218,23 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
 
        mutex_init(&pcf->lock);
 
+       pcf->regmap = regmap_init_i2c(client, &pcf50633_regmap_config);
+       if (IS_ERR(pcf->regmap)) {
+               ret = PTR_ERR(pcf->regmap);
+               dev_err(pcf->dev, "Failed to allocate register map: %d\n",
+                       ret);
+               goto err_free;
+       }
+
        i2c_set_clientdata(client, pcf);
        pcf->dev = &client->dev;
-       pcf->i2c_client = client;
 
        version = pcf50633_reg_read(pcf, 0);
        variant = pcf50633_reg_read(pcf, 1);
        if (version < 0 || variant < 0) {
                dev_err(pcf->dev, "Unable to probe pcf50633\n");
                ret = -ENODEV;
-               goto err_free;
+               goto err_regmap;
        }
 
        dev_info(pcf->dev, "Probed device version %d variant %d\n",
@@ -328,6 +281,8 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
 
        return 0;
 
+err_regmap:
+       regmap_exit(pcf->regmap);
 err_free:
        kfree(pcf);
 
@@ -351,6 +306,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
        for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
                platform_device_unregister(pcf->regulator_pdev[i]);
 
+       regmap_exit(pcf->regmap);
        kfree(pcf);
 
        return 0;
index c27e515..de97974 100644 (file)
@@ -357,6 +357,7 @@ static int __devexit tc3589x_remove(struct i2c_client *client)
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int tc3589x_suspend(struct device *dev)
 {
        struct tc3589x *tc3589x = dev_get_drvdata(dev);
@@ -387,6 +388,7 @@ static int tc3589x_resume(struct device *dev)
 
 static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend,
                                                tc3589x_resume);
+#endif
 
 static const struct i2c_device_id tc3589x_id[] = {
        { "tc3589x", 24 },
index 696879e..02d6569 100644 (file)
@@ -697,7 +697,7 @@ static int __devinit timb_probe(struct pci_dev *dev,
                dev_err(&dev->dev, "The driver supports an older "
                        "version of the FPGA, please update the driver to "
                        "support %d.%d\n", priv->fw.major, priv->fw.minor);
-               goto err_ioremap;
+               goto err_config;
        }
        if (priv->fw.major < TIMB_SUPPORTED_MAJOR ||
                priv->fw.minor < TIMB_REQUIRED_MINOR) {
@@ -705,13 +705,13 @@ static int __devinit timb_probe(struct pci_dev *dev,
                        "please upgrade the FPGA to at least: %d.%d\n",
                        priv->fw.major, priv->fw.minor,
                        TIMB_SUPPORTED_MAJOR, TIMB_REQUIRED_MINOR);
-               goto err_ioremap;
+               goto err_config;
        }
 
        msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries),
                GFP_KERNEL);
        if (!msix_entries)
-               goto err_ioremap;
+               goto err_config;
 
        for (i = 0; i < TIMBERDALE_NR_IRQS; i++)
                msix_entries[i].entry = i;
@@ -825,6 +825,8 @@ err_mfd:
 err_create_file:
        pci_disable_msix(dev);
 err_msix:
+       kfree(msix_entries);
+err_config:
        iounmap(priv->ctl_membase);
 err_ioremap:
        release_mem_region(priv->ctl_mapbase, CHIPCTLSIZE);
@@ -833,7 +835,6 @@ err_request:
 err_start:
        pci_disable_device(dev);
 err_enable:
-       kfree(msix_entries);
        kfree(priv);
        pci_set_drvdata(dev, NULL);
        return -ENODEV;
index 955bc00..5fec23a 100644 (file)
@@ -131,9 +131,6 @@ int tps65912_device_init(struct tps65912 *tps65912)
        if (init_data == NULL)
                return -ENOMEM;
 
-       init_data->irq = pmic_plat_data->irq;
-       init_data->irq_base = pmic_plat_data->irq;
-
        mutex_init(&tps65912->io_mutex);
        dev_set_drvdata(tps65912->dev, tps65912);
 
@@ -153,10 +150,13 @@ int tps65912_device_init(struct tps65912 *tps65912)
        if (ret < 0)
                goto err;
 
+       init_data->irq = pmic_plat_data->irq;
+       init_data->irq_base = pmic_plat_data->irq;
        ret = tps65912_irq_init(tps65912, init_data->irq, init_data);
        if (ret < 0)
                goto err;
 
+       kfree(init_data);
        return ret;
 
 err:
index 01ecfee..b8eef46 100644 (file)
 #define twl_has_watchdog()        false
 #endif
 
-#if defined(CONFIG_TWL4030_CODEC) || defined(CONFIG_TWL4030_CODEC_MODULE) ||\
+#if defined(CONFIG_MFD_TWL4030_AUDIO) || defined(CONFIG_MFD_TWL4030_AUDIO_MODULE) ||\
        defined(CONFIG_TWL6040_CORE) || defined(CONFIG_TWL6040_CORE_MODULE)
 #define twl_has_codec()        true
 #else
index 8a7ee31..f062c8c 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/kthread.h>
 #include <linux/slab.h>
 
 #include <linux/i2c/twl.h>
@@ -278,59 +277,6 @@ static const struct sih sih_modules_twl5031[8] = {
 
 static unsigned twl4030_irq_base;
 
-static struct completion irq_event;
-
-/*
- * This thread processes interrupts reported by the Primary Interrupt Handler.
- */
-static int twl4030_irq_thread(void *data)
-{
-       long irq = (long)data;
-       static unsigned i2c_errors;
-       static const unsigned max_i2c_errors = 100;
-
-
-       current->flags |= PF_NOFREEZE;
-
-       while (!kthread_should_stop()) {
-               int ret;
-               int module_irq;
-               u8 pih_isr;
-
-               /* Wait for IRQ, then read PIH irq status (also blocking) */
-               wait_for_completion_interruptible(&irq_event);
-
-               ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
-                                         REG_PIH_ISR_P1);
-               if (ret) {
-                       pr_warning("twl4030: I2C error %d reading PIH ISR\n",
-                                       ret);
-                       if (++i2c_errors >= max_i2c_errors) {
-                               printk(KERN_ERR "Maximum I2C error count"
-                                               " exceeded.  Terminating %s.\n",
-                                               __func__);
-                               break;
-                       }
-                       complete(&irq_event);
-                       continue;
-               }
-
-               /* these handlers deal with the relevant SIH irq status */
-               local_irq_disable();
-               for (module_irq = twl4030_irq_base;
-                               pih_isr;
-                               pih_isr >>= 1, module_irq++) {
-                       if (pih_isr & 0x1)
-                               generic_handle_irq(module_irq);
-               }
-               local_irq_enable();
-
-               enable_irq(irq);
-       }
-
-       return 0;
-}
-
 /*
  * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt.
  * This is a chained interrupt, so there is no desc->action method for it.
@@ -342,9 +288,25 @@ static int twl4030_irq_thread(void *data)
  */
 static irqreturn_t handle_twl4030_pih(int irq, void *devid)
 {
-       /* Acknowledge, clear *AND* mask the interrupt... */
-       disable_irq_nosync(irq);
-       complete(devid);
+       int             module_irq;
+       irqreturn_t     ret;
+       u8              pih_isr;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
+                       REG_PIH_ISR_P1);
+       if (ret) {
+               pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret);
+               return IRQ_NONE;
+       }
+
+       /* these handlers deal with the relevant SIH irq status */
+       for (module_irq = twl4030_irq_base;
+                       pih_isr;
+                       pih_isr >>= 1, module_irq++) {
+               if (pih_isr & 0x1)
+                       handle_nested_irq(module_irq);
+       }
+
        return IRQ_HANDLED;
 }
 /*----------------------------------------------------------------------*/
@@ -460,113 +422,17 @@ static inline void activate_irq(int irq)
 
 /*----------------------------------------------------------------------*/
 
-static DEFINE_SPINLOCK(sih_agent_lock);
-
-static struct workqueue_struct *wq;
-
 struct sih_agent {
        int                     irq_base;
        const struct sih        *sih;
 
        u32                     imr;
        bool                    imr_change_pending;
-       struct work_struct      mask_work;
-
-       u32                     edge_change;
-       struct work_struct      edge_work;
-};
-
-static void twl4030_sih_do_mask(struct work_struct *work)
-{
-       struct sih_agent        *agent;
-       const struct sih        *sih;
-       union {
-               u8      bytes[4];
-               u32     word;
-       }                       imr;
-       int                     status;
 
-       agent = container_of(work, struct sih_agent, mask_work);
-
-       /* see what work we have */
-       spin_lock_irq(&sih_agent_lock);
-       if (agent->imr_change_pending) {
-               sih = agent->sih;
-               /* byte[0] gets overwritten as we write ... */
-               imr.word = cpu_to_le32(agent->imr << 8);
-               agent->imr_change_pending = false;
-       } else
-               sih = NULL;
-       spin_unlock_irq(&sih_agent_lock);
-       if (!sih)
-               return;
-
-       /* write the whole mask ... simpler than subsetting it */
-       status = twl_i2c_write(sih->module, imr.bytes,
-                       sih->mask[irq_line].imr_offset, sih->bytes_ixr);
-       if (status)
-               pr_err("twl4030: %s, %s --> %d\n", __func__,
-                               "write", status);
-}
-
-static void twl4030_sih_do_edge(struct work_struct *work)
-{
-       struct sih_agent        *agent;
-       const struct sih        *sih;
-       u8                      bytes[6];
        u32                     edge_change;
-       int                     status;
-
-       agent = container_of(work, struct sih_agent, edge_work);
-
-       /* see what work we have */
-       spin_lock_irq(&sih_agent_lock);
-       edge_change = agent->edge_change;
-       agent->edge_change = 0;
-       sih = edge_change ? agent->sih : NULL;
-       spin_unlock_irq(&sih_agent_lock);
-       if (!sih)
-               return;
-
-       /* Read, reserving first byte for write scratch.  Yes, this
-        * could be cached for some speedup ... but be careful about
-        * any processor on the other IRQ line, EDR registers are
-        * shared.
-        */
-       status = twl_i2c_read(sih->module, bytes + 1,
-                       sih->edr_offset, sih->bytes_edr);
-       if (status) {
-               pr_err("twl4030: %s, %s --> %d\n", __func__,
-                               "read", status);
-               return;
-       }
-
-       /* Modify only the bits we know must change */
-       while (edge_change) {
-               int             i = fls(edge_change) - 1;
-               struct irq_data *idata = irq_get_irq_data(i + agent->irq_base);
-               int             byte = 1 + (i >> 2);
-               int             off = (i & 0x3) * 2;
-               unsigned int    type;
-
-               bytes[byte] &= ~(0x03 << off);
 
-               type = irqd_get_trigger_type(idata);
-               if (type & IRQ_TYPE_EDGE_RISING)
-                       bytes[byte] |= BIT(off + 1);
-               if (type & IRQ_TYPE_EDGE_FALLING)
-                       bytes[byte] |= BIT(off + 0);
-
-               edge_change &= ~BIT(i);
-       }
-
-       /* Write */
-       status = twl_i2c_write(sih->module, bytes,
-                       sih->edr_offset, sih->bytes_edr);
-       if (status)
-               pr_err("twl4030: %s, %s --> %d\n", __func__,
-                               "write", status);
-}
+       struct mutex            irq_lock;
+};
 
 /*----------------------------------------------------------------------*/
 
@@ -579,50 +445,125 @@ static void twl4030_sih_do_edge(struct work_struct *work)
 
 static void twl4030_sih_mask(struct irq_data *data)
 {
-       struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-       unsigned long flags;
-
-       spin_lock_irqsave(&sih_agent_lock, flags);
-       sih->imr |= BIT(data->irq - sih->irq_base);
-       sih->imr_change_pending = true;
-       queue_work(wq, &sih->mask_work);
-       spin_unlock_irqrestore(&sih_agent_lock, flags);
+       struct sih_agent *agent = irq_data_get_irq_chip_data(data);
+
+       agent->imr |= BIT(data->irq - agent->irq_base);
+       agent->imr_change_pending = true;
 }
 
 static void twl4030_sih_unmask(struct irq_data *data)
 {
-       struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-       unsigned long flags;
-
-       spin_lock_irqsave(&sih_agent_lock, flags);
-       sih->imr &= ~BIT(data->irq - sih->irq_base);
-       sih->imr_change_pending = true;
-       queue_work(wq, &sih->mask_work);
-       spin_unlock_irqrestore(&sih_agent_lock, flags);
+       struct sih_agent *agent = irq_data_get_irq_chip_data(data);
+
+       agent->imr &= ~BIT(data->irq - agent->irq_base);
+       agent->imr_change_pending = true;
 }
 
 static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
 {
-       struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-       unsigned long flags;
+       struct sih_agent *agent = irq_data_get_irq_chip_data(data);
 
        if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
                return -EINVAL;
 
-       spin_lock_irqsave(&sih_agent_lock, flags);
-       if (irqd_get_trigger_type(data) != trigger) {
-               sih->edge_change |= BIT(data->irq - sih->irq_base);
-               queue_work(wq, &sih->edge_work);
-       }
-       spin_unlock_irqrestore(&sih_agent_lock, flags);
+       if (irqd_get_trigger_type(data) != trigger)
+               agent->edge_change |= BIT(data->irq - agent->irq_base);
+
        return 0;
 }
 
+static void twl4030_sih_bus_lock(struct irq_data *data)
+{
+       struct sih_agent        *agent = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&agent->irq_lock);
+}
+
+static void twl4030_sih_bus_sync_unlock(struct irq_data *data)
+{
+       struct sih_agent        *agent = irq_data_get_irq_chip_data(data);
+       const struct sih        *sih = agent->sih;
+       int                     status;
+
+       if (agent->imr_change_pending) {
+               union {
+                       u32     word;
+                       u8      bytes[4];
+               } imr;
+
+               /* byte[0] gets overwriten as we write ... */
+               imr.word = cpu_to_le32(agent->imr << 8);
+               agent->imr_change_pending = false;
+
+               /* write the whole mask ... simpler than subsetting it */
+               status = twl_i2c_write(sih->module, imr.bytes,
+                               sih->mask[irq_line].imr_offset,
+                               sih->bytes_ixr);
+               if (status)
+                       pr_err("twl4030: %s, %s --> %d\n", __func__,
+                                       "write", status);
+       }
+
+       if (agent->edge_change) {
+               u32             edge_change;
+               u8              bytes[6];
+
+               edge_change = agent->edge_change;
+               agent->edge_change = 0;
+
+               /*
+                * Read, reserving first byte for write scratch.  Yes, this
+                * could be cached for some speedup ... but be careful about
+                * any processor on the other IRQ line, EDR registers are
+                * shared.
+                */
+               status = twl_i2c_read(sih->module, bytes + 1,
+                               sih->edr_offset, sih->bytes_edr);
+               if (status) {
+                       pr_err("twl4030: %s, %s --> %d\n", __func__,
+                                       "read", status);
+                       return;
+               }
+
+               /* Modify only the bits we know must change */
+               while (edge_change) {
+                       int             i = fls(edge_change) - 1;
+                       struct irq_data *idata;
+                       int             byte = 1 + (i >> 2);
+                       int             off = (i & 0x3) * 2;
+                       unsigned int    type;
+
+                       idata = irq_get_irq_data(i + agent->irq_base);
+
+                       bytes[byte] &= ~(0x03 << off);
+
+                       type = irqd_get_trigger_type(idata);
+                       if (type & IRQ_TYPE_EDGE_RISING)
+                               bytes[byte] |= BIT(off + 1);
+                       if (type & IRQ_TYPE_EDGE_FALLING)
+                               bytes[byte] |= BIT(off + 0);
+
+                       edge_change &= ~BIT(i);
+               }
+
+               /* Write */
+               status = twl_i2c_write(sih->module, bytes,
+                               sih->edr_offset, sih->bytes_edr);
+               if (status)
+                       pr_err("twl4030: %s, %s --> %d\n", __func__,
+                                       "write", status);
+       }
+
+       mutex_unlock(&agent->irq_lock);
+}
+
 static struct irq_chip twl4030_sih_irq_chip = {
        .name           = "twl4030",
-       .irq_mask       = twl4030_sih_mask,
+       .irq_mask       = twl4030_sih_mask,
        .irq_unmask     = twl4030_sih_unmask,
        .irq_set_type   = twl4030_sih_set_type,
+       .irq_bus_lock   = twl4030_sih_bus_lock,
+       .irq_bus_sync_unlock = twl4030_sih_bus_sync_unlock,
 };
 
 /*----------------------------------------------------------------------*/
@@ -655,9 +596,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
        int isr;
 
        /* reading ISR acks the IRQs, using clear-on-read mode */
-       local_irq_enable();
        isr = sih_read_isr(sih);
-       local_irq_disable();
 
        if (isr < 0) {
                pr_err("twl4030: %s SIH, read ISR error %d\n",
@@ -672,7 +611,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
                isr &= ~BIT(irq);
 
                if (irq < sih->bits)
-                       generic_handle_irq(agent->irq_base + irq);
+                       handle_nested_irq(agent->irq_base + irq);
                else
                        pr_err("twl4030: %s SIH, invalid ISR bit %d\n",
                                sih->name, irq);
@@ -718,15 +657,14 @@ int twl4030_sih_setup(int module)
        agent->irq_base = irq_base;
        agent->sih = sih;
        agent->imr = ~0;
-       INIT_WORK(&agent->mask_work, twl4030_sih_do_mask);
-       INIT_WORK(&agent->edge_work, twl4030_sih_do_edge);
+       mutex_init(&agent->irq_lock);
 
        for (i = 0; i < sih->bits; i++) {
                irq = irq_base + i;
 
+               irq_set_chip_data(irq, agent);
                irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip,
                                         handle_edge_irq);
-               irq_set_chip_data(irq, agent);
                activate_irq(irq);
        }
 
@@ -758,7 +696,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
 
        int                     status;
        int                     i;
-       struct task_struct      *task;
 
        /*
         * Mask and clear all TWL4030 interrupts since initially we do
@@ -768,12 +705,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        if (status < 0)
                return status;
 
-       wq = create_singlethread_workqueue("twl4030-irqchip");
-       if (!wq) {
-               pr_err("twl4030: workqueue FAIL\n");
-               return -ESRCH;
-       }
-
        twl4030_irq_base = irq_base;
 
        /* install an irq handler for each of the SIH modules;
@@ -787,6 +718,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        for (i = irq_base; i < irq_end; i++) {
                irq_set_chip_and_handler(i, &twl4030_irq_chip,
                                         handle_simple_irq);
+               irq_set_nested_thread(i, 1);
                activate_irq(i);
        }
        twl4030_irq_next = i;
@@ -801,34 +733,22 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        }
 
        /* install an irq handler to demultiplex the TWL4030 interrupt */
-
-
-       init_completion(&irq_event);
-
-       status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED,
-                               "TWL4030-PIH", &irq_event);
+       status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih, 0,
+                                       "TWL4030-PIH", NULL);
        if (status < 0) {
                pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
                goto fail_rqirq;
        }
 
-       task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num,
-                                                               "twl4030-irq");
-       if (IS_ERR(task)) {
-               pr_err("twl4030: could not create irq %d thread!\n", irq_num);
-               status = PTR_ERR(task);
-               goto fail_kthread;
-       }
        return status;
-fail_kthread:
-       free_irq(irq_num, &irq_event);
 fail_rqirq:
        /* clean up twl4030_sih_setup */
 fail:
-       for (i = irq_base; i < irq_end; i++)
+       for (i = irq_base; i < irq_end; i++) {
+               irq_set_nested_thread(i, 0);
                irq_set_chip_and_handler(i, NULL, NULL);
-       destroy_workqueue(wq);
-       wq = NULL;
+       }
+
        return status;
 }
 
index 7cbf2aa..834f824 100644 (file)
@@ -740,6 +740,28 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev)
                        TWL4030_BCI_BCICTL1);
                goto err_i2c;
        }
+
+       /* Check that MADC clock is on */
+       ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
+       if (ret) {
+               dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
+                               TWL4030_REG_GPBR1);
+               goto err_i2c;
+       }
+
+       /* If MADC clk is not on, turn it on */
+       if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
+               dev_info(&pdev->dev, "clk disabled, enabling\n");
+               regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
+               ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
+                                      TWL4030_REG_GPBR1);
+               if (ret) {
+                       dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
+                                       TWL4030_REG_GPBR1);
+                       goto err_i2c;
+               }
+       }
+
        platform_set_drvdata(pdev, madc);
        mutex_init(&madc->lock);
        ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
index eb3b5f8..deec3ec 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kthread.h>
 #include <linux/i2c/twl.h>
 #include <linux/platform_device.h>
+#include <linux/suspend.h>
 
 #include "twl-core.h"
 
@@ -83,8 +84,48 @@ static int twl6030_interrupt_mapping[24] = {
 /*----------------------------------------------------------------------*/
 
 static unsigned twl6030_irq_base;
+static int twl_irq;
+static bool twl_irq_wake_enabled;
 
 static struct completion irq_event;
+static atomic_t twl6030_wakeirqs = ATOMIC_INIT(0);
+
+static int twl6030_irq_pm_notifier(struct notifier_block *notifier,
+                                  unsigned long pm_event, void *unused)
+{
+       int chained_wakeups;
+
+       switch (pm_event) {
+       case PM_SUSPEND_PREPARE:
+               chained_wakeups = atomic_read(&twl6030_wakeirqs);
+
+               if (chained_wakeups && !twl_irq_wake_enabled) {
+                       if (enable_irq_wake(twl_irq))
+                               pr_err("twl6030 IRQ wake enable failed\n");
+                       else
+                               twl_irq_wake_enabled = true;
+               } else if (!chained_wakeups && twl_irq_wake_enabled) {
+                       disable_irq_wake(twl_irq);
+                       twl_irq_wake_enabled = false;
+               }
+
+               disable_irq(twl_irq);
+               break;
+
+       case PM_POST_SUSPEND:
+               enable_irq(twl_irq);
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block twl6030_irq_pm_notifier_block = {
+       .notifier_call = twl6030_irq_pm_notifier,
+};
 
 /*
  * This thread processes interrupts reported by the Primary Interrupt Handler.
@@ -187,6 +228,16 @@ static inline void activate_irq(int irq)
 #endif
 }
 
+int twl6030_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+       if (on)
+               atomic_inc(&twl6030_wakeirqs);
+       else
+               atomic_dec(&twl6030_wakeirqs);
+
+       return 0;
+}
+
 /*----------------------------------------------------------------------*/
 
 static unsigned twl6030_irq_next;
@@ -318,10 +369,12 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
        twl6030_irq_chip = dummy_irq_chip;
        twl6030_irq_chip.name = "twl6030";
        twl6030_irq_chip.irq_set_type = NULL;
+       twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake;
 
        for (i = irq_base; i < irq_end; i++) {
                irq_set_chip_and_handler(i, &twl6030_irq_chip,
                                         handle_simple_irq);
+               irq_set_chip_data(i, (void *)irq_num);
                activate_irq(i);
        }
 
@@ -331,6 +384,14 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
 
        /* install an irq handler to demultiplex the TWL6030 interrupt */
        init_completion(&irq_event);
+
+       status = request_irq(irq_num, handle_twl6030_pih, 0,
+                               "TWL6030-PIH", &irq_event);
+       if (status < 0) {
+               pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
+               goto fail_irq;
+       }
+
        task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
        if (IS_ERR(task)) {
                pr_err("twl6030: could not create irq %d thread!\n", irq_num);
@@ -338,17 +399,14 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
                goto fail_kthread;
        }
 
-       status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED,
-                               "TWL6030-PIH", &irq_event);
-       if (status < 0) {
-               pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
-               goto fail_irq;
-       }
+       twl_irq = irq_num;
+       register_pm_notifier(&twl6030_irq_pm_notifier_block);
        return status;
-fail_irq:
-       free_irq(irq_num, &irq_event);
 
 fail_kthread:
+       free_irq(irq_num, &irq_event);
+
+fail_irq:
        for (i = irq_base; i < irq_end; i++)
                irq_set_chip_and_handler(i, NULL, NULL);
        return status;
@@ -356,6 +414,7 @@ fail_kthread:
 
 int twl6030_exit_irq(void)
 {
+       unregister_pm_notifier(&twl6030_irq_pm_notifier_block);
 
        if (twl6030_irq_base) {
                pr_err("twl6030: can't yet clean up IRQs?\n");
index ada1835..f4747a4 100644 (file)
@@ -420,12 +420,19 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
        switch (type) {
        case IRQ_TYPE_EDGE_BOTH:
                wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE;
+               wm831x->gpio_level[irq] = false;
                break;
        case IRQ_TYPE_EDGE_RISING:
                wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
+               wm831x->gpio_level[irq] = false;
                break;
        case IRQ_TYPE_EDGE_FALLING:
                wm831x->gpio_update[irq] = 0x10000;
+               wm831x->gpio_level[irq] = false;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
+               wm831x->gpio_level[irq] = true;
                break;
        default:
                return -EINVAL;
@@ -449,7 +456,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
 {
        struct wm831x *wm831x = data;
        unsigned int i;
-       int primary, status_addr;
+       int primary, status_addr, ret;
        int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
        int read[WM831X_NUM_IRQ_REGS] = { 0 };
        int *status;
@@ -507,6 +514,19 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
 
                if (*status & wm831x_irqs[i].mask)
                        handle_nested_irq(wm831x->irq_base + i);
+
+               /* Simulate an edge triggered IRQ by polling the input
+                * status.  This is sucky but improves interoperability.
+                */
+               if (primary == WM831X_GP_INT &&
+                   wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) {
+                       ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
+                       while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) {
+                               handle_nested_irq(wm831x->irq_base + i);
+                               ret = wm831x_reg_read(wm831x,
+                                                     WM831X_GPIO_LEVEL);
+                       }
+               }
        }
 
 out:
@@ -596,8 +616,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
                         "No interrupt specified - functionality limited\n");
        }
 
-
-
        /* Enable top level interrupts, we mask at secondary level */
        wm831x_reg_write(wm831x, WM831X_SYSTEM_INTERRUPTS_MASK, 0);
 
index b03be1d..5d6ba13 100644 (file)
@@ -217,6 +217,47 @@ static int wm8994_suspend(struct device *dev)
                return 0;
        }
 
+       ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_4);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read power status: %d\n", ret);
+       } else if (ret & (WM8994_AIF2ADCL_ENA | WM8994_AIF2ADCR_ENA |
+                         WM8994_AIF1ADC2L_ENA | WM8994_AIF1ADC2R_ENA |
+                         WM8994_AIF1ADC1L_ENA | WM8994_AIF1ADC1R_ENA)) {
+               dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+               return 0;
+       }
+
+       ret = wm8994_reg_read(wm8994, WM8994_POWER_MANAGEMENT_5);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read power status: %d\n", ret);
+       } else if (ret & (WM8994_AIF2DACL_ENA | WM8994_AIF2DACR_ENA |
+                         WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA |
+                         WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA)) {
+               dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+               return 0;
+       }
+
+       switch (wm8994->type) {
+       case WM8958:
+               ret = wm8994_reg_read(wm8994, WM8958_MIC_DETECT_1);
+               if (ret < 0) {
+                       dev_err(dev, "Failed to read power status: %d\n", ret);
+               } else if (ret & WM8958_MICD_ENA) {
+                       dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+                       return 0;
+               }
+               break;
+       default:
+               break;
+       }
+
+       /* Disable LDO pulldowns while the device is suspended if we
+        * don't know that something will be driving them. */
+       if (!wm8994->ldo_ena_always_driven)
+               wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+                               WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+                               WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
+
        /* GPIO configuration state is saved here since we may be configuring
         * the GPIO alternate functions even if we're not using the gpiolib
         * driver for them.
@@ -286,6 +327,11 @@ static int wm8994_resume(struct device *dev)
        if (ret < 0)
                dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
 
+       /* Disable LDO pulldowns while the device is active */
+       wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+                       WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+                       0);
+
        wm8994->suspended = false;
 
        return 0;
@@ -467,8 +513,15 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
                                                pdata->gpio_defaults[i]);
                        }
                }
+
+               wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
        }
 
+       /* Disable LDO pulldowns while the device is active */
+       wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
+                       WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
+                       0);
+
        /* In some system designs where the regulators are not in use,
         * we can achieve a small reduction in leakage currents by
         * floating LDO outputs.  This bit makes no difference if the
index 2bb8f45..2d014a1 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/err.h>
 #include <linux/spinlock.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/db8500-prcmu.h>
index 730f43a..cb2841f 100644 (file)
@@ -336,9 +336,9 @@ static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv;
        struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
-       struct mc13783_regulator_platform_data *pdata =
+       struct mc13xxx_regulator_platform_data *pdata =
                dev_get_platdata(&pdev->dev);
-       struct mc13783_regulator_init_data *init_data;
+       struct mc13xxx_regulator_init_data *init_data;
        int i, ret;
 
        dev_dbg(&pdev->dev, "%s id %d\n", __func__, pdev->id);
@@ -381,7 +381,7 @@ err:
 static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
-       struct mc13783_regulator_platform_data *pdata =
+       struct mc13xxx_regulator_platform_data *pdata =
                dev_get_platdata(&pdev->dev);
        int i;
 
index 6427d29..530e11b 100644 (file)
@@ -129,6 +129,10 @@ enum sample_type {
 #define REG_BCICTL2             0x024
 #define TWL4030_BCI_ITHSENS    0x007
 
+/* Register and bits for GPBR1 register */
+#define TWL4030_REG_GPBR1              0x0c
+#define TWL4030_GPBR1_MADC_HFCLK_EN    (1 << 7)
+
 struct twl4030_madc_user_parms {
        int channel;
        int average;
diff --git a/include/linux/mfd/ab5500/ab5500.h b/include/linux/mfd/ab5500/ab5500.h
new file mode 100644 (file)
index 0000000..a720051
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) ST-Ericsson 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+#ifndef MFD_AB5500_H
+#define MFD_AB5500_H
+
+#include <linux/device.h>
+
+enum ab5500_devid {
+       AB5500_DEVID_ADC,
+       AB5500_DEVID_LEDS,
+       AB5500_DEVID_POWER,
+       AB5500_DEVID_REGULATORS,
+       AB5500_DEVID_SIM,
+       AB5500_DEVID_RTC,
+       AB5500_DEVID_CHARGER,
+       AB5500_DEVID_FUELGAUGE,
+       AB5500_DEVID_VIBRATOR,
+       AB5500_DEVID_CODEC,
+       AB5500_DEVID_USB,
+       AB5500_DEVID_OTP,
+       AB5500_DEVID_VIDEO,
+       AB5500_DEVID_DBIECI,
+       AB5500_DEVID_ONSWA,
+       AB5500_NUM_DEVICES,
+};
+
+enum ab5500_banks {
+       AB5500_BANK_VIT_IO_I2C_CLK_TST_OTP = 0,
+       AB5500_BANK_VDDDIG_IO_I2C_CLK_TST = 1,
+       AB5500_BANK_VDENC = 2,
+       AB5500_BANK_SIM_USBSIM  = 3,
+       AB5500_BANK_LED = 4,
+       AB5500_BANK_ADC  = 5,
+       AB5500_BANK_RTC  = 6,
+       AB5500_BANK_STARTUP  = 7,
+       AB5500_BANK_DBI_ECI  = 8,
+       AB5500_BANK_CHG  = 9,
+       AB5500_BANK_FG_BATTCOM_ACC = 10,
+       AB5500_BANK_USB = 11,
+       AB5500_BANK_IT = 12,
+       AB5500_BANK_VIBRA = 13,
+       AB5500_BANK_AUDIO_HEADSETUSB = 14,
+       AB5500_NUM_BANKS = 15,
+};
+
+enum ab5500_banks_addr {
+       AB5500_ADDR_VIT_IO_I2C_CLK_TST_OTP = 0x4A,
+       AB5500_ADDR_VDDDIG_IO_I2C_CLK_TST = 0x4B,
+       AB5500_ADDR_VDENC = 0x06,
+       AB5500_ADDR_SIM_USBSIM  = 0x04,
+       AB5500_ADDR_LED = 0x10,
+       AB5500_ADDR_ADC  = 0x0A,
+       AB5500_ADDR_RTC  = 0x0F,
+       AB5500_ADDR_STARTUP  = 0x03,
+       AB5500_ADDR_DBI_ECI  = 0x07,
+       AB5500_ADDR_CHG  = 0x0B,
+       AB5500_ADDR_FG_BATTCOM_ACC = 0x0C,
+       AB5500_ADDR_USB = 0x05,
+       AB5500_ADDR_IT = 0x0E,
+       AB5500_ADDR_VIBRA = 0x02,
+       AB5500_ADDR_AUDIO_HEADSETUSB = 0x0D,
+};
+
+/*
+ * Interrupt register offsets
+ * Bank : 0x0E
+ */
+#define AB5500_IT_SOURCE0_REG          0x20
+#define AB5500_IT_SOURCE1_REG          0x21
+#define AB5500_IT_SOURCE2_REG          0x22
+#define AB5500_IT_SOURCE3_REG          0x23
+#define AB5500_IT_SOURCE4_REG          0x24
+#define AB5500_IT_SOURCE5_REG          0x25
+#define AB5500_IT_SOURCE6_REG          0x26
+#define AB5500_IT_SOURCE7_REG          0x27
+#define AB5500_IT_SOURCE8_REG          0x28
+#define AB5500_IT_SOURCE9_REG          0x29
+#define AB5500_IT_SOURCE10_REG         0x2A
+#define AB5500_IT_SOURCE11_REG         0x2B
+#define AB5500_IT_SOURCE12_REG         0x2C
+#define AB5500_IT_SOURCE13_REG         0x2D
+#define AB5500_IT_SOURCE14_REG         0x2E
+#define AB5500_IT_SOURCE15_REG         0x2F
+#define AB5500_IT_SOURCE16_REG         0x30
+#define AB5500_IT_SOURCE17_REG         0x31
+#define AB5500_IT_SOURCE18_REG         0x32
+#define AB5500_IT_SOURCE19_REG         0x33
+#define AB5500_IT_SOURCE20_REG         0x34
+#define AB5500_IT_SOURCE21_REG         0x35
+#define AB5500_IT_SOURCE22_REG         0x36
+#define AB5500_IT_SOURCE23_REG         0x37
+
+#define AB5500_NUM_IRQ_REGS            23
+
+/**
+ * struct ab5500
+ * @access_mutex: lock out concurrent accesses to the AB registers
+ * @dev: a pointer to the device struct for this chip driver
+ * @ab5500_irq: the analog baseband irq
+ * @irq_base: the platform configuration irq base for subdevices
+ * @chip_name: name of this chip variant
+ * @chip_id: 8 bit chip ID for this chip variant
+ * @irq_lock: a lock to protect the mask
+ * @abb_events: a local bit mask of the prcmu wakeup events
+ * @event_mask: a local copy of the mask event registers
+ * @last_event_mask: a copy of the last event_mask written to hardware
+ * @startup_events: a copy of the first reading of the event registers
+ * @startup_events_read: whether the first events have been read
+ */
+struct ab5500 {
+       struct mutex access_mutex;
+       struct device *dev;
+       unsigned int ab5500_irq;
+       unsigned int irq_base;
+       char chip_name[32];
+       u8 chip_id;
+       struct mutex irq_lock;
+       u32 abb_events;
+       u8 mask[AB5500_NUM_IRQ_REGS];
+       u8 oldmask[AB5500_NUM_IRQ_REGS];
+       u8 startup_events[AB5500_NUM_IRQ_REGS];
+       bool startup_events_read;
+#ifdef CONFIG_DEBUG_FS
+       unsigned int debug_bank;
+       unsigned int debug_address;
+#endif
+};
+
+struct ab5500_platform_data {
+       struct {unsigned int base; unsigned int count; } irq;
+       void *dev_data[AB5500_NUM_DEVICES];
+       struct abx500_init_settings *init_settings;
+       unsigned int init_settings_sz;
+       bool pm_power_off;
+};
+
+#endif /* MFD_AB5500_H */
index 46b9540..2529667 100644 (file)
@@ -27,6 +27,9 @@
 struct ab8500_gpadc;
 
 struct ab8500_gpadc *ab8500_gpadc_get(char *name);
-int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input);
+int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 channel);
+int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel);
+int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc,
+    u8 channel, int ad_value);
 
 #endif /* _AB8500_GPADC_H */
index 896b5e4..9970337 100644 (file)
@@ -6,7 +6,7 @@
  *
  * ABX500 core access functions.
  * The abx500 interface is used for the Analog Baseband chip
- * ab3100, ab3550, ab5500, and ab8500.
+ * ab3100, ab5500, and ab8500.
  *
  * Author: Mattias Wallin <mattias.wallin@stericsson.com>
  * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com>
 #define AB3100_P1G     0xc6
 #define AB3100_R2A     0xc7
 #define AB3100_R2B     0xc8
-#define AB3550_P1A     0x10
 #define AB5500_1_0     0x20
-#define AB5500_2_0     0x21
-#define AB5500_2_1     0x22
+#define AB5500_1_1     0x21
+#define AB5500_2_0     0x24
 
 /* AB8500 CIDs*/
-#define AB8500_CUTEARLY        0x00
 #define AB8500_CUT1P0  0x10
 #define AB8500_CUT1P1  0x11
 #define AB8500_CUT2P0  0x20
 #define AB8500_CUT3P0  0x30
+#define AB8500_CUT3P3  0x33
 
 /*
  * AB3100, EVENTA1, A2 and A3 event register flags
@@ -143,39 +142,6 @@ int ab3100_event_register(struct ab3100 *ab3100,
 int ab3100_event_unregister(struct ab3100 *ab3100,
                            struct notifier_block *nb);
 
-/* AB3550, STR register flags */
-#define AB3550_STR_ONSWA                               (0x01)
-#define AB3550_STR_ONSWB                               (0x02)
-#define AB3550_STR_ONSWC                               (0x04)
-#define AB3550_STR_DCIO                                        (0x08)
-#define AB3550_STR_BOOT_MODE                           (0x10)
-#define AB3550_STR_SIM_OFF                             (0x20)
-#define AB3550_STR_BATT_REMOVAL                                (0x40)
-#define AB3550_STR_VBUS                                        (0x80)
-
-/* Interrupt mask registers */
-#define AB3550_IMR1 0x29
-#define AB3550_IMR2 0x2a
-#define AB3550_IMR3 0x2b
-#define AB3550_IMR4 0x2c
-#define AB3550_IMR5 0x2d
-
-enum ab3550_devid {
-       AB3550_DEVID_ADC,
-       AB3550_DEVID_DAC,
-       AB3550_DEVID_LEDS,
-       AB3550_DEVID_POWER,
-       AB3550_DEVID_REGULATORS,
-       AB3550_DEVID_SIM,
-       AB3550_DEVID_UART,
-       AB3550_DEVID_RTC,
-       AB3550_DEVID_CHARGER,
-       AB3550_DEVID_FUELGAUGE,
-       AB3550_DEVID_VIBRATOR,
-       AB3550_DEVID_CODEC,
-       AB3550_NUM_DEVICES,
-};
-
 /**
  * struct abx500_init_setting
  * Initial value of the registers for driver to use during setup.
@@ -186,18 +152,6 @@ struct abx500_init_settings {
        u8 setting;
 };
 
-/**
- * struct ab3550_platform_data
- * Data supplied to initialize board connections to the AB3550
- */
-struct ab3550_platform_data {
-       struct {unsigned int base; unsigned int count; } irq;
-       void *dev_data[AB3550_NUM_DEVICES];
-       size_t dev_data_sz[AB3550_NUM_DEVICES];
-       struct abx500_init_settings *init_settings;
-       unsigned int init_settings_sz;
-};
-
 int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
        u8 value);
 int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
index f097798..9890687 100644 (file)
@@ -5,21 +5,35 @@
  *
  * U5500 PRCMU API.
  */
-#ifndef __MACH_PRCMU_U5500_H
-#define __MACH_PRCMU_U5500_H
+#ifndef __MFD_DB5500_PRCMU_H
+#define __MFD_DB5500_PRCMU_H
 
-#ifdef CONFIG_UX500_SOC_DB5500
+#ifdef CONFIG_MFD_DB5500_PRCMU
 
 void db5500_prcmu_early_init(void);
-
+int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state);
+int db5500_prcmu_set_display_clocks(void);
+int db5500_prcmu_disable_dsipll(void);
+int db5500_prcmu_enable_dsipll(void);
 int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+void db5500_prcmu_enable_wakeups(u32 wakeups);
+int db5500_prcmu_request_clock(u8 clock, bool enable);
+void db5500_prcmu_config_abb_event_readout(u32 abb_events);
+void db5500_prcmu_get_abb_event_buffer(void __iomem **buf);
+int prcmu_resetout(u8 resoutn, u8 state);
+int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+       bool keep_ap_pll);
+int db5500_prcmu_config_esram0_deep_sleep(u8 state);
+void db5500_prcmu_system_reset(u16 reset_code);
+u16 db5500_prcmu_get_reset_code(void);
+bool db5500_prcmu_is_ac_wake_requested(void);
+int db5500_prcmu_set_arm_opp(u8 opp);
+int db5500_prcmu_get_arm_opp(void);
 
 #else /* !CONFIG_UX500_SOC_DB5500 */
 
-static inline void db5500_prcmu_early_init(void)
-{
-}
+static inline void db5500_prcmu_early_init(void) {}
 
 static inline int db5500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 {
@@ -31,15 +45,75 @@ static inline int db5500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
        return -ENOSYS;
 }
 
-#endif /* CONFIG_UX500_SOC_DB5500 */
+static inline int db5500_prcmu_request_clock(u8 clock, bool enable)
+{
+       return 0;
+}
+
+static inline int db5500_prcmu_set_display_clocks(void)
+{
+       return 0;
+}
+
+static inline int db5500_prcmu_disable_dsipll(void)
+{
+       return 0;
+}
+
+static inline int db5500_prcmu_enable_dsipll(void)
+{
+       return 0;
+}
 
-static inline int db5500_prcmu_config_abb_event_readout(u32 abb_events)
+static inline int db5500_prcmu_config_esram0_deep_sleep(u8 state)
 {
-#ifdef CONFIG_MACH_U5500_SIMULATOR
        return 0;
-#else
-       return -1;
-#endif
 }
 
-#endif /* __MACH_PRCMU_U5500_H */
+static inline void db5500_prcmu_enable_wakeups(u32 wakeups) {}
+
+static inline int prcmu_resetout(u8 resoutn, u8 state)
+{
+       return 0;
+}
+
+static inline int db5500_prcmu_set_epod(u16 epod_id, u8 epod_state)
+{
+       return 0;
+}
+
+static inline void db5500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
+static inline void db5500_prcmu_config_abb_event_readout(u32 abb_events) {}
+
+static inline int db5500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+       bool keep_ap_pll)
+{
+       return 0;
+}
+
+static inline void db5500_prcmu_system_reset(u16 reset_code) {}
+
+static inline u16 db5500_prcmu_get_reset_code(void)
+{
+       return 0;
+}
+
+static inline bool db5500_prcmu_is_ac_wake_requested(void)
+{
+       return 0;
+}
+
+static inline int db5500_prcmu_set_arm_opp(u8 opp)
+{
+       return 0;
+}
+
+static inline int db5500_prcmu_get_arm_opp(void)
+{
+       return 0;
+}
+
+
+#endif /* CONFIG_MFD_DB5500_PRCMU */
+
+#endif /* __MFD_DB5500_PRCMU_H */
index 917dbca..60d27f7 100644 (file)
@@ -11,7 +11,6 @@
 #define __MFD_DB8500_PRCMU_H
 
 #include <linux/interrupt.h>
-#include <linux/notifier.h>
 
 /* This portion previously known as <mach/prcmu-fw-defs_v1.h> */
 
@@ -133,7 +132,7 @@ enum ap_pwrst {
  * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle
  */
 enum ap_pwrst_trans {
-       NO_TRANSITION                   = 0x00,
+       PRCMU_AP_NO_CHANGE              = 0x00,
        APEXECUTE_TO_APSLEEP            = 0x01,
        APIDLE_TO_APSLEEP               = 0x02, /* To be removed */
        PRCMU_AP_SLEEP                  = 0x01,
@@ -145,54 +144,6 @@ enum ap_pwrst_trans {
        PRCMU_AP_DEEP_IDLE              = 0x07,
 };
 
-/**
- * enum ddr_pwrst - DDR power states definition
- * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
- * @DDR_PWR_STATE_ON:
- * @DDR_PWR_STATE_OFFLOWLAT:
- * @DDR_PWR_STATE_OFFHIGHLAT:
- */
-enum ddr_pwrst {
-       DDR_PWR_STATE_UNCHANGED     = 0x00,
-       DDR_PWR_STATE_ON            = 0x01,
-       DDR_PWR_STATE_OFFLOWLAT     = 0x02,
-       DDR_PWR_STATE_OFFHIGHLAT    = 0x03
-};
-
-/**
- * enum arm_opp - ARM OPP states definition
- * @ARM_OPP_INIT:
- * @ARM_NO_CHANGE: The ARM operating point is unchanged
- * @ARM_100_OPP: The new ARM operating point is arm100opp
- * @ARM_50_OPP: The new ARM operating point is arm50opp
- * @ARM_MAX_OPP: Operating point is "max" (more than 100)
- * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100
- * @ARM_EXTCLK: The new ARM operating point is armExtClk
- */
-enum arm_opp {
-       ARM_OPP_INIT = 0x00,
-       ARM_NO_CHANGE = 0x01,
-       ARM_100_OPP = 0x02,
-       ARM_50_OPP = 0x03,
-       ARM_MAX_OPP = 0x04,
-       ARM_MAX_FREQ100OPP = 0x05,
-       ARM_EXTCLK = 0x07
-};
-
-/**
- * enum ape_opp - APE OPP states definition
- * @APE_OPP_INIT:
- * @APE_NO_CHANGE: The APE operating point is unchanged
- * @APE_100_OPP: The new APE operating point is ape100opp
- * @APE_50_OPP: 50%
- */
-enum ape_opp {
-       APE_OPP_INIT = 0x00,
-       APE_NO_CHANGE = 0x01,
-       APE_100_OPP = 0x02,
-       APE_50_OPP = 0x03
-};
-
 /**
  * enum hw_acc_state - State definition for hardware accelerator
  * @HW_NO_CHANGE: The hardware accelerator state must remain unchanged
@@ -469,26 +420,6 @@ enum auto_enable {
 
 /* End of file previously known as prcmu-fw-defs_v1.h */
 
-/* PRCMU Wakeup defines */
-enum prcmu_wakeup_index {
-       PRCMU_WAKEUP_INDEX_RTC,
-       PRCMU_WAKEUP_INDEX_RTT0,
-       PRCMU_WAKEUP_INDEX_RTT1,
-       PRCMU_WAKEUP_INDEX_HSI0,
-       PRCMU_WAKEUP_INDEX_HSI1,
-       PRCMU_WAKEUP_INDEX_USB,
-       PRCMU_WAKEUP_INDEX_ABB,
-       PRCMU_WAKEUP_INDEX_ABB_FIFO,
-       PRCMU_WAKEUP_INDEX_ARM,
-       NUM_PRCMU_WAKEUP_INDICES
-};
-#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
-
-/* PRCMU QoS APE OPP class */
-#define PRCMU_QOS_APE_OPP 1
-#define PRCMU_QOS_DDR_OPP 2
-#define PRCMU_QOS_DEFAULT_VALUE -1
-
 /**
  * enum hw_acc_dev - enum for hw accelerators
  * @HW_ACC_SVAMMDSP: for SVAMMDSP
@@ -526,64 +457,6 @@ enum hw_acc_dev {
        NUM_HW_ACC
 };
 
-/*
- * Ids for all EPODs (power domains)
- * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP
- * - EPOD_ID_SVAPIPE: power domain for SVA pipe
- * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP
- * - EPOD_ID_SIAPIPE: power domain for SIA pipe
- * - EPOD_ID_SGA: power domain for SGA
- * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE
- * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2
- * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4
- * - NUM_EPOD_ID: number of power domains
- */
-#define EPOD_ID_SVAMMDSP       0
-#define EPOD_ID_SVAPIPE                1
-#define EPOD_ID_SIAMMDSP       2
-#define EPOD_ID_SIAPIPE                3
-#define EPOD_ID_SGA            4
-#define EPOD_ID_B2R2_MCDE      5
-#define EPOD_ID_ESRAM12                6
-#define EPOD_ID_ESRAM34                7
-#define NUM_EPOD_ID            8
-
-/*
- * state definition for EPOD (power domain)
- * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
- * - EPOD_STATE_OFF: The EPOD is switched off
- * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in
- *                         retention
- * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off
- * - EPOD_STATE_ON: Same as above, but with clock enabled
- */
-#define EPOD_STATE_NO_CHANGE   0x00
-#define EPOD_STATE_OFF         0x01
-#define EPOD_STATE_RAMRET      0x02
-#define EPOD_STATE_ON_CLK_OFF  0x03
-#define EPOD_STATE_ON          0x04
-
-/*
- * CLKOUT sources
- */
-#define PRCMU_CLKSRC_CLK38M            0x00
-#define PRCMU_CLKSRC_ACLK              0x01
-#define PRCMU_CLKSRC_SYSCLK            0x02
-#define PRCMU_CLKSRC_LCDCLK            0x03
-#define PRCMU_CLKSRC_SDMMCCLK          0x04
-#define PRCMU_CLKSRC_TVCLK             0x05
-#define PRCMU_CLKSRC_TIMCLK            0x06
-#define PRCMU_CLKSRC_CLK009            0x07
-/* These are only valid for CLKOUT1: */
-#define PRCMU_CLKSRC_SIAMMDSPCLK       0x40
-#define PRCMU_CLKSRC_I2CCLK            0x41
-#define PRCMU_CLKSRC_MSP02CLK          0x42
-#define PRCMU_CLKSRC_ARMPLL_OBSCLK     0x43
-#define PRCMU_CLKSRC_HSIRXCLK          0x44
-#define PRCMU_CLKSRC_HSITXCLK          0x45
-#define PRCMU_CLKSRC_ARMCLKFIX         0x46
-#define PRCMU_CLKSRC_HDMICLK           0x47
-
 /*
  * Definitions for autonomous power management configuration.
  */
@@ -620,88 +493,12 @@ struct prcmu_auto_pm_config {
        u8 sva_policy;
 };
 
-/**
- * enum ddr_opp - DDR OPP states definition
- * @DDR_100_OPP: The new DDR operating point is ddr100opp
- * @DDR_50_OPP: The new DDR operating point is ddr50opp
- * @DDR_25_OPP: The new DDR operating point is ddr25opp
- */
-enum ddr_opp {
-       DDR_100_OPP = 0x00,
-       DDR_50_OPP = 0x01,
-       DDR_25_OPP = 0x02,
-};
-
-/*
- * Clock identifiers.
- */
-enum prcmu_clock {
-       PRCMU_SGACLK,
-       PRCMU_UARTCLK,
-       PRCMU_MSP02CLK,
-       PRCMU_MSP1CLK,
-       PRCMU_I2CCLK,
-       PRCMU_SDMMCCLK,
-       PRCMU_SLIMCLK,
-       PRCMU_PER1CLK,
-       PRCMU_PER2CLK,
-       PRCMU_PER3CLK,
-       PRCMU_PER5CLK,
-       PRCMU_PER6CLK,
-       PRCMU_PER7CLK,
-       PRCMU_LCDCLK,
-       PRCMU_BMLCLK,
-       PRCMU_HSITXCLK,
-       PRCMU_HSIRXCLK,
-       PRCMU_HDMICLK,
-       PRCMU_APEATCLK,
-       PRCMU_APETRACECLK,
-       PRCMU_MCDECLK,
-       PRCMU_IPI2CCLK,
-       PRCMU_DSIALTCLK,
-       PRCMU_DMACLK,
-       PRCMU_B2R2CLK,
-       PRCMU_TVCLK,
-       PRCMU_SSPCLK,
-       PRCMU_RNGCLK,
-       PRCMU_UICCCLK,
-       PRCMU_NUM_REG_CLOCKS,
-       PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
-       PRCMU_TIMCLK,
-};
-
-/*
- * Definitions for controlling ESRAM0 in deep sleep.
- */
-#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
-#define ESRAM0_DEEP_SLEEP_STATE_RET 2
-
-#ifdef CONFIG_MFD_DB8500_PRCMU
-void __init prcmu_early_init(void);
-int prcmu_set_display_clocks(void);
-int prcmu_disable_dsipll(void);
-int prcmu_enable_dsipll(void);
-#else
-static inline void __init prcmu_early_init(void) {}
-#endif
-
 #ifdef CONFIG_MFD_DB8500_PRCMU
 
+void db8500_prcmu_early_init(void);
 int prcmu_set_rc_a2p(enum romcode_write);
 enum romcode_read prcmu_get_rc_p2a(void);
 enum ap_pwrst prcmu_get_xp70_current_state(void);
-int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
-
-void prcmu_enable_wakeups(u32 wakeups);
-static inline void prcmu_disable_wakeups(void)
-{
-       prcmu_enable_wakeups(0);
-}
-
-void prcmu_config_abb_event_readout(u32 abb_events);
-void prcmu_get_abb_event_buffer(void __iomem **buf);
-int prcmu_set_arm_opp(u8 opp);
-int prcmu_get_arm_opp(void);
 bool prcmu_has_arm_maxopp(void);
 bool prcmu_is_u8400(void);
 int prcmu_set_ape_opp(u8 opp);
@@ -710,19 +507,14 @@ int prcmu_request_ape_opp_100_voltage(bool enable);
 int prcmu_release_usb_wakeup_state(void);
 int prcmu_set_ddr_opp(u8 opp);
 int prcmu_get_ddr_opp(void);
-unsigned long prcmu_qos_get_cpufreq_opp_delay(void);
-void prcmu_qos_set_cpufreq_opp_delay(unsigned long);
 /* NOTE! Use regulator framework instead */
 int prcmu_set_hwacc(u16 hw_acc_dev, u8 state);
-int prcmu_set_epod(u16 epod_id, u8 epod_state);
 void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
        struct prcmu_auto_pm_config *idle);
 bool prcmu_is_auto_pm_enabled(void);
 
 int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
-int prcmu_request_clock(u8 clock, bool enable);
 int prcmu_set_clock_divider(u8 clock, u8 divider);
-int prcmu_config_esram0_deep_sleep(u8 state);
 int prcmu_config_hotdog(u8 threshold);
 int prcmu_config_hotmon(u8 low, u8 high);
 int prcmu_start_temp_sense(u16 cycles32k);
@@ -732,14 +524,36 @@ int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
 
 void prcmu_ac_wake_req(void);
 void prcmu_ac_sleep_req(void);
-void prcmu_system_reset(u16 reset_code);
 void prcmu_modem_reset(void);
-bool prcmu_is_ac_wake_requested(void);
 void prcmu_enable_spi2(void);
 void prcmu_disable_spi2(void);
 
+int prcmu_config_a9wdog(u8 num, bool sleep_auto_off);
+int prcmu_enable_a9wdog(u8 id);
+int prcmu_disable_a9wdog(u8 id);
+int prcmu_kick_a9wdog(u8 id);
+int prcmu_load_a9wdog(u8 id, u32 val);
+
+void db8500_prcmu_system_reset(u16 reset_code);
+int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
+void db8500_prcmu_enable_wakeups(u32 wakeups);
+int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state);
+int db8500_prcmu_request_clock(u8 clock, bool enable);
+int db8500_prcmu_set_display_clocks(void);
+int db8500_prcmu_disable_dsipll(void);
+int db8500_prcmu_enable_dsipll(void);
+void db8500_prcmu_config_abb_event_readout(u32 abb_events);
+void db8500_prcmu_get_abb_event_buffer(void __iomem **buf);
+int db8500_prcmu_config_esram0_deep_sleep(u8 state);
+u16 db8500_prcmu_get_reset_code(void);
+bool db8500_prcmu_is_ac_wake_requested(void);
+int db8500_prcmu_set_arm_opp(u8 opp);
+int db8500_prcmu_get_arm_opp(void);
+
 #else /* !CONFIG_MFD_DB8500_PRCMU */
 
+static inline void db8500_prcmu_early_init(void) {}
+
 static inline int prcmu_set_rc_a2p(enum romcode_write code)
 {
        return 0;
@@ -755,34 +569,12 @@ static inline enum ap_pwrst prcmu_get_xp70_current_state(void)
        return AP_EXECUTE;
 }
 
-static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-       bool keep_ap_pll)
-{
-       return 0;
-}
-
-static inline void prcmu_enable_wakeups(u32 wakeups) {}
-
-static inline void prcmu_disable_wakeups(void) {}
-
-static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
-
-static inline int prcmu_set_arm_opp(u8 opp)
-{
-       return 0;
-}
-
-static inline int prcmu_get_arm_opp(void)
-{
-       return ARM_100_OPP;
-}
-
-static bool prcmu_has_arm_maxopp(void)
+static inline bool prcmu_has_arm_maxopp(void)
 {
        return false;
 }
 
-static bool prcmu_is_u8400(void)
+static inline bool prcmu_is_u8400(void)
 {
        return false;
 }
@@ -817,13 +609,6 @@ static inline int prcmu_get_ddr_opp(void)
        return DDR_100_OPP;
 }
 
-static inline unsigned long prcmu_qos_get_cpufreq_opp_delay(void)
-{
-       return 0;
-}
-
-static inline void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) {}
-
 static inline int prcmu_set_hwacc(u16 hw_acc_dev, u8 state)
 {
        return 0;
@@ -844,21 +629,11 @@ static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
        return 0;
 }
 
-static inline int prcmu_request_clock(u8 clock, bool enable)
-{
-       return 0;
-}
-
 static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
 {
        return 0;
 }
 
-int prcmu_config_esram0_deep_sleep(u8 state)
-{
-       return 0;
-}
-
 static inline int prcmu_config_hotdog(u8 threshold)
 {
        return 0;
@@ -893,86 +668,107 @@ static inline void prcmu_ac_wake_req(void) {}
 
 static inline void prcmu_ac_sleep_req(void) {}
 
-static inline void prcmu_system_reset(u16 reset_code) {}
-
 static inline void prcmu_modem_reset(void) {}
 
-static inline bool prcmu_is_ac_wake_requested(void)
+static inline int prcmu_enable_spi2(void)
 {
-       return false;
+       return 0;
 }
 
-#ifndef CONFIG_UX500_SOC_DB5500
-static inline int prcmu_set_display_clocks(void)
+static inline int prcmu_disable_spi2(void)
 {
        return 0;
 }
 
-static inline int prcmu_disable_dsipll(void)
+static inline void db8500_prcmu_system_reset(u16 reset_code) {}
+
+static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+       bool keep_ap_pll)
 {
        return 0;
 }
 
-static inline int prcmu_enable_dsipll(void)
+static inline void db8500_prcmu_enable_wakeups(u32 wakeups) {}
+
+static inline int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
        return 0;
 }
-#endif
 
-static inline int prcmu_enable_spi2(void)
+static inline int db8500_prcmu_request_clock(u8 clock, bool enable)
 {
        return 0;
 }
 
-static inline int prcmu_disable_spi2(void)
+static inline int db8500_prcmu_set_display_clocks(void)
 {
        return 0;
 }
 
-#endif /* !CONFIG_MFD_DB8500_PRCMU */
+static inline int db8500_prcmu_disable_dsipll(void)
+{
+       return 0;
+}
+
+static inline int db8500_prcmu_enable_dsipll(void)
+{
+       return 0;
+}
+
+static inline int db8500_prcmu_config_esram0_deep_sleep(u8 state)
+{
+       return 0;
+}
+
+static inline void db8500_prcmu_config_abb_event_readout(u32 abb_events) {}
 
-#ifdef CONFIG_UX500_PRCMU_QOS_POWER
-int prcmu_qos_requirement(int pm_qos_class);
-int prcmu_qos_add_requirement(int pm_qos_class, char *name, s32 value);
-int prcmu_qos_update_requirement(int pm_qos_class, char *name, s32 new_value);
-void prcmu_qos_remove_requirement(int pm_qos_class, char *name);
-int prcmu_qos_add_notifier(int prcmu_qos_class,
-                          struct notifier_block *notifier);
-int prcmu_qos_remove_notifier(int prcmu_qos_class,
-                             struct notifier_block *notifier);
-#else
-static inline int prcmu_qos_requirement(int prcmu_qos_class)
+static inline void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
+
+static inline u16 db8500_prcmu_get_reset_code(void)
 {
        return 0;
 }
 
-static inline int prcmu_qos_add_requirement(int prcmu_qos_class,
-                                           char *name, s32 value)
+static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 {
        return 0;
 }
 
-static inline int prcmu_qos_update_requirement(int prcmu_qos_class,
-                                              char *name, s32 new_value)
+static inline int prcmu_enable_a9wdog(u8 id)
 {
        return 0;
 }
 
-static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name)
+static inline int prcmu_disable_a9wdog(u8 id)
 {
+       return 0;
 }
 
-static inline int prcmu_qos_add_notifier(int prcmu_qos_class,
-                                        struct notifier_block *notifier)
+static inline int prcmu_kick_a9wdog(u8 id)
 {
        return 0;
 }
-static inline int prcmu_qos_remove_notifier(int prcmu_qos_class,
-                                           struct notifier_block *notifier)
+
+static inline int prcmu_load_a9wdog(u8 id, u32 val)
 {
        return 0;
 }
 
-#endif
+static inline bool db8500_prcmu_is_ac_wake_requested(void)
+{
+       return 0;
+}
+
+static inline int db8500_prcmu_set_arm_opp(u8 opp)
+{
+       return 0;
+}
+
+static inline int db8500_prcmu_get_arm_opp(void)
+{
+       return 0;
+}
+
+#endif /* !CONFIG_MFD_DB8500_PRCMU */
 
 #endif /* __MFD_DB8500_PRCMU_H */
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
new file mode 100644 (file)
index 0000000..bac942f
--- /dev/null
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) ST Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * STE Ux500 PRCMU API
+ */
+#ifndef __MACH_PRCMU_H
+#define __MACH_PRCMU_H
+
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <asm/mach-types.h>
+
+/* PRCMU Wakeup defines */
+enum prcmu_wakeup_index {
+       PRCMU_WAKEUP_INDEX_RTC,
+       PRCMU_WAKEUP_INDEX_RTT0,
+       PRCMU_WAKEUP_INDEX_RTT1,
+       PRCMU_WAKEUP_INDEX_HSI0,
+       PRCMU_WAKEUP_INDEX_HSI1,
+       PRCMU_WAKEUP_INDEX_USB,
+       PRCMU_WAKEUP_INDEX_ABB,
+       PRCMU_WAKEUP_INDEX_ABB_FIFO,
+       PRCMU_WAKEUP_INDEX_ARM,
+       PRCMU_WAKEUP_INDEX_CD_IRQ,
+       NUM_PRCMU_WAKEUP_INDICES
+};
+#define PRCMU_WAKEUP(_name) (BIT(PRCMU_WAKEUP_INDEX_##_name))
+
+/* EPOD (power domain) IDs */
+
+/*
+ * DB8500 EPODs
+ * - EPOD_ID_SVAMMDSP: power domain for SVA MMDSP
+ * - EPOD_ID_SVAPIPE: power domain for SVA pipe
+ * - EPOD_ID_SIAMMDSP: power domain for SIA MMDSP
+ * - EPOD_ID_SIAPIPE: power domain for SIA pipe
+ * - EPOD_ID_SGA: power domain for SGA
+ * - EPOD_ID_B2R2_MCDE: power domain for B2R2 and MCDE
+ * - EPOD_ID_ESRAM12: power domain for ESRAM 1 and 2
+ * - EPOD_ID_ESRAM34: power domain for ESRAM 3 and 4
+ * - NUM_EPOD_ID: number of power domains
+ *
+ * TODO: These should be prefixed.
+ */
+#define EPOD_ID_SVAMMDSP       0
+#define EPOD_ID_SVAPIPE                1
+#define EPOD_ID_SIAMMDSP       2
+#define EPOD_ID_SIAPIPE                3
+#define EPOD_ID_SGA            4
+#define EPOD_ID_B2R2_MCDE      5
+#define EPOD_ID_ESRAM12                6
+#define EPOD_ID_ESRAM34                7
+#define NUM_EPOD_ID            8
+
+/*
+ * DB5500 EPODs
+ */
+#define DB5500_EPOD_ID_BASE 0x0100
+#define DB5500_EPOD_ID_SGA (DB5500_EPOD_ID_BASE + 0)
+#define DB5500_EPOD_ID_HVA (DB5500_EPOD_ID_BASE + 1)
+#define DB5500_EPOD_ID_SIA (DB5500_EPOD_ID_BASE + 2)
+#define DB5500_EPOD_ID_DISP (DB5500_EPOD_ID_BASE + 3)
+#define DB5500_EPOD_ID_ESRAM12 (DB5500_EPOD_ID_BASE + 6)
+#define DB5500_NUM_EPOD_ID 7
+
+/*
+ * state definition for EPOD (power domain)
+ * - EPOD_STATE_NO_CHANGE: The EPOD should remain unchanged
+ * - EPOD_STATE_OFF: The EPOD is switched off
+ * - EPOD_STATE_RAMRET: The EPOD is switched off with its internal RAM in
+ *                         retention
+ * - EPOD_STATE_ON_CLK_OFF: The EPOD is switched on, clock is still off
+ * - EPOD_STATE_ON: Same as above, but with clock enabled
+ */
+#define EPOD_STATE_NO_CHANGE   0x00
+#define EPOD_STATE_OFF         0x01
+#define EPOD_STATE_RAMRET      0x02
+#define EPOD_STATE_ON_CLK_OFF  0x03
+#define EPOD_STATE_ON          0x04
+
+/*
+ * CLKOUT sources
+ */
+#define PRCMU_CLKSRC_CLK38M            0x00
+#define PRCMU_CLKSRC_ACLK              0x01
+#define PRCMU_CLKSRC_SYSCLK            0x02
+#define PRCMU_CLKSRC_LCDCLK            0x03
+#define PRCMU_CLKSRC_SDMMCCLK          0x04
+#define PRCMU_CLKSRC_TVCLK             0x05
+#define PRCMU_CLKSRC_TIMCLK            0x06
+#define PRCMU_CLKSRC_CLK009            0x07
+/* These are only valid for CLKOUT1: */
+#define PRCMU_CLKSRC_SIAMMDSPCLK       0x40
+#define PRCMU_CLKSRC_I2CCLK            0x41
+#define PRCMU_CLKSRC_MSP02CLK          0x42
+#define PRCMU_CLKSRC_ARMPLL_OBSCLK     0x43
+#define PRCMU_CLKSRC_HSIRXCLK          0x44
+#define PRCMU_CLKSRC_HSITXCLK          0x45
+#define PRCMU_CLKSRC_ARMCLKFIX         0x46
+#define PRCMU_CLKSRC_HDMICLK           0x47
+
+/*
+ * Clock identifiers.
+ */
+enum prcmu_clock {
+       PRCMU_SGACLK,
+       PRCMU_UARTCLK,
+       PRCMU_MSP02CLK,
+       PRCMU_MSP1CLK,
+       PRCMU_I2CCLK,
+       PRCMU_SDMMCCLK,
+       PRCMU_SLIMCLK,
+       PRCMU_PER1CLK,
+       PRCMU_PER2CLK,
+       PRCMU_PER3CLK,
+       PRCMU_PER5CLK,
+       PRCMU_PER6CLK,
+       PRCMU_PER7CLK,
+       PRCMU_LCDCLK,
+       PRCMU_BMLCLK,
+       PRCMU_HSITXCLK,
+       PRCMU_HSIRXCLK,
+       PRCMU_HDMICLK,
+       PRCMU_APEATCLK,
+       PRCMU_APETRACECLK,
+       PRCMU_MCDECLK,
+       PRCMU_IPI2CCLK,
+       PRCMU_DSIALTCLK,
+       PRCMU_DMACLK,
+       PRCMU_B2R2CLK,
+       PRCMU_TVCLK,
+       PRCMU_SSPCLK,
+       PRCMU_RNGCLK,
+       PRCMU_UICCCLK,
+       PRCMU_PWMCLK,
+       PRCMU_IRDACLK,
+       PRCMU_IRRCCLK,
+       PRCMU_SIACLK,
+       PRCMU_SVACLK,
+       PRCMU_NUM_REG_CLOCKS,
+       PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
+       PRCMU_TIMCLK,
+       PRCMU_PLLSOC0,
+       PRCMU_PLLSOC1,
+       PRCMU_PLLDDR,
+};
+
+/**
+ * enum ape_opp - APE OPP states definition
+ * @APE_OPP_INIT:
+ * @APE_NO_CHANGE: The APE operating point is unchanged
+ * @APE_100_OPP: The new APE operating point is ape100opp
+ * @APE_50_OPP: 50%
+ */
+enum ape_opp {
+       APE_OPP_INIT = 0x00,
+       APE_NO_CHANGE = 0x01,
+       APE_100_OPP = 0x02,
+       APE_50_OPP = 0x03
+};
+
+/**
+ * enum arm_opp - ARM OPP states definition
+ * @ARM_OPP_INIT:
+ * @ARM_NO_CHANGE: The ARM operating point is unchanged
+ * @ARM_100_OPP: The new ARM operating point is arm100opp
+ * @ARM_50_OPP: The new ARM operating point is arm50opp
+ * @ARM_MAX_OPP: Operating point is "max" (more than 100)
+ * @ARM_MAX_FREQ100OPP: Set max opp if available, else 100
+ * @ARM_EXTCLK: The new ARM operating point is armExtClk
+ */
+enum arm_opp {
+       ARM_OPP_INIT = 0x00,
+       ARM_NO_CHANGE = 0x01,
+       ARM_100_OPP = 0x02,
+       ARM_50_OPP = 0x03,
+       ARM_MAX_OPP = 0x04,
+       ARM_MAX_FREQ100OPP = 0x05,
+       ARM_EXTCLK = 0x07
+};
+
+/**
+ * enum ddr_opp - DDR OPP states definition
+ * @DDR_100_OPP: The new DDR operating point is ddr100opp
+ * @DDR_50_OPP: The new DDR operating point is ddr50opp
+ * @DDR_25_OPP: The new DDR operating point is ddr25opp
+ */
+enum ddr_opp {
+       DDR_100_OPP = 0x00,
+       DDR_50_OPP = 0x01,
+       DDR_25_OPP = 0x02,
+};
+
+/*
+ * Definitions for controlling ESRAM0 in deep sleep.
+ */
+#define ESRAM0_DEEP_SLEEP_STATE_OFF 1
+#define ESRAM0_DEEP_SLEEP_STATE_RET 2
+
+/**
+ * enum ddr_pwrst - DDR power states definition
+ * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged
+ * @DDR_PWR_STATE_ON:
+ * @DDR_PWR_STATE_OFFLOWLAT:
+ * @DDR_PWR_STATE_OFFHIGHLAT:
+ */
+enum ddr_pwrst {
+       DDR_PWR_STATE_UNCHANGED     = 0x00,
+       DDR_PWR_STATE_ON            = 0x01,
+       DDR_PWR_STATE_OFFLOWLAT     = 0x02,
+       DDR_PWR_STATE_OFFHIGHLAT    = 0x03
+};
+
+#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/db5500-prcmu.h>
+
+#if defined(CONFIG_UX500_SOC_DB8500) || defined(CONFIG_UX500_SOC_DB5500)
+
+static inline void __init prcmu_early_init(void)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_early_init();
+       else
+               return db8500_prcmu_early_init();
+}
+
+static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+               bool keep_ap_pll)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_set_power_state(state, keep_ulp_clk,
+                       keep_ap_pll);
+       else
+               return db8500_prcmu_set_power_state(state, keep_ulp_clk,
+                       keep_ap_pll);
+}
+
+static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
+{
+       if (machine_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_set_epod(epod_id, epod_state);
+}
+
+static inline void prcmu_enable_wakeups(u32 wakeups)
+{
+       if (machine_is_u5500())
+               db5500_prcmu_enable_wakeups(wakeups);
+       else
+               db8500_prcmu_enable_wakeups(wakeups);
+}
+
+static inline void prcmu_disable_wakeups(void)
+{
+       prcmu_enable_wakeups(0);
+}
+
+static inline void prcmu_config_abb_event_readout(u32 abb_events)
+{
+       if (machine_is_u5500())
+               db5500_prcmu_config_abb_event_readout(abb_events);
+       else
+               db8500_prcmu_config_abb_event_readout(abb_events);
+}
+
+static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
+{
+       if (machine_is_u5500())
+               db5500_prcmu_get_abb_event_buffer(buf);
+       else
+               db8500_prcmu_get_abb_event_buffer(buf);
+}
+
+int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
+int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
+
+static inline int prcmu_request_clock(u8 clock, bool enable)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_request_clock(clock, enable);
+       else
+               return db8500_prcmu_request_clock(clock, enable);
+}
+
+int prcmu_set_ape_opp(u8 opp);
+int prcmu_get_ape_opp(void);
+int prcmu_set_ddr_opp(u8 opp);
+int prcmu_get_ddr_opp(void);
+
+static inline int prcmu_set_arm_opp(u8 opp)
+{
+       if (machine_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_set_arm_opp(opp);
+}
+
+static inline int prcmu_get_arm_opp(void)
+{
+       if (machine_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_get_arm_opp();
+}
+
+static inline void prcmu_system_reset(u16 reset_code)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_system_reset(reset_code);
+       else
+               return db8500_prcmu_system_reset(reset_code);
+}
+
+static inline u16 prcmu_get_reset_code(void)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_get_reset_code();
+       else
+               return db8500_prcmu_get_reset_code();
+}
+
+void prcmu_ac_wake_req(void);
+void prcmu_ac_sleep_req(void);
+void prcmu_modem_reset(void);
+static inline bool prcmu_is_ac_wake_requested(void)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_is_ac_wake_requested();
+       else
+               return db8500_prcmu_is_ac_wake_requested();
+}
+
+static inline int prcmu_set_display_clocks(void)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_set_display_clocks();
+       else
+               return db8500_prcmu_set_display_clocks();
+}
+
+static inline int prcmu_disable_dsipll(void)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_disable_dsipll();
+       else
+               return db8500_prcmu_disable_dsipll();
+}
+
+static inline int prcmu_enable_dsipll(void)
+{
+       if (machine_is_u5500())
+               return db5500_prcmu_enable_dsipll();
+       else
+               return db8500_prcmu_enable_dsipll();
+}
+
+static inline int prcmu_config_esram0_deep_sleep(u8 state)
+{
+       if (machine_is_u5500())
+               return -EINVAL;
+       else
+               return db8500_prcmu_config_esram0_deep_sleep(state);
+}
+#else
+
+static inline void __init prcmu_early_init(void) {}
+
+static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+       bool keep_ap_pll)
+{
+       return 0;
+}
+
+static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
+{
+       return 0;
+}
+
+static inline void prcmu_enable_wakeups(u32 wakeups) {}
+
+static inline void prcmu_disable_wakeups(void) {}
+
+static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+       return -ENOSYS;
+}
+
+static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+       return -ENOSYS;
+}
+
+static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
+{
+       return 0;
+}
+
+static inline int prcmu_request_clock(u8 clock, bool enable)
+{
+       return 0;
+}
+
+static inline int prcmu_set_ape_opp(u8 opp)
+{
+       return 0;
+}
+
+static inline int prcmu_get_ape_opp(void)
+{
+       return APE_100_OPP;
+}
+
+static inline int prcmu_set_arm_opp(u8 opp)
+{
+       return 0;
+}
+
+static inline int prcmu_get_arm_opp(void)
+{
+       return ARM_100_OPP;
+}
+
+static inline int prcmu_set_ddr_opp(u8 opp)
+{
+       return 0;
+}
+
+static inline int prcmu_get_ddr_opp(void)
+{
+       return DDR_100_OPP;
+}
+
+static inline void prcmu_system_reset(u16 reset_code) {}
+
+static inline u16 prcmu_get_reset_code(void)
+{
+       return 0;
+}
+
+static inline void prcmu_ac_wake_req(void) {}
+
+static inline void prcmu_ac_sleep_req(void) {}
+
+static inline void prcmu_modem_reset(void) {}
+
+static inline bool prcmu_is_ac_wake_requested(void)
+{
+       return false;
+}
+
+static inline int prcmu_set_display_clocks(void)
+{
+       return 0;
+}
+
+static inline int prcmu_disable_dsipll(void)
+{
+       return 0;
+}
+
+static inline int prcmu_enable_dsipll(void)
+{
+       return 0;
+}
+
+static inline int prcmu_config_esram0_deep_sleep(u8 state)
+{
+       return 0;
+}
+
+static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
+
+static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
+{
+       *buf = NULL;
+}
+
+#endif
+
+/* PRCMU QoS APE OPP class */
+#define PRCMU_QOS_APE_OPP 1
+#define PRCMU_QOS_DDR_OPP 2
+#define PRCMU_QOS_DEFAULT_VALUE -1
+
+#ifdef CONFIG_UX500_PRCMU_QOS_POWER
+
+unsigned long prcmu_qos_get_cpufreq_opp_delay(void);
+void prcmu_qos_set_cpufreq_opp_delay(unsigned long);
+void prcmu_qos_force_opp(int, s32);
+int prcmu_qos_requirement(int pm_qos_class);
+int prcmu_qos_add_requirement(int pm_qos_class, char *name, s32 value);
+int prcmu_qos_update_requirement(int pm_qos_class, char *name, s32 new_value);
+void prcmu_qos_remove_requirement(int pm_qos_class, char *name);
+int prcmu_qos_add_notifier(int prcmu_qos_class,
+                          struct notifier_block *notifier);
+int prcmu_qos_remove_notifier(int prcmu_qos_class,
+                             struct notifier_block *notifier);
+
+#else
+
+static inline unsigned long prcmu_qos_get_cpufreq_opp_delay(void)
+{
+       return 0;
+}
+
+static inline void prcmu_qos_set_cpufreq_opp_delay(unsigned long n) {}
+
+static inline void prcmu_qos_force_opp(int prcmu_qos_class, s32 i) {}
+
+static inline int prcmu_qos_requirement(int prcmu_qos_class)
+{
+       return 0;
+}
+
+static inline int prcmu_qos_add_requirement(int prcmu_qos_class,
+                                           char *name, s32 value)
+{
+       return 0;
+}
+
+static inline int prcmu_qos_update_requirement(int prcmu_qos_class,
+                                              char *name, s32 new_value)
+{
+       return 0;
+}
+
+static inline void prcmu_qos_remove_requirement(int prcmu_qos_class, char *name)
+{
+}
+
+static inline int prcmu_qos_add_notifier(int prcmu_qos_class,
+                                        struct notifier_block *notifier)
+{
+       return 0;
+}
+static inline int prcmu_qos_remove_notifier(int prcmu_qos_class,
+                                           struct notifier_block *notifier)
+{
+       return 0;
+}
+
+#endif
+
+#endif /* __MACH_PRCMU_H */
diff --git a/include/linux/mfd/intel_msic.h b/include/linux/mfd/intel_msic.h
new file mode 100644 (file)
index 0000000..439a7a6
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * include/linux/mfd/intel_msic.h - Core interface for Intel MSIC
+ *
+ * Copyright (C) 2011, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg@linux.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.
+ */
+
+#ifndef __LINUX_MFD_INTEL_MSIC_H__
+#define __LINUX_MFD_INTEL_MSIC_H__
+
+/* ID */
+#define INTEL_MSIC_ID0                 0x000   /* RO */
+#define INTEL_MSIC_ID1                 0x001   /* RO */
+
+/* IRQ */
+#define INTEL_MSIC_IRQLVL1             0x002
+#define INTEL_MSIC_ADC1INT             0x003
+#define INTEL_MSIC_CCINT               0x004
+#define INTEL_MSIC_PWRSRCINT           0x005
+#define INTEL_MSIC_PWRSRCINT1          0x006
+#define INTEL_MSIC_CHRINT              0x007
+#define INTEL_MSIC_CHRINT1             0x008
+#define INTEL_MSIC_RTCIRQ              0x009
+#define INTEL_MSIC_GPIO0LVIRQ          0x00a
+#define INTEL_MSIC_GPIO1LVIRQ          0x00b
+#define INTEL_MSIC_GPIOHVIRQ           0x00c
+#define INTEL_MSIC_VRINT               0x00d
+#define INTEL_MSIC_OCAUDIO             0x00e
+#define INTEL_MSIC_ACCDET              0x00f
+#define INTEL_MSIC_RESETIRQ1           0x010
+#define INTEL_MSIC_RESETIRQ2           0x011
+#define INTEL_MSIC_MADC1INT            0x012
+#define INTEL_MSIC_MCCINT              0x013
+#define INTEL_MSIC_MPWRSRCINT          0x014
+#define INTEL_MSIC_MPWRSRCINT1         0x015
+#define INTEL_MSIC_MCHRINT             0x016
+#define INTEL_MSIC_MCHRINT1            0x017
+#define INTEL_MSIC_RTCIRQMASK          0x018
+#define INTEL_MSIC_GPIO0LVIRQMASK      0x019
+#define INTEL_MSIC_GPIO1LVIRQMASK      0x01a
+#define INTEL_MSIC_GPIOHVIRQMASK       0x01b
+#define INTEL_MSIC_VRINTMASK           0x01c
+#define INTEL_MSIC_OCAUDIOMASK         0x01d
+#define INTEL_MSIC_ACCDETMASK          0x01e
+#define INTEL_MSIC_RESETIRQ1MASK       0x01f
+#define INTEL_MSIC_RESETIRQ2MASK       0x020
+#define INTEL_MSIC_IRQLVL1MSK          0x021
+#define INTEL_MSIC_PBCONFIG            0x03e
+#define INTEL_MSIC_PBSTATUS            0x03f   /* RO */
+
+/* GPIO */
+#define INTEL_MSIC_GPIO0LV7CTLO                0x040
+#define INTEL_MSIC_GPIO0LV6CTLO                0x041
+#define INTEL_MSIC_GPIO0LV5CTLO                0x042
+#define INTEL_MSIC_GPIO0LV4CTLO                0x043
+#define INTEL_MSIC_GPIO0LV3CTLO                0x044
+#define INTEL_MSIC_GPIO0LV2CTLO                0x045
+#define INTEL_MSIC_GPIO0LV1CTLO                0x046
+#define INTEL_MSIC_GPIO0LV0CTLO                0x047
+#define INTEL_MSIC_GPIO1LV7CTLOS       0x048
+#define INTEL_MSIC_GPIO1LV6CTLO                0x049
+#define INTEL_MSIC_GPIO1LV5CTLO                0x04a
+#define INTEL_MSIC_GPIO1LV4CTLO                0x04b
+#define INTEL_MSIC_GPIO1LV3CTLO                0x04c
+#define INTEL_MSIC_GPIO1LV2CTLO                0x04d
+#define INTEL_MSIC_GPIO1LV1CTLO                0x04e
+#define INTEL_MSIC_GPIO1LV0CTLO                0x04f
+#define INTEL_MSIC_GPIO0LV7CTLI                0x050
+#define INTEL_MSIC_GPIO0LV6CTLI                0x051
+#define INTEL_MSIC_GPIO0LV5CTLI                0x052
+#define INTEL_MSIC_GPIO0LV4CTLI                0x053
+#define INTEL_MSIC_GPIO0LV3CTLI                0x054
+#define INTEL_MSIC_GPIO0LV2CTLI                0x055
+#define INTEL_MSIC_GPIO0LV1CTLI                0x056
+#define INTEL_MSIC_GPIO0LV0CTLI                0x057
+#define INTEL_MSIC_GPIO1LV7CTLIS       0x058
+#define INTEL_MSIC_GPIO1LV6CTLI                0x059
+#define INTEL_MSIC_GPIO1LV5CTLI                0x05a
+#define INTEL_MSIC_GPIO1LV4CTLI                0x05b
+#define INTEL_MSIC_GPIO1LV3CTLI                0x05c
+#define INTEL_MSIC_GPIO1LV2CTLI                0x05d
+#define INTEL_MSIC_GPIO1LV1CTLI                0x05e
+#define INTEL_MSIC_GPIO1LV0CTLI                0x05f
+#define INTEL_MSIC_PWM0CLKDIV1         0x061
+#define INTEL_MSIC_PWM0CLKDIV0         0x062
+#define INTEL_MSIC_PWM1CLKDIV1         0x063
+#define INTEL_MSIC_PWM1CLKDIV0         0x064
+#define INTEL_MSIC_PWM2CLKDIV1         0x065
+#define INTEL_MSIC_PWM2CLKDIV0         0x066
+#define INTEL_MSIC_PWM0DUTYCYCLE       0x067
+#define INTEL_MSIC_PWM1DUTYCYCLE       0x068
+#define INTEL_MSIC_PWM2DUTYCYCLE       0x069
+#define INTEL_MSIC_GPIO0HV3CTLO                0x06d
+#define INTEL_MSIC_GPIO0HV2CTLO                0x06e
+#define INTEL_MSIC_GPIO0HV1CTLO                0x06f
+#define INTEL_MSIC_GPIO0HV0CTLO                0x070
+#define INTEL_MSIC_GPIO1HV3CTLO                0x071
+#define INTEL_MSIC_GPIO1HV2CTLO                0x072
+#define INTEL_MSIC_GPIO1HV1CTLO                0x073
+#define INTEL_MSIC_GPIO1HV0CTLO                0x074
+#define INTEL_MSIC_GPIO0HV3CTLI                0x075
+#define INTEL_MSIC_GPIO0HV2CTLI                0x076
+#define INTEL_MSIC_GPIO0HV1CTLI                0x077
+#define INTEL_MSIC_GPIO0HV0CTLI                0x078
+#define INTEL_MSIC_GPIO1HV3CTLI                0x079
+#define INTEL_MSIC_GPIO1HV2CTLI                0x07a
+#define INTEL_MSIC_GPIO1HV1CTLI                0x07b
+#define INTEL_MSIC_GPIO1HV0CTLI                0x07c
+
+/* SVID */
+#define INTEL_MSIC_SVIDCTRL0           0x080
+#define INTEL_MSIC_SVIDCTRL1           0x081
+#define INTEL_MSIC_SVIDCTRL2           0x082
+#define INTEL_MSIC_SVIDTXLASTPKT3      0x083   /* RO */
+#define INTEL_MSIC_SVIDTXLASTPKT2      0x084   /* RO */
+#define INTEL_MSIC_SVIDTXLASTPKT1      0x085   /* RO */
+#define INTEL_MSIC_SVIDTXLASTPKT0      0x086   /* RO */
+#define INTEL_MSIC_SVIDPKTOUTBYTE3     0x087
+#define INTEL_MSIC_SVIDPKTOUTBYTE2     0x088
+#define INTEL_MSIC_SVIDPKTOUTBYTE1     0x089
+#define INTEL_MSIC_SVIDPKTOUTBYTE0     0x08a
+#define INTEL_MSIC_SVIDRXVPDEBUG1      0x08b
+#define INTEL_MSIC_SVIDRXVPDEBUG0      0x08c
+#define INTEL_MSIC_SVIDRXLASTPKT3      0x08d   /* RO */
+#define INTEL_MSIC_SVIDRXLASTPKT2      0x08e   /* RO */
+#define INTEL_MSIC_SVIDRXLASTPKT1      0x08f   /* RO */
+#define INTEL_MSIC_SVIDRXLASTPKT0      0x090   /* RO */
+#define INTEL_MSIC_SVIDRXCHKSTATUS3    0x091   /* RO */
+#define INTEL_MSIC_SVIDRXCHKSTATUS2    0x092   /* RO */
+#define INTEL_MSIC_SVIDRXCHKSTATUS1    0x093   /* RO */
+#define INTEL_MSIC_SVIDRXCHKSTATUS0    0x094   /* RO */
+
+/* VREG */
+#define INTEL_MSIC_VCCLATCH            0x0c0
+#define INTEL_MSIC_VNNLATCH            0x0c1
+#define INTEL_MSIC_VCCCNT              0x0c2
+#define INTEL_MSIC_SMPSRAMP            0x0c3
+#define INTEL_MSIC_VNNCNT              0x0c4
+#define INTEL_MSIC_VNNAONCNT           0x0c5
+#define INTEL_MSIC_VCC122AONCNT                0x0c6
+#define INTEL_MSIC_V180AONCNT          0x0c7
+#define INTEL_MSIC_V500CNT             0x0c8
+#define INTEL_MSIC_VIHFCNT             0x0c9
+#define INTEL_MSIC_LDORAMP1            0x0ca
+#define INTEL_MSIC_LDORAMP2            0x0cb
+#define INTEL_MSIC_VCC108AONCNT                0x0cc
+#define INTEL_MSIC_VCC108ASCNT         0x0cd
+#define INTEL_MSIC_VCC108CNT           0x0ce
+#define INTEL_MSIC_VCCA100ASCNT                0x0cf
+#define INTEL_MSIC_VCCA100CNT          0x0d0
+#define INTEL_MSIC_VCC180AONCNT                0x0d1
+#define INTEL_MSIC_VCC180CNT           0x0d2
+#define INTEL_MSIC_VCC330CNT           0x0d3
+#define INTEL_MSIC_VUSB330CNT          0x0d4
+#define INTEL_MSIC_VCCSDIOCNT          0x0d5
+#define INTEL_MSIC_VPROG1CNT           0x0d6
+#define INTEL_MSIC_VPROG2CNT           0x0d7
+#define INTEL_MSIC_VEMMCSCNT           0x0d8
+#define INTEL_MSIC_VEMMC1CNT           0x0d9
+#define INTEL_MSIC_VEMMC2CNT           0x0da
+#define INTEL_MSIC_VAUDACNT            0x0db
+#define INTEL_MSIC_VHSPCNT             0x0dc
+#define INTEL_MSIC_VHSNCNT             0x0dd
+#define INTEL_MSIC_VHDMICNT            0x0de
+#define INTEL_MSIC_VOTGCNT             0x0df
+#define INTEL_MSIC_V1P35CNT            0x0e0
+#define INTEL_MSIC_V330AONCNT          0x0e1
+
+/* RESET */
+#define INTEL_MSIC_CHIPCNTRL           0x100   /* WO */
+#define INTEL_MSIC_ERCONFIG            0x101
+
+/* BURST */
+#define INTEL_MSIC_BATCURRENTLIMIT12   0x102
+#define INTEL_MSIC_BATTIMELIMIT12      0x103
+#define INTEL_MSIC_BATTIMELIMIT3       0x104
+#define INTEL_MSIC_BATTIMEDB           0x105
+#define INTEL_MSIC_BRSTCONFIGOUTPUTS   0x106
+#define INTEL_MSIC_BRSTCONFIGACTIONS   0x107
+#define INTEL_MSIC_BURSTCONTROLSTATUS  0x108
+
+/* RTC */
+#define INTEL_MSIC_RTCB1               0x140   /* RO */
+#define INTEL_MSIC_RTCB2               0x141   /* RO */
+#define INTEL_MSIC_RTCB3               0x142   /* RO */
+#define INTEL_MSIC_RTCB4               0x143   /* RO */
+#define INTEL_MSIC_RTCOB1              0x144
+#define INTEL_MSIC_RTCOB2              0x145
+#define INTEL_MSIC_RTCOB3              0x146
+#define INTEL_MSIC_RTCOB4              0x147
+#define INTEL_MSIC_RTCAB1              0x148
+#define INTEL_MSIC_RTCAB2              0x149
+#define INTEL_MSIC_RTCAB3              0x14a
+#define INTEL_MSIC_RTCAB4              0x14b
+#define INTEL_MSIC_RTCWAB1             0x14c
+#define INTEL_MSIC_RTCWAB2             0x14d
+#define INTEL_MSIC_RTCWAB3             0x14e
+#define INTEL_MSIC_RTCWAB4             0x14f
+#define INTEL_MSIC_RTCSC1              0x150
+#define INTEL_MSIC_RTCSC2              0x151
+#define INTEL_MSIC_RTCSC3              0x152
+#define INTEL_MSIC_RTCSC4              0x153
+#define INTEL_MSIC_RTCSTATUS           0x154   /* RO */
+#define INTEL_MSIC_RTCCONFIG1          0x155
+#define INTEL_MSIC_RTCCONFIG2          0x156
+
+/* CHARGER */
+#define INTEL_MSIC_BDTIMER             0x180
+#define INTEL_MSIC_BATTRMV             0x181
+#define INTEL_MSIC_VBUSDET             0x182
+#define INTEL_MSIC_VBUSDET1            0x183
+#define INTEL_MSIC_ADPHVDET            0x184
+#define INTEL_MSIC_ADPLVDET            0x185
+#define INTEL_MSIC_ADPDETDBDM          0x186
+#define INTEL_MSIC_LOWBATTDET          0x187
+#define INTEL_MSIC_CHRCTRL             0x188
+#define INTEL_MSIC_CHRCVOLTAGE         0x189
+#define INTEL_MSIC_CHRCCURRENT         0x18a
+#define INTEL_MSIC_SPCHARGER           0x18b
+#define INTEL_MSIC_CHRTTIME            0x18c
+#define INTEL_MSIC_CHRCTRL1            0x18d
+#define INTEL_MSIC_PWRSRCLMT           0x18e
+#define INTEL_MSIC_CHRSTWDT            0x18f
+#define INTEL_MSIC_WDTWRITE            0x190   /* WO */
+#define INTEL_MSIC_CHRSAFELMT          0x191
+#define INTEL_MSIC_SPWRSRCINT          0x192   /* RO */
+#define INTEL_MSIC_SPWRSRCINT1         0x193   /* RO */
+#define INTEL_MSIC_CHRLEDPWM           0x194
+#define INTEL_MSIC_CHRLEDCTRL          0x195
+
+/* ADC */
+#define INTEL_MSIC_ADC1CNTL1           0x1c0
+#define INTEL_MSIC_ADC1CNTL2           0x1c1
+#define INTEL_MSIC_ADC1CNTL3           0x1c2
+#define INTEL_MSIC_ADC1OFFSETH         0x1c3   /* RO */
+#define INTEL_MSIC_ADC1OFFSETL         0x1c4   /* RO */
+#define INTEL_MSIC_ADC1ADDR0           0x1c5
+#define INTEL_MSIC_ADC1ADDR1           0x1c6
+#define INTEL_MSIC_ADC1ADDR2           0x1c7
+#define INTEL_MSIC_ADC1ADDR3           0x1c8
+#define INTEL_MSIC_ADC1ADDR4           0x1c9
+#define INTEL_MSIC_ADC1ADDR5           0x1ca
+#define INTEL_MSIC_ADC1ADDR6           0x1cb
+#define INTEL_MSIC_ADC1ADDR7           0x1cc
+#define INTEL_MSIC_ADC1ADDR8           0x1cd
+#define INTEL_MSIC_ADC1ADDR9           0x1ce
+#define INTEL_MSIC_ADC1ADDR10          0x1cf
+#define INTEL_MSIC_ADC1ADDR11          0x1d0
+#define INTEL_MSIC_ADC1ADDR12          0x1d1
+#define INTEL_MSIC_ADC1ADDR13          0x1d2
+#define INTEL_MSIC_ADC1ADDR14          0x1d3
+#define INTEL_MSIC_ADC1SNS0H           0x1d4   /* RO */
+#define INTEL_MSIC_ADC1SNS0L           0x1d5   /* RO */
+#define INTEL_MSIC_ADC1SNS1H           0x1d6   /* RO */
+#define INTEL_MSIC_ADC1SNS1L           0x1d7   /* RO */
+#define INTEL_MSIC_ADC1SNS2H           0x1d8   /* RO */
+#define INTEL_MSIC_ADC1SNS2L           0x1d9   /* RO */
+#define INTEL_MSIC_ADC1SNS3H           0x1da   /* RO */
+#define INTEL_MSIC_ADC1SNS3L           0x1db   /* RO */
+#define INTEL_MSIC_ADC1SNS4H           0x1dc   /* RO */
+#define INTEL_MSIC_ADC1SNS4L           0x1dd   /* RO */
+#define INTEL_MSIC_ADC1SNS5H           0x1de   /* RO */
+#define INTEL_MSIC_ADC1SNS5L           0x1df   /* RO */
+#define INTEL_MSIC_ADC1SNS6H           0x1e0   /* RO */
+#define INTEL_MSIC_ADC1SNS6L           0x1e1   /* RO */
+#define INTEL_MSIC_ADC1SNS7H           0x1e2   /* RO */
+#define INTEL_MSIC_ADC1SNS7L           0x1e3   /* RO */
+#define INTEL_MSIC_ADC1SNS8H           0x1e4   /* RO */
+#define INTEL_MSIC_ADC1SNS8L           0x1e5   /* RO */
+#define INTEL_MSIC_ADC1SNS9H           0x1e6   /* RO */
+#define INTEL_MSIC_ADC1SNS9L           0x1e7   /* RO */
+#define INTEL_MSIC_ADC1SNS10H          0x1e8   /* RO */
+#define INTEL_MSIC_ADC1SNS10L          0x1e9   /* RO */
+#define INTEL_MSIC_ADC1SNS11H          0x1ea   /* RO */
+#define INTEL_MSIC_ADC1SNS11L          0x1eb   /* RO */
+#define INTEL_MSIC_ADC1SNS12H          0x1ec   /* RO */
+#define INTEL_MSIC_ADC1SNS12L          0x1ed   /* RO */
+#define INTEL_MSIC_ADC1SNS13H          0x1ee   /* RO */
+#define INTEL_MSIC_ADC1SNS13L          0x1ef   /* RO */
+#define INTEL_MSIC_ADC1SNS14H          0x1f0   /* RO */
+#define INTEL_MSIC_ADC1SNS14L          0x1f1   /* RO */
+#define INTEL_MSIC_ADC1BV0H            0x1f2   /* RO */
+#define INTEL_MSIC_ADC1BV0L            0x1f3   /* RO */
+#define INTEL_MSIC_ADC1BV1H            0x1f4   /* RO */
+#define INTEL_MSIC_ADC1BV1L            0x1f5   /* RO */
+#define INTEL_MSIC_ADC1BV2H            0x1f6   /* RO */
+#define INTEL_MSIC_ADC1BV2L            0x1f7   /* RO */
+#define INTEL_MSIC_ADC1BV3H            0x1f8   /* RO */
+#define INTEL_MSIC_ADC1BV3L            0x1f9   /* RO */
+#define INTEL_MSIC_ADC1BI0H            0x1fa   /* RO */
+#define INTEL_MSIC_ADC1BI0L            0x1fb   /* RO */
+#define INTEL_MSIC_ADC1BI1H            0x1fc   /* RO */
+#define INTEL_MSIC_ADC1BI1L            0x1fd   /* RO */
+#define INTEL_MSIC_ADC1BI2H            0x1fe   /* RO */
+#define INTEL_MSIC_ADC1BI2L            0x1ff   /* RO */
+#define INTEL_MSIC_ADC1BI3H            0x200   /* RO */
+#define INTEL_MSIC_ADC1BI3L            0x201   /* RO */
+#define INTEL_MSIC_CCCNTL              0x202
+#define INTEL_MSIC_CCOFFSETH           0x203   /* RO */
+#define INTEL_MSIC_CCOFFSETL           0x204   /* RO */
+#define INTEL_MSIC_CCADCHA             0x205   /* RO */
+#define INTEL_MSIC_CCADCLA             0x206   /* RO */
+
+/* AUDIO */
+#define INTEL_MSIC_AUDPLLCTRL          0x240
+#define INTEL_MSIC_DMICBUF0123         0x241
+#define INTEL_MSIC_DMICBUF45           0x242
+#define INTEL_MSIC_DMICGPO             0x244
+#define INTEL_MSIC_DMICMUX             0x245
+#define INTEL_MSIC_DMICCLK             0x246
+#define INTEL_MSIC_MICBIAS             0x247
+#define INTEL_MSIC_ADCCONFIG           0x248
+#define INTEL_MSIC_MICAMP1             0x249
+#define INTEL_MSIC_MICAMP2             0x24a
+#define INTEL_MSIC_NOISEMUX            0x24b
+#define INTEL_MSIC_AUDIOMUX12          0x24c
+#define INTEL_MSIC_AUDIOMUX34          0x24d
+#define INTEL_MSIC_AUDIOSINC           0x24e
+#define INTEL_MSIC_AUDIOTXEN           0x24f
+#define INTEL_MSIC_HSEPRXCTRL          0x250
+#define INTEL_MSIC_IHFRXCTRL           0x251
+#define INTEL_MSIC_VOICETXVOL          0x252
+#define INTEL_MSIC_SIDETONEVOL         0x253
+#define INTEL_MSIC_MUSICSHARVOL                0x254
+#define INTEL_MSIC_VOICETXCTRL         0x255
+#define INTEL_MSIC_HSMIXER             0x256
+#define INTEL_MSIC_DACCONFIG           0x257
+#define INTEL_MSIC_SOFTMUTE            0x258
+#define INTEL_MSIC_HSLVOLCTRL          0x259
+#define INTEL_MSIC_HSRVOLCTRL          0x25a
+#define INTEL_MSIC_IHFLVOLCTRL         0x25b
+#define INTEL_MSIC_IHFRVOLCTRL         0x25c
+#define INTEL_MSIC_DRIVEREN            0x25d
+#define INTEL_MSIC_LINEOUTCTRL         0x25e
+#define INTEL_MSIC_VIB1CTRL1           0x25f
+#define INTEL_MSIC_VIB1CTRL2           0x260
+#define INTEL_MSIC_VIB1CTRL3           0x261
+#define INTEL_MSIC_VIB1SPIPCM_1                0x262
+#define INTEL_MSIC_VIB1SPIPCM_2                0x263
+#define INTEL_MSIC_VIB1CTRL5           0x264
+#define INTEL_MSIC_VIB2CTRL1           0x265
+#define INTEL_MSIC_VIB2CTRL2           0x266
+#define INTEL_MSIC_VIB2CTRL3           0x267
+#define INTEL_MSIC_VIB2SPIPCM_1                0x268
+#define INTEL_MSIC_VIB2SPIPCM_2                0x269
+#define INTEL_MSIC_VIB2CTRL5           0x26a
+#define INTEL_MSIC_BTNCTRL1            0x26b
+#define INTEL_MSIC_BTNCTRL2            0x26c
+#define INTEL_MSIC_PCM1TXSLOT01                0x26d
+#define INTEL_MSIC_PCM1TXSLOT23                0x26e
+#define INTEL_MSIC_PCM1TXSLOT45                0x26f
+#define INTEL_MSIC_PCM1RXSLOT0123      0x270
+#define INTEL_MSIC_PCM1RXSLOT045       0x271
+#define INTEL_MSIC_PCM2TXSLOT01                0x272
+#define INTEL_MSIC_PCM2TXSLOT23                0x273
+#define INTEL_MSIC_PCM2TXSLOT45                0x274
+#define INTEL_MSIC_PCM2RXSLOT01                0x275
+#define INTEL_MSIC_PCM2RXSLOT23                0x276
+#define INTEL_MSIC_PCM2RXSLOT45                0x277
+#define INTEL_MSIC_PCM1CTRL1           0x278
+#define INTEL_MSIC_PCM1CTRL2           0x279
+#define INTEL_MSIC_PCM1CTRL3           0x27a
+#define INTEL_MSIC_PCM2CTRL1           0x27b
+#define INTEL_MSIC_PCM2CTRL2           0x27c
+
+/* HDMI */
+#define INTEL_MSIC_HDMIPUEN            0x280
+#define INTEL_MSIC_HDMISTATUS          0x281   /* RO */
+
+/* Physical address of the start of the MSIC interrupt tree in SRAM */
+#define INTEL_MSIC_IRQ_PHYS_BASE       0xffff7fc0
+
+/**
+ * struct intel_msic_gpio_pdata - platform data for the MSIC GPIO driver
+ * @gpio_base: base number for the GPIOs
+ */
+struct intel_msic_gpio_pdata {
+       unsigned        gpio_base;
+};
+
+/**
+ * struct intel_msic_ocd_pdata - platform data for the MSIC OCD driver
+ * @gpio: GPIO number used for OCD interrupts
+ *
+ * The MSIC MFD driver converts @gpio into an IRQ number and passes it to
+ * the OCD driver as %IORESOURCE_IRQ.
+ */
+struct intel_msic_ocd_pdata {
+       unsigned        gpio;
+};
+
+/* MSIC embedded blocks (subdevices) */
+enum intel_msic_block {
+       INTEL_MSIC_BLOCK_TOUCH,
+       INTEL_MSIC_BLOCK_ADC,
+       INTEL_MSIC_BLOCK_BATTERY,
+       INTEL_MSIC_BLOCK_GPIO,
+       INTEL_MSIC_BLOCK_AUDIO,
+       INTEL_MSIC_BLOCK_HDMI,
+       INTEL_MSIC_BLOCK_THERMAL,
+       INTEL_MSIC_BLOCK_POWER_BTN,
+       INTEL_MSIC_BLOCK_OCD,
+
+       INTEL_MSIC_BLOCK_LAST,
+};
+
+/**
+ * struct intel_msic_platform_data - platform data for the MSIC driver
+ * @irq: array of interrupt numbers, one per device. If @irq is set to %0
+ *      for a given block, the corresponding platform device is not
+ *      created. For devices which don't have an interrupt, use %0xff
+ *      (this is same as in SFI spec).
+ * @gpio: platform data for the MSIC GPIO driver
+ * @ocd: platform data for the MSIC OCD driver
+ *
+ * Once the MSIC driver is initialized, the register interface is ready to
+ * use. All the platform devices for subdevices are created after the
+ * register interface is ready so that we can guarantee its availability to
+ * the subdevice drivers.
+ *
+ * Interrupt numbers are passed to the subdevices via %IORESOURCE_IRQ
+ * resources of the created platform device.
+ */
+struct intel_msic_platform_data {
+       int                             irq[INTEL_MSIC_BLOCK_LAST];
+       struct intel_msic_gpio_pdata    *gpio;
+       struct intel_msic_ocd_pdata     *ocd;
+};
+
+struct intel_msic;
+
+extern int intel_msic_reg_read(unsigned short reg, u8 *val);
+extern int intel_msic_reg_write(unsigned short reg, u8 val);
+extern int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask);
+extern int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count);
+extern int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count);
+
+/*
+ * pdev_to_intel_msic - gets an MSIC instance from the platform device
+ * @pdev: platform device pointer
+ *
+ * The client drivers need to have pointer to the MSIC instance if they
+ * want to call intel_msic_irq_read(). This macro can be used for
+ * convenience to get the MSIC pointer from @pdev where needed. This is
+ * _only_ valid for devices which are managed by the MSIC.
+ */
+#define pdev_to_intel_msic(pdev)       (dev_get_drvdata(pdev->dev.parent))
+
+extern int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg,
+                              u8 *val);
+
+#endif /* __LINUX_MFD_INTEL_MSIC_H__ */
index 5ff2400..3f4deb6 100644 (file)
@@ -326,7 +326,6 @@ struct max8997_dev {
        int irq;
        int ono;
        int irq_base;
-       bool wakeup;
        struct mutex irqlock;
        int irq_masks_cur[MAX8997_IRQ_GROUP_NR];
        int irq_masks_cache[MAX8997_IRQ_GROUP_NR];
index 7d0f3d6..a8eeda7 100644 (file)
 
 #include <linux/mfd/mc13xxx.h>
 
-struct mc13783;
-
-struct mc13xxx *mc13783_to_mc13xxx(struct mc13783 *mc13783);
-
-static inline void mc13783_lock(struct mc13783 *mc13783)
-{
-       mc13xxx_lock(mc13783_to_mc13xxx(mc13783));
-}
-
-static inline void mc13783_unlock(struct mc13783 *mc13783)
-{
-       mc13xxx_unlock(mc13783_to_mc13xxx(mc13783));
-}
-
-static inline int mc13783_reg_read(struct mc13783 *mc13783,
-               unsigned int offset, u32 *val)
-{
-       return mc13xxx_reg_read(mc13783_to_mc13xxx(mc13783), offset, val);
-}
-
-static inline int mc13783_reg_write(struct mc13783 *mc13783,
-               unsigned int offset, u32 val)
-{
-       return mc13xxx_reg_write(mc13783_to_mc13xxx(mc13783), offset, val);
-}
-
-static inline int mc13783_reg_rmw(struct mc13783 *mc13783,
-               unsigned int offset, u32 mask, u32 val)
-{
-       return mc13xxx_reg_rmw(mc13783_to_mc13xxx(mc13783), offset, mask, val);
-}
-
-static inline int mc13783_get_flags(struct mc13783 *mc13783)
-{
-       return mc13xxx_get_flags(mc13783_to_mc13xxx(mc13783));
-}
-
-static inline int mc13783_irq_request(struct mc13783 *mc13783, int irq,
-               irq_handler_t handler, const char *name, void *dev)
-{
-       return mc13xxx_irq_request(mc13783_to_mc13xxx(mc13783), irq,
-                       handler, name, dev);
-}
-
-static inline int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq,
-               irq_handler_t handler, const char *name, void *dev)
-{
-       return mc13xxx_irq_request_nounmask(mc13783_to_mc13xxx(mc13783), irq,
-                       handler, name, dev);
-}
-
-static inline int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev)
-{
-       return mc13xxx_irq_free(mc13783_to_mc13xxx(mc13783), irq, dev);
-}
-
-static inline int mc13783_irq_mask(struct mc13783 *mc13783, int irq)
-{
-       return mc13xxx_irq_mask(mc13783_to_mc13xxx(mc13783), irq);
-}
-
-static inline int mc13783_irq_unmask(struct mc13783 *mc13783, int irq)
-{
-       return mc13xxx_irq_unmask(mc13783_to_mc13xxx(mc13783), irq);
-}
-static inline int mc13783_irq_status(struct mc13783 *mc13783, int irq,
-               int *enabled, int *pending)
-{
-       return mc13xxx_irq_status(mc13783_to_mc13xxx(mc13783),
-                       irq, enabled, pending);
-}
-
-static inline int mc13783_irq_ack(struct mc13783 *mc13783, int irq)
-{
-       return mc13xxx_irq_ack(mc13783_to_mc13xxx(mc13783), irq);
-}
-
-#define MC13783_ADC0           43
-#define MC13783_ADC0_ADREFEN           (1 << 10)
-#define MC13783_ADC0_ADREFMODE         (1 << 11)
-#define MC13783_ADC0_TSMOD0            (1 << 12)
-#define MC13783_ADC0_TSMOD1            (1 << 13)
-#define MC13783_ADC0_TSMOD2            (1 << 14)
-#define MC13783_ADC0_ADINC1            (1 << 16)
-#define MC13783_ADC0_ADINC2            (1 << 17)
-
-#define MC13783_ADC0_TSMOD_MASK                (MC13783_ADC0_TSMOD0 | \
-                                       MC13783_ADC0_TSMOD1 | \
-                                       MC13783_ADC0_TSMOD2)
-
-#define mc13783_regulator_init_data mc13xxx_regulator_init_data
-#define mc13783_regulator_platform_data mc13xxx_regulator_platform_data
-#define mc13783_led_platform_data mc13xxx_led_platform_data
-#define mc13783_leds_platform_data mc13xxx_leds_platform_data
-
-#define mc13783_platform_data mc13xxx_platform_data
-#define MC13783_USE_TOUCHSCREEN        MC13XXX_USE_TOUCHSCREEN
-#define MC13783_USE_CODEC      MC13XXX_USE_CODEC
-#define MC13783_USE_ADC                MC13XXX_USE_ADC
-#define MC13783_USE_RTC                MC13XXX_USE_RTC
-#define MC13783_USE_REGULATOR  MC13XXX_USE_REGULATOR
-#define MC13783_USE_LED                MC13XXX_USE_LED
-
-#define MC13783_ADC_MODE_TS            1
-#define MC13783_ADC_MODE_SINGLE_CHAN   2
-#define MC13783_ADC_MODE_MULT_CHAN     3
-
-int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
-               unsigned int channel, unsigned int *sample);
-
-
 #define        MC13783_REG_SW1A                0
 #define        MC13783_REG_SW1B                1
 #define        MC13783_REG_SW2A                2
index c064bea..3816c2f 100644 (file)
@@ -37,6 +37,9 @@ int mc13xxx_irq_ack(struct mc13xxx *mc13xxx, int irq);
 
 int mc13xxx_get_flags(struct mc13xxx *mc13xxx);
 
+int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx,
+               unsigned int mode, unsigned int channel, unsigned int *sample);
+
 #define MC13XXX_IRQ_ADCDONE    0
 #define MC13XXX_IRQ_ADCBISDONE 1
 #define MC13XXX_IRQ_TS         2
@@ -137,17 +140,48 @@ struct mc13xxx_leds_platform_data {
        char tc3_period;
 };
 
+struct mc13xxx_buttons_platform_data {
+#define MC13783_BUTTON_DBNC_0MS                0
+#define MC13783_BUTTON_DBNC_30MS       1
+#define MC13783_BUTTON_DBNC_150MS      2
+#define MC13783_BUTTON_DBNC_750MS      3
+#define MC13783_BUTTON_ENABLE          (1 << 2)
+#define MC13783_BUTTON_POL_INVERT      (1 << 3)
+#define MC13783_BUTTON_RESET_EN                (1 << 4)
+       int b1on_flags;
+       unsigned short b1on_key;
+       int b2on_flags;
+       unsigned short b2on_key;
+       int b3on_flags;
+       unsigned short b3on_key;
+};
+
 struct mc13xxx_platform_data {
 #define MC13XXX_USE_TOUCHSCREEN (1 << 0)
 #define MC13XXX_USE_CODEC      (1 << 1)
 #define MC13XXX_USE_ADC                (1 << 2)
 #define MC13XXX_USE_RTC                (1 << 3)
-#define MC13XXX_USE_REGULATOR  (1 << 4)
-#define MC13XXX_USE_LED                (1 << 5)
        unsigned int flags;
 
        struct mc13xxx_regulator_platform_data regulators;
        struct mc13xxx_leds_platform_data *leds;
+       struct mc13xxx_buttons_platform_data *buttons;
 };
 
+#define MC13XXX_ADC_MODE_TS            1
+#define MC13XXX_ADC_MODE_SINGLE_CHAN   2
+#define MC13XXX_ADC_MODE_MULT_CHAN     3
+
+#define MC13XXX_ADC0           43
+#define MC13XXX_ADC0_ADREFEN           (1 << 10)
+#define MC13XXX_ADC0_TSMOD0            (1 << 12)
+#define MC13XXX_ADC0_TSMOD1            (1 << 13)
+#define MC13XXX_ADC0_TSMOD2            (1 << 14)
+#define MC13XXX_ADC0_ADINC1            (1 << 16)
+#define MC13XXX_ADC0_ADINC2            (1 << 17)
+
+#define MC13XXX_ADC0_TSMOD_MASK                (MC13XXX_ADC0_TSMOD0 | \
+                                       MC13XXX_ADC0_TSMOD1 | \
+                                       MC13XXX_ADC0_TSMOD2)
+
 #endif /* ifndef __LINUX_MFD_MC13XXX_H */
index 50d4a04..a808407 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/mfd/pcf50633/backlight.h>
 
 struct pcf50633;
+struct regmap;
 
 #define PCF50633_NUM_REGULATORS        11
 
@@ -134,7 +135,7 @@ enum {
 
 struct pcf50633 {
        struct device *dev;
-       struct i2c_client *i2c_client;
+       struct regmap *regmap;
 
        struct pcf50633_platform_data *pdata;
        int irq;
index ed8fe0d..4b12118 100644 (file)
@@ -382,6 +382,7 @@ struct wm831x {
 
        /* Used by the interrupt controller code to post writes */
        int gpio_update[WM831X_NUM_GPIO_REGS];
+       bool gpio_level[WM831X_NUM_GPIO_REGS];
 
        struct mutex auxadc_lock;
        struct list_head auxadc_pending;
index 6268091..f44bdb7 100644 (file)
@@ -59,6 +59,8 @@ struct wm8994 {
        struct device *dev;
        struct regmap *regmap;
 
+       bool ldo_ena_always_driven;
+
        int gpio_base;
        int irq_base;
 
index 97cf4f2..ea32f30 100644 (file)
@@ -167,6 +167,13 @@ struct wm8994_pdata {
 
        /* WM8958 microphone bias configuration */
        int micbias[2];
+
+       /* Disable the internal pull downs on the LDOs if they are
+        * always driven (eg, connected to an always on supply or
+        * GPIO that always drives an output.  If they float power
+        * consumption will rise.
+        */
+       bool ldo_ena_always_driven;
 };
 
 #endif