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