1 /*-
2 * Copyright (c) 2006 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD: releng/6.4/sys/arm/xscale/ixp425/avila_ata.c 167038 2007-02-26 23:13:09Z cognet $");
32
33 /*
34 * Compact Flash Support for the Avila Gateworks XScale boards.
35 * There are 1 or 2 optional CF slots operated in "True IDE" mode.
36 * Registers are on the Expansion Bus connected to CS1. Interrupts
37 * are tied to GPIO pin 12. No DMA, just PIO.
38 *
39 * See also http://www.intel.com/design/network/applnots/302456.htm.
40 */
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/module.h>
45 #include <sys/time.h>
46 #include <sys/bus.h>
47 #include <sys/resource.h>
48 #define __RMAN_RESOURCE_VISIBLE
49 #include <sys/rman.h>
50 #include <sys/sysctl.h>
51 #include <sys/endian.h>
52
53 #include <machine/bus.h>
54 #include <machine/cpu.h>
55 #include <machine/cpufunc.h>
56 #include <machine/resource.h>
57 #include <machine/intr.h>
58 #include <arm/xscale/ixp425/ixp425reg.h>
59 #include <arm/xscale/ixp425/ixp425var.h>
60
61 #include <sys/ata.h>
62 #include <sys/sema.h>
63 #include <sys/taskqueue.h>
64 #include <vm/uma.h>
65 #include <dev/ata/ata-all.h>
66 #include <ata_if.h>
67
68 #define AVILA_IDE_GPIN 12 /* GPIO pin # */
69 #define AVILA_IDE_IRQ IXP425_INT_GPIO_12
70 #define AVILA_IDE_CTRL 0x1e /* control register */
71
72 struct ata_avila_softc {
73 device_t sc_dev;
74 bus_space_tag_t sc_iot;
75 bus_space_handle_t sc_exp_ioh; /* Exp Bus config registers */
76 bus_space_handle_t sc_ioh; /* CS1 data registers */
77 struct bus_space sc_expbus_tag;
78 struct resource sc_ata; /* hand-crafted for ATA */
79 int sc_rid; /* rid for IRQ */
80 struct resource *sc_irq; /* IRQ resource */
81 void *sc_ih; /* interrupt handler */
82 struct {
83 void (*cb)(void *);
84 void *arg;
85 } sc_intr[1]; /* NB: 1/channel */
86 };
87
88 static void ata_avila_intr(void *);
89 bs_protos(ata);
90 static void ata_bs_rm_2_s(void *, bus_space_handle_t, bus_size_t,
91 u_int16_t *, bus_size_t);
92 static void ata_bs_wm_2_s(void *, bus_space_handle_t, bus_size_t,
93 const u_int16_t *, bus_size_t);
94
95 static int
96 ata_avila_probe(device_t dev)
97 {
98 /* XXX any way to check? */
99 device_set_desc_copy(dev, "Gateworks Avila IDE/CF Controller");
100 return 0;
101 }
102
103 static int
104 ata_avila_attach(device_t dev)
105 {
106 struct ata_avila_softc *sc = device_get_softc(dev);
107 struct ixp425_softc *sa = device_get_softc(device_get_parent(dev));
108
109 sc->sc_dev = dev;
110 /* NB: borrow from parent */
111 sc->sc_iot = sa->sc_iot;
112 sc->sc_exp_ioh = sa->sc_exp_ioh;
113 if (bus_space_map(sc->sc_iot,
114 IXP425_EXP_BUS_CS1_HWBASE, IXP425_EXP_BUS_CS1_SIZE, 0, &sc->sc_ioh))
115 panic("%s: unable to map Expansion Bus CS1 window", __func__);
116
117 /*
118 * Craft special resource for ATA bus space ops
119 * that go through the expansion bus and require
120 * special hackery to ena/dis 16-bit operations.
121 *
122 * XXX probably should just make this generic for
123 * accessing the expansion bus.
124 */
125 sc->sc_expbus_tag.bs_cookie = sc; /* NB: backpointer */
126 /* read single */
127 sc->sc_expbus_tag.bs_r_1 = ata_bs_r_1,
128 sc->sc_expbus_tag.bs_r_2 = ata_bs_r_2,
129 /* read multiple */
130 sc->sc_expbus_tag.bs_rm_2 = ata_bs_rm_2,
131 sc->sc_expbus_tag.bs_rm_2_s = ata_bs_rm_2_s,
132 /* write (single) */
133 sc->sc_expbus_tag.bs_w_1 = ata_bs_w_1,
134 sc->sc_expbus_tag.bs_w_2 = ata_bs_w_2,
135 /* write multiple */
136 sc->sc_expbus_tag.bs_wm_2 = ata_bs_wm_2,
137 sc->sc_expbus_tag.bs_wm_2_s = ata_bs_wm_2_s,
138
139 rman_set_bustag(&sc->sc_ata, &sc->sc_expbus_tag);
140 rman_set_bushandle(&sc->sc_ata, sc->sc_ioh);
141
142 GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPOER,
143 GPIO_CONF_READ_4(sa, IXP425_GPIO_GPOER) | (1<<AVILA_IDE_GPIN));
144 /* interrupt is active low */
145 GPIO_CONF_WRITE_4(sa, GPIO_TYPE_REG(AVILA_IDE_GPIN),
146 GPIO_CONF_READ_4(sa, GPIO_TYPE_REG(AVILA_IDE_GPIN) |
147 GPIO_TYPE(AVILA_IDE_GPIN, GPIO_TYPE_ACT_LOW)));
148
149 /* clear ISR */
150 GPIO_CONF_WRITE_4(sa, IXP425_GPIO_GPISR, (1<<AVILA_IDE_GPIN));
151
152 /* configure CS1 window, leaving timing unchanged */
153 EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET,
154 EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) |
155 EXP_BYTE_EN | EXP_WR_EN | EXP_BYTE_RD16 | EXP_CS_EN);
156
157 /* setup interrupt */
158 sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_rid,
159 AVILA_IDE_IRQ, AVILA_IDE_IRQ, 1, RF_ACTIVE);
160 if (!sc->sc_irq)
161 panic("Unable to allocate irq %u.\n", AVILA_IDE_IRQ);
162 bus_setup_intr(dev, sc->sc_irq,
163 INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
164 ata_avila_intr, sc, &sc->sc_ih);
165
166 /* attach channel on this controller */
167 device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 0));
168 bus_generic_attach(dev);
169
170 return 0;
171 }
172
173 static int
174 ata_avila_detach(device_t dev)
175 {
176 struct ata_avila_softc *sc = device_get_softc(dev);
177 device_t *children;
178 int nc;
179
180 /* XXX quiesce gpio? */
181
182 /* detach & delete all children */
183 if (device_get_children(dev, &children, &nc) == 0) {
184 if (nc > 0)
185 device_delete_child(dev, children[0]);
186 free(children, M_TEMP);
187 }
188
189 bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih);
190 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid, sc->sc_irq);
191
192 return 0;
193 }
194
195 static void
196 ata_avila_intr(void *xsc)
197 {
198 struct ata_avila_softc *sc = xsc;
199
200 if (sc->sc_intr[0].cb != NULL)
201 sc->sc_intr[0].cb(sc->sc_intr[0].arg);
202 }
203
204 static struct resource *
205 ata_avila_alloc_resource(device_t dev, device_t child, int type, int *rid,
206 u_long start, u_long end, u_long count, u_int flags)
207 {
208 struct ata_avila_softc *sc = device_get_softc(dev);
209
210 KASSERT(type == SYS_RES_IRQ && *rid == ATA_IRQ_RID,
211 ("type %u rid %u start %lu end %lu count %lu flags %u",
212 type, *rid, start, end, count, flags));
213
214 /* doesn't matter what we return so reuse the real thing */
215 return sc->sc_irq;
216 }
217
218 static int
219 ata_avila_release_resource(device_t dev, device_t child, int type, int rid,
220 struct resource *r)
221 {
222 KASSERT(type == SYS_RES_IRQ && rid == ATA_IRQ_RID,
223 ("type %u rid %u", type, rid));
224 return 0;
225 }
226
227 static int
228 ata_avila_setup_intr(device_t dev, device_t child, struct resource *irq,
229 int flags, driver_intr_t *function, void *argument,
230 void **cookiep)
231 {
232 struct ata_avila_softc *sc = device_get_softc(dev);
233 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
234
235 KASSERT(unit == 0, ("unit %d", unit));
236 sc->sc_intr[unit].cb = function;
237 sc->sc_intr[unit].arg = argument;
238 *cookiep = sc;
239 return 0;
240 }
241
242 static int
243 ata_avila_teardown_intr(device_t dev, device_t child, struct resource *irq,
244 void *cookie)
245 {
246 struct ata_avila_softc *sc = device_get_softc(dev);
247 int unit = ((struct ata_channel *)device_get_softc(child))->unit;
248
249 KASSERT(unit == 0, ("unit %d", unit));
250 sc->sc_intr[unit].cb = NULL;
251 sc->sc_intr[unit].arg = NULL;
252 return 0;
253 }
254
255 /*
256 * Bus space accessors for CF-IDE PIO operations.
257 */
258
259 /*
260 * Enable/disable 16-bit ops on the expansion bus.
261 */
262 static void __inline
263 enable_16(struct ata_avila_softc *sc)
264 {
265 EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET,
266 EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) &~ EXP_BYTE_EN);
267 DELAY(100); /* XXX? */
268 }
269
270 static void __inline
271 disable_16(struct ata_avila_softc *sc)
272 {
273 DELAY(100); /* XXX? */
274 EXP_BUS_WRITE_4(sc, EXP_TIMING_CS1_OFFSET,
275 EXP_BUS_READ_4(sc, EXP_TIMING_CS1_OFFSET) | EXP_BYTE_EN);
276 }
277
278 uint8_t
279 ata_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o)
280 {
281 struct ata_avila_softc *sc = t;
282
283 return bus_space_read_1(sc->sc_iot, h, o);
284 }
285
286 void
287 ata_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, u_int8_t v)
288 {
289 struct ata_avila_softc *sc = t;
290
291 bus_space_write_1(sc->sc_iot, h, o, v);
292 }
293
294 uint16_t
295 ata_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o)
296 {
297 struct ata_avila_softc *sc = t;
298 uint16_t v;
299
300 enable_16(sc);
301 v = bus_space_read_2(sc->sc_iot, h, o);
302 disable_16(sc);
303 return v;
304 }
305
306 void
307 ata_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, uint16_t v)
308 {
309 struct ata_avila_softc *sc = t;
310
311 enable_16(sc);
312 bus_space_write_2(sc->sc_iot, h, o, v);
313 disable_16(sc);
314 }
315
316 void
317 ata_bs_rm_2(void *t, bus_space_handle_t h, bus_size_t o,
318 u_int16_t *d, bus_size_t c)
319 {
320 struct ata_avila_softc *sc = t;
321
322 enable_16(sc);
323 bus_space_read_multi_2(sc->sc_iot, h, o, d, c);
324 disable_16(sc);
325 }
326
327 void
328 ata_bs_wm_2(void *t, bus_space_handle_t h, bus_size_t o,
329 const u_int16_t *d, bus_size_t c)
330 {
331 struct ata_avila_softc *sc = t;
332
333 enable_16(sc);
334 bus_space_write_multi_2(sc->sc_iot, h, o, d, c);
335 disable_16(sc);
336 }
337
338 /* XXX workaround ata driver by (incorrectly) byte swapping stream cases */
339
340 void
341 ata_bs_rm_2_s(void *t, bus_space_handle_t h, bus_size_t o,
342 u_int16_t *d, bus_size_t c)
343 {
344 struct ata_avila_softc *sc = t;
345 uint16_t v;
346 bus_size_t i;
347
348 enable_16(sc);
349 #if 1
350 for (i = 0; i < c; i++) {
351 v = bus_space_read_2(sc->sc_iot, h, o);
352 d[i] = bswap16(v);
353 }
354 #else
355 bus_space_read_multi_stream_2(sc->sc_iot, h, o, d, c);
356 #endif
357 disable_16(sc);
358 }
359
360 void
361 ata_bs_wm_2_s(void *t, bus_space_handle_t h, bus_size_t o,
362 const u_int16_t *d, bus_size_t c)
363 {
364 struct ata_avila_softc *sc = t;
365 bus_size_t i;
366
367 enable_16(sc);
368 #if 1
369 for (i = 0; i < c; i++)
370 bus_space_write_2(sc->sc_iot, h, o, bswap16(d[i]));
371 #else
372 bus_space_write_multi_stream_2(sc->sc_iot, h, o, d, c);
373 #endif
374 disable_16(sc);
375 }
376
377 static device_method_t ata_avila_methods[] = {
378 /* device interface */
379 DEVMETHOD(device_probe, ata_avila_probe),
380 DEVMETHOD(device_attach, ata_avila_attach),
381 DEVMETHOD(device_detach, ata_avila_detach),
382 DEVMETHOD(device_shutdown, bus_generic_shutdown),
383 DEVMETHOD(device_suspend, bus_generic_suspend),
384 DEVMETHOD(device_resume, bus_generic_resume),
385
386 /* bus methods */
387 DEVMETHOD(bus_alloc_resource, ata_avila_alloc_resource),
388 DEVMETHOD(bus_release_resource, ata_avila_release_resource),
389 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
390 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
391 DEVMETHOD(bus_setup_intr, ata_avila_setup_intr),
392 DEVMETHOD(bus_teardown_intr, ata_avila_teardown_intr),
393
394 { 0, 0 }
395 };
396
397 devclass_t ata_avila_devclass;
398
399 static driver_t ata_avila_driver = {
400 "ata_avila",
401 ata_avila_methods,
402 sizeof(struct ata_avila_softc),
403 };
404
405 DRIVER_MODULE(ata_avila, ixp, ata_avila_driver, ata_avila_devclass, 0, 0);
406 MODULE_VERSION(ata_avila, 1);
407 MODULE_DEPEND(ata_avila, ata, 1, 1, 1);
408
409 static int
410 avila_channel_probe(device_t dev)
411 {
412 struct ata_channel *ch = device_get_softc(dev);
413
414 ch->unit = 0;
415 ch->flags |= ATA_USE_16BIT | ATA_NO_SLAVE;
416 device_set_desc_copy(dev, "ATA channel 0");
417
418 return ata_probe(dev);
419 }
420
421 static int
422 avila_channel_attach(device_t dev)
423 {
424 struct ata_avila_softc *sc = device_get_softc(device_get_parent(dev));
425 struct ata_channel *ch = device_get_softc(dev);
426 int i;
427
428 for (i = 0; i < ATA_MAX_RES; i++)
429 ch->r_io[i].res = &sc->sc_ata;
430
431 ch->r_io[ATA_DATA].offset = ATA_DATA;
432 ch->r_io[ATA_FEATURE].offset = ATA_FEATURE;
433 ch->r_io[ATA_COUNT].offset = ATA_COUNT;
434 ch->r_io[ATA_SECTOR].offset = ATA_SECTOR;
435 ch->r_io[ATA_CYL_LSB].offset = ATA_CYL_LSB;
436 ch->r_io[ATA_CYL_MSB].offset = ATA_CYL_MSB;
437 ch->r_io[ATA_DRIVE].offset = ATA_DRIVE;
438 ch->r_io[ATA_COMMAND].offset = ATA_COMMAND;
439 ch->r_io[ATA_ERROR].offset = ATA_FEATURE;
440 /* NB: should be used only for ATAPI devices */
441 ch->r_io[ATA_IREASON].offset = ATA_COUNT;
442 ch->r_io[ATA_STATUS].offset = ATA_COMMAND;
443 /* alias this; required by ata_generic_status */
444 ch->r_io[ATA_ALTSTAT].offset = ch->r_io[ATA_STATUS].offset;
445
446 /* NB: the control register is special */
447 ch->r_io[ATA_CONTROL].offset = AVILA_IDE_CTRL;
448
449 /* NB: by convention this points at the base of registers */
450 ch->r_io[ATA_IDX_ADDR].offset = 0;
451
452 ata_generic_hw(dev);
453 return ata_attach(dev);
454 }
455
456 /* XXX override ata_generic_reset to handle non-standard status */
457 static void
458 avila_channel_reset(device_t dev)
459 {
460 struct ata_channel *ch = device_get_softc(dev);
461 u_int8_t ostat0 = 0, stat0 = 0;
462 u_int8_t err = 0, lsb = 0, msb = 0;
463 int mask = 0, timeout;
464
465 /* do we have any signs of ATA/ATAPI HW being present ? */
466 ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
467 DELAY(10);
468 ostat0 = ATA_IDX_INB(ch, ATA_STATUS);
469 if ((ostat0 & 0xf8) != 0xf8 && ostat0 != 0xa5) {
470 stat0 = ATA_S_BUSY;
471 mask |= 0x01;
472 }
473
474 if (bootverbose)
475 device_printf(dev, "%s: reset tp1 mask=%02x ostat0=%02x\n",
476 __func__, mask, ostat0);
477
478 /* if nothing showed up there is no need to get any further */
479 /* XXX SOS is that too strong?, we just might loose devices here */
480 ch->devices = 0;
481 if (!mask)
482 return;
483
484 /* reset (both) devices on this channel */
485 ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_D_LBA | ATA_MASTER);
486 DELAY(10);
487 ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS | ATA_A_RESET);
488 ata_udelay(10000);
489 ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_IDS);
490 ata_udelay(100000);
491 ATA_IDX_INB(ch, ATA_ERROR);
492
493 /* wait for BUSY to go inactive */
494 for (timeout = 0; timeout < 310; timeout++) {
495 if ((mask & 0x01) && (stat0 & ATA_S_BUSY)) {
496 ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | ATA_MASTER);
497 DELAY(10);
498 err = ATA_IDX_INB(ch, ATA_ERROR);
499 lsb = ATA_IDX_INB(ch, ATA_CYL_LSB);
500 msb = ATA_IDX_INB(ch, ATA_CYL_MSB);
501 stat0 = ATA_IDX_INB(ch, ATA_STATUS);
502 if (bootverbose)
503 device_printf(dev,
504 "%s: stat0=0x%02x err=0x%02x lsb=0x%02x "
505 "msb=0x%02x\n", __func__,
506 stat0, err, lsb, msb);
507 if (stat0 == err && lsb == err && msb == err &&
508 timeout > (stat0 & ATA_S_BUSY ? 100 : 10))
509 mask &= ~0x01;
510 if (!(stat0 & ATA_S_BUSY)) {
511 if ((err & 0x7f) == ATA_E_ILI || err == 0) {
512 if (lsb == ATAPI_MAGIC_LSB &&
513 msb == ATAPI_MAGIC_MSB) {
514 ch->devices |= ATA_ATAPI_MASTER;
515 } else if (stat0 & ATA_S_READY) {
516 ch->devices |= ATA_ATA_MASTER;
517 }
518 } else if ((stat0 & 0x0f) &&
519 err == lsb && err == msb) {
520 stat0 |= ATA_S_BUSY;
521 }
522 }
523 }
524 if (mask == 0x00) /* nothing to wait for */
525 break;
526 /* wait for master */
527 if (!(stat0 & ATA_S_BUSY) || (stat0 == 0xff && timeout > 10))
528 break;
529 ata_udelay(100000);
530 }
531
532 if (bootverbose)
533 device_printf(dev, "%s: reset tp2 stat0=%02x devices=0x%b\n",
534 __func__, stat0, ch->devices,
535 "\2\4ATAPI_SLAVE\3ATAPI_MASTER\2ATA_SLAVE\1ATA_MASTER");
536 }
537
538 static device_method_t avila_channel_methods[] = {
539 /* device interface */
540 DEVMETHOD(device_probe, avila_channel_probe),
541 DEVMETHOD(device_attach, avila_channel_attach),
542 DEVMETHOD(device_detach, ata_detach),
543 DEVMETHOD(device_shutdown, bus_generic_shutdown),
544 DEVMETHOD(device_suspend, ata_suspend),
545 DEVMETHOD(device_resume, ata_resume),
546
547 DEVMETHOD(ata_reset, avila_channel_reset),
548
549 { 0, 0 }
550 };
551
552 driver_t avila_channel_driver = {
553 "ata",
554 avila_channel_methods,
555 sizeof(struct ata_channel),
556 };
557 DRIVER_MODULE(ata, ata_avila, avila_channel_driver, ata_devclass, 0, 0);
Cache object: 05e8e29ad2bdb9526c31ab01852febd7
|