From 52c10ad22b7e317960b4d411c9a9ddeaf3d5ae39 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Date: Thu, 14 Apr 2011 17:13:53 +0900 Subject: [PATCH 01/23] sh: clkfwk: fixup clk_rate_table_build parameter in div6 clock div6 clock should not use arch_flags for clk_rate_table_build, because SH_CLK_DIV6_EXT doesn't care .arch_flags. clk->freq_table[] will be all CPUFREQ_ENTRY_INVALID without this patch. Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Cc: stable@kernel.org Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/sh/clk/cpg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 6172335ae3234..82dd6fb178386 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -105,7 +105,7 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) /* Rebuild the frequency table */ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, - table, &clk->arch_flags); + table, NULL); return 0; } From 5744c88111f076c98f389eae28ec2ff206ba2e14 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Fri, 15 Apr 2011 20:03:17 +0200 Subject: [PATCH 02/23] sh: fix SD / MMC configuration dependencies on ecovec Update CONFIG_MMC_TMIO to the new CONFIG_MMC_SDHI symbol and fix MMCIF to also function in modular builds for ecovec. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Simon Horman <horms@verge.net.au> Cc: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/boards/mach-ecovec24/setup.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 86a0d565adede..bb13d0e1b964c 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -482,7 +482,7 @@ static struct i2c_board_info ts_i2c_clients = { .irq = IRQ0, }; -#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE) +#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) /* SDHI0 */ static void sdhi0_set_pwr(struct platform_device *pdev, int state) { @@ -522,7 +522,7 @@ static struct platform_device sdhi0_device = { }, }; -#if !defined(CONFIG_MMC_SH_MMCIF) +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) /* SDHI1 */ static void sdhi1_set_pwr(struct platform_device *pdev, int state) { @@ -836,7 +836,7 @@ static struct platform_device vou_device = { }, }; -#if defined(CONFIG_MMC_SH_MMCIF) +#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE) /* SH_MMCIF */ static void mmcif_set_pwr(struct platform_device *pdev, int state) { @@ -898,9 +898,9 @@ static struct platform_device *ecovec_devices[] __initdata = { &ceu0_device, &ceu1_device, &keysc_device, -#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE) +#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) &sdhi0_device, -#if !defined(CONFIG_MMC_SH_MMCIF) +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) &sdhi1_device, #endif #else @@ -912,7 +912,7 @@ static struct platform_device *ecovec_devices[] __initdata = { &fsi_device, &irda_device, &vou_device, -#if defined(CONFIG_MMC_SH_MMCIF) +#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE) &sh_mmcif_device, #endif }; @@ -1180,7 +1180,7 @@ static int __init arch_setup(void) gpio_direction_input(GPIO_PTR5); gpio_direction_input(GPIO_PTR6); -#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE) +#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE) /* enable SDHI0 on CN11 (needs DS2.4 set to ON) */ gpio_request(GPIO_FN_SDHI0CD, NULL); gpio_request(GPIO_FN_SDHI0WP, NULL); @@ -1193,7 +1193,7 @@ static int __init arch_setup(void) gpio_request(GPIO_PTB6, NULL); gpio_direction_output(GPIO_PTB6, 0); -#if !defined(CONFIG_MMC_SH_MMCIF) +#if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE) /* enable SDHI1 on CN12 (needs DS2.6,7 set to ON,OFF) */ gpio_request(GPIO_FN_SDHI1CD, NULL); gpio_request(GPIO_FN_SDHI1WP, NULL); @@ -1284,7 +1284,7 @@ static int __init arch_setup(void) gpio_request(GPIO_PTU5, NULL); gpio_direction_output(GPIO_PTU5, 0); -#if defined(CONFIG_MMC_SH_MMCIF) +#if defined(CONFIG_MMC_SH_MMCIF) || defined(CONFIG_MMC_SH_MMCIF_MODULE) /* enable MMCIF (needs DS2.6,7 set to OFF,ON) */ gpio_request(GPIO_FN_MMC_D7, NULL); gpio_request(GPIO_FN_MMC_D6, NULL); From 013b19e3aa843e206a47098063258d5cc5c3482e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Fri, 15 Apr 2011 20:04:12 +0200 Subject: [PATCH 03/23] sh: update SDHI configuration symbols in defconfigs Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Simon Horman <horms@verge.net.au> Cc: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/configs/ecovec24_defconfig | 2 +- arch/sh/configs/sh7757lcr_defconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig index 8d13e8a5a7502..911e30c9abfdc 100644 --- a/arch/sh/configs/ecovec24_defconfig +++ b/arch/sh/configs/ecovec24_defconfig @@ -115,7 +115,7 @@ CONFIG_USB_GADGET=y CONFIG_USB_FILE_STORAGE=m CONFIG_MMC=y CONFIG_MMC_SPI=y -CONFIG_MMC_TMIO=y +CONFIG_MMC_SDHI=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_RS5C372=y CONFIG_UIO=y diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig index fa0ecf87034c8..33ddb130a7c8c 100644 --- a/arch/sh/configs/sh7757lcr_defconfig +++ b/arch/sh/configs/sh7757lcr_defconfig @@ -70,7 +70,7 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_MMC=y -CONFIG_MMC_TMIO=y +CONFIG_MMC_SDHI=y CONFIG_MMC_SH_MMCIF=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y From c40eb1e9e53dbd1e5601650565e2ed8bf14866ba Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Fri, 15 Apr 2011 20:17:34 +0200 Subject: [PATCH 04/23] ALSA: add a module alias to the FSI driver This patch enables FSI driver autoloading on sh-mobile systems. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Reviewed-by: Simon Horman <horms@verge.net.au> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- sound/soc/sh/fsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 0c9997e2d8c05..88b669c9af753 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1321,3 +1321,4 @@ module_exit(fsi_mobile_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("SuperH onchip FSI audio driver"); MODULE_AUTHOR("Kuninori Morimoto <morimoto.kuninori@renesas.com>"); +MODULE_ALIAS("platform:fsi-pcm-audio"); From 7ef0c12a280c059f4624d311bb1a7d946cbac7b7 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Fri, 15 Apr 2011 20:18:57 +0200 Subject: [PATCH 05/23] i2c: add a module alias to the sh-mobile driver This patch enables I2C driver autoloading on sh-mobile systems. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Reviewed-by: Simon Horman <horms@verge.net.au> Cc: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/i2c/busses/i2c-sh_mobile.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 2707f5e17158a..81ccd7875627e 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -729,3 +729,4 @@ module_exit(sh_mobile_i2c_adap_exit); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); MODULE_AUTHOR("Magnus Damm"); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:i2c-sh_mobile"); From a375b15164dd9264f724ad941825e52c90145151 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Date: Fri, 15 Apr 2011 16:44:27 +0900 Subject: [PATCH 06/23] sh: fixup fpu.o compile order arch_ptrace() was modified to reference init_fpu() to fix up xstate initialization, which overlooked the fact that there are configurations that don't enable any of hard FPU support or emulation, resulting in build errors on DSP parts. Given that init_fpu() simply sets up the xstate slab cache and is side-stepped entirely for the DSP case, we can simply always build in the helper and fix up the references. Reported-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Cc: stable@kernel.org Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/kernel/cpu/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index d49c2135fd480..ae95935d93cde 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -17,7 +17,5 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/ obj-$(CONFIG_SH_ADC) += adc.o obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o -obj-$(CONFIG_SH_FPU) += fpu.o -obj-$(CONFIG_SH_FPU_EMU) += fpu.o -obj-y += irq/ init.o clock.o hwblk.o proc.o +obj-y += irq/ init.o clock.o fpu.o hwblk.o proc.o From 442f56d917959cbc3fd7a56c5eb43b0d728cad26 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Mon, 18 Apr 2011 11:45:08 +0900 Subject: [PATCH 07/23] sh: intc: Set virtual IRQs as nothread. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/sh/intc/virq.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c index ce5f81d7cc6b8..1e6e2d0353ea5 100644 --- a/drivers/sh/intc/virq.c +++ b/drivers/sh/intc/virq.c @@ -235,6 +235,11 @@ static void __init intc_subgroup_map(struct intc_desc_int *d) irq_set_handler_data(irq, (void *)entry->handle); + /* + * Set the virtual IRQ as non-threadable. + */ + irq_set_nothread(irq); + irq_set_chained_handler(entry->pirq, intc_virq_handler); add_virq_to_pirq(entry->pirq, irq); From ed170924dd0db14b135a388966e0b6fd5188c3e5 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Mon, 18 Apr 2011 11:45:27 +0900 Subject: [PATCH 08/23] sh: select IRQ_FORCED_THREADING. With virtual IRQs fixed up with the genirq nothread infrastructure, IRQ threads can be enabled across the board. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 4b89da248d17a..dd4bf55094b28 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -21,6 +21,7 @@ config SUPERH select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_GENERIC_HARDIRQS select HAVE_SPARSE_IRQ + select IRQ_FORCED_THREADING select RTC_LIB select GENERIC_ATOMIC64 select GENERIC_IRQ_SHOW From 5e50d2d622c745d4439fc9a33d932cc3add2318f Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@opensource.se> Date: Tue, 19 Apr 2011 10:38:25 +0000 Subject: [PATCH 09/23] serial: sh-sci: Runtime PM support Add support for Runtime PM in the sh-sci driver. Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/tty/serial/sh-sci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 920a6f929c8b6..bb682c4e72a8c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -43,6 +43,7 @@ #include <linux/platform_device.h> #include <linux/serial_sci.h> #include <linux/notifier.h> +#include <linux/pm_runtime.h> #include <linux/cpufreq.h> #include <linux/clk.h> #include <linux/ctype.h> @@ -562,6 +563,9 @@ static void sci_break_timer(unsigned long data) { struct sci_port *port = (struct sci_port *)data; + if (port->enable) + port->enable(&port->port); + if (sci_rxd_in(&port->port) == 0) { port->break_flag = 1; sci_schedule_break_timer(port); @@ -571,6 +575,9 @@ static void sci_break_timer(unsigned long data) sci_schedule_break_timer(port); } else port->break_flag = 0; + + if (port->disable) + port->disable(&port->port); } static int sci_handle_errors(struct uart_port *port) @@ -839,6 +846,8 @@ static void sci_clk_enable(struct uart_port *port) { struct sci_port *sci_port = to_sci_port(port); + pm_runtime_get_sync(port->dev); + clk_enable(sci_port->iclk); sci_port->port.uartclk = clk_get_rate(sci_port->iclk); clk_enable(sci_port->fclk); @@ -850,6 +859,8 @@ static void sci_clk_disable(struct uart_port *port) clk_disable(sci_port->fclk); clk_disable(sci_port->iclk); + + pm_runtime_put_sync(port->dev); } static int sci_request_irq(struct sci_port *port) @@ -1758,6 +1769,8 @@ static int __devinit sci_init_single(struct platform_device *dev, sci_port->enable = sci_clk_enable; sci_port->disable = sci_clk_disable; port->dev = &dev->dev; + + pm_runtime_enable(&dev->dev); } sci_port->break_timer.data = (unsigned long)sci_port; @@ -1938,6 +1951,7 @@ static int sci_remove(struct platform_device *dev) clk_put(port->iclk); clk_put(port->fclk); + pm_runtime_disable(&dev->dev); return 0; } From 54aa89ea29d7dd7fd414297d4bdc8f6eff905784 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@opensource.se> Date: Thu, 21 Apr 2011 13:08:46 +0000 Subject: [PATCH 10/23] serial: sh-sci: suspend/resume wakeup support V2 This patch adds wakeup support to the sh-sci driver. The serial core deals with all details but defaults to wakeup disabled. So to make use of this feature enable wakeup in sysfs: echo enabled > /sys/class/tty/ttySC0/power/wakeup Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/tty/serial/sh-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index bb682c4e72a8c..c529580cee933 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1790,7 +1790,7 @@ static int __devinit sci_init_single(struct platform_device *dev, * * For the muxed case there's nothing more to do. */ - port->irq = p->irqs[SCIx_TXI_IRQ]; + port->irq = p->irqs[SCIx_RXI_IRQ]; if (p->dma_dev) dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n", From 3e4cd0737d2e9c3dd52153a23aef1753e3a99fc4 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Fri, 15 Apr 2011 18:05:27 +0000 Subject: [PATCH 11/23] sh: cosmetic improvement: use an existing pointer Use an existing local variable, instead of calculating the pointer multiple times explicitly. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Cc: Simon Horman <horms@verge.net.au> Cc: Magnus Damm <damm@opensource.se> Reviewed-by: Simon Horman <horms@verge.net.au> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/kernel/cpu/shmobile/pm_runtime.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c index 22db127afa7b2..64c807c392087 100644 --- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c +++ b/arch/sh/kernel/cpu/shmobile/pm_runtime.c @@ -157,7 +157,7 @@ static int default_platform_runtime_suspend(struct device *dev) might_sleep(); /* catch misconfigured drivers not starting with resume */ - if (test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags)) { + if (test_bit(PDEV_ARCHDATA_FLAG_INIT, &ad->flags)) { ret = -EINVAL; goto out; } @@ -170,8 +170,8 @@ static int default_platform_runtime_suspend(struct device *dev) /* put device on idle list */ spin_lock_irqsave(&hwblk_lock, flags); - list_add_tail(&pdev->archdata.entry, &hwblk_idle_list); - __set_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags); + list_add_tail(&ad->entry, &hwblk_idle_list); + __set_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags); spin_unlock_irqrestore(&hwblk_lock, flags); /* increase idle count */ From 5b02c51af48d6bd78e53c1e95196ce3a3572fad9 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@opensource.se> Date: Thu, 28 Apr 2011 03:10:35 +0000 Subject: [PATCH 12/23] sh: sh-sci: sh7377 and sh73a0 build fixes Fix sh7377 and sh73a0 build failure: drivers/tty/serial/sh-sci.c: In function 'scif_txfill': drivers/tty/serial/sh-sci.c:338: error: implicit declaration of function 'sci_SCTFDR_in' drivers/tty/serial/sh-sci.c: In function 'scif_rxfill': drivers/tty/serial/sh-sci.c:351: error: implicit declaration of function 'sci_SCRFDR_in' make[3]: *** [drivers/tty/serial/sh-sci.o] Error 1 make[2]: *** [drivers/tty/serial] Error 2 make[1]: *** [drivers/tty] Error 2 make: *** [drivers] Error 2 Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/tty/serial/sh-sci.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h index 5fefed53fa423..b04d937c91100 100644 --- a/drivers/tty/serial/sh-sci.h +++ b/drivers/tty/serial/sh-sci.h @@ -270,12 +270,12 @@ #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_ARCH_SH73A0) || \ - defined(CONFIG_ARCH_SH7367) || \ - defined(CONFIG_ARCH_SH7377) + defined(CONFIG_ARCH_SH7367) #define SCIF_FNS(name, scif_offset, scif_size) \ CPU_SCIF_FNS(name, scif_offset, scif_size) -#elif defined(CONFIG_ARCH_SH7372) +#elif defined(CONFIG_ARCH_SH7377) || \ + defined(CONFIG_ARCH_SH7372) || \ + defined(CONFIG_ARCH_SH73A0) #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) \ CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scifb_offset, sh4_scifb_size) #define SCIF_FNS(name, scif_offset, scif_size) \ @@ -313,9 +313,7 @@ #if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_ARCH_SH73A0) || \ - defined(CONFIG_ARCH_SH7367) || \ - defined(CONFIG_ARCH_SH7377) + defined(CONFIG_ARCH_SH7367) SCIF_FNS(SCSMR, 0x00, 16) SCIF_FNS(SCBRR, 0x04, 8) @@ -326,7 +324,9 @@ SCIF_FNS(SCFDR, 0x1c, 16) SCIF_FNS(SCxTDR, 0x20, 8) SCIF_FNS(SCxRDR, 0x24, 8) SCIF_FNS(SCLSR, 0x00, 0) -#elif defined(CONFIG_ARCH_SH7372) +#elif defined(CONFIG_ARCH_SH7377) || \ + defined(CONFIG_ARCH_SH7372) || \ + defined(CONFIG_ARCH_SH73A0) SCIF_FNS(SCSMR, 0x00, 16) SCIF_FNS(SCBRR, 0x04, 8) SCIF_FNS(SCSCR, 0x08, 16) From 2dc666673b5a39d005579a0ef63ae69b5094e686 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Fri, 29 Apr 2011 17:09:21 +0000 Subject: [PATCH 13/23] dmaengine: shdma: fix locking Close multiple theoretical races, especially the one in .device_free_chan_resources(). Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/dma/shdma.c | 104 +++++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 36 deletions(-) diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index d50da41ac328c..727f51e903d90 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -48,7 +48,7 @@ enum sh_dmae_desc_status { /* * Used for write-side mutual exclusion for the global device list, - * read-side synchronization by way of RCU. + * read-side synchronization by way of RCU, and per-controller data. */ static DEFINE_SPINLOCK(sh_dmae_lock); static LIST_HEAD(sh_dmae_devices); @@ -85,22 +85,35 @@ static void dmaor_write(struct sh_dmae_device *shdev, u16 data) */ static void sh_dmae_ctl_stop(struct sh_dmae_device *shdev) { - unsigned short dmaor = dmaor_read(shdev); + unsigned short dmaor; + unsigned long flags; + + spin_lock_irqsave(&sh_dmae_lock, flags); + dmaor = dmaor_read(shdev); dmaor_write(shdev, dmaor & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME)); + + spin_unlock_irqrestore(&sh_dmae_lock, flags); } static int sh_dmae_rst(struct sh_dmae_device *shdev) { unsigned short dmaor; + unsigned long flags; - sh_dmae_ctl_stop(shdev); - dmaor = dmaor_read(shdev) | shdev->pdata->dmaor_init; + spin_lock_irqsave(&sh_dmae_lock, flags); - dmaor_write(shdev, dmaor); - if (dmaor_read(shdev) & (DMAOR_AE | DMAOR_NMIF)) { - pr_warning("dma-sh: Can't initialize DMAOR.\n"); - return -EINVAL; + dmaor = dmaor_read(shdev) & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME); + + dmaor_write(shdev, dmaor | shdev->pdata->dmaor_init); + + dmaor = dmaor_read(shdev); + + spin_unlock_irqrestore(&sh_dmae_lock, flags); + + if (dmaor & (DMAOR_AE | DMAOR_NMIF)) { + dev_warn(shdev->common.dev, "Can't initialize DMAOR.\n"); + return -EIO; } return 0; } @@ -184,7 +197,7 @@ static void dmae_init(struct sh_dmae_chan *sh_chan) static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val) { - /* When DMA was working, can not set data to CHCR */ + /* If DMA is active, cannot set CHCR. TODO: remove this superfluous check */ if (dmae_is_busy(sh_chan)) return -EBUSY; @@ -374,7 +387,12 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) LIST_HEAD(list); int descs = sh_chan->descs_allocated; + /* Protect against ISR */ + spin_lock_irq(&sh_chan->desc_lock); dmae_halt(sh_chan); + spin_unlock_irq(&sh_chan->desc_lock); + + /* Now no new interrupts will occur */ /* Prepared and not submitted descriptors can still be on the queue */ if (!list_empty(&sh_chan->ld_queue)) @@ -384,6 +402,7 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan) /* The caller is holding dma_list_mutex */ struct sh_dmae_slave *param = chan->private; clear_bit(param->slave_id, sh_dmae_slave_used); + chan->private = NULL; } spin_lock_bh(&sh_chan->desc_lock); @@ -563,8 +582,6 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_memcpy( if (!chan || !len) return NULL; - chan->private = NULL; - sh_chan = to_sh_chan(chan); sg_init_table(&sg, 1); @@ -620,9 +637,9 @@ static int sh_dmae_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, if (!chan) return -EINVAL; + spin_lock_bh(&sh_chan->desc_lock); dmae_halt(sh_chan); - spin_lock_bh(&sh_chan->desc_lock); if (!list_empty(&sh_chan->ld_queue)) { /* Record partial transfer */ struct sh_desc *desc = list_entry(sh_chan->ld_queue.next, @@ -716,6 +733,14 @@ static dma_async_tx_callback __ld_cleanup(struct sh_dmae_chan *sh_chan, bool all list_move(&desc->node, &sh_chan->ld_free); } } + + if (all && !callback) + /* + * Terminating and the loop completed normally: forgive + * uncompleted cookies + */ + sh_chan->completed_cookie = sh_chan->common.cookie; + spin_unlock_bh(&sh_chan->desc_lock); if (callback) @@ -733,10 +758,6 @@ static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all) { while (__ld_cleanup(sh_chan, all)) ; - - if (all) - /* Terminating - forgive uncompleted cookies */ - sh_chan->completed_cookie = sh_chan->common.cookie; } static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan) @@ -782,8 +803,10 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan, sh_dmae_chan_ld_cleanup(sh_chan, false); - last_used = chan->cookie; + /* First read completed cookie to avoid a skew */ last_complete = sh_chan->completed_cookie; + rmb(); + last_used = chan->cookie; BUG_ON(last_complete < 0); dma_set_tx_state(txstate, last_complete, last_used, 0); @@ -813,8 +836,12 @@ static enum dma_status sh_dmae_tx_status(struct dma_chan *chan, static irqreturn_t sh_dmae_interrupt(int irq, void *data) { irqreturn_t ret = IRQ_NONE; - struct sh_dmae_chan *sh_chan = (struct sh_dmae_chan *)data; - u32 chcr = sh_dmae_readl(sh_chan, CHCR); + struct sh_dmae_chan *sh_chan = data; + u32 chcr; + + spin_lock(&sh_chan->desc_lock); + + chcr = sh_dmae_readl(sh_chan, CHCR); if (chcr & CHCR_TE) { /* DMA stop */ @@ -824,10 +851,13 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data) tasklet_schedule(&sh_chan->tasklet); } + spin_unlock(&sh_chan->desc_lock); + return ret; } -static unsigned int sh_dmae_reset(struct sh_dmae_device *shdev) +/* Called from error IRQ or NMI */ +static bool sh_dmae_reset(struct sh_dmae_device *shdev) { unsigned int handled = 0; int i; @@ -839,22 +869,32 @@ static unsigned int sh_dmae_reset(struct sh_dmae_device *shdev) for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) { struct sh_dmae_chan *sh_chan = shdev->chan[i]; struct sh_desc *desc; + LIST_HEAD(dl); if (!sh_chan) continue; + spin_lock(&sh_chan->desc_lock); + /* Stop the channel */ dmae_halt(sh_chan); + list_splice_init(&sh_chan->ld_queue, &dl); + + spin_unlock(&sh_chan->desc_lock); + /* Complete all */ - list_for_each_entry(desc, &sh_chan->ld_queue, node) { + list_for_each_entry(desc, &dl, node) { struct dma_async_tx_descriptor *tx = &desc->async_tx; desc->mark = DESC_IDLE; if (tx->callback) tx->callback(tx->callback_param); } - list_splice_init(&sh_chan->ld_queue, &sh_chan->ld_free); + spin_lock(&sh_chan->desc_lock); + list_splice(&dl, &sh_chan->ld_free); + spin_unlock(&sh_chan->desc_lock); + handled++; } @@ -867,10 +907,11 @@ static irqreturn_t sh_dmae_err(int irq, void *data) { struct sh_dmae_device *shdev = data; - if (dmaor_read(shdev) & DMAOR_AE) - return IRQ_RETVAL(sh_dmae_reset(data)); - else + if (!(dmaor_read(shdev) & DMAOR_AE)) return IRQ_NONE; + + sh_dmae_reset(data); + return IRQ_HANDLED; } static void dmae_do_tasklet(unsigned long data) @@ -902,17 +943,11 @@ static void dmae_do_tasklet(unsigned long data) static bool sh_dmae_nmi_notify(struct sh_dmae_device *shdev) { - unsigned int handled; - /* Fast path out if NMIF is not asserted for this controller */ if ((dmaor_read(shdev) & DMAOR_NMIF) == 0) return false; - handled = sh_dmae_reset(shdev); - if (handled) - return true; - - return false; + return sh_dmae_reset(shdev); } static int sh_dmae_nmi_handler(struct notifier_block *self, @@ -982,9 +1017,6 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, tasklet_init(&new_sh_chan->tasklet, dmae_do_tasklet, (unsigned long)new_sh_chan); - /* Init the channel */ - dmae_init(new_sh_chan); - spin_lock_init(&new_sh_chan->desc_lock); /* Init descripter manage list */ @@ -1115,7 +1147,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) list_add_tail_rcu(&shdev->node, &sh_dmae_devices); spin_unlock_irqrestore(&sh_dmae_lock, flags); - /* reset dma controller */ + /* reset dma controller - only needed as a test */ err = sh_dmae_rst(shdev); if (err) goto rst_err; From 467017b83b5bc445be5d275cf727b4f7ba3d2b2d Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Fri, 29 Apr 2011 17:09:25 +0000 Subject: [PATCH 14/23] dmaengine: shdma: add runtime- and system-level power management This patch extends and fixes runtime power management in the shdma driver to support powering down the DMA controller and adds support for system-level suspend and resume. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/dma/shdma.c | 68 +++++++++++++++++++++++++++++++++++++++++++++ drivers/dma/shdma.h | 1 + 2 files changed, 69 insertions(+) diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 727f51e903d90..00b5f320b0e8b 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1255,6 +1255,8 @@ static int __init sh_dmae_probe(struct platform_device *pdev) spin_unlock_irqrestore(&sh_dmae_lock, flags); pm_runtime_put(&pdev->dev); + pm_runtime_disable(&pdev->dev); + if (dmars) iounmap(shdev->dmars); emapdmars: @@ -1313,12 +1315,78 @@ static void sh_dmae_shutdown(struct platform_device *pdev) sh_dmae_ctl_stop(shdev); } +static int sh_dmae_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int sh_dmae_runtime_resume(struct device *dev) +{ + struct sh_dmae_device *shdev = dev_get_drvdata(dev); + + return sh_dmae_rst(shdev); +} + +#ifdef CONFIG_PM +static int sh_dmae_suspend(struct device *dev) +{ + struct sh_dmae_device *shdev = dev_get_drvdata(dev); + int i; + + for (i = 0; i < shdev->pdata->channel_num; i++) { + struct sh_dmae_chan *sh_chan = shdev->chan[i]; + if (sh_chan->descs_allocated) + sh_chan->pm_error = pm_runtime_put_sync(dev); + } + + return 0; +} + +static int sh_dmae_resume(struct device *dev) +{ + struct sh_dmae_device *shdev = dev_get_drvdata(dev); + int i; + + for (i = 0; i < shdev->pdata->channel_num; i++) { + struct sh_dmae_chan *sh_chan = shdev->chan[i]; + struct sh_dmae_slave *param = sh_chan->common.private; + + if (!sh_chan->descs_allocated) + continue; + + if (!sh_chan->pm_error) + pm_runtime_get_sync(dev); + + if (param) { + const struct sh_dmae_slave_config *cfg = param->config; + dmae_set_dmars(sh_chan, cfg->mid_rid); + dmae_set_chcr(sh_chan, cfg->chcr); + } else { + dmae_init(sh_chan); + } + } + + return 0; +} +#else +#define sh_dmae_suspend NULL +#define sh_dmae_resume NULL +#endif + +const struct dev_pm_ops sh_dmae_pm = { + .suspend = sh_dmae_suspend, + .resume = sh_dmae_resume, + .runtime_suspend = sh_dmae_runtime_suspend, + .runtime_resume = sh_dmae_runtime_resume, +}; + static struct platform_driver sh_dmae_driver = { .remove = __exit_p(sh_dmae_remove), .shutdown = sh_dmae_shutdown, .driver = { .owner = THIS_MODULE, .name = "sh-dma-engine", + .pm = &sh_dmae_pm, }, }; diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 52e4fb1738057..3f9d3cd065841 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h @@ -37,6 +37,7 @@ struct sh_dmae_chan { int id; /* Raw id of this channel */ u32 __iomem *base; char dev_id[16]; /* unique name per DMAC of channel */ + int pm_error; }; struct sh_dmae_device { From 31705e21f9b5a0628c043f88ff4d20488b47b8ab Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Date: Mon, 2 May 2011 07:59:02 +0000 Subject: [PATCH 15/23] dmaengine: shdma: synchronize RCU before freeing, simplify spinlock List elements, deleted using list_del_rcu(), cannot be freed without synchronising RCU. Further, the spinlock, used to protect the RCU writer, is called in process context, so, we don't have to save flags. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/dma/shdma.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 00b5f320b0e8b..dcc1b2139fffd 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1077,7 +1077,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev) struct sh_dmae_pdata *pdata = pdev->dev.platform_data; unsigned long irqflags = IRQF_DISABLED, chan_flag[SH_DMAC_MAX_CHANNELS] = {}; - unsigned long flags; int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; int err, i, irq_cnt = 0, irqres = 0; struct sh_dmae_device *shdev; @@ -1143,9 +1142,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_add_tail_rcu(&shdev->node, &sh_dmae_devices); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); /* reset dma controller - only needed as a test */ err = sh_dmae_rst(shdev); @@ -1250,9 +1249,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev) eirq_err: #endif rst_err: - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_del_rcu(&shdev->node); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); pm_runtime_put(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -1261,6 +1260,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) iounmap(shdev->dmars); emapdmars: iounmap(shdev->chan_reg); + synchronize_rcu(); emapchan: kfree(shdev); ealloc: @@ -1276,7 +1276,6 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) { struct sh_dmae_device *shdev = platform_get_drvdata(pdev); struct resource *res; - unsigned long flags; int errirq = platform_get_irq(pdev, 0); dma_async_device_unregister(&shdev->common); @@ -1284,9 +1283,9 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) if (errirq > 0) free_irq(errirq, shdev); - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_del_rcu(&shdev->node); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); /* channel data remove */ sh_dmae_chan_remove(shdev); @@ -1297,6 +1296,7 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) iounmap(shdev->dmars); iounmap(shdev->chan_reg); + synchronize_rcu(); kfree(shdev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); From 3593f5fe40a13badf6921ccbc3378b02fbf6a532 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@opensource.se> Date: Mon, 25 Apr 2011 22:32:11 +0900 Subject: [PATCH 16/23] clocksource: sh_cmt: __clocksource_updatefreq_hz() update This patch updates the clocksource part of the CMT driver to make use of the __clocksource_updatefreq_hz() function. Without this patch the old code uses clocksource_register() together with a hack that assumes a never changing clock rate (see clk_enable(), clk_get_rate() and clk_disable()). The patch uses clocksource_register_hz() with 1 Hz as initial value, then lets the ->enable() callback update the value with __clocksource_updatefreq_hz() once the struct clk has been enabled and the frequency is stable. Signed-off-by: Magnus Damm <damm@opensource.se> Acked-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/clocksource/sh_cmt.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index f975d24890fad..dc7c033ef5871 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -416,11 +416,15 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs) static int sh_cmt_clocksource_enable(struct clocksource *cs) { + int ret; struct sh_cmt_priv *p = cs_to_sh_cmt(cs); p->total_cycles = 0; - return sh_cmt_start(p, FLAG_CLOCKSOURCE); + ret = sh_cmt_start(p, FLAG_CLOCKSOURCE); + if (!ret) + __clocksource_updatefreq_hz(cs, p->rate); + return ret; } static void sh_cmt_clocksource_disable(struct clocksource *cs) @@ -448,19 +452,10 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - /* clk_get_rate() needs an enabled clock */ - clk_enable(p->clk); - p->rate = clk_get_rate(p->clk) / ((p->width == 16) ? 512 : 8); - clk_disable(p->clk); - - /* TODO: calculate good shift from rate and counter bit width */ - cs->shift = 0; - cs->mult = clocksource_hz2mult(p->rate, cs->shift); - dev_info(&p->pdev->dev, "used as clock source\n"); - clocksource_register(cs); - + /* Register with dummy 1 Hz value, gets updated in ->enable() */ + clocksource_register_hz(cs, 1); return 0; } From 01fa68b58492a5d6708a91c1f474b6a099a9509e Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@opensource.se> Date: Mon, 25 Apr 2011 22:36:10 +0900 Subject: [PATCH 17/23] clocksource: sh_cmt: Runtime PM support Add Runtime PM support to the CMT driver. The hardware device is enabled as long as the clocksource or the clockevent portion of the driver is used. Signed-off-by: Magnus Damm <damm@opensource.se> Acked-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/clocksource/sh_cmt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index dc7c033ef5871..036e5865eb400 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -24,6 +24,7 @@ #include <linux/ioport.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/pm_runtime.h> #include <linux/irq.h> #include <linux/err.h> #include <linux/clocksource.h> @@ -152,10 +153,12 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) { int ret; - /* enable clock */ + /* wake up device and enable clock */ + pm_runtime_get_sync(&p->pdev->dev); ret = clk_enable(p->clk); if (ret) { dev_err(&p->pdev->dev, "cannot enable clock\n"); + pm_runtime_put_sync(&p->pdev->dev); return ret; } @@ -187,8 +190,9 @@ static void sh_cmt_disable(struct sh_cmt_priv *p) /* disable interrupts in CMT block */ sh_cmt_write(p, CMCSR, 0); - /* stop clock */ + /* stop clock and mark device as idle */ clk_disable(p->clk); + pm_runtime_put_sync(&p->pdev->dev); } /* private flags */ @@ -660,6 +664,7 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev) if (p) { dev_info(&pdev->dev, "kept as earlytimer\n"); + pm_runtime_enable(&pdev->dev); return 0; } @@ -674,6 +679,9 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev) kfree(p); platform_set_drvdata(pdev, NULL); } + + if (!is_early_platform_device(pdev)) + pm_runtime_enable(&pdev->dev); return ret; } From 0aeac458d9ebea5f0dc483e2d3f2c06bfa520c02 Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@opensource.se> Date: Mon, 25 Apr 2011 22:38:37 +0900 Subject: [PATCH 18/23] clocksource: sh_tmu: __clocksource_updatefreq_hz() update This patch updates the clocksource part of the TMU driver to make use of the __clocksource_updatefreq_hz() function. Without this patch the old code uses clocksource_register() together with a hack that assumes a never changing clock rate (see clk_enable(), clk_get_rate() and clk_disable()). The patch uses clocksource_register_hz() with 1 Hz as initial value, then lets the ->enable() callback update the value with __clocksource_updatefreq_hz() once the struct clk has been enabled and the frequency is stable. Signed-off-by: Magnus Damm <damm@opensource.se> Acked-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/clocksource/sh_tmu.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 36aba9923060f..8081357686178 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -199,8 +199,12 @@ static cycle_t sh_tmu_clocksource_read(struct clocksource *cs) static int sh_tmu_clocksource_enable(struct clocksource *cs) { struct sh_tmu_priv *p = cs_to_sh_tmu(cs); + int ret; - return sh_tmu_enable(p); + ret = sh_tmu_enable(p); + if (!ret) + __clocksource_updatefreq_hz(cs, p->rate); + return ret; } static void sh_tmu_clocksource_disable(struct clocksource *cs) @@ -221,17 +225,10 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, cs->mask = CLOCKSOURCE_MASK(32); cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; - /* clk_get_rate() needs an enabled clock */ - clk_enable(p->clk); - /* channel will be configured at parent clock / 4 */ - p->rate = clk_get_rate(p->clk) / 4; - clk_disable(p->clk); - /* TODO: calculate good shift from rate and counter bit width */ - cs->shift = 10; - cs->mult = clocksource_hz2mult(p->rate, cs->shift); - dev_info(&p->pdev->dev, "used as clock source\n"); - clocksource_register(cs); + + /* Register with dummy 1 Hz value, gets updated in ->enable() */ + clocksource_register_hz(cs, 1); return 0; } From 1b842e91fea9447eff5eb687e28ad61c02f5033e Mon Sep 17 00:00:00 2001 From: Magnus Damm <damm@opensource.se> Date: Mon, 25 Apr 2011 22:40:26 +0900 Subject: [PATCH 19/23] clocksource: sh_tmu: Runtime PM support Add Runtime PM support to the TMU driver. The hardware device is enabled as long as the clocksource or the clockevent portion of the driver is used. Signed-off-by: Magnus Damm <damm@opensource.se> Acked-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- drivers/clocksource/sh_tmu.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 8081357686178..17296288a2052 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -25,6 +25,7 @@ #include <linux/delay.h> #include <linux/io.h> #include <linux/clk.h> +#include <linux/pm_runtime.h> #include <linux/irq.h> #include <linux/err.h> #include <linux/clocksource.h> @@ -109,10 +110,12 @@ static int sh_tmu_enable(struct sh_tmu_priv *p) { int ret; - /* enable clock */ + /* wake up device and enable clock */ + pm_runtime_get_sync(&p->pdev->dev); ret = clk_enable(p->clk); if (ret) { dev_err(&p->pdev->dev, "cannot enable clock\n"); + pm_runtime_put_sync(&p->pdev->dev); return ret; } @@ -141,8 +144,9 @@ static void sh_tmu_disable(struct sh_tmu_priv *p) /* disable interrupts in TMU block */ sh_tmu_write(p, TCR, 0x0000); - /* stop clock */ + /* stop clock and mark device as idle */ clk_disable(p->clk); + pm_runtime_put_sync(&p->pdev->dev); } static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta, @@ -411,6 +415,7 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev) if (p) { dev_info(&pdev->dev, "kept as earlytimer\n"); + pm_runtime_enable(&pdev->dev); return 0; } @@ -425,6 +430,9 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev) kfree(p); platform_set_drvdata(pdev, NULL); } + + if (!is_early_platform_device(pdev)) + pm_runtime_enable(&pdev->dev); return ret; } From c7434dbf29b4803d1caa0d1267fb6a455494d0d7 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Mon, 23 May 2011 14:41:32 +0900 Subject: [PATCH 20/23] sh: wire up sys_sendmmsg. Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/include/asm/unistd_32.h | 3 ++- arch/sh/include/asm/unistd_64.h | 3 ++- arch/sh/kernel/syscalls_32.S | 1 + arch/sh/kernel/syscalls_64.S | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h index ca7765e5f9679..bb7d2702c2c91 100644 --- a/arch/sh/include/asm/unistd_32.h +++ b/arch/sh/include/asm/unistd_32.h @@ -373,8 +373,9 @@ #define __NR_open_by_handle_at 360 #define __NR_clock_adjtime 361 #define __NR_syncfs 362 +#define __NR_sendmmsg 363 -#define NR_syscalls 363 +#define NR_syscalls 364 #ifdef __KERNEL__ diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h index a694009bb8169..46327cea1e5c5 100644 --- a/arch/sh/include/asm/unistd_64.h +++ b/arch/sh/include/asm/unistd_64.h @@ -394,10 +394,11 @@ #define __NR_open_by_handle_at 371 #define __NR_clock_adjtime 372 #define __NR_syncfs 373 +#define __NR_sendmmsg 374 #ifdef __KERNEL__ -#define NR_syscalls 374 +#define NR_syscalls 375 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S index 030966a9305cf..7c486f3e3a3c1 100644 --- a/arch/sh/kernel/syscalls_32.S +++ b/arch/sh/kernel/syscalls_32.S @@ -380,3 +380,4 @@ ENTRY(sys_call_table) .long sys_open_by_handle_at /* 360 */ .long sys_clock_adjtime .long sys_syncfs + .long sys_sendmmsg diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S index ca0a6142ab632..ba1a737afe807 100644 --- a/arch/sh/kernel/syscalls_64.S +++ b/arch/sh/kernel/syscalls_64.S @@ -400,3 +400,4 @@ sys_call_table: .long sys_open_by_handle_at .long sys_clock_adjtime .long sys_syncfs + .long sys_sendmmsg From d39e17c7f8f8fb4012618d25ddc4436407b174a6 Mon Sep 17 00:00:00 2001 From: Richard Weinberger <richard@nod.at> Date: Thu, 12 May 2011 13:11:11 +0000 Subject: [PATCH 21/23] sh: remove warning and warning_symbol from struct stacktrace_ops Both warning and warning_symbol are nowhere used. Let's get rid of them. Signed-off-by: Richard Weinberger <richard@nod.at> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/include/asm/stacktrace.h | 3 --- arch/sh/kernel/dumpstack.c | 15 --------------- arch/sh/kernel/perf_callchain.c | 12 ------------ arch/sh/kernel/stacktrace.c | 13 ------------- arch/sh/oprofile/backtrace.c | 13 ------------- 5 files changed, 56 deletions(-) diff --git a/arch/sh/include/asm/stacktrace.h b/arch/sh/include/asm/stacktrace.h index 7970182137182..a7e2d4dfd0877 100644 --- a/arch/sh/include/asm/stacktrace.h +++ b/arch/sh/include/asm/stacktrace.h @@ -10,9 +10,6 @@ /* Generic stack tracer with callbacks */ struct stacktrace_ops { - void (*warning)(void *data, char *msg); - /* msg must contain %s for the symbol */ - void (*warning_symbol)(void *data, char *msg, unsigned long symbol); void (*address)(void *data, unsigned long address, int reliable); /* On negative return stop dumping */ int (*stack)(void *data, char *name); diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c index 6f5ad1513409b..694158b9a50f5 100644 --- a/arch/sh/kernel/dumpstack.c +++ b/arch/sh/kernel/dumpstack.c @@ -69,19 +69,6 @@ stack_reader_dump(struct task_struct *task, struct pt_regs *regs, } } -static void -print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) -{ - printk(data); - print_symbol(msg, symbol); - printk("\n"); -} - -static void print_trace_warning(void *data, char *msg) -{ - printk("%s%s\n", (char *)data, msg); -} - static int print_trace_stack(void *data, char *name) { printk("%s <%s> ", (char *)data, name); @@ -98,8 +85,6 @@ static void print_trace_address(void *data, unsigned long addr, int reliable) } static const struct stacktrace_ops print_trace_ops = { - .warning = print_trace_warning, - .warning_symbol = print_trace_warning_symbol, .stack = print_trace_stack, .address = print_trace_address, }; diff --git a/arch/sh/kernel/perf_callchain.c b/arch/sh/kernel/perf_callchain.c index d5ca1ef50fa96..cc80b614b5fae 100644 --- a/arch/sh/kernel/perf_callchain.c +++ b/arch/sh/kernel/perf_callchain.c @@ -14,16 +14,6 @@ #include <asm/unwinder.h> #include <asm/ptrace.h> - -static void callchain_warning(void *data, char *msg) -{ -} - -static void -callchain_warning_symbol(void *data, char *msg, unsigned long symbol) -{ -} - static int callchain_stack(void *data, char *name) { return 0; @@ -38,8 +28,6 @@ static void callchain_address(void *data, unsigned long addr, int reliable) } static const struct stacktrace_ops callchain_ops = { - .warning = callchain_warning, - .warning_symbol = callchain_warning_symbol, .stack = callchain_stack, .address = callchain_address, }; diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c index c2e45c48409cd..bf989e063a0cd 100644 --- a/arch/sh/kernel/stacktrace.c +++ b/arch/sh/kernel/stacktrace.c @@ -17,15 +17,6 @@ #include <asm/ptrace.h> #include <asm/stacktrace.h> -static void save_stack_warning(void *data, char *msg) -{ -} - -static void -save_stack_warning_symbol(void *data, char *msg, unsigned long symbol) -{ -} - static int save_stack_stack(void *data, char *name) { return 0; @@ -51,8 +42,6 @@ static void save_stack_address(void *data, unsigned long addr, int reliable) } static const struct stacktrace_ops save_stack_ops = { - .warning = save_stack_warning, - .warning_symbol = save_stack_warning_symbol, .stack = save_stack_stack, .address = save_stack_address, }; @@ -88,8 +77,6 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable) } static const struct stacktrace_ops save_stack_ops_nosched = { - .warning = save_stack_warning, - .warning_symbol = save_stack_warning_symbol, .stack = save_stack_stack, .address = save_stack_address_nosched, }; diff --git a/arch/sh/oprofile/backtrace.c b/arch/sh/oprofile/backtrace.c index 37f3a75ea6cbf..9c88dcd56e865 100644 --- a/arch/sh/oprofile/backtrace.c +++ b/arch/sh/oprofile/backtrace.c @@ -23,17 +23,6 @@ #include <asm/sections.h> #include <asm/stacktrace.h> -static void backtrace_warning_symbol(void *data, char *msg, - unsigned long symbol) -{ - /* Ignore warnings */ -} - -static void backtrace_warning(void *data, char *msg) -{ - /* Ignore warnings */ -} - static int backtrace_stack(void *data, char *name) { /* Yes, we want all stacks */ @@ -49,8 +38,6 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) } static struct stacktrace_ops backtrace_ops = { - .warning = backtrace_warning, - .warning_symbol = backtrace_warning_symbol, .stack = backtrace_stack, .address = backtrace_address, }; From 116ceec20069f5bab507eab817e56a4b60480845 Mon Sep 17 00:00:00 2001 From: Ralf Baechle <ralf@linux-mips.org> Date: Fri, 13 May 2011 12:17:46 +0000 Subject: [PATCH 22/23] SH: SE7751: Fix pcibios_map_platform_irq prototype. Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/drivers/pci/fixups-se7751.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c index a4c7d3a4efca4..fd3e6b02f2898 100644 --- a/arch/sh/drivers/pci/fixups-se7751.c +++ b/arch/sh/drivers/pci/fixups-se7751.c @@ -6,7 +6,7 @@ #include <linux/io.h> #include "pci-sh4.h" -int __init pcibios_map_platform_irq(u8 slot, u8 pin) +int __init pcibios_map_platform_irq(struct pci_dev *, u8 slot, u8 pin) { switch (slot) { case 0: return 13; From 78207ffd0e00d39238f0a8a455a31a12659b30b3 Mon Sep 17 00:00:00 2001 From: Paul Mundt <lethal@linux-sh.org> Date: Mon, 23 May 2011 17:09:30 +0900 Subject: [PATCH 23/23] sh: Ignore R_SH_NONE module relocations. Some modules may end up with R_SH_NONE relocs with the right combination of compiler/kernel config (specifically dwarf unwinder), so simply trap and ignore them instead of letting them get down to the error path. Reported-by: Carmelo AMOROSO <carmelo.amoroso@st.com> Signed-off-by: Paul Mundt <lethal@linux-sh.org> --- arch/sh/kernel/module.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index ae0be697a89e4..19b1f8826aef9 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c @@ -93,6 +93,8 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, #endif switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_SH_NONE: + break; case R_SH_DIR32: value = get_unaligned(location); value += relocation;