tcu.c revision 1.1
11.1Schristos/* $NetBSD: tcu.c,v 1.1 2016/08/11 09:05:42 christos Exp $ */
21.1Schristos
31.1Schristos/*-
41.1Schristos * Copyright (c) 2016, Felix Deichmann
51.1Schristos * All rights reserved.
61.1Schristos *
71.1Schristos * Redistribution and use in source and binary forms, with or without
81.1Schristos * modification, are permitted provided that the following conditions
91.1Schristos * are met:
101.1Schristos * 1. Redistributions of source code must retain the above copyright
111.1Schristos *    notice, this list of conditions and the following disclaimer.
121.1Schristos * 2. Redistributions in binary form must reproduce the above copyright
131.1Schristos *    notice, this list of conditions and the following disclaimer in the
141.1Schristos *    documentation and/or other materials provided with the distribution.
151.1Schristos *
161.1Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171.1Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
181.1Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191.1Schristos * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
201.1Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211.1Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221.1Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
231.1Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
241.1Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
251.1Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
261.1Schristos * POSSIBILITY OF SUCH DAMAGE.
271.1Schristos */
281.1Schristos
291.1Schristos/*
301.1Schristos * flxd TC-USB - TURBOchannel USB host option
311.1Schristos */
321.1Schristos
331.1Schristos#include <sys/cdefs.h>
341.1Schristos__KERNEL_RCSID(0, "$NetBSD: tcu.c,v 1.1 2016/08/11 09:05:42 christos Exp $");
351.1Schristos
361.1Schristos#include <sys/param.h>
371.1Schristos#include <sys/systm.h>
381.1Schristos#include <sys/device.h>
391.1Schristos#include <sys/gpio.h>
401.1Schristos
411.1Schristos#include <sys/bus.h>
421.1Schristos
431.1Schristos#include <dev/tc/tcvar.h>
441.1Schristos
451.1Schristos#include <dev/gpio/gpiovar.h>
461.1Schristos
471.1Schristos#include "gpio.h"
481.1Schristos#include "slhci_tcu.h"
491.1Schristos
501.1Schristos#define TCU_GPIO_NPINS	8
511.1Schristos#define TCU_GPIO_OFFS	0x80
521.1Schristos#define TCU_GPIO_SIZE	(3 * 4)
531.1Schristos#define TCU_GPIO_DIR	0x0
541.1Schristos#define TCU_GPIO_IN	0x4
551.1Schristos#define TCU_GPIO_OUT	0x8
561.1Schristos
571.1Schristosstruct tcu_softc {
581.1Schristos#if NGPIO > 0
591.1Schristos	kmutex_t		sc_gpio_mtx;
601.1Schristos	struct gpio_chipset_tag	sc_gpio_gc;
611.1Schristos	gpio_pin_t		sc_gpio_pins[TCU_GPIO_NPINS];
621.1Schristos	bus_space_tag_t		sc_gpio_iot;
631.1Schristos	bus_space_handle_t	sc_gpio_ioh;
641.1Schristos#endif /* NGPIO > 0 */
651.1Schristos};
661.1Schristos
671.1Schristosstatic int  tcu_match(device_t, cfdata_t, void *);
681.1Schristosstatic void tcu_attach(device_t, device_t, void *);
691.1Schristos
701.1Schristos#if NSLHCI_TCU > 0
711.1Schristosstatic int  tcu_print(void *, const char *);
721.1Schristos#endif /* NSLHCI_TCU > 0 */
731.1Schristos#if NGPIO > 0
741.1Schristosstatic void tcu_gpio_attach(device_t, device_t, void *);
751.1Schristosstatic int  tcu_gpio_read(void *, int);
761.1Schristosstatic void tcu_gpio_write(void *, int, int);
771.1Schristosstatic void tcu_gpio_ctl(void *, int, int);
781.1Schristos#endif /* NGPIO > 0 */
791.1Schristos
801.1SchristosCFATTACH_DECL_NEW(tcu, sizeof(struct tcu_softc),
811.1Schristos    tcu_match, tcu_attach, NULL, NULL);
821.1Schristos
831.1Schristosstatic int
841.1Schristostcu_match(device_t parent, cfdata_t cf, void *aux)
851.1Schristos{
861.1Schristos	struct tc_attach_args *ta = aux;
871.1Schristos
881.1Schristos	if (strncmp("TC-USB  ", ta->ta_modname, TC_ROM_LLEN))
891.1Schristos		return 0;
901.1Schristos
911.1Schristos	return 1;
921.1Schristos}
931.1Schristos
941.1Schristosstatic void
951.1Schristostcu_attach(device_t parent, device_t self, void *aux)
961.1Schristos{
971.1Schristos
981.1Schristos	printf(": TC-USB\n");
991.1Schristos#if NSLHCI_TCU > 0
1001.1Schristos	/* Attach slhci. */
1011.1Schristos	(void)config_found_ia(self, "tcu", aux, tcu_print);
1021.1Schristos#endif /* NSLHCI_TCU > 0 */
1031.1Schristos#if NGPIO > 0
1041.1Schristos	/* Attach gpio(bus). */
1051.1Schristos	tcu_gpio_attach(parent, self, aux);
1061.1Schristos#endif /* NGPIO > 0 */
1071.1Schristos}
1081.1Schristos
1091.1Schristos#if NSLHCI_TCU > 0
1101.1Schristosstatic int
1111.1Schristostcu_print(void *aux, const char *pnp)
1121.1Schristos{
1131.1Schristos
1141.1Schristos	/* This function is only used for "slhci at tcu". */
1151.1Schristos	if (pnp)
1161.1Schristos		aprint_normal("slhci at %s", pnp);
1171.1Schristos
1181.1Schristos	return UNCONF;
1191.1Schristos}
1201.1Schristos#endif /* NSLHCI_TCU > 0 */
1211.1Schristos
1221.1Schristos#if NGPIO > 0
1231.1Schristosstatic void
1241.1Schristostcu_gpio_attach(device_t parent, device_t self, void *aux)
1251.1Schristos{
1261.1Schristos	struct tcu_softc *sc = device_private(self);
1271.1Schristos	struct tc_attach_args *ta = aux;
1281.1Schristos	struct gpiobus_attach_args gba;
1291.1Schristos	bus_space_tag_t iot = ta->ta_memt;
1301.1Schristos	uint32_t v;
1311.1Schristos	int error;
1321.1Schristos
1331.1Schristos	sc->sc_gpio_iot = iot;
1341.1Schristos
1351.1Schristos	error = bus_space_map(iot, ta->ta_addr + TCU_GPIO_OFFS, TCU_GPIO_SIZE,
1361.1Schristos	    0, &sc->sc_gpio_ioh);
1371.1Schristos	if (error) {
1381.1Schristos		aprint_error_dev(self, "bus_space_map() failed (%d)\n", error);
1391.1Schristos		return;
1401.1Schristos	}
1411.1Schristos
1421.1Schristos	mutex_init(&sc->sc_gpio_mtx, MUTEX_DEFAULT, IPL_NONE);
1431.1Schristos
1441.1Schristos	v = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, TCU_GPIO_DIR);
1451.1Schristos
1461.1Schristos	for (int pin = 0; pin < TCU_GPIO_NPINS; pin++) {
1471.1Schristos		sc->sc_gpio_pins[pin].pin_num = pin;
1481.1Schristos		sc->sc_gpio_pins[pin].pin_caps = GPIO_PIN_INPUT |
1491.1Schristos		    GPIO_PIN_OUTPUT;
1501.1Schristos		sc->sc_gpio_pins[pin].pin_flags = (v & (UINT32_C(1) << pin)) ?
1511.1Schristos		    GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
1521.1Schristos		sc->sc_gpio_pins[pin].pin_state = tcu_gpio_read(sc, pin);
1531.1Schristos	}
1541.1Schristos
1551.1Schristos	sc->sc_gpio_gc.gp_cookie = sc;
1561.1Schristos	sc->sc_gpio_gc.gp_pin_read = tcu_gpio_read;
1571.1Schristos	sc->sc_gpio_gc.gp_pin_write = tcu_gpio_write;
1581.1Schristos	sc->sc_gpio_gc.gp_pin_ctl = tcu_gpio_ctl;
1591.1Schristos
1601.1Schristos	memset(&gba, 0, sizeof(gba));
1611.1Schristos
1621.1Schristos	gba.gba_gc = &sc->sc_gpio_gc;
1631.1Schristos	gba.gba_pins = sc->sc_gpio_pins;
1641.1Schristos	gba.gba_npins = TCU_GPIO_NPINS;
1651.1Schristos
1661.1Schristos	(void)config_found_ia(self, "gpiobus", &gba, gpiobus_print);
1671.1Schristos}
1681.1Schristos
1691.1Schristosstatic int
1701.1Schristostcu_gpio_read(void *arg, int pin)
1711.1Schristos{
1721.1Schristos	struct tcu_softc *sc = arg;
1731.1Schristos	uint32_t v;
1741.1Schristos
1751.1Schristos	mutex_enter(&sc->sc_gpio_mtx);
1761.1Schristos	v = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, TCU_GPIO_IN);
1771.1Schristos	mutex_exit(&sc->sc_gpio_mtx);
1781.1Schristos
1791.1Schristos	return (v & (UINT32_C(1) << pin)) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
1801.1Schristos}
1811.1Schristos
1821.1Schristosstatic void
1831.1Schristostcu_gpio_write(void *arg, int pin, int val)
1841.1Schristos{
1851.1Schristos	struct tcu_softc *sc = arg;
1861.1Schristos	uint32_t v;
1871.1Schristos
1881.1Schristos	mutex_enter(&sc->sc_gpio_mtx);
1891.1Schristos
1901.1Schristos	v = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, TCU_GPIO_OUT);
1911.1Schristos
1921.1Schristos	if (val == GPIO_PIN_LOW)
1931.1Schristos		v &= ~(UINT32_C(1) << pin);
1941.1Schristos	else if (val == GPIO_PIN_HIGH)
1951.1Schristos		v |= (UINT32_C(1) << pin);
1961.1Schristos
1971.1Schristos	bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, TCU_GPIO_OUT, v);
1981.1Schristos
1991.1Schristos	mutex_exit(&sc->sc_gpio_mtx);
2001.1Schristos}
2011.1Schristos
2021.1Schristosstatic void
2031.1Schristostcu_gpio_ctl(void *arg, int pin, int flags)
2041.1Schristos{
2051.1Schristos	struct tcu_softc *sc = arg;
2061.1Schristos	uint32_t v;
2071.1Schristos
2081.1Schristos	mutex_enter(&sc->sc_gpio_mtx);
2091.1Schristos
2101.1Schristos	v = bus_space_read_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, TCU_GPIO_DIR);
2111.1Schristos
2121.1Schristos	if (flags & GPIO_PIN_INPUT)
2131.1Schristos		v &= ~(UINT32_C(1) << pin);
2141.1Schristos	if (flags & GPIO_PIN_OUTPUT)
2151.1Schristos		v |= (UINT32_C(1) << pin);
2161.1Schristos
2171.1Schristos	bus_space_write_4(sc->sc_gpio_iot, sc->sc_gpio_ioh, TCU_GPIO_DIR, v);
2181.1Schristos
2191.1Schristos	mutex_exit(&sc->sc_gpio_mtx);
2201.1Schristos}
2211.1Schristos#endif /* NGPIO > 0 */
222