OSDN Git Service

RX update
authorYoshinori Sato <ysato@users.sourceforge.jp>
Sun, 27 Dec 2015 10:11:14 +0000 (19:11 +0900)
committerYoshinori Sato <yo-satoh@sios.com>
Fri, 28 Jan 2022 12:39:23 +0000 (21:39 +0900)
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
25 files changed:
arch/rx/Kconfig
arch/rx/Makefile
arch/rx/boot/dts/Makefile [new file with mode: 0644]
arch/rx/boot/dts/rx_sim.dts [new file with mode: 0644]
arch/rx/include/asm/cmpxchg.h [new file with mode: 0644]
arch/rx/include/asm/switch_to.h [new file with mode: 0644]
arch/rx/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/rx/kernel/Makefile
arch/rx/kernel/entry.S
arch/rx/kernel/head.S
arch/rx/kernel/irq.c
arch/rx/kernel/setup.c
arch/rx/kernel/syscalls.c [new file with mode: 0644]
arch/rx/lib/Makefile
arch/rx/lib/memcpy.S [new file with mode: 0644]
arch/rx/lib/memset.S [new file with mode: 0644]
drivers/clk/Makefile
drivers/clk/rx/Makefile [new file with mode: 0644]
drivers/clk/rx/clk-multi.c [new file with mode: 0644]
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/rx_cmt.c [new file with mode: 0644]
drivers/clocksource/rx_tpu.c [new file with mode: 0644]
drivers/irqchip/Makefile
drivers/irqchip/irq-renesas-rxicu.c [new file with mode: 0644]

index 27b3eae..16d7d06 100644 (file)
@@ -13,7 +13,17 @@ config RX
        select GENERIC_ATOMIC64
        select HAVE_UID16
        select VIRT_TO_BUS
+       select IRQ_DOMAIN
+       select OF
+       select OF_IRQ
+       select OF_FLATTREE
+       select HAVE_MEMBLOCK
+       select OF_EARLY_FLATTREE
+       select SERIAL_EARLYCON
+       select COMMON_CLK
+       select CLKSRC_OF
+       select GENERIC_CLOCKEVENTS
+
 config MMU
        def_bool n
 
@@ -47,9 +57,6 @@ config GENERIC_HWEIGHT
 config GENERIC_HARDIRQS
        def_bool y
 
-config GENERIC_CALIBRATE_DELAY
-       def_bool y
-
 config GENERIC_TIME
        def_bool y
 
@@ -121,9 +128,15 @@ config AP_RX64M
        select CPU_RX64M
 endchoice
 
+config RX_BUILTIN_DTB
+        string "Builtin DTB"
+       default ""
+
 config CPU_RX610
        bool
        select RX_ICUA
+       select RX_TPU
+       select RX_CMT
 
 config CPU_RX62N
        bool
@@ -217,7 +230,11 @@ source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
-source "arch/rx/Kconfig.debug"
+menu "Kernel Hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
 
 source "security/Kconfig"
 
index b1322e4..982a5c0 100644 (file)
@@ -19,13 +19,23 @@ KBUILD_AFLAGS += -Wa,-mcpu=rxv2
 LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
 core-y += arch/$(ARCH)/kernel/ \
-          arch/$(ARCH)/mm/ \
-           arch/$(ARCH)/boards/ \
-          arch/$(ARCH)/lib/ 
-libs-y += $(LIBGCC)
+          arch/$(ARCH)/mm/
+
+ifneq '$(CONFIG_RX_BUILTIN_DTB)' '""'
+core-y += arch/$(ARCH)/boot/dts/
+endif
+
+libs-y += arch/$(ARCH)/lib/ $(LIBGCC)
 
 boot := arch/$(ARCH)/boot
 
+%.dtb %.dtb.S %.dtb.o: | scripts
+       $(Q)$(MAKE) $(build)=arch/$(ARCH)/boot/dts arch/$(ARCH)/boot/dts/$@
+
+PHONY += dtbs
+dtbs: scripts
+       $(Q)$(MAKE) $(build)=arch/$(ARCH)/boot/dts
+
 archmrproper:
 
 archclean:
