]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'pm-runtime' of ssh://master.kernel.org/pub/scm/linux/kernel/git/khilman...
authorTony Lindgren <tony@atomide.com>
Fri, 24 Sep 2010 00:29:36 +0000 (17:29 -0700)
committerTony Lindgren <tony@atomide.com>
Fri, 24 Sep 2010 00:29:36 +0000 (17:29 -0700)
22 files changed:
arch/arm/mach-omap1/board-htcherald.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm2xxx_3xxx.c [new file with mode: 0644]
arch/arm/mach-omap2/prm44xx.c [new file with mode: 0644]
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/plat/common.h
arch/arm/plat-omap/include/plat/omap_device.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/include/plat/prcm.h
arch/arm/plat-omap/omap_device.c

index 311899ff5ffcdfee5425f2f949cd1828863eea2b..7ea75c11653c25178dbaa16c02a1f31c5bd31edb 100644 (file)
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/htcpld.h>
+#include <linux/leds.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -39,6 +46,7 @@
 #include <plat/board.h>
 #include <plat/keypad.h>
 #include <plat/usb.h>
+#include <plat/mmc.h>
 
 #include <mach/irqs.h>
 
 #define       OMAP_LCDC_CTRL_LCD_EN           (1 << 0)
 #define       OMAP_LCDC_STAT_DONE             (1 << 0)
 
-static struct omap_lcd_config htcherald_lcd_config __initdata = {
-       .ctrl_name      = "internal",
-};
+/* GPIO definitions for the power button and keyboard slide switch */
+#define HTCHERALD_GPIO_POWER 139
+#define HTCHERALD_GPIO_SLIDE 174
+#define HTCHERALD_GIRQ_BTNS 141
 
-static struct omap_board_config_kernel htcherald_config[] __initdata = {
-       { OMAP_TAG_LCD, &htcherald_lcd_config },
-};
+/* GPIO definitions for the touchscreen */
+#define HTCHERALD_GPIO_TS 76
+
+/* HTCPLD definitions */
+
+/*
+ * CPLD Logic
+ *
+ * Chip 3 - 0x03
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * DPAD light          x x x x  x x x 1
+ * SoundDev            x x x x  1 x x x
+ * Screen white        1 x x x  x x x x
+ * MMC power on        x x x x  x 1 x x
+ * Happy times (n)     0 x x x  x 1 x x
+ *
+ * Chip 4 - 0x04
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Keyboard light      x x x x  x x x 1
+ * LCD Bright (4)      x x x x  x 1 1 x
+ * LCD Bright (3)      x x x x  x 0 1 x
+ * LCD Bright (2)      x x x x  x 1 0 x
+ * LCD Bright (1)      x x x x  x 0 0 x
+ * LCD Off             x x x x  0 x x x
+ * LCD image (fb)      1 x x x  x x x x
+ * LCD image (white)   0 x x x  x x x x
+ * Caps lock LED       x x 1 x  x x x x
+ *
+ * Chip 5 - 0x05
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Red (solid)         x x x x  x 1 x x
+ * Red (flash)         x x x x  x x 1 x
+ * Green (GSM flash)   x x x x  1 x x x
+ * Green (GSM solid)   x x x 1  x x x x
+ * Green (wifi flash)  x x 1 x  x x x x
+ * Blue (bt flash)     x 1 x x  x x x x
+ * DPAD Int Enable     1 x x x  x x x 0
+ *
+ * (Combinations of the above can be made for different colors.)
+ * The direction pad interrupt enable must be set each time the
+ * interrupt is handled.
+ *
+ * Chip 6 - 0x06
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Vibrator            x x x x  1 x x x
+ * Alt LED             x x x 1  x x x x
+ * Screen white        1 x x x  x x x x
+ * Screen white        x x 1 x  x x x x
+ * Screen white        x 0 x x  x x x x
+ * Enable kbd dpad     x x x x  x x 0 x
+ * Happy Times         0 1 0 x  x x 0 x
+ */
+
+/*
+ * HTCPLD GPIO lines start 16 after OMAP_MAX_GPIO_LINES to account
+ * for the 16 MPUIO lines.
+ */
+#define HTCPLD_GPIO_START_OFFSET       (OMAP_MAX_GPIO_LINES + 16)
+#define HTCPLD_IRQ(chip, offset)       (OMAP_IRQ_END + 8 * (chip) + (offset))
+#define HTCPLD_BASE(chip, offset)      \
+       (HTCPLD_GPIO_START_OFFSET + 8 * (chip) + (offset))
+
+#define HTCPLD_GPIO_LED_DPAD           HTCPLD_BASE(0, 0)
+#define HTCPLD_GPIO_LED_KBD            HTCPLD_BASE(1, 0)
+#define HTCPLD_GPIO_LED_CAPS           HTCPLD_BASE(1, 5)
+#define HTCPLD_GPIO_LED_RED_FLASH      HTCPLD_BASE(2, 1)
+#define HTCPLD_GPIO_LED_RED_SOLID      HTCPLD_BASE(2, 2)
+#define HTCPLD_GPIO_LED_GREEN_FLASH    HTCPLD_BASE(2, 3)
+#define HTCPLD_GPIO_LED_GREEN_SOLID    HTCPLD_BASE(2, 4)
+#define HTCPLD_GPIO_LED_WIFI           HTCPLD_BASE(2, 5)
+#define HTCPLD_GPIO_LED_BT             HTCPLD_BASE(2, 6)
+#define HTCPLD_GPIO_LED_VIBRATE                HTCPLD_BASE(3, 3)
+#define HTCPLD_GPIO_LED_ALT            HTCPLD_BASE(3, 4)
+
+#define HTCPLD_GPIO_RIGHT_KBD          HTCPLD_BASE(6, 7)
+#define HTCPLD_GPIO_UP_KBD             HTCPLD_BASE(6, 6)
+#define HTCPLD_GPIO_LEFT_KBD           HTCPLD_BASE(6, 5)
+#define HTCPLD_GPIO_DOWN_KBD           HTCPLD_BASE(6, 4)
+
+#define HTCPLD_GPIO_RIGHT_DPAD         HTCPLD_BASE(7, 7)
+#define HTCPLD_GPIO_UP_DPAD            HTCPLD_BASE(7, 6)
+#define HTCPLD_GPIO_LEFT_DPAD          HTCPLD_BASE(7, 5)
+#define HTCPLD_GPIO_DOWN_DPAD          HTCPLD_BASE(7, 4)
+#define HTCPLD_GPIO_ENTER_DPAD         HTCPLD_BASE(7, 3)
+
+/*
+ * The htcpld chip requires a gpio write to a specific line
+ * to re-enable interrupts after one has occurred.
+ */
+#define HTCPLD_GPIO_INT_RESET_HI       HTCPLD_BASE(2, 7)
+#define HTCPLD_GPIO_INT_RESET_LO       HTCPLD_BASE(2, 0)
+
+/* Chip 5 */
+#define HTCPLD_IRQ_RIGHT_KBD           HTCPLD_IRQ(0, 7)
+#define HTCPLD_IRQ_UP_KBD              HTCPLD_IRQ(0, 6)
+#define HTCPLD_IRQ_LEFT_KBD            HTCPLD_IRQ(0, 5)
+#define HTCPLD_IRQ_DOWN_KBD            HTCPLD_IRQ(0, 4)
+
+/* Chip 6 */
+#define HTCPLD_IRQ_RIGHT_DPAD          HTCPLD_IRQ(1, 7)
+#define HTCPLD_IRQ_UP_DPAD             HTCPLD_IRQ(1, 6)
+#define HTCPLD_IRQ_LEFT_DPAD           HTCPLD_IRQ(1, 5)
+#define HTCPLD_IRQ_DOWN_DPAD           HTCPLD_IRQ(1, 4)
+#define HTCPLD_IRQ_ENTER_DPAD          HTCPLD_IRQ(1, 3)
 
 /* Keyboard definition */
 
@@ -140,6 +258,129 @@ static struct platform_device kp_device = {
        .resource       = kp_resources,
 };
 
