Merge tag 'pm' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 9 Jan 2012 22:39:59 +0000 (14:39 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 9 Jan 2012 22:39:59 +0000 (14:39 -0800)
power management changes for omap and imx

A significant part of the changes for these two platforms went into
power management, so they are split out into a separate branch.

* tag 'pm' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (65 commits)
  ARM: imx6: remove __CPUINIT annotation from v7_invalidate_l1
  ARM: imx6: fix v7_invalidate_l1 by adding I-Cache invalidation
  ARM: imx6q: resume PL310 only when CACHE_L2X0 defined
  ARM: imx6q: build pm code only when CONFIG_PM selected
  ARM: mx5: use generic irq chip pm interface for pm functions on
  ARM: omap: pass minimal SoC/board data for UART from dt
  arm/dts: Add minimal device tree support for omap2420 and omap2430
  omap-serial: Add minimal device tree support
  omap-serial: Use default clock speed (48Mhz) if not specified
  omap-serial: Get rid of all pdev->id usage
  ARM: OMAP2+: hwmod: Add a new flag to handle hwmods left enabled at init
  ARM: OMAP4: PRM: use PRCM interrupt handler
  ARM: OMAP3: pm: use prcm chain handler
  ARM: OMAP: hwmod: add support for selecting mpu_irq for each wakeup pad
  ARM: OMAP2+: mux: add support for PAD wakeup interrupts
  ARM: OMAP: PRCM: add suspend prepare / finish support
  ARM: OMAP: PRCM: add support for chain interrupt handler
  ARM: OMAP3/4: PRM: add functions to read pending IRQs, PRM barrier
  ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup
  ARM: OMAP2+: mux: add wakeup-capable hwmod mux entries to dynamic list
  ...

16 files changed:
1  2 
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/plat-mxc/include/mach/common.h
arch/arm/plat-omap/include/plat/serial.h
arch/arm/plat-omap/sram.c
drivers/tty/serial/omap-serial.c

index 9d8598f29fda0391e130723ce554f44408fc6780,0929768573ba621bc4a41e82bdfc38517479f097..0e6de366c6482026157656ad3ea9f8866299ba50
@@@ -98,7 -98,6 +98,7 @@@ config MACH_SCB932
  config MACH_APF9328
        bool "APF9328"
        select SOC_IMX1
 +      select IMX_HAVE_PLATFORM_IMX_I2C
        select IMX_HAVE_PLATFORM_IMX_UART
        help
          Say Yes here if you are using the Armadeus APF9328 development board
@@@ -133,7 -132,7 +133,7 @@@ config MACH_MX25_3D
        select IMX_HAVE_PLATFORM_MXC_NAND
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
  
 -config MACH_EUKREA_CPUIMX25
 +config MACH_EUKREA_CPUIMX25SD
        bool "Support Eukrea CPUIMX25 Platform"
        select SOC_IMX25
        select IMX_HAVE_PLATFORM_FLEXCAN
  
  choice
        prompt "Baseboard"
 -      depends on MACH_EUKREA_CPUIMX25
 +      depends on MACH_EUKREA_CPUIMX25SD
        default MACH_EUKREA_MBIMXSD25_BASEBOARD
  
  config MACH_EUKREA_MBIMXSD25_BASEBOARD
@@@ -543,7 -542,7 +543,7 @@@ config MACH_MX35_3D
          Include support for MX35PDK platform. This includes specific
          configurations for the board and its peripherals.
  
 -config MACH_EUKREA_CPUIMX35
 +config MACH_EUKREA_CPUIMX35SD
        bool "Support Eukrea CPUIMX35 Platform"
        select SOC_IMX35
        select IMX_HAVE_PLATFORM_FLEXCAN
  
  choice
        prompt "Baseboard"
 -      depends on MACH_EUKREA_CPUIMX35
 +      depends on MACH_EUKREA_CPUIMX35SD
        default MACH_EUKREA_MBIMXSD35_BASEBOARD
  
  config MACH_EUKREA_MBIMXSD35_BASEBOARD
@@@ -596,13 -595,14 +596,14 @@@ comment "i.MX6 family:
  
  config SOC_IMX6Q
        bool "i.MX6 Quad support"
+       select ARM_CPU_SUSPEND if PM
        select ARM_GIC
 -      select CACHE_L2X0
        select CPU_V7
        select HAVE_ARM_SCU
        select HAVE_IMX_GPC
        select HAVE_IMX_MMDC
        select HAVE_IMX_SRC
 +      select HAVE_SMP
        select USE_OF
  
        help
index d97f409ce98be4a9d796dc21d3dc30fb9c7de9c7,7a739bb5915ee7b0117863b1fe5ecc548734775a..f5920c24f7d7eab486a8a340e4e6b6b785038483
@@@ -24,7 -24,7 +24,7 @@@ obj-$(CONFIG_MACH_MX21ADS) += mach-mx21
  
  # i.MX25 based machines
  obj-$(CONFIG_MACH_MX25_3DS) += mach-mx25_3ds.o
 -obj-$(CONFIG_MACH_EUKREA_CPUIMX25) += mach-eukrea_cpuimx25.o
 +obj-$(CONFIG_MACH_EUKREA_CPUIMX25SD) += mach-eukrea_cpuimx25.o
  obj-$(CONFIG_MACH_EUKREA_MBIMXSD25_BASEBOARD) += eukrea_mbimxsd25-baseboard.o
  
  # i.MX27 based machines
@@@ -57,7 -57,7 +57,7 @@@ obj-$(CONFIG_MACH_BUG) += mach-bug.
  # i.MX35 based machines
  obj-$(CONFIG_MACH_PCM043) += mach-pcm043.o
  obj-$(CONFIG_MACH_MX35_3DS) += mach-mx35_3ds.o
 -obj-$(CONFIG_MACH_EUKREA_CPUIMX35) += mach-cpuimx35.o
 +obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o
  obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
  obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
  
@@@ -70,4 -70,8 +70,8 @@@ AFLAGS_head-v7.o :=-Wa,-march=armv7-
  obj-$(CONFIG_SMP) += platsmp.o
  obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
  obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
- obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o pm-imx6q.o
+ obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o
+ ifeq ($(CONFIG_PM),y)
+ obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
+ endif
index b7407154c8813e27b77b9383b57575f55f8947c4,a34d0f7d1bfaea554a9cf577ae807a76d656c692..904bd1dfcd2e26b194f24ebe62eee9a377a05016
@@@ -43,10 -43,8 +43,10 @@@ config ARCH_OMAP
        bool "TI OMAP4"
        default y
        depends on ARCH_OMAP2PLUS
 +      select CACHE_L2X0
        select CPU_V7
        select ARM_GIC
 +      select HAVE_SMP
        select LOCAL_TIMERS if SMP
        select PL310_ERRATA_588369
        select PL310_ERRATA_727915
@@@ -324,11 -322,6 +324,11 @@@ config MACH_TI8168EV
        depends on SOC_OMAPTI81XX
        default y
  
 +config MACH_TI8148EVM
 +      bool "TI8148 Evaluation Module"
 +      depends on SOC_OMAPTI81XX
 +      default y
 +
  config MACH_OMAP_4430SDP
        bool "OMAP 4430 SDP board"
        default y
@@@ -365,6 -358,27 +365,27 @@@ config OMAP3_SDRC_AC_TIMIN
          wish to say no.  Selecting yes without understanding what is
          going on could result in system crashes;
  
+ config OMAP4_ERRATA_I688
+       bool "OMAP4 errata: Async Bridge Corruption"
+       depends on ARCH_OMAP4
+       select ARCH_HAS_BARRIERS
+       help
+         If a data is stalled inside asynchronous bridge because of back
+         pressure, it may be accepted multiple times, creating pointer
+         misalignment that will corrupt next transfers on that data path
+         until next reset of the system (No recovery procedure once the
+         issue is hit, the path remains consistently broken). Async bridge
+         can be found on path between MPU to EMIF and MPU to L3 interconnect.
+         This situation can happen only when the idle is initiated by a
+         Master Request Disconnection (which is trigged by software when
+         executing WFI on CPU).
+         The work-around for this errata needs all the initiators connected
+         through async bridge must ensure that data path is properly drained
+         before issuing WFI. This condition will be met if one Strongly ordered
+         access is performed to the target right before executing the WFI.
+         In MPU case, L3 T2ASYNC FIFO and DDR T2ASYNC FIFO needs to be drained.
+         IO barrier ensure that there is no synchronisation loss on initiators
+         operating on both interconnect port simultaneously.
  endmenu
  
  endif
index 6d226a76d0577ee62cafb559086eb02aca404910,63a5efad70e850ed84e1a3a2696617fbb8449294..fc9b238cbc190c1e657d07552131c7c767fa1104
@@@ -11,10 -11,11 +11,11 @@@ hwmod-common                               = omap_hwmod.o 
                                          omap_hwmod_common_data.o
  clock-common                          = clock.o clock_common_data.o \
                                          clkt_dpll.o clkt_clksel.o
+ secure-common                          = omap-smc.o omap-secure.o
  
- obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
- obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common)
- obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common)
+ obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
+ obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
+ obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
  
  obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
  
@@@ -24,11 -25,13 +25,13 @@@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.
  obj-$(CONFIG_SMP)                     += omap-smp.o omap-headsmp.o
  obj-$(CONFIG_LOCAL_TIMERS)            += timer-mpu.o
  obj-$(CONFIG_HOTPLUG_CPU)             += omap-hotplug.o
- obj-$(CONFIG_ARCH_OMAP4)              += omap44xx-smc.o omap4-common.o
+ obj-$(CONFIG_ARCH_OMAP4)              += omap4-common.o omap-wakeupgen.o \
+                                          sleep44xx.o
  
  plus_sec := $(call as-instr,.arch_extension sec,+sec)
  AFLAGS_omap-headsmp.o                 :=-Wa,-march=armv7-a$(plus_sec)
- AFLAGS_omap44xx-smc.o                 :=-Wa,-march=armv7-a$(plus_sec)
+ AFLAGS_omap-smc.o                     :=-Wa,-march=armv7-a$(plus_sec)
+ AFLAGS_sleep44xx.o                    :=-Wa,-march=armv7-a$(plus_sec)
  
  # Functions loaded to SRAM
  obj-$(CONFIG_SOC_OMAP2420)            += sram242x.o
