diff options
Diffstat (limited to 'drivers/ide/h8300/ide-h8300.c')
-rw-r--r-- | drivers/ide/h8300/ide-h8300.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c new file mode 100644 index 000000000000..fb91cb8bf2d2 --- /dev/null +++ b/drivers/ide/h8300/ide-h8300.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * drivers/ide/ide-h8300.c | ||
3 | * H8/300 generic IDE interface | ||
4 | */ | ||
5 | |||
6 | #include <linux/init.h> | ||
7 | #include <linux/ide.h> | ||
8 | #include <linux/config.h> | ||
9 | |||
10 | #include <asm/io.h> | ||
11 | #include <asm/irq.h> | ||
12 | |||
13 | #define bswap(d) \ | ||
14 | ({ \ | ||
15 | u16 r; \ | ||
16 | __asm__("mov.b %w1,r1h\n\t" \ | ||
17 | "mov.b %x1,r1l\n\t" \ | ||
18 | "mov.w r1,%0" \ | ||
19 | :"=r"(r) \ | ||
20 | :"r"(d) \ | ||
21 | :"er1"); \ | ||
22 | (r); \ | ||
23 | }) | ||
24 | |||
25 | static void mm_outw(u16 d, unsigned long a) | ||
26 | { | ||
27 | __asm__("mov.b %w0,r2h\n\t" | ||
28 | "mov.b %x0,r2l\n\t" | ||
29 | "mov.w r2,@%1" | ||
30 | : | ||
31 | :"r"(d),"r"(a) | ||
32 | :"er2"); | ||
33 | } | ||
34 | |||
35 | static u16 mm_inw(unsigned long a) | ||
36 | { | ||
37 | register u16 r __asm__("er0"); | ||
38 | __asm__("mov.w @%1,r2\n\t" | ||
39 | "mov.b r2l,%x0\n\t" | ||
40 | "mov.b r2h,%w0" | ||
41 | :"=r"(r) | ||
42 | :"r"(a) | ||
43 | :"er2"); | ||
44 | return r; | ||
45 | } | ||
46 | |||
47 | static void mm_outsw(unsigned long addr, void *buf, u32 len) | ||
48 | { | ||
49 | unsigned short *bp = (unsigned short *)buf; | ||
50 | for (; len > 0; len--, bp++) | ||
51 | *(volatile u16 *)addr = bswap(*bp); | ||
52 | } | ||
53 | |||
54 | static void mm_insw(unsigned long addr, void *buf, u32 len) | ||
55 | { | ||
56 | unsigned short *bp = (unsigned short *)buf; | ||
57 | for (; len > 0; len--, bp++) | ||
58 | *bp = bswap(*(volatile u16 *)addr); | ||
59 | } | ||
60 | |||
61 | #define H8300_IDE_GAP (2) | ||
62 | |||
63 | static inline void hw_setup(hw_regs_t *hw) | ||
64 | { | ||
65 | int i; | ||
66 | |||
67 | memset(hw, 0, sizeof(hw_regs_t)); | ||
68 | for (i = 0; i <= IDE_STATUS_OFFSET; i++) | ||
69 | hw->io_ports[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; | ||
70 | hw->io_ports[IDE_CONTROL_OFFSET] = CONFIG_H8300_IDE_ALT; | ||
71 | hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; | ||
72 | hw->dma = NO_DMA; | ||
73 | hw->chipset = ide_generic; | ||
74 | } | ||
75 | |||
76 | static inline void hwif_setup(ide_hwif_t *hwif) | ||
77 | { | ||
78 | default_hwif_iops(hwif); | ||
79 | |||
80 | hwif->mmio = 2; | ||
81 | hwif->OUTW = mm_outw; | ||
82 | hwif->OUTSW = mm_outsw; | ||
83 | hwif->INW = mm_inw; | ||
84 | hwif->INSW = mm_insw; | ||
85 | hwif->OUTL = NULL; | ||
86 | hwif->INL = NULL; | ||
87 | hwif->OUTSL = NULL; | ||
88 | hwif->INSL = NULL; | ||
89 | } | ||
90 | |||
91 | void __init h8300_ide_init(void) | ||
92 | { | ||
93 | hw_regs_t hw; | ||
94 | ide_hwif_t *hwif; | ||
95 | int idx; | ||
96 | |||
97 | if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300")) | ||
98 | goto out_busy; | ||
99 | if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) { | ||
100 | release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8); | ||
101 | goto out_busy; | ||
102 | } | ||
103 | |||
104 | hw_setup(&hw); | ||
105 | |||
106 | /* register if */ | ||
107 | idx = ide_register_hw(&hw, &hwif); | ||
108 | if (idx == -1) { | ||
109 | printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | hwif_setup(hwif); | ||
114 | printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", idx); | ||
115 | return; | ||
116 | |||
117 | out_busy: | ||
118 | printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); | ||
119 | } | ||