linux/arch/mips/alchemy/devboards/platform.c
<<
>>
Prefs
   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
  21void __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
  38void 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
  47static struct platform_device db1x00_rtc_dev = {
  48        .name   = "rtc-au1xxx",
  49        .id     = -1,
  50};
  51
  52
  53static 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
  61static void db1x_reset(char *c)
  62{
  63        bcsr_write(BCSR_RESETS, 0);
  64        bcsr_write(BCSR_SYSTEM, 0);
  65}
  66
  67static 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}
  80device_initcall(db1x_late_setup);
  81
  82/* register a pcmcia socket */
  83int __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);
 159out:
 160        kfree(sr);
 161        return ret;
 162}
 163
 164#define YAMON_SIZE      0x00100000
 165#define YAMON_ENV_SIZE  0x00040000
 166
 167int __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);
 255out3:
 256        kfree(pfd);
 257out2:
 258        kfree(res);
 259out1:
 260        kfree(parts);
 261out:
 262        return ret;
 263}
 264