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