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