Add GPIO driver, and GPIO access functions for other subsystems.

This commit is contained in:
gdamore 2006-02-12 20:49:34 +00:00
parent cbb0e8c88b
commit 1388c544a6
6 changed files with 418 additions and 6 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: DBAU1550,v 1.3 2006/02/09 00:26:39 gdamore Exp $
# $NetBSD: DBAU1550,v 1.4 2006/02/12 20:49:34 gdamore Exp $
#
# Kernel config for the AMD Alchemy DBAu1550 evaluation board.
@ -19,6 +19,9 @@ options PCI_NETBSD_CONFIGURE
aupci* at aubus? addr ?
pci* at aupci?
augpio* at aubus? addr ?
gpio* at augpio?
# Note that this is just fairly random selection of PCI devices.
# Only the hptide controller is actually on-board.

View File

@ -1,4 +1,4 @@
/* $NetBSD: au1550.c,v 1.2 2006/02/09 00:26:40 gdamore Exp $ */
/* $NetBSD: au1550.c,v 1.3 2006/02/12 20:49:34 gdamore Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
@ -97,7 +97,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: au1550.c,v 1.2 2006/02/09 00:26:40 gdamore Exp $");
__KERNEL_RCSID(0, "$NetBSD: au1550.c,v 1.3 2006/02/12 20:49:34 gdamore Exp $");
#include <sys/param.h>
#include <machine/bus.h>
@ -182,14 +182,14 @@ static struct au_dev au1550_devices[] = {
{ "ohci", { AU1550_USBH_BASE, AU1550_USBH_ENABLE,
AU1550_USBH_SIZE }, { 26, -1 }},
{ "aupci", { PCI_BASE }, { -1, -1 }},
{ "augpio", { SYS_BASE, 27 }, { -1, -1 }},
{ "augpio", { GPIO2_BASE, 16 }, { -1, -1 }},
#if 0
{ "usbd", { USBD_BASE }, { 24, 25 }},
{ "aupsc", { PSC0_BASE }, { 10, -1 }},
{ "aupsc", { PSC1_BASE }, { 11, -1 }},
{ "aupsc", { PSC2_BASE }, { 12, -1 }},
{ "aupsc", { PSC3_BASE }, { 13, -1 }},
{ "gpio", { SYS_BASE }, { -1, -1 }},
{ "gpio", { GPIO2_BASE }, { -1, -1 }},
{ "aucrypto", { CRYPTO_BASE }, { 4, -1 }},
#endif
{ NULL }

View File

@ -0,0 +1,294 @@
/* $NetBSD: augpio.c,v 1.1 2006/02/12 20:49:34 gdamore Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: augpio.c,v 1.1 2006/02/12 20:49:34 gdamore Exp $");
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/device.h>
#include <sys/gpio.h>
#include <sys/kernel.h>
#include <dev/gpio/gpiovar.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <mips/alchemy/include/aubusvar.h>
#include <mips/alchemy/include/aureg.h>
#include <mips/alchemy/dev/augpioreg.h>
#include <mips/alchemy/dev/augpiovar.h>
struct augpio_softc {
struct device sc_dev;
struct gpio_chipset_tag sc_gc;
gpio_pin_t sc_pins[AUGPIO_NPINS];
int sc_npins;
int sc_isgpio2;
};
static int augpio_pin_read(void *, int);
static void augpio_pin_write(void *, int, int);
static void augpio_pin_ctl(void *, int, int);
static int augpio_match(struct device *, struct cfdata *, void *);
static void augpio_attach(struct device *, struct device *, void *);
CFATTACH_DECL(augpio, sizeof(struct augpio_softc),
augpio_match, augpio_attach, NULL, NULL);
#define GETREG(x) \
(*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x))
#define PUTREG(x, v) \
((*(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(x)) = (v))
static int augpio_found = 0;
int
augpio_match(struct device *parent, struct cfdata *match, void *aux)
{
struct aubus_attach_args *aa = (struct aubus_attach_args *)aux;
if (strcmp(aa->aa_name, "augpio") != 0)
return 0;
if (augpio_found)
return 0;
return 1;
}
void
augpio_attach(struct device *parent, struct device *self, void *aux)
{
int pin;
struct augpio_softc *sc = (struct augpio_softc *)self;
struct aubus_attach_args *aa = aux;
struct gpiobus_attach_args gba;
sc->sc_npins = 0;
printf(": Alchemy GPIO");
if (aa->aa_addrs[0] == SYS_BASE) {
for (pin = 0; pin < aa->aa_addrs[1]; pin++) {
sc->sc_pins[sc->sc_npins].pin_num = pin;
sc->sc_pins[sc->sc_npins].pin_caps =
GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
GPIO_PIN_TRISTATE;
sc->sc_pins[sc->sc_npins].pin_flags =
au_gpio_ctl(pin, 0);
sc->sc_pins[sc->sc_npins].pin_state =
au_gpio_read(pin);
sc->sc_npins++;
}
sc->sc_isgpio2 = 0;
printf(", primary block");
} else if (aa->aa_addrs[0] == GPIO2_BASE) {
/* initialize GPIO2 block */
uint32_t val;
val = AUGPIO_GPIO2_ENABLE_MR | AUGPIO_GPIO2_ENABLE_CE;
PUTREG(GPIO2_BASE + AUGPIO_GPIO2_ENABLE, val);
delay(10);
val &= ~AUGPIO_GPIO2_ENABLE_MR;
PUTREG(GPIO2_BASE + AUGPIO_GPIO2_ENABLE, val);
for (pin = 0; pin < aa->aa_addrs[1]; pin++) {
sc->sc_pins[sc->sc_npins].pin_num = pin;
sc->sc_pins[sc->sc_npins].pin_caps =
GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
sc->sc_pins[sc->sc_npins].pin_flags =
au_gpio2_ctl(pin, 0);
sc->sc_pins[sc->sc_npins].pin_state =
au_gpio2_read(pin);
sc->sc_npins++;
}
printf(", secondary block");
sc->sc_isgpio2 = 1;
} else {
printf(", unidentified block");
}
printf("\n");
sc->sc_gc.gp_cookie = sc;
sc->sc_gc.gp_pin_read = augpio_pin_read;
sc->sc_gc.gp_pin_write = augpio_pin_write;
sc->sc_gc.gp_pin_ctl = augpio_pin_ctl;
gba.gba_gc = &sc->sc_gc;
gba.gba_pins = sc->sc_pins;
gba.gba_npins = sc->sc_npins;
config_found_ia(&sc->sc_dev, "gpiobus", &gba, gpiobus_print);
}
int
augpio_pin_read(void *arg, int pin)
{
struct augpio_softc *sc = arg;
return (sc->sc_isgpio2 ? au_gpio2_read(pin) : au_gpio_read(pin));
}
void
augpio_pin_write(void *arg, int pin, int value)
{
struct augpio_softc *sc = arg;
if (sc->sc_isgpio2)
au_gpio2_write(pin, value);
else
au_gpio_write(pin, value);
}
void
augpio_pin_ctl(void *arg, int pin, int flags)
{
struct augpio_softc *sc = arg;
if (sc->sc_isgpio2)
(void) au_gpio2_ctl(pin, flags);
else
(void) au_gpio_ctl(pin, flags);
}
int
au_gpio_read(int pin)
{
pin = 1 << pin;
return ((GETREG(SYS_BASE + AUGPIO_SYS_PINSTATERD) & pin) ?
GPIO_PIN_HIGH : GPIO_PIN_LOW);
}
void
au_gpio_write(int pin, int value)
{
pin = 1 << pin;
if (value) {
PUTREG(SYS_BASE + AUGPIO_SYS_OUTPUTSET, pin);
} else {
PUTREG(SYS_BASE + AUGPIO_SYS_OUTPUTCLR, pin);
}
}
int
au_gpio_ctl(int pin, int flags)
{
uint32_t tri, out;
int old;
old = 0;
pin = 1 << pin;
tri = GETREG(SYS_BASE + AUGPIO_SYS_TRIOUTRD);
out = GETREG(SYS_BASE + AUGPIO_SYS_OUTPUTRD);
old = 0;
if (tri & pin) {
old |= GPIO_PIN_INPUT;
} else {
old |= GPIO_PIN_OUTPUT;
}
if (flags & (GPIO_PIN_TRISTATE|GPIO_PIN_INPUT)) {
PUTREG(SYS_BASE + AUGPIO_SYS_TRIOUTCLR, pin);
} else if (flags & GPIO_PIN_OUTPUT) {
if (pin & out) {
PUTREG(SYS_BASE + AUGPIO_SYS_OUTPUTSET, pin);
} else {
PUTREG(SYS_BASE + AUGPIO_SYS_OUTPUTCLR, pin);
}
}
return old;
}
int
au_gpio2_read(int pin)
{
pin = 1 << pin;
return ((GETREG(GPIO2_BASE + AUGPIO_GPIO2_PINSTATE) & pin) ?
GPIO_PIN_HIGH : GPIO_PIN_LOW);
}
void
au_gpio2_write(int pin, int value)
{
pin = 1 << pin;
if (value) {
PUTREG(GPIO2_BASE + AUGPIO_GPIO2_OUTPUT, (pin | (pin << 16)));
} else {
PUTREG(GPIO2_BASE + AUGPIO_GPIO2_OUTPUT, (pin << 16));
}
}
int
au_gpio2_ctl(int pin, int flags)
{
uint32_t dir;
int old;
pin = 1 << pin;
dir = GETREG(GPIO2_BASE + AUGPIO_GPIO2_DIR);
old = dir;
if (dir & pin) {
old |= GPIO_PIN_OUTPUT;
} else {
old |= GPIO_PIN_INPUT;
}
if (flags & GPIO_PIN_INPUT) {
dir |= pin;
PUTREG(GPIO2_BASE + AUGPIO_GPIO2_DIR, pin);
} else if (flags & GPIO_PIN_OUTPUT) {
dir &= ~pin;
PUTREG(GPIO2_BASE + AUGPIO_GPIO2_DIR, pin);
}
return old;
}