diff --git a/arch/rx/boot/dts/Makefile b/arch/rx/boot/dts/Makefile
new file mode 100644 (file)
index 0000000..39e9b60
--- /dev/null
@@ -0,0 +1,13 @@
+ifneq '$(CONFIG_RX_BUILTIN_DTB)' '""'
+BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_RX_BUILTIN_DTB)).dtb.o
+endif
+
+obj-y += $(BUILTIN_DTB)
+
+dtb-$(CONFIG_RX_SIM) := rx_sim.dtb
+
+dtstree                := $(srctree)/$(src)
+dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(dtstree)/%.dts,%.dtb, $(wildcard $(dtstree)/*.dts))
+
+always     := $(dtb-y)
+clean-files := *.dtb.S *.dtb
diff --git a/arch/rx/boot/dts/rx_sim.dts b/arch/rx/boot/dts/rx_sim.dts
new file mode 100644 (file)
index 0000000..6634adf
--- /dev/null
@@ -0,0 +1,97 @@
+/dts-v1/;
+/ {
+        compatible = "gnu,gdbsim";
+        #address-cells = <1>;
+        #size-cells = <1>;
+       interrupt-parent = <&rxicu>;
+
+       chosen {
+               bootargs = "earlycon=rxsim";
+               stdout-path = <&sci0>;
+       };
+       aliases {
+               serial0 = &sci0;
+               serial1 = &sci1;
+       };
+
+       xclk: oscillator {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <12000000>;
+               clock-output-names = "xtal";
+       };
+       iclk: iclk {
+               compatible = "renesas,rx-mul-clock";
+               clocks = <&xclk>;
+               #clock-cells = <0>;
+               reg = <0x00080020 4>;
+               renesas,offset = <24>;
+               renesas,maxfreq = <100000000>;
+       };
+       pclk: pclk {
+               compatible = "renesas,rx-mul-clock";
+               clocks = <&xclk>;
+               #clock-cells = <0>;
+               reg = <0x00080020 4>;
+               renesas,offset = <8>;
+               renesas,maxfreq = <50000000>;
+       };
+       bclk: bclk {
+               compatible = "renesas,rx-mul-clock";
+               clocks = <&xclk>;
+               #clock-cells = <0>;
+               reg = <0x00080020 4>;
+               renesas,offset = <16>;
+               renesas,maxfreq = <50000000>;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               cpu@0 {
+                       compatible = "renesas,rx";
+                       clock-frequency = <96000000>;
+                       mem-cycle = <2>;
+               };
+       };
+       memory@01000000 {
+               device_type = "memory";
+               reg = <0x01000000 0x01000000>;
+       };
+
+       rxicu: interrupt-controller@87000 {
+               compatible = "renesas,rx-icu";
+               #interrupt-cells = <2>;
+               interrupt-controller;
+               reg = <0x00087000 0x600>;
+       };
+       
+       tpu: timer@00088100 {
+               compatible = "renesas,rx-tpu";
+               reg = <0x00088100 0x70>;
+               clocks = <&pclk>;
+               clock-names = "fck";
+       };
+       cmt: timer@00088000 {
+               compatible = "renesas,rx-cmt";
+               reg = <0x00088000 0x70>;
+               clocks = <&pclk>;
+               interrupts = <28 0>;
+       };
+               
+       sci0: serial@00088240 {
+               compatible = "renesas,sci";
+               reg = <0x00088240 8>;
+               interrupts = <214 0>, <215 0>, <216 0>, <217 0>;
+               clocks = <&pclk>;
+               clock-names = "sci_ick";
+       };
+
+       sci1: serial@00088248 {
+               compatible = "renesas,sci";
+               reg = <0x00088248 8>;
+               interrupts = <218 0>, <219 0>, <220 0>, <221 0>;
+               clocks = <&pclk>;
+               clock-names = "sci_ick";
+       };
+};
diff --git a/arch/rx/include/asm/cmpxchg.h b/arch/rx/include/asm/cmpxchg.h
new file mode 100644 (file)
index 0000000..6ab62df
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __ARCH_RX_CMPXCHG__
+#define __ARCH_RX_CMPXCHG__
+
+#define xchg(ptr, x) \
+       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), \
+                                   sizeof(*(ptr))))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((volatile struct __xchg_dummy *)(x))
+
+extern void __bad_xchg_size(void);
+
+static inline unsigned long __xchg(unsigned long x,
+                                  volatile void *ptr, int size)
+{
+       switch (size) {
+       case 1:
+               __asm__ __volatile__
+                       ("xchg %1.b,%0"
+                        : "=&r" (x), "=Q" (*__xg(ptr)));
+               break;
+       case 2:
+               __asm__ __volatile__
+                       ("xchg %1.w,%0"
+                        : "=&r" (x), "=Q" (*__xg(ptr)));
+               break;
+       case 4:
+               __asm__ __volatile__
+                       ("xchg %1.l,%0"
+                        : "=&r" (x), "=Q" (*__xg(ptr)));
+               break;
+       default:
+               __bad_xchg_size();
+       }
+       return x;
+}
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)                                        \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),              \
+                                                    (unsigned long)(o), \
+                                                    (unsigned long)(n), \
+                                                    sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+
+#ifndef CONFIG_SMP
+#include <asm-generic/cmpxchg.h>
+#endif
+
+#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
+
+#endif /* __ARCH_RX_CMPXCHG__ */
diff --git a/arch/rx/include/asm/switch_to.h b/arch/rx/include/asm/switch_to.h
new file mode 100644 (file)
index 0000000..5956787
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __ASM_RX_SWITCH_TO_H__
+#define __ASM_RX_SWITCH_TO_H__
+
+#define switch_to(prev,next,last)                      \
+do {                                                   \
+__asm__ volatile("switch_to:");                                \
+       __asm__ volatile("pushm r1-r15\n\t"             \
+                        "mov.l #1f,%0\n\t"             \
+                        "mov.l r0,%1\n\t"              \
+                        "mov.l %3,r0\n\t"              \
+                        "jmp %2\n"                     \
+                        "1:\n\t"                       \
+                        "popm r1-r15\n\t"              \
+                        ::"m"(prev->thread.pc),        \
+                                "m"(prev->thread.sp),  \
+                                "r"(next->thread.pc),  \
+                                "g"(next->thread.sp)); \
+       last = prev;                                    \
+} while(0)
+
+#endif
diff --git a/arch/rx/include/uapi/asm/unistd.h b/arch/rx/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..7a2eb69
--- /dev/null
@@ -0,0 +1,3 @@
+#define __ARCH_NOMMU
+
+#include <asm-generic/unistd.h>
index edaebe0..9e8efe1 100644 (file)
@@ -4,8 +4,7 @@
 
 extra-y := vmlinux.lds
 
-obj-y := head.o process.o traps.o irq.o time.o signal.o \
-         setup.o syscalls.o entry.o ptrace.o dma-nommu.o \
-        timer/ cpu/
+obj-y := head.o process.o traps.o irq.o signal.o \
+         setup.o syscalls.o entry.o ptrace.o dma-nommu.o
 
-obj-$(CONFIG_EARLY_PRINTK) += early-printk.o
+obj-$(CONFIG_RX_GDB_SIM) += sim-console.o
index 88b838f..8712aca 100644 (file)
@@ -108,10 +108,7 @@ work_pending:
        bra     resume_userspace
 work_resched:
        bsr     schedule
-       clrpsw  i
-       mov     TI_FLAGS[r13],r14
-       tst     #_TIF_WORK_MASK,r14
-       bne     work_pending
+       bra     resume_userspace
 restore_all:
        mov.l   OFF_USP[r0],r1
        mvtc    r1,usp
index 0b0995d..1d5eec3 100644 (file)
@@ -21,37 +21,41 @@ startup:
        mov.l   #setup_bsc,r1
        jsr     r1
 
-       /* copy rw data for ram */
+       /* copy rw data to ram */
        mov.l   #__data_romtop,r2
        mov.l   #_sdata,r1
        mov.l   #_edata,r3
        sub     r1,r3
        smovf
+       sub     r4,r4
 #endif
 #else
        /* setup args */
-       mov.l   #12, r5
+       sub     r4,r4
+       mov     #12, r5
        int     #255
-       mov.l   r1,r2
-       mov.l   #0x400,r1
-       mov.l   #13, r5
+       mov     r1,r2
+       mov     #boot_command_line,r1
+       mov     #13, r5
        int     #255
+       cmp     #1,r1
+       beq     2f
        /* r1 - argc */
        /* r2 -length */
        /* skip argv[0] */
-       mov.l   r1,r4
-       mov.l   r2,r3
-       mov.l   #0x400,r1
-       mov.l   #0,r2
+       mov     r1,r4
+       mov     r2,r3
+       mov     #boot_command_line,r1
+       mov     #0,r2
        suntil.b
-       mov.l   r3,r5
-       mov.l   r1,r2
-       mov.l   #0x400,r1
+       mov     r3,r5
+       mov     r1,r2
+       mov     #boot_command_line,r1
        smovf
-       mov.l   #0x400,r1
-       mov.l   #0,r2
+       mov     #boot_command_line,r1
+       mov     #0,r2
        sub     #1,r4
-       mov.l   r5,r3
+       mov     r5,r3
 1:     
        suntil.b
        sub     #1,r1
@@ -59,24 +63,30 @@ startup:
        add     #1,r1
        sub     #1,r4
        bne     1b
+       sub     #1,r1
        mov.b   #0,[r1]
+       mov     #-1,r4
+2:     
 #endif
        /* clear BSS */
-       mov.l   #_sbss,r1
-       mov.l   #_ebss,r3
+       mov     #_sbss,r1
+       mov     #_ebss,r3
        sub     r1,r3
        shlr    #2,r3
-       mov.l   #0,r2
+       mov     #0,r2
        sstr.l
+       mov     r4,r1
+       mov     #rx_fdt_init,r2
+       jsr     r2
        /* exception handler setup */
 #if defined(CONFIG_RAMKERNEL)
-       mov.l   #install_exception_entry,r1
+       mov     #install_exception_entry,r1
        jsr     r1
 #endif
        /* start kernel */
-       mov.l   #init_thread_union, r1
+       mov     #init_thread_union, r1
        add     #PAGE_SIZE, r1, r0
-       mov.l   #start_kernel, r1
+       mov     #start_kernel, r1
        jmp     r1
 
        .weak   setup_bsc
index a67ade4..1f60bfb 100644 (file)
@@ -1,13 +1,13 @@
 /*
  * arch/rx/kernel/irq.c
  *
- * Copyright (C) 2009 Yoshinori Sato <ysato@users.sourceforge.jp>
+ * Copyright (C) 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  *
  */
 
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/seq_file.h>
+#include <linux/irqchip.h>
 #include <asm/processor.h>
 #include <asm/io.h>
 
@@ -17,17 +17,6 @@ extern unsigned long rx_int_table[NR_IRQS];
 extern unsigned long rx_exp_table[32];
 static unsigned long *interrupt_vector[NR_IRQS];
 
-#define EXT_IRQ0 64
-#define EXT_IRQS 16
-#define IR (0x00087000)
-#define IER (0x00087200)
-#define IRQER (0x0008c300)
-
-void rx_force_interrupt(unsigned int no)
-{
-       __raw_writeb(1, (void __iomem *)(IR + no));
-}
-
 void __init setup_vector(void)
 {
        int i;
@@ -40,7 +29,7 @@ void __init setup_vector(void)
 void __init init_IRQ(void)
 {
        setup_vector();
-       setup_rx_irq_desc();
+       irqchip_init();
 }
 
 asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs)
index 7481ffa..54702b8 100644 (file)
@@ -12,9 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
-#include <linux/fb.h>
 #include <linux/console.h>
-#include <linux/genhd.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/seq_file.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/initrd.h>
-#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/memblock.h>
+#include <linux/clocksource.h>
+#include <linux/clk-provider.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
@@ -32,8 +34,6 @@ unsigned long rom_length;
 unsigned long memory_start;
 unsigned long memory_end;
 
-#define COMMAND_LINE ((char *)0x400)
-
 static struct resource code_resource = {
        .name   = "Kernel code",
 };
@@ -52,89 +52,88 @@ extern void *_sdata, *_edata;
 extern void *_sbss, *_ebss;
 extern void *_end;
 
-void early_device_register(void);
+void __init rx_fdt_init(void *fdt)
+{
+       char saved_command_line[512];
 
-void __init setup_arch(char **cmdline_p)
+       *saved_command_line = 0;
+       if (fdt == (void *)-1) {
+               memcpy(saved_command_line, boot_command_line,
+                      sizeof(saved_command_line));
+               fdt = NULL;
+       }
+       if (!fdt)
+               fdt = __dtb_start;
+
+       early_init_dt_scan(fdt);
+       memblock_allow_resize();
+       if (*saved_command_line) {
+               memcpy(boot_command_line, saved_command_line,
+                      sizeof(saved_command_line));
+       }
+}
+
+static void __init bootmem_init(void)
 {
        int bootmap_size;
+       unsigned long ram_start_pfn;
+       unsigned long free_ram_start_pfn;
+       unsigned long ram_end_pfn;
+       struct memblock_region *region;
 
-#ifdef CONFIG_CMDLINE
-       if (*COMMAND_LINE == 0)
-               memcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
-#endif
-       if(*boot_command_line == '\0')
-               memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE);
-       *cmdline_p = boot_command_line;
+       memory_end = memory_start = 0;
 
-#ifdef DEBUG
-       if (strlen(boot_command_line)) 
-               printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p);
-#endif
+       /* Find main memory where is the kernel */
+       for_each_memblock(memory, region) {
+               memory_start = region->base;
+               memory_end = region->base + region->size;
+       }
 
