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