@@@ -62,7 -65,8 +65,8 @@@ obj-$(CONFIG_ARCH_OMAP2)              += pm24xx.
  obj-$(CONFIG_ARCH_OMAP2)              += sleep24xx.o
  obj-$(CONFIG_ARCH_OMAP3)              += pm34xx.o sleep34xx.o \
                                           cpuidle34xx.o
- obj-$(CONFIG_ARCH_OMAP4)              += pm44xx.o
+ obj-$(CONFIG_ARCH_OMAP4)              += pm44xx.o omap-mpuss-lowpower.o \
+                                          cpuidle44xx.o
  obj-$(CONFIG_PM_DEBUG)                        += pm-debug.o
  obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
  obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
@@@ -77,6 -81,7 +81,7 @@@ endi
  endif
  
  # PRCM
+ obj-y                                 += prm_common.o
  obj-$(CONFIG_ARCH_OMAP2)              += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
  obj-$(CONFIG_ARCH_OMAP3)              += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
                                           vc3xxx_data.o vp3xxx_data.o
@@@ -86,7 -91,7 +91,7 @@@
  obj-$(CONFIG_ARCH_OMAP4)              += prcm.o cm2xxx_3xxx.o cminst44xx.o \
                                           cm44xx.o prcm_mpu44xx.o \
                                           prminst44xx.o vc44xx_data.o \
-                                          vp44xx_data.o
+                                          vp44xx_data.o prm44xx.o
  
  # OMAP voltage domains
  voltagedomain-common                  := voltage.o vc.o vp.o
@@@ -232,7 -237,6 +237,7 @@@ obj-$(CONFIG_MACH_CRANEBOARD)              += board
  
  obj-$(CONFIG_MACH_SBC3530)            += board-omap3stalker.o
  obj-$(CONFIG_MACH_TI8168EVM)          += board-ti8168evm.o
 +obj-$(CONFIG_MACH_TI8148EVM)          += board-ti8168evm.o
  
  # Platform specific device init code
  
index 9996334cb6879f2fe6b7b770608a7db7cde8375f,109b434159f566ef7856d135ba342cc6a7fa8267..383717ba63b9ae7f72bcf3d8999bf371abed4032
@@@ -475,106 -475,8 +475,8 @@@ static const struct usbhs_omap_board_da
  static struct omap_board_mux board_mux[] __initdata = {
        { .reg_offset = OMAP_MUX_TERMINATOR },
  };
- static struct omap_device_pad serial1_pads[] __initdata = {
-       /*
-        * Note that off output enable is an active low
-        * signal. So setting this means pin is a
-        * input enabled in off mode
-        */
-       OMAP_MUX_STATIC("uart1_cts.uart1_cts",
-                        OMAP_PIN_INPUT |
-                        OMAP_PIN_OFF_INPUT_PULLDOWN |
-                        OMAP_OFFOUT_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart1_rts.uart1_rts",
-                        OMAP_PIN_OUTPUT |
-                        OMAP_OFF_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart1_rx.uart1_rx",
-                        OMAP_PIN_INPUT |
-                        OMAP_PIN_OFF_INPUT_PULLDOWN |
-                        OMAP_OFFOUT_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart1_tx.uart1_tx",
-                        OMAP_PIN_OUTPUT |
-                        OMAP_OFF_EN |
-                        OMAP_MUX_MODE0),
- };
- static struct omap_device_pad serial2_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart2_cts.uart2_cts",
-                        OMAP_PIN_INPUT_PULLUP |
-                        OMAP_PIN_OFF_INPUT_PULLDOWN |
-                        OMAP_OFFOUT_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_rts.uart2_rts",
-                        OMAP_PIN_OUTPUT |
-                        OMAP_OFF_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_rx.uart2_rx",
-                        OMAP_PIN_INPUT |
-                        OMAP_PIN_OFF_INPUT_PULLDOWN |
-                        OMAP_OFFOUT_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_tx.uart2_tx",
-                        OMAP_PIN_OUTPUT |
-                        OMAP_OFF_EN |
-                        OMAP_MUX_MODE0),
- };
- static struct omap_device_pad serial3_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
-                        OMAP_PIN_INPUT_PULLDOWN |
-                        OMAP_PIN_OFF_INPUT_PULLDOWN |
-                        OMAP_OFFOUT_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
-                        OMAP_PIN_OUTPUT |
-                        OMAP_OFF_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
-                        OMAP_PIN_INPUT |
-                        OMAP_PIN_OFF_INPUT_PULLDOWN |
-                        OMAP_OFFOUT_EN |
-                        OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
-                        OMAP_PIN_OUTPUT |
-                        OMAP_OFF_EN |
-                        OMAP_MUX_MODE0),
- };
- static struct omap_board_data serial1_data __initdata = {
-       .id             = 0,
-       .pads           = serial1_pads,
-       .pads_cnt       = ARRAY_SIZE(serial1_pads),
- };
- static struct omap_board_data serial2_data __initdata = {
-       .id             = 1,
-       .pads           = serial2_pads,
-       .pads_cnt       = ARRAY_SIZE(serial2_pads),
- };
- static struct omap_board_data serial3_data __initdata = {
-       .id             = 2,
-       .pads           = serial3_pads,
-       .pads_cnt       = ARRAY_SIZE(serial3_pads),
- };
- static inline void board_serial_init(void)
- {
-       omap_serial_init_port(&serial1_data);
-       omap_serial_init_port(&serial2_data);
-       omap_serial_init_port(&serial3_data);
- }
  #else
  #define board_mux     NULL
- static inline void board_serial_init(void)
- {
-       omap_serial_init();
- }
  #endif
  
  /*
@@@ -711,7 -613,7 +613,7 @@@ static void __init omap_3430sdp_init(vo
        else
                gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
        omap_ads7846_init(1, gpio_pendown, 310, NULL);
-       board_serial_init();
+       omap_serial_init();
        omap_sdrc_init(hyb18m512160af6_sdrc_params, NULL);
        usb_musb_init(NULL);
        board_smc91x_init();
@@@ -731,5 -633,4 +633,5 @@@ MACHINE_START(OMAP_3430SDP, "OMAP3430 3
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_3430sdp_init,
        .timer          = &omap3_timer,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
index 4b4c9e25a83ecfa41074cae080138c7f6bd2c91f,5f264fad69bc3197f22739af5ab6fc0bd387244b..2ceb75d21eb2fdfb12073ba57579acb38a6aedf0
@@@ -372,17 -372,11 +372,17 @@@ static struct platform_device sdp4430_v
        },
  };
  
 +static struct platform_device sdp4430_dmic_codec = {
 +      .name   = "dmic-codec",
 +      .id     = -1,
 +};
 +
  static struct platform_device *sdp4430_devices[] __initdata = {
        &sdp4430_gpio_keys_device,
        &sdp4430_leds_gpio,
        &sdp4430_leds_pwm,
        &sdp4430_vbat,
 +      &sdp4430_dmic_codec,
  };
  
  static struct omap_musb_board_data musb_board_data = {
@@@ -410,7 -404,6 +410,7 @@@ static struct omap2_hsmmc_info mmc[] = 
        {
                .mmc            = 5,
                .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
 +              .pm_caps        = MMC_PM_KEEP_POWER,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .ocr_mask       = MMC_VDD_165_195,
@@@ -844,74 -837,8 +844,8 @@@ static struct omap_board_mux board_mux[
        { .reg_offset = OMAP_MUX_TERMINATOR },
  };
  
- static struct omap_device_pad serial2_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart2_cts.uart2_cts",
-                        OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_rts.uart2_rts",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_rx.uart2_rx",
-                        OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_tx.uart2_tx",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- };
- static struct omap_device_pad serial3_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
-                        OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
-                        OMAP_PIN_INPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- };
- static struct omap_device_pad serial4_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart4_rx.uart4_rx",
-                        OMAP_PIN_INPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart4_tx.uart4_tx",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- };
- static struct omap_board_data serial2_data __initdata = {
-       .id             = 1,
-       .pads           = serial2_pads,
-       .pads_cnt       = ARRAY_SIZE(serial2_pads),
- };
- static struct omap_board_data serial3_data __initdata = {
-       .id             = 2,
-       .pads           = serial3_pads,
-       .pads_cnt       = ARRAY_SIZE(serial3_pads),
- };
- static struct omap_board_data serial4_data __initdata = {
-       .id             = 3,
-       .pads           = serial4_pads,
-       .pads_cnt       = ARRAY_SIZE(serial4_pads),
- };
- static inline void board_serial_init(void)
- {
-       struct omap_board_data bdata;
-       bdata.flags     = 0;
-       bdata.pads      = NULL;
-       bdata.pads_cnt  = 0;
-       bdata.id        = 0;
-       /* pass dummy data for UART1 */
-       omap_serial_init_port(&bdata);
-       omap_serial_init_port(&serial2_data);
-       omap_serial_init_port(&serial3_data);
-       omap_serial_init_port(&serial4_data);
- }
  #else
  #define board_mux     NULL
- static inline void board_serial_init(void)
- {
-       omap_serial_init();
- }
   #endif
  
  static void omap4_sdp4430_wifi_mux_init(void)