View File

@ -0,0 +1,58 @@
/* $NetBSD: augpioreg.h,v 1.1 2006/02/12 20:49:34 gdamore Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MIPS_ALCHEMY_DEV_AUGPIOREG_H
#define _MIPS_ALCHEMY_DEV_AUGPIOREG_H
#define AUGPIO_NPINS 64
/* SYS_GPIO registers -- offset from SYS_BASE */
#define AUGPIO_SYS_TRIOUTRD 0x100
#define AUGPIO_SYS_TRIOUTCLR 0x100
#define AUGPIO_SYS_OUTPUTRD 0x108
#define AUGPIO_SYS_OUTPUTSET 0x108
#define AUGPIO_SYS_OUTPUTCLR 0x10C
#define AUGPIO_SYS_PINSTATERD 0x110
#define AUGPIO_SYS_PININPUTEN 0x110
/* GPIO2 registers -- offset from GPIO2_BASE */
#define AUGPIO_GPIO2_DIR 0x00
#define AUGPIO_GPIO2_OUTPUT 0x08
#define AUGPIO_GPIO2_PINSTATE 0x0C
#define AUGPIO_GPIO2_INTEN 0x10
#define AUGPIO_GPIO2_ENABLE 0x14
#define AUGPIO_GPIO2_ENABLE_CE 0x1
#define AUGPIO_GPIO2_ENABLE_MR 0x2
#endif /* _MIPS_ALCHEMY_DEV_AUPCIREG_H */

