From c601a51af10f714292f42eab45fa8c9154dc1414 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 3 Jul 2009 16:16:54 +0900 Subject: [PATCH 001/262] sh: Use bootmem ontop of lmb Rework the bootmem allocator to use the lmb framework. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/include/asm/lmb.h | 6 ++++ arch/sh/kernel/setup.c | 75 ++++++++++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 21 deletions(-) create mode 100644 arch/sh/include/asm/lmb.h diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index e2bdd7b94fd..0fb99b0eac5 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -10,6 +10,7 @@ config SUPERH select EMBEDDED select HAVE_CLK select HAVE_IDE + select HAVE_LMB select HAVE_OPROFILE select HAVE_GENERIC_DMA_COHERENT select HAVE_IOREMAP_PROT if MMU diff --git a/arch/sh/include/asm/lmb.h b/arch/sh/include/asm/lmb.h new file mode 100644 index 00000000000..9b437f657ff --- /dev/null +++ b/arch/sh/include/asm/lmb.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_LMB_H +#define __ASM_SH_LMB_H + +#define LMB_REAL_LIMIT 0 + +#endif /* __ASM_SH_LMB_H */ diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index dd38338553e..ceb409bf774 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -233,39 +234,45 @@ void __init __add_active_range(unsigned int nid, unsigned long start_pfn, void __init setup_bootmem_allocator(unsigned long free_pfn) { unsigned long bootmap_size; + unsigned long bootmap_pages, bootmem_paddr; + u64 total_pages = (lmb_end_of_DRAM() - __MEMORY_START) >> PAGE_SHIFT; + int i; + + bootmap_pages = bootmem_bootmap_pages(total_pages); + + bootmem_paddr = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); /* * Find a proper area for the bootmem bitmap. After this * bootstrap step all allocations (until the page allocator * is intact) must be done via bootmem_alloc(). */ - bootmap_size = init_bootmem_node(NODE_DATA(0), free_pfn, + bootmap_size = init_bootmem_node(NODE_DATA(0), + bootmem_paddr >> PAGE_SHIFT, min_low_pfn, max_low_pfn); - __add_active_range(0, min_low_pfn, max_low_pfn); + /* Add active regions with valid PFNs. */ + for (i = 0; i < lmb.memory.cnt; i++) { + unsigned long start_pfn, end_pfn; + start_pfn = lmb.memory.region[i].base >> PAGE_SHIFT; + end_pfn = start_pfn + lmb_size_pages(&lmb.memory, i); + __add_active_range(0, start_pfn, end_pfn); + } + + /* + * Add all physical memory to the bootmem map and mark each + * area as present. + */ register_bootmem_low_pages(); - node_set_online(0); - - /* - * Reserve the kernel text and - * Reserve the bootmem bitmap. We do this in two steps (first step - * was init_bootmem()), because this catches the (definitely buggy) - * case of us accidentally initializing the bootmem allocator with - * an invalid RAM area. - */ - reserve_bootmem(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, - (PFN_PHYS(free_pfn) + bootmap_size + PAGE_SIZE - 1) - - (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET), - BOOTMEM_DEFAULT); - - /* - * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. - */ - if (CONFIG_ZERO_PAGE_OFFSET != 0) - reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET, + /* Reserve the sections we're already using. */ + for (i = 0; i < lmb.reserved.cnt; i++) + reserve_bootmem(lmb.reserved.region[i].base, + lmb_size_bytes(&lmb.reserved, i), BOOTMEM_DEFAULT); + node_set_online(0); + sparse_memory_present_with_active_regions(0); #ifdef CONFIG_BLK_DEV_INITRD @@ -296,12 +303,37 @@ void __init setup_bootmem_allocator(unsigned long free_pfn) static void __init setup_memory(void) { unsigned long start_pfn; + u64 base = min_low_pfn << PAGE_SHIFT; + u64 size = (max_low_pfn << PAGE_SHIFT) - base; /* * Partially used pages are not usable - thus * we are rounding upwards: */ start_pfn = PFN_UP(__pa(_end)); + + lmb_add(base, size); + + /* + * Reserve the kernel text and + * Reserve the bootmem bitmap. We do this in two steps (first step + * was init_bootmem()), because this catches the (definitely buggy) + * case of us accidentally initializing the bootmem allocator with + * an invalid RAM area. + */ + lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, + (PFN_PHYS(start_pfn) + PAGE_SIZE - 1) - + (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); + + /* + * Reserve physical pages below CONFIG_ZERO_PAGE_OFFSET. + */ + if (CONFIG_ZERO_PAGE_OFFSET != 0) + lmb_reserve(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET); + + lmb_analyze(); + lmb_dump_all(); + setup_bootmem_allocator(start_pfn); } #else @@ -402,6 +434,7 @@ void __init setup_arch(char **cmdline_p) nodes_clear(node_online_map); /* Setup bootmem with available RAM */ + lmb_init(); setup_memory(); sparse_init(); From 79714acbab080ad351acf4bba9a2bbc21d65c93c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 3 Jul 2009 10:08:05 +0000 Subject: [PATCH 002/262] sh: hwblk base implementation This patch is the hwblk base implementation, containing structures and shared functions dealing with hardware blocks. A each processor model should provide a list of hwblks and describe which module stop bit that is associated with each hwblck and how the hwblks are grouped together into areas. The shared code keeps track of the usage count for each hwblk and the areas. Fallback implementations for processor specific code are also kept as weak symbols. The clock framework, the runtime pm code and cpuidle will all tie into this hwblk implementation. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/hwblk.h | 61 +++++++++++++++++ arch/sh/kernel/cpu/Makefile | 2 +- arch/sh/kernel/cpu/hwblk.c | 130 ++++++++++++++++++++++++++++++++++++ arch/sh/kernel/time.c | 2 + 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 arch/sh/include/asm/hwblk.h create mode 100644 arch/sh/kernel/cpu/hwblk.c diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h new file mode 100644 index 00000000000..51a46f49663 --- /dev/null +++ b/arch/sh/include/asm/hwblk.h @@ -0,0 +1,61 @@ +#ifndef __ASM_SH_HWBLK_H +#define __ASM_SH_HWBLK_H + +#include +#include + +#define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */ + +#define HWBLK_AREA(_flags, _parent) \ +{ \ + .flags = _flags, \ + .parent = _parent, \ +} + +struct hwblk_area { + unsigned long cnt; + unsigned char parent; + unsigned char flags; +}; + +#define HWBLK(_mstp, _bit, _area) \ +{ \ + .mstp = (void __iomem *)_mstp, \ + .bit = _bit, \ + .area = _area, \ +} + +struct hwblk { + void __iomem *mstp; + unsigned char bit; + unsigned char area; + unsigned long cnt; +}; + +struct hwblk_info { + struct hwblk_area *areas; + int nr_areas; + struct hwblk *hwblks; + int nr_hwblks; +}; + +/* Should be defined by processor-specific code */ +int arch_hwblk_init(void); +int arch_hwblk_sleep_mode(void); + +int hwblk_register(struct hwblk_info *info); +int hwblk_init(void); + +/* allow clocks to enable and disable hardware blocks */ +#define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \ +{ \ + .name = _name, \ + .id = _id, \ + .parent = _parent, \ + .arch_flags = _hwblk, \ + .flags = _flags, \ +} + +int sh_hwblk_clk_register(struct clk *clks, int nr); + +#endif /* __ASM_SH_HWBLK_H */ diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index eecad7cbd61..3d6b9312dc4 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -19,4 +19,4 @@ obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_SH_ADC) += adc.o obj-$(CONFIG_SH_CLK_CPG) += clock-cpg.o -obj-y += irq/ init.o clock.o +obj-y += irq/ init.o clock.o hwblk.o diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c new file mode 100644 index 00000000000..7c3a73deff2 --- /dev/null +++ b/arch/sh/kernel/cpu/hwblk.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_SPINLOCK(hwblk_lock); + +static void hwblk_area_inc(struct hwblk_info *info, int area) +{ + struct hwblk_area *hap = info->areas + area; + + hap->cnt++; + if (hap->cnt == 1) + if (hap->flags & HWBLK_AREA_FLAG_PARENT) + hwblk_area_inc(info, hap->parent); +} + +static void hwblk_area_dec(struct hwblk_info *info, int area) +{ + struct hwblk_area *hap = info->areas + area; + + if (hap->cnt == 1) + if (hap->flags & HWBLK_AREA_FLAG_PARENT) + hwblk_area_dec(info, hap->parent); + hap->cnt--; +} + +static void hwblk_enable(struct hwblk_info *info, int hwblk) +{ + struct hwblk *hp = info->hwblks + hwblk; + unsigned long tmp; + unsigned long flags; + + spin_lock_irqsave(&hwblk_lock, flags); + + hp->cnt++; + if (hp->cnt == 1) { + hwblk_area_inc(info, hp->area); + + tmp = __raw_readl(hp->mstp); + tmp &= ~(1 << hp->bit); + __raw_writel(tmp, hp->mstp); + } + + spin_unlock_irqrestore(&hwblk_lock, flags); +} + +static void hwblk_disable(struct hwblk_info *info, int hwblk) +{ + struct hwblk *hp = info->hwblks + hwblk; + unsigned long tmp; + unsigned long flags; + + spin_lock_irqsave(&hwblk_lock, flags); + + if (hp->cnt == 1) { + hwblk_area_dec(info, hp->area); + + tmp = __raw_readl(hp->mstp); + tmp |= 1 << hp->bit; + __raw_writel(tmp, hp->mstp); + } + hp->cnt--; + + spin_unlock_irqrestore(&hwblk_lock, flags); +} + +static struct hwblk_info *hwblk_info; + +int __init hwblk_register(struct hwblk_info *info) +{ + hwblk_info = info; + return 0; +} + +int __init __weak arch_hwblk_init(void) +{ + return 0; +} + +int __weak arch_hwblk_sleep_mode(void) +{ + return SUSP_SH_SLEEP; +} + +int __init hwblk_init(void) +{ + return arch_hwblk_init(); +} + +/* allow clocks to enable and disable hardware blocks */ +static int sh_hwblk_clk_enable(struct clk *clk) +{ + if (!hwblk_info) + return -ENOENT; + + hwblk_enable(hwblk_info, clk->arch_flags); + return 0; +} + +static void sh_hwblk_clk_disable(struct clk *clk) +{ + if (hwblk_info) + hwblk_disable(hwblk_info, clk->arch_flags); +} + +static struct clk_ops sh_hwblk_clk_ops = { + .enable = sh_hwblk_clk_enable, + .disable = sh_hwblk_clk_disable, + .recalc = followparent_recalc, +}; + +int __init sh_hwblk_clk_register(struct clk *clks, int nr) +{ + struct clk *clkp; + int ret = 0; + int k; + + for (k = 0; !ret && (k < nr); k++) { + clkp = clks + k; + clkp->ops = &sh_hwblk_clk_ops; + ret |= clk_register(clkp); + } + + return ret; +} diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 9b352a1e3fb..d2424b068b7 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -21,6 +21,7 @@ #include #include #include +#include #include /* Dummy RTC ops */ @@ -96,6 +97,7 @@ void __init time_init(void) if (board_time_init) board_time_init(); + hwblk_init(); clk_init(); rtc_sh_get_time(&xtime); From a61c1a636628a28ab5b42a9d36582a8f6a08893a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 3 Jul 2009 10:15:25 +0000 Subject: [PATCH 003/262] sh: hwblk for sh7722 This patch contains the sh7722 specific hwblk implementation. Hwblk ids are added to the processor specific header file, module stop bits and areas are kept track of as hwblks, clocks are converted to make use of the shared hwblk code. Code to determine allowed sleep modes is also added. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/cpu-sh4/cpu/sh7722.h | 14 ++++ arch/sh/kernel/cpu/sh4a/Makefile | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 56 +++++++------ arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c | 106 +++++++++++++++++++++++++ 4 files changed, 151 insertions(+), 27 deletions(-) create mode 100644 arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c diff --git a/arch/sh/include/cpu-sh4/cpu/sh7722.h b/arch/sh/include/cpu-sh4/cpu/sh7722.h index 738ea43c503..48560407cbe 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7722.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7722.h @@ -221,4 +221,18 @@ enum { GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5, }; +enum { + HWBLK_UNKNOWN = 0, + HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_URAM, HWBLK_XYMEM, + HWBLK_INTC, HWBLK_DMAC, HWBLK_SHYWAY, HWBLK_HUDI, + HWBLK_UBC, HWBLK_TMU, HWBLK_CMT, HWBLK_RWDT, HWBLK_FLCTL, + HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SIO, + HWBLK_SIOF0, HWBLK_SIOF1, HWBLK_IIC, HWBLK_RTC, + HWBLK_TPU, HWBLK_IRDA, HWBLK_SDHI, HWBLK_SIM, HWBLK_KEYSC, + HWBLK_TSIF, HWBLK_USBF, HWBLK_2DG, HWBLK_SIU, HWBLK_VOU, + HWBLK_JPU, HWBLK_BEU, HWBLK_CEU, HWBLK_VEU, HWBLK_VPU, + HWBLK_LCDC, + HWBLK_NR, +}; + #endif /* __ASM_SH7722_H__ */ diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index ebdd391d5f4..3cafda69637 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -25,7 +25,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 +clock-$(CONFIG_CPU_SUBTYPE_SH7722) := clock-sh7722.o hwblk-sh7722.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 diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 40f859354f7..1fa9e1dd1cc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include /* SH7722 registers */ #define FRQCR 0xa4150000 @@ -140,35 +142,37 @@ struct clk div6_clks[] = { SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; -#define MSTP(_str, _parent, _reg, _bit, _flags) \ - SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _flags) +#define R_CLK &r_clk +#define P_CLK &div4_clks[DIV4_P] +#define B_CLK &div4_clks[DIV4_B] +#define U_CLK &div4_clks[DIV4_U] static struct clk mstp_clks[] = { - MSTP("uram0", &div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT), - MSTP("xymem0", &div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT), - MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0), - MSTP("cmt0", &r_clk, MSTPCR0, 14, 0), - MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0), - MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0), - MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 7, 0), - MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 6, 0), - MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 5, 0), + SH_HWBLK_CLK("uram0", -1, U_CLK, HWBLK_URAM, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("xymem0", -1, B_CLK, HWBLK_XYMEM, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU, 0), + SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), + SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), + SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), + SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0), - MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0), - MSTP("rtc0", &r_clk, MSTPCR1, 8, 0), + SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0), + SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), - MSTP("sdhi0", &div4_clks[DIV4_P], MSTPCR2, 18, 0), - MSTP("keysc0", &r_clk, MSTPCR2, 14, 0), - MSTP("usbf0", &div4_clks[DIV4_P], MSTPCR2, 11, 0), - MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 9, 0), - MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0), - MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0), - MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, CLK_ENABLE_ON_INIT), - MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0), - MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0), - MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, CLK_ENABLE_ON_INIT), - MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, CLK_ENABLE_ON_INIT), - MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0), + SH_HWBLK_CLK("sdhi0", -1, P_CLK, HWBLK_SDHI, 0), + SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0), + SH_HWBLK_CLK("usbf0", -1, P_CLK, HWBLK_USBF, 0), + SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0), + SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0), + SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0), + SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0), + SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0), + SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("lcdc0", -1, P_CLK, HWBLK_LCDC, 0), }; int __init arch_clk_init(void) @@ -191,7 +195,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks)); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c new file mode 100644 index 00000000000..00a1c02d82b --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c @@ -0,0 +1,106 @@ +/* + * 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) + return SUSP_SH_STANDBY | SUSP_SH_SF; + + if (!sh7722_hwblk_area[CORE_AREA_BM].cnt) + return SUSP_SH_SLEEP | SUSP_SH_SF; + + return SUSP_SH_SLEEP; +} + +int __init arch_hwblk_init(void) +{ + return hwblk_register(&sh7722_hwblk_info); +} From 7426394f20c2e74b7c560bcd266cec1b327a269b Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 3 Jul 2009 10:28:00 +0000 Subject: [PATCH 004/262] sh: cpuidle for SuperH Mobile using hwblk This patch adds cpuidle support for SuperH Mobile. The sleep mode selected by cpuidle is compared with the mode selected by the hwblk sleep code and the best allowed mode is entered. At this point "Sleep mode" and "Sleep mode + SF" are supported. This code can easily be extended to support "Software suspend mode", but the assembly code must first be updated to avoid loosing interrupts. Also, update the code to only copy the assembly snippet into internal memory once at bootup. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/suspend.h | 9 +++ arch/sh/kernel/cpu/shmobile/Makefile | 1 + arch/sh/kernel/cpu/shmobile/cpuidle.c | 102 ++++++++++++++++++++++++++ arch/sh/kernel/cpu/shmobile/pm.c | 26 +++---- 4 files changed, 125 insertions(+), 13 deletions(-) create mode 100644 arch/sh/kernel/cpu/shmobile/cpuidle.c diff --git a/arch/sh/include/asm/suspend.h b/arch/sh/include/asm/suspend.h index b1b995370e7..5c8ea28ff7a 100644 --- a/arch/sh/include/asm/suspend.h +++ b/arch/sh/include/asm/suspend.h @@ -10,6 +10,15 @@ struct swsusp_arch_regs { struct pt_regs user_regs; unsigned long bank1_regs[8]; }; + +void sh_mobile_call_standby(unsigned long mode); + +#ifdef CONFIG_CPU_IDLE +void sh_mobile_setup_cpuidle(void); +#else +static inline void sh_mobile_setup_cpuidle(void) {} +#endif + #endif /* flags passed to assembly suspend code */ diff --git a/arch/sh/kernel/cpu/shmobile/Makefile b/arch/sh/kernel/cpu/shmobile/Makefile index 08bfa7c7db2..e8a5111e848 100644 --- a/arch/sh/kernel/cpu/shmobile/Makefile +++ b/arch/sh/kernel/cpu/shmobile/Makefile @@ -4,3 +4,4 @@ # Power Management & Sleep mode obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c new file mode 100644 index 00000000000..4afdd975cc6 --- /dev/null +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c @@ -0,0 +1,102 @@ +/* + * arch/sh/kernel/cpu/shmobile/cpuidle.c + * + * Cpuidle 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 +#include + +static unsigned long cpuidle_mode[] = { + SUSP_SH_SLEEP, /* regular sleep mode */ + SUSP_SH_SLEEP | SUSP_SH_SF, /* sleep mode + self refresh */ +}; + +static int cpuidle_sleep_enter(struct cpuidle_device *dev, + struct cpuidle_state *state) +{ + unsigned long allowed_mode = arch_hwblk_sleep_mode(); + ktime_t before, after; + int requested_state = state - &dev->states[0]; + int allowed_state; + int k; + + /* convert allowed mode to allowed state */ + for (k = ARRAY_SIZE(cpuidle_mode) - 1; k > 0; k--) + if (cpuidle_mode[k] == allowed_mode) + break; + + allowed_state = k; + + /* take the following into account for sleep mode selection: + * - allowed_state: best mode allowed by hardware (clock deps) + * - requested_state: best mode allowed by software (latencies) + */ + k = min_t(int, allowed_state, requested_state); + + dev->last_state = &dev->states[k]; + before = ktime_get(); + sh_mobile_call_standby(cpuidle_mode[k]); + after = ktime_get(); + return ktime_to_ns(ktime_sub(after, before)) >> 10; +} + +static struct cpuidle_device cpuidle_dev; +static struct cpuidle_driver cpuidle_driver = { + .name = "sh_idle", + .owner = THIS_MODULE, +}; + +void sh_mobile_setup_cpuidle(void) +{ + struct cpuidle_device *dev = &cpuidle_dev; + struct cpuidle_state *state; + int i; + + cpuidle_register_driver(&cpuidle_driver); + + for (i = 0; i < CPUIDLE_STATE_MAX; i++) { + dev->states[i].name[0] = '\0'; + dev->states[i].desc[0] = '\0'; + } + + i = CPUIDLE_DRIVER_STATE_START; + + state = &dev->states[i++]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C0"); + strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN); + state->exit_latency = 1; + state->target_residency = 1 * 2; + state->power_usage = 3; + state->flags = 0; + state->flags |= CPUIDLE_FLAG_SHALLOW; + state->flags |= CPUIDLE_FLAG_TIME_VALID; + state->enter = cpuidle_sleep_enter; + + dev->safe_state = state; + + state = &dev->states[i++]; + snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); + strncpy(state->desc, "SuperH Sleep Mode [SF]", CPUIDLE_DESC_LEN); + state->exit_latency = 100; + state->target_residency = 1 * 2; + state->power_usage = 1; + state->flags = 0; + state->flags |= CPUIDLE_FLAG_TIME_VALID; + state->enter = cpuidle_sleep_enter; + + dev->state_count = i; + + cpuidle_register_device(dev); +} diff --git a/arch/sh/kernel/cpu/shmobile/pm.c b/arch/sh/kernel/cpu/shmobile/pm.c index 8c067adf683..de078d24ce5 100644 --- a/arch/sh/kernel/cpu/shmobile/pm.c +++ b/arch/sh/kernel/cpu/shmobile/pm.c @@ -1,5 +1,5 @@ /* - * arch/sh/kernel/cpu/sh4a/pm-sh_mobile.c + * arch/sh/kernel/cpu/shmobile/pm.c * * Power management support code for SuperH Mobile * @@ -32,20 +32,17 @@ * * R-standby mode is unsupported, but will be added in the future * U-standby mode is low priority since it needs bootloader hacks - * - * All modes should be tied in with cpuidle. But before that can - * happen we need to keep track of enabled hardware blocks so we - * can avoid entering sleep modes that stop clocks to hardware - * blocks that are in use even though the cpu core is idle. */ +#define ILRAM_BASE 0xe5200000 + extern const unsigned char sh_mobile_standby[]; extern const unsigned int sh_mobile_standby_size; -static void sh_mobile_call_standby(unsigned long mode) +void sh_mobile_call_standby(unsigned long mode) { extern void *vbr_base; - void *onchip_mem = (void *)0xe5200000; /* ILRAM */ + void *onchip_mem = (void *)ILRAM_BASE; void (*standby_onchip_mem)(unsigned long) = onchip_mem; /* Note: Wake up from sleep may generate exceptions! @@ -55,11 +52,6 @@ static void sh_mobile_call_standby(unsigned long mode) if (mode & SUSP_SH_SF) asm volatile("ldc %0, vbr" : : "r" (onchip_mem) : "memory"); - /* Copy the assembly snippet to the otherwise ununsed ILRAM */ - memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size); - wmb(); - ctrl_barrier(); - /* Let assembly snippet in on-chip memory handle the rest */ standby_onchip_mem(mode); @@ -85,7 +77,15 @@ static struct platform_suspend_ops sh_pm_ops = { static int __init sh_pm_init(void) { + void *onchip_mem = (void *)ILRAM_BASE; + + /* Copy the assembly snippet to the otherwise ununsed ILRAM */ + memcpy(onchip_mem, sh_mobile_standby, sh_mobile_standby_size); + wmb(); + ctrl_barrier(); + suspend_set_ops(&sh_pm_ops); + sh_mobile_setup_cpuidle(); return 0; } From 5084f61a4d6c9c7bfd3be07fbb5253c1a08cd568 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 3 Jul 2009 23:34:51 +0100 Subject: [PATCH 005/262] sh: Use bootmem ontop of lmb for NUMA Like the UP case, use lmb as the foundation of memory resource management on NUMA. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/mm/numa.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c index 095d93bec7c..9b784fdb947 100644 --- a/arch/sh/mm/numa.c +++ b/arch/sh/mm/numa.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -26,6 +27,15 @@ EXPORT_SYMBOL_GPL(node_data); void __init setup_memory(void) { unsigned long free_pfn = PFN_UP(__pa(_end)); + u64 base = min_low_pfn << PAGE_SHIFT; + u64 size = (max_low_pfn << PAGE_SHIFT) - min_low_pfn; + + lmb_add(base, size); + + /* Reserve the LMB regions used by the kernel, initrd, etc.. */ + lmb_reserve(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET, + (PFN_PHYS(free_pfn) + PAGE_SIZE - 1) - + (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET)); /* * Node 0 sets up its pgdat at the first available pfn, @@ -45,24 +55,23 @@ void __init setup_memory(void) void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end) { - unsigned long bootmap_pages, bootmap_start, bootmap_size; - unsigned long start_pfn, free_pfn, end_pfn; + unsigned long bootmap_pages; + unsigned long start_pfn, end_pfn; + unsigned long bootmem_paddr; /* Don't allow bogus node assignment */ BUG_ON(nid > MAX_NUMNODES || nid == 0); - /* - * The free pfn starts at the beginning of the range, and is - * advanced as necessary for pgdat and node map allocations. - */ - free_pfn = start_pfn = start >> PAGE_SHIFT; + start_pfn = start >> PAGE_SHIFT; end_pfn = end >> PAGE_SHIFT; + lmb_add(start, end - start); + __add_active_range(nid, start_pfn, end_pfn); /* Node-local pgdat */ - NODE_DATA(nid) = pfn_to_kaddr(free_pfn); - free_pfn += PFN_UP(sizeof(struct pglist_data)); + NODE_DATA(nid) = __va(lmb_alloc_base(sizeof(struct pglist_data), + SMP_CACHE_BYTES, end_pfn)); memset(NODE_DATA(nid), 0, sizeof(struct pglist_data)); NODE_DATA(nid)->bdata = &bootmem_node_data[nid]; @@ -71,16 +80,17 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end) /* Node-local bootmap */ bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn); - bootmap_start = (unsigned long)pfn_to_kaddr(free_pfn); - bootmap_size = init_bootmem_node(NODE_DATA(nid), free_pfn, start_pfn, - end_pfn); + bootmem_paddr = lmb_alloc_base(bootmap_pages << PAGE_SHIFT, + PAGE_SIZE, end_pfn); + init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT, + start_pfn, end_pfn); free_bootmem_with_active_regions(nid, end_pfn); /* Reserve the pgdat and bootmap space with the bootmem allocator */ reserve_bootmem_node(NODE_DATA(nid), start_pfn << PAGE_SHIFT, sizeof(struct pglist_data), BOOTMEM_DEFAULT); - reserve_bootmem_node(NODE_DATA(nid), free_pfn << PAGE_SHIFT, + reserve_bootmem_node(NODE_DATA(nid), bootmem_paddr, bootmap_pages << PAGE_SHIFT, BOOTMEM_DEFAULT); /* It's up */ From 4048e5ca29afbd747a16245f2bc4d1d521a6d0d0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 26 Jun 2009 06:59:17 +0000 Subject: [PATCH 006/262] usb: m66592-udc buffer management update This patch updates the m66592-udc buffer management code. Use fixed buffers for bulk and isochronous pipes, also make sure to handle the isochronous-as-bulk case. With fixed buffers there is no need to keep track of used buffers with bi_bufnum. Also, this fixes a potential buffer offset problem where the base offset incorrectly varies with the number of pipes used. With this patch applied it is possible to use m66592-udc for both Ethernet and Serial using CONFIG_USB_CDC_COMPOSITE. Signed-off-by: Magnus Damm Acked-by: Yoshihiro Shimoda Acked-by: Greg Kroah-Hartman Signed-off-by: Paul Mundt --- drivers/usb/gadget/m66592-udc.c | 34 ++++++++++++--------------------- drivers/usb/gadget/m66592-udc.h | 1 - 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 43dcf9e1af6..0dddd2f8ff3 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -37,7 +37,7 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yoshihiro Shimoda"); MODULE_ALIAS("platform:m66592_udc"); -#define DRIVER_VERSION "18 Oct 2007" +#define DRIVER_VERSION "26 Jun 2009" /* module parameters */ #if defined(CONFIG_SUPERH_BUILT_IN_M66592) @@ -276,24 +276,27 @@ static int pipe_buffer_setting(struct m66592 *m66592, buf_bsize = 0; break; case M66592_BULK: - bufnum = m66592->bi_bufnum + - (info->pipe - M66592_BASE_PIPENUM_BULK) * 16; - m66592->bi_bufnum += 16; + /* isochronous pipes may be used as bulk pipes */ + if (info->pipe > M66592_BASE_PIPENUM_BULK) + bufnum = info->pipe - M66592_BASE_PIPENUM_BULK; + else + bufnum = info->pipe - M66592_BASE_PIPENUM_ISOC; + + bufnum = M66592_BASE_BUFNUM + (bufnum * 16); buf_bsize = 7; pipecfg |= M66592_DBLB; if (!info->dir_in) pipecfg |= M66592_SHTNAK; break; case M66592_ISO: - bufnum = m66592->bi_bufnum + + bufnum = M66592_BASE_BUFNUM + (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16; - m66592->bi_bufnum += 16; buf_bsize = 7; break; } - if (m66592->bi_bufnum > M66592_MAX_BUFNUM) { - pr_err("m66592 pipe memory is insufficient(%d)\n", - m66592->bi_bufnum); + + if (buf_bsize && ((bufnum + 16) >= M66592_MAX_BUFNUM)) { + pr_err("m66592 pipe memory is insufficient\n"); return -ENOMEM; } @@ -313,17 +316,6 @@ static void pipe_buffer_release(struct m66592 *m66592, if (info->pipe == 0) return; - switch (info->type) { - case M66592_BULK: - if (is_bulk_pipe(info->pipe)) - m66592->bi_bufnum -= 16; - break; - case M66592_ISO: - if (is_isoc_pipe(info->pipe)) - m66592->bi_bufnum -= 16; - break; - } - if (is_bulk_pipe(info->pipe)) { m66592->bulk--; } else if (is_interrupt_pipe(info->pipe)) @@ -1603,8 +1595,6 @@ static int __init m66592_probe(struct platform_device *pdev) m66592->timer.data = (unsigned long)m66592; m66592->reg = reg; - m66592->bi_bufnum = M66592_BASE_BUFNUM; - ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED, udc_name, m66592); if (ret < 0) { diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h index 286ce07e796..9a9c2bf9fbd 100644 --- a/drivers/usb/gadget/m66592-udc.h +++ b/drivers/usb/gadget/m66592-udc.h @@ -506,7 +506,6 @@ struct m66592 { int interrupt; int isochronous; int num_dma; - int bi_bufnum; /* bulk and isochronous's bufnum */ }; #define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget) From c63c3105e4991b2991ba73a742b8b59bfdbe4acd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sun, 5 Jul 2009 02:50:10 +0900 Subject: [PATCH 007/262] sh: use kprobes_built_in() for notify_page_fault(). Kill off the KPROBES ifdef, as per x86. Signed-off-by: Paul Mundt --- arch/sh/mm/fault_32.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 71925946f1e..ce75b8882ef 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -25,14 +25,12 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap) { int ret = 0; -#ifdef CONFIG_KPROBES - if (!user_mode(regs)) { + if (kprobes_built_in() && !user_mode(regs)) { preempt_disable(); if (kprobe_running() && kprobe_fault_handler(regs, trap)) ret = 1; preempt_enable(); } -#endif return ret; } From 0f60bb25b4036d30fd795709be09626c58c52464 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sun, 5 Jul 2009 03:18:47 +0900 Subject: [PATCH 008/262] sh: Tidy up vmalloc fault handling. This rewrites the vmalloc fault handling as per x86, which subsequently allows for easy future tie-in for vmalloc_sync_all(). Signed-off-by: Paul Mundt --- arch/sh/mm/fault_32.c | 153 ++++++++++++++++++++++++++---------------- 1 file changed, 97 insertions(+), 56 deletions(-) diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index ce75b8882ef..08d0117d90f 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -2,7 +2,7 @@ * Page fault handler for SH with an MMU. * * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2003 - 2008 Paul Mundt + * Copyright (C) 2003 - 2009 Paul Mundt * * Based on linux/arch/i386/mm/fault.c: * Copyright (C) 1995 Linus Torvalds @@ -35,6 +35,74 @@ static inline int notify_page_fault(struct pt_regs *regs, int trap) return ret; } +static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) +{ + unsigned index = pgd_index(address); + pgd_t *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + pgd += index; + pgd_k = init_mm.pgd + index; + + if (!pgd_present(*pgd_k)) + return NULL; + + pud = pud_offset(pgd, address); + pud_k = pud_offset(pgd_k, address); + if (!pud_present(*pud_k)) + return NULL; + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (!pmd_present(*pmd_k)) + return NULL; + + if (!pmd_present(*pmd)) + set_pmd(pmd, *pmd_k); + else + BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); + + return pmd_k; +} + +/* + * Handle a fault on the vmalloc or module mapping area + */ +static noinline int vmalloc_fault(unsigned long address) +{ + pgd_t *pgd_k; + pmd_t *pmd_k; + pte_t *pte_k; + + /* Make sure we are in vmalloc area: */ + if (!(address >= VMALLOC_START && address < VMALLOC_END)) + return -1; + + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "current" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + pgd_k = get_TTB(); + pmd_k = vmalloc_sync_one(__va((unsigned long)pgd_k), address); + if (!pmd_k) + return -1; + + pte_k = pte_offset_kernel(pmd_k, address); + if (!pte_present(*pte_k)) + return -1; + + return 0; +} + +static int fault_in_kernel_space(unsigned long address) +{ + return address >= TASK_SIZE; +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -44,6 +112,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writeaccess, unsigned long address) { + unsigned long vec; struct task_struct *tsk; struct mm_struct *mm; struct vm_area_struct * vma; @@ -51,59 +120,30 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, int fault; siginfo_t info; - /* - * We don't bother with any notifier callbacks here, as they are - * all handled through the __do_page_fault() fast-path. - */ - tsk = current; + mm = tsk->mm; si_code = SEGV_MAPERR; + vec = lookup_exception_vector(); - if (unlikely(address >= TASK_SIZE)) { - /* - * Synchronize this task's top level page-table - * with the 'reference' page table. - * - * Do _not_ use "tsk" here. We might be inside - * an interrupt in the middle of a task switch.. - */ - int offset = pgd_index(address); - pgd_t *pgd, *pgd_k; - pud_t *pud, *pud_k; - pmd_t *pmd, *pmd_k; - - pgd = get_TTB() + offset; - pgd_k = swapper_pg_dir + offset; - - if (!pgd_present(*pgd)) { - if (!pgd_present(*pgd_k)) - goto bad_area_nosemaphore; - set_pgd(pgd, *pgd_k); + /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + */ + if (unlikely(fault_in_kernel_space(address))) { + if (vmalloc_fault(address) >= 0) return; - } - - pud = pud_offset(pgd, address); - pud_k = pud_offset(pgd_k, address); - - if (!pud_present(*pud)) { - if (!pud_present(*pud_k)) - goto bad_area_nosemaphore; - set_pud(pud, *pud_k); + if (notify_page_fault(regs, vec)) return; - } - pmd = pmd_offset(pud, address); - pmd_k = pmd_offset(pud_k, address); - if (pmd_present(*pmd) || !pmd_present(*pmd_k)) - goto bad_area_nosemaphore; - set_pmd(pmd, *pmd_k); - - return; + goto bad_area_nosemaphore; } - mm = tsk->mm; - - if (unlikely(notify_page_fault(regs, lookup_exception_vector()))) + if (unlikely(notify_page_fault(regs, vec))) return; /* Only enable interrupts if they were on before the fault */ @@ -113,8 +153,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); /* - * If we're in an interrupt or have no user - * context, we must not take the fault.. + * If we're in an interrupt, have no user context or are running + * in an atomic region then we must not take the fault: */ if (in_atomic() || !mm) goto no_context; @@ -130,10 +170,11 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, goto bad_area; if (expand_stack(vma, address)) goto bad_area; -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ + + /* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ good_area: si_code = SEGV_ACCERR; if (writeaccess) { @@ -171,10 +212,10 @@ survive: up_read(&mm->mmap_sem); return; -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ + /* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ bad_area: up_read(&mm->mmap_sem); From ca0d17277fd101ce4878f92b398b6ab71fb2c287 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sun, 28 Jun 2009 12:53:07 +0100 Subject: [PATCH 009/262] sh: Fix the value of MCOUNT_INSN_OFFSET It seems that MCOUNT_INSN_OFFSET was calculating the distance between the wrong functions. The value that should have actually been computed is the distance between ftrace_call and ftrace_stub. I discovered this when I added some code to ftrace_caller. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/include/asm/ftrace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h index 8fea7d8c825..b09311ad1db 100644 --- a/arch/sh/include/asm/ftrace.h +++ b/arch/sh/include/asm/ftrace.h @@ -11,10 +11,10 @@ extern void mcount(void); #define MCOUNT_ADDR ((long)(mcount)) #ifdef CONFIG_DYNAMIC_FTRACE -#define CALLER_ADDR ((long)(ftrace_caller)) +#define CALL_ADDR ((long)(ftrace_call)) #define STUB_ADDR ((long)(ftrace_stub)) -#define MCOUNT_INSN_OFFSET ((STUB_ADDR - CALLER_ADDR) >> 1) +#define MCOUNT_INSN_OFFSET ((STUB_ADDR - CALL_ADDR) - 4) struct dyn_arch_ftrace { /* No extra data needed on sh */ From c1340c053be7a43d837a3acb352d5008be865a55 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sun, 28 Jun 2009 14:05:44 +0100 Subject: [PATCH 010/262] sh: Define HAVE_FUNCTION_TRACE_MCOUNT_TEST Enable HAVE_FUNCTION_TRACE_MCOUNT_TEST and test the value of function_trace_stop from our assembly code as opposed to using the generic C function. This should optimise our mcount/ftrace code path. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/lib/mcount.S | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index e2bdd7b94fd..801a4a79ffe 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -31,6 +31,7 @@ config SUPERH32 select HAVE_FUNCTION_TRACER select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE + select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_ARCH_KGDB select ARCH_HIBERNATION_POSSIBLE if MMU diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 110fbfe1831..cb87ef580b3 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -2,7 +2,7 @@ * arch/sh/lib/mcount.S * * Copyright (C) 2008 Paul Mundt - * Copyright (C) 2008 Matt Fleming + * Copyright (C) 2008, 2009 Matt Fleming * * 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 @@ -35,6 +35,12 @@ .type mcount,@function _mcount: mcount: +#ifndef CONFIG_DYNAMIC_FTRACE + mov.l .Lfunction_trace_stop, r0 + mov.l @r0, r0 + tst r0, r0 + bf ftrace_stub +#endif MCOUNT_ENTER() #ifdef CONFIG_DYNAMIC_FTRACE @@ -62,6 +68,11 @@ skip_trace: #ifdef CONFIG_DYNAMIC_FTRACE .globl ftrace_caller ftrace_caller: + mov.l .Lfunction_trace_stop, r0 + mov.l @r0, r0 + tst r0, r0 + bf ftrace_stub + MCOUNT_ENTER() .globl ftrace_call @@ -88,3 +99,7 @@ ftrace_call: ftrace_stub: rts nop + + .align 2 +.Lfunction_trace_stop: + .long function_trace_stop From c652d780c9cf7f860141de232b37160fe013feca Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Mon, 6 Jul 2009 20:16:33 +0900 Subject: [PATCH 011/262] sh: Add ftrace syscall tracing support Now that I've added TIF_SYSCALL_FTRACE the thread flags do not fit into a single byte any more. Code testing them now needs to be aware of the upper and lower bytes. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/include/asm/syscall_32.h | 1 + arch/sh/include/asm/thread_info.h | 11 +++-- arch/sh/kernel/Makefile_32 | 1 + arch/sh/kernel/entry-common.S | 18 +++++--- arch/sh/kernel/ftrace.c | 68 +++++++++++++++++++++++++++++++ arch/sh/kernel/ptrace_32.c | 8 ++++ arch/sh/lib/mcount.S | 2 +- 8 files changed, 100 insertions(+), 10 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 801a4a79ffe..29e41ec6537 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -32,6 +32,7 @@ config SUPERH32 select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACE_MCOUNT_TEST + select HAVE_FTRACE_SYSCALLS select HAVE_ARCH_KGDB select ARCH_HIBERNATION_POSSIBLE if MMU diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h index 6f83f2cc45c..7d80df4f09c 100644 --- a/arch/sh/include/asm/syscall_32.h +++ b/arch/sh/include/asm/syscall_32.h @@ -65,6 +65,7 @@ static inline void syscall_get_arguments(struct task_struct *task, case 3: args[2] = regs->regs[6]; case 2: args[1] = regs->regs[5]; case 1: args[0] = regs->regs[4]; + case 0: break; default: BUG(); diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h index f09ac480629..499e315f4be 100644 --- a/arch/sh/include/asm/thread_info.h +++ b/arch/sh/include/asm/thread_info.h @@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void) extern struct thread_info *alloc_thread_info(struct task_struct *tsk); extern void free_thread_info(struct thread_info *ti); - + #endif /* THREAD_SHIFT < PAGE_SHIFT */ #endif /* __ASSEMBLY__ */ @@ -116,6 +116,7 @@ extern void free_thread_info(struct thread_info *ti); #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ #define TIF_SECCOMP 6 /* secure computing */ #define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ +#define TIF_SYSCALL_FTRACE 8 /* for ftrace syscall instrumentation */ #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 18 @@ -129,25 +130,27 @@ extern void free_thread_info(struct thread_info *ti); #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) #define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) +#define _TIF_SYSCALL_FTRACE (1 << TIF_SYSCALL_FTRACE) #define _TIF_USEDFPU (1 << TIF_USEDFPU) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_FREEZE (1 << TIF_FREEZE) /* - * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we + * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or we * blow the tst immediate size constraints and need to fix up * arch/sh/kernel/entry-common.S. */ /* work to do in syscall trace */ #define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \ - _TIF_SYSCALL_AUDIT | _TIF_SECCOMP) + _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ + _TIF_SYSCALL_FTRACE) /* work to do on any return to u-space */ #define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ _TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \ - _TIF_NOTIFY_RESUME) + _TIF_NOTIFY_RESUME | _TIF_SYSCALL_FTRACE) /* work to do on interrupt/exception return */ #define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 9411e3e31e6..fee924a9c46 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -29,6 +29,7 @@ obj-$(CONFIG_IO_TRAPPED) += io_trapped.o obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o +obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o obj-$(CONFIG_HIBERNATION) += swsusp.o diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index d62359cfbbe..d62175650c5 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -131,7 +131,7 @@ ENTRY(resume_userspace) nop #endif mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 + tst #(_TIF_WORK_MASK & 0xff), r0 bt/s __restore_all tst #_TIF_NEED_RESCHED, r0 @@ -163,7 +163,7 @@ work_resched: #endif ! mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_WORK_MASK, r0 + tst #(_TIF_WORK_MASK & 0xff), r0 bt __restore_all bra work_pending tst #_TIF_NEED_RESCHED, r0 @@ -181,7 +181,7 @@ work_resched: syscall_exit_work: ! r0: current_thread_info->flags ! r8: current_thread_info - tst #_TIF_WORK_SYSCALL_MASK, r0 + tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0 bt/s work_pending tst #_TIF_NEED_RESCHED, r0 #ifdef CONFIG_TRACE_IRQFLAGS @@ -331,8 +331,12 @@ ENTRY(system_call) ! get_current_thread_info r8, r10 mov.l @(TI_FLAGS,r8), r8 - mov #_TIF_WORK_SYSCALL_MASK, r10 + mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10 + mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9 tst r10, r8 + shll8 r9 + bf syscall_trace_entry + tst r9, r8 bf syscall_trace_entry ! mov.l 2f, r8 ! Number of syscalls @@ -359,7 +363,11 @@ syscall_exit: ! get_current_thread_info r8, r0 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags - tst #_TIF_ALLWORK_MASK, r0 + tst #(_TIF_ALLWORK_MASK & 0xff), r0 + mov #(_TIF_ALLWORK_MASK >> 8), r1 + bf syscall_exit_work + shlr8 r0 + tst r0, r1 bf syscall_exit_work bra __restore_all nop diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c index 066f37dc32a..4f62eced0ae 100644 --- a/arch/sh/kernel/ftrace.c +++ b/arch/sh/kernel/ftrace.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; @@ -131,3 +133,69 @@ int __init ftrace_dyn_arch_init(void *data) return 0; } + +#ifdef CONFIG_FTRACE_SYSCALLS + +extern unsigned long __start_syscalls_metadata[]; +extern unsigned long __stop_syscalls_metadata[]; +extern unsigned long *sys_call_table; + +static struct syscall_metadata **syscalls_metadata; + +static struct syscall_metadata *find_syscall_meta(unsigned long *syscall) +{ + struct syscall_metadata *start; + struct syscall_metadata *stop; + char str[KSYM_SYMBOL_LEN]; + + + start = (struct syscall_metadata *)__start_syscalls_metadata; + stop = (struct syscall_metadata *)__stop_syscalls_metadata; + kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str); + + for ( ; start < stop; start++) { + if (start->name && !strcmp(start->name, str)) + return start; + } + + return NULL; +} + +#define FTRACE_SYSCALL_MAX (NR_syscalls - 1) + +struct syscall_metadata *syscall_nr_to_meta(int nr) +{ + if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0) + return NULL; + + return syscalls_metadata[nr]; +} + +void arch_init_ftrace_syscalls(void) +{ + int i; + struct syscall_metadata *meta; + unsigned long **psys_syscall_table = &sys_call_table; + static atomic_t refs; + + if (atomic_inc_return(&refs) != 1) + goto end; + + syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * + FTRACE_SYSCALL_MAX, GFP_KERNEL); + if (!syscalls_metadata) { + WARN_ON(1); + return; + } + + for (i = 0; i < FTRACE_SYSCALL_MAX; i++) { + meta = find_syscall_meta(psys_syscall_table[i]); + syscalls_metadata[i] = meta; + } + return; + + /* Paranoid: avoid overflow */ +end: + atomic_dec(&refs); +} +#endif /* CONFIG_FTRACE_SYSCALLS */ diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index 3392e835a37..c198eceaee9 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -34,6 +34,8 @@ #include #include +#include + /* * This routine will get a word off of the process kernel stack. */ @@ -459,6 +461,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) */ ret = -1L; + if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) + ftrace_syscall_enter(regs); + if (unlikely(current->audit_context)) audit_syscall_entry(audit_arch(), regs->regs[3], regs->regs[4], regs->regs[5], @@ -475,6 +480,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), regs->regs[0]); + if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) + ftrace_syscall_exit(regs); + step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index cb87ef580b3..71e87f9b4fd 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -72,7 +72,7 @@ ftrace_caller: mov.l @r0, r0 tst r0, r0 bf ftrace_stub - + MCOUNT_ENTER() .globl ftrace_call From 727dc3fde82969609e1e69f1f12de83c2fe41238 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 7 Jul 2009 10:30:02 +0900 Subject: [PATCH 012/262] video: sh_mobile_lcdcfb: depends on HAVE_CLK. This deifdefs the driver and adds an explicit HAVE_CLK dependency. Given that all SH platforms provide it, there is no reason to keep this as an ifdef. Other architectures that implement support for this driver will already have to provide clock framework support for timers and so on already, so adding this as an additional dependency is not terribly probematic. Signed-off-by: Paul Mundt --- drivers/video/Kconfig | 2 +- drivers/video/sh_mobile_lcdcfb.c | 16 +--------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8afcf08eba9..ca330b1b365 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1866,7 +1866,7 @@ config FB_W100 config FB_SH_MOBILE_LCDC tristate "SuperH Mobile LCDC framebuffer support" - depends on FB && SUPERH + depends on FB && SUPERH && HAVE_CLK select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index da983b720f0..65806ec3313 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -42,11 +42,9 @@ struct sh_mobile_lcdc_chan { struct sh_mobile_lcdc_priv { void __iomem *base; int irq; -#ifdef CONFIG_HAVE_CLK atomic_t clk_usecnt; struct clk *dot_clk; struct clk *clk; -#endif unsigned long lddckr; struct sh_mobile_lcdc_chan ch[2]; int started; @@ -185,7 +183,6 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { lcdc_sys_read_data, }; -#ifdef CONFIG_HAVE_CLK static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) { if (atomic_inc_and_test(&priv->clk_usecnt)) { @@ -203,10 +200,6 @@ static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) clk_disable(priv->clk); } } -#else -static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) {} -static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) {} -#endif static int sh_mobile_lcdc_sginit(struct fb_info *info, struct list_head *pagelist) @@ -515,7 +508,6 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) board_cfg = &ch->cfg.board_cfg; if (board_cfg->display_off) board_cfg->display_off(board_cfg->board_data); - } /* stop the lcdc */ @@ -574,9 +566,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, int clock_source, struct sh_mobile_lcdc_priv *priv) { -#ifdef CONFIG_HAVE_CLK char clk_name[8]; -#endif char *str; int icksel; @@ -590,7 +580,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, priv->lddckr = icksel << 16; -#ifdef CONFIG_HAVE_CLK atomic_set(&priv->clk_usecnt, -1); snprintf(clk_name, sizeof(clk_name), "lcdc%d", pdev->id); priv->clk = clk_get(&pdev->dev, clk_name); @@ -598,7 +587,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); return PTR_ERR(priv->clk); } - + if (str) { priv->dot_clk = clk_get(&pdev->dev, str); if (IS_ERR(priv->dot_clk)) { @@ -607,7 +596,6 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, return PTR_ERR(priv->dot_clk); } } -#endif return 0; } @@ -934,11 +922,9 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) fb_dealloc_cmap(&info->cmap); } -#ifdef CONFIG_HAVE_CLK if (priv->dot_clk) clk_put(priv->dot_clk); clk_put(priv->clk); -#endif if (priv->base) iounmap(priv->base); From 2802e34590f290173a3f2aa5a4d662ae5373b420 Mon Sep 17 00:00:00 2001 From: Tim Abbott Date: Thu, 9 Jul 2009 14:45:59 +0000 Subject: [PATCH 013/262] sh: Clean up linker script using new linker script macros. This patch converts the sh architecture to use the new linker script macros in include/asm-generic/vmlinux.lds.h. Signed-off-by: Tim Abbott Cc: Paul Mundt Cc: Sam Ravnborg Cc: linux-sh@vger.kernel.org Signed-off-by: Paul Mundt --- arch/sh/kernel/vmlinux.lds.S | 87 +++++------------------------------- 1 file changed, 11 insertions(+), 76 deletions(-) diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index f53c76acaed..674ed8feb8a 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -50,12 +50,7 @@ SECTIONS _etext = .; /* End of text section */ } = 0x0009 - . = ALIGN(16); /* Exception table */ - __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } + EXCEPTION_TABLE(16) NOTES RO_DATA(PAGE_SIZE) @@ -71,69 +66,14 @@ SECTIONS __uncached_end = .; } - . = ALIGN(THREAD_SIZE); - .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ - *(.data.init_task) - - . = ALIGN(L1_CACHE_BYTES); - *(.data.cacheline_aligned) - - . = ALIGN(L1_CACHE_BYTES); - *(.data.read_mostly) - - . = ALIGN(PAGE_SIZE); - *(.data.page_aligned) - - __nosave_begin = .; - *(.data.nosave) - . = ALIGN(PAGE_SIZE); - __nosave_end = .; - - DATA_DATA - CONSTRUCTORS - } + RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE) _edata = .; /* End of data section */ . = ALIGN(PAGE_SIZE); /* Init code and data */ - .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { - __init_begin = .; - _sinittext = .; - INIT_TEXT - _einittext = .; - } - - .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { INIT_DATA } - - . = ALIGN(16); - .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - - .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { - __initcall_start = .; - INITCALLS - __initcall_end = .; - } - - .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - - SECURITY_INIT - -#ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(PAGE_SIZE); - .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } -#endif + __init_begin = .; + INIT_TEXT_SECTION(PAGE_SIZE) + INIT_DATA_SECTION(16) . = ALIGN(4); .machvec.init : AT(ADDR(.machvec.init) - LOAD_OFFSET) { @@ -152,16 +92,11 @@ SECTIONS .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { EXIT_DATA } . = ALIGN(PAGE_SIZE); - .bss : AT(ADDR(.bss) - LOAD_OFFSET) { - __init_end = .; - __bss_start = .; /* BSS */ - *(.bss.page_aligned) - *(.bss) - *(COMMON) - . = ALIGN(4); - _ebss = .; /* uClinux MTD sucks */ - _end = . ; - } + __init_end = .; + BSS(PAGE_SIZE) + . = ALIGN(4); + _ebss = .; /* uClinux MTD sucks */ + _end = . ; /* * When something in the kernel is NOT compiled as a module, the @@ -170,7 +105,7 @@ SECTIONS * it's a module. */ /DISCARD/ : { - *(.exitcall.exit) + EXIT_CALL } STABS_DEBUG From b99610fb9cdf390965c62c22322596d961591160 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 11 Jul 2009 01:00:23 +0000 Subject: [PATCH 014/262] sh: Provide diagnostic kernel stack checks Enable kernel stack checking code in both the dynamic ftrace and mcount code paths. Check the stack to see if it's overflowing and make sure that the stack pointer contains an address that's either in init_stack or after the bss. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/Kconfig.debug | 11 +++++ arch/sh/kernel/asm-offsets.c | 1 + arch/sh/lib/mcount.S | 85 ++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 39224b57c6e..52a132c24aa 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -123,4 +123,15 @@ config SH64_SR_WATCH bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" depends on SUPERH64 +config STACK_DEBUG + bool "Enable diagnostic checks of the kernel stack" + depends on FUNCTION_TRACER + select DEBUG_STACKOVERFLOW + default n + help + This option allows checks to be performed on the kernel stack + at runtime. Saying Y here will add overhead to every function + call and will therefore incur a major performance hit. Most + users should say N. + endmenu diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c index 99aceb28ee2..d218e808294 100644 --- a/arch/sh/kernel/asm-offsets.c +++ b/arch/sh/kernel/asm-offsets.c @@ -26,6 +26,7 @@ int main(void) DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); + DEFINE(TI_SIZE, sizeof(struct thread_info)); #ifdef CONFIG_HIBERNATION DEFINE(PBE_ADDRESS, offsetof(struct pbe, address)); diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 71e87f9b4fd..8596483f7b4 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -9,6 +9,8 @@ * for more details. */ #include +#include +#include #define MCOUNT_ENTER() \ mov.l r4, @-r15; \ @@ -28,6 +30,55 @@ rts; \ mov.l @r15+, r4 +#ifdef CONFIG_STACK_DEBUG +/* + * Perform diagnostic checks on the state of the kernel stack. + * + * Check for stack overflow. If there is less than 1KB free + * then it has overflowed. + * + * Make sure the stack pointer contains a valid address. Valid + * addresses for kernel stacks are anywhere after the bss + * (after _ebss) and anywhere in init_thread_union (init_stack). + */ +#define STACK_CHECK() \ + mov #(THREAD_SIZE >> 10), r0; \ + shll8 r0; \ + shll2 r0; \ + \ + /* r1 = sp & (THREAD_SIZE - 1) */ \ + mov #-1, r1; \ + add r0, r1; \ + and r15, r1; \ + \ + mov #TI_SIZE, r3; \ + mov #(STACK_WARN >> 8), r2; \ + shll8 r2; \ + add r3, r2; \ + \ + /* Is the stack overflowing? */ \ + cmp/hi r2, r1; \ + bf stack_panic; \ + \ + /* If sp > _ebss then we're OK. */ \ + mov.l .L_ebss, r1; \ + cmp/hi r1, r15; \ + bt 1f; \ + \ + /* If sp < init_stack, we're not OK. */ \ + mov.l .L_init_thread_union, r1; \ + cmp/hs r1, r15; \ + bf stack_panic; \ + \ + /* If sp > init_stack && sp < _ebss, not OK. */ \ + add r0, r1; \ + cmp/hs r1, r15; \ + bt stack_panic; \ +1: +#else +#define STACK_CHECK() +#endif /* CONFIG_STACK_DEBUG */ + .align 2 .globl _mcount .type _mcount,@function @@ -41,6 +92,8 @@ mcount: tst r0, r0 bf ftrace_stub #endif + STACK_CHECK() + MCOUNT_ENTER() #ifdef CONFIG_DYNAMIC_FTRACE @@ -73,6 +126,8 @@ ftrace_caller: tst r0, r0 bf ftrace_stub + STACK_CHECK() + MCOUNT_ENTER() .globl ftrace_call @@ -100,6 +155,36 @@ ftrace_stub: rts nop +#ifdef CONFIG_STACK_DEBUG + .globl stack_panic +stack_panic: + mov.l .Ldump_stack, r0 + jsr @r0 + nop + + mov.l .Lpanic, r0 + jsr @r0 + mov.l .Lpanic_s, r4 + + rts + nop + .align 2 .Lfunction_trace_stop: .long function_trace_stop +.L_ebss: + .long _ebss +.L_init_thread_union: + .long init_thread_union +.Lpanic: + .long panic +.Lpanic_s: + .long .Lpanic_str +.Ldump_stack: + .long dump_stack + + .section .rodata + .align 2 +.Lpanic_str: + .string "Stack error" +#endif /* CONFIG_STACK_DEBUG */ From 327933f5d6cdf083284d3c06e0370d1de464aef4 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 11 Jul 2009 00:29:03 +0000 Subject: [PATCH 015/262] sh: Function graph tracer support Add both dynamic and static function graph tracer support for sh. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/include/asm/ftrace.h | 3 + arch/sh/kernel/Makefile_32 | 1 + arch/sh/kernel/ftrace.c | 122 ++++++++++++++++++++++++++++++++ arch/sh/kernel/vmlinux_64.lds.S | 0 arch/sh/lib/Makefile | 1 + arch/sh/lib/mcount.S | 117 +++++++++++++++++++++++++++++- 7 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 arch/sh/kernel/vmlinux_64.lds.S diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 29e41ec6537..6d110a4f7f6 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -33,6 +33,7 @@ config SUPERH32 select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_FTRACE_SYSCALLS + select HAVE_FUNCTION_GRAPH_TRACER select HAVE_ARCH_KGDB select ARCH_HIBERNATION_POSSIBLE if MMU diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h index b09311ad1db..7e0bcc4d4a9 100644 --- a/arch/sh/include/asm/ftrace.h +++ b/arch/sh/include/asm/ftrace.h @@ -13,8 +13,11 @@ extern void mcount(void); #ifdef CONFIG_DYNAMIC_FTRACE #define CALL_ADDR ((long)(ftrace_call)) #define STUB_ADDR ((long)(ftrace_stub)) +#define GRAPH_ADDR ((long)(ftrace_graph_call)) +#define CALLER_ADDR ((long)(ftrace_caller)) #define MCOUNT_INSN_OFFSET ((STUB_ADDR - CALL_ADDR) - 4) +#define GRAPH_INSN_OFFSET ((CALLER_ADDR - GRAPH_ADDR) - 4) struct dyn_arch_ftrace { /* No extra data needed on sh */ diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index fee924a9c46..94ed99b6800 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 @@ -30,6 +30,7 @@ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_GENERIC_GPIO) += gpio.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o +obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_DUMP_CODE) += disassemble.o obj-$(CONFIG_HIBERNATION) += swsusp.o diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c index 4f62eced0ae..6647dfcb781 100644 --- a/arch/sh/kernel/ftrace.c +++ b/arch/sh/kernel/ftrace.c @@ -16,11 +16,13 @@ #include #include #include +#include #include #include #include #include +#ifdef CONFIG_DYNAMIC_FTRACE static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; static unsigned char ftrace_nop[4]; @@ -133,6 +135,126 @@ int __init ftrace_dyn_arch_init(void *data) return 0; } +#endif /* CONFIG_DYNAMIC_FTRACE */ + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +#ifdef CONFIG_DYNAMIC_FTRACE +extern void ftrace_graph_call(void); + +static int ftrace_mod(unsigned long ip, unsigned long old_addr, + unsigned long new_addr) +{ + unsigned char code[MCOUNT_INSN_SIZE]; + + if (probe_kernel_read(code, (void *)ip, MCOUNT_INSN_SIZE)) + return -EFAULT; + + if (old_addr != __raw_readl((unsigned long *)code)) + return -EINVAL; + + __raw_writel(new_addr, ip); + return 0; +} + +int ftrace_enable_ftrace_graph_caller(void) +{ + unsigned long ip, old_addr, new_addr; + + ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET; + old_addr = (unsigned long)(&skip_trace); + new_addr = (unsigned long)(&ftrace_graph_caller); + + return ftrace_mod(ip, old_addr, new_addr); +} + +int ftrace_disable_ftrace_graph_caller(void) +{ + unsigned long ip, old_addr, new_addr; + + ip = (unsigned long)(&ftrace_graph_call) + GRAPH_INSN_OFFSET; + old_addr = (unsigned long)(&ftrace_graph_caller); + new_addr = (unsigned long)(&skip_trace); + + return ftrace_mod(ip, old_addr, new_addr); +} +#endif /* CONFIG_DYNAMIC_FTRACE */ + +/* + * Hook the return address and push it in the stack of return addrs + * in the current thread info. + * + * This is the main routine for the function graph tracer. The function + * graph tracer essentially works like this: + * + * parent is the stack address containing self_addr's return address. + * We pull the real return address out of parent and store it in + * current's ret_stack. Then, we replace the return address on the stack + * with the address of return_to_handler. self_addr is the function that + * called mcount. + * + * When self_addr returns, it will jump to return_to_handler which calls + * ftrace_return_to_handler. ftrace_return_to_handler will pull the real + * return address off of current's ret_stack and jump to it. + */ +void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) +{ + unsigned long old; + int faulted, err; + struct ftrace_graph_ent trace; + unsigned long return_hooker = (unsigned long)&return_to_handler; + + if (unlikely(atomic_read(¤t->tracing_graph_pause))) + return; + + /* + * Protect against fault, even if it shouldn't + * happen. This tool is too much intrusive to + * ignore such a protection. + */ + __asm__ __volatile__( + "1: \n\t" + "mov.l @%2, %0 \n\t" + "2: \n\t" + "mov.l %3, @%2 \n\t" + "mov #0, %1 \n\t" + "3: \n\t" + ".section .fixup, \"ax\" \n\t" + "4: \n\t" + "mov.l 5f, %0 \n\t" + "jmp @%0 \n\t" + " mov #1, %1 \n\t" + ".balign 4 \n\t" + "5: .long 3b \n\t" + ".previous \n\t" + ".section __ex_table,\"a\" \n\t" + ".long 1b, 4b \n\t" + ".long 2b, 4b \n\t" + ".previous \n\t" + : "=&r" (old), "=r" (faulted) + : "r" (parent), "r" (return_hooker) + ); + + if (unlikely(faulted)) { + ftrace_graph_stop(); + WARN_ON(1); + return; + } + + err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0); + if (err == -EBUSY) { + __raw_writel(old, parent); + return; + } + + trace.func = self_addr; + + /* Only trace if the calling function expects to */ + if (!ftrace_graph_entry(&trace)) { + current->curr_ret_stack--; + __raw_writel(old, parent); + } +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #ifdef CONFIG_FTRACE_SYSCALLS diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S new file mode 100644 index 00000000000..e69de29bb2d diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index aaea580b65b..19328d90a2d 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -25,6 +25,7 @@ memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o lib-$(CONFIG_MMU) += copy_page.o clear_page.o lib-$(CONFIG_FUNCTION_TRACER) += mcount.o +lib-$(CONFIG_FUNCTION_GRAPH_TRACER) += mcount.o lib-y += $(memcpy-y) $(udivsi3-y) EXTRA_CFLAGS += -Werror diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 8596483f7b4..bd3ec648bec 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -111,14 +111,62 @@ mcount_call: jsr @r6 nop +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + mov.l .Lftrace_graph_return, r6 + mov.l .Lftrace_stub, r7 + cmp/eq r6, r7 + bt 1f + + mov.l .Lftrace_graph_caller, r0 + jmp @r0 + nop + +1: + mov.l .Lftrace_graph_entry, r6 + mov.l .Lftrace_graph_entry_stub, r7 + cmp/eq r6, r7 + bt skip_trace + + mov.l .Lftrace_graph_caller, r0 + jmp @r0 + nop + + .align 2 +.Lftrace_graph_return: + .long ftrace_graph_return +.Lftrace_graph_entry: + .long ftrace_graph_entry +.Lftrace_graph_entry_stub: + .long ftrace_graph_entry_stub +.Lftrace_graph_caller: + .long ftrace_graph_caller +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + + .globl skip_trace skip_trace: MCOUNT_LEAVE() .align 2 .Lftrace_trace_function: - .long ftrace_trace_function + .long ftrace_trace_function #ifdef CONFIG_DYNAMIC_FTRACE +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +/* + * NOTE: Do not move either ftrace_graph_call or ftrace_caller + * as this will affect the calculation of GRAPH_INSN_OFFSET. + */ + .globl ftrace_graph_call +ftrace_graph_call: + mov.l .Lskip_trace, r0 + jmp @r0 + nop + + .align 2 +.Lskip_trace: + .long skip_trace +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ + .globl ftrace_caller ftrace_caller: mov.l .Lfunction_trace_stop, r0 @@ -136,7 +184,12 @@ ftrace_call: jsr @r6 nop +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + bra ftrace_graph_call + nop +#else MCOUNT_LEAVE() +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #endif /* CONFIG_DYNAMIC_FTRACE */ /* @@ -188,3 +241,65 @@ stack_panic: .Lpanic_str: .string "Stack error" #endif /* CONFIG_STACK_DEBUG */ + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + .globl ftrace_graph_caller +ftrace_graph_caller: + mov.l 2f, r0 + mov.l @r0, r0 + tst r0, r0 + bt 1f + + mov.l 3f, r1 + jmp @r1 + nop +1: + /* + * MCOUNT_ENTER() pushed 5 registers onto the stack, so + * the stack address containing our return address is + * r15 + 20. + */ + mov #20, r0 + add r15, r0 + mov r0, r4 + + mov.l .Lprepare_ftrace_return, r0 + jsr @r0 + nop + + MCOUNT_LEAVE() + + .align 2 +2: .long function_trace_stop +3: .long skip_trace +.Lprepare_ftrace_return: + .long prepare_ftrace_return + + .globl return_to_handler +return_to_handler: + /* + * Save the return values. + */ + mov.l r0, @-r15 + mov.l r1, @-r15 + + mov #0, r4 + + mov.l .Lftrace_return_to_handler, r0 + jsr @r0 + nop + + /* + * The return value from ftrace_return_handler has the real + * address that we should return to. + */ + lds r0, pr + mov.l @r15+, r1 + rts + mov.l @r15+, r0 + + + .align 2 +.Lftrace_return_to_handler: + .long ftrace_return_to_handler +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ From 7816fecd03e480ed0b47d674ed772ca0b45e1b5e Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Sat, 11 Jul 2009 00:29:04 +0000 Subject: [PATCH 016/262] sh: Mark __switch_to() as __notrace_funcgraph Annotate __switch_to() so that the function graph tracer does not try to trace it. Use __notrace_funcgraph, as opposed to notrace, so that other tracers can continue to trace __switch_to(). The reason that we don't want to trace __switch_to() with the function graph tracer is because of how the return address stack in task_struct is implemented. When we enter __switch_to we store the real return address on prev's ret_stack. When we return from __switch_to() we've patched the return address on the kernel stack to be return_to_handler. Calling return_to_handler we do, -> ftrace_return_to_handler() -> ftrace_pop_return_ftrace() Which tries to pop the real return address from current->ret_stack. The problem being that we stored the return address on prev->ret_stack, but current now points to next, and next->ret_stack doesn't contain the correct return address (and is possibly even empty). Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/kernel/process_32.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 92d7740faab..9fee977f176 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -264,8 +265,8 @@ static void ubc_set_tracing(int asid, unsigned long pc) * switch_to(x,y) should switch tasks from x to y. * */ -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *next) +__notrace_funcgraph struct task_struct * +__switch_to(struct task_struct *prev, struct task_struct *next) { #if defined(CONFIG_SH_FPU) unlazy_fpu(prev, task_pt_regs(prev)); From 473d1cf4ee623b043790838bcf77e77958840bf2 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 19:56:58 +0900 Subject: [PATCH 017/262] sh: Decouple mcount from ftrace. This adds a general CONFIG_MCOUNT in order to permit mcount generation without ftrace support. This is primarily for allowing platforms to enable aggressive stack overflow checking without having to enable ftrace support. Based on the sparc64 implementation. Signed-off-by: Paul Mundt --- arch/sh/Kconfig.debug | 5 +++++ arch/sh/Makefile | 4 ++++ arch/sh/boot/compressed/Makefile | 2 +- arch/sh/kernel/sh_ksyms_32.c | 2 +- arch/sh/lib/Makefile | 3 +-- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 52a132c24aa..75b5f4e0667 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -134,4 +134,9 @@ config STACK_DEBUG call and will therefore incur a major performance hit. Most users should say N. +config MCOUNT + def_bool y + depends on SUPERH32 + depends on STACK_DEBUG || FUNCTION_TRACER + endmenu diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 75d049b03f7..52c34bf5696 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -186,6 +186,10 @@ KBUILD_CFLAGS += -pipe $(cflags-y) KBUILD_CPPFLAGS += $(cflags-y) KBUILD_AFLAGS += $(cflags-y) +ifeq ($(CONFIG_MCOUNT),y) + KBUILD_CFLAGS += -pg +endif + libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 9531bf1b7c2..3af239cb9b0 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -23,7 +23,7 @@ IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) -ifeq ($(CONFIG_FUNCTION_TRACER),y) +ifeq ($(CONFIG_MCOUNT),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS)) endif diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index fcc5de31f83..5b81116046c 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -106,7 +106,7 @@ EXPORT_SYMBOL(flush_dcache_page); EXPORT_SYMBOL(clear_user_page); #endif -#ifdef CONFIG_FUNCTION_TRACER +#ifdef CONFIG_MCOUNT EXPORT_SYMBOL(mcount); #endif EXPORT_SYMBOL(csum_partial); diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index 19328d90a2d..c2b28d8b2dd 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -24,8 +24,7 @@ memcpy-y := memcpy.o memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o lib-$(CONFIG_MMU) += copy_page.o clear_page.o -lib-$(CONFIG_FUNCTION_TRACER) += mcount.o -lib-$(CONFIG_FUNCTION_GRAPH_TRACER) += mcount.o +lib-$(CONFIG_MCOUNT) += mcount.o lib-y += $(memcpy-y) $(udivsi3-y) EXTRA_CFLAGS += -Werror From 9f14b84afda297d301b81a5bcbd65e83d7b02034 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 20:05:34 +0900 Subject: [PATCH 018/262] sh: Replace DEBUG_STACKOVERFLOW with STACK_DEBUG. STACK_DEBUG ties in to mcount in order to do function-granular stack overflow checks as opposed to lazily checking from IRQ context. As the default is nohz, the frequency of overflow checking is too irregular to catch much useful information, and so the mcount approach employed by sparc64 is adopted instead. This kills off the old check entirely from the do_IRQ() path and now adopts CONFIG_MCOUNT instead. Signed-off-by: Paul Mundt --- arch/sh/Kconfig.debug | 17 ++++------------- arch/sh/kernel/irq.c | 17 ----------------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 75b5f4e0667..b440fd93671 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -61,12 +61,14 @@ config EARLY_PRINTK select both the EARLY_SCIF_CONSOLE and SH_STANDARD_BIOS, using the kernel command line option to toggle back and forth. -config DEBUG_STACKOVERFLOW +config STACK_DEBUG bool "Check for stack overflows" depends on DEBUG_KERNEL && SUPERH32 help This option will cause messages to be printed if free stack space - drops below a certain limit. + drops below a certain limit. Saying Y here will add overhead to + every function call and will therefore incur a major + performance hit. Most users should say N. config DEBUG_STACK_USAGE bool "Stack utilization instrumentation" @@ -123,17 +125,6 @@ config SH64_SR_WATCH bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" depends on SUPERH64 -config STACK_DEBUG - bool "Enable diagnostic checks of the kernel stack" - depends on FUNCTION_TRACER - select DEBUG_STACKOVERFLOW - default n - help - This option allows checks to be performed on the kernel stack - at runtime. Saying Y here will add overhead to every function - call and will therefore incur a major performance hit. Most - users should say N. - config MCOUNT def_bool y depends on SUPERH32 diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 3d09062f468..278c68c6048 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -114,23 +114,6 @@ asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs) #endif irq_enter(); - -#ifdef CONFIG_DEBUG_STACKOVERFLOW - /* Debugging check for stack overflow: is there less than 1KB free? */ - { - long sp; - - __asm__ __volatile__ ("and r15, %0" : - "=r" (sp) : "0" (THREAD_SIZE - 1)); - - if (unlikely(sp < (sizeof(struct thread_info) + STACK_WARN))) { - printk("do_IRQ: stack overflow: %ld\n", - sp - sizeof(struct thread_info)); - dump_stack(); - } - } -#endif - irq = irq_demux(intc_evt2irq(irq)); #ifdef CONFIG_IRQSTACKS From fe27932052aebf77ac5f3e73962825d2aeb457a0 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 20:32:14 +0900 Subject: [PATCH 019/262] sh: Use DECLARE_EXPORT() for mcount symbol export. The function prototype for mcount is not defined if we are not building with ftrace support enabled, so use DECLARE_EXPORT() to stub one in. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_ksyms_32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index 5b81116046c..cec610888e2 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -107,7 +107,7 @@ EXPORT_SYMBOL(clear_user_page); #endif #ifdef CONFIG_MCOUNT -EXPORT_SYMBOL(mcount); +DECLARE_EXPORT(mcount); #endif EXPORT_SYMBOL(csum_partial); EXPORT_SYMBOL(csum_partial_copy_generic); From a470b95e99ea77ef1e307ff181e59a4a16caa4f4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 20:33:34 +0900 Subject: [PATCH 020/262] sh: Fix up ftrace build error when STACK_DEBUG=n. Presently the closest reference to function_trace_stop is within a CONFIG_STACK_DEBUG block. When this is turned off, the build bails out with a pcrel too far error. Reorder things a bit to handle the various combinations. Signed-off-by: Paul Mundt --- arch/sh/lib/mcount.S | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index bd3ec648bec..9e397aafc16 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -192,6 +192,10 @@ ftrace_call: #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ #endif /* CONFIG_DYNAMIC_FTRACE */ + .align 2 +.Lfunction_trace_stop: + .long function_trace_stop + /* * NOTE: From here on the locations of the .Lftrace_stub label and * ftrace_stub itself are fixed. Adding additional data here will skew @@ -199,7 +203,6 @@ ftrace_call: * Place new labels either after the ftrace_stub body, or before * ftrace_caller. You have been warned. */ - .align 2 .Lftrace_stub: .long ftrace_stub @@ -223,8 +226,6 @@ stack_panic: nop .align 2 -.Lfunction_trace_stop: - .long function_trace_stop .L_ebss: .long _ebss .L_init_thread_union: From e460ab27b6c3ea313762169713086529d5bfb8bc Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 21:06:53 +0900 Subject: [PATCH 021/262] sh: Fix up stack overflow check with ftrace disabled. Presently the STACK_CHECK() code is called in to multiple times, although it's only necessary from the mcount entry. The code still attempts to treat the nop case as an ftrace path resulting in superfluous code flow for the case where ftrace is disabled. And finally, this also fixes up references to a few undefined symbols when FUNCTION_TRACER=n. Signed-off-by: Paul Mundt --- arch/sh/lib/mcount.S | 76 +++++++++++++++++++++++--------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index 9e397aafc16..84a57761f17 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S @@ -1,7 +1,7 @@ /* * arch/sh/lib/mcount.S * - * Copyright (C) 2008 Paul Mundt + * Copyright (C) 2008, 2009 Paul Mundt * Copyright (C) 2008, 2009 Matt Fleming * * This file is subject to the terms and conditions of the GNU General Public @@ -86,13 +86,18 @@ .type mcount,@function _mcount: mcount: + STACK_CHECK() + +#ifndef CONFIG_FUNCTION_TRACER + rts + nop +#else #ifndef CONFIG_DYNAMIC_FTRACE mov.l .Lfunction_trace_stop, r0 mov.l @r0, r0 tst r0, r0 bf ftrace_stub #endif - STACK_CHECK() MCOUNT_ENTER() @@ -174,8 +179,6 @@ ftrace_caller: tst r0, r0 bf ftrace_stub - STACK_CHECK() - MCOUNT_ENTER() .globl ftrace_call @@ -211,38 +214,6 @@ ftrace_stub: rts nop -#ifdef CONFIG_STACK_DEBUG - .globl stack_panic -stack_panic: - mov.l .Ldump_stack, r0 - jsr @r0 - nop - - mov.l .Lpanic, r0 - jsr @r0 - mov.l .Lpanic_s, r4 - - rts - nop - - .align 2 -.L_ebss: - .long _ebss -.L_init_thread_union: - .long init_thread_union -.Lpanic: - .long panic -.Lpanic_s: - .long .Lpanic_str -.Ldump_stack: - .long dump_stack - - .section .rodata - .align 2 -.Lpanic_str: - .string "Stack error" -#endif /* CONFIG_STACK_DEBUG */ - #ifdef CONFIG_FUNCTION_GRAPH_TRACER .globl ftrace_graph_caller ftrace_graph_caller: @@ -304,3 +275,36 @@ return_to_handler: .Lftrace_return_to_handler: .long ftrace_return_to_handler #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +#endif /* CONFIG_FUNCTION_TRACER */ + +#ifdef CONFIG_STACK_DEBUG + .globl stack_panic +stack_panic: + mov.l .Ldump_stack, r0 + jsr @r0 + nop + + mov.l .Lpanic, r0 + jsr @r0 + mov.l .Lpanic_s, r4 + + rts + nop + + .align 2 +.L_ebss: + .long _ebss +.L_init_thread_union: + .long init_thread_union +.Lpanic: + .long panic +.Lpanic_s: + .long .Lpanic_str +.Ldump_stack: + .long dump_stack + + .section .rodata + .align 2 +.Lpanic_str: + .string "Stack error" +#endif /* CONFIG_STACK_DEBUG */ From df8ce2595fbac8b046322fce9df61ce1cf8ddf62 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sun, 12 Jul 2009 01:37:30 +0900 Subject: [PATCH 022/262] sh: Tidy up gzip-based zImage decompression. This brings the zImage handling in to the current century, in preparation for handling the other compression types. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 1 + arch/sh/boot/compressed/misc_32.c | 106 +++---------------------- arch/sh/boot/compressed/misc_64.c | 127 ++---------------------------- 3 files changed, 19 insertions(+), 215 deletions(-) diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 120bd31a46e..9f531ca3c8e 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -17,6 +17,7 @@ config SUPERH select HAVE_ARCH_TRACEHOOK select HAVE_DMA_API_DEBUG select HAVE_PERF_COUNTERS + select HAVE_KERNEL_GZIP select RTC_LIB select GENERIC_ATOMIC64 help diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c index efdba6b2957..1ab4f49153b 100644 --- a/arch/sh/boot/compressed/misc_32.c +++ b/arch/sh/boot/compressed/misc_32.c @@ -14,73 +14,23 @@ #include #include #include -#ifdef CONFIG_SH_STANDARD_BIOS #include -#endif /* * gzip declarations */ -#define OF(args) args #define STATIC static #undef memset #undef memcpy #define memzero(s, n) memset ((s), 0, (n)) -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* Window size must be at least 32k, */ - /* and a power of two */ - -static uch *inbuf; /* input buffer */ -static uch window[WSIZE]; /* Sliding window buffer */ - -static unsigned insize = 0; /* valid bytes in inbuf */ -static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -static unsigned outcnt = 0; /* bytes in output buffer */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -static int fill_inbuf(void); -static void flush_window(void); static void error(char *m); extern char input_data[]; extern int input_len; - -static long bytes_out = 0; -static uch *output_data; -static unsigned long output_ptr = 0; +static unsigned char *output; static void error(char *m); @@ -93,7 +43,9 @@ static unsigned long free_mem_end_ptr; #define HEAP_SIZE 0x10000 -#include "../../../../lib/inflate.c" +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif #ifdef CONFIG_SH_STANDARD_BIOS size_t strlen(const char *s) @@ -138,44 +90,6 @@ void* memcpy(void* __dest, __const void* __src, return __dest; } -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - */ -static int fill_inbuf(void) -{ - if (insize != 0) { - error("ran out of input data"); - } - - inbuf = input_data; - insize = input_len; - inptr = 1; - return inbuf[0]; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, *out, ch; - - in = window; - out = &output_data[output_ptr]; - for (n = 0; n < outcnt; n++) { - ch = *out++ = *in++; - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - output_ptr += (ulg)outcnt; - outcnt = 0; -} - static void error(char *x) { puts("\n\n"); @@ -191,16 +105,18 @@ long* stack_start = &user_stack[STACK_SIZE]; void decompress_kernel(void) { - output_data = NULL; - output_ptr = PHYSADDR((unsigned long)&_text+PAGE_SIZE); + unsigned long output_addr; + + output_addr = PHYSADDR((unsigned long)&_text+PAGE_SIZE); #ifdef CONFIG_29BIT - output_ptr |= P2SEG; + output_addr |= P2SEG; #endif + + output = (unsigned char *)output_addr; free_mem_ptr = (unsigned long)&_end; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - makecrc(); puts("Uncompressing Linux... "); - gunzip(); + decompress(input_data, input_len, NULL, NULL, output, NULL, error); puts("Ok, booting the kernel.\n"); } diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c index 2941657e18a..0c6894e3711 100644 --- a/arch/sh/boot/compressed/misc_64.c +++ b/arch/sh/boot/compressed/misc_64.c @@ -20,67 +20,18 @@ int cache_control(unsigned int command); * gzip declarations */ -#define OF(args) args #define STATIC static #undef memset #undef memcpy #define memzero(s, n) memset ((s), 0, (n)) -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* Window size must be at least 32k, */ - /* and a power of two */ - -static uch *inbuf; /* input buffer */ -static uch window[WSIZE]; /* Sliding window buffer */ - -static unsigned insize = 0; /* valid bytes in inbuf */ -static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -static unsigned outcnt = 0; /* bytes in output buffer */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -static int fill_inbuf(void); -static void flush_window(void); static void error(char *m); extern char input_data[]; extern int input_len; -static long bytes_out = 0; -static uch *output_data; -static unsigned long output_ptr = 0; - -static void error(char *m); +static unsigned char *output_data; static void puts(const char *); @@ -91,7 +42,9 @@ static unsigned long free_mem_end_ptr; #define HEAP_SIZE 0x10000 -#include "../../../../lib/inflate.c" +#ifdef CONFIG_KERNEL_GZIP +#include "../../../../lib/decompress_inflate.c" +#endif void puts(const char *s) { @@ -117,45 +70,6 @@ void *memcpy(void *__dest, __const void *__src, size_t __n) return __dest; } -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - */ -static int fill_inbuf(void) -{ - if (insize != 0) { - error("ran out of input data\n"); - } - - inbuf = input_data; - insize = input_len; - inptr = 1; - return inbuf[0]; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, *out, ch; - - in = window; - out = &output_data[output_ptr]; - for (n = 0; n < outcnt; n++) { - ch = *out++ = *in++; - c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg) outcnt; - output_ptr += (ulg) outcnt; - outcnt = 0; - puts("."); -} - static void error(char *x) { puts("\n\n"); @@ -171,40 +85,13 @@ long *stack_start = &user_stack[STACK_SIZE]; void decompress_kernel(void) { - output_data = (uch *) (CONFIG_MEMORY_START + 0x2000); + output_data = (unsigned char *) (CONFIG_MEMORY_START + 0x2000); free_mem_ptr = (unsigned long) &_end; free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - makecrc(); puts("Uncompressing Linux... "); cache_control(CACHE_ENABLE); - gunzip(); - puts("\n"); - -#if 0 - /* When booting from ROM may want to do something like this if the - * boot loader doesn't. - */ - - /* Set up the parameters and command line */ - { - volatile unsigned int *parambase = - (int *) (CONFIG_MEMORY_START + 0x1000); - - parambase[0] = 0x1; /* MOUNT_ROOT_RDONLY */ - parambase[1] = 0x0; /* RAMDISK_FLAGS */ - parambase[2] = 0x0200; /* ORIG_ROOT_DEV */ - parambase[3] = 0x0; /* LOADER_TYPE */ - parambase[4] = 0x0; /* INITRD_START */ - parambase[5] = 0x0; /* INITRD_SIZE */ - parambase[6] = 0; - - strcpy((char *) ((int) parambase + 0x100), - "console=ttySC0,38400"); - } -#endif - - puts("Ok, booting the kernel.\n"); - + decompress(input_data, input_len, NULL, NULL, output_data, NULL, error); cache_control(CACHE_DISABLE); + puts("Ok, booting the kernel.\n"); } From 07e88e1bfc128681a80578724fde6a872f413862 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 13:21:19 -0400 Subject: [PATCH 023/262] sh: bzip2/lzma zImage support. This plugs in bzip2 and lzma support for zImages. Signed-off-by: Paul Mundt --- arch/sh/Kconfig | 2 ++ arch/sh/boot/compressed/.gitignore | 1 + arch/sh/boot/compressed/Makefile | 19 ++++++++++++++++--- arch/sh/boot/compressed/misc_32.c | 14 +++++++++++++- arch/sh/boot/compressed/misc_64.c | 14 +++++++++++++- arch/sh/boot/compressed/piggy.S | 8 -------- arch/sh/boot/compressed/vmlinux.scr | 10 ++++++++++ 7 files changed, 55 insertions(+), 13 deletions(-) create mode 100644 arch/sh/boot/compressed/.gitignore delete mode 100644 arch/sh/boot/compressed/piggy.S create mode 100644 arch/sh/boot/compressed/vmlinux.scr diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 9f531ca3c8e..c4a955d2545 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -18,6 +18,8 @@ config SUPERH select HAVE_DMA_API_DEBUG select HAVE_PERF_COUNTERS select HAVE_KERNEL_GZIP + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_LZMA select RTC_LIB select GENERIC_ATOMIC64 help diff --git a/arch/sh/boot/compressed/.gitignore b/arch/sh/boot/compressed/.gitignore new file mode 100644 index 00000000000..2374a83d87b --- /dev/null +++ b/arch/sh/boot/compressed/.gitignore @@ -0,0 +1 @@ +vmlinux.bin.* diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 9531bf1b7c2..0a4e7af8a71 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -5,6 +5,7 @@ # targets := vmlinux vmlinux.bin vmlinux.bin.gz \ + vmlinux.bin.bz2 vmlinux.bin.lzma \ head_$(BITS).o misc_$(BITS).o piggy.o OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc_$(BITS).o $(obj)/cache.o @@ -38,10 +39,22 @@ $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) -$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE +vmlinux.bin.all-y := $(obj)/vmlinux.bin + +$(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE $(call if_changed,gzip) +$(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE + $(call if_changed,bzip2) +$(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE + $(call if_changed,lzma) + +suffix-$(CONFIG_KERNEL_GZIP) := gz +suffix-$(CONFIG_KERNEL_BZIP2) := bz2 +suffix-$(CONFIG_KERNEL_LZMA) := lzma OBJCOPYFLAGS += -R .empty_zero_page -$(obj)/piggy.o: $(obj)/piggy.S $(obj)/vmlinux.bin.gz FORCE - $(call if_changed,as_o_S) +LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T + +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) FORCE + $(call if_changed,ld) diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c index 1ab4f49153b..b86e3596918 100644 --- a/arch/sh/boot/compressed/misc_32.c +++ b/arch/sh/boot/compressed/misc_32.c @@ -41,12 +41,24 @@ extern int _end; static unsigned long free_mem_ptr; static unsigned long free_mem_end_ptr; -#define HEAP_SIZE 0x10000 +#ifdef CONFIG_HAVE_KERNEL_BZIP2 +#define HEAP_SIZE 0x400000 +#else +#define HEAP_SIZE 0x10000 +#endif #ifdef CONFIG_KERNEL_GZIP #include "../../../../lib/decompress_inflate.c" #endif +#ifdef CONFIG_KERNEL_BZIP2 +#include "../../../../lib/decompress_bunzip2.c" +#endif + +#ifdef CONFIG_KERNEL_LZMA +#include "../../../../lib/decompress_unlzma.c" +#endif + #ifdef CONFIG_SH_STANDARD_BIOS size_t strlen(const char *s) { diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c index 0c6894e3711..09b7b7cd24f 100644 --- a/arch/sh/boot/compressed/misc_64.c +++ b/arch/sh/boot/compressed/misc_64.c @@ -40,12 +40,24 @@ extern int _end; static unsigned long free_mem_ptr; static unsigned long free_mem_end_ptr; -#define HEAP_SIZE 0x10000 +#ifdef CONFIG_HAVE_KERNEL_BZIP2 +#define HEAP_SIZE 0x400000 +#else +#define HEAP_SIZE 0x10000 +#endif #ifdef CONFIG_KERNEL_GZIP #include "../../../../lib/decompress_inflate.c" #endif +#ifdef CONFIG_KERNEL_BZIP2 +#include "../../../../lib/decompress_bunzip2.c" +#endif + +#ifdef CONFIG_KERNEL_LZMA +#include "../../../../lib/decompress_unlzma.c" +#endif + void puts(const char *s) { } diff --git a/arch/sh/boot/compressed/piggy.S b/arch/sh/boot/compressed/piggy.S deleted file mode 100644 index 566071926b1..00000000000 --- a/arch/sh/boot/compressed/piggy.S +++ /dev/null @@ -1,8 +0,0 @@ - .global input_len, input_data - .data -input_len: - .long input_data_end - input_data -input_data: - .incbin "arch/sh/boot/compressed/vmlinux.bin.gz" -input_data_end: - .end diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr new file mode 100644 index 00000000000..f02382ae5c4 --- /dev/null +++ b/arch/sh/boot/compressed/vmlinux.scr @@ -0,0 +1,10 @@ +SECTIONS +{ + .rodata.compressed : { + input_len = .; + LONG(input_data_end - input_data) input_data = .; + *(.data) + output_len = . - 4; + input_data_end = .; + } +} From b14c6d428a54fb3235e69fd78fba9080c96645be Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 13:30:38 -0400 Subject: [PATCH 024/262] sh: Consolidate the sh64 changes in arch/sh/boot/compressed/misc_32.c This makes some minor changes to misc_32.c so that it can be used by sh64. Signed-off-by: Paul Mundt --- arch/sh/boot/compressed/misc_32.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc_32.c index b86e3596918..4eb27e61f8e 100644 --- a/arch/sh/boot/compressed/misc_32.c +++ b/arch/sh/boot/compressed/misc_32.c @@ -26,7 +26,10 @@ #undef memcpy #define memzero(s, n) memset ((s), 0, (n)) -static void error(char *m); +/* cache.c */ +#define CACHE_ENABLE 0 +#define CACHE_DISABLE 1 +int cache_control(unsigned int command); extern char input_data[]; extern int input_len; @@ -111,9 +114,15 @@ static void error(char *x) while(1); /* Halt */ } +#ifdef CONFIG_SUPERH64 +#define stackalign 8 +#else +#define stackalign 4 +#endif + #define STACK_SIZE (4096) -long user_stack [STACK_SIZE]; -long* stack_start = &user_stack[STACK_SIZE]; +long __attribute__ ((aligned(stackalign))) user_stack[STACK_SIZE]; +long *stack_start = &user_stack[STACK_SIZE]; void decompress_kernel(void) { @@ -129,6 +138,8 @@ void decompress_kernel(void) free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; puts("Uncompressing Linux... "); + cache_control(CACHE_ENABLE); decompress(input_data, input_len, NULL, NULL, output, NULL, error); + cache_control(CACHE_DISABLE); puts("Ok, booting the kernel.\n"); } From 59f002964f4e6668a0132cd796b82f7f8a4803f0 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 13:32:24 -0400 Subject: [PATCH 025/262] sh: rename arch/sh/boot/compressed/misc_32.c -> misc.c This is now used by both sh64 and regular sh, kill off the old sh64 version now too. Signed-off-by: Paul Mundt --- arch/sh/boot/compressed/Makefile | 4 +- arch/sh/boot/compressed/{misc_32.c => misc.c} | 0 arch/sh/boot/compressed/misc_64.c | 109 ------------------ 3 files changed, 2 insertions(+), 111 deletions(-) rename arch/sh/boot/compressed/{misc_32.c => misc.c} (100%) delete mode 100644 arch/sh/boot/compressed/misc_64.c diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 0a4e7af8a71..3324019e207 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -6,9 +6,9 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \ vmlinux.bin.bz2 vmlinux.bin.lzma \ - head_$(BITS).o misc_$(BITS).o piggy.o + head_$(BITS).o misc.o piggy.o -OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc_$(BITS).o $(obj)/cache.o +OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o ifdef CONFIG_SH_STANDARD_BIOS OBJECTS += $(obj)/../../kernel/sh_bios.o diff --git a/arch/sh/boot/compressed/misc_32.c b/arch/sh/boot/compressed/misc.c similarity index 100% rename from arch/sh/boot/compressed/misc_32.c rename to arch/sh/boot/compressed/misc.c diff --git a/arch/sh/boot/compressed/misc_64.c b/arch/sh/boot/compressed/misc_64.c deleted file mode 100644 index 09b7b7cd24f..00000000000 --- a/arch/sh/boot/compressed/misc_64.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * arch/sh/boot/compressed/misc_64.c - * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 - * - * Adapted for SHmedia from sh by Stuart Menefy, May 2002 - */ - -#include - -/* cache.c */ -#define CACHE_ENABLE 0 -#define CACHE_DISABLE 1 -int cache_control(unsigned int command); - -/* - * gzip declarations - */ - -#define STATIC static - -#undef memset -#undef memcpy -#define memzero(s, n) memset ((s), 0, (n)) - -static void error(char *m); - -extern char input_data[]; -extern int input_len; - -static unsigned char *output_data; - -static void puts(const char *); - -extern int _text; /* Defined in vmlinux.lds.S */ -extern int _end; -static unsigned long free_mem_ptr; -static unsigned long free_mem_end_ptr; - -#ifdef CONFIG_HAVE_KERNEL_BZIP2 -#define HEAP_SIZE 0x400000 -#else -#define HEAP_SIZE 0x10000 -#endif - -#ifdef CONFIG_KERNEL_GZIP -#include "../../../../lib/decompress_inflate.c" -#endif - -#ifdef CONFIG_KERNEL_BZIP2 -#include "../../../../lib/decompress_bunzip2.c" -#endif - -#ifdef CONFIG_KERNEL_LZMA -#include "../../../../lib/decompress_unlzma.c" -#endif - -void puts(const char *s) -{ -} - -void *memset(void *s, int c, size_t n) -{ - int i; - char *ss = (char *) s; - - for (i = 0; i < n; i++) - ss[i] = c; - return s; -} - -void *memcpy(void *__dest, __const void *__src, size_t __n) -{ - int i; - char *d = (char *) __dest, *s = (char *) __src; - - for (i = 0; i < __n; i++) - d[i] = s[i]; - return __dest; -} - -static void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); - - while (1) ; /* Halt */ -} - -#define STACK_SIZE (4096) -long __attribute__ ((aligned(8))) user_stack[STACK_SIZE]; -long *stack_start = &user_stack[STACK_SIZE]; - -void decompress_kernel(void) -{ - output_data = (unsigned char *) (CONFIG_MEMORY_START + 0x2000); - free_mem_ptr = (unsigned long) &_end; - free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - - puts("Uncompressing Linux... "); - cache_control(CACHE_ENABLE); - decompress(input_data, input_len, NULL, NULL, output_data, NULL, error); - cache_control(CACHE_DISABLE); - puts("Ok, booting the kernel.\n"); -} From 040f43e0bf70935cbe8a775110206d11367e11db Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Sat, 11 Jul 2009 13:36:25 -0400 Subject: [PATCH 026/262] sh64: Don't use PHYSADDR() for output_addr calculation. Opencode the MEMORY_START offset directly, sh64 uses a slightly different calculation. Signed-off-by: Paul Mundt --- arch/sh/boot/compressed/misc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c index 4eb27e61f8e..fd56a71ca9d 100644 --- a/arch/sh/boot/compressed/misc.c +++ b/arch/sh/boot/compressed/misc.c @@ -128,9 +128,13 @@ void decompress_kernel(void) { unsigned long output_addr; +#ifdef CONFIG_SUPERH64 + output_addr = (CONFIG_MEMORY_START + 0x2000); +#else output_addr = PHYSADDR((unsigned long)&_text+PAGE_SIZE); #ifdef CONFIG_29BIT output_addr |= P2SEG; +#endif #endif output = (unsigned char *)output_addr; From 05dd2cd3bb3299540e33ff60c5b401dd88f273bd Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Mon, 13 Jul 2009 11:38:04 +0000 Subject: [PATCH 027/262] sh: Restore previous behaviour on kernel fault The last commit changed the behaviour on kernel faults when we were doing something other than syncing the page tables. vmalloc_sync_one() needs to return NULL if the page tables are up to date, because the reason for the fault was not a missing/inconsitent page table entry. By returning NULL if the page tables are sync'd we signal to the calling function that further work must be done to resolve this fault. Also, remove the superfluous __va() around the first argument to vmalloc_sync_one(). The value of pgd_k is already a virtual address and using it wth __va() causes a NULL dereference. Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/mm/fault_32.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index 08d0117d90f..dbbdeba2cee 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c @@ -60,8 +60,15 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) if (!pmd_present(*pmd)) set_pmd(pmd, *pmd_k); - else + else { + /* + * The page tables are fully synchronised so there must + * be another reason for the fault. Return NULL here to + * signal that we have not taken care of the fault. + */ BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k)); + return NULL; + } return pmd_k; } @@ -87,7 +94,7 @@ static noinline int vmalloc_fault(unsigned long address) * an interrupt in the middle of a task switch.. */ pgd_k = get_TTB(); - pmd_k = vmalloc_sync_one(__va((unsigned long)pgd_k), address); + pmd_k = vmalloc_sync_one(pgd_k, address); if (!pmd_k) return -1; From 72849873cdf213b5d7b8ae006e6740b2d78f6ad8 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 14 Jul 2009 06:51:54 -0400 Subject: [PATCH 028/262] sh: Kill off zero-sized vmlinux_64.lds.S This seems to be some merge damage, kill it off. Signed-off-by: Paul Mundt --- arch/sh/kernel/vmlinux_64.lds.S | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 arch/sh/kernel/vmlinux_64.lds.S diff --git a/arch/sh/kernel/vmlinux_64.lds.S b/arch/sh/kernel/vmlinux_64.lds.S deleted file mode 100644 index e69de29bb2d..00000000000 From 0f8ee1874fa80899debc0a0670e2bed0a28d2548 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 17 Jul 2009 14:24:55 +0000 Subject: [PATCH 029/262] sh: Add support for multiple hwblk counters Extend the SuperH hwblk code to support more than one counter. Contains ground work for the future Runtime PM implementation. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/hwblk.h | 13 ++++- arch/sh/kernel/cpu/hwblk.c | 69 ++++++++++++++++++-------- arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c | 4 +- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/arch/sh/include/asm/hwblk.h b/arch/sh/include/asm/hwblk.h index 51a46f49663..c01d72cb675 100644 --- a/arch/sh/include/asm/hwblk.h +++ b/arch/sh/include/asm/hwblk.h @@ -4,6 +4,9 @@ #include #include +#define HWBLK_CNT_USAGE 0 +#define HWBLK_CNT_NR 1 + #define HWBLK_AREA_FLAG_PARENT (1 << 0) /* valid parent */ #define HWBLK_AREA(_flags, _parent) \ @@ -13,7 +16,7 @@ } struct hwblk_area { - unsigned long cnt; + int cnt[HWBLK_CNT_NR]; unsigned char parent; unsigned char flags; }; @@ -29,7 +32,7 @@ struct hwblk { void __iomem *mstp; unsigned char bit; unsigned char area; - unsigned long cnt; + int cnt[HWBLK_CNT_NR]; }; struct hwblk_info { @@ -46,6 +49,12 @@ int arch_hwblk_sleep_mode(void); int hwblk_register(struct hwblk_info *info); int hwblk_init(void); +void hwblk_enable(struct hwblk_info *info, int hwblk); +void hwblk_disable(struct hwblk_info *info, int hwblk); + +void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int cnt); +void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int cnt); + /* allow clocks to enable and disable hardware blocks */ #define SH_HWBLK_CLK(_name, _id, _parent, _hwblk, _flags) \ { \ diff --git a/arch/sh/kernel/cpu/hwblk.c b/arch/sh/kernel/cpu/hwblk.c index 7c3a73deff2..c0ad7d46e78 100644 --- a/arch/sh/kernel/cpu/hwblk.c +++ b/arch/sh/kernel/cpu/hwblk.c @@ -9,38 +9,64 @@ static DEFINE_SPINLOCK(hwblk_lock); -static void hwblk_area_inc(struct hwblk_info *info, int area) +static void hwblk_area_mod_cnt(struct hwblk_info *info, + int area, int counter, int value, int goal) { struct hwblk_area *hap = info->areas + area; - hap->cnt++; - if (hap->cnt == 1) - if (hap->flags & HWBLK_AREA_FLAG_PARENT) - hwblk_area_inc(info, hap->parent); + hap->cnt[counter] += value; + + if (hap->cnt[counter] != goal) + return; + + if (hap->flags & HWBLK_AREA_FLAG_PARENT) + hwblk_area_mod_cnt(info, hap->parent, counter, value, goal); } -static void hwblk_area_dec(struct hwblk_info *info, int area) + +static int __hwblk_mod_cnt(struct hwblk_info *info, int hwblk, + int counter, int value, int goal) { - struct hwblk_area *hap = info->areas + area; + struct hwblk *hp = info->hwblks + hwblk; - if (hap->cnt == 1) - if (hap->flags & HWBLK_AREA_FLAG_PARENT) - hwblk_area_dec(info, hap->parent); - hap->cnt--; + hp->cnt[counter] += value; + if (hp->cnt[counter] == goal) + hwblk_area_mod_cnt(info, hp->area, counter, value, goal); + + return hp->cnt[counter]; } -static void hwblk_enable(struct hwblk_info *info, int hwblk) +static void hwblk_mod_cnt(struct hwblk_info *info, int hwblk, + int counter, int value, int goal) +{ + unsigned long flags; + + spin_lock_irqsave(&hwblk_lock, flags); + __hwblk_mod_cnt(info, hwblk, counter, value, goal); + spin_unlock_irqrestore(&hwblk_lock, flags); +} + +void hwblk_cnt_inc(struct hwblk_info *info, int hwblk, int counter) +{ + hwblk_mod_cnt(info, hwblk, counter, 1, 1); +} + +void hwblk_cnt_dec(struct hwblk_info *info, int hwblk, int counter) +{ + hwblk_mod_cnt(info, hwblk, counter, -1, 0); +} + +void hwblk_enable(struct hwblk_info *info, int hwblk) { struct hwblk *hp = info->hwblks + hwblk; unsigned long tmp; unsigned long flags; + int ret; spin_lock_irqsave(&hwblk_lock, flags); - hp->cnt++; - if (hp->cnt == 1) { - hwblk_area_inc(info, hp->area); - + ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, 1, 1); + if (ret == 1) { tmp = __raw_readl(hp->mstp); tmp &= ~(1 << hp->bit); __raw_writel(tmp, hp->mstp); @@ -49,27 +75,26 @@ static void hwblk_enable(struct hwblk_info *info, int hwblk) spin_unlock_irqrestore(&hwblk_lock, flags); } -static void hwblk_disable(struct hwblk_info *info, int hwblk) +void hwblk_disable(struct hwblk_info *info, int hwblk) { struct hwblk *hp = info->hwblks + hwblk; unsigned long tmp; unsigned long flags; + int ret; spin_lock_irqsave(&hwblk_lock, flags); - if (hp->cnt == 1) { - hwblk_area_dec(info, hp->area); - + ret = __hwblk_mod_cnt(info, hwblk, HWBLK_CNT_USAGE, -1, 0); + if (ret == 0) { tmp = __raw_readl(hp->mstp); tmp |= 1 << hp->bit; __raw_writel(tmp, hp->mstp); } - hp->cnt--; spin_unlock_irqrestore(&hwblk_lock, flags); } -static struct hwblk_info *hwblk_info; +struct hwblk_info *hwblk_info; int __init hwblk_register(struct hwblk_info *info) { diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c index 00a1c02d82b..a288b5d9234 100644 --- a/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7722.c @@ -91,10 +91,10 @@ static struct hwblk_info sh7722_hwblk_info = { int arch_hwblk_sleep_mode(void) { - if (!sh7722_hwblk_area[CORE_AREA].cnt) + 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) + if (!sh7722_hwblk_area[CORE_AREA_BM].cnt[HWBLK_CNT_USAGE]) return SUSP_SH_SLEEP | SUSP_SH_SF; return SUSP_SH_SLEEP; From 2094e504a7489a2d774d544592360e578d9325f8 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 17 Jul 2009 14:43:38 +0000 Subject: [PATCH 030/262] sh: hwblk support for sh7723 This patch adds hwblk support for the sh7723 processor. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/cpu-sh4/cpu/sh7723.h | 17 ++++ arch/sh/kernel/cpu/sh4a/Makefile | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7723.c | 106 +++++++++++----------- arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c | 117 +++++++++++++++++++++++++ 4 files changed, 191 insertions(+), 51 deletions(-) create mode 100644 arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c diff --git a/arch/sh/include/cpu-sh4/cpu/sh7723.h b/arch/sh/include/cpu-sh4/cpu/sh7723.h index 14c8ca93678..9b36fae7232 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7723.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7723.h @@ -265,4 +265,21 @@ enum { GPIO_FN_IDEA1, GPIO_FN_IDEA0, }; +enum { + HWBLK_UNKNOWN = 0, + HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_L2C, HWBLK_ILMEM, HWBLK_FPU, + HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY, + HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC, HWBLK_SUBC, + HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1, + HWBLK_FLCTL, + HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, + HWBLK_SCIF3, HWBLK_SCIF4, HWBLK_SCIF5, + HWBLK_MSIOF0, HWBLK_MSIOF1, HWBLK_MERAM, HWBLK_IIC, HWBLK_RTC, + HWBLK_ATAPI, HWBLK_ADC, HWBLK_TPU, HWBLK_IRDA, HWBLK_TSIF, HWBLK_ICB, + HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_KEYSC, HWBLK_USB, + HWBLK_2DG, HWBLK_SIU, HWBLK_VEU2H1, HWBLK_VOU, HWBLK_BEU, HWBLK_CEU, + HWBLK_VEU2H0, HWBLK_VPU, HWBLK_LCDC, + HWBLK_NR, +}; + #endif /* __ASM_SH7723_H__ */ diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 3cafda69637..1d7ae38bc61 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -26,7 +26,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 hwblk-sh7722.o -clock-$(CONFIG_CPU_SUBTYPE_SH7723) := clock-sh7723.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 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 e67c2678b8a..bf64c78eee3 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include /* SH7723 registers */ #define FRQCR 0xa4150000 @@ -140,60 +142,64 @@ struct clk div6_clks[] = { SH_CLK_DIV6("video_clk", &pll_clk, VCLKCR, 0), }; -#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \ - SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT) +#define R_CLK (&r_clk) +#define P_CLK (&div4_clks[DIV4_P]) +#define B_CLK (&div4_clks[DIV4_B]) +#define U_CLK (&div4_clks[DIV4_U]) +#define I_CLK (&div4_clks[DIV4_I]) +#define SH_CLK (&div4_clks[DIV4_SH]) static struct clk mstp_clks[] = { /* See page 60 of Datasheet V1.0: Overview -> Block Diagram */ - MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0), - MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0), - MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0), - MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 28, 1, 1, 0), - MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0), - MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0), - MSTP("intc0", &div4_clks[DIV4_I], MSTPCR0, 22, 1, 1, 0), - MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1), - MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0), - MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0), - MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0), - MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0), - MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0), - MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0), - MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1), - MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 11, 0, 1, 0), - MSTP("flctl0", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0), - MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0), - MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0), - MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0), - MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0), - MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0), - MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0), - MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0), - MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0), - MSTP("meram0", &div4_clks[DIV4_SH], MSTPCR0, 0, 1, 1, 0), + SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("intc0", -1, I_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0), + SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0), + SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0), + SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0), + SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), + SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), + SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), + SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0), + SH_HWBLK_CLK("flctl0", -1, P_CLK, HWBLK_FLCTL, 0), + SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0), + SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0), + SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0), + SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), + SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), + SH_HWBLK_CLK("meram0", -1, SH_CLK, HWBLK_MERAM, 0), - MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0), - MSTP("rtc0", &r_clk, MSTPCR1, 8, 0, 0, 0), + SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC, 0), + SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), - MSTP("atapi0", &div4_clks[DIV4_SH], MSTPCR2, 28, 0, 1, 0), - MSTP("adc0", &div4_clks[DIV4_P], MSTPCR2, 27, 0, 1, 0), - MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0), - MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0), - MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0), - MSTP("icb0", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1), - MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0), - MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0), - MSTP("keysc0", &r_clk, MSTPCR2, 14, 0, 0, 0), - MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 11, 0, 1, 0), - MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 10, 0, 1, 1), - MSTP("siu0", &div4_clks[DIV4_B], MSTPCR2, 8, 0, 1, 0), - MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1), - MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1), - MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1), - MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1), - MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1), - MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1), - MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1), + SH_HWBLK_CLK("atapi0", -1, SH_CLK, HWBLK_ATAPI, 0), + SH_HWBLK_CLK("adc0", -1, P_CLK, HWBLK_ADC, 0), + SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0), + SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0), + SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0), + SH_HWBLK_CLK("icb0", -1, B_CLK, HWBLK_ICB, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0), + SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0), + SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0), + SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB, 0), + SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0), + SH_HWBLK_CLK("siu0", -1, B_CLK, HWBLK_SIU, 0), + SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU2H1, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0), + SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU, 0), + SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU, 0), + SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU2H0, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), }; int __init arch_clk_init(void) @@ -216,7 +222,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks)); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c new file mode 100644 index 00000000000..a7f4684d203 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7723.c @@ -0,0 +1,117 @@ +/* + * 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); +} From ae1cef6ea155328905cb359ec7c2a47776d2d4d4 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 17 Jul 2009 14:52:05 +0000 Subject: [PATCH 031/262] usb: convert r8a66597-hcd to dev_pm_ops Convert the r8a66597-hcd driver to dev_pm_ops. This makes the driver a good PM citizen and removes a warning printout. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/usb/host/r8a66597-hcd.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index e18f74946e6..09895a97c10 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2305,9 +2305,9 @@ static struct hc_driver r8a66597_hc_driver = { }; #if defined(CONFIG_PM) -static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) +static int r8a66597_suspend(struct device *dev) { - struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); + struct r8a66597 *r8a66597 = dev_get_drvdata(dev); int port; dbg("%s", __func__); @@ -2323,9 +2323,9 @@ static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int r8a66597_resume(struct platform_device *pdev) +static int r8a66597_resume(struct device *dev) { - struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); + struct r8a66597 *r8a66597 = dev_get_drvdata(dev); struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); dbg("%s", __func__); @@ -2335,9 +2335,15 @@ static int r8a66597_resume(struct platform_device *pdev) return 0; } + +static struct dev_pm_ops r8a66597_dev_pm_ops = { + .suspend = r8a66597_suspend, + .resume = r8a66597_resume, +}; + +#define R8A66597_DEV_PM_OPS (&r8a66597_dev_pm_ops) #else /* if defined(CONFIG_PM) */ -#define r8a66597_suspend NULL -#define r8a66597_resume NULL +#define R8A66597_DEV_PM_OPS NULL #endif static int __init_or_module r8a66597_remove(struct platform_device *pdev) @@ -2473,11 +2479,10 @@ clean_up: static struct platform_driver r8a66597_driver = { .probe = r8a66597_probe, .remove = r8a66597_remove, - .suspend = r8a66597_suspend, - .resume = r8a66597_resume, .driver = { .name = (char *) hcd_name, .owner = THIS_MODULE, + .pm = R8A66597_DEV_PM_OPS, }, }; From 719a72b7c75bb239ca6184190ab994b71a31c6dc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 17 Jul 2009 14:59:55 +0000 Subject: [PATCH 032/262] usb: r8a66597-hcd platform data on_chip support Convert the r8a66597-hcd driver to use the on_chip flag from platform data to enable on chip behaviour instead of relying on CONFIG_SUPERH_ON_CHIP_R8A66597 ugliness. This makes the code cleaner and also allows us to support both external and internal r8a66597 with the same kernel. It also makes the Kconfig part more future proof since we with this patch can add support for new processors with on-chip r8a66597 without modifying the Kconfig. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-se/7724/setup.c | 1 + arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 2 +- drivers/usb/host/Kconfig | 7 - drivers/usb/host/r8a66597-hcd.c | 189 ++++++++++++++----------- drivers/usb/host/r8a66597.h | 76 +++++----- include/linux/usb/r8a66597.h | 3 + 7 files changed, 148 insertions(+), 132 deletions(-) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 8fed45a2fb8..4fb7e48e284 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -304,6 +304,7 @@ static struct platform_device sh_eth_device = { }; static struct r8a66597_platdata sh7724_usb0_host_data = { + .on_chip = 1, }; static struct resource sh7724_usb0_host_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index c18f7d09281..f6d20881356 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -40,7 +40,7 @@ static struct platform_device iic_device = { }; static struct r8a66597_platdata r8a66597_data = { - /* This set zero to all members */ + .on_chip = 1, }; static struct resource usb_host_resources[] = { diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index e1bb80b2a27..28516499a2c 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -398,7 +398,7 @@ static struct platform_device rtc_device = { }; static struct r8a66597_platdata r8a66597_data = { - /* This set zero to all members */ + .on_chip = 1, }; static struct resource sh7723_usb_host_resources[] = { diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 1a920c70b5a..f21ca7d27a4 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -336,13 +336,6 @@ config USB_R8A66597_HCD To compile this driver as a module, choose M here: the module will be called r8a66597-hcd. -config SUPERH_ON_CHIP_R8A66597 - boolean "Enable SuperH on-chip R8A66597 USB" - depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724) - help - This driver enables support for the on-chip R8A66597 in the - SH7366, SH7723 and SH7724 processors. - config USB_WHCI_HCD tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 09895a97c10..82dce3e0d4d 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -91,43 +91,43 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597) u16 tmp; int i = 0; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#if defined(CONFIG_HAVE_CLK) - clk_enable(r8a66597->clk); + if (r8a66597->pdata->on_chip) { +#ifdef CONFIG_HAVE_CLK + clk_enable(r8a66597->clk); #endif - do { - r8a66597_write(r8a66597, SCKE, SYSCFG0); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 1000) { - printk(KERN_ERR "r8a66597: register access fail.\n"); - return -ENXIO; - } - } while ((tmp & SCKE) != SCKE); - r8a66597_write(r8a66597, 0x04, 0x02); -#else - do { - r8a66597_write(r8a66597, USBE, SYSCFG0); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 1000) { - printk(KERN_ERR "r8a66597: register access fail.\n"); - return -ENXIO; - } - } while ((tmp & USBE) != USBE); - r8a66597_bclr(r8a66597, USBE, SYSCFG0); - r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata), XTAL, - SYSCFG0); + do { + r8a66597_write(r8a66597, SCKE, SYSCFG0); + tmp = r8a66597_read(r8a66597, SYSCFG0); + if (i++ > 1000) { + printk(KERN_ERR "r8a66597: reg access fail.\n"); + return -ENXIO; + } + } while ((tmp & SCKE) != SCKE); + r8a66597_write(r8a66597, 0x04, 0x02); + } else { + do { + r8a66597_write(r8a66597, USBE, SYSCFG0); + tmp = r8a66597_read(r8a66597, SYSCFG0); + if (i++ > 1000) { + printk(KERN_ERR "r8a66597: reg access fail.\n"); + return -ENXIO; + } + } while ((tmp & USBE) != USBE); + r8a66597_bclr(r8a66597, USBE, SYSCFG0); + r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata), + XTAL, SYSCFG0); - i = 0; - r8a66597_bset(r8a66597, XCKE, SYSCFG0); - do { - msleep(1); - tmp = r8a66597_read(r8a66597, SYSCFG0); - if (i++ > 500) { - printk(KERN_ERR "r8a66597: register access fail.\n"); - return -ENXIO; - } - } while ((tmp & SCKE) != SCKE); -#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ + i = 0; + r8a66597_bset(r8a66597, XCKE, SYSCFG0); + do { + msleep(1); + tmp = r8a66597_read(r8a66597, SYSCFG0); + if (i++ > 500) { + printk(KERN_ERR "r8a66597: reg access fail.\n"); + return -ENXIO; + } + } while ((tmp & SCKE) != SCKE); + } return 0; } @@ -136,15 +136,16 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597) { r8a66597_bclr(r8a66597, SCKE, SYSCFG0); udelay(1); -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#if defined(CONFIG_HAVE_CLK) - clk_disable(r8a66597->clk); -#endif -#else - r8a66597_bclr(r8a66597, PLLC, SYSCFG0); - r8a66597_bclr(r8a66597, XCKE, SYSCFG0); - r8a66597_bclr(r8a66597, USBE, SYSCFG0); + + if (r8a66597->pdata->on_chip) { +#ifdef CONFIG_HAVE_CLK + clk_disable(r8a66597->clk); #endif + } else { + r8a66597_bclr(r8a66597, PLLC, SYSCFG0); + r8a66597_bclr(r8a66597, XCKE, SYSCFG0); + r8a66597_bclr(r8a66597, USBE, SYSCFG0); + } } static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port) @@ -205,7 +206,7 @@ static int enable_controller(struct r8a66597 *r8a66597) r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1); - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) + for (port = 0; port < r8a66597->max_root_hub; port++) r8a66597_enable_port(r8a66597, port); return 0; @@ -218,7 +219,7 @@ static void disable_controller(struct r8a66597 *r8a66597) r8a66597_write(r8a66597, 0, INTENB0); r8a66597_write(r8a66597, 0, INTSTS0); - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) + for (port = 0; port < r8a66597->max_root_hub; port++) r8a66597_disable_port(r8a66597, port); r8a66597_clock_disable(r8a66597); @@ -249,11 +250,12 @@ static int is_hub_limit(char *devpath) return ((strlen(devpath) >= 4) ? 1 : 0); } -static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port) +static void get_port_number(struct r8a66597 *r8a66597, + char *devpath, u16 *root_port, u16 *hub_port) { if (root_port) { *root_port = (devpath[0] & 0x0F) - 1; - if (*root_port >= R8A66597_MAX_ROOT_HUB) + if (*root_port >= r8a66597->max_root_hub) printk(KERN_ERR "r8a66597: Illegal root port number.\n"); } if (hub_port) @@ -355,7 +357,8 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597, INIT_LIST_HEAD(&dev->device_list); list_add_tail(&dev->device_list, &r8a66597->child_device); - get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port); + get_port_number(r8a66597, urb->dev->devpath, + &dev->root_port, &dev->hub_port); if (!is_child_device(urb->dev->devpath)) r8a66597->root_hub[dev->root_port].dev = dev; @@ -420,7 +423,7 @@ static void free_usb_address(struct r8a66597 *r8a66597, list_del(&dev->device_list); kfree(dev); - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + for (port = 0; port < r8a66597->max_root_hub; port++) { if (r8a66597->root_hub[port].dev == dev) { r8a66597->root_hub[port].dev = NULL; break; @@ -495,10 +498,20 @@ static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597, r8a66597_bset(r8a66597, SQCLR, pipe->pipectr); } +static inline unsigned short mbw_value(struct r8a66597 *r8a66597) +{ + if (r8a66597->pdata->on_chip) + return MBW_32; + else + return MBW_16; +} + /* this function must be called with interrupt disabled */ static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum) { - r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL); + unsigned short mbw = mbw_value(r8a66597); + + r8a66597_mdfy(r8a66597, mbw | pipenum, mbw | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum); } @@ -506,11 +519,13 @@ static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum) static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe) { - cfifo_change(r8a66597, 0); - r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL); - r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL); + unsigned short mbw = mbw_value(r8a66597); - r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE, + cfifo_change(r8a66597, 0); + r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D0FIFOSEL); + r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D1FIFOSEL); + + r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum, mbw | CURPIPE, pipe->fifosel); r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum); } @@ -742,9 +757,13 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe, struct urb *urb) { -#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597) int i; struct r8a66597_pipe_info *info = &pipe->info; + unsigned short mbw = mbw_value(r8a66597); + + /* pipe dma is only for external controlles */ + if (r8a66597->pdata->on_chip) + return; if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) { for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) { @@ -763,8 +782,8 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, set_pipe_reg_addr(pipe, i); cfifo_change(r8a66597, 0); - r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, - MBW | CURPIPE, pipe->fifosel); + r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum, + mbw | CURPIPE, pipe->fifosel); r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum); @@ -772,7 +791,6 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, break; } } -#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ } /* this function must be called with interrupt disabled */ @@ -1769,7 +1787,7 @@ static void r8a66597_timer(unsigned long _r8a66597) spin_lock_irqsave(&r8a66597->lock, flags); - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) + for (port = 0; port < r8a66597->max_root_hub; port++) r8a66597_root_hub_control(r8a66597, port); spin_unlock_irqrestore(&r8a66597->lock, flags); @@ -1807,7 +1825,7 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb) u16 root_port, hub_port; if (usb_address == 0) { - get_port_number(urb->dev->devpath, + get_port_number(r8a66597, urb->dev->devpath, &root_port, &hub_port); set_devadd_reg(r8a66597, 0, get_r8a66597_usb_speed(urb->dev->speed), @@ -2082,7 +2100,7 @@ static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf) *buf = 0; /* initialize (no change) */ - for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) { + for (i = 0; i < r8a66597->max_root_hub; i++) { if (r8a66597->root_hub[i].port & 0xffff0000) *buf |= 1 << (i + 1); } @@ -2097,11 +2115,11 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597, { desc->bDescriptorType = 0x29; desc->bHubContrCurrent = 0; - desc->bNbrPorts = R8A66597_MAX_ROOT_HUB; + desc->bNbrPorts = r8a66597->max_root_hub; desc->bDescLength = 9; desc->bPwrOn2PwrGood = 0; desc->wHubCharacteristics = cpu_to_le16(0x0011); - desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1; + desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1; desc->bitmap[1] = ~0; } @@ -2129,7 +2147,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, } break; case ClearPortFeature: - if (wIndex > R8A66597_MAX_ROOT_HUB) + if (wIndex > r8a66597->max_root_hub) goto error; if (wLength != 0) goto error; @@ -2162,12 +2180,12 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, *buf = 0x00; break; case GetPortStatus: - if (wIndex > R8A66597_MAX_ROOT_HUB) + if (wIndex > r8a66597->max_root_hub) goto error; *(__le32 *)buf = cpu_to_le32(rh->port); break; case SetPortFeature: - if (wIndex > R8A66597_MAX_ROOT_HUB) + if (wIndex > r8a66597->max_root_hub) goto error; if (wLength != 0) goto error; @@ -2216,7 +2234,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd) dbg("%s", __func__); - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + for (port = 0; port < r8a66597->max_root_hub; port++) { struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; unsigned long dvstctr_reg = get_dvstctr_reg(port); @@ -2247,7 +2265,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd) dbg("%s", __func__); - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + for (port = 0; port < r8a66597->max_root_hub; port++) { struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; unsigned long dvstctr_reg = get_dvstctr_reg(port); @@ -2314,7 +2332,7 @@ static int r8a66597_suspend(struct device *dev) disable_controller(r8a66597); - for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + for (port = 0; port < r8a66597->max_root_hub; port++) { struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; rh->port = 0x00000000; @@ -2354,8 +2372,9 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev) del_timer_sync(&r8a66597->rh_timer); usb_remove_hcd(hcd); iounmap((void *)r8a66597->reg); -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) - clk_put(r8a66597->clk); +#ifdef CONFIG_HAVE_CLK + if (r8a66597->pdata->on_chip) + clk_put(r8a66597->clk); #endif usb_put_hcd(hcd); return 0; @@ -2363,7 +2382,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev) static int __devinit r8a66597_probe(struct platform_device *pdev) { -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) +#ifdef CONFIG_HAVE_CLK char clk_name[8]; #endif struct resource *res = NULL, *ires; @@ -2425,15 +2444,20 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) r8a66597->pdata = pdev->dev.platform_data; r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) - snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id); - r8a66597->clk = clk_get(&pdev->dev, clk_name); - if (IS_ERR(r8a66597->clk)) { - dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); - ret = PTR_ERR(r8a66597->clk); - goto clean_up2; - } + if (r8a66597->pdata->on_chip) { +#ifdef CONFIG_HAVE_CLK + snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id); + r8a66597->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(r8a66597->clk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", + clk_name); + ret = PTR_ERR(r8a66597->clk); + goto clean_up2; + } #endif + r8a66597->max_root_hub = 1; + } else + r8a66597->max_root_hub = 2; spin_lock_init(&r8a66597->lock); init_timer(&r8a66597->rh_timer); @@ -2463,8 +2487,9 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) return 0; clean_up3: -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) - clk_put(r8a66597->clk); +#ifdef CONFIG_HAVE_CLK + if (r8a66597->pdata->on_chip) + clk_put(r8a66597->clk); clean_up2: #endif usb_put_hcd(hcd); diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index d72680b433f..eecbd917bc8 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -26,7 +26,7 @@ #ifndef __R8A66597_H__ #define __R8A66597_H__ -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) +#ifdef CONFIG_HAVE_CLK #include #endif @@ -193,13 +193,9 @@ #define REW 0x4000 /* b14: Buffer rewind */ #define DCLRM 0x2000 /* b13: DMA buffer clear mode */ #define DREQE 0x1000 /* b12: DREQ output enable */ -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#define MBW 0x0800 -#else -#define MBW 0x0400 /* b10: Maximum bit width for FIFO access */ -#endif #define MBW_8 0x0000 /* 8bit */ #define MBW_16 0x0400 /* 16bit */ +#define MBW_32 0x0800 /* 32bit */ #define BIGEND 0x0100 /* b8: Big endian mode */ #define BYTE_LITTLE 0x0000 /* little dendian */ #define BYTE_BIG 0x0100 /* big endifan */ @@ -405,11 +401,7 @@ #define R8A66597_MAX_NUM_PIPE 10 #define R8A66597_BUF_BSIZE 8 #define R8A66597_MAX_DEVICE 10 -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) -#define R8A66597_MAX_ROOT_HUB 1 -#else #define R8A66597_MAX_ROOT_HUB 2 -#endif #define R8A66597_MAX_SAMPLING 5 #define R8A66597_RH_POLL_TIME 10 #define R8A66597_MAX_DMA_CHANNEL 2 @@ -487,7 +479,7 @@ struct r8a66597_root_hub { struct r8a66597 { spinlock_t lock; unsigned long reg; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK) +#ifdef CONFIG_HAVE_CLK struct clk *clk; #endif struct r8a66597_platdata *pdata; @@ -504,6 +496,7 @@ struct r8a66597 { unsigned short interval_map; unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE]; unsigned char dma_map; + unsigned int max_root_hub; struct list_head child_device; unsigned long child_connect_map[4]; @@ -550,21 +543,22 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, unsigned long offset, u16 *buf, int len) { -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) unsigned long fifoaddr = r8a66597->reg + offset; unsigned long count; - count = len / 4; - insl(fifoaddr, buf, count); + if (r8a66597->pdata->on_chip) { + count = len / 4; + insl(fifoaddr, buf, count); - if (len & 0x00000003) { - unsigned long tmp = inl(fifoaddr); - memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03); + if (len & 0x00000003) { + unsigned long tmp = inl(fifoaddr); + memcpy((unsigned char *)buf + count * 4, &tmp, + len & 0x03); + } + } else { + len = (len + 1) / 2; + insw(fifoaddr, buf, len); } -#else - len = (len + 1) / 2; - insw(r8a66597->reg + offset, buf, len); -#endif } static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, @@ -578,33 +572,33 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, int len) { unsigned long fifoaddr = r8a66597->reg + offset; -#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) unsigned long count; unsigned char *pb; int i; - count = len / 4; - outsl(fifoaddr, buf, count); + if (r8a66597->pdata->on_chip) { + count = len / 4; + outsl(fifoaddr, buf, count); - if (len & 0x00000003) { - pb = (unsigned char *)buf + count * 4; - for (i = 0; i < (len & 0x00000003); i++) { - if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) - outb(pb[i], fifoaddr + i); - else - outb(pb[i], fifoaddr + 3 - i); + if (len & 0x00000003) { + pb = (unsigned char *)buf + count * 4; + for (i = 0; i < (len & 0x00000003); i++) { + if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) + outb(pb[i], fifoaddr + i); + else + outb(pb[i], fifoaddr + 3 - i); + } + } + } else { + int odd = len & 0x0001; + + len = len / 2; + outsw(fifoaddr, buf, len); + if (unlikely(odd)) { + buf = &buf[len]; + outb((unsigned char)*buf, fifoaddr); } } -#else - int odd = len & 0x0001; - - len = len / 2; - outsw(fifoaddr, buf, len); - if (unlikely(odd)) { - buf = &buf[len]; - outb((unsigned char)*buf, fifoaddr); - } -#endif } static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, diff --git a/include/linux/usb/r8a66597.h b/include/linux/usb/r8a66597.h index e9f0384fa20..460ee3f6a2c 100644 --- a/include/linux/usb/r8a66597.h +++ b/include/linux/usb/r8a66597.h @@ -31,6 +31,9 @@ struct r8a66597_platdata { /* This ops can controll port power instead of DVSTCTR register. */ void (*port_power)(int port, int power); + /* set one = on chip controller, set zero = external controller */ + unsigned on_chip:1; + /* (external controller only) set R8A66597_PLATDATA_XTAL_nnMHZ */ unsigned xtal:2; From 6bde607e699b9f3c6fa5e4a97d78c7778e643b3d Mon Sep 17 00:00:00 2001 From: Tim Abbott Date: Mon, 20 Jul 2009 23:30:24 +0900 Subject: [PATCH 033/262] sh: Clean up linker script using new BSS_SECTION macro. Updated to use the fixed BSS linker script macros from this thread: http://www.spinics.net/lists/kernel/msg913238.html Signed-off-by: Tim Abbott Cc: Sam Ravnborg Cc: linux-sh@vger.kernel.org Signed-off-by: Paul Mundt --- arch/sh/kernel/vmlinux.lds.S | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 674ed8feb8a..80dc9f8d941 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -93,8 +93,7 @@ SECTIONS . = ALIGN(PAGE_SIZE); __init_end = .; - BSS(PAGE_SIZE) - . = ALIGN(4); + BSS_SECTION(0, PAGE_SIZE, 4) _ebss = .; /* uClinux MTD sucks */ _end = . ; From ef9b542fce00dafc6bb1d9097b045a777f4a2382 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 21 Jul 2009 17:24:36 +0900 Subject: [PATCH 034/262] sh: bzip2/lzma uImage support. This builds on the bzip2/lzma zImage support change and wires it up for uImages. Based on the blackfin implementation. Signed-off-by: Paul Mundt --- arch/sh/Makefile | 15 ++++++++---- arch/sh/boot/.gitignore | 5 ++-- arch/sh/boot/Makefile | 39 +++++++++++++++++++++++--------- arch/sh/boot/compressed/Makefile | 4 ---- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 75d049b03f7..2aba73eccb3 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -189,14 +189,16 @@ KBUILD_AFLAGS += $(cflags-y) libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) -PHONY += maketools FORCE +BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec \ + zImage vmlinux.srec +PHONY += maketools $(BOOT_TARGETS) FORCE maketools: include/linux/version.h FORCE $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h all: $(KBUILD_IMAGE) -zImage uImage uImage.srec vmlinux.srec: vmlinux +$(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ compressed: zImage @@ -208,10 +210,13 @@ archclean: $(Q)$(MAKE) $(clean)=arch/sh/kernel/vsyscall define archhelp - @echo '* zImage - Compressed kernel image' + @echo ' zImage - Compressed kernel image' @echo ' vmlinux.srec - Create an ELF S-record' - @echo ' uImage - Create a bootable image for U-Boot' - @echo ' uImage.srec - Create an S-record for U-Boot' + @echo '* uImage - Alias to bootable U-Boot image' + @echo ' uImage.srec - Create an S-record for U-Boot' + @echo '* uImage.gz - Kernel-only image for U-Boot (gzip)' + @echo ' uImage.bz2 - Kernel-only image for U-Boot (bzip2)' + @echo ' uImage.lzma - Kernel-only image for U-Boot (lzma)' endef CLEAN_FILES += include/asm-sh/machtypes.h diff --git a/arch/sh/boot/.gitignore b/arch/sh/boot/.gitignore index aad5edddf93..541087d2029 100644 --- a/arch/sh/boot/.gitignore +++ b/arch/sh/boot/.gitignore @@ -1,4 +1,3 @@ zImage -vmlinux.srec -uImage -uImage.srec +vmlinux* +uImage* diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile index 78efb04c28f..dd2a852041e 100644 --- a/arch/sh/boot/Makefile +++ b/arch/sh/boot/Makefile @@ -20,7 +20,12 @@ CONFIG_BOOT_LINK_OFFSET ?= 0x00800000 CONFIG_ZERO_PAGE_OFFSET ?= 0x00001000 CONFIG_ENTRY_OFFSET ?= 0x00001000 -targets := zImage vmlinux.srec uImage uImage.srec +suffix-$(CONFIG_KERNEL_GZIP) := gz +suffix-$(CONFIG_KERNEL_BZIP2) := bz2 +suffix-$(CONFIG_KERNEL_LZMA) := lzma + +targets := zImage vmlinux.srec uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma +extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma subdir- := compressed $(obj)/zImage: $(obj)/compressed/vmlinux FORCE @@ -40,9 +45,6 @@ KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \ $$[$(CONFIG_MEMORY_START)]') endif -export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \ - CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY - KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%08x" \ $$[$(CONFIG_PAGE_OFFSET) + \ $(KERNEL_MEMORY) + \ @@ -55,19 +57,30 @@ KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%08x" \ quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \ - -C gzip -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \ + -C $(2) -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \ -n 'Linux-$(KERNELRELEASE)' -d $< $@ -$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE - $(call if_changed,uimage) - @echo ' Image $@ is ready' - $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) $(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) +$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE + $(call if_changed,bzip2) + +$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE + $(call if_changed,lzma) + +$(obj)/uImage.bz2: $(obj)/vmlinux.bin.bz2 + $(call if_changed,uimage,bzip2) + +$(obj)/uImage.gz: $(obj)/vmlinux.bin.gz + $(call if_changed,uimage,gzip) + +$(obj)/uImage.lzma: $(obj)/vmlinux.bin.lzma + $(call if_changed,uimage,lzma) + OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec $(obj)/vmlinux.srec: $(obj)/compressed/vmlinux $(call if_changed,objcopy) @@ -76,5 +89,9 @@ OBJCOPYFLAGS_uImage.srec := -I binary -O srec $(obj)/uImage.srec: $(obj)/uImage $(call if_changed,objcopy) -clean-files += uImage uImage.srec vmlinux.srec \ - vmlinux.bin vmlinux.bin.gz +$(obj)/uImage: $(obj)/uImage.$(suffix-y) + @ln -sf $(notdir $<) $@ + @echo ' Image $@ is ready' + +export CONFIG_PAGE_OFFSET CONFIG_MEMORY_START CONFIG_BOOT_LINK_OFFSET \ + CONFIG_ZERO_PAGE_OFFSET CONFIG_ENTRY_OFFSET KERNEL_MEMORY suffix-y diff --git a/arch/sh/boot/compressed/Makefile b/arch/sh/boot/compressed/Makefile index 3324019e207..b31618e9e8c 100644 --- a/arch/sh/boot/compressed/Makefile +++ b/arch/sh/boot/compressed/Makefile @@ -48,10 +48,6 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE $(call if_changed,lzma) -suffix-$(CONFIG_KERNEL_GZIP) := gz -suffix-$(CONFIG_KERNEL_BZIP2) := bz2 -suffix-$(CONFIG_KERNEL_LZMA) := lzma - OBJCOPYFLAGS += -R .empty_zero_page LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T From c0b96cf639aa1bfa8983f734d4225091aa813e00 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 22 Jul 2009 16:50:57 +0900 Subject: [PATCH 035/262] sh: Provide _PAGE_SPECIAL for 32-bit. Allocate one of the unused PTE bits for _PAGE_SPECIAL directly. This is prep work for fast gup and the zero page revival. Signed-off-by: Paul Mundt --- arch/sh/include/asm/pgtable_32.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/sh/include/asm/pgtable_32.h b/arch/sh/include/asm/pgtable_32.h index 72ea209195b..0db19db913c 100644 --- a/arch/sh/include/asm/pgtable_32.h +++ b/arch/sh/include/asm/pgtable_32.h @@ -20,7 +20,7 @@ * - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE. * * - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages. - * Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused. + * Bit 10 is used for _PAGE_ACCESSED, and bit 11 is used for _PAGE_SPECIAL. * * - On 29 bit platforms, bits 31 to 29 are used for the space attributes * and timing control which (together with bit 0) are moved into the @@ -52,6 +52,7 @@ #define _PAGE_PROTNONE 0x200 /* software: if not present */ #define _PAGE_ACCESSED 0x400 /* software: page referenced */ #define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */ +#define _PAGE_SPECIAL 0x800 /* software: special page */ #define _PAGE_SZ_MASK (_PAGE_SZ0 | _PAGE_SZ1) #define _PAGE_PR_MASK (_PAGE_RW | _PAGE_USER) @@ -148,8 +149,12 @@ # define _PAGE_SZHUGE (_PAGE_FLAGS_HARD) #endif +/* + * Mask of bits that are to be preserved accross pgprot changes. + */ #define _PAGE_CHG_MASK \ - (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY) + (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_SPECIAL) #ifndef __ASSEMBLY__ @@ -328,7 +333,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte) #define pte_dirty(pte) ((pte).pte_low & _PAGE_DIRTY) #define pte_young(pte) ((pte).pte_low & _PAGE_ACCESSED) #define pte_file(pte) ((pte).pte_low & _PAGE_FILE) -#define pte_special(pte) (0) +#define pte_special(pte) ((pte).pte_low & _PAGE_SPECIAL) #ifdef CONFIG_X2TLB #define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE) @@ -358,8 +363,9 @@ PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY); PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY); PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED); PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED); +PTE_BIT_FUNC(low, mkspecial, |= _PAGE_SPECIAL); -static inline pte_t pte_mkspecial(pte_t pte) { return pte; } +#define __HAVE_ARCH_PTE_SPECIAL /* * Macro and implementation to make a page protection as uncachable. From 2277ab4a1df50e05bc732fe9488d4e902bb8399a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 22 Jul 2009 19:20:49 +0900 Subject: [PATCH 036/262] sh: Migrate from PG_mapped to PG_dcache_dirty. This inverts the delayed dcache flush a bit to be more in line with other platforms. At the same time this also gives us the ability to do some more optimizations and cleanup. Now that the update_mmu_cache() callsite only tests for the bit, the implementation can gradually be split out and made generic, rather than relying on special implementations for each of the peculiar CPU types. SH7705 in 32kB mode and SH-4 still need slightly different handling, but this is something that can remain isolated in the varying page copy/clear routines. On top of that, SH-X3 is dcache coherent, so there is no need to bother with any of these tests in the PTEAEX version of update_mmu_cache(), so we kill that off too. Signed-off-by: Paul Mundt --- arch/sh/include/asm/page.h | 6 ++ arch/sh/include/asm/pgtable.h | 7 --- arch/sh/include/cpu-sh3/cpu/cacheflush.h | 5 +- arch/sh/include/cpu-sh4/cpu/cacheflush.h | 2 +- arch/sh/mm/cache-sh4.c | 10 +++- arch/sh/mm/cache-sh7705.c | 7 ++- arch/sh/mm/pg-sh4.c | 74 ++++++++++-------------- arch/sh/mm/pg-sh7705.c | 54 +++-------------- arch/sh/mm/tlb-pteaex.c | 17 ------ arch/sh/mm/tlb-sh3.c | 20 +++---- arch/sh/mm/tlb-sh4.c | 23 ++++---- 11 files changed, 82 insertions(+), 143 deletions(-) diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 49592c780a6..a31ab40040f 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -50,6 +50,12 @@ extern unsigned long shm_align_mask; extern unsigned long max_low_pfn, min_low_pfn; extern unsigned long memory_start, memory_end; +static inline unsigned long +pages_do_alias(unsigned long addr1, unsigned long addr2) +{ + return (addr1 ^ addr2) & shm_align_mask; +} + extern void clear_page(void *to); extern void copy_page(void *to, void *from); diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index 2a011b18090..d9f68f9c3cb 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -133,13 +133,6 @@ typedef pte_t *pte_addr_t; */ #define pgtable_cache_init() do { } while (0) -#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ - defined(CONFIG_SH7705_CACHE_32KB)) -struct mm_struct; -#define __HAVE_ARCH_PTEP_GET_AND_CLEAR -pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); -#endif - struct vm_area_struct; extern void update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte); diff --git a/arch/sh/include/cpu-sh3/cpu/cacheflush.h b/arch/sh/include/cpu-sh3/cpu/cacheflush.h index 1ac27aae670..6485ad5649a 100644 --- a/arch/sh/include/cpu-sh3/cpu/cacheflush.h +++ b/arch/sh/include/cpu-sh3/cpu/cacheflush.h @@ -15,10 +15,7 @@ * SH4. Unlike the SH4 this is a unified cache so we need to do some work * in mmap when 'exec'ing a new binary */ - /* 32KB cache, 4kb PAGE sizes need to check bit 12 */ -#define CACHE_ALIAS 0x00001000 - -#define PG_mapped PG_arch_1 +#define PG_dcache_dirty PG_arch_1 void flush_cache_all(void); void flush_cache_mm(struct mm_struct *mm); diff --git a/arch/sh/include/cpu-sh4/cpu/cacheflush.h b/arch/sh/include/cpu-sh4/cpu/cacheflush.h index 065306d376e..3564f172219 100644 --- a/arch/sh/include/cpu-sh4/cpu/cacheflush.h +++ b/arch/sh/include/cpu-sh4/cpu/cacheflush.h @@ -38,6 +38,6 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, /* Initialization of P3 area for copy_user_page */ void p3_cache_init(void); -#define PG_mapped PG_arch_1 +#define PG_dcache_dirty PG_arch_1 #endif /* __ASM_CPU_SH4_CACHEFLUSH_H */ diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index 5cfe08dbb59..c3a09b27f8d 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -246,7 +247,14 @@ static inline void flush_cache_4096(unsigned long start, */ void flush_dcache_page(struct page *page) { - if (test_bit(PG_mapped, &page->flags)) { + struct address_space *mapping = page_mapping(page); + +#ifndef CONFIG_SMP + if (mapping && !mapping_mapped(mapping)) + set_bit(PG_dcache_dirty, &page->flags); + else +#endif + { unsigned long phys = PHYSADDR(page_address(page)); unsigned long addr = CACHE_OC_ADDRESS_ARRAY; int i, n; diff --git a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c index 22dacc77882..fa37bff306b 100644 --- a/arch/sh/mm/cache-sh7705.c +++ b/arch/sh/mm/cache-sh7705.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -128,7 +129,11 @@ static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys) */ void flush_dcache_page(struct page *page) { - if (test_bit(PG_mapped, &page->flags)) + struct address_space *mapping = page_mapping(page); + + if (mapping && !mapping_mapped(mapping)) + set_bit(PG_dcache_dirty, &page->flags); + else __flush_dcache_page(PHYSADDR(page_address(page))); } diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index 2fe14da1f83..f3c4b2a54fc 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -15,8 +15,6 @@ #include #include -#define CACHE_ALIAS (current_cpu_data.dcache.alias_mask) - #define kmap_get_fixmap_pte(vaddr) \ pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr)) @@ -68,10 +66,9 @@ static inline void kunmap_coherent(struct page *page) */ void clear_user_page(void *to, unsigned long address, struct page *page) { - __set_bit(PG_mapped, &page->flags); - clear_page(to); - if ((((address & PAGE_MASK) ^ (unsigned long)to) & CACHE_ALIAS)) + + if (pages_do_alias((unsigned long)to, address & PAGE_MASK)) __flush_wback_region(to, PAGE_SIZE); } @@ -79,13 +76,14 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - void *vto; - - __set_bit(PG_mapped, &page->flags); - - vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); - memcpy(vto, src, len); - kunmap_coherent(vto); + if (page_mapped(page) && !test_bit(PG_dcache_dirty, &page->flags)) { + void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(vto, src, len); + kunmap_coherent(vto); + } else { + memcpy(dst, src, len); + set_bit(PG_dcache_dirty, &page->flags); + } if (vma->vm_flags & VM_EXEC) flush_cache_page(vma, vaddr, page_to_pfn(page)); @@ -95,13 +93,14 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - void *vfrom; - - __set_bit(PG_mapped, &page->flags); - - vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); - memcpy(dst, vfrom, len); - kunmap_coherent(vfrom); + if (page_mapped(page) && !test_bit(PG_dcache_dirty, &page->flags)) { + void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); + memcpy(dst, vfrom, len); + kunmap_coherent(vfrom); + } else { + memcpy(dst, src, len); + set_bit(PG_dcache_dirty, &page->flags); + } } void copy_user_highpage(struct page *to, struct page *from, @@ -109,14 +108,19 @@ void copy_user_highpage(struct page *to, struct page *from, { void *vfrom, *vto; - __set_bit(PG_mapped, &to->flags); - vto = kmap_atomic(to, KM_USER1); - vfrom = kmap_coherent(from, vaddr); - copy_page(vto, vfrom); - kunmap_coherent(vfrom); - if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS)) + if (page_mapped(from) && !test_bit(PG_dcache_dirty, &from->flags)) { + vfrom = kmap_coherent(from, vaddr); + copy_page(vto, vfrom); + kunmap_coherent(vfrom); + } else { + vfrom = kmap_atomic(from, KM_USER0); + copy_page(vto, vfrom); + kunmap_atomic(vfrom, KM_USER0); + } + + if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK)) __flush_wback_region(vto, PAGE_SIZE); kunmap_atomic(vto, KM_USER1); @@ -124,23 +128,3 @@ void copy_user_highpage(struct page *to, struct page *from, smp_wmb(); } EXPORT_SYMBOL(copy_user_highpage); - -/* - * For SH-4, we have our own implementation for ptep_get_and_clear - */ -pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) -{ - pte_t pte = *ptep; - - pte_clear(mm, addr, ptep); - if (!pte_not_present(pte)) { - unsigned long pfn = pte_pfn(pte); - if (pfn_valid(pfn)) { - struct page *page = pfn_to_page(pfn); - struct address_space *mapping = page_mapping(page); - if (!mapping || !mapping_writably_mapped(mapping)) - __clear_bit(PG_mapped, &page->flags); - } - } - return pte; -} diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c index eaf25147194..684891b5c8c 100644 --- a/arch/sh/mm/pg-sh7705.c +++ b/arch/sh/mm/pg-sh7705.c @@ -26,7 +26,7 @@ #include #include -static inline void __flush_purge_virtual_region(void *p1, void *virt, int size) +static void __flush_purge_virtual_region(void *p1, void *virt, int size) { unsigned long v; unsigned long begin, end; @@ -75,19 +75,13 @@ static inline void __flush_purge_virtual_region(void *p1, void *virt, int size) */ void clear_user_page(void *to, unsigned long address, struct page *pg) { - struct page *page = virt_to_page(to); - - __set_bit(PG_mapped, &page->flags); - if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { - clear_page(to); - __flush_wback_region(to, PAGE_SIZE); - } else { + if (pages_do_alias(address, (unsigned long)to)) __flush_purge_virtual_region(to, (void *)(address & 0xfffff000), PAGE_SIZE); - clear_page(to); - __flush_wback_region(to, PAGE_SIZE); - } + + clear_page(to); + __flush_wback_region(to, PAGE_SIZE); } /* @@ -98,41 +92,11 @@ void clear_user_page(void *to, unsigned long address, struct page *pg) */ void copy_user_page(void *to, void *from, unsigned long address, struct page *pg) { - struct page *page = virt_to_page(to); - - - __set_bit(PG_mapped, &page->flags); - if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) { - copy_page(to, from); - __flush_wback_region(to, PAGE_SIZE); - } else { + if (pages_do_alias(address, (unsigned long)to)) __flush_purge_virtual_region(to, (void *)(address & 0xfffff000), PAGE_SIZE); - copy_page(to, from); - __flush_wback_region(to, PAGE_SIZE); - } + + copy_page(to, from); + __flush_wback_region(to, PAGE_SIZE); } - -/* - * For SH7705, we have our own implementation for ptep_get_and_clear - * Copied from pg-sh4.c - */ -pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) -{ - pte_t pte = *ptep; - - pte_clear(mm, addr, ptep); - if (!pte_not_present(pte)) { - unsigned long pfn = pte_pfn(pte); - if (pfn_valid(pfn)) { - struct page *page = pfn_to_page(pfn); - struct address_space *mapping = page_mapping(page); - if (!mapping || !mapping_writably_mapped(mapping)) - __clear_bit(PG_mapped, &page->flags); - } - } - - return pte; -} - diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c index 2aab3ea934d..c39b7736335 100644 --- a/arch/sh/mm/tlb-pteaex.c +++ b/arch/sh/mm/tlb-pteaex.c @@ -27,23 +27,6 @@ void update_mmu_cache(struct vm_area_struct * vma, if (vma && current->active_mm != vma->vm_mm) return; -#ifndef CONFIG_CACHE_OFF - { - unsigned long pfn = pte_pfn(pte); - - if (pfn_valid(pfn)) { - struct page *page = pfn_to_page(pfn); - - if (!test_bit(PG_mapped, &page->flags)) { - unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; - __flush_wback_region((void *)P1SEGADDR(phys), - PAGE_SIZE); - __set_bit(PG_mapped, &page->flags); - } - } - } -#endif - local_irq_save(flags); /* Set PTEH register */ diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c index 17cb7c3adf2..9b8459c74ab 100644 --- a/arch/sh/mm/tlb-sh3.c +++ b/arch/sh/mm/tlb-sh3.c @@ -33,25 +33,25 @@ void update_mmu_cache(struct vm_area_struct * vma, unsigned long flags; unsigned long pteval; unsigned long vpn; + unsigned long pfn = pte_pfn(pte); + struct page *page; /* Ptrace may call this routine. */ if (vma && current->active_mm != vma->vm_mm) return; + page = pfn_to_page(pfn); + if (pfn_valid(pfn) && page_mapping(page)) { #if defined(CONFIG_SH7705_CACHE_32KB) - { - struct page *page = pte_page(pte); - unsigned long pfn = pte_pfn(pte); + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); + if (dirty) { + unsigned long addr = (unsigned long)page_address(page); - if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) { - unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; - - __flush_wback_region((void *)P1SEGADDR(phys), - PAGE_SIZE); - __set_bit(PG_mapped, &page->flags); + if (pages_do_alias(addr, address & PAGE_MASK)) + __flush_wback_region((void *)addr, PAGE_SIZE); } - } #endif + } local_irq_save(flags); diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c index f0c7b7397fa..cf50082d243 100644 --- a/arch/sh/mm/tlb-sh4.c +++ b/arch/sh/mm/tlb-sh4.c @@ -21,27 +21,26 @@ void update_mmu_cache(struct vm_area_struct * vma, unsigned long flags; unsigned long pteval; unsigned long vpn; + unsigned long pfn = pte_pfn(pte); + struct page *page; /* Ptrace may call this routine. */ if (vma && current->active_mm != vma->vm_mm) return; -#ifndef CONFIG_CACHE_OFF - { - unsigned long pfn = pte_pfn(pte); + page = pfn_to_page(pfn); + if (pfn_valid(pfn) && page_mapping(page)) { +#ifndef CONFIG_SMP + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); + if (dirty) { - if (pfn_valid(pfn)) { - struct page *page = pfn_to_page(pfn); + unsigned long addr = (unsigned long)page_address(page); - if (!test_bit(PG_mapped, &page->flags)) { - unsigned long phys = pte_val(pte) & PTE_PHYS_MASK; - __flush_wback_region((void *)P1SEGADDR(phys), - PAGE_SIZE); - __set_bit(PG_mapped, &page->flags); - } + if (pages_do_alias(addr, address & PAGE_MASK)) + __flush_wback_region((void *)addr, PAGE_SIZE); } - } #endif + } local_irq_save(flags); From cf4f1e76c49dacfde0680b170b9a9b6a42f296bb Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 14:32:03 +0000 Subject: [PATCH 037/262] usb: move r8a66597 register defines Move r8a66597 hardware register definitions from the host controller header file to the platform data header file. With this change in place we can easily share register definitions between the host controller driver and a future gadget driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/usb/host/r8a66597.h | 366 ---------------------------------- include/linux/usb/r8a66597.h | 372 ++++++++++++++++++++++++++++++++++- 2 files changed, 370 insertions(+), 368 deletions(-) diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index eecbd917bc8..228e3fb2385 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -32,372 +32,6 @@ #include -#define SYSCFG0 0x00 -#define SYSCFG1 0x02 -#define SYSSTS0 0x04 -#define SYSSTS1 0x06 -#define DVSTCTR0 0x08 -#define DVSTCTR1 0x0A -#define TESTMODE 0x0C -#define PINCFG 0x0E -#define DMA0CFG 0x10 -#define DMA1CFG 0x12 -#define CFIFO 0x14 -#define D0FIFO 0x18 -#define D1FIFO 0x1C -#define CFIFOSEL 0x20 -#define CFIFOCTR 0x22 -#define CFIFOSIE 0x24 -#define D0FIFOSEL 0x28 -#define D0FIFOCTR 0x2A -#define D1FIFOSEL 0x2C -#define D1FIFOCTR 0x2E -#define INTENB0 0x30 -#define INTENB1 0x32 -#define INTENB2 0x34 -#define BRDYENB 0x36 -#define NRDYENB 0x38 -#define BEMPENB 0x3A -#define SOFCFG 0x3C -#define INTSTS0 0x40 -#define INTSTS1 0x42 -#define INTSTS2 0x44 -#define BRDYSTS 0x46 -#define NRDYSTS 0x48 -#define BEMPSTS 0x4A -#define FRMNUM 0x4C -#define UFRMNUM 0x4E -#define USBADDR 0x50 -#define USBREQ 0x54 -#define USBVAL 0x56 -#define USBINDX 0x58 -#define USBLENG 0x5A -#define DCPCFG 0x5C -#define DCPMAXP 0x5E -#define DCPCTR 0x60 -#define PIPESEL 0x64 -#define PIPECFG 0x68 -#define PIPEBUF 0x6A -#define PIPEMAXP 0x6C -#define PIPEPERI 0x6E -#define PIPE1CTR 0x70 -#define PIPE2CTR 0x72 -#define PIPE3CTR 0x74 -#define PIPE4CTR 0x76 -#define PIPE5CTR 0x78 -#define PIPE6CTR 0x7A -#define PIPE7CTR 0x7C -#define PIPE8CTR 0x7E -#define PIPE9CTR 0x80 -#define PIPE1TRE 0x90 -#define PIPE1TRN 0x92 -#define PIPE2TRE 0x94 -#define PIPE2TRN 0x96 -#define PIPE3TRE 0x98 -#define PIPE3TRN 0x9A -#define PIPE4TRE 0x9C -#define PIPE4TRN 0x9E -#define PIPE5TRE 0xA0 -#define PIPE5TRN 0xA2 -#define DEVADD0 0xD0 -#define DEVADD1 0xD2 -#define DEVADD2 0xD4 -#define DEVADD3 0xD6 -#define DEVADD4 0xD8 -#define DEVADD5 0xDA -#define DEVADD6 0xDC -#define DEVADD7 0xDE -#define DEVADD8 0xE0 -#define DEVADD9 0xE2 -#define DEVADDA 0xE4 - -/* System Configuration Control Register */ -#define XTAL 0xC000 /* b15-14: Crystal selection */ -#define XTAL48 0x8000 /* 48MHz */ -#define XTAL24 0x4000 /* 24MHz */ -#define XTAL12 0x0000 /* 12MHz */ -#define XCKE 0x2000 /* b13: External clock enable */ -#define PLLC 0x0800 /* b11: PLL control */ -#define SCKE 0x0400 /* b10: USB clock enable */ -#define PCSDIS 0x0200 /* b9: not CS wakeup */ -#define LPSME 0x0100 /* b8: Low power sleep mode */ -#define HSE 0x0080 /* b7: Hi-speed enable */ -#define DCFM 0x0040 /* b6: Controller function select */ -#define DRPD 0x0020 /* b5: D+/- pull down control */ -#define DPRPU 0x0010 /* b4: D+ pull up control */ -#define USBE 0x0001 /* b0: USB module operation enable */ - -/* System Configuration Status Register */ -#define OVCBIT 0x8000 /* b15-14: Over-current bit */ -#define OVCMON 0xC000 /* b15-14: Over-current monitor */ -#define SOFEA 0x0020 /* b5: SOF monitor */ -#define IDMON 0x0004 /* b3: ID-pin monitor */ -#define LNST 0x0003 /* b1-0: D+, D- line status */ -#define SE1 0x0003 /* SE1 */ -#define FS_KSTS 0x0002 /* Full-Speed K State */ -#define FS_JSTS 0x0001 /* Full-Speed J State */ -#define LS_JSTS 0x0002 /* Low-Speed J State */ -#define LS_KSTS 0x0001 /* Low-Speed K State */ -#define SE0 0x0000 /* SE0 */ - -/* Device State Control Register */ -#define EXTLP0 0x0400 /* b10: External port */ -#define VBOUT 0x0200 /* b9: VBUS output */ -#define WKUP 0x0100 /* b8: Remote wakeup */ -#define RWUPE 0x0080 /* b7: Remote wakeup sense */ -#define USBRST 0x0040 /* b6: USB reset enable */ -#define RESUME 0x0020 /* b5: Resume enable */ -#define UACT 0x0010 /* b4: USB bus enable */ -#define RHST 0x0007 /* b1-0: Reset handshake status */ -#define HSPROC 0x0004 /* HS handshake is processing */ -#define HSMODE 0x0003 /* Hi-Speed mode */ -#define FSMODE 0x0002 /* Full-Speed mode */ -#define LSMODE 0x0001 /* Low-Speed mode */ -#define UNDECID 0x0000 /* Undecided */ - -/* Test Mode Register */ -#define UTST 0x000F /* b3-0: Test select */ -#define H_TST_PACKET 0x000C /* HOST TEST Packet */ -#define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ -#define H_TST_K 0x000A /* HOST TEST K */ -#define H_TST_J 0x0009 /* HOST TEST J */ -#define H_TST_NORMAL 0x0000 /* HOST Normal Mode */ -#define P_TST_PACKET 0x0004 /* PERI TEST Packet */ -#define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ -#define P_TST_K 0x0002 /* PERI TEST K */ -#define P_TST_J 0x0001 /* PERI TEST J */ -#define P_TST_NORMAL 0x0000 /* PERI Normal Mode */ - -/* Data Pin Configuration Register */ -#define LDRV 0x8000 /* b15: Drive Current Adjust */ -#define VIF1 0x0000 /* VIF = 1.8V */ -#define VIF3 0x8000 /* VIF = 3.3V */ -#define INTA 0x0001 /* b1: USB INT-pin active */ - -/* DMAx Pin Configuration Register */ -#define DREQA 0x4000 /* b14: Dreq active select */ -#define BURST 0x2000 /* b13: Burst mode */ -#define DACKA 0x0400 /* b10: Dack active select */ -#define DFORM 0x0380 /* b9-7: DMA mode select */ -#define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ -#define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ -#define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ -#define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ -#define DENDA 0x0040 /* b6: Dend active select */ -#define PKTM 0x0020 /* b5: Packet mode */ -#define DENDE 0x0010 /* b4: Dend enable */ -#define OBUS 0x0004 /* b2: OUTbus mode */ - -/* CFIFO/DxFIFO Port Select Register */ -#define RCNT 0x8000 /* b15: Read count mode */ -#define REW 0x4000 /* b14: Buffer rewind */ -#define DCLRM 0x2000 /* b13: DMA buffer clear mode */ -#define DREQE 0x1000 /* b12: DREQ output enable */ -#define MBW_8 0x0000 /* 8bit */ -#define MBW_16 0x0400 /* 16bit */ -#define MBW_32 0x0800 /* 32bit */ -#define BIGEND 0x0100 /* b8: Big endian mode */ -#define BYTE_LITTLE 0x0000 /* little dendian */ -#define BYTE_BIG 0x0100 /* big endifan */ -#define ISEL 0x0020 /* b5: DCP FIFO port direction select */ -#define CURPIPE 0x000F /* b2-0: PIPE select */ - -/* CFIFO/DxFIFO Port Control Register */ -#define BVAL 0x8000 /* b15: Buffer valid flag */ -#define BCLR 0x4000 /* b14: Buffer clear */ -#define FRDY 0x2000 /* b13: FIFO ready */ -#define DTLN 0x0FFF /* b11-0: FIFO received data length */ - -/* Interrupt Enable Register 0 */ -#define VBSE 0x8000 /* b15: VBUS interrupt */ -#define RSME 0x4000 /* b14: Resume interrupt */ -#define SOFE 0x2000 /* b13: Frame update interrupt */ -#define DVSE 0x1000 /* b12: Device state transition interrupt */ -#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ -#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ - -/* Interrupt Enable Register 1 */ -#define OVRCRE 0x8000 /* b15: Over-current interrupt */ -#define BCHGE 0x4000 /* b14: USB us chenge interrupt */ -#define DTCHE 0x1000 /* b12: Detach sense interrupt */ -#define ATTCHE 0x0800 /* b11: Attach sense interrupt */ -#define EOFERRE 0x0040 /* b6: EOF error interrupt */ -#define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ -#define SACKE 0x0010 /* b4: SETUP ACK interrupt */ - -/* BRDY Interrupt Enable/Status Register */ -#define BRDY9 0x0200 /* b9: PIPE9 */ -#define BRDY8 0x0100 /* b8: PIPE8 */ -#define BRDY7 0x0080 /* b7: PIPE7 */ -#define BRDY6 0x0040 /* b6: PIPE6 */ -#define BRDY5 0x0020 /* b5: PIPE5 */ -#define BRDY4 0x0010 /* b4: PIPE4 */ -#define BRDY3 0x0008 /* b3: PIPE3 */ -#define BRDY2 0x0004 /* b2: PIPE2 */ -#define BRDY1 0x0002 /* b1: PIPE1 */ -#define BRDY0 0x0001 /* b1: PIPE0 */ - -/* NRDY Interrupt Enable/Status Register */ -#define NRDY9 0x0200 /* b9: PIPE9 */ -#define NRDY8 0x0100 /* b8: PIPE8 */ -#define NRDY7 0x0080 /* b7: PIPE7 */ -#define NRDY6 0x0040 /* b6: PIPE6 */ -#define NRDY5 0x0020 /* b5: PIPE5 */ -#define NRDY4 0x0010 /* b4: PIPE4 */ -#define NRDY3 0x0008 /* b3: PIPE3 */ -#define NRDY2 0x0004 /* b2: PIPE2 */ -#define NRDY1 0x0002 /* b1: PIPE1 */ -#define NRDY0 0x0001 /* b1: PIPE0 */ - -/* BEMP Interrupt Enable/Status Register */ -#define BEMP9 0x0200 /* b9: PIPE9 */ -#define BEMP8 0x0100 /* b8: PIPE8 */ -#define BEMP7 0x0080 /* b7: PIPE7 */ -#define BEMP6 0x0040 /* b6: PIPE6 */ -#define BEMP5 0x0020 /* b5: PIPE5 */ -#define BEMP4 0x0010 /* b4: PIPE4 */ -#define BEMP3 0x0008 /* b3: PIPE3 */ -#define BEMP2 0x0004 /* b2: PIPE2 */ -#define BEMP1 0x0002 /* b1: PIPE1 */ -#define BEMP0 0x0001 /* b0: PIPE0 */ - -/* SOF Pin Configuration Register */ -#define TRNENSEL 0x0100 /* b8: Select transaction enable period */ -#define BRDYM 0x0040 /* b6: BRDY clear timing */ -#define INTL 0x0020 /* b5: Interrupt sense select */ -#define EDGESTS 0x0010 /* b4: */ -#define SOFMODE 0x000C /* b3-2: SOF pin select */ -#define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */ -#define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ -#define SOF_DISABLE 0x0000 /* SOF OUT Disable */ - -/* Interrupt Status Register 0 */ -#define VBINT 0x8000 /* b15: VBUS interrupt */ -#define RESM 0x4000 /* b14: Resume interrupt */ -#define SOFR 0x2000 /* b13: SOF frame update interrupt */ -#define DVST 0x1000 /* b12: Device state transition interrupt */ -#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ -#define BEMP 0x0400 /* b10: Buffer empty interrupt */ -#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ -#define BRDY 0x0100 /* b8: Buffer ready interrupt */ -#define VBSTS 0x0080 /* b7: VBUS input port */ -#define DVSQ 0x0070 /* b6-4: Device state */ -#define DS_SPD_CNFG 0x0070 /* Suspend Configured */ -#define DS_SPD_ADDR 0x0060 /* Suspend Address */ -#define DS_SPD_DFLT 0x0050 /* Suspend Default */ -#define DS_SPD_POWR 0x0040 /* Suspend Powered */ -#define DS_SUSP 0x0040 /* Suspend */ -#define DS_CNFG 0x0030 /* Configured */ -#define DS_ADDS 0x0020 /* Address */ -#define DS_DFLT 0x0010 /* Default */ -#define DS_POWR 0x0000 /* Powered */ -#define DVSQS 0x0030 /* b5-4: Device state */ -#define VALID 0x0008 /* b3: Setup packet detected flag */ -#define CTSQ 0x0007 /* b2-0: Control transfer stage */ -#define CS_SQER 0x0006 /* Sequence error */ -#define CS_WRND 0x0005 /* Control write nodata status stage */ -#define CS_WRSS 0x0004 /* Control write status stage */ -#define CS_WRDS 0x0003 /* Control write data stage */ -#define CS_RDSS 0x0002 /* Control read status stage */ -#define CS_RDDS 0x0001 /* Control read data stage */ -#define CS_IDST 0x0000 /* Idle or setup stage */ - -/* Interrupt Status Register 1 */ -#define OVRCR 0x8000 /* b15: Over-current interrupt */ -#define BCHG 0x4000 /* b14: USB bus chenge interrupt */ -#define DTCH 0x1000 /* b12: Detach sense interrupt */ -#define ATTCH 0x0800 /* b11: Attach sense interrupt */ -#define EOFERR 0x0040 /* b6: EOF-error interrupt */ -#define SIGN 0x0020 /* b5: Setup ignore interrupt */ -#define SACK 0x0010 /* b4: Setup acknowledge interrupt */ - -/* Frame Number Register */ -#define OVRN 0x8000 /* b15: Overrun error */ -#define CRCE 0x4000 /* b14: Received data error */ -#define FRNM 0x07FF /* b10-0: Frame number */ - -/* Micro Frame Number Register */ -#define UFRNM 0x0007 /* b2-0: Micro frame number */ - -/* Default Control Pipe Maxpacket Size Register */ -/* Pipe Maxpacket Size Register */ -#define DEVSEL 0xF000 /* b15-14: Device address select */ -#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ - -/* Default Control Pipe Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define SUREQ 0x4000 /* b14: Send USB request */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define SUREQCLR 0x0800 /* b11: stop setup request */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PINGE 0x0010 /* b4: ping enable */ -#define CCPL 0x0004 /* b2: Enable control transfer complete */ -#define PID 0x0003 /* b1-0: Response PID */ -#define PID_STALL11 0x0003 /* STALL */ -#define PID_STALL 0x0002 /* STALL */ -#define PID_BUF 0x0001 /* BUF */ -#define PID_NAK 0x0000 /* NAK */ - -/* Pipe Window Select Register */ -#define PIPENM 0x0007 /* b2-0: Pipe select */ - -/* Pipe Configuration Register */ -#define R8A66597_TYP 0xC000 /* b15-14: Transfer type */ -#define R8A66597_ISO 0xC000 /* Isochronous */ -#define R8A66597_INT 0x8000 /* Interrupt */ -#define R8A66597_BULK 0x4000 /* Bulk */ -#define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */ -#define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */ -#define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */ -#define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */ -#define R8A66597_DIR 0x0010 /* b4: Transfer direction select */ -#define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */ - -/* Pipe Buffer Configuration Register */ -#define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ -#define BUFNMB 0x007F /* b6-0: Pipe buffer number */ -#define PIPE0BUF 256 -#define PIPExBUF 64 - -/* Pipe Maxpacket Size Register */ -#define MXPS 0x07FF /* b10-0: Maxpacket size */ - -/* Pipe Cycle Configuration Register */ -#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ -#define IITV 0x0007 /* b2-0: Isochronous interval */ - -/* Pipex Control Register */ -#define BSTS 0x8000 /* b15: Buffer status */ -#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ -#define CSCLR 0x2000 /* b13: complete-split status clear */ -#define CSSTS 0x1000 /* b12: complete-split status */ -#define ATREPM 0x0400 /* b10: Auto repeat mode */ -#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ -#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ -#define SQSET 0x0080 /* b7: Sequence toggle bit set */ -#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ -#define PBUSY 0x0020 /* b5: pipe busy */ -#define PID 0x0003 /* b1-0: Response PID */ - -/* PIPExTRE */ -#define TRENB 0x0200 /* b9: Transaction counter enable */ -#define TRCLR 0x0100 /* b8: Transaction counter clear */ - -/* PIPExTRN */ -#define TRNCNT 0xFFFF /* b15-0: Transaction counter */ - -/* DEVADDx */ -#define UPPHUB 0x7800 -#define HUBPORT 0x0700 -#define USBSPD 0x00C0 -#define RTPORT 0x0001 - #define R8A66597_MAX_NUM_PIPE 10 #define R8A66597_BUF_BSIZE 8 #define R8A66597_MAX_DEVICE 10 diff --git a/include/linux/usb/r8a66597.h b/include/linux/usb/r8a66597.h index 460ee3f6a2c..26d21673405 100644 --- a/include/linux/usb/r8a66597.h +++ b/include/linux/usb/r8a66597.h @@ -28,7 +28,7 @@ #define R8A66597_PLATDATA_XTAL_48MHZ 0x03 struct r8a66597_platdata { - /* This ops can controll port power instead of DVSTCTR register. */ + /* This callback can control port power instead of DVSTCTR register. */ void (*port_power)(int port, int power); /* set one = on chip controller, set zero = external controller */ @@ -43,5 +43,373 @@ struct r8a66597_platdata { /* set one = big endian, set zero = little endian */ unsigned endian:1; }; -#endif + +/* Register definitions */ +#define SYSCFG0 0x00 +#define SYSCFG1 0x02 +#define SYSSTS0 0x04 +#define SYSSTS1 0x06 +#define DVSTCTR0 0x08 +#define DVSTCTR1 0x0A +#define TESTMODE 0x0C +#define PINCFG 0x0E +#define DMA0CFG 0x10 +#define DMA1CFG 0x12 +#define CFIFO 0x14 +#define D0FIFO 0x18 +#define D1FIFO 0x1C +#define CFIFOSEL 0x20 +#define CFIFOCTR 0x22 +#define CFIFOSIE 0x24 +#define D0FIFOSEL 0x28 +#define D0FIFOCTR 0x2A +#define D1FIFOSEL 0x2C +#define D1FIFOCTR 0x2E +#define INTENB0 0x30 +#define INTENB1 0x32 +#define INTENB2 0x34 +#define BRDYENB 0x36 +#define NRDYENB 0x38 +#define BEMPENB 0x3A +#define SOFCFG 0x3C +#define INTSTS0 0x40 +#define INTSTS1 0x42 +#define INTSTS2 0x44 +#define BRDYSTS 0x46 +#define NRDYSTS 0x48 +#define BEMPSTS 0x4A +#define FRMNUM 0x4C +#define UFRMNUM 0x4E +#define USBADDR 0x50 +#define USBREQ 0x54 +#define USBVAL 0x56 +#define USBINDX 0x58 +#define USBLENG 0x5A +#define DCPCFG 0x5C +#define DCPMAXP 0x5E +#define DCPCTR 0x60 +#define PIPESEL 0x64 +#define PIPECFG 0x68 +#define PIPEBUF 0x6A +#define PIPEMAXP 0x6C +#define PIPEPERI 0x6E +#define PIPE1CTR 0x70 +#define PIPE2CTR 0x72 +#define PIPE3CTR 0x74 +#define PIPE4CTR 0x76 +#define PIPE5CTR 0x78 +#define PIPE6CTR 0x7A +#define PIPE7CTR 0x7C +#define PIPE8CTR 0x7E +#define PIPE9CTR 0x80 +#define PIPE1TRE 0x90 +#define PIPE1TRN 0x92 +#define PIPE2TRE 0x94 +#define PIPE2TRN 0x96 +#define PIPE3TRE 0x98 +#define PIPE3TRN 0x9A +#define PIPE4TRE 0x9C +#define PIPE4TRN 0x9E +#define PIPE5TRE 0xA0 +#define PIPE5TRN 0xA2 +#define DEVADD0 0xD0 +#define DEVADD1 0xD2 +#define DEVADD2 0xD4 +#define DEVADD3 0xD6 +#define DEVADD4 0xD8 +#define DEVADD5 0xDA +#define DEVADD6 0xDC +#define DEVADD7 0xDE +#define DEVADD8 0xE0 +#define DEVADD9 0xE2 +#define DEVADDA 0xE4 + +/* System Configuration Control Register */ +#define XTAL 0xC000 /* b15-14: Crystal selection */ +#define XTAL48 0x8000 /* 48MHz */ +#define XTAL24 0x4000 /* 24MHz */ +#define XTAL12 0x0000 /* 12MHz */ +#define XCKE 0x2000 /* b13: External clock enable */ +#define PLLC 0x0800 /* b11: PLL control */ +#define SCKE 0x0400 /* b10: USB clock enable */ +#define PCSDIS 0x0200 /* b9: not CS wakeup */ +#define LPSME 0x0100 /* b8: Low power sleep mode */ +#define HSE 0x0080 /* b7: Hi-speed enable */ +#define DCFM 0x0040 /* b6: Controller function select */ +#define DRPD 0x0020 /* b5: D+/- pull down control */ +#define DPRPU 0x0010 /* b4: D+ pull up control */ +#define USBE 0x0001 /* b0: USB module operation enable */ + +/* System Configuration Status Register */ +#define OVCBIT 0x8000 /* b15-14: Over-current bit */ +#define OVCMON 0xC000 /* b15-14: Over-current monitor */ +#define SOFEA 0x0020 /* b5: SOF monitor */ +#define IDMON 0x0004 /* b3: ID-pin monitor */ +#define LNST 0x0003 /* b1-0: D+, D- line status */ +#define SE1 0x0003 /* SE1 */ +#define FS_KSTS 0x0002 /* Full-Speed K State */ +#define FS_JSTS 0x0001 /* Full-Speed J State */ +#define LS_JSTS 0x0002 /* Low-Speed J State */ +#define LS_KSTS 0x0001 /* Low-Speed K State */ +#define SE0 0x0000 /* SE0 */ + +/* Device State Control Register */ +#define EXTLP0 0x0400 /* b10: External port */ +#define VBOUT 0x0200 /* b9: VBUS output */ +#define WKUP 0x0100 /* b8: Remote wakeup */ +#define RWUPE 0x0080 /* b7: Remote wakeup sense */ +#define USBRST 0x0040 /* b6: USB reset enable */ +#define RESUME 0x0020 /* b5: Resume enable */ +#define UACT 0x0010 /* b4: USB bus enable */ +#define RHST 0x0007 /* b1-0: Reset handshake status */ +#define HSPROC 0x0004 /* HS handshake is processing */ +#define HSMODE 0x0003 /* Hi-Speed mode */ +#define FSMODE 0x0002 /* Full-Speed mode */ +#define LSMODE 0x0001 /* Low-Speed mode */ +#define UNDECID 0x0000 /* Undecided */ + +/* Test Mode Register */ +#define UTST 0x000F /* b3-0: Test select */ +#define H_TST_PACKET 0x000C /* HOST TEST Packet */ +#define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ +#define H_TST_K 0x000A /* HOST TEST K */ +#define H_TST_J 0x0009 /* HOST TEST J */ +#define H_TST_NORMAL 0x0000 /* HOST Normal Mode */ +#define P_TST_PACKET 0x0004 /* PERI TEST Packet */ +#define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ +#define P_TST_K 0x0002 /* PERI TEST K */ +#define P_TST_J 0x0001 /* PERI TEST J */ +#define P_TST_NORMAL 0x0000 /* PERI Normal Mode */ + +/* Data Pin Configuration Register */ +#define LDRV 0x8000 /* b15: Drive Current Adjust */ +#define VIF1 0x0000 /* VIF = 1.8V */ +#define VIF3 0x8000 /* VIF = 3.3V */ +#define INTA 0x0001 /* b1: USB INT-pin active */ + +/* DMAx Pin Configuration Register */ +#define DREQA 0x4000 /* b14: Dreq active select */ +#define BURST 0x2000 /* b13: Burst mode */ +#define DACKA 0x0400 /* b10: Dack active select */ +#define DFORM 0x0380 /* b9-7: DMA mode select */ +#define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ +#define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ +#define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ +#define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ +#define DENDA 0x0040 /* b6: Dend active select */ +#define PKTM 0x0020 /* b5: Packet mode */ +#define DENDE 0x0010 /* b4: Dend enable */ +#define OBUS 0x0004 /* b2: OUTbus mode */ + +/* CFIFO/DxFIFO Port Select Register */ +#define RCNT 0x8000 /* b15: Read count mode */ +#define REW 0x4000 /* b14: Buffer rewind */ +#define DCLRM 0x2000 /* b13: DMA buffer clear mode */ +#define DREQE 0x1000 /* b12: DREQ output enable */ +#define MBW_8 0x0000 /* 8bit */ +#define MBW_16 0x0400 /* 16bit */ +#define MBW_32 0x0800 /* 32bit */ +#define BIGEND 0x0100 /* b8: Big endian mode */ +#define BYTE_LITTLE 0x0000 /* little dendian */ +#define BYTE_BIG 0x0100 /* big endifan */ +#define ISEL 0x0020 /* b5: DCP FIFO port direction select */ +#define CURPIPE 0x000F /* b2-0: PIPE select */ + +/* CFIFO/DxFIFO Port Control Register */ +#define BVAL 0x8000 /* b15: Buffer valid flag */ +#define BCLR 0x4000 /* b14: Buffer clear */ +#define FRDY 0x2000 /* b13: FIFO ready */ +#define DTLN 0x0FFF /* b11-0: FIFO received data length */ + +/* Interrupt Enable Register 0 */ +#define VBSE 0x8000 /* b15: VBUS interrupt */ +#define RSME 0x4000 /* b14: Resume interrupt */ +#define SOFE 0x2000 /* b13: Frame update interrupt */ +#define DVSE 0x1000 /* b12: Device state transition interrupt */ +#define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ +#define BEMPE 0x0400 /* b10: Buffer empty interrupt */ +#define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ +#define BRDYE 0x0100 /* b8: Buffer ready interrupt */ + +/* Interrupt Enable Register 1 */ +#define OVRCRE 0x8000 /* b15: Over-current interrupt */ +#define BCHGE 0x4000 /* b14: USB us chenge interrupt */ +#define DTCHE 0x1000 /* b12: Detach sense interrupt */ +#define ATTCHE 0x0800 /* b11: Attach sense interrupt */ +#define EOFERRE 0x0040 /* b6: EOF error interrupt */ +#define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ +#define SACKE 0x0010 /* b4: SETUP ACK interrupt */ + +/* BRDY Interrupt Enable/Status Register */ +#define BRDY9 0x0200 /* b9: PIPE9 */ +#define BRDY8 0x0100 /* b8: PIPE8 */ +#define BRDY7 0x0080 /* b7: PIPE7 */ +#define BRDY6 0x0040 /* b6: PIPE6 */ +#define BRDY5 0x0020 /* b5: PIPE5 */ +#define BRDY4 0x0010 /* b4: PIPE4 */ +#define BRDY3 0x0008 /* b3: PIPE3 */ +#define BRDY2 0x0004 /* b2: PIPE2 */ +#define BRDY1 0x0002 /* b1: PIPE1 */ +#define BRDY0 0x0001 /* b1: PIPE0 */ + +/* NRDY Interrupt Enable/Status Register */ +#define NRDY9 0x0200 /* b9: PIPE9 */ +#define NRDY8 0x0100 /* b8: PIPE8 */ +#define NRDY7 0x0080 /* b7: PIPE7 */ +#define NRDY6 0x0040 /* b6: PIPE6 */ +#define NRDY5 0x0020 /* b5: PIPE5 */ +#define NRDY4 0x0010 /* b4: PIPE4 */ +#define NRDY3 0x0008 /* b3: PIPE3 */ +#define NRDY2 0x0004 /* b2: PIPE2 */ +#define NRDY1 0x0002 /* b1: PIPE1 */ +#define NRDY0 0x0001 /* b1: PIPE0 */ + +/* BEMP Interrupt Enable/Status Register */ +#define BEMP9 0x0200 /* b9: PIPE9 */ +#define BEMP8 0x0100 /* b8: PIPE8 */ +#define BEMP7 0x0080 /* b7: PIPE7 */ +#define BEMP6 0x0040 /* b6: PIPE6 */ +#define BEMP5 0x0020 /* b5: PIPE5 */ +#define BEMP4 0x0010 /* b4: PIPE4 */ +#define BEMP3 0x0008 /* b3: PIPE3 */ +#define BEMP2 0x0004 /* b2: PIPE2 */ +#define BEMP1 0x0002 /* b1: PIPE1 */ +#define BEMP0 0x0001 /* b0: PIPE0 */ + +/* SOF Pin Configuration Register */ +#define TRNENSEL 0x0100 /* b8: Select transaction enable period */ +#define BRDYM 0x0040 /* b6: BRDY clear timing */ +#define INTL 0x0020 /* b5: Interrupt sense select */ +#define EDGESTS 0x0010 /* b4: */ +#define SOFMODE 0x000C /* b3-2: SOF pin select */ +#define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */ +#define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ +#define SOF_DISABLE 0x0000 /* SOF OUT Disable */ + +/* Interrupt Status Register 0 */ +#define VBINT 0x8000 /* b15: VBUS interrupt */ +#define RESM 0x4000 /* b14: Resume interrupt */ +#define SOFR 0x2000 /* b13: SOF frame update interrupt */ +#define DVST 0x1000 /* b12: Device state transition interrupt */ +#define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ +#define BEMP 0x0400 /* b10: Buffer empty interrupt */ +#define NRDY 0x0200 /* b9: Buffer not ready interrupt */ +#define BRDY 0x0100 /* b8: Buffer ready interrupt */ +#define VBSTS 0x0080 /* b7: VBUS input port */ +#define DVSQ 0x0070 /* b6-4: Device state */ +#define DS_SPD_CNFG 0x0070 /* Suspend Configured */ +#define DS_SPD_ADDR 0x0060 /* Suspend Address */ +#define DS_SPD_DFLT 0x0050 /* Suspend Default */ +#define DS_SPD_POWR 0x0040 /* Suspend Powered */ +#define DS_SUSP 0x0040 /* Suspend */ +#define DS_CNFG 0x0030 /* Configured */ +#define DS_ADDS 0x0020 /* Address */ +#define DS_DFLT 0x0010 /* Default */ +#define DS_POWR 0x0000 /* Powered */ +#define DVSQS 0x0030 /* b5-4: Device state */ +#define VALID 0x0008 /* b3: Setup packet detected flag */ +#define CTSQ 0x0007 /* b2-0: Control transfer stage */ +#define CS_SQER 0x0006 /* Sequence error */ +#define CS_WRND 0x0005 /* Control write nodata status stage */ +#define CS_WRSS 0x0004 /* Control write status stage */ +#define CS_WRDS 0x0003 /* Control write data stage */ +#define CS_RDSS 0x0002 /* Control read status stage */ +#define CS_RDDS 0x0001 /* Control read data stage */ +#define CS_IDST 0x0000 /* Idle or setup stage */ + +/* Interrupt Status Register 1 */ +#define OVRCR 0x8000 /* b15: Over-current interrupt */ +#define BCHG 0x4000 /* b14: USB bus chenge interrupt */ +#define DTCH 0x1000 /* b12: Detach sense interrupt */ +#define ATTCH 0x0800 /* b11: Attach sense interrupt */ +#define EOFERR 0x0040 /* b6: EOF-error interrupt */ +#define SIGN 0x0020 /* b5: Setup ignore interrupt */ +#define SACK 0x0010 /* b4: Setup acknowledge interrupt */ + +/* Frame Number Register */ +#define OVRN 0x8000 /* b15: Overrun error */ +#define CRCE 0x4000 /* b14: Received data error */ +#define FRNM 0x07FF /* b10-0: Frame number */ + +/* Micro Frame Number Register */ +#define UFRNM 0x0007 /* b2-0: Micro frame number */ + +/* Default Control Pipe Maxpacket Size Register */ +/* Pipe Maxpacket Size Register */ +#define DEVSEL 0xF000 /* b15-14: Device address select */ +#define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ + +/* Default Control Pipe Control Register */ +#define BSTS 0x8000 /* b15: Buffer status */ +#define SUREQ 0x4000 /* b14: Send USB request */ +#define CSCLR 0x2000 /* b13: complete-split status clear */ +#define CSSTS 0x1000 /* b12: complete-split status */ +#define SUREQCLR 0x0800 /* b11: stop setup request */ +#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ +#define SQSET 0x0080 /* b7: Sequence toggle bit set */ +#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ +#define PBUSY 0x0020 /* b5: pipe busy */ +#define PINGE 0x0010 /* b4: ping enable */ +#define CCPL 0x0004 /* b2: Enable control transfer complete */ +#define PID 0x0003 /* b1-0: Response PID */ +#define PID_STALL11 0x0003 /* STALL */ +#define PID_STALL 0x0002 /* STALL */ +#define PID_BUF 0x0001 /* BUF */ +#define PID_NAK 0x0000 /* NAK */ + +/* Pipe Window Select Register */ +#define PIPENM 0x0007 /* b2-0: Pipe select */ + +/* Pipe Configuration Register */ +#define R8A66597_TYP 0xC000 /* b15-14: Transfer type */ +#define R8A66597_ISO 0xC000 /* Isochronous */ +#define R8A66597_INT 0x8000 /* Interrupt */ +#define R8A66597_BULK 0x4000 /* Bulk */ +#define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */ +#define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */ +#define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */ +#define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */ +#define R8A66597_DIR 0x0010 /* b4: Transfer direction select */ +#define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */ + +/* Pipe Buffer Configuration Register */ +#define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ +#define BUFNMB 0x007F /* b6-0: Pipe buffer number */ +#define PIPE0BUF 256 +#define PIPExBUF 64 + +/* Pipe Maxpacket Size Register */ +#define MXPS 0x07FF /* b10-0: Maxpacket size */ + +/* Pipe Cycle Configuration Register */ +#define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ +#define IITV 0x0007 /* b2-0: Isochronous interval */ + +/* Pipex Control Register */ +#define BSTS 0x8000 /* b15: Buffer status */ +#define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ +#define CSCLR 0x2000 /* b13: complete-split status clear */ +#define CSSTS 0x1000 /* b12: complete-split status */ +#define ATREPM 0x0400 /* b10: Auto repeat mode */ +#define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ +#define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ +#define SQSET 0x0080 /* b7: Sequence toggle bit set */ +#define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ +#define PBUSY 0x0020 /* b5: pipe busy */ +#define PID 0x0003 /* b1-0: Response PID */ + +/* PIPExTRE */ +#define TRENB 0x0200 /* b9: Transaction counter enable */ +#define TRCLR 0x0100 /* b8: Transaction counter clear */ + +/* PIPExTRN */ +#define TRNCNT 0xFFFF /* b15-0: Transaction counter */ + +/* DEVADDx */ +#define UPPHUB 0x7800 +#define HUBPORT 0x0700 +#define USBSPD 0x00C0 +#define RTPORT 0x0001 + +#endif /* __LINUX_USB_R8A66597_H */ From 2c59b0b70b9d5d61c726f179724660c4c2423f31 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 14:41:35 +0000 Subject: [PATCH 038/262] usb: m66592-udc platform data on_chip support Convert the m66592-udc driver to use the on_chip flag from platform data to enable on chip behaviour instead of relying on CONFIG_SUPERH_BUILT_IN_M66592 ugliness. This makes the code cleaner and also allows us to support both external and internal m66592 with the same kernel. It also makes the Kconfig part more future proof since we with this patch can add support for new processors with on-chip m66592 without modifying the Kconfig. The patch adds a m66592 header file for platform data and ties in platform data to the existing m66592 devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-highlander/setup.c | 7 + arch/sh/boards/mach-x3proto/setup.c | 7 + arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 8 +- drivers/usb/gadget/Kconfig | 10 - drivers/usb/gadget/m66592-udc.c | 266 ++++++++++++++----------- drivers/usb/gadget/m66592-udc.h | 85 ++++---- include/linux/usb/m66592.h | 44 ++++ 7 files changed, 262 insertions(+), 165 deletions(-) create mode 100644 include/linux/usb/m66592.h diff --git a/arch/sh/boards/mach-highlander/setup.c b/arch/sh/boards/mach-highlander/setup.c index 1639f891500..566e69d8d72 100644 --- a/arch/sh/boards/mach-highlander/setup.c +++ b/arch/sh/boards/mach-highlander/setup.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -60,6 +61,11 @@ static struct platform_device r8a66597_usb_host_device = { .resource = r8a66597_usb_host_resources, }; +static struct m66592_platdata usbf_platdata = { + .xtal = M66592_PLATDATA_XTAL_24MHZ, + .vif = 1, +}; + static struct resource m66592_usb_peripheral_resources[] = { [0] = { .name = "m66592_udc", @@ -81,6 +87,7 @@ static struct platform_device m66592_usb_peripheral_device = { .dev = { .dma_mask = NULL, /* don't use dma */ .coherent_dma_mask = 0xffffffff, + .platform_data = &usbf_platdata, }, .num_resources = ARRAY_SIZE(m66592_usb_peripheral_resources), .resource = m66592_usb_peripheral_resources, diff --git a/arch/sh/boards/mach-x3proto/setup.c b/arch/sh/boards/mach-x3proto/setup.c index 8913ae39a80..efe4cb9f8a7 100644 --- a/arch/sh/boards/mach-x3proto/setup.c +++ b/arch/sh/boards/mach-x3proto/setup.c @@ -17,6 +17,7 @@ #include #include #include +#include #include static struct resource heartbeat_resources[] = { @@ -89,6 +90,11 @@ static struct platform_device r8a66597_usb_host_device = { .resource = r8a66597_usb_host_resources, }; +static struct m66592_platdata usbf_platdata = { + .xtal = M66592_PLATDATA_XTAL_24MHZ, + .vif = 1, +}; + static struct resource m66592_usb_peripheral_resources[] = { [0] = { .name = "m66592_udc", @@ -109,6 +115,7 @@ static struct platform_device m66592_usb_peripheral_device = { .dev = { .dma_mask = NULL, /* don't use dma */ .coherent_dma_mask = 0xffffffff, + .platform_data = &usbf_platdata, }, .num_resources = ARRAY_SIZE(m66592_usb_peripheral_resources), .resource = m66592_usb_peripheral_resources, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index ea524a2da3e..0bad14a4423 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -47,9 +48,13 @@ static struct platform_device rtc_device = { .resource = rtc_resources, }; +static struct m66592_platdata usbf_platdata = { + .on_chip = 1, +}; + static struct resource usbf_resources[] = { [0] = { - .name = "m66592_udc", + .name = "USBF", .start = 0x04480000, .end = 0x044800FF, .flags = IORESOURCE_MEM, @@ -67,6 +72,7 @@ static struct platform_device usbf_device = { .dev = { .dma_mask = NULL, .coherent_dma_mask = 0xffffffff, + .platform_data = &usbf_platdata, }, .num_resources = ARRAY_SIZE(usbf_resources), .resource = usbf_resources, diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 7f8e83a954a..b7f10bc25c2 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -360,16 +360,6 @@ config USB_M66592 default USB_GADGET select USB_GADGET_SELECTED -config SUPERH_BUILT_IN_M66592 - boolean "Enable SuperH built-in USB like the M66592" - depends on USB_GADGET_M66592 && CPU_SUBTYPE_SH7722 - help - SH7722 has USB like the M66592. - - The transfer rate is very slow when use "Ethernet Gadget". - However, this problem is improved if change a value of - NET_IP_ALIGN to 4. - # # Controllers available only in discrete form (and all PCI controllers) # diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 0dddd2f8ff3..a61c70caff1 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -31,38 +31,12 @@ #include "m66592-udc.h" - MODULE_DESCRIPTION("M66592 USB gadget driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Yoshihiro Shimoda"); MODULE_ALIAS("platform:m66592_udc"); -#define DRIVER_VERSION "26 Jun 2009" - -/* module parameters */ -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) -static unsigned short endian = M66592_LITTLE; -module_param(endian, ushort, 0644); -MODULE_PARM_DESC(endian, "data endian: big=0, little=0 (default=0)"); -#else -static unsigned short clock = M66592_XTAL24; -module_param(clock, ushort, 0644); -MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " - "(default=16384)"); - -static unsigned short vif = M66592_LDRV; -module_param(vif, ushort, 0644); -MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0 (default=32768)"); - -static unsigned short endian; -module_param(endian, ushort, 0644); -MODULE_PARM_DESC(endian, "data endian: big=256, little=0 (default=0)"); - -static unsigned short irq_sense = M66592_INTL; -module_param(irq_sense, ushort, 0644); -MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0 " - "(default=2)"); -#endif +#define DRIVER_VERSION "21 July 2009" static const char udc_name[] = "m66592_udc"; static const char *m66592_ep_name[] = { @@ -244,6 +218,7 @@ static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum) static inline void pipe_change(struct m66592 *m66592, u16 pipenum) { struct m66592_ep *ep = m66592->pipenum2ep[pipenum]; + unsigned short mbw; if (ep->use_dma) return; @@ -252,7 +227,12 @@ static inline void pipe_change(struct m66592 *m66592, u16 pipenum) ndelay(450); - m66592_bset(m66592, M66592_MBW, ep->fifosel); + if (m66592->pdata->on_chip) + mbw = M66592_MBW_32; + else + mbw = M66592_MBW_16; + + m66592_bset(m66592, mbw, ep->fifosel); } static int pipe_buffer_setting(struct m66592 *m66592, @@ -332,6 +312,7 @@ static void pipe_buffer_release(struct m66592 *m66592, static void pipe_initialize(struct m66592_ep *ep) { struct m66592 *m66592 = ep->m66592; + unsigned short mbw; m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel); @@ -343,7 +324,12 @@ static void pipe_initialize(struct m66592_ep *ep) ndelay(450); - m66592_bset(m66592, M66592_MBW, ep->fifosel); + if (m66592->pdata->on_chip) + mbw = M66592_MBW_32; + else + mbw = M66592_MBW_16; + + m66592_bset(m66592, mbw, ep->fifosel); } } @@ -359,15 +345,13 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, ep->fifosel = M66592_D0FIFOSEL; ep->fifoctr = M66592_D0FIFOCTR; ep->fifotrn = M66592_D0FIFOTRN; -#if !defined(CONFIG_SUPERH_BUILT_IN_M66592) - } else if (m66592->num_dma == 1) { + } else if (!m66592->pdata->on_chip && m66592->num_dma == 1) { m66592->num_dma++; ep->use_dma = 1; ep->fifoaddr = M66592_D1FIFO; ep->fifosel = M66592_D1FIFOSEL; ep->fifoctr = M66592_D1FIFOCTR; ep->fifotrn = M66592_D1FIFOTRN; -#endif } else { ep->use_dma = 0; ep->fifoaddr = M66592_CFIFO; @@ -612,76 +596,120 @@ static void start_ep0(struct m66592_ep *ep, struct m66592_request *req) } } -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) static void init_controller(struct m66592 *m66592) { - m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */ - m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG); - m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); - m66592_bset(m66592, M66592_USBE, M66592_SYSCFG); + unsigned int endian; - /* This is a workaound for SH7722 2nd cut */ - m66592_bset(m66592, 0x8000, M66592_DVSTCTR); - m66592_bset(m66592, 0x1000, M66592_TESTMODE); - m66592_bclr(m66592, 0x8000, M66592_DVSTCTR); + if (m66592->pdata->on_chip) { + if (m66592->pdata->endian) + endian = 0; /* big endian */ + else + endian = M66592_LITTLE; /* little endian */ - m66592_bset(m66592, M66592_INTL, M66592_INTENB1); + m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */ + m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG); + m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); + m66592_bset(m66592, M66592_USBE, M66592_SYSCFG); - m66592_write(m66592, 0, M66592_CFBCFG); - m66592_write(m66592, 0, M66592_D0FBCFG); - m66592_bset(m66592, endian, M66592_CFBCFG); - m66592_bset(m66592, endian, M66592_D0FBCFG); + /* This is a workaound for SH7722 2nd cut */ + m66592_bset(m66592, 0x8000, M66592_DVSTCTR); + m66592_bset(m66592, 0x1000, M66592_TESTMODE); + m66592_bclr(m66592, 0x8000, M66592_DVSTCTR); + + m66592_bset(m66592, M66592_INTL, M66592_INTENB1); + + m66592_write(m66592, 0, M66592_CFBCFG); + m66592_write(m66592, 0, M66592_D0FBCFG); + m66592_bset(m66592, endian, M66592_CFBCFG); + m66592_bset(m66592, endian, M66592_D0FBCFG); + } else { + unsigned int clock, vif, irq_sense; + + if (m66592->pdata->endian) + endian = M66592_BIGEND; /* big endian */ + else + endian = 0; /* little endian */ + + if (m66592->pdata->vif) + vif = M66592_LDRV; /* 3.3v */ + else + vif = 0; /* 1.5v */ + + switch (m66592->pdata->xtal) { + case M66592_PLATDATA_XTAL_12MHZ: + clock = M66592_XTAL12; + break; + case M66592_PLATDATA_XTAL_24MHZ: + clock = M66592_XTAL24; + break; + case M66592_PLATDATA_XTAL_48MHZ: + clock = M66592_XTAL48; + break; + default: + pr_warning("m66592-udc: xtal configuration error\n"); + clock = 0; + } + + switch (m66592->irq_trigger) { + case IRQF_TRIGGER_LOW: + irq_sense = M66592_INTL; + break; + case IRQF_TRIGGER_FALLING: + irq_sense = 0; + break; + default: + pr_warning("m66592-udc: irq trigger config error\n"); + irq_sense = 0; + } + + m66592_bset(m66592, + (vif & M66592_LDRV) | (endian & M66592_BIGEND), + M66592_PINCFG); + m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */ + m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, + M66592_SYSCFG); + m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG); + m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); + m66592_bset(m66592, M66592_USBE, M66592_SYSCFG); + + m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); + + msleep(3); + + m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG); + + msleep(1); + + m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG); + + m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1); + m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR, + M66592_DMA0CFG); + } } -#else /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */ -static void init_controller(struct m66592 *m66592) -{ - m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND), - M66592_PINCFG); - m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */ - m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG); - - m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG); - m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); - m66592_bset(m66592, M66592_USBE, M66592_SYSCFG); - - m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); - - msleep(3); - - m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG); - - msleep(1); - - m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG); - - m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1); - m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR, - M66592_DMA0CFG); -} -#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */ static void disable_controller(struct m66592 *m66592) { -#if !defined(CONFIG_SUPERH_BUILT_IN_M66592) - m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG); - udelay(1); - m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG); - udelay(1); - m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG); - udelay(1); - m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG); -#endif + if (!m66592->pdata->on_chip) { + m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG); + udelay(1); + m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG); + udelay(1); + m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG); + udelay(1); + m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG); + } } static void m66592_start_xclock(struct m66592 *m66592) { -#if !defined(CONFIG_SUPERH_BUILT_IN_M66592) u16 tmp; - tmp = m66592_read(m66592, M66592_SYSCFG); - if (!(tmp & M66592_XCKE)) - m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); -#endif + if (!m66592->pdata->on_chip) { + tmp = m66592_read(m66592, M66592_SYSCFG); + if (!(tmp & M66592_XCKE)) + m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); + } } /*-------------------------------------------------------------------------*/ @@ -1169,8 +1197,7 @@ static irqreturn_t m66592_irq(int irq, void *_m66592) intsts0 = m66592_read(m66592, M66592_INTSTS0); intenb0 = m66592_read(m66592, M66592_INTENB0); -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) - if (!intsts0 && !intenb0) { + if (m66592->pdata->on_chip && !intsts0 && !intenb0) { /* * When USB clock stops, it cannot read register. Even if a * clock stops, the interrupt occurs. So this driver turn on @@ -1180,7 +1207,6 @@ static irqreturn_t m66592_irq(int irq, void *_m66592) intsts0 = m66592_read(m66592, M66592_INTSTS0); intenb0 = m66592_read(m66592, M66592_INTENB0); } -#endif savepipe = m66592_read(m66592, M66592_CFIFOSEL); @@ -1526,9 +1552,11 @@ static int __exit m66592_remove(struct platform_device *pdev) iounmap(m66592->reg); free_irq(platform_get_irq(pdev, 0), m66592); m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK) - clk_disable(m66592->clk); - clk_put(m66592->clk); +#ifdef CONFIG_HAVE_CLK + if (m66592->pdata->on_chip) { + clk_disable(m66592->clk); + clk_put(m66592->clk); + } #endif kfree(m66592); return 0; @@ -1540,11 +1568,10 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r) static int __init m66592_probe(struct platform_device *pdev) { - struct resource *res; - int irq; + struct resource *res, *ires; void __iomem *reg = NULL; struct m66592 *m66592 = NULL; -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK) +#ifdef CONFIG_HAVE_CLK char clk_name[8]; #endif int ret = 0; @@ -1557,10 +1584,11 @@ static int __init m66592_probe(struct platform_device *pdev) goto clean_up; } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { + ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!ires) { ret = -ENODEV; - pr_err("platform_get_irq error.\n"); + dev_err(&pdev->dev, + "platform_get_resource IORESOURCE_IRQ error.\n"); goto clean_up; } @@ -1571,6 +1599,12 @@ static int __init m66592_probe(struct platform_device *pdev) goto clean_up; } + if (pdev->dev.platform_data == NULL) { + dev_err(&pdev->dev, "no platform data\n"); + ret = -ENODEV; + goto clean_up; + } + /* initialize ucd */ m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL); if (m66592 == NULL) { @@ -1578,6 +1612,9 @@ static int __init m66592_probe(struct platform_device *pdev) goto clean_up; } + m66592->pdata = pdev->dev.platform_data; + m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK; + spin_lock_init(&m66592->lock); dev_set_drvdata(&pdev->dev, m66592); @@ -1595,22 +1632,25 @@ static int __init m66592_probe(struct platform_device *pdev) m66592->timer.data = (unsigned long)m66592; m66592->reg = reg; - ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED, + ret = request_irq(ires->start, m66592_irq, IRQF_DISABLED | IRQF_SHARED, udc_name, m66592); if (ret < 0) { pr_err("request_irq error (%d)\n", ret); goto clean_up; } -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK) - snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id); - m66592->clk = clk_get(&pdev->dev, clk_name); - if (IS_ERR(m66592->clk)) { - dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); - ret = PTR_ERR(m66592->clk); - goto clean_up2; +#ifdef CONFIG_HAVE_CLK + if (m66592->pdata->on_chip) { + snprintf(clk_name, sizeof(clk_name), "usbf%d", pdev->id); + m66592->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(m66592->clk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", + clk_name); + ret = PTR_ERR(m66592->clk); + goto clean_up2; + } + clk_enable(m66592->clk); } - clk_enable(m66592->clk); #endif INIT_LIST_HEAD(&m66592->gadget.ep_list); m66592->gadget.ep0 = &m66592->ep[0].ep; @@ -1652,12 +1692,14 @@ static int __init m66592_probe(struct platform_device *pdev) return 0; clean_up3: -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK) - clk_disable(m66592->clk); - clk_put(m66592->clk); +#ifdef CONFIG_HAVE_CLK + if (m66592->pdata->on_chip) { + clk_disable(m66592->clk); + clk_put(m66592->clk); + } clean_up2: #endif - free_irq(irq, m66592); + free_irq(ires->start, m66592); clean_up: if (m66592) { if (m66592->ep0_req) diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h index 9a9c2bf9fbd..8b960deed68 100644 --- a/drivers/usb/gadget/m66592-udc.h +++ b/drivers/usb/gadget/m66592-udc.h @@ -23,10 +23,12 @@ #ifndef __M66592_UDC_H__ #define __M66592_UDC_H__ -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK) +#ifdef CONFIG_HAVE_CLK #include #endif +#include + #define M66592_SYSCFG 0x00 #define M66592_XTAL 0xC000 /* b15-14: Crystal selection */ #define M66592_XTAL48 0x8000 /* 48MHz */ @@ -76,11 +78,11 @@ #define M66592_P_TST_J 0x0001 /* PERI TEST J */ #define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */ -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) +/* built-in registers */ #define M66592_CFBCFG 0x0A #define M66592_D0FBCFG 0x0C #define M66592_LITTLE 0x0100 /* b8: Little endian mode */ -#else +/* external chip case */ #define M66592_PINCFG 0x0A #define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */ #define M66592_BIGEND 0x0100 /* b8: Big endian mode */ @@ -100,8 +102,8 @@ #define M66592_PKTM 0x0020 /* b5: Packet mode */ #define M66592_DENDE 0x0010 /* b4: Dend enable */ #define M66592_OBUS 0x0004 /* b2: OUTbus mode */ -#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */ +/* common case */ #define M66592_CFIFO 0x10 #define M66592_D0FIFO 0x14 #define M66592_D1FIFO 0x18 @@ -113,13 +115,9 @@ #define M66592_REW 0x4000 /* b14: Buffer rewind */ #define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */ #define M66592_DREQE 0x1000 /* b12: DREQ output enable */ -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) -#define M66592_MBW 0x0800 /* b11: Maximum bit width for FIFO */ -#else -#define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO */ -#define M66592_MBW_8 0x0000 /* 8bit */ -#define M66592_MBW_16 0x0400 /* 16bit */ -#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */ +#define M66592_MBW_8 0x0000 /* 8bit */ +#define M66592_MBW_16 0x0400 /* 16bit */ +#define M66592_MBW_32 0x0800 /* 32bit */ #define M66592_TRENB 0x0200 /* b9: Transaction counter enable */ #define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */ #define M66592_DEZPM 0x0080 /* b7: Zero-length packet mode */ @@ -480,9 +478,11 @@ struct m66592_ep { struct m66592 { spinlock_t lock; void __iomem *reg; -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) && defined(CONFIG_HAVE_CLK) +#ifdef CONFIG_HAVE_CLK struct clk *clk; #endif + struct m66592_platdata *pdata; + unsigned long irq_trigger; struct usb_gadget gadget; struct usb_gadget_driver *driver; @@ -546,13 +546,13 @@ static inline void m66592_read_fifo(struct m66592 *m66592, { unsigned long fifoaddr = (unsigned long)m66592->reg + offset; -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) - len = (len + 3) / 4; - insl(fifoaddr, buf, len); -#else - len = (len + 1) / 2; - insw(fifoaddr, buf, len); -#endif + if (m66592->pdata->on_chip) { + len = (len + 3) / 4; + insl(fifoaddr, buf, len); + } else { + len = (len + 1) / 2; + insw(fifoaddr, buf, len); + } } static inline void m66592_write(struct m66592 *m66592, u16 val, @@ -566,33 +566,34 @@ static inline void m66592_write_fifo(struct m66592 *m66592, void *buf, unsigned long len) { unsigned long fifoaddr = (unsigned long)m66592->reg + offset; -#if defined(CONFIG_SUPERH_BUILT_IN_M66592) - unsigned long count; - unsigned char *pb; - int i; - count = len / 4; - outsl(fifoaddr, buf, count); + if (m66592->pdata->on_chip) { + unsigned long count; + unsigned char *pb; + int i; - if (len & 0x00000003) { - pb = buf + count * 4; - for (i = 0; i < (len & 0x00000003); i++) { - if (m66592_read(m66592, M66592_CFBCFG)) /* little */ - outb(pb[i], fifoaddr + (3 - i)); - else - outb(pb[i], fifoaddr + i); + count = len / 4; + outsl(fifoaddr, buf, count); + + if (len & 0x00000003) { + pb = buf + count * 4; + for (i = 0; i < (len & 0x00000003); i++) { + if (m66592_read(m66592, M66592_CFBCFG)) /* le */ + outb(pb[i], fifoaddr + (3 - i)); + else + outb(pb[i], fifoaddr + i); + } + } + } else { + unsigned long odd = len & 0x0001; + + len = len / 2; + outsw(fifoaddr, buf, len); + if (odd) { + unsigned char *p = buf + len*2; + outb(*p, fifoaddr); } } -#else - unsigned long odd = len & 0x0001; - - len = len / 2; - outsw(fifoaddr, buf, len); - if (odd) { - unsigned char *p = buf + len*2; - outb(*p, fifoaddr); - } -#endif /* #if defined(CONFIG_SUPERH_BUILT_IN_M66592) */ } static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat, diff --git a/include/linux/usb/m66592.h b/include/linux/usb/m66592.h new file mode 100644 index 00000000000..cda9625e7df --- /dev/null +++ b/include/linux/usb/m66592.h @@ -0,0 +1,44 @@ +/* + * M66592 driver platform data + * + * Copyright (C) 2009 Renesas Solutions Corp. + * + * 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; 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __LINUX_USB_M66592_H +#define __LINUX_USB_M66592_H + +#define M66592_PLATDATA_XTAL_12MHZ 0x01 +#define M66592_PLATDATA_XTAL_24MHZ 0x02 +#define M66592_PLATDATA_XTAL_48MHZ 0x03 + +struct m66592_platdata { + /* one = on chip controller, zero = external controller */ + unsigned on_chip:1; + + /* one = big endian, zero = little endian */ + unsigned endian:1; + + /* (external controller only) M66592_PLATDATA_XTAL_nnMHZ */ + unsigned xtal:2; + + /* (external controller only) one = 3.3V, zero = 1.5V */ + unsigned vif:1; + +}; + +#endif /* __LINUX_USB_M66592_H */ + From c690be1cb48cf5a95c34c879841cc6e2c4fbc425 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 14:58:39 +0000 Subject: [PATCH 039/262] i2c: change i2c-sh_mobile.c module_init() to subsys_initcall() Convert the i2c-sh_mobile i2c bus driver to use subsys_initcall() instead of module_init(). This change makes the driver register a bit earlier which together with earlier platform data moves the time for probe(). The earlier probe() makes it possible to use i2c_get_adapter() and i2c_transfer() from device_initcall(). The same strategy is used by other i2c bus drivers such as i2c-pxa.c and i2c-s3c2410.c. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/i2c/busses/i2c-sh_mobile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index 4f3d99cd169..820487d0d5c 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c @@ -637,7 +637,7 @@ static void __exit sh_mobile_i2c_adap_exit(void) platform_driver_unregister(&sh_mobile_i2c_driver); } -module_init(sh_mobile_i2c_adap_init); +subsys_initcall(sh_mobile_i2c_adap_init); module_exit(sh_mobile_i2c_adap_exit); MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); From 955c9863bb5855a994751843e7066017edc00410 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 15:14:29 +0000 Subject: [PATCH 040/262] sh: convert processor device setup functions to arch_initcall() Convert the processor platform device setup functions from __initcall() and sometimes device_initcall() to arch_initcall(). This makes sure that the platform devices are registered a bit earlier so the devices are available when drivers register using initcall levels earlier than device_initcall(). A good example is platform devices needed by i2c-sh_mobile.c which registers a bit earlier using subsys_initcall(). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh2/setup-sh7619.c | 2 +- arch/sh/kernel/cpu/sh2a/setup-mxg.c | 2 +- arch/sh/kernel/cpu/sh2a/setup-sh7201.c | 2 +- arch/sh/kernel/cpu/sh2a/setup-sh7203.c | 2 +- arch/sh/kernel/cpu/sh2a/setup-sh7206.c | 2 +- arch/sh/kernel/cpu/sh3/setup-sh7705.c | 2 +- arch/sh/kernel/cpu/sh3/setup-sh770x.c | 2 +- arch/sh/kernel/cpu/sh3/setup-sh7710.c | 2 +- arch/sh/kernel/cpu/sh3/setup-sh7720.c | 2 +- arch/sh/kernel/cpu/sh4/setup-sh4-202.c | 2 +- arch/sh/kernel/cpu/sh4/setup-sh7750.c | 2 +- arch/sh/kernel/cpu/sh4/setup-sh7760.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7343.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7366.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7763.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7770.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7780.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7785.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-sh7786.c | 2 +- arch/sh/kernel/cpu/sh4a/setup-shx3.c | 2 +- arch/sh/kernel/cpu/sh5/setup-sh5.c | 2 +- 24 files changed, 24 insertions(+), 24 deletions(-) diff --git a/arch/sh/kernel/cpu/sh2/setup-sh7619.c b/arch/sh/kernel/cpu/sh2/setup-sh7619.c index 13798733f2d..8555c05e866 100644 --- a/arch/sh/kernel/cpu/sh2/setup-sh7619.c +++ b/arch/sh/kernel/cpu/sh2/setup-sh7619.c @@ -187,7 +187,7 @@ static int __init sh7619_devices_setup(void) return platform_add_devices(sh7619_devices, ARRAY_SIZE(sh7619_devices)); } -__initcall(sh7619_devices_setup); +arch_initcall(sh7619_devices_setup); void __init plat_irq_setup(void) { diff --git a/arch/sh/kernel/cpu/sh2a/setup-mxg.c b/arch/sh/kernel/cpu/sh2a/setup-mxg.c index 869c2da4820..b6737644531 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-mxg.c +++ b/arch/sh/kernel/cpu/sh2a/setup-mxg.c @@ -238,7 +238,7 @@ static int __init mxg_devices_setup(void) return platform_add_devices(mxg_devices, ARRAY_SIZE(mxg_devices)); } -__initcall(mxg_devices_setup); +arch_initcall(mxg_devices_setup); void __init plat_irq_setup(void) { diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c index d8febe12806..fbde5b75deb 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7201.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7201.c @@ -357,7 +357,7 @@ static int __init sh7201_devices_setup(void) return platform_add_devices(sh7201_devices, ARRAY_SIZE(sh7201_devices)); } -__initcall(sh7201_devices_setup); +arch_initcall(sh7201_devices_setup); void __init plat_irq_setup(void) { diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c index 62e3039d239..d3fd536c9a8 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7203.c @@ -367,7 +367,7 @@ static int __init sh7203_devices_setup(void) return platform_add_devices(sh7203_devices, ARRAY_SIZE(sh7203_devices)); } -__initcall(sh7203_devices_setup); +arch_initcall(sh7203_devices_setup); void __init plat_irq_setup(void) { diff --git a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c index 3e6f3d7a58b..a9ccc5e8d9e 100644 --- a/arch/sh/kernel/cpu/sh2a/setup-sh7206.c +++ b/arch/sh/kernel/cpu/sh2a/setup-sh7206.c @@ -338,7 +338,7 @@ static int __init sh7206_devices_setup(void) return platform_add_devices(sh7206_devices, ARRAY_SIZE(sh7206_devices)); } -__initcall(sh7206_devices_setup); +arch_initcall(sh7206_devices_setup); void __init plat_irq_setup(void) { diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7705.c b/arch/sh/kernel/cpu/sh3/setup-sh7705.c index 88f742fed9e..c2310598387 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7705.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7705.c @@ -222,7 +222,7 @@ static int __init sh7705_devices_setup(void) return platform_add_devices(sh7705_devices, ARRAY_SIZE(sh7705_devices)); } -__initcall(sh7705_devices_setup); +arch_initcall(sh7705_devices_setup); static struct platform_device *sh7705_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh770x.c b/arch/sh/kernel/cpu/sh3/setup-sh770x.c index c5630679858..347ab35d069 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh770x.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh770x.c @@ -250,7 +250,7 @@ static int __init sh770x_devices_setup(void) return platform_add_devices(sh770x_devices, ARRAY_SIZE(sh770x_devices)); } -__initcall(sh770x_devices_setup); +arch_initcall(sh770x_devices_setup); static struct platform_device *sh770x_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7710.c b/arch/sh/kernel/cpu/sh3/setup-sh7710.c index efa76c8148f..717e90ae109 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7710.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7710.c @@ -226,7 +226,7 @@ static int __init sh7710_devices_setup(void) return platform_add_devices(sh7710_devices, ARRAY_SIZE(sh7710_devices)); } -__initcall(sh7710_devices_setup); +arch_initcall(sh7710_devices_setup); static struct platform_device *sh7710_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh3/setup-sh7720.c b/arch/sh/kernel/cpu/sh3/setup-sh7720.c index 5b2107798ed..74d8baaf8e9 100644 --- a/arch/sh/kernel/cpu/sh3/setup-sh7720.c +++ b/arch/sh/kernel/cpu/sh3/setup-sh7720.c @@ -388,7 +388,7 @@ static int __init sh7720_devices_setup(void) return platform_add_devices(sh7720_devices, ARRAY_SIZE(sh7720_devices)); } -__initcall(sh7720_devices_setup); +arch_initcall(sh7720_devices_setup); static struct platform_device *sh7720_early_devices[] __initdata = { &cmt0_device, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c index 6d088d12359..de4827df19a 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh4-202.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh4-202.c @@ -138,7 +138,7 @@ static int __init sh4202_devices_setup(void) return platform_add_devices(sh4202_devices, ARRAY_SIZE(sh4202_devices)); } -__initcall(sh4202_devices_setup); +arch_initcall(sh4202_devices_setup); static struct platform_device *sh4202_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7750.c b/arch/sh/kernel/cpu/sh4/setup-sh7750.c index 851672d15cf..1b8b122e8f3 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7750.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7750.c @@ -239,7 +239,7 @@ static int __init sh7750_devices_setup(void) return platform_add_devices(sh7750_devices, ARRAY_SIZE(sh7750_devices)); } -__initcall(sh7750_devices_setup); +arch_initcall(sh7750_devices_setup); static struct platform_device *sh7750_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh4/setup-sh7760.c b/arch/sh/kernel/cpu/sh4/setup-sh7760.c index 5b822519bd9..7fbb7be9284 100644 --- a/arch/sh/kernel/cpu/sh4/setup-sh7760.c +++ b/arch/sh/kernel/cpu/sh4/setup-sh7760.c @@ -265,7 +265,7 @@ static int __init sh7760_devices_setup(void) return platform_add_devices(sh7760_devices, ARRAY_SIZE(sh7760_devices)); } -__initcall(sh7760_devices_setup); +arch_initcall(sh7760_devices_setup); static struct platform_device *sh7760_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c index 6307e087c86..ac4d5672ec1 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c @@ -325,7 +325,7 @@ static int __init sh7343_devices_setup(void) return platform_add_devices(sh7343_devices, ARRAY_SIZE(sh7343_devices)); } -__initcall(sh7343_devices_setup); +arch_initcall(sh7343_devices_setup); static struct platform_device *sh7343_early_devices[] __initdata = { &cmt_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c index f6d20881356..4a9010bf4fd 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c @@ -318,7 +318,7 @@ static int __init sh7366_devices_setup(void) return platform_add_devices(sh7366_devices, ARRAY_SIZE(sh7366_devices)); } -__initcall(sh7366_devices_setup); +arch_initcall(sh7366_devices_setup); static struct platform_device *sh7366_early_devices[] __initdata = { &cmt_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 0bad14a4423..67b0d87fcb2 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -365,7 +365,7 @@ static int __init sh7722_devices_setup(void) return platform_add_devices(sh7722_devices, ARRAY_SIZE(sh7722_devices)); } -__initcall(sh7722_devices_setup); +arch_initcall(sh7722_devices_setup); static struct platform_device *sh7722_early_devices[] __initdata = { &cmt_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 28516499a2c..26dc4d32325 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -473,7 +473,7 @@ static int __init sh7723_devices_setup(void) return platform_add_devices(sh7723_devices, ARRAY_SIZE(sh7723_devices)); } -__initcall(sh7723_devices_setup); +arch_initcall(sh7723_devices_setup); static struct platform_device *sh7723_early_devices[] __initdata = { &cmt_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index e5ac9eb11c6..a04edaab9a2 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -508,7 +508,7 @@ static int __init sh7724_devices_setup(void) return platform_add_devices(sh7724_devices, ARRAY_SIZE(sh7724_devices)); } -device_initcall(sh7724_devices_setup); +arch_initcall(sh7724_devices_setup); static struct platform_device *sh7724_early_devices[] __initdata = { &cmt_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c index f1e0c0d36da..4659fff6b84 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7763.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7763.c @@ -314,7 +314,7 @@ static int __init sh7763_devices_setup(void) return platform_add_devices(sh7763_devices, ARRAY_SIZE(sh7763_devices)); } -__initcall(sh7763_devices_setup); +arch_initcall(sh7763_devices_setup); static struct platform_device *sh7763_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c index 1e86209db28..eead08d89d3 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7770.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7770.c @@ -368,7 +368,7 @@ static int __init sh7770_devices_setup(void) return platform_add_devices(sh7770_devices, ARRAY_SIZE(sh7770_devices)); } -__initcall(sh7770_devices_setup); +arch_initcall(sh7770_devices_setup); static struct platform_device *sh7770_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c index 715e05b431e..2c901f44695 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c @@ -256,7 +256,7 @@ static int __init sh7780_devices_setup(void) return platform_add_devices(sh7780_devices, ARRAY_SIZE(sh7780_devices)); } -__initcall(sh7780_devices_setup); +arch_initcall(sh7780_devices_setup); static struct platform_device *sh7780_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c index af561402570..7f6c718b6c3 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c @@ -263,7 +263,7 @@ static int __init sh7785_devices_setup(void) return platform_add_devices(sh7785_devices, ARRAY_SIZE(sh7785_devices)); } -__initcall(sh7785_devices_setup); +arch_initcall(sh7785_devices_setup); static struct platform_device *sh7785_early_devices[] __initdata = { &tmu0_device, diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c index b70049470a0..0104a8ec536 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7786.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7786.c @@ -547,7 +547,7 @@ static int __init sh7786_devices_setup(void) return platform_add_devices(sh7786_devices, ARRAY_SIZE(sh7786_devices)); } -device_initcall(sh7786_devices_setup); +arch_initcall(sh7786_devices_setup); void __init plat_early_device_setup(void) { diff --git a/arch/sh/kernel/cpu/sh4a/setup-shx3.c b/arch/sh/kernel/cpu/sh4a/setup-shx3.c index 53c65fd9cce..07f078961c7 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/setup-shx3.c @@ -256,7 +256,7 @@ static int __init shx3_devices_setup(void) return platform_add_devices(shx3_devices, ARRAY_SIZE(shx3_devices)); } -__initcall(shx3_devices_setup); +arch_initcall(shx3_devices_setup); void __init plat_early_device_setup(void) { diff --git a/arch/sh/kernel/cpu/sh5/setup-sh5.c b/arch/sh/kernel/cpu/sh5/setup-sh5.c index f5ff1ac57fc..6a0f82f7003 100644 --- a/arch/sh/kernel/cpu/sh5/setup-sh5.c +++ b/arch/sh/kernel/cpu/sh5/setup-sh5.c @@ -186,7 +186,7 @@ static int __init sh5_devices_setup(void) return platform_add_devices(sh5_devices, ARRAY_SIZE(sh5_devices)); } -__initcall(sh5_devices_setup); +arch_initcall(sh5_devices_setup); void __init plat_early_device_setup(void) { From e7d165146a7de5ceb4f68e188b2679f003744f54 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 16:20:54 +0000 Subject: [PATCH 041/262] sh: kfr2r09 board support - SCIF console This patch adds basic kfr2r09 board support. Only the SCIF1 console is supported with this patch, but this patch and a proper sh7724 configuration is all that is needed. Combine with an initramfs to have a small RAM based kernel and distribution booted as zImage from RAM via JTAG. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Makefile | 1 + arch/sh/boards/Kconfig | 7 ++++ arch/sh/boards/mach-kfr2r09/Makefile | 1 + arch/sh/boards/mach-kfr2r09/setup.c | 48 ++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 arch/sh/boards/mach-kfr2r09/Makefile create mode 100644 arch/sh/boards/mach-kfr2r09/setup.c diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 75d049b03f7..d7358d70f15 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -136,6 +136,7 @@ machdir-$(CONFIG_SH_7751_SYSTEMH) += mach-systemh machdir-$(CONFIG_SH_EDOSK7705) += mach-edosk7705 machdir-$(CONFIG_SH_HIGHLANDER) += mach-highlander machdir-$(CONFIG_SH_MIGOR) += mach-migor +machdir-$(CONFIG_SH_KFR2R09) += mach-kfr2r09 machdir-$(CONFIG_SH_SDK7780) += mach-sdk7780 machdir-$(CONFIG_SH_X3PROTO) += mach-x3proto machdir-$(CONFIG_SH_SH7763RDP) += mach-sh7763rdp diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig index 2b1af0eefa6..db04c85971a 100644 --- a/arch/sh/boards/Kconfig +++ b/arch/sh/boards/Kconfig @@ -193,6 +193,13 @@ config SH_AP325RXA Renesas "AP-325RXA" support. Compatible with ALGO SYSTEM CO.,LTD. "AP-320A" +config SH_KFR2R09 + bool "KFR2R09" + depends on CPU_SUBTYPE_SH7724 + select ARCH_REQUIRE_GPIOLIB + help + "Kit For R2R for 2009" support. + config SH_SH7763RDP bool "SH7763RDP" depends on CPU_SUBTYPE_SH7763 diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile new file mode 100644 index 00000000000..77037567633 --- /dev/null +++ b/arch/sh/boards/mach-kfr2r09/Makefile @@ -0,0 +1 @@ +obj-y := setup.o diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c new file mode 100644 index 00000000000..224318abc9e --- /dev/null +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -0,0 +1,48 @@ +/* + * KFR2R09 board support code + * + * 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 +#include +#include +#include + +static int __init kfr2r09_devices_setup(void) +{ + /* enable SCIF1 serial port for YC401 console support */ + gpio_request(GPIO_FN_SCIF1_RXD, NULL); + gpio_request(GPIO_FN_SCIF1_TXD, NULL); + + return 0; +} +device_initcall(kfr2r09_devices_setup); + +/* Return the board specific boot mode pin configuration */ +static int kfr2r09_mode_pins(void) +{ + /* MD0=1, MD1=1, MD2=0: Clock Mode 3 + * MD3=0: 16-bit Area0 Bus Width + * MD5=1: Little Endian + * MD8=1: Test Mode Disabled + */ + return MODE_PIN0 | MODE_PIN1 | MODE_PIN5 | MODE_PIN8; +} + +/* + * The Machine Vector + */ +static struct sh_machine_vector mv_kfr2r09 __initmv = { + .mv_name = "kfr2r09", + .mv_mode_pins = kfr2r09_mode_pins, +}; From a366aa64f3a51ca3deebe74447f929a5614d9b90 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 16:22:28 +0000 Subject: [PATCH 042/262] sh: kfr2r09 board support - NOR flash This patch adds NOR flash support to the kfr2r09 board. NOR flash support is added by describing the NOR flash chip hooked up to CS0 as platform device data for the physmap-flash MTD driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-kfr2r09/setup.c | 54 ++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 224318abc9e..382bf188430 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -18,13 +19,64 @@ #include #include +static struct mtd_partition kfr2r09_nor_flash_partitions[] = +{ + { + .name = "boot", + .offset = 0, + .size = (4 * 1024 * 1024), + .mask_flags = MTD_WRITEABLE, /* Read-only */ + }, + { + .name = "other", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct physmap_flash_data kfr2r09_nor_flash_data = { + .width = 2, + .parts = kfr2r09_nor_flash_partitions, + .nr_parts = ARRAY_SIZE(kfr2r09_nor_flash_partitions), +}; + +static struct resource kfr2r09_nor_flash_resources[] = { + [0] = { + .name = "NOR Flash", + .start = 0x00000000, + .end = 0x03ffffff, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device kfr2r09_nor_flash_device = { + .name = "physmap-flash", + .resource = kfr2r09_nor_flash_resources, + .num_resources = ARRAY_SIZE(kfr2r09_nor_flash_resources), + .dev = { + .platform_data = &kfr2r09_nor_flash_data, + }, +}; + +static struct platform_device *kfr2r09_devices[] __initdata = { + &kfr2r09_nor_flash_device, +}; + +#define BSC_CS0BCR 0xfec10004 +#define BSC_CS0WCR 0xfec10024 + static int __init kfr2r09_devices_setup(void) { /* enable SCIF1 serial port for YC401 console support */ gpio_request(GPIO_FN_SCIF1_RXD, NULL); gpio_request(GPIO_FN_SCIF1_TXD, NULL); - return 0; + /* setup NOR flash at CS0 */ + ctrl_outl(0x36db0400, BSC_CS0BCR); + ctrl_outl(0x00000500, BSC_CS0WCR); + + return platform_add_devices(kfr2r09_devices, + ARRAY_SIZE(kfr2r09_devices)); } device_initcall(kfr2r09_devices_setup); From 39a6bf1426af4aed2348bb533481027862346a37 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 22 Jul 2009 16:23:45 +0000 Subject: [PATCH 043/262] sh: kfr2r09 board support - KEYSC keypad This patch adds KEYSC keypad support to the kfr2r09 board. The keys driven by the sh7724 on-chip KEYSC block are described as a platform device and platform data for the sh_keysc driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-kfr2r09/setup.c | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index 382bf188430..bf5f8f8d3b5 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -14,9 +14,11 @@ #include #include #include +#include #include #include #include +#include #include static struct mtd_partition kfr2r09_nor_flash_partitions[] = @@ -58,8 +60,46 @@ static struct platform_device kfr2r09_nor_flash_device = { }, }; +static struct sh_keysc_info kfr2r09_sh_keysc_info = { + .mode = SH_KEYSC_MODE_1, /* KEYOUT0->4, KEYIN0->4 */ + .scan_timing = 3, + .delay = 10, + .keycodes = { + KEY_PHONE, KEY_CLEAR, KEY_MAIL, KEY_WWW, KEY_ENTER, + KEY_1, KEY_2, KEY_3, 0, KEY_UP, + KEY_4, KEY_5, KEY_6, 0, KEY_LEFT, + KEY_7, KEY_8, KEY_9, KEY_PROG1, KEY_RIGHT, + KEY_S, KEY_0, KEY_P, KEY_PROG2, KEY_DOWN, + 0, 0, 0, 0, 0 + }, +}; + +static struct resource kfr2r09_sh_keysc_resources[] = { + [0] = { + .name = "KEYSC", + .start = 0x044b0000, + .end = 0x044b000f, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 79, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device kfr2r09_sh_keysc_device = { + .name = "sh_keysc", + .id = 0, /* "keysc0" clock */ + .num_resources = ARRAY_SIZE(kfr2r09_sh_keysc_resources), + .resource = kfr2r09_sh_keysc_resources, + .dev = { + .platform_data = &kfr2r09_sh_keysc_info, + }, +}; + static struct platform_device *kfr2r09_devices[] __initdata = { &kfr2r09_nor_flash_device, + &kfr2r09_sh_keysc_device, }; #define BSC_CS0BCR 0xfec10004 @@ -75,6 +115,19 @@ static int __init kfr2r09_devices_setup(void) ctrl_outl(0x36db0400, BSC_CS0BCR); ctrl_outl(0x00000500, BSC_CS0WCR); + /* setup KEYSC pins */ + gpio_request(GPIO_FN_KEYOUT0, NULL); + gpio_request(GPIO_FN_KEYOUT1, NULL); + gpio_request(GPIO_FN_KEYOUT2, NULL); + gpio_request(GPIO_FN_KEYOUT3, NULL); + gpio_request(GPIO_FN_KEYOUT4_IN6, NULL); + gpio_request(GPIO_FN_KEYIN0, NULL); + gpio_request(GPIO_FN_KEYIN1, NULL); + gpio_request(GPIO_FN_KEYIN2, NULL); + gpio_request(GPIO_FN_KEYIN3, NULL); + gpio_request(GPIO_FN_KEYIN4, NULL); + gpio_request(GPIO_FN_KEYOUT5_IN5, NULL); + return platform_add_devices(kfr2r09_devices, ARRAY_SIZE(kfr2r09_devices)); } From 5bdef865eb358b6f3760e25e591ae115e9eeddef Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 23 Jul 2009 08:59:48 +0000 Subject: [PATCH 044/262] sh: kfr2r09 board support - mach-type and defconfig This patch adds a defconfig and a mach-types entry for the kfr2r09 board. At this point only a few devices like SCIF, KEYSC and NOR Flash are supported together with sh7724 devices such as IIC0, IIC1 and the multimedia blocks exported via UIO. Kexec is supported, but booting from flash is not (yet). Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/configs/kfr2r09_defconfig | 877 ++++++++++++++++++++++++++++++ arch/sh/tools/mach-types | 1 + 2 files changed, 878 insertions(+) create mode 100644 arch/sh/configs/kfr2r09_defconfig diff --git a/arch/sh/configs/kfr2r09_defconfig b/arch/sh/configs/kfr2r09_defconfig new file mode 100644 index 00000000000..90e575c34d5 --- /dev/null +++ b/arch/sh/configs/kfr2r09_defconfig @@ -0,0 +1,877 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.31-rc3 +# Thu Jul 23 17:45:09 2009 +# +CONFIG_SUPERH=y +CONFIG_SUPERH32=y +# CONFIG_SUPERH64 is not set +CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig" +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_IRQ_PER_CPU=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_SYS_SUPPORTS_CMT=y +CONFIG_SYS_SUPPORTS_TMU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_NO_VIRT_TO_BUS=y +CONFIG_ARCH_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_CONSTRUCTORS=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set +# CONFIG_CGROUPS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +# CONFIG_KALLSYMS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_HAVE_PERF_COUNTERS=y + +# +# Performance Counters +# +# CONFIG_PERF_COUNTERS is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +# CONFIG_SLOW_WORK is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +CONFIG_LBDAF=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_NOOP=y +CONFIG_DEFAULT_IOSCHED="noop" +# CONFIG_FREEZER is not set + +# +# System type +# +CONFIG_CPU_SH4=y +CONFIG_CPU_SH4A=y +CONFIG_CPU_SHX2=y +CONFIG_ARCH_SHMOBILE=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7201 is not set +# CONFIG_CPU_SUBTYPE_SH7203 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7263 is not set +# CONFIG_CPU_SUBTYPE_MXG is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7721 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set +# CONFIG_CPU_SUBTYPE_SH7723 is not set +CONFIG_CPU_SUBTYPE_SH7724=y +# CONFIG_CPU_SUBTYPE_SH7763 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set +# CONFIG_CPU_SUBTYPE_SH7785 is not set +# CONFIG_CPU_SUBTYPE_SH7786 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +# CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH7366 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x80000000 +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_MEMORY_START=0x08000000 +CONFIG_MEMORY_SIZE=0x08000000 +CONFIG_29BIT=y +# CONFIG_X2TLB is not set +CONFIG_VSYSCALL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=1 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=2 +CONFIG_HAVE_MLOCK=y +CONFIG_HAVE_MLOCKED_PAGE_BIT=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 + +# +# Cache configuration +# +CONFIG_CACHE_WRITEBACK=y +# CONFIG_CACHE_WRITETHROUGH is not set +# CONFIG_CACHE_OFF is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SH_FPU=y +# CONFIG_SH_STORE_QUEUES is not set +CONFIG_CPU_HAS_INTEVT=y +CONFIG_CPU_HAS_SR_RB=y +CONFIG_CPU_HAS_FPU=y + +# +# Board support +# +# CONFIG_SH_7724_SOLUTION_ENGINE is not set +CONFIG_SH_KFR2R09=y + +# +# Timer and clock configuration +# +# CONFIG_SH_TIMER_TMU is not set +CONFIG_SH_TIMER_CMT=y +CONFIG_SH_PCLK_FREQ=33333333 +CONFIG_SH_CLK_CPG=y +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# +# CONFIG_SH_DMA is not set + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +# CONFIG_HEARTBEAT is not set +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +# CONFIG_HZ_100 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_300 is not set +CONFIG_HZ_1000=y +CONFIG_HZ=1000 +# CONFIG_SCHED_HRTICK is not set +CONFIG_KEXEC=y +# CONFIG_CRASH_DUMP is not set +# CONFIG_SECCOMP is not set +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PREEMPT is not set +CONFIG_GUSA=y +# CONFIG_SPARSE_IRQ is not set + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_ENTRY_OFFSET=0x00001000 +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttySC1,115200" + +# +# Bus options +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options (EXPERIMENTAL) +# +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# CONFIG_SUSPEND is not set +# CONFIG_HIBERNATION is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_WIRELESS is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_CONCAT=y +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +# CONFIG_MTD_PHYSMAP_COMPAT is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_GLUEBI is not set + +# +# UBI debugging options +# +# CONFIG_MTD_UBI_DEBUG is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_NETDEVICES is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_GPIO is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +CONFIG_KEYBOARD_SH_KEYSC=y +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_DEVKMEM=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_SH_SCI=y +CONFIG_SERIAL_SH_SCI_NR_UARTS=6 +CONFIG_SERIAL_SH_SCI_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +# CONFIG_R3964 is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_CHARDEV is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_OCORES is not set +CONFIG_I2C_SH_MOBILE=y +# CONFIG_I2C_SIMTEC is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_PCA_PLATFORM is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_PCF8575 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set +# CONFIG_SPI is not set + +# +# PPS support +# +# CONFIG_PPS is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO expanders: +# + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set + +# +# PCI GPIO expanders: +# + +# +# SPI GPIO expanders: +# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_TPS65010 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_AB3100_CORE is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +# CONFIG_HID_SUPPORT is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +CONFIG_UIO=y +# CONFIG_UIO_PDRV is not set +CONFIG_UIO_PDRV_GENIRQ=y +# CONFIG_UIO_SMX is not set +# CONFIG_UIO_SERCOS3 is not set + +# +# TI VLYNQ +# +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_FILE_LOCKING=y +# CONFIG_FSNOTIFY is not set +# CONFIG_INOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_LATENCYTOP is not set +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FTRACE_SYSCALLS=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +CONFIG_CRC_T10DIF=y +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +CONFIG_CRC7=y +# CONFIG_LIBCRC32C is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_HAVE_LMB=y +CONFIG_NLATTR=y +CONFIG_GENERIC_ATOMIC64=y diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index fec3a53b865..09eef360dde 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -56,3 +56,4 @@ SH7785LCR SH_SH7785LCR URQUELL SH_URQUELL ESPT SH_ESPT POLARIS SH_POLARIS +KFR2R09 SH_KFR2R09 From dfff0fa65ab15db45acd64b3189787d37ab163cd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 27 Jul 2009 20:53:22 +0900 Subject: [PATCH 045/262] sh: wire up clear_user_highpage() for sh4, convert sh7705. This wires up clear_user_highpage() on SH-4 and subsequently converts the SH7705 32kB cache mode over to using it. Now that the SH-4 implementation handles all of the dcache purging directly in the aliasing case, there is no need to do this in the default clear_page() implementation. Signed-off-by: Paul Mundt --- arch/sh/include/asm/cacheflush.h | 2 +- arch/sh/include/asm/page.h | 12 ++-- arch/sh/include/asm/pgtable.h | 3 +- arch/sh/kernel/sh_ksyms_32.c | 6 -- arch/sh/lib/clear_page.S | 46 -------------- arch/sh/mm/Makefile_32 | 2 +- arch/sh/mm/pg-nommu.c | 7 +-- arch/sh/mm/pg-sh4.c | 29 +++++---- arch/sh/mm/pg-sh7705.c | 102 ------------------------------- 9 files changed, 27 insertions(+), 182 deletions(-) delete mode 100644 arch/sh/mm/pg-sh7705.c diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h index 4c5462daa74..4e360114269 100644 --- a/arch/sh/include/asm/cacheflush.h +++ b/arch/sh/include/asm/cacheflush.h @@ -49,7 +49,7 @@ static inline void flush_kernel_dcache_page(struct page *page) flush_dcache_page(page); } -#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_CACHE_OFF) +#if (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) && !defined(CONFIG_CACHE_OFF) extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len); diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index a31ab40040f..5208b7bfc24 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -56,21 +56,25 @@ pages_do_alias(unsigned long addr1, unsigned long addr2) return (addr1 ^ addr2) & shm_align_mask; } -extern void clear_page(void *to); + +#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE) extern void copy_page(void *to, void *from); +struct page; +struct vm_area_struct; + #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ (defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \ defined(CONFIG_SH7705_CACHE_32KB)) -struct page; -struct vm_area_struct; extern void clear_user_page(void *to, unsigned long address, struct page *page); extern void copy_user_page(void *to, void *from, unsigned long address, struct page *page); -#if defined(CONFIG_CPU_SH4) +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) extern void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr, struct vm_area_struct *vma); #define __HAVE_ARCH_COPY_USER_HIGHPAGE +extern void clear_user_highpage(struct page *page, unsigned long vaddr); +#define clear_user_highpage clear_user_highpage #endif #else #define clear_user_page(page, vaddr, pg) clear_page(page) diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index d9f68f9c3cb..bef3ab7fc09 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -141,7 +141,8 @@ extern void paging_init(void); extern void page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd); -#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_CPU_SH4) && defined(CONFIG_MMU) +#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ + defined(CONFIG_SH7705_CACHE_32KB)) && defined(CONFIG_MMU) extern void kmap_coherent_init(void); #else #define kmap_coherent_init() do { } while (0) diff --git a/arch/sh/kernel/sh_ksyms_32.c b/arch/sh/kernel/sh_ksyms_32.c index cec610888e2..8dbe26b17c4 100644 --- a/arch/sh/kernel/sh_ksyms_32.c +++ b/arch/sh/kernel/sh_ksyms_32.c @@ -101,11 +101,6 @@ EXPORT_SYMBOL(flush_cache_range); EXPORT_SYMBOL(flush_dcache_page); #endif -#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ - (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) -EXPORT_SYMBOL(clear_user_page); -#endif - #ifdef CONFIG_MCOUNT DECLARE_EXPORT(mcount); #endif @@ -114,7 +109,6 @@ EXPORT_SYMBOL(csum_partial_copy_generic); #ifdef CONFIG_IPV6 EXPORT_SYMBOL(csum_ipv6_magic); #endif -EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(_ebss); diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/clear_page.S index 8342bfbde64..bee9817e055 100644 --- a/arch/sh/lib/clear_page.S +++ b/arch/sh/lib/clear_page.S @@ -8,52 +8,6 @@ #include #include -/* - * clear_page - * @to: P1 address - * - * void clear_page(void *to) - */ - -/* - * r0 --- scratch - * r4 --- to - * r5 --- to + PAGE_SIZE - */ -ENTRY(clear_page) - mov r4,r5 - mov.l .Llimit,r0 - add r0,r5 - mov #0,r0 - ! -1: -#if defined(CONFIG_CPU_SH4) - movca.l r0,@r4 - mov r4,r1 -#else - mov.l r0,@r4 -#endif - add #32,r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 -#if defined(CONFIG_CPU_SH4) - ocbwb @r1 -#endif - cmp/eq r5,r4 - bf/s 1b - add #28,r4 - ! - rts - nop - - .balign 4 -.Llimit: .long (PAGE_SIZE-28) - ENTRY(__clear_user) ! mov #0, r0 diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 986a1e05583..5c04bbb08d3 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 @@ -31,7 +31,7 @@ tlb-$(CONFIG_CPU_HAS_PTEAEX) := tlb-pteaex.o obj-y += $(tlb-y) ifndef CONFIG_CACHE_OFF obj-$(CONFIG_CPU_SH4) += pg-sh4.o -obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o +obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh4.o endif endif diff --git a/arch/sh/mm/pg-nommu.c b/arch/sh/mm/pg-nommu.c index 91ed4e695ff..7e33b486b7e 100644 --- a/arch/sh/mm/pg-nommu.c +++ b/arch/sh/mm/pg-nommu.c @@ -1,7 +1,7 @@ /* * arch/sh/mm/pg-nommu.c * - * clear_page()/copy_page() implementation for MMUless SH. + * copy_page()/__copy_user()/__clear_user() implementations for MMUless SH. * * Copyright (C) 2003 Paul Mundt * @@ -20,11 +20,6 @@ void copy_page(void *to, void *from) memcpy(to, from, PAGE_SIZE); } -void clear_page(void *to) -{ - memset(to, 0, PAGE_SIZE); -} - __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n) { memcpy(to, from, n); diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c index f3c4b2a54fc..4d93070b822 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-sh4.c @@ -2,7 +2,7 @@ * arch/sh/mm/pg-sh4.c * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka - * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 - 2009 Paul Mundt * * Released under the terms of the GNU GPL v2.0. */ @@ -58,20 +58,6 @@ static inline void kunmap_coherent(struct page *page) preempt_check_resched(); } -/* - * clear_user_page - * @to: P1 address - * @address: U0 address to be mapped - * @page: page (virt_to_page(to)) - */ -void clear_user_page(void *to, unsigned long address, struct page *page) -{ - clear_page(to); - - if (pages_do_alias((unsigned long)to, address & PAGE_MASK)) - __flush_wback_region(to, PAGE_SIZE); -} - void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) @@ -128,3 +114,16 @@ void copy_user_highpage(struct page *to, struct page *from, smp_wmb(); } EXPORT_SYMBOL(copy_user_highpage); + +void clear_user_highpage(struct page *page, unsigned long vaddr) +{ + void *kaddr = kmap_atomic(page, KM_USER0); + + clear_page(kaddr); + + if (pages_do_alias((unsigned long)kaddr, vaddr & PAGE_MASK)) + __flush_wback_region(kaddr, PAGE_SIZE); + + kunmap_atomic(kaddr, KM_USER0); +} +EXPORT_SYMBOL(clear_user_highpage); diff --git a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c deleted file mode 100644 index 684891b5c8c..00000000000 --- a/arch/sh/mm/pg-sh7705.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * arch/sh/mm/pg-sh7705.c - * - * Copyright (C) 1999, 2000 Niibe Yutaka - * Copyright (C) 2004 Alex Song - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -static void __flush_purge_virtual_region(void *p1, void *virt, int size) -{ - unsigned long v; - unsigned long begin, end; - unsigned long p1_begin; - - - begin = L1_CACHE_ALIGN((unsigned long)virt); - end = L1_CACHE_ALIGN((unsigned long)virt + size); - - p1_begin = (unsigned long)p1 & ~(L1_CACHE_BYTES - 1); - - /* do this the slow way as we may not have TLB entries - * for virt yet. */ - for (v = begin; v < end; v += L1_CACHE_BYTES) { - unsigned long p; - unsigned long ways, addr; - - p = __pa(p1_begin); - - ways = current_cpu_data.dcache.ways; - addr = CACHE_OC_ADDRESS_ARRAY; - - do { - unsigned long data; - - addr |= (v & current_cpu_data.dcache.entry_mask); - - data = ctrl_inl(addr); - if ((data & CACHE_PHYSADDR_MASK) == - (p & CACHE_PHYSADDR_MASK)) { - data &= ~(SH_CACHE_UPDATED|SH_CACHE_VALID); - ctrl_outl(data, addr); - } - - addr += current_cpu_data.dcache.way_incr; - } while (--ways); - - p1_begin += L1_CACHE_BYTES; - } -} - -/* - * clear_user_page - * @to: P1 address - * @address: U0 address to be mapped - */ -void clear_user_page(void *to, unsigned long address, struct page *pg) -{ - if (pages_do_alias(address, (unsigned long)to)) - __flush_purge_virtual_region(to, - (void *)(address & 0xfffff000), - PAGE_SIZE); - - clear_page(to); - __flush_wback_region(to, PAGE_SIZE); -} - -/* - * copy_user_page - * @to: P1 address - * @from: P1 address - * @address: U0 address to be mapped - */ -void copy_user_page(void *to, void *from, unsigned long address, struct page *pg) -{ - if (pages_do_alias(address, (unsigned long)to)) - __flush_purge_virtual_region(to, - (void *)(address & 0xfffff000), - PAGE_SIZE); - - copy_page(to, from); - __flush_wback_region(to, PAGE_SIZE); -} From 221c007b028ebf663ebee4fc90483909547d92a7 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 27 Jul 2009 20:55:46 +0900 Subject: [PATCH 046/262] sh: Rename arch/sh/lib/clear_page.S -> __clear_user.S. Now that this only contains the __clear_user() function, rename it accordingly. Signed-off-by: Paul Mundt --- arch/sh/lib/Makefile | 2 +- arch/sh/lib/{clear_page.S => __clear_user.S} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename arch/sh/lib/{clear_page.S => __clear_user.S} (100%) diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index c2b28d8b2dd..a969b47c546 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -23,7 +23,7 @@ obj-y += io.o memcpy-y := memcpy.o memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o -lib-$(CONFIG_MMU) += copy_page.o clear_page.o +lib-$(CONFIG_MMU) += copy_page.o __clear_user.o lib-$(CONFIG_MCOUNT) += mcount.o lib-y += $(memcpy-y) $(udivsi3-y) diff --git a/arch/sh/lib/clear_page.S b/arch/sh/lib/__clear_user.S similarity index 100% rename from arch/sh/lib/clear_page.S rename to arch/sh/lib/__clear_user.S From 0dfae7d5a21901b28ec0452d71be64adf5ea323e Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 27 Jul 2009 21:30:17 +0900 Subject: [PATCH 047/262] sh: Use the now generic SH-4 clear/copy page ops for all MMU platforms. Now that the SH-4 page clear/copy ops are generic, they can be used for all platforms with CONFIG_MMU=y. SH-5 remains the odd one out, but it too will gradually be converted over to using this interface. SH-3 platforms which do not contain aliases will see no impact from this change, while aliasing SH-3 platforms will get the same interface as SH-4. Signed-off-by: Paul Mundt --- arch/sh/include/asm/cacheflush.h | 15 --------------- arch/sh/include/asm/page.h | 11 ++++++----- arch/sh/include/asm/pgtable.h | 3 +-- arch/sh/mm/Makefile_32 | 6 +----- arch/sh/mm/cache-sh5.c | 17 +++++++++++++++++ arch/sh/mm/{pg-sh4.c => pg-mmu.c} | 19 +++++++++++++------ 6 files changed, 38 insertions(+), 33 deletions(-) rename arch/sh/mm/{pg-sh4.c => pg-mmu.c} (83%) diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h index 4e360114269..4c85d55847c 100644 --- a/arch/sh/include/asm/cacheflush.h +++ b/arch/sh/include/asm/cacheflush.h @@ -49,7 +49,6 @@ static inline void flush_kernel_dcache_page(struct page *page) flush_dcache_page(page); } -#if (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) && !defined(CONFIG_CACHE_OFF) extern void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len); @@ -57,20 +56,6 @@ extern void copy_to_user_page(struct vm_area_struct *vma, extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len); -#else -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ - do { \ - flush_cache_page(vma, vaddr, page_to_pfn(page));\ - memcpy(dst, src, len); \ - flush_icache_user_range(vma, page, vaddr, len); \ - } while (0) - -#define copy_from_user_page(vma, page, vaddr, dst, src, len) \ - do { \ - flush_cache_page(vma, vaddr, page_to_pfn(page));\ - memcpy(dst, src, len); \ - } while (0) -#endif #define flush_cache_vmap(start, end) flush_cache_all() #define flush_cache_vunmap(start, end) flush_cache_all() diff --git a/arch/sh/include/asm/page.h b/arch/sh/include/asm/page.h index 5208b7bfc24..847eeabb908 100644 --- a/arch/sh/include/asm/page.h +++ b/arch/sh/include/asm/page.h @@ -63,22 +63,23 @@ extern void copy_page(void *to, void *from); struct page; struct vm_area_struct; -#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ - (defined(CONFIG_CPU_SH5) || defined(CONFIG_CPU_SH4) || \ - defined(CONFIG_SH7705_CACHE_32KB)) +#if defined(CONFIG_CPU_SH5) extern void clear_user_page(void *to, unsigned long address, struct page *page); extern void copy_user_page(void *to, void *from, unsigned long address, struct page *page); -#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) + +#elif defined(CONFIG_MMU) extern void copy_user_highpage(struct page *to, struct page *from, unsigned long vaddr, struct vm_area_struct *vma); #define __HAVE_ARCH_COPY_USER_HIGHPAGE extern void clear_user_highpage(struct page *page, unsigned long vaddr); #define clear_user_highpage clear_user_highpage -#endif + #else + #define clear_user_page(page, vaddr, pg) clear_page(page) #define copy_user_page(to, from, vaddr, pg) copy_page(to, from) + #endif /* diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index bef3ab7fc09..ba2333216c5 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -141,8 +141,7 @@ extern void paging_init(void); extern void page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd); -#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ - defined(CONFIG_SH7705_CACHE_32KB)) && defined(CONFIG_MMU) +#if defined(CONFIG_MMU) && !defined(CONFIG_CPU_SH5) extern void kmap_coherent_init(void); #else #define kmap_coherent_init() do { } while (0) diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 5c04bbb08d3..62e280734dc 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 @@ -15,7 +15,7 @@ endif obj-y += $(cache-y) mmu-y := tlb-nommu.o pg-nommu.o -mmu-$(CONFIG_MMU) := fault_32.o tlbflush_32.o ioremap_32.o +mmu-$(CONFIG_MMU) := fault_32.o tlbflush_32.o ioremap_32.o pg-mmu.o obj-y += $(mmu-y) obj-$(CONFIG_DEBUG_FS) += asids-debugfs.o @@ -29,10 +29,6 @@ tlb-$(CONFIG_CPU_SH3) := tlb-sh3.o tlb-$(CONFIG_CPU_SH4) := tlb-sh4.o tlb-$(CONFIG_CPU_HAS_PTEAEX) := tlb-pteaex.o obj-y += $(tlb-y) -ifndef CONFIG_CACHE_OFF -obj-$(CONFIG_CPU_SH4) += pg-sh4.o -obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh4.o -endif endif obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff --git a/arch/sh/mm/cache-sh5.c b/arch/sh/mm/cache-sh5.c index 86762092508..3e2d7321b63 100644 --- a/arch/sh/mm/cache-sh5.c +++ b/arch/sh/mm/cache-sh5.c @@ -831,4 +831,21 @@ void clear_user_page(void *to, unsigned long address, struct page *page) else sh64_clear_user_page_coloured(to, address); } + +void copy_to_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + flush_cache_page(vma, vaddr, page_to_pfn(page)); + memcpy(dst, src, len); + flush_icache_user_range(vma, page, vaddr, len); +} + +void copy_from_user_page(struct vm_area_struct *vma, struct page *page, + unsigned long vaddr, void *dst, const void *src, + unsigned long len) +{ + flush_cache_page(vma, vaddr, page_to_pfn(page)); + memcpy(dst, src, len); +} #endif diff --git a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-mmu.c similarity index 83% rename from arch/sh/mm/pg-sh4.c rename to arch/sh/mm/pg-mmu.c index 4d93070b822..356d2cdcb20 100644 --- a/arch/sh/mm/pg-sh4.c +++ b/arch/sh/mm/pg-mmu.c @@ -1,5 +1,5 @@ /* - * arch/sh/mm/pg-sh4.c + * arch/sh/mm/pg-mmu.c * * Copyright (C) 1999, 2000, 2002 Niibe Yutaka * Copyright (C) 2002 - 2009 Paul Mundt @@ -22,11 +22,13 @@ static pte_t *kmap_coherent_pte; void __init kmap_coherent_init(void) { +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) unsigned long vaddr; /* cache the first coherent kmap pte */ vaddr = __fix_to_virt(FIX_CMAP_BEGIN); kmap_coherent_pte = kmap_get_fixmap_pte(vaddr); +#endif } static inline void *kmap_coherent(struct page *page, unsigned long addr) @@ -62,13 +64,15 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (page_mapped(page) && !test_bit(PG_dcache_dirty, &page->flags)) { + if (boot_cpu_data.dcache.n_aliases && page_mapped(page) && + !test_bit(PG_dcache_dirty, &page->flags)) { void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(vto, src, len); kunmap_coherent(vto); } else { memcpy(dst, src, len); - set_bit(PG_dcache_dirty, &page->flags); + if (boot_cpu_data.dcache.n_aliases) + set_bit(PG_dcache_dirty, &page->flags); } if (vma->vm_flags & VM_EXEC) @@ -79,13 +83,15 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page, unsigned long vaddr, void *dst, const void *src, unsigned long len) { - if (page_mapped(page) && !test_bit(PG_dcache_dirty, &page->flags)) { + if (boot_cpu_data.dcache.n_aliases && page_mapped(page) && + !test_bit(PG_dcache_dirty, &page->flags)) { void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(dst, vfrom, len); kunmap_coherent(vfrom); } else { memcpy(dst, src, len); - set_bit(PG_dcache_dirty, &page->flags); + if (boot_cpu_data.dcache.n_aliases) + set_bit(PG_dcache_dirty, &page->flags); } } @@ -96,7 +102,8 @@ void copy_user_highpage(struct page *to, struct page *from, vto = kmap_atomic(to, KM_USER1); - if (page_mapped(from) && !test_bit(PG_dcache_dirty, &from->flags)) { + if (boot_cpu_data.dcache.n_aliases && page_mapped(from) && + !test_bit(PG_dcache_dirty, &from->flags)) { vfrom = kmap_coherent(from, vaddr); copy_page(vto, vfrom); kunmap_coherent(vfrom); From 9cef7492696a416663b4edb953a4eade8517ebeb Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 29 Jul 2009 00:12:17 +0900 Subject: [PATCH 048/262] sh: update_mmu_cache() consolidation. This splits out a separate __update_cache()/__update_tlb() for update_mmu_cache() to wrap in to. This lets us share the common __update_cache() bits while keeping special __update_tlb() handling broken out. Signed-off-by: Paul Mundt --- arch/sh/include/asm/pgtable.h | 15 +++++++++++++-- arch/sh/mm/pg-mmu.c | 21 +++++++++++++++++++++ arch/sh/mm/tlb-nommu.c | 9 ++++++--- arch/sh/mm/tlb-pteaex.c | 13 ++++++------- arch/sh/mm/tlb-sh3.c | 29 ++++++----------------------- arch/sh/mm/tlb-sh4.c | 29 ++++++----------------------- arch/sh/mm/tlbflush_64.c | 25 +++++++++---------------- 7 files changed, 67 insertions(+), 74 deletions(-) diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index ba2333216c5..43ef3e99fdd 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -134,8 +134,19 @@ typedef pte_t *pte_addr_t; #define pgtable_cache_init() do { } while (0) struct vm_area_struct; -extern void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte); + +extern void __update_cache(struct vm_area_struct *vma, + unsigned long address, pte_t pte); +extern void __update_tlb(struct vm_area_struct *vma, + unsigned long address, pte_t pte); + +static inline void +update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +{ + __update_cache(vma, address, pte); + __update_tlb(vma, address, pte); +} + extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern void paging_init(void); extern void page_table_range_init(unsigned long start, unsigned long end, diff --git a/arch/sh/mm/pg-mmu.c b/arch/sh/mm/pg-mmu.c index 356d2cdcb20..8602f68af4c 100644 --- a/arch/sh/mm/pg-mmu.c +++ b/arch/sh/mm/pg-mmu.c @@ -134,3 +134,24 @@ void clear_user_highpage(struct page *page, unsigned long vaddr) kunmap_atomic(kaddr, KM_USER0); } EXPORT_SYMBOL(clear_user_highpage); + +void __update_cache(struct vm_area_struct *vma, + unsigned long address, pte_t pte) +{ + struct page *page; + unsigned long pfn = pte_pfn(pte); + + if (!boot_cpu_data.dcache.n_aliases) + return; + + page = pfn_to_page(pfn); + if (pfn_valid(pfn) && page_mapping(page)) { + int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); + if (dirty) { + unsigned long addr = (unsigned long)page_address(page); + + if (pages_do_alias(addr, address & PAGE_MASK)) + __flush_wback_region((void *)addr, PAGE_SIZE); + } + } +} diff --git a/arch/sh/mm/tlb-nommu.c b/arch/sh/mm/tlb-nommu.c index 71c742b5aee..0ef5429943d 100644 --- a/arch/sh/mm/tlb-nommu.c +++ b/arch/sh/mm/tlb-nommu.c @@ -46,10 +46,13 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) BUG(); } -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) +{ +} + +void __update_cache(struct vm_area_struct *vma, + unsigned long address, pte_t pte) { - BUG(); } void __init page_table_range_init(unsigned long start, unsigned long end, diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c index c39b7736335..9aabd313ced 100644 --- a/arch/sh/mm/tlb-pteaex.c +++ b/arch/sh/mm/tlb-pteaex.c @@ -16,15 +16,14 @@ #include #include -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) { - unsigned long flags; - unsigned long pteval; - unsigned long vpn; + unsigned long flags, pteval, vpn; - /* Ptrace may call this routine. */ - if (vma && current->active_mm != vma->vm_mm) + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) return; local_irq_save(flags); diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c index 9b8459c74ab..425f1f23cf9 100644 --- a/arch/sh/mm/tlb-sh3.c +++ b/arch/sh/mm/tlb-sh3.c @@ -27,32 +27,16 @@ #include #include -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) { - unsigned long flags; - unsigned long pteval; - unsigned long vpn; - unsigned long pfn = pte_pfn(pte); - struct page *page; + unsigned long flags, pteval, vpn; - /* Ptrace may call this routine. */ - if (vma && current->active_mm != vma->vm_mm) + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) return; - page = pfn_to_page(pfn); - if (pfn_valid(pfn) && page_mapping(page)) { -#if defined(CONFIG_SH7705_CACHE_32KB) - int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); - if (dirty) { - unsigned long addr = (unsigned long)page_address(page); - - if (pages_do_alias(addr, address & PAGE_MASK)) - __flush_wback_region((void *)addr, PAGE_SIZE); - } -#endif - } - local_irq_save(flags); /* Set PTEH register */ @@ -93,4 +77,3 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page) for (i = 0; i < ways; i++) ctrl_outl(data, addr + (i << 8)); } - diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c index cf50082d243..81199f1e594 100644 --- a/arch/sh/mm/tlb-sh4.c +++ b/arch/sh/mm/tlb-sh4.c @@ -15,33 +15,16 @@ #include #include -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) { - unsigned long flags; - unsigned long pteval; - unsigned long vpn; - unsigned long pfn = pte_pfn(pte); - struct page *page; + unsigned long flags, pteval, vpn; - /* Ptrace may call this routine. */ - if (vma && current->active_mm != vma->vm_mm) + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) return; - page = pfn_to_page(pfn); - if (pfn_valid(pfn) && page_mapping(page)) { -#ifndef CONFIG_SMP - int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); - if (dirty) { - - unsigned long addr = (unsigned long)page_address(page); - - if (pages_do_alias(addr, address & PAGE_MASK)) - __flush_wback_region((void *)addr, PAGE_SIZE); - } -#endif - } - local_irq_save(flags); /* Set PTEH register */ diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index 3ce40ea3482..f2e44e9ffb7 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c @@ -329,22 +329,6 @@ do_sigbus: goto no_context; } -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - /* - * This appears to get called once for every pte entry that gets - * established => I don't think it's efficient to try refilling the - * TLBs with the pages - some may not get accessed even. Also, for - * executable pages, it is impossible to determine reliably here which - * TLB they should be mapped into (or both even). - * - * So, just do nothing here and handle faults on demand. In the - * TLBMISS handling case, the refill is now done anyway after the pte - * has been fixed up, so that deals with most useful cases. - */ -} - void local_flush_tlb_one(unsigned long asid, unsigned long page) { unsigned long long match, pteh=0, lpage; @@ -482,3 +466,12 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) /* FIXME: Optimize this later.. */ flush_tlb_all(); } + +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) +{ +} + +void __update_cache(struct vm_area_struct *vma, + unsigned long address, pte_t pte) +{ +} From 3725f28b478035a0410268f06a383f24ede7971c Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Wed, 29 Jul 2009 09:24:41 +0000 Subject: [PATCH 049/262] usb: fix hibernate in r8a66597-hcd dev_pm_ops conversion. This fixes up the dev_pm_ops conversion and wires up the callbacks needed for hibernation. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- drivers/usb/host/r8a66597-hcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 82dce3e0d4d..749b5374282 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2357,6 +2357,8 @@ static int r8a66597_resume(struct device *dev) static struct dev_pm_ops r8a66597_dev_pm_ops = { .suspend = r8a66597_suspend, .resume = r8a66597_resume, + .poweroff = r8a66597_suspend, + .restore = r8a66597_resume, }; #define R8A66597_DEV_PM_OPS (&r8a66597_dev_pm_ops) From 3ed6e129390fb872c3b7e05a232e5d380fbdfb48 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 29 Jul 2009 22:06:58 +0900 Subject: [PATCH 050/262] sh: Handle a NULL vma in __update_tlb() for the fast-path. The TLB miss fast-path presently calls in to update_mmu_cache() to set up the entry, and does so with a NULL vma. Check for vma validity in the __update_tlb() ptrace checks. Signed-off-by: Paul Mundt --- arch/sh/mm/tlb-pteaex.c | 2 +- arch/sh/mm/tlb-sh3.c | 2 +- arch/sh/mm/tlb-sh4.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/sh/mm/tlb-pteaex.c b/arch/sh/mm/tlb-pteaex.c index 9aabd313ced..409b7c2b4b9 100644 --- a/arch/sh/mm/tlb-pteaex.c +++ b/arch/sh/mm/tlb-pteaex.c @@ -23,7 +23,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) /* * Handle debugger faulting in for debugee. */ - if (current->active_mm != vma->vm_mm) + if (vma && current->active_mm != vma->vm_mm) return; local_irq_save(flags); diff --git a/arch/sh/mm/tlb-sh3.c b/arch/sh/mm/tlb-sh3.c index 425f1f23cf9..ace8e6d2f59 100644 --- a/arch/sh/mm/tlb-sh3.c +++ b/arch/sh/mm/tlb-sh3.c @@ -34,7 +34,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) /* * Handle debugger faulting in for debugee. */ - if (current->active_mm != vma->vm_mm) + if (vma && current->active_mm != vma->vm_mm) return; local_irq_save(flags); diff --git a/arch/sh/mm/tlb-sh4.c b/arch/sh/mm/tlb-sh4.c index 81199f1e594..7d3c63e707a 100644 --- a/arch/sh/mm/tlb-sh4.c +++ b/arch/sh/mm/tlb-sh4.c @@ -22,7 +22,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) /* * Handle debugger faulting in for debugee. */ - if (current->active_mm != vma->vm_mm) + if (vma && current->active_mm != vma->vm_mm) return; local_irq_save(flags); From 82b242214b6f5b96eb9b76452ac6e2b67dd81abd Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 29 Jul 2009 22:43:58 +0900 Subject: [PATCH 051/262] Revert "sh: Bump the earlytimer bits back to time_init()." This reverts commit 1d29ebebcb951ab6b04d22807cafb24b893310a2. Bumping up the earlytimer initialization causes IRQs to be enabled too early, which blows up lockdep: ... NR_IRQS:256 nr_irqs:256 ------------[ cut here ]------------ Badness at kernel/lockdep.c:2128 Pid : 0, Comm: swapper CPU : 0 Not tainted (2.6.31-rc3-00205-g3ed6e12-dirty #2443) PC is at trace_hardirqs_on_caller+0x48/0x10c PR is at trace_hardirqs_on_caller+0x3c/0x10c ... Revert it back to late_time_init time, which fixes up lockdep. Signed-off-by: Paul Mundt --- arch/sh/kernel/time.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index d2424b068b7..7f95f479060 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -92,6 +92,21 @@ module_init(rtc_generic_init); void (*board_time_init)(void); +static void __init sh_late_time_init(void) +{ + /* + * Make sure all compiled-in early timers register themselves. + * + * Run probe() for two "earlytimer" devices, these will be the + * clockevents and clocksource devices respectively. In the event + * that only a clockevents device is available, we -ENODEV on the + * clocksource and the jiffies clocksource is used transparently + * instead. No error handling is necessary here. + */ + early_platform_driver_register_all("earlytimer"); + early_platform_driver_probe("earlytimer", 2, 0); +} + void __init time_init(void) { if (board_time_init) @@ -108,15 +123,5 @@ void __init time_init(void) local_timer_setup(smp_processor_id()); #endif - /* - * Make sure all compiled-in early timers register themselves. - * - * Run probe() for two "earlytimer" devices, these will be the - * clockevents and clocksource devices respectively. In the event - * that only a clockevents device is available, we -ENODEV on the - * clocksource and the jiffies clocksource is used transparently - * instead. No error handling is necessary here. - */ - early_platform_driver_register_all("earlytimer"); - early_platform_driver_probe("earlytimer", 2, 0); + late_time_init = sh_late_time_init; } From fd78a76aefb5bf28a11d6960d29e03a11db62320 Mon Sep 17 00:00:00 2001 From: Stuart Menefy Date: Wed, 29 Jul 2009 23:01:24 +0900 Subject: [PATCH 052/262] sh: Rework irqflags tracing to fix up CONFIG_PROVE_LOCKING. This cleans up the irqflags tracing code quite a bit and ties it in to various missing callsites that caused an imbalance when CONFIG_PROVE_LOCKING was enabled. Previously this was catching on: 987 #ifdef CONFIG_PROVE_LOCKING 988 DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled); 989 DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); 990 #endif 991 retval = -EAGAIN; with hardirqs being doubly enabled, and subsequently bailing out with the following call trace: Call trace: [<88035224>] __lock_acquire+0x616/0x6a6 [<88015a8c>] do_fork+0xf8/0x2b0 [<880331ec>] trace_hardirqs_on_caller+0xd4/0x114 [<88241074>] _spin_unlock_irq+0x20/0x64 [<88035224>] __lock_acquire+0x616/0x6a6 [<8800386c>] kernel_thread+0x48/0x70 [<88024ecc>] ____call_usermodehelper+0x0/0x110 [<88024ecc>] ____call_usermodehelper+0x0/0x110 [<88003894>] kernel_thread_helper+0x0/0x14 [<88024bac>] __call_usermodehelper+0x38/0x70 [<88025dc0>] worker_thread+0x150/0x274 [<88035b9c>] lock_release+0x0/0x198 [<88024b74>] __call_usermodehelper+0x0/0x70 [<88028cf0>] autoremove_wake_function+0x0/0x30 [<88028bf2>] kthread+0x3e/0x70 [<88025c70>] worker_thread+0x0/0x274 [<8800389c>] kernel_thread_helper+0x8/0x14 [<88028bb4>] kthread+0x0/0x70 [<88003894>] kernel_thread_helper+0x0/0x14 Reported-by: Nobuhiro Iwamatsu Signed-off-by: Stuart Menefy Signed-off-by: Matt Fleming Signed-off-by: Paul Mundt --- arch/sh/Kconfig.debug | 2 +- arch/sh/include/asm/entry-macros.S | 72 ++++++++++++++++++++++++++++++ arch/sh/kernel/entry-common.S | 63 +++++++------------------- arch/sh/kernel/io_trapped.c | 7 +-- drivers/serial/sh-sci.c | 5 ++- 5 files changed, 96 insertions(+), 53 deletions(-) diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index b440fd93671..a6dce41296e 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -38,7 +38,7 @@ config EARLY_SCIF_CONSOLE_PORT default "0xffe00000" if CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7763 || \ CPU_SUBTYPE_SH7722 || CPU_SUBTYPE_SH7366 || \ CPU_SUBTYPE_SH7343 - default "0xffea0000" if CPU_SUBTYPE_SH7785 + default "0xffeb0000" if CPU_SUBTYPE_SH7785 default "0xffeb0000" if CPU_SUBTYPE_SH7786 default "0xfffe8000" if CPU_SUBTYPE_SH7203 default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263 diff --git a/arch/sh/include/asm/entry-macros.S b/arch/sh/include/asm/entry-macros.S index 3a4752a6572..1bdd93891cd 100644 --- a/arch/sh/include/asm/entry-macros.S +++ b/arch/sh/include/asm/entry-macros.S @@ -31,6 +31,78 @@ #endif .endm +#ifdef CONFIG_TRACE_IRQFLAGS + + .macro TRACE_IRQS_ON + mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l r2, @-r15 + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + + mov.l 7834f, r0 + jsr @r0 + nop + + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + mov.l 7834f, r0 + + bra 7835f + nop + .balign 4 +7834: .long trace_hardirqs_on +7835: + .endm + .macro TRACE_IRQS_OFF + + mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l r2, @-r15 + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + + mov.l 7834f, r0 + jsr @r0 + nop + + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + mov.l 7834f, r0 + + bra 7835f + nop + .balign 4 +7834: .long trace_hardirqs_off +7835: + .endm + +#else + .macro TRACE_IRQS_ON + .endm + + .macro TRACE_IRQS_OFF + .endm +#endif + #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4) # define PREF(x) pref @x #else diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index d62175650c5..fc26ccd8278 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -45,7 +45,7 @@ */ #if defined(CONFIG_PREEMPT) -# define preempt_stop() cli +# define preempt_stop() cli ; TRACE_IRQS_OFF #else # define preempt_stop() # define resume_kernel __restore_all @@ -55,11 +55,7 @@ .align 2 ENTRY(exception_error) ! -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 2f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_ON sti mov.l 1f, r0 jmp @r0 @@ -67,22 +63,23 @@ ENTRY(exception_error) .align 2 1: .long do_exception_error -#ifdef CONFIG_TRACE_IRQFLAGS -2: .long trace_hardirqs_on -#endif .align 2 ret_from_exception: preempt_stop() -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 4f, r0 - jsr @r0 - nop -#endif ENTRY(ret_from_irq) ! mov #OFF_SR, r0 mov.l @(r0,r15), r0 ! get status register + + shlr2 r0 + and #0x3c, r0 + cmp/eq #0x3c, r0 + bt 9f + TRACE_IRQS_ON +9: + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register shll r0 shll r0 ! kernel space? get_current_thread_info r8, r0 @@ -125,11 +122,7 @@ noresched: ENTRY(resume_userspace) ! r8: current_thread_info cli -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_OfF mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #(_TIF_WORK_MASK & 0xff), r0 bt/s __restore_all @@ -156,11 +149,7 @@ work_resched: jsr @r1 ! schedule nop cli -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_OFF ! mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #(_TIF_WORK_MASK & 0xff), r0 @@ -172,10 +161,6 @@ work_resched: 1: .long schedule 2: .long do_notify_resume 3: .long resume_userspace -#ifdef CONFIG_TRACE_IRQFLAGS -4: .long trace_hardirqs_on -5: .long trace_hardirqs_off -#endif .align 2 syscall_exit_work: @@ -184,11 +169,7 @@ syscall_exit_work: tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0 bt/s work_pending tst #_TIF_NEED_RESCHED, r0 -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_ON sti mov r15, r4 mov.l 8f, r0 ! do_syscall_trace_leave @@ -321,11 +302,7 @@ ENTRY(system_call) bt/s debug_trap ! it's a debug trap.. nop -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 5f, r10 - jsr @r10 - nop -#endif + TRACE_IRQS_ON sti ! @@ -355,11 +332,7 @@ syscall_call: ! syscall_exit: cli -#ifdef CONFIG_TRACE_IRQFLAGS - mov.l 6f, r0 - jsr @r0 - nop -#endif + TRACE_IRQS_OFF ! get_current_thread_info r8, r0 mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags @@ -377,9 +350,5 @@ syscall_exit: #endif 2: .long NR_syscalls 3: .long sys_call_table -#ifdef CONFIG_TRACE_IRQFLAGS -5: .long trace_hardirqs_on -6: .long trace_hardirqs_off -#endif 7: .long do_syscall_trace_enter 8: .long do_syscall_trace_leave diff --git a/arch/sh/kernel/io_trapped.c b/arch/sh/kernel/io_trapped.c index 77dfecb6437..e27a19e1f46 100644 --- a/arch/sh/kernel/io_trapped.c +++ b/arch/sh/kernel/io_trapped.c @@ -112,14 +112,15 @@ void __iomem *match_trapped_io_handler(struct list_head *list, struct trapped_io *tiop; struct resource *res; int k, len; + unsigned long flags; - spin_lock_irq(&trapped_lock); + spin_lock_irqsave(&trapped_lock, flags); list_for_each_entry(tiop, list, list) { voffs = 0; for (k = 0; k < tiop->num_resources; k++) { res = tiop->resource + k; if (res->start == offset) { - spin_unlock_irq(&trapped_lock); + spin_unlock_irqrestore(&trapped_lock, flags); return tiop->virt_base + voffs; } @@ -127,7 +128,7 @@ void __iomem *match_trapped_io_handler(struct list_head *list, voffs += roundup(len, PAGE_SIZE); } } - spin_unlock_irq(&trapped_lock); + spin_unlock_irqrestore(&trapped_lock, flags); return NULL; } EXPORT_SYMBOL_GPL(match_trapped_io_handler); diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 8e2feb56334..4cbb87ad070 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -662,10 +662,11 @@ static irqreturn_t sci_rx_interrupt(int irq, void *port) static irqreturn_t sci_tx_interrupt(int irq, void *ptr) { struct uart_port *port = ptr; + unsigned long flags; - spin_lock_irq(&port->lock); + spin_lock_irqsave(&port->lock, flags); sci_transmit_chars(port); - spin_unlock_irq(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); return IRQ_HANDLED; } From 3c928320b2254cb6c8d8a7919a1fcf94ca7cae66 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 29 Jul 2009 15:04:05 +0000 Subject: [PATCH 053/262] sh: romImage support V2 This patch contains support for the romImage build target V2. The resulting romImage file should be burned to rom or flash and could be used as small boot loader. Board code should keep their setup code in the file romimage.h located in their mach include directory. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/Makefile | 2 +- arch/sh/boot/Makefile | 11 +++++++++-- arch/sh/boot/romimage/Makefile | 19 +++++++++++++++++++ arch/sh/boot/romimage/head.S | 10 ++++++++++ arch/sh/boot/romimage/vmlinux.scr | 6 ++++++ arch/sh/include/mach-common/romimage.h | 1 + 6 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 arch/sh/boot/romimage/Makefile create mode 100644 arch/sh/boot/romimage/head.S create mode 100644 arch/sh/boot/romimage/vmlinux.scr create mode 100644 arch/sh/include/mach-common/romimage.h diff --git a/arch/sh/Makefile b/arch/sh/Makefile index c46b3d508f2..2a7e73faee8 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -195,7 +195,7 @@ libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.srec \ - zImage vmlinux.srec + zImage vmlinux.srec romImage PHONY += maketools $(BOOT_TARGETS) FORCE maketools: include/linux/version.h FORCE diff --git a/arch/sh/boot/Makefile b/arch/sh/boot/Makefile index dd2a852041e..a1316872be6 100644 --- a/arch/sh/boot/Makefile +++ b/arch/sh/boot/Makefile @@ -24,9 +24,9 @@ suffix-$(CONFIG_KERNEL_GZIP) := gz suffix-$(CONFIG_KERNEL_BZIP2) := bz2 suffix-$(CONFIG_KERNEL_LZMA) := lzma -targets := zImage vmlinux.srec uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma +targets := zImage vmlinux.srec romImage uImage uImage.srec uImage.gz uImage.bz2 uImage.lzma extra-y += vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma -subdir- := compressed +subdir- := compressed romimage $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(call if_changed,objcopy) @@ -35,6 +35,13 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE $(obj)/compressed/vmlinux: FORCE $(Q)$(MAKE) $(build)=$(obj)/compressed $@ +$(obj)/romImage: $(obj)/romimage/vmlinux FORCE + $(call if_changed,objcopy) + @echo ' Kernel: $@ is ready' + +$(obj)/romimage/vmlinux: $(obj)/zImage FORCE + $(Q)$(MAKE) $(build)=$(obj)/romimage $@ + KERNEL_MEMORY := 0x00000000 ifeq ($(CONFIG_PMB_FIXED),y) KERNEL_MEMORY := $(shell /bin/bash -c 'printf "0x%08x" \ diff --git a/arch/sh/boot/romimage/Makefile b/arch/sh/boot/romimage/Makefile new file mode 100644 index 00000000000..5806eee84f6 --- /dev/null +++ b/arch/sh/boot/romimage/Makefile @@ -0,0 +1,19 @@ +# +# linux/arch/sh/boot/romimage/Makefile +# +# create an image suitable for burning to flash from zImage +# + +targets := vmlinux head.o + +OBJECTS = $(obj)/head.o +LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext 0 -e romstart + +$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE + $(call if_changed,ld) + @: + +LDFLAGS_piggy.o := -r --format binary --oformat $(ld-bfd) -T + +$(obj)/piggy.o: $(obj)/vmlinux.scr arch/sh/boot/zImage FORCE + $(call if_changed,ld) diff --git a/arch/sh/boot/romimage/head.S b/arch/sh/boot/romimage/head.S new file mode 100644 index 00000000000..97a087bc9c4 --- /dev/null +++ b/arch/sh/boot/romimage/head.S @@ -0,0 +1,10 @@ +/* + * linux/arch/sh/boot/romimage/head.S + * + * Board specific setup code, executed before zImage loader + */ + +.text + .global romstart +romstart: +#include diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr new file mode 100644 index 00000000000..287c08f8b4b --- /dev/null +++ b/arch/sh/boot/romimage/vmlinux.scr @@ -0,0 +1,6 @@ +SECTIONS +{ + .text : { + *(.data) + } +} diff --git a/arch/sh/include/mach-common/romimage.h b/arch/sh/include/mach-common/romimage.h new file mode 100644 index 00000000000..267e24112d8 --- /dev/null +++ b/arch/sh/include/mach-common/romimage.h @@ -0,0 +1 @@ +/* do nothing here by default */ From d162300e6c963fe255ea7f73b956a7716e24205d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 29 Jul 2009 15:06:15 +0000 Subject: [PATCH 054/262] sh: kfr2r09 romImage support V2 This patch is romImage support for the kfr2r09 board V2. The partner-jet-setup.txt file is converted into assembly code which becomes the first code to execute from the reset vector. The file partner-jet-setup.txt can also be used to setup the hardware using a JTAG debugger so booting from RAM can be done without burning the code to flash. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- .../mach-kfr2r09/partner-jet-setup.txt | 134 ++++++++++++++++++ arch/sh/include/mach-kfr2r09/romimage.h | 75 ++++++++++ 2 files changed, 209 insertions(+) create mode 100644 arch/sh/include/mach-kfr2r09/partner-jet-setup.txt create mode 100644 arch/sh/include/mach-kfr2r09/romimage.h diff --git a/arch/sh/include/mach-kfr2r09/partner-jet-setup.txt b/arch/sh/include/mach-kfr2r09/partner-jet-setup.txt new file mode 100644 index 00000000000..9c85088728a --- /dev/null +++ b/arch/sh/include/mach-kfr2r09/partner-jet-setup.txt @@ -0,0 +1,134 @@ +LIST "partner-jet-setup.txt - 20090729 Magnus Damm" +LIST "set up enough of the kfr2r09 hardware to boot the kernel" + +LIST "zImage (RAM boot)" +LIST "This script can be used to boot the kernel from RAM via JTAG:" +LIST "> < partner-jet-setup.txt" +LIST "> RD zImage, 0xa8800000" +LIST "> G=0xa8800000" + +LIST "romImage (Flash boot)" +LIST "Use the following command to burn the zImage to flash via JTAG:" +LIST "> RD romImage, 0" + +LIST "--------------------------------" + +LIST "disable watchdog" +EW 0xa4520004, 0xa507 + +LIST "select mode for cs5 + cs6" +ED 0xff800020, 0xa5a50001 +ED 0xfec10000, 0x0000001b + +LIST "setup clocks" +ED 0xa4150004, 0x00000050 +ED 0xa4150000, 0x91053508 +WAIT 1 +ED 0xa4150024, 0x00005000 + +LIST "setup pins" +EB 0xa4050120, 0x00 +EB 0xa4050122, 0x00 +EB 0xa4050124, 0x00 +EB 0xa4050126, 0x00 +EB 0xa4050128, 0xA0 +EB 0xa405012A, 0x10 +EB 0xa405012C, 0x00 +EB 0xa405012E, 0x00 +EB 0xa4050130, 0x00 +EB 0xa4050132, 0x00 +EB 0xa4050134, 0x01 +EB 0xa4050136, 0x40 +EB 0xa4050138, 0x00 +EB 0xa405013A, 0x00 +EB 0xa405013C, 0x00 +EB 0xa405013E, 0x20 +EB 0xa4050160, 0x00 +EB 0xa4050162, 0x40 +EB 0xa4050164, 0x03 +EB 0xa4050166, 0x00 +EB 0xa4050168, 0x00 +EB 0xa405016A, 0x00 +EB 0xa405016C, 0x00 + +EW 0xa405014E, 0x5660 +EW 0xa4050150, 0x0145 +EW 0xa4050152, 0x1550 +EW 0xa4050154, 0x0200 +EW 0xa4050156, 0x0040 + +EW 0xa4050158, 0x0000 +EW 0xa405015a, 0x0000 +EW 0xa405015c, 0x0000 +EW 0xa405015e, 0x0000 + +EW 0xa4050180, 0x0000 +EW 0xa4050182, 0x8002 +EW 0xa4050184, 0x0000 + +EW 0xa405018a, 0x9991 +EW 0xa405018c, 0x8011 +EW 0xa405018e, 0x9550 + +EW 0xa4050100, 0x0000 +EW 0xa4050102, 0x5540 +EW 0xa4050104, 0x0000 +EW 0xa4050106, 0x0000 +EW 0xa4050108, 0x4550 +EW 0xa405010a, 0x0130 +EW 0xa405010c, 0x0555 +EW 0xa405010e, 0x0000 +EW 0xa4050110, 0x0000 +EW 0xa4050112, 0xAAA8 +EW 0xa4050114, 0x8305 +EW 0xa4050116, 0x10F0 +EW 0xa4050118, 0x0F50 +EW 0xa405011a, 0x0000 +EW 0xa405011c, 0x0000 +EW 0xa405011e, 0x0555 +EW 0xa4050140, 0x0000 +EW 0xa4050142, 0x5141 +EW 0xa4050144, 0x5005 +EW 0xa4050146, 0xAAA9 +EW 0xa4050148, 0xFAA9 +EW 0xa405014a, 0x3000 +EW 0xa405014c, 0x0000 + +LIST "setup sdram" +ED 0xFD000108, 0x40000301 +ED 0xFD000020, 0x011B0002 +ED 0xFD000030, 0x03060E02 +ED 0xFD000034, 0x01020102 +ED 0xFD000038, 0x01090406 +ED 0xFD000008, 0x00000004 +ED 0xFD000040, 0x00000001 +ED 0xFD000040, 0x00000000 +ED 0xFD000018, 0x00000001 + +WAIT 1 + +ED 0xFD000014, 0x00000002 +ED 0xFD000060, 0x00000032 +ED 0xFD000060, 0x00020000 +ED 0xFD000014, 0x00000004 +ED 0xFD000014, 0x00000004 +ED 0xFD000010, 0x00000001 +ED 0xFD000044, 0x000004AF +ED 0xFD000048, 0x20CF0037 + +LIST "read 16 bytes from sdram" +DD 0xa8000000, 0xa8000000, 1 +DD 0xa8000004, 0xa8000004, 1 +DD 0xa8000008, 0xa8000008, 1 +DD 0xa800000c, 0xa800000c, 1 + +ED 0xFD000014, 0x00000002 +ED 0xFD000014, 0x00000004 +ED 0xFD000108, 0x40000300 +ED 0xFD000040, 0x00010000 + +LIST "write to internal ram" +ED 0xfd8007fc, 0 + +LIST "setup cache" +ED 0xff00001c, 0x0000090b diff --git a/arch/sh/include/mach-kfr2r09/romimage.h b/arch/sh/include/mach-kfr2r09/romimage.h new file mode 100644 index 00000000000..f5aa8e16770 --- /dev/null +++ b/arch/sh/include/mach-kfr2r09/romimage.h @@ -0,0 +1,75 @@ +/* kfr2r09 board specific boot code: + * converts the "partner-jet-script.txt" script into assembly + * the assembly code is the first code to be executed in the romImage + */ + +/* The LIST command is used to include comments in the script */ +.macro LIST comment +.endm + +/* The ED command is used to write a 32-bit word */ +.macro ED, addr, data + mov.l 1f ,r1 + mov.l 2f ,r0 + mov.l r0, @r1 + bra 3f + nop + .align 2 +1: .long \addr +2: .long \data +3: +.endm + +/* The EW command is used to write a 16-bit word */ +.macro EW, addr, data + mov.l 1f ,r1 + mov.l 2f ,r0 + mov.w r0, @r1 + bra 3f + nop + .align 2 +1: .long \addr +2: .long \data +3: +.endm + +/* The EB command is used to write an 8-bit word */ +.macro EB, addr, data + mov.l 1f ,r1 + mov.l 2f ,r0 + mov.b r0, @r1 + bra 3f + nop + .align 2 +1: .long \addr +2: .long \data +3: +.endm + +/* The WAIT command is used to delay the execution */ +.macro WAIT, time + mov.l 2f ,r3 +1: + nop + tst r3, r3 + bf/s 1b + dt r3 + bra 3f + nop + .align 2 +2: .long \time * 100 +3: +.endm + +/* The DD command is used to read a 32-bit word */ +.macro DD, addr, addr2, nr + mov.l 1f ,r1 + mov.l @r1, r0 + bra 2f + nop + .align 2 +1: .long \addr +2: +.endm + +#include "partner-jet-setup.txt" From fdeb076f20df14b1c7f2817362172548d146b121 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 30 Jul 2009 00:27:35 +0900 Subject: [PATCH 055/262] sh: Add romImage target to archhelp. Adds an archhelp blurb for the romImage target so it is reflected in 'make help'. Signed-off-by: Paul Mundt --- arch/sh/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 2a7e73faee8..b6ff337fd85 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -216,6 +216,7 @@ archclean: define archhelp @echo ' zImage - Compressed kernel image' + @echo ' romImage - Compressed ROM image, if supported' @echo ' vmlinux.srec - Create an ELF S-record' @echo '* uImage - Alias to bootable U-Boot image' @echo ' uImage.srec - Create an S-record for U-Boot' From 05aa7882757f68af799140142ec44f83b2df4298 Mon Sep 17 00:00:00 2001 From: Rafael Ignacio Zurita Date: Tue, 4 Aug 2009 14:38:08 +0900 Subject: [PATCH 056/262] sh: Add early printk support for SH770x CPUs. This adds early printk support for SH770x (tested on SH7709 based hp6xx). Signed-off-by: Rafael Ignacio Zurita Signed-off-by: Paul Mundt --- arch/sh/Kconfig.debug | 1 + arch/sh/kernel/early_printk.c | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index a6dce41296e..763b792b161 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -43,6 +43,7 @@ config EARLY_SCIF_CONSOLE_PORT default "0xfffe8000" if CPU_SUBTYPE_SH7203 default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263 default "0xffe80000" if CPU_SH4 + default "0xa4000150" if CPU_SH3 default "0x00000000" config EARLY_PRINTK diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index a952dcf9999..64f2746baf9 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c @@ -134,7 +134,7 @@ static void scif_sercon_init(char *s) sci_out(&scif_port, SCFCR, 0x0030); /* TTRG=b'11 */ sci_out(&scif_port, SCSCR, 0x0030); /* TE, RE */ } -#elif defined(CONFIG_CPU_SH4) +#elif defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3) #define DEFAULT_BAUD 115200 /* * Simple SCIF init, primarily aimed at SH7750 and other similar SH-4 @@ -220,10 +220,8 @@ static int __init setup_early_printk(char *buf) early_console = &scif_console; #if !defined(CONFIG_SH_STANDARD_BIOS) -#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SUBTYPE_SH7720) || \ - defined(CONFIG_CPU_SUBTYPE_SH7721) +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3) scif_sercon_init(buf + 6); -#endif #endif } #endif From 6ba4a8f0f542e791e4158c91a844234b142578dc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 06:57:36 +0000 Subject: [PATCH 057/262] sh: hwblk support for sh7724 This patch adds hwblk support for the sh7724 processor. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/cpu-sh4/cpu/sh7724.h | 17 ++++ arch/sh/kernel/cpu/sh4a/Makefile | 2 +- arch/sh/kernel/cpu/sh4a/clock-sh7724.c | 115 ++++++++++++----------- arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c | 121 +++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 56 deletions(-) create mode 100644 arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h index 66fd1184359..0cd1f71a111 100644 --- a/arch/sh/include/cpu-sh4/cpu/sh7724.h +++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h @@ -266,4 +266,21 @@ enum { GPIO_FN_INTC_IRQ1, GPIO_FN_INTC_IRQ0, }; +enum { + HWBLK_UNKNOWN = 0, + HWBLK_TLB, HWBLK_IC, HWBLK_OC, HWBLK_RSMEM, HWBLK_ILMEM, HWBLK_L2C, + HWBLK_FPU, HWBLK_INTC, HWBLK_DMAC0, HWBLK_SHYWAY, + HWBLK_HUDI, HWBLK_DBG, HWBLK_UBC, + HWBLK_TMU0, HWBLK_CMT, HWBLK_RWDT, HWBLK_DMAC1, HWBLK_TMU1, + HWBLK_SCIF0, HWBLK_SCIF1, HWBLK_SCIF2, HWBLK_SCIF3, + HWBLK_SCIF4, HWBLK_SCIF5, HWBLK_MSIOF0, HWBLK_MSIOF1, + HWBLK_KEYSC, HWBLK_RTC, HWBLK_IIC0, HWBLK_IIC1, + HWBLK_MMC, HWBLK_ETHER, HWBLK_ATAPI, HWBLK_TPU, HWBLK_IRDA, + HWBLK_TSIF, HWBLK_USB1, HWBLK_USB0, HWBLK_2DG, + HWBLK_SDHI0, HWBLK_SDHI1, HWBLK_VEU1, HWBLK_CEU1, HWBLK_BEU1, + HWBLK_2DDMAC, HWBLK_SPU, HWBLK_JPU, HWBLK_VOU, + HWBLK_BEU0, HWBLK_CEU0, HWBLK_VEU0, HWBLK_VPU, HWBLK_LCDC, + HWBLK_NR, +}; + #endif /* __ASM_SH7724_H__ */ diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile index 1d7ae38bc61..12cddf4c721 100644 --- a/arch/sh/kernel/cpu/sh4a/Makefile +++ b/arch/sh/kernel/cpu/sh4a/Makefile @@ -27,7 +27,7 @@ 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_SH7723) := clock-sh7723.o hwblk-sh7723.o -clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o +clock-$(CONFIG_CPU_SUBTYPE_SH7724) := clock-sh7724.o hwblk-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-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index 5d5c9b95288..ba24e38c9fc 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include /* SH7724 registers */ #define FRQCRA 0xa4150000 @@ -156,64 +158,67 @@ struct clk div6_clks[] = { SH_CLK_DIV6("spu_clk", &div3_clk, SPUCLKCR, 0), }; -#define MSTP(_str, _parent, _reg, _bit, _force_on, _need_cpg, _need_ram) \ - SH_CLK_MSTP32(_str, -1, _parent, _reg, _bit, _force_on * CLK_ENABLE_ON_INIT) +#define R_CLK (&r_clk) +#define P_CLK (&div4_clks[DIV4_P]) +#define B_CLK (&div4_clks[DIV4_B]) +#define I_CLK (&div4_clks[DIV4_I]) +#define SH_CLK (&div4_clks[DIV4_SH]) static struct clk mstp_clks[] = { - MSTP("tlb0", &div4_clks[DIV4_I], MSTPCR0, 31, 1, 1, 0), - MSTP("ic0", &div4_clks[DIV4_I], MSTPCR0, 30, 1, 1, 0), - MSTP("oc0", &div4_clks[DIV4_I], MSTPCR0, 29, 1, 1, 0), - MSTP("rs0", &div4_clks[DIV4_B], MSTPCR0, 28, 1, 1, 0), - MSTP("ilmem0", &div4_clks[DIV4_I], MSTPCR0, 27, 1, 1, 0), - MSTP("l2c0", &div4_clks[DIV4_SH], MSTPCR0, 26, 1, 1, 0), - MSTP("fpu0", &div4_clks[DIV4_I], MSTPCR0, 24, 1, 1, 0), - MSTP("intc0", &div4_clks[DIV4_P], MSTPCR0, 22, 1, 1, 0), - MSTP("dmac0", &div4_clks[DIV4_B], MSTPCR0, 21, 0, 1, 1), - MSTP("sh0", &div4_clks[DIV4_SH], MSTPCR0, 20, 0, 1, 0), - MSTP("hudi0", &div4_clks[DIV4_P], MSTPCR0, 19, 0, 1, 0), - MSTP("ubc0", &div4_clks[DIV4_I], MSTPCR0, 17, 0, 1, 0), - MSTP("tmu0", &div4_clks[DIV4_P], MSTPCR0, 15, 0, 1, 0), - MSTP("cmt0", &r_clk, MSTPCR0, 14, 0, 0, 0), - MSTP("rwdt0", &r_clk, MSTPCR0, 13, 0, 0, 0), - MSTP("dmac1", &div4_clks[DIV4_B], MSTPCR0, 12, 0, 1, 1), - MSTP("tmu1", &div4_clks[DIV4_P], MSTPCR0, 10, 0, 1, 0), - MSTP("scif0", &div4_clks[DIV4_P], MSTPCR0, 9, 0, 1, 0), - MSTP("scif1", &div4_clks[DIV4_P], MSTPCR0, 8, 0, 1, 0), - MSTP("scif2", &div4_clks[DIV4_P], MSTPCR0, 7, 0, 1, 0), - MSTP("scif3", &div4_clks[DIV4_B], MSTPCR0, 6, 0, 1, 0), - MSTP("scif4", &div4_clks[DIV4_B], MSTPCR0, 5, 0, 1, 0), - MSTP("scif5", &div4_clks[DIV4_B], MSTPCR0, 4, 0, 1, 0), - MSTP("msiof0", &div4_clks[DIV4_B], MSTPCR0, 2, 0, 1, 0), - MSTP("msiof1", &div4_clks[DIV4_B], MSTPCR0, 1, 0, 1, 0), + SH_HWBLK_CLK("tlb0", -1, I_CLK, HWBLK_TLB, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("ic0", -1, I_CLK, HWBLK_IC, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("oc0", -1, I_CLK, HWBLK_OC, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("rs0", -1, B_CLK, HWBLK_RSMEM, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("ilmem0", -1, I_CLK, HWBLK_ILMEM, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("l2c0", -1, SH_CLK, HWBLK_L2C, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("fpu0", -1, I_CLK, HWBLK_FPU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("intc0", -1, P_CLK, HWBLK_INTC, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("dmac0", -1, B_CLK, HWBLK_DMAC0, 0), + SH_HWBLK_CLK("sh0", -1, SH_CLK, HWBLK_SHYWAY, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("hudi0", -1, P_CLK, HWBLK_HUDI, 0), + SH_HWBLK_CLK("ubc0", -1, I_CLK, HWBLK_UBC, 0), + SH_HWBLK_CLK("tmu0", -1, P_CLK, HWBLK_TMU0, 0), + SH_HWBLK_CLK("cmt0", -1, R_CLK, HWBLK_CMT, 0), + SH_HWBLK_CLK("rwdt0", -1, R_CLK, HWBLK_RWDT, 0), + SH_HWBLK_CLK("dmac1", -1, B_CLK, HWBLK_DMAC1, 0), + SH_HWBLK_CLK("tmu1", -1, P_CLK, HWBLK_TMU1, 0), + SH_HWBLK_CLK("scif0", -1, P_CLK, HWBLK_SCIF0, 0), + SH_HWBLK_CLK("scif1", -1, P_CLK, HWBLK_SCIF1, 0), + SH_HWBLK_CLK("scif2", -1, P_CLK, HWBLK_SCIF2, 0), + SH_HWBLK_CLK("scif3", -1, B_CLK, HWBLK_SCIF3, 0), + SH_HWBLK_CLK("scif4", -1, B_CLK, HWBLK_SCIF4, 0), + SH_HWBLK_CLK("scif5", -1, B_CLK, HWBLK_SCIF5, 0), + SH_HWBLK_CLK("msiof0", -1, B_CLK, HWBLK_MSIOF0, 0), + SH_HWBLK_CLK("msiof1", -1, B_CLK, HWBLK_MSIOF1, 0), - MSTP("keysc0", &r_clk, MSTPCR1, 12, 0, 0, 0), - MSTP("rtc0", &r_clk, MSTPCR1, 11, 0, 0, 0), - MSTP("i2c0", &div4_clks[DIV4_P], MSTPCR1, 9, 0, 1, 0), - MSTP("i2c1", &div4_clks[DIV4_P], MSTPCR1, 8, 0, 1, 0), + SH_HWBLK_CLK("keysc0", -1, R_CLK, HWBLK_KEYSC, 0), + SH_HWBLK_CLK("rtc0", -1, R_CLK, HWBLK_RTC, 0), + SH_HWBLK_CLK("i2c0", -1, P_CLK, HWBLK_IIC0, 0), + SH_HWBLK_CLK("i2c1", -1, P_CLK, HWBLK_IIC1, 0), - MSTP("mmc0", &div4_clks[DIV4_B], MSTPCR2, 29, 0, 1, 0), - MSTP("eth0", &div4_clks[DIV4_B], MSTPCR2, 28, 0, 1, 0), - MSTP("atapi0", &div4_clks[DIV4_B], MSTPCR2, 26, 0, 1, 0), - MSTP("tpu0", &div4_clks[DIV4_B], MSTPCR2, 25, 0, 1, 0), - MSTP("irda0", &div4_clks[DIV4_P], MSTPCR2, 24, 0, 1, 0), - MSTP("tsif0", &div4_clks[DIV4_B], MSTPCR2, 22, 0, 1, 0), - MSTP("usb1", &div4_clks[DIV4_B], MSTPCR2, 21, 0, 1, 1), - MSTP("usb0", &div4_clks[DIV4_B], MSTPCR2, 20, 0, 1, 1), - MSTP("2dg0", &div4_clks[DIV4_B], MSTPCR2, 19, 0, 1, 1), - MSTP("sdhi0", &div4_clks[DIV4_B], MSTPCR2, 18, 0, 1, 0), - MSTP("sdhi1", &div4_clks[DIV4_B], MSTPCR2, 17, 0, 1, 0), - MSTP("veu1", &div4_clks[DIV4_B], MSTPCR2, 15, 1, 1, 1), - MSTP("ceu1", &div4_clks[DIV4_B], MSTPCR2, 13, 0, 1, 1), - MSTP("beu1", &div4_clks[DIV4_B], MSTPCR2, 12, 0, 1, 1), - MSTP("2ddmac0", &div4_clks[DIV4_SH], MSTPCR2, 10, 0, 1, 1), - MSTP("spu0", &div4_clks[DIV4_B], MSTPCR2, 9, 0, 1, 0), - MSTP("jpu0", &div4_clks[DIV4_B], MSTPCR2, 6, 1, 1, 1), - MSTP("vou0", &div4_clks[DIV4_B], MSTPCR2, 5, 0, 1, 1), - MSTP("beu0", &div4_clks[DIV4_B], MSTPCR2, 4, 0, 1, 1), - MSTP("ceu0", &div4_clks[DIV4_B], MSTPCR2, 3, 0, 1, 1), - MSTP("veu0", &div4_clks[DIV4_B], MSTPCR2, 2, 1, 1, 1), - MSTP("vpu0", &div4_clks[DIV4_B], MSTPCR2, 1, 1, 1, 1), - MSTP("lcdc0", &div4_clks[DIV4_B], MSTPCR2, 0, 0, 1, 1), + SH_HWBLK_CLK("mmc0", -1, B_CLK, HWBLK_MMC, 0), + SH_HWBLK_CLK("eth0", -1, B_CLK, HWBLK_ETHER, 0), + SH_HWBLK_CLK("atapi0", -1, B_CLK, HWBLK_ATAPI, 0), + SH_HWBLK_CLK("tpu0", -1, B_CLK, HWBLK_TPU, 0), + SH_HWBLK_CLK("irda0", -1, P_CLK, HWBLK_IRDA, 0), + SH_HWBLK_CLK("tsif0", -1, B_CLK, HWBLK_TSIF, 0), + SH_HWBLK_CLK("usb1", -1, B_CLK, HWBLK_USB1, 0), + SH_HWBLK_CLK("usb0", -1, B_CLK, HWBLK_USB0, 0), + SH_HWBLK_CLK("2dg0", -1, B_CLK, HWBLK_2DG, 0), + SH_HWBLK_CLK("sdhi0", -1, B_CLK, HWBLK_SDHI0, 0), + SH_HWBLK_CLK("sdhi1", -1, B_CLK, HWBLK_SDHI1, 0), + SH_HWBLK_CLK("veu1", -1, B_CLK, HWBLK_VEU1, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("ceu1", -1, B_CLK, HWBLK_CEU1, 0), + SH_HWBLK_CLK("beu1", -1, B_CLK, HWBLK_BEU1, 0), + SH_HWBLK_CLK("2ddmac0", -1, SH_CLK, HWBLK_2DDMAC, 0), + SH_HWBLK_CLK("spu0", -1, B_CLK, HWBLK_SPU, 0), + SH_HWBLK_CLK("jpu0", -1, B_CLK, HWBLK_JPU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("vou0", -1, B_CLK, HWBLK_VOU, 0), + SH_HWBLK_CLK("beu0", -1, B_CLK, HWBLK_BEU0, 0), + SH_HWBLK_CLK("ceu0", -1, B_CLK, HWBLK_CEU0, 0), + SH_HWBLK_CLK("veu0", -1, B_CLK, HWBLK_VEU0, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("vpu0", -1, B_CLK, HWBLK_VPU, CLK_ENABLE_ON_INIT), + SH_HWBLK_CLK("lcdc0", -1, B_CLK, HWBLK_LCDC, 0), }; int __init arch_clk_init(void) @@ -236,7 +241,7 @@ int __init arch_clk_init(void) ret = sh_clk_div6_register(div6_clks, ARRAY_SIZE(div6_clks)); if (!ret) - ret = sh_clk_mstp32_register(mstp_clks, ARRAY_SIZE(mstp_clks)); + ret = sh_hwblk_clk_register(mstp_clks, ARRAY_SIZE(mstp_clks)); return ret; } diff --git a/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c new file mode 100644 index 00000000000..1613ad6013c --- /dev/null +++ b/arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c @@ -0,0 +1,121 @@ +/* + * arch/sh/kernel/cpu/sh4a/hwblk-sh7724.c + * + * SH7724 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 + +/* SH7724 registers */ +#define MSTPCR0 0xa4150030 +#define MSTPCR1 0xa4150034 +#define MSTPCR2 0xa4150038 + +/* SH7724 Power Domains */ +enum { CORE_AREA, SUB_AREA, CORE_AREA_BM }; +static struct hwblk_area sh7724_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 sh7724_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_RSMEM] = HWBLK(MSTPCR0, 28, CORE_AREA), + [HWBLK_ILMEM] = HWBLK(MSTPCR0, 27, CORE_AREA), + [HWBLK_L2C] = HWBLK(MSTPCR0, 26, 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_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, 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_KEYSC] = HWBLK(MSTPCR1, 12, SUB_AREA), + [HWBLK_RTC] = HWBLK(MSTPCR1, 11, SUB_AREA), + [HWBLK_IIC0] = HWBLK(MSTPCR1, 9, CORE_AREA), + [HWBLK_IIC1] = HWBLK(MSTPCR1, 8, CORE_AREA), + + [HWBLK_MMC] = HWBLK(MSTPCR2, 29, CORE_AREA), + [HWBLK_ETHER] = HWBLK(MSTPCR2, 28, CORE_AREA_BM), + [HWBLK_ATAPI] = HWBLK(MSTPCR2, 26, CORE_AREA_BM), + [HWBLK_TPU] = HWBLK(MSTPCR2, 25, CORE_AREA), + [HWBLK_IRDA] = HWBLK(MSTPCR2, 24, CORE_AREA), + [HWBLK_TSIF] = HWBLK(MSTPCR2, 22, CORE_AREA), + [HWBLK_USB1] = HWBLK(MSTPCR2, 21, CORE_AREA), + [HWBLK_USB0] = HWBLK(MSTPCR2, 20, CORE_AREA), + [HWBLK_2DG] = HWBLK(MSTPCR2, 19, CORE_AREA_BM), + [HWBLK_SDHI0] = HWBLK(MSTPCR2, 18, CORE_AREA), + [HWBLK_SDHI1] = HWBLK(MSTPCR2, 17, CORE_AREA), + [HWBLK_VEU1] = HWBLK(MSTPCR2, 15, CORE_AREA_BM), + [HWBLK_CEU1] = HWBLK(MSTPCR2, 13, CORE_AREA_BM), + [HWBLK_BEU1] = HWBLK(MSTPCR2, 12, CORE_AREA_BM), + [HWBLK_2DDMAC] = HWBLK(MSTPCR2, 10, CORE_AREA_BM), + [HWBLK_SPU] = HWBLK(MSTPCR2, 9, CORE_AREA_BM), + [HWBLK_JPU] = HWBLK(MSTPCR2, 6, CORE_AREA_BM), + [HWBLK_VOU] = HWBLK(MSTPCR2, 5, CORE_AREA_BM), + [HWBLK_BEU0] = HWBLK(MSTPCR2, 4, CORE_AREA_BM), + [HWBLK_CEU0] = HWBLK(MSTPCR2, 3, CORE_AREA_BM), + [HWBLK_VEU0] = 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 sh7724_hwblk_info = { + .areas = sh7724_hwblk_area, + .nr_areas = ARRAY_SIZE(sh7724_hwblk_area), + .hwblks = sh7724_hwblk, + .nr_hwblks = ARRAY_SIZE(sh7724_hwblk), +}; + +int arch_hwblk_sleep_mode(void) +{ + if (!sh7724_hwblk_area[CORE_AREA].cnt[HWBLK_CNT_USAGE]) + return SUSP_SH_STANDBY | SUSP_SH_SF; + + if (!sh7724_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(&sh7724_hwblk_info); +} From 133b170f08d6c20578f25b1ae71f80a5e638ccb6 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:01:36 +0000 Subject: [PATCH 058/262] sh: clean up MSTPCRn register definitions This patch removes the unused MSTPCRn register definitions from the SuperH Mobile code for sh7722, sh7723 and sh7724. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7722.c | 3 --- arch/sh/kernel/cpu/sh4a/clock-sh7723.c | 3 --- arch/sh/kernel/cpu/sh4a/clock-sh7724.c | 3 --- 3 files changed, 9 deletions(-) diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c index 1fa9e1dd1cc..5b1bbbe63b1 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7722.c @@ -32,9 +32,6 @@ #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 */ diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c index bf64c78eee3..e5c63911403 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7723.c @@ -32,9 +32,6 @@ #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 */ diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index ba24e38c9fc..34611d97378 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -33,9 +33,6 @@ #define FCLKBCR 0xa415000c #define IRDACLKCR 0xa4150018 #define PLLCR 0xa4150024 -#define MSTPCR0 0xa4150030 -#define MSTPCR1 0xa4150034 -#define MSTPCR2 0xa4150038 #define SPUCLKCR 0xa415003c #define FLLFRQ 0xa4150050 #define LSTATS 0xa4150060 From 4f3243117ad42b4d1faeecd452f7b24306fcfc4a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Aug 2009 04:52:03 +0000 Subject: [PATCH 059/262] sh: ms7724se: add 1280x720 lcdc output support There was no big meaning in the support of SVGA, but 720p support is necessary for ms7724se board. So, this patch support 720p instead of SVGA. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/boards/mach-se/7724/setup.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 4fb7e48e284..957ed176ea2 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -39,7 +39,15 @@ * SW41 : abxx xxxx -> a = 0 : Analog monitor * 1 : Digital monitor * b = 0 : VGA - * 1 : SVGA + * 1 : 720p + */ + +/* + * about 720p + * + * When you use 1280 x 720 lcdc output, + * you should change OSC6 lcdc clock from 25.175MHz to 74.25MHz, + * and change SW41 to use 720p */ /* Heartbeat */ @@ -546,15 +554,15 @@ static int __init devices_setup(void) sh_eth_init(); if (sw & SW41_B) { - /* SVGA */ - lcdc_info.ch[0].lcd_cfg.xres = 800; - lcdc_info.ch[0].lcd_cfg.yres = 600; - lcdc_info.ch[0].lcd_cfg.left_margin = 142; - lcdc_info.ch[0].lcd_cfg.right_margin = 52; - lcdc_info.ch[0].lcd_cfg.hsync_len = 96; - lcdc_info.ch[0].lcd_cfg.upper_margin = 24; - lcdc_info.ch[0].lcd_cfg.lower_margin = 2; - lcdc_info.ch[0].lcd_cfg.vsync_len = 2; + /* 720p */ + lcdc_info.ch[0].lcd_cfg.xres = 1280; + lcdc_info.ch[0].lcd_cfg.yres = 720; + lcdc_info.ch[0].lcd_cfg.left_margin = 220; + lcdc_info.ch[0].lcd_cfg.right_margin = 110; + lcdc_info.ch[0].lcd_cfg.hsync_len = 40; + lcdc_info.ch[0].lcd_cfg.upper_margin = 20; + lcdc_info.ch[0].lcd_cfg.lower_margin = 5; + lcdc_info.ch[0].lcd_cfg.vsync_len = 5; } else { /* VGA */ lcdc_info.ch[0].lcd_cfg.xres = 640; From edc67b29425b12312356fe9a92352ce6b7307c68 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 3 Aug 2009 04:52:24 +0000 Subject: [PATCH 060/262] sh: Add SH7724 DMAC support. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/include/asm/dma-sh.h | 1 + arch/sh/include/cpu-sh4/cpu/dma-sh4a.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h index 0c8f8e14622..68a5f4cb034 100644 --- a/arch/sh/include/asm/dma-sh.h +++ b/arch/sh/include/asm/dma-sh.h @@ -16,6 +16,7 @@ /* DMAOR contorl: The DMAOR access size is different by CPU.*/ #if defined(CONFIG_CPU_SUBTYPE_SH7723) || \ + defined(CONFIG_CPU_SUBTYPE_SH7724) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) #define dmaor_read_reg(n) \ diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h index 0ed5178fed6..f0886bc880e 100644 --- a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h +++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h @@ -16,7 +16,8 @@ #define DMAE0_IRQ 38 #define SH_DMAC_BASE0 0xFF608020 #define SH_DMARS_BASE 0xFF609000 -#elif defined(CONFIG_CPU_SUBTYPE_SH7723) +#elif defined(CONFIG_CPU_SUBTYPE_SH7723) || \ + defined(CONFIG_CPU_SUBTYPE_SH7724) #define DMTE0_IRQ 48 /* DMAC0A*/ #define DMTE4_IRQ 40 /* DMAC0B */ #define DMTE6_IRQ 42 From 9aaa74908b2117bcd560ab3ea8a9d6a491a77c28 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:47:17 +0000 Subject: [PATCH 061/262] sh: Runtime PM pdev hwblk These patches extend struct platform device data for a bunch of SuperH Mobile processors and embedded boards. The patches simply add hardware block ids to on-chip platform devices. Platform devices off chip (such as external ethernet controllers or flash chips) are left out which gives them a special case hardware block id of zero. Upcoming Runtime PM code will make use of the hardware block id to group devices together. The hardware block id can also be used to extend the SuperH Mobile clock framework implementation. This series of patches depend on the following: "Driver Core: Add platform device arch data V3". This patch adds a hwblk_id member to struct pdev_archdata. This member should be used to point out on-chip hardware block id. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/include/asm/device.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/sh/include/asm/device.h b/arch/sh/include/asm/device.h index 8688a88303e..783ecdc64e2 100644 --- a/arch/sh/include/asm/device.h +++ b/arch/sh/include/asm/device.h @@ -3,7 +3,9 @@ * * This file is released under the GPLv2 */ -#include + +struct dev_archdata { +}; struct platform_device; /* allocate contiguous memory chunk and fill in struct resource */ @@ -12,3 +14,6 @@ int platform_resource_setup_memory(struct platform_device *pdev, void plat_early_device_setup(void); +struct pdev_archdata { + int hwblk_id; +}; From f69d5782742e57d5f047ed13440bcf1b320cb074 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:47:27 +0000 Subject: [PATCH 062/262] sh: Runtime PM pdev hwblk - sh7722 Add hwblk_id to on-chip sh7722 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7722.c | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c index 67b0d87fcb2..35097753456 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c @@ -17,6 +17,7 @@ #include #include #include +#include static struct resource rtc_resources[] = { [0] = { @@ -46,6 +47,9 @@ static struct platform_device rtc_device = { .id = -1, .num_resources = ARRAY_SIZE(rtc_resources), .resource = rtc_resources, + .archdata = { + .hwblk_id = HWBLK_RTC, + }, }; static struct m66592_platdata usbf_platdata = { @@ -76,6 +80,9 @@ static struct platform_device usbf_device = { }, .num_resources = ARRAY_SIZE(usbf_resources), .resource = usbf_resources, + .archdata = { + .hwblk_id = HWBLK_USBF, + }, }; static struct resource iic_resources[] = { @@ -97,6 +104,9 @@ static struct platform_device iic_device = { .id = 0, /* "i2c0" clock */ .num_resources = ARRAY_SIZE(iic_resources), .resource = iic_resources, + .archdata = { + .hwblk_id = HWBLK_IIC, + }, }; static struct uio_info vpu_platform_data = { @@ -125,6 +135,9 @@ static struct platform_device vpu_device = { }, .resource = vpu_resources, .num_resources = ARRAY_SIZE(vpu_resources), + .archdata = { + .hwblk_id = HWBLK_VPU, + }, }; static struct uio_info veu_platform_data = { @@ -153,6 +166,9 @@ static struct platform_device veu_device = { }, .resource = veu_resources, .num_resources = ARRAY_SIZE(veu_resources), + .archdata = { + .hwblk_id = HWBLK_VEU, + }, }; static struct uio_info jpu_platform_data = { @@ -181,6 +197,9 @@ static struct platform_device jpu_device = { }, .resource = jpu_resources, .num_resources = ARRAY_SIZE(jpu_resources), + .archdata = { + .hwblk_id = HWBLK_JPU, + }, }; static struct sh_timer_config cmt_platform_data = { @@ -213,6 +232,9 @@ static struct platform_device cmt_device = { }, .resource = cmt_resources, .num_resources = ARRAY_SIZE(cmt_resources), + .archdata = { + .hwblk_id = HWBLK_CMT, + }, }; static struct sh_timer_config tmu0_platform_data = { @@ -244,6 +266,9 @@ static struct platform_device tmu0_device = { }, .resource = tmu0_resources, .num_resources = ARRAY_SIZE(tmu0_resources), + .archdata = { + .hwblk_id = HWBLK_TMU, + }, }; static struct sh_timer_config tmu1_platform_data = { @@ -275,6 +300,9 @@ static struct platform_device tmu1_device = { }, .resource = tmu1_resources, .num_resources = ARRAY_SIZE(tmu1_resources), + .archdata = { + .hwblk_id = HWBLK_TMU, + }, }; static struct sh_timer_config tmu2_platform_data = { @@ -305,6 +333,9 @@ static struct platform_device tmu2_device = { }, .resource = tmu2_resources, .num_resources = ARRAY_SIZE(tmu2_resources), + .archdata = { + .hwblk_id = HWBLK_TMU, + }, }; static struct plat_sci_port sci_platform_data[] = { From 2de63cf376585508f6942aaa7337848f8c4cdd7d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:47:35 +0000 Subject: [PATCH 063/262] sh: Runtime PM pdev hwblk - Migo-R Add hwblk_id to Migo-R board specific on-chip sh7722 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-migor/setup.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index f70f4644deb..a508a0fa731 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -98,6 +98,9 @@ static struct platform_device sh_keysc_device = { .dev = { .platform_data = &sh_keysc_info, }, + .archdata = { + .hwblk_id = HWBLK_KEYSC, + }, }; static struct mtd_partition migor_nor_flash_partitions[] = @@ -292,6 +295,9 @@ static struct platform_device migor_lcdc_device = { .dev = { .platform_data = &sh_mobile_lcdc_info, }, + .archdata = { + .hwblk_id = HWBLK_LCDC, + }, }; static struct clk *camera_clk; @@ -379,6 +385,9 @@ static struct platform_device migor_ceu_device = { .dev = { .platform_data = &sh_mobile_ceu_info, }, + .archdata = { + .hwblk_id = HWBLK_CEU, + }, }; struct spi_gpio_platform_data sdcard_cn9_platform_data = { From 66d9c51ac434615b0f0e864c0c9a81d7264ca3ef Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:47:44 +0000 Subject: [PATCH 064/262] sh: Runtime PM pdev hwblk - Solution Engine 7722 Add hwblk_id to Solution Engine 7722 board specific on-chip sh7722 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-se/7722/setup.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c index af84904ed86..36374078e52 100644 --- a/arch/sh/boards/mach-se/7722/setup.c +++ b/arch/sh/boards/mach-se/7722/setup.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Heartbeat */ static struct heartbeat_data heartbeat_data = { @@ -137,6 +138,9 @@ static struct platform_device sh_keysc_device = { .dev = { .platform_data = &sh_keysc_info, }, + .archdata = { + .hwblk_id = HWBLK_KEYSC, + }, }; static struct platform_device *se7722_devices[] __initdata = { From 09d21f9c83c49afd04850b8701772c09954054e0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:47:53 +0000 Subject: [PATCH 065/262] sh: Runtime PM pdev hwblk - sh7723 Add hwblk_id to on-chip sh7723 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7723.c | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c index 26dc4d32325..4caa5a7ca86 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c @@ -18,6 +18,7 @@ #include #include #include +#include static struct uio_info vpu_platform_data = { .name = "VPU5", @@ -45,6 +46,9 @@ static struct platform_device vpu_device = { }, .resource = vpu_resources, .num_resources = ARRAY_SIZE(vpu_resources), + .archdata = { + .hwblk_id = HWBLK_VPU, + }, }; static struct uio_info veu0_platform_data = { @@ -73,6 +77,9 @@ static struct platform_device veu0_device = { }, .resource = veu0_resources, .num_resources = ARRAY_SIZE(veu0_resources), + .archdata = { + .hwblk_id = HWBLK_VEU2H0, + }, }; static struct uio_info veu1_platform_data = { @@ -101,6 +108,9 @@ static struct platform_device veu1_device = { }, .resource = veu1_resources, .num_resources = ARRAY_SIZE(veu1_resources), + .archdata = { + .hwblk_id = HWBLK_VEU2H1, + }, }; static struct sh_timer_config cmt_platform_data = { @@ -133,6 +143,9 @@ static struct platform_device cmt_device = { }, .resource = cmt_resources, .num_resources = ARRAY_SIZE(cmt_resources), + .archdata = { + .hwblk_id = HWBLK_CMT, + }, }; static struct sh_timer_config tmu0_platform_data = { @@ -164,6 +177,9 @@ static struct platform_device tmu0_device = { }, .resource = tmu0_resources, .num_resources = ARRAY_SIZE(tmu0_resources), + .archdata = { + .hwblk_id = HWBLK_TMU0, + }, }; static struct sh_timer_config tmu1_platform_data = { @@ -195,6 +211,9 @@ static struct platform_device tmu1_device = { }, .resource = tmu1_resources, .num_resources = ARRAY_SIZE(tmu1_resources), + .archdata = { + .hwblk_id = HWBLK_TMU0, + }, }; static struct sh_timer_config tmu2_platform_data = { @@ -225,6 +244,9 @@ static struct platform_device tmu2_device = { }, .resource = tmu2_resources, .num_resources = ARRAY_SIZE(tmu2_resources), + .archdata = { + .hwblk_id = HWBLK_TMU0, + }, }; static struct sh_timer_config tmu3_platform_data = { @@ -255,6 +277,9 @@ static struct platform_device tmu3_device = { }, .resource = tmu3_resources, .num_resources = ARRAY_SIZE(tmu3_resources), + .archdata = { + .hwblk_id = HWBLK_TMU1, + }, }; static struct sh_timer_config tmu4_platform_data = { @@ -285,6 +310,9 @@ static struct platform_device tmu4_device = { }, .resource = tmu4_resources, .num_resources = ARRAY_SIZE(tmu4_resources), + .archdata = { + .hwblk_id = HWBLK_TMU1, + }, }; static struct sh_timer_config tmu5_platform_data = { @@ -315,6 +343,9 @@ static struct platform_device tmu5_device = { }, .resource = tmu5_resources, .num_resources = ARRAY_SIZE(tmu5_resources), + .archdata = { + .hwblk_id = HWBLK_TMU1, + }, }; static struct plat_sci_port sci_platform_data[] = { @@ -395,6 +426,9 @@ static struct platform_device rtc_device = { .id = -1, .num_resources = ARRAY_SIZE(rtc_resources), .resource = rtc_resources, + .archdata = { + .hwblk_id = HWBLK_RTC, + }, }; static struct r8a66597_platdata r8a66597_data = { @@ -424,6 +458,9 @@ static struct platform_device sh7723_usb_host_device = { }, .num_resources = ARRAY_SIZE(sh7723_usb_host_resources), .resource = sh7723_usb_host_resources, + .archdata = { + .hwblk_id = HWBLK_USB, + }, }; static struct resource iic_resources[] = { @@ -445,6 +482,9 @@ static struct platform_device iic_device = { .id = 0, /* "i2c0" clock */ .num_resources = ARRAY_SIZE(iic_resources), .resource = iic_resources, + .archdata = { + .hwblk_id = HWBLK_IIC, + }, }; static struct platform_device *sh7723_devices[] __initdata = { From d3a6f6260a3fecd9a8e301fcf37d87ee70edca12 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:48:02 +0000 Subject: [PATCH 066/262] sh: Runtime PM pdev hwblk - AP325RXA Add hwblk_id to AP325RXA board specific on-chip sh7723 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/board-ap325rxa.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index 7ffd1b4315b..07a54740d43 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c @@ -227,6 +227,9 @@ static struct platform_device lcdc_device = { .dev = { .platform_data = &lcdc_info, }, + .archdata = { + .hwblk_id = HWBLK_LCDC, + }, }; static void camera_power(int val) @@ -377,6 +380,9 @@ static struct platform_device ceu_device = { .dev = { .platform_data = &sh_mobile_ceu_info, }, + .archdata = { + .hwblk_id = HWBLK_CEU, + }, }; struct spi_gpio_platform_data sdcard_cn3_platform_data = { From 593a0c898ac2f09f001d536f699966ec4bc1d25f Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:48:11 +0000 Subject: [PATCH 067/262] sh: Runtime PM pdev hwblk - sh7724 Add hwblk_id to on-chip sh7724 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c index a04edaab9a2..f3851fd757e 100644 --- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Serial */ static struct plat_sci_port sci_platform_data[] = { @@ -103,6 +104,9 @@ static struct platform_device rtc_device = { .id = -1, .num_resources = ARRAY_SIZE(rtc_resources), .resource = rtc_resources, + .archdata = { + .hwblk_id = HWBLK_RTC, + }, }; /* I2C0 */ @@ -125,6 +129,9 @@ static struct platform_device iic0_device = { .id = 0, /* "i2c0" clock */ .num_resources = ARRAY_SIZE(iic0_resources), .resource = iic0_resources, + .archdata = { + .hwblk_id = HWBLK_IIC0, + }, }; /* I2C1 */ @@ -147,6 +154,9 @@ static struct platform_device iic1_device = { .id = 1, /* "i2c1" clock */ .num_resources = ARRAY_SIZE(iic1_resources), .resource = iic1_resources, + .archdata = { + .hwblk_id = HWBLK_IIC1, + }, }; /* VPU */ @@ -176,6 +186,9 @@ static struct platform_device vpu_device = { }, .resource = vpu_resources, .num_resources = ARRAY_SIZE(vpu_resources), + .archdata = { + .hwblk_id = HWBLK_VPU, + }, }; /* VEU0 */ @@ -205,6 +218,9 @@ static struct platform_device veu0_device = { }, .resource = veu0_resources, .num_resources = ARRAY_SIZE(veu0_resources), + .archdata = { + .hwblk_id = HWBLK_VEU0, + }, }; /* VEU1 */ @@ -234,6 +250,9 @@ static struct platform_device veu1_device = { }, .resource = veu1_resources, .num_resources = ARRAY_SIZE(veu1_resources), + .archdata = { + .hwblk_id = HWBLK_VEU1, + }, }; static struct sh_timer_config cmt_platform_data = { @@ -266,6 +285,9 @@ static struct platform_device cmt_device = { }, .resource = cmt_resources, .num_resources = ARRAY_SIZE(cmt_resources), + .archdata = { + .hwblk_id = HWBLK_CMT, + }, }; static struct sh_timer_config tmu0_platform_data = { @@ -297,6 +319,9 @@ static struct platform_device tmu0_device = { }, .resource = tmu0_resources, .num_resources = ARRAY_SIZE(tmu0_resources), + .archdata = { + .hwblk_id = HWBLK_TMU0, + }, }; static struct sh_timer_config tmu1_platform_data = { @@ -328,6 +353,9 @@ static struct platform_device tmu1_device = { }, .resource = tmu1_resources, .num_resources = ARRAY_SIZE(tmu1_resources), + .archdata = { + .hwblk_id = HWBLK_TMU0, + }, }; static struct sh_timer_config tmu2_platform_data = { @@ -358,6 +386,9 @@ static struct platform_device tmu2_device = { }, .resource = tmu2_resources, .num_resources = ARRAY_SIZE(tmu2_resources), + .archdata = { + .hwblk_id = HWBLK_TMU0, + }, }; @@ -389,6 +420,9 @@ static struct platform_device tmu3_device = { }, .resource = tmu3_resources, .num_resources = ARRAY_SIZE(tmu3_resources), + .archdata = { + .hwblk_id = HWBLK_TMU1, + }, }; static struct sh_timer_config tmu4_platform_data = { @@ -419,6 +453,9 @@ static struct platform_device tmu4_device = { }, .resource = tmu4_resources, .num_resources = ARRAY_SIZE(tmu4_resources), + .archdata = { + .hwblk_id = HWBLK_TMU1, + }, }; static struct sh_timer_config tmu5_platform_data = { @@ -449,6 +486,9 @@ static struct platform_device tmu5_device = { }, .resource = tmu5_resources, .num_resources = ARRAY_SIZE(tmu5_resources), + .archdata = { + .hwblk_id = HWBLK_TMU1, + }, }; /* JPU */ @@ -478,6 +518,9 @@ static struct platform_device jpu_device = { }, .resource = jpu_resources, .num_resources = ARRAY_SIZE(jpu_resources), + .archdata = { + .hwblk_id = HWBLK_JPU, + }, }; static struct platform_device *sh7724_devices[] __initdata = { From 442c37534c6a46d8ed27144fb09818833edbd049 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:48:21 +0000 Subject: [PATCH 068/262] sh: Runtime PM pdev hwblk - kfr2r09 Add hwblk_id to kfr2r09 board specific on-chip sh7724 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-kfr2r09/setup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index bf5f8f8d3b5..0e9b39034df 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -95,6 +95,9 @@ static struct platform_device kfr2r09_sh_keysc_device = { .dev = { .platform_data = &kfr2r09_sh_keysc_info, }, + .archdata = { + .hwblk_id = HWBLK_KEYSC, + }, }; static struct platform_device *kfr2r09_devices[] __initdata = { From df47cd096c8f54a5242e3a2ffb4525c804567eda Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 31 Jul 2009 07:48:29 +0000 Subject: [PATCH 069/262] sh: Runtime PM pdev hwblk - Solution Engine 7724 Add hwblk_id to Solution Engine 7724 board specific on-chip sh7724 platform devices. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-se/7724/setup.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index 4fb7e48e284..8de5ebc36b6 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -174,6 +174,9 @@ static struct platform_device lcdc_device = { .dev = { .platform_data = &lcdc_info, }, + .archdata = { + .hwblk_id = HWBLK_LCDC, + }, }; /* CEU0 */ @@ -205,6 +208,9 @@ static struct platform_device ceu0_device = { .dev = { .platform_data = &sh_mobile_ceu0_info, }, + .archdata = { + .hwblk_id = HWBLK_CEU0, + }, }; /* CEU1 */ @@ -236,6 +242,9 @@ static struct platform_device ceu1_device = { .dev = { .platform_data = &sh_mobile_ceu1_info, }, + .archdata = { + .hwblk_id = HWBLK_CEU1, + }, }; /* KEYSC */ @@ -273,6 +282,9 @@ static struct platform_device keysc_device = { .dev = { .platform_data = &keysc_info, }, + .archdata = { + .hwblk_id = HWBLK_KEYSC, + }, }; /* SH Eth */ @@ -301,6 +313,9 @@ static struct platform_device sh_eth_device = { }, .num_resources = ARRAY_SIZE(sh_eth_resources), .resource = sh_eth_resources, + .archdata = { + .hwblk_id = HWBLK_ETHER, + }, }; static struct r8a66597_platdata sh7724_usb0_host_data = { @@ -330,6 +345,9 @@ static struct platform_device sh7724_usb0_host_device = { }, .num_resources = ARRAY_SIZE(sh7724_usb0_host_resources), .resource = sh7724_usb0_host_resources, + .archdata = { + .hwblk_id = HWBLK_USB0, + }, }; static struct platform_device *ms7724se_devices[] __initdata = { From 11d82905e0159c07fe2d1bfe5e7d80e4cea333ce Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 15:54:33 +0900 Subject: [PATCH 070/262] sh: Fix up early printk build error. Missing endif in the early printk case, fix it up.. Signed-off-by: Paul Mundt --- arch/sh/kernel/early_printk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sh/kernel/early_printk.c b/arch/sh/kernel/early_printk.c index 64f2746baf9..81a46145ffa 100644 --- a/arch/sh/kernel/early_printk.c +++ b/arch/sh/kernel/early_printk.c @@ -222,6 +222,7 @@ static int __init setup_early_printk(char *buf) #if !defined(CONFIG_SH_STANDARD_BIOS) #if defined(CONFIG_CPU_SH4) || defined(CONFIG_CPU_SH3) scif_sercon_init(buf + 6); +#endif #endif } #endif From 700487c158163f14e6ff10de770b565c1c993c69 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 15:57:44 +0900 Subject: [PATCH 071/262] sh: Add a PG_dcache_dirty sanity check in kmap_coherent(). This plugs in a BUG_ON() in kmap_coherent() for PG_dcache_dirty pages to catch when things go horribly wrong. Copied from the MIPS implementation. Signed-off-by: Paul Mundt --- arch/sh/mm/pg-mmu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sh/mm/pg-mmu.c b/arch/sh/mm/pg-mmu.c index 8602f68af4c..32351206edd 100644 --- a/arch/sh/mm/pg-mmu.c +++ b/arch/sh/mm/pg-mmu.c @@ -37,6 +37,8 @@ static inline void *kmap_coherent(struct page *page, unsigned long addr) unsigned long vaddr, flags; pte_t pte; + BUG_ON(test_bit(PG_dcache_dirty, &page->flags)); + inc_preempt_count(); idx = (addr & current_cpu_data.dcache.alias_mask) >> PAGE_SHIFT; From 222db3e5f21fca563f5f692e000afcc01cb4395c Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 15:59:15 +0900 Subject: [PATCH 072/262] sh: Bring kmap_coherent() out-of-line. kmap_coherent() has gotten too big to leave as an inline, so we bring it out-of-line. Signed-off-by: Paul Mundt --- arch/sh/mm/pg-mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/mm/pg-mmu.c b/arch/sh/mm/pg-mmu.c index 32351206edd..e5c5122f4d6 100644 --- a/arch/sh/mm/pg-mmu.c +++ b/arch/sh/mm/pg-mmu.c @@ -31,7 +31,7 @@ void __init kmap_coherent_init(void) #endif } -static inline void *kmap_coherent(struct page *page, unsigned long addr) +static void *kmap_coherent(struct page *page, unsigned long addr) { enum fixed_addresses idx; unsigned long vaddr, flags; From b5eb10ae901fa797c19accb684825f0e36ecbe0f Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 16:00:36 +0900 Subject: [PATCH 073/262] sh: Drop unused arguments for kunmap_coherent(). kunmap_coherent() doesn't do anything with its arguments, so just kill them off. Signed-off-by: Paul Mundt --- arch/sh/mm/pg-mmu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sh/mm/pg-mmu.c b/arch/sh/mm/pg-mmu.c index e5c5122f4d6..a9ede7bae52 100644 --- a/arch/sh/mm/pg-mmu.c +++ b/arch/sh/mm/pg-mmu.c @@ -56,7 +56,7 @@ static void *kmap_coherent(struct page *page, unsigned long addr) return (void *)vaddr; } -static inline void kunmap_coherent(struct page *page) +static inline void kunmap_coherent(void) { dec_preempt_count(); preempt_check_resched(); @@ -70,7 +70,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, !test_bit(PG_dcache_dirty, &page->flags)) { void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(vto, src, len); - kunmap_coherent(vto); + kunmap_coherent(); } else { memcpy(dst, src, len); if (boot_cpu_data.dcache.n_aliases) @@ -89,7 +89,7 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page, !test_bit(PG_dcache_dirty, &page->flags)) { void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK); memcpy(dst, vfrom, len); - kunmap_coherent(vfrom); + kunmap_coherent(); } else { memcpy(dst, src, len); if (boot_cpu_data.dcache.n_aliases) @@ -108,7 +108,7 @@ void copy_user_highpage(struct page *to, struct page *from, !test_bit(PG_dcache_dirty, &from->flags)) { vfrom = kmap_coherent(from, vaddr); copy_page(vto, vfrom); - kunmap_coherent(vfrom); + kunmap_coherent(); } else { vfrom = kmap_atomic(from, KM_USER0); copy_page(vto, vfrom); From c0fe478dbb14fd32e71d1383dbe302b54ce94134 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 16:02:43 +0900 Subject: [PATCH 074/262] sh: Provide __flush_anon_page(). This provides a __flush_anon_page() that handles both the aliasing and non-aliasing cases. This fixes up some crashes with heavy get_user_pages() users. Signed-off-by: Paul Mundt --- arch/sh/include/asm/cacheflush.h | 14 ++++++++++++++ arch/sh/mm/pg-mmu.c | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h index 4c85d55847c..5dffbd126e4 100644 --- a/arch/sh/include/asm/cacheflush.h +++ b/arch/sh/include/asm/cacheflush.h @@ -1,6 +1,8 @@ #ifndef __ASM_SH_CACHEFLUSH_H #define __ASM_SH_CACHEFLUSH_H +#include + #ifdef __KERNEL__ #ifdef CONFIG_CACHE_OFF @@ -43,6 +45,18 @@ extern void __flush_purge_region(void *start, int size); extern void __flush_invalidate_region(void *start, int size); #endif +#ifdef CONFIG_MMU +#define ARCH_HAS_FLUSH_ANON_PAGE +extern void __flush_anon_page(struct page *page, unsigned long); + +static inline void flush_anon_page(struct vm_area_struct *vma, + struct page *page, unsigned long vmaddr) +{ + if (boot_cpu_data.dcache.n_aliases && PageAnon(page)) + __flush_anon_page(page, vmaddr); +} +#endif + #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE static inline void flush_kernel_dcache_page(struct page *page) { diff --git a/arch/sh/mm/pg-mmu.c b/arch/sh/mm/pg-mmu.c index a9ede7bae52..027c4d83fb8 100644 --- a/arch/sh/mm/pg-mmu.c +++ b/arch/sh/mm/pg-mmu.c @@ -157,3 +157,20 @@ void __update_cache(struct vm_area_struct *vma, } } } + +void __flush_anon_page(struct page *page, unsigned long vmaddr) +{ + unsigned long addr = (unsigned long) page_address(page); + + if (pages_do_alias(addr, vmaddr)) { + if (boot_cpu_data.dcache.n_aliases && page_mapped(page) && + !test_bit(PG_dcache_dirty, &page->flags)) { + void *kaddr; + + kaddr = kmap_coherent(page, vmaddr); + __flush_wback_region((void *)kaddr, PAGE_SIZE); + kunmap_coherent(); + } else + __flush_wback_region((void *)addr, PAGE_SIZE); + } +} From c7914834ef3b8a396b7e82ea34ac07cdcfe6f868 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 17:14:39 +0900 Subject: [PATCH 075/262] sh: Tidy up NEFF-based sign extension for SH-5. This consolidates all of the NEFF-based sign extension for SH-5. In the future the other SH code will need to make use of this as well, so make it generic in preparation for more 32/64 consolidation. Signed-off-by: Paul Mundt --- arch/sh/include/asm/pgtable.h | 6 ++++++ arch/sh/kernel/process_64.c | 24 +++++++++------------- arch/sh/kernel/signal_64.c | 38 ++++++++++++----------------------- arch/sh/mm/fault_64.c | 11 +--------- arch/sh/mm/tlb-sh5.c | 21 +++++-------------- arch/sh/mm/tlbflush_64.c | 2 +- 6 files changed, 36 insertions(+), 66 deletions(-) diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h index 43ef3e99fdd..3cd7127af95 100644 --- a/arch/sh/include/asm/pgtable.h +++ b/arch/sh/include/asm/pgtable.h @@ -36,6 +36,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define NEFF_SIGN (1LL << (NEFF - 1)) #define NEFF_MASK (-1LL << NEFF) +static inline unsigned long long neff_sign_extend(unsigned long val) +{ + unsigned long long extended = val; + return (extended & NEFF_SIGN) ? (extended | NEFF_MASK) : extended; +} + #ifdef CONFIG_29BIT #define NPHYS 29 #else diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 24de7421494..1192398ef58 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c @@ -425,7 +425,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; - unsigned long long se; /* Sign extension */ #ifdef CONFIG_SH_FPU if(last_task_used_math == current) { @@ -441,11 +440,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, *childregs = *regs; + /* + * Sign extend the edited stack. + * Note that thread.pc and thread.pc will stay + * 32-bit wide and context switch must take care + * of NEFF sign extension. + */ if (user_mode(regs)) { - childregs->regs[15] = usp; + childregs->regs[15] = neff_sign_extend(usp); p->thread.uregs = childregs; } else { - childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; + childregs->regs[15] = + neff_sign_extend((unsigned long)task_stack_page(p) + + THREAD_SIZE); } childregs->regs[9] = 0; /* Set return value for child */ @@ -454,17 +461,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; - /* - * Sign extend the edited stack. - * Note that thread.pc and thread.pc will stay - * 32-bit wide and context switch must take care - * of NEFF sign extension. - */ - - se = childregs->regs[15]; - se = (se & NEFF_SIGN) ? (se | NEFF_MASK) : se; - childregs->regs[15] = se; - return 0; } diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 0663a0ee602..026fd1cfe17 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -561,13 +561,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { - DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; - /* * On SH5 all edited pointers are subject to NEFF */ - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + DEREF_REG_PR = neff_sign_extend((unsigned long) + ka->sa.sa_restorer | 0x1); } else { /* * Different approach on SH5. @@ -580,9 +578,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, * . being code, linker turns ShMedia bit on, always * dereference index -1. */ - DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + DEREF_REG_PR = neff_sign_extend((unsigned long) + frame->retcode | 0x01); if (__copy_to_user(frame->retcode, (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0) @@ -596,9 +593,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, * Set up registers for signal handler. * All edited pointers are subject to NEFF. */ - regs->regs[REG_SP] = (unsigned long) frame; - regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? - (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; + regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame); regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ /* FIXME: @@ -613,8 +608,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; + regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler); set_fs(USER_DS); @@ -676,13 +670,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { - DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; - /* * On SH5 all edited pointers are subject to NEFF */ - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + DEREF_REG_PR = neff_sign_extend((unsigned long) + ka->sa.sa_restorer | 0x1); } else { /* * Different approach on SH5. @@ -695,15 +687,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * . being code, linker turns ShMedia bit on, always * dereference index -1. */ - - DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + DEREF_REG_PR = neff_sign_extend((unsigned long) + frame->retcode | 0x01); if (__copy_to_user(frame->retcode, (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0) goto give_sigsegv; + /* Cohere the trampoline with the I-cache. */ flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); } @@ -711,14 +702,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, * Set up registers for signal handler. * All edited pointers are subject to NEFF. */ - regs->regs[REG_SP] = (unsigned long) frame; - regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? - (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; + regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame); regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; + regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler); set_fs(USER_DS); diff --git a/arch/sh/mm/fault_64.c b/arch/sh/mm/fault_64.c index bd63b961b2a..2b356cec248 100644 --- a/arch/sh/mm/fault_64.c +++ b/arch/sh/mm/fault_64.c @@ -56,16 +56,7 @@ inline void __do_tlb_refill(unsigned long address, /* * Set PTEH register */ - pteh = address & MMU_VPN_MASK; - - /* Sign extend based on neff. */ -#if (NEFF == 32) - /* Faster sign extension */ - pteh = (unsigned long long)(signed long long)(signed long)pteh; -#else - /* General case */ - pteh = (pteh & NEFF_SIGN) ? (pteh | NEFF_MASK) : pteh; -#endif + pteh = neff_sign_extend(address & MMU_VPN_MASK); /* Set the ASID. */ pteh |= get_asid() << PTEH_ASID_SHIFT; diff --git a/arch/sh/mm/tlb-sh5.c b/arch/sh/mm/tlb-sh5.c index dae131243bc..fdb64e41ec5 100644 --- a/arch/sh/mm/tlb-sh5.c +++ b/arch/sh/mm/tlb-sh5.c @@ -117,26 +117,15 @@ int sh64_put_wired_dtlb_entry(unsigned long long entry) * Load up a virtual<->physical translation for @eaddr<->@paddr in the * pre-allocated TLB slot @config_addr (see sh64_get_wired_dtlb_entry). */ -inline void sh64_setup_tlb_slot(unsigned long long config_addr, - unsigned long eaddr, - unsigned long asid, - unsigned long paddr) +void sh64_setup_tlb_slot(unsigned long long config_addr, unsigned long eaddr, + unsigned long asid, unsigned long paddr) { unsigned long long pteh, ptel; - /* Sign extension */ -#if (NEFF == 32) - pteh = (unsigned long long)(signed long long)(signed long) eaddr; -#else -#error "Can't sign extend more than 32 bits yet" -#endif + pteh = neff_sign_extend(eaddr); pteh &= PAGE_MASK; pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID; -#if (NEFF == 32) - ptel = (unsigned long long)(signed long long)(signed long) paddr; -#else -#error "Can't sign extend more than 32 bits yet" -#endif + ptel = neff_sign_extend(paddr); ptel &= PAGE_MASK; ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE); @@ -152,5 +141,5 @@ inline void sh64_setup_tlb_slot(unsigned long long config_addr, * * Teardown any existing mapping in the TLB slot @config_addr. */ -inline void sh64_teardown_tlb_slot(unsigned long long config_addr) +void sh64_teardown_tlb_slot(unsigned long long config_addr) __attribute__ ((alias("__flush_tlb_slot"))); diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c index f2e44e9ffb7..fa5a95a062d 100644 --- a/arch/sh/mm/tlbflush_64.c +++ b/arch/sh/mm/tlbflush_64.c @@ -337,7 +337,7 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page) /* * Sign-extend based on neff. */ - lpage = (page & NEFF_SIGN) ? (page | NEFF_MASK) : page; + lpage = neff_sign_extend(page); match = (asid << PTEH_ASID_SHIFT) | PTEH_VALID; match |= lpage; From d14d751ff9234595639a16e53b3cf0c575946bde Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 17:17:00 +0900 Subject: [PATCH 076/262] sh64: Kill off special clear_page() implementation. This can use the now generic clear_page() implementation, which is backed by the sh64 optimized memset routine. This also fixes up the case where PAGE_SIZE != 4kB. Signed-off-by: Paul Mundt --- arch/sh/kernel/sh_ksyms_64.c | 1 - arch/sh/lib64/Makefile | 2 +- arch/sh/lib64/clear_page.S | 54 ------------------------------------ 3 files changed, 1 insertion(+), 56 deletions(-) delete mode 100644 arch/sh/lib64/clear_page.S diff --git a/arch/sh/kernel/sh_ksyms_64.c b/arch/sh/kernel/sh_ksyms_64.c index f5bd156ea50..f96c95c07c4 100644 --- a/arch/sh/kernel/sh_ksyms_64.c +++ b/arch/sh/kernel/sh_ksyms_64.c @@ -52,7 +52,6 @@ EXPORT_SYMBOL(__get_user_asm_l); EXPORT_SYMBOL(__get_user_asm_q); EXPORT_SYMBOL(__strnlen_user); EXPORT_SYMBOL(__strncpy_from_user); -EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(__clear_user); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(__copy_user); diff --git a/arch/sh/lib64/Makefile b/arch/sh/lib64/Makefile index 334bb2da36e..1fee75aa1f9 100644 --- a/arch/sh/lib64/Makefile +++ b/arch/sh/lib64/Makefile @@ -11,7 +11,7 @@ # Panic should really be compiled as PIC lib-y := udelay.o dbg.o panic.o memcpy.o memset.o \ - copy_user_memcpy.o copy_page.o clear_page.o strcpy.o strlen.o + copy_user_memcpy.o copy_page.o strcpy.o strlen.o # Extracted from libgcc lib-y += udivsi3.o udivdi3.o sdivsi3.o diff --git a/arch/sh/lib64/clear_page.S b/arch/sh/lib64/clear_page.S deleted file mode 100644 index 007ab48ecc1..00000000000 --- a/arch/sh/lib64/clear_page.S +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright 2003 Richard Curnow, SuperH (UK) Ltd. - - 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. - - Tight version of memset for the case of just clearing a page. It turns out - that having the alloco's spaced out slightly due to the increment/branch - pair causes them to contend less for access to the cache. Similarly, - keeping the stores apart from the allocos causes less contention. => Do two - separate loops. Do multiple stores per loop to amortise the - increment/branch cost a little. - - Parameters: - r2 : source effective address (start of page) - - Always clears 4096 bytes. - - Note : alloco guarded by synco to avoid TAKum03020 erratum - -*/ - - .section .text..SHmedia32,"ax" - .little - - .balign 8 - .global clear_page -clear_page: - pta/l 1f, tr1 - pta/l 2f, tr2 - ptabs/l r18, tr0 - - movi 4096, r7 - add r2, r7, r7 - add r2, r63, r6 -1: - alloco r6, 0 - synco ! TAKum03020 - addi r6, 32, r6 - bgt/l r7, r6, tr1 - - add r2, r63, r6 -2: - st.q r6, 0, r63 - st.q r6, 8, r63 - st.q r6, 16, r63 - st.q r6, 24, r63 - addi r6, 32, r6 - bgt/l r7, r6, tr2 - - blink tr0, r63 - - From 817425275271f2514f0dc6952182aa057ce80973 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 18:06:01 +0900 Subject: [PATCH 077/262] sh: Split out SH-4 __flush_xxx_region() ops. This splits out the SH-4 __flush_xxx_region() functions and defines them as weak symbols. This allows us to provide optimized versions without having to ifdef cache-sh4.c to death. Signed-off-by: Paul Mundt --- arch/sh/mm/Makefile_32 | 2 +- arch/sh/mm/cache-sh4.c | 60 ---------------------------------------- arch/sh/mm/flush-sh4.c | 63 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 61 deletions(-) create mode 100644 arch/sh/mm/flush-sh4.c diff --git a/arch/sh/mm/Makefile_32 b/arch/sh/mm/Makefile_32 index 62e280734dc..17b02522214 100644 --- a/arch/sh/mm/Makefile_32 +++ b/arch/sh/mm/Makefile_32 @@ -8,7 +8,7 @@ ifndef CONFIG_CACHE_OFF cache-$(CONFIG_CPU_SH2) := cache-sh2.o cache-$(CONFIG_CPU_SH2A) := cache-sh2a.o cache-$(CONFIG_CPU_SH3) := cache-sh3.o -cache-$(CONFIG_CPU_SH4) := cache-sh4.o +cache-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o cache-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o endif diff --git a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c index c3a09b27f8d..dfc1d037947 100644 --- a/arch/sh/mm/cache-sh4.c +++ b/arch/sh/mm/cache-sh4.c @@ -118,66 +118,6 @@ void __init p3_cache_init(void) emit_cache_params(); } -/* - * Write back the dirty D-caches, but not invalidate them. - * - * START: Virtual Address (U0, P1, or P3) - * SIZE: Size of the region. - */ -void __flush_wback_region(void *start, int size) -{ - unsigned long v; - unsigned long begin, end; - - begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); - end = ((unsigned long)start + size + L1_CACHE_BYTES-1) - & ~(L1_CACHE_BYTES-1); - for (v = begin; v < end; v+=L1_CACHE_BYTES) { - asm volatile("ocbwb %0" - : /* no output */ - : "m" (__m(v))); - } -} - -/* - * Write back the dirty D-caches and invalidate them. - * - * START: Virtual Address (U0, P1, or P3) - * SIZE: Size of the region. - */ -void __flush_purge_region(void *start, int size) -{ - unsigned long v; - unsigned long begin, end; - - begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); - end = ((unsigned long)start + size + L1_CACHE_BYTES-1) - & ~(L1_CACHE_BYTES-1); - for (v = begin; v < end; v+=L1_CACHE_BYTES) { - asm volatile("ocbp %0" - : /* no output */ - : "m" (__m(v))); - } -} - -/* - * No write back please - */ -void __flush_invalidate_region(void *start, int size) -{ - unsigned long v; - unsigned long begin, end; - - begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); - end = ((unsigned long)start + size + L1_CACHE_BYTES-1) - & ~(L1_CACHE_BYTES-1); - for (v = begin; v < end; v+=L1_CACHE_BYTES) { - asm volatile("ocbi %0" - : /* no output */ - : "m" (__m(v))); - } -} - /* * Write back the range of D-cache, and purge the I-cache. * diff --git a/arch/sh/mm/flush-sh4.c b/arch/sh/mm/flush-sh4.c new file mode 100644 index 00000000000..e6d918f6ec0 --- /dev/null +++ b/arch/sh/mm/flush-sh4.c @@ -0,0 +1,63 @@ +#include +#include +#include + +/* + * Write back the dirty D-caches, but not invalidate them. + * + * START: Virtual Address (U0, P1, or P3) + * SIZE: Size of the region. + */ +void __weak __flush_wback_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + asm volatile("ocbwb %0" + : /* no output */ + : "m" (__m(v))); + } +} + +/* + * Write back the dirty D-caches and invalidate them. + * + * START: Virtual Address (U0, P1, or P3) + * SIZE: Size of the region. + */ +void __weak __flush_purge_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + asm volatile("ocbp %0" + : /* no output */ + : "m" (__m(v))); + } +} + +/* + * No write back please + */ +void __weak __flush_invalidate_region(void *start, int size) +{ + unsigned long v; + unsigned long begin, end; + + begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + end = ((unsigned long)start + size + L1_CACHE_BYTES-1) + & ~(L1_CACHE_BYTES-1); + for (v = begin; v < end; v+=L1_CACHE_BYTES) { + asm volatile("ocbi %0" + : /* no output */ + : "m" (__m(v))); + } +} From 0837f52463583f76670ab2350e0f1541cb0351f5 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 4 Aug 2009 18:09:54 +0900 Subject: [PATCH 078/262] sh: Partially unroll the SH-4 __flush_xxx_region() flushers. This does a bit of unrolling for the SH-4 region flushers. Based on an earlier patch by SUGIOKA Toshinobu. Signed-off-by: Paul Mundt --- arch/sh/mm/flush-sh4.c | 104 ++++++++++++++++++++++++++++++++--------- 1 file changed, 83 insertions(+), 21 deletions(-) diff --git a/arch/sh/mm/flush-sh4.c b/arch/sh/mm/flush-sh4.c index e6d918f6ec0..edefc53891a 100644 --- a/arch/sh/mm/flush-sh4.c +++ b/arch/sh/mm/flush-sh4.c @@ -10,16 +10,37 @@ */ void __weak __flush_wback_region(void *start, int size) { - unsigned long v; - unsigned long begin, end; + unsigned long v, cnt, end; - begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + v = (unsigned long)start & ~(L1_CACHE_BYTES-1); end = ((unsigned long)start + size + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1); - for (v = begin; v < end; v+=L1_CACHE_BYTES) { - asm volatile("ocbwb %0" - : /* no output */ - : "m" (__m(v))); + cnt = (end - v) / L1_CACHE_BYTES; + + while (cnt >= 8) { + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + cnt -= 8; + } + + while (cnt) { + asm volatile("ocbwb @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + cnt--; } } @@ -31,16 +52,36 @@ void __weak __flush_wback_region(void *start, int size) */ void __weak __flush_purge_region(void *start, int size) { - unsigned long v; - unsigned long begin, end; + unsigned long v, cnt, end; - begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + v = (unsigned long)start & ~(L1_CACHE_BYTES-1); end = ((unsigned long)start + size + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1); - for (v = begin; v < end; v+=L1_CACHE_BYTES) { - asm volatile("ocbp %0" - : /* no output */ - : "m" (__m(v))); + cnt = (end - v) / L1_CACHE_BYTES; + + while (cnt >= 8) { + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + cnt -= 8; + } + while (cnt) { + asm volatile("ocbp @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + cnt--; } } @@ -49,15 +90,36 @@ void __weak __flush_purge_region(void *start, int size) */ void __weak __flush_invalidate_region(void *start, int size) { - unsigned long v; - unsigned long begin, end; + unsigned long v, cnt, end; - begin = (unsigned long)start & ~(L1_CACHE_BYTES-1); + v = (unsigned long)start & ~(L1_CACHE_BYTES-1); end = ((unsigned long)start + size + L1_CACHE_BYTES-1) & ~(L1_CACHE_BYTES-1); - for (v = begin; v < end; v+=L1_CACHE_BYTES) { - asm volatile("ocbi %0" - : /* no output */ - : "m" (__m(v))); + cnt = (end - v) / L1_CACHE_BYTES; + + while (cnt >= 8) { + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + cnt -= 8; + } + + while (cnt) { + asm volatile("ocbi @%0" : : "r" (v)); + v += L1_CACHE_BYTES; + cnt--; } } From c1155e34998bc07937cdf0c9db16b6902633a255 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 4 Aug 2009 16:55:29 +0200 Subject: [PATCH 079/262] sh: convert to asm-generic/hardirq.h Signed-off-by: Christoph Hellwig Signed-off-by: Paul Mundt --- arch/sh/include/asm/hardirq.h | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/sh/include/asm/hardirq.h b/arch/sh/include/asm/hardirq.h index 715ee237fc7..a5be4afa790 100644 --- a/arch/sh/include/asm/hardirq.h +++ b/arch/sh/include/asm/hardirq.h @@ -1,16 +1,9 @@ #ifndef __ASM_SH_HARDIRQ_H #define __ASM_SH_HARDIRQ_H -#include -#include - -/* entry.S is sensitive to the offsets of these fields */ -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - extern void ack_bad_irq(unsigned int irq); +#define ack_bad_irq ack_bad_irq + +#include #endif /* __ASM_SH_HARDIRQ_H */ From 909f10de5de81668e4d0a401f3cb5ca6b8a3d20d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 6 Aug 2009 14:28:12 +0000 Subject: [PATCH 080/262] sh: LCDC SYS bus access wait fix Update the SuperH Mobile LCDC driver to wait for SYS bus to become idle after reading or writing. This is needed by the kfr2r09 board, but also fixes potential problems on other boards making use of the LCDC in a SYS configuration. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 98fb82f1161..d1eb9656ca5 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -154,6 +154,7 @@ static void lcdc_sys_write_index(void *handle, unsigned long data) lcdc_write(ch->lcdc, _LDDWD0R, data | 0x10000000); lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); + lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); } static void lcdc_sys_write_data(void *handle, unsigned long data) @@ -163,6 +164,7 @@ static void lcdc_sys_write_data(void *handle, unsigned long data) lcdc_write(ch->lcdc, _LDDWD0R, data | 0x11000000); lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); lcdc_write(ch->lcdc, _LDDWAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); + lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); } static unsigned long lcdc_sys_read_data(void *handle) @@ -173,6 +175,7 @@ static unsigned long lcdc_sys_read_data(void *handle) lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); lcdc_write(ch->lcdc, _LDDRAR, 1 | (lcdc_chan_is_sublcd(ch) ? 2 : 0)); udelay(1); + lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff; } From ec56b66fed526e3b7dd58dba8945c405448f48d1 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 6 Aug 2009 14:34:38 +0000 Subject: [PATCH 081/262] sh: 18-bit SYS panel fix for SuperH Mobile LCDC Fix the SuperH Mobile LCDC driver to make use of the full 18-bit DRD field in the LDDRDR register. Without this patch only 16-bit register access is possible. Needed by 18-bit SYS panels such as the one used on kfr2r09. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index d1eb9656ca5..cff406de3d1 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -177,7 +177,7 @@ static unsigned long lcdc_sys_read_data(void *handle) udelay(1); lcdc_wait_bit(ch->lcdc, _LDSR, 2, 0); - return lcdc_read(ch->lcdc, _LDDRDR) & 0xffff; + return lcdc_read(ch->lcdc, _LDDRDR) & 0x3ffff; } struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { From 9f26e659d8caf5820c51b9c695f0a313e636b99c Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 6 Aug 2009 14:51:30 +0000 Subject: [PATCH 082/262] sh: kfr2r09 board support - LCDC panel This patch adds support for the WQVGA LCD display used by the KFR2R09 board. The LCD module is a TX07D34VM0AAA made by Hitachi, and this module is made up by a R61517 chip together with a 240x400 pixel display. The screen is attached to the SuperH Mobile LCDC using a 18-bit SYS bus. The register settings used by the SYS panel setup code are based on an out-of-tree driver which apart from duplicating all LCDC driver code and writing to non-existing hardware registers also never was posted for upstream merge. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/sh/boards/mach-kfr2r09/Makefile | 1 + arch/sh/boards/mach-kfr2r09/lcd_wqvga.c | 332 ++++++++++++++++++++ arch/sh/boards/mach-kfr2r09/setup.c | 94 ++++++ arch/sh/include/mach-kfr2r09/mach/kfr2r09.h | 21 ++ 4 files changed, 448 insertions(+) create mode 100644 arch/sh/boards/mach-kfr2r09/lcd_wqvga.c create mode 100644 arch/sh/include/mach-kfr2r09/mach/kfr2r09.h diff --git a/arch/sh/boards/mach-kfr2r09/Makefile b/arch/sh/boards/mach-kfr2r09/Makefile index 77037567633..5d5867826e3 100644 --- a/arch/sh/boards/mach-kfr2r09/Makefile +++ b/arch/sh/boards/mach-kfr2r09/Makefile @@ -1 +1,2 @@ obj-y := setup.o +obj-$(CONFIG_FB_SH_MOBILE_LCDC) += lcd_wqvga.o diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c new file mode 100644 index 00000000000..8ccb1cc8b58 --- /dev/null +++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c @@ -0,0 +1,332 @@ +/* + * KFR2R09 LCD panel support + * + * Copyright (C) 2009 Magnus Damm + * + * Register settings based on the out-of-tree t33fb.c driver + * Copyright (C) 2008 Lineo Solutions, Inc. + * + * 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 +#include