xref: /freebsd/sys/powerpc/powermac/ata_kauai.c (revision 6ac8f17ee4bdbdb838e3dd1e061066b335366e9a)
160727d8bSWarner Losh /*-
2321fd460SPeter Grehan  * Copyright 2004 by Peter Grehan. All rights reserved.
3321fd460SPeter Grehan  *
4321fd460SPeter Grehan  * Redistribution and use in source and binary forms, with or without
5321fd460SPeter Grehan  * modification, are permitted provided that the following conditions
6321fd460SPeter Grehan  * are met:
7321fd460SPeter Grehan  * 1. Redistributions of source code must retain the above copyright
8321fd460SPeter Grehan  *    notice, this list of conditions and the following disclaimer.
9321fd460SPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
10321fd460SPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
11321fd460SPeter Grehan  *    documentation and/or other materials provided with the distribution.
12321fd460SPeter Grehan  * 3. The name of the author may not be used to endorse or promote products
13321fd460SPeter Grehan  *    derived from this software without specific prior written permission.
14321fd460SPeter Grehan  *
15321fd460SPeter Grehan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16321fd460SPeter Grehan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17321fd460SPeter Grehan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18321fd460SPeter Grehan  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19321fd460SPeter Grehan  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20321fd460SPeter Grehan  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21321fd460SPeter Grehan  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22321fd460SPeter Grehan  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23321fd460SPeter Grehan  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24321fd460SPeter Grehan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25321fd460SPeter Grehan  * SUCH DAMAGE.
26321fd460SPeter Grehan  *
27321fd460SPeter Grehan  */
28321fd460SPeter Grehan #include <sys/cdefs.h>
29321fd460SPeter Grehan __FBSDID("$FreeBSD$");
30321fd460SPeter Grehan 
31321fd460SPeter Grehan /*
32321fd460SPeter Grehan  * Mac 'Kauai' PCI ATA controller
33321fd460SPeter Grehan  */
34321fd460SPeter Grehan #include "opt_ata.h"
35321fd460SPeter Grehan #include <sys/param.h>
36321fd460SPeter Grehan #include <sys/systm.h>
37321fd460SPeter Grehan #include <sys/kernel.h>
38321fd460SPeter Grehan #include <sys/module.h>
39321fd460SPeter Grehan #include <sys/bus.h>
40321fd460SPeter Grehan #include <sys/malloc.h>
41321fd460SPeter Grehan #include <sys/sema.h>
42321fd460SPeter Grehan #include <sys/taskqueue.h>
43321fd460SPeter Grehan #include <vm/uma.h>
44321fd460SPeter Grehan #include <machine/stdarg.h>
45321fd460SPeter Grehan #include <machine/resource.h>
46321fd460SPeter Grehan #include <machine/bus.h>
47321fd460SPeter Grehan #include <sys/rman.h>
48321fd460SPeter Grehan #include <sys/ata.h>
49321fd460SPeter Grehan #include <dev/ata/ata-all.h>
5098cbfce5SPeter Grehan #include <ata_if.h>
51321fd460SPeter Grehan 
52321fd460SPeter Grehan #include <dev/ofw/openfirm.h>
53321fd460SPeter Grehan 
54321fd460SPeter Grehan #include <dev/pci/pcivar.h>
55321fd460SPeter Grehan #include <dev/pci/pcireg.h>
56321fd460SPeter Grehan 
57321fd460SPeter Grehan #define  ATA_KAUAI_REGOFFSET	0x2000
5880bd99beSPeter Grehan 
5980bd99beSPeter Grehan /*
6080bd99beSPeter Grehan  * Offset to alt-control register from base
6180bd99beSPeter Grehan  */
6280bd99beSPeter Grehan #define  ATA_KAUAI_ALTOFFSET    (ATA_KAUAI_REGOFFSET + 0x160)
6380bd99beSPeter Grehan 
6480bd99beSPeter Grehan /*
6580bd99beSPeter Grehan  * Define the gap between registers
6680bd99beSPeter Grehan  */
6780bd99beSPeter Grehan #define ATA_KAUAI_REGGAP        16
68321fd460SPeter Grehan 
69321fd460SPeter Grehan /*
70321fd460SPeter Grehan  * Define the kauai pci bus attachment.
71321fd460SPeter Grehan  */
72321fd460SPeter Grehan static  int  ata_kauai_probe(device_t dev);
7398cbfce5SPeter Grehan static  void ata_kauai_setmode(device_t parent, device_t dev);
74321fd460SPeter Grehan 
75321fd460SPeter Grehan static device_method_t ata_kauai_methods[] = {
76321fd460SPeter Grehan         /* Device interface */
77321fd460SPeter Grehan 	DEVMETHOD(device_probe,		ata_kauai_probe),
78321fd460SPeter Grehan 	DEVMETHOD(device_attach,	ata_attach),
79321fd460SPeter Grehan 	DEVMETHOD(device_detach,	bus_generic_detach),
80321fd460SPeter Grehan 	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
81321fd460SPeter Grehan 	DEVMETHOD(device_suspend,	bus_generic_suspend),
82321fd460SPeter Grehan 	DEVMETHOD(device_resume,	bus_generic_resume),
83321fd460SPeter Grehan 
8498cbfce5SPeter Grehan 	/* ATA interface */
8598cbfce5SPeter Grehan 	DEVMETHOD(ata_setmode,		ata_kauai_setmode),
86321fd460SPeter Grehan 	{ 0, 0 }
87321fd460SPeter Grehan };
88321fd460SPeter Grehan 
89321fd460SPeter Grehan static driver_t ata_kauai_driver = {
90321fd460SPeter Grehan 	"ata",
91321fd460SPeter Grehan 	ata_kauai_methods,
92321fd460SPeter Grehan 	sizeof(struct ata_channel),
93321fd460SPeter Grehan };
94321fd460SPeter Grehan 
95321fd460SPeter Grehan DRIVER_MODULE(ata, pci, ata_kauai_driver, ata_devclass, 0, 0);
9605a016a3SPeter Grehan MODULE_DEPEND(ata, ata, 1, 1, 1);
97321fd460SPeter Grehan 
98321fd460SPeter Grehan /*
99321fd460SPeter Grehan  * PCI ID search table
100321fd460SPeter Grehan  */
101321fd460SPeter Grehan static struct kauai_pci_dev {
102321fd460SPeter Grehan         u_int32_t  kpd_devid;
103321fd460SPeter Grehan         char    *kpd_desc;
104321fd460SPeter Grehan } kauai_pci_devlist[] = {
105321fd460SPeter Grehan         { 0x0033106b, "Uninorth2 Kauai ATA Controller" },
106321fd460SPeter Grehan         { 0x003b106b, "Intrepid Kauai ATA Controller" },
107321fd460SPeter Grehan         { 0x0043106b, "K2 Kauai ATA Controller" },
108321fd460SPeter Grehan         { 0, NULL }
109321fd460SPeter Grehan };
110321fd460SPeter Grehan 
111321fd460SPeter Grehan static int
112321fd460SPeter Grehan ata_kauai_probe(device_t dev)
113321fd460SPeter Grehan {
114321fd460SPeter Grehan 	struct ata_channel *ch;
115321fd460SPeter Grehan 	struct resource *mem;
116321fd460SPeter Grehan 	u_long startp, countp;
117321fd460SPeter Grehan 	u_int32_t devid;
118321fd460SPeter Grehan 	int i, found, rid, status;
119321fd460SPeter Grehan 
120321fd460SPeter Grehan 	found = 0;
121321fd460SPeter Grehan 	devid = pci_get_devid(dev);
122321fd460SPeter Grehan         for (i = 0; kauai_pci_devlist[i].kpd_desc != NULL; i++) {
123321fd460SPeter Grehan                 if (devid == kauai_pci_devlist[i].kpd_devid) {
124321fd460SPeter Grehan 			found = 1;
125321fd460SPeter Grehan                         device_set_desc(dev, kauai_pci_devlist[i].kpd_desc);
126321fd460SPeter Grehan 		}
127321fd460SPeter Grehan 	}
128321fd460SPeter Grehan 
129321fd460SPeter Grehan 	if (!found)
130321fd460SPeter Grehan 		return (ENXIO);
131321fd460SPeter Grehan 
132321fd460SPeter Grehan 	/*
133321fd460SPeter Grehan 	 * This device seems to ignore writes to the interrupt
134321fd460SPeter Grehan 	 * config register, resulting in interrupt resources
135321fd460SPeter Grehan 	 * not being attached. If this is the case, use
136321fd460SPeter Grehan 	 * Open Firmware to determine the irq, and then attach
137321fd460SPeter Grehan 	 * the resource. This allows the ATA common code to
138321fd460SPeter Grehan 	 * allocate the irq.
139321fd460SPeter Grehan 	 */
140321fd460SPeter Grehan 	status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp, &countp);
141321fd460SPeter Grehan 	if (status == ENOENT) {
142321fd460SPeter Grehan 		int irq;
143321fd460SPeter Grehan 
144321fd460SPeter Grehan 		/*
145321fd460SPeter Grehan 		 * Aargh, hideous hack until ofw pci intr routine is
146321fd460SPeter Grehan 		 * exported
147321fd460SPeter Grehan 		 */
148321fd460SPeter Grehan 		irq = 39; /* XXX */
149321fd460SPeter Grehan 		bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
150321fd460SPeter Grehan 
151321fd460SPeter Grehan 		/*
152321fd460SPeter Grehan 		 * Sanity check...
153321fd460SPeter Grehan 		 */
154321fd460SPeter Grehan 		status = bus_get_resource(dev, SYS_RES_IRQ, 0, &startp,
155321fd460SPeter Grehan 		    &countp);
156321fd460SPeter Grehan 		if (status == ENOENT ||
157321fd460SPeter Grehan 		    startp != 39) {
158321fd460SPeter Grehan 			printf("kauai irq not set!\n");
159321fd460SPeter Grehan 			return (ENXIO);
160321fd460SPeter Grehan 		}
161321fd460SPeter Grehan 	}
162321fd460SPeter Grehan 
163321fd460SPeter Grehan 	ch = device_get_softc(dev);
16450069af1SPeter Grehan 	bzero(ch, sizeof(struct ata_channel));
165321fd460SPeter Grehan 
16680bd99beSPeter Grehan         rid = PCIR_BARS;
1672e428c54SPeter Grehan 	mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
168321fd460SPeter Grehan         if (mem == NULL) {
169321fd460SPeter Grehan                 device_printf(dev, "could not allocate memory\n");
170321fd460SPeter Grehan                 return (ENXIO);
171321fd460SPeter Grehan         }
172321fd460SPeter Grehan 
173321fd460SPeter Grehan 	/*
174321fd460SPeter Grehan 	 * Set up the resource vectors
175321fd460SPeter Grehan 	 */
1765a276744SPeter Grehan         for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
177321fd460SPeter Grehan                 ch->r_io[i].res = mem;
17880bd99beSPeter Grehan                 ch->r_io[i].offset = i*ATA_KAUAI_REGGAP + ATA_KAUAI_REGOFFSET;
179321fd460SPeter Grehan         }
180a378bbabSPeter Grehan         ch->r_io[ATA_CONTROL].res = mem;
181a378bbabSPeter Grehan         ch->r_io[ATA_CONTROL].offset = ATA_KAUAI_ALTOFFSET;
1826ac8f17eSPeter Grehan 	ata_default_registers(dev);
183321fd460SPeter Grehan 
184321fd460SPeter Grehan         ch->unit = 0;
185321fd460SPeter Grehan         ch->flags |= ATA_USE_16BIT|ATA_NO_SLAVE;
1866ac8f17eSPeter Grehan 	ata_generic_hw(dev);
187321fd460SPeter Grehan 
188321fd460SPeter Grehan         return (ata_probe(dev));
189321fd460SPeter Grehan }
190321fd460SPeter Grehan 
19198cbfce5SPeter Grehan static void
19298cbfce5SPeter Grehan ata_kauai_setmode(device_t parent, device_t dev)
19398cbfce5SPeter Grehan {
19498cbfce5SPeter Grehan 	struct ata_device *atadev = device_get_softc(dev);
19598cbfce5SPeter Grehan 
19698cbfce5SPeter Grehan 	/* TODO bang kauai speed register */
19798cbfce5SPeter Grehan 	atadev->mode = ATA_PIO;
19898cbfce5SPeter Grehan }
199