Module Name: src Committed By: kardel Date: Sun Apr 6 17:59:39 UTC 2014
Modified Files: src/distrib/sets/lists/man: mi src/doc: CHANGES src/share/man/man4: Makefile src/sys/arch/evbarm/conf: RPI src/sys/dev/spi: files.spi Added Files: src/share/man/man4: mcp23s17gpio.4 src/sys/dev/spi: mcp23s17.c mcp23s17.h Log Message: add Microchip MCP23S17 GPIO driver (via SPI interface) To generate a diff of this commit: cvs rdiff -u -r1.1467 -r1.1468 src/distrib/sets/lists/man/mi cvs rdiff -u -r1.1910 -r1.1911 src/doc/CHANGES cvs rdiff -u -r1.611 -r1.612 src/share/man/man4/Makefile cvs rdiff -u -r0 -r1.1 src/share/man/man4/mcp23s17gpio.4 cvs rdiff -u -r1.42 -r1.43 src/sys/arch/evbarm/conf/RPI cvs rdiff -u -r1.3 -r1.4 src/sys/dev/spi/files.spi cvs rdiff -u -r0 -r1.1 src/sys/dev/spi/mcp23s17.c src/sys/dev/spi/mcp23s17.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/man/mi diff -u src/distrib/sets/lists/man/mi:1.1467 src/distrib/sets/lists/man/mi:1.1468 --- src/distrib/sets/lists/man/mi:1.1467 Tue Apr 1 21:40:46 2014 +++ src/distrib/sets/lists/man/mi Sun Apr 6 17:59:39 2014 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1467 2014/04/01 21:40:46 christos Exp $ +# $NetBSD: mi,v 1.1468 2014/04/06 17:59:39 kardel Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -1391,6 +1391,7 @@ ./usr/share/man/cat4/mlx.0 man-sys-catman .cat ./usr/share/man/cat4/mly.0 man-sys-catman .cat ./usr/share/man/cat4/module.0 man-obsolete obsolete +./usr/share/man/cat4/mcp23s17gpio.0 man-sys-catman .cat ./usr/share/man/cat4/mpii.0 man-sys-catman .cat ./usr/share/man/cat4/mpl115a.0 man-sys-catman .cat ./usr/share/man/cat4/mpls.0 man-sys-catman .cat @@ -4387,6 +4388,7 @@ ./usr/share/man/html4/mlx.html man-sys-htmlman html ./usr/share/man/html4/mly.html man-sys-htmlman html ./usr/share/man/html4/module.html man-obsolete obsolete +./usr/share/man/html4/mcp23s17gpio.html man-sys-htmlman html ./usr/share/man/html4/mpii.html man-sys-htmlman html ./usr/share/man/html4/mpl115a.html man-sys-htmlman html ./usr/share/man/html4/mpls.html man-sys-htmlman html @@ -7231,6 +7233,7 @@ ./usr/share/man/man4/mlx.4 man-sys-man .man ./usr/share/man/man4/mly.4 man-sys-man .man ./usr/share/man/man4/module.4 man-obsolete obsolete +./usr/share/man/man4/mcp23s17gpio.4 man-sys-man .man ./usr/share/man/man4/mpii.4 man-sys-man .man ./usr/share/man/man4/mpl115a.4 man-sys-man .man ./usr/share/man/man4/mpls.4 man-sys-man .man Index: src/doc/CHANGES diff -u src/doc/CHANGES:1.1910 src/doc/CHANGES:1.1911 --- src/doc/CHANGES:1.1910 Sat Apr 5 02:25:44 2014 +++ src/doc/CHANGES Sun Apr 6 17:59:39 2014 @@ -1,4 +1,4 @@ -# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1910 $> +# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.1911 $> # # # [Note: This file does not mention every change made to the NetBSD source tree. @@ -382,3 +382,5 @@ Changes from NetBSD 6.0 to NetBSD 7.0: ptyfs: Allow multiple mounts and support proper device visibility in chroots (Ilya Zykov) [christos 20140404] i386: Switched to GCC 4.8. [christos 20140404] + mcp23s17gpio: Add Microchip MCP23S17 16-bit GPIO chip driver. + e.g. Rasberry Pi interface boards [kardel 20140406] \ No newline at end of file Index: src/share/man/man4/Makefile diff -u src/share/man/man4/Makefile:1.611 src/share/man/man4/Makefile:1.612 --- src/share/man/man4/Makefile:1.611 Wed Mar 19 15:26:41 2014 +++ src/share/man/man4/Makefile Sun Apr 6 17:59:39 2014 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.611 2014/03/19 15:26:41 nonaka Exp $ +# $NetBSD: Makefile,v 1.612 2014/04/06 17:59:39 kardel Exp $ # @(#)Makefile 8.1 (Berkeley) 6/18/93 MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \ @@ -37,7 +37,8 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 a jme.4 jmide.4 joy.4 \ kloader.4 kse.4 ksyms.4 kttcp.4 \ lc.4 ld.4 lii.4 lo.4 lua.4 lxtphy.4 \ - mainbus.4 makphy.4 malo.4 mbe.4 mca.4 mcclock.4 md.4 mfb.4 mfi.4 mhzc.4 \ + mainbus.4 makphy.4 malo.4 mbe.4 mca.4 mcclock.4 mcp23s17gpio.4 md.4 mfb.4 \ + mfi.4 mhzc.4 \ micphy.4 midi.4 mii.4 mk48txx.4 mlx.4 mly.4 mpls.4 mpii.4 mpt.4 mpu.4 mtd.4 \ mtio.4 msm6242b.4 multicast.4 mvsata.4 \ nadb.4 ne.4 neo.4 netintro.4 nfe.4 nfsmb.4 njata.4 njs.4 \ Index: src/sys/arch/evbarm/conf/RPI diff -u src/sys/arch/evbarm/conf/RPI:1.42 src/sys/arch/evbarm/conf/RPI:1.43 --- src/sys/arch/evbarm/conf/RPI:1.42 Fri Jan 31 08:18:03 2014 +++ src/sys/arch/evbarm/conf/RPI Sun Apr 6 17:59:39 2014 @@ -1,5 +1,5 @@ # -# $NetBSD: RPI,v 1.42 2014/01/31 08:18:03 skrll Exp $ +# $NetBSD: RPI,v 1.43 2014/04/06 17:59:39 kardel Exp $ # # RPi -- Raspberry Pi # @@ -225,6 +225,15 @@ iic* at i2cbus? bcmspi* at obio? spi* at spibus? +# PIFace or other boards using that chip (needs gpio) +#mcp23s17gpio0 at spi? slave 0 flags 0 +#mcp23s17gpio1 at spi? slave 0 flags 1 +#mcp23s17gpio2 at spi? slave 0 flags 2 +#mcp23s17gpio3 at spi? slave 0 flags 3 + +# gpio support (e. g. mcp23s17gpio) +#gpio* at gpiobus? + # various options for wscons - we try to look as much like a standard # sun console as possible options WSEMUL_VT100 # sun terminal emulation Index: src/sys/dev/spi/files.spi diff -u src/sys/dev/spi/files.spi:1.3 src/sys/dev/spi/files.spi:1.4 --- src/sys/dev/spi/files.spi:1.3 Tue Feb 25 20:09:37 2014 +++ src/sys/dev/spi/files.spi Sun Apr 6 17:59:39 2014 @@ -1,4 +1,4 @@ -# $NetBSD: files.spi,v 1.3 2014/02/25 20:09:37 rkujawa Exp $ +# $NetBSD: files.spi,v 1.4 2014/04/06 17:59:39 kardel Exp $ define spibus { } @@ -31,3 +31,7 @@ device mcp48x1dac attach mcp48x1dac at spi file dev/spi/mcp48x1.c mcp48x1dac +# MCP23S17 16-bit GPIO +device mcp23s17gpio: gpiobus +attach mcp23s17gpio at spi +file dev/spi/mcp23s17.c mcp23s17gpio Added files: Index: src/share/man/man4/mcp23s17gpio.4 diff -u /dev/null src/share/man/man4/mcp23s17gpio.4:1.1 --- /dev/null Sun Apr 6 17:59:39 2014 +++ src/share/man/man4/mcp23s17gpio.4 Sun Apr 6 17:59:39 2014 @@ -0,0 +1,61 @@ +.\" $NetBSD: mcp23s17gpio.4,v 1.1 2014/04/06 17:59:39 kardel Exp $ +.\" +.\"Copyright (c) 2014 Frank Kardel +.\"All rights reserved. +.\" +.\"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. +.\" +.\"THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS +.\"``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 THE FOUNDATION OR CONTRIBUTORS +.\"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. +.\" +.Dd April 6th, 2014 +.Dt MCP23S17GPIO 4 +.Os +.Sh NAME +.Nm mcp23s17gpio +.Nd Driver for MCP23S17 gpio chip via SPI bus +.Sh SYNOPSIS +.Cd "mcp23s17gpio0 at spi? slave 0 flags 0" +.Cd "mcp23s17gpio1 at spi? slave 0 flags 1" +.Cd "mcp23s17gpio2 at spi? slave 0 flags 2" +.Cd "mcp23s17gpio3 at spi? slave 0 flags 3" +.Cd "gpio* at gpiobus?" +.Sh DESCRIPTION +The +.Nm +driver supports up to 8 instances of the MCP23S17 16-bit GPIO chips. Access to +the pins is provided by the +.Xr gpio 4 +interface. The +.Nm flags argument selects the hardware address of the chip instance. +.Sh SEE ALSO +.Xr spi 4 , +.Xr intro 4 , +.Xr gpio 4 +.Sh HISTORY +The +.Nm +driver first appeared in +.Nx 7.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Frank Kardel Aq Mt kar...@netbsd.org . Index: src/sys/dev/spi/mcp23s17.c diff -u /dev/null src/sys/dev/spi/mcp23s17.c:1.1 --- /dev/null Sun Apr 6 17:59:39 2014 +++ src/sys/dev/spi/mcp23s17.c Sun Apr 6 17:59:39 2014 @@ -0,0 +1,301 @@ +/* $NetBSD: mcp23s17.c,v 1.1 2014/04/06 17:59:39 kardel Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank Kardel. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 THE FOUNDATION OR CONTRIBUTORS + * 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: mcp23s17.c,v 1.1 2014/04/06 17:59:39 kardel Exp $"); + +/* + * Driver for Microchip MCP23S17 GPIO + * + * see: http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf + */ + +#include "gpio.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/types.h> +#include <sys/gpio.h> +#include <sys/sysctl.h> + +#include <dev/gpio/gpiovar.h> + +#include <dev/spi/spivar.h> + +#include <dev/spi/mcp23s17.h> + +/* #define MCP23S17_DEBUG */ +#ifdef MCP23S17_DEBUG +int mcp23S17debug = 3; +#define DPRINTF(l, x) do { if (l <= mcp23S17debug) { printf x; } } while (0) +#else +#define DPRINTF(l, x) +#endif + +struct mcp23s17gpio_softc { + device_t sc_dev; + struct spi_handle *sc_sh; + uint8_t sc_ha; /* hardware address */ + uint8_t sc_bank; /* addressing scheme */ + struct gpio_chipset_tag sc_gpio_gc; + gpio_pin_t sc_gpio_pins[MCP23x17_GPIO_NPINS]; +}; + +static int mcp23s17gpio_match(device_t, cfdata_t, void *); +static void mcp23s17gpio_attach(device_t, device_t, void *); + +static void mcp23s17gpio_write(struct mcp23s17gpio_softc *, uint8_t, uint8_t); + +#if NGPIO > 0 +static uint8_t mcp23s17gpio_read(struct mcp23s17gpio_softc *, uint8_t); + +static int mcp23s17gpio_gpio_pin_read(void *, int); +static void mcp23s17gpio_gpio_pin_write(void *, int, int); +static void mcp23s17gpio_gpio_pin_ctl(void *, int, int); +#endif + +CFATTACH_DECL_NEW(mcp23s17gpio, sizeof(struct mcp23s17gpio_softc), + mcp23s17gpio_match, mcp23s17gpio_attach, NULL, NULL); + +static int +mcp23s17gpio_match(device_t parent, cfdata_t cf, void *aux) +{ + struct spi_attach_args *sa = aux; + + /* MCP23S17 has no way to detect it! */ + + /* run at 10MHz */ + if (spi_configure(sa->sa_handle, SPI_MODE_0, 10000000)) + return 0; + + return 1; +} + +static void +mcp23s17gpio_attach(device_t parent, device_t self, void *aux) +{ + struct mcp23s17gpio_softc *sc; + struct spi_attach_args *sa; +#if NGPIO > 0 + int i; + struct gpiobus_attach_args gba; +#endif + + sa = aux; + sc = device_private(self); + sc->sc_dev = self; + sc->sc_sh = sa->sa_handle; + sc->sc_bank = 0; + sc->sc_ha = device_cfdata(sc->sc_dev)->cf_flags & 0x7; + + aprint_naive(": GPIO\n"); + aprint_normal(": MCP23S17 GPIO (ha=%d)\n", sc->sc_ha); + + DPRINTF(1, ("%s: initialize (HAEN|SEQOP)\n", device_xname(sc->sc_dev))); + + /* basic setup */ + mcp23s17gpio_write(sc, MCP23x17_IOCONA(sc->sc_bank), MCP23x17_IOCON_HAEN|MCP23x17_IOCON_SEQOP); + +#if NGPIO > 0 + for (i = 0; i < MCP23x17_GPIO_NPINS; i++) { + sc->sc_gpio_pins[i].pin_num = i; + sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT | + GPIO_PIN_OUTPUT | + GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE | + GPIO_PIN_PULLUP | + GPIO_PIN_INVIN; + + /* read initial state */ + sc->sc_gpio_pins[i].pin_state = + mcp23s17gpio_gpio_pin_read(sc, i); + } + + /* create controller tag */ + sc->sc_gpio_gc.gp_cookie = sc; + sc->sc_gpio_gc.gp_pin_read = mcp23s17gpio_gpio_pin_read; + sc->sc_gpio_gc.gp_pin_write = mcp23s17gpio_gpio_pin_write; + sc->sc_gpio_gc.gp_pin_ctl = mcp23s17gpio_gpio_pin_ctl; + + gba.gba_gc = &sc->sc_gpio_gc; + gba.gba_pins = sc->sc_gpio_pins; + gba.gba_npins = MCP23x17_GPIO_NPINS; + + config_found_ia(self, "gpiobus", &gba, gpiobus_print); +#else + aprint_normal_dev(sc->sc_dev, "no GPIO configured in kernel"); +#endif +} + +#if NGPIO > 0 +static uint8_t +mcp23s17gpio_read(struct mcp23s17gpio_softc *sc, uint8_t addr) +{ + uint8_t buf[2]; + uint8_t val = 0; + int rc; + + buf[0] = MCP23x17_OP_READ(sc->sc_ha); + buf[1] = addr; + + rc = spi_send_recv(sc->sc_sh, 2, buf, 1, &val); + if (rc != 0) + { + aprint_normal_dev(sc->sc_dev, "SPI send_recv failed rc=%d\n", rc); + } + + DPRINTF(3, ("%s: read(0x%02x) @0x%02x->0x%02x\n", device_xname(sc->sc_dev), buf[0], addr, val)); + return val; +} +#endif + +static void +mcp23s17gpio_write(struct mcp23s17gpio_softc *sc, uint8_t addr, uint8_t val) +{ + uint8_t buf[3]; + int rc; + + buf[0] = MCP23x17_OP_WRITE(sc->sc_ha); + buf[1] = addr; + buf[2] = val; + + rc = spi_send(sc->sc_sh, 3, buf); + if (rc != 0) + { + aprint_normal_dev(sc->sc_dev, "SPI send failed rc=%d\n", rc); + } + DPRINTF(3, ("%s: write(0x%02x) @0x%02x<-0x%02x\n", device_xname(sc->sc_dev), buf[0], addr, val)); +} + +#if NGPIO > 0 +/* GPIO support functions */ +static int +mcp23s17gpio_gpio_pin_read(void *arg, int pin) +{ + struct mcp23s17gpio_softc *sc = arg; + int epin = pin & MCP23x17_GPIO_NPINS_MASK; + uint8_t data; + uint8_t addr; + int val; + + if (epin < 8) { + addr = MCP23x17_GPIOA(sc->sc_bank); + } else { + addr = MCP23x17_GPIOB(sc->sc_bank); + epin = pin - 8; + } + + data = mcp23s17gpio_read(sc, addr); + + val = data & (1 << epin) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; + + DPRINTF(2, ("%s: gpio_read pin %d->%d\n", device_xname(sc->sc_dev), pin, (val == GPIO_PIN_HIGH))); + + return val; +} + +static void +mcp23s17gpio_gpio_pin_write(void *arg, int pin, int value) +{ + struct mcp23s17gpio_softc *sc = arg; + int epin = pin & MCP23x17_GPIO_NPINS_MASK; + uint8_t data; + uint8_t addr; + + if (epin < 8) { + addr = MCP23x17_OLATA(sc->sc_bank); + } else { + addr = MCP23x17_OLATB(sc->sc_bank); + epin = pin - 8; + } + + data = mcp23s17gpio_read(sc, addr); + + if (value == GPIO_PIN_HIGH) { + data |= 1 << epin; + } else { + data &= ~(1 << epin); + } + + mcp23s17gpio_write(sc, addr, data); + + DPRINTF(2, ("%s: gpio_write pin %d<-%d\n", device_xname(sc->sc_dev), pin, (value == GPIO_PIN_HIGH))); +} + +static void +mcp23s17gpio_gpio_pin_ctl(void *arg, int pin, int flags) +{ + struct mcp23s17gpio_softc *sc = arg; + int epin = pin & MCP23x17_GPIO_NPINS_MASK; + uint8_t bit; + uint8_t port; + uint8_t data; + + if (epin < 8) { + port = 0; + } else { + port = 1; + epin = pin - 8; + } + + bit = 1 << epin; + + DPRINTF(2, ("%s: gpio_ctl pin %d flags 0x%x\n", device_xname(sc->sc_dev), pin, flags)); + + if (flags & (GPIO_PIN_OUTPUT|GPIO_PIN_INPUT)) { + data = mcp23s17gpio_read(sc, MCP23x17_IODIR(sc->sc_bank, port)); + if ((flags & GPIO_PIN_INPUT) || !(flags & GPIO_PIN_OUTPUT)) { + /* for safety INPUT will overide output */ + data |= bit; + } else { + data &= ~bit; + } + mcp23s17gpio_write(sc, MCP23x17_IODIR(sc->sc_bank, port), data); + } + + data = mcp23s17gpio_read(sc, MCP23x17_IPOL(sc->sc_bank, port)); + if (flags & GPIO_PIN_INVIN) { + data |= bit; + } else { + data &= ~bit; + } + mcp23s17gpio_write(sc, MCP23x17_IPOL(sc->sc_bank, port), data); + + data = mcp23s17gpio_read(sc, MCP23x17_GPPU(sc->sc_bank, port)); + if (flags & GPIO_PIN_PULLUP) { + data |= bit; + } else { + data &= ~bit; + } + mcp23s17gpio_write(sc, MCP23x17_GPPU(sc->sc_bank, port), data); +} +#endif /* NGPIO > 0 */ Index: src/sys/dev/spi/mcp23s17.h diff -u /dev/null src/sys/dev/spi/mcp23s17.h:1.1 --- /dev/null Sun Apr 6 17:59:39 2014 +++ src/sys/dev/spi/mcp23s17.h Sun Apr 6 17:59:39 2014 @@ -0,0 +1,96 @@ +/* $NetBSD: mcp23s17.h,v 1.1 2014/04/06 17:59:39 kardel Exp $ */ + +/*- + * Copyright (c) 2014 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank Kardel. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 THE FOUNDATION OR CONTRIBUTORS + * 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 MCP23S17_H +#define MCP23S17_H + +/* + * SPI connected 16-bit general purpose parallel I/O + * + * see http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf + */ + +/* resources */ +#define MCP23x17_GPIO_NPINS 16 +#define MCP23x17_GPIO_NPINS_MASK (MCP23x17_GPIO_NPINS-1) + +/* address layout */ +#define MCP23x17_BANKADDR(BANK, ADDR, PORT) (((BANK) == 1) ? ((PORT) << 4 | (ADDR)) : ((ADDR)<<1 | (PORT))) + +#define MCP23x17_IODIR(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x0, PORT) +#define MCP23x17_IODIRA(BANK) MCP23x17_IODIR(BANK, 0) +#define MCP23x17_IODIRB(BANK) MCP23x17_IODIR(BANK, 1) +#define MCP23x17_IPOL(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x1, PORT) +#define MCP23x17_IPOLA(BANK) MCP23x17_IPOL(BANK, 0) +#define MCP23x17_IPOLB(BANK) MCP23x17_IPOL(BANK, 1) +#define MCP23x17_GPINTEN(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x2, PORT) +#define MCP23x17_GPINTENA(BANK) MCP23x17_GPINTEN(BANK, 0) +#define MCP23x17_GPINTENB(BANK) MCP23x17_GPINTEN(BANK, 1) +#define MCP23x17_DEFVAL(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x3, PORT) +#define MCP23x17_DEFVALA(BANK) MCP23x17_DEFVAL(BANK, 0) +#define MCP23x17_DEFVALB(BANK) MCP23x17_DEFVAL(BANK, 1) +#define MCP23x17_INTCON(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x4, PORT) +#define MCP23x17_INTCONA(BANK) MCP23x17_INTCON(BANK, 0) +#define MCP23x17_INTCONB(BANK) MCP23x17_INTCON(BANK, 0) +#define MCP23x17_IOCON(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x5, PORT) +#define MCP23x17_IOCONA(BANK) MCP23x17_IOCON(BANK, 0) +#define MCP23x17_IOCONB(BANK) MCP23x17_IOCON(BANK, 1) +#define MCP23x17_GPPU(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x6, PORT) +#define MCP23x17_GPPUA(BANK) MCP23x17_GPPU(BANK, 0) +#define MCP23x17_GPPUB(BANK) MCP23x17_GPPU(BANK, 1) +#define MCP23x17_INTF(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x7, PORT) +#define MCP23x17_INTFA(BANK) MCP23x17_INTF(BANK, 0) +#define MCP23x17_INTFB(BANK) MCP23x17_INTF(BANK, 1) +#define MCP23x17_INTCAP(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x8, PORT) +#define MCP23x17_INTCAPA(BANK) MCP23x17_INTCAP(BANK, 0) +#define MCP23x17_INTCAPB(BANK) MCP23x17_INTCAP(BANK, 1) +#define MCP23x17_GPIO(BANK, PORT) MCP23x17_BANKADDR(BANK, 0x9, PORT) +#define MCP23x17_GPIOA(BANK) MCP23x17_GPIO(BANK, 0) +#define MCP23x17_GPIOB(BANK) MCP23x17_GPIO(BANK, 1) +#define MCP23x17_OLAT(BANK, PORT) MCP23x17_BANKADDR(BANK, 0xA, PORT) +#define MCP23x17_OLATA(BANK) MCP23x17_OLAT(BANK, 0) +#define MCP23x17_OLATB(BANK) MCP23x17_OLAT(BANK, 1) + +/* commands */ +#define MCP23x17_OP_BASE_WR 0x40 /* write register */ +#define MCP23x17_OP_BASE_RD 0x41 /* read register */ +#define MCP23x17_OP_READ(HA) (MCP23x17_OP_BASE_RD|(HA)<<1) +#define MCP23x17_OP_WRITE(HA) (MCP23x17_OP_BASE_WR|(HA)<<1) + +/* bits */ +#define MCP23x17_IOCON_BANK __BIT(7) /* select address layout */ +#define MCP23x17_IOCON_MIRROR __BIT(6) /* mirror INTA/INTB interrupt outputs */ +#define MCP23x17_IOCON_SEQOP __BIT(5) /* sequential address operation */ +#define MCP23x17_IOCON_DISLW __BIT(4) /* slew rate SDA output */ +#define MCP23x17_IOCON_HAEN __BIT(3) /* hardware address enable bit (only MCP23S17) */ +#define MCP23x17_IOCON_ODR __BIT(2) /* configure INT pin as open drain */ +#define MCP23x17_IOCON_INTPOL __BIT(1) /* INT pin polarity (unless ODR is set) */ + +#endif