+/* GPIO buttons for keyboard slide and power button */
+static struct gpio_keys_button herald_gpio_keys_table[] = {
+       {BTN_0,  HTCHERALD_GPIO_POWER, 1, "POWER", EV_KEY, 1, 20},
+       {SW_LID, HTCHERALD_GPIO_SLIDE, 0, "SLIDE", EV_SW,  1, 20},
+
+       {KEY_LEFT,  HTCPLD_GPIO_LEFT_KBD,  1, "LEFT",  EV_KEY, 1, 20},
+       {KEY_RIGHT, HTCPLD_GPIO_RIGHT_KBD, 1, "RIGHT", EV_KEY, 1, 20},
+       {KEY_UP,    HTCPLD_GPIO_UP_KBD,    1, "UP",    EV_KEY, 1, 20},
+       {KEY_DOWN,  HTCPLD_GPIO_DOWN_KBD,  1, "DOWN",  EV_KEY, 1, 20},
+
+       {KEY_LEFT,  HTCPLD_GPIO_LEFT_DPAD,   1, "DLEFT",  EV_KEY, 1, 20},
+       {KEY_RIGHT, HTCPLD_GPIO_RIGHT_DPAD,  1, "DRIGHT", EV_KEY, 1, 20},
+       {KEY_UP,    HTCPLD_GPIO_UP_DPAD,     1, "DUP",    EV_KEY, 1, 20},
+       {KEY_DOWN,  HTCPLD_GPIO_DOWN_DPAD,   1, "DDOWN",  EV_KEY, 1, 20},
+       {KEY_ENTER, HTCPLD_GPIO_ENTER_DPAD,  1, "DENTER", EV_KEY, 1, 20},
+};
+
+static struct gpio_keys_platform_data herald_gpio_keys_data = {
+       .buttons        = herald_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(herald_gpio_keys_table),
+       .rep            = 1,
+};
+
+static struct platform_device herald_gpiokeys_device = {
+       .name      = "gpio-keys",
+       .id             = -1,
+       .dev = {
+               .platform_data = &herald_gpio_keys_data,
+       },
+};
+
+/* LEDs for the Herald.  These connect to the HTCPLD GPIO device. */
+static struct gpio_led gpio_leds[] = {
+       {"dpad",        NULL, HTCPLD_GPIO_LED_DPAD,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"kbd",         NULL, HTCPLD_GPIO_LED_KBD,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"vibrate",     NULL, HTCPLD_GPIO_LED_VIBRATE,     0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"green_solid", NULL, HTCPLD_GPIO_LED_GREEN_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"green_flash", NULL, HTCPLD_GPIO_LED_GREEN_FLASH, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"red_solid",   "mmc0", HTCPLD_GPIO_LED_RED_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"red_flash",   NULL, HTCPLD_GPIO_LED_RED_FLASH,   0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"wifi",        NULL, HTCPLD_GPIO_LED_WIFI,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"bt",          NULL, HTCPLD_GPIO_LED_BT,          0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"caps",        NULL, HTCPLD_GPIO_LED_CAPS,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"alt",         NULL, HTCPLD_GPIO_LED_ALT,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+};
+
+static struct gpio_led_platform_data gpio_leds_data = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+       .name           = "leds-gpio",
+       .id             = 0,
+       .dev    = {
+               .platform_data  = &gpio_leds_data,
+       },
+};
+
+/* HTC PLD chips */
+
+static struct resource htcpld_resources[] = {
+       [0] = {
+               .start  = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+               .end    = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct htcpld_chip_platform_data htcpld_chips[] = {
+       [0] = {
+               .addr           = 0x03,
+               .reset          = 0x04,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(0, 0),
+               .gpio_in_base   = HTCPLD_BASE(4, 0),
+       },
+       [1] = {
+               .addr           = 0x04,
+               .reset          = 0x8e,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(1, 0),
+               .gpio_in_base   = HTCPLD_BASE(5, 0),
+       },
+       [2] = {
+               .addr           = 0x05,
+               .reset          = 0x80,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(2, 0),
+               .gpio_in_base   = HTCPLD_BASE(6, 0),
+               .irq_base       = HTCPLD_IRQ(0, 0),
+               .num_irqs       = 8,
+       },
+       [3] = {
+               .addr           = 0x06,
+               .reset          = 0x40,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(3, 0),
+               .gpio_in_base   = HTCPLD_BASE(7, 0),
+               .irq_base       = HTCPLD_IRQ(1, 0),
+               .num_irqs       = 8,
+       },
+};
+
+struct htcpld_core_platform_data htcpld_pfdata = {
+       .int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
+       .int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
+       .i2c_adapter_id    = 1,
+
+       .chip              = htcpld_chips,
+       .num_chip          = ARRAY_SIZE(htcpld_chips),
+};
+
+static struct platform_device htcpld_device = {
+       .name           = "i2c-htcpld",
+       .id             = -1,
+       .resource       = htcpld_resources,
+       .num_resources  = ARRAY_SIZE(htcpld_resources),
+       .dev    = {
+               .platform_data  = &htcpld_pfdata,
+       },
+};
+
 /* USB Device */
 static struct omap_usb_config htcherald_usb_config __initdata = {
        .otg = 0,
@@ -150,14 +391,72 @@ static struct omap_usb_config htcherald_usb_config __initdata = {
 };
 
 /* LCD Device resources */
+static struct omap_lcd_config htcherald_lcd_config __initdata = {
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel htcherald_config[] __initdata = {
+       { OMAP_TAG_LCD, &htcherald_lcd_config },
+};
+
 static struct platform_device lcd_device = {
        .name           = "lcd_htcherald",
        .id             = -1,
 };
 
+/* MMC Card */
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+static struct omap_mmc_platform_data htc_mmc1_data = {
+       .nr_slots                       = 1,
+       .switch_slot                    = NULL,
+       .slots[0]       = {
+               .ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
+                                         MMC_VDD_32_33 | MMC_VDD_33_34,
+               .name                   = "mmcblk",
+               .nomux                  = 1,
+               .wires                  = 4,
+               .switch_pin             = -1,
+       },
+};
+
+static struct omap_mmc_platform_data *htc_mmc_data[1];
+#endif
+
+
+/* Platform devices for the Herald */
 static struct platform_device *devices[] __initdata = {
        &kp_device,
        &lcd_device,
+       &htcpld_device,
+       &gpio_leds_device,
+       &herald_gpiokeys_device,
+};
+
+/*
+ * Touchscreen
+ */
+static const struct ads7846_platform_data htcherald_ts_platform_data = {
+       .model                  = 7846,
+       .keep_vref_on           = 1,
+       .x_plate_ohms           = 496,
+       .gpio_pendown           = HTCHERALD_GPIO_TS,
+       .pressure_max           = 100000,
+       .pressure_min           = 5000,
+       .x_min                  = 528,
+       .x_max                  = 3760,
+       .y_min                  = 624,
+       .y_max                  = 3760,
+};
+
+static struct spi_board_info __initdata htcherald_spi_board_info[] = {
+       {
+               .modalias               = "ads7846",
+               .platform_data          = &htcherald_ts_platform_data,
+               .irq                    = OMAP_GPIO_IRQ(HTCHERALD_GPIO_TS),
+               .max_speed_hz           = 2500000,
+               .bus_num                = 2,
+               .chip_select            = 1,
+       }
 };
 
 /*
@@ -278,6 +577,7 @@ static void __init htcherald_init(void)
 {
        printk(KERN_INFO "HTC Herald init.\n");
 
+       /* Do board initialization before we register all the devices */
        omap_gpio_init();
 
        omap_board_config = htcherald_config;
@@ -288,6 +588,16 @@ static void __init htcherald_init(void)
 
        htcherald_usb_enable();
        omap1_usb_init(&htcherald_usb_config);
+
+       spi_register_board_info(htcherald_spi_board_info,
+               ARRAY_SIZE(htcherald_spi_board_info));
+
+       omap_register_i2c_bus(1, 100, NULL, 0);
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+       htc_mmc_data[0] = &htc_mmc1_data;
+       omap1_init_mmc(htc_mmc_data, 1);
+#endif
 }
 
 static void __init htcherald_init_irq(void)
index b48ca6039d83d1ad63c3669819e5dd7c12fc73a0..e599ae2a5de42ff44a374bb6ecf5fe76473d327d 100644 (file)
@@ -5,7 +5,7 @@
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o
 
-omap-2-3-common                                = irq.o sdrc.o
+omap-2-3-common                                = irq.o sdrc.o prm2xxx_3xxx.o
 hwmod-common                           = omap_hwmod.o \
                                          omap_hwmod_common_data.o
 prcm-common                            = prcm.o powerdomain.o
@@ -15,7 +15,7 @@ clock-common                          = clock.o clock_common_data.o \
 
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
-obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
@@ -91,6 +91,7 @@ obj-$(CONFIG_ARCH_OMAP2430)           += opp2430_data.o
 obj-$(CONFIG_ARCH_OMAP2420)            += omap_hwmod_2420_data.o
 obj-$(CONFIG_ARCH_OMAP2430)            += omap_hwmod_2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)               += omap_hwmod_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)               += omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)                        += emu.o
index 5d80cb897489505839a847c460cc9ade5e1bb05b..6fb61b1a0d46105f7d18fb8434d3d91caaa4be41 100644 (file)
@@ -258,97 +258,6 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
 
 }
 
-/**
- * _init_wkdep_usecount - initialize wkdep usecounts to match hardware
- * @clkdm: clockdomain to initialize wkdep usecounts
- *
- * Initialize the wakeup dependency usecount variables for clockdomain @clkdm.
- * If a wakeup dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software wakeup dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_wkdep_usecount(struct clockdomain *clkdm)
-{
-       u32 v;
-       struct clkdm_dep *cd;
-
-       if (!clkdm->wkdep_srcs)
-               return;
-
-       for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) {
-               if (!omap_chip_is(cd->omap_chip))
-                       continue;
-
-               if (!cd->clkdm && cd->clkdm_name)
-                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-               if (!cd->clkdm) {
-                       WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not "
-                            "found\n", clkdm->name, cd->clkdm_name);
-                       continue;
-               }
-
-               v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-                                           PM_WKDEP,
-                                           (1 << cd->clkdm->dep_bit));
-
-               if (v)
-                       pr_debug("clockdomain: %s: wakeup dependency already "
-                                "set to wake up when %s wakes\n",
-                                clkdm->name, cd->clkdm->name);
-
-               atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0);
-       }
-}
-
-/**
- * _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware
- * @clkdm: clockdomain to initialize sleepdep usecounts
- *
- * Initialize the sleep dependency usecount variables for clockdomain @clkdm.
- * If a sleep dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software sleep dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_sleepdep_usecount(struct clockdomain *clkdm)
-{
-       u32 v;
-       struct clkdm_dep *cd;
-
-       if (!cpu_is_omap34xx())
-               return;
-
-       if (!clkdm->sleepdep_srcs)
-               return;
-
-       for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) {
-               if (!omap_chip_is(cd->omap_chip))
-                       continue;
-
-               if (!cd->clkdm && cd->clkdm_name)
-                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-               if (!cd->clkdm) {
-                       WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s "
-                            "not found\n", clkdm->name, cd->clkdm_name);
-                       continue;
-               }
-
-               v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-                                           OMAP3430_CM_SLEEPDEP,
-                                           (1 << cd->clkdm->dep_bit));
-
-               if (v)
-                       pr_debug("clockdomain: %s: sleep dependency already "
-                                "set to prevent from idling until %s "
-                                "idles\n", clkdm->name, cd->clkdm->name);
-
-               atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0);
-       }
-};
-
 /* Public functions */
 
 /**
@@ -379,12 +288,17 @@ void clkdm_init(struct clockdomain **clkdms,
                        _autodep_lookup(autodep);
 
        /*
-        * Ensure that the *dep_usecount registers reflect the current
-        * state of the PRCM.
+        * Put all clockdomains into software-supervised mode; PM code
+        * should later enable hardware-supervised mode as appropriate
         */
        list_for_each_entry(clkdm, &clkdm_list, node) {
-               _init_wkdep_usecount(clkdm);
-               _init_sleepdep_usecount(clkdm);
+               if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+                       omap2_clkdm_wakeup(clkdm);
+               else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
+                       omap2_clkdm_deny_idle(clkdm);
+
+               clkdm_clear_all_wkdeps(clkdm);
+               clkdm_clear_all_sleepdeps(clkdm);
        }
 }
 
@@ -592,6 +506,9 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
                if (!omap_chip_is(cd->omap_chip))
                        continue;
 
+               if (!cd->clkdm && cd->clkdm_name)
+                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
                /* PRM accesses are slow, so minimize them */
                mask |= 1 << cd->clkdm->dep_bit;
                atomic_set(&cd->wkdep_usecount, 0);
