Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/khorben-n900]: src/sys Added GPIO support to the TPS65950 companion chip...
details: https://anonhg.NetBSD.org/src/rev/276d9518139e
branches: khorben-n900
changeset: 786704:276d9518139e
user: khorben <khorben%NetBSD.org@localhost>
date: Sun May 12 00:42:50 2013 +0000
description:
Added GPIO support to the TPS65950 companion chip. I haven't been able to
test it properly thus far unfortunately.
XXX Implement level-triggered interrupts.
diffstat:
sys/arch/evbarm/conf/N900 | 7 +-
sys/dev/i2c/tps65950.c | 340 +++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/i2c/tps65950reg.h | 51 ++++++-
3 files changed, 391 insertions(+), 7 deletions(-)
diffs (truncated from 486 to 300 lines):
diff -r c8ea6de5fea1 -r 276d9518139e sys/arch/evbarm/conf/N900
--- a/sys/arch/evbarm/conf/N900 Sat May 11 18:22:47 2013 +0000
+++ b/sys/arch/evbarm/conf/N900 Sun May 12 00:42:50 2013 +0000
@@ -1,5 +1,5 @@
#
-# $NetBSD: N900,v 1.13.2.3 2013/05/11 18:22:47 khorben Exp $
+# $NetBSD: N900,v 1.13.2.4 2013/05/12 00:42:50 khorben Exp $
#
# N900 -- Nokia N900 Kernel
#
@@ -248,9 +248,12 @@
# I2C devices
# Power Management and System Companion Device
tps65950pm0 at iic0 addr 0x48
-tps65950pm1 at iic0 addr 0x49 intr 7
+tps65950pm1 at iic0 addr 0x49 intrbase 288 intr 7
tps65950pm2 at iic0 addr 0x4a
tps65950pm3 at iic0 addr 0x4b
+#tps65950pm4 at iic1 addr 0x12
+
+gpio* at tps65950pm1
# SPI devices
omapspi0 at obio0 addr 0x48098000 size 0x1000 intr 65
diff -r c8ea6de5fea1 -r 276d9518139e sys/dev/i2c/tps65950.c
--- a/sys/dev/i2c/tps65950.c Sat May 11 18:22:47 2013 +0000
+++ b/sys/dev/i2c/tps65950.c Sun May 12 00:42:50 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tps65950.c,v 1.3.10.2 2013/05/11 18:22:47 khorben Exp $ */
+/* $NetBSD: tps65950.c,v 1.3.10.3 2013/05/12 00:42:50 khorben Exp $ */
/*-
* Copyright (c) 2012 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -31,7 +31,11 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tps65950.c,v 1.3.10.2 2013/05/11 18:22:47 khorben Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tps65950.c,v 1.3.10.3 2013/05/12 00:42:50 khorben Exp $");
+
+#define _INTR_PRIVATE
+
+#include "gpio.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -45,6 +49,12 @@
#include <dev/i2c/i2cvar.h>
+#if NGPIO > 0
+#include <arm/pic/picvar.h>
+#include <sys/gpio.h>
+#include <dev/gpio/gpiovar.h>
+#endif /* NGPIO > 0 */
+
#include <dev/clock_subr.h>
#include <dev/sysmon/sysmonvar.h>
@@ -68,6 +78,17 @@
struct work sc_work;
bool sc_queued;
+#if NGPIO > 0
+ /* GPIO */
+ struct gpio_chipset_tag sc_gpio;
+ gpio_pin_t sc_gpio_pins[18];
+ struct pic_softc sc_gpio_pic;
+
+#define PIC_TO_SOFTC(pic) \
+ ((struct tps65950_softc *)((char *)(pic) - \
+ offsetof(struct tps65950_softc, sc_gpio_pic)))
+#endif /* NGPIO > 0 */
+
/* WATCHDOG */
struct sysmon_wdog sc_smw;
struct todr_chip_handle sc_todr;
@@ -93,6 +114,31 @@
static void tps65950_pih_attach(struct tps65950_softc *, int);
static void tps65950_pih_intr_work(struct work *, void *);
+#if NGPIO > 0
+static void tps65950_gpio_attach(struct tps65950_softc *, int);
+
+static void tps65950_gpio_intr(struct tps65950_softc *);
+
+static int tps65950_gpio_pin_read(void *, int);
+static void tps65950_gpio_pin_write(void *, int, int);
+static void tps65950_gpio_pin_ctl(void *, int, int);
+
+static void tps65950_gpio_pic_block_irqs(struct pic_softc *, size_t,
+ uint32_t);
+static void tps65950_gpio_pic_unblock_irqs(struct pic_softc *, size_t,
+ uint32_t);
+static int tps65950_gpio_pic_find_pending_irqs(struct pic_softc *);
+static void tps65950_gpio_pic_establish_irq(struct pic_softc *,
+ struct intrsource *);
+
+const struct pic_ops tps65950_gpio_pic_ops = {
+ .pic_block_irqs = tps65950_gpio_pic_block_irqs,
+ .pic_unblock_irqs = tps65950_gpio_pic_unblock_irqs,
+ .pic_find_pending_irqs = tps65950_gpio_pic_find_pending_irqs,
+ .pic_establish_irq = tps65950_gpio_pic_establish_irq
+};
+#endif /* NGPIO > 0 */
+
static void tps65950_rtc_attach(struct tps65950_softc *);
static int tps65950_rtc_enable(struct tps65950_softc *, bool);
static int tps65950_rtc_gettime(todr_chip_handle_t, struct clock_ymdhms *);
@@ -151,8 +197,15 @@
(buf[2] << 16) | (buf[3] << 24);
aprint_normal(": IDCODE %08X", idcode);
- aprint_normal(": PIH\n");
+ aprint_normal(": PIH");
tps65950_pih_attach(sc, ia->ia_intr);
+
+#if NGPIO > 0
+ aprint_normal(", GPIO");
+ tps65950_gpio_attach(sc, ia->ia_intrbase);
+#else
+ aprint_normal("\n");
+#endif /* NGPIO > 0 */
break;
case TPS65950_ADDR_ID3:
aprint_normal(": LED\n");
@@ -312,6 +365,12 @@
tps65950_read_1(sc, TPS65950_PIH_REG_ISR_P1, &u8);
tps65950_write_1(sc, TPS65950_PIH_REG_ISR_P1, u8);
+ /* dispatch the interrupt */
+#if NGPIO > 0
+ if (u8 & TPS65950_PIH_REG_ISR_P1_ISR0)
+ tps65950_gpio_intr(sc);
+#endif /* NGPIO > 0 */
+
iic_release_bus(sc->sc_i2c, 0);
/* allow the workqueue to be entered again */
@@ -365,6 +424,281 @@
intr_enable(sc->sc_intr);
}
+#if NGPIO > 0
+static void
+tps65950_gpio_attach(struct tps65950_softc *sc, int intrbase)
+{
+ struct gpio_chipset_tag * const gp = &sc->sc_gpio;
+ struct gpiobus_attach_args gba;
+ gpio_pin_t *pins;
+ uint32_t mask;
+ int pin;
+
+ /* disable interrupts */
+ iic_acquire_bus(sc->sc_i2c, 0);
+ tps65950_write_1(sc, TPS65950_GPIO_GPIO_IMR1A, 0);
+ tps65950_write_1(sc, TPS65950_GPIO_GPIO_IMR2A, 0);
+ tps65950_write_1(sc, TPS65950_GPIO_GPIO_IMR3A, 0);
+ iic_release_bus(sc->sc_i2c, 0);
+
+ /* map interrupts */
+ if (sc->sc_intr == NULL || intrbase < 0) {
+ aprint_normal("\n");
+ aprint_error_dev(sc->sc_dev, "couldn't map GPIO interrupts\n");
+ return;
+ } else {
+ sc->sc_gpio_pic.pic_ops = &tps65950_gpio_pic_ops;
+ strlcpy(sc->sc_gpio_pic.pic_name, device_xname(sc->sc_dev),
+ sizeof(sc->sc_gpio_pic.pic_name));
+ sc->sc_gpio_pic.pic_maxsources = 18;
+ pic_add(&sc->sc_gpio_pic, intrbase);
+ aprint_normal(": interrupts %d..%d\n", intrbase, intrbase + 17);
+ }
+
+ gp->gp_cookie = sc;
+ gp->gp_pin_read = tps65950_gpio_pin_read;
+ gp->gp_pin_write = tps65950_gpio_pin_write;
+ gp->gp_pin_ctl = tps65950_gpio_pin_ctl;
+
+ gba.gba_gc = gp;
+ gba.gba_pins = sc->sc_gpio_pins;
+ gba.gba_npins = __arraycount(sc->sc_gpio_pins);
+
+ for (pin = 0, mask = 1, pins = sc->sc_gpio_pins;
+ pin < 18; pin++, mask <<= 1, pins++) {
+ pins->pin_num = pin;
+ pins->pin_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+ pins->pin_flags = GPIO_PIN_INPUT;
+ pins->pin_state = GPIO_PIN_HIGH;
+ }
+
+ config_found_ia(sc->sc_dev, "gpiobus", &gba, gpiobus_print);
+}
+
+static void
+tps65950_gpio_intr(struct tps65950_softc *sc)
+{
+ pic_handle_intr(&sc->sc_gpio_pic);
+}
+
+static int
+tps65950_gpio_pin_read(void *v, int pin)
+{
+ struct tps65950_softc *sc = v;
+ uint8_t reg;
+ uint8_t bit;
+ uint8_t val;
+
+ if (pin < 0)
+ return ENODEV;
+ else if (pin < 8)
+ {
+ reg = TPS65950_GPIO_GPIODATAIN1;
+ bit = pin;
+ }
+ else if (pin < 16)
+ {
+ reg = TPS65950_GPIO_GPIODATAIN2;
+ bit = pin - 8;
+ }
+ else if (pin < 18)
+ {
+ reg = TPS65950_GPIO_GPIODATAIN3;
+ bit = pin - 16;
+ }
+ else
+ return ENODEV;
+
+ iic_acquire_bus(sc->sc_i2c, 0);
+ tps65950_read_1(sc, reg, &val);
+ iic_release_bus(sc->sc_i2c, 0);
+
+ return val & (1 << bit);
+}
+
+static void
+tps65950_gpio_pin_write(void *v, int pin, int value)
+{
+ struct tps65950_softc *sc = v;
+ uint8_t reg;
+ uint8_t bit;
+ uint8_t val;
+ uint8_t new;
+
+ if (pin < 0)
+ return;
+ else if (pin < 8)
+ {
+ reg = TPS65950_GPIO_GPIODATAOUT1;
+ bit = pin;
+ }
+ else if (pin < 16)
+ {
+ reg = TPS65950_GPIO_GPIODATAOUT2;
+ bit = pin - 8;
+ }
+ else if (pin < 18)
+ {
+ reg = TPS65950_GPIO_GPIODATAOUT3;
+ bit = pin - 16;
+ }
+ else
+ return;
+
+ iic_acquire_bus(sc->sc_i2c, 0);
+ tps65950_read_1(sc, reg, &val);
+ new = val;
+ if (value)
+ new |= (1 << bit);
+ else
+ new &= ~(1 << bit);
+ if (new != val)
+ tps65950_write_1(sc, reg, new);
+ iic_release_bus(sc->sc_i2c, 0);
+}
+
+static void
+tps65950_gpio_pin_ctl(void *v, int pin, int flags)
+{
+ struct tps65950_softc *sc = v;
+ uint8_t reg;
+ uint8_t bit;
+ uint8_t val;
+ uint8_t new;
+
+ if (pin < 0)
+ return;
+ else if (pin < 8)
+ {
+ reg = TPS65950_GPIO_GPIODATADIR1;
+ bit = pin;
+ }
+ else if (pin < 16)
+ {
+ reg = TPS65950_GPIO_GPIODATADIR2;
+ bit = pin - 8;
+ }
+ else if (pin < 18)
+ {
+ reg = TPS65950_GPIO_GPIODATADIR3;
Home |
Main Index |
Thread Index |
Old Index