xref: /linux/arch/mips/alchemy/devboards/platform.c (revision e2f48710459487341a70b5c433b87046da861ac9)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * devoard misc stuff.
4  */
5 
6 #include <linux/init.h>
7 #include <linux/mtd/mtd.h>
8 #include <linux/mtd/map.h>
9 #include <linux/mtd/physmap.h>
10 #include <linux/slab.h>
11 #include <linux/platform_device.h>
12 #include <linux/pm.h>
13 
14 #include <asm/bootinfo.h>
15 #include <asm/idle.h>
16 #include <asm/reboot.h>
17 #include <asm/setup.h>
18 #include <asm/mach-au1x00/au1000.h>
19 #include <asm/mach-db1x00/bcsr.h>
20 
21 #include <prom.h>
22 
23 #include "platform.h"
24 
25 void prom_putchar(char c)
26 {
27 	if (alchemy_get_cputype() == ALCHEMY_CPU_AU1300)
28 		alchemy_uart_putchar(AU1300_UART2_PHYS_ADDR, c);
29 	else
30 		alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
31 }
32 
33 
34 static struct platform_device db1x00_rtc_dev = {
35 	.name	= "rtc-au1xxx",
36 	.id	= -1,
37 };
38 
39 
40 static void db1x_power_off(void)
41 {
42 	bcsr_write(BCSR_RESETS, 0);
43 	bcsr_write(BCSR_SYSTEM, BCSR_SYSTEM_PWROFF | BCSR_SYSTEM_RESET);
44 	while (1)		/* sit and spin */
45 		cpu_wait();
46 }
47 
48 static void db1x_reset(char *c)
49 {
50 	bcsr_write(BCSR_RESETS, 0);
51 	bcsr_write(BCSR_SYSTEM, 0);
52 }
53 
54 static int __init db1x_late_setup(void)
55 {
56 	if (!pm_power_off)
57 		pm_power_off = db1x_power_off;
58 	if (!_machine_halt)
59 		_machine_halt = db1x_power_off;
60 	if (!_machine_restart)
61 		_machine_restart = db1x_reset;
62 
63 	platform_device_register(&db1x00_rtc_dev);
64 
65 	return 0;
66 }
67 device_initcall(db1x_late_setup);
68 
69 /* register a pcmcia socket */
70 int __init db1x_register_pcmcia_socket(phys_addr_t pcmcia_attr_start,
71 				       phys_addr_t pcmcia_attr_end,
72 				       phys_addr_t pcmcia_mem_start,
73 				       phys_addr_t pcmcia_mem_end,
74 				       phys_addr_t pcmcia_io_start,
75 				       phys_addr_t pcmcia_io_end,
76 				       int card_irq,
77 				       int cd_irq,
78 				       int stschg_irq,
79 				       int eject_irq,
80 				       int id)
81 {
82 	int cnt, i, ret;
83 	struct resource *sr;
84 	struct platform_device *pd;
85 
86 	cnt = 5;
87 	if (eject_irq)
88 		cnt++;
89 	if (stschg_irq)
90 		cnt++;
91 
92 	sr = kzalloc_objs(struct resource, cnt);
93 	if (!sr)
94 		return -ENOMEM;
95 
96 	pd = platform_device_alloc("db1xxx_pcmcia", id);
97 	if (!pd) {
98 		ret = -ENOMEM;
99 		goto out;
100 	}
101 
102 	sr[0].name	= "pcmcia-attr";
103 	sr[0].flags	= IORESOURCE_MEM;
104 	sr[0].start	= pcmcia_attr_start;
105 	sr[0].end	= pcmcia_attr_end;
106 
107 	sr[1].name	= "pcmcia-mem";
108 	sr[1].flags	= IORESOURCE_MEM;
109 	sr[1].start	= pcmcia_mem_start;
110 	sr[1].end	= pcmcia_mem_end;
111 
112 	sr[2].name	= "pcmcia-io";
113 	sr[2].flags	= IORESOURCE_MEM;
114 	sr[2].start	= pcmcia_io_start;
115 	sr[2].end	= pcmcia_io_end;
116 
117 	sr[3].name	= "insert";
118 	sr[3].flags	= IORESOURCE_IRQ;
119 	sr[3].start = sr[3].end = cd_irq;
120 
121 	sr[4].name	= "card";
122 	sr[4].flags	= IORESOURCE_IRQ;
123 	sr[4].start = sr[4].end = card_irq;
124 
125 	i = 5;
126 	if (stschg_irq) {
127 		sr[i].name	= "stschg";
128 		sr[i].flags	= IORESOURCE_IRQ;
129 		sr[i].start = sr[i].end = stschg_irq;
130 		i++;
131 	}
132 	if (eject_irq) {
133 		sr[i].name	= "eject";
134 		sr[i].flags	= IORESOURCE_IRQ;
135 		sr[i].start = sr[i].end = eject_irq;
136 	}
137 
138 	pd->resource = sr;
139 	pd->num_resources = cnt;
140 
141 	ret = platform_device_add(pd);
142 	if (!ret)
143 		return 0;
144 
145 	platform_device_put(pd);
146 out:
147 	kfree(sr);
148 	return ret;
149 }
150 
151 #define YAMON_SIZE	0x00100000
152 #define YAMON_ENV_SIZE	0x00040000
153 
154 int __init db1x_register_norflash(unsigned long size, int width,
155 				  int swapped)
156 {
157 	struct physmap_flash_data *pfd;
158 	struct platform_device *pd;
159 	struct mtd_partition *parts;
160 	struct resource *res;
161 	int ret, i;
162 
163 	if (size < (8 * 1024 * 1024))
164 		return -EINVAL;
165 
166 	ret = -ENOMEM;
167 	parts = kzalloc_objs(struct mtd_partition, 5);
168 	if (!parts)
169 		goto out;
170 
171 	res = kzalloc_obj(struct resource);
172 	if (!res)
173 		goto out1;
174 
175 	pfd = kzalloc_obj(struct physmap_flash_data);
176 	if (!pfd)
177 		goto out2;
178 
179 	pd = platform_device_alloc("physmap-flash", 0);
180 	if (!pd)
181 		goto out3;
182 
183 	/* NOR flash ends at 0x20000000, regardless of size */
184 	res->start = 0x20000000 - size;
185 	res->end = 0x20000000 - 1;
186 	res->flags = IORESOURCE_MEM;
187 
188 	/* partition setup.  Most Develboards have a switch which allows
189 	 * to swap the physical locations of the 2 NOR flash banks.
190 	 */
191 	i = 0;
192 	if (!swapped) {
193 		/* first NOR chip */
194 		parts[i].offset = 0;
195 		parts[i].name = "User FS";
196 		parts[i].size = size / 2;
197 		i++;
198 	}
199 
200 	parts[i].offset = MTDPART_OFS_APPEND;
201 	parts[i].name = "User FS 2";
202 	parts[i].size = (size / 2) - (0x20000000 - 0x1fc00000);
203 	i++;
204 
205 	parts[i].offset = MTDPART_OFS_APPEND;
206 	parts[i].name = "YAMON";
207 	parts[i].size = YAMON_SIZE;
208 	parts[i].mask_flags = MTD_WRITEABLE;
209 	i++;
210 
211 	parts[i].offset = MTDPART_OFS_APPEND;
212 	parts[i].name = "raw kernel";
213 	parts[i].size = 0x00400000 - YAMON_SIZE - YAMON_ENV_SIZE;
214 	i++;
215 
216 	parts[i].offset = MTDPART_OFS_APPEND;
217 	parts[i].name = "YAMON Env";
218 	parts[i].size = YAMON_ENV_SIZE;
219 	parts[i].mask_flags = MTD_WRITEABLE;
220 	i++;
221 
222 	if (swapped) {
223 		parts[i].offset = MTDPART_OFS_APPEND;
224 		parts[i].name = "User FS";
225 		parts[i].size = size / 2;
226 		i++;
227 	}
228 
229 	pfd->width = width;
230 	pfd->parts = parts;
231 	pfd->nr_parts = 5;
232 
233 	pd->dev.platform_data = pfd;
234 	pd->resource = res;
235 	pd->num_resources = 1;
236 
237 	ret = platform_device_add(pd);
238 	if (!ret)
239 		return ret;
240 
241 	platform_device_put(pd);
242 out3:
243 	kfree(pfd);
244 out2:
245 	kfree(res);
246 out1:
247 	kfree(parts);
248 out:
249 	return ret;
250 }
251