@@ -752,6 +669,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
                if (!omap_chip_is(cd->omap_chip))
                        continue;
 
+               if (!cd->clkdm && cd->clkdm_name)
+                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
                /* PRM accesses are slow, so minimize them */
                mask |= 1 << cd->clkdm->dep_bit;
                atomic_set(&cd->sleepdep_usecount, 0);
index 3d3d035db9aff62ce522e0080e570cfdbf8e70cc..8ea012ef0b5a7f5b34ca9c6467ac1c942e71c3cb 100644 (file)
@@ -60,7 +60,8 @@ struct omap3_processor_cx {
 
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
 struct omap3_processor_cx current_cx_state;
-struct powerdomain *mpu_pd, *core_pd;
+struct powerdomain *mpu_pd, *core_pd, *per_pd;
+struct powerdomain *cam_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -233,14 +234,62 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
                               struct cpuidle_state *state)
 {
        struct cpuidle_state *new_state = next_valid_state(dev, state);
+       u32 core_next_state, per_next_state = 0, per_saved_state = 0;
+       u32 cam_state;
+       struct omap3_processor_cx *cx;
+       int ret;
 
        if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
                BUG_ON(!dev->safe_state);
                new_state = dev->safe_state;
+               goto select_state;
+       }
+
+       cx = cpuidle_get_statedata(state);
+       core_next_state = cx->core_state;
+
+       /*
+        * FIXME: we currently manage device-specific idle states
+        *        for PER and CORE in combination with CPU-specific
+        *        idle states.  This is wrong, and device-specific
+        *        idle managment needs to be separated out into 
+        *        its own code.
+        */
+
+       /*
+        * Prevent idle completely if CAM is active.
+        * CAM does not have wakeup capability in OMAP3.
+        */
+       cam_state = pwrdm_read_pwrst(cam_pd);
+       if (cam_state == PWRDM_POWER_ON) {
+               new_state = dev->safe_state;
+               goto select_state;
+       }
+
+       /*
+        * Prevent PER off if CORE is not in retention or off as this
+        * would disable PER wakeups completely.
+        */
+       per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
+       if ((per_next_state == PWRDM_POWER_OFF) &&
+           (core_next_state > PWRDM_POWER_RET)) {
+               per_next_state = PWRDM_POWER_RET;
+               pwrdm_set_next_pwrst(per_pd, per_next_state);
        }
 
+       /* Are we changing PER target state? */
+       if (per_next_state != per_saved_state)
+               pwrdm_set_next_pwrst(per_pd, per_next_state);
+
+select_state:
        dev->last_state = new_state;
-       return omap3_enter_idle(dev, new_state);
+       ret = omap3_enter_idle(dev, new_state);
+
+       /* Restore original PER state if it was modified */
+       if (per_next_state != per_saved_state)
+               pwrdm_set_next_pwrst(per_pd, per_saved_state);
+
+       return ret;
 }
 
 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
@@ -328,7 +377,8 @@ void omap_init_power_states(void)
                        cpuidle_params_table[OMAP3_STATE_C2].threshold;
        omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
        omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
-       omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
+       omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
+                               CPUIDLE_FLAG_CHECK_BM;
 
        /* C3 . MPU CSWR + Core inactive */
        omap3_power_states[OMAP3_STATE_C3].valid =
@@ -426,6 +476,8 @@ int __init omap3_idle_init(void)
 
        mpu_pd = pwrdm_lookup("mpu_pwrdm");
        core_pd = pwrdm_lookup("core_pwrdm");
+       per_pd = pwrdm_lookup("per_pwrdm");
+       cam_pd = pwrdm_lookup("cam_pwrdm");
 
        omap_init_power_states();
        cpuidle_register_driver(&omap3_idle_driver);
index b9ea70bce5635d431ef2651058bd72b0619420df..490d87082fad6162b5098921b772b489eaeaece3 100644 (file)
@@ -323,6 +323,9 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
                omap2430_hwmod_init();
        else if (cpu_is_omap34xx())
                omap3xxx_hwmod_init();
+       else if (cpu_is_omap44xx())
+               omap44xx_hwmod_init();
+
        /* The OPP tables have to be registered before a clk init */
        omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
 
@@ -342,9 +345,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
 #ifndef CONFIG_PM_RUNTIME
        skip_setup_idle = 1;
 #endif
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())   /* FIXME: OMAP4 */
-               omap_hwmod_late_init(skip_setup_idle);
-
+       omap_hwmod_late_init(skip_setup_idle);
        if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
                omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
                _omap2_init_reprogram_sdrc();
index cb911d7d1a3c1535ba88eda74577ea6ef2e1ecd0..c3a5889d8add44373762a0cb6833c6f1e3406928 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * This code manages "OMAP modules" (on-chip devices) and their
- * integration with Linux device driver and bus code.
- *
- * References:
+ * Introduction
+ * ------------
+ * One way to view an OMAP SoC is as a collection of largely unrelated
+ * IP blocks connected by interconnects.  The IP blocks include
+ * devices such as ARM processors, audio serial interfaces, UARTs,
+ * etc.  Some of these devices, like the DSP, are created by TI;
+ * others, like the SGX, largely originate from external vendors.  In
+ * TI's documentation, on-chip devices are referred to as "OMAP
+ * modules."  Some of these IP blocks are identical across several
+ * OMAP versions.  Others are revised frequently.
+ *
+ * These OMAP modules are tied together by various interconnects.
+ * Most of the address and data flow between modules is via OCP-based
+ * interconnects such as the L3 and L4 buses; but there are other
+ * interconnects that distribute the hardware clock tree, handle idle
+ * and reset signaling, supply power, and connect the modules to
+ * various pads or balls on the OMAP package.
+ *
+ * OMAP hwmod provides a consistent way to describe the on-chip
+ * hardware blocks and their integration into the rest of the chip.
+ * This description can be automatically generated from the TI
+ * hardware database.  OMAP hwmod provides a standard, consistent API
+ * to reset, enable, idle, and disable these hardware blocks.  And
+ * hwmod provides a way for other core code, such as the Linux device
+ * code or the OMAP power management and address space mapping code,
+ * to query the hardware database.
+ *
+ * Using hwmod
+ * -----------
+ * Drivers won't call hwmod functions directly.  That is done by the
+ * omap_device code, and in rare occasions, by custom integration code
+ * in arch/arm/ *omap*.  The omap_device code includes functions to
+ * build a struct platform_device using omap_hwmod data, and that is
+ * currently how hwmod data is communicated to drivers and to the
+ * Linux driver model.  Most drivers will call omap_hwmod functions only
+ * indirectly, via pm_runtime*() functions.
+ *
+ * From a layering perspective, here is where the OMAP hwmod code
+ * fits into the kernel software stack:
+ *
+ *            +-------------------------------+
+ *            |      Device driver code       |
+ *            |      (e.g., drivers/)         |
+ *            +-------------------------------+
+ *            |      Linux driver model       |
+ *            |     (platform_device /        |
+ *            |  platform_driver data/code)   |
+ *            +-------------------------------+
+ *            | OMAP core-driver integration  |
+ *            |(arch/arm/mach-omap2/devices.c)|
+ *            +-------------------------------+
+ *            |      omap_device code         |
+ *            | (../plat-omap/omap_device.c)  |
+ *            +-------------------------------+
+ *   ---->    |    omap_hwmod code/data       |    <-----
+ *            | (../mach-omap2/omap_hwmod*)   |
+ *            +-------------------------------+
+ *            | OMAP clock/PRCM/register fns  |
+ *            | (__raw_{read,write}l, clk*)   |
+ *            +-------------------------------+
+ *
+ * Device drivers should not contain any OMAP-specific code or data in
+ * them.  They should only contain code to operate the IP block that
+ * the driver is responsible for.  This is because these IP blocks can
+ * also appear in other SoCs, either from TI (such as DaVinci) or from
+ * other manufacturers; and drivers should be reusable across other
+ * platforms.
+ *
+ * The OMAP hwmod code also will attempt to reset and idle all on-chip
+ * devices upon boot.  The goal here is for the kernel to be
+ * completely self-reliant and independent from bootloaders.  This is
+ * to ensure a repeatable configuration, both to ensure consistent
+ * runtime behavior, and to make it easier for others to reproduce
+ * bugs.
+ *
+ * OMAP module activity states
+ * ---------------------------
+ * The hwmod code considers modules to be in one of several activity
+ * states.  IP blocks start out in an UNKNOWN state, then once they
+ * are registered via the hwmod code, proceed to the REGISTERED state.
+ * Once their clock names are resolved to clock pointers, the module
+ * enters the CLKS_INITED state; and finally, once the module has been
+ * reset and the integration registers programmed, the INITIALIZED state
+ * is entered.  The hwmod code will then place the module into either
+ * the IDLE state to save power, or in the case of a critical system
+ * module, the ENABLED state.
+ *
+ * OMAP core integration code can then call omap_hwmod*() functions
+ * directly to move the module between the IDLE, ENABLED, and DISABLED
+ * states, as needed.  This is done during both the PM idle loop, and
+ * in the OMAP core integration code's implementation of the PM runtime
+ * functions.
+ *
+ * References
+ * ----------
+ * This is a partial list.
  * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
  * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
  * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
 #include <plat/powerdomain.h>
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
+#include <plat/prcm.h>
 
 #include "cm.h"
+#include "prm.h"
 
-/* Maximum microseconds to wait for OMAP module to reset */
-#define MAX_MODULE_RESET_WAIT          10000
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT      10000
 
 /* Name of the OMAP hwmod for the MPU */
 #define MPU_INITIATOR_NAME             "mpu"
@@ -544,6 +638,36 @@ static int _disable_clocks(struct omap_hwmod *oh)
        return 0;
 }
 
+static void _enable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: enabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
+                                oc->_clk->name);
+                       clk_enable(oc->_clk);
+               }
+}
+
+static void _disable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: disabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
+                                oc->_clk->name);
+                       clk_disable(oc->_clk);
+               }
+}
+
 /**
  * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
  * @oh: struct omap_hwmod *
@@ -622,7 +746,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
 }
 
 /**
- * _sysc_enable - try to bring a module out of idle via OCP_SYSCONFIG
+ * _enable_sysc - try to bring a module out of idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module out of slave
@@ -630,7 +754,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
  * as SWSUP_MSUSPEND, force the module out of master standby;
  * otherwise, configure it for smart-standby.  No return value.
  */