@@@ -961,7 -888,7 +895,7 @@@ static void __init omap_4430sdp_init(vo
        omap4_i2c_init();
        omap_sfh7741prox_init();
        platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
-       board_serial_init();
+       omap_serial_init();
        omap_sdrc_init(NULL, NULL);
        omap4_sdp4430_wifi_init();
        omap4_twl6030_hsmmc_init(mmc);
@@@ -994,5 -921,4 +928,5 @@@ MACHINE_START(OMAP_4430SDP, "OMAP4430 4
        .handle_irq     = gic_handle_irq,
        .init_machine   = omap_4430sdp_init,
        .timer          = &omap4_timer,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
index f8c5b2cc7c9c228c14847b16ca3d9f98eaa35426,a508ed5cc890786209f713bf20465cd30dddcd7e..d587560604836f5d7ee836b773f37798c17cdf41
@@@ -69,7 -69,6 +69,6 @@@ static void __init omap_generic_init(vo
        if (node)
                irq_domain_add_simple(node, 0);
  
-       omap_serial_init();
        omap_sdrc_init(NULL, NULL);
  
        of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
@@@ -106,7 -105,6 +105,7 @@@ DT_MACHINE_START(OMAP242X_DT, "Generic 
        .init_machine   = omap_generic_init,
        .timer          = &omap2_timer,
        .dt_compat      = omap242x_boards_compat,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
  #endif
  
@@@ -126,7 -124,6 +125,7 @@@ DT_MACHINE_START(OMAP243X_DT, "Generic 
        .init_machine   = omap_generic_init,
        .timer          = &omap2_timer,
        .dt_compat      = omap243x_boards_compat,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
  #endif
  
@@@ -145,7 -142,6 +144,7 @@@ DT_MACHINE_START(OMAP3_DT, "Generic OMA
        .init_machine   = omap3_init,
        .timer          = &omap3_timer,
        .dt_compat      = omap3_boards_compat,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
  #endif
  
@@@ -164,6 -160,5 +163,6 @@@ DT_MACHINE_START(OMAP4_DT, "Generic OMA
        .init_machine   = omap4_init,
        .timer          = &omap4_timer,
        .dt_compat      = omap4_boards_compat,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
  #endif
index 72d76ed94a6549450ab71e4da9c4918d3118639d,118f38c4b37d1be9cf7dbc58722c2c560fdfd032..42a4d11fad23de92c36cec7a87fe5ebfd34e4bbe
@@@ -46,7 -46,7 +46,7 @@@ static struct device *mmc_device
  #define TUSB6010_GPIO_ENABLE  0
  #define TUSB6010_DMACHAN      0x3f
  
 -#ifdef CONFIG_USB_MUSB_TUSB6010
 +#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
  /*
   * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
   * 1.5 V voltage regulators of PM companion chip. Companion chip will then
@@@ -644,15 -644,15 +644,15 @@@ static inline void board_serial_init(vo
        bdata.pads_cnt = 0;
  
        bdata.id = 0;
-       omap_serial_init_port(&bdata);
+       omap_serial_init_port(&bdata, NULL);
  
        bdata.id = 1;
-       omap_serial_init_port(&bdata);
+       omap_serial_init_port(&bdata, NULL);
  
        bdata.id = 2;
        bdata.pads = serial2_pads;
        bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
-       omap_serial_init_port(&bdata);
+       omap_serial_init_port(&bdata, NULL);
  }
  
  #else
@@@ -692,7 -692,6 +692,7 @@@ MACHINE_START(NOKIA_N800, "Nokia N800"
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = n8x0_init_machine,
        .timer          = &omap2_timer,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
  
  MACHINE_START(NOKIA_N810, "Nokia N810")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = n8x0_init_machine,
        .timer          = &omap2_timer,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
  
  MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = n8x0_init_machine,
        .timer          = &omap2_timer,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
index 8b06c6a60d02767819f4cdb833f72f3f6471c580,ea45f5835103395a2825134e5406c73448ec1bd3..e96a2e7ad36f527b81b321ce5f01fe5488c88f5f
@@@ -364,74 -364,8 +364,8 @@@ static struct omap_board_mux board_mux[
        { .reg_offset = OMAP_MUX_TERMINATOR },
  };
  
- static struct omap_device_pad serial2_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart2_cts.uart2_cts",
-                        OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_rts.uart2_rts",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_rx.uart2_rx",
-                        OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart2_tx.uart2_tx",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- };
- static struct omap_device_pad serial3_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
-                        OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
-                        OMAP_PIN_INPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- };
- static struct omap_device_pad serial4_pads[] __initdata = {
-       OMAP_MUX_STATIC("uart4_rx.uart4_rx",
-                        OMAP_PIN_INPUT | OMAP_MUX_MODE0),
-       OMAP_MUX_STATIC("uart4_tx.uart4_tx",
-                        OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
- };
- static struct omap_board_data serial2_data __initdata = {
-       .id             = 1,
-       .pads           = serial2_pads,
-       .pads_cnt       = ARRAY_SIZE(serial2_pads),
- };
- static struct omap_board_data serial3_data __initdata = {
-       .id             = 2,
-       .pads           = serial3_pads,
-       .pads_cnt       = ARRAY_SIZE(serial3_pads),
- };
- static struct omap_board_data serial4_data __initdata = {
-       .id             = 3,
-       .pads           = serial4_pads,
-       .pads_cnt       = ARRAY_SIZE(serial4_pads),
- };
- static inline void board_serial_init(void)
- {
-       struct omap_board_data bdata;
-       bdata.flags     = 0;
-       bdata.pads      = NULL;
-       bdata.pads_cnt  = 0;
-       bdata.id        = 0;
-       /* pass dummy data for UART1 */
-       omap_serial_init_port(&bdata);
-       omap_serial_init_port(&serial2_data);
-       omap_serial_init_port(&serial3_data);
-       omap_serial_init_port(&serial4_data);
- }
  #else
  #define board_mux     NULL
- static inline void board_serial_init(void)
- {
-       omap_serial_init();
- }
  #endif
  
  /* Display DVI */
@@@ -562,7 -496,7 +496,7 @@@ static void __init omap4_panda_init(voi
        omap4_panda_i2c_init();
        platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
        platform_device_register(&omap_vwlan_device);
-       board_serial_init();
+       omap_serial_init();
        omap_sdrc_init(NULL, NULL);
        omap4_twl6030_hsmmc_init(mmc);
        omap4_ehci_init();
@@@ -580,5 -514,4 +514,5 @@@ MACHINE_START(OMAP4_PANDA, "OMAP4 Pand
        .handle_irq     = gic_handle_irq,
        .init_machine   = omap4_panda_init,
        .timer          = &omap4_timer,
 +      .restart        = omap_prcm_restart,
  MACHINE_END
index 9403b2ce6c85e9b9dd969a811f1122eb62ec15d1,90bd2ae8559638144fa6d1e569dc191aafe9c22a..febffde2ff109ed4682fe0e311f93ee23aee2cbd
  
  #ifndef __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H
  #define __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H
+ #ifndef __ASSEMBLER__
  
  #include <linux/delay.h>
  #include <plat/common.h>
+ #include <asm/proc-fns.h>
  
  #ifdef CONFIG_SOC_OMAP2420
  extern void omap242x_map_common_io(void);
@@@ -92,7 -94,6 +94,7 @@@ void omap3_init_early(void);  /* Do not 
  void am35xx_init_early(void);
  void ti81xx_init_early(void);
  void omap4430_init_early(void);
 +void omap_prcm_restart(char, const char *);
  
  /*
   * IO bases for various OMAP processors
@@@ -168,23 -169,23 +170,23 @@@ void omap3_intc_resume_idle(void)
  void omap2_intc_handle_irq(struct pt_regs *regs);
  void omap3_intc_handle_irq(struct pt_regs *regs);
  
- /*
-  * wfi used in low power code. Directly opcode is used instead
-  * of instruction to avoid mulit-omap build break
-  */
- #ifdef CONFIG_THUMB2_KERNEL
- #define do_wfi() __asm__ __volatile__ ("wfi" : : : "memory")
- #else
- #define do_wfi()                      \
-               __asm__ __volatile__ (".word    0xe320f003" : : : "memory")
+ #ifdef CONFIG_CACHE_L2X0
+ extern void __iomem *omap4_get_l2cache_base(void);
  #endif
  
- #ifdef CONFIG_CACHE_L2X0
- extern void __iomem *l2cache_base;
+ #ifdef CONFIG_SMP
+ extern void __iomem *omap4_get_scu_base(void);
+ #else
+ static inline void __iomem *omap4_get_scu_base(void)
+ {
+       return NULL;
+ }
  #endif
  
  extern void __init gic_init_irq(void);
  extern void omap_smc1(u32 fn, u32 arg);
+ extern void __iomem *omap4_get_sar_ram_base(void);
+ extern void omap_do_wfi(void);
  
  #ifdef CONFIG_SMP
  /* Needed for secondary core boot */
@@@ -194,4 -195,44 +196,44 @@@ extern void omap_auxcoreboot_addr(u32 c
  extern u32 omap_read_auxcoreboot0(void);
  #endif
  
+ #if defined(CONFIG_SMP) && defined(CONFIG_PM)
+ extern int omap4_mpuss_init(void);
+ extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
+ extern int omap4_finish_suspend(unsigned long cpu_state);
+ extern void omap4_cpu_resume(void);
+ extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
+ extern u32 omap4_mpuss_read_prev_context_state(void);
+ #else
+ static inline int omap4_enter_lowpower(unsigned int cpu,
+                                       unsigned int power_state)
+ {
+       cpu_do_idle();
+       return 0;
+ }
+ static inline int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
+ {
+       cpu_do_idle();
+       return 0;
+ }
+ static inline int omap4_mpuss_init(void)
+ {
+       return 0;
+ }
+ static inline int omap4_finish_suspend(unsigned long cpu_state)
+ {
+       return 0;
+ }
+ static inline void omap4_cpu_resume(void)
+ {}
+ static inline u32 omap4_mpuss_read_prev_context_state(void)
+ {
+       return 0;
+ }
+ #endif
+ #endif /* __ASSEMBLER__ */
  #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
index 373d1f15c4eb2543573cd93f50191060ac3e5e70,ee9416bcc3e6072c1777ea9397ffb5578832827b..5192cabb40ed812ca39363124f2a94eebf8541dc
  #include <linux/list.h>
  #include <linux/mutex.h>
  #include <linux/spinlock.h>
+ #include <linux/slab.h>
  
  #include "common.h"
  #include <plat/cpu.h>
@@@ -380,6 -381,51 +381,51 @@@ static int _set_module_autoidle(struct 
        return 0;
  }
  
+ /**
+  * _set_idle_ioring_wakeup - enable/disable IO pad wakeup on hwmod idle for mux
+  * @oh: struct omap_hwmod *
+  * @set_wake: bool value indicating to set (true) or clear (false) wakeup enable
+  *
+  * Set or clear the I/O pad wakeup flag in the mux entries for the
+  * hwmod @oh.  This function changes the @oh->mux->pads_dynamic array
+  * in memory.  If the hwmod is currently idled, and the new idle
+  * values don't match the previous ones, this function will also
+  * update the SCM PADCTRL registers.  Otherwise, if the hwmod is not
+  * currently idled, this function won't touch the hardware: the new
+  * mux settings are written to the SCM PADCTRL registers when the
+  * hwmod is idled.  No return value.
+  */
+ static void _set_idle_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+ {
+       struct omap_device_pad *pad;
+       bool change = false;
+       u16 prev_idle;
+       int j;
+       if (!oh->mux || !oh->mux->enabled)
+               return;
+       for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+               pad = oh->mux->pads_dynamic[j];
+               if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP))
+                       continue;
+               prev_idle = pad->idle;
+               if (set_wake)
+                       pad->idle |= OMAP_WAKEUP_EN;
+               else
+                       pad->idle &= ~OMAP_WAKEUP_EN;
+               if (prev_idle != pad->idle)
+                       change = true;
+       }
+       if (change && oh->_state == _HWMOD_STATE_IDLE)
+               omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+ }
  /**
   * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
   * @oh: struct omap_hwmod *
@@@ -706,65 -752,27 +752,65 @@@ static void _enable_module(struct omap_
  }
  
  /**
 - * _disable_module - enable CLKCTRL modulemode on OMAP4
 + * _omap4_wait_target_disable - wait for a module to be disabled on OMAP4
 + * @oh: struct omap_hwmod *
 + *
 + * Wait for a module @oh to enter slave idle.  Returns 0 if the module
 + * does not have an IDLEST bit or if the module successfully enters
 + * slave idle; otherwise, pass along the return value of the
 + * appropriate *_cm*_wait_module_idle() function.
 + */
 +static int _omap4_wait_target_disable(struct omap_hwmod *oh)
 +{
 +      if (!cpu_is_omap44xx())
 +              return 0;
 +
 +      if (!oh)
 +              return -EINVAL;
 +
 +      if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
 +              return 0;
 +
 +      if (oh->flags & HWMOD_NO_IDLEST)
 +              return 0;
 +
 +      return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
 +                                           oh->clkdm->cm_inst,
 +                                           oh->clkdm->clkdm_offs,
 +                                           oh->prcm.omap4.clkctrl_offs);
 +}
 +
 +/**
 + * _omap4_disable_module - enable CLKCTRL modulemode on OMAP4
   * @oh: struct omap_hwmod *
   *
   * Disable the PRCM module mode related to the hwmod @oh.
 - * No return value.
 + * Return EINVAL if the modulemode is not supported and 0 in case of success.
   */
 -static void _disable_module(struct omap_hwmod *oh)
 +static int _omap4_disable_module(struct omap_hwmod *oh)
  {
 +      int v;
 +
        /* The module mode does not exist prior OMAP4 */
 -      if (cpu_is_omap24xx() || cpu_is_omap34xx())
 -              return;
 +      if (!cpu_is_omap44xx())
 +              return -EINVAL;
  
        if (!oh->clkdm || !oh->prcm.omap4.modulemode)
 -              return;
 +              return -EINVAL;
  
 -      pr_debug("omap_hwmod: %s: _disable_module\n", oh->name);
 +      pr_debug("omap_hwmod: %s: %s\n", oh->name, __func__);
  
        omap4_cminst_module_disable(oh->clkdm->prcm_partition,
                                    oh->clkdm->cm_inst,
                                    oh->clkdm->clkdm_offs,
                                    oh->prcm.omap4.clkctrl_offs);
 +
 +      v = _omap4_wait_target_disable(oh);
 +      if (v)
 +              pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
 +                      oh->name);
 +
 +      return 0;
  }
  
  /**
@@@ -1190,6 -1198,36 +1236,6 @@@ static int _wait_target_ready(struct om
        return ret;
  }
  
 -/**
 - * _wait_target_disable - wait for a module to be disabled
 - * @oh: struct omap_hwmod *
 - *
 - * Wait for a module @oh to enter slave idle.  Returns 0 if the module
 - * does not have an IDLEST bit or if the module successfully enters
 - * slave idle; otherwise, pass along the return value of the
 - * appropriate *_cm*_wait_module_idle() function.
 - */
 -static int _wait_target_disable(struct omap_hwmod *oh)
 -{
 -      /* TODO: For now just handle OMAP4+ */
 -      if (cpu_is_omap24xx() || cpu_is_omap34xx())
 -              return 0;
 -
 -      if (!oh)
 -              return -EINVAL;
 -
 -      if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
 -              return 0;
 -
 -      if (oh->flags & HWMOD_NO_IDLEST)
 -              return 0;
 -
 -      return omap4_cminst_wait_module_idle(oh->clkdm->prcm_partition,
 -                                           oh->clkdm->cm_inst,
 -                                           oh->clkdm->clkdm_offs,
 -                                           oh->prcm.omap4.clkctrl_offs);
 -}
 -
  /**
   * _lookup_hardreset - fill register bit info for this hwmod/reset line
   * @oh: struct omap_hwmod *
@@@ -1449,6 -1487,25 +1495,25 @@@ static int _enable(struct omap_hwmod *o
  
        pr_debug("omap_hwmod: %s: enabling\n", oh->name);
  
+       /*
+        * hwmods with HWMOD_INIT_NO_IDLE flag set are left
+        * in enabled state at init.
+        * Now that someone is really trying to enable them,
+        * just ensure that the hwmod mux is set.
+        */
+       if (oh->_int_flags & _HWMOD_SKIP_ENABLE) {
+               /*
+                * If the caller has mux data populated, do the mux'ing
+                * which wouldn't have been done as part of the _enable()
+                * done during setup.
+                */
+               if (oh->mux)
+                       omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
+               oh->_int_flags &= ~_HWMOD_SKIP_ENABLE;
+               return 0;
+       }
        if (oh->_state != _HWMOD_STATE_INITIALIZED &&
            oh->_state != _HWMOD_STATE_IDLE &&
            oh->_state != _HWMOD_STATE_DISABLED) {
   */
  static int _idle(struct omap_hwmod *oh)
  {
 -      int ret;
 -
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
  
        if (oh->_state != _HWMOD_STATE_ENABLED) {
        if (oh->class->sysc)
                _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
 -      _disable_module(oh);
 -      ret = _wait_target_disable(oh);
 -      if (ret)
 -              pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
 -                      oh->name);
 +
 +      _omap4_disable_module(oh);
 +
        /*
         * The module must be in idle mode before disabling any parents
         * clocks. Otherwise, the parent clock might be disabled before
@@@ -1646,7 -1707,11 +1711,7 @@@ 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 */
 -              _disable_module(oh);
 -              ret = _wait_target_disable(oh);
 -              if (ret)
 -                      pr_warn("omap_hwmod: %s: _wait_target_disable failed\n",
 -                              oh->name);
 +              _omap4_disable_module(oh);
                _disable_clocks(oh);
                if (oh->clkdm)
                        clkdm_hwmod_disable(oh->clkdm, oh);
@@@ -1744,8 -1809,10 +1809,10 @@@ static int _setup(struct omap_hwmod *oh
         * it should be set by the core code as a runtime flag during startup
         */
        if ((oh->flags & HWMOD_INIT_NO_IDLE) &&
-           (postsetup_state == _HWMOD_STATE_IDLE))
+           (postsetup_state == _HWMOD_STATE_IDLE)) {
+               oh->_int_flags |= _HWMOD_SKIP_ENABLE;
                postsetup_state = _HWMOD_STATE_ENABLED;
+       }
  
        if (postsetup_state == _HWMOD_STATE_IDLE)
                _idle(oh);
@@@ -2416,6 -2483,7 +2483,7 @@@ int omap_hwmod_enable_wakeup(struct oma
        v = oh->_sysc_cache;
        _enable_wakeup(oh, &v);
        _write_sysconfig(v, oh);
+       _set_idle_ioring_wakeup(oh, true);
        spin_unlock_irqrestore(&oh->_lock, flags);
  
        return 0;
@@@ -2446,6 -2514,7 +2514,7 @@@ int omap_hwmod_disable_wakeup(struct om
        v = oh->_sysc_cache;
        _disable_wakeup(oh, &v);
        _write_sysconfig(v, oh);
+       _set_idle_ioring_wakeup(oh, false);
        spin_unlock_irqrestore(&oh->_lock, flags);
  
        return 0;
@@@ -2662,3 -2731,57 +2731,57 @@@ int omap_hwmod_no_setup_reset(struct om
  
        return 0;
  }
+ /**
+  * omap_hwmod_pad_route_irq - route an I/O pad wakeup to a particular MPU IRQ
+  * @oh: struct omap_hwmod * containing hwmod mux entries
+  * @pad_idx: array index in oh->mux of the hwmod mux entry to route wakeup
+  * @irq_idx: the hwmod mpu_irqs array index of the IRQ to trigger on wakeup
+  *
+  * When an I/O pad wakeup arrives for the dynamic or wakeup hwmod mux
+  * entry number @pad_idx for the hwmod @oh, trigger the interrupt
+  * service routine for the hwmod's mpu_irqs array index @irq_idx.  If
+  * this function is not called for a given pad_idx, then the ISR
+  * associated with @oh's first MPU IRQ will be triggered when an I/O
+  * pad wakeup occurs on that pad.  Note that @pad_idx is the index of
+  * the _dynamic or wakeup_ entry: if there are other entries not
+  * marked with OMAP_DEVICE_PAD_WAKEUP or OMAP_DEVICE_PAD_REMUX, these
+  * entries are NOT COUNTED in the dynamic pad index.  This function
+  * must be called separately for each pad that requires its interrupt
+  * to be re-routed this way.  Returns -EINVAL if there is an argument
+  * problem or if @oh does not have hwmod mux entries or MPU IRQs;
+  * returns -ENOMEM if memory cannot be allocated; or 0 upon success.
+  *
+  * XXX This function interface is fragile.  Rather than using array
+  * indexes, which are subject to unpredictable change, it should be
+  * using hwmod IRQ names, and some other stable key for the hwmod mux
+  * pad records.
+  */
+ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx)
+ {
+       int nr_irqs;
+       might_sleep();
+       if (!oh || !oh->mux || !oh->mpu_irqs || pad_idx < 0 ||
+           pad_idx >= oh->mux->nr_pads_dynamic)
+               return -EINVAL;
+       /* Check the number of available mpu_irqs */
+       for (nr_irqs = 0; oh->mpu_irqs[nr_irqs].irq >= 0; nr_irqs++)
+               ;
+       if (irq_idx >= nr_irqs)
+               return -EINVAL;
+       if (!oh->mux->irqs) {
+               /* XXX What frees this? */
+               oh->mux->irqs = kzalloc(sizeof(int) * oh->mux->nr_pads_dynamic,
+                       GFP_KERNEL);
+               if (!oh->mux->irqs)
+                       return -ENOMEM;
+       }
+       oh->mux->irqs[pad_idx] = irq_idx;
+       return 0;
+ }
index da2d80f5fcbdf809637506088a57a1ab7eefc444,0f69d8fc5628809251abc557dc904d07a33c505a..5aa5435e3ff186fbc5254c8463d8f97a90ba9445
@@@ -4,7 -4,7 +4,7 @@@
  /*
   * OMAP2/3 PRCM base and module definitions
   *
-  * Copyright (C) 2007-2009 Texas Instruments, Inc.
+  * Copyright (C) 2007-2009, 2011 Texas Instruments, Inc.
   * Copyright (C) 2007-2009 Nokia Corporation
   *
   * Written by Paul Walmsley
  #define OMAP3430_EN_MMC2_SHIFT                                25
  #define OMAP3430_EN_MMC1_MASK                         (1 << 24)
  #define OMAP3430_EN_MMC1_SHIFT                                24
 +#define OMAP3430_EN_UART4_MASK                                (1 << 23)
 +#define OMAP3430_EN_UART4_SHIFT                               23
  #define OMAP3430_EN_MCSPI4_MASK                               (1 << 21)
  #define OMAP3430_EN_MCSPI4_SHIFT                      21
  #define OMAP3430_EN_MCSPI3_MASK                               (1 << 20)
  extern void __iomem *prm_base;
  extern void __iomem *cm_base;
  extern void __iomem *cm2_base;
+ /**
+  * struct omap_prcm_irq - describes a PRCM interrupt bit
+  * @name: a short name describing the interrupt type, e.g. "wkup" or "io"
+  * @offset: the bit shift of the interrupt inside the IRQ{ENABLE,STATUS} regs
+  * @priority: should this interrupt be handled before @priority=false IRQs?
+  *
+  * Describes interrupt bits inside the PRM_IRQ{ENABLE,STATUS}_MPU* registers.
+  * On systems with multiple PRM MPU IRQ registers, the bitfields read from
+  * the registers are concatenated, so @offset could be > 31 on these systems -
+  * see omap_prm_irq_handler() for more details.  I/O ring interrupts should
+  * have @priority set to true.
+  */
+ struct omap_prcm_irq {
+       const char *name;
+       unsigned int offset;
+       bool priority;
+ };
+ /**
+  * struct omap_prcm_irq_setup - PRCM interrupt controller details
+  * @ack: PRM register offset for the first PRM_IRQSTATUS_MPU register
+  * @mask: PRM register offset for the first PRM_IRQENABLE_MPU register
+  * @nr_regs: number of PRM_IRQ{STATUS,ENABLE}_MPU* registers
+  * @nr_irqs: number of entries in the @irqs array
+  * @irqs: ptr to an array of PRCM interrupt bits (see @nr_irqs)
+  * @irq: MPU IRQ asserted when a PRCM interrupt arrives
+  * @read_pending_irqs: fn ptr to determine if any PRCM IRQs are pending
+  * @ocp_barrier: fn ptr to force buffered PRM writes to complete
+  * @save_and_clear_irqen: fn ptr to save and clear IRQENABLE regs
+  * @restore_irqen: fn ptr to save and clear IRQENABLE regs
+  * @saved_mask: IRQENABLE regs are saved here during suspend
+  * @priority_mask: 1 bit per IRQ, set to 1 if omap_prcm_irq.priority = true
+  * @base_irq: base dynamic IRQ number, returned from irq_alloc_descs() in init
+  * @suspended: set to true after Linux suspend code has called our ->prepare()
+  * @suspend_save_flag: set to true after IRQ masks have been saved and disabled
+  *
+  * @saved_mask, @priority_mask, @base_irq, @suspended, and
+  * @suspend_save_flag are populated dynamically, and are not to be
+  * specified in static initializers.
+  */
+ struct omap_prcm_irq_setup {
+       u16 ack;
+       u16 mask;
+       u8 nr_regs;
+       u8 nr_irqs;
+       const struct omap_prcm_irq *irqs;
+       int irq;
+       void (*read_pending_irqs)(unsigned long *events);
+       void (*ocp_barrier)(void);
+       void (*save_and_clear_irqen)(u32 *saved_mask);
+       void (*restore_irqen)(u32 *saved_mask);
+       u32 *saved_mask;
+       u32 *priority_mask;
+       int base_irq;
+       bool suspended;
+       bool suspend_save_flag;
+ };
+ /* OMAP_PRCM_IRQ: convenience macro for creating struct omap_prcm_irq records */
+ #define OMAP_PRCM_IRQ(_name, _offset, _priority) {    \
+       .name = _name,                                  \
+       .offset = _offset,                              \
+       .priority = _priority                           \
+       }
+ extern void omap_prcm_irq_cleanup(void);
+ extern int omap_prcm_register_chain_handler(
+       struct omap_prcm_irq_setup *irq_setup);
+ extern int omap_prcm_event_to_irq(const char *event);
+ extern void omap_prcm_irq_prepare(void);
+ extern void omap_prcm_irq_complete(void);
  # endif
  
  #endif
index 83cca9bcfc972729fd74fecc8ce1272189d04b6a,3846c53f5b5d1395cdfe065376daa3a9074b1086..1bf0df81bdc69dec5c08140454adcebc0f888dd0
@@@ -71,8 -71,8 +71,8 @@@ extern int mx6q_clocks_init(void)
  extern struct platform_device *mxc_register_gpio(char *name, int id,
        resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
  extern void mxc_set_cpu_type(unsigned int type);
 +extern void mxc_restart(char, const char *);
  extern void mxc_arch_reset_init(void __iomem *);
 -extern void mx51_efikamx_reset(void);
  extern int mx53_revision(void);
  extern int mx53_display_revision(void);
  
@@@ -121,7 -121,6 +121,7 @@@ static inline void imx_smp_prepare(void
  extern void imx_enable_cpu(int cpu, bool enable);
  extern void imx_set_cpu_jump(int cpu, void *jump_addr);
  extern void imx_src_init(void);
 +extern void imx_src_prepare_restart(void);
  extern void imx_gpc_init(void);
  extern void imx_gpc_pre_suspend(void);
  extern void imx_gpc_post_resume(void);
@@@ -131,6 -130,12 +131,12 @@@ extern void imx53_evk_common_init(void)
  extern void imx53_qsb_common_init(void);
  extern void imx53_smd_common_init(void);
  extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
- extern void imx6q_pm_init(void);
  extern void imx6q_clock_map_io(void);
+ #ifdef CONFIG_PM
+ extern void imx6q_pm_init(void);
+ #else
+ static inline void imx6q_pm_init(void) {}
+ #endif
  #endif
index 80b6d39c31ecffdc5313c700ba7e560c54c32f60,38b3e38df2a059edee7b0a7a34a52d0b020cc5fb..198d1e6a4a6c946268a4a4feef21fc0d39312647
@@@ -2,7 -2,7 +2,7 @@@
   * arch/arm/plat-omap/include/mach/serial.h
   *
   * Copyright (C) 2009 Texas Instruments
 - * Addded OMAP4 support- Santosh Shilimkar <santosh.shilimkar@ti.com>
 + * Added OMAP4 support- Santosh Shilimkar <santosh.shilimkar@ti.com>
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@@ -44,7 -44,6 +44,7 @@@
  #define OMAP3_UART2_BASE      OMAP2_UART2_BASE
  #define OMAP3_UART3_BASE      0x49020000
  #define OMAP3_UART4_BASE      0x49042000      /* Only on 36xx */
 +#define OMAP3_UART4_AM35XX_BASE       0x4809E000      /* Only on AM35xx */
  
  /* OMAP4 serial ports */
  #define OMAP4_UART1_BASE      OMAP2_UART1_BASE
  #ifndef __ASSEMBLER__
  
  struct omap_board_data;
+ struct omap_uart_port_info;
  
  extern void omap_serial_init(void);
- extern void omap_serial_init_port(struct omap_board_data *bdata);
  extern int omap_uart_can_sleep(void);
- extern void omap_uart_check_wakeup(void);
- extern void omap_uart_prepare_suspend(void);
- extern void omap_uart_prepare_idle(int num);
- extern void omap_uart_resume_idle(int num);
- extern void omap_uart_enable_irqs(int enable);
+ extern void omap_serial_board_init(struct omap_uart_port_info *platform_data);
+ extern void omap_serial_init_port(struct omap_board_data *bdata,
+               struct omap_uart_port_info *platform_data);
  #endif
  
  #endif
index 6b058a621e8db870d9a80cc759dd41e4656df57a,ad6a71a00cefaa8f54dd5c228cdba22f85333b01..4243bdcc87bcb99fe8ba3f26341757cd47ea41d9
  #define OMAP1_SRAM_PA         0x20000000
  #define OMAP2_SRAM_PUB_PA     (OMAP2_SRAM_PA + 0xf800)
  #define OMAP3_SRAM_PUB_PA       (OMAP3_SRAM_PA + 0x8000)
+ #ifdef CONFIG_OMAP4_ERRATA_I688
+ #define OMAP4_SRAM_PUB_PA     OMAP4_SRAM_PA
+ #else
  #define OMAP4_SRAM_PUB_PA     (OMAP4_SRAM_PA + 0x4000)
+ #endif
  
  #if defined(CONFIG_ARCH_OMAP2PLUS)
  #define SRAM_BOOTLOADER_SZ    0x00
@@@ -141,9 -145,11 +145,9 @@@ static void __init omap_detect_sram(voi
                        omap_sram_size = 0x32000;       /* 200K */
                else if (cpu_is_omap15xx())
                        omap_sram_size = 0x30000;       /* 192K */
 -              else if (cpu_is_omap1610() || cpu_is_omap1621() ||
 -                   cpu_is_omap1710())
 +              else if (cpu_is_omap1610() || cpu_is_omap1611() ||
 +                              cpu_is_omap1621() || cpu_is_omap1710())
                        omap_sram_size = 0x4000;        /* 16K */
 -              else if (cpu_is_omap1611())
 -                      omap_sram_size = SZ_256K;
                else {
                        pr_err("Could not detect SRAM size\n");
                        omap_sram_size = 0x4000;
@@@ -161,6 -167,10 +165,10 @@@ static void __init omap_map_sram(void
        if (omap_sram_size == 0)
                return;
  
+ #ifdef CONFIG_OMAP4_ERRATA_I688
+               omap_sram_start += PAGE_SIZE;
+               omap_sram_size -= SZ_16K;
+ #endif
        if (cpu_is_omap34xx()) {
                /*
                 * SRAM must be marked as non-cached on OMAP3 since the
@@@ -222,9 -232,6 +230,9 @@@ static void (*_omap_sram_reprogram_cloc
  void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl)
  {
        BUG_ON(!_omap_sram_reprogram_clock);
 +      /* On 730, bit 13 must always be 1 */
 +      if (cpu_is_omap7xx())
 +              ckctl |= 0x2000;
        _omap_sram_reprogram_clock(dpllctl, ckctl);
  }
  
index f2a1380ed678b007f4690ac1d6f7d10e202aca37,ca24ab37d11c96cfa9618b52a9260296806bfea1..d192dcbb82f5e464f9ab6beb8805a2dcd1c6733b
  #include <linux/clk.h>
  #include <linux/serial_core.h>
  #include <linux/irq.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/of.h>
  
  #include <plat/dma.h>
  #include <plat/dmtimer.h>
  #include <plat/omap-serial.h>
  
+ #define DEFAULT_CLK_SPEED 48000000 /* 48Mhz*/
  static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
  
  /* Forward declaration of functions */
  static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
- static void serial_omap_rx_timeout(unsigned long uart_no);
+ static void serial_omap_rxdma_poll(unsigned long uart_no);
  static int serial_omap_start_rxdma(struct uart_omap_port *up);
+ static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
+ static struct workqueue_struct *serial_omap_uart_wq;
  
  static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
  {
@@@ -102,6 -109,8 +109,8 @@@ static void serial_omap_stop_rxdma(stru
                omap_free_dma(up->uart_dma.rx_dma_channel);
                up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
                up->uart_dma.rx_dma_used = false;
+               pm_runtime_mark_last_busy(&up->pdev->dev);
+               pm_runtime_put_autosuspend(&up->pdev->dev);
        }
  }
  
@@@ -109,9 -118,12 +118,12 @@@ static void serial_omap_enable_ms(struc
  {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
  
-       dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
+       dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->port.line);
+       pm_runtime_get_sync(&up->pdev->dev);
        up->ier |= UART_IER_MSI;
        serial_out(up, UART_IER, up->ier);
+       pm_runtime_put(&up->pdev->dev);
  }
  
  static void serial_omap_stop_tx(struct uart_port *port)
                omap_stop_dma(up->uart_dma.tx_dma_channel);
                omap_free_dma(up->uart_dma.tx_dma_channel);
                up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+               pm_runtime_mark_last_busy(&up->pdev->dev);
+               pm_runtime_put_autosuspend(&up->pdev->dev);
        }
  
+       pm_runtime_get_sync(&up->pdev->dev);
        if (up->ier & UART_IER_THRI) {
                up->ier &= ~UART_IER_THRI;
                serial_out(up, UART_IER, up->ier);
        }
+       pm_runtime_mark_last_busy(&up->pdev->dev);
+       pm_runtime_put_autosuspend(&up->pdev->dev);
  }
  
  static void serial_omap_stop_rx(struct uart_port *port)
  {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
  
+       pm_runtime_get_sync(&up->pdev->dev);
        if (up->use_dma)
                serial_omap_stop_rxdma(up);
        up->ier &= ~UART_IER_RLSI;
        up->port.read_status_mask &= ~UART_LSR_DR;
        serial_out(up, UART_IER, up->ier);
+       pm_runtime_mark_last_busy(&up->pdev->dev);
+       pm_runtime_put_autosuspend(&up->pdev->dev);
  }
  
- static inline void receive_chars(struct uart_omap_port *up, int *status)
+ static inline void receive_chars(struct uart_omap_port *up,
+               unsigned int *status)
  {
        struct tty_struct *tty = up->port.state->port.tty;
-       unsigned int flag;
-       unsigned char ch, lsr = *status;
+       unsigned int flag, lsr = *status;
+       unsigned char ch = 0;
        int max_count = 256;
  
        do {
@@@ -262,7 -284,10 +284,10 @@@ static void serial_omap_start_tx(struc
        int ret = 0;
  
        if (!up->use_dma) {
+               pm_runtime_get_sync(&up->pdev->dev);
                serial_omap_enable_ier_thri(up);
+               pm_runtime_mark_last_busy(&up->pdev->dev);
+               pm_runtime_put_autosuspend(&up->pdev->dev);
                return;
        }
  
        xmit = &up->port.state->xmit;
  
        if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
+               pm_runtime_get_sync(&up->pdev->dev);
                ret = omap_request_dma(up->uart_dma.uart_dma_tx,
                                "UART Tx DMA",
                                (void *)uart_tx_dma_callback, up,
@@@ -354,9 -380,13 +380,13 @@@ static inline irqreturn_t serial_omap_i
        unsigned int iir, lsr;
        unsigned long flags;
  
+       pm_runtime_get_sync(&up->pdev->dev);
        iir = serial_in(up, UART_IIR);
-       if (iir & UART_IIR_NO_INT)
+       if (iir & UART_IIR_NO_INT) {
+               pm_runtime_mark_last_busy(&up->pdev->dev);
+               pm_runtime_put_autosuspend(&up->pdev->dev);
                return IRQ_NONE;
+       }
  
        spin_lock_irqsave(&up->port.lock, flags);
        lsr = serial_in(up, UART_LSR);
                transmit_chars(up);
  
        spin_unlock_irqrestore(&up->port.lock, flags);
+       pm_runtime_mark_last_busy(&up->pdev->dev);
+       pm_runtime_put_autosuspend(&up->pdev->dev);
        up->port_activity = jiffies;
        return IRQ_HANDLED;
  }
@@@ -388,22 -421,26 +421,26 @@@ static unsigned int serial_omap_tx_empt
        unsigned long flags = 0;
        unsigned int ret = 0;
  
-       dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
+       pm_runtime_get_sync(&up->pdev->dev);
+       dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->port.line);
        spin_lock_irqsave(&up->port.lock, flags);
        ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
        spin_unlock_irqrestore(&up->port.lock, flags);
+       pm_runtime_put(&up->pdev->dev);
        return ret;
  }
  
  static unsigned int serial_omap_get_mctrl(struct uart_port *port)
  {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
 -      unsigned char status;
 +      unsigned int status;
        unsigned int ret = 0;
  
+       pm_runtime_get_sync(&up->pdev->dev);
        status = check_modem_status(up);
-       dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
+       pm_runtime_put(&up->pdev->dev);
+       dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->port.line);
  
        if (status & UART_MSR_DCD)
                ret |= TIOCM_CAR;
@@@ -421,7 -458,7 +458,7 @@@ static void serial_omap_set_mctrl(struc
        struct uart_omap_port *up = (struct uart_omap_port *)port;
        unsigned char mcr = 0;
  
-       dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
+       dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->port.line);
        if (mctrl & TIOCM_RTS)
                mcr |= UART_MCR_RTS;
        if (mctrl & TIOCM_DTR)
        if (mctrl & TIOCM_LOOP)
                mcr |= UART_MCR_LOOP;
  
-       mcr |= up->mcr;
-       serial_out(up, UART_MCR, mcr);
+       pm_runtime_get_sync(&up->pdev->dev);
+       up->mcr = serial_in(up, UART_MCR);
+       up->mcr |= mcr;
+       serial_out(up, UART_MCR, up->mcr);
+       pm_runtime_put(&up->pdev->dev);
  }
  
  static void serial_omap_break_ctl(struct uart_port *port, int break_state)
        struct uart_omap_port *up = (struct uart_omap_port *)port;
        unsigned long flags = 0;
  
-       dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+       dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->port.line);
+       pm_runtime_get_sync(&up->pdev->dev);
        spin_lock_irqsave(&up->port.lock, flags);
        if (break_state == -1)
                up->lcr |= UART_LCR_SBC;
                up->lcr &= ~UART_LCR_SBC;
        serial_out(up, UART_LCR, up->lcr);
        spin_unlock_irqrestore(&up->port.lock, flags);
+       pm_runtime_put(&up->pdev->dev);
  }
  
  static int serial_omap_startup(struct uart_port *port)
        if (retval)
                return retval;
  
-       dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
+       dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->port.line);
  
+       pm_runtime_get_sync(&up->pdev->dev);
        /*
         * Clear the FIFO buffers and disable them.
         * (they will be reenabled in set_termios())
                        (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
                        0);
                init_timer(&(up->uart_dma.rx_timer));
-               up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
-               up->uart_dma.rx_timer.data = up->pdev->id;
+               up->uart_dma.rx_timer.function = serial_omap_rxdma_poll;
+               up->uart_dma.rx_timer.data = up->port.line;
                /* Currently the buffer size is 4KB. Can increase it */
                up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
                        up->uart_dma.rx_buf_size,
        /* Enable module level wake up */
        serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
  
+       pm_runtime_mark_last_busy(&up->pdev->dev);
+       pm_runtime_put_autosuspend(&up->pdev->dev);
        up->port_activity = jiffies;
        return 0;
  }
@@@ -532,7 -577,9 +577,9 @@@ static void serial_omap_shutdown(struc
        struct uart_omap_port *up = (struct uart_omap_port *)port;
        unsigned long flags = 0;
  
-       dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+       dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->port.line);
+       pm_runtime_get_sync(&up->pdev->dev);
        /*
         * Disable interrupts from this port
         */
                        up->uart_dma.rx_buf_dma_phys);
                up->uart_dma.rx_buf = NULL;
        }
+       pm_runtime_put(&up->pdev->dev);
        free_irq(up->port.irq, up);
  }
  
@@@ -573,8 -622,6 +622,6 @@@ static inline voi
  serial_omap_configure_xonxoff
                (struct uart_omap_port *up, struct ktermios *termios)
  {
-       unsigned char efr = 0;
        up->lcr = serial_in(up, UART_LCR);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
        up->efr = serial_in(up, UART_EFR);
        serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
  
        /* clear SW control mode bits */
-       efr = up->efr;
-       efr &= OMAP_UART_SW_CLR;
+       up->efr &= OMAP_UART_SW_CLR;
  
        /*
         * IXON Flag:
         * Transmit XON1, XOFF1
         */
        if (termios->c_iflag & IXON)
-               efr |= OMAP_UART_SW_TX;
+               up->efr |= OMAP_UART_SW_TX;
  
        /*
         * IXOFF Flag:
         * Receiver compares XON1, XOFF1.
         */
        if (termios->c_iflag & IXOFF)
-               efr |= OMAP_UART_SW_RX;
+               up->efr |= OMAP_UART_SW_RX;
  
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
         * load the new software flow control mode IXON or IXOFF
         * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
         */
-       serial_out(up, UART_EFR, efr | UART_EFR_SCD);
+       serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
  
        serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
        serial_out(up, UART_LCR, up->lcr);
  }
  
+ static void serial_omap_uart_qos_work(struct work_struct *work)
+ {
+       struct uart_omap_port *up = container_of(work, struct uart_omap_port,
+                                               qos_work);
+       pm_qos_update_request(&up->pm_qos_request, up->latency);
+ }
  static void
  serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
                        struct ktermios *old)
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
        quot = serial_omap_get_divisor(port, baud);
  
+       /* calculate wakeup latency constraint */
+       up->calc_latency = (1000000 * up->port.fifosize) /
+                               (1000 * baud / 8);
+       up->latency = up->calc_latency;
+       schedule_work(&up->qos_work);
+       up->dll = quot & 0xff;
+       up->dlh = quot >> 8;
+       up->mdr1 = UART_OMAP_MDR1_DISABLE;
        up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
                        UART_FCR_ENABLE_FIFO;
        if (up->use_dma)
         * Ok, we're now changing the port state. Do it with
         * interrupts disabled.
         */
+       pm_runtime_get_sync(&up->pdev->dev);
        spin_lock_irqsave(&up->port.lock, flags);
  
        /*
                up->ier |= UART_IER_MSI;
        serial_out(up, UART_IER, up->ier);
        serial_out(up, UART_LCR, cval);         /* reset DLAB */
+       up->lcr = cval;
+       up->scr = OMAP_UART_SCR_TX_EMPTY;
  
        /* FIFOs and DMA Settings */
  
  
        if (up->use_dma) {
                serial_out(up, UART_TI752_TLR, 0);
-               serial_out(up, UART_OMAP_SCR,
-                       (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8));
+               up->scr |= (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8);
        }
  
+       serial_out(up, UART_OMAP_SCR, up->scr);
        serial_out(up, UART_EFR, up->efr);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
        serial_out(up, UART_MCR, up->mcr);
  
        /* Protocol, Baud Rate, and Interrupt Settings */
  
-       serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+       if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+               serial_omap_mdr1_errataset(up, up->mdr1);
+       else
+               serial_out(up, UART_OMAP_MDR1, up->mdr1);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
  
        up->efr = serial_in(up, UART_EFR);
        serial_out(up, UART_IER, 0);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
  
-       serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
-       serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
+       serial_out(up, UART_DLL, up->dll);      /* LS of divisor */
+       serial_out(up, UART_DLM, up->dlh);      /* MS of divisor */
  
        serial_out(up, UART_LCR, 0);
        serial_out(up, UART_IER, up->ier);
        serial_out(up, UART_LCR, cval);
  
        if (baud > 230400 && baud != 3000000)
-               serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE);
+               up->mdr1 = UART_OMAP_MDR1_13X_MODE;
        else
