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