Merge commit '7185684' into omap-for-v3.10/timer
authorTony Lindgren <tony@atomide.com>
Wed, 3 Apr 2013 17:32:47 +0000 (10:32 -0700)
committerTony Lindgren <tony@atomide.com>
Wed, 3 Apr 2013 17:32:47 +0000 (10:32 -0700)
Conflicts:
arch/arm/plat-omap/dmtimer.c

Resolve merge conflict in omap_device.c as per
Lothar Waßmann <LW@KARO-electronics.de>.

14 files changed:
1  2 
arch/arm/kernel/process.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-tegra/tegra2_emc.c
arch/arm/mach-ux500/cpu.c
arch/arm/plat-omap/dmtimer.c

@@@ -172,9 -172,14 +172,9 @@@ static void default_idle(void
        local_irq_enable();
  }
  
 -void (*pm_idle)(void) = default_idle;
 -EXPORT_SYMBOL(pm_idle);
 -
  /*
 - * The idle thread, has rather strange semantics for calling pm_idle,
 - * but this is what x86 does and we need to do the same, so that
 - * things like cpuidle get called in the same way.  The only difference
 - * is that we always respect 'hlt_counter' to prevent low power idle.
 + * The idle thread.
 + * We always respect 'hlt_counter' to prevent low power idle.
   */
  void cpu_idle(void)
  {
                        } else if (!need_resched()) {
                                stop_critical_timings();
                                if (cpuidle_idle_call())
 -                                      pm_idle();
 +                                      default_idle();
                                start_critical_timings();
                                /*
 -                               * pm_idle functions must always
 +                               * default_idle functions must always
                                 * return with IRQs enabled.
                                 */
                                WARN_ON(irqs_disabled());
@@@ -459,15 -464,16 +459,16 @@@ unsigned long arch_randomize_brk(struc
   * atomic helpers and the signal restart code. Insert it into the
   * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
   */
- static struct vm_area_struct gate_vma;
+ static struct vm_area_struct gate_vma = {
+       .vm_start       = 0xffff0000,
+       .vm_end         = 0xffff0000 + PAGE_SIZE,
+       .vm_flags       = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
+       .vm_mm          = &init_mm,
+ };
  
  static int __init gate_vma_init(void)
  {
-       gate_vma.vm_start       = 0xffff0000;
-       gate_vma.vm_end         = 0xffff0000 + PAGE_SIZE;
-       gate_vma.vm_page_prot   = PAGE_READONLY_EXEC;
-       gate_vma.vm_flags       = VM_READ | VM_EXEC |
-                                 VM_MAYREAD | VM_MAYEXEC;
+       gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
        return 0;
  }
  arch_initcall(gate_vma_init);
@@@ -94,7 -94,7 +94,7 @@@ void __iomem *ap_syscon_base
   * f1b00000   1b000000        GPIO
   */
  
 -static struct map_desc ap_io_desc[] __initdata = {
 +static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
        {
                .virtual        = IO_ADDRESS(INTEGRATOR_HDR_BASE),
                .pfn            = __phys_to_pfn(INTEGRATOR_HDR_BASE),
@@@ -425,7 -425,7 +425,7 @@@ void __init ap_init_early(void
  
  #ifdef CONFIG_OF
  
 -static void __init ap_init_timer_of(void)
 +static void __init ap_of_timer_init(void)
  {
        struct device_node *node;
        const char *path;
        integrator_clockevent_init(rate, base, irq);
  }
  
 -static struct sys_timer ap_of_timer = {
 -      .init           = ap_init_timer_of,
 -};
 -
  static const struct of_device_id fpga_irq_of_match[] __initconst = {
        { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
        { /* Sentinel */ }
@@@ -536,16 -540,14 +536,14 @@@ static void __init ap_init_of(void
                                           'A' + (ap_sc_id & 0x0f));
  
        soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR_OR_NULL(soc_dev)) {
+       if (IS_ERR(soc_dev)) {
                kfree(soc_dev_attr->revision);
                kfree(soc_dev_attr);
                return;
        }
  
        parent = soc_device_to_device(soc_dev);
-       if (!IS_ERR_OR_NULL(parent))
-               integrator_init_sysfs(parent, ap_sc_id);
+       integrator_init_sysfs(parent, ap_sc_id);
  
        of_platform_populate(root, of_default_bus_match_table,
                        ap_auxdata_lookup, parent);
@@@ -582,7 -584,7 +580,7 @@@ DT_MACHINE_START(INTEGRATOR_AP_DT, "AR
        .init_early     = ap_init_early,
        .init_irq       = ap_init_irq_of,
        .handle_irq     = fpga_handle_irq,
 -      .timer          = &ap_of_timer,
 +      .init_time      = ap_of_timer_init,
        .init_machine   = ap_init_of,
        .restart        = integrator_restart,
        .dt_compat      = ap_dt_board_compat,
@@@ -609,6 -611,7 +607,6 @@@ static struct map_desc ap_io_desc_atag[
  static void __init ap_map_io_atag(void)
  {
        iotable_init(ap_io_desc_atag, ARRAY_SIZE(ap_io_desc_atag));
 -      ap_syscon_base = __io_address(INTEGRATOR_SC_BASE);
        ap_map_io();
  }
  
@@@ -633,7 -636,7 +631,7 @@@ static struct platform_device cfi_flash
        .resource       = &cfi_flash_resource,
  };
  
 -static void __init ap_init_timer(void)
 +static void __init ap_timer_init(void)
  {
        struct clk *clk;
        unsigned long rate;
                                IRQ_TIMERINT1);
  }
  
 -static struct sys_timer ap_timer = {
 -      .init           = ap_init_timer,
 -};
 -
  #define INTEGRATOR_SC_VALID_INT       0x003fffff
  
  static void __init ap_init_irq(void)
@@@ -676,7 -683,6 +674,7 @@@ static void __init ap_init(void
  
        platform_device_register(&cfi_flash_device);
  
 +      ap_syscon_base = __io_address(INTEGRATOR_SC_BASE);
        sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
        for (i = 0; i < 4; i++) {
                struct lm_device *lmdev;
@@@ -708,7 -714,7 +706,7 @@@ MACHINE_START(INTEGRATOR, "ARM-Integrat
        .init_early     = ap_init_early,
        .init_irq       = ap_init_irq,
        .handle_irq     = fpga_handle_irq,
 -      .timer          = &ap_timer,
 +      .init_time      = ap_timer_init,
        .init_machine   = ap_init,
        .restart        = integrator_restart,
  MACHINE_END
@@@ -78,7 -78,7 +78,7 @@@ static void __iomem *intcp_con_base
   * fcb00000   cb000000        CP system control
   */
  
 -static struct map_desc intcp_io_desc[] __initdata = {
 +static struct map_desc intcp_io_desc[] __initdata __maybe_unused = {
        {
                .virtual        = IO_ADDRESS(INTEGRATOR_HDR_BASE),
                .pfn            = __phys_to_pfn(INTEGRATOR_HDR_BASE),
@@@ -251,7 -251,7 +251,7 @@@ static void __init intcp_init_early(voi
  
  #ifdef CONFIG_OF
  
 -static void __init intcp_timer_init_of(void)
 +static void __init cp_of_timer_init(void)
  {
        struct device_node *node;
        const char *path;
        sp804_clockevents_init(base, irq, node->name);
  }
  
 -static struct sys_timer cp_of_timer = {
 -      .init           = intcp_timer_init_of,
 -};
 -
  static const struct of_device_id fpga_irq_of_match[] __initconst = {
        { .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
        { /* Sentinel */ }
@@@ -360,17 -364,14 +360,14 @@@ static void __init intcp_init_of(void
                                           'A' + (intcp_sc_id & 0x0f));
  
        soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR_OR_NULL(soc_dev)) {
+       if (IS_ERR(soc_dev)) {
                kfree(soc_dev_attr->revision);
                kfree(soc_dev_attr);
                return;
        }
  
        parent = soc_device_to_device(soc_dev);
-       if (!IS_ERR_OR_NULL(parent))
-               integrator_init_sysfs(parent, intcp_sc_id);
+       integrator_init_sysfs(parent, intcp_sc_id);
        of_platform_populate(root, of_default_bus_match_table,
                        intcp_auxdata_lookup, parent);
  }
@@@ -386,7 -387,7 +383,7 @@@ DT_MACHINE_START(INTEGRATOR_CP_DT, "AR
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq_of,
        .handle_irq     = fpga_handle_irq,
 -      .timer          = &cp_of_timer,
 +      .init_time      = cp_of_timer_init,
        .init_machine   = intcp_init_of,
        .restart        = integrator_restart,
        .dt_compat      = intcp_dt_board_compat,
@@@ -508,7 -509,7 +505,7 @@@ static void __init intcp_init_irq(void
  #define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
  #define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
  
 -static void __init intcp_timer_init(void)
 +static void __init cp_timer_init(void)
  {
        writel(0, TIMER0_VA_BASE + TIMER_CTRL);
        writel(0, TIMER1_VA_BASE + TIMER_CTRL);
        sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1");
  }
  
 -static struct sys_timer cp_timer = {
 -      .init           = intcp_timer_init,
 -};
 -
  #define INTEGRATOR_CP_MMC_IRQS        { IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
  #define INTEGRATOR_CP_AACI_IRQS       { IRQ_CP_AACIINT }
  
@@@ -557,7 -562,7 +554,7 @@@ MACHINE_START(CINTEGRATOR, "ARM-Integra
        .init_early     = intcp_init_early,
        .init_irq       = intcp_init_irq,
        .handle_irq     = fpga_handle_irq,
 -      .timer          = &cp_timer,
 +      .init_time      = cp_timer_init,
        .init_machine   = intcp_init,
        .restart        = integrator_restart,
  MACHINE_END
@@@ -20,8 -20,6 +20,8 @@@
  #include <linux/clk.h>
  #include <linux/io.h>
  #include <linux/leds.h>
 +#include <linux/pwm.h>
 +#include <linux/leds_pwm.h>
  #include <linux/gpio.h>
  #include <linux/input.h>
  #include <linux/gpio_keys.h>
@@@ -32,7 -30,6 +32,7 @@@
  #include <linux/mtd/partitions.h>
  #include <linux/mtd/nand.h>
  #include <linux/mmc/host.h>
 +#include <linux/usb/phy.h>
  
  #include <linux/regulator/machine.h>
  #include <linux/i2c/twl.h>
  
  #define       NAND_CS 0
  
 +static struct pwm_lookup pwm_lookup[] = {
 +      /* LEDB -> PMU_STAT */
 +      PWM_LOOKUP("twl-pwmled", 1, "leds_pwm", "beagleboard::pmu_stat"),
 +};
 +
 +static struct led_pwm pwm_leds[] = {
 +      {
 +              .name           = "beagleboard::pmu_stat",
 +              .max_brightness = 127,
 +              .pwm_period_ns  = 7812500,
 +      },
 +};
 +
 +static struct led_pwm_platform_data pwm_data = {
 +      .num_leds       = ARRAY_SIZE(pwm_leds),
 +      .leds           = pwm_leds,
 +};
 +
 +static struct platform_device leds_pwm = {
 +      .name   = "leds_pwm",
 +      .id     = -1,
 +      .dev    = {
 +              .platform_data = &pwm_data,
 +      },
 +};
 +
  /*
   * OMAP3 Beagle revision
   * Run time detection of Beagle revision is done by reading GPIO.
@@@ -321,6 -292,9 +321,6 @@@ static int beagle_twl_gpio_setup(struc
        gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level,
                        "nEN_USB_PWR");
  
 -      /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
 -      gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
 -
        return 0;
  }
  
@@@ -402,6 -376,11 +402,6 @@@ static struct gpio_led gpio_leds[] = 
                .default_trigger        = "mmc0",
                .gpio                   = 149,
        },
 -      {
 -              .name                   = "beagleboard::pmu_stat",
 -              .gpio                   = -EINVAL,      /* gets replaced */
 -              .active_low             = true,
 -      },
  };
  
  static struct gpio_led_platform_data gpio_led_info = {
@@@ -449,10 -428,9 +449,10 @@@ static struct platform_device *omap3_be
        &leds_gpio,
        &keys_gpio,
        &madc_hwmon,
 +      &leds_pwm,
  };
  
 -static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 +static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
  
        .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
@@@ -479,7 -457,7 +479,7 @@@ static int __init beagle_opp_init(void
  
        /* Initialize the omap3 opp table if not already created. */
        r = omap3_opp_init();
-       if (IS_ERR_VALUE(r) && (r != -EEXIST)) {
+       if (r < 0 && (r != -EEXIST)) {
                pr_err("%s: opp default init failed\n", __func__);
                return r;
        }
        }
        return 0;
  }
 -device_initcall(beagle_opp_init);
 +omap_device_initcall(beagle_opp_init);
  
  static void __init omap3_beagle_init(void)
  {
        omap_sdrc_init(mt46h32m32lf6_sdrc_params,
                                  mt46h32m32lf6_sdrc_params);
  
 +      usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(NULL);
        usbhs_init(&usbhs_bdata);
        board_nand_init(omap3beagle_nand_partitions,
                        ARRAY_SIZE(omap3beagle_nand_partitions), NAND_CS,
                        NAND_BUSWIDTH_16, NULL);
 -      omap_twl4030_audio_init("omap3beagle");
 +      omap_twl4030_audio_init("omap3beagle", NULL);
  
        /* Ensure msecure is mux'd to be able to set the RTC. */
        omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
        /* Ensure SDRC pins are mux'd for self-refresh */
        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
 +
 +      pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup));
  }
  
  MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap3_beagle_init,
        .init_late      = omap3_init_late,
 -      .timer          = &omap3_secure_timer,
 +      .init_time      = omap3_secure_sync32k_timer_init,
        .restart        = omap3xxx_restart,
  MACHINE_END
@@@ -303,7 -303,7 +303,7 @@@ static int omap2_onenand_setup_async(vo
        t = omap2_onenand_calc_async_timings();
  
        ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
-       if (IS_ERR_VALUE(ret))
+       if (ret < 0)
                return ret;
  
        omap2_onenand_set_async_mode(onenand_base);
@@@ -325,7 -325,7 +325,7 @@@ static int omap2_onenand_setup_sync(voi
        t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
  
        ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
-       if (IS_ERR_VALUE(ret))
+       if (ret < 0)
                return ret;
  
        set_onenand_cfg(onenand_base);
@@@ -356,7 -356,7 +356,7 @@@ static int gpmc_onenand_setup(void __io
        return ret;
  }
  
 -void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 +void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
  {
        int err;
  
  #include <linux/module.h>
  #include <linux/interrupt.h>
  #include <linux/platform_device.h>
 +#include <linux/of.h>
 +#include <linux/of_mtd.h>
 +#include <linux/of_device.h>
 +#include <linux/mtd/nand.h>
  
  #include <linux/platform_data/mtd-nand-omap2.h>
  
@@@ -38,8 -34,6 +38,8 @@@
  #include "common.h"
  #include "omap_device.h"
  #include "gpmc.h"
 +#include "gpmc-nand.h"
 +#include "gpmc-onenand.h"
  
  #define       DEVICE_NAME             "omap-gpmc"
  
@@@ -151,8 -145,7 +151,8 @@@ static unsigned gpmc_irq_start
  static struct resource        gpmc_mem_root;
  static struct resource        gpmc_cs_mem[GPMC_CS_NUM];
  static DEFINE_SPINLOCK(gpmc_mem_lock);
 -static unsigned int gpmc_cs_map;      /* flag for cs which are initialized */
 +/* Define chip-selects as reserved by default until probe completes */
 +static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
  static struct device *gpmc_dev;
  static int gpmc_irq;
  static resource_size_t phys_base, mem_size;
@@@ -716,7 -709,7 +716,7 @@@ static int gpmc_setup_irq(void
                return -EINVAL;
  
        gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
-       if (IS_ERR_VALUE(gpmc_irq_start)) {
+       if (gpmc_irq_start < 0) {
                pr_err("irq_alloc_descs failed\n");
                return gpmc_irq_start;
        }
@@@ -790,6 -783,9 +790,6 @@@ static int gpmc_mem_init(void
         * even if we didn't boot from ROM.
         */
        boot_rom_space = BOOT_ROM_SPACE;
 -      /* In apollon the CS0 is mapped as 0x0000 0000 */
 -      if (machine_is_omap_apollon())
 -              boot_rom_space = 0;
        gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
        gpmc_mem_root.end = GPMC_MEM_END;
  
                        continue;
                gpmc_cs_get_memconf(cs, &base, &size);
                rc = gpmc_cs_insert_mem(cs, base, size);
-               if (IS_ERR_VALUE(rc)) {
+               if (rc < 0) {
                        while (--cs >= 0)
                                if (gpmc_cs_mem_enabled(cs))
                                        gpmc_cs_delete_mem(cs);
@@@ -1125,210 -1121,6 +1125,210 @@@ int gpmc_calc_timings(struct gpmc_timin
        return 0;
  }
  
 +#ifdef CONFIG_OF
 +static struct of_device_id gpmc_dt_ids[] = {
 +      { .compatible = "ti,omap2420-gpmc" },
 +      { .compatible = "ti,omap2430-gpmc" },
 +      { .compatible = "ti,omap3430-gpmc" },   /* omap3430 & omap3630 */
 +      { .compatible = "ti,omap4430-gpmc" },   /* omap4430 & omap4460 & omap543x */
 +      { .compatible = "ti,am3352-gpmc" },     /* am335x devices */
 +      { }
 +};
 +MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
 +
 +static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
 +                                              struct gpmc_timings *gpmc_t)
 +{
 +      u32 val;
 +
 +      memset(gpmc_t, 0, sizeof(*gpmc_t));
 +
 +      /* minimum clock period for syncronous mode */
 +      if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
 +              gpmc_t->sync_clk = val;
 +
 +      /* chip select timtings */
 +      if (!of_property_read_u32(np, "gpmc,cs-on", &val))
 +              gpmc_t->cs_on = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
 +              gpmc_t->cs_rd_off = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
 +              gpmc_t->cs_wr_off = val;
 +
 +      /* ADV signal timings */
 +      if (!of_property_read_u32(np, "gpmc,adv-on", &val))
 +              gpmc_t->adv_on = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
 +              gpmc_t->adv_rd_off = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
 +              gpmc_t->adv_wr_off = val;
 +
 +      /* WE signal timings */
 +      if (!of_property_read_u32(np, "gpmc,we-on", &val))
 +              gpmc_t->we_on = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,we-off", &val))
 +              gpmc_t->we_off = val;
 +
 +      /* OE signal timings */
 +      if (!of_property_read_u32(np, "gpmc,oe-on", &val))
 +              gpmc_t->oe_on = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,oe-off", &val))
 +              gpmc_t->oe_off = val;
 +
 +      /* access and cycle timings */
 +      if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
 +              gpmc_t->page_burst_access = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,access", &val))
 +              gpmc_t->access = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
 +              gpmc_t->rd_cycle = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
 +              gpmc_t->wr_cycle = val;
 +
 +      /* only for OMAP3430 */
 +      if (!of_property_read_u32(np, "gpmc,wr-access", &val))
 +              gpmc_t->wr_access = val;
 +
 +      if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
 +              gpmc_t->wr_data_mux_bus = val;
 +}
 +
 +#ifdef CONFIG_MTD_NAND
 +
 +static const char * const nand_ecc_opts[] = {
 +      [OMAP_ECC_HAMMING_CODE_DEFAULT]         = "sw",
 +      [OMAP_ECC_HAMMING_CODE_HW]              = "hw",
 +      [OMAP_ECC_HAMMING_CODE_HW_ROMCODE]      = "hw-romcode",
 +      [OMAP_ECC_BCH4_CODE_HW]                 = "bch4",
 +      [OMAP_ECC_BCH8_CODE_HW]                 = "bch8",
 +};
 +
 +static int gpmc_probe_nand_child(struct platform_device *pdev,
 +                               struct device_node *child)
 +{
 +      u32 val;
 +      const char *s;
 +      struct gpmc_timings gpmc_t;
 +      struct omap_nand_platform_data *gpmc_nand_data;
 +
 +      if (of_property_read_u32(child, "reg", &val) < 0) {
 +              dev_err(&pdev->dev, "%s has no 'reg' property\n",
 +                      child->full_name);
 +              return -ENODEV;
 +      }
 +
 +      gpmc_nand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_nand_data),
 +                                    GFP_KERNEL);
 +      if (!gpmc_nand_data)
 +              return -ENOMEM;
 +
 +      gpmc_nand_data->cs = val;
 +      gpmc_nand_data->of_node = child;
 +
 +      if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
 +              for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
 +                      if (!strcasecmp(s, nand_ecc_opts[val])) {
 +                              gpmc_nand_data->ecc_opt = val;
 +                              break;
 +                      }
 +
 +      val = of_get_nand_bus_width(child);
 +      if (val == 16)
 +              gpmc_nand_data->devsize = NAND_BUSWIDTH_16;
 +
 +      gpmc_read_timings_dt(child, &gpmc_t);
 +      gpmc_nand_init(gpmc_nand_data, &gpmc_t);
 +
 +      return 0;
 +}
 +#else
 +static int gpmc_probe_nand_child(struct platform_device *pdev,
 +                               struct device_node *child)
 +{
 +      return 0;
 +}
 +#endif
 +
 +#ifdef CONFIG_MTD_ONENAND
 +static int gpmc_probe_onenand_child(struct platform_device *pdev,
 +                               struct device_node *child)
 +{
 +      u32 val;
 +      struct omap_onenand_platform_data *gpmc_onenand_data;
 +
 +      if (of_property_read_u32(child, "reg", &val) < 0) {
 +              dev_err(&pdev->dev, "%s has no 'reg' property\n",
 +                      child->full_name);
 +              return -ENODEV;
 +      }
 +
 +      gpmc_onenand_data = devm_kzalloc(&pdev->dev, sizeof(*gpmc_onenand_data),
 +                                       GFP_KERNEL);
 +      if (!gpmc_onenand_data)
 +              return -ENOMEM;
 +
 +      gpmc_onenand_data->cs = val;
 +      gpmc_onenand_data->of_node = child;
 +      gpmc_onenand_data->dma_channel = -1;
 +
 +      if (!of_property_read_u32(child, "dma-channel", &val))
 +              gpmc_onenand_data->dma_channel = val;
 +
 +      gpmc_onenand_init(gpmc_onenand_data);
 +
 +      return 0;
 +}
 +#else
 +static int gpmc_probe_onenand_child(struct platform_device *pdev,
 +                                  struct device_node *child)
 +{
 +      return 0;
 +}
 +#endif
 +
 +static int gpmc_probe_dt(struct platform_device *pdev)
 +{
 +      int ret;
 +      struct device_node *child;
 +      const struct of_device_id *of_id =
 +              of_match_device(gpmc_dt_ids, &pdev->dev);
 +
 +      if (!of_id)
 +              return 0;
 +
 +      for_each_node_by_name(child, "nand") {
 +              ret = gpmc_probe_nand_child(pdev, child);
 +              if (ret < 0) {
 +                      of_node_put(child);
 +                      return ret;
 +              }
 +      }
 +
 +      for_each_node_by_name(child, "onenand") {
 +              ret = gpmc_probe_onenand_child(pdev, child);
 +              if (ret < 0) {
 +                      of_node_put(child);
 +                      return ret;
 +              }
 +      }
 +      return 0;
 +}
 +#else
 +static int gpmc_probe_dt(struct platform_device *pdev)
 +{
 +      return 0;
 +}
 +#endif
 +
  static int gpmc_probe(struct platform_device *pdev)
  {
        int rc;
        phys_base = res->start;
        mem_size = resource_size(res);
  
 -      gpmc_base = devm_request_and_ioremap(&pdev->dev, res);
 -      if (!gpmc_base) {
 -              dev_err(&pdev->dev, "error: request memory / ioremap\n");
 -              return -EADDRNOTAVAIL;
 -      }
 +      gpmc_base = devm_ioremap_resource(&pdev->dev, res);
 +      if (IS_ERR(gpmc_base))
 +              return PTR_ERR(gpmc_base);
  
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (res == NULL)
                 GPMC_REVISION_MINOR(l));
  
        rc = gpmc_mem_init();
-       if (IS_ERR_VALUE(rc)) {
+       if (rc < 0) {
                clk_disable_unprepare(gpmc_l3_clk);
                clk_put(gpmc_l3_clk);
                dev_err(gpmc_dev, "failed to reserve memory\n");
                return rc;
        }
  
-       if (IS_ERR_VALUE(gpmc_setup_irq()))
+       if (gpmc_setup_irq() < 0)
                dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
  
 +      /* Now the GPMC is initialised, unreserve the chip-selects */
 +      gpmc_cs_map = 0;
 +
 +      rc = gpmc_probe_dt(pdev);
 +      if (rc < 0) {
 +              clk_disable_unprepare(gpmc_l3_clk);
 +              clk_put(gpmc_l3_clk);
 +              dev_err(gpmc_dev, "failed to probe DT parameters\n");
 +              return rc;
 +      }
 +
        return 0;
  }
  
@@@ -1408,7 -1191,6 +1408,7 @@@ static struct platform_driver gpmc_driv
        .driver         = {
                .name   = DEVICE_NAME,
                .owner  = THIS_MODULE,
 +              .of_match_table = of_match_ptr(gpmc_dt_ids),
        },
  };
  
@@@ -1423,7 -1205,7 +1423,7 @@@ static __exit void gpmc_exit(void
  
  }
  
 -postcore_initcall(gpmc_init);
 +omap_postcore_initcall(gpmc_init);
  module_exit(gpmc_exit);
  
  static int __init omap_gpmc_init(void)
        struct platform_device *pdev;
        char *oh_name = "gpmc";
  
 +      /*
 +       * if the board boots up with a populated DT, do not
 +       * manually add the device from this initcall
 +       */
 +      if (of_have_populated_dt())
 +              return -ENODEV;
 +
        oh = omap_hwmod_lookup(oh_name);
        if (!oh) {
                pr_err("Could not look up %s\n", oh_name);
                return -ENODEV;
        }
  
 -      pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0, NULL, 0, 0);
 +      pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0);
        WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
  
        return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
  }
 -postcore_initcall(omap_gpmc_init);
 +omap_postcore_initcall(omap_gpmc_init);
  
  static irqreturn_t gpmc_handle_irq(int irq, void *dev)
  {
   * to control power management and interconnect properties of their
   * devices.
   *
 - * In the medium- to long-term, this code should either be
 - * a) implemented via arch-specific pointers in platform_data
 - * or
 - * b) implemented as a proper omap_bus/omap_device in Linux, no more
 - *    platform_data func pointers
 + * In the medium- to long-term, this code should be implemented as a
 + * proper omap_bus/omap_device in Linux, no more platform_data func
 + * pointers
   *
   *
 - * Guidelines for usage by driver authors:
 - *
 - * 1. These functions are intended to be used by device drivers via
 - * function pointers in struct platform_data.  As an example,
 - * omap_device_enable() should be passed to the driver as
 - *
 - * struct foo_driver_platform_data {
 - * ...
 - *      int (*device_enable)(struct platform_device *pdev);
 - * ...
 - * }
 - *
 - * Note that the generic "device_enable" name is used, rather than
 - * "omap_device_enable".  This is so other architectures can pass in their
 - * own enable/disable functions here.
 - *
 - * This should be populated during device setup:
 - *
 - * ...
 - * pdata->device_enable = omap_device_enable;
 - * ...
 - *
 - * 2. Drivers should first check to ensure the function pointer is not null
 - * before calling it, as in:
 - *
 - * if (pdata->device_enable)
 - *     pdata->device_enable(pdev);
 - *
 - * This allows other architectures that don't use similar device_enable()/
 - * device_shutdown() functions to execute normally.
 - *
 - * ...
 - *
 - * Suggested usage by device drivers:
 - *
 - * During device initialization:
 - * device_enable()
 - *
 - * During device idle:
 - * (save remaining device context if necessary)
 - * device_idle();
 - *
 - * During device resume:
 - * device_enable();
 - * (restore context if necessary)
 - *
 - * During device shutdown:
 - * device_shutdown()
 - * (device must be reinitialized at this point to use it again)
 - *
   */
  #undef DEBUG
  
  #include <linux/kernel.h>
 -#include <linux/export.h>
  #include <linux/platform_device.h>
  #include <linux/slab.h>
  #include <linux/err.h>
  #include <linux/of.h>
  #include <linux/notifier.h>
  
 +#include "soc.h"
  #include "omap_device.h"
  #include "omap_hwmod.h"
  
 -/* These parameters are passed to _omap_device_{de,}activate() */
 -#define USE_WAKEUP_LAT                        0
 -#define IGNORE_WAKEUP_LAT             1
 -
 -static int omap_early_device_register(struct platform_device *pdev);
 -
 -static struct omap_device_pm_latency omap_default_latency[] = {
 -      {
 -              .deactivate_func = omap_device_idle_hwmods,
 -              .activate_func   = omap_device_enable_hwmods,
 -              .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 -      }
 -};
 -
  /* Private functions */
  
 -/**
 - * _omap_device_activate - increase device readiness
 - * @od: struct omap_device *
 - * @ignore_lat: increase to latency target (0) or full readiness (1)?
 - *
 - * Increase readiness of omap_device @od (thus decreasing device
 - * wakeup latency, but consuming more power).  If @ignore_lat is
 - * IGNORE_WAKEUP_LAT, make the omap_device fully active.  Otherwise,
 - * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
 - * latency is greater than the requested maximum wakeup latency, step
 - * backwards in the omap_device_pm_latency table to ensure the
 - * device's maximum wakeup latency is less than or equal to the
 - * requested maximum wakeup latency.  Returns 0.
 - */
 -static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
 -{
 -      struct timespec a, b, c;
 -
 -      dev_dbg(&od->pdev->dev, "omap_device: activating\n");
 -
 -      while (od->pm_lat_level > 0) {
 -              struct omap_device_pm_latency *odpl;
 -              unsigned long long act_lat = 0;
 -
 -              od->pm_lat_level--;
 -
 -              odpl = od->pm_lats + od->pm_lat_level;
 -
 -              if (!ignore_lat &&
 -                  (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit))
 -                      break;
 -
 -              read_persistent_clock(&a);
 -
 -              /* XXX check return code */
 -              odpl->activate_func(od);
 -
 -              read_persistent_clock(&b);
 -
 -              c = timespec_sub(b, a);
 -              act_lat = timespec_to_ns(&c);
 -
 -              dev_dbg(&od->pdev->dev,
 -                      "omap_device: pm_lat %d: activate: elapsed time %llu nsec\n",
 -                      od->pm_lat_level, act_lat);
 -
 -              if (act_lat > odpl->activate_lat) {
 -                      odpl->activate_lat_worst = act_lat;
 -                      if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 -                              odpl->activate_lat = act_lat;
 -                              dev_dbg(&od->pdev->dev,
 -                                      "new worst case activate latency %d: %llu\n",
 -                                      od->pm_lat_level, act_lat);
 -                      } else
 -                              dev_warn(&od->pdev->dev,
 -                                       "activate latency %d higher than expected. (%llu > %d)\n",
 -                                       od->pm_lat_level, act_lat,
 -                                       odpl->activate_lat);
 -              }
 -
 -              od->dev_wakeup_lat -= odpl->activate_lat;
 -      }
 -
 -      return 0;
 -}
 -
 -/**
 - * _omap_device_deactivate - decrease device readiness
 - * @od: struct omap_device *
 - * @ignore_lat: decrease to latency target (0) or full inactivity (1)?
 - *
 - * Decrease readiness of omap_device @od (thus increasing device
 - * wakeup latency, but conserving power).  If @ignore_lat is
 - * IGNORE_WAKEUP_LAT, make the omap_device fully inactive.  Otherwise,
 - * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
 - * latency is less than the requested maximum wakeup latency, step
 - * forwards in the omap_device_pm_latency table to ensure the device's
 - * maximum wakeup latency is less than or equal to the requested
 - * maximum wakeup latency.  Returns 0.
 - */
 -static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
 -{
 -      struct timespec a, b, c;
 -
 -      dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
 -
 -      while (od->pm_lat_level < od->pm_lats_cnt) {
 -              struct omap_device_pm_latency *odpl;
 -              unsigned long long deact_lat = 0;
 -
 -              odpl = od->pm_lats + od->pm_lat_level;
 -
 -              if (!ignore_lat &&
 -                  ((od->dev_wakeup_lat + odpl->activate_lat) >
 -                   od->_dev_wakeup_lat_limit))
 -                      break;
 -
 -              read_persistent_clock(&a);
 -
 -              /* XXX check return code */
 -              odpl->deactivate_func(od);
 -
 -              read_persistent_clock(&b);
 -
 -              c = timespec_sub(b, a);
 -              deact_lat = timespec_to_ns(&c);
 -
 -              dev_dbg(&od->pdev->dev,
 -                      "omap_device: pm_lat %d: deactivate: elapsed time %llu nsec\n",
 -                      od->pm_lat_level, deact_lat);
 -
 -              if (deact_lat > odpl->deactivate_lat) {
 -                      odpl->deactivate_lat_worst = deact_lat;
 -                      if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
 -                              odpl->deactivate_lat = deact_lat;
 -                              dev_dbg(&od->pdev->dev,
 -                                      "new worst case deactivate latency %d: %llu\n",
 -                                      od->pm_lat_level, deact_lat);
 -                      } else
 -                              dev_warn(&od->pdev->dev,
 -                                       "deactivate latency %d higher than expected. (%llu > %d)\n",
 -                                       od->pm_lat_level, deact_lat,
 -                                       odpl->deactivate_lat);
 -              }
 -
 -              od->dev_wakeup_lat += odpl->activate_lat;
 -
 -              od->pm_lat_level++;
 -      }
 -
 -      return 0;
 -}
 -
  static void _add_clkdev(struct omap_device *od, const char *clk_alias,
                       const char *clk_name)
  {
@@@ -116,6 -315,9 +116,6 @@@ static void _add_hwmod_clocks_clkdev(st
   * @oh: ptr to the single omap_hwmod that backs this omap_device
   * @pdata: platform_data ptr to associate with the platform_device
   * @pdata_len: amount of memory pointed to by @pdata
 - * @pm_lats: pointer to a omap_device_pm_latency array for this device
 - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
 - * @is_early_device: should the device be registered as an early device or not
   *
   * Function for building an omap_device already registered from device-tree
   *
@@@ -131,7 -333,7 +131,7 @@@ static int omap_device_build_from_dt(st
        int oh_cnt, i, ret = 0;
  
        oh_cnt = of_property_count_strings(node, "ti,hwmods");
-       if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+       if (oh_cnt <= 0) {
                dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
                return -ENODEV;
        }
                hwmods[i] = oh;
        }
  
 -      od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
 +      od = omap_device_alloc(pdev, hwmods, oh_cnt);
        if (!od) {
                dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
                        oh_name);
@@@ -205,39 -407,6 +205,39 @@@ static int _omap_device_notifier_call(s
        return NOTIFY_DONE;
  }
  
 +/**
 + * _omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
 + * @od: struct omap_device *od
 + *
 + * Enable all underlying hwmods.  Returns 0.
 + */
 +static int _omap_device_enable_hwmods(struct omap_device *od)
 +{
 +      int i;
 +
 +      for (i = 0; i < od->hwmods_cnt; i++)
 +              omap_hwmod_enable(od->hwmods[i]);
 +
 +      /* XXX pass along return value here? */
 +      return 0;
 +}
 +
 +/**
 + * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
 + * @od: struct omap_device *od
 + *
 + * Idle all underlying hwmods.  Returns 0.
 + */
 +static int _omap_device_idle_hwmods(struct omap_device *od)
 +{
 +      int i;
 +
 +      for (i = 0; i < od->hwmods_cnt; i++)
 +              omap_hwmod_idle(od->hwmods[i]);
 +
 +      /* XXX pass along return value here? */
 +      return 0;
 +}
  
  /* Public functions for use by core code */
  
@@@ -357,14 -526,18 +357,14 @@@ static int _od_fill_dma_resources(struc
   * @oh: ptr to the single omap_hwmod that backs this omap_device
   * @pdata: platform_data ptr to associate with the platform_device
   * @pdata_len: amount of memory pointed to by @pdata
 - * @pm_lats: pointer to a omap_device_pm_latency array for this device
 - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
   *
   * Convenience function for allocating an omap_device structure and filling
 - * hwmods, resources and pm_latency attributes.
 + * hwmods, and resources.
   *
   * Returns an struct omap_device pointer or ERR_PTR() on error;
   */
  struct omap_device *omap_device_alloc(struct platform_device *pdev,
 -                                      struct omap_hwmod **ohs, int oh_cnt,
 -                                      struct omap_device_pm_latency *pm_lats,
 -                                      int pm_lats_cnt)
 +                                      struct omap_hwmod **ohs, int oh_cnt)
  {
        int ret = -ENOMEM;
        struct omap_device *od;
                goto oda_exit3;
  
  have_everything:
 -      if (!pm_lats) {
 -              pm_lats = omap_default_latency;
 -              pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
 -      }
 -
 -      od->pm_lats_cnt = pm_lats_cnt;
 -      od->pm_lats = kmemdup(pm_lats,
 -                      sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
 -                      GFP_KERNEL);
 -      if (!od->pm_lats)
 -              goto oda_exit3;
 -
        pdev->archdata.od = od;
  
        for (i = 0; i < oh_cnt; i++) {
@@@ -478,6 -663,7 +478,6 @@@ void omap_device_delete(struct omap_dev
                return;
  
        od->pdev->archdata.od = NULL;
 -      kfree(od->pm_lats);
        kfree(od->hwmods);
        kfree(od);
  }
   * @oh: ptr to the single omap_hwmod that backs this omap_device
   * @pdata: platform_data ptr to associate with the platform_device
   * @pdata_len: amount of memory pointed to by @pdata
 - * @pm_lats: pointer to a omap_device_pm_latency array for this device
 - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
 - * @is_early_device: should the device be registered as an early device or not
   *
   * Convenience function for building and registering a single
   * omap_device record, which in turn builds and registers a
   * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
   * passes along the return value of omap_device_build_ss().
   */
 -struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id,
 -                                    struct omap_hwmod *oh, void *pdata,
 -                                    int pdata_len,
 -                                    struct omap_device_pm_latency *pm_lats,
 -                                    int pm_lats_cnt, int is_early_device)
 +struct platform_device __init *omap_device_build(const char *pdev_name,
 +                                               int pdev_id,
 +                                               struct omap_hwmod *oh,
 +                                               void *pdata, int pdata_len)
  {
        struct omap_hwmod *ohs[] = { oh };
  
                return ERR_PTR(-EINVAL);
  
        return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
 -                                  pdata_len, pm_lats, pm_lats_cnt,
 -                                  is_early_device);
 +                                  pdata_len);
  }
  
  /**
   * @oh: ptr to the single omap_hwmod that backs this omap_device
   * @pdata: platform_data ptr to associate with the platform_device
   * @pdata_len: amount of memory pointed to by @pdata
 - * @pm_lats: pointer to a omap_device_pm_latency array for this device
 - * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
 - * @is_early_device: should the device be registered as an early device or not
   *
   * Convenience function for building and registering an omap_device
   * subsystem record.  Subsystem records consist of multiple
   * platform_device record.  Returns an ERR_PTR() on error, or passes
   * along the return value of omap_device_register().
   */
 -struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id,
 -                                       struct omap_hwmod **ohs, int oh_cnt,
 -                                       void *pdata, int pdata_len,
 -                                       struct omap_device_pm_latency *pm_lats,
 -                                       int pm_lats_cnt, int is_early_device)
 +struct platform_device __init *omap_device_build_ss(const char *pdev_name,
 +                                                  int pdev_id,
 +                                                  struct omap_hwmod **ohs,
 +                                                  int oh_cnt, void *pdata,
 +                                                  int pdata_len)
  {
        int ret = -ENOMEM;
        struct platform_device *pdev;
        else
                dev_set_name(&pdev->dev, "%s", pdev->name);
  
 -      od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
 +      od = omap_device_alloc(pdev, ohs, oh_cnt);
        if (IS_ERR(od))
                goto odbs_exit1;
  
        if (ret)
                goto odbs_exit2;
  
 -      if (is_early_device)
 -              ret = omap_early_device_register(pdev);
 -      else
 -              ret = omap_device_register(pdev);
 +      ret = omap_device_register(pdev);
        if (ret)
                goto odbs_exit2;
  
@@@ -577,6 -774,24 +577,6 @@@ odbs_exit
        return ERR_PTR(ret);
  }
  
 -/**
 - * omap_early_device_register - register an omap_device as an early platform
 - * device.
 - * @od: struct omap_device * to register
 - *
 - * Register the omap_device structure.  This currently just calls
 - * platform_early_add_device() on the underlying platform_device.
 - * Returns 0 by default.
 - */
 -static int __init omap_early_device_register(struct platform_device *pdev)
 -{
 -      struct platform_device *devices[1];
 -
 -      devices[0] = pdev;
 -      early_platform_add_devices(devices, 1);
 -      return 0;
 -}
 -
  #ifdef CONFIG_PM_RUNTIME
  static int _od_runtime_suspend(struct device *dev)
  {
@@@ -687,9 -902,10 +687,9 @@@ int omap_device_register(struct platfor
   * to be accessible and ready to operate.  This generally involves
   * enabling clocks, setting SYSCONFIG registers; and in the future may
   * involve remuxing pins.  Device drivers should call this function
 - * (through platform_data function pointers) where they would normally
 - * enable clocks, etc.  Returns -EINVAL if called when the omap_device
 - * is already enabled, or passes along the return value of
 - * _omap_device_activate().
 + * indirectly via pm_runtime_get*().  Returns -EINVAL if called when
 + * the omap_device is already enabled, or passes along the return
 + * value of _omap_device_enable_hwmods().
   */
  int omap_device_enable(struct platform_device *pdev)
  {
                return -EINVAL;
        }
  
 -      /* Enable everything if we're enabling this device from scratch */
 -      if (od->_state == OMAP_DEVICE_STATE_UNKNOWN)
 -              od->pm_lat_level = od->pm_lats_cnt;
 +      ret = _omap_device_enable_hwmods(od);
  
 -      ret = _omap_device_activate(od, IGNORE_WAKEUP_LAT);
 -
 -      od->dev_wakeup_lat = 0;
 -      od->_dev_wakeup_lat_limit = UINT_MAX;
        od->_state = OMAP_DEVICE_STATE_ENABLED;
  
        return ret;
   * omap_device_idle - idle an omap_device
   * @od: struct omap_device * to idle
   *
 - * Idle omap_device @od by calling as many .deactivate_func() entries
 - * in the omap_device's pm_lats table as is possible without exceeding
 - * the device's maximum wakeup latency limit, pm_lat_limit.  Device
 - * drivers should call this function (through platform_data function
 - * pointers) where they would normally disable clocks after operations
 - * complete, etc..  Returns -EINVAL if the omap_device is not
 + * Idle omap_device @od.  Device drivers call this function indirectly
 + * via pm_runtime_put*().  Returns -EINVAL if the omap_device is not
   * currently enabled, or passes along the return value of
 - * _omap_device_deactivate().
 + * _omap_device_idle_hwmods().
   */
  int omap_device_idle(struct platform_device *pdev)
  {
                return -EINVAL;
        }
  
 -      ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
 +      ret = _omap_device_idle_hwmods(od);
  
        od->_state = OMAP_DEVICE_STATE_IDLE;
  
  }
  
  /**
 - * omap_device_shutdown - shut down an omap_device
 - * @od: struct omap_device * to shut down
 - *
 - * Shut down omap_device @od by calling all .deactivate_func() entries
 - * in the omap_device's pm_lats table and then shutting down all of
 - * the underlying omap_hwmods.  Used when a device is being "removed"
 - * or a device driver is being unloaded.  Returns -EINVAL if the
 - * omap_device is not currently enabled or idle, or passes along the
 - * return value of _omap_device_deactivate().
 - */
 -int omap_device_shutdown(struct platform_device *pdev)
 -{
 -      int ret, i;
 -      struct omap_device *od;
 -
 -      od = to_omap_device(pdev);
 -
 -      if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
 -          od->_state != OMAP_DEVICE_STATE_IDLE) {
 -              dev_warn(&pdev->dev,
 -                       "omap_device: %s() called from invalid state %d\n",
 -                       __func__, od->_state);
 -              return -EINVAL;
 -      }
 -
 -      ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
 -
 -      for (i = 0; i < od->hwmods_cnt; i++)
 -              omap_hwmod_shutdown(od->hwmods[i]);
 -
 -      od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
 -
 -      return ret;
 -}
 -
 -/**
   * omap_device_assert_hardreset - set a device's hardreset line
   * @pdev: struct platform_device * to reset
   * @name: const char * name of the reset line
@@@ -798,6 -1060,86 +798,6 @@@ int omap_device_deassert_hardreset(stru
  }
  
  /**
 - * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim
 - * @od: struct omap_device *
 - *
 - * When a device's maximum wakeup latency limit changes, call some of
 - * the .activate_func or .deactivate_func function pointers in the
 - * omap_device's pm_lats array to ensure that the device's maximum
 - * wakeup latency is less than or equal to the new latency limit.
 - * Intended to be called by OMAP PM code whenever a device's maximum
 - * wakeup latency limit changes (e.g., via
 - * omap_pm_set_dev_wakeup_lat()).  Returns 0 if nothing needs to be
 - * done (e.g., if the omap_device is not currently idle, or if the
 - * wakeup latency is already current with the new limit) or passes
 - * along the return value of _omap_device_deactivate() or
 - * _omap_device_activate().
 - */
 -int omap_device_align_pm_lat(struct platform_device *pdev,
 -                           u32 new_wakeup_lat_limit)
 -{
 -      int ret = -EINVAL;
 -      struct omap_device *od;
 -
 -      od = to_omap_device(pdev);
 -
 -      if (new_wakeup_lat_limit == od->dev_wakeup_lat)
 -              return 0;
 -
 -      od->_dev_wakeup_lat_limit = new_wakeup_lat_limit;
 -
 -      if (od->_state != OMAP_DEVICE_STATE_IDLE)
 -              return 0;
 -      else if (new_wakeup_lat_limit > od->dev_wakeup_lat)
 -              ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
 -      else if (new_wakeup_lat_limit < od->dev_wakeup_lat)
 -              ret = _omap_device_activate(od, USE_WAKEUP_LAT);
 -
 -      return ret;
 -}
 -
 -/**
 - * omap_device_get_pwrdm - return the powerdomain * associated with @od
 - * @od: struct omap_device *
 - *
 - * Return the powerdomain associated with the first underlying
 - * omap_hwmod for this omap_device.  Intended for use by core OMAP PM
 - * code.  Returns NULL on error or a struct powerdomain * upon
 - * success.
 - */
 -struct powerdomain *omap_device_get_pwrdm(struct omap_device *od)
 -{
 -      /*
 -       * XXX Assumes that all omap_hwmod powerdomains are identical.
 -       * This may not necessarily be true.  There should be a sanity
 -       * check in here to WARN() if any difference appears.
 -       */
 -      if (!od->hwmods_cnt)
 -              return NULL;
 -
 -      return omap_hwmod_get_pwrdm(od->hwmods[0]);
 -}
 -
 -/**
 - * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base
 - * @od: struct omap_device *
 - *
 - * Return the MPU's virtual address for the base of the hwmod, from
 - * the ioremap() that the hwmod code does.  Only valid if there is one
 - * hwmod associated with this device.  Returns NULL if there are zero
 - * or more than one hwmods associated with this omap_device;
 - * otherwise, passes along the return value from
 - * omap_hwmod_get_mpu_rt_va().
 - */
 -void __iomem *omap_device_get_rt_va(struct omap_device *od)
 -{
 -      if (od->hwmods_cnt != 1)
 -              return NULL;
 -
 -      return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
 -}
 -
 -/**
   * omap_device_get_by_hwmod_name() - convert a hwmod name to
   * device pointer.
   * @oh_name: name of the hwmod device
@@@ -815,22 -1157,95 +815,19 @@@ struct device *omap_device_get_by_hwmod
        }
  
        oh = omap_hwmod_lookup(oh_name);
-       if (IS_ERR_OR_NULL(oh)) {
+       if (!oh) {
                WARN(1, "%s: no hwmod for %s\n", __func__,
                        oh_name);
-               return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
 -              return -ENODEV;
++              return ERR_PTR(-ENODEV);
        }
-       if (IS_ERR_OR_NULL(oh->od)) {
+       if (!oh->od) {
                WARN(1, "%s: no omap_device for %s\n", __func__,
                        oh_name);
-               return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
 -              return -ENODEV;
++              return ERR_PTR(-ENODEV);
        }
  
-       if (IS_ERR_OR_NULL(oh->od->pdev))
-               return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
        return &oh->od->pdev->dev;
  }
 -EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
 -
 -/*
 - * Public functions intended for use in omap_device_pm_latency
 - * .activate_func and .deactivate_func function pointers
 - */
 -
 -/**
 - * omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
 - * @od: struct omap_device *od
 - *
 - * Enable all underlying hwmods.  Returns 0.
 - */
 -int omap_device_enable_hwmods(struct omap_device *od)
 -{
 -      int i;
 -
 -      for (i = 0; i < od->hwmods_cnt; i++)
 -              omap_hwmod_enable(od->hwmods[i]);
 -
 -      /* XXX pass along return value here? */
 -      return 0;
 -}
 -
 -/**
 - * omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
 - * @od: struct omap_device *od
 - *
 - * Idle all underlying hwmods.  Returns 0.
 - */
 -int omap_device_idle_hwmods(struct omap_device *od)
 -{
 -      int i;
 -
 -      for (i = 0; i < od->hwmods_cnt; i++)
 -              omap_hwmod_idle(od->hwmods[i]);
 -
 -      /* XXX pass along return value here? */
 -      return 0;
 -}
 -
 -/**
 - * omap_device_disable_clocks - disable all main and interface clocks
 - * @od: struct omap_device *od
 - *
 - * Disable the main functional clock and interface clock for all of the
 - * omap_hwmods associated with the omap_device.  Returns 0.
 - */
 -int omap_device_disable_clocks(struct omap_device *od)
 -{
 -      int i;
 -
 -      for (i = 0; i < od->hwmods_cnt; i++)
 -              omap_hwmod_disable_clocks(od->hwmods[i]);
 -
 -      /* XXX pass along return value here? */
 -      return 0;
 -}
 -
 -/**
 - * omap_device_enable_clocks - enable all main and interface clocks
 - * @od: struct omap_device *od
 - *
 - * Enable the main functional clock and interface clock for all of the
 - * omap_hwmods associated with the omap_device.  Returns 0.
 - */
 -int omap_device_enable_clocks(struct omap_device *od)
 -{
 -      int i;
 -
 -      for (i = 0; i < od->hwmods_cnt; i++)
 -              omap_hwmod_enable_clocks(od->hwmods[i]);
 -
 -      /* XXX pass along return value here? */
 -      return 0;
 -}
  
  static struct notifier_block platform_nb = {
        .notifier_call = _omap_device_notifier_call,
@@@ -841,7 -1256,7 +838,7 @@@ static int __init omap_device_init(void
        bus_register_notifier(&platform_bus_type, &platform_nb);
        return 0;
  }
 -core_initcall(omap_device_init);
 +omap_core_initcall(omap_device_init);
  
  /**
   * omap_device_late_idle - idle devices without drivers
@@@ -879,4 -1294,4 +876,4 @@@ static int __init omap_device_late_init
        bus_for_each_dev(&platform_bus_type, NULL, NULL, omap_device_late_idle);
        return 0;
  }
 -late_initcall(omap_device_late_init);
 +omap_late_initcall(omap_device_late_init);
  #include <linux/slab.h>
  #include <linux/bootmem.h>
  
 +#include <asm/system_misc.h>
 +
  #include "clock.h"
  #include "omap_hwmod.h"
  
@@@ -610,6 -608,8 +610,6 @@@ static int _enable_wakeup(struct omap_h
  
        /* XXX test pwrdm_get_wken for this hwmod's subsystem */
  
 -      oh->_int_flags |= _HWMOD_WAKEUP_ENABLED;
 -
        return 0;
  }
  
@@@ -643,6 -643,8 +643,6 @@@ static int _disable_wakeup(struct omap_
  
        /* XXX test pwrdm_get_wken for this hwmod's subsystem */
  
 -      oh->_int_flags &= ~_HWMOD_WAKEUP_ENABLED;
 -
        return 0;
  }
  
@@@ -1659,7 -1661,7 +1659,7 @@@ static int _deassert_hardreset(struct o
                return -ENOSYS;
  
        ret = _lookup_hardreset(oh, name, &ohri);
-       if (IS_ERR_VALUE(ret))
+       if (ret < 0)
                return ret;
  
        if (oh->clkdm) {
@@@ -2051,23 -2053,6 +2051,23 @@@ static int _omap4_get_context_lost(stru
  }
  
  /**
 + * _enable_preprogram - Pre-program an IP block during the _enable() process
 + * @oh: struct omap_hwmod *
 + *
 + * Some IP blocks (such as AESS) require some additional programming
 + * after enable before they can enter idle.  If a function pointer to
 + * do so is present in the hwmod data, then call it and pass along the
 + * return value; otherwise, return 0.
 + */
 +static int __init _enable_preprogram(struct omap_hwmod *oh)
 +{
 +      if (!oh->class->enable_preprogram)
 +              return 0;
 +
 +      return oh->class->enable_preprogram(oh);
 +}
 +
 +/**
   * _enable - enable an omap_hwmod
   * @oh: struct omap_hwmod *
   *
@@@ -2149,8 -2134,6 +2149,8 @@@ static int _enable(struct omap_hwmod *o
        _enable_clocks(oh);
        if (soc_ops.enable_module)
                soc_ops.enable_module(oh);
 +      if (oh->flags & HWMOD_BLOCK_WFI)
 +              disable_hlt();
  
        if (soc_ops.update_context_lost)
                soc_ops.update_context_lost(oh);
                                _update_sysc_cache(oh);
                        _enable_sysc(oh);
                }
 +              r = _enable_preprogram(oh);
        } else {
                if (soc_ops.disable_module)
                        soc_ops.disable_module(oh);
@@@ -2213,8 -2195,6 +2213,8 @@@ static int _idle(struct omap_hwmod *oh
                _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
  
 +      if (oh->flags & HWMOD_BLOCK_WFI)
 +              enable_hlt();
        if (soc_ops.disable_module)
                soc_ops.disable_module(oh);
  
@@@ -2323,8 -2303,6 +2323,8 @@@ static int _shutdown(struct omap_hwmod 
        if (oh->_state == _HWMOD_STATE_ENABLED) {
                _del_initiator_dep(oh, mpu_oh);
                /* XXX what about the other system initiators here? dma, dsp */
 +              if (oh->flags & HWMOD_BLOCK_WFI)
 +                      enable_hlt();
                if (soc_ops.disable_module)
                        soc_ops.disable_module(oh);
                _disable_clocks(oh);
@@@ -2409,7 -2387,7 +2409,7 @@@ static int __init _init(struct omap_hwm
        _init_mpu_rt_base(oh, NULL);
  
        r = _init_clocks(oh, NULL);
-       if (IS_ERR_VALUE(r)) {
+       if (r < 0) {
                WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name);
                return -EINVAL;
        }
@@@ -3063,8 -3041,11 +3063,8 @@@ static int _am33xx_assert_hardreset(str
  static int _am33xx_deassert_hardreset(struct omap_hwmod *oh,
                                     struct omap_hwmod_rst_info *ohri)
  {
 -      if (ohri->st_shift)
 -              pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
 -                     oh->name, ohri->name);
 -
        return am33xx_prm_deassert_hardreset(ohri->rst_shift,
 +                              ohri->st_shift,
                                oh->clkdm->pwrdm.ptr->prcm_offs,
                                oh->prcm.omap4.rstctrl_offs,
                                oh->prcm.omap4.rstst_offs);
@@@ -3322,7 -3303,7 +3322,7 @@@ static int __init omap_hwmod_setup_all(
  
        return 0;
  }
 -core_initcall(omap_hwmod_setup_all);
 +omap_core_initcall(omap_hwmod_setup_all);
  
  /**
   * omap_hwmod_enable - enable an omap_hwmod
@@@ -83,8 -83,10 +83,8 @@@ static int clkdm_dbg_show_counter(struc
                strncmp(clkdm->name, "dpll", 4) == 0)
                return 0;
  
 -      seq_printf(s, "%s->%s (%d)", clkdm->name,
 -                      clkdm->pwrdm.ptr->name,
 -                      atomic_read(&clkdm->usecount));
 -      seq_printf(s, "\n");
 +      seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
 +                 clkdm->usecount);
  
        return 0;
  }
@@@ -217,7 -219,7 +217,7 @@@ static int __init pwrdms_setup(struct p
                return 0;
  
        d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
-       if (!(IS_ERR_OR_NULL(d)))
+       if (d)
                (void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d,
                        (void *)pwrdm, &pwrdm_suspend_fops);
  
@@@ -261,8 -263,8 +261,8 @@@ static int __init pm_dbg_init(void
                return 0;
  
        d = debugfs_create_dir("pm_debug", NULL);
-       if (IS_ERR_OR_NULL(d))
-               return PTR_ERR(d);
+       if (!d)
+               return -EINVAL;
  
        (void) debugfs_create_file("count", S_IRUGO,
                d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
  
        return 0;
  }
 -arch_initcall(pm_dbg_init);
 +omap_arch_initcall(pm_dbg_init);
  
  #endif
@@@ -19,7 -19,6 +19,7 @@@
  #include <linux/list.h>
  #include <linux/errno.h>
  #include <linux/string.h>
 +#include <linux/spinlock.h>
  #include <trace/events/power.h>
  
  #include "cm2xxx_3xxx.h"
@@@ -43,15 -42,6 +43,15 @@@ enum 
        PWRDM_STATE_PREV,
  };
  
 +/*
 + * Types of sleep_switch used internally in omap_set_pwrdm_state()
 + * and its associated static functions
 + *
 + * XXX Better documentation is needed here
 + */
 +#define ALREADYACTIVE_SWITCH          0
 +#define FORCEWAKEUP_SWITCH            1
 +#define LOWPOWERSTATE_SWITCH          2
  
  /* pwrdm_list contains all registered struct powerdomains */
  static LIST_HEAD(pwrdm_list);
@@@ -111,7 -101,6 +111,7 @@@ static int _pwrdm_register(struct power
        pwrdm->voltdm.ptr = voltdm;
        INIT_LIST_HEAD(&pwrdm->voltdm_node);
        voltdm_add_pwrdm(voltdm, pwrdm);
 +      spin_lock_init(&pwrdm->_lock);
  
        list_add(&pwrdm->node, &pwrdm_list);
  
        for (i = 0; i < pwrdm->banks; i++)
                pwrdm->ret_mem_off_counter[i] = 0;
  
 -      pwrdm_wait_transition(pwrdm);
 +      arch_pwrdm->pwrdm_wait_transition(pwrdm);
        pwrdm->state = pwrdm_read_pwrst(pwrdm);
        pwrdm->state_counter[pwrdm->state] = 1;
  
@@@ -154,7 -143,7 +154,7 @@@ static void _update_logic_membank_count
  static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
  {
  
 -      int prev, state, trace_state = 0;
 +      int prev, next, state, trace_state = 0;
  
        if (pwrdm == NULL)
                return -EINVAL;
                 * If the power domain did not hit the desired state,
                 * generate a trace event with both the desired and hit states
                 */
 -              if (state != prev) {
 +              next = pwrdm_read_next_pwrst(pwrdm);
 +              if (next != prev) {
                        trace_state = (PWRDM_TRACE_STATES_FLAG |
 -                                     ((state & OMAP_POWERSTATE_MASK) << 8) |
 +                                     ((next & OMAP_POWERSTATE_MASK) << 8) |
                                       ((prev & OMAP_POWERSTATE_MASK) << 0));
                        trace_power_domain_target(pwrdm->name, trace_state,
                                                  smp_processor_id());
@@@ -211,77 -199,6 +211,77 @@@ static int _pwrdm_post_transition_cb(st
        return 0;
  }
  
 +/**
 + * _pwrdm_save_clkdm_state_and_activate - prepare for power state change
 + * @pwrdm: struct powerdomain * to operate on
 + * @curr_pwrst: current power state of @pwrdm
 + * @pwrst: power state to switch to
 + * @hwsup: ptr to a bool to return whether the clkdm is hardware-supervised
 + *
 + * Determine whether the powerdomain needs to be turned on before
 + * attempting to switch power states.  Called by
 + * omap_set_pwrdm_state().  NOTE that if the powerdomain contains
 + * multiple clockdomains, this code assumes that the first clockdomain
 + * supports software-supervised wakeup mode - potentially a problem.
 + * Returns the power state switch mode currently in use (see the
 + * "Types of sleep_switch" comment above).
 + */
 +static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
 +                                             u8 curr_pwrst, u8 pwrst,
 +                                             bool *hwsup)
 +{
 +      u8 sleep_switch;
 +
 +      if (curr_pwrst < PWRDM_POWER_ON) {
 +              if (curr_pwrst > pwrst &&
 +                  pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
 +                  arch_pwrdm->pwrdm_set_lowpwrstchange) {
 +                      sleep_switch = LOWPOWERSTATE_SWITCH;
 +              } else {
 +                      *hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
 +                      clkdm_wakeup_nolock(pwrdm->pwrdm_clkdms[0]);
 +                      sleep_switch = FORCEWAKEUP_SWITCH;
 +              }
 +      } else {
 +              sleep_switch = ALREADYACTIVE_SWITCH;
 +      }
 +
 +      return sleep_switch;
 +}
 +
 +/**
 + * _pwrdm_restore_clkdm_state - restore the clkdm hwsup state after pwrst change
 + * @pwrdm: struct powerdomain * to operate on
 + * @sleep_switch: return value from _pwrdm_save_clkdm_state_and_activate()
 + * @hwsup: should @pwrdm's first clockdomain be set to hardware-supervised mode?
 + *
 + * Restore the clockdomain state perturbed by
 + * _pwrdm_save_clkdm_state_and_activate(), and call the power state
 + * bookkeeping code.  Called by omap_set_pwrdm_state().  NOTE that if
 + * the powerdomain contains multiple clockdomains, this assumes that
 + * the first associated clockdomain supports either
 + * hardware-supervised idle control in the register, or
 + * software-supervised sleep.  No return value.
 + */
 +static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
 +                                     u8 sleep_switch, bool hwsup)
 +{
 +      switch (sleep_switch) {
 +      case FORCEWAKEUP_SWITCH:
 +              if (hwsup)
 +                      clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]);
 +              else
 +                      clkdm_sleep_nolock(pwrdm->pwrdm_clkdms[0]);
 +              break;
 +      case LOWPOWERSTATE_SWITCH:
 +              if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
 +                  arch_pwrdm->pwrdm_set_lowpwrstchange)
 +                      arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
 +              pwrdm_state_switch_nolock(pwrdm);
 +              break;
 +      }
 +}
 +
  /* Public functions */
  
  /**
@@@ -358,30 -275,6 +358,30 @@@ int pwrdm_complete_init(void
  }
  
  /**
 + * pwrdm_lock - acquire a Linux spinlock on a powerdomain
 + * @pwrdm: struct powerdomain * to lock
 + *
 + * Acquire the powerdomain spinlock on @pwrdm.  No return value.
 + */
 +void pwrdm_lock(struct powerdomain *pwrdm)
 +      __acquires(&pwrdm->_lock)
 +{
 +      spin_lock_irqsave(&pwrdm->_lock, pwrdm->_lock_flags);
 +}
 +
 +/**
 + * pwrdm_unlock - release a Linux spinlock on a powerdomain
 + * @pwrdm: struct powerdomain * to unlock
 + *
 + * Release the powerdomain spinlock on @pwrdm.  No return value.
 + */
 +void pwrdm_unlock(struct powerdomain *pwrdm)
 +      __releases(&pwrdm->_lock)
 +{
 +      spin_unlock_irqrestore(&pwrdm->_lock, pwrdm->_lock_flags);
 +}
 +
 +/**
   * pwrdm_lookup - look up a powerdomain by name, return a pointer
   * @name: name of powerdomain
   *
@@@ -1027,27 -920,65 +1027,27 @@@ bool pwrdm_has_hdwr_sar(struct powerdom
        return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
  }
  
 -/**
 - * pwrdm_set_lowpwrstchange - Request a low power state change
 - * @pwrdm: struct powerdomain *
 - *
 - * Allows a powerdomain to transtion to a lower power sleep state
 - * from an existing sleep state without waking up the powerdomain.
 - * Returns -EINVAL if the powerdomain pointer is null or if the
 - * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0
 - * upon success.
 - */
 -int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
 -{
 -      int ret = -EINVAL;
 -
 -      if (!pwrdm)
 -              return -EINVAL;
 -
 -      if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE))
 -              return -EINVAL;
 -
 -      pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
 -               pwrdm->name);
 -
 -      if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange)
 -              ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
 -
 -      return ret;
 -}
 -
 -/**
 - * pwrdm_wait_transition - wait for powerdomain power transition to finish
 - * @pwrdm: struct powerdomain * to wait for
 - *
 - * If the powerdomain @pwrdm is in the process of a state transition,
 - * spin until it completes the power transition, or until an iteration
 - * bailout value is reached. Returns -EINVAL if the powerdomain
 - * pointer is null, -EAGAIN if the bailout value was reached, or
 - * returns 0 upon success.
 - */
 -int pwrdm_wait_transition(struct powerdomain *pwrdm)
 +int pwrdm_state_switch_nolock(struct powerdomain *pwrdm)
  {
 -      int ret = -EINVAL;
 +      int ret;
  
 -      if (!pwrdm)
 +      if (!pwrdm || !arch_pwrdm)
                return -EINVAL;
  
 -      if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
 -              ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
 +      ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
 +      if (!ret)
 +              ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
  
        return ret;
  }
  
 -int pwrdm_state_switch(struct powerdomain *pwrdm)
 +int __deprecated pwrdm_state_switch(struct powerdomain *pwrdm)
  {
        int ret;
  
 -      ret = pwrdm_wait_transition(pwrdm);
 -      if (!ret)
 -              ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
 +      pwrdm_lock(pwrdm);
 +      ret = pwrdm_state_switch_nolock(pwrdm);
 +      pwrdm_unlock(pwrdm);
  
        return ret;
  }
@@@ -1073,63 -1004,6 +1073,63 @@@ int pwrdm_post_transition(struct powerd
  }
  
  /**
 + * omap_set_pwrdm_state - change a powerdomain's current power state
 + * @pwrdm: struct powerdomain * to change the power state of
 + * @pwrst: power state to change to
 + *
 + * Change the current hardware power state of the powerdomain
 + * represented by @pwrdm to the power state represented by @pwrst.
 + * Returns -EINVAL if @pwrdm is null or invalid or if the
 + * powerdomain's current power state could not be read, or returns 0
 + * upon success or if @pwrdm does not support @pwrst or any
 + * lower-power state.  XXX Should not return 0 if the @pwrdm does not
 + * support @pwrst or any lower-power state: this should be an error.
 + */
 +int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
 +{
 +      u8 next_pwrst, sleep_switch;
 +      int curr_pwrst;
 +      int ret = 0;
 +      bool hwsup = false;
 +
 +      if (!pwrdm || IS_ERR(pwrdm))
 +              return -EINVAL;
 +
 +      while (!(pwrdm->pwrsts & (1 << pwrst))) {
 +              if (pwrst == PWRDM_POWER_OFF)
 +                      return ret;
 +              pwrst--;
 +      }
 +
 +      pwrdm_lock(pwrdm);
 +
 +      curr_pwrst = pwrdm_read_pwrst(pwrdm);
 +      if (curr_pwrst < 0) {
 +              ret = -EINVAL;
 +              goto osps_out;
 +      }
 +
 +      next_pwrst = pwrdm_read_next_pwrst(pwrdm);
 +      if (curr_pwrst == pwrst && next_pwrst == pwrst)
 +              goto osps_out;
 +
 +      sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, curr_pwrst,
 +                                                          pwrst, &hwsup);
 +
 +      ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
 +      if (ret)
 +              pr_err("%s: unable to set power state of powerdomain: %s\n",
 +                     __func__, pwrdm->name);
 +
 +      _pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
 +
 +osps_out:
 +      pwrdm_unlock(pwrdm);
 +
 +      return ret;
 +}
 +
 +/**
   * pwrdm_get_context_loss_count - get powerdomain's context loss count
   * @pwrdm: struct powerdomain * to wait for
   *
@@@ -1180,7 -1054,7 +1180,7 @@@ bool pwrdm_can_ever_lose_context(struc
  {
        int i;
  
-       if (IS_ERR_OR_NULL(pwrdm)) {
+       if (!pwrdm) {
                pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
                         __func__);
                return 1;
@@@ -62,7 -62,6 +62,7 @@@
  #define OMAP2_MPU_SOURCE      "sys_ck"
  #define OMAP3_MPU_SOURCE      OMAP2_MPU_SOURCE
  #define OMAP4_MPU_SOURCE      "sys_clkin_ck"
 +#define OMAP5_MPU_SOURCE      "sys_clkin"
  #define OMAP2_32K_SOURCE      "func_32k_ck"
  #define OMAP3_32K_SOURCE      "omap_32k_fck"
  #define OMAP4_32K_SOURCE      "sys_32k_ck"
@@@ -132,6 -131,7 +132,6 @@@ static void omap2_gp_timer_set_mode(enu
  static struct clock_event_device clockevent_gpt = {
        .name           = "gp_timer",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 -      .shift          = 32,
        .rating         = 300,
        .set_next_event = omap2_gp_timer_set_next_event,
        .set_mode       = omap2_gp_timer_set_mode,
@@@ -228,7 -228,7 +228,7 @@@ static int __init omap_dm_timer_init_on
        int r = 0;
  
        if (of_have_populated_dt()) {
 -              np = omap_get_timer_dt(omap_timer_match, NULL);
 +              np = omap_get_timer_dt(omap_timer_match, property);
                if (!np)
                        return -ENODEV;
  
                        r = -EINVAL;
                } else {
                        r = clk_set_parent(timer->fclk, src);
-                       if (IS_ERR_VALUE(r))
+                       if (r < 0)
                                pr_warn("%s: %s cannot set source\n",
                                        __func__, oh->name);
                        clk_put(src);
@@@ -336,11 -336,17 +336,11 @@@ static void __init omap2_gp_clockevent_
  
        __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW);
  
 -      clockevent_gpt.mult = div_sc(clkev.rate, NSEC_PER_SEC,
 -                                   clockevent_gpt.shift);
 -      clockevent_gpt.max_delta_ns =
 -              clockevent_delta2ns(0xffffffff, &clockevent_gpt);
 -      clockevent_gpt.min_delta_ns =
 -              clockevent_delta2ns(3, &clockevent_gpt);
 -              /* Timer internal resynch latency. */
 -
        clockevent_gpt.cpumask = cpu_possible_mask;
        clockevent_gpt.irq = omap_dm_timer_get_irq(&clkev);
 -      clockevents_register_device(&clockevent_gpt);
 +      clockevents_config_and_register(&clockevent_gpt, clkev.rate,
 +                                      3, /* Timer internal resynch latency */
 +                                      0xffffffff);
  
        pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
                gptimer_id, clkev.rate);
@@@ -488,7 -494,7 +488,7 @@@ static void __init realtime_counter_ini
                pr_err("%s: ioremap failed\n", __func__);
                return;
        }
 -      sys_clk = clk_get(NULL, "sys_clkin_ck");
 +      sys_clk = clk_get(NULL, OMAP5_MPU_SOURCE);
        if (IS_ERR(sys_clk)) {
                pr_err("%s: failed to get system clock handle\n", __func__);
                iounmap(base);
@@@ -546,7 -552,7 +546,7 @@@ static inline void __init realtime_coun
  
  #define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
                               clksrc_nr, clksrc_src)                   \
 -static void __init omap##name##_gptimer_timer_init(void)              \
 +void __init omap##name##_gptimer_timer_init(void)                     \
  {                                                                     \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
  
  #define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop,        \
                                clksrc_nr, clksrc_src)                  \
 -static void __init omap##name##_sync32k_timer_init(void)              \
 +void __init omap##name##_sync32k_timer_init(void)             \
  {                                                                     \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
                omap2_sync32k_clocksource_init();                       \
  }
  
 -#define OMAP_SYS_TIMER(name, clksrc)                                  \
 -struct sys_timer omap##name##_timer = {                                       \
 -      .init   = omap##name##_##clksrc##_timer_init,                   \
 -};
 -
  #ifdef CONFIG_ARCH_OMAP2
  OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon",
                        2, OMAP2_MPU_SOURCE);
 -OMAP_SYS_TIMER(2, sync32k);
  #endif /* CONFIG_ARCH_OMAP2 */
  
  #ifdef CONFIG_ARCH_OMAP3
  OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon",
                        2, OMAP3_MPU_SOURCE);
 -OMAP_SYS_TIMER(3, sync32k);
  OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure",
                        2, OMAP3_MPU_SOURCE);
 -OMAP_SYS_TIMER(3_secure, sync32k);
  OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon",
                       2, OMAP3_MPU_SOURCE);
 -OMAP_SYS_TIMER(3_gp, gptimer);
  #endif /* CONFIG_ARCH_OMAP3 */
  
  #ifdef CONFIG_SOC_AM33XX
  OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon",
                       2, OMAP4_MPU_SOURCE);
 -OMAP_SYS_TIMER(3_am33xx, gptimer);
  #endif /* CONFIG_SOC_AM33XX */
  
  #ifdef CONFIG_ARCH_OMAP4
@@@ -590,7 -606,7 +590,7 @@@ OMAP_SYS_32K_TIMER_INIT(4, 1, OMAP4_32K
                        2, OMAP4_MPU_SOURCE);
  #ifdef CONFIG_LOCAL_TIMERS
  static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
 -static void __init omap4_local_timer_init(void)
 +void __init omap4_local_timer_init(void)
  {
        omap4_sync32k_timer_init();
        /* Local timers are not supprted on OMAP4430 ES1.0 */
        }
  }
  #else /* CONFIG_LOCAL_TIMERS */
 -static void __init omap4_local_timer_init(void)
 +void __init omap4_local_timer_init(void)
  {
        omap4_sync32k_timer_init();
  }
  #endif /* CONFIG_LOCAL_TIMERS */
 -OMAP_SYS_TIMER(4, local);
  #endif /* CONFIG_ARCH_OMAP4 */
  
  #ifdef CONFIG_SOC_OMAP5
  OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
 -                      2, OMAP4_MPU_SOURCE);
 -static void __init omap5_realtime_timer_init(void)
 +                      2, OMAP5_MPU_SOURCE);
 +void __init omap5_realtime_timer_init(void)
  {
        int err;
  
        if (err)
                pr_err("%s: arch_timer_register failed %d\n", __func__, err);
  }
 -OMAP_SYS_TIMER(5, realtime);
  #endif /* CONFIG_SOC_OMAP5 */
  
  /**
@@@ -684,7 -702,8 +684,7 @@@ static int __init omap_timer_init(struc
        pdata->timer_errata = omap_dm_timer_get_errata();
        pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
  
 -      pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
 -                               NULL, 0, 0);
 +      pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata));
  
        if (IS_ERR(pdev)) {
                pr_err("%s: Can't build omap_device for %s: %s.\n",
@@@ -719,7 -738,7 +719,7 @@@ static int __init omap2_dm_timer_init(v
  
        return 0;
  }
 -arch_initcall(omap2_dm_timer_init);
 +omap_arch_initcall(omap2_dm_timer_init);
  
  /**
   * omap2_override_clocksource - clocksource override with user configuration
@@@ -276,7 -276,7 +276,7 @@@ static struct tegra_emc_pdata *tegra_em
        int i;
  
        WARN_ON(pdev->dev.platform_data);
-       BUG_ON(IS_ERR_OR_NULL(c));
+       BUG_ON(IS_ERR(c));
  
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        pdata->tables = devm_kzalloc(&pdev->dev, sizeof(*pdata->tables),
@@@ -312,9 -312,11 +312,9 @@@ static int tegra_emc_probe(struct platf
                return -ENOMEM;
        }
  
 -      emc_regbase = devm_request_and_ioremap(&pdev->dev, res);
 -      if (!emc_regbase) {
 -              dev_err(&pdev->dev, "failed to remap registers\n");
 -              return -ENOMEM;
 -      }
 +      emc_regbase = devm_ioremap_resource(&pdev->dev, res);
 +      if (IS_ERR(emc_regbase))
 +              return PTR_ERR(emc_regbase);
  
        pdata = pdev->dev.platform_data;
  
  #include <linux/of.h>
  #include <linux/of_irq.h>
  #include <linux/irq.h>
 +#include <linux/irqchip.h>
 +#include <linux/irqchip/arm-gic.h>
  #include <linux/platform_data/clk-ux500.h>
  
 -#include <asm/hardware/gic.h>
  #include <asm/mach/map.h>
  
  #include <mach/hardware.h>
@@@ -28,7 -27,6 +28,7 @@@
  #include <mach/devices.h>
  
  #include "board-mop500.h"
 +#include "id.h"
  
  void __iomem *_PRCMU_BASE;
  
   * This feels fragile because it depends on the gpio device getting probed
   * _before_ any device uses the gpio interrupts.
  */
 -static const struct of_device_id ux500_dt_irq_match[] = {
 -      { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
 -      {},
 -};
 -
  void __init ux500_init_irq(void)
  {
        void __iomem *dist_base;
@@@ -59,7 -62,7 +59,7 @@@
  
  #ifdef CONFIG_OF
        if (of_have_populated_dt())
 -              of_irq_init(ux500_dt_irq_match);
 +              irqchip_init();
        else
  #endif
                gic_init(0, 29, dist_base, cpu_base);
         * Init clocks here so that they are available for system timer
         * initialization.
         */
 -      if (cpu_is_u8500_family())
 +      if (cpu_is_u8500_family() || cpu_is_u9540())
                db8500_prcmu_early_init();
  
 -      if (cpu_is_u8500_family())
 +      if (cpu_is_u8500_family() || cpu_is_u9540())
                u8500_clk_init();
 -      else if (cpu_is_u9540())
 -              u9540_clk_init();
        else if (cpu_is_u8540())
                u8540_clk_init();
  }
@@@ -140,14 -145,13 +140,13 @@@ struct device * __init ux500_soc_device
        soc_info_populate(soc_dev_attr, soc_id);
  
        soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR_OR_NULL(soc_dev)) {
+       if (IS_ERR(soc_dev)) {
                kfree(soc_dev_attr);
                return NULL;
        }
  
        parent = soc_device_to_device(soc_dev);
-       if (!IS_ERR_OR_NULL(parent))
-               device_create_file(parent, &ux500_soc_attr);
+       device_create_file(parent, &ux500_soc_attr);
  
        return parent;
  }
