sh: SH-MobileR SH7722 CPU support.
Paul Mundt [Mon, 11 Dec 2006 11:28:03 +0000 (20:28 +0900)]
This adds CPU support for the SH7722.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>

22 files changed:
arch/sh/kernel/cpu/Makefile
arch/sh/kernel/cpu/sh4/Makefile
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4a/Makefile [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/clock-sh73180.c [moved from arch/sh/kernel/cpu/sh4/clock-sh73180.c with 100% similarity]
arch/sh/kernel/cpu/sh4a/clock-sh7343.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/clock-sh7770.c [moved from arch/sh/kernel/cpu/sh4/clock-sh7770.c with 100% similarity]
arch/sh/kernel/cpu/sh4a/clock-sh7780.c [moved from arch/sh/kernel/cpu/sh4/clock-sh7780.c with 100% similarity]
arch/sh/kernel/cpu/sh4a/setup-sh73180.c [moved from arch/sh/kernel/cpu/sh4/setup-sh73180.c with 100% similarity]
arch/sh/kernel/cpu/sh4a/setup-sh7343.c [moved from arch/sh/kernel/cpu/sh4/setup-sh7343.c with 100% similarity]
arch/sh/kernel/cpu/sh4a/setup-sh7722.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/setup-sh7770.c [moved from arch/sh/kernel/cpu/sh4/setup-sh7770.c with 100% similarity]
arch/sh/kernel/cpu/sh4a/setup-sh7780.c [moved from arch/sh/kernel/cpu/sh4/setup-sh7780.c with 100% similarity]
arch/sh/kernel/setup.c
arch/sh/mm/Kconfig
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
include/asm-sh/bugs.h
include/asm-sh/cpu-sh4/cache.h
include/asm-sh/cpu-sh4/freq.h
include/asm-sh/irq.h
include/asm-sh/processor.h

index 0582e67..d055a3e 100644 (file)
@@ -6,6 +6,7 @@ obj-$(CONFIG_CPU_SH2)           = sh2/
 obj-$(CONFIG_CPU_SH2A)         = sh2a/
 obj-$(CONFIG_CPU_SH3)          = sh3/
 obj-$(CONFIG_CPU_SH4)          = sh4/
+obj-$(CONFIG_CPU_SH4A)         += sh4a/
 
 obj-$(CONFIG_UBC_WAKEUP)       += ubc.o
 obj-$(CONFIG_SH_ADC)           += adc.o
index 6e415ba..19ca68c 100644 (file)
@@ -12,17 +12,12 @@ obj-$(CONFIG_SH_STORE_QUEUES)               += sq.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7750)       += setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7751)       += setup-sh7750.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7760)       += setup-sh7760.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
-obj-$(CONFIG_CPU_SUBTYPE_SH73180)      += setup-sh73180.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH4_202)      += setup-sh4-202.o
 
 # Primary on-chip clocks (common)
+ifndef CONFIG_CPU_SH4A
 clock-$(CONFIG_CPU_SH4)                        := clock-sh4.o
-clock-$(CONFIG_CPU_SUBTYPE_SH73180)    := clock-sh73180.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7770)     := clock-sh7770.o
-clock-$(CONFIG_CPU_SUBTYPE_SH7780)     := clock-sh7780.o
+endif
 
 # Additional clocks by subtype
 clock-$(CONFIG_CPU_SUBTYPE_SH4_202)    += clock-sh4-202.o
index afe0f1b..9031a22 100644 (file)
@@ -119,11 +119,20 @@ int __init detect_cpu_and_cache_system(void)
                break;
        case 0x3000:
        case 0x3003:
+       case 0x3009:
                cpu_data->type = CPU_SH7343;
                cpu_data->icache.ways = 4;
                cpu_data->dcache.ways = 4;
                cpu_data->flags |= CPU_HAS_LLSC;
                break;
+       case 0x3008:
+               if (prr == 0xa0) {
+                       cpu_data->type = CPU_SH7722;
+                       cpu_data->icache.ways = 4;
+                       cpu_data->dcache.ways = 4;
+                       cpu_data->flags |= CPU_HAS_LLSC;
+               }
+               break;
        case 0x8000:
                cpu_data->type = CPU_ST40RA;
                cpu_data->flags |= CPU_HAS_FPU;
