[BACK]Return to pcfiic_ebus.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc64 / dev

Annotation of sys/arch/sparc64/dev/pcfiic_ebus.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pcfiic_ebus.c,v 1.7 2007/05/21 03:11:11 jsg Exp $ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: /*
        !            20:  * Device specific driver for the EBus i2c devices found on some sun4u
        !            21:  * systems. On systems not having a boot-bus controller the i2c devices
        !            22:  * are PCF8584.
        !            23:  */
        !            24:
        !            25: #include <sys/param.h>
        !            26: #include <sys/systm.h>
        !            27: #include <sys/device.h>
        !            28: #include <sys/kernel.h>
        !            29: #include <sys/rwlock.h>
        !            30:
        !            31: #include <machine/bus.h>
        !            32: #include <machine/openfirm.h>
        !            33: #include <machine/autoconf.h>
        !            34:
        !            35: #include <sparc64/dev/ebusreg.h>
        !            36: #include <sparc64/dev/ebusvar.h>
        !            37:
        !            38: #include <dev/i2c/i2cvar.h>
        !            39: #include <sparc64/dev/ofwi2cvar.h>
        !            40:
        !            41: #include <dev/ic/pcf8584var.h>
        !            42:
        !            43: int    pcfiic_ebus_match(struct device *, void *, void *);
        !            44: void   pcfiic_ebus_attach(struct device *, struct device *, void *);
        !            45:
        !            46: struct pcfiic_ebus_softc {
        !            47:        struct pcfiic_softc     esc_sc;
        !            48:
        !            49:        int                     esc_node;
        !            50:        void                    *esc_ih;
        !            51: };
        !            52:
        !            53: struct cfattach pcfiic_ebus_ca = {
        !            54:        sizeof(struct pcfiic_ebus_softc), pcfiic_ebus_match, pcfiic_ebus_attach
        !            55: };
        !            56:
        !            57: int
        !            58: pcfiic_ebus_match(struct device *parent, void *match, void *aux)
        !            59: {
        !            60:        struct ebus_attach_args         *ea = aux;
        !            61:        char                            compat[32];
        !            62:
        !            63:        if (strcmp(ea->ea_name, "i2c") != 0)
        !            64:                return (0);
        !            65:
        !            66:        if (OF_getprop(ea->ea_node, "compatible", compat, sizeof(compat)) == -1)
        !            67:                return (0);
        !            68:
        !            69:        if (strcmp(compat, "i2cpcf,8584") ||
        !            70:            strcmp(compat, "SUNW,bbc-i2c"))
        !            71:                return (1);
        !            72:
        !            73:        return (0);
        !            74: }
        !            75:
        !            76: void
        !            77: pcfiic_ebus_attach(struct device *parent, struct device *self, void *aux)
        !            78: {
        !            79:        struct pcfiic_ebus_softc        *esc = (struct pcfiic_ebus_softc *)self;
        !            80:        struct pcfiic_softc             *sc = &esc->esc_sc;
        !            81:        struct ebus_attach_args         *ea = aux;
        !            82:        char                            compat[32];
        !            83:        u_int64_t                       addr;
        !            84:        u_int8_t                        clock = PCF_CLOCK_12;
        !            85:        int                             swapregs = 0;
        !            86:
        !            87:        if (ea->ea_nregs < 1 || ea->ea_nregs > 2) {
        !            88:                printf(": expected 1 or 2 registers, got %d\n", ea->ea_nregs);
        !            89:                return;
        !            90:        }
        !            91:
        !            92:        if (OF_getprop(ea->ea_node, "compatible", compat, sizeof(compat)) == -1)
        !            93:                return;
        !            94:
        !            95:        if (strcmp(compat, "SUNW,bbc-i2c") == 0) {
        !            96:                /*
        !            97:                 * On BBC-based machines, Sun swapped the order of
        !            98:                 * the registers on their clone pcf, plus they feed
        !            99:                 * it a non-standard clock.
        !           100:                 */
        !           101:                int clk = getpropint(findroot(), "clock-frequency", 0);
        !           102:
        !           103:                if (clk < 105000000)
        !           104:                        clock = PCF_CLOCK_3;
        !           105:                else if (clk < 160000000)
        !           106:                        clock = PCF_CLOCK_4_43;
        !           107:                swapregs = 1;
        !           108:        }
        !           109:
        !           110:        if (OF_getprop(ea->ea_node, "own-address", &addr, sizeof(addr)) == -1) {
        !           111:                addr = 0xaa;
        !           112:        } else if (addr == 0x00 || addr > 0xff) {
        !           113:                printf(": invalid address on I2C bus");
        !           114:                return;
        !           115:        }
        !           116:
        !           117:        /* Prefer prom mapping, then memory mapping, then io mapping */
        !           118:        if (ea->ea_nvaddrs) {
        !           119:                if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
        !           120:                    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_ioh) != 0)
        !           121:                        goto fail;
        !           122:                sc->sc_iot = ea->ea_memtag;
        !           123:        } else if (ebus_bus_map(ea->ea_memtag, 0,
        !           124:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
        !           125:            ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
        !           126:                sc->sc_iot = ea->ea_memtag;
        !           127:        } else if (ebus_bus_map(ea->ea_iotag, 0,
        !           128:            EBUS_PADDR_FROM_REG(&ea->ea_regs[0]),
        !           129:            ea->ea_regs[0].size, 0, 0, &sc->sc_ioh) == 0) {
        !           130:                sc->sc_iot = ea->ea_iotag;
        !           131:        } else {
        !           132: fail:
        !           133:                printf(": can't map register space\n");
        !           134:                        return;
        !           135:        }
        !           136:
        !           137:        if (ea->ea_nregs == 2) {
        !           138:                /*
        !           139:                 * Second register only occurs on BBC-based machines,
        !           140:                 * and is likely not prom mapped
        !           141:                */
        !           142:                if (ebus_bus_map(sc->sc_iot, 0, EBUS_PADDR_FROM_REG(&ea->ea_regs[1]),
        !           143:                    ea->ea_regs[1].size, 0, 0, &sc->sc_ioh2) != 0) {
        !           144:                        printf(": can't map 2nd register space\n");
        !           145:                        return;
        !           146:                }
        !           147:                sc->sc_master = 1;
        !           148:        }
        !           149:
        !           150:        if (ea->ea_nintrs >= 1)
        !           151:                esc->esc_ih = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0],
        !           152:                    IPL_BIO, 0, pcfiic_intr, sc, self->dv_xname);
        !           153:        else
        !           154:                esc->esc_ih = NULL;
        !           155:
        !           156:
        !           157:        if (esc->esc_ih == NULL)
        !           158:                sc->sc_poll = 1;
        !           159:
        !           160:        pcfiic_attach(sc, (i2c_addr_t)(addr >> 1), clock, swapregs,
        !           161:            ofwiic_scan, &ea->ea_node);
        !           162: }

CVSweb