1 /* 2 * linux/arch/arm/mach-sa1100/neponset.c 3 */ 4 #include <linux/err.h> 5 #include <linux/init.h> 6 #include <linux/ioport.h> 7 #include <linux/irq.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/pm.h> 12 #include <linux/serial_core.h> 13 #include <linux/slab.h> 14 15 #include <asm/mach-types.h> 16 #include <asm/mach/map.h> 17 #include <asm/mach/serial_sa1100.h> 18 #include <asm/hardware/sa1111.h> 19 #include <asm/sizes.h> 20 21 #include <mach/hardware.h> 22 #include <mach/assabet.h> 23 #include <mach/neponset.h> 24 25 #define NEP_IRQ_SMC91X 0 26 #define NEP_IRQ_USAR 1 27 #define NEP_IRQ_SA1111 2 28 #define NEP_IRQ_NR 3 29 30 struct neponset_drvdata { 31 struct platform_device *sa1111; 32 struct platform_device *smc91x; 33 unsigned irq_base; 34 #ifdef CONFIG_PM_SLEEP 35 u32 ncr0; 36 u32 mdm_ctl_0; 37 #endif 38 }; 39 40 void neponset_ncr_frob(unsigned int mask, unsigned int val) 41 { 42 unsigned long flags; 43 44 local_irq_save(flags); 45 NCR_0 = (NCR_0 & ~mask) | val; 46 local_irq_restore(flags); 47 } 48 49 static void neponset_set_mctrl(struct uart_port *port, u_int mctrl) 50 { 51 u_int mdm_ctl0 = MDM_CTL_0; 52 53 if (port->mapbase == _Ser1UTCR0) { 54 if (mctrl & TIOCM_RTS) 55 mdm_ctl0 &= ~MDM_CTL0_RTS2; 56 else 57 mdm_ctl0 |= MDM_CTL0_RTS2; 58 59 if (mctrl & TIOCM_DTR) 60 mdm_ctl0 &= ~MDM_CTL0_DTR2; 61 else 62 mdm_ctl0 |= MDM_CTL0_DTR2; 63 } else if (port->mapbase == _Ser3UTCR0) { 64 if (mctrl & TIOCM_RTS) 65 mdm_ctl0 &= ~MDM_CTL0_RTS1; 66 else 67 mdm_ctl0 |= MDM_CTL0_RTS1; 68 69 if (mctrl & TIOCM_DTR) 70 mdm_ctl0 &= ~MDM_CTL0_DTR1; 71 else 72 mdm_ctl0 |= MDM_CTL0_DTR1; 73 } 74 75 MDM_CTL_0 = mdm_ctl0; 76 } 77 78 static u_int neponset_get_mctrl(struct uart_port *port) 79 { 80 u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; 81 u_int mdm_ctl1 = MDM_CTL_1; 82 83 if (port->mapbase == _Ser1UTCR0) { 84 if (mdm_ctl1 & MDM_CTL1_DCD2) 85 ret &= ~TIOCM_CD; 86 if (mdm_ctl1 & MDM_CTL1_CTS2) 87 ret &= ~TIOCM_CTS; 88 if (mdm_ctl1 & MDM_CTL1_DSR2) 89 ret &= ~TIOCM_DSR; 90 } else if (port->mapbase == _Ser3UTCR0) { 91 if (mdm_ctl1 & MDM_CTL1_DCD1) 92 ret &= ~TIOCM_CD; 93 if (mdm_ctl1 & MDM_CTL1_CTS1) 94 ret &= ~TIOCM_CTS; 95 if (mdm_ctl1 & MDM_CTL1_DSR1) 96 ret &= ~TIOCM_DSR; 97 } 98 99 return ret; 100 } 101 102 static struct sa1100_port_fns neponset_port_fns __devinitdata = { 103 .set_mctrl = neponset_set_mctrl, 104 .get_mctrl = neponset_get_mctrl, 105 }; 106 107 /* 108 * Install handler for Neponset IRQ. Note that we have to loop here 109 * since the ETHERNET and USAR IRQs are level based, and we need to 110 * ensure that the IRQ signal is deasserted before returning. This 111 * is rather unfortunate. 112 */ 113 static void neponset_irq_handler(unsigned int irq, struct irq_desc *desc) 114 { 115 struct neponset_drvdata *d = irq_desc_get_handler_data(desc); 116 unsigned int irr; 117 118 while (1) { 119 /* 120 * Acknowledge the parent IRQ. 121 */ 122 desc->irq_data.chip->irq_ack(&desc->irq_data); 123 124 /* 125 * Read the interrupt reason register. Let's have all 126 * active IRQ bits high. Note: there is a typo in the 127 * Neponset user's guide for the SA1111 IRR level. 128 */ 129 irr = IRR ^ (IRR_ETHERNET | IRR_USAR); 130 131 if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0) 132 break; 133 134 /* 135 * Since there is no individual mask, we have to 136 * mask the parent IRQ. This is safe, since we'll 137 * recheck the register for any pending IRQs. 138 */ 139 if (irr & (IRR_ETHERNET | IRR_USAR)) { 140 desc->irq_data.chip->irq_mask(&desc->irq_data); 141 142 /* 143 * Ack the interrupt now to prevent re-entering 144 * this neponset handler. Again, this is safe 145 * since we'll check the IRR register prior to 146 * leaving. 147 */ 148 desc->irq_data.chip->irq_ack(&desc->irq_data); 149 150 if (irr & IRR_ETHERNET) 151 generic_handle_irq(d->irq_base + NEP_IRQ_SMC91X); 152 153 if (irr & IRR_USAR) 154 generic_handle_irq(d->irq_base + NEP_IRQ_USAR); 155 156 desc->irq_data.chip->irq_unmask(&desc->irq_data); 157 } 158 159 if (irr & IRR_SA1111) 160 generic_handle_irq(d->irq_base + NEP_IRQ_SA1111); 161 } 162 } 163 164 /* Yes, we really do not have any kind of masking or unmasking */ 165 static void nochip_noop(struct irq_data *irq) 166 { 167 } 168 169 static struct irq_chip nochip = { 170 .name = "neponset", 171 .irq_ack = nochip_noop, 172 .irq_mask = nochip_noop, 173 .irq_unmask = nochip_noop, 174 }; 175 176 static struct sa1111_platform_data sa1111_info = { 177 .irq_base = IRQ_BOARD_END, 178 }; 179 180 static int __devinit neponset_probe(struct platform_device *dev) 181 { 182 struct neponset_drvdata *d; 183 struct resource *sa1111_res, *smc91x_res; 184 struct resource sa1111_resources[] = { 185 DEFINE_RES_MEM(0x40000000, SZ_8K), 186 { .flags = IORESOURCE_IRQ }, 187 }; 188 struct platform_device_info sa1111_devinfo = { 189 .parent = &dev->dev, 190 .name = "sa1111", 191 .id = 0, 192 .res = sa1111_resources, 193 .num_res = ARRAY_SIZE(sa1111_resources), 194 .data = &sa1111_info, 195 .size_data = sizeof(sa1111_info), 196 .dma_mask = 0xffffffffUL, 197 }; 198 struct resource smc91x_resources[] = { 199 DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS, 200 0x02000000, "smc91x-regs"), 201 DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS + 0x02000000, 202 0x02000000, "smc91x-attrib"), 203 { .flags = IORESOURCE_IRQ }, 204 }; 205 struct platform_device_info smc91x_devinfo = { 206 .parent = &dev->dev, 207 .name = "smc91x", 208 .id = 0, 209 .res = smc91x_resources, 210 .num_res = ARRAY_SIZE(smc91x_resources), 211 }; 212 int ret, irq; 213 214 irq = ret = platform_get_irq(dev, 0); 215 if (ret < 0) 216 goto err_alloc; 217 218 smc91x_res = platform_get_resource(dev, IORESOURCE_MEM, 1); 219 sa1111_res = platform_get_resource(dev, IORESOURCE_MEM, 2); 220 if (!smc91x_res || !sa1111_res) { 221 ret = -ENXIO; 222 goto err_alloc; 223 } 224 225 d = kzalloc(sizeof(*d), GFP_KERNEL); 226 if (!d) { 227 ret = -ENOMEM; 228 goto err_alloc; 229 } 230 231 ret = irq_alloc_descs(-1, IRQ_BOARD_START, NEP_IRQ_NR, -1); 232 if (ret <= 0) { 233 dev_err(&dev->dev, "unable to allocate %u irqs: %d\n", 234 NEP_IRQ_NR, ret); 235 if (ret == 0) 236 ret = -ENOMEM; 237 goto err_irq_alloc; 238 } 239 240 d->irq_base = ret; 241 242 irq_set_chip_and_handler(d->irq_base + NEP_IRQ_SMC91X, &nochip, 243 handle_simple_irq); 244 set_irq_flags(d->irq_base + NEP_IRQ_SMC91X, IRQF_VALID | IRQF_PROBE); 245 irq_set_chip_and_handler(d->irq_base + NEP_IRQ_USAR, &nochip, 246 handle_simple_irq); 247 set_irq_flags(d->irq_base + NEP_IRQ_USAR, IRQF_VALID | IRQF_PROBE); 248 irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip); 249 250 irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); 251 irq_set_handler_data(irq, d); 252 irq_set_chained_handler(irq, neponset_irq_handler); 253 254 /* 255 * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately 256 * something on the Neponset activates this IRQ on sleep (eth?) 257 */ 258 #if 0 259 enable_irq_wake(irq); 260 #endif 261 262 dev_info(&dev->dev, "Neponset daughter board, providing IRQ%u-%u\n", 263 d->irq_base, d->irq_base + NEP_IRQ_NR - 1); 264 265 sa1100_register_uart_fns(&neponset_port_fns); 266 267 /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */ 268 NCR_0 = NCR_GP01_OFF; 269 270 sa1111_resources[0].parent = sa1111_res; 271 sa1111_resources[1].start = d->irq_base + NEP_IRQ_SA1111; 272 sa1111_resources[1].end = d->irq_base + NEP_IRQ_SA1111; 273 d->sa1111 = platform_device_register_full(&sa1111_devinfo); 274 275 smc91x_resources[0].parent = smc91x_res; 276 smc91x_resources[1].parent = smc91x_res; 277 smc91x_resources[2].start = d->irq_base + NEP_IRQ_SMC91X; 278 smc91x_resources[2].end = d->irq_base + NEP_IRQ_SMC91X; 279 d->smc91x = platform_device_register_full(&smc91x_devinfo); 280 281 platform_set_drvdata(dev, d); 282 283 return 0; 284 285 err_irq_alloc: 286 kfree(d); 287 err_alloc: 288 return ret; 289 } 290 291 static int __devexit neponset_remove(struct platform_device *dev) 292 { 293 struct neponset_drvdata *d = platform_get_drvdata(dev); 294 int irq = platform_get_irq(dev, 0); 295 296 if (!IS_ERR(d->sa1111)) 297 platform_device_unregister(d->sa1111); 298 if (!IS_ERR(d->smc91x)) 299 platform_device_unregister(d->smc91x); 300 irq_set_chained_handler(irq, NULL); 301 irq_free_descs(d->irq_base, NEP_IRQ_NR); 302 kfree(d); 303 304 return 0; 305 } 306 307 #ifdef CONFIG_PM_SLEEP 308 static int neponset_suspend(struct device *dev) 309 { 310 struct neponset_drvdata *d = dev_get_drvdata(dev); 311 312 d->ncr0 = NCR_0; 313 d->mdm_ctl_0 = MDM_CTL_0; 314 315 return 0; 316 } 317 318 static int neponset_resume(struct device *dev) 319 { 320 struct neponset_drvdata *d = dev_get_drvdata(dev); 321 322 NCR_0 = d->ncr0; 323 MDM_CTL_0 = d->mdm_ctl_0; 324 325 return 0; 326 } 327 328 static const struct dev_pm_ops neponset_pm_ops = { 329 .suspend_noirq = neponset_suspend, 330 .resume_noirq = neponset_resume, 331 .freeze_noirq = neponset_suspend, 332 .restore_noirq = neponset_resume, 333 }; 334 #define PM_OPS &neponset_pm_ops 335 #else 336 #define PM_OPS NULL 337 #endif 338 339 static struct platform_driver neponset_device_driver = { 340 .probe = neponset_probe, 341 .remove = __devexit_p(neponset_remove), 342 .driver = { 343 .name = "neponset", 344 .owner = THIS_MODULE, 345 .pm = PM_OPS, 346 }, 347 }; 348 349 static struct resource neponset_resources[] = { 350 DEFINE_RES_MEM(0x10000000, 0x08000000), 351 DEFINE_RES_MEM(0x18000000, 0x04000000), 352 DEFINE_RES_MEM(0x40000000, SZ_8K), 353 DEFINE_RES_IRQ(IRQ_GPIO25), 354 }; 355 356 static struct platform_device neponset_device = { 357 .name = "neponset", 358 .id = 0, 359 .num_resources = ARRAY_SIZE(neponset_resources), 360 .resource = neponset_resources, 361 }; 362 363 extern void sa1110_mb_disable(void); 364 365 static int __init neponset_init(void) 366 { 367 platform_driver_register(&neponset_device_driver); 368 369 /* 370 * The Neponset is only present on the Assabet machine type. 371 */ 372 if (!machine_is_assabet()) 373 return -ENODEV; 374 375 /* 376 * Ensure that the memory bus request/grant signals are setup, 377 * and the grant is held in its inactive state, whether or not 378 * we actually have a Neponset attached. 379 */ 380 sa1110_mb_disable(); 381 382 if (!machine_has_neponset()) { 383 printk(KERN_DEBUG "Neponset expansion board not present\n"); 384 return -ENODEV; 385 } 386 387 if (WHOAMI != 0x11) { 388 printk(KERN_WARNING "Neponset board detected, but " 389 "wrong ID: %02x\n", WHOAMI); 390 return -ENODEV; 391 } 392 393 return platform_device_register(&neponset_device); 394 } 395 396 subsys_initcall(neponset_init); 397 398 static struct map_desc neponset_io_desc[] __initdata = { 399 { /* System Registers */ 400 .virtual = 0xf3000000, 401 .pfn = __phys_to_pfn(0x10000000), 402 .length = SZ_1M, 403 .type = MT_DEVICE 404 }, { /* SA-1111 */ 405 .virtual = 0xf4000000, 406 .pfn = __phys_to_pfn(0x40000000), 407 .length = SZ_1M, 408 .type = MT_DEVICE 409 } 410 }; 411 412 void __init neponset_map_io(void) 413 { 414 iotable_init(neponset_io_desc, ARRAY_SIZE(neponset_io_desc)); 415 } 416