-       memory_start = (unsigned long) &_end;
+       if (!memory_end)
+               panic("No memory!");
 
-       /* allow for ROMFS on the end of the kernel */
-       if (memcmp((void *)memory_start, "-rom1fs-", 8) == 0) {
-#if defined(CONFIG_BLK_DEV_INITRD)
-               initrd_start = memory_start;
-               initrd_end = memory_start += be32_to_cpu(((unsigned long *) (memory_start))[2]);
-#else
-               memory_start += be32_to_cpu(((unsigned long *) memory_start)[2]);
-#endif
-       }
-       memory_start = PAGE_ALIGN(memory_start);
-#if !defined(CONFIG_BLKDEV_RESERVE)
-       memory_end = (unsigned long) &_ramend; /* by now the stack is part of the init task */
-#else
-       if ((memory_end < CONFIG_BLKDEV_RESERVE_ADDRESS) && 
-           (memory_end > CONFIG_BLKDEV_RESERVE_ADDRESS))
-           /* overlap userarea */
-           memory_end = CONFIG_BLKDEV_RESERVE_ADDRESS; 
-#endif
+       ram_start_pfn = PFN_UP(memory_start);
+       /* free_ram_start_pfn is first page after kernel */
+       free_ram_start_pfn = PFN_UP(__pa(&_end));
+       ram_end_pfn = PFN_DOWN(memblock_end_of_DRAM());
+
+       max_pfn = ram_end_pfn;
 
