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