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