[BACK]Return to gscsio.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/gscsio.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: gscsio.c,v 1.9 2007/06/05 08:37:20 jsg Exp $  */
                      2: /*
                      3:  * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: /*
                     19:  * National Semiconductor Geode SC1100 Super I/O.
                     20:  * Only ACCESS.bus logical device is supported.
                     21:  */
                     22:
                     23: #include <sys/param.h>
                     24: #include <sys/systm.h>
                     25: #include <sys/device.h>
                     26: #include <sys/kernel.h>
                     27: #include <sys/rwlock.h>
                     28: #include <sys/proc.h>
                     29:
                     30: #include <machine/bus.h>
                     31:
                     32: #include <dev/i2c/i2cvar.h>
                     33:
                     34: #include <dev/isa/isareg.h>
                     35: #include <dev/isa/isavar.h>
                     36:
                     37: #include <dev/isa/gscsioreg.h>
                     38:
                     39: struct gscsio_softc {
                     40:        struct device sc_dev;
                     41:
                     42:        bus_space_tag_t sc_iot;
                     43:        bus_space_handle_t sc_ioh;
                     44:
                     45:        int sc_ld_en[GSCSIO_LDNUM];
                     46:        bus_space_handle_t sc_ld_ioh0[GSCSIO_LDNUM];
                     47:        bus_space_handle_t sc_ld_ioh1[GSCSIO_LDNUM];
                     48:
                     49:        /* ACCESS.bus */
                     50:        struct gscsio_acb {
                     51:                void *sc;
                     52:                bus_space_handle_t ioh;
                     53:                struct rwlock buslock;
                     54:        } sc_acb[2];
                     55:        struct i2c_controller sc_acb1_tag;
                     56:        struct i2c_controller sc_acb2_tag;
                     57: };
                     58:
                     59: /* Supported logical devices description */
                     60: static const struct {
                     61:        const char *ld_name;
                     62:        int ld_num;
                     63:        int ld_iosize0;
                     64:        int ld_iosize1;
                     65: } gscsio_ld[] = {
                     66:        { "ACB1", GSCSIO_LDN_ACB1, 6, 0 },
                     67:        { "ACB2", GSCSIO_LDN_ACB2, 6, 0 },
                     68: };
                     69:
                     70: int    gscsio_probe(struct device *, void *, void *);
                     71: void   gscsio_attach(struct device *, struct device *, void *);
                     72:
                     73: void   gscsio_acb_init(struct gscsio_acb *, i2c_tag_t);
                     74: int    gscsio_acb_wait(struct gscsio_acb *, int, int);
                     75: void   gscsio_acb_reset(struct gscsio_acb *acb);
                     76:
                     77: int    gscsio_acb_acquire_bus(void *, int);
                     78: void   gscsio_acb_release_bus(void *, int);
                     79: int    gscsio_acb_send_start(void *, int);
                     80: int    gscsio_acb_send_stop(void *, int);
                     81: int    gscsio_acb_initiate_xfer(void *, uint16_t, int);
                     82: int    gscsio_acb_read_byte(void *, uint8_t *, int);
                     83: int    gscsio_acb_write_byte(void *, uint8_t, int);
                     84:
                     85: struct cfattach gscsio_ca = {
                     86:        sizeof(struct gscsio_softc),
                     87:        gscsio_probe,
                     88:        gscsio_attach
                     89: };
                     90:
                     91: struct cfdriver gscsio_cd = {
                     92:        NULL, "gscsio", DV_DULL
                     93: };
                     94:
                     95: #define ACB_READ(reg) \
                     96:        bus_space_read_1(sc->sc_iot, acb->ioh, (reg))
                     97: #define ACB_WRITE(reg, val) \
                     98:        bus_space_write_1(sc->sc_iot, acb->ioh, (reg), (val))
                     99:
                    100: static __inline u_int8_t
                    101: idxread(bus_space_tag_t iot, bus_space_handle_t ioh, int idx)
                    102: {
                    103:        bus_space_write_1(iot, ioh, GSCSIO_IDX, idx);
                    104:
                    105:        return (bus_space_read_1(iot, ioh, GSCSIO_DAT));
                    106: }
                    107:
                    108: static __inline void
                    109: idxwrite(bus_space_tag_t iot, bus_space_handle_t ioh, int idx, u_int8_t data)
                    110: {
                    111:        bus_space_write_1(iot, ioh, GSCSIO_IDX, idx);
                    112:        bus_space_write_1(iot, ioh, GSCSIO_DAT, data);
                    113: }
                    114:
                    115: int
                    116: gscsio_probe(struct device *parent, void *match, void *aux)
                    117: {
                    118:        struct isa_attach_args *ia = aux;
                    119:        bus_space_tag_t iot;
                    120:        bus_space_handle_t ioh;
                    121:        int iobase;
                    122:        int rv = 0;
                    123:
                    124:        iot = ia->ia_iot;
                    125:        iobase = ia->ipa_io[0].base;
                    126:        if (bus_space_map(iot, iobase, GSCSIO_IOSIZE, 0, &ioh))
                    127:                return (0);
                    128:        if (idxread(iot, ioh, GSCSIO_ID) == GSCSIO_ID_SC1100)
                    129:                rv = 1;
                    130:        bus_space_unmap(iot, ioh, GSCSIO_IOSIZE);
                    131:
                    132:        if (rv) {
                    133:                ia->ipa_nio = 1;
                    134:                ia->ipa_io[0].length = GSCSIO_IOSIZE;
                    135:                ia->ipa_nmem = 0;
                    136:                ia->ipa_nirq = 0;
                    137:                ia->ipa_ndrq = 0;
                    138:        }
                    139:
                    140:        return (rv);
                    141: }
                    142:
                    143: void
                    144: gscsio_attach(struct device *parent, struct device *self, void *aux)
                    145: {
                    146:        struct gscsio_softc *sc = (void *)self;
                    147:        struct isa_attach_args *ia = aux;
                    148:        int i;
                    149:        int iobase;
                    150:
                    151:        sc->sc_iot = ia->ia_iot;
                    152:        if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base, GSCSIO_IOSIZE,
                    153:            0, &sc->sc_ioh)) {
                    154:                printf(": can't map I/O space\n");
                    155:                return;
                    156:        }
                    157:        printf(": SC1100 SIO rev %d:",
                    158:            idxread(sc->sc_iot, sc->sc_ioh, GSCSIO_REV));
                    159:
                    160:        /* Configure all supported logical devices */
                    161:        for (i = 0; i < sizeof (gscsio_ld) / sizeof(gscsio_ld[0]); i++) {
                    162:                sc->sc_ld_en[gscsio_ld[i].ld_num] = 0;
                    163:
                    164:                /* Select the device and check if it's activated */
                    165:                idxwrite(sc->sc_iot, sc->sc_ioh, GSCSIO_LDN,
                    166:                    gscsio_ld[i].ld_num);
                    167:                if ((idxread(sc->sc_iot, sc->sc_ioh, GSCSIO_ACT) &
                    168:                    GSCSIO_ACT_EN) == 0)
                    169:                        continue;
                    170:
                    171:                /* Map I/O space 0 if necessary */
                    172:                if (gscsio_ld[i].ld_iosize0 != 0) {
                    173:                        iobase = idxread(sc->sc_iot, sc->sc_ioh,
                    174:                            GSCSIO_IO0_MSB);
                    175:                        iobase <<= 8;
                    176:                        iobase |= idxread(sc->sc_iot, sc->sc_ioh,
                    177:                            GSCSIO_IO0_LSB);
                    178:                        if (bus_space_map(sc->sc_iot, iobase,
                    179:                            gscsio_ld[i].ld_iosize0, 0,
                    180:                            &sc->sc_ld_ioh0[gscsio_ld[i].ld_num]))
                    181:                                continue;
                    182:                }
                    183:
                    184:                /* Map I/O space 1 if necessary */
                    185:                if (gscsio_ld[i].ld_iosize1 != 0) {
                    186:                        iobase = idxread(sc->sc_iot, sc->sc_ioh,
                    187:                            GSCSIO_IO1_MSB);
                    188:                        iobase <<= 8;
                    189:                        iobase |= idxread(sc->sc_iot, sc->sc_ioh,
                    190:                            GSCSIO_IO1_LSB);
                    191:                        if (bus_space_map(sc->sc_iot, iobase,
                    192:                            gscsio_ld[i].ld_iosize1, 0,
                    193:                            &sc->sc_ld_ioh0[gscsio_ld[i].ld_num])) {
                    194:                                bus_space_unmap(sc->sc_iot,
                    195:                                    sc->sc_ld_ioh0[gscsio_ld[i].ld_num],
                    196:                                    gscsio_ld[i].ld_iosize0);
                    197:                                continue;
                    198:                        }
                    199:                }
                    200:
                    201:                sc->sc_ld_en[gscsio_ld[i].ld_num] = 1;
                    202:                printf(" %s", gscsio_ld[i].ld_name);
                    203:        }
                    204:        printf("\n");
                    205:
                    206:        /* Initialize ACCESS.bus 1 */
                    207:        if (sc->sc_ld_en[GSCSIO_LDN_ACB1]) {
                    208:                sc->sc_acb[0].sc = sc;
                    209:                sc->sc_acb[0].ioh = sc->sc_ld_ioh0[GSCSIO_LDN_ACB1];
                    210:                rw_init(&sc->sc_acb[0].buslock, "iiclk");
                    211:                gscsio_acb_init(&sc->sc_acb[0], &sc->sc_acb1_tag);
                    212:        }
                    213:
                    214:        /* Initialize ACCESS.bus 2 */
                    215:        if (sc->sc_ld_en[GSCSIO_LDN_ACB2]) {
                    216:                sc->sc_acb[1].sc = sc;
                    217:                sc->sc_acb[1].ioh = sc->sc_ld_ioh0[GSCSIO_LDN_ACB2];
                    218:                rw_init(&sc->sc_acb[1].buslock, "iiclk");
                    219:                gscsio_acb_init(&sc->sc_acb[1], &sc->sc_acb2_tag);
                    220:        }
                    221: }
                    222:
                    223: void
                    224: gscsio_acb_init(struct gscsio_acb *acb, i2c_tag_t tag)
                    225: {
                    226:        struct gscsio_softc *sc = acb->sc;
                    227:        struct i2cbus_attach_args iba;
                    228:
                    229:        /* Enable ACB and configure clock frequency */
                    230:        ACB_WRITE(GSCSIO_ACB_CTL2, GSCSIO_ACB_CTL2_EN |
                    231:            (GSCSIO_ACB_FREQ << GSCSIO_ACB_CTL2_FREQ_SHIFT));
                    232:
                    233:        /* Select polling mode */
                    234:        ACB_WRITE(GSCSIO_ACB_CTL1, ACB_READ(GSCSIO_ACB_CTL1) &
                    235:            ~GSCSIO_ACB_CTL1_INTEN);
                    236:
                    237:        /* Disable slave address */
                    238:        ACB_WRITE(GSCSIO_ACB_ADDR, ACB_READ(GSCSIO_ACB_ADDR) &
                    239:            ~GSCSIO_ACB_ADDR_SAEN);
                    240:
                    241:        /* Attach I2C framework */
                    242:        tag->ic_cookie = acb;
                    243:        tag->ic_acquire_bus = gscsio_acb_acquire_bus;
                    244:        tag->ic_release_bus = gscsio_acb_release_bus;
                    245:        tag->ic_send_start = gscsio_acb_send_start;
                    246:        tag->ic_send_stop = gscsio_acb_send_stop;
                    247:        tag->ic_initiate_xfer = gscsio_acb_initiate_xfer;
                    248:        tag->ic_read_byte = gscsio_acb_read_byte;
                    249:        tag->ic_write_byte = gscsio_acb_write_byte;
                    250:
                    251:        bzero(&iba, sizeof(iba));
                    252:        iba.iba_name = "iic";
                    253:        iba.iba_tag = tag;
                    254:        config_found(&sc->sc_dev, &iba, iicbus_print);
                    255: }
                    256:
                    257: int
                    258: gscsio_acb_wait(struct gscsio_acb *acb, int bits, int flags)
                    259: {
                    260:        struct gscsio_softc *sc = acb->sc;
                    261:        u_int8_t st;
                    262:        int i;
                    263:
                    264:        for (i = 0; i < 100; i++) {
                    265:                st = ACB_READ(GSCSIO_ACB_ST);
                    266:                if (st & GSCSIO_ACB_ST_BER) {
                    267:                        printf("%s: bus error, flags=0x%x\n",
                    268:                            sc->sc_dev.dv_xname, flags);
                    269:                        gscsio_acb_reset(acb);
                    270:                        return (EIO);
                    271:                }
                    272:                if (st & GSCSIO_ACB_ST_NEGACK) {
                    273: #if 0
                    274:                        printf("%s: negative ack, flags=0x%x\n",
                    275:                            sc->sc_dev.dv_xname, flags);
                    276: #endif
                    277:                        gscsio_acb_reset(acb);
                    278:                        return (EIO);
                    279:                }
                    280:                if ((st & bits) == bits)
                    281:                        break;
                    282:                delay(10);
                    283:        }
                    284:        if ((st & bits) != bits) {
                    285:                printf("%s: timeout, flags=0x%x\n",
                    286:                    sc->sc_dev.dv_xname, flags);
                    287:                gscsio_acb_reset(acb);
                    288:                return (ETIMEDOUT);
                    289:        }
                    290:
                    291:        return (0);
                    292: }
                    293:
                    294: void
                    295: gscsio_acb_reset(struct gscsio_acb *acb)
                    296: {
                    297:        struct gscsio_softc *sc = acb->sc;
                    298:        u_int8_t st, ctl;
                    299:
                    300:        /* Clear MASTER, NEGACK and BER */
                    301:        st = ACB_READ(GSCSIO_ACB_ST);
                    302:        st |= GSCSIO_ACB_ST_MASTER | GSCSIO_ACB_ST_NEGACK | GSCSIO_ACB_ST_BER;
                    303:        ACB_WRITE(GSCSIO_ACB_ST, st);
                    304:
                    305:        /* Disable and re-enable ACB */
                    306:        ACB_WRITE(GSCSIO_ACB_CTL2, 0);
                    307:        ACB_WRITE(GSCSIO_ACB_CTL2, GSCSIO_ACB_CTL2_EN |
                    308:            (GSCSIO_ACB_FREQ << GSCSIO_ACB_CTL2_FREQ_SHIFT));
                    309:
                    310:        /* Send stop */
                    311:        ctl = ACB_READ(GSCSIO_ACB_CTL1);
                    312:        ctl |= GSCSIO_ACB_CTL1_STOP;
                    313:        ACB_WRITE(GSCSIO_ACB_CTL1, ctl);
                    314: }
                    315:
                    316: int
                    317: gscsio_acb_acquire_bus(void *cookie, int flags)
                    318: {
                    319:        struct gscsio_acb *acb = cookie;
                    320:
                    321:        if (cold || flags & I2C_F_POLL)
                    322:                return (0);
                    323:
                    324:        return (rw_enter(&acb->buslock, RW_WRITE | RW_INTR));
                    325: }
                    326:
                    327: void
                    328: gscsio_acb_release_bus(void *cookie, int flags)
                    329: {
                    330:        struct gscsio_acb *acb = cookie;
                    331:
                    332:        if (cold || flags & I2C_F_POLL)
                    333:                return;
                    334:
                    335:        rw_exit(&acb->buslock);
                    336: }
                    337:
                    338: int
                    339: gscsio_acb_send_start(void *cookie, int flags)
                    340: {
                    341:        struct gscsio_acb *acb = cookie;
                    342:        struct gscsio_softc *sc = acb->sc;
                    343:        u_int8_t ctl;
                    344:
                    345:        ctl = ACB_READ(GSCSIO_ACB_CTL1);
                    346:        ctl |= GSCSIO_ACB_CTL1_START;
                    347:        ACB_WRITE(GSCSIO_ACB_CTL1, ctl);
                    348:
                    349:        return (0);
                    350: }
                    351:
                    352: int
                    353: gscsio_acb_send_stop(void *cookie, int flags)
                    354: {
                    355:        struct gscsio_acb *acb = cookie;
                    356:        struct gscsio_softc *sc = acb->sc;
                    357:        u_int8_t ctl;
                    358:
                    359:        ctl = ACB_READ(GSCSIO_ACB_CTL1);
                    360:        ctl |= GSCSIO_ACB_CTL1_STOP;
                    361:        ACB_WRITE(GSCSIO_ACB_CTL1, ctl);
                    362:
                    363:        return (0);
                    364: }
                    365:
                    366: int
                    367: gscsio_acb_initiate_xfer(void *cookie, uint16_t addr, int flags)
                    368: {
                    369:        struct gscsio_acb *acb = cookie;
                    370:        struct gscsio_softc *sc = acb->sc;
                    371:        u_int8_t ctl;
                    372:        int dir;
                    373:        int error;
                    374:
                    375:        /* Issue start condition */
                    376:        ctl = ACB_READ(GSCSIO_ACB_CTL1);
                    377:        ctl |= GSCSIO_ACB_CTL1_START;
                    378:        ACB_WRITE(GSCSIO_ACB_CTL1, ctl);
                    379:
                    380:        /* Wait for bus mastership */
                    381:        if ((error = gscsio_acb_wait(acb,
                    382:            GSCSIO_ACB_ST_MASTER | GSCSIO_ACB_ST_SDAST, flags)))
                    383:                return (error);
                    384:
                    385:        /* Send address byte */
                    386:        dir = (flags & I2C_F_READ ? 1 : 0);
                    387:        ACB_WRITE(GSCSIO_ACB_SDA, (addr << 1) | dir);
                    388:
                    389:        return (0);
                    390: }
                    391:
                    392: int
                    393: gscsio_acb_read_byte(void *cookie, uint8_t *bytep, int flags)
                    394: {
                    395:        struct gscsio_acb *acb = cookie;
                    396:        struct gscsio_softc *sc = acb->sc;
                    397:        u_int8_t ctl;
                    398:        int error;
                    399:
                    400:        /* Wait for the bus to be ready */
                    401:        if ((error = gscsio_acb_wait(acb, GSCSIO_ACB_ST_SDAST, flags)))
                    402:                return (error);
                    403:
                    404:        /* Acknowledge the last byte */
                    405:        if (flags & I2C_F_LAST) {
                    406:                ctl = ACB_READ(GSCSIO_ACB_CTL1);
                    407:                ctl |= GSCSIO_ACB_CTL1_ACK;
                    408:                ACB_WRITE(GSCSIO_ACB_CTL1, ctl);
                    409:        }
                    410:
                    411:        /* Read data byte */
                    412:        *bytep = ACB_READ(GSCSIO_ACB_SDA);
                    413:
                    414:        return (0);
                    415: }
                    416:
                    417: int
                    418: gscsio_acb_write_byte(void *cookie, uint8_t byte, int flags)
                    419: {
                    420:        struct gscsio_acb *acb = cookie;
                    421:        struct gscsio_softc *sc = acb->sc;
                    422:        u_int8_t ctl;
                    423:        int error;
                    424:
                    425:        /* Wait for the bus to be ready */
                    426:        if ((error = gscsio_acb_wait(acb, GSCSIO_ACB_ST_SDAST, flags)))
                    427:                return (error);
                    428:
                    429:        /* Send stop after the last byte */
                    430:        if (flags & I2C_F_STOP) {
                    431:                ctl = ACB_READ(GSCSIO_ACB_CTL1);
                    432:                ctl |= GSCSIO_ACB_CTL1_STOP;
                    433:                ACB_WRITE(GSCSIO_ACB_CTL1, ctl);
                    434:        }
                    435:
                    436:        /* Write data byte */
                    437:        ACB_WRITE(GSCSIO_ACB_SDA, byte);
                    438:
                    439:        return (0);
                    440: }

CVSweb