-static void _sysc_enable(struct omap_hwmod *oh)
+static void _enable_sysc(struct omap_hwmod *oh)
 {
        u8 idlemode, sf;
        u32 v;
@@ -659,8 +783,6 @@ static void _sysc_enable(struct omap_hwmod *oh)
                _set_module_autoidle(oh, idlemode, &v);
        }
 
-       /* XXX OCP ENAWAKEUP bit? */
-
        /*
         * XXX The clock framework should handle this, by
         * calling into this code.  But this must wait until the
@@ -671,10 +793,14 @@ static void _sysc_enable(struct omap_hwmod *oh)
                _set_clockactivity(oh, oh->class->sysc->clockact, &v);
 
        _write_sysconfig(v, oh);
+
+       /* If slave is in SMARTIDLE, also enable wakeup */
+       if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
+               _enable_wakeup(oh);
 }
 
 /**
- * _sysc_idle - try to put a module into idle via OCP_SYSCONFIG
+ * _idle_sysc - try to put a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module into slave
@@ -682,7 +808,7 @@ static void _sysc_enable(struct omap_hwmod *oh)
  * as SWSUP_MSUSPEND, force the module into master standby; otherwise,
  * configure it for smart-standby.  No return value.
  */
-static void _sysc_idle(struct omap_hwmod *oh)
+static void _idle_sysc(struct omap_hwmod *oh)
 {
        u8 idlemode, sf;
        u32 v;
@@ -709,13 +835,13 @@ static void _sysc_idle(struct omap_hwmod *oh)
 }
 
 /**
- * _sysc_shutdown - force a module into idle via OCP_SYSCONFIG
+ * _shutdown_sysc - force a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * Force the module into slave idle and master suspend. No return
  * value.
  */
-static void _sysc_shutdown(struct omap_hwmod *oh)
+static void _shutdown_sysc(struct omap_hwmod *oh)
 {
        u32 v;
        u8 sf;
@@ -767,10 +893,10 @@ static struct omap_hwmod *_lookup(const char *name)
  * @data: not used; pass NULL
  *
  * Called by omap_hwmod_late_init() (after omap2_clk_init()).
- * Resolves all clock names embedded in the hwmod.  Must be called
- * with omap_hwmod_mutex held.  Returns -EINVAL if the omap_hwmod
- * has not yet been registered or if the clocks have already been
- * initialized, 0 on success, or a non-zero error on failure.
+ * Resolves all clock names embedded in the hwmod.  Returns -EINVAL if
+ * the omap_hwmod has not yet been registered or if the clocks have
+ * already been initialized, 0 on success, or a non-zero error on
+ * failure.
  */
 static int _init_clocks(struct omap_hwmod *oh, void *data)
 {
@@ -833,57 +959,203 @@ static int _wait_target_ready(struct omap_hwmod *oh)
        return ret;
 }
 
+/**
+ * _lookup_hardreset - return the register bit shift for this hwmod/reset line
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line in the context of this hwmod
+ *
+ * Return the bit position of the reset line that match the
+ * input name. Return -ENOENT if not found.
+ */
+static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int i;
+
+       for (i = 0; i < oh->rst_lines_cnt; i++) {
+               const char *rst_line = oh->rst_lines[i].name;
+               if (!strcmp(rst_line, name)) {
+                       u8 shift = oh->rst_lines[i].rst_shift;
+                       pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
+                                oh->name, rst_line, shift);
+
+                       return shift;
+               }
+       }
+
+       return -ENOENT;
+}
+
+/**
+ * _assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
+                                                 shift);
+       else if (cpu_is_omap44xx())
+               return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
+                                                 shift);
+       else
+               return -EINVAL;
+}
+
+/**
+ * _deassert_hardreset - deassert the HW reset line of submodules contained
+ * in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+       int r;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
+                                                shift);
+       else if (cpu_is_omap44xx())
+               r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
+                                                shift);
+       else
+               return -EINVAL;
+
+       if (r == -EBUSY)
+               pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
+
+       return r;
+}
+
+/**
+ * _read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the state of the reset line.
+ */
+static int _read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+               return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
+                                                      shift);
+       } else if (cpu_is_omap44xx()) {
+               return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
+                                                      shift);
+       } else {
+               return -EINVAL;
+       }
+}
+
 /**
  * _reset - reset an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit.  hwmod must be
- * enabled for this to work.  Must be called with omap_hwmod_mutex
- * held.  Returns -EINVAL if the hwmod cannot be reset this way or if
- * the hwmod is in the wrong state, -ETIMEDOUT if the module did not
- * reset in time, or 0 upon success.
+ * enabled for this to work.  Returns -EINVAL if the hwmod cannot be
+ * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
+ * the module did not reset in time, or 0 upon success.
+ *
+ * In OMAP3 a specific SYSSTATUS register is used to get the reset status.
+ * Starting in OMAP4, some IPs does not have SYSSTATUS register and instead
+ * use the SYSCONFIG softreset bit to provide the status.
+ *
+ * Note that some IP like McBSP does have a reset control but no reset status.
  */
 static int _reset(struct omap_hwmod *oh)
 {
-       u32 r, v;
+       u32 v;
        int c = 0;
+       int ret = 0;
 
        if (!oh->class->sysc ||
-           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET) ||
-           (oh->class->sysc->sysc_flags & SYSS_MISSING))
+           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
                return -EINVAL;
 
        /* clocks must be on for this operation */
        if (oh->_state != _HWMOD_STATE_ENABLED) {
-               WARN(1, "omap_hwmod: %s: reset can only be entered from "
-                    "enabled state\n", oh->name);
+               pr_warning("omap_hwmod: %s: reset can only be entered from "
+                          "enabled state\n", oh->name);
                return -EINVAL;
        }
 
+       /* For some modules, all optionnal clocks need to be enabled as well */
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _enable_optional_clocks(oh);
+
        pr_debug("omap_hwmod: %s: resetting\n", oh->name);
 
        v = oh->_sysc_cache;
-       r = _set_softreset(oh, &v);
-       if (r)
-               return r;
+       ret = _set_softreset(oh, &v);
+       if (ret)
+               goto dis_opt_clks;
        _write_sysconfig(v, oh);
 
-       omap_test_timeout((omap_hwmod_readl(oh, oh->class->sysc->syss_offs) &
-                          SYSS_RESETDONE_MASK),
-                         MAX_MODULE_RESET_WAIT, c);
-
-       if (c == MAX_MODULE_RESET_WAIT)
-               WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
-                    oh->name, MAX_MODULE_RESET_WAIT);
+       if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+               omap_test_timeout((omap_hwmod_readl(oh,
+                                                   oh->class->sysc->syss_offs)
+                                  & SYSS_RESETDONE_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
+               omap_test_timeout(!(omap_hwmod_readl(oh,
+                                                    oh->class->sysc->sysc_offs)
+                                  & SYSC_TYPE2_SOFTRESET_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT)
+               pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
+                          oh->name, MAX_MODULE_SOFTRESET_WAIT);
        else
-               pr_debug("omap_hwmod: %s: reset in %d usec\n", oh->name, c);
+               pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
 
        /*
         * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
         * _wait_target_ready() or _reset()
         */
 
-       return (c == MAX_MODULE_RESET_WAIT) ? -ETIMEDOUT : 0;
+       ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+dis_opt_clks:
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _disable_optional_clocks(oh);
+
+       return ret;
 }
 
 /**
@@ -891,9 +1163,11 @@ static int _reset(struct omap_hwmod *oh)
  * @oh: struct omap_hwmod *
  *
  * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
- * register target.  Must be called with omap_hwmod_mutex held.
- * Returns -EINVAL if the hwmod is in the wrong state or passes along
- * the return value of _wait_target_ready().
+ * register target.  (This function has a full name --
+ * _omap_hwmod_enable() rather than simply _enable() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or passes along the return value of
+ * _wait_target_ready().
  */
 int _omap_hwmod_enable(struct omap_hwmod *oh)
 {
@@ -909,6 +1183,15 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
 
        pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
+       /*
+        * If an IP contains only one HW reset line, then de-assert it in order
+        * to allow to enable the clocks. Otherwise the PRCM will return
+        * Intransition status, and the init will failed.
+        */
+       if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
+            oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
+               _deassert_hardreset(oh, oh->rst_lines[0].name);
+
        /* XXX mux balls */
 
        _add_initiator_dep(oh, mpu_oh);
@@ -922,7 +1205,7 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
                if (oh->class->sysc) {
                        if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
                                _update_sysc_cache(oh);
-                       _sysc_enable(oh);
+                       _enable_sysc(oh);
                }
        } else {
                pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
@@ -933,12 +1216,14 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
 }
 
 /**
- * _idle - idle an omap_hwmod
+ * _omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Idles an omap_hwmod @oh.  This should be called once the hwmod has
- * no further work.  Returns -EINVAL if the hwmod is in the wrong
- * state or returns 0.
+ * no further work.  (This function has a full name --
+ * _omap_hwmod_idle() rather than simply _idle() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or returns 0.
  */
 int _omap_hwmod_idle(struct omap_hwmod *oh)
 {
@@ -951,7 +1236,7 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
        if (oh->class->sysc)
-               _sysc_idle(oh);
+               _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
        _disable_clocks(oh);
 
@@ -981,10 +1266,21 @@ static int _shutdown(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: disabling\n", oh->name);
 
        if (oh->class->sysc)
-               _sysc_shutdown(oh);
-       _del_initiator_dep(oh, mpu_oh);
-       /* XXX what about the other system initiators here? DMA, tesla, d2d */
-       _disable_clocks(oh);
+               _shutdown_sysc(oh);
+
+       /*
+        * If an IP contains only one HW reset line, then assert it
+        * before disabling the clocks and shutting down the IP.
+        */
+       if (oh->rst_lines_cnt == 1)
+               _assert_hardreset(oh, oh->rst_lines[0].name);
+
+       /* clocks and deps are already disabled in idle */
+       if (oh->_state == _HWMOD_STATE_ENABLED) {
+               _del_initiator_dep(oh, mpu_oh);
+               /* XXX what about the other system initiators here? dma, dsp */
+               _disable_clocks(oh);
+       }
        /* XXX Should this code also force-disable the optional clocks? */
 
        /* XXX mux any associated balls to safe mode */
@@ -1000,11 +1296,10 @@ static int _shutdown(struct omap_hwmod *oh)
  * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
  *
  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  Must be called with omap_hwmod_mutex held.
- * @skip_setup_idle is intended to be used on a system that will not
- * call omap_hwmod_enable() to enable devices (e.g., a system without
- * PM runtime).  Returns -EINVAL if the hwmod is in the wrong state or
- * returns 0.
+ * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on
+ * a system that will not call omap_hwmod_enable() to enable devices
+ * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod
+ * is in the wrong state or returns 0.
  */
 static int _setup(struct omap_hwmod *oh, void *data)
 {
@@ -1034,8 +1329,19 @@ static int _setup(struct omap_hwmod *oh, void *data)
                }
        }
 
+       mutex_init(&oh->_mutex);
        oh->_state = _HWMOD_STATE_INITIALIZED;
 
+       /*
+        * In the case of hwmod with hardreset that should not be
+        * de-assert at boot time, we have to keep the module
+        * initialized, because we cannot enable it properly with the
+        * reset asserted. Exit without warning because that behavior is
+        * expected.
+        */
+       if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
+               return 0;
+
        r = _omap_hwmod_enable(oh);
        if (r) {
                pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
@@ -1044,16 +1350,16 @@ static int _setup(struct omap_hwmod *oh, void *data)
        }
 
        if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
+               _reset(oh);
+
                /*
-                * XXX Do the OCP_SYSCONFIG bits need to be
-                * reprogrammed after a reset?  If not, then this can
-                * be removed.  If they do, then probably the
-                * _omap_hwmod_enable() function should be split to avoid the
-                * rewrite of the OCP_SYSCONFIG register.
+                * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
+                * The _omap_hwmod_enable() function should be split to
+                * avoid the rewrite of the OCP_SYSCONFIG register.
                 */
                if (oh->class->sysc) {
                        _update_sysc_cache(oh);
-                       _sysc_enable(oh);
+                       _enable_sysc(oh);
                }
        }
 
@@ -1309,7 +1615,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh)
  * omap_hwmod_enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Enable an omap_hwomd @oh.  Intended to be called by omap_device_enable().
