From 8cc88a55b03bd4940390125c2521c99368513be5 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 17 Nov 2011 14:55:47 +0100 Subject: sh: sh7724: use runtime PM implementation, common with arm/mach-shmobile Switch sh7724 to a runtime PM implementation, common with ARM-based sh-mobile platforms. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/sh/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 67e272ab162..30c25940cfc 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_GENERIC_GPIO) += pfc.o # special casing can go away. # obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o +obj-$(CONFIG_CPU_SUBTYPE_SH7724) += pm_runtime.o -- cgit v1.2.3 From 6a06d5bf26f078212de084da93e4af863a6e5ccf Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 17 Nov 2011 14:55:52 +0100 Subject: sh: sh7722: use runtime PM implementation, common with arm/mach-shmobile Switch sh7722 to a runtime PM implementation, common with ARM-based sh-mobile platforms. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/sh/include/asm/hwblk.h | 2 +- arch/sh/kernel/cpu/Makefile | 2 +- arch/sh/kernel/cpu/sh4a/Makefile | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 77 ++++++++++++------------ arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c | 106 --------------------------------- arch/sh/kernel/cpu/shmobile/Makefile | 2 +- drivers/sh/Makefile | 1 + 7 files changed, 45 insertions(+), 147 deletions(-) delete mode 100644 arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c (limited to 'drivers') diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h index 567c9aa1ced..d6b7deaaeca 100644 --- a/arch/sh/include/asm/hwblk.h +++ b/arch/sh/include/asm/hwblk.h @@ -44,7 +44,7 @@ struct hwblk_info { int nr_hwblks; }; -#if !defined(CONFIG_CPU_SUBTYPE_SH7724) +#if !defined(CONFIG_CPU_SUBTYPE_SH7724) && !defined(CONFIG_CPU_SUBTYPE_SH7722) /* Should be defined by processor-specific code */ int arch_hwblk_init(void); int arch_hwblk_sleep_mode(void); diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index b937f1a17a4..b1f515cb4c7 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -19,6 +19,6 @@ obj-$(CONFIG_SH_ADC) += adc.o obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o obj-y += irq/ init.o clock.o fpu.o proc.o -ifneq ($(CONFIG_CPU_SUBTYPE_SH7724),y) +ifneq ($(CONFIG_CPU_SUBTYPE_SH7724)$(CONFIG_CPU_SUBTYPE_SH7722),y) obj-y += hwblk.o endif diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index cb932872aba..9f28773d678 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -27,7 +27,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o -clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o hwblk-sh7722.o +clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o hwblk-sh7723.o clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index c9a48088ad4..212c72ef959 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include #include /* SH7722 registers */ @@ -33,6 +33,9 @@ #define SCLKBCR 0xa415000c #define IRDACLKCR 0xa4150018 #define PLLCR 0xa4150024 +#define MSTPCR0 0xa4150030 +#define MSTPCR1 0xa4150034 +#define MSTPCR2 0xa4150038 #define DLLFRQ 0xa4150050 /* Fixed 32 KHz root clock for RTC and Power Management purposes */ @@ -148,31 +151,31 @@ struct clk div6_clks[DIV6_NR] = { }; static struct clk mstp_clks[HWBLK_NR] = { - SH_HWBLK_CLK(HWBLK_URAM, &div4_clks[DIV4_U], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_XYMEM, &div4_clks[DIV4_B], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_TMU, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_CMT, &r_clk, 0), - SH_HWBLK_CLK(HWBLK_RWDT, &r_clk, 0), - SH_HWBLK_CLK(HWBLK_FLCTL, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_SCIF0, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_SCIF1, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_SCIF2, &div4_clks[DIV4_P], 0), - - SH_HWBLK_CLK(HWBLK_IIC, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_RTC, &r_clk, 0), - - SH_HWBLK_CLK(HWBLK_SDHI, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_KEYSC, &r_clk, 0), - SH_HWBLK_CLK(HWBLK_USBF, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_2DG, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_SIU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_VOU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_JPU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_BEU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_CEU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_VEU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_VPU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_P], 0), + [HWBLK_URAM] = SH_CLK_MSTP32(&div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), + [HWBLK_XYMEM] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), + [HWBLK_TMU] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), + [HWBLK_CMT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 14, 0), + [HWBLK_RWDT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 13, 0), + [HWBLK_FLCTL] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0), + [HWBLK_SCIF0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0), + [HWBLK_SCIF1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 6, 0), + [HWBLK_SCIF2] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 5, 0), + + [HWBLK_IIC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0), + [HWBLK_RTC] = SH_CLK_MSTP32(&r_clk, MSTPCR1, 8, 0), + + [HWBLK_SDHI] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 18, 0), + [HWBLK_KEYSC] = SH_CLK_MSTP32(&r_clk, MSTPCR2, 14, 0), + [HWBLK_USBF] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 11, 0), + [HWBLK_2DG] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 9, 0), + [HWBLK_SIU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 8, 0), + [HWBLK_JPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 6, 0), + [HWBLK_VOU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 5, 0), + [HWBLK_BEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 4, 0), + [HWBLK_CEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 3, 0), + [HWBLK_VEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 2, 0), + [HWBLK_VPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 1, 0), + [HWBLK_LCDC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 0, 0), }; static struct clk_lookup lookups[] = { @@ -205,27 +208,27 @@ static struct clk_lookup lookups[] = { CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU]), CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]), - CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]), + CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]), CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]), - CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]), + CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[HWBLK_SCIF0]), + CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[HWBLK_SCIF1]), + CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[HWBLK_SCIF2]), CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]), CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]), - CLKDEV_CON_ID("sdhi0", &mstp_clks[HWBLK_SDHI]), - CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]), + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI]), + CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[HWBLK_KEYSC]), CLKDEV_CON_ID("usbf0", &mstp_clks[HWBLK_USBF]), CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]), - CLKDEV_CON_ID("siu0", &mstp_clks[HWBLK_SIU]), - CLKDEV_CON_ID("vou0", &mstp_clks[HWBLK_VOU]), + CLKDEV_DEV_ID("siu-pcm-audio", &mstp_clks[HWBLK_SIU]), + CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]), CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]), CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]), - CLKDEV_CON_ID("ceu0", &mstp_clks[HWBLK_CEU]), + CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[HWBLK_CEU]), CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU]), CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]), - CLKDEV_CON_ID("lcdc0", &mstp_clks[HWBLK_LCDC]), + CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]), }; int __init arch_clk_init(void) @@ -258,7 +261,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); + ret = sh_clk_mstp32_register(mstp_clks, HWBLK_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c deleted file mode 100644 index a288b5d9234..00000000000 --- a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c - * - * SH7722 hardware block support - * - * Copyright (C) 2009 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include - -/* SH7722 registers */ -#define MSTPCR0 0xa4150030 -#define MSTPCR1 0xa4150034 -#define MSTPCR2 0xa4150038 - -/* SH7722 Power Domains */ -enum { CORE_AREA, SUB_AREA, CORE_AREA_BM }; -static struct hwblk_area sh7722_hwblk_area[] = { - [CORE_AREA] = HWBLK_AREA(0, 0), - [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA), - [SUB_AREA] = HWBLK_AREA(0, 0), -}; - -/* Table mapping HWBLK to Module Stop Bit and Power Domain */ -static struct hwblk sh7722_hwblk[HWBLK_NR] = { - [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA), - [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA), - [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA), - [HWBLK_URAM] = HWBLK(MSTPCR0, 28, CORE_AREA), - [HWBLK_XYMEM] = HWBLK(MSTPCR0, 26, CORE_AREA), - [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA), - [HWBLK_DMAC] = HWBLK(MSTPCR0, 21, CORE_AREA_BM), - [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA), - [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA), - [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA), - [HWBLK_TMU] = HWBLK(MSTPCR0, 15, CORE_AREA), - [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA), - [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA), - [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA), - [HWBLK_SCIF0] = HWBLK(MSTPCR0, 7, CORE_AREA), - [HWBLK_SCIF1] = HWBLK(MSTPCR0, 6, CORE_AREA), - [HWBLK_SCIF2] = HWBLK(MSTPCR0, 5, CORE_AREA), - [HWBLK_SIO] = HWBLK(MSTPCR0, 3, CORE_AREA), - [HWBLK_SIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA), - [HWBLK_SIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA), - - [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA), - [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA), - - [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA), - [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA), - [HWBLK_SDHI] = HWBLK(MSTPCR2, 18, CORE_AREA), - [HWBLK_SIM] = HWBLK(MSTPCR2, 16, CORE_AREA), - [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA), - [HWBLK_TSIF] = HWBLK(MSTPCR2, 13, SUB_AREA), - [HWBLK_USBF] = HWBLK(MSTPCR2, 11, CORE_AREA), - [HWBLK_2DG] = HWBLK(MSTPCR2, 9, CORE_AREA_BM), - [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA), - [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM), - [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM), - [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM), - [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM), - [HWBLK_VEU] = HWBLK(MSTPCR2, 2, CORE_AREA_BM), - [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM), - [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM), -}; - -static struct hwblk_info sh7722_hwblk_info = { - .areas = sh7722_hwblk_area, - .nr_areas = ARRAY_SIZE(sh7722_hwblk_area), - .hwblks = sh7722_hwblk, - .nr_hwblks = ARRAY_SIZE(sh7722_hwblk), -}; - -int arch_hwblk_sleep_mode(void) -{ - if (!sh7722_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE]) - return SUSP_SH_STANDBY | SUSP_SH_SF; - - if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE]) - return SUSP_SH_SLEEP | SUSP_SH_SF; - - return SUSP_SH_SLEEP; -} - -int __init arch_hwblk_init(void) -{ - return hwblk_register(&sh7722_hwblk_info); -} diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile index 2f32a0352aa..e83c9d55ccd 100644 --- a/arch/sh/kernel/cpu/shmobile/Makefile +++ b/arch/sh/kernel/cpu/shmobile/Makefile @@ -5,6 +5,6 @@ # Power Management & Sleep mode obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o -ifneq ($(CONFIG_CPU_SUBTYPE_SH7724),y) +ifneq ($(CONFIG_CPU_SUBTYPE_SH7724)$(CONFIG_CPU_SUBTYPE_SH7722),y) obj-$(CONFIG_PM_RUNTIME) += pm_runtime.o endif diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 30c25940cfc..ffca2b4441a 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -16,3 +16,4 @@ obj-$(CONFIG_GENERIC_GPIO) += pfc.o # obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o obj-$(CONFIG_CPU_SUBTYPE_SH7724) += pm_runtime.o +obj-$(CONFIG_CPU_SUBTYPE_SH7722) += pm_runtime.o -- cgit v1.2.3 From 7fa4632db8bfadf37b5e19f6b73398c6bccb5c90 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Thu, 17 Nov 2011 14:55:56 +0100 Subject: sh: sh7723: use runtime PM implementation, common with arm/mach-shmobile Switch sh7723 to a runtime PM implementation, common with ARM-based sh-mobile platforms. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/sh/include/asm/hwblk.h | 4 +- arch/sh/kernel/cpu/Makefile | 2 +- arch/sh/kernel/cpu/sh4a/Makefile | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7723.c | 168 ++++++++++++++------------------- arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c | 117 ----------------------- arch/sh/kernel/cpu/shmobile/Makefile | 2 +- drivers/sh/Makefile | 3 +- 7 files changed, 81 insertions(+), 217 deletions(-) delete mode 100644 arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c (limited to 'drivers') diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h index d6b7deaaeca..e29461bbe84 100644 --- a/arch/sh/include/asm/hwblk.h +++ b/arch/sh/include/asm/hwblk.h @@ -44,7 +44,9 @@ struct hwblk_info { int nr_hwblks; }; -#if !defined(CONFIG_CPU_SUBTYPE_SH7724) && !defined(CONFIG_CPU_SUBTYPE_SH7722) +#if !defined(CONFIG_CPU_SUBTYPE_SH7722) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7723) && \ + !defined(CONFIG_CPU_SUBTYPE_SH7724) /* Should be defined by processor-specific code */ int arch_hwblk_init(void); int arch_hwblk_sleep_mode(void); diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index b1f515cb4c7..5366fdf8c56 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -19,6 +19,6 @@ obj-$(CONFIG_SH_ADC) += adc.o obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o obj-y += irq/ init.o clock.o fpu.o proc.o -ifneq ($(CONFIG_CPU_SUBTYPE_SH7724)$(CONFIG_CPU_SUBTYPE_SH7722),y) +ifneq ($(CONFIG_CPU_SUBTYPE_SH7722)$(CONFIG_CPU_SUBTYPE_SH7723)$(CONFIG_CPU_SUBTYPE_SH7724),y) obj-y += hwblk.o endif diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 9f28773d678..0b22d108f4c 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -28,7 +28,7 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7785) := clock-sh7785.o clock-$(CONFIG_CPU_SUBTYPE_SH7786) := clock-sh7786.o clock-$(CONFIG_CPU_SUBTYPE_SH7343) := clock-sh7343.o clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o -clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o hwblk-sh7723.o +clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.o clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o clock-$(CONFIG_CPU_SUBTYPE_SH7366) := clock-sh7366.o clock-$(CONFIG_CPU_SUBTYPE_SHX3) := clock-shx3.o diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index 3cc3827380e..041c415e9c4 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -23,8 +23,8 @@ #include #include #include +#include #include -#include #include /* SH7723 registers */ @@ -34,6 +34,9 @@ #define SCLKBCR 0xa415000c #define IRDACLKCR 0xa4150018 #define PLLCR 0xa4150024 +#define MSTPCR0 0xa4150030 +#define MSTPCR1 0xa4150034 +#define MSTPCR2 0xa4150038 #define DLLFRQ 0xa4150050 /* Fixed 32 KHz root clock for RTC and Power Management purposes */ @@ -149,55 +152,55 @@ struct clk div6_clks[DIV6_NR] = { static struct clk mstp_clks[] = { /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ - SH_HWBLK_CLK(HWBLK_TLB, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_IC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_OC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_L2C, &div4_clks[DIV4_SH], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_ILMEM, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_FPU, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_INTC, &div4_clks[DIV4_I], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_DMAC0, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_SHYWAY, &div4_clks[DIV4_SH], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_HUDI, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_UBC, &div4_clks[DIV4_I], 0), - SH_HWBLK_CLK(HWBLK_TMU0, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_CMT, &r_clk, 0), - SH_HWBLK_CLK(HWBLK_RWDT, &r_clk, 0), - SH_HWBLK_CLK(HWBLK_DMAC1, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_TMU1, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_FLCTL, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_SCIF0, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_SCIF1, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_SCIF2, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_SCIF3, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_SCIF4, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_SCIF5, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_MSIOF0, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_MSIOF1, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_MERAM, &div4_clks[DIV4_SH], 0), - - SH_HWBLK_CLK(HWBLK_IIC, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_RTC, &r_clk, 0), - - SH_HWBLK_CLK(HWBLK_ATAPI, &div4_clks[DIV4_SH], 0), - SH_HWBLK_CLK(HWBLK_ADC, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_TPU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_IRDA, &div4_clks[DIV4_P], 0), - SH_HWBLK_CLK(HWBLK_TSIF, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_ICB, &div4_clks[DIV4_B], CLK_ENABLE_ON_INIT), - SH_HWBLK_CLK(HWBLK_SDHI0, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_SDHI1, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_KEYSC, &r_clk, 0), - SH_HWBLK_CLK(HWBLK_USB, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_2DG, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_SIU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_VEU2H1, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_VOU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_BEU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_CEU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_VEU2H0, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_VPU, &div4_clks[DIV4_B], 0), - SH_HWBLK_CLK(HWBLK_LCDC, &div4_clks[DIV4_B], 0), + [HWBLK_TLB] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 31, CLK_ENABLE_ON_INIT), + [HWBLK_IC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 30, CLK_ENABLE_ON_INIT), + [HWBLK_OC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 29, CLK_ENABLE_ON_INIT), + [HWBLK_L2C] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 28, CLK_ENABLE_ON_INIT), + [HWBLK_ILMEM] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 27, CLK_ENABLE_ON_INIT), + [HWBLK_FPU] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 24, CLK_ENABLE_ON_INIT), + [HWBLK_INTC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 22, CLK_ENABLE_ON_INIT), + [HWBLK_DMAC0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 21, 0), + [HWBLK_SHYWAY] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 20, CLK_ENABLE_ON_INIT), + [HWBLK_HUDI] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 19, 0), + [HWBLK_UBC] = SH_CLK_MSTP32(&div4_clks[DIV4_I], MSTPCR0, 17, 0), + [HWBLK_TMU0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0), + [HWBLK_CMT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 14, 0), + [HWBLK_RWDT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 13, 0), + [HWBLK_DMAC1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 12, 0), + [HWBLK_TMU1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 11, 0), + [HWBLK_FLCTL] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0), + [HWBLK_SCIF0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0), + [HWBLK_SCIF1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0), + [HWBLK_SCIF2] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0), + [HWBLK_SCIF3] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 6, 0), + [HWBLK_SCIF4] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 5, 0), + [HWBLK_SCIF5] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 4, 0), + [HWBLK_MSIOF0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 2, 0), + [HWBLK_MSIOF1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 1, 0), + [HWBLK_MERAM] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR0, 0, 0), + + [HWBLK_IIC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0), + [HWBLK_RTC] = SH_CLK_MSTP32(&r_clk, MSTPCR1, 8, 0), + + [HWBLK_ATAPI] = SH_CLK_MSTP32(&div4_clks[DIV4_SH], MSTPCR2, 28, 0), + [HWBLK_ADC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 27, 0), + [HWBLK_TPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 25, 0), + [HWBLK_IRDA] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 24, 0), + [HWBLK_TSIF] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 22, 0), + [HWBLK_ICB] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 21, CLK_ENABLE_ON_INIT), + [HWBLK_SDHI0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 18, 0), + [HWBLK_SDHI1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 17, 0), + [HWBLK_KEYSC] = SH_CLK_MSTP32(&r_clk, MSTPCR2, 14, 0), + [HWBLK_USB] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 11, 0), + [HWBLK_2DG] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 10, 0), + [HWBLK_SIU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 8, 0), + [HWBLK_VEU2H1] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 6, 0), + [HWBLK_VOU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 5, 0), + [HWBLK_BEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 4, 0), + [HWBLK_CEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 3, 0), + [HWBLK_VEU2H0] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 2, 0), + [HWBLK_VPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 1, 0), + [HWBLK_LCDC] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 0, 0), }; static struct clk_lookup lookups[] = { @@ -229,7 +232,7 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("ilmem0", &mstp_clks[HWBLK_ILMEM]), CLKDEV_CON_ID("fpu0", &mstp_clks[HWBLK_FPU]), CLKDEV_CON_ID("intc0", &mstp_clks[HWBLK_INTC]), - CLKDEV_CON_ID("dmac0", &mstp_clks[HWBLK_DMAC0]), + CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[HWBLK_DMAC0]), CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]), CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]), CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]), @@ -250,8 +253,8 @@ static struct clk_lookup lookups[] = { .clk = &mstp_clks[HWBLK_TMU0], }, CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]), - CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]), - CLKDEV_CON_ID("dmac1", &mstp_clks[HWBLK_DMAC1]), + CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]), + CLKDEV_DEV_ID("sh-dma-engine.1", &mstp_clks[HWBLK_DMAC1]), { /* TMU3 */ .dev_id = "sh_tmu.3", @@ -269,40 +272,15 @@ static struct clk_lookup lookups[] = { .clk = &mstp_clks[HWBLK_TMU1], }, CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]), - { - /* SCIF0 */ - .dev_id = "sh-sci.0", - .con_id = "sci_fck", - .clk = &mstp_clks[HWBLK_SCIF0], - }, { - /* SCIF1 */ - .dev_id = "sh-sci.1", - .con_id = "sci_fck", - .clk = &mstp_clks[HWBLK_SCIF1], - }, { - /* SCIF2 */ - .dev_id = "sh-sci.2", - .con_id = "sci_fck", - .clk = &mstp_clks[HWBLK_SCIF2], - }, { - /* SCIF3 */ - .dev_id = "sh-sci.3", - .con_id = "sci_fck", - .clk = &mstp_clks[HWBLK_SCIF3], - }, { - /* SCIF4 */ - .dev_id = "sh-sci.4", - .con_id = "sci_fck", - .clk = &mstp_clks[HWBLK_SCIF4], - }, { - /* SCIF5 */ - .dev_id = "sh-sci.5", - .con_id = "sci_fck", - .clk = &mstp_clks[HWBLK_SCIF5], - }, - CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]), - CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]), - CLKDEV_CON_ID("meram0", &mstp_clks[HWBLK_MERAM]), + CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[HWBLK_SCIF0]), + CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[HWBLK_SCIF1]), + CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[HWBLK_SCIF2]), + CLKDEV_DEV_ID("sh-sci.3", &mstp_clks[HWBLK_SCIF3]), + CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[HWBLK_SCIF4]), + CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[HWBLK_SCIF5]), + CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[HWBLK_MSIOF0]), + CLKDEV_DEV_ID("spi_sh_msiof.1", &mstp_clks[HWBLK_MSIOF1]), + CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[HWBLK_MERAM]), CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]), CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]), CLKDEV_CON_ID("atapi0", &mstp_clks[HWBLK_ATAPI]), @@ -311,19 +289,19 @@ static struct clk_lookup lookups[] = { CLKDEV_CON_ID("irda0", &mstp_clks[HWBLK_IRDA]), CLKDEV_CON_ID("tsif0", &mstp_clks[HWBLK_TSIF]), CLKDEV_CON_ID("icb0", &mstp_clks[HWBLK_ICB]), - CLKDEV_CON_ID("sdhi0", &mstp_clks[HWBLK_SDHI0]), - CLKDEV_CON_ID("sdhi1", &mstp_clks[HWBLK_SDHI1]), - CLKDEV_CON_ID("keysc0", &mstp_clks[HWBLK_KEYSC]), + CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI0]), + CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[HWBLK_SDHI1]), + CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[HWBLK_KEYSC]), CLKDEV_CON_ID("usb0", &mstp_clks[HWBLK_USB]), CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]), - CLKDEV_CON_ID("siu0", &mstp_clks[HWBLK_SIU]), + CLKDEV_DEV_ID("siu-pcm-audio", &mstp_clks[HWBLK_SIU]), CLKDEV_CON_ID("veu1", &mstp_clks[HWBLK_VEU2H1]), - CLKDEV_CON_ID("vou0", &mstp_clks[HWBLK_VOU]), + CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]), CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]), - CLKDEV_CON_ID("ceu0", &mstp_clks[HWBLK_CEU]), + CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[HWBLK_CEU]), CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU2H0]), CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]), - CLKDEV_CON_ID("lcdc0", &mstp_clks[HWBLK_LCDC]), + CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]), }; int __init arch_clk_init(void) @@ -356,7 +334,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, DIV6_NR); if (!ret) - ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR); + ret = sh_clk_mstp32_register(mstp_clks, HWBLK_NR); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c deleted file mode 100644 index a7f4684d203..00000000000 --- a/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c - * - * SH7723 hardware block support - * - * Copyright (C) 2009 Magnus Damm - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include - -/* SH7723 registers */ -#define MSTPCR0 0xa4150030 -#define MSTPCR1 0xa4150034 -#define MSTPCR2 0xa4150038 - -/* SH7723 Power Domains */ -enum { CORE_AREA, SUB_AREA, CORE_AREA_BM }; -static struct hwblk_area sh7723_hwblk_area[] = { - [CORE_AREA] = HWBLK_AREA(0, 0), - [CORE_AREA_BM] = HWBLK_AREA(HWBLK_AREA_FLAG_PARENT, CORE_AREA), - [SUB_AREA] = HWBLK_AREA(0, 0), -}; - -/* Table mapping HWBLK to Module Stop Bit and Power Domain */ -static struct hwblk sh7723_hwblk[HWBLK_NR] = { - [HWBLK_TLB] = HWBLK(MSTPCR0, 31, CORE_AREA), - [HWBLK_IC] = HWBLK(MSTPCR0, 30, CORE_AREA), - [HWBLK_OC] = HWBLK(MSTPCR0, 29, CORE_AREA), - [HWBLK_L2C] = HWBLK(MSTPCR0, 28, CORE_AREA), - [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA), - [HWBLK_FPU] = HWBLK(MSTPCR0, 24, CORE_AREA), - [HWBLK_INTC] = HWBLK(MSTPCR0, 22, CORE_AREA), - [HWBLK_DMAC0] = HWBLK(MSTPCR0, 21, CORE_AREA_BM), - [HWBLK_SHYWAY] = HWBLK(MSTPCR0, 20, CORE_AREA), - [HWBLK_HUDI] = HWBLK(MSTPCR0, 19, CORE_AREA), - [HWBLK_DBG] = HWBLK(MSTPCR0, 18, CORE_AREA), - [HWBLK_UBC] = HWBLK(MSTPCR0, 17, CORE_AREA), - [HWBLK_SUBC] = HWBLK(MSTPCR0, 16, CORE_AREA), - [HWBLK_TMU0] = HWBLK(MSTPCR0, 15, CORE_AREA), - [HWBLK_CMT] = HWBLK(MSTPCR0, 14, SUB_AREA), - [HWBLK_RWDT] = HWBLK(MSTPCR0, 13, SUB_AREA), - [HWBLK_DMAC1] = HWBLK(MSTPCR0, 12, CORE_AREA_BM), - [HWBLK_TMU1] = HWBLK(MSTPCR0, 11, CORE_AREA), - [HWBLK_FLCTL] = HWBLK(MSTPCR0, 10, CORE_AREA), - [HWBLK_SCIF0] = HWBLK(MSTPCR0, 9, CORE_AREA), - [HWBLK_SCIF1] = HWBLK(MSTPCR0, 8, CORE_AREA), - [HWBLK_SCIF2] = HWBLK(MSTPCR0, 7, CORE_AREA), - [HWBLK_SCIF3] = HWBLK(MSTPCR0, 6, CORE_AREA), - [HWBLK_SCIF4] = HWBLK(MSTPCR0, 5, CORE_AREA), - [HWBLK_SCIF5] = HWBLK(MSTPCR0, 4, CORE_AREA), - [HWBLK_MSIOF0] = HWBLK(MSTPCR0, 2, CORE_AREA), - [HWBLK_MSIOF1] = HWBLK(MSTPCR0, 1, CORE_AREA), - [HWBLK_MERAM] = HWBLK(MSTPCR0, 0, CORE_AREA), - - [HWBLK_IIC] = HWBLK(MSTPCR1, 9, CORE_AREA), - [HWBLK_RTC] = HWBLK(MSTPCR1, 8, SUB_AREA), - - [HWBLK_ATAPI] = HWBLK(MSTPCR2, 28, CORE_AREA_BM), - [HWBLK_ADC] = HWBLK(MSTPCR2, 27, CORE_AREA), - [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA), - [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA), - [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA), - [HWBLK_ICB] = HWBLK(MSTPCR2, 21, CORE_AREA_BM), - [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA), - [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA), - [HWBLK_KEYSC] = HWBLK(MSTPCR2, 14, SUB_AREA), - [HWBLK_USB] = HWBLK(MSTPCR2, 11, CORE_AREA), - [HWBLK_2DG] = HWBLK(MSTPCR2, 10, CORE_AREA_BM), - [HWBLK_SIU] = HWBLK(MSTPCR2, 8, CORE_AREA), - [HWBLK_VEU2H1] = HWBLK(MSTPCR2, 6, CORE_AREA_BM), - [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM), - [HWBLK_BEU] = HWBLK(MSTPCR2, 4, CORE_AREA_BM), - [HWBLK_CEU] = HWBLK(MSTPCR2, 3, CORE_AREA_BM), - [HWBLK_VEU2H0] = HWBLK(MSTPCR2, 2, CORE_AREA_BM), - [HWBLK_VPU] = HWBLK(MSTPCR2, 1, CORE_AREA_BM), - [HWBLK_LCDC] = HWBLK(MSTPCR2, 0, CORE_AREA_BM), -}; - -static struct hwblk_info sh7723_hwblk_info = { - .areas = sh7723_hwblk_area, - .nr_areas = ARRAY_SIZE(sh7723_hwblk_area), - .hwblks = sh7723_hwblk, - .nr_hwblks = ARRAY_SIZE(sh7723_hwblk), -}; - -int arch_hwblk_sleep_mode(void) -{ - if (!sh7723_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE]) - return SUSP_SH_STANDBY | SUSP_SH_SF; - - if (!sh7723_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE]) - return SUSP_SH_SLEEP | SUSP_SH_SF; - - return SUSP_SH_SLEEP; -} - -int __init arch_hwblk_init(void) -{ - return hwblk_register(&sh7723_hwblk_info); -} diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile index e83c9d55ccd..7eb4502dfb6 100644 --- a/arch/sh/kernel/cpu/shmobile/Makefile +++ b/arch/sh/kernel/cpu/shmobile/Makefile @@ -5,6 +5,6 @@ # Power Management & Sleep mode obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o -ifneq ($(CONFIG_CPU_SUBTYPE_SH7724)$(CONFIG_CPU_SUBTYPE_SH7722),y) +ifneq ($(CONFIG_CPU_SUBTYPE_SH7722)$(CONFIG_CPU_SUBTYPE_SH7723)$(CONFIG_CPU_SUBTYPE_SH7724),y) obj-$(CONFIG_PM_RUNTIME) += pm_runtime.o endif diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index ffca2b4441a..51f171b0148 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -15,5 +15,6 @@ obj-$(CONFIG_GENERIC_GPIO) += pfc.o # special casing can go away. # obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o -obj-$(CONFIG_CPU_SUBTYPE_SH7724) += pm_runtime.o obj-$(CONFIG_CPU_SUBTYPE_SH7722) += pm_runtime.o +obj-$(CONFIG_CPU_SUBTYPE_SH7723) += pm_runtime.o +obj-$(CONFIG_CPU_SUBTYPE_SH7724) += pm_runtime.o -- cgit v1.2.3 From 62d3ba8bba6fb1d1362dcaa1da2679f4ab740226 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 18 Nov 2011 16:05:52 +0900 Subject: sh: Kill off remaining private runtime PM bits. This kills of the now unused runtime PM stub in favour of the generic one. Signed-off-by: Paul Mundt --- arch/sh/include/asm/device.h | 9 - arch/sh/kernel/cpu/shmobile/Makefile | 3 - arch/sh/kernel/cpu/shmobile/pm_runtime.c | 319 ------------------------------- drivers/sh/Makefile | 12 +- 4 files changed, 1 insertion(+), 342 deletions(-) delete mode 100644 arch/sh/kernel/cpu/shmobile/pm_runtime.c (limited to 'drivers') diff --git a/arch/sh/include/asm/device.h b/arch/sh/include/asm/device.h index b16debfe8c1..783ecdc64e2 100644 --- a/arch/sh/include/asm/device.h +++ b/arch/sh/include/asm/device.h @@ -14,15 +14,6 @@ int platform_resource_setup_memory(struct platform_device *pdev, void plat_early_device_setup(void); -#define PDEV_ARCHDATA_FLAG_INIT 0 -#define PDEV_ARCHDATA_FLAG_IDLE 1 -#define PDEV_ARCHDATA_FLAG_SUSP 2 - struct pdev_archdata { int hwblk_id; -#ifdef CONFIG_PM_RUNTIME - unsigned long flags; - struct list_head entry; - struct mutex mutex; -#endif }; diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile index 7eb4502dfb6..e8a5111e848 100644 --- a/arch/sh/kernel/cpu/shmobile/Makefile +++ b/arch/sh/kernel/cpu/shmobile/Makefile @@ -5,6 +5,3 @@ # Power Management & Sleep mode obj-$(CONFIG_PM) += pm.o sleep.o obj-$(CONFIG_CPU_IDLE) += cpuidle.o -ifneq ($(CONFIG_CPU_SUBTYPE_SH7722)$(CONFIG_CPU_SUBTYPE_SH7723)$(CONFIG_CPU_SUBTYPE_SH7724),y) -obj-$(CONFIG_PM_RUNTIME) += pm_runtime.o -endif diff --git a/arch/sh/kernel/cpu/shmobile/pm_runtime.c b/arch/sh/kernel/cpu/shmobile/pm_runtime.c deleted file mode 100644 index bf280c812d2..00000000000 --- a/arch/sh/kernel/cpu/shmobile/pm_runtime.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * arch/sh/kernel/cpu/shmobile/pm_runtime.c - * - * Runtime PM support code for SuperH Mobile - * - * Copyright (C) 2009 Magnus Damm - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include -#include - -static DEFINE_SPINLOCK(hwblk_lock); -static LIST_HEAD(hwblk_idle_list); -static struct work_struct hwblk_work; - -extern struct hwblk_info *hwblk_info; - -static void platform_pm_runtime_not_idle(struct platform_device *pdev) -{ - unsigned long flags; - - /* remove device from idle list */ - spin_lock_irqsave(&hwblk_lock, flags); - if (test_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags)) { - list_del(&pdev->archdata.entry); - __clear_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags); - } - spin_unlock_irqrestore(&hwblk_lock, flags); -} - -static int __platform_pm_runtime_resume(struct platform_device *pdev) -{ - struct device *d = &pdev->dev; - struct pdev_archdata *ad = &pdev->archdata; - int hwblk = ad->hwblk_id; - int ret = -ENOSYS; - - dev_dbg(d, "__platform_pm_runtime_resume() [%d]\n", hwblk); - - if (d->driver) { - hwblk_enable(hwblk_info, hwblk); - ret = 0; - - if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) { - if (d->driver->pm && d->driver->pm->runtime_resume) - ret = d->driver->pm->runtime_resume(d); - - if (!ret) - clear_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); - else - hwblk_disable(hwblk_info, hwblk); - } - } - - dev_dbg(d, "__platform_pm_runtime_resume() [%d] - returns %d\n", - hwblk, ret); - - return ret; -} - -static int __platform_pm_runtime_suspend(struct platform_device *pdev) -{ - struct device *d = &pdev->dev; - struct pdev_archdata *ad = &pdev->archdata; - int hwblk = ad->hwblk_id; - int ret = -ENOSYS; - - dev_dbg(d, "__platform_pm_runtime_suspend() [%d]\n", hwblk); - - if (d->driver) { - BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags)); - ret = 0; - - if (d->driver->pm && d->driver->pm->runtime_suspend) { - hwblk_enable(hwblk_info, hwblk); - ret = d->driver->pm->runtime_suspend(d); - hwblk_disable(hwblk_info, hwblk); - } - - if (!ret) { - set_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags); - platform_pm_runtime_not_idle(pdev); - hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE); - } - } - - dev_dbg(d, "__platform_pm_runtime_suspend() [%d] - returns %d\n", - hwblk, ret); - - return ret; -} - -static void platform_pm_runtime_work(struct work_struct *work) -{ - struct platform_device *pdev; - unsigned long flags; - int ret; - - /* go through the idle list and suspend one device at a time */ - do { - spin_lock_irqsave(&hwblk_lock, flags); - if (list_empty(&hwblk_idle_list)) - pdev = NULL; - else - pdev = list_first_entry(&hwblk_idle_list, - struct platform_device, - archdata.entry); - spin_unlock_irqrestore(&hwblk_lock, flags); - - if (pdev) { - mutex_lock(&pdev->archdata.mutex); - ret = __platform_pm_runtime_suspend(pdev); - - /* at this point the platform device may be: - * suspended: ret = 0, FLAG_SUSP set, clock stopped - * failed: ret < 0, FLAG_IDLE set, clock stopped - */ - mutex_unlock(&pdev->archdata.mutex); - } else { - ret = -ENODEV; - } - } while (!ret); -} - -/* this function gets called from cpuidle context when all devices in the - * main power domain are unused but some are counted as idle, ie the hwblk - * counter values are (HWBLK_CNT_USAGE == 0) && (HWBLK_CNT_IDLE != 0) - */ -void platform_pm_runtime_suspend_idle(void) -{ - queue_work(pm_wq, &hwblk_work); -} - -static int default_platform_runtime_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pdev_archdata *ad = &pdev->archdata; - unsigned long flags; - int hwblk = ad->hwblk_id; - int ret = 0; - - dev_dbg(dev, "%s() [%d]\n", __func__, hwblk); - - /* ignore off-chip platform devices */ - if (!hwblk) - goto out; - - /* interrupt context not allowed */ - might_sleep(); - - /* catch misconfigured drivers not starting with resume */ - if (test_bit(PDEV_ARCHDATA_FLAG_INIT, &ad->flags)) { - ret = -EINVAL; - goto out; - } - - /* serialize */ - mutex_lock(&ad->mutex); - - /* disable clock */ - hwblk_disable(hwblk_info, hwblk); - - /* put device on idle list */ - spin_lock_irqsave(&hwblk_lock, 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 */ - hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_IDLE); - - /* at this point the platform device is: - * idle: ret = 0, FLAG_IDLE set, clock stopped - */ - mutex_unlock(&ad->mutex); - -out: - dev_dbg(dev, "%s() [%d] returns %d\n", - __func__, hwblk, ret); - - return ret; -} - -static int default_platform_runtime_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pdev_archdata *ad = &pdev->archdata; - int hwblk = ad->hwblk_id; - int ret = 0; - - dev_dbg(dev, "%s() [%d]\n", __func__, hwblk); - - /* ignore off-chip platform devices */ - if (!hwblk) - goto out; - - /* interrupt context not allowed */ - might_sleep(); - - /* serialize */ - mutex_lock(&ad->mutex); - - /* make sure device is removed from idle list */ - platform_pm_runtime_not_idle(pdev); - - /* decrease idle count */ - if (!test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags) && - !test_bit(PDEV_ARCHDATA_FLAG_SUSP, &pdev->archdata.flags)) - hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE); - - /* resume the device if needed */ - ret = __platform_pm_runtime_resume(pdev); - - /* the driver has been initialized now, so clear the init flag */ - clear_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); - - /* at this point the platform device may be: - * resumed: ret = 0, flags = 0, clock started - * failed: ret < 0, FLAG_SUSP set, clock stopped - */ - mutex_unlock(&ad->mutex); -out: - dev_dbg(dev, "%s() [%d] returns %d\n", - __func__, hwblk, ret); - - return ret; -} - -static int default_platform_runtime_idle(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - int hwblk = pdev->archdata.hwblk_id; - int ret = 0; - - dev_dbg(dev, "%s() [%d]\n", __func__, hwblk); - - /* ignore off-chip platform devices */ - if (!hwblk) - goto out; - - /* interrupt context not allowed, use pm_runtime_put()! */ - might_sleep(); - - /* suspend synchronously to disable clocks immediately */ - ret = pm_runtime_suspend(dev); -out: - dev_dbg(dev, "%s() [%d] done!\n", __func__, hwblk); - return ret; -} - -static struct dev_pm_domain default_pm_domain = { - .ops = { - .runtime_suspend = default_platform_runtime_suspend, - .runtime_resume = default_platform_runtime_resume, - .runtime_idle = default_platform_runtime_idle, - USE_PLATFORM_PM_SLEEP_OPS - }, -}; - -static int platform_bus_notify(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - struct platform_device *pdev = to_platform_device(dev); - int hwblk = pdev->archdata.hwblk_id; - - /* ignore off-chip platform devices */ - if (!hwblk) - return 0; - - switch (action) { - case BUS_NOTIFY_ADD_DEVICE: - INIT_LIST_HEAD(&pdev->archdata.entry); - mutex_init(&pdev->archdata.mutex); - /* platform devices without drivers should be disabled */ - hwblk_enable(hwblk_info, hwblk); - hwblk_disable(hwblk_info, hwblk); - /* make sure driver re-inits itself once */ - __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); - dev->pm_domain = &default_pm_domain; - break; - /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */ - case BUS_NOTIFY_BOUND_DRIVER: - /* keep track of number of devices in use per hwblk */ - hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_DEVICES); - break; - case BUS_NOTIFY_UNBOUND_DRIVER: - /* keep track of number of devices in use per hwblk */ - hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_DEVICES); - /* make sure driver re-inits itself once */ - __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags); - break; - case BUS_NOTIFY_DEL_DEVICE: - dev->pm_domain = NULL; - break; - } - return 0; -} - -static struct notifier_block platform_bus_notifier = { - .notifier_call = platform_bus_notify -}; - -static int __init sh_pm_runtime_init(void) -{ - INIT_WORK(&hwblk_work, platform_pm_runtime_work); - - bus_register_notifier(&platform_bus_type, &platform_bus_notifier); - return 0; -} -core_initcall(sh_pm_runtime_init); diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 51f171b0148..c393894ff35 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -7,14 +7,4 @@ obj-$(CONFIG_HAVE_CLK) += clk/ obj-$(CONFIG_MAPLE) += maple/ obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_GENERIC_GPIO) += pfc.o - -# -# For the moment we only use this framework for ARM-based SH/R-Mobile -# platforms and generic SH. SH-based SH-Mobile platforms are still using -# an older framework that is pending up-porting, at which point this -# special casing can go away. -# -obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o -obj-$(CONFIG_CPU_SUBTYPE_SH7722) += pm_runtime.o -obj-$(CONFIG_CPU_SUBTYPE_SH7723) += pm_runtime.o -obj-$(CONFIG_CPU_SUBTYPE_SH7724) += pm_runtime.o +obj-$(CONFIG_PM_RUNTIME) += pm_runtime.o -- cgit v1.2.3 From 56242a1fc595d158eddefbb4d6d76e82c2535f55 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 21 Nov 2011 21:33:18 -0800 Subject: sh: clkfwk: setup clock parent from current register value Some clocks can select its parent clock by CPG register. But it might have been modified by boot-loader or something. This patch removed fixed initial parent clock, and setup it from their current register settings. It works on div6 reparent clocks for now. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/clock-sh7372.c | 6 +++--- arch/sh/kernel/cpu/sh4a/clock-sh7724.c | 4 ++-- drivers/sh/clk/cpg.c | 35 ++++++++++++++++++++++++++++++++++ include/linux/sh_clk.h | 9 ++++++--- 4 files changed, 46 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c index 995a9c3aec8..e349c22a0d7 100644 --- a/arch/arm/mach-shmobile/clock-sh7372.c +++ b/arch/arm/mach-shmobile/clock-sh7372.c @@ -411,11 +411,11 @@ static struct clk *fsibckcr_parent[] = { }; static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { - [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0, + [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0, hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2), - [DIV6_FSIA] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIACKCR, 0, + [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0, fsiackcr_parent, ARRAY_SIZE(fsiackcr_parent), 6, 2), - [DIV6_FSIB] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIBCKCR, 0, + [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0, fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2), }; diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 8668f557e0a..77118387f1c 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -189,9 +189,9 @@ static struct clk *fclkbcr_parent[] = { }; static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = { - [DIV6_FA] = SH_CLK_DIV6_EXT(&div3_clk, FCLKACR, 0, + [DIV6_FA] = SH_CLK_DIV6_EXT(FCLKACR, 0, fclkacr_parent, ARRAY_SIZE(fclkacr_parent), 6, 2), - [DIV6_FB] = SH_CLK_DIV6_EXT(&div3_clk, FCLKBCR, 0, + [DIV6_FB] = SH_CLK_DIV6_EXT(FCLKBCR, 0, fclkbcr_parent, ARRAY_SIZE(fclkbcr_parent), 6, 2), }; diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 82dd6fb1783..5e4301b936e 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = { .set_parent = sh_clk_div6_set_parent, }; +static int __init sh_clk_init_parent(struct clk *clk) +{ + u32 val; + + if (clk->parent) + return 0; + + if (!clk->parent_table || !clk->parent_num) + return 0; + + if (!clk->src_width) { + pr_err("sh_clk_init_parent: cannot select parent clock\n"); + return -EINVAL; + } + + val = (__raw_readl(clk->enable_reg) >> clk->src_shift); + val &= (1 << clk->src_width) - 1; + + if (val >= clk->parent_num) { + pr_err("sh_clk_init_parent: parent table size failed\n"); + return -EINVAL; + } + + clk->parent = clk->parent_table[val]; + if (!clk->parent) { + pr_err("sh_clk_init_parent: unable to set parent"); + return -EINVAL; + } + + return 0; +} + static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, struct clk_ops *ops) { @@ -190,6 +222,9 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, clkp->ops = ops; clkp->freq_table = freq_table + (k * freq_table_size); clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; + ret = sh_clk_init_parent(clkp); + if (ret < 0) + break; ret = clk_register(clkp); } diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h index a20831cf336..e834304c0b6 100644 --- a/include/linux/sh_clk.h +++ b/include/linux/sh_clk.h @@ -131,10 +131,9 @@ int sh_clk_div4_enable_register(struct clk *clks, int nr, int sh_clk_div4_reparent_register(struct clk *clks, int nr, struct clk_div4_table *table); -#define SH_CLK_DIV6_EXT(_parent, _reg, _flags, _parents, \ +#define SH_CLK_DIV6_EXT(_reg, _flags, _parents, \ _num_parents, _src_shift, _src_width) \ { \ - .parent = _parent, \ .enable_reg = (void __iomem *)_reg, \ .flags = _flags, \ .parent_table = _parents, \ @@ -144,7 +143,11 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr, } #define SH_CLK_DIV6(_parent, _reg, _flags) \ - SH_CLK_DIV6_EXT(_parent, _reg, _flags, NULL, 0, 0, 0) +{ \ + .parent = _parent, \ + .enable_reg = (void __iomem *)_reg, \ + .flags = _flags, \ +} int sh_clk_div6_register(struct clk *clks, int nr); int sh_clk_div6_reparent_register(struct clk *clks, int nr); -- cgit v1.2.3 From 0979e0e641d21d3bb318da90a64fc0024a95f50e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 Nov 2011 18:35:49 +0900 Subject: serial: sh-sci: Fix up SCFCR handling. Presently there are a few places that make assumptions about the existence of SCFCR, which doesn't hold true for several port types. While generally harmless, this does lead to bogus reads/writes in both the termios/runtime PM cases that are better off simply never being made in the first place. While we're at it, also get rid of a straggling PORT_SCI check that infers all non-SCI ports contain SCFCR. This doesn't presently have any impact, but as we're now able to test for the existence of registers without defering to the port type we future proof for additional port types. Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index aff9d612dff..c13910587bc 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1652,6 +1652,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, static void sci_reset(struct uart_port *port) { + struct plat_sci_reg *reg; unsigned int status; do { @@ -1660,7 +1661,8 @@ static void sci_reset(struct uart_port *port) sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ - if (port->type != PORT_SCI) + reg = sci_getreg(port, SCFCR); + if (reg->size) sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); } @@ -1668,9 +1670,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct sci_port *s = to_sci_port(port); + struct plat_sci_reg *reg; unsigned int baud, smr_val, max_baud; int t = -1; - u16 scfcr = 0; /* * earlyprintk comes here early on with port->uartclk set to zero. @@ -1720,7 +1722,18 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, } sci_init_pins(port, termios->c_cflag); - sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); + + reg = sci_getreg(port, SCFCR); + if (reg->size) { + unsigned short ctrl; + + ctrl = sci_in(port, SCFCR); + if (termios->c_cflag & CRTSCTS) + ctrl |= SCFCR_MCE; + else + ctrl &= ~SCFCR_MCE; + sci_out(port, SCFCR, ctrl); + } sci_out(port, SCSCR, s->cfg->scscr); @@ -2113,9 +2126,16 @@ static int sci_runtime_suspend(struct device *dev) struct uart_port *port = &sci_port->port; if (uart_console(port)) { + struct plat_sci_reg *reg; + sci_port->saved_smr = sci_in(port, SCSMR); sci_port->saved_brr = sci_in(port, SCBRR); - sci_port->saved_fcr = sci_in(port, SCFCR); + + reg = sci_getreg(port, SCFCR); + if (reg->size) + sci_port->saved_fcr = sci_in(port, SCFCR); + else + sci_port->saved_fcr = 0; } return 0; } @@ -2129,7 +2149,10 @@ static int sci_runtime_resume(struct device *dev) sci_reset(port); sci_out(port, SCSMR, sci_port->saved_smr); sci_out(port, SCBRR, sci_port->saved_brr); - sci_out(port, SCFCR, sci_port->saved_fcr); + + if (sci_port->saved_fcr) + sci_out(port, SCFCR, sci_port->saved_fcr); + sci_out(port, SCSCR, sci_port->cfg->scscr); } return 0; -- cgit v1.2.3 From d97fbbed6e5bb37df75be8993bb0c61adb7d3558 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 Nov 2011 19:15:06 +0900 Subject: serial: sh-sci: Support icount statistics for error cases. Presently the icount stats are only adjusted for the rx/tx case, this makes sure that they're updated appropriately for the non-tx/rx cases, too (specifically overruns, breaks, as well as frame and parity errors). Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c13910587bc..3bea91b3a6f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -621,6 +621,7 @@ static void sci_receive_chars(struct uart_port *port) } else { for (i = 0; i < count; i++) { char c = sci_in(port, SCxRDR); + status = sci_in(port, SCxSR); #if defined(CONFIG_CPU_SH3) /* Skip "chars" during break */ @@ -649,9 +650,11 @@ static void sci_receive_chars(struct uart_port *port) /* Store data and status */ if (status & SCxSR_FER(port)) { flag = TTY_FRAME; + port->icount.frame++; dev_notice(port->dev, "frame error\n"); } else if (status & SCxSR_PER(port)) { flag = TTY_PARITY; + port->icount.parity++; dev_notice(port->dev, "parity error\n"); } else flag = TTY_NORMAL; @@ -723,6 +726,8 @@ static int sci_handle_errors(struct uart_port *port) */ if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) { if (status & (1 << s->cfg->overrun_bit)) { + port->icount.overrun++; + /* overrun error */ if (tty_insert_flip_char(tty, 0, TTY_OVERRUN)) copied++; @@ -737,6 +742,8 @@ static int sci_handle_errors(struct uart_port *port) struct sci_port *sci_port = to_sci_port(port); if (!sci_port->break_flag) { + port->icount.brk++; + sci_port->break_flag = 1; sci_schedule_break_timer(sci_port); @@ -752,6 +759,8 @@ static int sci_handle_errors(struct uart_port *port) } else { /* frame error */ + port->icount.frame++; + if (tty_insert_flip_char(tty, 0, TTY_FRAME)) copied++; @@ -761,6 +770,8 @@ static int sci_handle_errors(struct uart_port *port) if (status & SCxSR_PER(port)) { /* parity error */ + port->icount.parity++; + if (tty_insert_flip_char(tty, 0, TTY_PARITY)) copied++; @@ -787,6 +798,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port) if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) { sci_out(port, SCLSR, 0); + port->icount.overrun++; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); tty_flip_buffer_push(tty); @@ -812,6 +825,9 @@ static int sci_handle_breaks(struct uart_port *port) /* Debounce break */ s->break_flag = 1; #endif + + port->icount.brk++; + /* Notify of BREAK */ if (tty_insert_flip_char(tty, 0, TTY_BREAK)) copied++; -- cgit v1.2.3 From d39ec6ce34f130d582880d1f3cbe2b38e723cafe Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 Nov 2011 19:36:46 +0900 Subject: serial: sh-sci: Clarify enable_ms/break_ctl comments. Technically there's nothing we can do for either of these, so update the comments to reflect this, rather than infering that there's additional work to be done. Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 3bea91b3a6f..cd1379235f1 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1465,12 +1465,17 @@ static void sci_stop_rx(struct uart_port *port) static void sci_enable_ms(struct uart_port *port) { - /* Nothing here yet .. */ + /* + * Not supported by hardware, always a nop. + */ } static void sci_break_ctl(struct uart_port *port, int break_state) { - /* Nothing here yet .. */ + /* + * Not supported by hardware. Most parts couple break and rx + * interrupts together, with break detection always enabled. + */ } #ifdef CONFIG_SERIAL_SH_SCI_DMA -- cgit v1.2.3 From cdf7c42fece7c641fcb85cfbf190fdc2a95d19ac Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 Nov 2011 20:18:32 +0900 Subject: serial: sh-sci: Fix up modem control handling. At the moment things like CTS/RTS are reported for all ports, while the vast majority of them do not implement support at all (and others implement support entirely in hardware). Fix up the ->get_mctrl() reporting to simply assert DSR/CAR as other drivers without control lines do. Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index cd1379235f1..680d34af71f 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1106,19 +1106,26 @@ static unsigned int sci_tx_empty(struct uart_port *port) return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0; } +/* + * Modem control is a bit of a mixed bag for SCI(F) ports. Generally + * CTS/RTS is supported in hardware by at least one port and controlled + * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently + * handled via the ->init_pins() op, which is a bit of a one-way street, + * lacking any ability to defer pin control -- this will later be + * converted over to the GPIO framework). + */ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) { - /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */ - /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */ - /* If you have signals for DTR and DCD, please implement here. */ + /* Nothing to do here. */ } static unsigned int sci_get_mctrl(struct uart_port *port) { - /* This routine is used for getting signals of: DTR, DCD, DSR, RI, - and CTS/RTS */ - - return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR; + /* + * CTS/RTS is handled in hardware when supported, while nothing + * else is wired up. Keep it simple and simply assert DSR/CAR. + */ + return TIOCM_DSR | TIOCM_CAR; } #ifdef CONFIG_SERIAL_SH_SCI_DMA -- cgit v1.2.3 From dc7e3ef7dade7041fb1809f2a5403efac655a791 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 Nov 2011 20:20:53 +0900 Subject: serial: sh-sci: Add support for loopback mode. This plugs in loopback control for SCFCR-enabled ports and plugs it in via the TIOCM_LOOP control, as others do. Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 680d34af71f..46deaaec836 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1113,10 +1113,23 @@ static unsigned int sci_tx_empty(struct uart_port *port) * handled via the ->init_pins() op, which is a bit of a one-way street, * lacking any ability to defer pin control -- this will later be * converted over to the GPIO framework). + * + * Other modes (such as loopback) are supported generically on certain + * port types, but not others. For these it's sufficient to test for the + * existence of the support register and simply ignore the port type. */ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl) { - /* Nothing to do here. */ + if (mctrl & TIOCM_LOOP) { + struct plat_sci_reg *reg; + + /* + * Standard loopback mode for SCFCR ports. + */ + reg = sci_getreg(port, SCFCR); + if (reg->size) + sci_out(port, SCFCR, sci_in(port, SCFCR) | 1); + } } static unsigned int sci_get_mctrl(struct uart_port *port) -- cgit v1.2.3 From faf02f8fee5563ea7f950b3f5f08c654aa6c4525 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 2 Dec 2011 17:44:50 +0900 Subject: serial: sh-sci: per-port modem control. The bulk of the ports do not support any sort of modem control, so blindly twiddling the MCE bit doesn't accomplish much. We now require ports to manually specify which line supports modem control signals. While at it, tidy up the RTS/CTSIO handling in SCSPTR parts so it's a bit more obvious what's going on (and without clobbering other configurations in the process). Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 31 ++++++++++++++++++++----------- include/linux/serial_sci.h | 10 ++++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 46deaaec836..fd60d72eac8 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -474,8 +474,15 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag) if (!reg->size) return; - if (!(cflag & CRTSCTS)) - sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */ + if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) && + ((!(cflag & CRTSCTS)))) { + unsigned short status; + + status = sci_in(port, SCSPTR); + status &= ~SCSPTR_CTSIO; + status |= SCSPTR_RTSIO; + sci_out(port, SCSPTR, status); /* Set RTS = 1 */ + } } static int sci_txfill(struct uart_port *port) @@ -1764,16 +1771,18 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_init_pins(port, termios->c_cflag); - reg = sci_getreg(port, SCFCR); - if (reg->size) { - unsigned short ctrl; + if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) { + reg = sci_getreg(port, SCFCR); + if (reg->size) { + unsigned short ctrl; - ctrl = sci_in(port, SCFCR); - if (termios->c_cflag & CRTSCTS) - ctrl |= SCFCR_MCE; - else - ctrl &= ~SCFCR_MCE; - sci_out(port, SCFCR, ctrl); + ctrl = sci_in(port, SCFCR); + if (termios->c_cflag & CRTSCTS) + ctrl |= SCFCR_MCE; + else + ctrl &= ~SCFCR_MCE; + sci_out(port, SCFCR, ctrl); + } } sci_out(port, SCSCR, s->cfg->scscr); diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 369273a5267..15b1bdcaa9f 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -49,6 +49,10 @@ enum { #define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK) +/* SCSPTR, optional */ +#define SCSPTR_RTSIO (1 << 7) +#define SCSPTR_CTSIO (1 << 5) + /* Offsets into the sci_port->irqs array */ enum { SCIx_ERI_IRQ, @@ -108,6 +112,11 @@ struct plat_sci_port_ops { void (*init_pins)(struct uart_port *, unsigned int cflag); }; +/* + * Port-specific capabilities + */ +#define SCIx_HAVE_RTSCTS (1 << 0) + /* * Platform device specific platform_data struct */ @@ -116,6 +125,7 @@ struct plat_sci_port { unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */ unsigned int type; /* SCI / SCIF / IRDA */ upf_t flags; /* UPF_* flags */ + unsigned long capabilities; /* Port features/capabilities */ unsigned int scbrr_algo_id; /* SCBRR calculation algo */ unsigned int scscr; /* SCSCR initialization */ -- cgit v1.2.3 From 73c3d53f38e0a8e6c67b0d12d77a8e77c082cd03 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 2 Dec 2011 19:02:06 +0900 Subject: serial: sh-sci: Avoid FIFO clear for MCE toggle. When toggling the MCE support we don't want to concern ourselves with the FIFO state, so ensure that the clearing bits are masked out when updating the MCE state. Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index fd60d72eac8..761a800cb48 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1771,18 +1771,25 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, sci_init_pins(port, termios->c_cflag); - if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) { - reg = sci_getreg(port, SCFCR); - if (reg->size) { - unsigned short ctrl; + reg = sci_getreg(port, SCFCR); + if (reg->size) { + unsigned short ctrl = sci_in(port, SCFCR); - ctrl = sci_in(port, SCFCR); + if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) { if (termios->c_cflag & CRTSCTS) ctrl |= SCFCR_MCE; else ctrl &= ~SCFCR_MCE; - sci_out(port, SCFCR, ctrl); } + + /* + * As we've done a sci_reset() above, ensure we don't + * interfere with the FIFOs while toggling MCE. As the + * reset values could still be set, simply mask them out. + */ + ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST); + + sci_out(port, SCFCR, ctrl); } sci_out(port, SCSCR, s->cfg->scscr); -- cgit v1.2.3 From 50f0959ad4f9ac1c5ee208bb820de299a1b3730b Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 2 Dec 2011 20:09:48 +0900 Subject: serial: sh-sci: Handle GPIO function requests. This adds initial support for requesting the various GPIO functions necessary for certain ports. This just plugs in dumb request/free logic, but serves as a building block for migrating off of the ->init_pins mess to a wholly gpiolib backed solution (primarily parts with external RTS/CTS pins, but will also allow us to clean up RXD pin testing). Signed-off-by: Paul Mundt --- drivers/tty/serial/sh-sci.c | 71 +++++++++++++++++++++++++++++++++++++++++++-- include/linux/serial_sci.h | 12 ++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 761a800cb48..9e62349b3d9 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -50,6 +50,7 @@ #include #include #include +#include #ifdef CONFIG_SUPERH #include @@ -73,6 +74,7 @@ struct sci_port { struct clk *fclk; char *irqstr[SCIx_NR_IRQS]; + char *gpiostr[SCIx_NR_FNS]; struct dma_chan *chan_tx; struct dma_chan *chan_rx; @@ -1105,6 +1107,67 @@ static void sci_free_irq(struct sci_port *port) } } +static const char *sci_gpio_names[SCIx_NR_FNS] = { + "sck", "rxd", "txd", "cts", "rts", +}; + +static const char *sci_gpio_str(unsigned int index) +{ + return sci_gpio_names[index]; +} + +static void __devinit sci_init_gpios(struct sci_port *port) +{ + struct uart_port *up = &port->port; + int i; + + if (!port->cfg) + return; + + for (i = 0; i < SCIx_NR_FNS; i++) { + const char *desc; + int ret; + + if (!port->cfg->gpios[i]) + continue; + + desc = sci_gpio_str(i); + + port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s", + dev_name(up->dev), desc); + + /* + * If we've failed the allocation, we can still continue + * on with a NULL string. + */ + if (!port->gpiostr[i]) + dev_notice(up->dev, "%s string allocation failure\n", + desc); + + ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]); + if (unlikely(ret != 0)) { + dev_notice(up->dev, "failed %s gpio request\n", desc); + + /* + * If we can't get the GPIO for whatever reason, + * no point in keeping the verbose string around. + */ + kfree(port->gpiostr[i]); + } + } +} + +static void sci_free_gpios(struct sci_port *port) +{ + int i; + + for (i = 0; i < SCIx_NR_FNS; i++) + if (port->cfg->gpios[i]) { + gpio_free(port->cfg->gpios[i]); + kfree(port->gpiostr[i]); + } +} + static unsigned int sci_tx_empty(struct uart_port *port) { unsigned short status = sci_in(port, SCxSR); @@ -1962,6 +2025,8 @@ static int __devinit sci_init_single(struct platform_device *dev, struct uart_port *port = &sci_port->port; int ret; + sci_port->cfg = p; + port->ops = &sci_uart_ops; port->iotype = UPIO_MEM; port->line = index; @@ -2007,6 +2072,8 @@ static int __devinit sci_init_single(struct platform_device *dev, port->dev = &dev->dev; + sci_init_gpios(sci_port); + pm_runtime_irq_safe(&dev->dev); pm_runtime_enable(&dev->dev); } @@ -2041,8 +2108,6 @@ static int __devinit sci_init_single(struct platform_device *dev, p->error_mask |= (1 << p->overrun_bit); } - sci_port->cfg = p; - port->mapbase = p->mapbase; port->type = p->type; port->flags = p->flags; @@ -2249,6 +2314,8 @@ static int sci_remove(struct platform_device *dev) cpufreq_unregister_notifier(&port->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); + sci_free_gpios(port); + uart_remove_one_port(&sci_uart_driver, &port->port); clk_put(port->iclk); diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h index 15b1bdcaa9f..78779074f6e 100644 --- a/include/linux/serial_sci.h +++ b/include/linux/serial_sci.h @@ -64,6 +64,17 @@ enum { SCIx_MUX_IRQ = SCIx_NR_IRQS, /* special case */ }; +/* Offsets into the sci_port->gpios array */ +enum { + SCIx_SCK, + SCIx_RXD, + SCIx_TXD, + SCIx_CTS, + SCIx_RTS, + + SCIx_NR_FNS, +}; + enum { SCIx_PROBE_REGTYPE, @@ -123,6 +134,7 @@ struct plat_sci_port_ops { struct plat_sci_port { unsigned long mapbase; /* resource base */ unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */ + unsigned int gpios[SCIx_NR_FNS]; /* SCK, RXD, TXD, CTS, RTS */ unsigned int type; /* SCI / SCIF / IRDA */ upf_t flags; /* UPF_* flags */ unsigned long capabilities; /* Port features/capabilities */ -- cgit v1.2.3 From eda2030a5b60bb818f062adacbcfb6fd2d366fb9 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Dec 2011 22:58:54 +0900 Subject: sh: extend clock struct with mapped_reg member Add a "mapped_reg" member to struct clk and use that to keep the ioremapped register based on enable_reg. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/clk/core.c | 9 +++++++-- include/linux/sh_clk.h | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index db257a35e71..7715de2629c 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -355,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk) */ if (!clk->parent) { clk->mapping = &dummy_mapping; - return 0; + goto out; } /* @@ -384,6 +384,9 @@ static int clk_establish_mapping(struct clk *clk) } clk->mapping = mapping; +out: + clk->mapped_reg = clk->mapping->base; + clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys; return 0; } @@ -402,10 +405,12 @@ static void clk_teardown_mapping(struct clk *clk) /* Nothing to do */ if (mapping == &dummy_mapping) - return; + goto out; kref_put(&mapping->ref, clk_destroy_mapping); clk->mapping = NULL; +out: + clk->mapped_reg = NULL; } int clk_register(struct clk *clk) diff --git a/include/linux/sh_clk.h b/include/linux/sh_clk.h index e834304c0b6..54341d81168 100644 --- a/include/linux/sh_clk.h +++ b/include/linux/sh_clk.h @@ -49,6 +49,7 @@ struct clk { void __iomem *enable_reg; unsigned int enable_bit; + void __iomem *mapped_reg; unsigned long arch_flags; void *priv; -- cgit v1.2.3 From b3ab82b3eb191ad2cd8110cb5de0afb790337000 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Dec 2011 22:59:03 +0900 Subject: sh: use ioread32/iowrite32 and mapped_reg for mstp32 Convert the CPG MSTP32 helper code to use the new mapped_reg together with ioread32() and iowrite32(). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/clk/cpg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 5e4301b936e..ed8bc70730f 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -15,15 +15,15 @@ static int sh_clk_mstp32_enable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), - clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), + clk->mapped_reg); return 0; } static void sh_clk_mstp32_disable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), - clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), + clk->mapped_reg); } static struct clk_ops sh_clk_mstp32_clk_ops = { -- cgit v1.2.3 From 0e027376f896e5dda293ffc8e6e7332d26d2ffc4 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Dec 2011 22:59:13 +0900 Subject: sh: use ioread32/iowrite32 and mapped_reg for div4 Convert the CPG DIV4 helper code to use the new mapped_reg together with ioread32() and iowrite32(). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/clk/cpg.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index ed8bc70730f..e4a2edf139f 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -252,7 +252,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk) clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, table, &clk->arch_flags); - idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; + idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f; return clk->freq_table[idx].frequency; } @@ -270,15 +270,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) */ if (parent->flags & CLK_ENABLE_ON_INIT) - value = __raw_readl(clk->enable_reg) & ~(1 << 7); + value = ioread32(clk->mapped_reg) & ~(1 << 7); else - value = __raw_readl(clk->enable_reg) | (1 << 7); + value = ioread32(clk->mapped_reg) | (1 << 7); ret = clk_reparent(clk, parent); if (ret < 0) return ret; - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); /* Rebiuld the frequency table */ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, @@ -295,10 +295,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) if (idx < 0) return idx; - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value &= ~(0xf << clk->enable_bit); value |= (idx << clk->enable_bit); - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); if (d4t->kick) d4t->kick(clk); @@ -308,13 +308,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate) static int sh_clk_div4_enable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg); return 0; } static void sh_clk_div4_disable(struct clk *clk) { - __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); + iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg); } static struct clk_ops sh_clk_div4_clk_ops = { -- cgit v1.2.3 From 2dacb97d9269e303ed761937a0e9db8711515e08 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 8 Dec 2011 22:59:22 +0900 Subject: sh: use ioread32/iowrite32 and mapped_reg for div6 Convert the CPG DIV6 helper code to use the new mapped_reg together with ioread32() and iowrite32(). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/clk/cpg.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index e4a2edf139f..a0d8faa40ba 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk) clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, table, NULL); - idx = __raw_readl(clk->enable_reg) & 0x003f; + idx = ioread32(clk->mapped_reg) & 0x003f; return clk->freq_table[idx].frequency; } @@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent) if (ret < 0) return ret; - value = __raw_readl(clk->enable_reg) & + value = ioread32(clk->mapped_reg) & ~(((1 << clk->src_width) - 1) << clk->src_shift); - __raw_writel(value | (i << clk->src_shift), clk->enable_reg); + iowrite32(value | (i << clk->src_shift), clk->mapped_reg); /* Rebuild the frequency table */ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, @@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate) if (idx < 0) return idx; - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value &= ~0x3f; value |= idx; - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); return 0; } @@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk *clk) ret = sh_clk_div6_set_rate(clk, clk->rate); if (ret == 0) { - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value &= ~0x100; /* clear stop bit to enable clock */ - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); } return ret; } @@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct clk *clk) { unsigned long value; - value = __raw_readl(clk->enable_reg); + value = ioread32(clk->mapped_reg); value |= 0x100; /* stop clock */ value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ - __raw_writel(value, clk->enable_reg); + iowrite32(value, clk->mapped_reg); } static struct clk_ops sh_clk_div6_clk_ops = { @@ -182,7 +182,7 @@ static int __init sh_clk_init_parent(struct clk *clk) return -EINVAL; } - val = (__raw_readl(clk->enable_reg) >> clk->src_shift); + val = (ioread32(clk->mapped_reg) >> clk->src_shift); val &= (1 << clk->src_width) - 1; if (val >= clk->parent_num) { -- cgit v1.2.3 From b0e10211cba1629e2e534ca9cb3d87cfc7e389ea Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 9 Dec 2011 12:14:27 +0900 Subject: sh: pfc: ioremap() support Add support for non-entity mapped PFC registers through the use of struct resource and ioremap()/iounmap(). The PFC main data structure gets updated with a pointer to a struct resources array that point out all register windows used by the PFC instance. The register definitions are kept as physical addresses but the PFC code will do transparent conversion into virtual addresses whenever register windows are specified using with struct resource. To introduce as little performance penalty as possible the virtual address of each data register is cached in memory. The virtual address of each configuration register is however calculated during run time. This because the configuration is considered slow path so focus is instead put on keeping memory foot print as small as possible. The PFC register access code is in this patch updated from __raw_readN() / __raw_writeN() into ioreadN() / iowriteN(). This patch is needed to support the PFC block in r8a7779. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/pfc.c | 137 ++++++++++++++++++++++++++++++++++++++++--------- include/linux/sh_pfc.h | 11 ++++ 2 files changed, 124 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c index e67fe170d8d..e7d127a9c1c 100644 --- a/drivers/sh/pfc.c +++ b/drivers/sh/pfc.c @@ -19,6 +19,75 @@ #include #include #include +#include +#include + +static void pfc_iounmap(struct pinmux_info *pip) +{ + int k; + + for (k = 0; k < pip->num_resources; k++) + if (pip->window[k].virt) + iounmap(pip->window[k].virt); + + kfree(pip->window); + pip->window = NULL; +} + +static int pfc_ioremap(struct pinmux_info *pip) +{ + struct resource *res; + int k; + + if (!pip->num_resources) + return 0; + + pip->window = kzalloc(pip->num_resources * sizeof(*pip->window), + GFP_NOWAIT); + if (!pip->window) + goto err1; + + for (k = 0; k < pip->num_resources; k++) { + res = pip->resource + k; + WARN_ON(resource_type(res) != IORESOURCE_MEM); + pip->window[k].phys = res->start; + pip->window[k].size = resource_size(res); + pip->window[k].virt = ioremap_nocache(res->start, + resource_size(res)); + if (!pip->window[k].virt) + goto err2; + } + + return 0; + +err2: + pfc_iounmap(pip); +err1: + return -1; +} + +static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip, + unsigned long address) +{ + struct pfc_window *window; + int k; + + /* scan through physical windows and convert address */ + for (k = 0; k < pip->num_resources; k++) { + window = pip->window + k; + + if (address < window->phys) + continue; + + if (address >= (window->phys + window->size)) + continue; + + return window->virt + (address - window->phys); + } + + /* no windows defined, register must be 1:1 mapped virt:phys */ + return (void __iomem *)address; +} static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) { @@ -31,35 +100,35 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r) return 1; } -static unsigned long gpio_read_raw_reg(unsigned long reg, +static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg, unsigned long reg_width) { switch (reg_width) { case 8: - return __raw_readb(reg); + return ioread8(mapped_reg); case 16: - return __raw_readw(reg); + return ioread16(mapped_reg); case 32: - return __raw_readl(reg); + return ioread32(mapped_reg); } BUG(); return 0; } -static void gpio_write_raw_reg(unsigned long reg, +static void gpio_write_raw_reg(void __iomem *mapped_reg, unsigned long reg_width, unsigned long data) { switch (reg_width) { case 8: - __raw_writeb(data, reg); + iowrite8(data, mapped_reg); return; case 16: - __raw_writew(data, reg); + iowrite16(data, mapped_reg); return; case 32: - __raw_writel(data, reg); + iowrite32(data, mapped_reg); return; } @@ -82,11 +151,12 @@ static void gpio_write_bit(struct pinmux_data_reg *dr, else clear_bit(pos, &dr->reg_shadow); - gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow); + gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow); } -static int gpio_read_reg(unsigned long reg, unsigned long reg_width, - unsigned long field_width, unsigned long in_pos) +static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width, + unsigned long field_width, unsigned long in_pos, + unsigned long reg) { unsigned long data, mask, pos; @@ -98,13 +168,13 @@ static int gpio_read_reg(unsigned long reg, unsigned long reg_width, "r_width = %ld, f_width = %ld\n", reg, pos, reg_width, field_width); - data = gpio_read_raw_reg(reg, reg_width); + data = gpio_read_raw_reg(mapped_reg, reg_width); return (data >> pos) & mask; } -static void gpio_write_reg(unsigned long reg, unsigned long reg_width, +static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width, unsigned long field_width, unsigned long in_pos, - unsigned long value) + unsigned long value, unsigned long reg) { unsigned long mask, pos; @@ -120,13 +190,13 @@ static void gpio_write_reg(unsigned long reg, unsigned long reg_width, switch (reg_width) { case 8: - __raw_writeb((__raw_readb(reg) & mask) | value, reg); + iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg); break; case 16: - __raw_writew((__raw_readw(reg) & mask) | value, reg); + iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg); break; case 32: - __raw_writel((__raw_readl(reg) & mask) | value, reg); + iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg); break; } } @@ -147,6 +217,8 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio) if (!data_reg->reg_width) break; + data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg); + for (n = 0; n < data_reg->reg_width; n++) { if (data_reg->enum_ids[n] == gpiop->enum_id) { gpiop->flags &= ~PINMUX_FLAG_DREG; @@ -179,7 +251,8 @@ static void setup_data_regs(struct pinmux_info *gpioc) if (!drp->reg_width) break; - drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width); + drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg, + drp->reg_width); k++; } } @@ -266,12 +339,16 @@ static void write_config_reg(struct pinmux_info *gpioc, int index) { unsigned long ncomb, pos, value; + void __iomem *mapped_reg; ncomb = 1 << crp->field_width; pos = index / ncomb; value = index % ncomb; - gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value); + mapped_reg = pfc_phys_to_virt(gpioc, crp->reg); + + gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width, + pos, value, crp->reg); } static int check_config_reg(struct pinmux_info *gpioc, @@ -279,13 +356,16 @@ static int check_config_reg(struct pinmux_info *gpioc, int index) { unsigned long ncomb, pos, value; + void __iomem *mapped_reg; ncomb = 1 << crp->field_width; pos = index / ncomb; value = index % ncomb; - if (gpio_read_reg(crp->reg, crp->reg_width, - crp->field_width, pos) == value) + mapped_reg = pfc_phys_to_virt(gpioc, crp->reg); + + if (gpio_read_reg(mapped_reg, crp->reg_width, + crp->field_width, pos, crp->reg) == value) return 0; return -1; @@ -564,7 +644,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio) if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) return -EINVAL; - return gpio_read_reg(dr->reg, dr->reg_width, 1, bit); + return gpio_read_reg(dr->mapped_reg, dr->reg_width, 1, bit, dr->reg); } static int sh_gpio_get(struct gpio_chip *chip, unsigned offset) @@ -606,10 +686,15 @@ static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset) int register_pinmux(struct pinmux_info *pip) { struct gpio_chip *chip = &pip->chip; + int ret; pr_info("%s handling gpio %d -> %d\n", pip->name, pip->first_gpio, pip->last_gpio); + ret = pfc_ioremap(pip); + if (ret < 0) + return ret; + setup_data_regs(pip); chip->request = sh_gpio_request; @@ -627,12 +712,16 @@ int register_pinmux(struct pinmux_info *pip) chip->base = pip->first_gpio; chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1; - return gpiochip_add(chip); + ret = gpiochip_add(chip); + if (ret < 0) + pfc_iounmap(pip); + + return ret; } int unregister_pinmux(struct pinmux_info *pip) { pr_info("%s deregistering\n", pip->name); - + pfc_iounmap(pip); return gpiochip_remove(&pip->chip); } diff --git a/include/linux/sh_pfc.h b/include/linux/sh_pfc.h index 8446789216e..91666a58529 100644 --- a/include/linux/sh_pfc.h +++ b/include/linux/sh_pfc.h @@ -55,6 +55,7 @@ struct pinmux_cfg_reg { struct pinmux_data_reg { unsigned long reg, reg_width, reg_shadow; pinmux_enum_t *enum_ids; + void __iomem *mapped_reg; }; #define PINMUX_DATA_REG(name, r, r_width) \ @@ -75,6 +76,12 @@ struct pinmux_range { pinmux_enum_t force; }; +struct pfc_window { + phys_addr_t phys; + void __iomem *virt; + unsigned long size; +}; + struct pinmux_info { char *name; pinmux_enum_t reserved_id; @@ -98,6 +105,10 @@ struct pinmux_info { struct pinmux_irq *gpio_irq; unsigned int gpio_irq_size; + struct resource *resource; + unsigned int num_resources; + struct pfc_window *window; + struct gpio_chip chip; }; -- cgit v1.2.3 From 7784f4da1a1b8b2519e008551fc4f69713451f89 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Sun, 11 Dec 2011 19:02:09 -0800 Subject: sh: clkfwk: sh_clk_init_parent() should be called after clk_register() sh_clk_init_parent() are using clk->mapped_reg which is mapped in clk_register() Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/sh/clk/cpg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index a0d8faa40ba..45fee368b09 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c @@ -222,11 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr, clkp->ops = ops; clkp->freq_table = freq_table + (k * freq_table_size); clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; - ret = sh_clk_init_parent(clkp); + ret = clk_register(clkp); if (ret < 0) break; - ret = clk_register(clkp); + ret = sh_clk_init_parent(clkp); } return ret; -- cgit v1.2.3 From d3442b2bb7ce4089fadcf483b8ae9766ab480238 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 10 Jan 2012 16:04:11 +0100 Subject: sh: also without PM_RUNTIME pm_runtime.o must be built When CONFIG_PM_RUNTIME is off, drivers/sh/pm_runtime.o still has to be built on sh platforms, because then it provides means to statically switch on device PM clocks. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- drivers/sh/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index c393894ff35..7139ad2f208 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile @@ -7,4 +7,4 @@ obj-$(CONFIG_HAVE_CLK) += clk/ obj-$(CONFIG_MAPLE) += maple/ obj-$(CONFIG_SUPERHYWAY) += superhyway/ obj-$(CONFIG_GENERIC_GPIO) += pfc.o -obj-$(CONFIG_PM_RUNTIME) += pm_runtime.o +obj-y += pm_runtime.o -- cgit v1.2.3