1 /* arch/arm/mach-lh7a40x/ide-lpd7a40x.c
3 * Copyright (C) 2004 Logic Product Development
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
12 #include <linux/config.h>
13 #include <linux/ide.h>
17 #define IOBARRIER_READ readl (IOBARRIER_VIRT)
19 static u8 lpd7a40x_ide_inb (unsigned long port)
21 u16 v = (u16) readw (port & ~0x1);
28 static u16 lpd7a40x_ide_inw (unsigned long port)
30 u16 v = (u16) readw (port);
35 static void lpd7a40x_ide_insw (unsigned long port, void *addr, u32 count)
38 *((u16*) addr)++ = (u16) readw (port);
43 static u32 lpd7a40x_ide_inl (unsigned long port)
45 u32 v = (u16) readw (port);
47 v |= (u16) readw (port + 2);
53 static void lpd7a40x_ide_insl (unsigned long port, void *addr, u32 count)
56 *((u16*) addr)++ = (u16) readw (port);
58 *((u16*) addr)++ = (u16) readw (port + 2);
63 /* lpd7a40x_ide_outb -- this function is complicated by the fact that
64 * the user wants to be able to do byte IO and the hardware cannot.
65 * In order to write the high byte, we need to write a short. So, we
66 * read before writing in order to maintain the register values that
67 * shouldn't change. This isn't a good idea for the data IO registers
68 * since reading from them will not return the current value. We
69 * expect that this function handles the control register adequately.
72 static void lpd7a40x_ide_outb (u8 valueUser, unsigned long port)
74 /* Block writes to SELECT register. Draconian, but the only
75 * way to cope with this hardware configuration without
76 * modifying the SELECT_DRIVE call in the ide driver. */
77 if ((port & 0xf) == 0x6)
80 if (port & 0x1) { /* Perform read before write. Only
81 * the COMMAND register needs
83 u16 value = (u16) readw (port & ~0x1);
85 value = (value & 0x00ff) | (valueUser << 8);
86 writew (value, port & ~0x1);
89 else { /* Allow low-byte writes which seem to
91 writeb (valueUser, port);
96 static void lpd7a40x_ide_outbsync (ide_drive_t *drive, u8 value,
99 lpd7a40x_ide_outb (value, port);
102 static void lpd7a40x_ide_outw (u16 value, unsigned long port)
104 writew (value, port);
108 static void lpd7a40x_ide_outsw (unsigned long port, void *addr, u32 count)
110 while (count-- > 0) {
111 writew (*((u16*) addr)++, port);
116 static void lpd7a40x_ide_outl (u32 value, unsigned long port)
118 writel (value, port);
122 static void lpd7a40x_ide_outsl (unsigned long port, void *addr, u32 count)
124 while (count-- > 0) {
125 writel (*((u32*) addr)++, port);
130 void lpd7a40x_SELECT_DRIVE (ide_drive_t *drive)
132 unsigned jifStart = jiffies;
133 #define WAIT_TIME (30*HZ/1000)
135 /* Check for readiness. */
136 while ((HWIF(drive)->INB(IDE_STATUS_REG) & 0x40) == 0)
137 if (jifStart <= jiffies + WAIT_TIME)
140 /* Only allow one drive.
141 For more information, see Documentation/arm/Sharp-LH/ */
142 if (drive->select.all & (1<<4))
145 /* OUTW so that the IDLE_IMMEDIATE (and not NOP) command is sent. */
146 HWIF(drive)->OUTW(drive->select.all | 0xe100, IDE_SELECT_REG);
149 void lpd7a40x_hwif_ioops (ide_hwif_t *hwif)
151 hwif->mmio = 2; /* Just for show */
152 hwif->irq = IDE_NO_IRQ; /* Stop this probing */
154 hwif->OUTB = lpd7a40x_ide_outb;
155 hwif->OUTBSYNC = lpd7a40x_ide_outbsync;
156 hwif->OUTW = lpd7a40x_ide_outw;
157 hwif->OUTL = lpd7a40x_ide_outl;
158 hwif->OUTSW = lpd7a40x_ide_outsw;
159 hwif->OUTSL = lpd7a40x_ide_outsl;
160 hwif->INB = lpd7a40x_ide_inb;
161 hwif->INW = lpd7a40x_ide_inw;
162 hwif->INL = lpd7a40x_ide_inl;
163 hwif->INSW = lpd7a40x_ide_insw;
164 hwif->INSL = lpd7a40x_ide_insl;
165 hwif->selectproc = lpd7a40x_SELECT_DRIVE;