-               serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
+               up->mdr1 = UART_OMAP_MDR1_16X_MODE;
+       if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+               serial_omap_mdr1_errataset(up, up->mdr1);
+       else
+               serial_out(up, UART_OMAP_MDR1, up->mdr1);
  
        /* Hardware Flow Control Configuration */
  
        serial_omap_configure_xonxoff(up, termios);
  
        spin_unlock_irqrestore(&up->port.lock, flags);
-       dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
+       pm_runtime_put(&up->pdev->dev);
+       dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->port.line);
  }
  
  static void
@@@ -819,7 -897,9 +897,9 @@@ serial_omap_pm(struct uart_port *port, 
        struct uart_omap_port *up = (struct uart_omap_port *)port;
        unsigned char efr;
  
-       dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+       dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->port.line);
+       pm_runtime_get_sync(&up->pdev->dev);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
        efr = serial_in(up, UART_EFR);
        serial_out(up, UART_EFR, efr | UART_EFR_ECB);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
        serial_out(up, UART_EFR, efr);
        serial_out(up, UART_LCR, 0);
+       if (!device_may_wakeup(&up->pdev->dev)) {
+               if (!state)
+                       pm_runtime_forbid(&up->pdev->dev);
+               else
+                       pm_runtime_allow(&up->pdev->dev);
+       }
+       pm_runtime_put(&up->pdev->dev);
  }
  
  static void serial_omap_release_port(struct uart_port *port)
