aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHuacai Chen <chenhc@lemote.com>2014-11-04 01:13:27 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-11-24 01:45:01 -0500
commit3adeb2566b9bc1dbf579ed515265c6aad756a5cd (patch)
tree5b01da67a65f1f6ad3177b157ea9d9fc62f7d6ca /arch
parentec0f8d3fbb7ea12cfd10083e340381b96e7c34f8 (diff)
MIPS: Loongson: Improve LEFI firmware interface
Machtypes of Loongson-3 machines become more and more, but there are only small differences among different machtypes. Keeping a large table of machtypes is very ugly and hard to extend. We found that the major machtype differences are UARTs information (number of UARTs, UART IRQs, UART clocks, etc.), platform devices (EC, temperature sensors, fan controllers, etc.) and some workarounds (because of some CPU bugs or mainboard bugs). In this patch we improve the UEFI-like (LEFI) interface to make all Loongson-3 machines use a same machtype "generic-loongson-machine". Signed-off-by: Huacai Chen <chenhc@lemote.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/8324/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/include/asm/bootinfo.h5
-rw-r--r--arch/mips/include/asm/mach-loongson/boot_param.h44
-rw-r--r--arch/mips/include/asm/mach-loongson/loongson.h2
-rw-r--r--arch/mips/include/asm/mach-loongson/loongson_hwmon.h55
-rw-r--r--arch/mips/include/asm/mach-loongson/machine.h2
-rw-r--r--arch/mips/include/asm/mach-loongson/workarounds.h7
-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
14 files changed, 234 insertions, 42 deletions
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 1f7ca8b00404..8b2eaa155d18 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -70,10 +70,7 @@ enum loongson_machine_type {
70 MACH_DEXXON_GDIUM2F10, 70 MACH_DEXXON_GDIUM2F10,
71 MACH_LEMOTE_NAS, 71 MACH_LEMOTE_NAS,
72 MACH_LEMOTE_LL2F, 72 MACH_LEMOTE_LL2F,
73 MACH_LEMOTE_A1004, 73 MACH_LOONGSON_GENERIC,
74 MACH_LEMOTE_A1101,
75 MACH_LEMOTE_A1201,
76 MACH_LEMOTE_A1205,
77 MACH_LOONGSON_END 74 MACH_LOONGSON_END
78}; 75};
79 76
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
index 11ebf4ca2b41..fa802926523f 100644
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -10,7 +10,8 @@
10#define VIDEO_ROM 7 10#define VIDEO_ROM 7
11#define ADAPTER_ROM 8 11#define ADAPTER_ROM 8
12#define ACPI_TABLE 9 12#define ACPI_TABLE 9
13#define MAX_MEMORY_TYPE 10 13#define SMBIOS_TABLE 10
14#define MAX_MEMORY_TYPE 11
14 15
15#define LOONGSON3_BOOT_MEM_MAP_MAX 128 16#define LOONGSON3_BOOT_MEM_MAP_MAX 128
16struct efi_memory_map_loongson { 17struct efi_memory_map_loongson {
@@ -48,10 +49,43 @@ struct efi_cpuinfo_loongson {
48 u32 nr_cpus; 49 u32 nr_cpus;
49} __packed; 50} __packed;
50 51
52#define MAX_UARTS 64
53struct uart_device {
54 u32 iotype; /* see include/linux/serial_core.h */
55 u32 uartclk;
56 u32 int_offset;
57 u64 uart_base;
58} __packed;
59
60#define MAX_SENSORS 64
61#define SENSOR_TEMPER 0x00000001
62#define SENSOR_VOLTAGE 0x00000002
63#define SENSOR_FAN 0x00000004
64struct sensor_device {
65 char name[32]; /* a formal name */
66 char label[64]; /* a flexible description */
67 u32 type; /* SENSOR_* */
68 u32 id; /* instance id of a sensor-class */
69 u32 fan_policy; /* see loongson_hwmon.h */
70 u32 fan_percent;/* only for constant speed policy */
71 u64 base_addr; /* base address of device registers */
72} __packed;
73
51struct system_loongson { 74struct system_loongson {
52 u16 vers; /* version of system_loongson */ 75 u16 vers; /* version of system_loongson */
53 u32 ccnuma_smp; /* 0: no numa; 1: has numa */ 76 u32 ccnuma_smp; /* 0: no numa; 1: has numa */
54 u32 sing_double_channel; /* 1:single; 2:double */ 77 u32 sing_double_channel; /* 1:single; 2:double */
78 u32 nr_uarts;
79 struct uart_device uarts[MAX_UARTS];
80 u32 nr_sensors;
81 struct sensor_device sensors[MAX_SENSORS];
82 char has_ec;
83 char ec_name[32];
84 u64 ec_base_addr;
85 char has_tcm;
86 char tcm_name[32];
87 u64 tcm_base_addr;
88 u64 workarounds; /* see workarounds.h */
55} __packed; 89} __packed;
56 90
57struct irq_source_routing_table { 91struct irq_source_routing_table {
@@ -162,9 +196,15 @@ struct loongson_system_configuration {
162 u64 suspend_addr; 196 u64 suspend_addr;
163 u64 vgabios_addr; 197 u64 vgabios_addr;
164 u32 dma_mask_bits; 198 u32 dma_mask_bits;
199 char ecname[32];
200 u32 nr_uarts;
201 struct uart_device uarts[MAX_UARTS];
202 u32 nr_sensors;
203 struct sensor_device sensors[MAX_SENSORS];
204 u64 workarounds;
165}; 205};
166 206
167extern struct efi_memory_map_loongson *loongson_memmap; 207extern struct efi_memory_map_loongson *loongson_memmap;
168extern struct loongson_system_configuration loongson_sysconf; 208extern struct loongson_system_configuration loongson_sysconf;
169extern int cpuhotplug_workaround; 209
170#endif 210#endif
diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
index 92bf76c21441..5459ac09679f 100644
--- a/arch/mips/include/asm/mach-loongson/loongson.h
+++ b/arch/mips/include/asm/mach-loongson/loongson.h
@@ -35,7 +35,7 @@ extern void __init prom_init_cmdline(void);
35extern void __init prom_init_machtype(void); 35extern void __init prom_init_machtype(void);
36extern void __init prom_init_env(void); 36extern void __init prom_init_env(void);
37#ifdef CONFIG_LOONGSON_UART_BASE 37#ifdef CONFIG_LOONGSON_UART_BASE
38extern unsigned long _loongson_uart_base, loongson_uart_base; 38extern unsigned long _loongson_uart_base[], loongson_uart_base[];
39extern void prom_init_loongson_uart_base(void); 39extern void prom_init_loongson_uart_base(void);
40#endif 40#endif
41 41
diff --git a/arch/mips/include/asm/mach-loongson/loongson_hwmon.h b/arch/mips/include/asm/mach-loongson/loongson_hwmon.h
new file mode 100644
index 000000000000..4431fc54a36c
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/loongson_hwmon.h
@@ -0,0 +1,55 @@
1#ifndef __LOONGSON_HWMON_H_
2#define __LOONGSON_HWMON_H_
3
4#include <linux/types.h>
5
6#define MIN_TEMP 0
7#define MAX_TEMP 255
8#define NOT_VALID_TEMP 999
9
10typedef int (*get_temp_fun)(int);
11extern int loongson3_cpu_temp(int);
12
13/* 0:Max speed, 1:Manual, 2:Auto */
14enum fan_control_mode {
15 FAN_FULL_MODE = 0,
16 FAN_MANUAL_MODE = 1,
17 FAN_AUTO_MODE = 2,
18 FAN_MODE_END
19};
20
21struct temp_range {
22 u8 low;
23 u8 high;
24 u8 level;
25};
26
27#define CONSTANT_SPEED_POLICY 0 /* at constent speed */
28#define STEP_SPEED_POLICY 1 /* use up/down arrays to describe policy */
29#define KERNEL_HELPER_POLICY 2 /* kernel as a helper to fan control */
30
31#define MAX_STEP_NUM 16
32#define MAX_FAN_LEVEL 255
33
34/* loongson_fan_policy works when fan work at FAN_AUTO_MODE */
35struct loongson_fan_policy {
36 u8 type;
37
38 /* percent only used when type is CONSTANT_SPEED_POLICY */
39 u8 percent;
40
41 /* period between two check. (Unit: S) */
42 u8 adjust_period;
43
44 /* fan adjust usually depend on a temprature input */
45 get_temp_fun depend_temp;
46
47 /* up_step/down_step used when type is STEP_SPEED_POLICY */
48 u8 up_step_num;
49 u8 down_step_num;
50 struct temp_range up_step[MAX_STEP_NUM];
51 struct temp_range down_step[MAX_STEP_NUM];
52 struct delayed_work work;
53};
54
55#endif /* __LOONGSON_HWMON_H_*/
diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
index 228e37847a36..cb2b60249cd2 100644
--- a/arch/mips/include/asm/mach-loongson/machine.h
+++ b/arch/mips/include/asm/mach-loongson/machine.h
@@ -26,7 +26,7 @@
26 26
27#ifdef CONFIG_LOONGSON_MACH3X 27#ifdef CONFIG_LOONGSON_MACH3X
28 28
29#define LOONGSON_MACHTYPE MACH_LEMOTE_A1101 29#define LOONGSON_MACHTYPE MACH_LOONGSON_GENERIC
30 30
31#endif /* CONFIG_LOONGSON_MACH3X */ 31#endif /* CONFIG_LOONGSON_MACH3X */
32 32
diff --git a/arch/mips/include/asm/mach-loongson/workarounds.h b/arch/mips/include/asm/mach-loongson/workarounds.h
new file mode 100644
index 000000000000..e180c1422eae
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/workarounds.h
@@ -0,0 +1,7 @@
1#ifndef __ASM_MACH_LOONGSON_WORKAROUNDS_H_
2#define __ASM_MACH_LOONGSON_WORKAROUNDS_H_
3
4#define WORKAROUND_CPUFREQ 0x00000001
5#define WORKAROUND_CPUHOTPLUG 0x00000002
6
7#endif
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)
30 int timeout; 30 int timeout;
31 unsigned char *uart_base; 31 unsigned char *uart_base;
32 32
33 uart_base = (unsigned char *)_loongson_uart_base; 33 uart_base = (unsigned char *)_loongson_uart_base[0];
34 timeout = 1024; 34 timeout = 1024;
35 35
36 while (((serial_in(uart_base, UART_LSR) & UART_LSR_THRE) == 0) && 36 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 @@
21#include <asm/bootinfo.h> 21#include <asm/bootinfo.h>
22#include <loongson.h> 22#include <loongson.h>
23#include <boot_param.h> 23#include <boot_param.h>
24#include <workarounds.h>
24 25
25u32 cpu_clock_freq; 26u32 cpu_clock_freq;
26EXPORT_SYMBOL(cpu_clock_freq); 27EXPORT_SYMBOL(cpu_clock_freq);
@@ -31,7 +32,6 @@ u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
31u64 loongson_freqctrl[MAX_PACKAGES]; 32u64 loongson_freqctrl[MAX_PACKAGES];
32 33
33unsigned long long smp_group[4]; 34unsigned long long smp_group[4];
34int cpuhotplug_workaround = 0;
35 35
36#define parse_even_earlier(res, option, p) \ 36#define parse_even_earlier(res, option, p) \
37do { \ 37do { \
@@ -67,6 +67,7 @@ void __init prom_init_env(void)
67#else 67#else
68 struct boot_params *boot_p; 68 struct boot_params *boot_p;
69 struct loongson_params *loongson_p; 69 struct loongson_params *loongson_p;
70 struct system_loongson *esys;
70 struct efi_cpuinfo_loongson *ecpu; 71 struct efi_cpuinfo_loongson *ecpu;
71 struct irq_source_routing_table *eirq_source; 72 struct irq_source_routing_table *eirq_source;
72 73
@@ -74,6 +75,8 @@ void __init prom_init_env(void)
74 boot_p = (struct boot_params *)fw_arg2; 75 boot_p = (struct boot_params *)fw_arg2;
75 loongson_p = &(boot_p->efi.smbios.lp); 76 loongson_p = &(boot_p->efi.smbios.lp);
76 77
78 esys = (struct system_loongson *)
79 ((u64)loongson_p + loongson_p->system_offset);
77 ecpu = (struct efi_cpuinfo_loongson *) 80 ecpu = (struct efi_cpuinfo_loongson *)
78 ((u64)loongson_p + loongson_p->cpu_offset); 81 ((u64)loongson_p + loongson_p->cpu_offset);
79 eirq_source = (struct irq_source_routing_table *) 82 eirq_source = (struct irq_source_routing_table *)
@@ -95,6 +98,7 @@ void __init prom_init_env(void)
95 loongson_chipcfg[2] = 0x900020001fe00180; 98 loongson_chipcfg[2] = 0x900020001fe00180;
96 loongson_chipcfg[3] = 0x900030001fe00180; 99 loongson_chipcfg[3] = 0x900030001fe00180;
97 loongson_sysconf.ht_control_base = 0x90000EFDFB000000; 100 loongson_sysconf.ht_control_base = 0x90000EFDFB000000;
101 loongson_sysconf.workarounds = WORKAROUND_CPUFREQ;
98 } else if (ecpu->cputype == Loongson_3B) { 102 } else if (ecpu->cputype == Loongson_3B) {
99 loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */ 103 loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */
100 loongson_sysconf.cores_per_package = 8; 104 loongson_sysconf.cores_per_package = 8;
@@ -111,7 +115,7 @@ void __init prom_init_env(void)
111 loongson_freqctrl[2] = 0x900040001fe001d0; 115 loongson_freqctrl[2] = 0x900040001fe001d0;
112 loongson_freqctrl[3] = 0x900060001fe001d0; 116 loongson_freqctrl[3] = 0x900060001fe001d0;
113 loongson_sysconf.ht_control_base = 0x90001EFDFB000000; 117 loongson_sysconf.ht_control_base = 0x90001EFDFB000000;
114 cpuhotplug_workaround = 1; 118 loongson_sysconf.workarounds = WORKAROUND_CPUHOTPLUG;
115 } else { 119 } else {
116 loongson_sysconf.cores_per_node = 1; 120 loongson_sysconf.cores_per_node = 1;
117 loongson_sysconf.cores_per_package = 1; 121 loongson_sysconf.cores_per_package = 1;
@@ -143,6 +147,24 @@ void __init prom_init_env(void)
143 pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n", 147 pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n",
144 loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr, 148 loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr,
145 loongson_sysconf.vgabios_addr); 149 loongson_sysconf.vgabios_addr);
150
151 memset(loongson_sysconf.ecname, 0, 32);
152 if (esys->has_ec)
153 memcpy(loongson_sysconf.ecname, esys->ec_name, 32);
154 loongson_sysconf.workarounds |= esys->workarounds;
155
156 loongson_sysconf.nr_uarts = esys->nr_uarts;
157 if (esys->nr_uarts < 1 || esys->nr_uarts > MAX_UARTS)
158 loongson_sysconf.nr_uarts = 1;
159 memcpy(loongson_sysconf.uarts, esys->uarts,
160 sizeof(struct uart_device) * loongson_sysconf.nr_uarts);
161
162 loongson_sysconf.nr_sensors = esys->nr_sensors;
163 if (loongson_sysconf.nr_sensors > MAX_SENSORS)
164 loongson_sysconf.nr_sensors = 0;
165 if (loongson_sysconf.nr_sensors)
166 memcpy(loongson_sysconf.sensors, esys->sensors,
167 sizeof(struct sensor_device) * loongson_sysconf.nr_sensors);
146#endif 168#endif
147 if (cpu_clock_freq == 0) { 169 if (cpu_clock_freq == 0) {
148 processor_id = (&current_cpu_data)->processor_id; 170 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[] = {
27 [MACH_DEXXON_GDIUM2F10] "dexxon-gdium-2f", 27 [MACH_DEXXON_GDIUM2F10] "dexxon-gdium-2f",
28 [MACH_LEMOTE_NAS] "lemote-nas-2f", 28 [MACH_LEMOTE_NAS] "lemote-nas-2f",
29 [MACH_LEMOTE_LL2F] "lemote-lynloong-2f", 29 [MACH_LEMOTE_LL2F] "lemote-lynloong-2f",
30 [MACH_LEMOTE_A1004] "lemote-3a-notebook-a1004", 30 [MACH_LOONGSON_GENERIC] "generic-loongson-machine",
31 [MACH_LEMOTE_A1101] "lemote-3a-itx-a1101",
32 [MACH_LEMOTE_A1201] "lemote-2gq-notebook-a1201",
33 [MACH_LEMOTE_A1205] "lemote-2gq-aio-a1205",
34 [MACH_LOONGSON_END] NULL, 31 [MACH_LOONGSON_END] NULL,
35}; 32};
36 33
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 @@
38 .regshift = 0, \ 38 .regshift = 0, \
39} 39}
40 40
41static struct plat_serial8250_port uart8250_data[][2] = { 41static struct plat_serial8250_port uart8250_data[][MAX_UARTS + 1] = {
42 [MACH_LOONGSON_UNKNOWN] {}, 42 [MACH_LOONGSON_UNKNOWN] {},
43 [MACH_LEMOTE_FL2E] {PORT(4, 1843200), {} }, 43 [MACH_LEMOTE_FL2E] {PORT(4, 1843200), {} },
44 [MACH_LEMOTE_FL2F] {PORT(3, 1843200), {} }, 44 [MACH_LEMOTE_FL2F] {PORT(3, 1843200), {} },
@@ -47,10 +47,7 @@ static struct plat_serial8250_port uart8250_data[][2] = {
47 [MACH_DEXXON_GDIUM2F10] {PORT_M(3, 3686400), {} }, 47 [MACH_DEXXON_GDIUM2F10] {PORT_M(3, 3686400), {} },
48 [MACH_LEMOTE_NAS] {PORT_M(3, 3686400), {} }, 48 [MACH_LEMOTE_NAS] {PORT_M(3, 3686400), {} },
49 [MACH_LEMOTE_LL2F] {PORT(3, 1843200), {} }, 49 [MACH_LEMOTE_LL2F] {PORT(3, 1843200), {} },
50 [MACH_LEMOTE_A1004] {PORT_M(2, 33177600), {} }, 50 [MACH_LOONGSON_GENERIC] {PORT_M(2, 25000000), {} },
51 [MACH_LEMOTE_A1101] {PORT_M(2, 25000000), {} },
52 [MACH_LEMOTE_A1201] {PORT_M(2, 25000000), {} },
53 [MACH_LEMOTE_A1205] {PORT_M(2, 25000000), {} },
54 [MACH_LOONGSON_END] {}, 51 [MACH_LOONGSON_END] {},
55}; 52};
56 53
@@ -61,17 +58,52 @@ static struct platform_device uart8250_device = {
61 58
62static int __init serial_init(void) 59static int __init serial_init(void)
63{ 60{
61 int i;
64 unsigned char iotype; 62 unsigned char iotype;
65 63
66 iotype = uart8250_data[mips_machtype][0].iotype; 64 iotype = uart8250_data[mips_machtype][0].iotype;
67 65
68 if (UPIO_MEM == iotype) 66 if (UPIO_MEM == iotype) {
67 uart8250_data[mips_machtype][0].mapbase =
68 loongson_uart_base[0];
69 uart8250_data[mips_machtype][0].membase = 69 uart8250_data[mips_machtype][0].membase =
70 (void __iomem *)_loongson_uart_base; 70 (void __iomem *)_loongson_uart_base[0];
71 }
71 else if (UPIO_PORT == iotype) 72 else if (UPIO_PORT == iotype)
72 uart8250_data[mips_machtype][0].iobase = 73 uart8250_data[mips_machtype][0].iobase =
73 loongson_uart_base - LOONGSON_PCIIO_BASE; 74 loongson_uart_base[0] - LOONGSON_PCIIO_BASE;
74 75
76 if (loongson_sysconf.uarts[0].uartclk)
77 uart8250_data[mips_machtype][0].uartclk =
78 loongson_sysconf.uarts[0].uartclk;
79
80 for (i = 1; i < loongson_sysconf.nr_uarts; i++) {
81 iotype = loongson_sysconf.uarts[i].iotype;
82 uart8250_data[mips_machtype][i].iotype = iotype;
83 loongson_uart_base[i] = loongson_sysconf.uarts[i].uart_base;
84
85 if (UPIO_MEM == iotype) {
86 uart8250_data[mips_machtype][i].irq =
87 MIPS_CPU_IRQ_BASE + loongson_sysconf.uarts[i].int_offset;
88 uart8250_data[mips_machtype][i].mapbase =
89 loongson_uart_base[i];
90 uart8250_data[mips_machtype][i].membase =
91 ioremap_nocache(loongson_uart_base[i], 8);
92 } else if (UPIO_PORT == iotype) {
93 uart8250_data[mips_machtype][i].irq =
94 loongson_sysconf.uarts[i].int_offset;
95 uart8250_data[mips_machtype][i].iobase =
96 loongson_uart_base[i] - LOONGSON_PCIIO_BASE;
97 }
98
99 uart8250_data[mips_machtype][i].uartclk =
100 loongson_sysconf.uarts[i].uartclk;
101 uart8250_data[mips_machtype][i].flags =
102 UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
103 }
104
105 memset(&uart8250_data[mips_machtype][loongson_sysconf.nr_uarts],
106 0, sizeof(struct plat_serial8250_port));
75 uart8250_device.dev.platform_data = uart8250_data[mips_machtype]; 107 uart8250_device.dev.platform_data = uart8250_data[mips_machtype];
76 108
77 return platform_device_register(&uart8250_device); 109 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 @@
13 13
14#include <loongson.h> 14#include <loongson.h>
15 15
16/* ioremapped */
17unsigned long _loongson_uart_base;
18EXPORT_SYMBOL(_loongson_uart_base);
19/* raw */ 16/* raw */
20unsigned long loongson_uart_base; 17unsigned long loongson_uart_base[MAX_UARTS] = {};
18/* ioremapped */
19unsigned long _loongson_uart_base[MAX_UARTS] = {};
20
21EXPORT_SYMBOL(loongson_uart_base); 21EXPORT_SYMBOL(loongson_uart_base);
22EXPORT_SYMBOL(_loongson_uart_base);
22 23
23void prom_init_loongson_uart_base(void) 24void prom_init_loongson_uart_base(void)
24{ 25{
25 switch (mips_machtype) { 26 switch (mips_machtype) {
27 case MACH_LOONGSON_GENERIC:
28 /* The CPU provided serial port (CPU) */
29 loongson_uart_base[0] = LOONGSON_REG_BASE + 0x1e0;
30 break;
26 case MACH_LEMOTE_FL2E: 31 case MACH_LEMOTE_FL2E:
27 loongson_uart_base = LOONGSON_PCIIO_BASE + 0x3f8; 32 loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x3f8;
28 break; 33 break;
29 case MACH_LEMOTE_FL2F: 34 case MACH_LEMOTE_FL2F:
30 case MACH_LEMOTE_LL2F: 35 case MACH_LEMOTE_LL2F:
31 loongson_uart_base = LOONGSON_PCIIO_BASE + 0x2f8; 36 loongson_uart_base[0] = LOONGSON_PCIIO_BASE + 0x2f8;
32 break; 37 break;
33 case MACH_LEMOTE_ML2F7: 38 case MACH_LEMOTE_ML2F7:
34 case MACH_LEMOTE_YL2F89: 39 case MACH_LEMOTE_YL2F89:
@@ -36,17 +41,10 @@ void prom_init_loongson_uart_base(void)
36 case MACH_LEMOTE_NAS: 41 case MACH_LEMOTE_NAS:
37 default: 42 default:
38 /* The CPU provided serial port (LPC) */ 43 /* The CPU provided serial port (LPC) */
39 loongson_uart_base = LOONGSON_LIO1_BASE + 0x3f8; 44 loongson_uart_base[0] = LOONGSON_LIO1_BASE + 0x3f8;
40 break;
41 case MACH_LEMOTE_A1004:
42 case MACH_LEMOTE_A1101:
43 case MACH_LEMOTE_A1201:
44 case MACH_LEMOTE_A1205:
45 /* The CPU provided serial port (CPU) */
46 loongson_uart_base = LOONGSON_REG_BASE + 0x1e0;
47 break; 45 break;
48 } 46 }
49 47
50 _loongson_uart_base = 48 _loongson_uart_base[0] =
51 (unsigned long)ioremap_nocache(loongson_uart_base, 8); 49 (unsigned long)ioremap_nocache(loongson_uart_base[0], 8);
52} 50}
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 @@
1# 1#
2# Makefile for Loongson-3 family machines 2# Makefile for Loongson-3 family machines
3# 3#
4obj-y += irq.o cop2-ex.o 4obj-y += irq.o cop2-ex.o platform.o
5 5
6obj-$(CONFIG_SMP) += smp.o 6obj-$(CONFIG_SMP) += smp.o
7 7
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 @@
1/*
2 * Copyright (C) 2009 Lemote Inc.
3 * Author: Wu Zhangjin, wuzhangjin@gmail.com
4 * Xiang Yu, xiangy@lemote.com
5 * Chen Huacai, chenhc@lemote.com
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/err.h>
14#include <linux/slab.h>
15#include <linux/platform_device.h>
16#include <asm/bootinfo.h>
17#include <boot_param.h>
18#include <loongson_hwmon.h>
19#include <workarounds.h>
20
21static int __init loongson3_platform_init(void)
22{
23 int i;
24 struct platform_device *pdev;
25
26 if (loongson_sysconf.ecname[0] != '\0')
27 platform_device_register_simple(loongson_sysconf.ecname, -1, NULL, 0);
28
29 for (i = 0; i < loongson_sysconf.nr_sensors; i++) {
30 if (loongson_sysconf.sensors[i].type > SENSOR_FAN)
31 continue;
32
33 pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
34 pdev->name = loongson_sysconf.sensors[i].name;
35 pdev->id = loongson_sysconf.sensors[i].id;
36 pdev->dev.platform_data = &loongson_sysconf.sensors[i];
37 platform_device_register(pdev);
38 }
39
40 return 0;
41}
42
43arch_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 @@
25#include <asm/tlbflush.h> 25#include <asm/tlbflush.h>
26#include <asm/cacheflush.h> 26#include <asm/cacheflush.h>
27#include <loongson.h> 27#include <loongson.h>
28#include <workarounds.h>
28 29
29#include "smp.h" 30#include "smp.h"
30 31
@@ -587,7 +588,7 @@ void loongson3_disable_clock(int cpu)
587 if (loongson_sysconf.cputype == Loongson_3A) { 588 if (loongson_sysconf.cputype == Loongson_3A) {
588 LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); 589 LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
589 } else if (loongson_sysconf.cputype == Loongson_3B) { 590 } else if (loongson_sysconf.cputype == Loongson_3B) {
590 if (!cpuhotplug_workaround) 591 if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
591 LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); 592 LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3));
592 } 593 }
593} 594}
@@ -600,7 +601,7 @@ void loongson3_enable_clock(int cpu)
600 if (loongson_sysconf.cputype == Loongson_3A) { 601 if (loongson_sysconf.cputype == Loongson_3A) {
601 LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); 602 LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
602 } else if (loongson_sysconf.cputype == Loongson_3B) { 603 } else if (loongson_sysconf.cputype == Loongson_3B) {
603 if (!cpuhotplug_workaround) 604 if (!(loongson_sysconf.workarounds & WORKAROUND_CPUHOTPLUG))
604 LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); 605 LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3);
605 } 606 }
606} 607}