diff options
Diffstat (limited to 'arch/arm/mach-omap2')
24 files changed, 229 insertions, 407 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 093458b62c8d..c89757abb0ae 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -241,6 +241,3 @@ obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o obj-y += $(onenand-m) $(onenand-y) - -nand-$(CONFIG_MTD_NAND_OMAP2) := gpmc-nand.o -obj-y += $(nand-m) $(nand-y) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 6b6fda65fb3b..91272db09fa3 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -117,7 +117,7 @@ static struct musb_hdrc_platform_data tusb_data = { static void __init n8x0_usb_init(void) { int ret = 0; - static char announce[] __initdata = KERN_INFO "TUSB 6010\n"; + static const char announce[] __initconst = KERN_INFO "TUSB 6010\n"; /* PM companion chip power control pin */ ret = gpio_request_one(TUSB6010_GPIO_ENABLE, GPIOF_OUT_INIT_LOW, diff --git a/arch/arm/mach-omap2/clockdomains7xx_data.c b/arch/arm/mach-omap2/clockdomains7xx_data.c index 6c679659cda5..67ebff829cf2 100644 --- a/arch/arm/mach-omap2/clockdomains7xx_data.c +++ b/arch/arm/mach-omap2/clockdomains7xx_data.c @@ -524,7 +524,7 @@ static struct clockdomain pcie_7xx_clkdm = { .dep_bit = DRA7XX_PCIE_STATDEP_SHIFT, .wkdep_srcs = pcie_wkup_sleep_deps, .sleepdep_srcs = pcie_wkup_sleep_deps, - .flags = CLKDM_CAN_HWSUP_SWSUP, + .flags = CLKDM_CAN_SWSUP, }; static struct clockdomain atl_7xx_clkdm = { diff --git a/arch/arm/mach-omap2/clockdomains81xx_data.c b/arch/arm/mach-omap2/clockdomains81xx_data.c index 3b5fb05ae701..65fbd136b20c 100644 --- a/arch/arm/mach-omap2/clockdomains81xx_data.c +++ b/arch/arm/mach-omap2/clockdomains81xx_data.c @@ -91,6 +91,14 @@ static struct clockdomain default_l3_slow_81xx_clkdm = { .flags = CLKDM_CAN_SWSUP, }; +static struct clockdomain default_sata_81xx_clkdm = { + .name = "default_clkdm", + .pwrdm = { .name = "default_pwrdm" }, + .cm_inst = TI81XX_CM_DEFAULT_MOD, + .clkdm_offs = TI816X_CM_DEFAULT_SATA_CLKDM, + .flags = CLKDM_CAN_SWSUP, +}; + /* 816x only */ static struct clockdomain alwon_mpu_816x_clkdm = { @@ -173,6 +181,7 @@ static struct clockdomain *clockdomains_ti814x[] __initdata = { &mmu_81xx_clkdm, &mmu_cfg_81xx_clkdm, &default_l3_slow_81xx_clkdm, + &default_sata_81xx_clkdm, NULL, }; @@ -200,6 +209,7 @@ static struct clockdomain *clockdomains_ti816x[] __initdata = { &default_ducati_816x_clkdm, &default_pci_816x_clkdm, &default_l3_slow_81xx_clkdm, + &default_sata_81xx_clkdm, NULL, }; diff --git a/arch/arm/mach-omap2/cm81xx.h b/arch/arm/mach-omap2/cm81xx.h index 3a0ccf07c76f..5d73a1057c82 100644 --- a/arch/arm/mach-omap2/cm81xx.h +++ b/arch/arm/mach-omap2/cm81xx.h @@ -57,5 +57,6 @@ #define TI816X_CM_DEFAULT_PCI_CLKDM 0x0010 #define TI816X_CM_DEFAULT_L3_SLOW_CLKDM 0x0014 #define TI816X_CM_DEFAULT_DUCATI_CLKDM 0x0018 +#define TI816X_CM_DEFAULT_SATA_CLKDM 0x0060 #endif diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index c4f2ace91ea2..3089d3bfa19b 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -270,6 +270,7 @@ extern const struct smp_operations omap4_smp_ops; extern int omap4_mpuss_init(void); extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state); extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state); +extern u32 omap4_get_cpu1_ns_pa_addr(void); #else static inline int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 3fdb94599184..473951203104 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -121,7 +121,7 @@ static inline void omap_init_mcspi(void) {} * * Bind the RNG hwmod to the RNG omap_device. No return value. */ -static void omap_init_rng(void) +static void __init omap_init_rng(void) { struct omap_hwmod *oh; struct platform_device *pdev; diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c deleted file mode 100644 index f6ac027f3c3b..000000000000 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * gpmc-nand.c - * - * Copyright (C) 2009 Texas Instruments - * Vimal Singh <vimalsingh@ti.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/omap-gpmc.h> -#include <linux/mtd/nand.h> -#include <linux/platform_data/mtd-nand-omap2.h> - -#include <asm/mach/flash.h> - -#include "soc.h" - -/* minimum size for IO mapping */ -#define NAND_IO_SIZE 4 - -static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt) -{ - /* platforms which support all ECC schemes */ - if (soc_is_am33xx() || soc_is_am43xx() || cpu_is_omap44xx() || - soc_is_omap54xx() || soc_is_dra7xx()) - return 1; - - if (ecc_opt == OMAP_ECC_BCH4_CODE_HW_DETECTION_SW || - ecc_opt == OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) { - if (cpu_is_omap24xx()) - return 0; - else if (cpu_is_omap3630() && (GET_OMAP_REVISION() == 0)) - return 0; - else - return 1; - } - - /* OMAP3xxx do not have ELM engine, so cannot support ECC schemes - * which require H/W based ECC error detection */ - if ((cpu_is_omap34xx() || cpu_is_omap3630()) && - ((ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (ecc_opt == OMAP_ECC_BCH8_CODE_HW))) - return 0; - - /* legacy platforms support only HAM1 (1-bit Hamming) ECC scheme */ - if (ecc_opt == OMAP_ECC_HAM1_CODE_HW || - ecc_opt == OMAP_ECC_HAM1_CODE_SW) - return 1; - else - return 0; -} - -/* This function will go away once the device-tree convertion is complete */ -static void gpmc_set_legacy(struct omap_nand_platform_data *gpmc_nand_data, - struct gpmc_settings *s) -{ - /* Enable RD PIN Monitoring Reg */ - if (gpmc_nand_data->dev_ready) { - s->wait_on_read = true; - s->wait_on_write = true; - } - - if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16) - s->device_width = GPMC_DEVWIDTH_16BIT; - else - s->device_width = GPMC_DEVWIDTH_8BIT; -} - -int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data, - struct gpmc_timings *gpmc_t) -{ - int err = 0; - struct gpmc_settings s; - struct platform_device *pdev; - struct resource gpmc_nand_res[] = { - { .flags = IORESOURCE_MEM, }, - { .flags = IORESOURCE_IRQ, }, - { .flags = IORESOURCE_IRQ, }, - }; - - BUG_ON(gpmc_nand_data->cs >= GPMC_CS_NUM); - - err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE, - (unsigned long *)&gpmc_nand_res[0].start); - if (err < 0) { - pr_err("omap2-gpmc: Cannot request GPMC CS %d, error %d\n", - gpmc_nand_data->cs, err); - return err; - } - gpmc_nand_res[0].end = gpmc_nand_res[0].start + NAND_IO_SIZE - 1; - gpmc_nand_res[1].start = gpmc_get_client_irq(GPMC_IRQ_FIFOEVENTENABLE); - gpmc_nand_res[2].start = gpmc_get_client_irq(GPMC_IRQ_COUNT_EVENT); - - memset(&s, 0, sizeof(struct gpmc_settings)); - gpmc_set_legacy(gpmc_nand_data, &s); - - s.device_nand = true; - - if (gpmc_t) { - err = gpmc_cs_set_timings(gpmc_nand_data->cs, gpmc_t, &s); - if (err < 0) { - pr_err("omap2-gpmc: Unable to set gpmc timings: %d\n", - err); - return err; - } - } - - err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s); - if (err < 0) - goto out_free_cs; - - err = gpmc_configure(GPMC_CONFIG_WP, 0); - if (err < 0) - goto out_free_cs; - - if (!gpmc_hwecc_bch_capable(gpmc_nand_data->ecc_opt)) { - pr_err("omap2-nand: Unsupported NAND ECC scheme selected\n"); - err = -EINVAL; - goto out_free_cs; - } - - - pdev = platform_device_alloc("omap2-nand", gpmc_nand_data->cs); - if (pdev) { - err = platform_device_add_resources(pdev, gpmc_nand_res, - ARRAY_SIZE(gpmc_nand_res)); - if (!err) - pdev->dev.platform_data = gpmc_nand_data; - } else { - err = -ENOMEM; - } - if (err) - goto out_free_pdev; - - err = platform_device_add(pdev); - if (err) { - dev_err(&pdev->dev, "Unable to register NAND device\n"); - goto out_free_pdev; - } - - return 0; - -out_free_pdev: - platform_device_put(pdev); -out_free_cs: - gpmc_cs_free(gpmc_nand_data->cs); - - return err; -} diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 8633c703546a..2944af820558 100644 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -367,7 +367,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr) return ret; } -void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) +int gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) { int err; struct device *dev = &gpmc_onenand_device.dev; @@ -393,15 +393,17 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) if (err < 0) { dev_err(dev, "Cannot request GPMC CS %d, error %d\n", gpmc_onenand_data->cs, err); - return; + return err; } gpmc_onenand_resource.end = gpmc_onenand_resource.start + ONENAND_IO_SIZE - 1; - if (platform_device_register(&gpmc_onenand_device) < 0) { + err = platform_device_register(&gpmc_onenand_device); + if (err) { dev_err(dev, "Unable to register OneNAND device\n"); gpmc_cs_free(gpmc_onenand_data->cs); - return; } + + return err; } diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S index fe36ce2734d4..4c6f14cf92a8 100644 --- a/arch/arm/mach-omap2/omap-headsmp.S +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -17,6 +17,7 @@ #include <linux/linkage.h> #include <linux/init.h> +#include <asm/assembler.h> #include "omap44xx.h" @@ -66,7 +67,7 @@ wait_2: ldr r2, =AUX_CORE_BOOT0_PA @ read from AuxCoreBoot0 cmp r0, r4 bne wait_2 ldr r12, =API_HYP_ENTRY - adr r0, hyp_boot + badr r0, hyp_boot smc #0 hyp_boot: b omap_secondary_startup diff --git a/arch/arm/mach-omap2/omap-hotplug.c b/arch/arm/mach-omap2/omap-hotplug.c index d3fb5661bb5d..433db6d0b073 100644 --- a/arch/arm/mach-omap2/omap-hotplug.c +++ b/arch/arm/mach-omap2/omap-hotplug.c @@ -50,7 +50,7 @@ void omap4_cpu_die(unsigned int cpu) omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF); if (omap_secure_apis_support()) - boot_cpu = omap_read_auxcoreboot0(); + boot_cpu = omap_read_auxcoreboot0() >> 9; else boot_cpu = readl_relaxed(base + OMAP_AUX_CORE_BOOT_0) >> 5; diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 113ab2dd2ee9..03ec6d307c82 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -64,6 +64,7 @@ #include "prm-regbits-44xx.h" static void __iomem *sar_base; +static u32 old_cpu1_ns_pa_addr; #if defined(CONFIG_PM) && defined(CONFIG_SMP) @@ -212,6 +213,11 @@ static void __init save_l2x0_context(void) {} #endif +u32 omap4_get_cpu1_ns_pa_addr(void) +{ + return old_cpu1_ns_pa_addr; +} + /** * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function * The purpose of this function is to manage low power programming @@ -460,22 +466,30 @@ int __init omap4_mpuss_init(void) void __init omap4_mpuss_early_init(void) { unsigned long startup_pa; + void __iomem *ns_pa_addr; - if (!(cpu_is_omap44xx() || soc_is_omap54xx())) + if (!(soc_is_omap44xx() || soc_is_omap54xx())) return; sar_base = omap4_get_sar_ram_base(); - if (cpu_is_omap443x()) + /* Save old NS_PA_ADDR for validity checks later on */ + if (soc_is_omap44xx()) + ns_pa_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + else + ns_pa_addr = sar_base + OMAP5_CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + old_cpu1_ns_pa_addr = readl_relaxed(ns_pa_addr); + + if (soc_is_omap443x()) startup_pa = __pa_symbol(omap4_secondary_startup); - else if (cpu_is_omap446x()) + else if (soc_is_omap446x()) startup_pa = __pa_symbol(omap4460_secondary_startup); else if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE) startup_pa = __pa_symbol(omap5_secondary_hyp_startup); else startup_pa = __pa_symbol(omap5_secondary_startup); - if (cpu_is_omap44xx()) + if (soc_is_omap44xx()) writel_relaxed(startup_pa, sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET); else diff --git a/arch/arm/mach-omap2/omap-smc.S b/arch/arm/mach-omap2/omap-smc.S index fd90125bffc7..72506e6cf9e7 100644 --- a/arch/arm/mach-omap2/omap-smc.S +++ b/arch/arm/mach-omap2/omap-smc.S @@ -94,6 +94,5 @@ ENTRY(omap_read_auxcoreboot0) ldr r12, =0x103 dsb smc #0 - mov r0, r0, lsr #9 ldmfd sp!, {r2-r12, pc} ENDPROC(omap_read_auxcoreboot0) diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index 003353b0b794..3faf454ba487 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -21,6 +21,7 @@ #include <linux/io.h> #include <linux/irqchip/arm-gic.h> +#include <asm/sections.h> #include <asm/smp_scu.h> #include <asm/virt.h> @@ -40,10 +41,14 @@ #define OMAP5_CORE_COUNT 0x2 +#define AUX_CORE_BOOT0_GP_RELEASE 0x020 +#define AUX_CORE_BOOT0_HS_RELEASE 0x200 + struct omap_smp_config { unsigned long cpu1_rstctrl_pa; void __iomem *cpu1_rstctrl_va; void __iomem *scu_base; + void __iomem *wakeupgen_base; void *startup_addr; }; @@ -140,7 +145,6 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) static struct clockdomain *cpu1_clkdm; static bool booted; static struct powerdomain *cpu1_pwrdm; - void __iomem *base = omap_get_wakeupgen_base(); /* * Set synchronisation state between this boot processor @@ -155,9 +159,11 @@ static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) * A barrier is added to ensure that write buffer is drained */ if (omap_secure_apis_support()) - omap_modify_auxcoreboot0(0x200, 0xfffffdff); + omap_modify_auxcoreboot0(AUX_CORE_BOOT0_HS_RELEASE, + 0xfffffdff); else - writel_relaxed(0x20, base + OMAP_AUX_CORE_BOOT_0); + writel_relaxed(AUX_CORE_BOOT0_GP_RELEASE, + cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_0); if (!cpu1_clkdm && !cpu1_pwrdm) { cpu1_clkdm = clkdm_lookup("mpu1_clkdm"); @@ -261,9 +267,72 @@ static void __init omap4_smp_init_cpus(void) set_cpu_possible(i, true); } +/* + * For now, just make sure the start-up address is not within the booting + * kernel space as that means we just overwrote whatever secondary_startup() + * code there was. + */ +static bool __init omap4_smp_cpu1_startup_valid(unsigned long addr) +{ + if ((addr >= __pa(PAGE_OFFSET)) && (addr <= __pa(__bss_start))) + return false; + + return true; +} + +/* + * We may need to reset CPU1 before configuring, otherwise kexec boot can end + * up trying to use old kernel startup address or suspend-resume will + * occasionally fail to bring up CPU1 on 4430 if CPU1 fails to enter deeper + * idle states. + */ +static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c) +{ + unsigned long cpu1_startup_pa, cpu1_ns_pa_addr; + bool needs_reset = false; + u32 released; + + if (omap_secure_apis_support()) + released = omap_read_auxcoreboot0() & AUX_CORE_BOOT0_HS_RELEASE; + else + released = readl_relaxed(cfg.wakeupgen_base + + OMAP_AUX_CORE_BOOT_0) & + AUX_CORE_BOOT0_GP_RELEASE; + if (released) { + pr_warn("smp: CPU1 not parked?\n"); + + return; + } + + cpu1_startup_pa = readl_relaxed(cfg.wakeupgen_base + + OMAP_AUX_CORE_BOOT_1); + cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr(); + + /* Did the configured secondary_startup() get overwritten? */ + if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa)) + needs_reset = true; + + /* + * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a + * deeper idle state in WFI and will wake to an invalid address. + */ + if ((soc_is_omap44xx() || soc_is_omap54xx()) && + !omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr)) + needs_reset = true; + + if (!needs_reset || !c->cpu1_rstctrl_va) + return; + + pr_info("smp: CPU1 parked within kernel, needs reset (0x%lx 0x%lx)\n", + cpu1_startup_pa, cpu1_ns_pa_addr); + + writel_relaxed(1, c->cpu1_rstctrl_va); + readl_relaxed(c->cpu1_rstctrl_va); + writel_relaxed(0, c->cpu1_rstctrl_va); +} + static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) { - void __iomem *base = omap_get_wakeupgen_base(); const struct omap_smp_config *c = NULL; if (soc_is_omap443x()) @@ -281,6 +350,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) /* Must preserve cfg.scu_base set earlier */ cfg.cpu1_rstctrl_pa = c->cpu1_rstctrl_pa; cfg.startup_addr = c->startup_addr; + cfg.wakeupgen_base = omap_get_wakeupgen_base(); if (soc_is_dra74x() || soc_is_omap54xx()) { if ((__boot_cpu_mode & MODE_MASK) == HYP_MODE) @@ -299,15 +369,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) if (cfg.scu_base) scu_enable(cfg.scu_base); - /* - * Reset CPU1 before configuring, otherwise kexec will - * end up trying to use old kernel startup address. - */ - if (cfg.cpu1_rstctrl_va) { - writel_relaxed(1, cfg.cpu1_rstctrl_va); - readl_relaxed(cfg.cpu1_rstctrl_va); - writel_relaxed(0, cfg.cpu1_rstctrl_va); - } + omap4_smp_maybe_reset_cpu1(&cfg); /* * Write the address of secondary startup routine into the @@ -319,7 +381,7 @@ static void __init omap4_smp_prepare_cpus(unsigned int max_cpus) omap_auxcoreboot_addr(__pa_symbol(cfg.startup_addr)); else writel_relaxed(__pa_symbol(cfg.startup_addr), - base + OMAP_AUX_CORE_BOOT_1); + cfg.wakeupgen_base + OMAP_AUX_CORE_BOOT_1); } const struct smp_operations omap4_smp_ops __initconst = { diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index e920dd83e443..f989145480c8 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -222,6 +222,14 @@ static int _omap_device_notifier_call(struct notifier_block *nb, dev_err(dev, "failed to idle\n"); } break; + case BUS_NOTIFY_BIND_DRIVER: + od = to_omap_device(pdev); + if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && + pm_runtime_status_suspended(dev)) { + od->_driver_status = BUS_NOTIFY_BIND_DRIVER; + pm_runtime_set_active(dev); + } + break; case BUS_NOTIFY_ADD_DEVICE: if (pdev->dev.of_node) omap_device_build_from_dt(pdev); diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 0da4f2ea76c4..8bcea0d83fa0 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -138,7 +138,6 @@ #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/slab.h> -#include <linux/bootmem.h> #include <linux/cpu.h> #include <linux/of.h> #include <linux/of_address.h> @@ -216,49 +215,12 @@ static LIST_HEAD(omap_hwmod_list); /* mpu_oh: used to add/remove MPU initiator from sleepdep list */ static struct omap_hwmod *mpu_oh; -/* - * linkspace: ptr to a buffer that struct omap_hwmod_link records are - * allocated from - used to reduce the number of small memory - * allocations, which has a significant impact on performance - */ -static struct omap_hwmod_link *linkspace; - -/* - * free_ls, max_ls: array indexes into linkspace; representing the - * next free struct omap_hwmod_link index, and the maximum number of - * struct omap_hwmod_link records allocated (respectively) - */ -static unsigned short free_ls, max_ls, ls_supp; - /* inited: set to true once the hwmod code is initialized */ static bool inited; /* Private functions */ /** - * _fetch_next_ocp_if - return the next OCP interface in a list - * @p: ptr to a ptr to the list_head inside the ocp_if to return - * @i: pointer to the index of the element pointed to by @p in the list - * - * Return a pointer to the struct omap_hwmod_ocp_if record - * containing the struct list_head pointed to by @p, and increment - * @p such that a future call to this routine will return the next - * record. - */ -static struct omap_hwmod_ocp_if *_fetch_next_ocp_if(struct list_head **p, - int *i) -{ - struct omap_hwmod_ocp_if *oi; - - oi = list_entry(*p, struct omap_hwmod_link, node)->ocp_if; - *p = (*p)->next; - - *i = *i + 1; - - return oi; -} - -/** * _update_sysc_cache - return the module OCP_SYSCONFIG register, keep copy * @oh: struct omap_hwmod * * @@ -794,15 +756,10 @@ static int _init_main_clk(struct omap_hwmod *oh) static int _init_interface_clks(struct omap_hwmod *oh) { struct omap_hwmod_ocp_if *os; - struct list_head *p; struct clk *c; - int i = 0; int ret = 0; - p = oh->slave_ports.next; - - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); + list_for_each_entry(os, &oh->slave_ports, node) { if (!os->clk) continue; @@ -905,19 +862,13 @@ static void _disable_optional_clocks(struct omap_hwmod *oh) static int _enable_clocks(struct omap_hwmod *oh) { struct omap_hwmod_ocp_if *os; - struct list_head *p; - int i = 0; pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name); if (oh->_clk) clk_enable(oh->_clk); - p = oh->slave_ports.next; - - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); - + list_for_each_entry(os, &oh->slave_ports, node) { if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) clk_enable(os->_clk); } @@ -939,19 +890,13 @@ static int _enable_clocks(struct omap_hwmod *oh) static int _disable_clocks(struct omap_hwmod *oh) { struct omap_hwmod_ocp_if *os; - struct list_head *p; - int i = 0; pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name); if (oh->_clk) clk_disable(oh->_clk); - p = oh->slave_ports.next; - - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); - + list_for_each_entry(os, &oh->slave_ports, node) { if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) clk_disable(os->_clk); } @@ -1190,16 +1135,11 @@ static int _get_sdma_req_by_name(struct omap_hwmod *oh, const char *name, static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name, u32 *pa_start, u32 *pa_end) { - int i, j; + int j; struct omap_hwmod_ocp_if *os; - struct list_head *p = NULL; bool found = false; - p = oh->slave_ports.next; - - i = 0; - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); + list_for_each_entry(os, &oh->slave_ports, node) { if (!os->addr) return -ENOENT; @@ -1239,18 +1179,13 @@ static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name, static void __init _save_mpu_port_index(struct omap_hwmod *oh) { struct omap_hwmod_ocp_if *os = NULL; - struct list_head *p; - int i = 0; if (!oh) return; oh->_int_flags |= _HWMOD_NO_MPU_PORT; - p = oh->slave_ports.next; - - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); + list_for_each_entry(os, &oh->slave_ports, node) { if (os->user & OCP_USER_MPU) { oh->_mpu_port = os; oh->_int_flags &= ~_HWMOD_NO_MPU_PORT; @@ -1393,7 +1328,7 @@ static void _enable_sysc(struct omap_hwmod *oh) */ if ((oh->flags & HWMOD_SET_DEFAULT_CLOCKACT) && (sf & SYSC_HAS_CLOCKACTIVITY)) - _set_clockactivity(oh, oh->class->sysc->clockact, &v); + _set_clockactivity(oh, CLOCKACT_TEST_ICLK, &v); _write_sysconfig(v, oh); @@ -2092,7 +2027,7 @@ static int _enable(struct omap_hwmod *oh) r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) : -EINVAL; - if (oh->clkdm) + if (oh->clkdm && !(oh->flags & HWMOD_CLKDM_NOAUTO)) clkdm_allow_idle(oh->clkdm); if (!r) { @@ -2149,7 +2084,12 @@ static int _idle(struct omap_hwmod *oh) _idle_sysc(oh); _del_initiator_dep(oh, mpu_oh); - if (oh->clkdm) + /* + * If HWMOD_CLKDM_NOAUTO is set then we don't + * deny idle the clkdm again since idle was already denied + * in _enable() + */ + if (oh->clkdm && !(oh->flags & HWMOD_CLKDM_NOAUTO)) clkdm_deny_idle(oh->clkdm); if (oh->flags & HWMOD_BLOCK_WFI) @@ -2451,15 +2391,11 @@ static int __init _init(struct omap_hwmod *oh, void *data) static void __init _setup_iclk_autoidle(struct omap_hwmod *oh) { struct omap_hwmod_ocp_if *os; - struct list_head *p; - int i = 0; + if (oh->_state != _HWMOD_STATE_INITIALIZED) return; - p = oh->slave_ports.next; - - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); + list_for_each_entry(os, &oh->slave_ports, node) { if (!os->_clk) continue; @@ -2657,7 +2593,6 @@ static int __init _register(struct omap_hwmod *oh) list_add_tail(&oh->node, &omap_hwmod_list); - INIT_LIST_HEAD(&oh->master_ports); INIT_LIST_HEAD(&oh->slave_ports); spin_lock_init(&oh->_lock); lockdep_set_class(&oh->_lock, &oh->hwmod_key); @@ -2675,49 +2610,10 @@ static int __init _register(struct omap_hwmod *oh) } /** - * _alloc_links - return allocated memory for hwmod links - * @ml: pointer to a struct omap_hwmod_link * for the master link - * @sl: pointer to a struct omap_hwmod_link * for the slave link - * - * Return pointers to two struct omap_hwmod_link records, via the - * addresses pointed to by @ml and @sl. Will first attempt to return - * memory allocated as part of a large initial block, but if that has - * been exhausted, will allocate memory itself. Since ideally this - * second allocation path will never occur, the number of these - * 'supplemental' allocations will be logged when debugging is - * enabled. Returns 0. - */ -static int __init _alloc_links(struct omap_hwmod_link **ml, - struct omap_hwmod_link **sl) -{ - unsigned int sz; - - if ((free_ls + LINKS_PER_OCP_IF) <= max_ls) { - *ml = &linkspace[free_ls++]; - *sl = &linkspace[free_ls++]; - return 0; - } - - sz = sizeof(struct omap_hwmod_link) * LINKS_PER_OCP_IF; - - *sl = NULL; - *ml = memblock_virt_alloc(sz, 0); - - *sl = (void *)(*ml) + sizeof(struct omap_hwmod_link); - - ls_supp++; - pr_debug("omap_hwmod: supplemental link allocations needed: %d\n", - ls_supp * LINKS_PER_OCP_IF); - - return 0; -}; - -/** * _add_link - add an interconnect between two IP blocks * @oi: pointer to a struct omap_hwmod_ocp_if record * - * Add struct omap_hwmod_link records connecting the master IP block - * specified in @oi->master to @oi, and connecting the slave IP block + * Add struct omap_hwmod_link records connecting the slave IP block * specified in @oi->slave to @oi. This code is assumed to run before * preemption or SMP has been enabled, thus avoiding the need for * locking in this code. Changes to this assumption will require @@ -2725,19 +2621,10 @@ static int __init _alloc_links(struct omap_hwmod_link **ml, */ static int __init _add_link(struct omap_hwmod_ocp_if *oi) { - struct omap_hwmod_link *ml, *sl; - pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name, oi->slave->name); - _alloc_links(&ml, &sl); - - ml->ocp_if = oi; - list_add(&ml->node, &oi->master->master_ports); - oi->master->masters_cnt++; - - sl->ocp_if = oi; - list_add(&sl->node, &oi->slave->slave_ports); + list_add(&oi->node, &oi->slave->slave_ports); oi->slave->slaves_cnt++; return 0; @@ -2784,45 +2671,6 @@ static int __init _register_link(struct omap_hwmod_ocp_if *oi) return 0; } -/** - * _alloc_linkspace - allocate large block of hwmod links - * @ois: pointer to an array of struct omap_hwmod_ocp_if records to count - * - * Allocate a large block of struct omap_hwmod_link records. This - * improves boot time significantly by avoiding the need to allocate - * individual records one by one. If the number of records to - * allocate in the block hasn't been manually specified, this function - * will count the number of struct omap_hwmod_ocp_if records in @ois - * and use that to determine the allocation size. For SoC families - * that require multiple list registrations, such as OMAP3xxx, this - * estimation process isn't optimal, so manual estimation is advised - * in those cases. Returns -EEXIST if the allocation has already occurred - * or 0 upon success. - */ -static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois) -{ - unsigned int i = 0; - unsigned int sz; - - if (linkspace) { - WARN(1, "linkspace already allocated\n"); - return -EEXIST; - } - - if (max_ls == 0) - while (ois[i++]) - max_ls += LINKS_PER_OCP_IF; - - sz = sizeof(struct omap_hwmod_link) * max_ls; - - pr_debug("omap_hwmod: %s: allocating %d byte linkspace (%d links)\n", - __func__, sz, max_ls); - - linkspace = memblock_virt_alloc(sz, 0); - - return 0; -} - /* Static functions intended only for use in soc_ops field function pointers */ /** @@ -3180,13 +3028,6 @@ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois) if (ois[0] == NULL) /* Empty list */ return 0; - if (!linkspace) { - if (_alloc_linkspace(ois)) { - pr_err("omap_hwmod: could not allocate link space\n"); - return -ENOMEM; - } - } - i = 0; do { r = _register_link(ois[i]); @@ -3398,14 +3239,10 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags) ret += _count_sdma_reqs(oh); if (flags & IORESOURCE_MEM) { - int i = 0; struct omap_hwmod_ocp_if *os; - struct list_head *p = oh->slave_ports.next; - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); + list_for_each_entry(os, &oh->slave_ports, node) ret += _count_ocp_if_addr_spaces(os); - } } return ret; @@ -3424,7 +3261,6 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags) int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res) { struct omap_hwmod_ocp_if *os; - struct list_head *p; int i, j, mpu_irqs_cnt, sdma_reqs_cnt, addr_cnt; int r = 0; @@ -3454,11 +3290,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res) r++; } - p = oh->slave_ports.next; - - i = 0; - while (i < oh->slaves_cnt) { - os = _fetch_next_ocp_if(&p, &i); + list_for_each_entry(os, &oh->slave_ports, node) { addr_cnt = _count_ocp_if_addr_spaces(os); for (j = 0; j < addr_cnt; j++) { diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h index 78904017f18c..a8f779381fd8 100644 --- a/arch/arm/mach-omap2/omap_hwmod.h +++ b/arch/arm/mach-omap2/omap_hwmod.h @@ -313,6 +313,7 @@ struct omap_hwmod_ocp_if { struct omap_hwmod_addr_space *addr; const char *clk; struct clk *_clk; + struct list_head node; union { struct omap_hwmod_omap2_firewall omap2; } fw; @@ -410,7 +411,6 @@ struct omap_hwmod_class_sysconfig { struct omap_hwmod_sysc_fields *sysc_fields; u8 srst_udelay; u8 idlemodes; - u8 clockact; }; /** @@ -531,6 +531,10 @@ struct omap_hwmod_omap4_prcm { * operate and they need to be handled at the same time as the main_clk. * HWMOD_NO_IDLE: Do not idle the hwmod at all. Useful to handle certain * IPs like CPSW on DRA7, where clocks to this module cannot be disabled. + * HWMOD_CLKDM_NOAUTO: Allows the hwmod's clockdomain to be prevented from + * entering HW_AUTO while hwmod is active. This is needed to workaround + * some modules which don't function correctly with HW_AUTO. For example, + * DCAN on DRA7x SoC needs this to workaround errata i893. */ #define HWMOD_SWSUP_SIDLE (1 << 0) #define HWMOD_SWSUP_MSTANDBY (1 << 1) @@ -548,6 +552,7 @@ struct omap_hwmod_omap4_prcm { #define HWMOD_RECONFIG_IO_CHAIN (1 << 13) #define HWMOD_OPT_CLKS_NEEDED (1 << 14) #define HWMOD_NO_IDLE (1 << 15) +#define HWMOD_CLKDM_NOAUTO (1 << 16) /* * omap_hwmod._int_flags definitions @@ -617,16 +622,6 @@ struct omap_hwmod_class { }; /** - * struct omap_hwmod_link - internal structure linking hwmods with ocp_ifs - * @ocp_if: OCP interface structure record pointer - * @node: list_head pointing to next struct omap_hwmod_link in a list - */ -struct omap_hwmod_link { - struct omap_hwmod_ocp_if *ocp_if; - struct list_head node; -}; - -/** * struct omap_hwmod - integration data for OMAP hardware "modules" (IP blocks) * @name: name of the hwmod * @class: struct omap_hwmod_class * to the class of this hwmod @@ -686,9 +681,8 @@ struct omap_hwmod { const char *main_clk; struct clk *_clk; struct omap_hwmod_opt_clk *opt_clks; - char *clkdm_name; + const char *clkdm_name; struct clockdomain *clkdm; - struct list_head master_ports; /* connect to *_IA */ struct list_head slave_ports; /* connect to *_TA */ void *dev_attr; u32 _sysc_cache; @@ -698,12 +692,11 @@ struct omap_hwmod { struct list_head node; struct omap_hwmod_ocp_if *_mpu_port; unsigned int (*xlate_irq)(unsigned int); - u16 flags; + u32 flags; u8 mpu_rt_idx; u8 response_lat; u8 rst_lines_cnt; u8 opt_clks_cnt; - u8 masters_cnt; u8 slaves_cnt; u8 hwmods_cnt; u8 _int_flags; diff --git a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c index e047033caa3e..d190f1ad97b7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c @@ -55,7 +55,6 @@ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = { SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 56f917ec8621..1c6ca4d5fa2d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -149,7 +149,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = { SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -424,7 +423,6 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = { SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -1045,7 +1043,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sysc = { SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), .sysc_fields = &omap_hwmod_sysc_type1, - .clockact = 0x2, }; static struct omap_hwmod_class omap3xxx_mcbsp_hwmod_class = { @@ -1210,7 +1207,6 @@ static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = { static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = { .sysc_offs = 0x24, .sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap34xx_sr_sysc_fields, }; @@ -2112,11 +2108,20 @@ static struct omap_hwmod_ocp_if omap3_l4_core__i2c3 = { }; /* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap3_sr1_addr_space[] = { + { + .pa_start = OMAP34XX_SR1_BASE, + .pa_end = OMAP34XX_SR1_BASE + SZ_1K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; static struct omap_hwmod_ocp_if omap34xx_l4_core__sr1 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap34xx_sr1_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr1_addr_space, .user = OCP_USER_MPU, }; @@ -2124,15 +2129,25 @@ static struct omap_hwmod_ocp_if omap36xx_l4_core__sr1 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap36xx_sr1_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr1_addr_space, .user = OCP_USER_MPU, }; /* L4 CORE -> SR1 interface */ +static struct omap_hwmod_addr_space omap3_sr2_addr_space[] = { + { + .pa_start = OMAP34XX_SR2_BASE, + .pa_end = OMAP34XX_SR2_BASE + SZ_1K - 1, + .flags = ADDR_TYPE_RT, + }, + { }, +}; static struct omap_hwmod_ocp_if omap34xx_l4_core__sr2 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap34xx_sr2_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr2_addr_space, .user = OCP_USER_MPU, }; @@ -2140,6 +2155,7 @@ static struct omap_hwmod_ocp_if omap36xx_l4_core__sr2 = { .master = &omap3xxx_l4_core_hwmod, .slave = &omap36xx_sr2_hwmod, .clk = "sr_l4_ick", + .addr = omap3_sr2_addr_space, .user = OCP_USER_MPU, }; @@ -3111,16 +3127,20 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_hwmod_ocp_ifs[] __initdata = { * Return: 0 if device named @dev_name is not likely to be accessible, * or 1 if it is likely to be accessible. */ -static int __init omap3xxx_hwmod_is_hs_ip_block_usable(struct device_node *bus, - const char *dev_name) +static bool __init omap3xxx_hwmod_is_hs_ip_block_usable(struct device_node *bus, + const char *dev_name) { + struct device_node *node; + bool available; + if (!bus) - return (omap_type() == OMAP2_DEVICE_TYPE_GP) ? 1 : 0; + return omap_type() == OMAP2_DEVICE_TYPE_GP; - if (of_device_is_available(of_find_node_by_name(bus, dev_name))) - return 1; + node = of_get_child_by_name(bus, dev_name); + available = of_device_is_available(node); + of_node_put(node); - return 0; + return available; } int __init omap3xxx_hwmod_init(void) @@ -3189,15 +3209,20 @@ int __init omap3xxx_hwmod_init(void) if (h_sham && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "sham")) { r = omap_hwmod_register_links(h_sham); - if (r < 0) + if (r < 0) { + of_node_put(bus); return r; + } } if (h_aes && omap3xxx_hwmod_is_hs_ip_block_usable(bus, "aes")) { r = omap_hwmod_register_links(h_aes); - if (r < 0) + if (r < 0) { + of_node_put(bus); return r; + } } + of_node_put(bus); /* * Register hwmod links specific to certain ES levels of a diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index dad871a4cd96..94f09c720f29 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1320,7 +1320,6 @@ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = { SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | SIDLE_SMART_WKUP), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -2548,7 +2547,6 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = { SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index a2d763a4cc57..9a67f013ebad 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -839,7 +839,6 @@ static struct omap_hwmod_class_sysconfig omap54xx_i2c_sysc = { SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | SIDLE_SMART_WKUP), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -1530,7 +1529,6 @@ static struct omap_hwmod_class_sysconfig omap54xx_timer_1ms_sysc = { .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | SIDLE_SMART_WKUP), .sysc_fields = &omap_hwmod_sysc_type2, - .clockact = CLOCKACT_TEST_ICLK, }; static struct omap_hwmod_class omap54xx_timer_1ms_hwmod_class = { diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c index d0585293a381..b3abb8d8b2f6 100644 --- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c @@ -359,6 +359,7 @@ static struct omap_hwmod dra7xx_dcan1_hwmod = { .class = &dra7xx_dcan_hwmod_class, .clkdm_name = "wkupaon_clkdm", .main_clk = "dcan1_sys_clk_mux", + .flags = HWMOD_CLKDM_NOAUTO, .prcm = { .omap4 = { .clkctrl_offs = DRA7XX_CM_WKUPAON_DCAN1_CLKCTRL_OFFSET, @@ -374,6 +375,7 @@ static struct omap_hwmod dra7xx_dcan2_hwmod = { .class = &dra7xx_dcan_hwmod_class, .clkdm_name = "l4per2_clkdm", .main_clk = "sys_clkin1", + .flags = HWMOD_CLKDM_NOAUTO, .prcm = { .omap4 = { .clkctrl_offs = DRA7XX_CM_L4PER2_DCAN2_CLKCTRL_OFFSET, @@ -1098,7 +1100,6 @@ static struct omap_hwmod_class_sysconfig dra7xx_i2c_sysc = { SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | SIDLE_SMART_WKUP), - .clockact = CLOCKACT_TEST_ICLK, .sysc_fields = &omap_hwmod_sysc_type1, }; @@ -2700,6 +2701,7 @@ static struct omap_hwmod dra7xx_usb_otg_ss1_hwmod = { .class = &dra7xx_usb_otg_ss_hwmod_class, .clkdm_name = "l3init_clkdm", .main_clk = "dpll_core_h13x2_ck", + .flags = HWMOD_CLKDM_NOAUTO, .prcm = { .omap4 = { .clkctrl_offs = DRA7XX_CM_L3INIT_USB_OTG_SS1_CLKCTRL_OFFSET, @@ -2721,6 +2723,7 @@ static struct omap_hwmod dra7xx_usb_otg_ss2_hwmod = { .class = &dra7xx_usb_otg_ss_hwmod_class, .clkdm_name = "l3init_clkdm", .main_clk = "dpll_core_h13x2_ck", + .flags = HWMOD_CLKDM_NOAUTO, .prcm = { .omap4 = { .clkctrl_offs = DRA7XX_CM_L3INIT_USB_OTG_SS2_CLKCTRL_OFFSET, diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c index b82b77cff24c..310afe474ec4 100644 --- a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c @@ -106,6 +106,7 @@ */ #define DM81XX_CM_DEFAULT_OFFSET 0x500 #define DM81XX_CM_DEFAULT_USB_CLKCTRL (0x558 - DM81XX_CM_DEFAULT_OFFSET) +#define DM81XX_CM_DEFAULT_SATA_CLKCTRL (0x560 - DM81XX_CM_DEFAULT_OFFSET) /* L3 Interconnect entries clocked at 125, 250 and 500MHz */ static struct omap_hwmod dm81xx_alwon_l3_slow_hwmod = { @@ -973,6 +974,38 @@ static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = { .user = OCP_USER_MPU, }; +static struct omap_hwmod_class_sysconfig dm81xx_sata_sysc = { + .sysc_offs = 0x1100, + .sysc_flags = SYSC_HAS_SIDLEMODE, + .idlemodes = SIDLE_FORCE, + .sysc_fields = &omap_hwmod_sysc_type3, +}; + +static struct omap_hwmod_class dm81xx_sata_hwmod_class = { + .name = "sata", + .sysc = &dm81xx_sata_sysc, +}; + +static struct omap_hwmod dm81xx_sata_hwmod = { + .name = "sata", + .clkdm_name = "default_sata_clkdm", + .flags = HWMOD_NO_IDLEST, + .prcm = { + .omap4 = { + .clkctrl_offs = DM81XX_CM_DEFAULT_SATA_CLKCTRL, + .modulemode = MODULEMODE_SWCTRL, + }, + }, + .class = &dm81xx_sata_hwmod_class, +}; + +static struct omap_hwmod_ocp_if dm81xx_l4_hs__sata = { + .master = &dm81xx_l4_hs_hwmod, + .slave = &dm81xx_sata_hwmod, + .clk = "sysclk5_ck", + .user = OCP_USER_MPU, +}; + static struct omap_hwmod_class_sysconfig dm81xx_mmc_sysc = { .rev_offs = 0x0, .sysc_offs = 0x110, @@ -1474,6 +1507,7 @@ static struct omap_hwmod_ocp_if *dm816x_hwmod_ocp_ifs[] __initdata = { &dm81xx_l4_hs__emac0, &dm81xx_emac0__mdio, &dm816x_l4_hs__emac1, + &dm81xx_l4_hs__sata, &dm81xx_alwon_l3_fast__tpcc, &dm81xx_alwon_l3_fast__tptc0, &dm81xx_alwon_l3_fast__tptc1, diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 0598630c1778..63027e60cc20 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -163,7 +163,6 @@ static int omap_pm_enter(suspend_state_t suspend_state) return -ENOENT; /* XXX doublecheck */ switch (suspend_state) { - case PM_SUSPEND_STANDBY: case PM_SUSPEND_MEM: ret = omap_pm_suspend(); break; |