+ * Enable an omap_hwmod @oh.  Intended to be called by omap_device_enable().
  * Returns -EINVAL on error or passes along the return value from _enable().
  */
 int omap_hwmod_enable(struct omap_hwmod *oh)
@@ -1319,9 +1625,9 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        r = _omap_hwmod_enable(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return r;
 }
@@ -1331,7 +1637,7 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
  * omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Idle an omap_hwomd @oh.  Intended to be called by omap_device_idle().
+ * Idle an omap_hwmod @oh.  Intended to be called by omap_device_idle().
  * Returns -EINVAL on error or passes along the return value from _idle().
  */
 int omap_hwmod_idle(struct omap_hwmod *oh)
@@ -1339,9 +1645,9 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _omap_hwmod_idle(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1350,7 +1656,7 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
  * omap_hwmod_shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Shutdown an omap_hwomd @oh.  Intended to be called by
+ * Shutdown an omap_hwmod @oh.  Intended to be called by
  * omap_device_shutdown().  Returns -EINVAL on error or passes along
  * the return value from _shutdown().
  */
@@ -1359,9 +1665,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _shutdown(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1374,9 +1680,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
  */
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
 {
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _enable_clocks(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1389,9 +1695,9 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
  */
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
 {
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _disable_clocks(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1430,20 +1736,18 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
  *
  * Under some conditions, a driver may wish to reset the entire device.
  * Called from omap_device code.  Returns -EINVAL on error or passes along
- * the return value from _reset()/_enable().
+ * the return value from _reset().
  */
 int omap_hwmod_reset(struct omap_hwmod *oh)
 {
        int r;
 
-       if (!oh || !(oh->_state & _HWMOD_STATE_ENABLED))
+       if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        r = _reset(oh);
-       if (!r)
-               r = _omap_hwmod_enable(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return r;
 }
@@ -1468,7 +1772,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
 {
        int ret, i;
 
-       ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
+       ret = oh->mpu_irqs_cnt + oh->sdma_reqs_cnt;
 
        for (i = 0; i < oh->slaves_cnt; i++)
                ret += oh->slaves[i]->addr_cnt;
@@ -1501,10 +1805,10 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
                r++;
        }
 
-       for (i = 0; i < oh->sdma_chs_cnt; i++) {
-               (res + r)->name = (oh->sdma_chs + i)->name;
-               (res + r)->start = (oh->sdma_chs + i)->dma_ch;
-               (res + r)->end = (oh->sdma_chs + i)->dma_ch;
+       for (i = 0; i < oh->sdma_reqs_cnt; i++) {
+               (res + r)->name = (oh->sdma_reqs + i)->name;
+               (res + r)->start = (oh->sdma_reqs + i)->dma_req;
+               (res + r)->end = (oh->sdma_reqs + i)->dma_req;
                (res + r)->flags = IORESOURCE_DMA;
                r++;
        }
@@ -1644,9 +1948,9 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
            !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _enable_wakeup(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1669,13 +1973,91 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
            !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _disable_wakeup(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
 
+/**
+ * omap_hwmod_assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _assert_hardreset().
+ */
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _assert_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+/**
+ * omap_hwmod_deassert_hardreset - deassert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _deassert_hardreset().
+ */
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _deassert_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+/**
+ * omap_hwmod_read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the current state of the hwmod @oh's reset line named @name:
+ * returns -EINVAL upon parameter error or if this operation
+ * is unsupported on the current OMAP; otherwise, passes along the return
+ * value from _read_hardreset().
+ */
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _read_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+
 /**
  * omap_hwmod_for_each_by_class - call @fn for each hwmod of class @classname
  * @classname: struct omap_hwmod_class name to search for
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
new file mode 100644 (file)
index 0000000..e20b0ee
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ * Hardware modules present on the OMAP44xx chips
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ * Benoit Cousson
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/cpu.h>
+
+#include "omap_hwmod_common_data.h"
+
+#include "cm.h"
+#include "prm-regbits-44xx.h"
+
+/* Base offset for all OMAP4 interrupts external to MPUSS */
+#define OMAP44XX_IRQ_GIC_START 32
+
+/* Base offset for all OMAP4 dma requests */
+#define OMAP44XX_DMA_REQ_START  1
+
+/* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dmm_hwmod;
+static struct omap_hwmod omap44xx_emif_fw_hwmod;
+static struct omap_hwmod omap44xx_l3_instr_hwmod;
+static struct omap_hwmod omap44xx_l3_main_1_hwmod;
+static struct omap_hwmod omap44xx_l3_main_2_hwmod;
+static struct omap_hwmod omap44xx_l3_main_3_hwmod;
+static struct omap_hwmod omap44xx_l4_abe_hwmod;
+static struct omap_hwmod omap44xx_l4_cfg_hwmod;
+static struct omap_hwmod omap44xx_l4_per_hwmod;
+static struct omap_hwmod omap44xx_l4_wkup_hwmod;
+static struct omap_hwmod omap44xx_mpu_hwmod;
+static struct omap_hwmod omap44xx_mpu_private_hwmod;
+
+/*
+ * Interconnects omap_hwmod structures
+ * hwmods that compose the global OMAP interconnect
+ */
+
+/*
+ * 'dmm' class
+ * instance(s): dmm
+ */
+static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
+       .name = "dmm",
+};
+
+/* dmm interface data */
+/* l3_main_1 -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_dmm_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_dmm_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dmm slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
+       &omap44xx_l3_main_1__dmm,
+       &omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
+       { .irq = 113 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod omap44xx_dmm_hwmod = {
+       .name           = "dmm",
+       .class          = &omap44xx_dmm_hwmod_class,
+       .slaves         = omap44xx_dmm_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_dmm_slaves),
+       .mpu_irqs       = omap44xx_dmm_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_dmm_irqs),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'emif_fw' class
+ * instance(s): emif_fw
+ */
+static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
+       .name = "emif_fw",
+};
+
+/* emif_fw interface data */
+/* dmm -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
+       .master         = &omap44xx_dmm_hwmod,
+       .slave          = &omap44xx_emif_fw_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_emif_fw_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* emif_fw slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
+       &omap44xx_dmm__emif_fw,
+       &omap44xx_l4_cfg__emif_fw,
+};
+
+static struct omap_hwmod omap44xx_emif_fw_hwmod = {
+       .name           = "emif_fw",
+       .class          = &omap44xx_emif_fw_hwmod_class,
+       .slaves         = omap44xx_emif_fw_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_emif_fw_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l3' class
+ * instance(s): l3_instr, l3_main_1, l3_main_2, l3_main_3
+ */
+static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
+       .name = "l3",
+};
+
+/* l3_instr interface data */
+/* l3_main_3 -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
+       .master         = &omap44xx_l3_main_3_hwmod,
+       .slave          = &omap44xx_l3_instr_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_instr slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
+       &omap44xx_l3_main_3__l3_instr,
+};
+
+static struct omap_hwmod omap44xx_l3_instr_hwmod = {
+       .name           = "l3_instr",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_instr_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_instr_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
+       &omap44xx_l3_main_2__l3_main_1,
+       &omap44xx_l4_cfg__l3_main_1,
+       &omap44xx_mpu__l3_main_1,
+};
+
+static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
+       .name           = "l3_main_1",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_1_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_2 interface data */
+/* l3_main_1 -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l3_main_2_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_2_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
+       &omap44xx_l3_main_1__l3_main_2,
+       &omap44xx_l4_cfg__l3_main_2,
+};
+
+static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
+       .name           = "l3_main_2",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_3 interface data */
+/* l3_main_1 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_3 = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_3 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
+       &omap44xx_l3_main_1__l3_main_3,
+       &omap44xx_l3_main_2__l3_main_3,
+       &omap44xx_l4_cfg__l3_main_3,
+};
+
+static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
+       .name           = "l3_main_3",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_3_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l4' class
+ * instance(s): l4_abe, l4_cfg, l4_per, l4_wkup
+ */
+static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
+       .name = "l4",
+};
+
+/* l4_abe interface data */
+/* l3_main_1 -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l4_abe_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_l4_abe_hwmod,
+       .clk            = "ocp_abe_iclk",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_abe slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
+       &omap44xx_l3_main_1__l4_abe,
+       &omap44xx_mpu__l4_abe,
+};
+
+static struct omap_hwmod omap44xx_l4_abe_hwmod = {
+       .name           = "l4_abe",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_abe_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_abe_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_cfg interface data */
+/* l3_main_1 -> l4_cfg */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l4_cfg_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
+       &omap44xx_l3_main_1__l4_cfg,
+};
+
+static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
+       .name           = "l4_cfg",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_cfg_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_cfg_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_per interface data */
+/* l3_main_2 -> l4_per */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l4_per_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
+       &omap44xx_l3_main_2__l4_per,
+};
+
+static struct omap_hwmod omap44xx_l4_per_hwmod = {
+       .name           = "l4_per",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_per_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_per_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_wkup interface data */
+/* l4_cfg -> l4_wkup */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l4_wkup_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
+       &omap44xx_l4_cfg__l4_wkup,
+};
+
+static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
+       .name           = "l4_wkup",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_wkup_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_wkup_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu_bus' class
+ * instance(s): mpu_private
+ */
+static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
+       .name = "mpu_bus",
+};
+
+/* mpu_private interface data */
+/* mpu -> mpu_private */
+static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_mpu_private_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu_private slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
+       &omap44xx_mpu__mpu_private,
+};
+
+static struct omap_hwmod omap44xx_mpu_private_hwmod = {
+       .name           = "mpu_private",
+       .class          = &omap44xx_mpu_bus_hwmod_class,
+       .slaves         = omap44xx_mpu_private_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_mpu_private_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu' class
+ * mpu sub-system
+ */
+
+static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
+       .name = "mpu",
+};
+
+/* mpu */
+static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
+       { .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
+       { .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
+       { .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* mpu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
+       &omap44xx_mpu__l3_main_1,
+       &omap44xx_mpu__l4_abe,
+       &omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod omap44xx_mpu_hwmod = {
+       .name           = "mpu",
+       .class          = &omap44xx_mpu_hwmod_class,
+       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+       .mpu_irqs       = omap44xx_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_mpu_irqs),
+       .main_clk       = "dpll_mpu_m2_ck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+               },
+       },
+       .masters        = omap44xx_mpu_masters,
+       .masters_cnt    = ARRAY_SIZE(omap44xx_mpu_masters),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
+       /* dmm class */
+       &omap44xx_dmm_hwmod,
+       /* emif_fw class */
+       &omap44xx_emif_fw_hwmod,
+       /* l3 class */
+       &omap44xx_l3_instr_hwmod,
+       &omap44xx_l3_main_1_hwmod,
+       &omap44xx_l3_main_2_hwmod,
+       &omap44xx_l3_main_3_hwmod,
+       /* l4 class */
+       &omap44xx_l4_abe_hwmod,
+       &omap44xx_l4_cfg_hwmod,
+       &omap44xx_l4_per_hwmod,
+       &omap44xx_l4_wkup_hwmod,
+       /* mpu_bus class */
+       &omap44xx_mpu_private_hwmod,
+
+       /* mpu class */
+       &omap44xx_mpu_hwmod,
+       NULL,
+};
+
+int __init omap44xx_hwmod_init(void)
+{
+       return omap_hwmod_init(omap44xx_hwmods);
+}
+
index 723b44e252fdc4ab5924a8b16d96f0645b22a2c0..af00c174d7a9bc8848d72c40018527dc29ab76a6 100644 (file)
 #include <plat/board.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/dmtimer.h>
 
 #include "prm.h"
 #include "cm.h"
 #include "pm.h"
 
 int omap2_pm_debug;
+u32 enable_off_mode;
+u32 sleep_while_idle;
+u32 wakeup_timer_seconds;
+u32 wakeup_timer_milliseconds;
 
 #define DUMP_PRM_MOD_REG(mod, reg)    \
        regs[reg_count].name = #mod "." #reg; \
@@ -349,6 +354,23 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
        pwrdm->timer = t;
 }
 
+void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
+{
+       u32 tick_rate, cycles;
+
+       if (!seconds && !milliseconds)
+               return;
+
+       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
+       omap_dm_timer_stop(gptimer_wakeup);
+       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+       pr_info("PM: Resume timer in %u.%03u secs"
+               " (%d ticks at %d ticks/sec.)\n",
+               seconds, milliseconds, cycles, tick_rate);
+}
+
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
        struct seq_file *s = (struct seq_file *)user;
@@ -494,8 +516,10 @@ int pm_dbg_regset_init(int reg_set)
 
 static int pwrdm_suspend_get(void *data, u64 *val)
 {
-       int ret;
-       ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
+       int ret = -EINVAL;
+
+       if (cpu_is_omap34xx())
+               ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
        *val = ret;
 
        if (ret >= 0)
@@ -505,7 +529,10 @@ static int pwrdm_suspend_get(void *data, u64 *val)
 
 static int pwrdm_suspend_set(void *data, u64 val)
 {
-       return omap3_pm_set_suspend_state((struct powerdomain *)data, (int)val);
+       if (cpu_is_omap34xx())
+               return omap3_pm_set_suspend_state(
+                       (struct powerdomain *)data, (int)val);
+       return -EINVAL;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
@@ -553,8 +580,10 @@ static int option_set(void *data, u64 val)
 
        *option = val;
 
-       if (option == &enable_off_mode)
-               omap3_pm_off_mode_enable(val);
+       if (option == &enable_off_mode) {
+               if (cpu_is_omap34xx())
+                       omap3_pm_off_mode_enable(val);
+       }
 
        return 0;
 }
@@ -609,6 +638,9 @@ static int __init pm_dbg_init(void)
                                   &sleep_while_idle, &pm_dbg_option_fops);
        (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d,
                                   &wakeup_timer_seconds, &pm_dbg_option_fops);
+       (void) debugfs_create_file("wakeup_timer_milliseconds",
+                       S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
+                       &pm_dbg_option_fops);
        pm_dbg_init_done = 1;
 
        return 0;
index 68f9f2e958917290f5814b7b186c33135d2ec2c4..59ca03b0e691c4dda171d68ffc30fce327352dbd 100644 (file)
 #include <plat/omap_device.h>
 #include <plat/common.h>
 
+#include <plat/powerdomain.h>
+#include <plat/clockdomain.h>
+
 static struct omap_device_pm_latency *pm_lats;
 
 static struct device *mpu_dev;
-static struct device *dsp_dev;
+static struct device *iva_dev;
 static struct device *l3_dev;
+static struct device *dsp_dev;
 
 struct device *omap2_get_mpuss_device(void)
 {
@@ -30,10 +34,10 @@ struct device *omap2_get_mpuss_device(void)
        return mpu_dev;
 }
 
-struct device *omap2_get_dsp_device(void)
+struct device *omap2_get_iva_device(void)
 {
-       WARN_ON_ONCE(!dsp_dev);
-       return dsp_dev;
+       WARN_ON_ONCE(!iva_dev);
+       return iva_dev;
 }
 
 struct device *omap2_get_l3_device(void)
@@ -42,6 +46,13 @@ struct device *omap2_get_l3_device(void)
        return l3_dev;
 }
 
+struct device *omap4_get_dsp_device(void)
+{
+       WARN_ON_ONCE(!dsp_dev);
+       return dsp_dev;
+}
+EXPORT_SYMBOL(omap4_get_dsp_device);
+
 /* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
 static int _init_omap_device(char *name, struct device **new_dev)
 {
@@ -69,8 +80,60 @@ static int _init_omap_device(char *name, struct device **new_dev)
 static void omap2_init_processor_devices(void)
 {
        _init_omap_device("mpu", &mpu_dev);
-       _init_omap_device("iva", &dsp_dev);
-       _init_omap_device("l3_main", &l3_dev);
+       _init_omap_device("iva", &iva_dev);
+       if (cpu_is_omap44xx()) {
+               _init_omap_device("l3_main_1", &l3_dev);
+               _init_omap_device("dsp", &dsp_dev);
+       } else {
+               _init_omap_device("l3_main", &l3_dev);
+       }
+}
+
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported. Function is assuming that clkdm doesn't have
+ * hw_sup mode enabled.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
+{
+       u32 cur_state;
+       int sleep_switch = 0;
+       int ret = 0;
+
+       if (pwrdm == NULL || IS_ERR(pwrdm))
+               return -EINVAL;
+
+       while (!(pwrdm->pwrsts & (1 << state))) {
+               if (state == PWRDM_POWER_OFF)
+                       return ret;
+               state--;
+       }
+
+       cur_state = pwrdm_read_next_pwrst(pwrdm);
+       if (cur_state == state)
+               return ret;
+
+       if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
+               omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+               sleep_switch = 1;
+               pwrdm_wait_transition(pwrdm);
+       }
+
+       ret = pwrdm_set_next_pwrst(pwrdm, state);
+       if (ret) {
+               printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
+                      pwrdm->name);
+               goto err;
+       }
+
+       if (sleep_switch) {
+               omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+               pwrdm_wait_transition(pwrdm);
+               pwrdm_state_switch(pwrdm);
+       }
+
+err:
+       return ret;
 }
 
 static int __init omap2_common_pm_init(void)
index 3de6ece23fc8b306653fde7af790926df2e05e1e..77770a13cea8f7a1e0863058a64dbf30115aad77 100644 (file)
@@ -20,7 +20,7 @@ extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap3_can_sleep(void);
-extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 
 struct cpuidle_params {
@@ -48,9 +48,11 @@ extern struct omap_dm_timer *gptimer_wakeup;
 
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
+extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
 extern int omap2_pm_debug;
 #else
 #define omap2_pm_dump(mode, resume, us)                do {} while (0);
+#define omap2_pm_wakeup_on_timer(seconds, milliseconds)        do {} while (0);
 #define omap2_pm_debug                         0
 #endif
 
index 7b03426c72a317307db1df3931a5018443117b33..d2b940c7215da92213ba7bed3030abdc641afc53 100644 (file)
@@ -38,7 +38,6 @@
 #include <plat/prcm.h>
 #include <plat/gpmc.h>
 #include <plat/dma.h>
-#include <plat/dmtimer.h>
 
 #include <asm/tlbflush.h>
 
 #define OMAP343X_TABLE_VALUE_OFFSET       0x30
 #define OMAP343X_CONTROL_REG_VALUE_OFFSET  0x32
 
-u32 enable_off_mode;
-u32 sleep_while_idle;
-u32 wakeup_timer_seconds;
-u32 wakeup_timer_milliseconds;
-
 struct power_state {
        struct powerdomain *pwrdm;
        u32 next_state;
@@ -351,7 +345,6 @@ void omap_sram_idle(void)
        int core_next_state = PWRDM_POWER_ON;
        int core_prev_state, per_prev_state;
        u32 sdrc_pwr = 0;
-       int per_state_modified = 0;
 
        if (!_omap_sram_idle)
                return;
@@ -385,9 +378,9 @@ void omap_sram_idle(void)
        /* Enable IO-PAD and IO-CHAIN wakeups */
        per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
        core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
-       if (omap3_has_io_wakeup() && \
-                       (per_next_state < PWRDM_POWER_ON ||
-                       core_next_state < PWRDM_POWER_ON)) {
+       if (omap3_has_io_wakeup() &&
+           (per_next_state < PWRDM_POWER_ON ||
+            core_next_state < PWRDM_POWER_ON)) {
                prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
                omap3_enable_io_chain();
        }
@@ -396,19 +389,10 @@ void omap_sram_idle(void)
        if (per_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(2);
                omap2_gpio_prepare_for_idle(per_next_state);
-               if (per_next_state == PWRDM_POWER_OFF) {
-                       if (core_next_state == PWRDM_POWER_ON) {
-                               per_next_state = PWRDM_POWER_RET;
-                               pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-                               per_state_modified = 1;
-                       } else
+               if (per_next_state == PWRDM_POWER_OFF)
                                omap3_per_save_context();
-               }
        }
 
-       if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-               omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
-
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(0);
@@ -475,8 +459,6 @@ void omap_sram_idle(void)
                if (per_prev_state == PWRDM_POWER_OFF)
                        omap3_per_restore_context();
                omap_uart_resume_idle(2);
-               if (per_state_modified)
-                       pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
        }
 
        /* Disable IO-PAD and IO-CHAIN wakeup */
@@ -501,51 +483,6 @@ int omap3_can_sleep(void)
        return 1;
 }
 
