aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2012-09-28 10:29:55 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-09-28 10:29:55 -0400
commitcb418b34caddc970c1513e515aaa535246a4bba3 (patch)
treeb89720b74d6a85a9407f03bb064248c7235b9dea /arch/mips
parent77a0d763c461da81c2a3fc9a7e58162a40854a1a (diff)
parentff401e52100dcdc85e572d1ad376d3307b3fe28e (diff)
Merge branch 'ralf-3.7' of git://git.linux-mips.org/pub/scm/sjhill/linux-sjhill into mips-for-linux-next
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kbuild.platforms1
-rw-r--r--arch/mips/Kconfig32
-rw-r--r--arch/mips/configs/sead3_defconfig124
-rw-r--r--arch/mips/include/asm/cpu.h1
-rw-r--r--arch/mips/include/asm/gic.h49
-rw-r--r--arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h72
-rw-r--r--arch/mips/include/asm/mach-sead3/irq.h9
-rw-r--r--arch/mips/include/asm/mach-sead3/kernel-entry-init.h52
-rw-r--r--arch/mips/include/asm/mach-sead3/war.h25
-rw-r--r--arch/mips/include/asm/mips-boards/maltaint.h55
-rw-r--r--arch/mips/include/asm/mips-boards/sead3int.h19
-rw-r--r--arch/mips/include/asm/mipsregs.h2
-rw-r--r--arch/mips/include/asm/uasm.h2
-rw-r--r--arch/mips/kernel/cevt-r4k.c5
-rw-r--r--arch/mips/kernel/cpu-probe.c4
-rw-r--r--arch/mips/kernel/irq-gic.c162
-rw-r--r--arch/mips/mm/c-r4k.c21
-rw-r--r--arch/mips/mm/tlbex.c30
-rw-r--r--arch/mips/mm/uasm.c23
-rw-r--r--arch/mips/mti-malta/malta-int.c34
-rw-r--r--arch/mips/mti-sead3/Makefile19
-rw-r--r--arch/mips/mti-sead3/Platform7
-rw-r--r--arch/mips/mti-sead3/leds-sead3.c128
-rw-r--r--arch/mips/mti-sead3/sead3-cmdline.c46
-rw-r--r--arch/mips/mti-sead3/sead3-console.c46
-rw-r--r--arch/mips/mti-sead3/sead3-display.c78
-rw-r--r--arch/mips/mti-sead3/sead3-ehci.c47
-rw-r--r--arch/mips/mti-sead3/sead3-i2c-dev.c33
-rw-r--r--arch/mips/mti-sead3/sead3-i2c-drv.c405
-rw-r--r--arch/mips/mti-sead3/sead3-i2c.c37
-rw-r--r--arch/mips/mti-sead3/sead3-init.c91
-rw-r--r--arch/mips/mti-sead3/sead3-int.c158
-rw-r--r--arch/mips/mti-sead3/sead3-lcd.c43
-rw-r--r--arch/mips/mti-sead3/sead3-leds.c83
-rw-r--r--arch/mips/mti-sead3/sead3-memory.c138
-rw-r--r--arch/mips/mti-sead3/sead3-mtd.c54
-rw-r--r--arch/mips/mti-sead3/sead3-net.c51
-rw-r--r--arch/mips/mti-sead3/sead3-pic32-bus.c103
-rw-r--r--arch/mips/mti-sead3/sead3-pic32-i2c-drv.c435
-rw-r--r--arch/mips/mti-sead3/sead3-platform.c45
-rw-r--r--arch/mips/mti-sead3/sead3-reset.c39
-rw-r--r--arch/mips/mti-sead3/sead3-serial.c45
-rw-r--r--arch/mips/mti-sead3/sead3-setup.c20
-rw-r--r--arch/mips/mti-sead3/sead3-time.c117
44 files changed, 2874 insertions, 116 deletions
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 0759dd2524bf..91b9d69f465c 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -16,6 +16,7 @@ platforms += lasat
16platforms += loongson 16platforms += loongson
17platforms += loongson1 17platforms += loongson1
18platforms += mti-malta 18platforms += mti-malta
19platforms += mti-sead3
19platforms += netlogic 20platforms += netlogic
20platforms += pmc-sierra 21platforms += pmc-sierra
21platforms += pnx833x 22platforms += pnx833x
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index c0cbde6c1770..566462c358c5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -322,6 +322,36 @@ config MIPS_MALTA
322 This enables support for the MIPS Technologies Malta evaluation 322 This enables support for the MIPS Technologies Malta evaluation
323 board. 323 board.
324 324
325config MIPS_SEAD3
326 bool "MIPS SEAD3 board"
327 select BOOT_ELF32
328 select BOOT_RAW
329 select CEVT_R4K
330 select CSRC_R4K
331 select CPU_MIPSR2_IRQ_VI
332 select CPU_MIPSR2_IRQ_EI
333 select DMA_NONCOHERENT
334 select IRQ_CPU
335 select IRQ_GIC
336 select MIPS_BOARDS_GEN
337 select MIPS_CPU_SCACHE
338 select MIPS_MSC
339 select SYS_HAS_CPU_MIPS32_R1
340 select SYS_HAS_CPU_MIPS32_R2
341 select SYS_HAS_CPU_MIPS64_R1
342 select SYS_HAS_EARLY_PRINTK
343 select SYS_SUPPORTS_32BIT_KERNEL
344 select SYS_SUPPORTS_64BIT_KERNEL
345 select SYS_SUPPORTS_BIG_ENDIAN
346 select SYS_SUPPORTS_LITTLE_ENDIAN
347 select SYS_SUPPORTS_SMARTMIPS
348 select USB_ARCH_HAS_EHCI
349 select USB_EHCI_BIG_ENDIAN_DESC
350 select USB_EHCI_BIG_ENDIAN_MMIO
351 help
352 This enables support for the MIPS Technologies SEAD3 evaluation
353 board.
354
325config NEC_MARKEINS 355config NEC_MARKEINS
326 bool "NEC EMMA2RH Mark-eins board" 356 bool "NEC EMMA2RH Mark-eins board"
327 select SOC_EMMA2RH 357 select SOC_EMMA2RH
@@ -1732,7 +1762,6 @@ config HARDWARE_WATCHPOINTS
1732menu "Kernel type" 1762menu "Kernel type"
1733 1763
1734choice 1764choice
1735
1736 prompt "Kernel code model" 1765 prompt "Kernel code model"
1737 help 1766 help
1738 You should only select this option if you have a workload that 1767 You should only select this option if you have a workload that
@@ -1938,7 +1967,6 @@ config SCHED_SMT
1938config SYS_SUPPORTS_SCHED_SMT 1967config SYS_SUPPORTS_SCHED_SMT
1939 bool 1968 bool
1940 1969
1941
1942config SYS_SUPPORTS_MULTITHREADING 1970config SYS_SUPPORTS_MULTITHREADING
1943 bool 1971 bool
1944 1972
diff --git a/arch/mips/configs/sead3_defconfig b/arch/mips/configs/sead3_defconfig
new file mode 100644
index 000000000000..e3eec68d9132
--- /dev/null
+++ b/arch/mips/configs/sead3_defconfig
@@ -0,0 +1,124 @@
1CONFIG_MIPS_SEAD3=y
2CONFIG_CPU_LITTLE_ENDIAN=y
3CONFIG_CPU_MIPS32_R2=y
4CONFIG_HZ_100=y
5CONFIG_EXPERIMENTAL=y
6CONFIG_SYSVIPC=y
7CONFIG_POSIX_MQUEUE=y
8CONFIG_NO_HZ=y
9CONFIG_HIGH_RES_TIMERS=y
10CONFIG_IKCONFIG=y
11CONFIG_IKCONFIG_PROC=y
12CONFIG_LOG_BUF_SHIFT=15
13CONFIG_EMBEDDED=y
14CONFIG_SLAB=y
15CONFIG_PROFILING=y
16CONFIG_OPROFILE=y
17CONFIG_MODULES=y
18# CONFIG_BLK_DEV_BSG is not set
19# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
20CONFIG_NET=y
21CONFIG_PACKET=y
22CONFIG_UNIX=y
23CONFIG_INET=y
24CONFIG_IP_PNP=y
25CONFIG_IP_PNP_DHCP=y
26CONFIG_IP_PNP_BOOTP=y
27# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
28# CONFIG_INET_XFRM_MODE_TUNNEL is not set
29# CONFIG_INET_XFRM_MODE_BEET is not set
30# CONFIG_INET_LRO is not set
31# CONFIG_INET_DIAG is not set
32# CONFIG_IPV6 is not set
33# CONFIG_WIRELESS is not set
34CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
35CONFIG_MTD=y
36CONFIG_MTD_CHAR=y
37CONFIG_MTD_BLOCK=y
38CONFIG_MTD_CFI=y
39CONFIG_MTD_CFI_INTELEXT=y
40CONFIG_MTD_PHYSMAP=y
41CONFIG_MTD_UBI=y
42CONFIG_MTD_UBI_GLUEBI=y
43CONFIG_BLK_DEV_LOOP=y
44CONFIG_BLK_DEV_CRYPTOLOOP=m
45CONFIG_SCSI=y
46# CONFIG_SCSI_PROC_FS is not set
47CONFIG_BLK_DEV_SD=y
48CONFIG_CHR_DEV_SG=y
49# CONFIG_SCSI_LOWLEVEL is not set
50CONFIG_NETDEVICES=y
51CONFIG_SMSC911X=y
52# CONFIG_NET_VENDOR_WIZNET is not set
53CONFIG_MARVELL_PHY=y
54CONFIG_DAVICOM_PHY=y
55CONFIG_QSEMI_PHY=y
56CONFIG_LXT_PHY=y
57CONFIG_CICADA_PHY=y
58CONFIG_VITESSE_PHY=y
59CONFIG_SMSC_PHY=y
60CONFIG_BROADCOM_PHY=y
61CONFIG_ICPLUS_PHY=y
62# CONFIG_WLAN is not set
63# CONFIG_INPUT_MOUSEDEV is not set
64# CONFIG_INPUT_KEYBOARD is not set
65# CONFIG_INPUT_MOUSE is not set
66# CONFIG_SERIO is not set
67# CONFIG_CONSOLE_TRANSLATIONS is not set
68CONFIG_VT_HW_CONSOLE_BINDING=y
69CONFIG_LEGACY_PTY_COUNT=32
70CONFIG_SERIAL_8250=y
71CONFIG_SERIAL_8250_CONSOLE=y
72CONFIG_SERIAL_8250_NR_UARTS=2
73CONFIG_SERIAL_8250_RUNTIME_UARTS=2
74# CONFIG_HW_RANDOM is not set
75CONFIG_I2C=y
76# CONFIG_I2C_COMPAT is not set
77CONFIG_I2C_CHARDEV=y
78# CONFIG_I2C_HELPER_AUTO is not set
79CONFIG_SPI=y
80CONFIG_SENSORS_ADT7475=y
81CONFIG_BACKLIGHT_LCD_SUPPORT=y
82CONFIG_LCD_CLASS_DEVICE=y
83CONFIG_BACKLIGHT_CLASS_DEVICE=y
84# CONFIG_VGA_CONSOLE is not set
85CONFIG_USB=y
86CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
87CONFIG_USB_EHCI_HCD=y
88CONFIG_USB_EHCI_ROOT_HUB_TT=y
89CONFIG_USB_STORAGE=y
90CONFIG_MMC=y
91CONFIG_MMC_DEBUG=y
92CONFIG_MMC_SPI=y
93CONFIG_NEW_LEDS=y
94CONFIG_LEDS_CLASS=y
95CONFIG_LEDS_TRIGGERS=y
96CONFIG_LEDS_TRIGGER_HEARTBEAT=y
97CONFIG_RTC_CLASS=y
98CONFIG_RTC_DRV_M41T80=y
99CONFIG_EXT3_FS=y
100# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
101CONFIG_XFS_FS=y
102CONFIG_XFS_QUOTA=y
103CONFIG_XFS_POSIX_ACL=y
104CONFIG_QUOTA=y
105# CONFIG_PRINT_QUOTA_WARNING is not set
106CONFIG_MSDOS_FS=m
107CONFIG_VFAT_FS=m
108CONFIG_TMPFS=y
109CONFIG_JFFS2_FS=y
110CONFIG_NFS_FS=y
111CONFIG_ROOT_NFS=y
112CONFIG_NLS_CODEPAGE_437=y
113CONFIG_NLS_ASCII=y
114CONFIG_NLS_ISO8859_1=y
115CONFIG_NLS_ISO8859_15=y
116CONFIG_NLS_UTF8=y
117# CONFIG_FTRACE is not set
118CONFIG_CRYPTO=y
119CONFIG_CRYPTO_CBC=y
120CONFIG_CRYPTO_ECB=y
121CONFIG_CRYPTO_AES=y
122CONFIG_CRYPTO_ARC4=y
123# CONFIG_CRYPTO_ANSI_CPRNG is not set
124# CONFIG_CRYPTO_HW is not set
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 1037d54f0597..554e2d29965d 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -94,6 +94,7 @@
94#define PRID_IMP_24KE 0x9600 94#define PRID_IMP_24KE 0x9600
95#define PRID_IMP_74K 0x9700 95#define PRID_IMP_74K 0x9700
96#define PRID_IMP_1004K 0x9900 96#define PRID_IMP_1004K 0x9900
97#define PRID_IMP_1074K 0x9a00
97#define PRID_IMP_M14KC 0x9c00 98#define PRID_IMP_M14KC 0x9c00
98 99
99/* 100/*
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h
index 991b659e2548..37620db588be 100644
--- a/arch/mips/include/asm/gic.h
+++ b/arch/mips/include/asm/gic.h
@@ -33,13 +33,13 @@
33 REG32(_gic_base + segment##_##SECTION_OFS + offset) 33 REG32(_gic_base + segment##_##SECTION_OFS + offset)
34 34
35#define GIC_ABS_REG(segment, offset) \ 35#define GIC_ABS_REG(segment, offset) \
36 (_gic_base + segment##_##SECTION_OFS + offset##_##OFS) 36 (_gic_base + segment##_##SECTION_OFS + offset##_##OFS)
37#define GIC_REG_ABS_ADDR(segment, offset) \ 37#define GIC_REG_ABS_ADDR(segment, offset) \
38 (_gic_base + segment##_##SECTION_OFS + offset) 38 (_gic_base + segment##_##SECTION_OFS + offset)
39 39
40#ifdef GICISBYTELITTLEENDIAN 40#ifdef GICISBYTELITTLEENDIAN
41#define GICREAD(reg, data) (data) = (reg), (data) = le32_to_cpu(data) 41#define GICREAD(reg, data) ((data) = (reg), (data) = le32_to_cpu(data))
42#define GICWRITE(reg, data) (reg) = cpu_to_le32(data) 42#define GICWRITE(reg, data) ((reg) = cpu_to_le32(data))
43#define GICBIS(reg, bits) \ 43#define GICBIS(reg, bits) \
44 ({unsigned int data; \ 44 ({unsigned int data; \
45 GICREAD(reg, data); \ 45 GICREAD(reg, data); \
@@ -48,9 +48,9 @@
48 }) 48 })
49 49
50#else 50#else
51#define GICREAD(reg, data) (data) = (reg) 51#define GICREAD(reg, data) ((data) = (reg))
52#define GICWRITE(reg, data) (reg) = (data) 52#define GICWRITE(reg, data) ((reg) = (data))
53#define GICBIS(reg, bits) (reg) |= (bits) 53#define GICBIS(reg, bits) ((reg) |= (bits))
54#endif 54#endif
55 55
56 56
@@ -304,15 +304,15 @@
304 GIC_SH_MAP_TO_VPE_REG_BIT(vpe)) 304 GIC_SH_MAP_TO_VPE_REG_BIT(vpe))
305 305
306struct gic_pcpu_mask { 306struct gic_pcpu_mask {
307 DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); 307 DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
308}; 308};
309 309
310struct gic_pending_regs { 310struct gic_pending_regs {
311 DECLARE_BITMAP(pending, GIC_NUM_INTRS); 311 DECLARE_BITMAP(pending, GIC_NUM_INTRS);
312}; 312};
313 313
314struct gic_intrmask_regs { 314struct gic_intrmask_regs {
315 DECLARE_BITMAP(intrmask, GIC_NUM_INTRS); 315 DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
316}; 316};
317 317
318/* 318/*
@@ -341,15 +341,44 @@ struct gic_shared_intr_map {
341 unsigned int local_intr_mask; 341 unsigned int local_intr_mask;
342}; 342};
343 343
344/* GIC nomenclature for Core Interrupt Pins. */
345#define GIC_CPU_INT0 0 /* Core Interrupt 2 */
346#define GIC_CPU_INT1 1 /* . */
347#define GIC_CPU_INT2 2 /* . */
348#define GIC_CPU_INT3 3 /* . */
349#define GIC_CPU_INT4 4 /* . */
350#define GIC_CPU_INT5 5 /* Core Interrupt 5 */
351
352/* Local GIC interrupts. */
353#define GIC_INT_TMR (GIC_CPU_INT5)
354#define GIC_INT_PERFCTR (GIC_CPU_INT5)
355
356/* Add 2 to convert non-EIC hardware interrupt to EIC vector number. */
357#define GIC_CPU_TO_VEC_OFFSET (2)
358
359/* Mapped interrupt to pin X, then GIC will generate the vector (X+1). */
360#define GIC_PIN_TO_VEC_OFFSET (1)
361
362extern unsigned long _gic_base;
363extern unsigned int gic_irq_base;
364extern unsigned int gic_irq_flags[];
365extern struct gic_shared_intr_map gic_shared_intr_map[];
366
344extern void gic_init(unsigned long gic_base_addr, 367extern void gic_init(unsigned long gic_base_addr,
345 unsigned long gic_addrspace_size, struct gic_intr_map *intrmap, 368 unsigned long gic_addrspace_size, struct gic_intr_map *intrmap,
346 unsigned int intrmap_size, unsigned int irqbase); 369 unsigned int intrmap_size, unsigned int irqbase);
347 370
371extern void gic_clocksource_init(unsigned int);
348extern unsigned int gic_get_int(void); 372extern unsigned int gic_get_int(void);
349extern void gic_send_ipi(unsigned int intr); 373extern void gic_send_ipi(unsigned int intr);
350extern unsigned int plat_ipi_call_int_xlate(unsigned int); 374extern unsigned int plat_ipi_call_int_xlate(unsigned int);
351extern unsigned int plat_ipi_resched_int_xlate(unsigned int); 375extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
352extern void gic_bind_eic_interrupt(int irq, int set); 376extern void gic_bind_eic_interrupt(int irq, int set);
353extern unsigned int gic_get_timer_pending(void); 377extern unsigned int gic_get_timer_pending(void);
378extern void gic_enable_interrupt(int irq_vec);
379extern void gic_disable_interrupt(int irq_vec);
380extern void gic_irq_ack(struct irq_data *d);
381extern void gic_finish_irq(struct irq_data *d);
382extern void gic_platform_init(int irqs, struct irq_chip *irq_controller);
354 383
355#endif /* _ASM_GICREGS_H */ 384#endif /* _ASM_GICREGS_H */
diff --git a/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h
new file mode 100644
index 000000000000..7f3e3f9bd23a
--- /dev/null
+++ b/arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h
@@ -0,0 +1,72 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2003, 2004 Chris Dearman
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 */
9#ifndef __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H
10#define __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H
11
12
13/*
14 * CPU feature overrides for MIPS boards
15 */
16#ifdef CONFIG_CPU_MIPS32
17#define cpu_has_tlb 1
18#define cpu_has_4kex 1
19#define cpu_has_4k_cache 1
20/* #define cpu_has_fpu ? */
21/* #define cpu_has_32fpr ? */
22#define cpu_has_counter 1
23/* #define cpu_has_watch ? */
24#define cpu_has_divec 1
25#define cpu_has_vce 0
26/* #define cpu_has_cache_cdex_p ? */
27/* #define cpu_has_cache_cdex_s ? */
28/* #define cpu_has_prefetch ? */
29#define cpu_has_mcheck 1
30/* #define cpu_has_ejtag ? */
31#ifdef CONFIG_CPU_HAS_LLSC
32#define cpu_has_llsc 1
33#else
34#define cpu_has_llsc 0
35#endif
36/* #define cpu_has_vtag_icache ? */
37/* #define cpu_has_dc_aliases ? */
38/* #define cpu_has_ic_fills_f_dc ? */
39#define cpu_has_nofpuex 0
40/* #define cpu_has_64bits ? */
41/* #define cpu_has_64bit_zero_reg ? */
42/* #define cpu_has_inclusive_pcaches ? */
43#define cpu_icache_snoops_remote_store 1
44#endif
45
46#ifdef CONFIG_CPU_MIPS64
47#define cpu_has_tlb 1
48#define cpu_has_4kex 1
49#define cpu_has_4k_cache 1
50/* #define cpu_has_fpu ? */
51/* #define cpu_has_32fpr ? */
52#define cpu_has_counter 1
53/* #define cpu_has_watch ? */
54#define cpu_has_divec 1
55#define cpu_has_vce 0
56/* #define cpu_has_cache_cdex_p ? */
57/* #define cpu_has_cache_cdex_s ? */
58/* #define cpu_has_prefetch ? */
59#define cpu_has_mcheck 1
60/* #define cpu_has_ejtag ? */
61#define cpu_has_llsc 1
62/* #define cpu_has_vtag_icache ? */
63/* #define cpu_has_dc_aliases ? */
64/* #define cpu_has_ic_fills_f_dc ? */
65#define cpu_has_nofpuex 0
66/* #define cpu_has_64bits ? */
67/* #define cpu_has_64bit_zero_reg ? */
68/* #define cpu_has_inclusive_pcaches ? */
69#define cpu_icache_snoops_remote_store 1
70#endif
71
72#endif /* __ASM_MACH_MIPS_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-sead3/irq.h b/arch/mips/include/asm/mach-sead3/irq.h
new file mode 100644
index 000000000000..652ea4c38cda
--- /dev/null
+++ b/arch/mips/include/asm/mach-sead3/irq.h
@@ -0,0 +1,9 @@
1#ifndef __ASM_MACH_MIPS_IRQ_H
2#define __ASM_MACH_MIPS_IRQ_H
3
4#define NR_IRQS 256
5
6
7#include_next <irq.h>
8
9#endif /* __ASM_MACH_MIPS_IRQ_H */
diff --git a/arch/mips/include/asm/mach-sead3/kernel-entry-init.h b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h
new file mode 100644
index 000000000000..3dfbd8e7947f
--- /dev/null
+++ b/arch/mips/include/asm/mach-sead3/kernel-entry-init.h
@@ -0,0 +1,52 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Chris Dearman (chris@mips.com)
7 * Copyright (C) 2007 Mips Technologies, Inc.
8 */
9#ifndef __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
10#define __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H
11
12 .macro kernel_entry_setup
13#ifdef CONFIG_MIPS_MT_SMTC
14 mfc0 t0, CP0_CONFIG
15 bgez t0, 9f
16 mfc0 t0, CP0_CONFIG, 1
17 bgez t0, 9f
18 mfc0 t0, CP0_CONFIG, 2
19 bgez t0, 9f
20 mfc0 t0, CP0_CONFIG, 3
21 and t0, 1<<2
22 bnez t0, 0f
239 :
24 /* Assume we came from YAMON... */
25 PTR_LA v0, 0x9fc00534 /* YAMON print */
26 lw v0, (v0)
27 move a0, zero
28 PTR_LA a1, nonmt_processor
29 jal v0
30
31 PTR_LA v0, 0x9fc00520 /* YAMON exit */
32 lw v0, (v0)
33 li a0, 1
34 jal v0
35
361 : b 1b
37
38 __INITDATA
39nonmt_processor :
40 .asciz "SMTC kernel requires the MT ASE to run\n"
41 __FINIT
420 :
43#endif
44 .endm
45
46/*
47 * Do SMP slave processor setup necessary before we can safely execute C code.
48 */
49 .macro smp_slave_setup
50 .endm
51
52#endif /* __ASM_MACH_MIPS_KERNEL_ENTRY_INIT_H */
diff --git a/arch/mips/include/asm/mach-sead3/war.h b/arch/mips/include/asm/mach-sead3/war.h
new file mode 100644
index 000000000000..7c6931d5f45f
--- /dev/null
+++ b/arch/mips/include/asm/mach-sead3/war.h
@@ -0,0 +1,25 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
7 */
8#ifndef __ASM_MIPS_MACH_MIPS_WAR_H
9#define __ASM_MIPS_MACH_MIPS_WAR_H
10
11#define R4600_V1_INDEX_ICACHEOP_WAR 0
12#define R4600_V1_HIT_CACHEOP_WAR 0
13#define R4600_V2_HIT_CACHEOP_WAR 0
14#define R5432_CP0_INTERRUPT_WAR 0
15#define BCM1250_M3_WAR 0
16#define SIBYTE_1956_WAR 0
17#define MIPS4K_ICACHE_REFILL_WAR 1
18#define MIPS_CACHE_SYNC_WAR 1
19#define TX49XX_ICACHE_INDEX_INV_WAR 0
20#define RM9000_CDEX_SMP_WAR 0
21#define ICACHE_REFILLS_WORKAROUND_WAR 1
22#define R10000_LLSC_WAR 0
23#define MIPS34K_MISSED_ITLB_WAR 0
24
25#endif /* __ASM_MIPS_MACH_MIPS_WAR_H */
diff --git a/arch/mips/include/asm/mips-boards/maltaint.h b/arch/mips/include/asm/mips-boards/maltaint.h
index 5447d9fc4219..669244815753 100644
--- a/arch/mips/include/asm/mips-boards/maltaint.h
+++ b/arch/mips/include/asm/mips-boards/maltaint.h
@@ -1,31 +1,16 @@
1/* 1/*
2 * Carsten Langgaard, carstenl@mips.com 2 * This file is subject to the terms and conditions of the GNU General Public
3 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. 3 * License. See the file "COPYING" in the main directory of this archive
4 * 4 * for more details.
5 * ########################################################################
6 *
7 * This program is free software; you can distribute it and/or modify it
8 * under the terms of the GNU General Public License (Version 2) as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 *
20 * ########################################################################
21 *
22 * Defines for the Malta interrupt controller.
23 * 5 *
6 * Copyright (C) 2000,2012 MIPS Technologies, Inc. All rights reserved.
7 * Carsten Langgaard <carstenl@mips.com>
8 * Steven J. Hill <sjhill@mips.com>
24 */ 9 */
25#ifndef _MIPS_MALTAINT_H 10#ifndef _MIPS_MALTAINT_H
26#define _MIPS_MALTAINT_H 11#define _MIPS_MALTAINT_H
27 12
28#include <irq.h> 13#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
29 14
30/* 15/*
31 * Interrupts 0..15 are used for Malta ISA compatible interrupts 16 * Interrupts 0..15 are used for Malta ISA compatible interrupts
@@ -78,26 +63,6 @@
78#define MSC01E_INT_PERFCTR 10 63#define MSC01E_INT_PERFCTR 10
79#define MSC01E_INT_CPUCTR 11 64#define MSC01E_INT_CPUCTR 11
80 65
81/* GIC's Nomenclature for Core Interrupt Pins on the Malta */
82#define GIC_CPU_INT0 0 /* Core Interrupt 2 */
83#define GIC_CPU_INT1 1 /* . */
84#define GIC_CPU_INT2 2 /* . */
85#define GIC_CPU_INT3 3 /* . */
86#define GIC_CPU_INT4 4 /* . */
87#define GIC_CPU_INT5 5 /* Core Interrupt 5 */
88
89/* MALTA GIC local interrupts */
90#define GIC_INT_TMR (GIC_CPU_INT5)
91#define GIC_INT_PERFCTR (GIC_CPU_INT5)
92
93/* GIC constants */
94/* Add 2 to convert non-eic hw int # to eic vector # */
95#define GIC_CPU_TO_VEC_OFFSET (2)
96/* If we map an intr to pin X, GIC will actually generate vector X+1 */
97#define GIC_PIN_TO_VEC_OFFSET (1)
98
99#define GIC_EXT_INTR(x) x
100
101/* External Interrupts used for IPI */ 66/* External Interrupts used for IPI */
102#define GIC_IPI_EXT_INTR_RESCHED_VPE0 16 67#define GIC_IPI_EXT_INTR_RESCHED_VPE0 16
103#define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17 68#define GIC_IPI_EXT_INTR_CALLFNC_VPE0 17
@@ -108,10 +73,4 @@
108#define GIC_IPI_EXT_INTR_RESCHED_VPE3 22 73#define GIC_IPI_EXT_INTR_RESCHED_VPE3 22
109#define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23 74#define GIC_IPI_EXT_INTR_CALLFNC_VPE3 23
110 75
111#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8)
112
113#ifndef __ASSEMBLY__
114extern void maltaint_init(void);
115#endif
116
117#endif /* !(_MIPS_MALTAINT_H) */ 76#endif /* !(_MIPS_MALTAINT_H) */
diff --git a/arch/mips/include/asm/mips-boards/sead3int.h b/arch/mips/include/asm/mips-boards/sead3int.h
new file mode 100644
index 000000000000..d634d9a807f6
--- /dev/null
+++ b/arch/mips/include/asm/mips-boards/sead3int.h
@@ -0,0 +1,19 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2000,2012 MIPS Technologies, Inc. All rights reserved.
7 * Douglas Leung <douglas@mips.com>
8 * Steven J. Hill <sjhill@mips.com>
9 */
10#ifndef _MIPS_SEAD3INT_H
11#define _MIPS_SEAD3INT_H
12
13/* SEAD-3 GIC address space definitions. */
14#define GIC_BASE_ADDR 0x1b1c0000
15#define GIC_ADDRSPACE_SZ (128 * 1024)
16
17#define MIPS_GIC_IRQ_BASE (MIPS_CPU_IRQ_BASE + 0)
18
19#endif /* !(_MIPS_SEAD3INT_H) */
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 4199dd3f8d54..528fda1e957c 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -597,6 +597,8 @@
597#define MIPS_CONF4_MMUEXTDEF (_ULCAST_(3) << 14) 597#define MIPS_CONF4_MMUEXTDEF (_ULCAST_(3) << 14)
598#define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14) 598#define MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT (_ULCAST_(1) << 14)
599 599
600#define MIPS_CONF6_SYND (_ULCAST_(1) << 13)
601
600#define MIPS_CONF7_WII (_ULCAST_(1) << 31) 602#define MIPS_CONF7_WII (_ULCAST_(1) << 31)
601 603
602#define MIPS_CONF7_RPS (_ULCAST_(1) << 2) 604#define MIPS_CONF7_RPS (_ULCAST_(1) << 2)
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index 3d9f75f7ffc9..7e0bf17c9324 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -90,6 +90,8 @@ Ip_u2u1u3(_dsrl);
90Ip_u2u1u3(_dsrl32); 90Ip_u2u1u3(_dsrl32);
91Ip_u3u1u2(_dsubu); 91Ip_u3u1u2(_dsubu);
92Ip_0(_eret); 92Ip_0(_eret);
93Ip_u2u1msbu3(_ext);
94Ip_u2u1msbu3(_ins);
93Ip_u1(_j); 95Ip_u1(_j);
94Ip_u1(_jal); 96Ip_u1(_jal);
95Ip_u1(_jr); 97Ip_u1(_jr);
diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c
index 51095dd9599d..75323925e537 100644
--- a/arch/mips/kernel/cevt-r4k.c
+++ b/arch/mips/kernel/cevt-r4k.c
@@ -15,6 +15,7 @@
15#include <asm/smtc_ipi.h> 15#include <asm/smtc_ipi.h>
16#include <asm/time.h> 16#include <asm/time.h>
17#include <asm/cevt-r4k.h> 17#include <asm/cevt-r4k.h>
18#include <asm/gic.h>
18 19
19/* 20/*
20 * The SMTC Kernel for the 34K, 1004K, et. al. replaces several 21 * The SMTC Kernel for the 34K, 1004K, et. al. replaces several
@@ -98,6 +99,10 @@ void mips_event_handler(struct clock_event_device *dev)
98 */ 99 */
99static int c0_compare_int_pending(void) 100static int c0_compare_int_pending(void)
100{ 101{
102#ifdef CONFIG_IRQ_GIC
103 if (cpu_has_veic)
104 return gic_get_timer_pending();
105#endif
101 return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP); 106 return (read_c0_cause() >> cp0_compare_irq_shift) & (1ul << CAUSEB_IP);
102} 107}
103 108
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 0beb75fb3980..bc58bd10a607 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -861,6 +861,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
861 c->cputype = CPU_1004K; 861 c->cputype = CPU_1004K;
862 __cpu_name[cpu] = "MIPS 1004Kc"; 862 __cpu_name[cpu] = "MIPS 1004Kc";
863 break; 863 break;
864 case PRID_IMP_1074K:
865 c->cputype = CPU_74K;
866 __cpu_name[cpu] = "MIPS 1074Kc";
867 break;
864 } 868 }
865 869
866 spram_config(); 870 spram_config();
diff --git a/arch/mips/kernel/irq-gic.c b/arch/mips/kernel/irq-gic.c
index 0c527f652196..485e6a961b31 100644
--- a/arch/mips/kernel/irq-gic.c
+++ b/arch/mips/kernel/irq-gic.c
@@ -1,5 +1,11 @@
1#undef DEBUG 1/*
2 2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2008 Ralf Baechle (ralf@linux-mips.org)
7 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
8 */
3#include <linux/bitmap.h> 9#include <linux/bitmap.h>
4#include <linux/init.h> 10#include <linux/init.h>
5#include <linux/smp.h> 11#include <linux/smp.h>
@@ -7,33 +13,80 @@
7 13
8#include <asm/io.h> 14#include <asm/io.h>
9#include <asm/gic.h> 15#include <asm/gic.h>
16#include <asm/setup.h>
17#include <asm/traps.h>
10#include <asm/gcmpregs.h> 18#include <asm/gcmpregs.h>
11#include <linux/hardirq.h> 19#include <linux/hardirq.h>
12#include <asm-generic/bitops/find.h> 20#include <asm-generic/bitops/find.h>
13 21
22unsigned long _gic_base;
23unsigned int gic_irq_base;
24unsigned int gic_irq_flags[GIC_NUM_INTRS];
14 25
15static unsigned long _gic_base; 26/* The index into this array is the vector # of the interrupt. */
16static unsigned int _irqbase; 27struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];
17static unsigned int gic_irq_flags[GIC_NUM_INTRS];
18#define GIC_IRQ_FLAG_EDGE 0x0001
19 28
20struct gic_pcpu_mask pcpu_masks[NR_CPUS]; 29static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
21static struct gic_pending_regs pending_regs[NR_CPUS]; 30static struct gic_pending_regs pending_regs[NR_CPUS];
22static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; 31static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
23 32
33unsigned int gic_get_timer_pending(void)
34{
35 unsigned int vpe_pending;
36
37 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
38 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_PEND), vpe_pending);
39 return (vpe_pending & GIC_VPE_PEND_TIMER_MSK);
40}
41
42void gic_bind_eic_interrupt(int irq, int set)
43{
44 /* Convert irq vector # to hw int # */
45 irq -= GIC_PIN_TO_VEC_OFFSET;
46
47 /* Set irq to use shadow set */
48 GICWRITE(GIC_REG_ADDR(VPE_LOCAL, GIC_VPE_EIC_SS(irq)), set);
49}
50
24void gic_send_ipi(unsigned int intr) 51void gic_send_ipi(unsigned int intr)
25{ 52{
26 pr_debug("CPU%d: %s status %08x\n", smp_processor_id(), __func__,
27 read_c0_status());
28 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr); 53 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
29} 54}
30 55
31/* This is Malta specific and needs to be exported */ 56static void gic_eic_irq_dispatch(void)
57{
58 unsigned int cause = read_c0_cause();
59 int irq;
60
61 irq = (cause & ST0_IM) >> STATUSB_IP2;
62 if (irq == 0)
63 irq = -1;
64
65 if (irq >= 0)
66 do_IRQ(gic_irq_base + irq);
67 else
68 spurious_interrupt();
69}
70
32static void __init vpe_local_setup(unsigned int numvpes) 71static void __init vpe_local_setup(unsigned int numvpes)
33{ 72{
34 int i; 73 unsigned long timer_intr = GIC_INT_TMR;
35 unsigned long timer_interrupt = 5, perf_interrupt = 5; 74 unsigned long perf_intr = GIC_INT_PERFCTR;
36 unsigned int vpe_ctl; 75 unsigned int vpe_ctl;
76 int i;
77
78 if (cpu_has_veic) {
79 /*
80 * GIC timer interrupt -> CPU HW Int X (vector X+2) ->
81 * map to pin X+2-1 (since GIC adds 1)
82 */
83 timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
84 /*
85 * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) ->
86 * map to pin X+2-1 (since GIC adds 1)
87 */
88 perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
89 }
37 90
38 /* 91 /*
39 * Setup the default performance counter timer interrupts 92 * Setup the default performance counter timer interrupts
@@ -46,11 +99,20 @@ static void __init vpe_local_setup(unsigned int numvpes)
46 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl); 99 GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
47 if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK) 100 if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
48 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP), 101 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
49 GIC_MAP_TO_PIN_MSK | timer_interrupt); 102 GIC_MAP_TO_PIN_MSK | timer_intr);
103 if (cpu_has_veic) {
104 set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET,
105 gic_eic_irq_dispatch);
106 gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK;
107 }
50 108
51 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK) 109 if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
52 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP), 110 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
53 GIC_MAP_TO_PIN_MSK | perf_interrupt); 111 GIC_MAP_TO_PIN_MSK | perf_intr);
112 if (cpu_has_veic) {
113 set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch);
114 gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK;
115 }
54 } 116 }
55} 117}
56 118
@@ -80,51 +142,30 @@ unsigned int gic_get_int(void)
80 bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS); 142 bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
81 bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS); 143 bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
82 144
83 i = find_first_bit(pending, GIC_NUM_INTRS); 145 return find_first_bit(pending, GIC_NUM_INTRS);
84
85 pr_debug("CPU%d: %s pend=%d\n", smp_processor_id(), __func__, i);
86
87 return i;
88}
89
90static void gic_irq_ack(struct irq_data *d)
91{
92 unsigned int irq = d->irq - _irqbase;
93
94 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
95 GIC_CLR_INTR_MASK(irq);
96
97 if (gic_irq_flags[irq] & GIC_IRQ_FLAG_EDGE)
98 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
99} 146}
100 147
101static void gic_mask_irq(struct irq_data *d) 148static void gic_mask_irq(struct irq_data *d)
102{ 149{
103 unsigned int irq = d->irq - _irqbase; 150 GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
104 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
105 GIC_CLR_INTR_MASK(irq);
106} 151}
107 152
108static void gic_unmask_irq(struct irq_data *d) 153static void gic_unmask_irq(struct irq_data *d)
109{ 154{
110 unsigned int irq = d->irq - _irqbase; 155 GIC_SET_INTR_MASK(d->irq - gic_irq_base);
111 pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
112 GIC_SET_INTR_MASK(irq);
113} 156}
114 157
115#ifdef CONFIG_SMP 158#ifdef CONFIG_SMP
116
117static DEFINE_SPINLOCK(gic_lock); 159static DEFINE_SPINLOCK(gic_lock);
118 160
119static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, 161static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
120 bool force) 162 bool force)
121{ 163{
122 unsigned int irq = d->irq - _irqbase; 164 unsigned int irq = (d->irq - gic_irq_base);
123 cpumask_t tmp = CPU_MASK_NONE; 165 cpumask_t tmp = CPU_MASK_NONE;
124 unsigned long flags; 166 unsigned long flags;
125 int i; 167 int i;
126 168
127 pr_debug("%s(%d) called\n", __func__, irq);
128 cpumask_and(&tmp, cpumask, cpu_online_mask); 169 cpumask_and(&tmp, cpumask, cpu_online_mask);
129 if (cpus_empty(tmp)) 170 if (cpus_empty(tmp))
130 return -1; 171 return -1;
@@ -154,7 +195,7 @@ static struct irq_chip gic_irq_controller = {
154 .irq_mask = gic_mask_irq, 195 .irq_mask = gic_mask_irq,
155 .irq_mask_ack = gic_mask_irq, 196 .irq_mask_ack = gic_mask_irq,
156 .irq_unmask = gic_unmask_irq, 197 .irq_unmask = gic_unmask_irq,
157 .irq_eoi = gic_unmask_irq, 198 .irq_eoi = gic_finish_irq,
158#ifdef CONFIG_SMP 199#ifdef CONFIG_SMP
159 .irq_set_affinity = gic_set_affinity, 200 .irq_set_affinity = gic_set_affinity,
160#endif 201#endif
@@ -164,6 +205,8 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
164 unsigned int pin, unsigned int polarity, unsigned int trigtype, 205 unsigned int pin, unsigned int polarity, unsigned int trigtype,
165 unsigned int flags) 206 unsigned int flags)
166{ 207{
208 struct gic_shared_intr_map *map_ptr;
209
167 /* Setup Intr to Pin mapping */ 210 /* Setup Intr to Pin mapping */
168 if (pin & GIC_MAP_TO_NMI_MSK) { 211 if (pin & GIC_MAP_TO_NMI_MSK) {
169 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin); 212 GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
@@ -178,6 +221,14 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
178 GIC_MAP_TO_PIN_MSK | pin); 221 GIC_MAP_TO_PIN_MSK | pin);
179 /* Setup Intr to CPU mapping */ 222 /* Setup Intr to CPU mapping */
180 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu); 223 GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
224 if (cpu_has_veic) {
225 set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET,
226 gic_eic_irq_dispatch);
227 map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET];
228 if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR)
229 BUG();
230 map_ptr->intr_list[map_ptr->num_shared_intr++] = intr;
231 }
181 } 232 }
182 233
183 /* Setup Intr Polarity */ 234 /* Setup Intr Polarity */
@@ -191,26 +242,39 @@ static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
191 /* Initialise per-cpu Interrupt software masks */ 242 /* Initialise per-cpu Interrupt software masks */
192 if (flags & GIC_FLAG_IPI) 243 if (flags & GIC_FLAG_IPI)
193 set_bit(intr, pcpu_masks[cpu].pcpu_mask); 244 set_bit(intr, pcpu_masks[cpu].pcpu_mask);
194 if (flags & GIC_FLAG_TRANSPARENT) 245 if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
195 GIC_SET_INTR_MASK(intr); 246 GIC_SET_INTR_MASK(intr);
196 if (trigtype == GIC_TRIG_EDGE) 247 if (trigtype == GIC_TRIG_EDGE)
197 gic_irq_flags[intr] |= GIC_IRQ_FLAG_EDGE; 248 gic_irq_flags[intr] |= GIC_TRIG_EDGE;
198} 249}
199 250
200static void __init gic_basic_init(int numintrs, int numvpes, 251static void __init gic_basic_init(int numintrs, int numvpes,
201 struct gic_intr_map *intrmap, int mapsize) 252 struct gic_intr_map *intrmap, int mapsize)
202{ 253{
203 unsigned int i, cpu; 254 unsigned int i, cpu;
255 unsigned int pin_offset = 0;
256
257 board_bind_eic_interrupt = &gic_bind_eic_interrupt;
204 258
205 /* Setup defaults */ 259 /* Setup defaults */
206 for (i = 0; i < numintrs; i++) { 260 for (i = 0; i < numintrs; i++) {
207 GIC_SET_POLARITY(i, GIC_POL_POS); 261 GIC_SET_POLARITY(i, GIC_POL_POS);
208 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL); 262 GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
209 GIC_CLR_INTR_MASK(i); 263 GIC_CLR_INTR_MASK(i);
210 if (i < GIC_NUM_INTRS) 264 if (i < GIC_NUM_INTRS) {
211 gic_irq_flags[i] = 0; 265 gic_irq_flags[i] = 0;
266 gic_shared_intr_map[i].num_shared_intr = 0;
267 gic_shared_intr_map[i].local_intr_mask = 0;
268 }
212 } 269 }
213 270
271 /*
272 * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
273 * one because the GIC will add one (since 0=no intr).
274 */
275 if (cpu_has_veic)
276 pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
277
214 /* Setup specifics */ 278 /* Setup specifics */
215 for (i = 0; i < mapsize; i++) { 279 for (i = 0; i < mapsize; i++) {
216 cpu = intrmap[i].cpunum; 280 cpu = intrmap[i].cpunum;
@@ -220,16 +284,13 @@ static void __init gic_basic_init(int numintrs, int numvpes,
220 continue; 284 continue;
221 gic_setup_intr(i, 285 gic_setup_intr(i,
222 intrmap[i].cpunum, 286 intrmap[i].cpunum,
223 intrmap[i].pin, 287 intrmap[i].pin + pin_offset,
224 intrmap[i].polarity, 288 intrmap[i].polarity,
225 intrmap[i].trigtype, 289 intrmap[i].trigtype,
226 intrmap[i].flags); 290 intrmap[i].flags);
227 } 291 }
228 292
229 vpe_local_setup(numvpes); 293 vpe_local_setup(numvpes);
230
231 for (i = _irqbase; i < (_irqbase + numintrs); i++)
232 irq_set_chip(i, &gic_irq_controller);
233} 294}
234 295
235void __init gic_init(unsigned long gic_base_addr, 296void __init gic_init(unsigned long gic_base_addr,
@@ -242,7 +303,7 @@ void __init gic_init(unsigned long gic_base_addr,
242 303
243 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr, 304 _gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
244 gic_addrspace_size); 305 gic_addrspace_size);
245 _irqbase = irqbase; 306 gic_irq_base = irqbase;
246 307
247 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig); 308 GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
248 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >> 309 numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
@@ -251,8 +312,9 @@ void __init gic_init(unsigned long gic_base_addr,
251 312
252 numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >> 313 numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
253 GIC_SH_CONFIG_NUMVPES_SHF; 314 GIC_SH_CONFIG_NUMVPES_SHF;
254 315 numvpes = numvpes + 1;
255 pr_debug("%s called\n", __func__);
256 316
257 gic_basic_init(numintrs, numvpes, intr_map, intr_map_size); 317 gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
318
319 gic_platform_init(numintrs, &gic_irq_controller);
258} 320}
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index f092c265dc63..4c32ede464b5 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -786,6 +786,25 @@ static inline void rm7k_erratum31(void)
786 } 786 }
787} 787}
788 788
789static inline void alias_74k_erratum(struct cpuinfo_mips *c)
790{
791 /*
792 * Early versions of the 74K do not update the cache tags on a
793 * vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG
794 * aliases. In this case it is better to treat the cache as always
795 * having aliases.
796 */
797 if ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(2, 4, 0))
798 c->dcache.flags |= MIPS_CACHE_VTAG;
799 if ((c->processor_id & 0xff) == PRID_REV_ENCODE_332(2, 4, 0))
800 write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
801 if (((c->processor_id & 0xff00) == PRID_IMP_1074K) &&
802 ((c->processor_id & 0xff) <= PRID_REV_ENCODE_332(1, 1, 0))) {
803 c->dcache.flags |= MIPS_CACHE_VTAG;
804 write_c0_config6(read_c0_config6() | MIPS_CONF6_SYND);
805 }
806}
807
789static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way", 808static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way",
790 "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" 809 "3-way", "4-way", "5-way", "6-way", "7-way", "8-way"
791}; 810};
@@ -1056,6 +1075,8 @@ static void __cpuinit probe_pcache(void)
1056 case CPU_34K: 1075 case CPU_34K:
1057 case CPU_74K: 1076 case CPU_74K:
1058 case CPU_1004K: 1077 case CPU_1004K:
1078 if (c->cputype == CPU_74K)
1079 alias_74k_erratum(c);
1059 if ((read_c0_config7() & (1 << 16))) { 1080 if ((read_c0_config7() & (1 << 16))) {
1060 /* effectively physically indexed dcache, 1081 /* effectively physically indexed dcache,
1061 thus no virtual aliases. */ 1082 thus no virtual aliases. */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 1832f17e6be4..e09d49256908 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -449,8 +449,20 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
449 } 449 }
450 450
451 if (cpu_has_mips_r2) { 451 if (cpu_has_mips_r2) {
452 if (cpu_has_mips_r2_exec_hazard) 452 /*
453 * The architecture spec says an ehb is required here,
454 * but a number of cores do not have the hazard and
455 * using an ehb causes an expensive pipeline stall.
456 */
457 switch (current_cpu_type()) {
458 case CPU_M14KC:
459 case CPU_74K:
460 break;
461
462 default:
453 uasm_i_ehb(p); 463 uasm_i_ehb(p);
464 break;
465 }
454 tlbw(p); 466 tlbw(p);
455 return; 467 return;
456 } 468 }
@@ -921,6 +933,13 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
921#endif 933#endif
922 uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ 934 uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
923 uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr); 935 uasm_i_lw(p, ptr, uasm_rel_lo(pgdc), ptr);
936
937 if (cpu_has_mips_r2) {
938 uasm_i_ext(p, tmp, tmp, PGDIR_SHIFT, (32 - PGDIR_SHIFT));
939 uasm_i_ins(p, ptr, tmp, PGD_T_LOG2, (32 - PGDIR_SHIFT));
940 return;
941 }
942
924 uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */ 943 uasm_i_srl(p, tmp, tmp, PGDIR_SHIFT); /* get pgd only bits */
925 uasm_i_sll(p, tmp, tmp, PGD_T_LOG2); 944 uasm_i_sll(p, tmp, tmp, PGD_T_LOG2);
926 uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */ 945 uasm_i_addu(p, ptr, ptr, tmp); /* add in pgd offset */
@@ -956,6 +975,15 @@ static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx)
956 975
957static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) 976static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr)
958{ 977{
978 if (cpu_has_mips_r2) {
979 /* PTE ptr offset is obtained from BadVAddr */
980 UASM_i_MFC0(p, tmp, C0_BADVADDR);
981 UASM_i_LW(p, ptr, 0, ptr);
982 uasm_i_ext(p, tmp, tmp, PAGE_SHIFT+1, PGDIR_SHIFT-PAGE_SHIFT-1);
983 uasm_i_ins(p, ptr, tmp, PTE_T_LOG2+1, PGDIR_SHIFT-PAGE_SHIFT-1);
984 return;
985 }
986
959 /* 987 /*
960 * Bug workaround for the Nevada. It seems as if under certain 988 * Bug workaround for the Nevada. It seems as if under certain
961 * circumstances the move from cp0_context might produce a 989 * circumstances the move from cp0_context might produce a
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index 64a28e819064..39b891056227 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -63,11 +63,12 @@ enum opcode {
63 insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm, 63 insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm,
64 insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll, 64 insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll,
65 insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret, 65 insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret,
66 insn_j, insn_jal, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld, 66 insn_ext, insn_ins, insn_j, insn_jal, insn_jr, insn_ld, insn_ldx,
67 insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, insn_or, insn_ori, 67 insn_ll, insn_lld, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0,
68 insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll, 68 insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd,
69 insn_sra, insn_srl, insn_subu, insn_sw, insn_syscall, insn_tlbp, 69 insn_sd, insn_sll, insn_sra, insn_srl, insn_subu, insn_sw,
70 insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, 70 insn_syscall, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor,
71 insn_xori,
71}; 72};
72 73
73struct insn { 74struct insn {
@@ -115,6 +116,9 @@ static struct insn insn_table[] __uasminitdata = {
115 { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE }, 116 { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
116 { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, 117 { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
117 { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, 118 { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 },
119 { insn_ext, M(spec3_op, 0, 0, 0, 0, ext_op), RS | RT | RD | RE },
120 { insn_ins, M(spec3_op, 0, 0, 0, 0, ins_op), RS | RT | RD | RE },
121 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
118 { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, 122 { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
119 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM }, 123 { insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
120 { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, 124 { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
@@ -341,6 +345,13 @@ Ip_u2u1msbu3(op) \
341} \ 345} \
342UASM_EXPORT_SYMBOL(uasm_i##op); 346UASM_EXPORT_SYMBOL(uasm_i##op);
343 347
348#define I_u2u1msbdu3(op) \
349Ip_u2u1msbu3(op) \
350{ \
351 build_insn(buf, insn##op, b, a, d-1, c); \
352} \
353UASM_EXPORT_SYMBOL(uasm_i##op);
354
344#define I_u1u2(op) \ 355#define I_u1u2(op) \
345Ip_u1u2(op) \ 356Ip_u1u2(op) \
346{ \ 357{ \
@@ -394,6 +405,8 @@ I_u2u1u3(_drotr)
394I_u2u1u3(_drotr32) 405I_u2u1u3(_drotr32)
395I_u3u1u2(_dsubu) 406I_u3u1u2(_dsubu)
396I_0(_eret) 407I_0(_eret)
408I_u2u1msbdu3(_ext)
409I_u2u1msbu3(_ins)
397I_u1(_j) 410I_u1(_j)
398I_u1(_jal) 411I_u1(_jal)
399I_u1(_jr) 412I_u1(_jr)
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index fea823f18479..647b86383184 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -750,3 +750,37 @@ int malta_be_handler(struct pt_regs *regs, int is_fixup)
750 750
751 return retval; 751 return retval;
752} 752}
753
754void gic_enable_interrupt(int irq_vec)
755{
756 GIC_SET_INTR_MASK(irq_vec);
757}
758
759void gic_disable_interrupt(int irq_vec)
760{
761 GIC_CLR_INTR_MASK(irq_vec);
762}
763
764void gic_irq_ack(struct irq_data *d)
765{
766 int irq = (d->irq - gic_irq_base);
767
768 GIC_CLR_INTR_MASK(irq);
769
770 if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
771 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
772}
773
774void gic_finish_irq(struct irq_data *d)
775{
776 /* Enable interrupts. */
777 GIC_SET_INTR_MASK(d->irq - gic_irq_base);
778}
779
780void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
781{
782 int i;
783
784 for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
785 irq_set_chip(i, irq_controller);
786}
diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile
new file mode 100644
index 000000000000..626afeac4386
--- /dev/null
+++ b/arch/mips/mti-sead3/Makefile
@@ -0,0 +1,19 @@
1#
2# Carsten Langgaard, carstenl@mips.com
3# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4#
5# Copyright (C) 2008 Wind River Systems, Inc.
6# written by Ralf Baechle <ralf@linux-mips.org>
7#
8obj-y := sead3-lcd.o sead3-cmdline.o \
9 sead3-display.o sead3-init.o sead3-int.o \
10 sead3-mtd.o sead3-net.o \
11 sead3-memory.o sead3-platform.o \
12 sead3-reset.o sead3-setup.o sead3-time.o
13
14obj-y += sead3-i2c-dev.o sead3-i2c.o \
15 sead3-pic32-i2c-drv.o sead3-pic32-bus.o \
16 leds-sead3.o sead3-leds.o
17
18obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
19obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o
diff --git a/arch/mips/mti-sead3/Platform b/arch/mips/mti-sead3/Platform
new file mode 100644
index 000000000000..387092427145
--- /dev/null
+++ b/arch/mips/mti-sead3/Platform
@@ -0,0 +1,7 @@
1#
2# MIPS SEAD-3 board
3#
4platform-$(CONFIG_MIPS_SEAD3) += mti-sead3/
5cflags-$(CONFIG_MIPS_SEAD3) += -I$(srctree)/arch/mips/include/asm/mach-sead3
6load-$(CONFIG_MIPS_SEAD3) += 0xffffffff80100000
7all-$(CONFIG_MIPS_SEAD3) := $(COMPRESSION_FNAME).srec
diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c
new file mode 100644
index 000000000000..a95ac5985206
--- /dev/null
+++ b/arch/mips/mti-sead3/leds-sead3.c
@@ -0,0 +1,128 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/platform_device.h>
12#include <linux/leds.h>
13#include <linux/err.h>
14#include <linux/io.h>
15
16#define DRVNAME "sead3-led"
17
18static struct platform_device *pdev;
19
20static void sead3_pled_set(struct led_classdev *led_cdev,
21 enum led_brightness value)
22{
23 pr_debug("sead3_pled_set\n");
24 writel(value, (void __iomem *)0xBF000210); /* FIXME */
25}
26
27static void sead3_fled_set(struct led_classdev *led_cdev,
28 enum led_brightness value)
29{
30 pr_debug("sead3_fled_set\n");
31 writel(value, (void __iomem *)0xBF000218); /* FIXME */
32}
33
34static struct led_classdev sead3_pled = {
35 .name = "sead3::pled",
36 .brightness_set = sead3_pled_set,
37};
38
39static struct led_classdev sead3_fled = {
40 .name = "sead3::fled",
41 .brightness_set = sead3_fled_set,
42};
43
44#ifdef CONFIG_PM
45static int sead3_led_suspend(struct platform_device *dev,
46 pm_message_t state)
47{
48 led_classdev_suspend(&sead3_pled);
49 led_classdev_suspend(&sead3_fled);
50 return 0;
51}
52
53static int sead3_led_resume(struct platform_device *dev)
54{
55 led_classdev_resume(&sead3_pled);
56 led_classdev_resume(&sead3_fled);
57 return 0;
58}
59#else
60#define sead3_led_suspend NULL
61#define sead3_led_resume NULL
62#endif
63
64static int sead3_led_probe(struct platform_device *pdev)
65{
66 int ret;
67
68 ret = led_classdev_register(&pdev->dev, &sead3_pled);
69 if (ret < 0)
70 return ret;
71
72 ret = led_classdev_register(&pdev->dev, &sead3_fled);
73 if (ret < 0)
74 led_classdev_unregister(&sead3_pled);
75
76 return ret;
77}
78
79static int sead3_led_remove(struct platform_device *pdev)
80{
81 led_classdev_unregister(&sead3_pled);
82 led_classdev_unregister(&sead3_fled);
83 return 0;
84}
85
86static struct platform_driver sead3_led_driver = {
87 .probe = sead3_led_probe,
88 .remove = sead3_led_remove,
89 .suspend = sead3_led_suspend,
90 .resume = sead3_led_resume,
91 .driver = {
92 .name = DRVNAME,
93 .owner = THIS_MODULE,
94 },
95};
96
97static int __init sead3_led_init(void)
98{
99 int ret;
100
101 ret = platform_driver_register(&sead3_led_driver);
102 if (ret < 0)
103 goto out;
104
105 pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
106 if (IS_ERR(pdev)) {
107 ret = PTR_ERR(pdev);
108 platform_driver_unregister(&sead3_led_driver);
109 goto out;
110 }
111
112out:
113 return ret;
114}
115
116static void __exit sead3_led_exit(void)
117{
118 platform_device_unregister(pdev);
119 platform_driver_unregister(&sead3_led_driver);
120}
121
122module_init(sead3_led_init);
123module_exit(sead3_led_exit);
124
125MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
126MODULE_DESCRIPTION("SEAD3 LED driver");
127MODULE_LICENSE("GPL");
128
diff --git a/arch/mips/mti-sead3/sead3-cmdline.c b/arch/mips/mti-sead3/sead3-cmdline.c
new file mode 100644
index 000000000000..a2e6cec67f57
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-cmdline.c
@@ -0,0 +1,46 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/string.h>
10
11#include <asm/bootinfo.h>
12
13extern int prom_argc;
14extern int *_prom_argv;
15
16/*
17 * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
18 * This macro take care of sign extension.
19 */
20#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
21
22char * __init prom_getcmdline(void)
23{
24 return &(arcs_cmdline[0]);
25}
26
27void __init prom_init_cmdline(void)
28{
29 char *cp;
30 int actr;
31
32 actr = 1; /* Always ignore argv[0] */
33
34 cp = &(arcs_cmdline[0]);
35 while (actr < prom_argc) {
36 strcpy(cp, prom_argv(actr));
37 cp += strlen(prom_argv(actr));
38 *cp++ = ' ';
39 actr++;
40 }
41 if (cp != &(arcs_cmdline[0])) {
42 /* get rid of trailing space */
43 --cp;
44 *cp = '\0';
45 }
46}
diff --git a/arch/mips/mti-sead3/sead3-console.c b/arch/mips/mti-sead3/sead3-console.c
new file mode 100644
index 000000000000..b36739108a0f
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-console.c
@@ -0,0 +1,46 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/console.h>
10#include <linux/serial_reg.h>
11#include <linux/io.h>
12
13#define SEAD_UART1_REGS_BASE 0xbf000800 /* ttyS1 = DB9 port */
14#define SEAD_UART0_REGS_BASE 0xbf000900 /* ttyS0 = USB port */
15#define PORT(base_addr, offset) ((unsigned int __iomem *)(base_addr+(offset)*4))
16
17static char console_port = 1;
18
19static inline unsigned int serial_in(int offset, unsigned int base_addr)
20{
21 return __raw_readl(PORT(base_addr, offset)) & 0xff;
22}
23
24static inline void serial_out(int offset, int value, unsigned int base_addr)
25{
26 __raw_writel(value, PORT(base_addr, offset));
27}
28
29void __init prom_init_early_console(char port)
30{
31 console_port = port;
32}
33
34int prom_putchar(char c)
35{
36 unsigned int base_addr;
37
38 base_addr = console_port ? SEAD_UART1_REGS_BASE : SEAD_UART0_REGS_BASE;
39
40 while ((serial_in(UART_LSR, base_addr) & UART_LSR_THRE) == 0)
41 ;
42
43 serial_out(UART_TX, c, base_addr);
44
45 return 1;
46}
diff --git a/arch/mips/mti-sead3/sead3-display.c b/arch/mips/mti-sead3/sead3-display.c
new file mode 100644
index 000000000000..8308c7fc188a
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-display.c
@@ -0,0 +1,78 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/timer.h>
9#include <linux/io.h>
10#include <asm/mips-boards/generic.h>
11#include <asm/mips-boards/prom.h>
12
13static unsigned int display_count;
14static unsigned int max_display_count;
15
16#define LCD_DISPLAY_POS_BASE 0x1f000400
17#define DISPLAY_LCDINSTRUCTION (0*2)
18#define DISPLAY_LCDDATA (1*2)
19#define DISPLAY_CPLDSTATUS (2*2)
20#define DISPLAY_CPLDDATA (3*2)
21#define LCD_SETDDRAM 0x80
22#define LCD_IR_BF 0x80
23
24const char display_string[] = " LINUX ON SEAD3 ";
25
26static void scroll_display_message(unsigned long data);
27static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
28
29static void lcd_wait(unsigned int __iomem *display)
30{
31 /* Wait for CPLD state machine to become idle. */
32 do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
33
34 do {
35 __raw_readl(display + DISPLAY_LCDINSTRUCTION);
36
37 /* Wait for CPLD state machine to become idle. */
38 do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
39 } while (__raw_readl(display + DISPLAY_CPLDDATA) & LCD_IR_BF);
40}
41
42void mips_display_message(const char *str)
43{
44 static unsigned int __iomem *display;
45 char ch;
46 int i;
47
48 if (unlikely(display == NULL))
49 display = ioremap_nocache(LCD_DISPLAY_POS_BASE,
50 (8 * sizeof(int)));
51
52 for (i = 0; i < 16; i++) {
53 if (*str)
54 ch = *str++;
55 else
56 ch = ' ';
57 lcd_wait(display);
58 __raw_writel((LCD_SETDDRAM | i),
59 (display + DISPLAY_LCDINSTRUCTION));
60 lcd_wait(display);
61 __raw_writel(ch, display + DISPLAY_LCDDATA);
62 }
63}
64
65static void scroll_display_message(unsigned long data)
66{
67 mips_display_message(&display_string[display_count++]);
68 if (display_count == max_display_count)
69 display_count = 0;
70 mod_timer(&mips_scroll_timer, jiffies + HZ);
71}
72
73void mips_scroll_message(void)
74{
75 del_timer_sync(&mips_scroll_timer);
76 max_display_count = strlen(display_string) + 1 - 16;
77 mod_timer(&mips_scroll_timer, jiffies + 1);
78}
diff --git a/arch/mips/mti-sead3/sead3-ehci.c b/arch/mips/mti-sead3/sead3-ehci.c
new file mode 100644
index 000000000000..772fc056a92d
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-ehci.c
@@ -0,0 +1,47 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/irq.h>
10#include <linux/dma-mapping.h>
11#include <linux/platform_device.h>
12
13struct resource ehci_resources[] = {
14 {
15 .start = 0x1b200000,
16 .end = 0x1b200fff,
17 .flags = IORESOURCE_MEM
18 },
19 {
20 .start = MIPS_CPU_IRQ_BASE + 2,
21 .flags = IORESOURCE_IRQ
22 }
23};
24
25u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32);
26
27static struct platform_device ehci_device = {
28 .name = "sead3-ehci",
29 .id = 0,
30 .dev = {
31 .dma_mask = &sead3_usbdev_dma_mask,
32 .coherent_dma_mask = DMA_BIT_MASK(32)
33 },
34 .num_resources = ARRAY_SIZE(ehci_resources),
35 .resource = ehci_resources
36};
37
38static int __init ehci_init(void)
39{
40 return platform_device_register(&ehci_device);
41}
42
43module_init(ehci_init);
44
45MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
46MODULE_LICENSE("GPL");
47MODULE_DESCRIPTION("EHCI probe driver for SEAD3");
diff --git a/arch/mips/mti-sead3/sead3-i2c-dev.c b/arch/mips/mti-sead3/sead3-i2c-dev.c
new file mode 100644
index 000000000000..eca0b53a71dd
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-i2c-dev.c
@@ -0,0 +1,33 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/i2c.h>
10
11static struct i2c_board_info __initdata sead3_i2c_devices[] = {
12 {
13 I2C_BOARD_INFO("adt7476", 0x2c),
14 .irq = 0,
15 },
16 {
17 I2C_BOARD_INFO("m41t80", 0x68),
18 .irq = 0,
19 },
20};
21
22static int __init sead3_i2c_init(void)
23{
24 int err;
25
26 err = i2c_register_board_info(0, sead3_i2c_devices,
27 ARRAY_SIZE(sead3_i2c_devices));
28 if (err < 0)
29 pr_err("sead3-i2c-dev: cannot register board I2C devices\n");
30 return err;
31}
32
33arch_initcall(sead3_i2c_init);
diff --git a/arch/mips/mti-sead3/sead3-i2c-drv.c b/arch/mips/mti-sead3/sead3-i2c-drv.c
new file mode 100644
index 000000000000..0375ee66bca3
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-i2c-drv.c
@@ -0,0 +1,405 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/module.h>
10#include <linux/slab.h>
11#include <linux/delay.h>
12#include <linux/i2c.h>
13#include <linux/platform_device.h>
14
15#define PIC32_I2CxCON 0x0000
16#define PIC32_I2CCON_ON (1<<15)
17#define PIC32_I2CCON_ACKDT (1<<5)
18#define PIC32_I2CCON_ACKEN (1<<4)
19#define PIC32_I2CCON_RCEN (1<<3)
20#define PIC32_I2CCON_PEN (1<<2)
21#define PIC32_I2CCON_RSEN (1<<1)
22#define PIC32_I2CCON_SEN (1<<0)
23#define PIC32_I2CxCONCLR 0x0004
24#define PIC32_I2CxCONSET 0x0008
25#define PIC32_I2CxSTAT 0x0010
26#define PIC32_I2CxSTATCLR 0x0014
27#define PIC32_I2CSTAT_ACKSTAT (1<<15)
28#define PIC32_I2CSTAT_TRSTAT (1<<14)
29#define PIC32_I2CSTAT_BCL (1<<10)
30#define PIC32_I2CSTAT_IWCOL (1<<7)
31#define PIC32_I2CSTAT_I2COV (1<<6)
32#define PIC32_I2CxBRG 0x0040
33#define PIC32_I2CxTRN 0x0050
34#define PIC32_I2CxRCV 0x0060
35
36static DEFINE_SPINLOCK(pic32_bus_lock);
37
38static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
39static void __iomem *bus_status = (void __iomem *)0xbf000060;
40
41#define DELAY() udelay(100)
42
43static inline unsigned int ioready(void)
44{
45 return readl(bus_status) & 1;
46}
47
48static inline void wait_ioready(void)
49{
50 do { } while (!ioready());
51}
52
53static inline void wait_ioclear(void)
54{
55 do { } while (ioready());
56}
57
58static inline void check_ioclear(void)
59{
60 if (ioready()) {
61 do {
62 (void) readl(bus_xfer);
63 DELAY();
64 } while (ioready());
65 }
66}
67
68static u32 pic32_bus_readl(u32 reg)
69{
70 unsigned long flags;
71 u32 status, val;
72
73 spin_lock_irqsave(&pic32_bus_lock, flags);
74
75 check_ioclear();
76 writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer);
77 DELAY();
78 wait_ioready();
79 status = readl(bus_xfer);
80 DELAY();
81 val = readl(bus_xfer);
82 wait_ioclear();
83
84 spin_unlock_irqrestore(&pic32_bus_lock, flags);
85
86 return val;
87}
88
89static void pic32_bus_writel(u32 val, u32 reg)
90{
91 unsigned long flags;
92 u32 status;
93
94 spin_lock_irqsave(&pic32_bus_lock, flags);
95
96 check_ioclear();
97 writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer);
98 DELAY();
99 writel(val, bus_xfer);
100 DELAY();
101 wait_ioready();
102 status = readl(bus_xfer);
103 wait_ioclear();
104
105 spin_unlock_irqrestore(&pic32_bus_lock, flags);
106}
107
108struct pic32_i2c_platform_data {
109 u32 base;
110 struct i2c_adapter adap;
111 u32 xfer_timeout;
112 u32 ack_timeout;
113 u32 ctl_timeout;
114};
115
116static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap)
117{
118 pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
119}
120
121static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap)
122{
123 pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
124}
125
126static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap)
127{
128 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
129 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
130}
131
132static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap)
133{
134 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
135 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
136}
137
138static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap)
139{
140 int i;
141
142 for (i = 0; i < adap->ctl_timeout; i++) {
143 if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
144 (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN |
145 PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN |
146 PIC32_I2CCON_SEN)) == 0) &&
147 ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
148 (PIC32_I2CSTAT_TRSTAT)) == 0))
149 return 0;
150 udelay(1);
151 }
152 return -ETIMEDOUT;
153}
154
155static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap,
156 u32 byte)
157{
158 pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
159 return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
160 PIC32_I2CSTAT_IWCOL;
161}
162
163static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap)
164{
165 pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
166 while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN)
167 ;
168 pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
169 return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
170}
171
172static int pic32_i2c_address(struct pic32_i2c_platform_data *adap,
173 unsigned int addr, int rd)
174{
175 pic32_i2c_idle(adap);
176 pic32_i2c_start(adap);
177 pic32_i2c_idle(adap);
178
179 addr <<= 1;
180 if (rd)
181 addr |= 1;
182
183 if (pic32_i2c_master_write(adap, addr))
184 return -EIO;
185 pic32_i2c_idle(adap);
186 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
187 PIC32_I2CSTAT_ACKSTAT)
188 return -EIO;
189 return 0;
190}
191
192static int sead3_i2c_read(struct pic32_i2c_platform_data *adap,
193 unsigned char *buf, unsigned int len)
194{
195 u32 data;
196 int i;
197
198 i = 0;
199 while (i < len) {
200 data = pic32_i2c_master_read(adap);
201 buf[i++] = data;
202 if (i < len)
203 pic32_i2c_ack(adap);
204 else
205 pic32_i2c_nack(adap);
206 }
207
208 pic32_i2c_stop(adap);
209 pic32_i2c_idle(adap);
210 return 0;
211}
212
213static int sead3_i2c_write(struct pic32_i2c_platform_data *adap,
214 unsigned char *buf, unsigned int len)
215{
216 int i;
217 u32 data;
218
219 i = 0;
220 while (i < len) {
221 data = buf[i];
222 if (pic32_i2c_master_write(adap, data))
223 return -EIO;
224 pic32_i2c_idle(adap);
225 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
226 PIC32_I2CSTAT_ACKSTAT)
227 return -EIO;
228 i++;
229 }
230
231 pic32_i2c_stop(adap);
232 pic32_i2c_idle(adap);
233 return 0;
234}
235
236static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap,
237 struct i2c_msg *msgs, int num)
238{
239 struct pic32_i2c_platform_data *adap = i2c_adap->algo_data;
240 struct i2c_msg *p;
241 int i, err = 0;
242
243 for (i = 0; i < num; i++) {
244#define __BUFSIZE 80
245 int ii;
246 static char buf[__BUFSIZE];
247 char *b = buf;
248
249 p = &msgs[i];
250 b += sprintf(buf, " [%d bytes]", p->len);
251 if ((p->flags & I2C_M_RD) == 0) {
252 for (ii = 0; ii < p->len; ii++) {
253 if (b < &buf[__BUFSIZE-4]) {
254 b += sprintf(b, " %02x", p->buf[ii]);
255 } else {
256 strcat(b, "...");
257 break;
258 }
259 }
260 }
261 }
262
263 for (i = 0; !err && i < num; i++) {
264 p = &msgs[i];
265 err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD);
266 if (err || !p->len)
267 continue;
268 if (p->flags & I2C_M_RD)
269 err = sead3_i2c_read(adap, p->buf, p->len);
270 else
271 err = sead3_i2c_write(adap, p->buf, p->len);
272 }
273
274 /* Return the number of messages processed, or the error code. */
275 if (err == 0)
276 err = num;
277
278 return err;
279}
280
281static u32 sead3_pic32_platform_func(struct i2c_adapter *adap)
282{
283 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
284}
285
286static const struct i2c_algorithm sead3_platform_algo = {
287 .master_xfer = sead3_pic32_platform_xfer,
288 .functionality = sead3_pic32_platform_func,
289};
290
291static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv)
292{
293 pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
294 pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
295 pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET);
296 pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL,
297 priv->base + PIC32_I2CxSTATCLR);
298}
299
300static int __devinit sead3_i2c_platform_probe(struct platform_device *pdev)
301{
302 struct pic32_i2c_platform_data *priv;
303 struct resource *r;
304 int ret;
305
306 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
307 if (!r) {
308 ret = -ENODEV;
309 goto out;
310 }
311
312 priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL);
313 if (!priv) {
314 ret = -ENOMEM;
315 goto out;
316 }
317
318 priv->base = r->start;
319 if (!priv->base) {
320 ret = -EBUSY;
321 goto out_mem;
322 }
323
324 priv->xfer_timeout = 200;
325 priv->ack_timeout = 200;
326 priv->ctl_timeout = 200;
327
328 priv->adap.nr = pdev->id;
329 priv->adap.algo = &sead3_platform_algo;
330 priv->adap.algo_data = priv;
331 priv->adap.dev.parent = &pdev->dev;
332 strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name));
333
334 sead3_i2c_platform_setup(priv);
335
336 ret = i2c_add_numbered_adapter(&priv->adap);
337 if (ret == 0) {
338 platform_set_drvdata(pdev, priv);
339 return 0;
340 }
341
342out_mem:
343 kfree(priv);
344out:
345 return ret;
346}
347
348static int __devexit sead3_i2c_platform_remove(struct platform_device *pdev)
349{
350 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
351
352 platform_set_drvdata(pdev, NULL);
353 i2c_del_adapter(&priv->adap);
354 kfree(priv);
355 return 0;
356}
357
358#ifdef CONFIG_PM
359static int sead3_i2c_platform_suspend(struct platform_device *pdev,
360 pm_message_t state)
361{
362 dev_dbg(&pdev->dev, "i2c_platform_disable\n");
363 return 0;
364}
365
366static int sead3_i2c_platform_resume(struct platform_device *pdev)
367{
368 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
369
370 dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n");
371 sead3_i2c_platform_setup(priv);
372
373 return 0;
374}
375#else
376#define sead3_i2c_platform_suspend NULL
377#define sead3_i2c_platform_resume NULL
378#endif
379
380static struct platform_driver sead3_i2c_platform_driver = {
381 .driver = {
382 .name = "sead3-i2c",
383 .owner = THIS_MODULE,
384 },
385 .probe = sead3_i2c_platform_probe,
386 .remove = __devexit_p(sead3_i2c_platform_remove),
387 .suspend = sead3_i2c_platform_suspend,
388 .resume = sead3_i2c_platform_resume,
389};
390
391static int __init sead3_i2c_platform_init(void)
392{
393 return platform_driver_register(&sead3_i2c_platform_driver);
394}
395module_init(sead3_i2c_platform_init);
396
397static void __exit sead3_i2c_platform_exit(void)
398{
399 platform_driver_unregister(&sead3_i2c_platform_driver);
400}
401module_exit(sead3_i2c_platform_exit);
402
403MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
404MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver");
405MODULE_LICENSE("GPL");
diff --git a/arch/mips/mti-sead3/sead3-i2c.c b/arch/mips/mti-sead3/sead3-i2c.c
new file mode 100644
index 000000000000..f70d5fc58ef5
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-i2c.c
@@ -0,0 +1,37 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/platform_device.h>
11#include <irq.h>
12
13struct resource sead3_i2c_resources[] = {
14 {
15 .start = 0x805200,
16 .end = 0x8053ff,
17 .flags = IORESOURCE_MEM,
18 },
19};
20
21static struct platform_device sead3_i2c_device = {
22 .name = "sead3-i2c",
23 .id = 0,
24 .num_resources = ARRAY_SIZE(sead3_i2c_resources),
25 .resource = sead3_i2c_resources,
26};
27
28static int __init sead3_i2c_init(void)
29{
30 return platform_device_register(&sead3_i2c_device);
31}
32
33module_init(sead3_i2c_init);
34
35MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
36MODULE_LICENSE("GPL");
37MODULE_DESCRIPTION("I2C probe driver for SEAD3");
diff --git a/arch/mips/mti-sead3/sead3-init.c b/arch/mips/mti-sead3/sead3-init.c
new file mode 100644
index 000000000000..a958cad6fff6
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-init.c
@@ -0,0 +1,91 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/io.h>
10
11#include <asm/bootinfo.h>
12#include <asm/cacheflush.h>
13#include <asm/traps.h>
14#include <asm/mips-boards/generic.h>
15#include <asm/mips-boards/prom.h>
16
17extern void prom_init_early_console(char port);
18
19extern char except_vec_nmi;
20extern char except_vec_ejtag_debug;
21
22int prom_argc;
23int *_prom_argv, *_prom_envp;
24
25#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
26
27char *prom_getenv(char *envname)
28{
29 /*
30 * Return a pointer to the given environment variable.
31 * In 64-bit mode: we're using 64-bit pointers, but all pointers
32 * in the PROM structures are only 32-bit, so we need some
33 * workarounds, if we are running in 64-bit mode.
34 */
35 int i, index = 0;
36
37 i = strlen(envname);
38
39 while (prom_envp(index)) {
40 if (strncmp(envname, prom_envp(index), i) == 0)
41 return prom_envp(index+1);
42 index += 2;
43 }
44
45 return NULL;
46}
47
48static void __init mips_nmi_setup(void)
49{
50 void *base;
51
52 base = cpu_has_veic ?
53 (void *)(CAC_BASE + 0xa80) :
54 (void *)(CAC_BASE + 0x380);
55 memcpy(base, &except_vec_nmi, 0x80);
56 flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
57}
58
59static void __init mips_ejtag_setup(void)
60{
61 void *base;
62
63 base = cpu_has_veic ?
64 (void *)(CAC_BASE + 0xa00) :
65 (void *)(CAC_BASE + 0x300);
66 memcpy(base, &except_vec_ejtag_debug, 0x80);
67 flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
68}
69
70void __init prom_init(void)
71{
72 prom_argc = fw_arg0;
73 _prom_argv = (int *) fw_arg1;
74 _prom_envp = (int *) fw_arg2;
75
76 board_nmi_handler_setup = mips_nmi_setup;
77 board_ejtag_handler_setup = mips_ejtag_setup;
78
79 prom_init_cmdline();
80 prom_meminit();
81#ifdef CONFIG_EARLY_PRINTK
82 if ((strstr(prom_getcmdline(), "console=ttyS0")) != NULL)
83 prom_init_early_console(0);
84 else if ((strstr(prom_getcmdline(), "console=ttyS1")) != NULL)
85 prom_init_early_console(1);
86#endif
87#ifdef CONFIG_SERIAL_8250_CONSOLE
88 if ((strstr(prom_getcmdline(), "console=")) == NULL)
89 strcat(prom_getcmdline(), " console=ttyS0,38400n8r");
90#endif
91}
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
new file mode 100644
index 000000000000..e26e08274fc5
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-int.c
@@ -0,0 +1,158 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/irq.h>
10#include <linux/io.h>
11
12#include <asm/gic.h>
13#include <asm/irq_cpu.h>
14#include <asm/setup.h>
15
16#include <asm/mips-boards/sead3int.h>
17
18#define SEAD_CONFIG_GIC_PRESENT_SHF 1
19#define SEAD_CONFIG_GIC_PRESENT_MSK (1 << SEAD_CONFIG_GIC_PRESENT_SHF)
20#define SEAD_CONFIG_BASE 0x1b100110
21#define SEAD_CONFIG_SIZE 4
22
23int gic_present;
24static unsigned long sead3_config_reg;
25
26/*
27 * This table defines the setup for each external GIC interrupt. It is
28 * indexed by interrupt number.
29 */
30#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
31static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
32 { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
33 { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
34 { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
35 { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
36 { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
37 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
38 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
39 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
40 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
41 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
42 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
43 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
44 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
45 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
46 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
47 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
48};
49
50asmlinkage void plat_irq_dispatch(void)
51{
52 unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
53 int irq;
54
55 irq = (fls(pending) - CAUSEB_IP - 1);
56 if (irq >= 0)
57 do_IRQ(MIPS_CPU_IRQ_BASE + irq);
58 else
59 spurious_interrupt();
60}
61
62void __init arch_init_irq(void)
63{
64 int i;
65
66 if (!cpu_has_veic) {
67 mips_cpu_irq_init();
68
69 if (cpu_has_vint) {
70 /* install generic handler */
71 for (i = 0; i < 8; i++)
72 set_vi_handler(i, plat_irq_dispatch);
73 }
74 }
75
76 sead3_config_reg = (unsigned long)ioremap_nocache(SEAD_CONFIG_BASE,
77 SEAD_CONFIG_SIZE);
78 gic_present = (REG32(sead3_config_reg) & SEAD_CONFIG_GIC_PRESENT_MSK) >>
79 SEAD_CONFIG_GIC_PRESENT_SHF;
80 pr_info("GIC: %spresent\n", (gic_present) ? "" : "not ");
81 pr_info("EIC: %s\n",
82 (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off");
83
84 if (gic_present)
85 gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
86 ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
87}
88
89void gic_enable_interrupt(int irq_vec)
90{
91 unsigned int i, irq_source;
92
93 /* enable all the interrupts associated with this vector */
94 for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
95 irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
96 GIC_SET_INTR_MASK(irq_source);
97 }
98 /* enable all local interrupts associated with this vector */
99 if (gic_shared_intr_map[irq_vec].local_intr_mask) {
100 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
101 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SMASK),
102 gic_shared_intr_map[irq_vec].local_intr_mask);
103 }
104}
105
106void gic_disable_interrupt(int irq_vec)
107{
108 unsigned int i, irq_source;
109
110 /* disable all the interrupts associated with this vector */
111 for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
112 irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
113 GIC_CLR_INTR_MASK(irq_source);
114 }
115 /* disable all local interrupts associated with this vector */
116 if (gic_shared_intr_map[irq_vec].local_intr_mask) {
117 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
118 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK),
119 gic_shared_intr_map[irq_vec].local_intr_mask);
120 }
121}
122
123void gic_irq_ack(struct irq_data *d)
124{
125 GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
126}
127
128void gic_finish_irq(struct irq_data *d)
129{
130 unsigned int irq = (d->irq - gic_irq_base);
131 unsigned int i, irq_source;
132
133 /* Clear edge detectors. */
134 for (i = 0; i < gic_shared_intr_map[irq].num_shared_intr; i++) {
135 irq_source = gic_shared_intr_map[irq].intr_list[i];
136 if (gic_irq_flags[irq_source] & GIC_TRIG_EDGE)
137 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq_source);
138 }
139
140 /* Enable interrupts. */
141 GIC_SET_INTR_MASK(irq);
142}
143
144void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
145{
146 int i;
147
148 /*
149 * For non-EIC mode, we want to setup the GIC in pass-through
150 * mode, as if the GIC didn't exist. Do not map any interrupts
151 * for an external interrupt controller.
152 */
153 if (!cpu_has_veic)
154 return;
155
156 for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
157 irq_set_chip_and_handler(i, irq_controller, handle_percpu_irq);
158}
diff --git a/arch/mips/mti-sead3/sead3-lcd.c b/arch/mips/mti-sead3/sead3-lcd.c
new file mode 100644
index 000000000000..10b10ed21f77
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-lcd.c
@@ -0,0 +1,43 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/platform_device.h>
10
11static struct resource __initdata sead3_lcd_resource = {
12 .start = 0x1f000400,
13 .end = 0x1f00041f,
14 .flags = IORESOURCE_MEM,
15};
16
17static __init int sead3_lcd_add(void)
18{
19 struct platform_device *pdev;
20 int retval;
21
22 /* SEAD-3 and Cobalt platforms use same display type. */
23 pdev = platform_device_alloc("cobalt-lcd", -1);
24 if (!pdev)
25 return -ENOMEM;
26
27 retval = platform_device_add_resources(pdev, &sead3_lcd_resource, 1);
28 if (retval)
29 goto err_free_device;
30
31 retval = platform_device_add(pdev);
32 if (retval)
33 goto err_free_device;
34
35 return 0;
36
37err_free_device:
38 platform_device_put(pdev);
39
40 return retval;
41}
42
43device_initcall(sead3_lcd_add);
diff --git a/arch/mips/mti-sead3/sead3-leds.c b/arch/mips/mti-sead3/sead3-leds.c
new file mode 100644
index 000000000000..20102a6d4141
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-leds.c
@@ -0,0 +1,83 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/leds.h>
10#include <linux/platform_device.h>
11
12#define LEDFLAGS(bits, shift) \
13 ((bits << 8) | (shift << 8))
14
15#define LEDBITS(id, shift, bits) \
16 .name = id #shift, \
17 .flags = LEDFLAGS(bits, shift)
18
19struct led_info led_data_info[] = {
20 { LEDBITS("bit", 0, 1) },
21 { LEDBITS("bit", 1, 1) },
22 { LEDBITS("bit", 2, 1) },
23 { LEDBITS("bit", 3, 1) },
24 { LEDBITS("bit", 4, 1) },
25 { LEDBITS("bit", 5, 1) },
26 { LEDBITS("bit", 6, 1) },
27 { LEDBITS("bit", 7, 1) },
28 { LEDBITS("all", 0, 8) },
29};
30
31static struct led_platform_data led_data = {
32 .num_leds = ARRAY_SIZE(led_data_info),
33 .leds = led_data_info
34};
35
36static struct resource pled_resources[] = {
37 {
38 .start = 0x1f000210,
39 .end = 0x1f000217,
40 .flags = IORESOURCE_MEM
41 }
42};
43
44static struct platform_device pled_device = {
45 .name = "sead3::pled",
46 .id = 0,
47 .dev = {
48 .platform_data = &led_data,
49 },
50 .num_resources = ARRAY_SIZE(pled_resources),
51 .resource = pled_resources
52};
53
54
55static struct resource fled_resources[] = {
56 {
57 .start = 0x1f000218,
58 .end = 0x1f00021f,
59 .flags = IORESOURCE_MEM
60 }
61};
62
63static struct platform_device fled_device = {
64 .name = "sead3::fled",
65 .id = 0,
66 .dev = {
67 .platform_data = &led_data,
68 },
69 .num_resources = ARRAY_SIZE(fled_resources),
70 .resource = fled_resources
71};
72
73static int __init led_init(void)
74{
75 platform_device_register(&pled_device);
76 return platform_device_register(&fled_device);
77}
78
79module_init(led_init);
80
81MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
82MODULE_LICENSE("GPL");
83MODULE_DESCRIPTION("LED probe driver for SEAD-3");
diff --git a/arch/mips/mti-sead3/sead3-memory.c b/arch/mips/mti-sead3/sead3-memory.c
new file mode 100644
index 000000000000..da9244106f86
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-memory.c
@@ -0,0 +1,138 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/bootmem.h>
9
10#include <asm/bootinfo.h>
11#include <asm/sections.h>
12#include <asm/mips-boards/prom.h>
13
14enum yamon_memtypes {
15 yamon_dontuse,
16 yamon_prom,
17 yamon_free,
18};
19
20static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
21
22/* determined physical memory size, not overridden by command line args */
23unsigned long physical_memsize = 0L;
24
25struct prom_pmemblock * __init prom_getmdesc(void)
26{
27 char *memsize_str, *ptr;
28 unsigned int memsize;
29 static char cmdline[COMMAND_LINE_SIZE] __initdata;
30 long val;
31 int tmp;
32
33 /* otherwise look in the environment */
34 memsize_str = prom_getenv("memsize");
35 if (!memsize_str) {
36 pr_warn("memsize not set in boot prom, set to default 32Mb\n");
37 physical_memsize = 0x02000000;
38 } else {
39 tmp = kstrtol(memsize_str, 0, &val);
40 physical_memsize = (unsigned long)val;
41 }
42
43#ifdef CONFIG_CPU_BIG_ENDIAN
44 /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
45 word of physical memory */
46 physical_memsize -= PAGE_SIZE;
47#endif
48
49 /* Check the command line for a memsize directive that overrides
50 the physical/default amount */
51 strcpy(cmdline, arcs_cmdline);
52 ptr = strstr(cmdline, "memsize=");
53 if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
54 ptr = strstr(ptr, " memsize=");
55
56 if (ptr)
57 memsize = memparse(ptr + 8, &ptr);
58 else
59 memsize = physical_memsize;
60
61 memset(mdesc, 0, sizeof(mdesc));
62
63 mdesc[0].type = yamon_dontuse;
64 mdesc[0].base = 0x00000000;
65 mdesc[0].size = 0x00001000;
66
67 mdesc[1].type = yamon_prom;
68 mdesc[1].base = 0x00001000;
69 mdesc[1].size = 0x000ef000;
70
71 /*
72 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
73 * south bridge and PCI access always forwarded to the ISA Bus and
74 * BIOSCS# is always generated.
75 * This mean that this area can't be used as DMA memory for PCI
76 * devices.
77 */
78 mdesc[2].type = yamon_dontuse;
79 mdesc[2].base = 0x000f0000;
80 mdesc[2].size = 0x00010000;
81
82 mdesc[3].type = yamon_dontuse;
83 mdesc[3].base = 0x00100000;
84 mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
85 mdesc[3].base;
86
87 mdesc[4].type = yamon_free;
88 mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
89 mdesc[4].size = memsize - mdesc[4].base;
90
91 return &mdesc[0];
92}
93
94static int __init prom_memtype_classify(unsigned int type)
95{
96 switch (type) {
97 case yamon_free:
98 return BOOT_MEM_RAM;
99 case yamon_prom:
100 return BOOT_MEM_ROM_DATA;
101 default:
102 return BOOT_MEM_RESERVED;
103 }
104}
105
106void __init prom_meminit(void)
107{
108 struct prom_pmemblock *p;
109
110 p = prom_getmdesc();
111
112 while (p->size) {
113 long type;
114 unsigned long base, size;
115
116 type = prom_memtype_classify(p->type);
117 base = p->base;
118 size = p->size;
119
120 add_memory_region(base, size, type);
121 p++;
122 }
123}
124
125void __init prom_free_prom_memory(void)
126{
127 unsigned long addr;
128 int i;
129
130 for (i = 0; i < boot_mem_map.nr_map; i++) {
131 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
132 continue;
133
134 addr = boot_mem_map.map[i].addr;
135 free_init_pages("prom memory",
136 addr, addr + boot_mem_map.map[i].size);
137 }
138}
diff --git a/arch/mips/mti-sead3/sead3-mtd.c b/arch/mips/mti-sead3/sead3-mtd.c
new file mode 100644
index 000000000000..ffa35f509789
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-mtd.c
@@ -0,0 +1,54 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/platform_device.h>
10#include <linux/mtd/physmap.h>
11
12static struct mtd_partition sead3_mtd_partitions[] = {
13 {
14 .name = "User FS",
15 .offset = 0x00000000,
16 .size = 0x01fc0000,
17 }, {
18 .name = "Board Config",
19 .offset = 0x01fc0000,
20 .size = 0x00040000,
21 .mask_flags = MTD_WRITEABLE
22 },
23};
24
25static struct physmap_flash_data sead3_flash_data = {
26 .width = 4,
27 .nr_parts = ARRAY_SIZE(sead3_mtd_partitions),
28 .parts = sead3_mtd_partitions
29};
30
31static struct resource sead3_flash_resource = {
32 .start = 0x1c000000,
33 .end = 0x1dffffff,
34 .flags = IORESOURCE_MEM
35};
36
37static struct platform_device sead3_flash = {
38 .name = "physmap-flash",
39 .id = 0,
40 .dev = {
41 .platform_data = &sead3_flash_data,
42 },
43 .num_resources = 1,
44 .resource = &sead3_flash_resource,
45};
46
47static int __init sead3_mtd_init(void)
48{
49 platform_device_register(&sead3_flash);
50
51 return 0;
52}
53
54module_init(sead3_mtd_init)
diff --git a/arch/mips/mti-sead3/sead3-net.c b/arch/mips/mti-sead3/sead3-net.c
new file mode 100644
index 000000000000..04d704df6098
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-net.c
@@ -0,0 +1,51 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/irq.h>
10#include <linux/platform_device.h>
11#include <linux/smsc911x.h>
12
13static struct smsc911x_platform_config sead3_smsc911x_data = {
14 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
15 .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
16 .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
17 .phy_interface = PHY_INTERFACE_MODE_MII,
18};
19
20struct resource sead3_net_resourcess[] = {
21 {
22 .start = 0x1f010000,
23 .end = 0x1f01ffff,
24 .flags = IORESOURCE_MEM
25 },
26 {
27 .start = MIPS_CPU_IRQ_BASE + 6,
28 .flags = IORESOURCE_IRQ
29 }
30};
31
32static struct platform_device sead3_net_device = {
33 .name = "smsc911x",
34 .id = 0,
35 .dev = {
36 .platform_data = &sead3_smsc911x_data,
37 },
38 .num_resources = ARRAY_SIZE(sead3_net_resourcess),
39 .resource = sead3_net_resourcess
40};
41
42static int __init sead3_net_init(void)
43{
44 return platform_device_register(&sead3_net_device);
45}
46
47module_init(sead3_net_init);
48
49MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
50MODULE_LICENSE("GPL");
51MODULE_DESCRIPTION("Network probe driver for SEAD-3");
diff --git a/arch/mips/mti-sead3/sead3-pic32-bus.c b/arch/mips/mti-sead3/sead3-pic32-bus.c
new file mode 100644
index 000000000000..9f0d89bc800e
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-pic32-bus.c
@@ -0,0 +1,103 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/delay.h>
9#include <linux/kernel.h>
10#include <linux/spinlock.h>
11#include <linux/init.h>
12#include <linux/io.h>
13#include <linux/errno.h>
14
15#define PIC32_NULL 0x00
16#define PIC32_RD 0x01
17#define PIC32_SYSRD 0x02
18#define PIC32_WR 0x10
19#define PIC32_SYSWR 0x20
20#define PIC32_IRQ_CLR 0x40
21#define PIC32_STATUS 0x80
22
23#define DELAY() udelay(100) /* FIXME: needed? */
24
25/* spinlock to ensure atomic access to PIC32 */
26static DEFINE_SPINLOCK(pic32_bus_lock);
27
28/* FIXME: io_remap these */
29static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
30static void __iomem *bus_status = (void __iomem *)0xbf000060;
31
32static inline unsigned int ioready(void)
33{
34 return readl(bus_status) & 1;
35}
36
37static inline void wait_ioready(void)
38{
39 do { } while (!ioready());
40}
41
42static inline void wait_ioclear(void)
43{
44 do { } while (ioready());
45}
46
47static inline void check_ioclear(void)
48{
49 if (ioready()) {
50 pr_debug("ioclear: initially busy\n");
51 do {
52 (void) readl(bus_xfer);
53 DELAY();
54 } while (ioready());
55 pr_debug("ioclear: cleared busy\n");
56 }
57}
58
59u32 pic32_bus_readl(u32 reg)
60{
61 unsigned long flags;
62 u32 status, val;
63
64 spin_lock_irqsave(&pic32_bus_lock, flags);
65
66 check_ioclear();
67
68 writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer);
69 DELAY();
70 wait_ioready();
71 status = readl(bus_xfer);
72 DELAY();
73 val = readl(bus_xfer);
74 wait_ioclear();
75
76 pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status);
77
78 spin_unlock_irqrestore(&pic32_bus_lock, flags);
79
80 return val;
81}
82
83void pic32_bus_writel(u32 val, u32 reg)
84{
85 unsigned long flags;
86 u32 status;
87
88 spin_lock_irqsave(&pic32_bus_lock, flags);
89
90 check_ioclear();
91
92 writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer);
93 DELAY();
94 writel(val, bus_xfer);
95 DELAY();
96 wait_ioready();
97 status = readl(bus_xfer);
98 wait_ioclear();
99
100 pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status);
101
102 spin_unlock_irqrestore(&pic32_bus_lock, flags);
103}
diff --git a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
new file mode 100644
index 000000000000..46509b0a620d
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
@@ -0,0 +1,435 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/delay.h>
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/spinlock.h>
12#include <linux/platform_device.h>
13#include <linux/init.h>
14#include <linux/errno.h>
15#include <linux/i2c.h>
16#include <linux/slab.h>
17
18#define PIC32_I2CxCON 0x0000
19#define PIC32_I2CxCONCLR 0x0004
20#define PIC32_I2CxCONSET 0x0008
21#define PIC32_I2CxCONINV 0x000C
22#define I2CCON_ON (1<<15)
23#define I2CCON_FRZ (1<<14)
24#define I2CCON_SIDL (1<<13)
25#define I2CCON_SCLREL (1<<12)
26#define I2CCON_STRICT (1<<11)
27#define I2CCON_A10M (1<<10)
28#define I2CCON_DISSLW (1<<9)
29#define I2CCON_SMEN (1<<8)
30#define I2CCON_GCEN (1<<7)
31#define I2CCON_STREN (1<<6)
32#define I2CCON_ACKDT (1<<5)
33#define I2CCON_ACKEN (1<<4)
34#define I2CCON_RCEN (1<<3)
35#define I2CCON_PEN (1<<2)
36#define I2CCON_RSEN (1<<1)
37#define I2CCON_SEN (1<<0)
38
39#define PIC32_I2CxSTAT 0x0010
40#define PIC32_I2CxSTATCLR 0x0014
41#define PIC32_I2CxSTATSET 0x0018
42#define PIC32_I2CxSTATINV 0x001C
43#define I2CSTAT_ACKSTAT (1<<15)
44#define I2CSTAT_TRSTAT (1<<14)
45#define I2CSTAT_BCL (1<<10)
46#define I2CSTAT_GCSTAT (1<<9)
47#define I2CSTAT_ADD10 (1<<8)
48#define I2CSTAT_IWCOL (1<<7)
49#define I2CSTAT_I2COV (1<<6)
50#define I2CSTAT_DA (1<<5)
51#define I2CSTAT_P (1<<4)
52#define I2CSTAT_S (1<<3)
53#define I2CSTAT_RW (1<<2)
54#define I2CSTAT_RBF (1<<1)
55#define I2CSTAT_TBF (1<<0)
56
57#define PIC32_I2CxADD 0x0020
58#define PIC32_I2CxADDCLR 0x0024
59#define PIC32_I2CxADDSET 0x0028
60#define PIC32_I2CxADDINV 0x002C
61#define PIC32_I2CxMSK 0x0030
62#define PIC32_I2CxMSKCLR 0x0034
63#define PIC32_I2CxMSKSET 0x0038
64#define PIC32_I2CxMSKINV 0x003C
65#define PIC32_I2CxBRG 0x0040
66#define PIC32_I2CxBRGCLR 0x0044
67#define PIC32_I2CxBRGSET 0x0048
68#define PIC32_I2CxBRGINV 0x004C
69#define PIC32_I2CxTRN 0x0050
70#define PIC32_I2CxTRNCLR 0x0054
71#define PIC32_I2CxTRNSET 0x0058
72#define PIC32_I2CxTRNINV 0x005C
73#define PIC32_I2CxRCV 0x0060
74
75struct i2c_platform_data {
76 u32 base;
77 struct i2c_adapter adap;
78 u32 xfer_timeout;
79 u32 ack_timeout;
80 u32 ctl_timeout;
81};
82
83extern u32 pic32_bus_readl(u32 reg);
84extern void pic32_bus_writel(u32 val, u32 reg);
85
86static inline void
87StartI2C(struct i2c_platform_data *adap)
88{
89 pr_debug("StartI2C\n");
90 pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
91}
92
93static inline void
94StopI2C(struct i2c_platform_data *adap)
95{
96 pr_debug("StopI2C\n");
97 pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
98}
99
100static inline void
101AckI2C(struct i2c_platform_data *adap)
102{
103 pr_debug("AckI2C\n");
104 pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
105 pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
106}
107
108static inline void
109NotAckI2C(struct i2c_platform_data *adap)
110{
111 pr_debug("NakI2C\n");
112 pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
113 pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
114}
115
116static inline int
117IdleI2C(struct i2c_platform_data *adap)
118{
119 int i;
120
121 pr_debug("IdleI2C\n");
122 for (i = 0; i < adap->ctl_timeout; i++) {
123 if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
124 (I2CCON_ACKEN | I2CCON_RCEN | I2CCON_PEN | I2CCON_RSEN |
125 I2CCON_SEN)) == 0) &&
126 ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
127 (I2CSTAT_TRSTAT)) == 0))
128 return 0;
129 udelay(1);
130 }
131 return -ETIMEDOUT;
132}
133
134static inline u32
135MasterWriteI2C(struct i2c_platform_data *adap, u32 byte)
136{
137 pr_debug("MasterWriteI2C\n");
138
139 pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
140
141 return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_IWCOL;
142}
143
144static inline u32
145MasterReadI2C(struct i2c_platform_data *adap)
146{
147 pr_debug("MasterReadI2C\n");
148
149 pic32_bus_writel(I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
150
151 while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & I2CCON_RCEN)
152 ;
153
154 pic32_bus_writel(I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
155
156 return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
157}
158
159static int
160do_address(struct i2c_platform_data *adap, unsigned int addr, int rd)
161{
162 pr_debug("doaddress\n");
163
164 IdleI2C(adap);
165 StartI2C(adap);
166 IdleI2C(adap);
167
168 addr <<= 1;
169 if (rd)
170 addr |= 1;
171
172 if (MasterWriteI2C(adap, addr))
173 return -EIO;
174 IdleI2C(adap);
175 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_ACKSTAT)
176 return -EIO;
177 return 0;
178}
179
180static int
181i2c_read(struct i2c_platform_data *adap, unsigned char *buf,
182 unsigned int len)
183{
184 int i;
185 u32 data;
186
187 pr_debug("i2c_read\n");
188
189 i = 0;
190 while (i < len) {
191 data = MasterReadI2C(adap);
192 buf[i++] = data;
193 if (i < len)
194 AckI2C(adap);
195 else
196 NotAckI2C(adap);
197 }
198
199 StopI2C(adap);
200 IdleI2C(adap);
201 return 0;
202}
203
204static int
205i2c_write(struct i2c_platform_data *adap, unsigned char *buf,
206 unsigned int len)
207{
208 int i;
209 u32 data;
210
211 pr_debug("i2c_write\n");
212
213 i = 0;
214 while (i < len) {
215 data = buf[i];
216 if (MasterWriteI2C(adap, data))
217 return -EIO;
218 IdleI2C(adap);
219 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
220 I2CSTAT_ACKSTAT)
221 return -EIO;
222 i++;
223 }
224
225 StopI2C(adap);
226 IdleI2C(adap);
227 return 0;
228}
229
230static int
231platform_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
232{
233 struct i2c_platform_data *adap = i2c_adap->algo_data;
234 struct i2c_msg *p;
235 int i, err = 0;
236
237 pr_debug("platform_xfer\n");
238 for (i = 0; i < num; i++) {
239#define __BUFSIZE 80
240 int ii;
241 static char buf[__BUFSIZE];
242 char *b = buf;
243
244 p = &msgs[i];
245 b += sprintf(buf, " [%d bytes]", p->len);
246 if ((p->flags & I2C_M_RD) == 0) {
247 for (ii = 0; ii < p->len; ii++) {
248 if (b < &buf[__BUFSIZE-4]) {
249 b += sprintf(b, " %02x", p->buf[ii]);
250 } else {
251 strcat(b, "...");
252 break;
253 }
254 }
255 }
256 pr_debug("xfer%d: DevAddr: %04x Op:%s Data:%s\n", i, p->addr,
257 (p->flags & I2C_M_RD) ? "Rd" : "Wr", buf);
258 }
259
260
261 for (i = 0; !err && i < num; i++) {
262 p = &msgs[i];
263 err = do_address(adap, p->addr, p->flags & I2C_M_RD);
264 if (err || !p->len)
265 continue;
266 if (p->flags & I2C_M_RD)
267 err = i2c_read(adap, p->buf, p->len);
268 else
269 err = i2c_write(adap, p->buf, p->len);
270 }
271
272 /* Return the number of messages processed, or the error code. */
273 if (err == 0)
274 err = num;
275
276 return err;
277}
278
279static u32
280platform_func(struct i2c_adapter *adap)
281{
282 pr_debug("platform_algo\n");
283 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
284}
285
286static const struct i2c_algorithm platform_algo = {
287 .master_xfer = platform_xfer,
288 .functionality = platform_func,
289};
290
291static void i2c_platform_setup(struct i2c_platform_data *priv)
292{
293 pr_debug("i2c_platform_setup\n");
294
295 pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
296 pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
297 pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONSET);
298 pic32_bus_writel((I2CSTAT_BCL | I2CSTAT_IWCOL),
299 (priv->base + PIC32_I2CxSTATCLR));
300}
301
302static void i2c_platform_disable(struct i2c_platform_data *priv)
303{
304 pr_debug("i2c_platform_disable\n");
305}
306
307static int __devinit
308i2c_platform_probe(struct platform_device *pdev)
309{
310 struct i2c_platform_data *priv;
311 struct resource *r;
312 int ret;
313
314 pr_debug("i2c_platform_probe\n");
315 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
316 if (!r) {
317 ret = -ENODEV;
318 goto out;
319 }
320
321 priv = kzalloc(sizeof(struct i2c_platform_data), GFP_KERNEL);
322 if (!priv) {
323 ret = -ENOMEM;
324 goto out;
325 }
326
327 /* FIXME: need to allocate resource in PIC32 space */
328#if 0
329 priv->base = bus_request_region(r->start, resource_size(r),
330 pdev->name);
331#else
332 priv->base = r->start;
333#endif
334 if (!priv->base) {
335 ret = -EBUSY;
336 goto out_mem;
337 }
338
339 priv->xfer_timeout = 200;
340 priv->ack_timeout = 200;
341 priv->ctl_timeout = 200;
342
343 priv->adap.nr = pdev->id;
344 priv->adap.algo = &platform_algo;
345 priv->adap.algo_data = priv;
346 priv->adap.dev.parent = &pdev->dev;
347 strlcpy(priv->adap.name, "PIC32 I2C", sizeof(priv->adap.name));
348
349 i2c_platform_setup(priv);
350
351 ret = i2c_add_numbered_adapter(&priv->adap);
352 if (ret == 0) {
353 platform_set_drvdata(pdev, priv);
354 return 0;
355 }
356
357 i2c_platform_disable(priv);
358
359out_mem:
360 kfree(priv);
361out:
362 return ret;
363}
364
365static int __devexit
366i2c_platform_remove(struct platform_device *pdev)
367{
368 struct i2c_platform_data *priv = platform_get_drvdata(pdev);
369
370 pr_debug("i2c_platform_remove\n");
371 platform_set_drvdata(pdev, NULL);
372 i2c_del_adapter(&priv->adap);
373 i2c_platform_disable(priv);
374 kfree(priv);
375 return 0;
376}
377
378#ifdef CONFIG_PM
379static int
380i2c_platform_suspend(struct platform_device *pdev, pm_message_t state)
381{
382 struct i2c_platform_data *priv = platform_get_drvdata(pdev);
383
384 dev_dbg(&pdev->dev, "i2c_platform_disable\n");
385 i2c_platform_disable(priv);
386
387 return 0;
388}
389
390static int
391i2c_platform_resume(struct platform_device *pdev)
392{
393 struct i2c_platform_data *priv = platform_get_drvdata(pdev);
394
395 dev_dbg(&pdev->dev, "i2c_platform_setup\n");
396 i2c_platform_setup(priv);
397
398 return 0;
399}
400#else
401#define i2c_platform_suspend NULL
402#define i2c_platform_resume NULL
403#endif
404
405static struct platform_driver i2c_platform_driver = {
406 .driver = {
407 .name = "i2c_pic32",
408 .owner = THIS_MODULE,
409 },
410 .probe = i2c_platform_probe,
411 .remove = __devexit_p(i2c_platform_remove),
412 .suspend = i2c_platform_suspend,
413 .resume = i2c_platform_resume,
414};
415
416static int __init
417i2c_platform_init(void)
418{
419 pr_debug("i2c_platform_init\n");
420 return platform_driver_register(&i2c_platform_driver);
421}
422
423static void __exit
424i2c_platform_exit(void)
425{
426 pr_debug("i2c_platform_exit\n");
427 platform_driver_unregister(&i2c_platform_driver);
428}
429
430MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
431MODULE_DESCRIPTION("PIC32 I2C driver");
432MODULE_LICENSE("GPL");
433
434module_init(i2c_platform_init);
435module_exit(i2c_platform_exit);
diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c
new file mode 100644
index 000000000000..6c3b33dbed18
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-platform.c
@@ -0,0 +1,45 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/serial_8250.h>
11
12#define UART(base, int) \
13{ \
14 .mapbase = base, \
15 .irq = int, \
16 .uartclk = 14745600, \
17 .iotype = UPIO_MEM32, \
18 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
19 .regshift = 2, \
20}
21
22static struct plat_serial8250_port uart8250_data[] = {
23 UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */
24 UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */
25 { },
26};
27
28static struct platform_device uart8250_device = {
29 .name = "serial8250",
30 .id = PLAT8250_DEV_PLATFORM2,
31 .dev = {
32 .platform_data = uart8250_data,
33 },
34};
35
36static int __init uart8250_init(void)
37{
38 return platform_device_register(&uart8250_device);
39}
40
41module_init(uart8250_init);
42
43MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
44MODULE_LICENSE("GPL");
45MODULE_DESCRIPTION("8250 UART probe driver for SEAD3");
diff --git a/arch/mips/mti-sead3/sead3-reset.c b/arch/mips/mti-sead3/sead3-reset.c
new file mode 100644
index 000000000000..20475c5e7b9c
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-reset.c
@@ -0,0 +1,39 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/io.h>
9#include <linux/pm.h>
10
11#include <asm/reboot.h>
12#include <asm/mips-boards/generic.h>
13
14static void mips_machine_restart(char *command)
15{
16 unsigned int __iomem *softres_reg =
17 ioremap(SOFTRES_REG, sizeof(unsigned int));
18
19 __raw_writel(GORESET, softres_reg);
20}
21
22static void mips_machine_halt(void)
23{
24 unsigned int __iomem *softres_reg =
25 ioremap(SOFTRES_REG, sizeof(unsigned int));
26
27 __raw_writel(GORESET, softres_reg);
28}
29
30static int __init mips_reboot_setup(void)
31{
32 _machine_restart = mips_machine_restart;
33 _machine_halt = mips_machine_halt;
34 pm_power_off = mips_machine_halt;
35
36 return 0;
37}
38
39arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/mti-sead3/sead3-serial.c b/arch/mips/mti-sead3/sead3-serial.c
new file mode 100644
index 000000000000..bc52705bbee4
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-serial.c
@@ -0,0 +1,45 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/serial_8250.h>
11
12#define UART(base, int) \
13{ \
14 .mapbase = base, \
15 .irq = int, \
16 .uartclk = 14745600, \
17 .iotype = UPIO_MEM32, \
18 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
19 .regshift = 2, \
20}
21
22static struct plat_serial8250_port uart8250_data[] = {
23 UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */
24 UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */
25 { },
26};
27
28static struct platform_device uart8250_device = {
29 .name = "serial8250",
30 .id = PLAT8250_DEV_PLATFORM,
31 .dev = {
32 .platform_data = uart8250_data,
33 },
34};
35
36static int __init uart8250_init(void)
37{
38 return platform_device_register(&uart8250_device);
39}
40
41module_init(uart8250_init);
42
43MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
44MODULE_LICENSE("GPL");
45MODULE_DESCRIPTION("8250 UART probe driver for the SEAD-3 platform");
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
new file mode 100644
index 000000000000..8ad46ad31b49
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -0,0 +1,20 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9
10int coherentio; /* 0 => no DMA cache coherency (may be set by user) */
11int hw_coherentio; /* 0 => no HW DMA cache coherency (reflects real HW) */
12
13const char *get_system_type(void)
14{
15 return "MIPS SEAD3";
16}
17
18void __init plat_mem_setup(void)
19{
20}
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c
new file mode 100644
index 000000000000..048e781a17a0
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-time.c
@@ -0,0 +1,117 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9
10#include <asm/setup.h>
11#include <asm/time.h>
12#include <asm/irq.h>
13#include <asm/mips-boards/generic.h>
14#include <asm/mips-boards/prom.h>
15
16unsigned long cpu_khz;
17
18static int mips_cpu_timer_irq;
19static int mips_cpu_perf_irq;
20
21static void mips_timer_dispatch(void)
22{
23 do_IRQ(mips_cpu_timer_irq);
24}
25
26static void mips_perf_dispatch(void)
27{
28 do_IRQ(mips_cpu_perf_irq);
29}
30
31static void __iomem *status_reg = (void __iomem *)0xbf000410;
32
33/*
34 * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect.
35 */
36static unsigned int __init estimate_cpu_frequency(void)
37{
38 unsigned int prid = read_c0_prid() & 0xffff00;
39 unsigned int tick = 0;
40 unsigned int freq;
41 unsigned int orig;
42 unsigned long flags;
43
44 local_irq_save(flags);
45
46 orig = readl(status_reg) & 0x2; /* get original sample */
47 /* wait for transition */
48 while ((readl(status_reg) & 0x2) == orig)
49 ;
50 orig = orig ^ 0x2; /* flip the bit */
51
52 write_c0_count(0);
53
54 /* wait 1 second (the sampling clock transitions every 10ms) */
55 while (tick < 100) {
56 /* wait for transition */
57 while ((readl(status_reg) & 0x2) == orig)
58 ;
59 orig = orig ^ 0x2; /* flip the bit */
60 tick++;
61 }
62
63 freq = read_c0_count();
64
65 local_irq_restore(flags);
66
67 mips_hpt_frequency = freq;
68
69 /* Adjust for processor */
70 if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
71 (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
72 freq *= 2;
73
74 freq += 5000; /* rounding */
75 freq -= freq%10000;
76
77 return freq ;
78}
79
80void read_persistent_clock(struct timespec *ts)
81{
82 ts->tv_sec = 0;
83 ts->tv_nsec = 0;
84}
85
86static void __init plat_perf_setup(void)
87{
88 if (cp0_perfcount_irq >= 0) {
89 if (cpu_has_vint)
90 set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
91 mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
92 }
93}
94
95unsigned int __cpuinit get_c0_compare_int(void)
96{
97 if (cpu_has_vint)
98 set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
99 mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
100 return mips_cpu_timer_irq;
101}
102
103void __init plat_time_init(void)
104{
105 unsigned int est_freq;
106
107 est_freq = estimate_cpu_frequency();
108
109 pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000),
110 (est_freq % 1000000) * 100 / 1000000);
111
112 cpu_khz = est_freq / 1000;
113
114 mips_scroll_message();
115
116 plat_perf_setup();
117}