Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * devoard misc stuff.
0004  */
0005 
0006 #include <linux/init.h>
0007 #include <linux/mtd/mtd.h>
0008 #include <linux/mtd/map.h>
0009 #include <linux/mtd/physmap.h>
0010 #include <linux/slab.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pm.h>
0013 
0014 #include <asm/bootinfo.h>
0015 #include <asm/idle.h>
0016 #include <asm/reboot.h>
0017 #include <asm/setup.h>
0018 #include <asm/mach-au1x00/au1000.h>
0019 #include <asm/mach-db1x00/bcsr.h>
0020 
0021 #include <prom.h>
0022 
0023 void prom_putchar(char c)
0024 {
0025     if (alchemy_get_cputype() == ALCHEMY_CPU_AU1300)
0026         alchemy_uart_putchar(AU1300_UART2_PHYS_ADDR, c);
0027     else
0028         alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
0029 }
0030 
0031 
0032 static struct platform_device db1x00_rtc_dev = {
0033     .name   = "rtc-au1xxx",
0034     .id = -1,
0035 };
0036 
0037 
0038 static void db1x_power_off(void)
0039 {
0040     bcsr_write(BCSR_RESETS, 0);
0041     bcsr_write(BCSR_SYSTEM, BCSR_SYSTEM_PWROFF | BCSR_SYSTEM_RESET);
0042     while (1)       /* sit and spin */
0043         cpu_wait();
0044 }
0045 
0046 static void db1x_reset(char *c)
0047 {
0048     bcsr_write(BCSR_RESETS, 0);
0049     bcsr_write(BCSR_SYSTEM, 0);
0050 }
0051 
0052 static int __init db1x_late_setup(void)
0053 {
0054     if (!pm_power_off)
0055         pm_power_off = db1x_power_off;
0056     if (!_machine_halt)
0057         _machine_halt = db1x_power_off;
0058     if (!_machine_restart)
0059         _machine_restart = db1x_reset;
0060 
0061     platform_device_register(&db1x00_rtc_dev);
0062 
0063     return 0;
0064 }
0065 device_initcall(db1x_late_setup);
0066 
0067 /* register a pcmcia socket */
0068 int __init db1x_register_pcmcia_socket(phys_addr_t pcmcia_attr_start,
0069                        phys_addr_t pcmcia_attr_end,
0070                        phys_addr_t pcmcia_mem_start,
0071                        phys_addr_t pcmcia_mem_end,
0072                        phys_addr_t pcmcia_io_start,
0073                        phys_addr_t pcmcia_io_end,
0074                        int card_irq,
0075                        int cd_irq,
0076                        int stschg_irq,
0077                        int eject_irq,
0078                        int id)
0079 {
0080     int cnt, i, ret;
0081     struct resource *sr;
0082     struct platform_device *pd;
0083 
0084     cnt = 5;
0085     if (eject_irq)
0086         cnt++;
0087     if (stschg_irq)
0088         cnt++;
0089 
0090     sr = kcalloc(cnt, sizeof(struct resource), GFP_KERNEL);
0091     if (!sr)
0092         return -ENOMEM;
0093 
0094     pd = platform_device_alloc("db1xxx_pcmcia", id);
0095     if (!pd) {
0096         ret = -ENOMEM;
0097         goto out;
0098     }
0099 
0100     sr[0].name  = "pcmcia-attr";
0101     sr[0].flags = IORESOURCE_MEM;
0102     sr[0].start = pcmcia_attr_start;
0103     sr[0].end   = pcmcia_attr_end;
0104 
0105     sr[1].name  = "pcmcia-mem";
0106     sr[1].flags = IORESOURCE_MEM;
0107     sr[1].start = pcmcia_mem_start;
0108     sr[1].end   = pcmcia_mem_end;
0109 
0110     sr[2].name  = "pcmcia-io";
0111     sr[2].flags = IORESOURCE_MEM;
0112     sr[2].start = pcmcia_io_start;
0113     sr[2].end   = pcmcia_io_end;
0114 
0115     sr[3].name  = "insert";
0116     sr[3].flags = IORESOURCE_IRQ;
0117     sr[3].start = sr[3].end = cd_irq;
0118 
0119     sr[4].name  = "card";
0120     sr[4].flags = IORESOURCE_IRQ;
0121     sr[4].start = sr[4].end = card_irq;
0122 
0123     i = 5;
0124     if (stschg_irq) {
0125         sr[i].name  = "stschg";
0126         sr[i].flags = IORESOURCE_IRQ;
0127         sr[i].start = sr[i].end = stschg_irq;
0128         i++;
0129     }
0130     if (eject_irq) {
0131         sr[i].name  = "eject";
0132         sr[i].flags = IORESOURCE_IRQ;
0133         sr[i].start = sr[i].end = eject_irq;
0134     }
0135 
0136     pd->resource = sr;
0137     pd->num_resources = cnt;
0138 
0139     ret = platform_device_add(pd);
0140     if (!ret)
0141         return 0;
0142 
0143     platform_device_put(pd);
0144 out:
0145     kfree(sr);
0146     return ret;
0147 }
0148 
0149 #define YAMON_SIZE  0x00100000
0150 #define YAMON_ENV_SIZE  0x00040000
0151 
0152 int __init db1x_register_norflash(unsigned long size, int width,
0153                   int swapped)
0154 {
0155     struct physmap_flash_data *pfd;
0156     struct platform_device *pd;
0157     struct mtd_partition *parts;
0158     struct resource *res;
0159     int ret, i;
0160 
0161     if (size < (8 * 1024 * 1024))
0162         return -EINVAL;
0163 
0164     ret = -ENOMEM;
0165     parts = kcalloc(5, sizeof(struct mtd_partition), GFP_KERNEL);
0166     if (!parts)
0167         goto out;
0168 
0169     res = kzalloc(sizeof(struct resource), GFP_KERNEL);
0170     if (!res)
0171         goto out1;
0172 
0173     pfd = kzalloc(sizeof(struct physmap_flash_data), GFP_KERNEL);
0174     if (!pfd)
0175         goto out2;
0176 
0177     pd = platform_device_alloc("physmap-flash", 0);
0178     if (!pd)
0179         goto out3;
0180 
0181     /* NOR flash ends at 0x20000000, regardless of size */
0182     res->start = 0x20000000 - size;
0183     res->end = 0x20000000 - 1;
0184     res->flags = IORESOURCE_MEM;
0185 
0186     /* partition setup.  Most Develboards have a switch which allows
0187      * to swap the physical locations of the 2 NOR flash banks.
0188      */
0189     i = 0;
0190     if (!swapped) {
0191         /* first NOR chip */
0192         parts[i].offset = 0;
0193         parts[i].name = "User FS";
0194         parts[i].size = size / 2;
0195         i++;
0196     }
0197 
0198     parts[i].offset = MTDPART_OFS_APPEND;
0199     parts[i].name = "User FS 2";
0200     parts[i].size = (size / 2) - (0x20000000 - 0x1fc00000);
0201     i++;
0202 
0203     parts[i].offset = MTDPART_OFS_APPEND;
0204     parts[i].name = "YAMON";
0205     parts[i].size = YAMON_SIZE;
0206     parts[i].mask_flags = MTD_WRITEABLE;
0207     i++;
0208 
0209     parts[i].offset = MTDPART_OFS_APPEND;
0210     parts[i].name = "raw kernel";
0211     parts[i].size = 0x00400000 - YAMON_SIZE - YAMON_ENV_SIZE;
0212     i++;
0213 
0214     parts[i].offset = MTDPART_OFS_APPEND;
0215     parts[i].name = "YAMON Env";
0216     parts[i].size = YAMON_ENV_SIZE;
0217     parts[i].mask_flags = MTD_WRITEABLE;
0218     i++;
0219 
0220     if (swapped) {
0221         parts[i].offset = MTDPART_OFS_APPEND;
0222         parts[i].name = "User FS";
0223         parts[i].size = size / 2;
0224         i++;
0225     }
0226 
0227     pfd->width = width;
0228     pfd->parts = parts;
0229     pfd->nr_parts = 5;
0230 
0231     pd->dev.platform_data = pfd;
0232     pd->resource = res;
0233     pd->num_resources = 1;
0234 
0235     ret = platform_device_add(pd);
0236     if (!ret)
0237         return ret;
0238 
0239     platform_device_put(pd);
0240 out3:
0241     kfree(pfd);
0242 out2:
0243     kfree(res);
0244 out1:
0245     kfree(parts);
0246 out:
0247     return ret;
0248 }