-/* This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported. Function is assuming that clkdm doesn't have
- * hw_sup mode enabled. */
-int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
-{
-       u32 cur_state;
-       int sleep_switch = 0;
-       int ret = 0;
-
-       if (pwrdm == NULL || IS_ERR(pwrdm))
-               return -EINVAL;
-
-       while (!(pwrdm->pwrsts & (1 << state))) {
-               if (state == PWRDM_POWER_OFF)
-                       return ret;
-               state--;
-       }
-
-       cur_state = pwrdm_read_next_pwrst(pwrdm);
-       if (cur_state == state)
-               return ret;
-
-       if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
-               omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-               sleep_switch = 1;
-               pwrdm_wait_transition(pwrdm);
-       }
-
-       ret = pwrdm_set_next_pwrst(pwrdm, state);
-       if (ret) {
-               printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
-                      pwrdm->name);
-               goto err;
-       }
-
-       if (sleep_switch) {
-               omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-               pwrdm_wait_transition(pwrdm);
-               pwrdm_state_switch(pwrdm);
-       }
-
-err:
-       return ret;
-}
-
 static void omap3_pm_idle(void)
 {
        local_irq_disable();
@@ -567,23 +504,6 @@ out:
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state;
 
-static void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-       u32 tick_rate, cycles;
-
-       if (!seconds && !milliseconds)
-               return;
-
-       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-       omap_dm_timer_stop(gptimer_wakeup);
-       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-       pr_info("PM: Resume timer in %u.%03u secs"
-               " (%d ticks at %d ticks/sec.)\n",
-               seconds, milliseconds, cycles, tick_rate);
-}
-
 static int omap3_pm_prepare(void)
 {
        disable_hlt();
@@ -604,7 +524,7 @@ static int omap3_pm_suspend(void)
                pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
        /* Set ones wanted by suspend */
        list_for_each_entry(pwrst, &pwrst_list, node) {
-               if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
+               if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
                        goto restore;
                if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
                        goto restore;
@@ -625,7 +545,7 @@ restore:
                               pwrst->pwrdm->name, pwrst->next_state);
                        ret = -1;
                }
