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