diff options
Diffstat (limited to 'drivers/sh')
| -rw-r--r-- | drivers/sh/Makefile | 14 | ||||
| -rw-r--r-- | drivers/sh/clk/core.c | 20 | ||||
| -rw-r--r-- | drivers/sh/clk/cpg.c | 38 | ||||
| -rw-r--r-- | drivers/sh/intc/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/sh/intc/core.c | 6 | ||||
| -rw-r--r-- | drivers/sh/pm_runtime.c | 60 | 
6 files changed, 105 insertions, 35 deletions
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index fc67f564f02..788ed9b59b4 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -1,10 +1,12 @@  #  # Makefile for the SuperH specific drivers.  # -obj-y	:= intc/ +obj-$(CONFIG_SUPERH)			+= intc/ +obj-$(CONFIG_ARCH_SHMOBILE_LEGACY)	+= intc/ +ifneq ($(CONFIG_COMMON_CLK),y) +obj-$(CONFIG_HAVE_CLK)			+= clk/ +endif +obj-$(CONFIG_MAPLE)			+= maple/ +obj-$(CONFIG_SUPERHYWAY)		+= superhyway/ -obj-$(CONFIG_HAVE_CLK)		+= clk/ -obj-$(CONFIG_MAPLE)		+= maple/ -obj-$(CONFIG_SUPERHYWAY)	+= superhyway/ - -obj-y				+= pm_runtime.o +obj-y					+= pm_runtime.o diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 74727851820..be56b22ca94 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -196,17 +196,11 @@ int clk_rate_table_find(struct clk *clk,  			struct cpufreq_frequency_table *freq_table,  			unsigned long rate)  { -	int i; - -	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { -		unsigned long freq = freq_table[i].frequency; +	struct cpufreq_frequency_table *pos; -		if (freq == CPUFREQ_ENTRY_INVALID) -			continue; - -		if (freq == rate) -			return i; -	} +	cpufreq_for_each_valid_entry(pos, freq_table) +		if (pos->frequency == rate) +			return pos - freq_table;  	return -ENOENT;  } @@ -575,11 +569,7 @@ long clk_round_parent(struct clk *clk, unsigned long target,  		return abs(target - *best_freq);  	} -	for (freq = parent->freq_table; freq->frequency != CPUFREQ_TABLE_END; -	     freq++) { -		if (freq->frequency == CPUFREQ_ENTRY_INVALID) -			continue; - +	cpufreq_for_each_valid_entry(freq, parent->freq_table) {  		if (unlikely(freq->frequency / target <= div_min - 1)) {  			unsigned long freq_max; diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 1ebe67cd183..7442bc13005 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -36,9 +36,47 @@ static void sh_clk_write(int value, struct clk *clk)  		iowrite32(value, clk->mapped_reg);  } +static unsigned int r8(const void __iomem *addr) +{ +	return ioread8(addr); +} + +static unsigned int r16(const void __iomem *addr) +{ +	return ioread16(addr); +} + +static unsigned int r32(const void __iomem *addr) +{ +	return ioread32(addr); +} +  static int sh_clk_mstp_enable(struct clk *clk)  {  	sh_clk_write(sh_clk_read(clk) & ~(1 << clk->enable_bit), clk); +	if (clk->status_reg) { +		unsigned int (*read)(const void __iomem *addr); +		int i; +		void __iomem *mapped_status = (phys_addr_t)clk->status_reg - +			(phys_addr_t)clk->enable_reg + clk->mapped_reg; + +		if (clk->flags & CLK_ENABLE_REG_8BIT) +			read = r8; +		else if (clk->flags & CLK_ENABLE_REG_16BIT) +			read = r16; +		else +			read = r32; + +		for (i = 1000; +		     (read(mapped_status) & (1 << clk->enable_bit)) && i; +		     i--) +			cpu_relax(); +		if (!i) { +			pr_err("cpg: failed to enable %p[%d]\n", +			       clk->enable_reg, clk->enable_bit); +			return -ETIMEDOUT; +		} +	}  	return 0;  } diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig index a305731742a..60228fae943 100644 --- a/drivers/sh/intc/Kconfig +++ b/drivers/sh/intc/Kconfig @@ -6,7 +6,7 @@ comment "Interrupt controller options"  config INTC_USERIMASK  	bool "Userspace interrupt masking support" -	depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A) +	depends on (SUPERH && CPU_SH4A) || COMPILE_TEST  	help  	  This enables support for hardware-assisted userspace hardirq  	  masking. diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c index 8f32a1323a7..81f22980b2d 100644 --- a/drivers/sh/intc/core.c +++ b/drivers/sh/intc/core.c @@ -80,12 +80,6 @@ static void __init intc_register_irq(struct intc_desc *desc,  	unsigned int data[2], primary;  	unsigned long flags; -	/* -	 * Register the IRQ position with the global IRQ map, then insert -	 * it in to the radix tree. -	 */ -	irq_reserve_irq(irq); -  	raw_spin_lock_irqsave(&intc_big_lock, flags);  	radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq));  	raw_spin_unlock_irqrestore(&intc_big_lock, flags); diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c index 8afa5a4589f..72f63817a1a 100644 --- a/drivers/sh/pm_runtime.c +++ b/drivers/sh/pm_runtime.c @@ -21,18 +21,43 @@  #include <linux/slab.h>  #ifdef CONFIG_PM_RUNTIME - -static int default_platform_runtime_idle(struct device *dev) +static int sh_pm_runtime_suspend(struct device *dev)  { -	/* suspend synchronously to disable clocks immediately */ +	int ret; + +	ret = pm_generic_runtime_suspend(dev); +	if (ret) { +		dev_err(dev, "failed to suspend device\n"); +		return ret; +	} + +	ret = pm_clk_suspend(dev); +	if (ret) { +		dev_err(dev, "failed to suspend clock\n"); +		pm_generic_runtime_resume(dev); +		return ret; +	} +  	return 0;  } +static int sh_pm_runtime_resume(struct device *dev) +{ +	int ret; + +	ret = pm_clk_resume(dev); +	if (ret) { +		dev_err(dev, "failed to resume clock\n"); +		return ret; +	} + +	return pm_generic_runtime_resume(dev); +} +  static struct dev_pm_domain default_pm_domain = {  	.ops = { -		.runtime_suspend = pm_clk_suspend, -		.runtime_resume = pm_clk_resume, -		.runtime_idle = default_platform_runtime_idle, +		.runtime_suspend = sh_pm_runtime_suspend, +		.runtime_resume = sh_pm_runtime_resume,  		USE_PLATFORM_PM_SLEEP_OPS  	},  }; @@ -50,8 +75,28 @@ static struct pm_clk_notifier_block platform_bus_notifier = {  	.con_ids = { NULL, },  }; +static bool default_pm_on; +  static int __init sh_pm_runtime_init(void)  { +	if (IS_ENABLED(CONFIG_ARCH_SHMOBILE_MULTI)) { +		if (!of_machine_is_compatible("renesas,emev2") && +		    !of_machine_is_compatible("renesas,r7s72100") && +		    !of_machine_is_compatible("renesas,r8a73a4") && +		    !of_machine_is_compatible("renesas,r8a7740") && +		    !of_machine_is_compatible("renesas,r8a7778") && +		    !of_machine_is_compatible("renesas,r8a7779") && +		    !of_machine_is_compatible("renesas,r8a7790") && +		    !of_machine_is_compatible("renesas,r8a7791") && +		    !of_machine_is_compatible("renesas,r8a7792") && +		    !of_machine_is_compatible("renesas,r8a7793") && +		    !of_machine_is_compatible("renesas,r8a7794") && +		    !of_machine_is_compatible("renesas,sh7372") && +		    !of_machine_is_compatible("renesas,sh73a0")) +			return 0; +	} + +	default_pm_on = true;  	pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);  	return 0;  } @@ -59,7 +104,8 @@ core_initcall(sh_pm_runtime_init);  static int __init sh_pm_runtime_late_init(void)  { -	pm_genpd_poweroff_unused(); +	if (default_pm_on) +		pm_genpd_poweroff_unused();  	return 0;  }  late_initcall(sh_pm_runtime_late_init);  | 
