diff options
author | Alexander Yurchenko <grange@cvs.openbsd.org> | 2004-05-23 17:41:10 +0000 |
---|---|---|
committer | Alexander Yurchenko <grange@cvs.openbsd.org> | 2004-05-23 17:41:10 +0000 |
commit | c3af576a7b133b4c2046eef9ddf14925c38ba25c (patch) | |
tree | 0cb54c1fdc2a67598086c8c20ba6195912df6a4b | |
parent | 71a75fdbc0855c8da85afd759f3d28e3e6a3c160 (diff) |
gscsio(4) -- National Semiconductor Geode SC1100 Super I/O driver.
For now it only supports I2C-compatible ACCESS.bus interface,
so we use it as an i2c master controller.
ACCESS.bus interface is enabled and used on the PC Engines WRAP.1C
board.
-rw-r--r-- | sys/arch/i386/conf/GENERIC | 5 | ||||
-rw-r--r-- | sys/dev/isa/files.isa | 7 | ||||
-rw-r--r-- | sys/dev/isa/gscsio.c | 448 | ||||
-rw-r--r-- | sys/dev/isa/gscsioreg.h | 89 |
4 files changed, 547 insertions, 2 deletions
diff --git a/sys/arch/i386/conf/GENERIC b/sys/arch/i386/conf/GENERIC index fefeaa95437..0a644f1d9c8 100644 --- a/sys/arch/i386/conf/GENERIC +++ b/sys/arch/i386/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.361 2004/05/23 03:23:00 deraadt Exp $ +# $OpenBSD: GENERIC,v 1.362 2004/05/23 17:41:08 grange Exp $ # # GENERIC -- everything that's currently supported # @@ -70,6 +70,9 @@ lm0 at isa? port 0x290 #lm1 at isa? port 0x280 #lm2 at isa? port 0x310 nsclpcsio* at isa? # NS PC87366 hardware monitor +gscsio* at isa? # NS Geode SC1100 Super I/O +iic0 at gscsio? # ACCESS.bus 1 +iic1 at gscsio? # ACCESS.bus 2 it0 at isa? port 0x290 # IT8705F, IT8712F and SiS970 hardware # monitors diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa index 8c8e3ef8a1e..5858dca16c6 100644 --- a/sys/dev/isa/files.isa +++ b/sys/dev/isa/files.isa @@ -1,4 +1,4 @@ -# $OpenBSD: files.isa,v 1.86 2004/01/05 17:27:30 markus Exp $ +# $OpenBSD: files.isa,v 1.87 2004/05/23 17:41:09 grange Exp $ # $NetBSD: files.isa,v 1.21 1996/05/16 03:45:55 mycroft Exp $ # # Config file and device description for machine-independent ISA code. @@ -383,6 +383,11 @@ device nsclpcsio attach nsclpcsio at isa with nsclpcsio_isa file dev/isa/nsclpcsio_isa.c nsclpcsio_isa +# National Semiconductor Geode SC1100 Super I/O +device gscsio: i2cbus +attach gscsio at isa +file dev/isa/gscsio.c gscsio + # IT8705F, IT8712F and SiS970 hardware monitors device it attach it at isa diff --git a/sys/dev/isa/gscsio.c b/sys/dev/isa/gscsio.c new file mode 100644 index 00000000000..1a448892af6 --- /dev/null +++ b/sys/dev/isa/gscsio.c @@ -0,0 +1,448 @@ +/* $OpenBSD: gscsio.c,v 1.1 2004/05/23 17:41:09 grange Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * National Semiconductor Geode SC1100 Super I/O. + * Only ACCESS.bus logical device is supported. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/proc.h> + +#include <machine/bus.h> + +#include <dev/i2c/i2cvar.h> + +#include <dev/isa/isareg.h> +#include <dev/isa/isavar.h> + +#include <dev/isa/gscsioreg.h> + +struct gscsio_softc { + struct device sc_dev; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + + int sc_ld_en[GSCSIO_LDNUM]; + bus_space_handle_t sc_ld_ioh0[GSCSIO_LDNUM]; + bus_space_handle_t sc_ld_ioh1[GSCSIO_LDNUM]; + + /* ACCESS.bus */ + struct gscsio_acb { + void *sc; + bus_space_handle_t ioh; + struct lock buslock; + } sc_acb[2]; + struct i2c_controller sc_acb1_tag; + struct i2c_controller sc_acb2_tag; +}; + +/* Supported logical devices description */ +static const struct { + const char *ld_name; + int ld_num; + int ld_iosize0; + int ld_iosize1; +} gscsio_ld[] = { + { "ACB1", GSCSIO_LDN_ACB1, 6, 0 }, + { "ACB2", GSCSIO_LDN_ACB2, 6, 0 }, +}; + +int gscsio_probe(struct device *, void *, void *); +void gscsio_attach(struct device *, struct device *, void *); + +void gscsio_acb_init(struct gscsio_acb *, i2c_tag_t); +int gscsio_acb_wait(struct gscsio_acb *, int, int); +void gscsio_acb_reset(struct gscsio_acb *acb); + +int gscsio_acb_acquire_bus(void *, int); +void gscsio_acb_release_bus(void *, int); +int gscsio_acb_send_start(void *, int); +int gscsio_acb_send_stop(void *, int); +int gscsio_acb_initiate_xfer(void *, uint16_t, int); +int gscsio_acb_read_byte(void *, uint8_t *, int); +int gscsio_acb_write_byte(void *, uint8_t, int); + +struct cfattach gscsio_ca = { + sizeof(struct gscsio_softc), + gscsio_probe, + gscsio_attach +}; + +struct cfdriver gscsio_cd = { + NULL, "gscsio", DV_DULL +}; + +#define ACB_READ(reg) \ + bus_space_read_1(sc->sc_iot, acb->ioh, (reg)) +#define ACB_WRITE(reg, val) \ + bus_space_write_1(sc->sc_iot, acb->ioh, (reg), (val)) + +static __inline u_int8_t +idxread(bus_space_tag_t iot, bus_space_handle_t ioh, int idx) +{ + bus_space_write_1(iot, ioh, GSCSIO_IDX, idx); + + return (bus_space_read_1(iot, ioh, GSCSIO_DAT)); +} + +static __inline void +idxwrite(bus_space_tag_t iot, bus_space_handle_t ioh, int idx, u_int8_t data) +{ + bus_space_write_1(iot, ioh, GSCSIO_IDX, idx); + bus_space_write_1(iot, ioh, GSCSIO_DAT, data); +} + +static int +ioprobe(bus_space_tag_t iot, int base) +{ + bus_space_handle_t ioh; + int rv = 0; + + if (bus_space_map(iot, base, GSCSIO_IOSIZE, 0, &ioh)) + return (0); + if (idxread(iot, ioh, GSCSIO_ID) == GSCSIO_ID_SC1100) + rv = 1; + bus_space_unmap(iot, ioh, GSCSIO_IOSIZE); + + return (rv); +} + +int +gscsio_probe(struct device *parent, void *match, void *aux) +{ + struct isa_attach_args *ia = aux; + int iobase; + + iobase = GSCSIO_IOBASE1; + if (ioprobe(ia->ia_iot, iobase)) + goto found; + iobase = GSCSIO_IOBASE2; + if (ioprobe(ia->ia_iot, iobase)) + goto found; + + return (0); + +found: + ia->ipa_nio = 1; + ia->ipa_io[0].base = iobase; + ia->ipa_io[0].length = GSCSIO_IOSIZE; + ia->ipa_nmem = 0; + ia->ipa_nirq = 0; + ia->ipa_ndrq = 0; + + return (1); +} + +void +gscsio_attach(struct device *parent, struct device *self, void *aux) +{ + struct gscsio_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + int i; + int iobase; + + sc->sc_iot = ia->ia_iot; + if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base, GSCSIO_IOSIZE, + 0, &sc->sc_ioh)) { + printf(": can't map I/O space\n"); + return; + } + printf(": SC1100 SIO rev %d:", + idxread(sc->sc_iot, sc->sc_ioh, GSCSIO_REV)); + + /* Configure all supported logical devices */ + for (i = 0; i < sizeof (gscsio_ld) / sizeof(gscsio_ld[0]); i++) { + sc->sc_ld_en[gscsio_ld[i].ld_num] = 0; + + /* Select the device and check if it's activated */ + idxwrite(sc->sc_iot, sc->sc_ioh, GSCSIO_LDN, + gscsio_ld[i].ld_num); + if ((idxread(sc->sc_iot, sc->sc_ioh, GSCSIO_ACT) & + GSCSIO_ACT_EN) == 0) + continue; + + /* Map I/O space 0 if necessary */ + if (gscsio_ld[i].ld_iosize0 != 0) { + iobase = idxread(sc->sc_iot, sc->sc_ioh, + GSCSIO_IO0_MSB); + iobase <<= 8; + iobase |= idxread(sc->sc_iot, sc->sc_ioh, + GSCSIO_IO0_LSB); + if (bus_space_map(sc->sc_iot, iobase, + gscsio_ld[i].ld_iosize0, 0, + &sc->sc_ld_ioh0[gscsio_ld[i].ld_num])) + continue; + } + + /* Map I/O space 1 if necessary */ + if (gscsio_ld[i].ld_iosize1 != 0) { + iobase = idxread(sc->sc_iot, sc->sc_ioh, + GSCSIO_IO1_MSB); + iobase <<= 8; + iobase |= idxread(sc->sc_iot, sc->sc_ioh, + GSCSIO_IO1_LSB); + if (bus_space_map(sc->sc_iot, iobase, + gscsio_ld[i].ld_iosize1, 0, + &sc->sc_ld_ioh0[gscsio_ld[i].ld_num])) { + bus_space_unmap(sc->sc_iot, + sc->sc_ld_ioh0[gscsio_ld[i].ld_num], + gscsio_ld[i].ld_iosize0); + continue; + } + } + + sc->sc_ld_en[gscsio_ld[i].ld_num] = 1; + printf(" %s", gscsio_ld[i].ld_name); + } + printf("\n"); + + /* Initialize ACCESS.bus 1 */ + if (sc->sc_ld_en[GSCSIO_LDN_ACB1]) { + sc->sc_acb[0].sc = sc; + sc->sc_acb[0].ioh = sc->sc_ld_ioh0[GSCSIO_LDN_ACB1]; + gscsio_acb_init(&sc->sc_acb[0], &sc->sc_acb1_tag); + } + + /* Initialize ACCESS.bus 2 */ + if (sc->sc_ld_en[GSCSIO_LDN_ACB2]) { + sc->sc_acb[1].sc = sc; + sc->sc_acb[1].ioh = sc->sc_ld_ioh0[GSCSIO_LDN_ACB2]; + gscsio_acb_init(&sc->sc_acb[1], &sc->sc_acb2_tag); + } +} + +void +gscsio_acb_init(struct gscsio_acb *acb, i2c_tag_t tag) +{ + struct gscsio_softc *sc = acb->sc; + struct i2cbus_attach_args iba; + + /* Enable ACB and configure clock frequency */ + ACB_WRITE(GSCSIO_ACB_CTL2, GSCSIO_ACB_CTL2_EN | + (GSCSIO_ACB_FREQ << GSCSIO_ACB_CTL2_FREQ_SHIFT)); + + /* Select polling mode */ + ACB_WRITE(GSCSIO_ACB_CTL1, ACB_READ(GSCSIO_ACB_CTL1) & + ~GSCSIO_ACB_CTL1_INTEN); + + /* Disable slave address */ + ACB_WRITE(GSCSIO_ACB_ADDR, ACB_READ(GSCSIO_ACB_ADDR) & + ~GSCSIO_ACB_ADDR_SAEN); + + /* Attach I2C framework */ + tag->ic_cookie = acb; + tag->ic_acquire_bus = gscsio_acb_acquire_bus; + tag->ic_release_bus = gscsio_acb_release_bus; + tag->ic_send_start = gscsio_acb_send_start; + tag->ic_send_stop = gscsio_acb_send_stop; + tag->ic_initiate_xfer = gscsio_acb_initiate_xfer; + tag->ic_read_byte = gscsio_acb_read_byte; + tag->ic_write_byte = gscsio_acb_write_byte; + + iba.iba_name = "iic"; + iba.iba_tag = tag; + config_found(&sc->sc_dev, &iba, iicbus_print); +} + +int +gscsio_acb_wait(struct gscsio_acb *acb, int bits, int flags) +{ + struct gscsio_softc *sc = acb->sc; + u_int8_t st; + int i; + + for (i = 0; i < 100; i++) { + st = ACB_READ(GSCSIO_ACB_ST); + if (st & GSCSIO_ACB_ST_BER) { + printf("%s: bus error, flags=0x%x\n", + sc->sc_dev.dv_xname, flags); + gscsio_acb_reset(acb); + return (EIO); + } + if (st & GSCSIO_ACB_ST_NEGACK) { + printf("%s: negative ack, flags=0x%x\n", + sc->sc_dev.dv_xname, flags); + gscsio_acb_reset(acb); + return (EIO); + } + if ((st & bits) == bits) + break; + delay(10); + } + if ((st & bits) != bits) { + printf("%s: timeout, flags=0x%x\n", + sc->sc_dev.dv_xname, flags); + gscsio_acb_reset(acb); + return (ETIMEDOUT); + } + + return (0); +} + +void +gscsio_acb_reset(struct gscsio_acb *acb) +{ + struct gscsio_softc *sc = acb->sc; + u_int8_t st, ctl; + + /* Clear MASTER, NEGACK and BER */ + st = ACB_READ(GSCSIO_ACB_ST); + st |= GSCSIO_ACB_ST_MASTER | GSCSIO_ACB_ST_NEGACK | GSCSIO_ACB_ST_BER; + ACB_WRITE(GSCSIO_ACB_ST, st); + + /* Disable and re-enable ACB */ + ACB_WRITE(GSCSIO_ACB_CTL2, 0); + ACB_WRITE(GSCSIO_ACB_CTL2, GSCSIO_ACB_CTL2_EN | + (GSCSIO_ACB_FREQ << GSCSIO_ACB_CTL2_FREQ_SHIFT)); + + /* Send stop */ + ctl = ACB_READ(GSCSIO_ACB_CTL1); + ctl |= GSCSIO_ACB_CTL1_STOP; + ACB_WRITE(GSCSIO_ACB_CTL1, ctl); +} + +int +gscsio_acb_acquire_bus(void *cookie, int flags) +{ + struct gscsio_acb *acb = cookie; + + if (flags & I2C_F_POLL) + return (0); + + return (lockmgr(&acb->buslock, LK_EXCLUSIVE, NULL, curproc)); +} + +void +gscsio_acb_release_bus(void *cookie, int flags) +{ + struct gscsio_acb *acb = cookie; + + if (flags & I2C_F_POLL) + return; + + lockmgr(&acb->buslock, LK_RELEASE, NULL, curproc); +} + +int +gscsio_acb_send_start(void *cookie, int flags) +{ + struct gscsio_acb *acb = cookie; + struct gscsio_softc *sc = acb->sc; + u_int8_t ctl; + + ctl = ACB_READ(GSCSIO_ACB_CTL1); + ctl |= GSCSIO_ACB_CTL1_START; + ACB_WRITE(GSCSIO_ACB_CTL1, ctl); + + return (0); +} + +int +gscsio_acb_send_stop(void *cookie, int flags) +{ + struct gscsio_acb *acb = cookie; + struct gscsio_softc *sc = acb->sc; + u_int8_t ctl; + + ctl = ACB_READ(GSCSIO_ACB_CTL1); + ctl |= GSCSIO_ACB_CTL1_STOP; + ACB_WRITE(GSCSIO_ACB_CTL1, ctl); + + return (0); +} + +int +gscsio_acb_initiate_xfer(void *cookie, uint16_t addr, int flags) +{ + struct gscsio_acb *acb = cookie; + struct gscsio_softc *sc = acb->sc; + u_int8_t ctl; + int dir; + int error; + + /* Issue start condition */ + ctl = ACB_READ(GSCSIO_ACB_CTL1); + ctl |= GSCSIO_ACB_CTL1_START; + ACB_WRITE(GSCSIO_ACB_CTL1, ctl); + + /* Wait for bus mastership */ + if ((error = gscsio_acb_wait(acb, + GSCSIO_ACB_ST_MASTER | GSCSIO_ACB_ST_SDAST, flags))) + return (error); + + /* Send address byte */ + dir = (flags & I2C_F_READ ? 1 : 0); + ACB_WRITE(GSCSIO_ACB_SDA, (addr << 1) | dir); + + return (0); +} + +int +gscsio_acb_read_byte(void *cookie, uint8_t *bytep, int flags) +{ + struct gscsio_acb *acb = cookie; + struct gscsio_softc *sc = acb->sc; + u_int8_t ctl; + int error; + + /* Wait for the bus to be ready */ + if ((error = gscsio_acb_wait(acb, GSCSIO_ACB_ST_SDAST, flags))) + return (error); + + /* Acknowledge the last byte */ + if (flags & I2C_F_LAST) { + ctl = ACB_READ(GSCSIO_ACB_CTL1); + ctl |= GSCSIO_ACB_CTL1_ACK; + ACB_WRITE(GSCSIO_ACB_CTL1, ctl); + } + + /* Read data byte */ + *bytep = ACB_READ(GSCSIO_ACB_SDA); + + return (0); +} + +int +gscsio_acb_write_byte(void *cookie, uint8_t byte, int flags) +{ + struct gscsio_acb *acb = cookie; + struct gscsio_softc *sc = acb->sc; + u_int8_t ctl; + int error; + + /* Wait for the bus to be ready */ + if ((error = gscsio_acb_wait(acb, GSCSIO_ACB_ST_SDAST, flags))) + return (error); + + /* Send stop after the last byte */ + if (flags & I2C_F_STOP) { + ctl = ACB_READ(GSCSIO_ACB_CTL1); + ctl |= GSCSIO_ACB_CTL1_STOP; + ACB_WRITE(GSCSIO_ACB_CTL1, ctl); + } + + /* Write data byte */ + ACB_WRITE(GSCSIO_ACB_SDA, byte); + + return (0); +} diff --git a/sys/dev/isa/gscsioreg.h b/sys/dev/isa/gscsioreg.h new file mode 100644 index 00000000000..dc8793b0bc4 --- /dev/null +++ b/sys/dev/isa/gscsioreg.h @@ -0,0 +1,89 @@ +/* $OpenBSD: gscsioreg.h,v 1.1 2004/05/23 17:41:09 grange Exp $ */ +/* + * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * National Semiconductor Geode SC1100 Super I/O register definitions. + */ + +/* Possible index-data register pair base addresses */ +#define GSCSIO_IOBASE1 0x2e +#define GSCSIO_IOBASE2 0x15c +#define GSCSIO_IOSIZE 2 /* I/O space size */ + +/* Index-data register pair */ +#define GSCSIO_IDX 0x0 /* index register */ +#define GSCSIO_DAT 0x1 /* data register */ + +/* SIO control and configuration registers */ +#define GSCSIO_LDN 0x07 /* logical device number */ +#define GSCSIO_LDN_ACB1 0x05 /* ACCESS.bus 1 */ +#define GSCSIO_LDN_ACB2 0x06 /* ACCESS.bus 2 */ +#define GSCSIO_ID 0x20 /* SIO ID */ +#define GSCSIO_ID_SC1100 0xf5 /* Geode SC1100 ID */ +#define GSCSIO_CFG1 0x21 /* configuration 1 */ +#define GSCSIO_CFG2 0x22 /* configuration 2 */ +#define GSCSIO_REV 0x27 /* revision ID */ + +/* Logical device control and configuration registers */ +#define GSCSIO_ACT 0x30 /* logical device activation control */ +#define GSCSIO_ACT_EN 0x01 /* enabled */ +#define GSCSIO_IO0_MSB 0x60 /* I/O space 0 base bits [15:8] */ +#define GSCSIO_IO0_LSB 0x61 /* I/O space 0 base bits [7:0] */ +#define GSCSIO_IO1_MSB 0x62 /* I/O space 1 base bits [15:8] */ +#define GSCSIO_IO1_LSB 0x63 /* I/O space 1 base bits [7:0] */ +#define GSCSIO_INUM 0x70 /* interrupt number */ +#define GSCSIO_ITYPE 0x71 /* interrupt type */ +#define GSCSIO_DMA0 0x74 /* DMA channel 0 */ +#define GSCSIO_DMA1 0x75 /* DMA channel 1 */ + +#define GSCSIO_LDNUM 6 /* total number of logical devices */ + +/* ACB (ACCESS.bus) logical device registers */ +#define GSCSIO_ACB_SDA 0x00 /* serial data */ +#define GSCSIO_ACB_ST 0x01 /* status */ +#define GSCSIO_ACB_ST_XMIT (1 << 0) /* transmit mode active */ +#define GSCSIO_ACB_ST_MASTER (1 << 1) /* master mode active */ +#define GSCSIO_ACB_ST_NMATCH (1 << 2) /* new match */ +#define GSCSIO_ACB_ST_STASTR (1 << 3) /* stall after start */ +#define GSCSIO_ACB_ST_NEGACK (1 << 4) /* negative ack */ +#define GSCSIO_ACB_ST_BER (1 << 5) /* bus error */ +#define GSCSIO_ACB_ST_SDAST (1 << 6) /* wait or hold data */ +#define GSCSIO_ACB_ST_SLVSTP (1 << 7) /* slave stop */ +#define GSCSIO_ACB_CST 0x02 /* control status */ +#define GSCSIO_ACB_CST_BUSY (1 << 0) /* busy */ +#define GSCSIO_ACB_CST_BB (1 << 1) /* bus busy */ +#define GSCSIO_ACB_CST_MATCH (1 << 2) /* match address */ +#define GSCSIO_ACB_CST_GCMTCH (1 << 3) /* global call match */ +#define GSCSIO_ACB_CST_TSDA (1 << 4) /* test ABD line */ +#define GSCSIO_ACB_CST_TGABC (1 << 5) /* toggle ABC line */ +#define GSCSIO_ACB_CTL1 0x03 /* control 1 */ +#define GSCSIO_ACB_CTL1_START (1 << 0) /* start condition */ +#define GSCSIO_ACB_CTL1_STOP (1 << 1) /* stop condition */ +#define GSCSIO_ACB_CTL1_INTEN (1 << 2) /* interrupt enabled */ +#define GSCSIO_ACB_CTL1_ACK (1 << 4) /* acknowledge */ +#define GSCSIO_ACB_CTL1_GCMEN (1 << 5) /* global call match enable */ +#define GSCSIO_ACB_CTL1_NMINTE (1 << 6) /* new match intr enable */ +#define GSCSIO_ACB_CTL1_STASTRE (1 << 7) /* stall after start enable */ +#define GSCSIO_ACB_ADDR 0x04 /* own address */ +#define GSCSIO_ACB_ADDR_MASK 0x7f /* address mask */ +#define GSCSIO_ACB_ADDR_SAEN (1 << 7) /* slave address enable */ +#define GSCSIO_ACB_CTL2 0x05 /* control 2 */ +#define GSCSIO_ACB_CTL2_EN (1 << 0) /* ACB enabled */ +#define GSCSIO_ACB_CTL2_FREQ_SHIFT 1 /* ACB frequency shift */ +#define GSCSIO_ACB_CTL2_FREQ_MASK 0x7f /* ACB frequency mask */ + +#define GSCSIO_ACB_FREQ 0x3c /* standard I2C frequency 100kHz */ |