1 /* $NetBSD: dbau1550.c,v 1.7 2006/10/02 08:13:53 gdamore Exp $ */
4 * Copyright (c) 2006 Itronix Inc.
7 * Written by Garrett D'Amore for Itronix Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of Itronix Inc. may not be used to endorse
18 * or promote products derived from this software without specific
19 * prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: dbau1550.c,v 1.7 2006/10/02 08:13:53 gdamore Exp $");
37 #include <sys/param.h>
38 #include <sys/kernel.h>
41 #include <machine/bus.h>
42 #include <machine/locore.h>
43 #include <mips/alchemy/include/aureg.h>
44 #include <mips/alchemy/dev/aupcmciavar.h>
45 #include <mips/alchemy/dev/aupcmciareg.h>
46 #include <mips/alchemy/dev/augpioreg.h>
47 #include <mips/alchemy/dev/auspivar.h>
48 #include <evbmips/alchemy/obiovar.h>
49 #include <evbmips/alchemy/board.h>
50 #include <evbmips/alchemy/dbau1550reg.h>
55 * This should be converted to use bus_space routines.
58 (*((volatile uint16_t *)MIPS_PHYS_TO_KSEG1(x)))
60 (*((volatile uint16_t *)MIPS_PHYS_TO_KSEG1(x)) = (v))
62 (*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x)))
64 (*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x)) = (v))
66 static void dbau1550_init(void);
67 static int dbau1550_pci_intr_map(struct pci_attach_args
*,
69 static void dbau1550_poweroff(void);
70 static void dbau1550_reboot(void);
71 static bus_addr_t
dbau1550_slot_offset(int);
72 static int dbau1550_slot_irq(int, int);
73 static void dbau1550_slot_enable(int);
74 static void dbau1550_slot_disable(int);
75 static int dbau1550_slot_status(int);
76 static const char *dbau1550_slot_name(int);
77 static const struct auspi_machdep
*dbau1550_spi(bus_addr_t
);
79 static const struct obiodev dbau1550_devices
[] = {
83 static struct aupcmcia_machdep dbau1550_pcmcia
= {
88 dbau1550_slot_disable
,
93 static struct alchemy_board dbau1550_info
= {
94 .ab_name
= "AMD Alchemy DBAu1550",
95 .ab_devices
= dbau1550_devices
,
96 .ab_init
= dbau1550_init
,
97 .ab_pci_intr_map
=dbau1550_pci_intr_map
,
98 .ab_reboot
= dbau1550_reboot
,
99 .ab_poweroff
= dbau1550_poweroff
,
100 .ab_pcmcia
= &dbau1550_pcmcia
,
101 .ab_spi
= dbau1550_spi
,
104 const struct alchemy_board
*
108 return &dbau1550_info
;
118 if (MIPS_PRID_COPTS(cpu_id
) != MIPS_AU1550
)
119 panic("dbau1550: CPU not Au1550");
121 /* check the whoami register for a match */
122 whoami
= GET16(DBAU1550_WHOAMI
);
124 if (DBAU1550_WHOAMI_BOARD(whoami
) != DBAU1550_WHOAMI_DBAU1550_REV1
)
125 panic("dbau1550: WHOAMI (%x) not DBAu1550!", whoami
);
127 printf("DBAu1550 (cabernet), CPLDv%d, ",
128 DBAU1550_WHOAMI_CPLD(whoami
));
130 if (DBAU1550_WHOAMI_DAUGHTER(whoami
) != 0xf)
131 printf("daughtercard 0x%x\n",
132 DBAU1550_WHOAMI_DAUGHTER(whoami
));
134 printf("no daughtercard\n");
136 /* leave console and clocks alone -- YAMON should have got it right! */
139 * Initialize PSC clocks.
141 * PSC0 is SPI. Use 48MHz FREQ1.
143 * PSC2 is SMBus, and must be 48MHz. (Configured by YAMON)
146 * FREQ2 is 48MHz for USBH/USBD.
148 sysclk
= GET32(SYS_CLKSRC
);
149 sysclk
&= ~(SCS_MP0(7) | SCS_DP0
| SCS_CP0
);
150 sysclk
|= SCS_MP0(3);
151 PUT32(SYS_CLKSRC
, sysclk
);
154 * Configure pin function for PSC devices.
156 pinfunc
= GET32(SYS_PINFUNC
);
157 /* configure PSC0 SYNC1 */
159 /* configure PSC2 for SMBus (YAMON default) */
160 pinfunc
&= ~SPF_PSC2_MASK
;
161 pinfunc
|= SPF_PSC2_SMBUS
;
162 /* configure PSC3 for I2S (YAMON default) */
163 pinfunc
&= ~SPF_PSC3_MASK
;
164 pinfunc
|= SPF_PSC3_I2S
;
165 PUT32(SYS_PINFUNC
, pinfunc
);
169 dbau1550_pci_intr_map(struct pci_attach_args
*pa
, pci_intr_handle_t
*ihp
)
172 * This platform has one onboard PCI IDE controller, and two
173 * PCI expansion slots.
175 static const int irqmap
[3/*device*/][4/*pin*/] = {
176 { 5, -1, -1, -1 }, /* 11: IDE */
177 { 2, 5, 6, 1 }, /* 12: PCI Slot 2 */
178 { 1, 2, 5, 6 }, /* 13: PCI Slot 3 */
182 /* if interrupt pin not used... */
183 if ((pin
= pa
->pa_intrpin
) == 0)
187 printf("pci: bad interrupt pin %d\n", pin
);
191 pci_decompose_tag(pa
->pa_pc
, pa
->pa_intrtag
, NULL
, &dev
, NULL
);
192 if ((dev
< 11) || (dev
> 13)) {
193 printf("pci: bad device %d\n", dev
);
197 if ((irq
= irqmap
[dev
- 11][pin
- 1]) == -1) {
198 printf("pci: no IRQ routing for device %d pin %d\n", dev
, pin
);
207 dbau1550_reboot(void)
209 PUT16(DBAU1550_SOFTWARE_RESET
, 0);
211 delay(100000); /* 100 msec */
215 dbau1550_poweroff(void)
217 printf("\n- poweroff -\n");
218 PUT16(DBAU1550_SOFTWARE_RESET
,
219 DBAU1550_SOFTWARE_RESET_PWROFF
| DBAU1550_SOFTWARE_RESET_RESET
);
221 delay(100000); /* 100 msec */
225 dbau1550_slot_irq(int slot
, int which
)
227 static const int irqmap
[2/*slot*/][2/*which*/] = {
228 { 35, 32 }, /* Slot 0: Bottom */
229 { 37, 33 }, /* Slot 1: Top */
232 if ((slot
>= 2) || (which
>= 2))
235 return (irqmap
[slot
][which
]);
239 dbau1550_slot_offset(int slot
)
243 return (DBAU1550_PC0_ADDR
);
245 return (DBAU1550_PC1_ADDR
);
248 return (bus_addr_t
)-1;
252 dbau1550_slot_enable(int slot
)
258 status
= GET16(DBAU1550_STATUS
);
261 status
>>= DBAU1550_STATUS_PCMCIA0_VS_SHIFT
;
262 shift
= DBAU1550_PCMCIA_PC0_SHIFT
;
265 status
>>= DBAU1550_STATUS_PCMCIA1_VS_SHIFT
;
266 shift
= DBAU1550_PCMCIA_PC1_SHIFT
;
272 status
&= DBAU1550_STATUS_PCMCIA_VS_MASK
;
274 case DBAU1550_STATUS_PCMCIA_VS_GND
:
275 vcc
= DBAU1550_PCMCIA_VCC_GND
;
276 vpp
= DBAU1550_PCMCIA_VPP_GND
;
278 case DBAU1550_STATUS_PCMCIA_VS_5V
:
279 vcc
= DBAU1550_PCMCIA_VCC_5V
;
280 vpp
= DBAU1550_PCMCIA_VPP_VCC
;
282 default: /* covers both 3.3v cases */
283 vcc
= DBAU1550_PCMCIA_VCC_3V
;
284 vpp
= DBAU1550_PCMCIA_VPP_VCC
;
288 status
= GET16(DBAU1550_PCMCIA
);
290 /* this clears all bits for this slot */
291 status
&= ~(DBAU1550_PCMCIA_MASK
<< shift
);
293 status
|= vcc
<< shift
;
294 status
|= vpp
<< shift
;
296 PUT16(DBAU1550_PCMCIA
, status
);
298 tsleep(&status
, PWAIT
, "pcmcia_reset_0", mstohz(100));
300 status
|= (DBAU1550_PCMCIA_DRV_EN
<< shift
);
301 PUT16(DBAU1550_PCMCIA
, status
);
303 tsleep(&status
, PWAIT
, "pcmcia_reset_start", mstohz(300));
305 /* take it out of reset */
306 status
|= (DBAU1550_PCMCIA_RST
<< shift
);
307 PUT16(DBAU1550_PCMCIA
, status
);
310 /* spec says 20 msec, but experience shows even 200 is not enough */
311 tsleep(&status
, PWAIT
, "pcmcia_reset_finish", mstohz(1000));
313 /* NOTE: WE DO NOT SUPPORT DIFFERENT VCC/VPP LEVELS! */
314 /* This means that 12V cards are not supported! */
318 dbau1550_slot_disable(int slot
)
325 shift
= DBAU1550_PCMCIA_PC0_SHIFT
;
328 shift
= DBAU1550_PCMCIA_PC1_SHIFT
;
332 status
= GET16(DBAU1550_PCMCIA
);
333 status
&= ~(DBAU1550_PCMCIA_MASK
);
334 PUT16(DBAU1550_PCMCIA
, status
);
339 dbau1550_slot_status(int slot
)
341 uint16_t status
, mask
;
342 status
= GET16(DBAU1550_STATUS
);
345 mask
= DBAU1550_STATUS_PCMCIA0_INSERTED
;
348 mask
= DBAU1550_STATUS_PCMCIA1_INSERTED
;
355 return ((mask
& status
) ? 0 : 1);
359 dbau1550_slot_name(int slot
)
363 return "bottom slot";
374 dbau1550_spi_select(void *arg
, int slave
)
377 if ((slave
< 0) || (slave
> 1))
379 status
= GET16(DBAU1550_BOARD_SPECIFIC
);
382 status
|= DBAU1550_SPI_DEV_SEL
;
384 status
&= ~DBAU1550_SPI_DEV_SEL
;
386 PUT16(DBAU1550_BOARD_SPECIFIC
, status
);
390 const struct auspi_machdep
*
391 dbau1550_spi(bus_addr_t ba
)
393 static const struct auspi_machdep md
= {
396 .am_select
= dbau1550_spi_select
,
399 /* DBAU1550 only has SPI on PSC0 */
406 #endif /* NAUSPI > 0 */