@@@ -847,7 -936,7 +936,7 @@@ static void serial_omap_config_port(str
        struct uart_omap_port *up = (struct uart_omap_port *)port;
  
        dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
-                                                       up->pdev->id);
+                                                       up->port.line);
        up->port.type = PORT_OMAP;
  }
  
@@@ -864,7 -953,7 +953,7 @@@ serial_omap_type(struct uart_port *port
  {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
  
-       dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id);
+       dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->port.line);
        return up->name;
  }
  
@@@ -906,19 -995,26 +995,26 @@@ static inline void wait_for_xmitr(struc
  static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
  {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
+       pm_runtime_get_sync(&up->pdev->dev);
        wait_for_xmitr(up);
        serial_out(up, UART_TX, ch);
+       pm_runtime_put(&up->pdev->dev);
  }
  
  static int serial_omap_poll_get_char(struct uart_port *port)
  {
        struct uart_omap_port *up = (struct uart_omap_port *)port;
-       unsigned int status = serial_in(up, UART_LSR);
+       unsigned int status;
  
+       pm_runtime_get_sync(&up->pdev->dev);
+       status = serial_in(up, UART_LSR);
        if (!(status & UART_LSR_DR))
                return NO_POLL_CHAR;
  
-       return serial_in(up, UART_RX);
+       status = serial_in(up, UART_RX);
+       pm_runtime_put(&up->pdev->dev);
+       return status;
  }
  
  #endif /* CONFIG_CONSOLE_POLL */
@@@ -946,6 -1042,8 +1042,8 @@@ serial_omap_console_write(struct consol
        unsigned int ier;
        int locked = 1;
  
+       pm_runtime_get_sync(&up->pdev->dev);
        local_irq_save(flags);
        if (up->port.sysrq)
                locked = 0;
        if (up->msr_saved_flags)
                check_modem_status(up);
  
+       pm_runtime_mark_last_busy(&up->pdev->dev);
+       pm_runtime_put_autosuspend(&up->pdev->dev);
        if (locked)
                spin_unlock(&up->port.lock);
        local_irq_restore(flags);
@@@ -1014,7 -1114,7 +1114,7 @@@ static struct console serial_omap_conso
  
  static void serial_omap_add_console_port(struct uart_omap_port *up)
  {
-       serial_omap_console_ports[up->pdev->id] = up;
+       serial_omap_console_ports[up->port.line] = up;
  }
  
  #define OMAP_CONSOLE  (&serial_omap_console)
@@@ -1060,26 -1160,30 +1160,30 @@@ static struct uart_driver serial_omap_r
        .cons           = OMAP_CONSOLE,
  };
  
- static int
- serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+ #ifdef CONFIG_SUSPEND
+ static int serial_omap_suspend(struct device *dev)
  {
-       struct uart_omap_port *up = platform_get_drvdata(pdev);
+       struct uart_omap_port *up = dev_get_drvdata(dev);
  
-       if (up)
+       if (up) {
                uart_suspend_port(&serial_omap_reg, &up->port);
+               flush_work_sync(&up->qos_work);
+       }
        return 0;
  }
  
- static int serial_omap_resume(struct platform_device *dev)
+ static int serial_omap_resume(struct device *dev)
  {
-       struct uart_omap_port *up = platform_get_drvdata(dev);
+       struct uart_omap_port *up = dev_get_drvdata(dev);
  
        if (up)
                uart_resume_port(&serial_omap_reg, &up->port);
        return 0;
  }
+ #endif
  
- static void serial_omap_rx_timeout(unsigned long uart_no)
+ static void serial_omap_rxdma_poll(unsigned long uart_no)
  {
        struct uart_omap_port *up = ui[uart_no];
        unsigned int curr_dma_pos, curr_transmitted_size;
        if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
                             (curr_dma_pos == 0)) {
                if (jiffies_to_msecs(jiffies - up->port_activity) <
-                                                       RX_TIMEOUT) {
+                                               up->uart_dma.rx_timeout) {
                        mod_timer(&up->uart_dma.rx_timer, jiffies +
-                               usecs_to_jiffies(up->uart_dma.rx_timeout));
+                               usecs_to_jiffies(up->uart_dma.rx_poll_rate));
                } else {
                        serial_omap_stop_rxdma(up);
                        up->ier |= (UART_IER_RDI | UART_IER_RLSI);
                }
        } else  {
                mod_timer(&up->uart_dma.rx_timer, jiffies +
-                       usecs_to_jiffies(up->uart_dma.rx_timeout));
+                       usecs_to_jiffies(up->uart_dma.rx_poll_rate));
        }
        up->port_activity = jiffies;
  }