View File

@ -0,0 +1,52 @@
/* $NetBSD: augpiovar.h,v 1.1 2006/02/12 20:49:34 gdamore Exp $ */
/*-
* Copyright (c) 2006 Itronix Inc.
* All rights reserved.
*
* Written by Garrett D'Amore for Itronix Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of Itronix Inc. may not be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _MIPS_ALCHEMY_DEV_AUGPIOVAR_H
#define _MIPS_ALCHEMY_DEV_AUGPIOVAR_H
#include <sys/gpio.h>
/*
* We export these interfaces so that other subsystems can access GPIOs
* without going thru the GPIO device driver.
*/
int au_gpio_read(int);
void au_gpio_write(int, int);
int au_gpio_ctl(int, int);
int au_gpio2_read(int);
void au_gpio2_write(int, int);
int au_gpio2_ctl(int, int);
#endif /* _MIPS_ALCHEMY_DEV_AUPCIVAR_H */

View File

@ -1,4 +1,4 @@
# $NetBSD: files.alchemy,v 1.6 2006/02/09 00:26:40 gdamore Exp $
# $NetBSD: files.alchemy,v 1.7 2006/02/12 20:49:34 gdamore Exp $
defflag opt_alchemy.h ALCHEMY_AU1000
ALCHEMY_AU1100
@ -52,3 +52,8 @@ file arch/mips/alchemy/dev/auaudio.c auaudio
device aupci: pcibus
attach aupci at aubus
file arch/mips/alchemy/dev/aupci.c aupci
# On-chip GPIO
device augpio: gpiobus
attach augpio at aubus
file arch/mips/alchemy/dev/augpio.c augpio