diff --git a/arch/sh/kernel/cpu/sh4a/Makefile b/arch/sh/kernel/cpu/sh4a/Makefile
new file mode 100644 (file)
index 0000000..a8f493f
--- /dev/null
@@ -0,0 +1,19 @@
+#
+# Makefile for the Linux/SuperH SH-4 backends.
+#
+
+# CPU subtype setup
+obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
+obj-$(CONFIG_CPU_SUBTYPE_SH73180)      += setup-sh73180.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o
+
+# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SUBTYPE_SH73180)    := clock-sh73180.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7770)     := clock-sh7770.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7780)     := clock-sh7780.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7343)     := clock-sh7343.o
+clock-$(CONFIG_CPU_SUBTYPE_SH7722)     := clock-sh7343.o
+
+obj-y  += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7343.c b/arch/sh/kernel/cpu/sh4a/clock-sh7343.c
new file mode 100644 (file)
index 0000000..1707a21
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * arch/sh/kernel/cpu/sh4/clock-sh7343.c
+ *
+ * SH7343/SH7722 support for the clock framework
+ *
+ *  Copyright (C) 2006  Paul Mundt
+ *
+ * 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 <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <asm/clock.h>
+#include <asm/freq.h>
+
+/*
+ * SH7343/SH7722 uses a common set of multipliers and divisors, so this
+ * is quite simple..
+ */
+static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };
+
+#define pll_calc() (((ctrl_inl(FRQCR) >> 24) & 0x1f) + 1)
+
+static void master_clk_init(struct clk *clk)
+{
+       clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void master_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inl(FRQCR) & 0x000f);
+       clk->rate *= clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_master_clk_ops = {
+       .init           = master_clk_init,
+       .recalc         = master_clk_recalc,
+};
+
+static void module_clk_init(struct clk *clk)
+{
+       clk->parent = NULL;
+       clk->rate = CONFIG_SH_PCLK_FREQ;
+}
+
+static struct clk_ops sh7343_module_clk_ops = {
+       .init           = module_clk_init,
+};
+
+static void bus_clk_init(struct clk *clk)
+{
+       clk->parent = clk_get(NULL, "cpu_clk");
+}
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inl(FRQCR) >> 8) & 0x000f;
+       clk->rate = clk->parent->rate * multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_bus_clk_ops = {
+       .init           = bus_clk_init,
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_init(struct clk *clk)
+{
+       clk->parent = clk_get(NULL, "module_clk");
+       clk->flags |= CLK_RATE_PROPAGATES;
+       clk_set_rate(clk, clk_get_rate(clk));
+}
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inl(FRQCR) >> 20) & 0x000f;
+       clk->rate = clk->parent->rate * pll_calc() *
+               multipliers[idx] / divisors[idx];
+}
+
+static struct clk_ops sh7343_cpu_clk_ops = {
+       .init           = cpu_clk_init,
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh7343_clk_ops[] = {
+       &sh7343_master_clk_ops,
+       &sh7343_module_clk_ops,
+       &sh7343_bus_clk_ops,
+       &sh7343_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       if (idx < ARRAY_SIZE(sh7343_clk_ops))
+               *ops = sh7343_clk_ops[idx];
+}
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
new file mode 100644 (file)
index 0000000..7528fc6
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * SH7722 Setup
+ *
+ *  Copyright (C) 2006  Paul Mundt
+ *
+ * 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 <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <asm/sci.h>
+
+static struct plat_sci_port sci_platform_data[] = {
+       {
+               .mapbase        = 0xffe00000,
+               .flags          = UPF_BOOT_AUTOCONF,
+               .type           = PORT_SCIF,
+               .irqs           = { 80, 81, 83, 82 },
+       }, {
+               .flags = 0,
+       }
+};
+
+static struct platform_device sci_device = {
+       .name           = "sh-sci",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = sci_platform_data,
+       },
+};
+
+static struct platform_device *sh7722_devices[] __initdata = {
+       &sci_device,
+};
+
+static int __init sh7722_devices_setup(void)
+{
+       return platform_add_devices(sh7722_devices,
+                                   ARRAY_SIZE(sh7722_devices));
+}
+__initcall(sh7722_devices_setup);
+
+static struct ipr_data sh7722_ipr_map[] = {
+       /* IRQ, IPR-idx, shift, prio */
+       { 16, 0, 12, 2 }, /* TMU0 */
+       { 17, 0,  8, 2 }, /* TMU1 */
+};
+
+static unsigned long ipr_offsets[] = {
+       0xa4080000, /*  0: IPRA */
+       0xa4080004, /*  1: IPRB */
+       0xa4080008, /*  2: IPRC */
+       0xa408000c, /*  3: IPRD */
+       0xa4080010, /*  4: IPRE */
+       0xa4080014, /*  5: IPRF */
+       0xa4080018, /*  6: IPRG */
+       0xa408001c, /*  7: IPRH */
+       0xa4080020, /*  8: IPRI */
+       0xa4080024, /*  9: IPRJ */
+       0xa4080028, /* 10: IPRK */
+       0xa408002c, /* 11: IPRL */
+};
+
+unsigned int map_ipridx_to_addr(int idx)
+{
+       if (unlikely(idx >= ARRAY_SIZE(ipr_offsets)))
+               return 0;
+       return ipr_offsets[idx];
+}
+
+void __init init_IRQ_ipr(void)
+{
+       make_ipr_irq(sh7722_ipr_map, ARRAY_SIZE(sh7722_ipr_map));
+}
index f8dd6b7..fe545bb 100644 (file)
@@ -325,14 +325,18 @@ void __init setup_arch(char **cmdline_p)
        ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
        if (&__rd_start != &__rd_end) {
                LOADER_TYPE = 1;
-               INITRD_START = PHYSADDR((unsigned long)&__rd_start) - __MEMORY_START;
-               INITRD_SIZE = (unsigned long)&__rd_end - (unsigned long)&__rd_start;
+               INITRD_START = PHYSADDR((unsigned long)&__rd_start) -
+                                       __MEMORY_START;
+               INITRD_SIZE = (unsigned long)&__rd_end -
+                             (unsigned long)&__rd_start;
        }
 
        if (LOADER_TYPE && INITRD_START) {
                if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
-                       reserve_bootmem_node(NODE_DATA(0), INITRD_START+__MEMORY_START, INITRD_SIZE);
-                       initrd_start = INITRD_START + PAGE_OFFSET + __MEMORY_START;
+                       reserve_bootmem_node(NODE_DATA(0), INITRD_START +
+                                               __MEMORY_START, INITRD_SIZE);
+                       initrd_start = INITRD_START + PAGE_OFFSET +
+                                       __MEMORY_START;
                        initrd_end = initrd_start + INITRD_SIZE;
                } else {
                        printk("initrd extends beyond end of memory "
@@ -404,7 +408,7 @@ static const char *cpu_name[] = {
        [CPU_SH4_202]   = "SH4-202",    [CPU_SH4_501]   = "SH4-501",
        [CPU_SH7770]    = "SH7770",     [CPU_SH7780]    = "SH7780",
        [CPU_SH7781]    = "SH7781",     [CPU_SH7343]    = "SH7343",
-       [CPU_SH7785]    = "SH7785",
+       [CPU_SH7785]    = "SH7785",     [CPU_SH7722]    = "SH7722",
        [CPU_SH_NONE]   = "Unknown"
 };
 
index 4e0362f..29f4ee3 100644 (file)
@@ -35,6 +35,9 @@ config CPU_SUBTYPE_ST40
        select CPU_SH4
        select CPU_HAS_INTC2_IRQ
 
+config CPU_SHX2
+       bool
+
 #
 # Processor subtypes
 #
@@ -180,6 +183,7 @@ config CPU_SUBTYPE_SH7780
 config CPU_SUBTYPE_SH7785
        bool "Support SH7785 processor"
        select CPU_SH4A
+       select CPU_SHX2
        select CPU_HAS_INTC2_IRQ
 
 comment "SH4AL-DSP Processor Support"
@@ -192,6 +196,12 @@ config CPU_SUBTYPE_SH7343
        bool "Support SH7343 processor"
        select CPU_SH4AL_DSP
 
+config CPU_SUBTYPE_SH7722
+       bool "Support SH7722 processor"
+       select CPU_SH4AL_DSP
+       select CPU_SHX2
+       select CPU_HAS_IPR_IRQ
+
 endmenu
 
 menu "Memory management options"
@@ -250,7 +260,7 @@ config 32BIT
 
 config X2TLB
        bool "Enable extended TLB mode"
-       depends on CPU_SUBTYPE_SH7785 && MMU && EXPERIMENTAL
+       depends on CPU_SHX2 && MMU && EXPERIMENTAL
        help
          Selecting this option will enable the extended mode of the SH-X2
          TLB. For legacy SH-X behaviour and interoperability, say N. For
index 9031b57..c53b696 100644 (file)
@@ -319,6 +319,28 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
 
        sci_out(port, SCFCR, fcr_val);
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
+{
+       unsigned int fcr_val = 0;
+
+       if (cflag & CRTSCTS) {
+               fcr_val |= SCFCR_MCE;
+
+               ctrl_outw(0x0000, PORT_PSCR);
+       } else {
+               unsigned short data;
+
+               data = ctrl_inw(PORT_PSCR);
+               data &= 0x033f;
+               data |= 0x0400;
+               ctrl_outw(data, PORT_PSCR);
+
+               ctrl_outw(ctrl_inw(SCSPTR0) & 0x17, SCSPTR0);
+       }
+
+       sci_out(port, SCFCR, fcr_val);
+}
 #else
 /* For SH7750 */
 static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
index d84c1f9..77f7d63 100644 (file)
 # define SCSPTR3 0xffe30010    /* 16 bit SCIF */
 # define SCSCR_INIT(port) 0x32 /* TIE=0,RIE=0,TE=1,RE=1,REIE=0,CKE=1 */
 # define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+# define SCPDR0                        0xA405013E      /* 16 bit SCIF0 PSDR */
+# define SCSPTR0               SCPDR0
+# define SCIF_ORER             0x0001  /* overrun error bit */
+# define SCSCR_INIT(port)      0x0038  /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
+# define PORT_PSCR             0xA405011E
 #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
 # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
 # define SCIF_ORER 0x0001   /* overrun error bit */
@@ -522,6 +529,13 @@ static inline int sci_rxd_in(struct uart_port *port)
                return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
        return 1;
 }
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+       if (port->mapbase == 0xffe00000)
+               return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */
+       return 1;
+}
 #elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
 static inline int sci_rxd_in(struct uart_port *port)
 {
index 795047d..a294997 100644 (file)
@@ -16,9 +16,8 @@
 
 static void __init check_bugs(void)
 {
-       extern char *get_cpu_subtype(void);
        extern unsigned long loops_per_jiffy;
-       char *p= &init_utsname()->machine[2]; /* "sh" */
+       char *p = &init_utsname()->machine[2]; /* "sh" */
 
        cpu_data->loops_per_jiffy = loops_per_jiffy;
 
@@ -40,6 +39,15 @@ static void __init check_bugs(void)
                *p++ = '4';
                *p++ = 'a';
                break;
+       case CPU_SH73180 ... CPU_SH7722:
+               *p++ = '4';
+               *p++ = 'a';
+               *p++ = 'l';
+               *p++ = '-';
+               *p++ = 'd';
+               *p++ = 's';
+               *p++ = 'p';
+               break;
        default:
                *p++ = '?';
                *p++ = '!';
index 6e9c7e6..f92b20a 100644 (file)
@@ -22,7 +22,7 @@
 #define CCR_CACHE_ICE  0x0100  /* Instruction Cache Enable */
 #define CCR_CACHE_ICI  0x0800  /* IC Invalidate */
 #define CCR_CACHE_IIX  0x8000  /* IC Index Enable */
-#ifndef CONFIG_CPU_SUBTYPE_SH7780
+#ifndef CONFIG_CPU_SH4A
 #define CCR_CACHE_EMODE        0x80000000      /* EMODE Enable */
 #endif
 
index ef2b9b1..602d061 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef __ASM_CPU_SH4_FREQ_H
 #define __ASM_CPU_SH4_FREQ_H
 
-#if defined(CONFIG_CPU_SUBTYPE_SH73180)
+#if defined(CONFIG_CPU_SUBTYPE_SH73180) || defined(CONFIG_CPU_SUBTYPE_SH7722)
 #define FRQCR                  0xa4150000
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define        FRQCR                   0xffc80000
index fd57608..bff965e 100644 (file)
@@ -37,7 +37,8 @@
 # define ONCHIP_NR_IRQS 144
 #elif defined(CONFIG_CPU_SUBTYPE_SH7300) || \
       defined(CONFIG_CPU_SUBTYPE_SH73180) || \
-      defined(CONFIG_CPU_SUBTYPE_SH7343)
+      defined(CONFIG_CPU_SUBTYPE_SH7343) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7722)
 # define ONCHIP_NR_IRQS 109
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 # define ONCHIP_NR_IRQS 111
@@ -79,6 +80,8 @@
 # define OFFCHIP_NR_IRQS 16
 #elif defined(CONFIG_SH_7343_SOLUTION_ENGINE)
 # define OFFCHIP_NR_IRQS 12
+#elif defined(CONFIG_SH_7722_SOLUTION_ENGINE)
+# define OFFCHIP_NR_IRQS 14
 #elif defined(CONFIG_SH_UNKNOWN)
 # define OFFCHIP_NR_IRQS 16    /* Must also be last */
 #else
index 6f1dd7c..e29f2ab 100644 (file)
@@ -27,6 +27,8 @@
 #define CCN_CVR                0xff000040
 #define CCN_PRR                0xff000044
 
+const char *get_cpu_subtype(void);
+
 /*
  *  CPU type and hardware bug flags. Kept separately for each CPU.
  *
@@ -52,8 +54,10 @@ enum cpu_type {
        CPU_SH7760, CPU_ST40RA, CPU_ST40GX1, CPU_SH4_202, CPU_SH4_501,
 
        /* SH-4A types */
-       CPU_SH73180, CPU_SH7343, CPU_SH7770, CPU_SH7780, CPU_SH7781,
-       CPU_SH7785,
+       CPU_SH7770, CPU_SH7780, CPU_SH7781, CPU_SH7785,
+
+       /* SH4AL-DSP types */
+       CPU_SH73180, CPU_SH7343, CPU_SH7722,
 
        /* Unknown subtype */
        CPU_SH_NONE