Path: blob/main/sys/arm/broadcom/bcm2835/bcm2835_bsc.c
39566 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2001 Tsubai Masanari.4* Copyright (c) 2012 Oleksandr Tymoshenko <[email protected]>5* Copyright (c) 2013 Luiz Otavio O Souza <[email protected]>6* Copyright (c) 2017 Ian Lepore <[email protected]>7* All rights reserved.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*30*/31#include <sys/cdefs.h>32/*33* Driver for bcm2835 i2c-compatible two-wire bus, named 'BSC' on this SoC.34*35* This controller can only perform complete transfers, it does not provide36* low-level control over sending start/repeat-start/stop sequences on the bus.37* In addition, bugs in the silicon make it somewhat difficult to perform a38* repeat-start, and limit the repeat-start to a read following a write on39* the same slave device. (The i2c protocol allows a repeat start to change40* direction or not, and change slave address or not at any time.)41*42* The repeat-start bug and workaround are described in a problem report at43* https://github.com/raspberrypi/linux/issues/254 with the crucial part being44* in a comment block from a fragment of a GPU i2c driver, containing this:45*46* -----------------------------------------------------------------------------47* - See i2c.v: The I2C peripheral samples the values for rw_bit and xfer_count48* - in the IDLE state if start is set.49* -50* - We want to generate a ReSTART not a STOP at the end of the TX phase. In51* - order to do that we must ensure the state machine goes RACK1 -> RACK2 ->52* - SRSTRT1 (not RACK1 -> RACK2 -> SSTOP1).53* -54* - So, in the RACK2 state when (TX) xfer_count==0 we must therefore have55* - already set, ready to be sampled:56* - READ ; rw_bit <= I2CC bit 0 -- must be "read"57* - ST; start <= I2CC bit 7 -- must be "Go" in order to not issue STOP58* - DLEN; xfer_count <= I2CDLEN -- must be equal to our read amount59* -60* - The plan to do this is:61* - 1. Start the sub-address write, but don't let it finish62* - (keep xfer_count > 0)63* - 2. Populate READ, DLEN and ST in preparation for ReSTART read sequence64* - 3. Let TX finish (write the rest of the data)65* - 4. Read back data as it arrives66* -----------------------------------------------------------------------------67*68* The transfer function below scans the list of messages passed to it, looking69* for a read following a write to the same slave. When it finds that, it70* starts the write without prefilling the tx fifo, which holds xfer_count>0,71* then presets the direction, length, and start command for the following read,72* as described above. Then the tx fifo is filled and the rest of the transfer73* proceeds as normal, with the controller automatically supplying a74* repeat-start on the bus when the write operation finishes.75*76* XXX I suspect the controller may be able to do a repeat-start on any77* write->read or write->write transition, even when the slave addresses differ.78* It's unclear whether the slave address can be prestaged along with the79* direction and length while the write xfer_count is being held at zero. In80* fact, if it can't do this, then it couldn't be used to read EDID data.81*/8283#include <sys/param.h>84#include <sys/systm.h>85#include <sys/kernel.h>86#include <sys/lock.h>87#include <sys/module.h>88#include <sys/mutex.h>89#include <sys/bus.h>90#include <machine/resource.h>91#include <machine/bus.h>92#include <sys/rman.h>93#include <sys/sysctl.h>9495#include <dev/iicbus/iicbus.h>96#include <dev/iicbus/iiconf.h>97#include <dev/ofw/ofw_bus.h>98#include <dev/ofw/ofw_bus_subr.h>99100#include <arm/broadcom/bcm2835/bcm2835_bscreg.h>101#include <arm/broadcom/bcm2835/bcm2835_bscvar.h>102103#include "iicbus_if.h"104105static struct ofw_compat_data compat_data[] = {106{"broadcom,bcm2835-bsc", 1},107{"brcm,bcm2708-i2c", 1},108{"brcm,bcm2835-i2c", 1},109{NULL, 0}110};111112#define DEVICE_DEBUGF(sc, lvl, fmt, args...) \113if ((lvl) <= (sc)->sc_debug) \114device_printf((sc)->sc_dev, fmt, ##args)115116#define DEBUGF(sc, lvl, fmt, args...) \117if ((lvl) <= (sc)->sc_debug) \118printf(fmt, ##args)119120static void bcm_bsc_intr(void *);121static int bcm_bsc_detach(device_t);122123static void124bcm_bsc_modifyreg(struct bcm_bsc_softc *sc, uint32_t off, uint32_t mask,125uint32_t value)126{127uint32_t reg;128129mtx_assert(&sc->sc_mtx, MA_OWNED);130reg = BCM_BSC_READ(sc, off);131reg &= ~mask;132reg |= value;133BCM_BSC_WRITE(sc, off, reg);134}135136static int137bcm_bsc_clock_proc(SYSCTL_HANDLER_ARGS)138{139struct bcm_bsc_softc *sc;140uint32_t clk;141142sc = (struct bcm_bsc_softc *)arg1;143BCM_BSC_LOCK(sc);144clk = BCM_BSC_READ(sc, BCM_BSC_CLOCK);145BCM_BSC_UNLOCK(sc);146clk &= 0xffff;147if (clk == 0)148clk = 32768;149clk = BCM_BSC_CORE_CLK / clk;150151return (sysctl_handle_int(oidp, &clk, 0, req));152}153154static int155bcm_bsc_clkt_proc(SYSCTL_HANDLER_ARGS)156{157struct bcm_bsc_softc *sc;158uint32_t clkt;159int error;160161sc = (struct bcm_bsc_softc *)arg1;162163BCM_BSC_LOCK(sc);164clkt = BCM_BSC_READ(sc, BCM_BSC_CLKT);165BCM_BSC_UNLOCK(sc);166clkt &= 0xffff;167error = sysctl_handle_int(oidp, &clkt, sizeof(clkt), req);168if (error != 0 || req->newptr == NULL)169return (error);170171BCM_BSC_LOCK(sc);172BCM_BSC_WRITE(sc, BCM_BSC_CLKT, clkt & 0xffff);173BCM_BSC_UNLOCK(sc);174175return (0);176}177178static int179bcm_bsc_fall_proc(SYSCTL_HANDLER_ARGS)180{181struct bcm_bsc_softc *sc;182uint32_t clk, reg;183int error;184185sc = (struct bcm_bsc_softc *)arg1;186187BCM_BSC_LOCK(sc);188reg = BCM_BSC_READ(sc, BCM_BSC_DELAY);189BCM_BSC_UNLOCK(sc);190reg >>= 16;191error = sysctl_handle_int(oidp, ®, sizeof(reg), req);192if (error != 0 || req->newptr == NULL)193return (error);194195BCM_BSC_LOCK(sc);196clk = BCM_BSC_READ(sc, BCM_BSC_CLOCK);197clk = BCM_BSC_CORE_CLK / clk;198if (reg > clk / 2)199reg = clk / 2 - 1;200bcm_bsc_modifyreg(sc, BCM_BSC_DELAY, 0xffff0000, reg << 16);201BCM_BSC_UNLOCK(sc);202203return (0);204}205206static int207bcm_bsc_rise_proc(SYSCTL_HANDLER_ARGS)208{209struct bcm_bsc_softc *sc;210uint32_t clk, reg;211int error;212213sc = (struct bcm_bsc_softc *)arg1;214215BCM_BSC_LOCK(sc);216reg = BCM_BSC_READ(sc, BCM_BSC_DELAY);217BCM_BSC_UNLOCK(sc);218reg &= 0xffff;219error = sysctl_handle_int(oidp, ®, sizeof(reg), req);220if (error != 0 || req->newptr == NULL)221return (error);222223BCM_BSC_LOCK(sc);224clk = BCM_BSC_READ(sc, BCM_BSC_CLOCK);225clk = BCM_BSC_CORE_CLK / clk;226if (reg > clk / 2)227reg = clk / 2 - 1;228bcm_bsc_modifyreg(sc, BCM_BSC_DELAY, 0xffff, reg);229BCM_BSC_UNLOCK(sc);230231return (0);232}233234static void235bcm_bsc_sysctl_init(struct bcm_bsc_softc *sc)236{237struct sysctl_ctx_list *ctx;238struct sysctl_oid *tree_node;239struct sysctl_oid_list *tree;240241/*242* Add system sysctl tree/handlers.243*/244ctx = device_get_sysctl_ctx(sc->sc_dev);245tree_node = device_get_sysctl_tree(sc->sc_dev);246tree = SYSCTL_CHILDREN(tree_node);247SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "frequency",248CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT,249sc, sizeof(*sc),250bcm_bsc_clock_proc, "IU", "I2C BUS clock frequency");251SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "clock_stretch",252CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT,253sc, sizeof(*sc),254bcm_bsc_clkt_proc, "IU", "I2C BUS clock stretch timeout");255SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "fall_edge_delay",256CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT,257sc, sizeof(*sc),258bcm_bsc_fall_proc, "IU", "I2C BUS falling edge delay");259SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "rise_edge_delay",260CTLFLAG_RW | CTLTYPE_UINT | CTLFLAG_NEEDGIANT,261sc, sizeof(*sc),262bcm_bsc_rise_proc, "IU", "I2C BUS rising edge delay");263SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "debug",264CTLFLAG_RWTUN, &sc->sc_debug, 0,265"Enable debug; 1=reads/writes, 2=add starts/stops");266}267268static void269bcm_bsc_reset(struct bcm_bsc_softc *sc)270{271272/* Enable the BSC Controller, disable interrupts. */273BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN);274/* Clear pending interrupts. */275BCM_BSC_WRITE(sc, BCM_BSC_STATUS, BCM_BSC_STATUS_CLKT |276BCM_BSC_STATUS_ERR | BCM_BSC_STATUS_DONE);277/* Clear the FIFO. */278bcm_bsc_modifyreg(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_CLEAR0,279BCM_BSC_CTRL_CLEAR0);280}281282static int283bcm_bsc_probe(device_t dev)284{285286if (!ofw_bus_status_okay(dev))287return (ENXIO);288289if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)290return (ENXIO);291292device_set_desc(dev, "BCM2708/2835 BSC controller");293294return (BUS_PROBE_DEFAULT);295}296297static int298bcm_bsc_attach(device_t dev)299{300struct bcm_bsc_softc *sc;301int rid;302303sc = device_get_softc(dev);304sc->sc_dev = dev;305306rid = 0;307sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,308RF_ACTIVE);309if (!sc->sc_mem_res) {310device_printf(dev, "cannot allocate memory window\n");311return (ENXIO);312}313314sc->sc_bst = rman_get_bustag(sc->sc_mem_res);315sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);316317rid = 0;318sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,319RF_ACTIVE | RF_SHAREABLE);320if (!sc->sc_irq_res) {321bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);322device_printf(dev, "cannot allocate interrupt\n");323return (ENXIO);324}325326/* Hook up our interrupt handler. */327if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,328NULL, bcm_bsc_intr, sc, &sc->sc_intrhand)) {329bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);330bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);331device_printf(dev, "cannot setup the interrupt handler\n");332return (ENXIO);333}334335mtx_init(&sc->sc_mtx, "bcm_bsc", NULL, MTX_DEF);336337bcm_bsc_sysctl_init(sc);338339/* Enable the BSC controller. Flush the FIFO. */340BCM_BSC_LOCK(sc);341bcm_bsc_reset(sc);342BCM_BSC_UNLOCK(sc);343344sc->sc_iicbus = device_add_child(dev, "iicbus", DEVICE_UNIT_ANY);345if (sc->sc_iicbus == NULL) {346bcm_bsc_detach(dev);347return (ENXIO);348}349350/* Probe and attach the iicbus when interrupts are available. */351bus_delayed_attach_children(dev);352return (0);353}354355static int356bcm_bsc_detach(device_t dev)357{358struct bcm_bsc_softc *sc;359360bus_generic_detach(dev);361362sc = device_get_softc(dev);363mtx_destroy(&sc->sc_mtx);364if (sc->sc_intrhand)365bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);366if (sc->sc_irq_res)367bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);368if (sc->sc_mem_res)369bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);370371return (0);372}373374static void375bcm_bsc_empty_rx_fifo(struct bcm_bsc_softc *sc)376{377uint32_t status;378379/* Assumes sc_totlen > 0 and BCM_BSC_STATUS_RXD is asserted on entry. */380do {381if (sc->sc_resid == 0) {382sc->sc_data = sc->sc_curmsg->buf;383sc->sc_dlen = sc->sc_curmsg->len;384sc->sc_resid = sc->sc_dlen;385++sc->sc_curmsg;386}387do {388*sc->sc_data = BCM_BSC_READ(sc, BCM_BSC_DATA);389DEBUGF(sc, 1, "0x%02x ", *sc->sc_data);390++sc->sc_data;391--sc->sc_resid;392--sc->sc_totlen;393status = BCM_BSC_READ(sc, BCM_BSC_STATUS);394} while (sc->sc_resid > 0 && (status & BCM_BSC_STATUS_RXD));395} while (sc->sc_totlen > 0 && (status & BCM_BSC_STATUS_RXD));396}397398static void399bcm_bsc_fill_tx_fifo(struct bcm_bsc_softc *sc)400{401uint32_t status;402403/* Assumes sc_totlen > 0 and BCM_BSC_STATUS_TXD is asserted on entry. */404do {405if (sc->sc_resid == 0) {406sc->sc_data = sc->sc_curmsg->buf;407sc->sc_dlen = sc->sc_curmsg->len;408sc->sc_resid = sc->sc_dlen;409++sc->sc_curmsg;410}411do {412BCM_BSC_WRITE(sc, BCM_BSC_DATA, *sc->sc_data);413DEBUGF(sc, 1, "0x%02x ", *sc->sc_data);414++sc->sc_data;415--sc->sc_resid;416--sc->sc_totlen;417status = BCM_BSC_READ(sc, BCM_BSC_STATUS);418} while (sc->sc_resid > 0 && (status & BCM_BSC_STATUS_TXD));419/*420* If a repeat-start was pending and we just hit the end of a tx421* buffer, see if it's also the end of the writes that preceeded422* the repeat-start. If so, log the repeat-start and the start423* of the following read, and return because we're not writing424* anymore (and TXD will be true because there's room to write425* in the fifo).426*/427if (sc->sc_replen > 0 && sc->sc_resid == 0) {428sc->sc_replen -= sc->sc_dlen;429if (sc->sc_replen == 0) {430DEBUGF(sc, 1, " err=0\n");431DEVICE_DEBUGF(sc, 2, "rstart 0x%02x\n",432sc->sc_curmsg->slave | 0x01);433DEVICE_DEBUGF(sc, 1,434"read 0x%02x len %d: ",435sc->sc_curmsg->slave | 0x01,436sc->sc_totlen);437sc->sc_flags |= BCM_I2C_READ;438return;439}440}441} while (sc->sc_totlen > 0 && (status & BCM_BSC_STATUS_TXD));442}443444static void445bcm_bsc_intr(void *arg)446{447struct bcm_bsc_softc *sc;448uint32_t status;449450sc = (struct bcm_bsc_softc *)arg;451452BCM_BSC_LOCK(sc);453454/* The I2C interrupt is shared among all the BSC controllers. */455if ((sc->sc_flags & BCM_I2C_BUSY) == 0) {456BCM_BSC_UNLOCK(sc);457return;458}459460status = BCM_BSC_READ(sc, BCM_BSC_STATUS);461DEBUGF(sc, 4, " <intrstatus=0x%08x> ", status);462463/* RXD and DONE can assert together, empty fifo before checking done. */464if ((sc->sc_flags & BCM_I2C_READ) && (status & BCM_BSC_STATUS_RXD))465bcm_bsc_empty_rx_fifo(sc);466467/* Check for completion. */468if (status & (BCM_BSC_STATUS_ERRBITS | BCM_BSC_STATUS_DONE)) {469sc->sc_flags |= BCM_I2C_DONE;470if (status & BCM_BSC_STATUS_ERRBITS)471sc->sc_flags |= BCM_I2C_ERROR;472/* Disable interrupts. */473bcm_bsc_reset(sc);474wakeup(sc);475} else if (!(sc->sc_flags & BCM_I2C_READ)) {476/*477* Don't check for TXD until after determining whether the478* transfer is complete; TXD will be asserted along with ERR or479* DONE if there is room in the fifo.480*/481if ((status & BCM_BSC_STATUS_TXD) && sc->sc_totlen > 0)482bcm_bsc_fill_tx_fifo(sc);483}484485BCM_BSC_UNLOCK(sc);486}487488static int489bcm_bsc_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)490{491struct bcm_bsc_softc *sc;492struct iic_msg *endmsgs, *nxtmsg;493uint32_t readctl, status;494int err;495uint16_t curlen;496uint8_t curisread, curslave, nxtisread, nxtslave;497498sc = device_get_softc(dev);499BCM_BSC_LOCK(sc);500501/* If the controller is busy wait until it is available. */502while (sc->sc_flags & BCM_I2C_BUSY)503mtx_sleep(dev, &sc->sc_mtx, 0, "bscbusw", 0);504505/* Now we have control over the BSC controller. */506sc->sc_flags = BCM_I2C_BUSY;507508DEVICE_DEBUGF(sc, 3, "Transfer %d msgs\n", nmsgs);509510/* Clear the FIFO and the pending interrupts. */511bcm_bsc_reset(sc);512513/*514* Perform all the transfers requested in the array of msgs. Note that515* it is bcm_bsc_empty_rx_fifo() and bcm_bsc_fill_tx_fifo() that advance516* sc->sc_curmsg through the array of messages, as the data from each517* message is fully consumed, but it is this loop that notices when we518* have no more messages to process.519*/520err = 0;521sc->sc_resid = 0;522sc->sc_curmsg = msgs;523endmsgs = &msgs[nmsgs];524while (sc->sc_curmsg < endmsgs) {525readctl = 0;526curslave = sc->sc_curmsg->slave >> 1;527curisread = sc->sc_curmsg->flags & IIC_M_RD;528sc->sc_replen = 0;529sc->sc_totlen = sc->sc_curmsg->len;530/*531* Scan for scatter/gather IO (same slave and direction) or532* repeat-start (read following write for the same slave).533*/534for (nxtmsg = sc->sc_curmsg + 1; nxtmsg < endmsgs; ++nxtmsg) {535nxtslave = nxtmsg->slave >> 1;536if (curslave == nxtslave) {537nxtisread = nxtmsg->flags & IIC_M_RD;538if (curisread == nxtisread) {539/*540* Same slave and direction, this541* message will be part of the same542* transfer as the previous one.543*/544sc->sc_totlen += nxtmsg->len;545continue;546} else if (curisread == IIC_M_WR) {547/*548* Read after write to same slave means549* repeat-start, remember how many bytes550* come before the repeat-start, switch551* the direction to IIC_M_RD, and gather552* up following reads to the same slave.553*/554curisread = IIC_M_RD;555sc->sc_replen = sc->sc_totlen;556sc->sc_totlen += nxtmsg->len;557continue;558}559}560break;561}562563/*564* curslave and curisread temporaries from above may refer to565* the after-repstart msg, reset them to reflect sc_curmsg.566*/567curisread = (sc->sc_curmsg->flags & IIC_M_RD) ? 1 : 0;568curslave = sc->sc_curmsg->slave | curisread;569570/* Write the slave address. */571BCM_BSC_WRITE(sc, BCM_BSC_SLAVE, curslave >> 1);572573DEVICE_DEBUGF(sc, 2, "start 0x%02x\n", curslave);574575/*576* Either set up read length and direction variables for a577* simple transfer or get the hardware started on the first578* piece of a transfer that involves a repeat-start and set up579* the read length and direction vars for the second piece.580*/581if (sc->sc_replen == 0) {582DEVICE_DEBUGF(sc, 1, "%-6s 0x%02x len %d: ",583(curisread) ? "read" : "write", curslave,584sc->sc_totlen);585curlen = sc->sc_totlen;586if (curisread) {587readctl = BCM_BSC_CTRL_READ;588sc->sc_flags |= BCM_I2C_READ;589} else {590readctl = 0;591sc->sc_flags &= ~BCM_I2C_READ;592}593} else {594DEVICE_DEBUGF(sc, 1, "%-6s 0x%02x len %d: ",595(curisread) ? "read" : "write", curslave,596sc->sc_replen);597598/*599* Start the write transfer with an empty fifo and wait600* for the 'transfer active' status bit to light up;601* that indicates that the hardware has latched the602* direction and length for the write, and we can safely603* reload those registers and issue the start for the604* following read; interrupts are not enabled here.605*/606BCM_BSC_WRITE(sc, BCM_BSC_DLEN, sc->sc_replen);607BCM_BSC_WRITE(sc, BCM_BSC_CTRL, BCM_BSC_CTRL_I2CEN |608BCM_BSC_CTRL_ST);609do {610status = BCM_BSC_READ(sc, BCM_BSC_STATUS);611if (status & BCM_BSC_STATUS_ERR) {612/* no ACK on slave addr */613err = EIO;614goto xfer_done;615}616} while ((status & BCM_BSC_STATUS_TA) == 0);617/*618* Set curlen and readctl for the repeat-start read that619* we need to set up below, but set sc_flags to write,620* because that is the operation in progress right now.621*/622curlen = sc->sc_totlen - sc->sc_replen;623readctl = BCM_BSC_CTRL_READ;624sc->sc_flags &= ~BCM_I2C_READ;625}626627/*628* Start the transfer with interrupts enabled, then if doing a629* write, fill the tx fifo. Not prefilling the fifo until after630* this start command is the key workaround for making631* repeat-start work, and it's harmless to do it in this order632* for a regular write too.633*/634BCM_BSC_WRITE(sc, BCM_BSC_DLEN, curlen);635BCM_BSC_WRITE(sc, BCM_BSC_CTRL, readctl | BCM_BSC_CTRL_I2CEN |636BCM_BSC_CTRL_ST | BCM_BSC_CTRL_INT_ALL);637638if (!(sc->sc_curmsg->flags & IIC_M_RD)) {639bcm_bsc_fill_tx_fifo(sc);640}641642/* Wait for the transaction to complete. */643while (err == 0 && !(sc->sc_flags & BCM_I2C_DONE)) {644err = mtx_sleep(sc, &sc->sc_mtx, 0, "bsciow", hz);645}646/* Check for errors. */647if (err == 0 && (sc->sc_flags & BCM_I2C_ERROR))648err = EIO;649xfer_done:650DEBUGF(sc, 1, " err=%d\n", err);651DEVICE_DEBUGF(sc, 2, "stop\n");652if (err != 0)653break;654}655656/* Disable interrupts, clean fifo, etc. */657bcm_bsc_reset(sc);658659/* Clean the controller flags. */660sc->sc_flags = 0;661662/* Wake up the threads waiting for bus. */663wakeup(dev);664665BCM_BSC_UNLOCK(sc);666667return (err);668}669670static int671bcm_bsc_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)672{673struct bcm_bsc_softc *sc;674uint32_t busfreq;675676sc = device_get_softc(dev);677BCM_BSC_LOCK(sc);678bcm_bsc_reset(sc);679if (sc->sc_iicbus == NULL)680busfreq = 100000;681else682busfreq = IICBUS_GET_FREQUENCY(sc->sc_iicbus, speed);683BCM_BSC_WRITE(sc, BCM_BSC_CLOCK, BCM_BSC_CORE_CLK / busfreq);684BCM_BSC_UNLOCK(sc);685686return (IIC_ENOADDR);687}688689static phandle_t690bcm_bsc_get_node(device_t bus, device_t dev)691{692693/* We only have one child, the I2C bus, which needs our own node. */694return (ofw_bus_get_node(bus));695}696697static device_method_t bcm_bsc_methods[] = {698/* Device interface */699DEVMETHOD(device_probe, bcm_bsc_probe),700DEVMETHOD(device_attach, bcm_bsc_attach),701DEVMETHOD(device_detach, bcm_bsc_detach),702703/* iicbus interface */704DEVMETHOD(iicbus_reset, bcm_bsc_iicbus_reset),705DEVMETHOD(iicbus_callback, iicbus_null_callback),706DEVMETHOD(iicbus_transfer, bcm_bsc_transfer),707708/* ofw_bus interface */709DEVMETHOD(ofw_bus_get_node, bcm_bsc_get_node),710711DEVMETHOD_END712};713714static driver_t bcm_bsc_driver = {715"iichb",716bcm_bsc_methods,717sizeof(struct bcm_bsc_softc),718};719720DRIVER_MODULE(iicbus, bcm2835_bsc, iicbus_driver, 0, 0);721DRIVER_MODULE(bcm2835_bsc, simplebus, bcm_bsc_driver, 0, 0);722723724