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