summaryrefslogtreecommitdiff
path: root/arch/mips/loongson
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/loongson')
-rw-r--r--arch/mips/loongson/common/early_printk.c2
-rw-r--r--arch/mips/loongson/common/env.c26
-rw-r--r--arch/mips/loongson/common/machtype.c5
-rw-r--r--arch/mips/loongson/common/serial.c48
-rw-r--r--arch/mips/loongson/common/uart_base.c30
-rw-r--r--arch/mips/loongson/loongson-3/Makefile2
-rw-r--r--arch/mips/loongson/loongson-3/platform.c43
-rw-r--r--arch/mips/loongson/loongson-3/smp.c5
8 files changed, 127 insertions, 34 deletions
diff --git a/arch/mips/loongson/common/early_printk.c b/arch/mips/loongson/common/early_printk.c
index ced461b39069..6ca632e529dc 100644
--- a/arch/mips/loongson/common/early_printk.c
+++ b/arch/mips/loongson/common/early_printk.c
@@ -30,7 +30,7 @@ void prom_putchar(char c)
int timeout;
unsigned char *uart_base;
- uart_base = (unsigned char *)_loongson_uart_base;
+ uart_base = (unsigned char *)_loongson_uart_base[0];
timeout = 1024;
while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) &&
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index d8be5398105c..045ea3d47c87 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -21,6 +21,7 @@
#include <asm/bootinfo.h>
#include <loongson.h>
#include <boot_param.h>
+#include <workarounds.h>
u32 cpu_clock_freq;
EXPORT_SYMBOL(cpu_clock_freq);
@@ -31,7 +32,6 @@ u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
u64 loongson_freqctrl[MAX_PACKAGES];
unsigned long long smp_group[4];
-int cpuhotplug_workaround = 0;
#define parse_even_earlier(res, option, p) \
do { \
@@ -67,6 +67,7 @@ void __init prom_init_env(void)
#else
struct boot_params *boot_p;
struct loongson_params *loongson_p;
+ struct system_loongson *esys;
struct efi_cpuinfo_loongson *ecpu;
struct irq_source_routing_table *eirq_source;
@@ -74,6 +75,8 @@ void __init prom_init_env(void)
boot_p = (struct boot_params *)fw_arg2;
loongson_p = &(boot_p->efi.smbios.lp);
+ esys = (struct system_loongson *)
+ ((u64)loongson_p + loongson_p->system_offset);
ecpu = (struct efi_cpuinfo_loongson *)
((u64)loongson_p + loongson_p->cpu_offset);
eirq_source = (struct irq_source_routing_table *)
@@ -95,6 +98,7 @@ void __init prom_init_env(void)
loongson_chipcfg[2] = 0x900020001fe00180;
loongson_chipcfg[3] = 0x900030001fe00180;
loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
+ loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
} else if (ecpu->cputype == Loongson_3B) {
loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
loongson_sysconf.cores_per_package = 8;
@@ -111,7 +115,7 @@ void __init prom_init_env(void)
loongson_freqctrl[2] = 0x900040001fe001d0;
loongson_freqctrl[3] = 0x900060001fe001d0;
loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
- cpuhotplug_workaround = 1;
+ loongson_sysconf.workarounds = WORKAROUND_CPUHOTPLUG;
} else {
loongson_sysconf.cores_per_node = 1;
loongson_sysconf.cores_per_package = 1;
@@ -143,6 +147,24 @@ void __init prom_init_env(void)
pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
loongson_sysconf.vgabios_addr);
+
+ memset(loongson_sysconf.ecname, 0, 32);
+ if (esys->has_ec)
+ memcpy(loongson_sysconf.ecname, esys->ec_name, 32);
+ loongson_sysconf.workarounds |= esys->workarounds;
+
+ loongson_sysconf.nr_uarts = esys->nr_uarts;
+ if (esys->nr_uarts < 1 || esys->nr_uarts > MAX_UARTS)
+ loongson_sysconf.nr_uarts = 1;
+ memcpy(loongson_sysconf.uarts, esys->uarts,
+ sizeof(struct uart_device) * loongson_sysconf.nr_uarts);
+
+ loongson_sysconf.nr_sensors = esys->nr_sensors;
+ if (loongson_sysconf.nr_sensors > MAX_SENSORS)
+ loongson_sysconf.nr_sensors = 0;
+ if (loongson_sysconf.nr_sensors)
+ memcpy(loongson_sysconf.sensors, esys->sensors,
+ sizeof(struct sensor_device) * loongson_sysconf.nr_sensors);
#endif
if (cpu_clock_freq == 0) {
processor_id = (&current_cpu_data)->processor_id;
diff --git a/arch/mips/loongson/common/machtype.c b/arch/mips/loongson/common/machtype.c
index 1a4797984b8d..26629abe3f1f 100644
--- a/arch/mips/loongson/common/machtype.c
+++ b/arch/mips/loongson/common/machtype.c
@@ -27,10 +27,7 @@ static const char *system_types[] = {
[MACH_DEXXON_GDIUM2F10] "dexxon-gdium-2f",
[MACH_LEMOTE_NAS] "lemote-nas-2f",
[MACH_LEMOTE_LL2F] "lemote-lynloong-2f",
- [MACH_LEMOTE_A1004] "lemote-3a-notebook-a1004",
- [MACH_LEMOTE_A1101] "lemote-3a-itx-a1101",
- [MACH_LEMOTE_A1201] "lemote-2gq-notebook-a1201",
- [MACH_LEMOTE_A1205] "lemote-2gq-aio-a1205",
+ [MACH_LOONGSON_GENERIC] "generic-loongson-machine",
[MACH_LOONGSON_END] NULL,
};
diff --git a/arch/mips/loongson/common/serial.c b/arch/mips/loongson/common/serial.c
index bd2b7095b6dc..d2f4817a4b45 100644
--- a/arch/mips/loongson/common/serial.c
+++ b/arch/mips/loongson/common/serial.c
@@ -38,7 +38,7 @@
.regshift = 0, \
}
-static struct plat_serial8250_port uart8250_data[][2] = {
+static struct plat_serial8250_port uart8250_data[][MAX_UARTS + 1] = {
[MACH_LOONGSON_UNKNOWN] {},
[MACH_LEMOTE_FL2E] {PORT(4, 1843200), {} },
[MACH_LEMOTE_FL2F] {PORT(3, 1843200), {} },
@@ -47,10 +47,7 @@ static struct plat_serial8250_port uart8250_data[][2] = {
[MACH_DEXXON_GDIUM2F10] {PORT_M(3, 3686400), {} },
[MACH_LEMOTE_NAS] {PORT_M(3, 3686400), {} },
[MACH_LEMOTE_LL2F] {PORT(3, 1843200), {} },
- [MACH_LEMOTE_A1004] {PORT_M(2, 33177600), {} },
- [MACH_LEMOTE_A1101] {PORT_M(2, 25000000), {} },
- [MACH_LEMOTE_A1201] {PORT_M(2, 25000000), {} },
- [MACH_LEMOTE_A1205] {PORT_M(2, 25000000), {} },
+ [MACH_LOONGSON_GENERIC] {PORT_M(2, 25000000), {} },
[MACH_LOONGSON_END] {},
};
@@ -61,17 +58,52 @@ static struct platform_device uart8250_device = {
static int __init serial_init(void)
{
+ int i;
unsigned char iotype;
iotype = uart8250_data[mips_machtype][0].iotype;
- if (UPIO_MEM == iotype)
+ if (UPIO_MEM == iotype) {
+ uart8250_data[mips_machtype][0].mapbase =
+ loongson_uart_base[0];
uart8250_data[mips_machtype][0].membase =
- (void __iomem *)_loongson_uart_base;
+ (void __iomem *)_loongson_uart_base[0];
+ }
else if (UPIO_PORT == iotype)
uart8250_data[mips_machtype][0].iobase =
- loongson_uart_base - LOONGSON_PCIIO_BASE;
+ loongson_uart_base[0] - LOONGSON_PCIIO_BASE;
+ if (loongson_sysconf.uarts[0].uartclk)
+ uart8250_data[mips_machtype][0].uartclk =
+ loongson_sysconf.uarts[0].uartclk;
+
+ for (i = 1; i < loongson_sysconf.nr_uarts; i++) {
+ iotype = loongson_sysconf.uarts[i].iotype;
+ uart8250_data[mips_machtype][i].iotype = iotype;
+ loongson_uart_base[i] = loongson_sysconf.uarts[i].uart_base;
+
+ if (UPIO_MEM == iotype) {
+ uart8250_data[mips_machtype][i].irq =
+ MIPS_CPU_IRQ_BASE + loongson_sysconf.uarts[i].int_offset;
+ uart8250_data[mips_machtype][i].mapbase =
+ loongson_uart_base[i];
+ uart8250_data[mips_machtype][i].membase =
+ ioremap_nocache(loongson_uart_base[i], 8);
+ } else if (UPIO_PORT == iotype) {
+ uart8250_data[mips_machtype][i].irq =
+ loongson_sysconf.uarts[i].int_offset;
+ uart8250_data[mips_machtype][i].iobase =
+ loongson_uart_base[i] - LOONGSON_PCIIO_BASE;
+ }
+
+ uart8250_data[mips_machtype][i].uartclk =
+ loongson_sysconf.uarts[i].uartclk;
+ uart8250_data[mips_machtype][i].flags =
+ UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
+ }
+
+ memset(&uart8250_data[mips_machtype][loongson_sysconf.nr_uarts],
+ 0, sizeof(struct plat_serial8250_port));
uart8250_device.dev.platform_data = uart8250_data[mips_machtype];
return platform_device_register(&uart8250_device);
diff --git a/arch/mips/loongson/common/uart_base.c b/arch/mips/loongson/common/uart_base.c
index 1e1eeea73fde..9de559d58e1f 100644
--- a/arch/mips/loongson/common/uart_base.c
+++ b/arch/mips/loongson/common/uart_base.c
@@ -13,22 +13,27 @@
#include <loongson.h>
-/* ioremapped */
-unsigned long _loongson_uart_base;
-EXPORT_SYMBOL(_loongson_uart_base);
/* raw */
-unsigned long loongson_uart_base;
+unsigned long loongson_uart_base[MAX_UARTS] = {};
+/* ioremapped */
+unsigned long _loongson_uart_base[MAX_UARTS] = {};
+
EXPORT_SYMBOL(loongson_uart_base);
+EXPORT_SYMBOL(_loongson_uart_base);
void prom_init_loongson_uart_base(void)
{
switch (mips_machtype) {
+ case MACH_LOONGSON_GENERIC:
+ /* The CPU provided serial port (CPU) */
+ loongson_uart_base[0] = LOONGSON_REG_BASE + 0x1e0;
+ break;
case MACH_LEMOTE_FL2E:
- loongson_uart_base = LOONGSON_PCIIO_BASE + 0x3f8;
+ loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x3f8;
break;
case MACH_LEMOTE_FL2F:
case MACH_LEMOTE_LL2F:
- loongson_uart_base = LOONGSON_PCIIO_BASE + 0x2f8;
+ loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x2f8;
break;
case MACH_LEMOTE_ML2F7:
case MACH_LEMOTE_YL2F89:
@@ -36,17 +41,10 @@ void prom_init_loongson_uart_base(void)
case MACH_LEMOTE_NAS:
default:
/* The CPU provided serial port (LPC) */
- loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8;
- break;
- case MACH_LEMOTE_A1004:
- case MACH_LEMOTE_A1101:
- case MACH_LEMOTE_A1201:
- case MACH_LEMOTE_A1205:
- /* The CPU provided serial port (CPU) */
- loongson_uart_base = LOONGSON_REG_BASE + 0x1e0;
+ loongson_uart_base[0] = LOONGSON_LIO1_BASE + 0x3f8;
break;
}
- _loongson_uart_base =
- (unsigned long)ioremap_nocache(loongson_uart_base, 8);
+ _loongson_uart_base[0] =
+ (unsigned long)ioremap_nocache(loongson_uart_base[0], 8);
}
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
index b4df775b9f30..69809a3d8f34 100644
--- a/arch/mips/loongson/loongson-3/Makefile
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for Loongson-3 family machines
#
-obj-y += irq.o cop2-ex.o
+obj-y += irq.o cop2-ex.o platform.o
obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/mips/loongson/loongson-3/platform.c b/arch/mips/loongson/loongson-3/platform.c
new file mode 100644
index 000000000000..25a97cc0ee33
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/platform.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Lemote Inc.
+ * Author: Wu Zhangjin, wuzhangjin@gmail.com
+ * Xiang Yu, xiangy@lemote.com
+ * Chen Huacai, chenhc@lemote.com
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <asm/bootinfo.h>
+#include <boot_param.h>
+#include <loongson_hwmon.h>
+#include <workarounds.h>
+
+static int __init loongson3_platform_init(void)
+{
+ int i;
+ struct platform_device *pdev;
+
+ if (loongson_sysconf.ecname[0] != '\0')
+ platform_device_register_simple(loongson_sysconf.ecname, -1, NULL, 0);
+
+ for (i = 0; i < loongson_sysconf.nr_sensors; i++) {
+ if (loongson_sysconf.sensors[i].type > SENSOR_FAN)
+ continue;
+
+ pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
+ pdev->name = loongson_sysconf.sensors[i].name;
+ pdev->id = loongson_sysconf.sensors[i].id;
+ pdev->dev.platform_data = &loongson_sysconf.sensors[i];
+ platform_device_register(pdev);
+ }
+
+ return 0;
+}
+
+arch_initcall(loongson3_platform_init);
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index 94ed8a57353c..e2eb688b5434 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -25,6 +25,7 @@
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
#include <loongson.h>
+#include <workarounds.h>
#include "smp.h"
@@ -587,7 +588,7 @@ void loongson3_disable_clock(int cpu)
if (loongson_sysconf.cputype == Loongson_3A) {
LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
} else if (loongson_sysconf.cputype == Loongson_3B) {
- if (!cpuhotplug_workaround)
+ if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
}
}
@@ -600,7 +601,7 @@ void loongson3_enable_clock(int cpu)
if (loongson_sysconf.cputype == Loongson_3A) {
LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
} else if (loongson_sysconf.cputype == Loongson_3B) {
- if (!cpuhotplug_workaround)
+ if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
}
}