-               set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+               omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
        }
        if (ret)
                printk(KERN_ERR "Could not enter target state in pm_suspend\n");
@@ -974,7 +894,7 @@ void omap3_pm_off_mode_enable(int enable)
 
        list_for_each_entry(pwrst, &pwrst_list, node) {
                pwrst->next_state = state;
-               set_pwrdm_state(pwrst->pwrdm, state);
+               omap_set_pwrdm_state(pwrst->pwrdm, state);
        }
 }
 
@@ -1019,7 +939,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
        if (pwrdm_has_hdwr_sar(pwrdm))
                pwrdm_enable_hdwr_sar(pwrdm);
 
-       return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+       return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
 /*
@@ -1029,9 +949,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
  */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-       clkdm_clear_all_wkdeps(clkdm);
-       clkdm_clear_all_sleepdeps(clkdm);
-
        if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
                omap2_clkdm_allow_idle(clkdm);
        else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
index c20137497c92fe3f88bcb16b1d9fa72b1b8013f0..d4388d34c26a0707594af067e7394eb775d947dc 100644 (file)
@@ -33,6 +33,7 @@
 #include "cm.h"
 #include "prm.h"
 #include "prm-regbits-24xx.h"
+#include "prm-regbits-44xx.h"
 
 static void __iomem *prm_base;
 static void __iomem *cm_base;
@@ -161,8 +162,8 @@ void omap_prcm_arch_reset(char mode, const char *cmd)
                prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
                                                 OMAP2_RM_RSTCTRL);
        if (cpu_is_omap44xx())
-               prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
-                                                OMAP4_RM_RSTCTRL);
+               prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK,
+                                    prcm_offs, OMAP4_RM_RSTCTRL);
 }
 
 static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
@@ -215,6 +216,30 @@ u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
        return v;
 }
 
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
+{
+       u32 v;
+
+       v = __raw_readl(reg);
+       v &= mask;
+       v >>= __ffs(mask);
+
+       return v;
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
+{
+       u32 v;
+
+       v = __raw_readl(reg);
+       v &= ~mask;
+       v |= bits;
+       __raw_writel(v, reg);
+
+       return v;
+}
 /* Read a register in a CM module */
 u32 cm_read_mod_reg(s16 module, u16 idx)
 {
index 588873b9303aa57c38bc716cb3c8b81a61b8d1d9..7be040b2fdab138ad180b5f140866f775b2c79ae 100644 (file)
@@ -5,7 +5,7 @@
  * OMAP2/3 Power/Reset Management (PRM) register definitions
  *
  * Copyright (C) 2007-2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2010 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -246,6 +246,15 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
        return prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
 }
 
+/* These omap2_ PRM functions apply to both OMAP2 and 3 */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
+
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+
 #endif
 
 /*
@@ -398,4 +407,11 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
 #define OMAP_POWERSTATE_MASK                           (0x3 << 0)
 
 
+/*
+ * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
+ * submodule to exit hardreset
+ */
+#define MAX_MODULE_HARDRESET_WAIT              10000
+
+
 #endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
new file mode 100644 (file)
index 0000000..421771e
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * OMAP2/3 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "prm-regbits-34xx.h"
+
+/**
+ * omap2_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL if called while running on a non-OMAP2/3 chip.
+ */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
+{
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       return prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
+                                      (1 << shift));
+}
+
+/**
+ * omap2_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
+{
+       u32 mask;
+
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       mask = 1 << shift;
+       prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
+
+       return 0;
+}
+
+/**
+ * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+{
+       u32 mask;
+       int c;
+
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       mask = 1 << shift;
+
+       /* Check the current status to avoid de-asserting the line twice */
+       if (prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
+       /* de-assert the reset control line */
+       prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
+       /* wait the status to be set */
+       omap_test_timeout(prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
+                                                 mask),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
new file mode 100644 (file)
index 0000000..a1ff918
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * OMAP4 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-44xx.h"
+
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET               4
+
+/**
+ * omap4_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
+{
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
+}
+
+/**
+ * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+       u32 mask;
+
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       mask = 1 << shift;
+       omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
+
+       return 0;
+}
+
+/**
+ * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+       u32 mask;
+       void __iomem *rstst_reg;
+       int c;
+
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
+
+       mask = 1 << shift;
+
+       /* Check the current status to avoid de-asserting the line twice */
+       if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
+       /* de-assert the reset control line */
+       omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
+       /* wait the status to be set */
+       omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
index 9405831b746a5e63dd4dc3a2a6220afce032713c..2a151917ef52874b38fe4f857ffd34d6601efd89 100644 (file)
@@ -31,4 +31,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y)
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
 
-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
\ No newline at end of file
+obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
index 7951eefe1a0e90d634c315882427f94fc9c32faa..11c5b0eefb85e5eaa8653df16900845c47ff2563 100644 (file)
@@ -2085,8 +2085,9 @@ void omap2_gpio_prepare_for_idle(int power_state)
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
                u32 l1, l2;
+               int j;
 
-               if (bank->dbck_enable_mask)
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_disable(bank->dbck);
 
                if (power_state > PWRDM_POWER_OFF)
@@ -2152,8 +2153,9 @@ void omap2_gpio_resume_after_idle(void)
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
                u32 l, gen, gen0, gen1;
+               int j;
 
-               if (bank->dbck_enable_mask)
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_enable(bank->dbck);
 
                if (!workaround_enabled)
index 9776b41ad76f57a9f63bd3be3e1044f2f58481af..c45dbb975e09bbd11a30ae400c206233309713b1 100644 (file)
@@ -91,7 +91,8 @@ void omap3_map_io(void);
 })
 
 extern struct device *omap2_get_mpuss_device(void);
-extern struct device *omap2_get_dsp_device(void);
+extern struct device *omap2_get_iva_device(void);
 extern struct device *omap2_get_l3_device(void);
