diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/clock44xx_data.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-omap2/devices.c | 93 | ||||
-rw-r--r-- | arch/arm/mach-omap2/id.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h | 56 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap2plus-cpufreq.c | 209 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 124 | ||||
-rw-r--r-- | arch/arm/mach-omap2/opp4xxx_data.c | 39 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm44xx.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-omap2/temp_sensor_device.c | 95 | ||||
-rw-r--r-- | arch/arm/plat-omap/Kconfig | 10 | ||||
-rw-r--r-- | arch/arm/plat-omap/devices.c | 96 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/dsscomp.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/temperature_sensor.h | 65 |
14 files changed, 658 insertions, 158 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 95fd52f..c3072d4 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o obj-$(CONFIG_TWL4030_CORE) += omap_twl.o obj-$(CONFIG_OMAP_TPS6236X) += omap_tps6236x.o +obj-$(CONFIG_OMAP_TEMP_SENSOR) +=temp_sensor_device.o # SMP support ONLY available for OMAP4 obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c index 836ab86..6f3e3a7 100644 --- a/arch/arm/mach-omap2/clock44xx_data.c +++ b/arch/arm/mach-omap2/clock44xx_data.c @@ -1286,11 +1286,26 @@ static struct clk l4_wkup_clk_mux_ck = { .recalc = &omap2_clksel_recalc, }; +static const struct clksel_rate div3_8to32_rates[] = { + { .div = 8, .val = 0, .flags = RATE_IN_44XX }, + { .div = 16, .val = 1, .flags = RATE_IN_44XX }, + { .div = 32, .val = 2, .flags = RATE_IN_44XX }, + { .div = 0 }, +}; + +static const struct clksel div_ts_ck_div[] = { + { .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates }, + { .parent = NULL }, +}; + static struct clk div_ts_ck = { .name = "div_ts_ck", .parent = &l4_wkup_clk_mux_ck, + .clksel = div_ts_ck_div, + .clksel_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL, + .clksel_mask = OMAP4430_CLKSEL_24_25_MASK, .ops = &clkops_null, - .recalc = &followparent_recalc, + .recalc = &omap2_clksel_recalc, }; static const struct clksel per_abe_nc_fclk_div[] = { @@ -3281,8 +3296,8 @@ static struct omap_clk omap44xx_clks[] = { CLK(NULL, "aes1_fck", &aes1_fck, CK_44XX), CLK(NULL, "aes2_fck", &aes2_fck, CK_44XX), CLK(NULL, "aess_fck", &aess_fck, CK_44XX), - CLK(NULL, "bandgap_fclk", &bandgap_fclk, CK_443X), - CLK(NULL, "bandgap_ts_fclk", &bandgap_ts_fclk, CK_446X), + CLK("omap_temp_sensor.0", "fck", &bandgap_fclk, CK_443X), + CLK("omap_temp_sensor.0", "fck", &bandgap_ts_fclk, CK_446X), CLK(NULL, "des3des_fck", &des3des_fck, CK_44XX), CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_44XX), CLK(NULL, "dmic_fck", &dmic_fck, CK_44XX), diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 3dc233d..d9add97 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -33,6 +33,9 @@ #include <plat/omap_hwmod.h> #include <plat/omap_device.h> #include <plat/omap4-keypad.h> +#include <plat/mcpdm.h> + +#include <sound/omap-abe-dsp.h> #include "mux.h" #include "control.h" @@ -294,6 +297,94 @@ static inline void omap_init_mbox(void) { } static inline void omap_init_sti(void) {} +#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \ + defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE) + +static struct omap_device_pm_latency omap_mcpdm_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +static void omap_init_mcpdm(void) +{ + struct omap_hwmod *oh; + struct omap_device *od; + struct omap_mcpdm_platform_data *pdata; + char *oh_name = "mcpdm"; + char *dev_name = "omap-mcpdm"; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("%s: could not look up %s\n", __func__, oh_name); + return; + } + + pdata = kzalloc(sizeof(struct omap_mcpdm_platform_data), GFP_KERNEL); + if (!pdata) { + pr_err("%s: could not allocate platform data\n", __func__); + return; + } + + od = omap_device_build(dev_name, -1, oh, pdata, + sizeof(struct omap_mcpdm_platform_data), + omap_mcpdm_latency, + ARRAY_SIZE(omap_mcpdm_latency), 0); + WARN(IS_ERR(od), "could not build omap_device for %s:%s\n", + oh_name, dev_name); +} +#else +static inline void omap_init_mcpdm(void) {} +#endif + +#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) || \ + defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE) + +static struct omap_device_pm_latency omap_aess_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; + +static void omap_init_aess(void) +{ + struct omap_hwmod *oh; + struct omap_device *od; + struct omap4_abe_dsp_pdata *pdata; + char *oh_name = "aess"; + char *dev_name = "aess"; + + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("%s: could not look up %s\n", __func__, oh_name); + return; + } + + pdata = kzalloc(sizeof(struct omap4_abe_dsp_pdata), GFP_KERNEL); + if (!pdata) { + pr_err("%s: could not allocate platform data\n", __func__); + return; + } + + pdata->device_scale = omap_device_scale; + + od = omap_device_build(dev_name, -1, oh, pdata, + sizeof(struct omap4_abe_dsp_pdata), + omap_aess_latency, + ARRAY_SIZE(omap_aess_latency), 0); + WARN(IS_ERR(od), "could not build omap_device for %s:%s\n", + oh_name, dev_name); + + kfree(pdata); +} +#else +static inline void omap_init_aess(void) {} +#endif + #if defined CONFIG_ARCH_OMAP4 static struct platform_device omap_abe_dai = { @@ -760,6 +851,8 @@ static int __init omap2_init_devices(void) * please keep these calls, and their implementations above, * in alphabetical order so they're easier to sort through. */ + omap_init_mcpdm(); + omap_init_aess(); omap_init_abe(); omap_init_audio(); omap_init_camera(); diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 72526f1..fe9dab5 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -242,6 +242,7 @@ static void __init omap4_check_features(void) case 2: /* High performance device */ omap4_features |= OMAP4_HAS_MPU_1_5GHZ; + omap4_features |= OMAP4_HAS_MPU_1_2GHZ; break; case 1: default: diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h index 2f7ac70..1e60707 100644 --- a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h +++ b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h @@ -257,18 +257,50 @@ #define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK (0x1f << 0) /* TEMP_SENSOR */ -#define OMAP4_BGAP_TEMPSOFF_SHIFT 12 -#define OMAP4_BGAP_TEMPSOFF_MASK (1 << 12) -#define OMAP4_BGAP_TSHUT_SHIFT 11 -#define OMAP4_BGAP_TSHUT_MASK (1 << 11) -#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT 10 -#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK (1 << 10) -#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT 9 -#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK (1 << 9) -#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT 8 -#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 8) -#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0 -#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK (0xff << 0) +#define OMAP4_BGAP_TEMPSOFF_SHIFT 13 +#define OMAP4_BGAP_TEMPSOFF_MASK (1 << 13) +#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT 12 +#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK (1 << 12) +#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT 11 +#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK (1 << 11) +#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT 10 +#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK (1 << 10) +#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT 0 +#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK (0x3ff << 0) + +/* BANDGAP_CTRL */ +#define OMAP4_SINGLE_MODE_SHIFT 31 +#define OMAP4_SINGLE_MODE_MASK (1 << 31) +#define OMAP4_MASK_HOT_SHIFT 1 +#define OMAP4_MASK_HOT_MASK (1 << 1) +#define OMAP4_MASK_COLD_SHIFT 0 +#define OMAP4_MASK_COLD_MASK (1 << 0) + +/* BANDGAP_COUNTER */ +#define OMAP4_COUNTER_SHIFT 0 +#define OMAP4_COUNTER_MASK (0xffffff << 0) + +/* BANDGAP_THRESHOLD */ +#define OMAP4_T_HOT_SHIFT 16 +#define OMAP4_T_HOT_MASK (0x3ff << 16) +#define OMAP4_T_COLD_SHIFT 0 +#define OMAP4_T_COLD_MASK (0x3ff << 0) + +/* TSHUT_THRESHOLD */ +#define OMAP4_TSHUT_HOT_SHIFT 16 +#define OMAP4_TSHUT_HOT_MASK (0x3ff << 16) +#define OMAP4_TSHUT_COLD_SHIFT 0 +#define OMAP4_TSHUT_COLD_MASK (0x3ff << 0) + +/* BANDGAP_STATUS */ +#define OMAP4_CLEAN_STOP_SHIFT 3 +#define OMAP4_CLEAN_STOP_MASK (1 << 3) +#define OMAP4_BGAP_ALERT_SHIFT 2 +#define OMAP4_BGAP_ALERT_MASK (1 << 2) +#define OMAP4_HOT_FLAG_SHIFT 1 +#define OMAP4_HOT_FLAG_MASK (1 << 1) +#define OMAP4_COLD_FLAG_SHIFT 0 +#define OMAP4_COLD_FLAG_MASK (1 << 0) /* DPLL_NWELL_TRIM_0 */ #define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT 29 diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c index 883325f..99a2f77 100644 --- a/arch/arm/mach-omap2/omap2plus-cpufreq.c +++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c @@ -46,6 +46,8 @@ struct lpj_info { unsigned int freq; }; +#define THROTTLE_DELAY_MS 1000 + static DEFINE_PER_CPU(struct lpj_info, lpj_ref); static struct lpj_info global_lpj_ref; #endif @@ -55,13 +57,11 @@ static atomic_t freq_table_users = ATOMIC_INIT(0); static struct clk *mpu_clk; static char *mpu_clk_name; static struct device *mpu_dev; +static DEFINE_MUTEX(omap_cpufreq_lock); -static int omap_verify_speed(struct cpufreq_policy *policy) -{ - if (!freq_table) - return -EINVAL; - return cpufreq_frequency_table_verify(policy, freq_table); -} +static unsigned int max_thermal; +static unsigned int max_freq; +static unsigned int current_target_freq; static unsigned int omap_getspeed(unsigned int cpu) { @@ -74,45 +74,28 @@ static unsigned int omap_getspeed(unsigned int cpu) return rate; } -static int omap_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int omap_cpufreq_scale(unsigned int target_freq, unsigned int cur_freq) { unsigned int i; - int ret = 0; + int ret; struct cpufreq_freqs freqs; - if (!freq_table) { - dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__, - policy->cpu); - return -EINVAL; - } + freqs.new = target_freq; + freqs.old = omap_getspeed(0); - ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, - relation, &i); - if (ret) { - dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n", - __func__, policy->cpu, target_freq, ret); - return ret; - } - freqs.new = freq_table[i].frequency; - if (!freqs.new) { - dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__, - policy->cpu, target_freq); - return -EINVAL; - } - - freqs.old = omap_getspeed(policy->cpu); - freqs.cpu = policy->cpu; + /* + * If the new frequency is more than the thermal max allowed + * frequency, go ahead and scale the mpu device to proper frequency. + */ + if (freqs.new > max_thermal) + freqs.new = max_thermal; - if (freqs.old == freqs.new && policy->cur == freqs.new) - return ret; + if ((freqs.old == freqs.new) && (cur_freq = freqs.new)) + return 0; /* notifiers */ - for_each_cpu(i, policy->cpus) { - freqs.cpu = i; + for_each_online_cpu(freqs.cpu) cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - } #ifdef CONFIG_CPU_FREQ_DEBUG pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new); @@ -120,7 +103,7 @@ static int omap_target(struct cpufreq_policy *policy, ret = omap_device_scale(mpu_dev, mpu_dev, freqs.new * 1000); - freqs.new = omap_getspeed(policy->cpu); + freqs.new = omap_getspeed(0); #ifdef CONFIG_SMP /* @@ -128,7 +111,7 @@ static int omap_target(struct cpufreq_policy *policy, * cpufreq driver. So, update the per-CPU loops_per_jiffy value * on frequency transition. We need to update all dependent CPUs. */ - for_each_cpu(i, policy->cpus) { + for_each_possible_cpu(i) { struct lpj_info *lpj = &per_cpu(lpj_ref, i); if (!lpj->freq) { lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy; @@ -149,11 +132,152 @@ static int omap_target(struct cpufreq_policy *policy, #endif /* notifiers */ - for_each_cpu(i, policy->cpus) { - freqs.cpu = i; + for_each_online_cpu(freqs.cpu) cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return ret; +} + +static unsigned int omap_thermal_lower_speed(void) +{ + unsigned int max = 0; + unsigned int curr; + int i; + + curr = max_thermal; + + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) + if (freq_table[i].frequency > max && + freq_table[i].frequency < curr) + max = freq_table[i].frequency; + + if (!max) + return curr; + + return max; +} + +static void throttle_delayed_work_fn(struct work_struct *work); + +static DECLARE_DELAYED_WORK(throttle_delayed_work, throttle_delayed_work_fn); + +static void throttle_delayed_work_fn(struct work_struct *work) +{ + unsigned int new_max; + unsigned int cur; + + mutex_lock(&omap_cpufreq_lock); + + if (max_thermal == max_freq) + goto out; + + new_max = omap_thermal_lower_speed(); + if (new_max == max_thermal) + goto out; + + max_thermal = new_max; + + pr_warn("%s: temperature still too high, throttling cpu to max %u\n", + __func__, max_thermal); + + cur = omap_getspeed(0); + if (cur > max_thermal) + omap_cpufreq_scale(max_thermal, cur); + + schedule_delayed_work(&throttle_delayed_work, + msecs_to_jiffies(THROTTLE_DELAY_MS)); + +out: + mutex_unlock(&omap_cpufreq_lock); +} + +void omap_thermal_throttle(void) +{ + unsigned int cur; + + mutex_lock(&omap_cpufreq_lock); + + if (max_thermal != max_freq) { + pr_warn("%s: already throttling\n", __func__); + goto out; + } + + max_thermal = omap_thermal_lower_speed(); + + pr_warn("%s: temperature too high, starting cpu throttling at max %u\n", + __func__, max_thermal); + + cur = omap_getspeed(0); + if (cur > max_thermal) + omap_cpufreq_scale(max_thermal, cur); + + schedule_delayed_work(&throttle_delayed_work, + msecs_to_jiffies(THROTTLE_DELAY_MS)); + +out: + mutex_unlock(&omap_cpufreq_lock); +} + +void omap_thermal_unthrottle(void) +{ + unsigned int cur; + + mutex_lock(&omap_cpufreq_lock); + + if (max_thermal == max_freq) { + pr_warn("%s: not throttling\n", __func__); + goto out; + } + + max_thermal = max_freq; + + cancel_delayed_work_sync(&throttle_delayed_work); + + pr_warn("%s: temperature reduced, ending cpu throttling\n", __func__); + + cur = omap_getspeed(0); + omap_cpufreq_scale(current_target_freq, cur); + +out: + mutex_unlock(&omap_cpufreq_lock); +} + +static int omap_verify_speed(struct cpufreq_policy *policy) +{ + if (!freq_table) + return -EINVAL; + return cpufreq_frequency_table_verify(policy, freq_table); +} + +static int omap_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int i; + int ret = 0; + + if (!freq_table) { + dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__, + policy->cpu); + return -EINVAL; } + ret = cpufreq_frequency_table_target(policy, freq_table, target_freq, + relation, &i); + if (ret) { + dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n", + __func__, policy->cpu, target_freq, ret); + return ret; + } + + mutex_lock(&omap_cpufreq_lock); + + current_target_freq = freq_table[i].frequency; + + ret = omap_cpufreq_scale(current_target_freq, policy->cur); + + mutex_unlock(&omap_cpufreq_lock); + return ret; } @@ -166,6 +290,7 @@ static inline void freq_table_free(void) static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) { int result = 0; + int i; mpu_clk = clk_get(NULL, mpu_clk_name); if (IS_ERR(mpu_clk)) @@ -197,6 +322,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) policy->max = policy->cpuinfo.max_freq; policy->cur = omap_getspeed(policy->cpu); + for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) + max_freq = max(freq_table[i].frequency, max_freq); + max_thermal = max_freq; + /* * On OMAP SMP configuartion, both processors share the voltage * and clock. So both CPUs needs to be scaled together and hence diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 333e813..5562def 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -1036,6 +1036,124 @@ static struct omap_hwmod omap44xx_aess_hwmod = { }; /* + * 'ctrl_module' class + * attila core control module + */ + +static struct omap_hwmod_class_sysconfig omap44xx_ctrl_module_sysc = { + .rev_offs = 0x0000, + .sysc_offs = 0x0010, + .sysc_flags = SYSC_HAS_SIDLEMODE, + .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | + SIDLE_SMART_WKUP), + .sysc_fields = &omap_hwmod_sysc_type2, +}; + +static struct omap_hwmod_class omap44xx_ctrl_module_hwmod_class = { + .name = "ctrl_module", + .sysc = &omap44xx_ctrl_module_sysc, +}; + +/* ctrl_module_core */ +static struct omap_hwmod omap44xx_ctrl_module_core_hwmod; +static struct omap_hwmod_irq_info omap44xx_ctrl_module_core_irqs[] = { + { .name = "sec_evts", .irq = 8 + OMAP44XX_IRQ_GIC_START }, + { .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_ctrl_module_core_addrs[] = { + { + .pa_start = 0x4a002000, + .pa_end = 0x4a0027ff, + + .flags = ADDR_TYPE_RT + }, +}; + +/* l4_cfg -> ctrl_module_core */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__ctrl_module_core = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_ctrl_module_core_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_ctrl_module_core_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_ctrl_module_core_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* ctrl_module_core slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_ctrl_module_core_slaves[] = { + &omap44xx_l4_cfg__ctrl_module_core, +}; + +static struct omap_hwmod omap44xx_ctrl_module_core_hwmod = { + .name = "ctrl_module_core", + .class = &omap44xx_ctrl_module_hwmod_class, + .mpu_irqs = omap44xx_ctrl_module_core_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_ctrl_module_core_irqs), + .main_clk = "l4_div_ck", + .slaves = omap44xx_ctrl_module_core_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_ctrl_module_core_slaves), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X), +}; +/* + * 'thermal_sensor' class + * thermal sensor module inside the bandgap / control module + */ + +static struct omap_hwmod_class omap44xx_thermal_sensor_hwmod_class = { + .name = "thermal_sensor", +}; + +static struct omap_hwmod_irq_info omap44xx_thermal_sensor_irqs[] = { + { .name = "thermal_alert", .irq = 126 + OMAP44XX_IRQ_GIC_START }, +}; + +static struct omap_hwmod_addr_space omap44xx_thermal_sensor_addrs[] = { + { + .pa_start = 0x4a002378, + .pa_end = 0x4a0023ff, + }, +}; + +static struct omap_hwmod omap44xx_thermal_sensor_hwmod; +/* l4_cfg -> ctrl_module_core */ +static struct omap_hwmod_ocp_if omap44xx_l4_cfg__thermal_sensor = { + .master = &omap44xx_l4_cfg_hwmod, + .slave = &omap44xx_thermal_sensor_hwmod, + .clk = "l4_div_ck", + .addr = omap44xx_thermal_sensor_addrs, + .addr_cnt = ARRAY_SIZE(omap44xx_thermal_sensor_addrs), + .user = OCP_USER_MPU | OCP_USER_SDMA, +}; + +/* ctrl_module_core slave ports */ +static struct omap_hwmod_ocp_if *omap44xx_thermal_sensor_slaves[] = { + &omap44xx_l4_cfg__thermal_sensor, +}; + +static struct omap_hwmod_opt_clk thermal_sensor446x_opt_clks[] = { + { .role = "fclk", .clk = "bandgap_ts_fclk" }, +}; + +static struct omap_hwmod omap44xx_thermal_sensor_hwmod = { + .name = "thermal_sensor", + .class = &omap44xx_thermal_sensor_hwmod_class, + .mpu_irqs = omap44xx_thermal_sensor_irqs, + .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_thermal_sensor_irqs), + .main_clk = "bandgap_ts_fclk", + .slaves = omap44xx_thermal_sensor_slaves, + .slaves_cnt = ARRAY_SIZE(omap44xx_thermal_sensor_slaves), + .prcm = { + .omap4 = { + .clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL, + }, + }, + .opt_clks = thermal_sensor446x_opt_clks, + .opt_clks_cnt = ARRAY_SIZE(thermal_sensor446x_opt_clks), + .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP446X), +}; + +/* * 'bandgap' class * bangap reference for ldo regulators */ @@ -5947,6 +6065,12 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = { &omap44xx_timer10_hwmod, &omap44xx_timer11_hwmod, + /* ctrl module class */ + &omap44xx_ctrl_module_core_hwmod, + + /* thermal sensor hwmod */ + &omap44xx_thermal_sensor_hwmod, + /* uart class */ &omap44xx_uart1_hwmod, &omap44xx_uart2_hwmod, diff --git a/arch/arm/mach-omap2/opp4xxx_data.c b/arch/arm/mach-omap2/opp4xxx_data.c index 9ea8aa7..1d5400f 100644 --- a/arch/arm/mach-omap2/opp4xxx_data.c +++ b/arch/arm/mach-omap2/opp4xxx_data.c @@ -19,8 +19,10 @@ * GNU General Public License for more details. */ #include <linux/module.h> +#include <linux/opp.h> #include <plat/cpu.h> +#include <plat/common.h> #include "control.h" #include "omap_opp_data.h" @@ -228,12 +230,7 @@ static struct omap_opp_def __initdata omap446x_opp_def_list[] = { OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 700000000, OMAP4460_VDD_MPU_OPP100_UV), /* MPU OPP3 - OPP-Turbo */ OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", true, 920000000, OMAP4460_VDD_MPU_OPPTURBO_UV), - /* - * MPU OPP4 - OPP-Nitro + Disabled as the reference schematics - * recommends TPS623631 - confirm and enable the opp in board file - * XXX: May be we should enable these based on mpu capability and - * Exception board files disable it... - */ + /* MPU OPP4 - OPP-Nitro */ OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", false, 1200000000, OMAP4460_VDD_MPU_OPPNITRO_UV), /* MPU OPP4 - OPP-Nitro SpeedBin */ OPP_INITIALIZER("mpu", "virt_dpll_mpu_ck", "mpu", false, 1500000000, OMAP4460_VDD_MPU_OPPNITRO_UV), @@ -286,6 +283,28 @@ static struct omap_opp_def __initdata omap446x_opp_def_list[] = { }; /** + * omap4_mpu_opp_enable() - helper to enable the OPP + * @freq: frequency to enable + */ +static void __init omap4_mpu_opp_enable(unsigned long freq) +{ + struct device *mpu_dev; + int r; + + mpu_dev = omap2_get_mpuss_device(); + if (!mpu_dev) { + pr_err("%s: no mpu_dev, did not enable f=%ld\n", __func__, + freq); + return; + } + + r = opp_enable(mpu_dev, freq); + if (r < 0) + dev_err(mpu_dev, "%s: opp_enable failed(%d) f=%ld\n", __func__, + r, freq); +} + +/** * omap4_opp_init() - initialize omap4 opp table */ int __init omap4_opp_init(void) @@ -300,6 +319,14 @@ int __init omap4_opp_init(void) else if (cpu_is_omap446x()) r = omap_init_opp_table(omap446x_opp_def_list, ARRAY_SIZE(omap446x_opp_def_list)); + + if (!r) { + if (omap4_has_mpu_1_2ghz()) + omap4_mpu_opp_enable(1200000000); + if (omap4_has_mpu_1_5ghz()) + omap4_mpu_opp_enable(1500000000); + } + return r; } device_initcall(omap4_opp_init); diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index faf93ec..2d3bb51 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -26,6 +26,7 @@ #include <mach/omap4-common.h> #include <plat/omap_hsi.h> #include <plat/common.h> +#include <plat/temperature_sensor.h> #include <plat/usb.h> #include "powerdomain.h" @@ -144,6 +145,7 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) omap_vc_set_auto_trans(iva_voltdm, OMAP_VC_CHANNEL_AUTO_TRANSITION_RETENTION); + omap_temp_sensor_prepare_idle(); omap2_gpio_prepare_for_idle(0); } } @@ -159,6 +161,8 @@ void omap4_enter_sleep(unsigned int cpu, unsigned int power_state, bool suspend) OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE); omap_vc_set_auto_trans(iva_voltdm, OMAP_VC_CHANNEL_AUTO_TRANSITION_DISABLE); + + omap_temp_sensor_resume_idle(); omap2_gpio_resume_after_idle(); if (!suspend) { omap_sr_enable(iva_voltdm); diff --git a/arch/arm/mach-omap2/temp_sensor_device.c b/arch/arm/mach-omap2/temp_sensor_device.c new file mode 100644 index 0000000..0a647a3 --- /dev/null +++ b/arch/arm/mach-omap2/temp_sensor_device.c @@ -0,0 +1,95 @@ +/* + * OMAP on die Temperature sensor device file + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Author: J Keerthy <j-keerthy@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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/io.h> +#include <plat/omap_device.h> +#include "control.h" +#include "pm.h" +#include <plat/temperature_sensor.h> + +void omap_temp_sensor_resume_idle(void) +{ + omap_temp_sensor_idle(0); +} + +void omap_temp_sensor_prepare_idle(void) +{ + omap_temp_sensor_idle(1); +} + +static struct omap_device_pm_latency omap_temp_sensor_latency[] = { + { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + } +}; + +static int temp_sensor_dev_init(struct omap_hwmod *oh, void *user) +{ + struct omap_temp_sensor_pdata *temp_sensor_pdata; + struct omap_device *od; + static int i; + int ret = 0; + + temp_sensor_pdata = + kzalloc(sizeof(struct omap_temp_sensor_pdata), GFP_KERNEL); + if (!temp_sensor_pdata) { + pr_err + ("%s: Unable to allocate memory for %s.Error!\n", + __func__, oh->name); + return -ENOMEM; + } + + temp_sensor_pdata->offset = OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR; + + temp_sensor_pdata->name = "omap_temp_sensor"; + + od = omap_device_build(temp_sensor_pdata->name, i, oh, temp_sensor_pdata, + sizeof(*temp_sensor_pdata), + omap_temp_sensor_latency, + ARRAY_SIZE(omap_temp_sensor_latency), 0); + if (IS_ERR(od)) { + pr_warning("%s: Could not build omap_device for %s: %s.\n\n", + __func__, temp_sensor_pdata->name, oh->name); + ret = -EINVAL; + goto done; + } + + i++; +done: + kfree(temp_sensor_pdata); + return ret; +} + +int __init omap_devinit_temp_sensor(void) +{ + if (!cpu_is_omap446x()) + return 0; + + return omap_hwmod_for_each_by_class("thermal_sensor", + temp_sensor_dev_init, NULL); +} + +arch_initcall(omap_devinit_temp_sensor); diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index e85abd8..77a1f82 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -220,6 +220,16 @@ config OMAP_SERIAL_WAKE to data on the serial RX line. This allows you to wake the system from serial console. +config OMAP_TEMP_SENSOR + bool "OMAP Temp Sensor Support" + depends on ARCH_OMAP4 + default n + help + Say Y here if you want support for the temp sensor on OMAP4460. + This provides the temperature of the MPU + subsystem. Only one instance of on die temperature + sensor is present. + # this carveout should probably become generic and not omap specific config OMAP_REMOTEPROC_MEMPOOL_SIZE hex "Physical carveout memory pool size (Byte)" diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index bb60ff7..d8add7e7 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -30,12 +30,9 @@ #include <mach/gpio.h> #include <plat/menelaus.h> #include <plat/mcbsp.h> -#include <plat/mcpdm.h> #include <plat/remoteproc.h> #include <plat/omap44xx.h> -#include <sound/omap-abe-dsp.h> - /*-------------------------------------------------------------------------*/ #if defined(CONFIG_OMAP_MCBSP) || defined(CONFIG_OMAP_MCBSP_MODULE) @@ -81,48 +78,6 @@ void omap_mcbsp_register_board_cfg(struct resource *res, int res_count, /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_SND_OMAP_SOC_MCPDM) || \ - defined(CONFIG_SND_OMAP_SOC_MCPDM_MODULE) - -static struct omap_device_pm_latency omap_mcpdm_latency[] = { - { - .deactivate_func = omap_device_idle_hwmods, - .activate_func = omap_device_enable_hwmods, - .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, - }, -}; - -static void omap_init_mcpdm(void) -{ - struct omap_hwmod *oh; - struct omap_device *od; - struct omap_mcpdm_platform_data *pdata; - - oh = omap_hwmod_lookup("mcpdm"); - if (!oh) { - printk(KERN_ERR "Could not look up mcpdm hw_mod\n"); - return; - } - - pdata = kzalloc(sizeof(struct omap_mcpdm_platform_data), GFP_KERNEL); - if (!pdata) { - printk(KERN_ERR "Could not allocate platform data\n"); - return; - } - - od = omap_device_build("omap-mcpdm", -1, oh, pdata, - sizeof(struct omap_mcpdm_platform_data), - omap_mcpdm_latency, - ARRAY_SIZE(omap_mcpdm_latency), 0); - if (IS_ERR(od)) - printk(KERN_ERR "Could not build omap_device for omap-mcpdm-dai\n"); -} -#else -static inline void omap_init_mcpdm(void) {} -#endif - -/*-------------------------------------------------------------------------*/ - #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) @@ -173,55 +128,6 @@ fail: /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP) || \ - defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE) - -static struct omap_device_pm_latency omap_aess_latency[] = { - { - .deactivate_func = omap_device_idle_hwmods, - .activate_func = omap_device_enable_hwmods, - .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, - }, -}; - -static void omap_init_aess(void) -{ - struct omap_hwmod *oh; - struct omap_device *od; - struct omap4_abe_dsp_pdata *pdata; - - oh = omap_hwmod_lookup("aess"); - if (!oh) { - printk (KERN_ERR "Could not look up aess hw_mod\n"); - return; - } - - pdata = kzalloc(sizeof(struct omap4_abe_dsp_pdata), GFP_KERNEL); - if (!pdata) { - printk(KERN_ERR "Could not allocate platform data\n"); - return; - } - - /* FIXME: Add correct context loss counter */ - //pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count; - - od = omap_device_build("aess", -1, oh, pdata, - sizeof(struct omap4_abe_dsp_pdata), - omap_aess_latency, - ARRAY_SIZE(omap_aess_latency), 0); - - kfree(pdata); - - if (IS_ERR(od)) - printk(KERN_ERR "Could not build omap_device for omap-aess-audio\n"); -} -#else -static inline void omap_init_aess(void) {} -#endif - - -/*-------------------------------------------------------------------------*/ - #if defined(CONFIG_HW_RANDOM_OMAP) || defined(CONFIG_HW_RANDOM_OMAP_MODULE) #ifdef CONFIG_ARCH_OMAP2 @@ -421,8 +327,6 @@ static int __init omap_init_devices(void) * in alphabetical order so they're easier to sort through. */ omap_init_rng(); - omap_init_mcpdm(); - omap_init_aess(); omap_init_uwire(); return 0; } diff --git a/arch/arm/plat-omap/include/plat/dsscomp.h b/arch/arm/plat-omap/include/plat/dsscomp.h index b9f5773..f9f87cb 100644 --- a/arch/arm/plat-omap/include/plat/dsscomp.h +++ b/arch/arm/plat-omap/include/plat/dsscomp.h @@ -18,7 +18,7 @@ int dsscomp_delayed_apply(dsscomp_t comp); void dsscomp_drop(dsscomp_t c); struct tiler_pa_info; -int dsscomp_gralloc_queue(struct dsscomp_setup_mgr_data *d, +int dsscomp_gralloc_queue(struct dsscomp_setup_dispc_data *d, struct tiler_pa_info **pas, void (*cb_fn)(void *, int), void *cb_arg); #endif diff --git a/arch/arm/plat-omap/include/plat/temperature_sensor.h b/arch/arm/plat-omap/include/plat/temperature_sensor.h new file mode 100644 index 0000000..5f0d6b3 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/temperature_sensor.h @@ -0,0 +1,65 @@ +/* + * OMAP446x Temperature sensor header file + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * Author: J Keerthy <j-keerthy@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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_TEMPERATURE_SENSOR_H + +/* + * Offsets from the base of temperature sensor registers + */ +#define TEMP_SENSOR_CTRL_OFFSET 0x00 +#define BGAP_CTRL_OFFSET 0x4c +#define BGAP_COUNTER_OFFSET 0x50 +#define BGAP_THRESHOLD_OFFSET 0x54 +#define BGAP_TSHUT_OFFSET 0x58 +#define BGAP_STATUS_OFFSET 0x5c + +#define OMAP_TSHUT_GPIO 86 + + +/* + * omap_temp_sensor platform data + * @name - name + * @irq - Irq number for thermal alertemp_sensor + * @offset - offset of the temp sensor ctrl register + */ +struct omap_temp_sensor_pdata { + char *name; + u32 offset; + int irq; +}; + +#ifdef CONFIG_OMAP_TEMP_SENSOR +void omap_temp_sensor_resume_idle(void); +void omap_temp_sensor_prepare_idle(void); +#else +static inline void omap_temp_sensor_resume_idle(void) { } +static inline void omap_temp_sensor_prepare_idle(void) { } +#endif + +#ifdef CONFIG_OMAP_DIE_TEMP_SENSOR +void omap_temp_sensor_idle(int idle_state); +#else +static inline void omap_temp_sensor_idle(int idle_state) { } +#endif + +#endif |