-       init_mm.start_code = (unsigned long) &_stext;
-       init_mm.end_code = (unsigned long) &_etext;
-       init_mm.end_data = (unsigned long) &_edata;
-       init_mm.brk = (unsigned long) &_end; 
-
-       code_resource.start = virt_to_bus(&_stext);
-       code_resource.end = virt_to_bus(&_etext)-1;
-       data_resource.start = virt_to_bus(&_sdata);
-       data_resource.end = virt_to_bus(&_edata)-1;
-       bss_resource.start = virt_to_bus(&_sbss);
-       bss_resource.end = virt_to_bus(&_ebss)-1;
-
-
-#ifdef DEBUG
-       printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x "
-               "BSS=0x%06x-0x%06x\n", (int) &_stext, (int) &_etext,
-               (int) &_sdata, (int) &_edata,
-               (int) &_sbss, (int) &_ebss);
-       printk(KERN_DEBUG "KERNEL -> ROMFS=0x%06x-0x%06x MEM=0x%06x-0x%06x "
-               "STACK=0x%06x-0x%06x\n",
-              (int) &_ebss, (int) memory_start,
-               (int) memory_start, (int) memory_end,
-               (int) memory_end, (int) &_ramend);
-#endif
        /*
         * give all the memory to the bootmap allocator,  tell it to put the
         * boot mem_map at the start of memory
         */
-       bootmap_size = init_bootmem_node(
-                       NODE_DATA(0),
-                       memory_start >> PAGE_SHIFT, /* map goes here */
-                       memory_start >> PAGE_SHIFT,
-                       memory_end >> PAGE_SHIFT);
+       bootmap_size = init_bootmem_node(NODE_DATA(0),
+                                        free_ram_start_pfn,
+                                        0,
+                                        ram_end_pfn);
        /*
         * free the usable memory,  we have to make sure we do not free
         * the bootmem bitmap so we then reserve it after freeing it :-)
         */
-       free_bootmem(memory_start, memory_end - memory_start);
-       reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
-       /* Let earlyprintk output early console messages */
-       early_device_register();
+       free_bootmem(PFN_PHYS(free_ram_start_pfn),
+                    (ram_end_pfn - free_ram_start_pfn) << PAGE_SHIFT);
+       reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
+                       BOOTMEM_DEFAULT);
+
+       for_each_memblock(reserved, region) {
+               reserve_bootmem(region->base, region->size, BOOTMEM_DEFAULT);
+       }
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+       unflatten_and_copy_device_tree();
+
+       init_mm.start_code = (unsigned long) &_stext;
+       init_mm.end_code = (unsigned long) &_etext;
+       init_mm.end_data = (unsigned long) &_edata;
+       init_mm.brk = 0; 
+
+       *cmdline_p = boot_command_line;
+
        parse_early_param();
