summaryrefslogtreecommitdiff
path: root/arch/mips/mti-sead3
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-08-05 17:04:01 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2015-08-05 17:04:01 -0300
commit57f0f512b273f60d52568b8c6b77e17f5636edc0 (patch)
tree5e910f0e82173f4ef4f51111366a3f1299037a7b /arch/mips/mti-sead3
Initial import
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.c77
-rw-r--r--arch/mips/mti-sead3/sead3-console.c46
-rw-r--r--arch/mips/mti-sead3/sead3-display.c77
-rw-r--r--arch/mips/mti-sead3/sead3-init.c152
-rw-r--r--arch/mips/mti-sead3/sead3-int.c42
-rw-r--r--arch/mips/mti-sead3/sead3-lcd.c43
-rw-r--r--arch/mips/mti-sead3/sead3-platform.c223
-rw-r--r--arch/mips/mti-sead3/sead3-reset.c40
-rw-r--r--arch/mips/mti-sead3/sead3-setup.c111
-rw-r--r--arch/mips/mti-sead3/sead3-time.c98
12 files changed, 935 insertions, 0 deletions
diff --git a/arch/mips/mti-sead3/Makefile b/arch/mips/mti-sead3/Makefile
new file mode 100644
index 000000000..ecd71db62
--- /dev/null
+++ b/arch/mips/mti-sead3/Makefile
@@ -0,0 +1,19 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+#
+# Copyright (C) 2008 Wind River Systems, Inc.
+# written by Ralf Baechle <ralf@linux-mips.org>
+#
+# Copyright (C) 2012 MIPS Technoligies, Inc. All rights reserved.
+# Steven J. Hill <sjhill@mips.com>
+#
+obj-y := sead3-lcd.o sead3-display.o sead3-init.o \
+ sead3-int.o sead3-platform.o sead3-reset.o \
+ sead3-setup.o sead3-time.o
+
+obj-y += leds-sead3.o
+
+obj-$(CONFIG_EARLY_PRINTK) += sead3-console.o
+
+CFLAGS_sead3-setup.o = -I$(src)/../../../scripts/dtc/libfdt
diff --git a/arch/mips/mti-sead3/Platform b/arch/mips/mti-sead3/Platform
new file mode 100644
index 000000000..387092427
--- /dev/null
+++ b/arch/mips/mti-sead3/Platform
@@ -0,0 +1,7 @@
+#
+# MIPS SEAD-3 board
+#
+platform-$(CONFIG_MIPS_SEAD3) += mti-sead3/
+cflags-$(CONFIG_MIPS_SEAD3) += -I$(srctree)/arch/mips/include/asm/mach-sead3
+load-$(CONFIG_MIPS_SEAD3) += 0xffffffff80100000
+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 000000000..c938ceeb8
--- /dev/null
+++ b/arch/mips/mti-sead3/leds-sead3.c
@@ -0,0 +1,77 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2015 Imagination Technologies, Inc.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/mips-boards/sead3-addr.h>
+
+static void sead3_pled_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ writel(value, (void __iomem *)SEAD3_CPLD_P_LED);
+}
+
+static void sead3_fled_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ writel(value, (void __iomem *)SEAD3_CPLD_F_LED);
+}
+
+static struct led_classdev sead3_pled = {
+ .name = "sead3::pled",
+ .brightness_set = sead3_pled_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+};
+
+static struct led_classdev sead3_fled = {
+ .name = "sead3::fled",
+ .brightness_set = sead3_fled_set,
+ .flags = LED_CORE_SUSPENDRESUME,
+};
+
+static int sead3_led_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = led_classdev_register(&pdev->dev, &sead3_pled);
+ if (ret < 0)
+ return ret;
+
+ ret = led_classdev_register(&pdev->dev, &sead3_fled);
+ if (ret < 0)
+ led_classdev_unregister(&sead3_pled);
+
+ return ret;
+}
+
+static int sead3_led_remove(struct platform_device *pdev)
+{
+ led_classdev_unregister(&sead3_pled);
+ led_classdev_unregister(&sead3_fled);
+ return 0;
+}
+
+static struct platform_driver sead3_led_driver = {
+ .probe = sead3_led_probe,
+ .remove = sead3_led_remove,
+ .driver = {
+ .name = "sead3-led",
+ },
+};
+
+module_platform_driver(sead3_led_driver);
+
+MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
+MODULE_DESCRIPTION("SEAD3 LED driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/mti-sead3/sead3-console.c b/arch/mips/mti-sead3/sead3-console.c
new file mode 100644
index 000000000..031f47d69
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-console.c
@@ -0,0 +1,46 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial_reg.h>
+#include <linux/io.h>
+
+#define SEAD_UART1_REGS_BASE 0xbf000800 /* ttyS1 = DB9 port */
+#define SEAD_UART0_REGS_BASE 0xbf000900 /* ttyS0 = USB port */
+#define PORT(base_addr, offset) ((unsigned int __iomem *)(base_addr+(offset)*4))
+
+static char console_port = 1;
+
+static inline unsigned int serial_in(int offset, unsigned int base_addr)
+{
+ return __raw_readl(PORT(base_addr, offset)) & 0xff;
+}
+
+static inline void serial_out(int offset, int value, unsigned int base_addr)
+{
+ __raw_writel(value, PORT(base_addr, offset));
+}
+
+void __init fw_init_early_console(char port)
+{
+ console_port = port;
+}
+
+int prom_putchar(char c)
+{
+ unsigned int base_addr;
+
+ base_addr = console_port ? SEAD_UART1_REGS_BASE : SEAD_UART0_REGS_BASE;
+
+ while ((serial_in(UART_LSR, base_addr) & UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(UART_TX, c, base_addr);
+
+ return 1;
+}
diff --git a/arch/mips/mti-sead3/sead3-display.c b/arch/mips/mti-sead3/sead3-display.c
new file mode 100644
index 000000000..948759919
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-display.c
@@ -0,0 +1,77 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/timer.h>
+#include <linux/io.h>
+#include <asm/mips-boards/generic.h>
+
+static unsigned int display_count;
+static unsigned int max_display_count;
+
+#define LCD_DISPLAY_POS_BASE 0x1f000400
+#define DISPLAY_LCDINSTRUCTION (0*2)
+#define DISPLAY_LCDDATA (1*2)
+#define DISPLAY_CPLDSTATUS (2*2)
+#define DISPLAY_CPLDDATA (3*2)
+#define LCD_SETDDRAM 0x80
+#define LCD_IR_BF 0x80
+
+const char display_string[] = " LINUX ON SEAD3 ";
+
+static void scroll_display_message(unsigned long data);
+static DEFINE_TIMER(mips_scroll_timer, scroll_display_message, HZ, 0);
+
+static void lcd_wait(unsigned int __iomem *display)
+{
+ /* Wait for CPLD state machine to become idle. */
+ do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
+
+ do {
+ __raw_readl(display + DISPLAY_LCDINSTRUCTION);
+
+ /* Wait for CPLD state machine to become idle. */
+ do { } while (__raw_readl(display + DISPLAY_CPLDSTATUS) & 1);
+ } while (__raw_readl(display + DISPLAY_CPLDDATA) & LCD_IR_BF);
+}
+
+void mips_display_message(const char *str)
+{
+ static unsigned int __iomem *display;
+ char ch;
+ int i;
+
+ if (unlikely(display == NULL))
+ display = ioremap_nocache(LCD_DISPLAY_POS_BASE,
+ (8 * sizeof(int)));
+
+ for (i = 0; i < 16; i++) {
+ if (*str)
+ ch = *str++;
+ else
+ ch = ' ';
+ lcd_wait(display);
+ __raw_writel((LCD_SETDDRAM | i),
+ (display + DISPLAY_LCDINSTRUCTION));
+ lcd_wait(display);
+ __raw_writel(ch, display + DISPLAY_LCDDATA);
+ }
+}
+
+static void scroll_display_message(unsigned long data)
+{
+ mips_display_message(&display_string[display_count++]);
+ if (display_count == max_display_count)
+ display_count = 0;
+ mod_timer(&mips_scroll_timer, jiffies + HZ);
+}
+
+void mips_scroll_message(void)
+{
+ del_timer_sync(&mips_scroll_timer);
+ max_display_count = strlen(display_string) + 1 - 16;
+ mod_timer(&mips_scroll_timer, jiffies + 1);
+}
diff --git a/arch/mips/mti-sead3/sead3-init.c b/arch/mips/mti-sead3/sead3-init.c
new file mode 100644
index 000000000..3572ea301
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-init.c
@@ -0,0 +1,152 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/fw/fw.h>
+
+extern char except_vec_nmi;
+extern char except_vec_ejtag_debug;
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void __init console_config(void)
+{
+ char console_string[40];
+ int baud = 0;
+ char parity = '\0', bits = '\0', flow = '\0';
+ char *s;
+
+ if ((strstr(fw_getcmdline(), "console=")) == NULL) {
+ s = fw_getenv("modetty0");
+ if (s) {
+ while (*s >= '0' && *s <= '9')
+ baud = baud*10 + *s++ - '0';
+ if (*s == ',')
+ s++;
+ if (*s)
+ parity = *s++;
+ if (*s == ',')
+ s++;
+ if (*s)
+ bits = *s++;
+ if (*s == ',')
+ s++;
+ if (*s == 'h')
+ flow = 'r';
+ }
+ if (baud == 0)
+ baud = 38400;
+ if (parity != 'n' && parity != 'o' && parity != 'e')
+ parity = 'n';
+ if (bits != '7' && bits != '8')
+ bits = '8';
+ if (flow == '\0')
+ flow = 'r';
+ sprintf(console_string, " console=ttyS0,%d%c%c%c", baud,
+ parity, bits, flow);
+ strcat(fw_getcmdline(), console_string);
+ }
+}
+#endif
+
+static void __init mips_nmi_setup(void)
+{
+ void *base;
+
+ base = cpu_has_veic ?
+ (void *)(CAC_BASE + 0xa80) :
+ (void *)(CAC_BASE + 0x380);
+#ifdef CONFIG_CPU_MICROMIPS
+ /*
+ * Decrement the exception vector address by one for microMIPS.
+ */
+ memcpy(base, (&except_vec_nmi - 1), 0x80);
+
+ /*
+ * This is a hack. We do not know if the boot loader was built with
+ * microMIPS instructions or not. If it was not, the NMI exception
+ * code at 0x80000a80 will be taken in MIPS32 mode. The hand coded
+ * assembly below forces us into microMIPS mode if we are a pure
+ * microMIPS kernel. The assembly instructions are:
+ *
+ * 3C1A8000 lui k0,0x8000
+ * 375A0381 ori k0,k0,0x381
+ * 03400008 jr k0
+ * 00000000 nop
+ *
+ * The mode switch occurs by jumping to the unaligned exception
+ * vector address at 0x80000381 which would have been 0x80000380
+ * in MIPS32 mode. The jump to the unaligned address transitions
+ * us into microMIPS mode.
+ */
+ if (!cpu_has_veic) {
+ void *base2 = (void *)(CAC_BASE + 0xa80);
+ *((unsigned int *)base2) = 0x3c1a8000;
+ *((unsigned int *)base2 + 1) = 0x375a0381;
+ *((unsigned int *)base2 + 2) = 0x03400008;
+ *((unsigned int *)base2 + 3) = 0x00000000;
+ flush_icache_range((unsigned long)base2,
+ (unsigned long)base2 + 0x10);
+ }
+#else
+ memcpy(base, &except_vec_nmi, 0x80);
+#endif
+ flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
+static void __init mips_ejtag_setup(void)
+{
+ void *base;
+
+ base = cpu_has_veic ?
+ (void *)(CAC_BASE + 0xa00) :
+ (void *)(CAC_BASE + 0x300);
+#ifdef CONFIG_CPU_MICROMIPS
+ /* Deja vu... */
+ memcpy(base, (&except_vec_ejtag_debug - 1), 0x80);
+ if (!cpu_has_veic) {
+ void *base2 = (void *)(CAC_BASE + 0xa00);
+ *((unsigned int *)base2) = 0x3c1a8000;
+ *((unsigned int *)base2 + 1) = 0x375a0301;
+ *((unsigned int *)base2 + 2) = 0x03400008;
+ *((unsigned int *)base2 + 3) = 0x00000000;
+ flush_icache_range((unsigned long)base2,
+ (unsigned long)base2 + 0x10);
+ }
+#else
+ memcpy(base, &except_vec_ejtag_debug, 0x80);
+#endif
+ flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
+void __init prom_init(void)
+{
+ board_nmi_handler_setup = mips_nmi_setup;
+ board_ejtag_handler_setup = mips_ejtag_setup;
+
+ fw_init_cmdline();
+#ifdef CONFIG_EARLY_PRINTK
+ if ((strstr(fw_getcmdline(), "console=ttyS0")) != NULL)
+ fw_init_early_console(0);
+ else if ((strstr(fw_getcmdline(), "console=ttyS1")) != NULL)
+ fw_init_early_console(1);
+#endif
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ if ((strstr(fw_getcmdline(), "console=")) == NULL)
+ strcat(fw_getcmdline(), " console=ttyS0,38400n8r");
+ console_config();
+#endif
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/mti-sead3/sead3-int.c b/arch/mips/mti-sead3/sead3-int.c
new file mode 100644
index 000000000..e31e17f81
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-int.c
@@ -0,0 +1,42 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/io.h>
+
+#include <asm/irq_cpu.h>
+#include <asm/setup.h>
+
+#include <asm/mips-boards/sead3int.h>
+
+#define SEAD_CONFIG_GIC_PRESENT_SHF 1
+#define SEAD_CONFIG_GIC_PRESENT_MSK (1 << SEAD_CONFIG_GIC_PRESENT_SHF)
+#define SEAD_CONFIG_BASE 0x1b100110
+#define SEAD_CONFIG_SIZE 4
+
+static void __iomem *sead3_config_reg;
+
+void __init arch_init_irq(void)
+{
+ if (!cpu_has_veic)
+ mips_cpu_irq_init();
+
+ sead3_config_reg = ioremap_nocache(SEAD_CONFIG_BASE, SEAD_CONFIG_SIZE);
+ gic_present = (__raw_readl(sead3_config_reg) &
+ SEAD_CONFIG_GIC_PRESENT_MSK) >>
+ SEAD_CONFIG_GIC_PRESENT_SHF;
+ pr_info("GIC: %spresent\n", (gic_present) ? "" : "not ");
+ pr_info("EIC: %s\n",
+ (current_cpu_data.options & MIPS_CPU_VEIC) ? "on" : "off");
+
+ if (gic_present)
+ gic_init(GIC_BASE_ADDR, GIC_ADDRSPACE_SZ, CPU_INT_GIC,
+ MIPS_GIC_IRQ_BASE);
+}
+
diff --git a/arch/mips/mti-sead3/sead3-lcd.c b/arch/mips/mti-sead3/sead3-lcd.c
new file mode 100644
index 000000000..10b10ed21
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-lcd.c
@@ -0,0 +1,43 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+static struct resource __initdata sead3_lcd_resource = {
+ .start = 0x1f000400,
+ .end = 0x1f00041f,
+ .flags = IORESOURCE_MEM,
+};
+
+static __init int sead3_lcd_add(void)
+{
+ struct platform_device *pdev;
+ int retval;
+
+ /* SEAD-3 and Cobalt platforms use same display type. */
+ pdev = platform_device_alloc("cobalt-lcd", -1);
+ if (!pdev)
+ return -ENOMEM;
+
+ retval = platform_device_add_resources(pdev, &sead3_lcd_resource, 1);
+ if (retval)
+ goto err_free_device;
+
+ retval = platform_device_add(pdev);
+ if (retval)
+ goto err_free_device;
+
+ return 0;
+
+err_free_device:
+ platform_device_put(pdev);
+
+ return retval;
+}
+
+device_initcall(sead3_lcd_add);
diff --git a/arch/mips/mti-sead3/sead3-platform.c b/arch/mips/mti-sead3/sead3-platform.c
new file mode 100644
index 000000000..73b73efbf
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-platform.c
@@ -0,0 +1,223 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/irqchip/mips-gic.h>
+#include <linux/leds.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/smsc911x.h>
+
+#include <asm/mips-boards/sead3int.h>
+
+#define UART(base) \
+{ \
+ .mapbase = base, \
+ .irq = -1, \
+ .uartclk = 14745600, \
+ .iotype = UPIO_MEM32, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP, \
+ .regshift = 2, \
+}
+
+static struct plat_serial8250_port uart8250_data[] = {
+ UART(0x1f000900), /* ttyS0 = USB */
+ UART(0x1f000800), /* ttyS1 = RS232 */
+ { },
+};
+
+static struct platform_device uart8250_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM2,
+ .dev = {
+ .platform_data = uart8250_data,
+ },
+};
+
+static struct smsc911x_platform_config sead3_smsc911x_data = {
+ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
+ .flags = SMSC911X_USE_32BIT | SMSC911X_SAVE_MAC_ADDRESS,
+ .phy_interface = PHY_INTERFACE_MODE_MII,
+};
+
+static struct resource sead3_net_resources[] = {
+ {
+ .start = 0x1f010000,
+ .end = 0x1f01ffff,
+ .flags = IORESOURCE_MEM
+ }, {
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static struct platform_device sead3_net_device = {
+ .name = "smsc911x",
+ .id = 0,
+ .dev = {
+ .platform_data = &sead3_smsc911x_data,
+ },
+ .num_resources = ARRAY_SIZE(sead3_net_resources),
+ .resource = sead3_net_resources
+};
+
+static struct mtd_partition sead3_mtd_partitions[] = {
+ {
+ .name = "User FS",
+ .offset = 0x00000000,
+ .size = 0x01fc0000,
+ }, {
+ .name = "Board Config",
+ .offset = 0x01fc0000,
+ .size = 0x00040000,
+ .mask_flags = MTD_WRITEABLE
+ },
+};
+
+static struct physmap_flash_data sead3_flash_data = {
+ .width = 4,
+ .nr_parts = ARRAY_SIZE(sead3_mtd_partitions),
+ .parts = sead3_mtd_partitions
+};
+
+static struct resource sead3_flash_resource = {
+ .start = 0x1c000000,
+ .end = 0x1dffffff,
+ .flags = IORESOURCE_MEM
+};
+
+static struct platform_device sead3_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &sead3_flash_data,
+ },
+ .num_resources = 1,
+ .resource = &sead3_flash_resource,
+};
+
+#define LEDFLAGS(bits, shift) \
+ ((bits << 8) | (shift << 8))
+
+#define LEDBITS(id, shift, bits) \
+ .name = id #shift, \
+ .flags = LEDFLAGS(bits, shift)
+
+static struct led_info led_data_info[] = {
+ { LEDBITS("bit", 0, 1) },
+ { LEDBITS("bit", 1, 1) },
+ { LEDBITS("bit", 2, 1) },
+ { LEDBITS("bit", 3, 1) },
+ { LEDBITS("bit", 4, 1) },
+ { LEDBITS("bit", 5, 1) },
+ { LEDBITS("bit", 6, 1) },
+ { LEDBITS("bit", 7, 1) },
+ { LEDBITS("all", 0, 8) },
+};
+
+static struct led_platform_data led_data = {
+ .num_leds = ARRAY_SIZE(led_data_info),
+ .leds = led_data_info
+};
+
+static struct resource pled_resources[] = {
+ {
+ .start = 0x1f000210,
+ .end = 0x1f000217,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct platform_device pled_device = {
+ .name = "sead3::pled",
+ .id = 0,
+ .dev = {
+ .platform_data = &led_data,
+ },
+ .num_resources = ARRAY_SIZE(pled_resources),
+ .resource = pled_resources
+};
+
+
+static struct resource fled_resources[] = {
+ {
+ .start = 0x1f000218,
+ .end = 0x1f00021f,
+ .flags = IORESOURCE_MEM
+ }
+};
+
+static struct platform_device fled_device = {
+ .name = "sead3::fled",
+ .id = 0,
+ .dev = {
+ .platform_data = &led_data,
+ },
+ .num_resources = ARRAY_SIZE(fled_resources),
+ .resource = fled_resources
+};
+
+static struct platform_device sead3_led_device = {
+ .name = "sead3-led",
+ .id = -1,
+};
+
+static struct resource ehci_resources[] = {
+ {
+ .start = 0x1b200000,
+ .end = 0x1b200fff,
+ .flags = IORESOURCE_MEM
+ }, {
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+static u64 sead3_usbdev_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ehci_device = {
+ .name = "sead3-ehci",
+ .id = 0,
+ .dev = {
+ .dma_mask = &sead3_usbdev_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32)
+ },
+ .num_resources = ARRAY_SIZE(ehci_resources),
+ .resource = ehci_resources
+};
+
+static struct platform_device *sead3_platform_devices[] __initdata = {
+ &uart8250_device,
+ &sead3_flash,
+ &pled_device,
+ &fled_device,
+ &sead3_led_device,
+ &ehci_device,
+ &sead3_net_device,
+};
+
+static int __init sead3_platforms_device_init(void)
+{
+ if (gic_present) {
+ uart8250_data[0].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART0;
+ uart8250_data[1].irq = MIPS_GIC_IRQ_BASE + GIC_INT_UART1;
+ ehci_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_EHCI;
+ sead3_net_resources[1].start = MIPS_GIC_IRQ_BASE + GIC_INT_NET;
+ } else {
+ uart8250_data[0].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART0;
+ uart8250_data[1].irq = MIPS_CPU_IRQ_BASE + CPU_INT_UART1;
+ ehci_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_EHCI;
+ sead3_net_resources[1].start = MIPS_CPU_IRQ_BASE + CPU_INT_NET;
+ }
+
+ return platform_add_devices(sead3_platform_devices,
+ ARRAY_SIZE(sead3_platform_devices));
+}
+
+device_initcall(sead3_platforms_device_init);
diff --git a/arch/mips/mti-sead3/sead3-reset.c b/arch/mips/mti-sead3/sead3-reset.c
new file mode 100644
index 000000000..e6fb24414
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-reset.c
@@ -0,0 +1,40 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <asm/reboot.h>
+
+#define SOFTRES_REG 0x1f000050
+#define GORESET 0x4d
+
+static void mips_machine_restart(char *command)
+{
+ unsigned int __iomem *softres_reg =
+ ioremap(SOFTRES_REG, sizeof(unsigned int));
+
+ __raw_writel(GORESET, softres_reg);
+}
+
+static void mips_machine_halt(void)
+{
+ unsigned int __iomem *softres_reg =
+ ioremap(SOFTRES_REG, sizeof(unsigned int));
+
+ __raw_writel(GORESET, softres_reg);
+}
+
+static int __init mips_reboot_setup(void)
+{
+ _machine_restart = mips_machine_restart;
+ _machine_halt = mips_machine_halt;
+ pm_power_off = mips_machine_halt;
+
+ return 0;
+}
+arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/mti-sead3/sead3-setup.c b/arch/mips/mti-sead3/sead3-setup.c
new file mode 100644
index 000000000..e43f4801a
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-setup.c
@@ -0,0 +1,111 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2013 Imagination Technologies Ltd.
+ */
+#include <linux/init.h>
+#include <linux/libfdt.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+
+#include <asm/prom.h>
+#include <asm/fw/fw.h>
+
+#include <asm/mips-boards/generic.h>
+
+const char *get_system_type(void)
+{
+ return "MIPS SEAD3";
+}
+
+static uint32_t get_memsize_from_cmdline(void)
+{
+ int memsize = 0;
+ char *p = arcs_cmdline;
+ char *s = "memsize=";
+
+ p = strstr(p, s);
+ if (p) {
+ p += strlen(s);
+ memsize = memparse(p, NULL);
+ }
+
+ return memsize;
+}
+
+static uint32_t get_memsize_from_env(void)
+{
+ int memsize = 0;
+ char *p;
+
+ p = fw_getenv("memsize");
+ if (p)
+ memsize = memparse(p, NULL);
+
+ return memsize;
+}
+
+static uint32_t get_memsize(void)
+{
+ uint32_t memsize;
+
+ memsize = get_memsize_from_cmdline();
+ if (memsize)
+ return memsize;
+
+ return get_memsize_from_env();
+}
+
+static void __init parse_memsize_param(void)
+{
+ int offset;
+ const uint64_t *prop_value;
+ int prop_len;
+ uint32_t memsize = get_memsize();
+
+ if (!memsize)
+ return;
+
+ offset = fdt_path_offset(__dtb_start, "/memory");
+ if (offset > 0) {
+ uint64_t new_value;
+ /*
+ * reg contains 2 32-bits BE values, offset and size. We just
+ * want to replace the size value without affecting the offset
+ */
+ prop_value = fdt_getprop(__dtb_start, offset, "reg", &prop_len);
+ new_value = be64_to_cpu(*prop_value);
+ new_value = (new_value & ~0xffffffffllu) | memsize;
+ fdt_setprop_inplace_u64(__dtb_start, offset, "reg", new_value);
+ }
+}
+
+void __init plat_mem_setup(void)
+{
+ /* allow command line/bootloader env to override memory size in DT */
+ parse_memsize_param();
+
+ /*
+ * Load the builtin devicetree. This causes the chosen node to be
+ * parsed resulting in our memory appearing
+ */
+ __dt_setup_arch(__dtb_start);
+}
+
+void __init device_tree_init(void)
+{
+ if (!initial_boot_params)
+ return;
+
+ unflatten_and_copy_device_tree();
+}
+
+static int __init customize_machine(void)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+ return 0;
+}
+arch_initcall(customize_machine);
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c
new file mode 100644
index 000000000..e1d69895f
--- /dev/null
+++ b/arch/mips/mti-sead3/sead3-time.c
@@ -0,0 +1,98 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
+ */
+#include <linux/init.h>
+#include <linux/irqchip/mips-gic.h>
+
+#include <asm/cpu.h>
+#include <asm/setup.h>
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+
+static void __iomem *status_reg = (void __iomem *)0xbf000410;
+
+/*
+ * Estimate CPU frequency. Sets mips_hpt_frequency as a side-effect.
+ */
+static unsigned int __init estimate_cpu_frequency(void)
+{
+ unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK);
+ unsigned int tick = 0;
+ unsigned int freq;
+ unsigned int orig;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ orig = readl(status_reg) & 0x2; /* get original sample */
+ /* wait for transition */
+ while ((readl(status_reg) & 0x2) == orig)
+ ;
+ orig = orig ^ 0x2; /* flip the bit */
+
+ write_c0_count(0);
+
+ /* wait 1 second (the sampling clock transitions every 10ms) */
+ while (tick < 100) {
+ /* wait for transition */
+ while ((readl(status_reg) & 0x2) == orig)
+ ;
+ orig = orig ^ 0x2; /* flip the bit */
+ tick++;
+ }
+
+ freq = read_c0_count();
+
+ local_irq_restore(flags);
+
+ mips_hpt_frequency = freq;
+
+ /* Adjust for processor */
+ if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+ (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+ freq *= 2;
+
+ freq += 5000; /* rounding */
+ freq -= freq%10000;
+
+ return freq ;
+}
+
+void read_persistent_clock(struct timespec *ts)
+{
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+}
+
+int get_c0_perfcount_int(void)
+{
+ if (gic_present)
+ return gic_get_c0_perfcount_int();
+ if (cp0_perfcount_irq >= 0)
+ return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
+ return -1;
+}
+
+unsigned int get_c0_compare_int(void)
+{
+ if (gic_present)
+ return gic_get_c0_compare_int();
+ return MIPS_CPU_IRQ_BASE + cp0_compare_irq;
+}
+
+void __init plat_time_init(void)
+{
+ unsigned int est_freq;
+
+ est_freq = estimate_cpu_frequency();
+
+ pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000),
+ (est_freq % 1000000) * 100 / 1000000);
+
+ mips_scroll_message();
+}