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