@@@ -1135,6 -1239,7 +1239,7 @@@ static int serial_omap_start_rxdma(stru
        int ret = 0;
  
        if (up->uart_dma.rx_dma_channel == -1) {
+               pm_runtime_get_sync(&up->pdev->dev);
                ret = omap_request_dma(up->uart_dma.uart_dma_rx,
                                "UART Rx DMA",
                                (void *)uart_rx_dma_callback, up,
        /* FIXME: Cache maintenance needed here? */
        omap_start_dma(up->uart_dma.rx_dma_channel);
        mod_timer(&up->uart_dma.rx_timer, jiffies +
-                               usecs_to_jiffies(up->uart_dma.rx_timeout));
+                               usecs_to_jiffies(up->uart_dma.rx_poll_rate));
        up->uart_dma.rx_dma_used = true;
        return ret;
  }
@@@ -1221,6 -1326,19 +1326,19 @@@ static void uart_tx_dma_callback(int lc
        return;
  }
  
+ static struct omap_uart_port_info *of_get_uart_port_info(struct device *dev)
+ {
+       struct omap_uart_port_info *omap_up_info;
+       omap_up_info = devm_kzalloc(dev, sizeof(*omap_up_info), GFP_KERNEL);
+       if (!omap_up_info)
+               return NULL; /* out of memory */
+       of_property_read_u32(dev->of_node, "clock-frequency",
+                                        &omap_up_info->uartclk);
+       return omap_up_info;
+ }
  static int serial_omap_probe(struct platform_device *pdev)
  {
        struct uart_omap_port   *up;
        struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
        int ret = -ENOSPC;
  
+       if (pdev->dev.of_node)
+               omap_up_info = of_get_uart_port_info(&pdev->dev);
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
                dev_err(&pdev->dev, "no mem resource?\n");
                ret = -ENOMEM;
                goto do_release_region;
        }
-       sprintf(up->name, "OMAP UART%d", pdev->id);
        up->pdev = pdev;
        up->port.dev = &pdev->dev;
        up->port.type = PORT_OMAP;
        up->port.regshift = 2;
        up->port.fifosize = 64;
        up->port.ops = &serial_omap_pops;
-       up->port.line = pdev->id;
  
-       up->port.membase = omap_up_info->membase;
-       up->port.mapbase = omap_up_info->mapbase;
+       if (pdev->dev.of_node)
+               up->port.line = of_alias_get_id(pdev->dev.of_node, "serial");
+       else
+               up->port.line = pdev->id;
+       if (up->port.line < 0) {
+               dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n",
+                                                               up->port.line);
+               ret = -ENODEV;
+               goto err;
+       }
+       sprintf(up->name, "OMAP UART%d", up->port.line);
+       up->port.mapbase = mem->start;
+       up->port.membase = ioremap(mem->start, resource_size(mem));
+       if (!up->port.membase) {
+               dev_err(&pdev->dev, "can't ioremap UART\n");
+               ret = -ENOMEM;
+               goto err;
+       }
        up->port.flags = omap_up_info->flags;