+extern struct device *omap4_get_dsp_device(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
index 25cd9ac3b0958eb1a61d166b485731be2a480dab..28e2d1a78433b6d57c94e40b4050bb8ab521717c 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <plat/omap_hwmod.h>
 
+extern struct device omap_device_parent;
+
 /* omap_device._state values */
 #define OMAP_DEVICE_STATE_UNKNOWN      0
 #define OMAP_DEVICE_STATE_ENABLED      1
@@ -62,7 +64,6 @@
  *
  */
 struct omap_device {
-       u32                             magic;
        struct platform_device          pdev;
        struct omap_hwmod               **hwmods;
        struct omap_device_pm_latency   *pm_lats;
@@ -82,7 +83,6 @@ int omap_device_shutdown(struct platform_device *pdev);
 
 /* Core code interface */
 
-bool omap_device_is_valid(struct omap_device *od);
 int omap_device_count_resources(struct omap_device *od);
 int omap_device_fill_resources(struct omap_device *od, struct resource *res);
 
index a4e508dfaba2716a46a9d20d1ac59337dce1fae2..c1835afc238d5235434f58ccf344e25840eb331a 100644 (file)
  *
  * These headers and macros are used to define OMAP on-chip module
  * data and their integration with other OMAP modules and Linux.
- *
- * References:
- * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
- * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
- * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
- * - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
- * - Open Core Protocol Specification 2.2
+ * Copious documentation and references can also be found in the
+ * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
+ * writing).
  *
  * To do:
  * - add interconnect error log structures
  * - add pinmuxing
  * - init_conn_id_bit (CONNID_BIT_VECTOR)
  * - implement default hwmod SMS/SDRC flags?
+ * - remove unused fields
  *
  */
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
@@ -35,6 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <linux/mutex.h>
 #include <plat/cpu.h>
 
 struct omap_device;
@@ -96,7 +94,7 @@ struct omap_hwmod_irq_info {
 /**
  * struct omap_hwmod_dma_info - DMA channels used by the hwmod
  * @name: name of the DMA channel (module local name)
- * @dma_ch: DMA channel ID
+ * @dma_req: DMA request ID
  *
  * @name should be something short, e.g., "tx" or "rx".  It is for use
  * by platform_get_resource_byname().  It is defined locally to the
@@ -104,7 +102,20 @@ struct omap_hwmod_irq_info {
  */
 struct omap_hwmod_dma_info {
        const char      *name;
-       u16             dma_ch;
+       u16             dma_req;
+};
+
+/**
+ * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
+ * @name: name of the reset line (module local name)
+ * @rst_shift: Offset of the reset bit
+ *
+ * @name should be something short, e.g., "cpu0" or "rst". It is defined
+ * locally to the hwmod.
+ */
+struct omap_hwmod_rst_info {
+       const char      *name;
+       u8              rst_shift;
 };
 
 /**
@@ -237,8 +248,9 @@ struct omap_hwmod_ocp_if {
 #define SYSC_HAS_CLOCKACTIVITY (1 << 4)
 #define SYSC_HAS_SIDLEMODE     (1 << 5)
 #define SYSC_HAS_MIDLEMODE     (1 << 6)
-#define SYSS_MISSING           (1 << 7)
+#define SYSS_HAS_RESET_STATUS  (1 << 7)
 #define SYSC_NO_CACHE          (1 << 8)  /* XXX SW flag, belongs elsewhere */
+#define SYSC_HAS_RESET_STATUS  (1 << 9)
 
 /* omap_hwmod_sysconfig.clockact flags */
 #define CLOCKACT_TEST_BOTH     0x0
@@ -327,10 +339,12 @@ struct omap_hwmod_omap2_prcm {
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
  * @clkctrl_reg: PRCM address of the clock control register
+ * @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
        void __iomem    *clkctrl_reg;
+       void __iomem    *rstctrl_reg;
        u8              submodule_wkdep_bit;
 };
 
@@ -352,6 +366,10 @@ struct omap_hwmod_omap4_prcm {
  * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
  * HWMOD_NO_IDLEST : this module does not have idle status - this is the case
  *     only for few initiator modules on OMAP2 & 3.
+ * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
+ *     This is needed for devices like DSS that require optional clocks enabled
+ *     in order to complete the reset. Optional clocks will be disabled
+ *     again after the reset.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -360,6 +378,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_OCP_AUTOIDLE                  (1 << 4)
 #define HWMOD_SET_DEFAULT_CLOCKACT             (1 << 5)
 #define HWMOD_NO_IDLEST                                (1 << 6)
+#define HWMOD_CONTROL_OPT_CLKS_IN_RESET                (1 << 7)
 
 /*
  * omap_hwmod._int_flags definitions
@@ -410,7 +429,7 @@ struct omap_hwmod_class {
  * @class: struct omap_hwmod_class * to the class of this hwmod
  * @od: struct omap_device currently associated with this hwmod (internal use)
  * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
- * @sdma_chs: ptr to an array of SDMA channel IDs (see also sdma_chs_cnt)
+ * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
  * @prcm: PRCM data pertaining to this hwmod
  * @main_clk: main clock: OMAP clock name
  * @_clk: pointer to the main struct clk (filled in at runtime)
@@ -424,7 +443,7 @@ struct omap_hwmod_class {
  * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
  * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
  * @mpu_irqs_cnt: number of @mpu_irqs
- * @sdma_chs_cnt: number of @sdma_chs
+ * @sdma_reqs_cnt: number of @sdma_reqs
  * @opt_clks_cnt: number of @opt_clks
  * @master_cnt: number of @master entries
  * @slaves_cnt: number of @slave entries
@@ -433,6 +452,7 @@ struct omap_hwmod_class {
  * @_state: internal-use hwmod state
  * @flags: hwmod flags (documented below)
  * @omap_chip: OMAP chips this hwmod is present on
+ * @_mutex: mutex serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
  * @main_clk refers to this module's "main clock," which for our
@@ -448,7 +468,8 @@ struct omap_hwmod {
        struct omap_hwmod_class         *class;
        struct omap_device              *od;
        struct omap_hwmod_irq_info      *mpu_irqs;
-       struct omap_hwmod_dma_info      *sdma_chs;
+       struct omap_hwmod_dma_info      *sdma_reqs;
+       struct omap_hwmod_rst_info      *rst_lines;
        union {
                struct omap_hwmod_omap2_prcm omap2;
                struct omap_hwmod_omap4_prcm omap4;
@@ -461,6 +482,7 @@ struct omap_hwmod {
        void                            *dev_attr;
        u32                             _sysc_cache;
        void __iomem                    *_mpu_rt_va;
+       struct mutex                    _mutex;
        struct list_head                node;
        u16                             flags;
        u8                              _mpu_port_index;
@@ -468,7 +490,8 @@ struct omap_hwmod {
        u8                              msuspendmux_shift;
        u8                              response_lat;
        u8                              mpu_irqs_cnt;
-       u8                              sdma_chs_cnt;
+       u8                              sdma_reqs_cnt;
+       u8                              rst_lines_cnt;
        u8                              opt_clks_cnt;
        u8                              masters_cnt;
        u8                              slaves_cnt;
@@ -492,6 +515,10 @@ int omap_hwmod_idle(struct omap_hwmod *oh);
 int _omap_hwmod_idle(struct omap_hwmod *oh);
 int omap_hwmod_shutdown(struct omap_hwmod *oh);
 
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
+
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
@@ -534,5 +561,6 @@ int omap_hwmod_for_each_by_class(const char *classname,
 extern int omap2420_hwmod_init(void);
 extern int omap2430_hwmod_init(void);
 extern int omap3xxx_hwmod_init(void);
+extern int omap44xx_hwmod_init(void);
 
 #endif
index 9fbd91419cd15b2849460eed590165e47b820c2a..ab77442e42ab1649cb1b0363f4a95af46c9470f3 100644 (file)
@@ -38,6 +38,8 @@ u32 prm_read_mod_reg(s16 module, u16 idx);
 void prm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
 u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
 u32 cm_read_mod_reg(s16 module, u16 idx);
 void cm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
index d2b160942ccc5ec0a2e0fb2efe3e7e288da9cb12..b5e5f6074b0b468ac78efb1ff735ef87e2c4a5d8 100644 (file)
@@ -82,6 +82,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
 #define USE_WAKEUP_LAT                 0
 #define IGNORE_WAKEUP_LAT              1
 
-/*
- * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device
- * obtained via container_of() is in fact a struct omap_device
- */
-#define OMAP_DEVICE_MAGIC               0xf00dcafe
-
 /* Private functions */
 
 /**
@@ -243,6 +238,44 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
        return container_of(pdev, struct omap_device, pdev);
 }
 
+/**
+ * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * @od: struct omap_device *od
+ *
+ * For every optional clock present per hwmod per omap_device, this function
+ * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
+ * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ *
+ * The function is called from inside omap_device_build_ss(), after
+ * omap_device_register.
+ *
+ * This allows drivers to get a pointer to its optional clocks based on its role
+ * by calling clk_get(<dev*>, <role>).
+ *
+ * No return value.
+ */
+static void _add_optional_clock_alias(struct omap_device *od,
+                                     struct omap_hwmod *oh)
+{
+       int i;
+
+       for (i = 0; i < oh->opt_clks_cnt; i++) {
+               struct omap_hwmod_opt_clk *oc;
+               int r;
+
+               oc = &oh->opt_clks[i];
+
+               if (!oc->_clk)
+                       continue;
+
+               r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
+                                 (char *)oc->clk, &od->pdev.dev);
+               if (r)
+                       pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+                              dev_name(&od->pdev.dev), oc->role);
+       }
+}
+
 
 /* Public functions for use by core code */
 
@@ -414,15 +447,15 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
        od->pm_lats = pm_lats;
        od->pm_lats_cnt = pm_lats_cnt;
 
-       od->magic = OMAP_DEVICE_MAGIC;
-
        if (is_early_device)
                ret = omap_early_device_register(od);
        else
                ret = omap_device_register(od);
 
-       for (i = 0; i < oh_cnt; i++)
+       for (i = 0; i < oh_cnt; i++) {
                hwmods[i]->od = od;
+               _add_optional_clock_alias(od, hwmods[i]);
+       }
 
        if (ret)
                goto odbs_exit4;
@@ -473,6 +506,7 @@ int omap_device_register(struct omap_device *od)
 {
        pr_debug("omap_device: %s: registering\n", od->pdev.name);
 
+       od->pdev.dev.parent = &omap_device_parent;
        return platform_device_register(&od->pdev);
 }
 
@@ -626,18 +660,6 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
        return ret;
 }
 
-/**
- * omap_device_is_valid - Check if pointer is a valid omap_device
- * @od: struct omap_device *
- *
- * Return whether struct omap_device pointer @od points to a valid
- * omap_device.
- */
-bool omap_device_is_valid(struct omap_device *od)
-{
-       return (od && od->magic == OMAP_DEVICE_MAGIC);
-}
-
 /**
  * omap_device_get_pwrdm - return the powerdomain * associated with @od
  * @od: struct omap_device *
@@ -757,3 +779,14 @@ int omap_device_enable_clocks(struct omap_device *od)
        /* XXX pass along return value here? */
        return 0;
 }
+
+struct device omap_device_parent = {
+       .init_name      = "omap",
+       .parent         = &platform_bus,
+};
+
+static int __init omap_device_init(void)
+{
+       return device_register(&omap_device_parent);
+}
+core_initcall(omap_device_init);