aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mti-sead3
diff options
context:
space:
mode:
authorSteven J. Hill <sjhill@mips.com>2012-05-30 17:02:49 -0400
committerSteven J. Hill <sjhill@mips.com>2012-09-13 16:43:46 -0400
commit3070033a16edcc21688d5ea8967c89522f833862 (patch)
tree48d1a4601dd4750d103bc0b02ff2494d75220321 /arch/mips/mti-sead3
parent006a851b10a395955c153a145ad8241494d43688 (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/mti-sead3')
-rw-r--r--arch/mips/mti-sead3/Makefile19
-rw-r--r--arch/mips/mti-sead3/Platform7
-rw-r--r--arch/mips/mti-sead3/leds-sead3.c128
-rw-r--r--arch/mips/mti-sead3/sead3-cmdline.c46
-rw-r--r--arch/mips/mti-sead3/sead3-console.c46
-rw-r--r--arch/mips/mti-sead3/sead3-display.c78
-rw-r--r--arch/mips/mti-sead3/sead3-ehci.c47
-rw-r--r--arch/mips/mti-sead3/sead3-i2c-dev.c33
-rw-r--r--arch/mips/mti-sead3/sead3-i2c-drv.c405
-rw-r--r--arch/mips/mti-sead3/sead3-i2c.c37
-rw-r--r--arch/mips/mti-sead3/sead3-init.c91
-rw-r--r--arch/mips/mti-sead3/sead3-int.c158
-rw-r--r--arch/mips/mti-sead3/sead3-lcd.c43
-rw-r--r--arch/mips/mti-sead3/sead3-leds.c83
-rw-r--r--arch/mips/mti-sead3/sead3-memory.c138
-rw-r--r--arch/mips/mti-sead3/sead3-mtd.c54
-rw-r--r--arch/mips/mti-sead3/sead3-net.c51
-rw-r--r--arch/mips/mti-sead3/sead3-pic32-bus.c103
-rw-r--r--arch/mips/mti-sead3/sead3-pic32-i2c-drv.c435
-rw-r--r--arch/mips/mti-sead3/sead3-platform.c45
-rw-r--r--arch/mips/mti-sead3/sead3-reset.c39
-rw-r--r--arch/mips/mti-sead3/sead3-serial.c45
-rw-r--r--arch/mips/mti-sead3/sead3-setup.c20
-rw-r--r--arch/mips/mti-sead3/sead3-time.c117
24 files changed, 2268 insertions, 0 deletions
diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile
new file mode 100644
index 00000000000..626afeac438
--- /dev/null
+++ b/arch/mips/mti-sead3/Makefile
@@ -0,0 +1,19 @@
1#
2# Carsten Langgaard, carstenl@mips.com
3# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4#
5# Copyright (C) 2008 Wind River Systems, Inc.
6# written by Ralf Baechle <ralf@linux-mips.org>
7#
8obj-y := sead3-lcd.o sead3-cmdline.o \
9 sead3-display.o sead3-init.o sead3-int.o \
10 sead3-mtd.o sead3-net.o \
11 sead3-memory.o sead3-platform.o \
12 sead3-reset.o sead3-setup.o sead3-time.o
13
14obj-y += sead3-i2c-dev.o sead3-i2c.o \
15 sead3-pic32-i2c-drv.o sead3-pic32-bus.o \
16 leds-sead3.o sead3-leds.o
17
18obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
19obj-$(CONFIG_USB_EHCI_HCD) += sead3-ehci.o
diff --git a/arch/mips/mti-sead3/Platform b/arch/mips/mti-sead3/Platform
new file mode 100644
index 00000000000..38709242714
--- /dev/null
+++ b/arch/mips/mti-sead3/Platform
@@ -0,0 +1,7 @@
1#
2# MIPS SEAD-3 board
3#
4platform-$(CONFIG_MIPS_SEAD3) += mti-sead3/
5cflags-$(CONFIG_MIPS_SEAD3) += -I$(srctree)/arch/mips/include/asm/mach-sead3
6load-$(CONFIG_MIPS_SEAD3) += 0xffffffff80100000
7all-$(CONFIG_MIPS_SEAD3) := $(COMPRESSION_FNAME).srec
diff --git a/arch/mips/mti-sead3/leds-sead3.c b/arch/mips/mti-sead3/leds-sead3.c
new file mode 100644
index 00000000000..a95ac598520
--- /dev/null
+++ b/arch/mips/mti-sead3/leds-sead3.c
@@ -0,0 +1,128 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/init.h>
11#include <linux/platform_device.h>
12#include <linux/leds.h>
13#include <linux/err.h>
14#include <linux/io.h>
15
16#define DRVNAME "sead3-led"
17
18static struct platform_device *pdev;
19
20static void sead3_pled_set(struct led_classdev *led_cdev,
21 enum led_brightness value)
22{
23 pr_debug("sead3_pled_set\n");
24 writel(value, (void __iomem *)0xBF000210); /* FIXME */
25}
26
27static void sead3_fled_set(struct led_classdev *led_cdev,
28 enum led_brightness value)
29{
30 pr_debug("sead3_fled_set\n");
31 writel(value, (void __iomem *)0xBF000218); /* FIXME */
32}
33
34static struct led_classdev sead3_pled = {
35 .name = "sead3::pled",
36 .brightness_set = sead3_pled_set,
37};
38
39static struct led_classdev sead3_fled = {
40 .name = "sead3::fled",
41 .brightness_set = sead3_fled_set,
42};
43
44#ifdef CONFIG_PM
45static int sead3_led_suspend(struct platform_device *dev,
46 pm_message_t state)
47{
48 led_classdev_suspend(&sead3_pled);
49 led_classdev_suspend(&sead3_fled);
50 return 0;
51}
52
53static int sead3_led_resume(struct platform_device *dev)
54{
55 led_classdev_resume(&sead3_pled);
56 led_classdev_resume(&sead3_fled);
57 return 0;
58}
59#else
60#define sead3_led_suspend NULL
61#define sead3_led_resume NULL
62#endif
63
64static int sead3_led_probe(struct platform_device *pdev)
65{
66 int ret;
67
68 ret = led_classdev_register(&pdev->dev, &sead3_pled);
69 if (ret < 0)
70 return ret;
71
72 ret = led_classdev_register(&pdev->dev, &sead3_fled);
73 if (ret < 0)
74 led_classdev_unregister(&sead3_pled);
75
76 return ret;
77}
78
79static int sead3_led_remove(struct platform_device *pdev)
80{
81 led_classdev_unregister(&sead3_pled);
82 led_classdev_unregister(&sead3_fled);
83 return 0;
84}
85
86static struct platform_driver sead3_led_driver = {
87 .probe = sead3_led_probe,
88 .remove = sead3_led_remove,
89 .suspend = sead3_led_suspend,
90 .resume = sead3_led_resume,
91 .driver = {
92 .name = DRVNAME,
93 .owner = THIS_MODULE,
94 },
95};
96
97static int __init sead3_led_init(void)
98{
99 int ret;
100
101 ret = platform_driver_register(&sead3_led_driver);
102 if (ret < 0)
103 goto out;
104
105 pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
106 if (IS_ERR(pdev)) {
107 ret = PTR_ERR(pdev);
108 platform_driver_unregister(&sead3_led_driver);
109 goto out;
110 }
111
112out:
113 return ret;
114}
115
116static void __exit sead3_led_exit(void)
117{
118 platform_device_unregister(pdev);
119 platform_driver_unregister(&sead3_led_driver);
120}
121
122module_init(sead3_led_init);
123module_exit(sead3_led_exit);
124
125MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
126MODULE_DESCRIPTION("SEAD3 LED driver");
127MODULE_LICENSE("GPL");
128
diff --git a/arch/mips/mti-sead3/sead3-cmdline.c b/arch/mips/mti-sead3/sead3-cmdline.c
new file mode 100644
index 00000000000..a2e6cec67f5
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-cmdline.c
@@ -0,0 +1,46 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/string.h>
10
11#include <asm/bootinfo.h>
12
13extern int prom_argc;
14extern int *_prom_argv;
15
16/*
17 * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
18 * This macro take care of sign extension.
19 */
20#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
21
22char * __init prom_getcmdline(void)
23{
24 return &(arcs_cmdline[0]);
25}
26
27void __init prom_init_cmdline(void)
28{
29 char *cp;
30 int actr;
31
32 actr = 1; /* Always ignore argv[0] */
33
34 cp = &(arcs_cmdline[0]);
35 while (actr < prom_argc) {
36 strcpy(cp, prom_argv(actr));
37 cp += strlen(prom_argv(actr));
38 *cp++ = ' ';
39 actr++;
40 }
41 if (cp != &(arcs_cmdline[0])) {
42 /* get rid of trailing space */
43 --cp;
44 *cp = '\0';
45 }
46}
diff --git a/arch/mips/mti-sead3/sead3-console.c b/arch/mips/mti-sead3/sead3-console.c
new file mode 100644
index 00000000000..b36739108a0
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-console.c
@@ -0,0 +1,46 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/console.h>
10#include <linux/serial_reg.h>
11#include <linux/io.h>
12
13#define SEAD_UART1_REGS_BASE 0xbf000800 /* ttyS1 = DB9 port */
14#define SEAD_UART0_REGS_BASE 0xbf000900 /* ttyS0 = USB port */
15#define PORT(base_addr, offset) ((unsigned int __iomem *)(base_addr+(offset)*4))
16
17static char console_port = 1;
18
19static inline unsigned int serial_in(int offset, unsigned int base_addr)
20{
21 return __raw_readl(PORT(base_addr, offset)) & 0xff;
22}
23
24static inline void serial_out(int offset, int value, unsigned int base_addr)
25{
26 __raw_writel(value, PORT(base_addr, offset));
27}
28
29void __init prom_init_early_console(char port)
30{
31 console_port = port;
32}
33
34int prom_putchar(char c)
35{
36 unsigned int base_addr;
37
38 base_addr = console_port ? SEAD_UART1_REGS_BASE : SEAD_UART0_REGS_BASE;
39
40 while ((serial_in(UART_LSR, base_addr) & UART_LSR_THRE) == 0)
41 ;
42
43 serial_out(UART_TX, c, base_addr);
44
45 return 1;
46}
diff --git a/arch/mips/mti-sead3/sead3-display.c b/arch/mips/mti-sead3/sead3-display.c
new file mode 100644
index 00000000000..8308c7fc188
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-display.c
@@ -0,0 +1,78 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/timer.h>
9#include <linux/io.h>
10#include <asm/mips-boards/generic.h>
11#include <asm/mips-boards/prom.h>
12
13static unsigned int display_count;
14static unsigned int max_display_count;
15
16#define LCD_DISPLAY_POS_BASE 0x1f000400
17#define DISPLAY_LCDINSTRUCTION (0*2)
18#define DISPLAY_LCDDATA (1*2)
19#define DISPLAY_CPLDSTATUS (2*2)
20#define DISPLAY_CPLDDATA (3*2)
21#define LCD_SETDDRAM 0x80
22#define LCD_IR_BF 0x80
23
24const char display_string[] = " LINUX ON SEAD3 ";
25
26static void scroll_display_message(unsigned long data);
27static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
28
29static void lcd_wait(unsigned int __iomem *display)
30{
31 /* Wait for CPLD state machine to become idle. */
32 do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
33
34 do {
35 __raw_readl(display + DISPLAY_LCDINSTRUCTION);
36
37 /* Wait for CPLD state machine to become idle. */
38 do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
39 } while (__raw_readl(display + DISPLAY_CPLDDATA) & LCD_IR_BF);
40}
41
42void mips_display_message(const char *str)
43{
44 static unsigned int __iomem *display;
45 char ch;
46 int i;
47
48 if (unlikely(display == NULL))
49 display = ioremap_nocache(LCD_DISPLAY_POS_BASE,
50 (8 * sizeof(int)));
51
52 for (i = 0; i < 16; i++) {
53 if (*str)
54 ch = *str++;
55 else
56 ch = ' ';
57 lcd_wait(display);
58 __raw_writel((LCD_SETDDRAM | i),
59 (display + DISPLAY_LCDINSTRUCTION));
60 lcd_wait(display);
61 __raw_writel(ch, display + DISPLAY_LCDDATA);
62 }
63}
64
65static void scroll_display_message(unsigned long data)
66{
67 mips_display_message(&display_string[display_count++]);
68 if (display_count == max_display_count)
69 display_count = 0;
70 mod_timer(&mips_scroll_timer, jiffies + HZ);
71}
72
73void mips_scroll_message(void)
74{
75 del_timer_sync(&mips_scroll_timer);
76 max_display_count = strlen(display_string) + 1 - 16;
77 mod_timer(&mips_scroll_timer, jiffies + 1);
78}
diff --git a/arch/mips/mti-sead3/sead3-ehci.c b/arch/mips/mti-sead3/sead3-ehci.c
new file mode 100644
index 00000000000..772fc056a92
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-ehci.c
@@ -0,0 +1,47 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/irq.h>
10#include <linux/dma-mapping.h>
11#include <linux/platform_device.h>
12
13struct resource ehci_resources[] = {
14 {
15 .start = 0x1b200000,
16 .end = 0x1b200fff,
17 .flags = IORESOURCE_MEM
18 },
19 {
20 .start = MIPS_CPU_IRQ_BASE + 2,
21 .flags = IORESOURCE_IRQ
22 }
23};
24
25u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32);
26
27static struct platform_device ehci_device = {
28 .name = "sead3-ehci",
29 .id = 0,
30 .dev = {
31 .dma_mask = &sead3_usbdev_dma_mask,
32 .coherent_dma_mask = DMA_BIT_MASK(32)
33 },
34 .num_resources = ARRAY_SIZE(ehci_resources),
35 .resource = ehci_resources
36};
37
38static int __init ehci_init(void)
39{
40 return platform_device_register(&ehci_device);
41}
42
43module_init(ehci_init);
44
45MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
46MODULE_LICENSE("GPL");
47MODULE_DESCRIPTION("EHCI probe driver for SEAD3");
diff --git a/arch/mips/mti-sead3/sead3-i2c-dev.c b/arch/mips/mti-sead3/sead3-i2c-dev.c
new file mode 100644
index 00000000000..eca0b53a71d
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-i2c-dev.c
@@ -0,0 +1,33 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/i2c.h>
10
11static struct i2c_board_info __initdata sead3_i2c_devices[] = {
12 {
13 I2C_BOARD_INFO("adt7476", 0x2c),
14 .irq = 0,
15 },
16 {
17 I2C_BOARD_INFO("m41t80", 0x68),
18 .irq = 0,
19 },
20};
21
22static int __init sead3_i2c_init(void)
23{
24 int err;
25
26 err = i2c_register_board_info(0, sead3_i2c_devices,
27 ARRAY_SIZE(sead3_i2c_devices));
28 if (err < 0)
29 pr_err("sead3-i2c-dev: cannot register board I2C devices\n");
30 return err;
31}
32
33arch_initcall(sead3_i2c_init);
diff --git a/arch/mips/mti-sead3/sead3-i2c-drv.c b/arch/mips/mti-sead3/sead3-i2c-drv.c
new file mode 100644
index 00000000000..0375ee66bca
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-i2c-drv.c
@@ -0,0 +1,405 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/module.h>
10#include <linux/slab.h>
11#include <linux/delay.h>
12#include <linux/i2c.h>
13#include <linux/platform_device.h>
14
15#define PIC32_I2CxCON 0x0000
16#define PIC32_I2CCON_ON (1<<15)
17#define PIC32_I2CCON_ACKDT (1<<5)
18#define PIC32_I2CCON_ACKEN (1<<4)
19#define PIC32_I2CCON_RCEN (1<<3)
20#define PIC32_I2CCON_PEN (1<<2)
21#define PIC32_I2CCON_RSEN (1<<1)
22#define PIC32_I2CCON_SEN (1<<0)
23#define PIC32_I2CxCONCLR 0x0004
24#define PIC32_I2CxCONSET 0x0008
25#define PIC32_I2CxSTAT 0x0010
26#define PIC32_I2CxSTATCLR 0x0014
27#define PIC32_I2CSTAT_ACKSTAT (1<<15)
28#define PIC32_I2CSTAT_TRSTAT (1<<14)
29#define PIC32_I2CSTAT_BCL (1<<10)
30#define PIC32_I2CSTAT_IWCOL (1<<7)
31#define PIC32_I2CSTAT_I2COV (1<<6)
32#define PIC32_I2CxBRG 0x0040
33#define PIC32_I2CxTRN 0x0050
34#define PIC32_I2CxRCV 0x0060
35
36static DEFINE_SPINLOCK(pic32_bus_lock);
37
38static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
39static void __iomem *bus_status = (void __iomem *)0xbf000060;
40
41#define DELAY() udelay(100)
42
43static inline unsigned int ioready(void)
44{
45 return readl(bus_status) & 1;
46}
47
48static inline void wait_ioready(void)
49{
50 do { } while (!ioready());
51}
52
53static inline void wait_ioclear(void)
54{
55 do { } while (ioready());
56}
57
58static inline void check_ioclear(void)
59{
60 if (ioready()) {
61 do {
62 (void) readl(bus_xfer);
63 DELAY();
64 } while (ioready());
65 }
66}
67
68static u32 pic32_bus_readl(u32 reg)
69{
70 unsigned long flags;
71 u32 status, val;
72
73 spin_lock_irqsave(&pic32_bus_lock, flags);
74
75 check_ioclear();
76 writel((0x01 << 24) | (reg & 0x00ffffff), bus_xfer);
77 DELAY();
78 wait_ioready();
79 status = readl(bus_xfer);
80 DELAY();
81 val = readl(bus_xfer);
82 wait_ioclear();
83
84 spin_unlock_irqrestore(&pic32_bus_lock, flags);
85
86 return val;
87}
88
89static void pic32_bus_writel(u32 val, u32 reg)
90{
91 unsigned long flags;
92 u32 status;
93
94 spin_lock_irqsave(&pic32_bus_lock, flags);
95
96 check_ioclear();
97 writel((0x10 << 24) | (reg & 0x00ffffff), bus_xfer);
98 DELAY();
99 writel(val, bus_xfer);
100 DELAY();
101 wait_ioready();
102 status = readl(bus_xfer);
103 wait_ioclear();
104
105 spin_unlock_irqrestore(&pic32_bus_lock, flags);
106}
107
108struct pic32_i2c_platform_data {
109 u32 base;
110 struct i2c_adapter adap;
111 u32 xfer_timeout;
112 u32 ack_timeout;
113 u32 ctl_timeout;
114};
115
116static inline void pic32_i2c_start(struct pic32_i2c_platform_data *adap)
117{
118 pic32_bus_writel(PIC32_I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
119}
120
121static inline void pic32_i2c_stop(struct pic32_i2c_platform_data *adap)
122{
123 pic32_bus_writel(PIC32_I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
124}
125
126static inline void pic32_i2c_ack(struct pic32_i2c_platform_data *adap)
127{
128 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
129 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
130}
131
132static inline void pic32_i2c_nack(struct pic32_i2c_platform_data *adap)
133{
134 pic32_bus_writel(PIC32_I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
135 pic32_bus_writel(PIC32_I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
136}
137
138static inline int pic32_i2c_idle(struct pic32_i2c_platform_data *adap)
139{
140 int i;
141
142 for (i = 0; i < adap->ctl_timeout; i++) {
143 if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
144 (PIC32_I2CCON_ACKEN | PIC32_I2CCON_RCEN |
145 PIC32_I2CCON_PEN | PIC32_I2CCON_RSEN |
146 PIC32_I2CCON_SEN)) == 0) &&
147 ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
148 (PIC32_I2CSTAT_TRSTAT)) == 0))
149 return 0;
150 udelay(1);
151 }
152 return -ETIMEDOUT;
153}
154
155static inline u32 pic32_i2c_master_write(struct pic32_i2c_platform_data *adap,
156 u32 byte)
157{
158 pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
159 return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
160 PIC32_I2CSTAT_IWCOL;
161}
162
163static inline u32 pic32_i2c_master_read(struct pic32_i2c_platform_data *adap)
164{
165 pic32_bus_writel(PIC32_I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
166 while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & PIC32_I2CCON_RCEN)
167 ;
168 pic32_bus_writel(PIC32_I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
169 return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
170}
171
172static int pic32_i2c_address(struct pic32_i2c_platform_data *adap,
173 unsigned int addr, int rd)
174{
175 pic32_i2c_idle(adap);
176 pic32_i2c_start(adap);
177 pic32_i2c_idle(adap);
178
179 addr <<= 1;
180 if (rd)
181 addr |= 1;
182
183 if (pic32_i2c_master_write(adap, addr))
184 return -EIO;
185 pic32_i2c_idle(adap);
186 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
187 PIC32_I2CSTAT_ACKSTAT)
188 return -EIO;
189 return 0;
190}
191
192static int sead3_i2c_read(struct pic32_i2c_platform_data *adap,
193 unsigned char *buf, unsigned int len)
194{
195 u32 data;
196 int i;
197
198 i = 0;
199 while (i < len) {
200 data = pic32_i2c_master_read(adap);
201 buf[i++] = data;
202 if (i < len)
203 pic32_i2c_ack(adap);
204 else
205 pic32_i2c_nack(adap);
206 }
207
208 pic32_i2c_stop(adap);
209 pic32_i2c_idle(adap);
210 return 0;
211}
212
213static int sead3_i2c_write(struct pic32_i2c_platform_data *adap,
214 unsigned char *buf, unsigned int len)
215{
216 int i;
217 u32 data;
218
219 i = 0;
220 while (i < len) {
221 data = buf[i];
222 if (pic32_i2c_master_write(adap, data))
223 return -EIO;
224 pic32_i2c_idle(adap);
225 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
226 PIC32_I2CSTAT_ACKSTAT)
227 return -EIO;
228 i++;
229 }
230
231 pic32_i2c_stop(adap);
232 pic32_i2c_idle(adap);
233 return 0;
234}
235
236static int sead3_pic32_platform_xfer(struct i2c_adapter *i2c_adap,
237 struct i2c_msg *msgs, int num)
238{
239 struct pic32_i2c_platform_data *adap = i2c_adap->algo_data;
240 struct i2c_msg *p;
241 int i, err = 0;
242
243 for (i = 0; i < num; i++) {
244#define __BUFSIZE 80
245 int ii;
246 static char buf[__BUFSIZE];
247 char *b = buf;
248
249 p = &msgs[i];
250 b += sprintf(buf, " [%d bytes]", p->len);
251 if ((p->flags & I2C_M_RD) == 0) {
252 for (ii = 0; ii < p->len; ii++) {
253 if (b < &buf[__BUFSIZE-4]) {
254 b += sprintf(b, " %02x", p->buf[ii]);
255 } else {
256 strcat(b, "...");
257 break;
258 }
259 }
260 }
261 }
262
263 for (i = 0; !err && i < num; i++) {
264 p = &msgs[i];
265 err = pic32_i2c_address(adap, p->addr, p->flags & I2C_M_RD);
266 if (err || !p->len)
267 continue;
268 if (p->flags & I2C_M_RD)
269 err = sead3_i2c_read(adap, p->buf, p->len);
270 else
271 err = sead3_i2c_write(adap, p->buf, p->len);
272 }
273
274 /* Return the number of messages processed, or the error code. */
275 if (err == 0)
276 err = num;
277
278 return err;
279}
280
281static u32 sead3_pic32_platform_func(struct i2c_adapter *adap)
282{
283 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
284}
285
286static const struct i2c_algorithm sead3_platform_algo = {
287 .master_xfer = sead3_pic32_platform_xfer,
288 .functionality = sead3_pic32_platform_func,
289};
290
291static void sead3_i2c_platform_setup(struct pic32_i2c_platform_data *priv)
292{
293 pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
294 pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
295 pic32_bus_writel(PIC32_I2CCON_ON, priv->base + PIC32_I2CxCONSET);
296 pic32_bus_writel(PIC32_I2CSTAT_BCL | PIC32_I2CSTAT_IWCOL,
297 priv->base + PIC32_I2CxSTATCLR);
298}
299
300static int __devinit sead3_i2c_platform_probe(struct platform_device *pdev)
301{
302 struct pic32_i2c_platform_data *priv;
303 struct resource *r;
304 int ret;
305
306 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
307 if (!r) {
308 ret = -ENODEV;
309 goto out;
310 }
311
312 priv = kzalloc(sizeof(struct pic32_i2c_platform_data), GFP_KERNEL);
313 if (!priv) {
314 ret = -ENOMEM;
315 goto out;
316 }
317
318 priv->base = r->start;
319 if (!priv->base) {
320 ret = -EBUSY;
321 goto out_mem;
322 }
323
324 priv->xfer_timeout = 200;
325 priv->ack_timeout = 200;
326 priv->ctl_timeout = 200;
327
328 priv->adap.nr = pdev->id;
329 priv->adap.algo = &sead3_platform_algo;
330 priv->adap.algo_data = priv;
331 priv->adap.dev.parent = &pdev->dev;
332 strlcpy(priv->adap.name, "SEAD3 PIC32", sizeof(priv->adap.name));
333
334 sead3_i2c_platform_setup(priv);
335
336 ret = i2c_add_numbered_adapter(&priv->adap);
337 if (ret == 0) {
338 platform_set_drvdata(pdev, priv);
339 return 0;
340 }
341
342out_mem:
343 kfree(priv);
344out:
345 return ret;
346}
347
348static int __devexit sead3_i2c_platform_remove(struct platform_device *pdev)
349{
350 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
351
352 platform_set_drvdata(pdev, NULL);
353 i2c_del_adapter(&priv->adap);
354 kfree(priv);
355 return 0;
356}
357
358#ifdef CONFIG_PM
359static int sead3_i2c_platform_suspend(struct platform_device *pdev,
360 pm_message_t state)
361{
362 dev_dbg(&pdev->dev, "i2c_platform_disable\n");
363 return 0;
364}
365
366static int sead3_i2c_platform_resume(struct platform_device *pdev)
367{
368 struct pic32_i2c_platform_data *priv = platform_get_drvdata(pdev);
369
370 dev_dbg(&pdev->dev, "sead3_i2c_platform_setup\n");
371 sead3_i2c_platform_setup(priv);
372
373 return 0;
374}
375#else
376#define sead3_i2c_platform_suspend NULL
377#define sead3_i2c_platform_resume NULL
378#endif
379
380static struct platform_driver sead3_i2c_platform_driver = {
381 .driver = {
382 .name = "sead3-i2c",
383 .owner = THIS_MODULE,
384 },
385 .probe = sead3_i2c_platform_probe,
386 .remove = __devexit_p(sead3_i2c_platform_remove),
387 .suspend = sead3_i2c_platform_suspend,
388 .resume = sead3_i2c_platform_resume,
389};
390
391static int __init sead3_i2c_platform_init(void)
392{
393 return platform_driver_register(&sead3_i2c_platform_driver);
394}
395module_init(sead3_i2c_platform_init);
396
397static void __exit sead3_i2c_platform_exit(void)
398{
399 platform_driver_unregister(&sead3_i2c_platform_driver);
400}
401module_exit(sead3_i2c_platform_exit);
402
403MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
404MODULE_DESCRIPTION("SEAD3 PIC32 I2C driver");
405MODULE_LICENSE("GPL");
diff --git a/arch/mips/mti-sead3/sead3-i2c.c b/arch/mips/mti-sead3/sead3-i2c.c
new file mode 100644
index 00000000000..f70d5fc58ef
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-i2c.c
@@ -0,0 +1,37 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/platform_device.h>
11#include <irq.h>
12
13struct resource sead3_i2c_resources[] = {
14 {
15 .start = 0x805200,
16 .end = 0x8053ff,
17 .flags = IORESOURCE_MEM,
18 },
19};
20
21static struct platform_device sead3_i2c_device = {
22 .name = "sead3-i2c",
23 .id = 0,
24 .num_resources = ARRAY_SIZE(sead3_i2c_resources),
25 .resource = sead3_i2c_resources,
26};
27
28static int __init sead3_i2c_init(void)
29{
30 return platform_device_register(&sead3_i2c_device);
31}
32
33module_init(sead3_i2c_init);
34
35MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
36MODULE_LICENSE("GPL");
37MODULE_DESCRIPTION("I2C probe driver for SEAD3");
diff --git a/arch/mips/mti-sead3/sead3-init.c b/arch/mips/mti-sead3/sead3-init.c
new file mode 100644
index 00000000000..a958cad6fff
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-init.c
@@ -0,0 +1,91 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/io.h>
10
11#include <asm/bootinfo.h>
12#include <asm/cacheflush.h>
13#include <asm/traps.h>
14#include <asm/mips-boards/generic.h>
15#include <asm/mips-boards/prom.h>
16
17extern void prom_init_early_console(char port);
18
19extern char except_vec_nmi;
20extern char except_vec_ejtag_debug;
21
22int prom_argc;
23int *_prom_argv, *_prom_envp;
24
25#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
26
27char *prom_getenv(char *envname)
28{
29 /*
30 * Return a pointer to the given environment variable.
31 * In 64-bit mode: we're using 64-bit pointers, but all pointers
32 * in the PROM structures are only 32-bit, so we need some
33 * workarounds, if we are running in 64-bit mode.
34 */
35 int i, index = 0;
36
37 i = strlen(envname);
38
39 while (prom_envp(index)) {
40 if (strncmp(envname, prom_envp(index), i) == 0)
41 return prom_envp(index+1);
42 index += 2;
43 }
44
45 return NULL;
46}
47
48static void __init mips_nmi_setup(void)
49{
50 void *base;
51
52 base = cpu_has_veic ?
53 (void *)(CAC_BASE + 0xa80) :
54 (void *)(CAC_BASE + 0x380);
55 memcpy(base, &except_vec_nmi, 0x80);
56 flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
57}
58
59static void __init mips_ejtag_setup(void)
60{
61 void *base;
62
63 base = cpu_has_veic ?
64 (void *)(CAC_BASE + 0xa00) :
65 (void *)(CAC_BASE + 0x300);
66 memcpy(base, &except_vec_ejtag_debug, 0x80);
67 flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
68}
69
70void __init prom_init(void)
71{
72 prom_argc = fw_arg0;
73 _prom_argv = (int *) fw_arg1;
74 _prom_envp = (int *) fw_arg2;
75
76 board_nmi_handler_setup = mips_nmi_setup;
77 board_ejtag_handler_setup = mips_ejtag_setup;
78
79 prom_init_cmdline();
80 prom_meminit();
81#ifdef CONFIG_EARLY_PRINTK
82 if ((strstr(prom_getcmdline(), "console=ttyS0")) != NULL)
83 prom_init_early_console(0);
84 else if ((strstr(prom_getcmdline(), "console=ttyS1")) != NULL)
85 prom_init_early_console(1);
86#endif
87#ifdef CONFIG_SERIAL_8250_CONSOLE
88 if ((strstr(prom_getcmdline(), "console=")) == NULL)
89 strcat(prom_getcmdline(), " console=ttyS0,38400n8r");
90#endif
91}
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
new file mode 100644
index 00000000000..e26e08274fc
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-int.c
@@ -0,0 +1,158 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/irq.h>
10#include <linux/io.h>
11
12#include <asm/gic.h>
13#include <asm/irq_cpu.h>
14#include <asm/setup.h>
15
16#include <asm/mips-boards/sead3int.h>
17
18#define SEAD_CONFIG_GIC_PRESENT_SHF 1
19#define SEAD_CONFIG_GIC_PRESENT_MSK (1 << SEAD_CONFIG_GIC_PRESENT_SHF)
20#define SEAD_CONFIG_BASE 0x1b100110
21#define SEAD_CONFIG_SIZE 4
22
23int gic_present;
24static unsigned long sead3_config_reg;
25
26/*
27 * This table defines the setup for each external GIC interrupt. It is
28 * indexed by interrupt number.
29 */
30#define GIC_CPU_NMI GIC_MAP_TO_NMI_MSK
31static struct gic_intr_map gic_intr_map[GIC_NUM_INTRS] = {
32 { 0, GIC_CPU_INT4, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
33 { 0, GIC_CPU_INT3, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
34 { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
35 { 0, GIC_CPU_INT2, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
36 { 0, GIC_CPU_INT1, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
37 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
38 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
39 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
40 { 0, GIC_CPU_INT0, GIC_POL_POS, GIC_TRIG_LEVEL, GIC_FLAG_TRANSPARENT },
41 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
42 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
43 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
44 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
45 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
46 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
47 { GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED, GIC_UNUSED },
48};
49
50asmlinkage void plat_irq_dispatch(void)
51{
52 unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
53 int irq;
54
55 irq = (fls(pending) - CAUSEB_IP - 1);
56 if (irq >= 0)
57 do_IRQ(MIPS_CPU_IRQ_BASE + irq);
58 else
59 spurious_interrupt();
60}
61
62void __init arch_init_irq(void)
63{
64 int i;
65
66 if (!cpu_has_veic) {
67 mips_cpu_irq_init();
68
69 if (cpu_has_vint) {
70 /* install generic handler */
71 for (i = 0; i < 8; i++)
72 set_vi_handler(i, plat_irq_dispatch);
73 }
74 }
75
76 sead3_config_reg = (unsigned long)ioremap_nocache(SEAD_CONFIG_BASE,
77 SEAD_CONFIG_SIZE);
78 gic_present = (REG32(sead3_config_reg) & SEAD_CONFIG_GIC_PRESENT_MSK) >>
79 SEAD_CONFIG_GIC_PRESENT_SHF;
80 pr_info("GIC: %spresent\n", (gic_present) ? "" : "not ");
81 pr_info("EIC: %s\n",
82 (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off");
83
84 if (gic_present)
85 gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, gic_intr_map,
86 ARRAY_SIZE(gic_intr_map), MIPS_GIC_IRQ_BASE);
87}
88
89void gic_enable_interrupt(int irq_vec)
90{
91 unsigned int i, irq_source;
92
93 /* enable all the interrupts associated with this vector */
94 for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
95 irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
96 GIC_SET_INTR_MASK(irq_source);
97 }
98 /* enable all local interrupts associated with this vector */
99 if (gic_shared_intr_map[irq_vec].local_intr_mask) {
100 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
101 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_SMASK),
102 gic_shared_intr_map[irq_vec].local_intr_mask);
103 }
104}
105
106void gic_disable_interrupt(int irq_vec)
107{
108 unsigned int i, irq_source;
109
110 /* disable all the interrupts associated with this vector */
111 for (i = 0; i < gic_shared_intr_map[irq_vec].num_shared_intr; i++) {
112 irq_source = gic_shared_intr_map[irq_vec].intr_list[i];
113 GIC_CLR_INTR_MASK(irq_source);
114 }
115 /* disable all local interrupts associated with this vector */
116 if (gic_shared_intr_map[irq_vec].local_intr_mask) {
117 GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
118 GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_RMASK),
119 gic_shared_intr_map[irq_vec].local_intr_mask);
120 }
121}
122
123void gic_irq_ack(struct irq_data *d)
124{
125 GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
126}
127
128void gic_finish_irq(struct irq_data *d)
129{
130 unsigned int irq = (d->irq - gic_irq_base);
131 unsigned int i, irq_source;
132
133 /* Clear edge detectors. */
134 for (i = 0; i < gic_shared_intr_map[irq].num_shared_intr; i++) {
135 irq_source = gic_shared_intr_map[irq].intr_list[i];
136 if (gic_irq_flags[irq_source] & GIC_TRIG_EDGE)
137 GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq_source);
138 }
139
140 /* Enable interrupts. */
141 GIC_SET_INTR_MASK(irq);
142}
143
144void __init gic_platform_init(int irqs, struct irq_chip *irq_controller)
145{
146 int i;
147
148 /*
149 * For non-EIC mode, we want to setup the GIC in pass-through
150 * mode, as if the GIC didn't exist. Do not map any interrupts
151 * for an external interrupt controller.
152 */
153 if (!cpu_has_veic)
154 return;
155
156 for (i = gic_irq_base; i < (gic_irq_base + irqs); i++)
157 irq_set_chip_and_handler(i, irq_controller, handle_percpu_irq);
158}
diff --git a/arch/mips/mti-sead3/sead3-lcd.c b/arch/mips/mti-sead3/sead3-lcd.c
new file mode 100644
index 00000000000..10b10ed21f7
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-lcd.c
@@ -0,0 +1,43 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/platform_device.h>
10
11static struct resource __initdata sead3_lcd_resource = {
12 .start = 0x1f000400,
13 .end = 0x1f00041f,
14 .flags = IORESOURCE_MEM,
15};
16
17static __init int sead3_lcd_add(void)
18{
19 struct platform_device *pdev;
20 int retval;
21
22 /* SEAD-3 and Cobalt platforms use same display type. */
23 pdev = platform_device_alloc("cobalt-lcd", -1);
24 if (!pdev)
25 return -ENOMEM;
26
27 retval = platform_device_add_resources(pdev, &sead3_lcd_resource, 1);
28 if (retval)
29 goto err_free_device;
30
31 retval = platform_device_add(pdev);
32 if (retval)
33 goto err_free_device;
34
35 return 0;
36
37err_free_device:
38 platform_device_put(pdev);
39
40 return retval;
41}
42
43device_initcall(sead3_lcd_add);
diff --git a/arch/mips/mti-sead3/sead3-leds.c b/arch/mips/mti-sead3/sead3-leds.c
new file mode 100644
index 00000000000..20102a6d414
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-leds.c
@@ -0,0 +1,83 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/leds.h>
10#include <linux/platform_device.h>
11
12#define LEDFLAGS(bits, shift) \
13 ((bits << 8) | (shift << 8))
14
15#define LEDBITS(id, shift, bits) \
16 .name = id #shift, \
17 .flags = LEDFLAGS(bits, shift)
18
19struct led_info led_data_info[] = {
20 { LEDBITS("bit", 0, 1) },
21 { LEDBITS("bit", 1, 1) },
22 { LEDBITS("bit", 2, 1) },
23 { LEDBITS("bit", 3, 1) },
24 { LEDBITS("bit", 4, 1) },
25 { LEDBITS("bit", 5, 1) },
26 { LEDBITS("bit", 6, 1) },
27 { LEDBITS("bit", 7, 1) },
28 { LEDBITS("all", 0, 8) },
29};
30
31static struct led_platform_data led_data = {
32 .num_leds = ARRAY_SIZE(led_data_info),
33 .leds = led_data_info
34};
35
36static struct resource pled_resources[] = {
37 {
38 .start = 0x1f000210,
39 .end = 0x1f000217,
40 .flags = IORESOURCE_MEM
41 }
42};
43
44static struct platform_device pled_device = {
45 .name = "sead3::pled",
46 .id = 0,
47 .dev = {
48 .platform_data = &led_data,
49 },
50 .num_resources = ARRAY_SIZE(pled_resources),
51 .resource = pled_resources
52};
53
54
55static struct resource fled_resources[] = {
56 {
57 .start = 0x1f000218,
58 .end = 0x1f00021f,
59 .flags = IORESOURCE_MEM
60 }
61};
62
63static struct platform_device fled_device = {
64 .name = "sead3::fled",
65 .id = 0,
66 .dev = {
67 .platform_data = &led_data,
68 },
69 .num_resources = ARRAY_SIZE(fled_resources),
70 .resource = fled_resources
71};
72
73static int __init led_init(void)
74{
75 platform_device_register(&pled_device);
76 return platform_device_register(&fled_device);
77}
78
79module_init(led_init);
80
81MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
82MODULE_LICENSE("GPL");
83MODULE_DESCRIPTION("LED probe driver for SEAD-3");
diff --git a/arch/mips/mti-sead3/sead3-memory.c b/arch/mips/mti-sead3/sead3-memory.c
new file mode 100644
index 00000000000..da9244106f8
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-memory.c
@@ -0,0 +1,138 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/bootmem.h>
9
10#include <asm/bootinfo.h>
11#include <asm/sections.h>
12#include <asm/mips-boards/prom.h>
13
14enum yamon_memtypes {
15 yamon_dontuse,
16 yamon_prom,
17 yamon_free,
18};
19
20static struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
21
22/* determined physical memory size, not overridden by command line args */
23unsigned long physical_memsize = 0L;
24
25struct prom_pmemblock * __init prom_getmdesc(void)
26{
27 char *memsize_str, *ptr;
28 unsigned int memsize;
29 static char cmdline[COMMAND_LINE_SIZE] __initdata;
30 long val;
31 int tmp;
32
33 /* otherwise look in the environment */
34 memsize_str = prom_getenv("memsize");
35 if (!memsize_str) {
36 pr_warn("memsize not set in boot prom, set to default 32Mb\n");
37 physical_memsize = 0x02000000;
38 } else {
39 tmp = kstrtol(memsize_str, 0, &val);
40 physical_memsize = (unsigned long)val;
41 }
42
43#ifdef CONFIG_CPU_BIG_ENDIAN
44 /* SOC-it swaps, or perhaps doesn't swap, when DMA'ing the last
45 word of physical memory */
46 physical_memsize -= PAGE_SIZE;
47#endif
48
49 /* Check the command line for a memsize directive that overrides
50 the physical/default amount */
51 strcpy(cmdline, arcs_cmdline);
52 ptr = strstr(cmdline, "memsize=");
53 if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
54 ptr = strstr(ptr, " memsize=");
55
56 if (ptr)
57 memsize = memparse(ptr + 8, &ptr);
58 else
59 memsize = physical_memsize;
60
61 memset(mdesc, 0, sizeof(mdesc));
62
63 mdesc[0].type = yamon_dontuse;
64 mdesc[0].base = 0x00000000;
65 mdesc[0].size = 0x00001000;
66
67 mdesc[1].type = yamon_prom;
68 mdesc[1].base = 0x00001000;
69 mdesc[1].size = 0x000ef000;
70
71 /*
72 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
73 * south bridge and PCI access always forwarded to the ISA Bus and
74 * BIOSCS# is always generated.
75 * This mean that this area can't be used as DMA memory for PCI
76 * devices.
77 */
78 mdesc[2].type = yamon_dontuse;
79 mdesc[2].base = 0x000f0000;
80 mdesc[2].size = 0x00010000;
81
82 mdesc[3].type = yamon_dontuse;
83 mdesc[3].base = 0x00100000;
84 mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) -
85 mdesc[3].base;
86
87 mdesc[4].type = yamon_free;
88 mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
89 mdesc[4].size = memsize - mdesc[4].base;
90
91 return &mdesc[0];
92}
93
94static int __init prom_memtype_classify(unsigned int type)
95{
96 switch (type) {
97 case yamon_free:
98 return BOOT_MEM_RAM;
99 case yamon_prom:
100 return BOOT_MEM_ROM_DATA;
101 default:
102 return BOOT_MEM_RESERVED;
103 }
104}
105
106void __init prom_meminit(void)
107{
108 struct prom_pmemblock *p;
109
110 p = prom_getmdesc();
111
112 while (p->size) {
113 long type;
114 unsigned long base, size;
115
116 type = prom_memtype_classify(p->type);
117 base = p->base;
118 size = p->size;
119
120 add_memory_region(base, size, type);
121 p++;
122 }
123}
124
125void __init prom_free_prom_memory(void)
126{
127 unsigned long addr;
128 int i;
129
130 for (i = 0; i < boot_mem_map.nr_map; i++) {
131 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
132 continue;
133
134 addr = boot_mem_map.map[i].addr;
135 free_init_pages("prom memory",
136 addr, addr + boot_mem_map.map[i].size);
137 }
138}
diff --git a/arch/mips/mti-sead3/sead3-mtd.c b/arch/mips/mti-sead3/sead3-mtd.c
new file mode 100644
index 00000000000..ffa35f50978
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-mtd.c
@@ -0,0 +1,54 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9#include <linux/platform_device.h>
10#include <linux/mtd/physmap.h>
11
12static struct mtd_partition sead3_mtd_partitions[] = {
13 {
14 .name = "User FS",
15 .offset = 0x00000000,
16 .size = 0x01fc0000,
17 }, {
18 .name = "Board Config",
19 .offset = 0x01fc0000,
20 .size = 0x00040000,
21 .mask_flags = MTD_WRITEABLE
22 },
23};
24
25static struct physmap_flash_data sead3_flash_data = {
26 .width = 4,
27 .nr_parts = ARRAY_SIZE(sead3_mtd_partitions),
28 .parts = sead3_mtd_partitions
29};
30
31static struct resource sead3_flash_resource = {
32 .start = 0x1c000000,
33 .end = 0x1dffffff,
34 .flags = IORESOURCE_MEM
35};
36
37static struct platform_device sead3_flash = {
38 .name = "physmap-flash",
39 .id = 0,
40 .dev = {
41 .platform_data = &sead3_flash_data,
42 },
43 .num_resources = 1,
44 .resource = &sead3_flash_resource,
45};
46
47static int __init sead3_mtd_init(void)
48{
49 platform_device_register(&sead3_flash);
50
51 return 0;
52}
53
54module_init(sead3_mtd_init)
diff --git a/arch/mips/mti-sead3/sead3-net.c b/arch/mips/mti-sead3/sead3-net.c
new file mode 100644
index 00000000000..04d704df609
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-net.c
@@ -0,0 +1,51 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/irq.h>
10#include <linux/platform_device.h>
11#include <linux/smsc911x.h>
12
13static struct smsc911x_platform_config sead3_smsc911x_data = {
14 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
15 .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
16 .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
17 .phy_interface = PHY_INTERFACE_MODE_MII,
18};
19
20struct resource sead3_net_resourcess[] = {
21 {
22 .start = 0x1f010000,
23 .end = 0x1f01ffff,
24 .flags = IORESOURCE_MEM
25 },
26 {
27 .start = MIPS_CPU_IRQ_BASE + 6,
28 .flags = IORESOURCE_IRQ
29 }
30};
31
32static struct platform_device sead3_net_device = {
33 .name = "smsc911x",
34 .id = 0,
35 .dev = {
36 .platform_data = &sead3_smsc911x_data,
37 },
38 .num_resources = ARRAY_SIZE(sead3_net_resourcess),
39 .resource = sead3_net_resourcess
40};
41
42static int __init sead3_net_init(void)
43{
44 return platform_device_register(&sead3_net_device);
45}
46
47module_init(sead3_net_init);
48
49MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
50MODULE_LICENSE("GPL");
51MODULE_DESCRIPTION("Network probe driver for SEAD-3");
diff --git a/arch/mips/mti-sead3/sead3-pic32-bus.c b/arch/mips/mti-sead3/sead3-pic32-bus.c
new file mode 100644
index 00000000000..9f0d89bc800
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-pic32-bus.c
@@ -0,0 +1,103 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/delay.h>
9#include <linux/kernel.h>
10#include <linux/spinlock.h>
11#include <linux/init.h>
12#include <linux/io.h>
13#include <linux/errno.h>
14
15#define PIC32_NULL 0x00
16#define PIC32_RD 0x01
17#define PIC32_SYSRD 0x02
18#define PIC32_WR 0x10
19#define PIC32_SYSWR 0x20
20#define PIC32_IRQ_CLR 0x40
21#define PIC32_STATUS 0x80
22
23#define DELAY() udelay(100) /* FIXME: needed? */
24
25/* spinlock to ensure atomic access to PIC32 */
26static DEFINE_SPINLOCK(pic32_bus_lock);
27
28/* FIXME: io_remap these */
29static void __iomem *bus_xfer = (void __iomem *)0xbf000600;
30static void __iomem *bus_status = (void __iomem *)0xbf000060;
31
32static inline unsigned int ioready(void)
33{
34 return readl(bus_status) & 1;
35}
36
37static inline void wait_ioready(void)
38{
39 do { } while (!ioready());
40}
41
42static inline void wait_ioclear(void)
43{
44 do { } while (ioready());
45}
46
47static inline void check_ioclear(void)
48{
49 if (ioready()) {
50 pr_debug("ioclear: initially busy\n");
51 do {
52 (void) readl(bus_xfer);
53 DELAY();
54 } while (ioready());
55 pr_debug("ioclear: cleared busy\n");
56 }
57}
58
59u32 pic32_bus_readl(u32 reg)
60{
61 unsigned long flags;
62 u32 status, val;
63
64 spin_lock_irqsave(&pic32_bus_lock, flags);
65
66 check_ioclear();
67
68 writel((PIC32_RD << 24) | (reg & 0x00ffffff), bus_xfer);
69 DELAY();
70 wait_ioready();
71 status = readl(bus_xfer);
72 DELAY();
73 val = readl(bus_xfer);
74 wait_ioclear();
75
76 pr_debug("pic32_bus_readl: *%x -> %x (status=%x)\n", reg, val, status);
77
78 spin_unlock_irqrestore(&pic32_bus_lock, flags);
79
80 return val;
81}
82
83void pic32_bus_writel(u32 val, u32 reg)
84{
85 unsigned long flags;
86 u32 status;
87
88 spin_lock_irqsave(&pic32_bus_lock, flags);
89
90 check_ioclear();
91
92 writel((PIC32_WR << 24) | (reg & 0x00ffffff), bus_xfer);
93 DELAY();
94 writel(val, bus_xfer);
95 DELAY();
96 wait_ioready();
97 status = readl(bus_xfer);
98 wait_ioclear();
99
100 pr_debug("pic32_bus_writel: *%x <- %x (status=%x)\n", reg, val, status);
101
102 spin_unlock_irqrestore(&pic32_bus_lock, flags);
103}
diff --git a/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
new file mode 100644
index 00000000000..46509b0a620
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-pic32-i2c-drv.c
@@ -0,0 +1,435 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/delay.h>
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/spinlock.h>
12#include <linux/platform_device.h>
13#include <linux/init.h>
14#include <linux/errno.h>
15#include <linux/i2c.h>
16#include <linux/slab.h>
17
18#define PIC32_I2CxCON 0x0000
19#define PIC32_I2CxCONCLR 0x0004
20#define PIC32_I2CxCONSET 0x0008
21#define PIC32_I2CxCONINV 0x000C
22#define I2CCON_ON (1<<15)
23#define I2CCON_FRZ (1<<14)
24#define I2CCON_SIDL (1<<13)
25#define I2CCON_SCLREL (1<<12)
26#define I2CCON_STRICT (1<<11)
27#define I2CCON_A10M (1<<10)
28#define I2CCON_DISSLW (1<<9)
29#define I2CCON_SMEN (1<<8)
30#define I2CCON_GCEN (1<<7)
31#define I2CCON_STREN (1<<6)
32#define I2CCON_ACKDT (1<<5)
33#define I2CCON_ACKEN (1<<4)
34#define I2CCON_RCEN (1<<3)
35#define I2CCON_PEN (1<<2)
36#define I2CCON_RSEN (1<<1)
37#define I2CCON_SEN (1<<0)
38
39#define PIC32_I2CxSTAT 0x0010
40#define PIC32_I2CxSTATCLR 0x0014
41#define PIC32_I2CxSTATSET 0x0018
42#define PIC32_I2CxSTATINV 0x001C
43#define I2CSTAT_ACKSTAT (1<<15)
44#define I2CSTAT_TRSTAT (1<<14)
45#define I2CSTAT_BCL (1<<10)
46#define I2CSTAT_GCSTAT (1<<9)
47#define I2CSTAT_ADD10 (1<<8)
48#define I2CSTAT_IWCOL (1<<7)
49#define I2CSTAT_I2COV (1<<6)
50#define I2CSTAT_DA (1<<5)
51#define I2CSTAT_P (1<<4)
52#define I2CSTAT_S (1<<3)
53#define I2CSTAT_RW (1<<2)
54#define I2CSTAT_RBF (1<<1)
55#define I2CSTAT_TBF (1<<0)
56
57#define PIC32_I2CxADD 0x0020
58#define PIC32_I2CxADDCLR 0x0024
59#define PIC32_I2CxADDSET 0x0028
60#define PIC32_I2CxADDINV 0x002C
61#define PIC32_I2CxMSK 0x0030
62#define PIC32_I2CxMSKCLR 0x0034
63#define PIC32_I2CxMSKSET 0x0038
64#define PIC32_I2CxMSKINV 0x003C
65#define PIC32_I2CxBRG 0x0040
66#define PIC32_I2CxBRGCLR 0x0044
67#define PIC32_I2CxBRGSET 0x0048
68#define PIC32_I2CxBRGINV 0x004C
69#define PIC32_I2CxTRN 0x0050
70#define PIC32_I2CxTRNCLR 0x0054
71#define PIC32_I2CxTRNSET 0x0058
72#define PIC32_I2CxTRNINV 0x005C
73#define PIC32_I2CxRCV 0x0060
74
75struct i2c_platform_data {
76 u32 base;
77 struct i2c_adapter adap;
78 u32 xfer_timeout;
79 u32 ack_timeout;
80 u32 ctl_timeout;
81};
82
83extern u32 pic32_bus_readl(u32 reg);
84extern void pic32_bus_writel(u32 val, u32 reg);
85
86static inline void
87StartI2C(struct i2c_platform_data *adap)
88{
89 pr_debug("StartI2C\n");
90 pic32_bus_writel(I2CCON_SEN, adap->base + PIC32_I2CxCONSET);
91}
92
93static inline void
94StopI2C(struct i2c_platform_data *adap)
95{
96 pr_debug("StopI2C\n");
97 pic32_bus_writel(I2CCON_PEN, adap->base + PIC32_I2CxCONSET);
98}
99
100static inline void
101AckI2C(struct i2c_platform_data *adap)
102{
103 pr_debug("AckI2C\n");
104 pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONCLR);
105 pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
106}
107
108static inline void
109NotAckI2C(struct i2c_platform_data *adap)
110{
111 pr_debug("NakI2C\n");
112 pic32_bus_writel(I2CCON_ACKDT, adap->base + PIC32_I2CxCONSET);
113 pic32_bus_writel(I2CCON_ACKEN, adap->base + PIC32_I2CxCONSET);
114}
115
116static inline int
117IdleI2C(struct i2c_platform_data *adap)
118{
119 int i;
120
121 pr_debug("IdleI2C\n");
122 for (i = 0; i < adap->ctl_timeout; i++) {
123 if (((pic32_bus_readl(adap->base + PIC32_I2CxCON) &
124 (I2CCON_ACKEN | I2CCON_RCEN | I2CCON_PEN | I2CCON_RSEN |
125 I2CCON_SEN)) == 0) &&
126 ((pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
127 (I2CSTAT_TRSTAT)) == 0))
128 return 0;
129 udelay(1);
130 }
131 return -ETIMEDOUT;
132}
133
134static inline u32
135MasterWriteI2C(struct i2c_platform_data *adap, u32 byte)
136{
137 pr_debug("MasterWriteI2C\n");
138
139 pic32_bus_writel(byte, adap->base + PIC32_I2CxTRN);
140
141 return pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_IWCOL;
142}
143
144static inline u32
145MasterReadI2C(struct i2c_platform_data *adap)
146{
147 pr_debug("MasterReadI2C\n");
148
149 pic32_bus_writel(I2CCON_RCEN, adap->base + PIC32_I2CxCONSET);
150
151 while (pic32_bus_readl(adap->base + PIC32_I2CxCON) & I2CCON_RCEN)
152 ;
153
154 pic32_bus_writel(I2CSTAT_I2COV, adap->base + PIC32_I2CxSTATCLR);
155
156 return pic32_bus_readl(adap->base + PIC32_I2CxRCV);
157}
158
159static int
160do_address(struct i2c_platform_data *adap, unsigned int addr, int rd)
161{
162 pr_debug("doaddress\n");
163
164 IdleI2C(adap);
165 StartI2C(adap);
166 IdleI2C(adap);
167
168 addr <<= 1;
169 if (rd)
170 addr |= 1;
171
172 if (MasterWriteI2C(adap, addr))
173 return -EIO;
174 IdleI2C(adap);
175 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) & I2CSTAT_ACKSTAT)
176 return -EIO;
177 return 0;
178}
179
180static int
181i2c_read(struct i2c_platform_data *adap, unsigned char *buf,
182 unsigned int len)
183{
184 int i;
185 u32 data;
186
187 pr_debug("i2c_read\n");
188
189 i = 0;
190 while (i < len) {
191 data = MasterReadI2C(adap);
192 buf[i++] = data;
193 if (i < len)
194 AckI2C(adap);
195 else
196 NotAckI2C(adap);
197 }
198
199 StopI2C(adap);
200 IdleI2C(adap);
201 return 0;
202}
203
204static int
205i2c_write(struct i2c_platform_data *adap, unsigned char *buf,
206 unsigned int len)
207{
208 int i;
209 u32 data;
210
211 pr_debug("i2c_write\n");
212
213 i = 0;
214 while (i < len) {
215 data = buf[i];
216 if (MasterWriteI2C(adap, data))
217 return -EIO;
218 IdleI2C(adap);
219 if (pic32_bus_readl(adap->base + PIC32_I2CxSTAT) &
220 I2CSTAT_ACKSTAT)
221 return -EIO;
222 i++;
223 }
224
225 StopI2C(adap);
226 IdleI2C(adap);
227 return 0;
228}
229
230static int
231platform_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
232{
233 struct i2c_platform_data *adap = i2c_adap->algo_data;
234 struct i2c_msg *p;
235 int i, err = 0;
236
237 pr_debug("platform_xfer\n");
238 for (i = 0; i < num; i++) {
239#define __BUFSIZE 80
240 int ii;
241 static char buf[__BUFSIZE];
242 char *b = buf;
243
244 p = &msgs[i];
245 b += sprintf(buf, " [%d bytes]", p->len);
246 if ((p->flags & I2C_M_RD) == 0) {
247 for (ii = 0; ii < p->len; ii++) {
248 if (b < &buf[__BUFSIZE-4]) {
249 b += sprintf(b, " %02x", p->buf[ii]);
250 } else {
251 strcat(b, "...");
252 break;
253 }
254 }
255 }
256 pr_debug("xfer%d: DevAddr: %04x Op:%s Data:%s\n", i, p->addr,
257 (p->flags & I2C_M_RD) ? "Rd" : "Wr", buf);
258 }
259
260
261 for (i = 0; !err && i < num; i++) {
262 p = &msgs[i];
263 err = do_address(adap, p->addr, p->flags & I2C_M_RD);
264 if (err || !p->len)
265 continue;
266 if (p->flags & I2C_M_RD)
267 err = i2c_read(adap, p->buf, p->len);
268 else
269 err = i2c_write(adap, p->buf, p->len);
270 }
271
272 /* Return the number of messages processed, or the error code. */
273 if (err == 0)
274 err = num;
275
276 return err;
277}
278
279static u32
280platform_func(struct i2c_adapter *adap)
281{
282 pr_debug("platform_algo\n");
283 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
284}
285
286static const struct i2c_algorithm platform_algo = {
287 .master_xfer = platform_xfer,
288 .functionality = platform_func,
289};
290
291static void i2c_platform_setup(struct i2c_platform_data *priv)
292{
293 pr_debug("i2c_platform_setup\n");
294
295 pic32_bus_writel(500, priv->base + PIC32_I2CxBRG);
296 pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONCLR);
297 pic32_bus_writel(I2CCON_ON, priv->base + PIC32_I2CxCONSET);
298 pic32_bus_writel((I2CSTAT_BCL | I2CSTAT_IWCOL),
299 (priv->base + PIC32_I2CxSTATCLR));
300}
301
302static void i2c_platform_disable(struct i2c_platform_data *priv)
303{
304 pr_debug("i2c_platform_disable\n");
305}
306
307static int __devinit
308i2c_platform_probe(struct platform_device *pdev)
309{
310 struct i2c_platform_data *priv;
311 struct resource *r;
312 int ret;
313
314 pr_debug("i2c_platform_probe\n");
315 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
316 if (!r) {
317 ret = -ENODEV;
318 goto out;
319 }
320
321 priv = kzalloc(sizeof(struct i2c_platform_data), GFP_KERNEL);
322 if (!priv) {
323 ret = -ENOMEM;
324 goto out;
325 }
326
327 /* FIXME: need to allocate resource in PIC32 space */
328#if 0
329 priv->base = bus_request_region(r->start, resource_size(r),
330 pdev->name);
331#else
332 priv->base = r->start;
333#endif
334 if (!priv->base) {
335 ret = -EBUSY;
336 goto out_mem;
337 }
338
339 priv->xfer_timeout = 200;
340 priv->ack_timeout = 200;
341 priv->ctl_timeout = 200;
342
343 priv->adap.nr = pdev->id;
344 priv->adap.algo = &platform_algo;
345 priv->adap.algo_data = priv;
346 priv->adap.dev.parent = &pdev->dev;
347 strlcpy(priv->adap.name, "PIC32 I2C", sizeof(priv->adap.name));
348
349 i2c_platform_setup(priv);
350
351 ret = i2c_add_numbered_adapter(&priv->adap);
352 if (ret == 0) {
353 platform_set_drvdata(pdev, priv);
354 return 0;
355 }
356
357 i2c_platform_disable(priv);
358
359out_mem:
360 kfree(priv);
361out:
362 return ret;
363}
364
365static int __devexit
366i2c_platform_remove(struct platform_device *pdev)
367{
368 struct i2c_platform_data *priv = platform_get_drvdata(pdev);
369
370 pr_debug("i2c_platform_remove\n");
371 platform_set_drvdata(pdev, NULL);
372 i2c_del_adapter(&priv->adap);
373 i2c_platform_disable(priv);
374 kfree(priv);
375 return 0;
376}
377
378#ifdef CONFIG_PM
379static int
380i2c_platform_suspend(struct platform_device *pdev, pm_message_t state)
381{
382 struct i2c_platform_data *priv = platform_get_drvdata(pdev);
383
384 dev_dbg(&pdev->dev, "i2c_platform_disable\n");
385 i2c_platform_disable(priv);
386
387 return 0;
388}
389
390static int
391i2c_platform_resume(struct platform_device *pdev)
392{
393 struct i2c_platform_data *priv = platform_get_drvdata(pdev);
394
395 dev_dbg(&pdev->dev, "i2c_platform_setup\n");
396 i2c_platform_setup(priv);
397
398 return 0;
399}
400#else
401#define i2c_platform_suspend NULL
402#define i2c_platform_resume NULL
403#endif
404
405static struct platform_driver i2c_platform_driver = {
406 .driver = {
407 .name = "i2c_pic32",
408 .owner = THIS_MODULE,
409 },
410 .probe = i2c_platform_probe,
411 .remove = __devexit_p(i2c_platform_remove),
412 .suspend = i2c_platform_suspend,
413 .resume = i2c_platform_resume,
414};
415
416static int __init
417i2c_platform_init(void)
418{
419 pr_debug("i2c_platform_init\n");
420 return platform_driver_register(&i2c_platform_driver);
421}
422
423static void __exit
424i2c_platform_exit(void)
425{
426 pr_debug("i2c_platform_exit\n");
427 platform_driver_unregister(&i2c_platform_driver);
428}
429
430MODULE_AUTHOR("Chris Dearman, MIPS Technologies INC.");
431MODULE_DESCRIPTION("PIC32 I2C driver");
432MODULE_LICENSE("GPL");
433
434module_init(i2c_platform_init);
435module_exit(i2c_platform_exit);
diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c
new file mode 100644
index 00000000000..6c3b33dbed1
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-platform.c
@@ -0,0 +1,45 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/serial_8250.h>
11
12#define UART(base, int) \
13{ \
14 .mapbase = base, \
15 .irq = int, \
16 .uartclk = 14745600, \
17 .iotype = UPIO_MEM32, \
18 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
19 .regshift = 2, \
20}
21
22static struct plat_serial8250_port uart8250_data[] = {
23 UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */
24 UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */
25 { },
26};
27
28static struct platform_device uart8250_device = {
29 .name = "serial8250",
30 .id = PLAT8250_DEV_PLATFORM2,
31 .dev = {
32 .platform_data = uart8250_data,
33 },
34};
35
36static int __init uart8250_init(void)
37{
38 return platform_device_register(&uart8250_device);
39}
40
41module_init(uart8250_init);
42
43MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
44MODULE_LICENSE("GPL");
45MODULE_DESCRIPTION("8250 UART probe driver for SEAD3");
diff --git a/arch/mips/mti-sead3/sead3-reset.c b/arch/mips/mti-sead3/sead3-reset.c
new file mode 100644
index 00000000000..20475c5e7b9
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-reset.c
@@ -0,0 +1,39 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/io.h>
9#include <linux/pm.h>
10
11#include <asm/reboot.h>
12#include <asm/mips-boards/generic.h>
13
14static void mips_machine_restart(char *command)
15{
16 unsigned int __iomem *softres_reg =
17 ioremap(SOFTRES_REG, sizeof(unsigned int));
18
19 __raw_writel(GORESET, softres_reg);
20}
21
22static void mips_machine_halt(void)
23{
24 unsigned int __iomem *softres_reg =
25 ioremap(SOFTRES_REG, sizeof(unsigned int));
26
27 __raw_writel(GORESET, softres_reg);
28}
29
30static int __init mips_reboot_setup(void)
31{
32 _machine_restart = mips_machine_restart;
33 _machine_halt = mips_machine_halt;
34 pm_power_off = mips_machine_halt;
35
36 return 0;
37}
38
39arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/mti-sead3/sead3-serial.c b/arch/mips/mti-sead3/sead3-serial.c
new file mode 100644
index 00000000000..bc52705bbee
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-serial.c
@@ -0,0 +1,45 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/serial_8250.h>
11
12#define UART(base, int) \
13{ \
14 .mapbase = base, \
15 .irq = int, \
16 .uartclk = 14745600, \
17 .iotype = UPIO_MEM32, \
18 .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
19 .regshift = 2, \
20}
21
22static struct plat_serial8250_port uart8250_data[] = {
23 UART(0x1f000900, MIPS_CPU_IRQ_BASE + 4), /* ttyS0 = USB */
24 UART(0x1f000800, MIPS_CPU_IRQ_BASE + 4), /* ttyS1 = RS232 */
25 { },
26};
27
28static struct platform_device uart8250_device = {
29 .name = "serial8250",
30 .id = PLAT8250_DEV_PLATFORM,
31 .dev = {
32 .platform_data = uart8250_data,
33 },
34};
35
36static int __init uart8250_init(void)
37{
38 return platform_device_register(&uart8250_device);
39}
40
41module_init(uart8250_init);
42
43MODULE_AUTHOR("Chris Dearman <chris@mips.com>");
44MODULE_LICENSE("GPL");
45MODULE_DESCRIPTION("8250 UART probe driver for the SEAD-3 platform");
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
new file mode 100644
index 00000000000..8ad46ad31b4
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -0,0 +1,20 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9
10int coherentio; /* 0 => no DMA cache coherency (may be set by user) */
11int hw_coherentio; /* 0 => no HW DMA cache coherency (reflects real HW) */
12
13const char *get_system_type(void)
14{
15 return "MIPS SEAD3";
16}
17
18void __init plat_mem_setup(void)
19{
20}
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c
new file mode 100644
index 00000000000..048e781a17a
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-time.c
@@ -0,0 +1,117 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 */
8#include <linux/init.h>
9
10#include <asm/setup.h>
11#include <asm/time.h>
12#include <asm/irq.h>
13#include <asm/mips-boards/generic.h>
14#include <asm/mips-boards/prom.h>
15
16unsigned long cpu_khz;
17
18static int mips_cpu_timer_irq;
19static int mips_cpu_perf_irq;
20
21static void mips_timer_dispatch(void)
22{
23 do_IRQ(mips_cpu_timer_irq);
24}
25
26static void mips_perf_dispatch(void)
27{
28 do_IRQ(mips_cpu_perf_irq);
29}
30
31static void __iomem *status_reg = (void __iomem *)0xbf000410;
32
33/*
34 * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect.
35 */
36static unsigned int __init estimate_cpu_frequency(void)
37{
38 unsigned int prid = read_c0_prid() & 0xffff00;
39 unsigned int tick = 0;
40 unsigned int freq;
41 unsigned int orig;
42 unsigned long flags;
43
44 local_irq_save(flags);
45
46 orig = readl(status_reg) & 0x2; /* get original sample */
47 /* wait for transition */
48 while ((readl(status_reg) & 0x2) == orig)
49 ;
50 orig = orig ^ 0x2; /* flip the bit */
51
52 write_c0_count(0);
53
54 /* wait 1 second (the sampling clock transitions every 10ms) */
55 while (tick < 100) {
56 /* wait for transition */
57 while ((readl(status_reg) & 0x2) == orig)
58 ;
59 orig = orig ^ 0x2; /* flip the bit */
60 tick++;
61 }
62
63 freq = read_c0_count();
64
65 local_irq_restore(flags);
66
67 mips_hpt_frequency = freq;
68
69 /* Adjust for processor */
70 if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
71 (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
72 freq *= 2;
73
74 freq += 5000; /* rounding */
75 freq -= freq%10000;
76
77 return freq ;
78}
79
80void read_persistent_clock(struct timespec *ts)
81{
82 ts->tv_sec = 0;
83 ts->tv_nsec = 0;
84}
85
86static void __init plat_perf_setup(void)
87{
88 if (cp0_perfcount_irq >= 0) {
89 if (cpu_has_vint)
90 set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
91 mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
92 }
93}
94
95unsigned int __cpuinit get_c0_compare_int(void)
96{
97 if (cpu_has_vint)
98 set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
99 mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
100 return mips_cpu_timer_irq;
101}
102
103void __init plat_time_init(void)
104{
105 unsigned int est_freq;
106
107 est_freq = estimate_cpu_frequency();
108
109 pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000),
110 (est_freq % 1000000) * 100 / 1000000);
111
112 cpu_khz = est_freq / 1000;
113
114 mips_scroll_message();
115
116 plat_perf_setup();
117}