diff options
Diffstat (limited to 'arch/mips/loongson1/common')
-rw-r--r-- | arch/mips/loongson1/common/Makefile | 5 | ||||
-rw-r--r-- | arch/mips/loongson1/common/clock.c | 165 | ||||
-rw-r--r-- | arch/mips/loongson1/common/irq.c | 147 | ||||
-rw-r--r-- | arch/mips/loongson1/common/platform.c | 124 | ||||
-rw-r--r-- | arch/mips/loongson1/common/prom.c | 87 | ||||
-rw-r--r-- | arch/mips/loongson1/common/reset.c | 45 | ||||
-rw-r--r-- | arch/mips/loongson1/common/setup.c | 29 |
7 files changed, 602 insertions, 0 deletions
diff --git a/arch/mips/loongson1/common/Makefile b/arch/mips/loongson1/common/Makefile new file mode 100644 index 000000000000..b2797709ef5b --- /dev/null +++ b/arch/mips/loongson1/common/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for common code of loongson1 based machines. | ||
3 | # | ||
4 | |||
5 | obj-y += clock.o irq.o platform.o prom.o reset.o setup.o | ||
diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c new file mode 100644 index 000000000000..2d98fb030596 --- /dev/null +++ b/arch/mips/loongson1/common/clock.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/list.h> | ||
12 | #include <linux/mutex.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <asm/clock.h> | ||
16 | #include <asm/time.h> | ||
17 | |||
18 | #include <loongson1.h> | ||
19 | |||
20 | static LIST_HEAD(clocks); | ||
21 | static DEFINE_MUTEX(clocks_mutex); | ||
22 | |||
23 | struct clk *clk_get(struct device *dev, const char *name) | ||
24 | { | ||
25 | struct clk *c; | ||
26 | struct clk *ret = NULL; | ||
27 | |||
28 | mutex_lock(&clocks_mutex); | ||
29 | list_for_each_entry(c, &clocks, node) { | ||
30 | if (!strcmp(c->name, name)) { | ||
31 | ret = c; | ||
32 | break; | ||
33 | } | ||
34 | } | ||
35 | mutex_unlock(&clocks_mutex); | ||
36 | |||
37 | return ret; | ||
38 | } | ||
39 | EXPORT_SYMBOL(clk_get); | ||
40 | |||
41 | unsigned long clk_get_rate(struct clk *clk) | ||
42 | { | ||
43 | return clk->rate; | ||
44 | } | ||
45 | EXPORT_SYMBOL(clk_get_rate); | ||
46 | |||
47 | static void pll_clk_init(struct clk *clk) | ||
48 | { | ||
49 | u32 pll; | ||
50 | |||
51 | pll = __raw_readl(LS1X_CLK_PLL_FREQ); | ||
52 | clk->rate = (12 + (pll & 0x3f)) * 33 / 2 | ||
53 | + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2; | ||
54 | clk->rate *= 1000000; | ||
55 | } | ||
56 | |||
57 | static void cpu_clk_init(struct clk *clk) | ||
58 | { | ||
59 | u32 pll, ctrl; | ||
60 | |||
61 | pll = clk_get_rate(clk->parent); | ||
62 | ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU; | ||
63 | clk->rate = pll / (ctrl >> DIV_CPU_SHIFT); | ||
64 | } | ||
65 | |||
66 | static void ddr_clk_init(struct clk *clk) | ||
67 | { | ||
68 | u32 pll, ctrl; | ||
69 | |||
70 | pll = clk_get_rate(clk->parent); | ||
71 | ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR; | ||
72 | clk->rate = pll / (ctrl >> DIV_DDR_SHIFT); | ||
73 | } | ||
74 | |||
75 | static void dc_clk_init(struct clk *clk) | ||
76 | { | ||
77 | u32 pll, ctrl; | ||
78 | |||
79 | pll = clk_get_rate(clk->parent); | ||
80 | ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC; | ||
81 | clk->rate = pll / (ctrl >> DIV_DC_SHIFT); | ||
82 | } | ||
83 | |||
84 | static struct clk_ops pll_clk_ops = { | ||
85 | .init = pll_clk_init, | ||
86 | }; | ||
87 | |||
88 | static struct clk_ops cpu_clk_ops = { | ||
89 | .init = cpu_clk_init, | ||
90 | }; | ||
91 | |||
92 | static struct clk_ops ddr_clk_ops = { | ||
93 | .init = ddr_clk_init, | ||
94 | }; | ||
95 | |||
96 | static struct clk_ops dc_clk_ops = { | ||
97 | .init = dc_clk_init, | ||
98 | }; | ||
99 | |||
100 | static struct clk pll_clk = { | ||
101 | .name = "pll", | ||
102 | .ops = &pll_clk_ops, | ||
103 | }; | ||
104 | |||
105 | static struct clk cpu_clk = { | ||
106 | .name = "cpu", | ||
107 | .parent = &pll_clk, | ||
108 | .ops = &cpu_clk_ops, | ||
109 | }; | ||
110 | |||
111 | static struct clk ddr_clk = { | ||
112 | .name = "ddr", | ||
113 | .parent = &pll_clk, | ||
114 | .ops = &ddr_clk_ops, | ||
115 | }; | ||
116 | |||
117 | static struct clk dc_clk = { | ||
118 | .name = "dc", | ||
119 | .parent = &pll_clk, | ||
120 | .ops = &dc_clk_ops, | ||
121 | }; | ||
122 | |||
123 | int clk_register(struct clk *clk) | ||
124 | { | ||
125 | mutex_lock(&clocks_mutex); | ||
126 | list_add(&clk->node, &clocks); | ||
127 | if (clk->ops->init) | ||
128 | clk->ops->init(clk); | ||
129 | mutex_unlock(&clocks_mutex); | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | EXPORT_SYMBOL(clk_register); | ||
134 | |||
135 | static struct clk *ls1x_clks[] = { | ||
136 | &pll_clk, | ||
137 | &cpu_clk, | ||
138 | &ddr_clk, | ||
139 | &dc_clk, | ||
140 | }; | ||
141 | |||
142 | int __init ls1x_clock_init(void) | ||
143 | { | ||
144 | int i; | ||
145 | |||
146 | for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++) | ||
147 | clk_register(ls1x_clks[i]); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | void __init plat_time_init(void) | ||
153 | { | ||
154 | struct clk *clk; | ||
155 | |||
156 | /* Initialize LS1X clocks */ | ||
157 | ls1x_clock_init(); | ||
158 | |||
159 | /* setup mips r4k timer */ | ||
160 | clk = clk_get(NULL, "cpu"); | ||
161 | if (IS_ERR(clk)) | ||
162 | panic("unable to get dc clock, err=%ld", PTR_ERR(clk)); | ||
163 | |||
164 | mips_hpt_frequency = clk_get_rate(clk) / 2; | ||
165 | } | ||
diff --git a/arch/mips/loongson1/common/irq.c b/arch/mips/loongson1/common/irq.c new file mode 100644 index 000000000000..41bc8ffe7bba --- /dev/null +++ b/arch/mips/loongson1/common/irq.c | |||
@@ -0,0 +1,147 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <asm/irq_cpu.h> | ||
13 | |||
14 | #include <loongson1.h> | ||
15 | #include <irq.h> | ||
16 | |||
17 | #define LS1X_INTC_REG(n, x) \ | ||
18 | ((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x))) | ||
19 | |||
20 | #define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0) | ||
21 | #define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4) | ||
22 | #define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8) | ||
23 | #define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc) | ||
24 | #define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10) | ||
25 | #define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14) | ||
26 | |||
27 | static void ls1x_irq_ack(struct irq_data *d) | ||
28 | { | ||
29 | unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; | ||
30 | unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; | ||
31 | |||
32 | __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) | ||
33 | | (1 << bit), LS1X_INTC_INTCLR(n)); | ||
34 | } | ||
35 | |||
36 | static void ls1x_irq_mask(struct irq_data *d) | ||
37 | { | ||
38 | unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; | ||
39 | unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; | ||
40 | |||
41 | __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) | ||
42 | & ~(1 << bit), LS1X_INTC_INTIEN(n)); | ||
43 | } | ||
44 | |||
45 | static void ls1x_irq_mask_ack(struct irq_data *d) | ||
46 | { | ||
47 | unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; | ||
48 | unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; | ||
49 | |||
50 | __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) | ||
51 | & ~(1 << bit), LS1X_INTC_INTIEN(n)); | ||
52 | __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) | ||
53 | | (1 << bit), LS1X_INTC_INTCLR(n)); | ||
54 | } | ||
55 | |||
56 | static void ls1x_irq_unmask(struct irq_data *d) | ||
57 | { | ||
58 | unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; | ||
59 | unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; | ||
60 | |||
61 | __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) | ||
62 | | (1 << bit), LS1X_INTC_INTIEN(n)); | ||
63 | } | ||
64 | |||
65 | static struct irq_chip ls1x_irq_chip = { | ||
66 | .name = "LS1X-INTC", | ||
67 | .irq_ack = ls1x_irq_ack, | ||
68 | .irq_mask = ls1x_irq_mask, | ||
69 | .irq_mask_ack = ls1x_irq_mask_ack, | ||
70 | .irq_unmask = ls1x_irq_unmask, | ||
71 | }; | ||
72 | |||
73 | static void ls1x_irq_dispatch(int n) | ||
74 | { | ||
75 | u32 int_status, irq; | ||
76 | |||
77 | /* Get pending sources, masked by current enables */ | ||
78 | int_status = __raw_readl(LS1X_INTC_INTISR(n)) & | ||
79 | __raw_readl(LS1X_INTC_INTIEN(n)); | ||
80 | |||
81 | if (int_status) { | ||
82 | irq = LS1X_IRQ(n, __ffs(int_status)); | ||
83 | do_IRQ(irq); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | asmlinkage void plat_irq_dispatch(void) | ||
88 | { | ||
89 | unsigned int pending; | ||
90 | |||
91 | pending = read_c0_cause() & read_c0_status() & ST0_IM; | ||
92 | |||
93 | if (pending & CAUSEF_IP7) | ||
94 | do_IRQ(TIMER_IRQ); | ||
95 | else if (pending & CAUSEF_IP2) | ||
96 | ls1x_irq_dispatch(0); /* INT0 */ | ||
97 | else if (pending & CAUSEF_IP3) | ||
98 | ls1x_irq_dispatch(1); /* INT1 */ | ||
99 | else if (pending & CAUSEF_IP4) | ||
100 | ls1x_irq_dispatch(2); /* INT2 */ | ||
101 | else if (pending & CAUSEF_IP5) | ||
102 | ls1x_irq_dispatch(3); /* INT3 */ | ||
103 | else if (pending & CAUSEF_IP6) | ||
104 | ls1x_irq_dispatch(4); /* INT4 */ | ||
105 | else | ||
106 | spurious_interrupt(); | ||
107 | |||
108 | } | ||
109 | |||
110 | struct irqaction cascade_irqaction = { | ||
111 | .handler = no_action, | ||
112 | .name = "cascade", | ||
113 | .flags = IRQF_NO_THREAD, | ||
114 | }; | ||
115 | |||
116 | static void __init ls1x_irq_init(int base) | ||
117 | { | ||
118 | int n; | ||
119 | |||
120 | /* Disable interrupts and clear pending, | ||
121 | * setup all IRQs as high level triggered | ||
122 | */ | ||
123 | for (n = 0; n < 4; n++) { | ||
124 | __raw_writel(0x0, LS1X_INTC_INTIEN(n)); | ||
125 | __raw_writel(0xffffffff, LS1X_INTC_INTCLR(n)); | ||
126 | __raw_writel(0xffffffff, LS1X_INTC_INTPOL(n)); | ||
127 | /* set DMA0, DMA1 and DMA2 to edge trigger */ | ||
128 | __raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n)); | ||
129 | } | ||
130 | |||
131 | |||
132 | for (n = base; n < LS1X_IRQS; n++) { | ||
133 | irq_set_chip_and_handler(n, &ls1x_irq_chip, | ||
134 | handle_level_irq); | ||
135 | } | ||
136 | |||
137 | setup_irq(INT0_IRQ, &cascade_irqaction); | ||
138 | setup_irq(INT1_IRQ, &cascade_irqaction); | ||
139 | setup_irq(INT2_IRQ, &cascade_irqaction); | ||
140 | setup_irq(INT3_IRQ, &cascade_irqaction); | ||
141 | } | ||
142 | |||
143 | void __init arch_init_irq(void) | ||
144 | { | ||
145 | mips_cpu_irq_init(); | ||
146 | ls1x_irq_init(LS1X_IRQ_BASE); | ||
147 | } | ||
diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c new file mode 100644 index 000000000000..e92d59c4bd78 --- /dev/null +++ b/arch/mips/loongson1/common/platform.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/clk.h> | ||
11 | #include <linux/dma-mapping.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/phy.h> | ||
14 | #include <linux/serial_8250.h> | ||
15 | #include <linux/stmmac.h> | ||
16 | #include <asm-generic/sizes.h> | ||
17 | |||
18 | #include <loongson1.h> | ||
19 | |||
20 | #define LS1X_UART(_id) \ | ||
21 | { \ | ||
22 | .mapbase = LS1X_UART ## _id ## _BASE, \ | ||
23 | .irq = LS1X_UART ## _id ## _IRQ, \ | ||
24 | .iotype = UPIO_MEM, \ | ||
25 | .flags = UPF_IOREMAP | UPF_FIXED_TYPE, \ | ||
26 | .type = PORT_16550A, \ | ||
27 | } | ||
28 | |||
29 | static struct plat_serial8250_port ls1x_serial8250_port[] = { | ||
30 | LS1X_UART(0), | ||
31 | LS1X_UART(1), | ||
32 | LS1X_UART(2), | ||
33 | LS1X_UART(3), | ||
34 | {}, | ||
35 | }; | ||
36 | |||
37 | struct platform_device ls1x_uart_device = { | ||
38 | .name = "serial8250", | ||
39 | .id = PLAT8250_DEV_PLATFORM, | ||
40 | .dev = { | ||
41 | .platform_data = ls1x_serial8250_port, | ||
42 | }, | ||
43 | }; | ||
44 | |||
45 | void __init ls1x_serial_setup(void) | ||
46 | { | ||
47 | struct clk *clk; | ||
48 | struct plat_serial8250_port *p; | ||
49 | |||
50 | clk = clk_get(NULL, "dc"); | ||
51 | if (IS_ERR(clk)) | ||
52 | panic("unable to get dc clock, err=%ld", PTR_ERR(clk)); | ||
53 | |||
54 | for (p = ls1x_serial8250_port; p->flags != 0; ++p) | ||
55 | p->uartclk = clk_get_rate(clk); | ||
56 | } | ||
57 | |||
58 | /* Synopsys Ethernet GMAC */ | ||
59 | static struct resource ls1x_eth0_resources[] = { | ||
60 | [0] = { | ||
61 | .start = LS1X_GMAC0_BASE, | ||
62 | .end = LS1X_GMAC0_BASE + SZ_64K - 1, | ||
63 | .flags = IORESOURCE_MEM, | ||
64 | }, | ||
65 | [1] = { | ||
66 | .name = "macirq", | ||
67 | .start = LS1X_GMAC0_IRQ, | ||
68 | .flags = IORESOURCE_IRQ, | ||
69 | }, | ||
70 | }; | ||
71 | |||
72 | static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { | ||
73 | .bus_id = 0, | ||
74 | .phy_mask = 0, | ||
75 | }; | ||
76 | |||
77 | static struct plat_stmmacenet_data ls1x_eth_data = { | ||
78 | .bus_id = 0, | ||
79 | .phy_addr = -1, | ||
80 | .mdio_bus_data = &ls1x_mdio_bus_data, | ||
81 | .has_gmac = 1, | ||
82 | .tx_coe = 1, | ||
83 | }; | ||
84 | |||
85 | struct platform_device ls1x_eth0_device = { | ||
86 | .name = "stmmaceth", | ||
87 | .id = 0, | ||
88 | .num_resources = ARRAY_SIZE(ls1x_eth0_resources), | ||
89 | .resource = ls1x_eth0_resources, | ||
90 | .dev = { | ||
91 | .platform_data = &ls1x_eth_data, | ||
92 | }, | ||
93 | }; | ||
94 | |||
95 | /* USB EHCI */ | ||
96 | static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32); | ||
97 | |||
98 | static struct resource ls1x_ehci_resources[] = { | ||
99 | [0] = { | ||
100 | .start = LS1X_EHCI_BASE, | ||
101 | .end = LS1X_EHCI_BASE + SZ_32K - 1, | ||
102 | .flags = IORESOURCE_MEM, | ||
103 | }, | ||
104 | [1] = { | ||
105 | .start = LS1X_EHCI_IRQ, | ||
106 | .flags = IORESOURCE_IRQ, | ||
107 | }, | ||
108 | }; | ||
109 | |||
110 | struct platform_device ls1x_ehci_device = { | ||
111 | .name = "ls1x-ehci", | ||
112 | .id = -1, | ||
113 | .num_resources = ARRAY_SIZE(ls1x_ehci_resources), | ||
114 | .resource = ls1x_ehci_resources, | ||
115 | .dev = { | ||
116 | .dma_mask = &ls1x_ehci_dmamask, | ||
117 | }, | ||
118 | }; | ||
119 | |||
120 | /* Real Time Clock */ | ||
121 | struct platform_device ls1x_rtc_device = { | ||
122 | .name = "ls1x-rtc", | ||
123 | .id = -1, | ||
124 | }; | ||
diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson1/common/prom.c new file mode 100644 index 000000000000..1f8e49f9886d --- /dev/null +++ b/arch/mips/loongson1/common/prom.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * Modified from arch/mips/pnx833x/common/prom.c. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/serial_reg.h> | ||
13 | #include <asm/bootinfo.h> | ||
14 | |||
15 | #include <loongson1.h> | ||
16 | #include <prom.h> | ||
17 | |||
18 | int prom_argc; | ||
19 | char **prom_argv, **prom_envp; | ||
20 | unsigned long memsize, highmemsize; | ||
21 | |||
22 | char *prom_getenv(char *envname) | ||
23 | { | ||
24 | char **env = prom_envp; | ||
25 | int i; | ||
26 | |||
27 | i = strlen(envname); | ||
28 | |||
29 | while (*env) { | ||
30 | if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=') | ||
31 | return *env + i + 1; | ||
32 | env++; | ||
33 | } | ||
34 | |||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | static inline unsigned long env_or_default(char *env, unsigned long dfl) | ||
39 | { | ||
40 | char *str = prom_getenv(env); | ||
41 | return str ? simple_strtol(str, 0, 0) : dfl; | ||
42 | } | ||
43 | |||
44 | void __init prom_init_cmdline(void) | ||
45 | { | ||
46 | char *c = &(arcs_cmdline[0]); | ||
47 | int i; | ||
48 | |||
49 | for (i = 1; i < prom_argc; i++) { | ||
50 | strcpy(c, prom_argv[i]); | ||
51 | c += strlen(prom_argv[i]); | ||
52 | if (i < prom_argc-1) | ||
53 | *c++ = ' '; | ||
54 | } | ||
55 | *c = 0; | ||
56 | } | ||
57 | |||
58 | void __init prom_init(void) | ||
59 | { | ||
60 | prom_argc = fw_arg0; | ||
61 | prom_argv = (char **)fw_arg1; | ||
62 | prom_envp = (char **)fw_arg2; | ||
63 | |||
64 | prom_init_cmdline(); | ||
65 | |||
66 | memsize = env_or_default("memsize", DEFAULT_MEMSIZE); | ||
67 | highmemsize = env_or_default("highmemsize", 0x0); | ||
68 | } | ||
69 | |||
70 | void __init prom_free_prom_memory(void) | ||
71 | { | ||
72 | } | ||
73 | |||
74 | #define PORT(offset) (u8 *)(KSEG1ADDR(LS1X_UART0_BASE + offset)) | ||
75 | |||
76 | void __init prom_putchar(char c) | ||
77 | { | ||
78 | int timeout; | ||
79 | |||
80 | timeout = 1024; | ||
81 | |||
82 | while (((readb(PORT(UART_LSR)) & UART_LSR_THRE) == 0) | ||
83 | && (timeout-- > 0)) | ||
84 | ; | ||
85 | |||
86 | writeb(c, PORT(UART_TX)); | ||
87 | } | ||
diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson1/common/reset.c new file mode 100644 index 000000000000..fb979a784eca --- /dev/null +++ b/arch/mips/loongson1/common/reset.c | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/io.h> | ||
11 | #include <linux/pm.h> | ||
12 | #include <asm/reboot.h> | ||
13 | |||
14 | #include <loongson1.h> | ||
15 | |||
16 | static void ls1x_restart(char *command) | ||
17 | { | ||
18 | __raw_writel(0x1, LS1X_WDT_EN); | ||
19 | __raw_writel(0x5000000, LS1X_WDT_TIMER); | ||
20 | __raw_writel(0x1, LS1X_WDT_SET); | ||
21 | } | ||
22 | |||
23 | static void ls1x_halt(void) | ||
24 | { | ||
25 | while (1) { | ||
26 | if (cpu_wait) | ||
27 | cpu_wait(); | ||
28 | } | ||
29 | } | ||
30 | |||
31 | static void ls1x_power_off(void) | ||
32 | { | ||
33 | ls1x_halt(); | ||
34 | } | ||
35 | |||
36 | static int __init ls1x_reboot_setup(void) | ||
37 | { | ||
38 | _machine_restart = ls1x_restart; | ||
39 | _machine_halt = ls1x_halt; | ||
40 | pm_power_off = ls1x_power_off; | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | arch_initcall(ls1x_reboot_setup); | ||
diff --git a/arch/mips/loongson1/common/setup.c b/arch/mips/loongson1/common/setup.c new file mode 100644 index 000000000000..62128cc27e68 --- /dev/null +++ b/arch/mips/loongson1/common/setup.c | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License as published by the | ||
6 | * Free Software Foundation; either version 2 of the License, or (at your | ||
7 | * option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <asm/bootinfo.h> | ||
11 | |||
12 | #include <prom.h> | ||
13 | |||
14 | void __init plat_mem_setup(void) | ||
15 | { | ||
16 | add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM); | ||
17 | } | ||
18 | |||
19 | const char *get_system_type(void) | ||
20 | { | ||
21 | unsigned int processor_id = (¤t_cpu_data)->processor_id; | ||
22 | |||
23 | switch (processor_id & PRID_REV_MASK) { | ||
24 | case PRID_REV_LOONGSON1B: | ||
25 | return "LOONGSON LS1B"; | ||
26 | default: | ||
27 | return "LOONGSON (unknown)"; | ||
28 | } | ||
29 | } | ||