]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/mips/atheros/ar71xx_pci.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / mips / atheros / ar71xx_pci.c
1 /*-
2  * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
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 unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33
34 #include <sys/bus.h>
35 #include <sys/interrupt.h>
36 #include <sys/malloc.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/rman.h>
40
41 #include <vm/vm.h>
42 #include <vm/pmap.h>
43 #include <vm/vm_extern.h>
44
45 #include <machine/bus.h>
46 #include <machine/cpu.h>
47 #include <machine/intr_machdep.h>
48 #include <machine/pmap.h>
49
50 #include <dev/pci/pcivar.h>
51 #include <dev/pci/pcireg.h>
52
53 #include <dev/pci/pcib_private.h>
54 #include "pcib_if.h"
55
56 #include <mips/atheros/ar71xxreg.h>
57 #include <mips/atheros/ar71xx_pci_bus_space.h>
58
59 #include <mips/atheros/ar71xx_cpudef.h>
60
61 #undef AR71XX_PCI_DEBUG
62 #ifdef AR71XX_PCI_DEBUG
63 #define dprintf printf
64 #else
65 #define dprintf(x, arg...)
66 #endif
67
68 struct ar71xx_pci_softc {
69         device_t                sc_dev;
70
71         int                     sc_busno;
72         struct rman             sc_mem_rman;
73         struct rman             sc_irq_rman;
74
75         struct intr_event       *sc_eventstab[AR71XX_PCI_NIRQS];        
76         mips_intrcnt_t          sc_intr_counter[AR71XX_PCI_NIRQS];      
77         struct resource         *sc_irq;
78         void                    *sc_ih;
79 };
80
81 static int ar71xx_pci_setup_intr(device_t, device_t, struct resource *, int, 
82                     driver_filter_t *, driver_intr_t *, void *, void **);
83 static int ar71xx_pci_teardown_intr(device_t, device_t, struct resource *,
84                     void *);
85 static int ar71xx_pci_intr(void *);
86
87 static void 
88 ar71xx_pci_mask_irq(void *source)
89 {
90         uint32_t reg;
91         unsigned int irq = (unsigned int)source;
92
93         reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
94         /* flush */
95         reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
96         ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg & ~(1 << irq));
97 }
98
99 static void 
100 ar71xx_pci_unmask_irq(void *source)
101 {
102         uint32_t reg;
103         unsigned int irq = (unsigned int)source;
104
105         reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
106         ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, reg | (1 << irq));
107         /* flush */
108         reg = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
109 }
110
111 /* 
112  * get bitmask for bytes of interest: 
113  *   0 - we want this byte, 1 - ignore it. e.g: we read 1 byte 
114  *   from register 7. Bitmask would be: 0111
115  */
116 static uint32_t
117 ar71xx_get_bytes_to_read(int reg, int bytes)
118 {
119         uint32_t bytes_to_read = 0;
120         if ((bytes % 4) == 0)
121                 bytes_to_read = 0;
122         else if ((bytes % 4) == 1)
123                 bytes_to_read = (~(1 << (reg % 4))) & 0xf;
124         else if ((bytes % 4) == 2)
125                 bytes_to_read = (~(3 << (reg % 4))) & 0xf;
126         else
127                 panic("%s: wrong combination", __func__);
128
129         return (bytes_to_read);
130 }
131
132 static int 
133 ar71xx_pci_check_bus_error(void)
134 {
135         uint32_t error, addr, has_errors = 0;
136         error = ATH_READ_REG(AR71XX_PCI_ERROR) & 0x3;
137         dprintf("%s: PCI error = %02x\n", __func__, error);
138         if (error) {
139                 addr = ATH_READ_REG(AR71XX_PCI_ERROR_ADDR);
140
141                 /* Do not report it yet */
142 #if 0
143                 printf("PCI bus error %d at addr 0x%08x\n", error, addr);
144 #endif
145                 ATH_WRITE_REG(AR71XX_PCI_ERROR, error);
146                 has_errors = 1;
147         }
148
149         error = ATH_READ_REG(AR71XX_PCI_AHB_ERROR) & 0x1;
150         dprintf("%s: AHB error = %02x\n", __func__, error);
151         if (error) {
152                 addr = ATH_READ_REG(AR71XX_PCI_AHB_ERROR_ADDR);
153                 /* Do not report it yet */
154 #if 0
155                 printf("AHB bus error %d at addr 0x%08x\n", error, addr);
156 #endif
157                 ATH_WRITE_REG(AR71XX_PCI_AHB_ERROR, error);
158                 has_errors = 1;
159         }
160
161         return (has_errors);
162 }
163
164 static uint32_t
165 ar71xx_pci_make_addr(int bus, int slot, int func, int reg)
166 {
167         if (bus == 0) {
168                 return ((1 << slot) | (func << 8) | (reg & ~3));
169         } else {
170                 return ((bus << 16) | (slot << 11) | (func << 8) 
171                     | (reg  & ~3) | 1);
172         }
173 }
174
175 static int
176 ar71xx_pci_conf_setup(int bus, int slot, int func, int reg, int bytes, 
177     uint32_t cmd)
178 {
179         uint32_t addr = ar71xx_pci_make_addr(bus, slot, func, (reg & ~3));
180         cmd |= (ar71xx_get_bytes_to_read(reg, bytes) << 4);
181         
182         ATH_WRITE_REG(AR71XX_PCI_CONF_ADDR, addr);
183         ATH_WRITE_REG(AR71XX_PCI_CONF_CMD, cmd);
184
185         dprintf("%s: tag (%x, %x, %x) %d/%d addr=%08x, cmd=%08x\n", __func__, 
186             bus, slot, func, reg, bytes, addr, cmd);
187
188         return ar71xx_pci_check_bus_error();
189 }
190
191 static uint32_t
192 ar71xx_pci_read_config(device_t dev, u_int bus, u_int slot, u_int func, 
193     u_int reg, int bytes)
194 {
195         uint32_t data;
196         uint32_t cmd, shift, mask;
197
198         /* register access is 32-bit aligned */
199         shift = (reg & 3) * 8;
200         if (shift)
201                 mask = (1 << shift) - 1;
202         else
203                 mask = 0xffffffff;
204
205         dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot, 
206             func, reg, bytes);
207
208         if ((bus == 0) && (slot == 0) && (func == 0)) {
209                 cmd = PCI_LCONF_CMD_READ | (reg & ~3);
210                 ATH_WRITE_REG(AR71XX_PCI_LCONF_CMD, cmd);
211                 data = ATH_READ_REG(AR71XX_PCI_LCONF_READ_DATA);
212         } else {
213                  if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes, 
214                      PCI_CONF_CMD_READ) == 0)
215                          data = ATH_READ_REG(AR71XX_PCI_CONF_READ_DATA);
216                  else
217                          data = -1;
218         }
219
220         /* get request bytes from 32-bit word */
221         data = (data >> shift) & mask;
222
223         dprintf("%s: read 0x%x\n", __func__, data);
224
225         return (data);
226 }
227
228 static void
229 ar71xx_pci_write_config(device_t dev, u_int bus, u_int slot, u_int func, 
230     u_int reg, uint32_t data, int bytes)
231 {
232         uint32_t cmd;
233
234         dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot, 
235             func, reg, bytes);
236
237         data = data << (8*(reg % 4));
238
239         if ((bus == 0) && (slot == 0) && (func == 0)) {
240                 cmd = PCI_LCONF_CMD_WRITE | (reg & ~3);
241                 cmd |= ar71xx_get_bytes_to_read(reg, bytes) << 20;
242                 ATH_WRITE_REG(AR71XX_PCI_LCONF_CMD, cmd);
243                 ATH_WRITE_REG(AR71XX_PCI_LCONF_WRITE_DATA, data);
244         } else {
245                  if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes, 
246                      PCI_CONF_CMD_WRITE) == 0)
247                          ATH_WRITE_REG(AR71XX_PCI_CONF_WRITE_DATA, data);
248         }
249 }
250
251 static int
252 ar71xx_pci_probe(device_t dev)
253 {
254
255         return (0);
256 }
257
258 static int
259 ar71xx_pci_attach(device_t dev)
260 {
261         int busno = 0;
262         int rid = 0;
263         struct ar71xx_pci_softc *sc = device_get_softc(dev);
264
265         sc->sc_mem_rman.rm_type = RMAN_ARRAY;
266         sc->sc_mem_rman.rm_descr = "ar71xx PCI memory window";
267         if (rman_init(&sc->sc_mem_rman) != 0 || 
268             rman_manage_region(&sc->sc_mem_rman, AR71XX_PCI_MEM_BASE, 
269                 AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1) != 0) {
270                 panic("ar71xx_pci_attach: failed to set up I/O rman");
271         }
272
273         sc->sc_irq_rman.rm_type = RMAN_ARRAY;
274         sc->sc_irq_rman.rm_descr = "ar71xx PCI IRQs";
275         if (rman_init(&sc->sc_irq_rman) != 0 ||
276             rman_manage_region(&sc->sc_irq_rman, AR71XX_PCI_IRQ_START, 
277                 AR71XX_PCI_IRQ_END) != 0)
278                 panic("ar71xx_pci_attach: failed to set up IRQ rman");
279
280
281         ATH_WRITE_REG(AR71XX_PCI_INTR_STATUS, 0);
282         ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, 0);
283
284         /* Hook up our interrupt handler. */
285         if ((sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
286             RF_SHAREABLE | RF_ACTIVE)) == NULL) {
287                 device_printf(dev, "unable to allocate IRQ resource\n");
288                 return ENXIO;
289         }
290
291         if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
292                             ar71xx_pci_intr, NULL, sc, &sc->sc_ih))) {
293                 device_printf(dev, 
294                     "WARNING: unable to register interrupt handler\n");
295                 return ENXIO;
296         }
297
298         /* reset PCI core and PCI bus */
299         ar71xx_device_stop(RST_RESET_PCI_CORE | RST_RESET_PCI_BUS);
300         DELAY(100000);
301
302         ar71xx_device_start(RST_RESET_PCI_CORE | RST_RESET_PCI_BUS);
303         DELAY(100000);
304
305         /* Init PCI windows */
306         ATH_WRITE_REG(AR71XX_PCI_WINDOW0, PCI_WINDOW0_ADDR);
307         ATH_WRITE_REG(AR71XX_PCI_WINDOW1, PCI_WINDOW1_ADDR);
308         ATH_WRITE_REG(AR71XX_PCI_WINDOW2, PCI_WINDOW2_ADDR);
309         ATH_WRITE_REG(AR71XX_PCI_WINDOW3, PCI_WINDOW3_ADDR);
310         ATH_WRITE_REG(AR71XX_PCI_WINDOW4, PCI_WINDOW4_ADDR);
311         ATH_WRITE_REG(AR71XX_PCI_WINDOW5, PCI_WINDOW5_ADDR);
312         ATH_WRITE_REG(AR71XX_PCI_WINDOW6, PCI_WINDOW6_ADDR);
313         ATH_WRITE_REG(AR71XX_PCI_WINDOW7, PCI_WINDOW7_CONF_ADDR);
314         DELAY(100000);
315
316         ar71xx_pci_check_bus_error();
317
318         /* Fixup internal PCI bridge */
319         ar71xx_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND, 
320             PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN 
321             | PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK
322             | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 2);
323
324         device_add_child(dev, "pci", busno);
325         return (bus_generic_attach(dev));
326 }
327
328 static int
329 ar71xx_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
330 {
331         struct ar71xx_pci_softc *sc = device_get_softc(dev);
332
333         switch (which) {
334         case PCIB_IVAR_DOMAIN:
335                 *result = 0;
336                 return (0);
337         case PCIB_IVAR_BUS:
338                 *result = sc->sc_busno;
339                 return (0);
340         }
341
342         return (ENOENT);
343 }
344
345 static int
346 ar71xx_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
347 {
348         struct ar71xx_pci_softc * sc = device_get_softc(dev);
349
350         switch (which) {
351         case PCIB_IVAR_BUS:
352                 sc->sc_busno = result;
353                 return (0);
354         }
355
356         return (ENOENT);
357 }
358
359 static struct resource *
360 ar71xx_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
361     u_long start, u_long end, u_long count, u_int flags)
362 {
363
364         struct ar71xx_pci_softc *sc = device_get_softc(bus);    
365         struct resource *rv;
366         struct rman *rm;
367
368         switch (type) {
369         case SYS_RES_IRQ:
370                 rm = &sc->sc_irq_rman;
371                 break;
372         case SYS_RES_MEMORY:
373                 rm = &sc->sc_mem_rman;
374                 break;
375         default:
376                 return (NULL);
377         }
378
379         rv = rman_reserve_resource(rm, start, end, count, flags, child);
380
381         if (rv == NULL)
382                 return (NULL);
383
384         rman_set_rid(rv, *rid);
385
386         if (flags & RF_ACTIVE) {
387                 if (bus_activate_resource(child, type, *rid, rv)) {
388                         rman_release_resource(rv);
389                         return (NULL);
390                 }
391         } 
392
393
394         return (rv);
395 }
396
397
398 static int
399 ar71xx_pci_activate_resource(device_t bus, device_t child, int type, int rid,
400     struct resource *r)
401 {
402         int res = (BUS_ACTIVATE_RESOURCE(device_get_parent(bus),
403             child, type, rid, r));
404
405         if (!res) {
406                 switch(type) {
407                 case SYS_RES_MEMORY:
408                 case SYS_RES_IOPORT:
409                         rman_set_bustag(r, ar71xx_bus_space_pcimem);
410                         break;
411                 }
412         }
413
414         return (res);
415 }
416
417
418
419 static int
420 ar71xx_pci_setup_intr(device_t bus, device_t child, struct resource *ires,
421                 int flags, driver_filter_t *filt, driver_intr_t *handler,
422                 void *arg, void **cookiep)
423 {
424         struct ar71xx_pci_softc *sc = device_get_softc(bus);
425         struct intr_event *event;
426         int irq, error;
427
428         irq = rman_get_start(ires);
429
430         if (irq > AR71XX_PCI_IRQ_END)
431                 panic("%s: bad irq %d", __func__, irq);
432
433         event = sc->sc_eventstab[irq];
434         if (event == NULL) {
435                 error = intr_event_create(&event, (void *)irq, 0, irq, 
436                     ar71xx_pci_mask_irq, ar71xx_pci_unmask_irq, NULL, NULL,
437                     "pci intr%d:", irq);
438
439                 if (error == 0) {
440                         sc->sc_eventstab[irq] = event;
441                         sc->sc_intr_counter[irq] =
442                             mips_intrcnt_create(event->ie_name);
443                 }
444                 else
445                         return error;
446         }
447
448         intr_event_add_handler(event, device_get_nameunit(child), filt,
449             handler, arg, intr_priority(flags), flags, cookiep);
450         mips_intrcnt_setname(sc->sc_intr_counter[irq], event->ie_fullname);
451
452         ar71xx_pci_unmask_irq((void*)irq);
453
454         return (0);
455 }
456
457 static int
458 ar71xx_pci_teardown_intr(device_t dev, device_t child, struct resource *ires,
459     void *cookie)
460 {
461         struct ar71xx_pci_softc *sc = device_get_softc(dev);
462         int irq, result;
463
464         irq = rman_get_start(ires);
465         if (irq > AR71XX_PCI_IRQ_END)
466                 panic("%s: bad irq %d", __func__, irq);
467
468         if (sc->sc_eventstab[irq] == NULL)
469                 panic("Trying to teardown unoccupied IRQ");
470
471         ar71xx_pci_mask_irq((void*)irq);
472
473         result = intr_event_remove_handler(cookie);
474         if (!result)
475                 sc->sc_eventstab[irq] = NULL;
476
477         return (result);
478 }
479
480 static int
481 ar71xx_pci_intr(void *arg)
482 {
483         struct ar71xx_pci_softc *sc = arg;
484         struct intr_event *event;
485         uint32_t reg, irq, mask;
486
487         reg = ATH_READ_REG(AR71XX_PCI_INTR_STATUS);
488         mask = ATH_READ_REG(AR71XX_PCI_INTR_MASK);
489         /*
490          * Handle only unmasked interrupts
491          */
492         reg &= mask;
493         for (irq = AR71XX_PCI_IRQ_START; irq <= AR71XX_PCI_IRQ_END; irq++) {
494                 if (reg & (1 << irq)) {
495                         event = sc->sc_eventstab[irq];
496                         if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
497                                 /* Ignore timer interrupts */
498                                 if (irq != 0)
499                                         printf("Stray IRQ %d\n", irq);
500                                 continue;
501                         }
502
503                         /* Flush DDR FIFO for IP2 */
504                         ar71xx_device_ddr_flush_ip2();
505
506                         /* TODO: frame instead of NULL? */
507                         intr_event_handle(event, NULL);
508                         mips_intrcnt_inc(sc->sc_intr_counter[irq]);
509                 }
510         }
511
512         return (FILTER_HANDLED);
513 }
514
515 static int
516 ar71xx_pci_maxslots(device_t dev)
517 {
518
519         return (PCI_SLOTMAX);
520 }
521
522 static int
523 ar71xx_pci_route_interrupt(device_t pcib, device_t device, int pin)
524 {
525         if (pci_get_slot(device) < AR71XX_PCI_BASE_SLOT)
526                 panic("%s: PCI slot %d is less then AR71XX_PCI_BASE_SLOT",
527                     __func__, pci_get_slot(device));
528
529         return (pci_get_slot(device) - AR71XX_PCI_BASE_SLOT);
530 }
531
532 static device_method_t ar71xx_pci_methods[] = {
533         /* Device interface */
534         DEVMETHOD(device_probe,         ar71xx_pci_probe),
535         DEVMETHOD(device_attach,        ar71xx_pci_attach),
536         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
537         DEVMETHOD(device_suspend,       bus_generic_suspend),
538         DEVMETHOD(device_resume,        bus_generic_resume),
539
540         /* Bus interface */
541         DEVMETHOD(bus_read_ivar,        ar71xx_pci_read_ivar),
542         DEVMETHOD(bus_write_ivar,       ar71xx_pci_write_ivar),
543         DEVMETHOD(bus_alloc_resource,   ar71xx_pci_alloc_resource),
544         DEVMETHOD(bus_release_resource, bus_generic_release_resource),
545         DEVMETHOD(bus_activate_resource, ar71xx_pci_activate_resource),
546         DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
547         DEVMETHOD(bus_setup_intr,       ar71xx_pci_setup_intr),
548         DEVMETHOD(bus_teardown_intr,    ar71xx_pci_teardown_intr),
549
550         /* pcib interface */
551         DEVMETHOD(pcib_maxslots,        ar71xx_pci_maxslots),
552         DEVMETHOD(pcib_read_config,     ar71xx_pci_read_config),
553         DEVMETHOD(pcib_write_config,    ar71xx_pci_write_config),
554         DEVMETHOD(pcib_route_interrupt, ar71xx_pci_route_interrupt),
555
556         DEVMETHOD_END
557 };
558
559 static driver_t ar71xx_pci_driver = {
560         "pcib",
561         ar71xx_pci_methods,
562         sizeof(struct ar71xx_pci_softc),
563 };
564
565 static devclass_t ar71xx_pci_devclass;
566
567 DRIVER_MODULE(ar71xx_pci, nexus, ar71xx_pci_driver, ar71xx_pci_devclass, 0, 0);