Home | History | Annotate | Line # | Download | only in alchemy
dbau1550.c revision 1.5.2.1
      1  1.5.2.1     yamt /* $NetBSD: dbau1550.c,v 1.5.2.1 2006/04/01 12:06:12 yamt Exp $ */
      2      1.1  gdamore 
      3      1.1  gdamore /*-
      4      1.1  gdamore  * Copyright (c) 2006 Itronix Inc.
      5      1.1  gdamore  * All rights reserved.
      6      1.1  gdamore  *
      7      1.1  gdamore  * Written by Garrett D'Amore for Itronix Inc.
      8      1.1  gdamore  *
      9      1.1  gdamore  * Redistribution and use in source and binary forms, with or without
     10      1.1  gdamore  * modification, are permitted provided that the following conditions
     11      1.1  gdamore  * are met:
     12      1.1  gdamore  * 1. Redistributions of source code must retain the above copyright
     13      1.1  gdamore  *    notice, this list of conditions and the following disclaimer.
     14      1.1  gdamore  * 2. Redistributions in binary form must reproduce the above copyright
     15      1.1  gdamore  *    notice, this list of conditions and the following disclaimer in the
     16      1.1  gdamore  *    documentation and/or other materials provided with the distribution.
     17      1.1  gdamore  * 3. The name of Itronix Inc. may not be used to endorse
     18      1.1  gdamore  *    or promote products derived from this software without specific
     19      1.1  gdamore  *    prior written permission.
     20      1.1  gdamore  *
     21      1.1  gdamore  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
     22      1.1  gdamore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23      1.1  gdamore  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24      1.1  gdamore  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
     25      1.1  gdamore  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26      1.1  gdamore  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     27      1.1  gdamore  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     28      1.1  gdamore  * ON ANY THEORY OF LIABILITY, WHETHER IN
     29      1.1  gdamore  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30      1.1  gdamore  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31      1.1  gdamore  * POSSIBILITY OF SUCH DAMAGE.
     32      1.1  gdamore  */
     33      1.1  gdamore 
     34      1.1  gdamore #include <sys/cdefs.h>
     35  1.5.2.1     yamt __KERNEL_RCSID(0, "$NetBSD: dbau1550.c,v 1.5.2.1 2006/04/01 12:06:12 yamt Exp $");
     36      1.1  gdamore 
     37      1.1  gdamore #include <sys/param.h>
     38      1.5  gdamore #include <sys/kernel.h>
     39      1.5  gdamore #include <sys/param.h>
     40      1.5  gdamore #include <sys/time.h>
     41      1.5  gdamore #include <sys/proc.h>
     42      1.1  gdamore #include <machine/bus.h>
     43      1.1  gdamore #include <machine/locore.h>
     44      1.5  gdamore #include <mips/alchemy/include/aureg.h>
     45      1.5  gdamore #include <mips/alchemy/dev/aupcmciavar.h>
     46      1.5  gdamore #include <mips/alchemy/dev/aupcmciareg.h>
     47      1.5  gdamore #include <mips/alchemy/dev/augpioreg.h>
     48      1.1  gdamore #include <evbmips/alchemy/obiovar.h>
     49      1.1  gdamore #include <evbmips/alchemy/board.h>
     50      1.1  gdamore #include <evbmips/alchemy/dbau1550reg.h>
     51      1.1  gdamore 
     52      1.5  gdamore /*
     53      1.5  gdamore  * This should be converted to use bus_space routines.
     54      1.5  gdamore  */
     55      1.4  gdamore #define	GET16(x)	\
     56      1.4  gdamore 	(*((volatile uint16_t *)MIPS_PHYS_TO_KSEG1(x)))
     57      1.3  gdamore #define	PUT16(x, v)	\
     58      1.3  gdamore 	(*((volatile uint16_t *)MIPS_PHYS_TO_KSEG1(x)) = (v))
     59      1.5  gdamore #define	GET32(x)	\
     60      1.5  gdamore 	(*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x)))
     61      1.5  gdamore #define	PUT32(x, v)	\
     62      1.5  gdamore 	(*((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x)) = (v))
     63      1.3  gdamore 
     64      1.1  gdamore static void dbau1550_init(void);
     65      1.1  gdamore static int dbau1550_pci_intr_map(struct pci_attach_args *,
     66      1.1  gdamore 				 pci_intr_handle_t *);
     67      1.3  gdamore static void dbau1550_poweroff(void);
     68      1.3  gdamore static void dbau1550_reboot(void);
     69      1.5  gdamore static bus_addr_t dbau1550_slot_offset(int);
     70      1.5  gdamore static int dbau1550_slot_irq(int, int);
     71      1.5  gdamore static void dbau1550_slot_enable(int);
     72      1.5  gdamore static void dbau1550_slot_disable(int);
     73      1.5  gdamore static int dbau1550_slot_status(int);
     74      1.5  gdamore static const char *dbau1550_slot_name(int);
     75      1.1  gdamore 
     76      1.1  gdamore static const struct obiodev dbau1550_devices[] = {
     77      1.1  gdamore #if 0
     78      1.1  gdamore 	{ "aupsc", -1, -1 },
     79      1.1  gdamore 	{ "aupsc", -1, -1 },
     80      1.1  gdamore 	{ "aupsc", -1, -1 },
     81      1.1  gdamore #endif
     82      1.1  gdamore 	{ NULL },
     83      1.1  gdamore };
     84      1.1  gdamore 
     85      1.5  gdamore static struct aupcmcia_machdep dbau1550_pcmcia = {
     86      1.5  gdamore 	2,	/* nslots */
     87      1.5  gdamore 	dbau1550_slot_offset,
     88      1.5  gdamore 	dbau1550_slot_irq,
     89      1.5  gdamore 	dbau1550_slot_enable,
     90      1.5  gdamore 	dbau1550_slot_disable,
     91      1.5  gdamore 	dbau1550_slot_status,
     92      1.5  gdamore 	dbau1550_slot_name,
     93      1.5  gdamore };
     94      1.5  gdamore 
     95      1.1  gdamore static struct alchemy_board dbau1550_info = {
     96      1.1  gdamore 	"AMD Alchemy DBAu1550",
     97      1.1  gdamore 	dbau1550_devices,
     98      1.1  gdamore 	dbau1550_init,
     99      1.1  gdamore 	dbau1550_pci_intr_map,
    100      1.3  gdamore 	dbau1550_reboot,
    101      1.3  gdamore 	dbau1550_poweroff,
    102      1.5  gdamore 	&dbau1550_pcmcia,
    103      1.1  gdamore };
    104      1.1  gdamore 
    105      1.1  gdamore const struct alchemy_board *
    106      1.1  gdamore board_info(void)
    107      1.1  gdamore {
    108      1.1  gdamore 
    109      1.1  gdamore 	return &dbau1550_info;
    110      1.1  gdamore }
    111      1.1  gdamore 
    112      1.1  gdamore void
    113      1.1  gdamore dbau1550_init(void)
    114      1.1  gdamore {
    115      1.4  gdamore 	uint16_t		whoami;
    116      1.1  gdamore 
    117      1.1  gdamore 	if (MIPS_PRID_COPTS(cpu_id) != MIPS_AU1550)
    118      1.1  gdamore 		panic("dbau1550: CPU not Au1550");
    119      1.1  gdamore 
    120      1.1  gdamore 	/* check the whoami register for a match */
    121      1.4  gdamore 	whoami = GET16(DBAU1550_WHOAMI);
    122      1.1  gdamore 
    123      1.1  gdamore 	if (DBAU1550_WHOAMI_BOARD(whoami) != DBAU1550_WHOAMI_DBAU1550_REV1)
    124      1.1  gdamore 		panic("dbau1550: WHOAMI (%x) not DBAu1550!", whoami);
    125      1.1  gdamore 
    126      1.1  gdamore 	printf("DBAu1550 (cabernet), CPLDv%d, ",
    127      1.1  gdamore 	    DBAU1550_WHOAMI_CPLD(whoami));
    128      1.1  gdamore 
    129      1.1  gdamore 	if (DBAU1550_WHOAMI_DAUGHTER(whoami) != 0xf)
    130      1.1  gdamore 		printf("daughtercard 0x%x\n",
    131      1.1  gdamore 		    DBAU1550_WHOAMI_DAUGHTER(whoami));
    132      1.1  gdamore 	else
    133      1.1  gdamore 		printf("no daughtercard\n");
    134      1.1  gdamore 
    135      1.1  gdamore 	/* leave console and clocks alone -- YAMON should have got it right! */
    136      1.1  gdamore }
    137      1.1  gdamore 
    138      1.1  gdamore int
    139      1.1  gdamore dbau1550_pci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
    140      1.1  gdamore {
    141      1.1  gdamore 	/*
    142      1.1  gdamore 	 * This platform has one onboard PCI IDE controller, and two
    143      1.1  gdamore 	 * PCI expansion slots.
    144      1.1  gdamore 	 */
    145      1.1  gdamore 	static const int irqmap[3/*device*/][4/*pin*/] = {
    146      1.1  gdamore 		{  5, -1, -1, -1 },	/* 11: IDE */
    147      1.1  gdamore 		{  2,  5,  6,  1 },	/* 12: PCI Slot 2 */
    148      1.1  gdamore 		{  1,  2,  5,  6 },	/* 13: PCI Slot 3 */
    149      1.1  gdamore 	};
    150      1.1  gdamore 	int	pin, dev, irq;
    151      1.1  gdamore 
    152      1.1  gdamore 	/* if interrupt pin not used... */
    153      1.1  gdamore 	if ((pin = pa->pa_intrpin) == 0)
    154      1.1  gdamore 		return 1;
    155      1.1  gdamore 
    156      1.1  gdamore 	if (pin > 4) {
    157      1.1  gdamore 		printf("pci: bad interrupt pin %d\n", pin);
    158      1.1  gdamore 		return 1;
    159      1.1  gdamore 	}
    160      1.1  gdamore 
    161      1.1  gdamore 	pci_decompose_tag(pa->pa_pc, pa->pa_intrtag, NULL, &dev, NULL);
    162      1.1  gdamore 	if ((dev < 11) || (dev > 13)) {
    163      1.1  gdamore 		printf("pci: bad device %d\n", dev);
    164      1.1  gdamore 		return 1;
    165      1.1  gdamore 	}
    166      1.1  gdamore 
    167      1.1  gdamore 	if ((irq = irqmap[dev - 11][pin - 1]) == -1) {
    168      1.1  gdamore 		printf("pci: no IRQ routing for device %d pin %d\n", dev, pin);
    169      1.1  gdamore 		return 1;
    170      1.1  gdamore 	}
    171      1.1  gdamore 
    172      1.1  gdamore 	*ihp = irq;
    173      1.1  gdamore 	return 0;
    174      1.1  gdamore }
    175      1.3  gdamore 
    176      1.3  gdamore void
    177      1.3  gdamore dbau1550_reboot(void)
    178      1.3  gdamore {
    179      1.3  gdamore 	PUT16(DBAU1550_SOFTWARE_RESET, 0);
    180      1.5  gdamore 	wbflush();
    181      1.3  gdamore 	delay(100000);	/* 100 msec */
    182      1.3  gdamore }
    183      1.3  gdamore 
    184      1.3  gdamore void
    185      1.3  gdamore dbau1550_poweroff(void)
    186      1.3  gdamore {
    187      1.3  gdamore 	printf("\n- poweroff -\n");
    188      1.3  gdamore 	PUT16(DBAU1550_SOFTWARE_RESET,
    189      1.3  gdamore 	    DBAU1550_SOFTWARE_RESET_PWROFF | DBAU1550_SOFTWARE_RESET_RESET);
    190      1.5  gdamore 	wbflush();
    191      1.3  gdamore 	delay(100000);	/* 100 msec */
    192      1.3  gdamore }
    193      1.5  gdamore 
    194      1.5  gdamore int
    195      1.5  gdamore dbau1550_slot_irq(int slot, int which)
    196      1.5  gdamore {
    197      1.5  gdamore 	static const int irqmap[2/*slot*/][2/*which*/] = {
    198      1.5  gdamore 		{ 35, 32 },		/* Slot 0: Bottom */
    199      1.5  gdamore 		{ 37, 33 },		/* Slot 1: Top */
    200      1.5  gdamore 	};
    201      1.5  gdamore 
    202      1.5  gdamore 	if ((slot >= 2) || (which >= 2))
    203      1.5  gdamore 		return -1;
    204      1.5  gdamore 
    205      1.5  gdamore 	return (irqmap[slot][which]);
    206      1.5  gdamore }
    207      1.5  gdamore 
    208      1.5  gdamore bus_addr_t
    209      1.5  gdamore dbau1550_slot_offset(int slot)
    210      1.5  gdamore {
    211      1.5  gdamore 	switch (slot) {
    212      1.5  gdamore 	case 0:
    213      1.5  gdamore 		return (DBAU1550_PC0_ADDR);
    214      1.5  gdamore 	case 1:
    215      1.5  gdamore 		return (DBAU1550_PC1_ADDR);
    216      1.5  gdamore 	}
    217      1.5  gdamore 
    218      1.5  gdamore 	return (bus_addr_t)-1;
    219      1.5  gdamore }
    220      1.5  gdamore 
    221      1.5  gdamore void
    222      1.5  gdamore dbau1550_slot_enable(int slot)
    223      1.5  gdamore {
    224      1.5  gdamore 	uint16_t	status;
    225      1.5  gdamore 	uint16_t	vcc, vpp;
    226      1.5  gdamore 	int		shift;
    227      1.5  gdamore 
    228      1.5  gdamore 	status = GET16(DBAU1550_STATUS);
    229      1.5  gdamore 	switch (slot) {
    230      1.5  gdamore 	case 0:
    231      1.5  gdamore 		status >>= DBAU1550_STATUS_PCMCIA0_VS_SHIFT;
    232      1.5  gdamore 		shift = DBAU1550_PCMCIA_PC0_SHIFT;
    233      1.5  gdamore 		break;
    234      1.5  gdamore 	case 1:
    235      1.5  gdamore 		status >>= DBAU1550_STATUS_PCMCIA1_VS_SHIFT;
    236      1.5  gdamore 		shift = DBAU1550_PCMCIA_PC1_SHIFT;
    237      1.5  gdamore 		break;
    238      1.5  gdamore 	default:
    239      1.5  gdamore 		return;
    240      1.5  gdamore 	}
    241      1.5  gdamore 
    242      1.5  gdamore 	status &= DBAU1550_STATUS_PCMCIA_VS_MASK;
    243      1.5  gdamore 	switch (status) {
    244      1.5  gdamore 	case DBAU1550_STATUS_PCMCIA_VS_GND:
    245      1.5  gdamore 		vcc = DBAU1550_PCMCIA_VCC_GND;
    246      1.5  gdamore 		vpp = DBAU1550_PCMCIA_VPP_GND;
    247      1.5  gdamore 		break;
    248      1.5  gdamore 	case DBAU1550_STATUS_PCMCIA_VS_5V:
    249      1.5  gdamore 		vcc = DBAU1550_PCMCIA_VCC_5V;
    250      1.5  gdamore 		vpp = DBAU1550_PCMCIA_VPP_VCC;
    251      1.5  gdamore 		break;
    252      1.5  gdamore 	default:	/* covers both 3.3v cases */
    253      1.5  gdamore 		vcc = DBAU1550_PCMCIA_VCC_3V;
    254      1.5  gdamore 		vpp = DBAU1550_PCMCIA_VPP_VCC;
    255      1.5  gdamore 		break;
    256      1.5  gdamore 	}
    257      1.5  gdamore 
    258      1.5  gdamore 	status = GET16(DBAU1550_PCMCIA);
    259      1.5  gdamore 
    260      1.5  gdamore 	/* this clears all bits for this slot */
    261      1.5  gdamore 	status &= ~(DBAU1550_PCMCIA_MASK << shift);
    262      1.5  gdamore 
    263      1.5  gdamore 	status |= vcc << shift;
    264      1.5  gdamore 	status |= vpp << shift;
    265      1.5  gdamore 
    266      1.5  gdamore 	PUT16(DBAU1550_PCMCIA, status);
    267      1.5  gdamore 	wbflush();
    268      1.5  gdamore 	tsleep(&status, PWAIT, "pcmcia_reset_0", mstohz(100));
    269      1.5  gdamore 
    270      1.5  gdamore 	status |= (DBAU1550_PCMCIA_DRV_EN << shift);
    271      1.5  gdamore 	PUT16(DBAU1550_PCMCIA, status);
    272      1.5  gdamore 	wbflush();
    273      1.5  gdamore 	tsleep(&status, PWAIT, "pcmcia_reset_start", mstohz(300));
    274      1.5  gdamore 
    275      1.5  gdamore 	/* take it out of reset */
    276      1.5  gdamore 	status |= (DBAU1550_PCMCIA_RST << shift);
    277      1.5  gdamore 	PUT16(DBAU1550_PCMCIA, status);
    278      1.5  gdamore 	wbflush();
    279  1.5.2.1     yamt 
    280  1.5.2.1     yamt 	/* spec says 20 msec, but experience shows even 200 is not enough */
    281  1.5.2.1     yamt 	tsleep(&status, PWAIT, "pcmcia_reset_finish", mstohz(1000));
    282      1.5  gdamore 
    283      1.5  gdamore 	/* NOTE: WE DO NOT SUPPORT DIFFERENT VCC/VPP LEVELS! */
    284      1.5  gdamore 	/* This means that 12V cards are not supported! */
    285      1.5  gdamore }
    286      1.5  gdamore 
    287      1.5  gdamore void
    288      1.5  gdamore dbau1550_slot_disable(int slot)
    289      1.5  gdamore {
    290      1.5  gdamore 	int		shift;
    291      1.5  gdamore 	uint16_t	status;
    292      1.5  gdamore 
    293      1.5  gdamore 	switch (slot) {
    294      1.5  gdamore 	case 0:
    295      1.5  gdamore 		shift = DBAU1550_PCMCIA_PC0_SHIFT;
    296      1.5  gdamore 		break;
    297      1.5  gdamore 	case 1:
    298      1.5  gdamore 		shift = DBAU1550_PCMCIA_PC1_SHIFT;
    299      1.5  gdamore 		break;
    300      1.5  gdamore 	}
    301      1.5  gdamore 
    302      1.5  gdamore 	status = GET16(DBAU1550_PCMCIA);
    303      1.5  gdamore 	status &= ~(DBAU1550_PCMCIA_MASK);
    304      1.5  gdamore 	PUT16(DBAU1550_PCMCIA, status);
    305      1.5  gdamore 	wbflush();
    306      1.5  gdamore }
    307      1.5  gdamore 
    308      1.5  gdamore int
    309      1.5  gdamore dbau1550_slot_status(int slot)
    310      1.5  gdamore {
    311      1.5  gdamore 	uint16_t	status, mask;
    312      1.5  gdamore 	status = GET16(DBAU1550_STATUS);
    313      1.5  gdamore 	switch (slot) {
    314      1.5  gdamore 	case 0:
    315      1.5  gdamore 		mask = DBAU1550_STATUS_PCMCIA0_INSERTED;
    316      1.5  gdamore 		break;
    317      1.5  gdamore 	case 1:
    318      1.5  gdamore 		mask = DBAU1550_STATUS_PCMCIA1_INSERTED;
    319      1.5  gdamore 		break;
    320      1.5  gdamore 
    321      1.5  gdamore 	default:
    322      1.5  gdamore 		return 0;
    323      1.5  gdamore 	}
    324      1.5  gdamore 
    325      1.5  gdamore 	return ((mask & status) ? 0 : 1);
    326      1.5  gdamore }
    327      1.5  gdamore 
    328      1.5  gdamore const char *
    329      1.5  gdamore dbau1550_slot_name(int slot)
    330      1.5  gdamore {
    331      1.5  gdamore 	switch (slot) {
    332      1.5  gdamore 	case 0:
    333      1.5  gdamore 		return "bottom slot";
    334      1.5  gdamore 	case 1:
    335      1.5  gdamore 		return "top slot";
    336      1.5  gdamore 	default:
    337      1.5  gdamore 		return "???";
    338      1.5  gdamore 	}
    339      1.5  gdamore }
    340