kogiidena | 94c0fa5 | 2006-09-27 14:53:35 +0900 | [diff] [blame] | 1 | /* |
| 2 | * arch/sh/boards/landisk/irq.c |
| 3 | * |
| 4 | * Copyright (C) 2001 Ian da Silva, Jeremy Siegel |
| 5 | * Based largely on io_se.c. |
| 6 | * |
| 7 | * I/O routine for I-O Data Device, Inc. LANDISK. |
| 8 | * |
| 9 | * Initial version only to support LAN access; some |
| 10 | * placeholder code from io_landisk.c left in with the |
| 11 | * expectation of later SuperIO and PCMCIA access. |
| 12 | */ |
| 13 | /* |
| 14 | * modified by kogiidena |
| 15 | * 2005.03.03 |
| 16 | */ |
| 17 | |
| 18 | #include <linux/config.h> |
| 19 | #include <linux/init.h> |
| 20 | #include <linux/irq.h> |
| 21 | #include <asm/io.h> |
| 22 | #include <asm/irq.h> |
| 23 | #include <asm/landisk/iodata_landisk.h> |
| 24 | |
| 25 | static void enable_landisk_irq(unsigned int irq); |
| 26 | static void disable_landisk_irq(unsigned int irq); |
| 27 | |
| 28 | /* shutdown is same as "disable" */ |
| 29 | #define shutdown_landisk_irq disable_landisk_irq |
| 30 | |
| 31 | static void ack_landisk_irq(unsigned int irq); |
| 32 | static void end_landisk_irq(unsigned int irq); |
| 33 | |
| 34 | static unsigned int startup_landisk_irq(unsigned int irq) |
| 35 | { |
| 36 | enable_landisk_irq(irq); |
| 37 | return 0; /* never anything pending */ |
| 38 | } |
| 39 | |
| 40 | static void disable_landisk_irq(unsigned int irq) |
| 41 | { |
kogiidena | 94c0fa5 | 2006-09-27 14:53:35 +0900 | [diff] [blame] | 42 | unsigned char val; |
| 43 | unsigned char mask = 0xff ^ (0x01 << (irq - 5)); |
| 44 | |
| 45 | /* Set the priority in IPR to 0 */ |
kogiidena | 94c0fa5 | 2006-09-27 14:53:35 +0900 | [diff] [blame] | 46 | val = ctrl_inb(PA_IMASK); |
| 47 | val &= mask; |
| 48 | ctrl_outb(val, PA_IMASK); |
kogiidena | 94c0fa5 | 2006-09-27 14:53:35 +0900 | [diff] [blame] | 49 | } |
| 50 | |
| 51 | static void enable_landisk_irq(unsigned int irq) |
| 52 | { |
kogiidena | 94c0fa5 | 2006-09-27 14:53:35 +0900 | [diff] [blame] | 53 | unsigned char val; |
| 54 | unsigned char value = (0x01 << (irq - 5)); |
| 55 | |
| 56 | /* Set priority in IPR back to original value */ |
kogiidena | 94c0fa5 | 2006-09-27 14:53:35 +0900 | [diff] [blame] | 57 | val = ctrl_inb(PA_IMASK); |
| 58 | val |= value; |
| 59 | ctrl_outb(val, PA_IMASK); |
kogiidena | 94c0fa5 | 2006-09-27 14:53:35 +0900 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | static void ack_landisk_irq(unsigned int irq) |
| 63 | { |
| 64 | disable_landisk_irq(irq); |
| 65 | } |
| 66 | |
| 67 | static void end_landisk_irq(unsigned int irq) |
| 68 | { |
| 69 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) |
| 70 | enable_landisk_irq(irq); |
| 71 | } |
| 72 | |
| 73 | static struct hw_interrupt_type landisk_irq_type = { |
| 74 | .typename = "LANDISK IRQ", |
| 75 | .startup = startup_landisk_irq, |
| 76 | .shutdown = shutdown_landisk_irq, |
| 77 | .enable = enable_landisk_irq, |
| 78 | .disable = disable_landisk_irq, |
| 79 | .ack = ack_landisk_irq, |
| 80 | .end = end_landisk_irq |
| 81 | }; |
| 82 | |
| 83 | static void make_landisk_irq(unsigned int irq) |
| 84 | { |
| 85 | disable_irq_nosync(irq); |
| 86 | irq_desc[irq].handler = &landisk_irq_type; |
| 87 | disable_landisk_irq(irq); |
| 88 | } |
| 89 | |
| 90 | /* |
| 91 | * Initialize IRQ setting |
| 92 | */ |
| 93 | void __init init_landisk_IRQ(void) |
| 94 | { |
| 95 | int i; |
| 96 | |
| 97 | for (i = 5; i < 14; i++) |
| 98 | make_landisk_irq(i); |
| 99 | } |