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