@@@ -140,8 -140,7 +140,7 @@@ static int omap_dm_timer_prepare(struc
         */
        if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
                timer->fclk = clk_get(&timer->pdev->dev, "fck");
-               if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
-                       timer->fclk = NULL;
+               if (WARN_ON_ONCE(IS_ERR(timer->fclk))) {
                        dev_err(&timer->pdev->dev, ": No fclk handle.\n");
                        return -EINVAL;
                }
@@@ -373,7 -372,7 +372,7 @@@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_
  
  struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
  {
-       if (timer)
+       if (timer && !IS_ERR(timer->fclk))
                return timer->fclk;
        return NULL;
  }
@@@ -482,7 -481,7 +481,7 @@@ int omap_dm_timer_set_source(struct oma
        if (pdata && pdata->set_timer_src)
                return pdata->set_timer_src(timer->pdev, source);
  
-       if (!timer->fclk)
+       if (IS_ERR(timer->fclk))
                return -EINVAL;
  
        switch (source) {
        }
  
        parent = clk_get(&timer->pdev->dev, parent_name);
-       if (IS_ERR_OR_NULL(parent)) {
+       if (IS_ERR(parent)) {
                pr_err("%s: %s not found\n", __func__, parent_name);
                return -EINVAL;
        }
  
        ret = clk_set_parent(timer->fclk, parent);
-       if (IS_ERR_VALUE(ret))
+       if (ret < 0)
                pr_err("%s: failed to set %s as parent\n", __func__,
                        parent_name);
  
@@@ -808,9 -807,12 +807,10 @@@ static int omap_dm_timer_probe(struct p
                return  -ENOMEM;
        }
  
 -      timer->io_base = devm_request_and_ioremap(dev, mem);
 -      if (!timer->io_base) {
 -              dev_err(dev, "%s: region already claimed.\n", __func__);
 -              return -ENOMEM;
 -      }
+       timer->fclk = ERR_PTR(-ENODEV);
 +      timer->io_base = devm_ioremap_resource(dev, mem);
 +      if (IS_ERR(timer->io_base))
 +              return PTR_ERR(timer->io_base);
  
        if (dev->of_node) {
                if (of_find_property(dev->of_node, "ti,timer-alwon", NULL))