diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2012-09-28 10:29:55 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-09-28 10:29:55 -0400 |
commit | cb418b34caddc970c1513e515aaa535246a4bba3 (patch) | |
tree | b89720b74d6a85a9407f03bb064248c7235b9dea /arch/mips | |
parent | 77a0d763c461da81c2a3fc9a7e58162a40854a1a (diff) | |
parent | ff401e52100dcdc85e572d1ad376d3307b3fe28e (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')
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 | |||
16 | platforms += loongson | 16 | platforms += loongson |
17 | platforms += loongson1 | 17 | platforms += loongson1 |
18 | platforms += mti-malta | 18 | platforms += mti-malta |
19 | platforms += mti-sead3 | ||
19 | platforms += netlogic | 20 | platforms += netlogic |
20 | platforms += pmc-sierra | 21 | platforms += pmc-sierra |
21 | platforms += pnx833x | 22 | platforms += 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 | ||
325 | config 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 | |||
325 | config NEC_MARKEINS | 355 | config 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 | |||
1732 | menu "Kernel type" | 1762 | menu "Kernel type" |
1733 | 1763 | ||
1734 | choice | 1764 | choice |
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 | |||
1938 | config SYS_SUPPORTS_SCHED_SMT | 1967 | config SYS_SUPPORTS_SCHED_SMT |
1939 | bool | 1968 | bool |
1940 | 1969 | ||
1941 | |||
1942 | config SYS_SUPPORTS_MULTITHREADING | 1970 | config 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 @@ | |||
1 | CONFIG_MIPS_SEAD3=y | ||
2 | CONFIG_CPU_LITTLE_ENDIAN=y | ||
3 | CONFIG_CPU_MIPS32_R2=y | ||
4 | CONFIG_HZ_100=y | ||
5 | CONFIG_EXPERIMENTAL=y | ||
6 | CONFIG_SYSVIPC=y | ||
7 | CONFIG_POSIX_MQUEUE=y | ||
8 | CONFIG_NO_HZ=y | ||
9 | CONFIG_HIGH_RES_TIMERS=y | ||
10 | CONFIG_IKCONFIG=y | ||
11 | CONFIG_IKCONFIG_PROC=y | ||
12 | CONFIG_LOG_BUF_SHIFT=15 | ||
13 | CONFIG_EMBEDDED=y | ||
14 | CONFIG_SLAB=y | ||
15 | CONFIG_PROFILING=y | ||
16 | CONFIG_OPROFILE=y | ||
17 | CONFIG_MODULES=y | ||
18 | # CONFIG_BLK_DEV_BSG is not set | ||
19 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
20 | CONFIG_NET=y | ||
21 | CONFIG_PACKET=y | ||
22 | CONFIG_UNIX=y | ||
23 | CONFIG_INET=y | ||
24 | CONFIG_IP_PNP=y | ||
25 | CONFIG_IP_PNP_DHCP=y | ||
26 | CONFIG_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 | ||
34 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
35 | CONFIG_MTD=y | ||
36 | CONFIG_MTD_CHAR=y | ||
37 | CONFIG_MTD_BLOCK=y | ||
38 | CONFIG_MTD_CFI=y | ||
39 | CONFIG_MTD_CFI_INTELEXT=y | ||
40 | CONFIG_MTD_PHYSMAP=y | ||
41 | CONFIG_MTD_UBI=y | ||
42 | CONFIG_MTD_UBI_GLUEBI=y | ||
43 | CONFIG_BLK_DEV_LOOP=y | ||
44 | CONFIG_BLK_DEV_CRYPTOLOOP=m | ||
45 | CONFIG_SCSI=y | ||
46 | # CONFIG_SCSI_PROC_FS is not set | ||
47 | CONFIG_BLK_DEV_SD=y | ||
48 | CONFIG_CHR_DEV_SG=y | ||
49 | # CONFIG_SCSI_LOWLEVEL is not set | ||
50 | CONFIG_NETDEVICES=y | ||
51 | CONFIG_SMSC911X=y | ||
52 | # CONFIG_NET_VENDOR_WIZNET is not set | ||
53 | CONFIG_MARVELL_PHY=y | ||
54 | CONFIG_DAVICOM_PHY=y | ||
55 | CONFIG_QSEMI_PHY=y | ||
56 | CONFIG_LXT_PHY=y | ||
57 | CONFIG_CICADA_PHY=y | ||
58 | CONFIG_VITESSE_PHY=y | ||
59 | CONFIG_SMSC_PHY=y | ||
60 | CONFIG_BROADCOM_PHY=y | ||
61 | CONFIG_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 | ||
68 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
69 | CONFIG_LEGACY_PTY_COUNT=32 | ||
70 | CONFIG_SERIAL_8250=y | ||
71 | CONFIG_SERIAL_8250_CONSOLE=y | ||
72 | CONFIG_SERIAL_8250_NR_UARTS=2 | ||
73 | CONFIG_SERIAL_8250_RUNTIME_UARTS=2 | ||
74 | # CONFIG_HW_RANDOM is not set | ||
75 | CONFIG_I2C=y | ||
76 | # CONFIG_I2C_COMPAT is not set | ||
77 | CONFIG_I2C_CHARDEV=y | ||
78 | # CONFIG_I2C_HELPER_AUTO is not set | ||
79 | CONFIG_SPI=y | ||
80 | CONFIG_SENSORS_ADT7475=y | ||
81 | CONFIG_BACKLIGHT_LCD_SUPPORT=y | ||
82 | CONFIG_LCD_CLASS_DEVICE=y | ||
83 | CONFIG_BACKLIGHT_CLASS_DEVICE=y | ||
84 | # CONFIG_VGA_CONSOLE is not set | ||
85 | CONFIG_USB=y | ||
86 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y | ||
87 | CONFIG_USB_EHCI_HCD=y | ||
88 | CONFIG_USB_EHCI_ROOT_HUB_TT=y | ||
89 | CONFIG_USB_STORAGE=y | ||
90 | CONFIG_MMC=y | ||
91 | CONFIG_MMC_DEBUG=y | ||
92 | CONFIG_MMC_SPI=y | ||
93 | CONFIG_NEW_LEDS=y | ||
94 | CONFIG_LEDS_CLASS=y | ||
95 | CONFIG_LEDS_TRIGGERS=y | ||
96 | CONFIG_LEDS_TRIGGER_HEARTBEAT=y | ||
97 | CONFIG_RTC_CLASS=y | ||
98 | CONFIG_RTC_DRV_M41T80=y | ||
99 | CONFIG_EXT3_FS=y | ||
100 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
101 | CONFIG_XFS_FS=y | ||
102 | CONFIG_XFS_QUOTA=y | ||
103 | CONFIG_XFS_POSIX_ACL=y | ||
104 | CONFIG_QUOTA=y | ||
105 | # CONFIG_PRINT_QUOTA_WARNING is not set | ||
106 | CONFIG_MSDOS_FS=m | ||
107 | CONFIG_VFAT_FS=m | ||
108 | CONFIG_TMPFS=y | ||
109 | CONFIG_JFFS2_FS=y | ||
110 | CONFIG_NFS_FS=y | ||
111 | CONFIG_ROOT_NFS=y | ||
112 | CONFIG_NLS_CODEPAGE_437=y | ||
113 | CONFIG_NLS_ASCII=y | ||
114 | CONFIG_NLS_ISO8859_1=y | ||
115 | CONFIG_NLS_ISO8859_15=y | ||
116 | CONFIG_NLS_UTF8=y | ||
117 | # CONFIG_FTRACE is not set | ||
118 | CONFIG_CRYPTO=y | ||
119 | CONFIG_CRYPTO_CBC=y | ||
120 | CONFIG_CRYPTO_ECB=y | ||
121 | CONFIG_CRYPTO_AES=y | ||
122 | CONFIG_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 | ||
306 | struct gic_pcpu_mask { | 306 | struct gic_pcpu_mask { |
307 | DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); | 307 | DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS); |
308 | }; | 308 | }; |
309 | 309 | ||
310 | struct gic_pending_regs { | 310 | struct gic_pending_regs { |
311 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); | 311 | DECLARE_BITMAP(pending, GIC_NUM_INTRS); |
312 | }; | 312 | }; |
313 | 313 | ||
314 | struct gic_intrmask_regs { | 314 | struct 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 | |||
362 | extern unsigned long _gic_base; | ||
363 | extern unsigned int gic_irq_base; | ||
364 | extern unsigned int gic_irq_flags[]; | ||
365 | extern struct gic_shared_intr_map gic_shared_intr_map[]; | ||
366 | |||
344 | extern void gic_init(unsigned long gic_base_addr, | 367 | extern 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 | ||
371 | extern void gic_clocksource_init(unsigned int); | ||
348 | extern unsigned int gic_get_int(void); | 372 | extern unsigned int gic_get_int(void); |
349 | extern void gic_send_ipi(unsigned int intr); | 373 | extern void gic_send_ipi(unsigned int intr); |
350 | extern unsigned int plat_ipi_call_int_xlate(unsigned int); | 374 | extern unsigned int plat_ipi_call_int_xlate(unsigned int); |
351 | extern unsigned int plat_ipi_resched_int_xlate(unsigned int); | 375 | extern unsigned int plat_ipi_resched_int_xlate(unsigned int); |
352 | extern void gic_bind_eic_interrupt(int irq, int set); | 376 | extern void gic_bind_eic_interrupt(int irq, int set); |
353 | extern unsigned int gic_get_timer_pending(void); | 377 | extern unsigned int gic_get_timer_pending(void); |
378 | extern void gic_enable_interrupt(int irq_vec); | ||
379 | extern void gic_disable_interrupt(int irq_vec); | ||
380 | extern void gic_irq_ack(struct irq_data *d); | ||
381 | extern void gic_finish_irq(struct irq_data *d); | ||
382 | extern 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 | ||
23 | 9 : | ||
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 | |||
36 | 1 : b 1b | ||
37 | |||
38 | __INITDATA | ||
39 | nonmt_processor : | ||
40 | .asciz "SMTC kernel requires the MT ASE to run\n" | ||
41 | __FINIT | ||
42 | 0 : | ||
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__ | ||
114 | extern 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); | |||
90 | Ip_u2u1u3(_dsrl32); | 90 | Ip_u2u1u3(_dsrl32); |
91 | Ip_u3u1u2(_dsubu); | 91 | Ip_u3u1u2(_dsubu); |
92 | Ip_0(_eret); | 92 | Ip_0(_eret); |
93 | Ip_u2u1msbu3(_ext); | ||
94 | Ip_u2u1msbu3(_ins); | ||
93 | Ip_u1(_j); | 95 | Ip_u1(_j); |
94 | Ip_u1(_jal); | 96 | Ip_u1(_jal); |
95 | Ip_u1(_jr); | 97 | Ip_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 | */ |
99 | static int c0_compare_int_pending(void) | 100 | static 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 | ||
22 | unsigned long _gic_base; | ||
23 | unsigned int gic_irq_base; | ||
24 | unsigned int gic_irq_flags[GIC_NUM_INTRS]; | ||
14 | 25 | ||
15 | static unsigned long _gic_base; | 26 | /* The index into this array is the vector # of the interrupt. */ |
16 | static unsigned int _irqbase; | 27 | struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS]; |
17 | static unsigned int gic_irq_flags[GIC_NUM_INTRS]; | ||
18 | #define GIC_IRQ_FLAG_EDGE 0x0001 | ||
19 | 28 | ||
20 | struct gic_pcpu_mask pcpu_masks[NR_CPUS]; | 29 | static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; |
21 | static struct gic_pending_regs pending_regs[NR_CPUS]; | 30 | static struct gic_pending_regs pending_regs[NR_CPUS]; |
22 | static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; | 31 | static struct gic_intrmask_regs intrmask_regs[NR_CPUS]; |
23 | 32 | ||
33 | unsigned 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 | |||
42 | void 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 | |||
24 | void gic_send_ipi(unsigned int intr) | 51 | void 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 */ | 56 | static 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 | |||
32 | static void __init vpe_local_setup(unsigned int numvpes) | 71 | static 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 | |||
90 | static 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 | ||
101 | static void gic_mask_irq(struct irq_data *d) | 148 | static 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 | ||
108 | static void gic_unmask_irq(struct irq_data *d) | 153 | static 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 | |||
117 | static DEFINE_SPINLOCK(gic_lock); | 159 | static DEFINE_SPINLOCK(gic_lock); |
118 | 160 | ||
119 | static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, | 161 | static 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 | ||
200 | static void __init gic_basic_init(int numintrs, int numvpes, | 251 | static 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 | ||
235 | void __init gic_init(unsigned long gic_base_addr, | 296 | void __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 | ||
789 | static 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 | |||
789 | static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way", | 808 | static 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 | ||
957 | static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) | 976 | static 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 | ||
73 | struct insn { | 74 | struct 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 | } \ |
342 | UASM_EXPORT_SYMBOL(uasm_i##op); | 346 | UASM_EXPORT_SYMBOL(uasm_i##op); |
343 | 347 | ||
348 | #define I_u2u1msbdu3(op) \ | ||
349 | Ip_u2u1msbu3(op) \ | ||
350 | { \ | ||
351 | build_insn(buf, insn##op, b, a, d-1, c); \ | ||
352 | } \ | ||
353 | UASM_EXPORT_SYMBOL(uasm_i##op); | ||
354 | |||
344 | #define I_u1u2(op) \ | 355 | #define I_u1u2(op) \ |
345 | Ip_u1u2(op) \ | 356 | Ip_u1u2(op) \ |
346 | { \ | 357 | { \ |
@@ -394,6 +405,8 @@ I_u2u1u3(_drotr) | |||
394 | I_u2u1u3(_drotr32) | 405 | I_u2u1u3(_drotr32) |
395 | I_u3u1u2(_dsubu) | 406 | I_u3u1u2(_dsubu) |
396 | I_0(_eret) | 407 | I_0(_eret) |
408 | I_u2u1msbdu3(_ext) | ||
409 | I_u2u1msbu3(_ins) | ||
397 | I_u1(_j) | 410 | I_u1(_j) |
398 | I_u1(_jal) | 411 | I_u1(_jal) |
399 | I_u1(_jr) | 412 | I_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 | |||
754 | void gic_enable_interrupt(int irq_vec) | ||
755 | { | ||
756 | GIC_SET_INTR_MASK(irq_vec); | ||
757 | } | ||
758 | |||
759 | void gic_disable_interrupt(int irq_vec) | ||
760 | { | ||
761 | GIC_CLR_INTR_MASK(irq_vec); | ||
762 | } | ||
763 | |||
764 | void 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 | |||
774 | void gic_finish_irq(struct irq_data *d) | ||
775 | { | ||
776 | /* Enable interrupts. */ | ||
777 | GIC_SET_INTR_MASK(d->irq - gic_irq_base); | ||
778 | } | ||
779 | |||
780 | void __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 | # | ||
8 | obj-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 | |||
14 | obj-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 | |||
18 | obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o | ||
19 | obj-$(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 | # | ||
4 | platform-$(CONFIG_MIPS_SEAD3) += mti-sead3/ | ||
5 | cflags-$(CONFIG_MIPS_SEAD3) += -I$(srctree)/arch/mips/include/asm/mach-sead3 | ||
6 | load-$(CONFIG_MIPS_SEAD3) += 0xffffffff80100000 | ||
7 | all-$(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 | |||
18 | static struct platform_device *pdev; | ||
19 | |||
20 | static 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 | |||
27 | static 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 | |||
34 | static struct led_classdev sead3_pled = { | ||
35 | .name = "sead3::pled", | ||
36 | .brightness_set = sead3_pled_set, | ||
37 | }; | ||
38 | |||
39 | static struct led_classdev sead3_fled = { | ||
40 | .name = "sead3::fled", | ||
41 | .brightness_set = sead3_fled_set, | ||
42 | }; | ||
43 | |||
44 | #ifdef CONFIG_PM | ||
45 | static 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 | |||
53 | static 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 | |||
64 | static 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 | |||
79 | static 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 | |||
86 | static 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 | |||
97 | static 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 | |||
112 | out: | ||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | static void __exit sead3_led_exit(void) | ||
117 | { | ||
118 | platform_device_unregister(pdev); | ||
119 | platform_driver_unregister(&sead3_led_driver); | ||
120 | } | ||
121 | |||
122 | module_init(sead3_led_init); | ||
123 | module_exit(sead3_led_exit); | ||
124 | |||
125 | MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>"); | ||
126 | MODULE_DESCRIPTION("SEAD3 LED driver"); | ||
127 | MODULE_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 | |||
13 | extern int prom_argc; | ||
14 | extern 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 | |||
22 | char * __init prom_getcmdline(void) | ||
23 | { | ||
24 | return &(arcs_cmdline[0]); | ||
25 | } | ||
26 | |||
27 | void __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 | |||
17 | static char console_port = 1; | ||
18 | |||
19 | static inline unsigned int serial_in(int offset, unsigned int base_addr) | ||
20 | { | ||
21 | return __raw_readl(PORT(base_addr, offset)) & 0xff; | ||
22 | } | ||
23 | |||
24 | static inline void serial_out(int offset, int value, unsigned int base_addr) | ||
25 | { | ||
26 | __raw_writel(value, PORT(base_addr, offset)); | ||
27 | } | ||
28 | |||
29 | void __init prom_init_early_console(char port) | ||
30 | { | ||
31 | console_port = port; | ||
32 | } | ||
33 | |||
34 | int 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 | |||
13 | static unsigned int display_count; | ||
14 | static 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 | |||
24 | const char display_string[] = " LINUX ON SEAD3 "; | ||
25 | |||
26 | static void scroll_display_message(unsigned long data); | ||
27 | static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0); | ||
28 | |||
29 | static 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 | |||
42 | void 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 | |||
65 | static 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 | |||
73 | void 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 | |||
13 | struct 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 | |||
25 | u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32); | ||
26 | |||
27 | static 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 | |||
38 | static int __init ehci_init(void) | ||
39 | { | ||
40 | return platform_device_register(&ehci_device); | ||
41 | } | ||
42 | |||
43 | module_init(ehci_init); | ||
44 | |||
45 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
46 | MODULE_LICENSE("GPL"); | ||
47 | MODULE_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 | |||
11 | static 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 | |||
22 | static 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 | |||
33 | arch_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 | |||
36 | static DEFINE_SPINLOCK(pic32_bus_lock); | ||
37 | |||
38 | static void __iomem *bus_xfer = (void __iomem *)0xbf000600; | ||
39 | static void __iomem *bus_status = (void __iomem *)0xbf000060; | ||
40 | |||
41 | #define DELAY() udelay(100) | ||
42 | |||
43 | static inline unsigned int ioready(void) | ||
44 | { | ||
45 | return readl(bus_status) & 1; | ||
46 | } | ||
47 | |||
48 | static inline void wait_ioready(void) | ||
49 | { | ||
50 | do { } while (!ioready()); | ||
51 | } | ||
52 | |||
53 | static inline void wait_ioclear(void) | ||
54 | { | ||
55 | do { } while (ioready()); | ||
56 | } | ||
57 | |||
58 | static inline void check_ioclear(void) | ||
59 | { | ||
60 | if (ioready()) { | ||
61 | do { | ||
62 | (void) readl(bus_xfer); | ||
63 | DELAY(); | ||
64 | } while (ioready()); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static 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 | |||
89 | static 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 | |||
108 | struct 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 | |||
116 | static 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 | |||
121 | static 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 | |||
126 | static 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 | |||
132 | static 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 | |||
138 | static 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 | |||
155 | static 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 | |||
163 | static 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 | |||
172 | static 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 | |||
192 | static 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 | |||
213 | static 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 | |||
236 | static 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 | |||
281 | static u32 sead3_pic32_platform_func(struct i2c_adapter *adap) | ||
282 | { | ||
283 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
284 | } | ||
285 | |||
286 | static const struct i2c_algorithm sead3_platform_algo = { | ||
287 | .master_xfer = sead3_pic32_platform_xfer, | ||
288 | .functionality = sead3_pic32_platform_func, | ||
289 | }; | ||
290 | |||
291 | static 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 | |||
300 | static 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 | |||
342 | out_mem: | ||
343 | kfree(priv); | ||
344 | out: | ||
345 | return ret; | ||
346 | } | ||
347 | |||
348 | static 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 | ||
359 | static 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 | |||
366 | static 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 | |||
380 | static 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 | |||
391 | static int __init sead3_i2c_platform_init(void) | ||
392 | { | ||
393 | return platform_driver_register(&sead3_i2c_platform_driver); | ||
394 | } | ||
395 | module_init(sead3_i2c_platform_init); | ||
396 | |||
397 | static void __exit sead3_i2c_platform_exit(void) | ||
398 | { | ||
399 | platform_driver_unregister(&sead3_i2c_platform_driver); | ||
400 | } | ||
401 | module_exit(sead3_i2c_platform_exit); | ||
402 | |||
403 | MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); | ||
404 | MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver"); | ||
405 | MODULE_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 | |||
13 | struct resource sead3_i2c_resources[] = { | ||
14 | { | ||
15 | .start = 0x805200, | ||
16 | .end = 0x8053ff, | ||
17 | .flags = IORESOURCE_MEM, | ||
18 | }, | ||
19 | }; | ||
20 | |||
21 | static 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 | |||
28 | static int __init sead3_i2c_init(void) | ||
29 | { | ||
30 | return platform_device_register(&sead3_i2c_device); | ||
31 | } | ||
32 | |||
33 | module_init(sead3_i2c_init); | ||
34 | |||
35 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
36 | MODULE_LICENSE("GPL"); | ||
37 | MODULE_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 | |||
17 | extern void prom_init_early_console(char port); | ||
18 | |||
19 | extern char except_vec_nmi; | ||
20 | extern char except_vec_ejtag_debug; | ||
21 | |||
22 | int prom_argc; | ||
23 | int *_prom_argv, *_prom_envp; | ||
24 | |||
25 | #define prom_envp(index) ((char *)(long)_prom_envp[(index)]) | ||
26 | |||
27 | char *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 | |||
48 | static 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 | |||
59 | static 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 | |||
70 | void __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 | |||
23 | int gic_present; | ||
24 | static 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 | ||
31 | static 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 | |||
50 | asmlinkage 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 | |||
62 | void __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 | |||
89 | void 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 | |||
106 | void 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 | |||
123 | void gic_irq_ack(struct irq_data *d) | ||
124 | { | ||
125 | GIC_CLR_INTR_MASK(d->irq - gic_irq_base); | ||
126 | } | ||
127 | |||
128 | void 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 | |||
144 | void __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 | |||
11 | static struct resource __initdata sead3_lcd_resource = { | ||
12 | .start = 0x1f000400, | ||
13 | .end = 0x1f00041f, | ||
14 | .flags = IORESOURCE_MEM, | ||
15 | }; | ||
16 | |||
17 | static __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 | |||
37 | err_free_device: | ||
38 | platform_device_put(pdev); | ||
39 | |||
40 | return retval; | ||
41 | } | ||
42 | |||
43 | device_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 | |||
19 | struct 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 | |||
31 | static struct led_platform_data led_data = { | ||
32 | .num_leds = ARRAY_SIZE(led_data_info), | ||
33 | .leds = led_data_info | ||
34 | }; | ||
35 | |||
36 | static struct resource pled_resources[] = { | ||
37 | { | ||
38 | .start = 0x1f000210, | ||
39 | .end = 0x1f000217, | ||
40 | .flags = IORESOURCE_MEM | ||
41 | } | ||
42 | }; | ||
43 | |||
44 | static 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 | |||
55 | static struct resource fled_resources[] = { | ||
56 | { | ||
57 | .start = 0x1f000218, | ||
58 | .end = 0x1f00021f, | ||
59 | .flags = IORESOURCE_MEM | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | static 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 | |||
73 | static int __init led_init(void) | ||
74 | { | ||
75 | platform_device_register(&pled_device); | ||
76 | return platform_device_register(&fled_device); | ||
77 | } | ||
78 | |||
79 | module_init(led_init); | ||
80 | |||
81 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
82 | MODULE_LICENSE("GPL"); | ||
83 | MODULE_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 | |||
14 | enum yamon_memtypes { | ||
15 | yamon_dontuse, | ||
16 | yamon_prom, | ||
17 | yamon_free, | ||
18 | }; | ||
19 | |||
20 | static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; | ||
21 | |||
22 | /* determined physical memory size, not overridden by command line args */ | ||
23 | unsigned long physical_memsize = 0L; | ||
24 | |||
25 | struct 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 | |||
94 | static 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 | |||
106 | void __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 | |||
125 | void __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 | |||
12 | static 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 | |||
25 | static 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 | |||
31 | static struct resource sead3_flash_resource = { | ||
32 | .start = 0x1c000000, | ||
33 | .end = 0x1dffffff, | ||
34 | .flags = IORESOURCE_MEM | ||
35 | }; | ||
36 | |||
37 | static 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 | |||
47 | static int __init sead3_mtd_init(void) | ||
48 | { | ||
49 | platform_device_register(&sead3_flash); | ||
50 | |||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | module_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 | |||
13 | static 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 | |||
20 | struct 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 | |||
32 | static 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 | |||
42 | static int __init sead3_net_init(void) | ||
43 | { | ||
44 | return platform_device_register(&sead3_net_device); | ||
45 | } | ||
46 | |||
47 | module_init(sead3_net_init); | ||
48 | |||
49 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
50 | MODULE_LICENSE("GPL"); | ||
51 | MODULE_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 */ | ||
26 | static DEFINE_SPINLOCK(pic32_bus_lock); | ||
27 | |||
28 | /* FIXME: io_remap these */ | ||
29 | static void __iomem *bus_xfer = (void __iomem *)0xbf000600; | ||
30 | static void __iomem *bus_status = (void __iomem *)0xbf000060; | ||
31 | |||
32 | static inline unsigned int ioready(void) | ||
33 | { | ||
34 | return readl(bus_status) & 1; | ||
35 | } | ||
36 | |||
37 | static inline void wait_ioready(void) | ||
38 | { | ||
39 | do { } while (!ioready()); | ||
40 | } | ||
41 | |||
42 | static inline void wait_ioclear(void) | ||
43 | { | ||
44 | do { } while (ioready()); | ||
45 | } | ||
46 | |||
47 | static 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 | |||
59 | u32 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 | |||
83 | void 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 | |||
75 | struct 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 | |||
83 | extern u32 pic32_bus_readl(u32 reg); | ||
84 | extern void pic32_bus_writel(u32 val, u32 reg); | ||
85 | |||
86 | static inline void | ||
87 | StartI2C(struct i2c_platform_data *adap) | ||
88 | { | ||
89 | pr_debug("StartI2C\n"); | ||
90 | pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET); | ||
91 | } | ||
92 | |||
93 | static inline void | ||
94 | StopI2C(struct i2c_platform_data *adap) | ||
95 | { | ||
96 | pr_debug("StopI2C\n"); | ||
97 | pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET); | ||
98 | } | ||
99 | |||
100 | static inline void | ||
101 | AckI2C(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 | |||
108 | static inline void | ||
109 | NotAckI2C(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 | |||
116 | static inline int | ||
117 | IdleI2C(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 | |||
134 | static inline u32 | ||
135 | MasterWriteI2C(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 | |||
144 | static inline u32 | ||
145 | MasterReadI2C(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 | |||
159 | static int | ||
160 | do_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 | |||
180 | static int | ||
181 | i2c_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 | |||
204 | static int | ||
205 | i2c_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 | |||
230 | static int | ||
231 | platform_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 | |||
279 | static u32 | ||
280 | platform_func(struct i2c_adapter *adap) | ||
281 | { | ||
282 | pr_debug("platform_algo\n"); | ||
283 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
284 | } | ||
285 | |||
286 | static const struct i2c_algorithm platform_algo = { | ||
287 | .master_xfer = platform_xfer, | ||
288 | .functionality = platform_func, | ||
289 | }; | ||
290 | |||
291 | static 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 | |||
302 | static void i2c_platform_disable(struct i2c_platform_data *priv) | ||
303 | { | ||
304 | pr_debug("i2c_platform_disable\n"); | ||
305 | } | ||
306 | |||
307 | static int __devinit | ||
308 | i2c_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 | |||
359 | out_mem: | ||
360 | kfree(priv); | ||
361 | out: | ||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static int __devexit | ||
366 | i2c_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 | ||
379 | static int | ||
380 | i2c_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 | |||
390 | static int | ||
391 | i2c_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 | |||
405 | static 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 | |||
416 | static int __init | ||
417 | i2c_platform_init(void) | ||
418 | { | ||
419 | pr_debug("i2c_platform_init\n"); | ||
420 | return platform_driver_register(&i2c_platform_driver); | ||
421 | } | ||
422 | |||
423 | static void __exit | ||
424 | i2c_platform_exit(void) | ||
425 | { | ||
426 | pr_debug("i2c_platform_exit\n"); | ||
427 | platform_driver_unregister(&i2c_platform_driver); | ||
428 | } | ||
429 | |||
430 | MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC."); | ||
431 | MODULE_DESCRIPTION("PIC32 I2C driver"); | ||
432 | MODULE_LICENSE("GPL"); | ||
433 | |||
434 | module_init(i2c_platform_init); | ||
435 | module_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 | |||
22 | static 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 | |||
28 | static struct platform_device uart8250_device = { | ||
29 | .name = "serial8250", | ||
30 | .id = PLAT8250_DEV_PLATFORM2, | ||
31 | .dev = { | ||
32 | .platform_data = uart8250_data, | ||
33 | }, | ||
34 | }; | ||
35 | |||
36 | static int __init uart8250_init(void) | ||
37 | { | ||
38 | return platform_device_register(&uart8250_device); | ||
39 | } | ||
40 | |||
41 | module_init(uart8250_init); | ||
42 | |||
43 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | MODULE_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 | |||
14 | static 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 | |||
22 | static 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 | |||
30 | static 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 | |||
39 | arch_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 | |||
22 | static 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 | |||
28 | static struct platform_device uart8250_device = { | ||
29 | .name = "serial8250", | ||
30 | .id = PLAT8250_DEV_PLATFORM, | ||
31 | .dev = { | ||
32 | .platform_data = uart8250_data, | ||
33 | }, | ||
34 | }; | ||
35 | |||
36 | static int __init uart8250_init(void) | ||
37 | { | ||
38 | return platform_device_register(&uart8250_device); | ||
39 | } | ||
40 | |||
41 | module_init(uart8250_init); | ||
42 | |||
43 | MODULE_AUTHOR("Chris Dearman <chris@mips.com>"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | MODULE_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 | |||
10 | int coherentio; /* 0 => no DMA cache coherency (may be set by user) */ | ||
11 | int hw_coherentio; /* 0 => no HW DMA cache coherency (reflects real HW) */ | ||
12 | |||
13 | const char *get_system_type(void) | ||
14 | { | ||
15 | return "MIPS SEAD3"; | ||
16 | } | ||
17 | |||
18 | void __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 | |||
16 | unsigned long cpu_khz; | ||
17 | |||
18 | static int mips_cpu_timer_irq; | ||
19 | static int mips_cpu_perf_irq; | ||
20 | |||
21 | static void mips_timer_dispatch(void) | ||
22 | { | ||
23 | do_IRQ(mips_cpu_timer_irq); | ||
24 | } | ||
25 | |||
26 | static void mips_perf_dispatch(void) | ||
27 | { | ||
28 | do_IRQ(mips_cpu_perf_irq); | ||
29 | } | ||
30 | |||
31 | static void __iomem *status_reg = (void __iomem *)0xbf000410; | ||
32 | |||
33 | /* | ||
34 | * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect. | ||
35 | */ | ||
36 | static 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 | |||
80 | void read_persistent_clock(struct timespec *ts) | ||
81 | { | ||
82 | ts->tv_sec = 0; | ||
83 | ts->tv_nsec = 0; | ||
84 | } | ||
85 | |||
86 | static 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 | |||
95 | unsigned 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 | |||
103 | void __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 | } | ||