diff options
author | Steven J. Hill <sjhill@mips.com> | 2012-05-30 17:02:49 -0400 |
---|---|---|
committer | Steven J. Hill <sjhill@mips.com> | 2012-09-13 16:43:46 -0400 |
commit | 3070033a16edcc21688d5ea8967c89522f833862 (patch) | |
tree | 48d1a4601dd4750d103bc0b02ff2494d75220321 /arch/mips | |
parent | 006a851b10a395955c153a145ad8241494d43688 (diff) |
MIPS: Add core files for MIPS SEAD-3 development platform.
More information about the SEAD-3 platform can be found at
<http://www.mips.com/products/development-kits/mips-sead-3/>
on MTI's site. Currently, the M14K family of cores is what
the SEAD-3 is utilised with.
Signed-off-by: Douglas Leung <douglas@mips.com>
Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Steven J. Hill <sjhill@mips.com>
Diffstat (limited to 'arch/mips')
29 files changed, 2445 insertions, 0 deletions
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/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/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 | } | ||