-       early_platform_driver_probe("earlyprintk", 1, 1);
+       bootmem_init();
        /*
         * get kmalloc into gear
         */
@@ -143,9 +142,6 @@ void __init setup_arch(char **cmdline_p)
        insert_resource(&iomem_resource, &code_resource);
        insert_resource(&iomem_resource, &data_resource);
        insert_resource(&iomem_resource, &bss_resource);
-#ifdef DEBUG
-       printk(KERN_DEBUG "Done setup_arch\n");
-#endif
 }
 
 /*
@@ -195,3 +191,33 @@ const struct seq_operations cpuinfo_op = {
        .stop   = c_stop,
        .show   = show_cpuinfo,
 };
+
+static int __init device_probe(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+       return 0;
+}
+
+device_initcall(device_probe);
+
+void __init time_init(void)
+{
+       of_clk_init(NULL);
+       clocksource_probe();
+}
+
+void __init calibrate_delay(void)
+{
+       struct device_node *cpu;
+       int freq;
+       int cycle;
+
+       cpu = of_find_compatible_node(NULL, NULL, "renesas,rx");
+       of_property_read_s32(cpu, "clock-frequency", &freq);
+       of_property_read_s32(cpu, "mem-cycle", &cycle);
+       loops_per_jiffy = freq / HZ / cycle;
+       pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+               loops_per_jiffy / (500000 / HZ),
+               (loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
+}
diff --git a/arch/rx/kernel/syscalls.c b/arch/rx/kernel/syscalls.c
new file mode 100644 (file)
index 0000000..1f9123a
--- /dev/null
@@ -0,0 +1,14 @@
+#include <linux/syscalls.h>
+#include <linux/signal.h>
+#include <linux/unistd.h>
+
+#undef __SYSCALL
+#define __SYSCALL(nr, call) [nr] = (call),
+
+#define sys_mmap2 sys_mmap_pgoff
+
+asmlinkage int sys_rt_sigreturn(void);
+
+void *_sys_call_table[__NR_syscalls] = {
+#include <asm/unistd.h>
+};
index 2d65664..6dfaeb6 100644 (file)
@@ -1 +1 @@
-obj-y=delay.o
+lib-y := delay.o memcpy.o memset.o
diff --git a/arch/rx/lib/memcpy.S b/arch/rx/lib/memcpy.S
new file mode 100644 (file)
index 0000000..c643c98
--- /dev/null
@@ -0,0 +1,7 @@
+       .global memcpy
+       .text
+memcpy:
+       mov     r1,r4
+       smovf
+       mov     r4,r1
+       rts
diff --git a/arch/rx/lib/memset.S b/arch/rx/lib/memset.S
new file mode 100644 (file)
index 0000000..59928d0
--- /dev/null
@@ -0,0 +1,7 @@
+       .global memset
+       .text
+memset:
+       mov     r1,r4
+       sstr
+       mov     r4,r1
+       rts
index e423121..69965ac 100644 (file)
@@ -122,3 +122,4 @@ endif
 obj-y                                  += xilinx/
 obj-$(CONFIG_ARCH_ZYNQ)                        += zynq/
 obj-$(CONFIG_COMMON_CLK_ZYNQMP)         += zynqmp/
+obj-$(CONFIG_RX)                       += rx/
diff --git a/drivers/clk/rx/Makefile b/drivers/clk/rx/Makefile
new file mode 100644 (file)
index 0000000..010e7a5
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CPU_RX610) += clk-multi.o
+obj-$(CONFIG_CPU_RX62N) += clk-multi.o
diff --git a/drivers/clk/rx/clk-multi.c b/drivers/clk/rx/clk-multi.c
new file mode 100644 (file)
index 0000000..952c473
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * RX610/RX62N clock multiply driver
+ *
+ * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#define MIN_FREQ 8000000
+
+static DEFINE_SPINLOCK(clklock);
+
+struct pll_clock {
+       struct clk_hw hw;
+       void __iomem *sckcr;
+       int offset;
+       int maxfreq;
+};
+
+#define to_pll_clock(_hw) container_of(_hw, struct pll_clock, hw)
+
+static unsigned long pll_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct pll_clock *pll_clock = to_pll_clock(hw);
+       unsigned long sckcr;
+       int mul;
+
+       sckcr = ioread32(pll_clock->sckcr);
+       sckcr >>= pll_clock->offset;
+       mul = 1 << (3 - sckcr);
+
+       return parent_rate * mul;
+}
+
+static long pll_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *prate)
+{
+       struct pll_clock *pll_clock = to_pll_clock(hw);
+       int i, m = -1;
+       long offset[4];
+
+       if (rate > pll_clock->maxfreq)
+               rate = pll_clock->maxfreq;
+       if (rate < MIN_FREQ)
+               rate = MIN_FREQ;
+
+       for (i = 0; i < 4; i++)
+               offset[i] = abs(rate - (*prate * (1 << i)));
+       for (i = 0; i < 4; i++)
+               if (m < 0)
+                       m = i;
+               else
+                       m = (offset[i] < offset[m])?i:m;
+
+       return *prate * (1 << m);
+}
+
+static int pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                       unsigned long parent_rate)
+{
+       int pll;
+       unsigned long val;
+       unsigned long flags;
+       struct pll_clock *pll_clock = to_pll_clock(hw);
+
+       pll = 3 - ffs(rate / parent_rate);
+       spin_lock_irqsave(&clklock, flags);
+       val = ioread32(pll_clock->sckcr);
+       val &= ~(0x0f << pll_clock->offset);
+       val |= pll << pll_clock->offset;
+       iowrite32(val, pll_clock->sckcr);
+       while (ioread32(pll_clock->sckcr) != val);
+       spin_unlock_irqrestore(&clklock, flags);
+       return 0;
+}
+
+static const struct clk_ops pll_ops = {
+       .recalc_rate = pll_recalc_rate,
+       .round_rate = pll_round_rate,
+       .set_rate = pll_set_rate,
+};
+
+static void __init rx_mul_clk_setup(struct device_node *node)
+{
+       int num_parents;
+       struct clk *clk;
+       const char *clk_name = node->name;
+       const char *parent_name;
+       struct pll_clock *pll_clock;
+       struct clk_init_data init;
+
+       num_parents = of_clk_get_parent_count(node);
+       if (num_parents < 1) {
+               pr_err("%s: no parent found", clk_name);
+               return;
+       }
+
+
+       pll_clock = kzalloc(sizeof(*pll_clock), GFP_KERNEL);
+       if (!pll_clock)
+               return;
+
+       pll_clock->sckcr = of_iomap(node, 0);
+       if (pll_clock->sckcr == NULL) {
+               pr_err("%s: failed to map sckcr register", clk_name);
+               goto free_clock;
+       }
+       of_property_read_u32(node,"renesas,offset", &pll_clock->offset);
+       of_property_read_u32(node,"renesas,maxfreq", &pll_clock->maxfreq);
+
+       parent_name = of_clk_get_parent_name(node, 0);
+       init.name = clk_name;
+       init.ops = &pll_ops;
+       init.flags = CLK_IS_BASIC;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+       pll_clock->hw.init = &init;
+
+       clk = clk_register(NULL, &pll_clock->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register %s div clock (%ld)\n",
+                      __func__, clk_name, PTR_ERR(clk));
+               goto unmap_sckcr;
+       }
+
+       of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       return;
+
+unmap_sckcr:
+       iounmap(pll_clock->sckcr);
+free_clock:
+       kfree(pll_clock);
+}
+
+CLK_OF_DECLARE(rx_mul_clk, "renesas,rx-mul-clock",
+              rx_mul_clk_setup);
index f65e31b..383844e 100644 (file)
@@ -586,6 +586,9 @@ config H8300_TPU
          This enables the clocksource for the H8300 platform with the
          H8S2678 CPU.
 
+config RX_TPU
+       bool
+
 config CLKSRC_IMX_GPT
        bool "Clocksource using i.MX GPT" if COMPILE_TEST
        depends on (ARM || ARM64) && HAVE_CLK
index c17ee32..923702f 100644 (file)
@@ -88,3 +88,5 @@ obj-$(CONFIG_CSKY_MP_TIMER)           += timer-mp-csky.o
 obj-$(CONFIG_GX6605S_TIMER)            += timer-gx6605s.o
 obj-$(CONFIG_HYPERV_TIMER)             += hyperv_timer.o
 obj-$(CONFIG_MICROCHIP_PIT64B)         += timer-microchip-pit64b.o
+obj-$(CONFIG_RX_TPU)                   += rx_tpu.o
+obj-$(CONFIG_RX_CMT)                   += rx_cmt.o
diff --git a/drivers/clocksource/rx_cmt.c b/drivers/clocksource/rx_cmt.c
new file mode 100644 (file)
index 0000000..6fa7450
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ *  RX CMT Driver
+ *
+ *  Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+
+enum {
+       STR = 0,
+       CMCR = 2,
+       CMCNT = 4,
+       CMCOR = 6
+};
+
+#define SCALE 128
+#define FLAG_STARTED 1
+
+struct cmt_priv {
+       struct clock_event_device ced;
+       void __iomem *base;
+       unsigned long flags;
+       unsigned int rate;
+};
+
+static irqreturn_t cmt_interrupt(int irq, void *dev_id)
+{
+       struct cmt_priv *p = dev_id;
+
+       if (clockevent_state_oneshot(&p->ced))
+               iowrite16(0x0000, p->base + STR);
+
+       p->ced.event_handler(&p->ced);
+       return IRQ_HANDLED;
+}
+
+static void cmt_set_next(struct cmt_priv *p, unsigned long delta)
+{
+       if (delta >= 0x10000)
+               pr_warn("delta out of range\n");
+       iowrite16(delta, p->base + CMCOR);
+       iowrite16(0x0000, p->base + CMCNT);
+}
+
+static int cmt_enable(struct cmt_priv *p)
+{
+       iowrite16(0xffff, p->base + CMCOR);
+       iowrite16(0x0000, p->base + CMCNT);
+       iowrite16(0x00c2, p->base + CMCR);
+       iowrite16(0x0001, p->base + STR);
+
+       return 0;
+}
+
+static int cmt_start(struct cmt_priv *p)
+{
+       int ret;
+
+       if ((p->flags & FLAG_STARTED))
+               return 0;
+
+       ret = cmt_enable(p);
+       if (!ret)
+               p->flags |= FLAG_STARTED;
+
+       return ret;
+}
+
+static void cmt_stop(struct cmt_priv *p)
+{
+       iowrite16be(0x0000, p->base + STR);
+}
+
+static inline struct cmt_priv *ced_to_priv(struct clock_event_device *ced)
+{
+       return container_of(ced, struct cmt_priv, ced);
+}
+
+static void cmt_clock_event_start(struct cmt_priv *p, unsigned long delta)
+{
+       struct clock_event_device *ced = &p->ced;
+
+       cmt_start(p);
+
+       ced->shift = 32;
+       ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift);
+       ced->max_delta_ns = clockevent_delta2ns(0xffff, ced);
+       ced->min_delta_ns = clockevent_delta2ns(0x0001, ced);
+
+       cmt_set_next(p, delta);
+}
+
+static int cmt_clock_event_shutdown(struct clock_event_device *ced)
+{
+       cmt_stop(ced_to_priv(ced));
+       return 0;
+}
+
+static int cmt_clock_event_periodic(struct clock_event_device *ced)
+{
+       struct cmt_priv *p = ced_to_priv(ced);
+
+       pr_info("%s: used for periodic clock events\n", ced->name);
+       cmt_stop(p);
+       cmt_clock_event_start(p, (p->rate + HZ/2) / HZ);
+
+       return 0;
+}
+
+static int cmt_clock_event_oneshot(struct clock_event_device *ced)
+{
+       struct cmt_priv *p = ced_to_priv(ced);
+
+       pr_info("%s: used for oneshot clock events\n", ced->name);
+       cmt_stop(p);
+       cmt_clock_event_start(p, 0x10000);
+
+       return 0;
+}
+
+static int cmt_clock_event_next(unsigned long delta,
+                                  struct clock_event_device *ced)
+{
+       struct cmt_priv *p = ced_to_priv(ced);
+
+       BUG_ON(!clockevent_state_oneshot(ced));
+       cmt_set_next(p, delta - 1);
+
+       return 0;
+}
+
+static struct cmt_priv cmt_priv = {
+       .ced = {
+               .name = "rx-cmt",
+               .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+               .rating = 200,
+               .set_next_event = cmt_clock_event_next,
+               .set_state_shutdown = cmt_clock_event_shutdown,
+               .set_state_periodic = cmt_clock_event_periodic,
+               .set_state_oneshot = cmt_clock_event_oneshot,
+       },
+};
+
+static void __init cmt_init(struct device_node *node)
+{
+       void __iomem *base;
+       int irq;
+       int ret = 0;
+       int rate;
+       struct clk *clk;
+
+       clk = of_clk_get(node, 0);
+       if (IS_ERR(clk)) {
+               pr_err("failed to get clock for clockevent\n");
+               return;
+       }
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("failed to map registers for clockevent\n");
+               goto free_clk;
+       }
+
+       irq = irq_of_parse_and_map(node, 0);
+       if (!irq) {
+               pr_err("failed to get irq for clockevent\n");
+               goto unmap_reg;
+       }
+
+       cmt_priv.base = base;
+
+       rate = clk_get_rate(clk) / SCALE;
+       if (!rate) {
+               pr_err("Failed to get rate for the clocksource\n");
+               goto unmap_reg;
+       }
+       cmt_priv.rate = rate;
+
+       ret = request_irq(irq, cmt_interrupt,
+                         IRQF_TIMER, cmt_priv.ced.name, &cmt_priv);
+       if (ret < 0) {
+               pr_err("failed to request irq %d for clockevent\n", irq);
+               goto unmap_reg;
+       }
+
+       clockevents_config_and_register(&cmt_priv.ced, rate, 1, 0x0000ffff);
+
+       return;
+unmap_reg:
+       iounmap(base);
+free_clk:
+       clk_put(clk);
+}
+
+CLOCKSOURCE_OF_DECLARE(rx_cmt, "renesas,rx-cmt", cmt_init);
diff --git a/drivers/clocksource/rx_tpu.c b/drivers/clocksource/rx_tpu.c
new file mode 100644 (file)
index 0000000..fc2bedd
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *  RX TPU Driver
+ *
+ *  Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clocksource.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define TCR    0x0
+#define TSR    0x5
+#define TCNT   0x6
+
+#define TCFV   0x10
+
+struct tpu_priv {
+       struct clocksource cs;
+       void __iomem *mapbase1;
+       void __iomem *mapbase2;
+       raw_spinlock_t lock;
+       unsigned int cs_enabled;
+};
+
+static inline unsigned long read_tcnt32(struct tpu_priv *p)
+{
+       unsigned long tcnt;
+
+       tcnt = ioread16(p->mapbase1 + TCNT) << 16;
+       tcnt |= ioread16(p->mapbase2 + TCNT);
+       return tcnt;
+}
+
+static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val)
+{
+       unsigned long v1, v2, v3;
+       int o1, o2;
+
+       o1 = ioread8(p->mapbase1 + TSR) & TCFV;
+
+       /* Make sure the timer value is stable. Stolen from acpi_pm.c */
+       do {
+               o2 = o1;
+               v1 = read_tcnt32(p);
+               v2 = read_tcnt32(p);
+               v3 = read_tcnt32(p);
+               o1 = ioread8(p->mapbase1 + TSR) & TCFV;
+       } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
+                         || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
+
+       *val = v2;
+       return o1;
+}
+
+static inline struct tpu_priv *cs_to_priv(struct clocksource *cs)
+{
+       return container_of(cs, struct tpu_priv, cs);
+}
+
+static cycle_t tpu_clocksource_read(struct clocksource *cs)
+{
+       struct tpu_priv *p = cs_to_priv(cs);
+       unsigned long flags;
+       unsigned long long value;
+
+       raw_spin_lock_irqsave(&p->lock, flags);
+       if (tpu_get_counter(p, &value))
+               value += 0x100000000;
+       raw_spin_unlock_irqrestore(&p->lock, flags);
+
+       return value;
+}
+
+static int tpu_clocksource_enable(struct clocksource *cs)
+{
+       struct tpu_priv *p = cs_to_priv(cs);
+
+       WARN_ON(p->cs_enabled);
+
+       iowrite16(0, p->mapbase1 + TCNT);
+       iowrite16(0, p->mapbase2 + TCNT);
+       iowrite8(0x0f, p->mapbase1 + TCR);
+       iowrite8(0x03, p->mapbase2 + TCR);
+
+       p->cs_enabled = true;
+       return 0;
+}
+
+static void tpu_clocksource_disable(struct clocksource *cs)
+{
+       struct tpu_priv *p = cs_to_priv(cs);
+
+       WARN_ON(!p->cs_enabled);
+
+       iowrite8(0, p->mapbase1 + TCR);
+       iowrite8(0, p->mapbase2 + TCR);
+       p->cs_enabled = false;
+}
+
+static struct tpu_priv tpu_priv = {
+       .cs = {
+               .name = "RX_TPU",
+               .rating = 200,
+               .read = tpu_clocksource_read,
+               .enable = tpu_clocksource_enable,
+               .disable = tpu_clocksource_disable,
+               .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8),
+               .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+       },
+};
+
+static void __init rx_tpu_init(struct device_node *node)
+{
+       void __iomem *base;
+       struct clk *clk;
+
+       clk = of_clk_get(node, 0);
+       if (IS_ERR(clk)) {
+               pr_err("failed to get clock for clocksource\n");
+               return;
+       }
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("failed to map registers for clocksource\n");
+               goto free_clk;
+       }
+               
+       tpu_priv.mapbase1 = base + 0x20;
+       tpu_priv.mapbase2 = base + 0x30;
+       iowrite8(ioread8(base) | 0x06, base);
+       clocksource_register_hz(&tpu_priv.cs, clk_get_rate(clk) / 64);
+
+       return;
+
+free_clk:
+       clk_put(clk);
+}
+
+CLOCKSOURCE_OF_DECLARE(rx_tpu, "renesas,rx-tpu", rx_tpu_init);
index c1f611c..3a9e367 100644 (file)
@@ -117,3 +117,4 @@ obj-$(CONFIG_WPCM450_AIC)           += irq-wpcm450-aic.o
 obj-$(CONFIG_IRQ_IDT3243X)             += irq-idt3243x.o
 obj-$(CONFIG_APPLE_AIC)                        += irq-apple-aic.o
 obj-$(CONFIG_MCHP_EIC)                 += irq-mchp-eic.o
