]>
Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
1da177e4 LT |
2 | * H8/300 generic IDE interface |
3 | */ | |
4 | ||
5 | #include <linux/init.h> | |
6 | #include <linux/ide.h> | |
1da177e4 LT |
7 | |
8 | #include <asm/io.h> | |
9 | #include <asm/irq.h> | |
10 | ||
11 | #define bswap(d) \ | |
12 | ({ \ | |
13 | u16 r; \ | |
14 | __asm__("mov.b %w1,r1h\n\t" \ | |
15 | "mov.b %x1,r1l\n\t" \ | |
16 | "mov.w r1,%0" \ | |
17 | :"=r"(r) \ | |
18 | :"r"(d) \ | |
19 | :"er1"); \ | |
20 | (r); \ | |
21 | }) | |
22 | ||
23 | static void mm_outw(u16 d, unsigned long a) | |
24 | { | |
25 | __asm__("mov.b %w0,r2h\n\t" | |
26 | "mov.b %x0,r2l\n\t" | |
27 | "mov.w r2,@%1" | |
28 | : | |
29 | :"r"(d),"r"(a) | |
30 | :"er2"); | |
31 | } | |
32 | ||
33 | static u16 mm_inw(unsigned long a) | |
34 | { | |
35 | register u16 r __asm__("er0"); | |
36 | __asm__("mov.w @%1,r2\n\t" | |
37 | "mov.b r2l,%x0\n\t" | |
38 | "mov.b r2h,%w0" | |
39 | :"=r"(r) | |
40 | :"r"(a) | |
41 | :"er2"); | |
42 | return r; | |
43 | } | |
44 | ||
45 | static void mm_outsw(unsigned long addr, void *buf, u32 len) | |
46 | { | |
47 | unsigned short *bp = (unsigned short *)buf; | |
48 | for (; len > 0; len--, bp++) | |
49 | *(volatile u16 *)addr = bswap(*bp); | |
50 | } | |
51 | ||
52 | static void mm_insw(unsigned long addr, void *buf, u32 len) | |
53 | { | |
54 | unsigned short *bp = (unsigned short *)buf; | |
55 | for (; len > 0; len--, bp++) | |
56 | *bp = bswap(*(volatile u16 *)addr); | |
57 | } | |
58 | ||
59 | #define H8300_IDE_GAP (2) | |
60 | ||
61 | static inline void hw_setup(hw_regs_t *hw) | |
62 | { | |
63 | int i; | |
64 | ||
65 | memset(hw, 0, sizeof(hw_regs_t)); | |
4c3032d8 BZ |
66 | for (i = 0; i <= 7; i++) |
67 | hw->io_ports_array[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; | |
68 | hw->io_ports.ctl_addr = CONFIG_H8300_IDE_ALT; | |
1da177e4 | 69 | hw->irq = EXT_IRQ0 + CONFIG_H8300_IDE_IRQ; |
1da177e4 LT |
70 | hw->chipset = ide_generic; |
71 | } | |
72 | ||
73 | static inline void hwif_setup(ide_hwif_t *hwif) | |
74 | { | |
75 | default_hwif_iops(hwif); | |
76 | ||
1da177e4 LT |
77 | hwif->OUTW = mm_outw; |
78 | hwif->OUTSW = mm_outsw; | |
79 | hwif->INW = mm_inw; | |
80 | hwif->INSW = mm_insw; | |
1da177e4 LT |
81 | hwif->OUTSL = NULL; |
82 | hwif->INSL = NULL; | |
83 | } | |
84 | ||
ade2daf9 | 85 | static int __init h8300_ide_init(void) |
1da177e4 LT |
86 | { |
87 | hw_regs_t hw; | |
88 | ide_hwif_t *hwif; | |
cbb010c1 | 89 | int index; |
8ac4ce74 | 90 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; |
1da177e4 LT |
91 | |
92 | if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300")) | |
93 | goto out_busy; | |
94 | if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) { | |
95 | release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8); | |
96 | goto out_busy; | |
97 | } | |
98 | ||
99 | hw_setup(&hw); | |
100 | ||
59bff5ba | 101 | hwif = ide_find_port(); |
cbb010c1 | 102 | if (hwif == NULL) { |
1da177e4 | 103 | printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); |
ade2daf9 | 104 | return -ENOENT; |
1da177e4 LT |
105 | } |
106 | ||
cbb010c1 BZ |
107 | index = hwif->index; |
108 | ide_init_port_data(hwif, index); | |
109 | ide_init_port_hw(hwif, &hw); | |
1da177e4 | 110 | hwif_setup(hwif); |
430c5d26 | 111 | hwif->host_flags = IDE_HFLAG_NO_IO_32BIT; |
cbb010c1 | 112 | printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index); |
8ac4ce74 BZ |
113 | |
114 | idx[0] = index; | |
115 | ||
c413b9b9 | 116 | ide_device_add(idx, NULL); |
8ac4ce74 | 117 | |
ade2daf9 | 118 | return 0; |
1da177e4 LT |
119 | |
120 | out_busy: | |
121 | printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); | |
ade2daf9 BZ |
122 | |
123 | return -EBUSY; | |
1da177e4 | 124 | } |
ade2daf9 BZ |
125 | |
126 | module_init(h8300_ide_init); | |
f95dc320 AB |
127 | |
128 | MODULE_LICENSE("GPL"); |