-       up->port.irqflags = omap_up_info->irqflags;
        up->port.uartclk = omap_up_info->uartclk;
+       if (!up->port.uartclk) {
+               up->port.uartclk = DEFAULT_CLK_SPEED;
+               dev_warn(&pdev->dev, "No clock speed specified: using default:"
+                                               "%d\n", DEFAULT_CLK_SPEED);
+       }
        up->uart_dma.uart_base = mem->start;
+       up->errata = omap_up_info->errata;
  
        if (omap_up_info->dma_enabled) {
                up->uart_dma.uart_dma_tx = dma_tx->start;
                up->uart_dma.uart_dma_rx = dma_rx->start;
                up->use_dma = 1;
-               up->uart_dma.rx_buf_size = 4096;
-               up->uart_dma.rx_timeout = 2;
+               up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
+               up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
+               up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate;
                spin_lock_init(&(up->uart_dma.tx_lock));
                spin_lock_init(&(up->uart_dma.rx_lock));
                up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
                up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
        }
  
-       ui[pdev->id] = up;
+       up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+       up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+       pm_qos_add_request(&up->pm_qos_request,
+               PM_QOS_CPU_DMA_LATENCY, up->latency);
+       serial_omap_uart_wq = create_singlethread_workqueue(up->name);
+       INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev,
+                       omap_up_info->autosuspend_timeout);
+       pm_runtime_irq_safe(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+       ui[up->port.line] = up;
        serial_omap_add_console_port(up);
  
        ret = uart_add_one_port(&serial_omap_reg, &up->port);
        if (ret != 0)
                goto do_release_region;
  
+       pm_runtime_put(&pdev->dev);
        platform_set_drvdata(pdev, up);
        return 0;
  err:
@@@ -1315,22 -1475,168 +1475,168 @@@ static int serial_omap_remove(struct pl
  {
        struct uart_omap_port *up = platform_get_drvdata(dev);
  
-       platform_set_drvdata(dev, NULL);
        if (up) {
+               pm_runtime_disable(&up->pdev->dev);
                uart_remove_one_port(&serial_omap_reg, &up->port);
+               pm_qos_remove_request(&up->pm_qos_request);
                kfree(up);
        }
+       platform_set_drvdata(dev, NULL);
+       return 0;
+ }
+ /*
+  * Work Around for Errata i202 (2430, 3430, 3630, 4430 and 4460)
+  * The access to uart register after MDR1 Access
+  * causes UART to corrupt data.
+  *
+  * Need a delay =
+  * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
+  * give 10 times as much
+  */
+ static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1)
+ {
+       u8 timeout = 255;
+       serial_out(up, UART_OMAP_MDR1, mdr1);
+       udelay(2);
+       serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
+                       UART_FCR_CLEAR_RCVR);
+       /*
+        * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
+        * TX_FIFO_E bit is 1.
+        */
+       while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
+                               (UART_LSR_THRE | UART_LSR_DR))) {
+               timeout--;
+               if (!timeout) {
+                       /* Should *never* happen. we warn and carry on */
+                       dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
+                                               serial_in(up, UART_LSR));
+                       break;
+               }
+               udelay(1);
+       }
+ }
+ static void serial_omap_restore_context(struct uart_omap_port *up)
+ {
+       if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+               serial_omap_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
+       else
+               serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+       serial_out(up, UART_EFR, UART_EFR_ECB);
+       serial_out(up, UART_LCR, 0x0); /* Operational mode */
+       serial_out(up, UART_IER, 0x0);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+       serial_out(up, UART_DLL, up->dll);
+       serial_out(up, UART_DLM, up->dlh);
+       serial_out(up, UART_LCR, 0x0); /* Operational mode */
+       serial_out(up, UART_IER, up->ier);
+       serial_out(up, UART_FCR, up->fcr);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+       serial_out(up, UART_MCR, up->mcr);
+       serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+       serial_out(up, UART_OMAP_SCR, up->scr);
+       serial_out(up, UART_EFR, up->efr);
+       serial_out(up, UART_LCR, up->lcr);
+       if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+               serial_omap_mdr1_errataset(up, up->mdr1);
+       else
+               serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ }
+ #ifdef CONFIG_PM_RUNTIME
+ static int serial_omap_runtime_suspend(struct device *dev)
+ {
+       struct uart_omap_port *up = dev_get_drvdata(dev);
+       struct omap_uart_port_info *pdata = dev->platform_data;
+       if (!up)
+               return -EINVAL;
+       if (!pdata || !pdata->enable_wakeup)
+               return 0;
+       if (pdata->get_context_loss_count)
+               up->context_loss_cnt = pdata->get_context_loss_count(dev);
+       if (device_may_wakeup(dev)) {
+               if (!up->wakeups_enabled) {
+                       pdata->enable_wakeup(up->pdev, true);
+                       up->wakeups_enabled = true;
+               }
+       } else {
+               if (up->wakeups_enabled) {
+                       pdata->enable_wakeup(up->pdev, false);
+                       up->wakeups_enabled = false;
+               }
+       }
+       /* Errata i291 */
+       if (up->use_dma && pdata->set_forceidle &&
+                       (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
+               pdata->set_forceidle(up->pdev);
+       up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
+       schedule_work(&up->qos_work);
+       return 0;
+ }
+ static int serial_omap_runtime_resume(struct device *dev)
+ {
+       struct uart_omap_port *up = dev_get_drvdata(dev);
+       struct omap_uart_port_info *pdata = dev->platform_data;
+       if (up) {
+               if (pdata->get_context_loss_count) {
+                       u32 loss_cnt = pdata->get_context_loss_count(dev);
+                       if (up->context_loss_cnt != loss_cnt)
+                               serial_omap_restore_context(up);
+               }
+               /* Errata i291 */
+               if (up->use_dma && pdata->set_noidle &&
+                               (up->errata & UART_ERRATA_i291_DMA_FORCEIDLE))
+                       pdata->set_noidle(up->pdev);
+               up->latency = up->calc_latency;
+               schedule_work(&up->qos_work);
+       }
        return 0;
  }
+ #endif
+ static const struct dev_pm_ops serial_omap_dev_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume)
+       SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend,
+                               serial_omap_runtime_resume, NULL)
+ };
+ #if defined(CONFIG_OF)
+ static const struct of_device_id omap_serial_of_match[] = {
+       { .compatible = "ti,omap2-uart" },
+       { .compatible = "ti,omap3-uart" },
+       { .compatible = "ti,omap4-uart" },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
+ #endif
  
  static struct platform_driver serial_omap_driver = {
        .probe          = serial_omap_probe,
        .remove         = serial_omap_remove,
-       .suspend        = serial_omap_suspend,
-       .resume         = serial_omap_resume,
        .driver         = {
                .name   = DRIVER_NAME,
+               .pm     = &serial_omap_dev_pm_ops,
+               .of_match_table = of_match_ptr(omap_serial_of_match),
        },
  };