+obj-$(CONFIG_RX)                       += irq-renesas-rxicu.o
diff --git a/drivers/irqchip/irq-renesas-rxicu.c b/drivers/irqchip/irq-renesas-rxicu.c
new file mode 100644 (file)
index 0000000..86abf25
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * RX interrupt controller driver
+ *
+ * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <asm/io.h>
+
+#define IRBASE 0x0000
+#define IERBASE 0x0200
+#define IPRBASE 0x0300
+
+#define IR (icu_base + IRBASE)
+#define IER (icu_base + IERBASE)
+#define IPR (icu_base + IPRBASE)
+
+static void *icu_base;
+
+static void disable_icua_irq(struct irq_data *data)
+{
+       void __iomem *ier = (void *)(IER + (data->irq >> 3));
+       unsigned char val;
+       val = ioread8(ier);
+       val &= ~(1 << (data->irq & 7));
+       iowrite8(val, ier);
+}
+
+static void enable_icua_irq(struct irq_data *data)
+{
+       void __iomem *ier = (void *)(IER + (data->irq >> 3));
+       unsigned char val;
+       val = ioread8(ier);
+       val |= 1 << (data->irq & 7);
+       iowrite8(val, ier);
+}
+
+static void icua_eoi(struct irq_data *data)
+{
+       iowrite8(0, (void *)(IR + data->irq));
+}
+
+static struct irq_chip chip = {
+       .name         = "RX-ICUa",
+       .irq_mask     = disable_icua_irq,
+       .irq_unmask   = enable_icua_irq,
+       .irq_eoi      = icua_eoi,
+       .irq_mask_ack = disable_icua_irq,
+};
+
+static int irq_map(struct irq_domain *h, unsigned int virq,
+                  irq_hw_number_t hw_irq_num)
+{
+       irq_set_chip_and_handler(virq, &chip, handle_fasteoi_irq);
+
+       return 0;
+}
+
+static struct irq_domain_ops irq_ops = {
+       .map    = irq_map,
+       .xlate  = irq_domain_xlate_onecell,
+};
+
+static int __init rx_icu_of_init(struct device_node *icu,
+                                struct device_node *parent)
+{
+       struct irq_domain *domain;
+       int i;
+
+       icu_base = of_iomap(icu, 0);
+       domain = irq_domain_add_linear(icu, NR_IRQS, &irq_ops, NULL);
+       BUG_ON(!domain);
+       irq_set_default_host(domain);
+       irq_domain_associate_many(domain, 0, 0, NR_IRQS);
+       for (i = 0; i < 0x90; i++)
+               __raw_writeb(1, (void __iomem *)(IPR + i));
+       return 0;
+}
+
+IRQCHIP_DECLARE(rxicu, "renesas,rx-icu", rx_icu_of_init);