diff options
Diffstat (limited to 'arch/arm/mach-imx')
| -rw-r--r-- | arch/arm/mach-imx/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/mach-imx/clk-busy.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-imx/clk-imx35.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-imx/clk-imx6q.c | 3 | ||||
| -rw-r--r-- | arch/arm/mach-imx/common.h | 2 | ||||
| -rw-r--r-- | arch/arm/mach-imx/cpufreq.c | 8 | ||||
| -rw-r--r-- | arch/arm/mach-imx/cpuidle-imx5.c | 37 | ||||
| -rw-r--r-- | arch/arm/mach-imx/cpuidle-imx6q.c | 26 | ||||
| -rw-r--r-- | arch/arm/mach-imx/cpuidle.c | 80 | ||||
| -rw-r--r-- | arch/arm/mach-imx/cpuidle.h | 10 | ||||
| -rw-r--r-- | arch/arm/mach-imx/hotplug.c | 12 | ||||
| -rw-r--r-- | arch/arm/mach-imx/pm-imx5.c | 30 | ||||
| -rw-r--r-- | arch/arm/mach-imx/src.c | 12 | 
13 files changed, 78 insertions, 148 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index c4ce0906d76..cb70961b623 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -30,7 +30,7 @@ obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o  obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o  ifeq ($(CONFIG_CPU_IDLE),y) -obj-y += cpuidle.o +obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o  obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o  endif diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c index 6809c99abb4..4bb1bc419b7 100644 --- a/arch/arm/mach-imx/clk-busy.c +++ b/arch/arm/mach-imx/clk-busy.c @@ -169,7 +169,7 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,  	busy->mux.reg = reg;  	busy->mux.shift = shift; -	busy->mux.width = width; +	busy->mux.mask = BIT(width) - 1;  	busy->mux.lock = &imx_ccm_lock;  	busy->mux_ops = &clk_mux_ops; diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c index e13a8fa5e62..2193c834f55 100644 --- a/arch/arm/mach-imx/clk-imx35.c +++ b/arch/arm/mach-imx/clk-imx35.c @@ -257,6 +257,7 @@ int __init mx35_clocks_init(void)  	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");  	clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");  	clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0"); +	clk_register_clkdev(clk[admux_gate], "audmux", NULL);  	clk_prepare_enable(clk[spba_gate]);  	clk_prepare_enable(clk[gpio1_gate]); @@ -265,6 +266,7 @@ int __init mx35_clocks_init(void)  	clk_prepare_enable(clk[iim_gate]);  	clk_prepare_enable(clk[emi_gate]);  	clk_prepare_enable(clk[max_gate]); +	clk_prepare_enable(clk[iomuxc_gate]);  	/*  	 * SCC is needed to boot via mmc after a watchdog reset. The clock code diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c index 2f9ff93a4e6..d38e54f5b6d 100644 --- a/arch/arm/mach-imx/clk-imx6q.c +++ b/arch/arm/mach-imx/clk-imx6q.c @@ -115,7 +115,7 @@ static const char *gpu2d_core_sels[]	= { "axi", "pll3_usb_otg", "pll2_pfd0_352m"  static const char *gpu3d_core_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };  static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };  static const char *ipu_sels[]		= { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; -static const char *ldb_di_sels[]	= { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_pfd1_540m", }; +static const char *ldb_di_sels[]	= { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };  static const char *ipu_di_pre_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };  static const char *ipu1_di0_sels[]	= { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };  static const char *ipu1_di1_sels[]	= { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; @@ -443,7 +443,6 @@ int __init mx6q_clocks_init(void)  	clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");  	clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0"); -	clk_register_clkdev(clk[twd], NULL, "smp_twd");  	clk_register_clkdev(clk[cko1_sel], "cko1_sel", NULL);  	clk_register_clkdev(clk[ahb], "ahb", NULL);  	clk_register_clkdev(clk[cko1], "cko1", NULL); diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 5a800bfcec5..5bf4a97ab24 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -110,6 +110,8 @@ void tzic_handle_irq(struct pt_regs *);  extern void imx_enable_cpu(int cpu, bool enable);  extern void imx_set_cpu_jump(int cpu, void *jump_addr); +extern u32 imx_get_cpu_arg(int cpu); +extern void imx_set_cpu_arg(int cpu, u32 arg);  extern void v7_cpu_resume(void);  extern u32 *pl310_get_save_ptr(void);  #ifdef CONFIG_SMP diff --git a/arch/arm/mach-imx/cpufreq.c b/arch/arm/mach-imx/cpufreq.c index d8c75c3c925..387dc4cceca 100644 --- a/arch/arm/mach-imx/cpufreq.c +++ b/arch/arm/mach-imx/cpufreq.c @@ -87,13 +87,12 @@ static int mxc_set_target(struct cpufreq_policy *policy,  	freqs.old = clk_get_rate(cpu_clk) / 1000;  	freqs.new = freq_Hz / 1000; -	freqs.cpu = 0;  	freqs.flags = 0; -	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); +	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);  	ret = set_cpu_freq(freq_Hz); -	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); +	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);  	return ret;  } @@ -145,14 +144,11 @@ static int mxc_cpufreq_init(struct cpufreq_policy *policy)  	imx_freq_table[i].frequency = CPUFREQ_TABLE_END;  	policy->cur = clk_get_rate(cpu_clk) / 1000; -	policy->min = policy->cpuinfo.min_freq = cpu_freq_khz_min; -	policy->max = policy->cpuinfo.max_freq = cpu_freq_khz_max;  	/* Manual states, that PLL stabilizes in two CLK32 periods */  	policy->cpuinfo.transition_latency = 2 * NANOSECOND / CLK32_FREQ;  	ret = cpufreq_frequency_table_cpuinfo(policy, imx_freq_table); -  	if (ret < 0) {  		printk(KERN_ERR "%s: failed to register i.MXC CPUfreq with error code %d\n",  		       __func__, ret); diff --git a/arch/arm/mach-imx/cpuidle-imx5.c b/arch/arm/mach-imx/cpuidle-imx5.c new file mode 100644 index 00000000000..5a47e3c6172 --- /dev/null +++ b/arch/arm/mach-imx/cpuidle-imx5.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 Freescale Semiconductor, Inc. + * + * 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/cpuidle.h> +#include <linux/module.h> +#include <asm/system_misc.h> + +static int imx5_cpuidle_enter(struct cpuidle_device *dev, +			      struct cpuidle_driver *drv, int index) +{ +	arm_pm_idle(); +	return index; +} + +static struct cpuidle_driver imx5_cpuidle_driver = { +	.name             = "imx5_cpuidle", +	.owner            = THIS_MODULE, +	.states[0] = { +		.enter            = imx5_cpuidle_enter, +		.exit_latency     = 2, +		.target_residency = 1, +		.flags            = CPUIDLE_FLAG_TIME_VALID, +		.name             = "IMX5 SRPG", +		.desc             = "CPU state retained,powered off", +	}, +	.state_count = 1, +}; + +int __init imx5_cpuidle_init(void) +{ +	return cpuidle_register(&imx5_cpuidle_driver, NULL); +} diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c index d533e2695f0..23ddfb693b2 100644 --- a/arch/arm/mach-imx/cpuidle-imx6q.c +++ b/arch/arm/mach-imx/cpuidle-imx6q.c @@ -6,7 +6,6 @@   * published by the Free Software Foundation.   */ -#include <linux/clockchips.h>  #include <linux/cpuidle.h>  #include <linux/module.h>  #include <asm/cpuidle.h> @@ -21,10 +20,6 @@ static DEFINE_SPINLOCK(master_lock);  static int imx6q_enter_wait(struct cpuidle_device *dev,  			    struct cpuidle_driver *drv, int index)  { -	int cpu = dev->cpu; - -	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); -  	if (atomic_inc_return(&master) == num_online_cpus()) {  		/*  		 * With this lock, we prevent other cpu to exit and enter @@ -43,26 +38,13 @@ idle:  	cpu_do_idle();  done:  	atomic_dec(&master); -	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);  	return index;  } -/* - * For each cpu, setup the broadcast timer because local timer - * stops for the states other than WFI. - */ -static void imx6q_setup_broadcast_timer(void *arg) -{ -	int cpu = smp_processor_id(); - -	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu); -} -  static struct cpuidle_driver imx6q_cpuidle_driver = {  	.name = "imx6q_cpuidle",  	.owner = THIS_MODULE, -	.en_core_tk_irqen = 1,  	.states = {  		/* WFI */  		ARM_CPUIDLE_WFI_STATE, @@ -70,7 +52,8 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {  		{  			.exit_latency = 50,  			.target_residency = 75, -			.flags = CPUIDLE_FLAG_TIME_VALID, +			.flags = CPUIDLE_FLAG_TIME_VALID | +			         CPUIDLE_FLAG_TIMER_STOP,  			.enter = imx6q_enter_wait,  			.name = "WAIT",  			.desc = "Clock off", @@ -88,8 +71,5 @@ int __init imx6q_cpuidle_init(void)  	/* Set chicken bit to get a reliable WAIT mode support */  	imx6q_set_chicken_bit(); -	/* Configure the broadcast timer on each cpu */ -	on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1); - -	return imx_cpuidle_init(&imx6q_cpuidle_driver); +	return cpuidle_register(&imx6q_cpuidle_driver, NULL);  } diff --git a/arch/arm/mach-imx/cpuidle.c b/arch/arm/mach-imx/cpuidle.c deleted file mode 100644 index d4cb511a44a..00000000000 --- a/arch/arm/mach-imx/cpuidle.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2012 Freescale Semiconductor, Inc. - * Copyright 2012 Linaro Ltd. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include <linux/cpuidle.h> -#include <linux/err.h> -#include <linux/hrtimer.h> -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/slab.h> - -static struct cpuidle_device __percpu * imx_cpuidle_devices; - -static void __init imx_cpuidle_devices_uninit(void) -{ -	int cpu_id; -	struct cpuidle_device *dev; - -	for_each_possible_cpu(cpu_id) { -		dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id); -		cpuidle_unregister_device(dev); -	} - -	free_percpu(imx_cpuidle_devices); -} - -int __init imx_cpuidle_init(struct cpuidle_driver *drv) -{ -	struct cpuidle_device *dev; -	int cpu_id, ret; - -	if (drv->state_count > CPUIDLE_STATE_MAX) { -		pr_err("%s: state_count exceeds maximum\n", __func__); -		return -EINVAL; -	} - -	ret = cpuidle_register_driver(drv); -	if (ret) { -		pr_err("%s: Failed to register cpuidle driver with error: %d\n", -			 __func__, ret); -		return ret; -	} - -	imx_cpuidle_devices = alloc_percpu(struct cpuidle_device); -	if (imx_cpuidle_devices == NULL) { -		ret = -ENOMEM; -		goto unregister_drv; -	} - -	/* initialize state data for each cpuidle_device */ -	for_each_possible_cpu(cpu_id) { -		dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id); -		dev->cpu = cpu_id; -		dev->state_count = drv->state_count; - -		ret = cpuidle_register_device(dev); -		if (ret) { -			pr_err("%s: Failed to register cpu %u, error: %d\n", -				__func__, cpu_id, ret); -			goto uninit; -		} -	} - -	return 0; - -uninit: -	imx_cpuidle_devices_uninit(); - -unregister_drv: -	cpuidle_unregister_driver(drv); -	return ret; -} diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h index e092d1359d9..786f98ecc14 100644 --- a/arch/arm/mach-imx/cpuidle.h +++ b/arch/arm/mach-imx/cpuidle.h @@ -10,18 +10,16 @@   * http://www.gnu.org/copyleft/gpl.html   */ -#include <linux/cpuidle.h> -  #ifdef CONFIG_CPU_IDLE -extern int imx_cpuidle_init(struct cpuidle_driver *drv); +extern int imx5_cpuidle_init(void);  extern int imx6q_cpuidle_init(void);  #else -static inline int imx_cpuidle_init(struct cpuidle_driver *drv) +static inline int imx5_cpuidle_init(void)  { -	return -ENODEV; +	return 0;  }  static inline int imx6q_cpuidle_init(void)  { -	return -ENODEV; +	return 0;  }  #endif diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 7bc5fe15dda..361a253e2b6 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(void)  void imx_cpu_die(unsigned int cpu)  {  	cpu_enter_lowpower(); +	/* +	 * We use the cpu jumping argument register to sync with +	 * imx_cpu_kill() which is running on cpu0 and waiting for +	 * the register being cleared to kill the cpu. +	 */ +	imx_set_cpu_arg(cpu, ~0);  	cpu_do_idle();  }  int imx_cpu_kill(unsigned int cpu)  { +	unsigned long timeout = jiffies + msecs_to_jiffies(50); + +	while (imx_get_cpu_arg(cpu) == 0) +		if (time_after(jiffies, timeout)) +			return 0;  	imx_enable_cpu(cpu, false); +	imx_set_cpu_arg(cpu, 0);  	return 1;  } diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c index f67fd7ee812..82e79c658eb 100644 --- a/arch/arm/mach-imx/pm-imx5.c +++ b/arch/arm/mach-imx/pm-imx5.c @@ -149,33 +149,6 @@ static void imx5_pm_idle(void)  	imx5_cpu_do_idle();  } -static int imx5_cpuidle_enter(struct cpuidle_device *dev, -				struct cpuidle_driver *drv, int idx) -{ -	int ret; - -	ret = imx5_cpu_do_idle(); -	if (ret < 0) -		return ret; - -	return idx; -} - -static struct cpuidle_driver imx5_cpuidle_driver = { -	.name			= "imx5_cpuidle", -	.owner			= THIS_MODULE, -	.en_core_tk_irqen	= 1, -	.states[0]	= { -		.enter			= imx5_cpuidle_enter, -		.exit_latency		= 2, -		.target_residency	= 1, -		.flags			= CPUIDLE_FLAG_TIME_VALID, -		.name			= "IMX5 SRPG", -		.desc			= "CPU state retained,powered off", -	}, -	.state_count		= 1, -}; -  static int __init imx5_pm_common_init(void)  {  	int ret; @@ -193,8 +166,7 @@ static int __init imx5_pm_common_init(void)  	/* Set the registers to the default cpu idle state. */  	mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE); -	imx_cpuidle_init(&imx5_cpuidle_driver); -	return 0; +	return imx5_cpuidle_init();  }  void __init imx51_pm_init(void) diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c index 648634d9b6c..324731c2a44 100644 --- a/arch/arm/mach-imx/src.c +++ b/arch/arm/mach-imx/src.c @@ -44,6 +44,18 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)  		       src_base + SRC_GPR1 + cpu * 8);  } +u32 imx_get_cpu_arg(int cpu) +{ +	cpu = cpu_logical_map(cpu); +	return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4); +} + +void imx_set_cpu_arg(int cpu, u32 arg) +{ +	cpu = cpu_logical_map(cpu); +	writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4); +} +  void imx_src_prepare_restart(void)  {  	u32 val;  |