revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-chrp / efika / ata / lowlevel_mpc5200b.c
blob1de7f1bed0809d545efc9641ce22f09147fb7641
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
8 #include <aros/debug.h>
9 #include <exec/types.h>
10 #include <asm/io.h>
11 #include <asm/mpc5200b.h>
12 #include <exec/exec.h>
13 #include <exec/tasks.h>
14 #include <exec/memory.h>
15 #include <exec/nodes.h>
16 #include <utility/utility.h>
17 #include <proto/exec.h>
18 #include <proto/timer.h>
19 #include <proto/oop.h>
20 #include <proto/openfirmware.h>
22 #include "ata.h"
24 extern uint8_t *sram;
25 extern bestcomm_t *bestcomm;
26 extern uint32_t bestcomm_taskid;
28 extern void bestcomm_init();
30 UBYTE *mbar;
31 uint32_t bus_frequency;
33 volatile ata_5k2_t *ata_5k2;
35 static void ata_out(UBYTE val, UWORD offset, IPTR port, APTR data)
37 while(inl(&ata_5k2->ata_status) & 0x80000000) asm volatile("nop");
39 if (port +offset * 4 == 0x3a7c)
41 ULONG val = inl(&mbar[port + offset * 4]);
42 outb(0, &mbar[port + 1 + offset * 4]);
45 outl((ULONG)val << 24, &mbar[port + offset * 4]);
48 static UBYTE ata_in(UWORD offset, IPTR port, APTR data)
50 while(inl(&ata_5k2->ata_status) & 0x80000000) asm volatile("nop");
52 if (port +offset * 4 == 0x3a7c)
54 ULONG val = inl(&mbar[port + offset * 4]);
55 outb(0, &mbar[port + 1 + offset * 4]);
58 return inl(&mbar[port + offset * 4]) >> 24;
61 static void ata_outl(ULONG val, UWORD offset, IPTR port, APTR data)
63 while(inl(&ata_5k2->ata_status) & 0x80000000) asm volatile("nop");
65 outl_le(val, &mbar[port + offset * 4]);
68 static VOID ata_insw(APTR address, UWORD port, ULONG count, APTR data)
70 UWORD *addr = address;
71 volatile UWORD *p = (UWORD*)(&mbar[port]);
73 D(bug("[ATA 5k2] insw(%08x, %04x)\n", address, count));
75 count &= ~1;
77 while(inl(&ata_5k2->ata_status) & 0x80000000) asm volatile("nop");
79 asm volatile("sync");
80 while(count)
82 // *addr++ = inw(p);
83 *addr++ = *p;
84 count -= 2;
86 asm volatile("sync");
89 static VOID ata_outsw(APTR address, UWORD port, ULONG count, APTR data)
91 UWORD *addr = address;
92 volatile UWORD *p = (UWORD*)(&mbar[port]);
94 D(bug("[ATA 5k2] outsw(%08x, %04x)\n", address, count));
96 count &= ~1;
98 while(inl(&ata_5k2->ata_status) & 0x80000000) asm volatile("nop");
100 asm volatile("sync");
101 while(count)
103 // outw(*addr++, p);
104 *p = *addr++;
105 count -= 2;
107 asm volatile("sync");
110 static void ata_400ns()
112 register ULONG tick_old, tick;
114 asm volatile("mftbl %0":"=r"(tick_old));
116 do {
117 asm volatile("mftbl %0":"=r"(tick));
118 } while(tick < (tick_old + 15));
121 static AROS_INTH1(ata_Interrupt, void *, data)
123 AROS_INTFUNC_INIT
125 * Our interrupt handler should call this function.
126 * It's our problem how to store bus pointer. Here we use h_Data for it.
128 ata_HandleIRQ(data);
130 return FALSE;
132 AROS_INTFUNC_EXIT
135 /* Actually a quick hack. Proper implementation really needs HIDDizing this code. */
136 static BOOL CreateInterrupt(struct ata_Bus *bus)
138 struct Interrupt *IntHandler = &bus->ab_IntHandler;
141 Prepare nice interrupt for our bus. Even if interrupt sharing is enabled,
142 it should work quite well
144 IntHandler->is_Node.ln_Pri = 10;
145 IntHandler->is_Node.ln_Name = bus->ab_Task->tc_Node.ln_Name;
146 IntHandler->is_Code = (VOID_FUNC)ata_Interrupt;
147 IntHandler->is_Data = bus;
149 AddIntServer(INTB_KERNEL + bus->ab_IRQ, IntHandler);
151 return TRUE;
154 static const struct ata_BusDriver mpc_driver =
156 ata_out,
157 ata_in,
158 ata_outl,
159 ata_insw,
160 ata_outsw,
161 ata_insw, /* These are intentionally the same as 16-bit routines */
162 ata_outsw,
163 CreateInterrupt
166 static int ata_mpc_init(struct ataBase *LIBBASE)
168 int i;
170 * I've decided to use memory pools again. Alloc everything needed from
171 * a pool, so that we avoid memory fragmentation.
173 LIBBASE->ata_MemPool = CreatePool(MEMF_CLEAR | MEMF_PUBLIC | MEMF_SEM_PROTECTED , 8192, 4096);
174 if (LIBBASE->ata_MemPool == NULL)
175 return FALSE;
177 void *OpenFirmwareBase = OpenResource("openfirmware.resource");
178 void *key = OF_OpenKey("/builtin");
179 if (key)
181 void *prop = OF_FindProperty(key, "reg");
182 if (prop)
184 intptr_t *m_ = OF_GetPropValue(prop);
185 mbar = (UBYTE *)*m_;
186 ata_5k2 = (ata_5k2_t *)(*m_ + 0x3a00);
188 D(bug("[ATA] MBAR located at %08x\n", mbar));
191 /* Get the bus frequency for Efika */
192 prop = OF_FindProperty(key, "bus-frequency");
193 if (prop)
195 bus_frequency = *(uint32_t *)OF_GetPropValue(prop);
196 D(bug("[ATA] bus frequency: %d\n", bus_frequency));
200 key = OF_OpenKey("/builtin/ata");
201 if (key)
203 void *prop = OF_FindProperty(key, "reg");
204 if (prop)
206 ata_5k2 = *(ata_5k2_t **)OF_GetPropValue(prop);
208 D(bug("[ATA] ATA registers at %08x\n", ata_5k2));
212 key = OF_OpenKey("/builtin/ata/bestcomm-task");
213 if (key)
215 void *prop = OF_FindProperty(key, "taskid");
216 if (prop)
218 bestcomm_taskid = *(uint32_t *)OF_GetPropValue(prop);
220 D(bug("[ATA] ATA uses bestcomm task %d\n", bestcomm_taskid));
224 key = OF_OpenKey("/builtin/sram");
225 if (key)
227 void *prop = OF_FindProperty(key, "reg");
228 if (prop)
230 sram = *(void **)OF_GetPropValue(prop);
232 D(bug("[ATA] SRAM at %08x\n", sram));
235 key = OF_OpenKey("/builtin/bestcomm");
236 if (key)
238 void *prop = OF_FindProperty(key, "reg");
239 if (prop)
241 bestcomm = *(void **)OF_GetPropValue(prop);
243 D(bug("[ATA] bestcomm at %08x\n", bestcomm));
246 D(bug("[ATA] ata_config=%08x\n", inl(&ata_5k2->ata_config)));
247 D(bug("[ATA] ata_status=%08x\n", inl(&ata_5k2->ata_status)));
248 D(bug("[ATA] ata_pio1=%08x\n", inl(&ata_5k2->ata_pio1)));
249 D(bug("[ATA] ata_pio2=%08x\n", inl(&ata_5k2->ata_pio2)));
251 /* Disable XLB pipelining... */
252 D(bug("[ATA] xlb_config=%08x\n", inl(mbar+0x1f40)));
253 outl(inl(mbar + 0x1f40) | 0x80000000, mbar + 0x1f40);
255 outl(0, &ata_5k2->ata_invalid);
256 outl(0xc3000000, &ata_5k2->ata_config);
258 for (i=0; i < 100 / 4; i++)
259 ata_400ns();
261 /* Hacky timing pokes */
262 outl(0x03000000, &ata_5k2->ata_config);
263 outl(132 << 16, &ata_5k2->ata_invalid);
265 /* PIO2 timing table. Replace it by correct calculations soon !!! */
267 #warning TODO: Set the timings in right way!
269 outl(0x21270e00, &ata_5k2->ata_pio1);
270 outl(0x03050600, &ata_5k2->ata_pio2);
272 bestcomm_init();
275 * FIXME: This code uses static data variables.
276 * Move them into DriverData instead.
278 ata_RegisterBus(0x3a60, 0x3a5c - 8, MPC5200B_ATA, 0, FALSE, &mpc_driver, NULL, LIBBASE);
280 return TRUE;
283 ADD2INITLIB(ata_mpc_init, 20)