MIPS: Alchemy: physmap-flash for all devboards
[firefly-linux-kernel-4.4.55.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
12 /* register a pcmcia socket */
13 int __init db1x_register_pcmcia_socket(unsigned long pseudo_attr_start,
14                                        unsigned long pseudo_attr_end,
15                                        unsigned long pseudo_mem_start,
16                                        unsigned long pseudo_mem_end,
17                                        unsigned long pseudo_io_start,
18                                        unsigned long pseudo_io_end,
19                                        int card_irq,
20                                        int cd_irq,
21                                        int stschg_irq,
22                                        int eject_irq,
23                                        int id)
24 {
25         int cnt, i, ret;
26         struct resource *sr;
27         struct platform_device *pd;
28
29         cnt = 5;
30         if (eject_irq)
31                 cnt++;
32         if (stschg_irq)
33                 cnt++;
34
35         sr = kzalloc(sizeof(struct resource) * cnt, GFP_KERNEL);
36         if (!sr)
37                 return -ENOMEM;
38
39         pd = platform_device_alloc("db1xxx_pcmcia", id);
40         if (!pd) {
41                 ret = -ENOMEM;
42                 goto out;
43         }
44
45         sr[0].name      = "pseudo-attr";
46         sr[0].flags     = IORESOURCE_MEM;
47         sr[0].start     = pseudo_attr_start;
48         sr[0].end       = pseudo_attr_end;
49
50         sr[1].name      = "pseudo-mem";
51         sr[1].flags     = IORESOURCE_MEM;
52         sr[1].start     = pseudo_mem_start;
53         sr[1].end       = pseudo_mem_end;
54
55         sr[2].name      = "pseudo-io";
56         sr[2].flags     = IORESOURCE_MEM;
57         sr[2].start     = pseudo_io_start;
58         sr[2].end       = pseudo_io_end;
59
60         sr[3].name      = "insert";
61         sr[3].flags     = IORESOURCE_IRQ;
62         sr[3].start = sr[3].end = cd_irq;
63
64         sr[4].name      = "card";
65         sr[4].flags     = IORESOURCE_IRQ;
66         sr[4].start = sr[4].end = card_irq;
67
68         i = 5;
69         if (stschg_irq) {
70                 sr[i].name      = "insert";
71                 sr[i].flags     = IORESOURCE_IRQ;
72                 sr[i].start = sr[i].end = cd_irq;
73                 i++;
74         }
75         if (eject_irq) {
76                 sr[i].name      = "eject";
77                 sr[i].flags     = IORESOURCE_IRQ;
78                 sr[i].start = sr[i].end = eject_irq;
79         }
80
81         pd->resource = sr;
82         pd->num_resources = cnt;
83
84         ret = platform_device_add(pd);
85         if (!ret)
86                 return 0;
87
88         platform_device_put(pd);
89 out:
90         kfree(sr);
91         return ret;
92 }
93
94 #define YAMON_SIZE      0x00100000
95 #define YAMON_ENV_SIZE  0x00040000
96
97 int __init db1x_register_norflash(unsigned long size, int width,
98                                   int swapped)
99 {
100         struct physmap_flash_data *pfd;
101         struct platform_device *pd;
102         struct mtd_partition *parts;
103         struct resource *res;
104         int ret, i;
105
106         if (size < (8 * 1024 * 1024))
107                 return -EINVAL;
108
109         ret = -ENOMEM;
110         parts = kzalloc(sizeof(struct mtd_partition) * 5, GFP_KERNEL);
111         if (!parts)
112                 goto out;
113
114         res = kzalloc(sizeof(struct resource), GFP_KERNEL);
115         if (!res)
116                 goto out1;
117
118         pfd = kzalloc(sizeof(struct physmap_flash_data), GFP_KERNEL);
119         if (!pfd)
120                 goto out2;
121
122         pd = platform_device_alloc("physmap-flash", 0);
123         if (!pd)
124                 goto out3;
125
126         /* NOR flash ends at 0x20000000, regardless of size */
127         res->start = 0x20000000 - size;
128         res->end = 0x20000000 - 1;
129         res->flags = IORESOURCE_MEM;
130
131         /* partition setup.  Most Develboards have a switch which allows
132          * to swap the physical locations of the 2 NOR flash banks.
133          */
134         i = 0;
135         if (!swapped) {
136                 /* first NOR chip */
137                 parts[i].offset = 0;
138                 parts[i].name = "User FS";
139                 parts[i].size = size / 2;
140                 i++;
141         }
142
143         parts[i].offset = MTDPART_OFS_APPEND;
144         parts[i].name = "User FS 2";
145         parts[i].size = (size / 2) - (0x20000000 - 0x1fc00000);
146         i++;
147
148         parts[i].offset = MTDPART_OFS_APPEND;
149         parts[i].name = "YAMON";
150         parts[i].size = YAMON_SIZE;
151         parts[i].mask_flags = MTD_WRITEABLE;
152         i++;
153
154         parts[i].offset = MTDPART_OFS_APPEND;
155         parts[i].name = "raw kernel";
156         parts[i].size = 0x00400000 - YAMON_SIZE - YAMON_ENV_SIZE;
157         i++;
158
159         parts[i].offset = MTDPART_OFS_APPEND;
160         parts[i].name = "YAMON Env";
161         parts[i].size = YAMON_ENV_SIZE;
162         parts[i].mask_flags = MTD_WRITEABLE;
163         i++;
164
165         if (swapped) {
166                 parts[i].offset = MTDPART_OFS_APPEND;
167                 parts[i].name = "User FS";
168                 parts[i].size = size / 2;
169                 i++;
170         }
171
172         pfd->width = width;
173         pfd->parts = parts;
174         pfd->nr_parts = 5;
175
176         pd->dev.platform_data = pfd;
177         pd->resource = res;
178         pd->num_resources = 1;
179
180         ret = platform_device_add(pd);
181         if (!ret)
182                 return ret;
183
184         platform_device_put(pd);
185 out3:
186         kfree(pfd);
187 out2:
188         kfree(res);
189 out1:
190         kfree(parts);
191 out:
192         return ret;
193 }