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)); | |
66 | for (i = 0; i <= IDE_STATUS_OFFSET; i++) | |
67 | hw->io_ports[i] = CONFIG_H8300_IDE_BASE + H8300_IDE_GAP*i; | |
68 | hw->io_ports[IDE_CONTROL_OFFSET] = CONFIG_H8300_IDE_ALT; | |
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 | ||
2ad1e558 | 77 | hwif->mmio = 1; |
1da177e4 LT |
78 | hwif->OUTW = mm_outw; |
79 | hwif->OUTSW = mm_outsw; | |
80 | hwif->INW = mm_inw; | |
81 | hwif->INSW = mm_insw; | |
1da177e4 LT |
82 | hwif->OUTSL = NULL; |
83 | hwif->INSL = NULL; | |
84 | } | |
85 | ||
ade2daf9 | 86 | static int __init h8300_ide_init(void) |
1da177e4 LT |
87 | { |
88 | hw_regs_t hw; | |
89 | ide_hwif_t *hwif; | |
cbb010c1 | 90 | int index; |
8ac4ce74 | 91 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; |
1da177e4 LT |
92 | |
93 | if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300")) | |
94 | goto out_busy; | |
95 | if (!request_region(CONFIG_H8300_IDE_ALT, H8300_IDE_GAP, "ide-h8300")) { | |
96 | release_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8); | |
97 | goto out_busy; | |
98 | } | |
99 | ||
100 | hw_setup(&hw); | |
101 | ||
102 | /* register if */ | |
cbb010c1 BZ |
103 | hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]); |
104 | if (hwif == NULL) { | |
1da177e4 | 105 | printk(KERN_ERR "ide-h8300: IDE I/F register failed\n"); |
ade2daf9 | 106 | return -ENOENT; |
1da177e4 LT |
107 | } |
108 | ||
cbb010c1 BZ |
109 | index = hwif->index; |
110 | ide_init_port_data(hwif, index); | |
111 | ide_init_port_hw(hwif, &hw); | |
1da177e4 | 112 | hwif_setup(hwif); |
430c5d26 | 113 | hwif->host_flags = IDE_HFLAG_NO_IO_32BIT; |
cbb010c1 | 114 | printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index); |
8ac4ce74 BZ |
115 | |
116 | idx[0] = index; | |
117 | ||
c413b9b9 | 118 | ide_device_add(idx, NULL); |
8ac4ce74 | 119 | |
ade2daf9 | 120 | return 0; |
1da177e4 LT |
121 | |
122 | out_busy: | |
123 | printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n"); | |
ade2daf9 BZ |
124 | |
125 | return -EBUSY; | |
1da177e4 | 126 | } |
ade2daf9 BZ |
127 | |
128 | module_init(h8300_ide_init); | |
f95dc320 AB |
129 | |
130 | MODULE_LICENSE("GPL"); |