1198160Srrs/*- 2198160Srrs * Copyright (c) 2003-2009 RMI Corporation 3198160Srrs * All rights reserved. 4198160Srrs * 5198160Srrs * Redistribution and use in source and binary forms, with or without 6198160Srrs * modification, are permitted provided that the following conditions 7198160Srrs * are met: 8198160Srrs * 1. Redistributions of source code must retain the above copyright 9198160Srrs * notice, this list of conditions and the following disclaimer. 10198160Srrs * 2. Redistributions in binary form must reproduce the above copyright 11198160Srrs * notice, this list of conditions and the following disclaimer in the 12198160Srrs * documentation and/or other materials provided with the distribution. 13198160Srrs * 3. Neither the name of RMI Corporation, nor the names of its contributors, 14198160Srrs * may be used to endorse or promote products derived from this software 15198160Srrs * without specific prior written permission. 16198160Srrs * 17198160Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18198160Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19198160Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20198160Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21198160Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22198160Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23198160Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24198160Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25198160Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26198160Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27198160Srrs * SUCH DAMAGE. 28198160Srrs * 29198160Srrs * RMI_BSD */ 30198160Srrs 31198160Srrs#include <sys/cdefs.h> 32202173Simp__FBSDID("$FreeBSD: stable/11/sys/mips/rmi/xlr_i2c.c 323467 2017-09-11 22:21:15Z ian $"); 33198160Srrs 34198160Srrs/* 35198160Srrs * I2C driver for the Palm-BK3220 I2C Host adapter on the RMI XLR. 36198160Srrs */ 37198160Srrs 38198160Srrs#include <sys/param.h> 39198160Srrs#include <sys/systm.h> 40198160Srrs#include <sys/kernel.h> 41216390Sjchandra#include <sys/lock.h> 42198160Srrs#include <sys/module.h> 43216390Sjchandra#include <sys/mutex.h> 44198625Srrs#include <sys/bus.h> 45198160Srrs#include <sys/rman.h> 46198160Srrs 47198160Srrs 48198160Srrs#include <dev/iicbus/iiconf.h> 49198160Srrs#include <dev/iicbus/iicbus.h> 50198160Srrs 51216390Sjchandra#include <mips/rmi/board.h> 52198607Srrs#include <mips/rmi/iomap.h> 53198160Srrs#include <mips/include/resource.h> 54198160Srrs 55198160Srrs#include "iicbus_if.h" 56198160Srrs 57216390Sjchandra/* XLR I2C REGISTERS */ 58216390Sjchandra#define XLR_I2C_CFG 0x00 59216390Sjchandra#define XLR_I2C_CLKDIV 0x01 60216390Sjchandra#define XLR_I2C_DEVADDR 0x02 61216390Sjchandra#define XLR_I2C_ADDR 0x03 62216390Sjchandra#define XLR_I2C_DATAOUT 0x04 63216390Sjchandra#define XLR_I2C_DATAIN 0x05 64216390Sjchandra#define XLR_I2C_STATUS 0x06 65216390Sjchandra#define XLR_I2C_STARTXFR 0x07 66216390Sjchandra#define XLR_I2C_BYTECNT 0x08 67216390Sjchandra#define XLR_I2C_HDSTATIM 0x09 68198160Srrs 69216390Sjchandra/* XLR I2C REGISTERS FLAGS */ 70216390Sjchandra#define XLR_I2C_BUS_BUSY 0x01 71216390Sjchandra#define XLR_I2C_SDOEMPTY 0x02 72216390Sjchandra#define XLR_I2C_RXRDY 0x04 73216390Sjchandra#define XLR_I2C_ACK_ERR 0x08 74216390Sjchandra#define XLR_I2C_ARB_STARTERR 0x30 75198160Srrs 76216390Sjchandra/* Register Programming Values!! Change as required */ 77216390Sjchandra#define XLR_I2C_CFG_ADDR 0xF8 /* 8-Bit dev Addr + POR Values */ 78216390Sjchandra#define XLR_I2C_CFG_NOADDR 0xFA /* 8-Bit reg Addr + POR Values : No dev addr */ 79216390Sjchandra#define XLR_I2C_STARTXFR_ND 0x02 /* No data , only addr */ 80216390Sjchandra#define XLR_I2C_STARTXFR_RD 0x01 /* Read */ 81216390Sjchandra#define XLR_I2C_STARTXFR_WR 0x00 /* Write */ 82216390Sjchandra#define XLR_I2C_CLKDIV_DEF 0x14A /* 0x00000052 */ 83216390Sjchandra#define XLR_I2C_HDSTATIM_DEF 0x107 /* 0x00000000 */ 84198160Srrs 85216390Sjchandra#define MAXTIME 0x10000 86216390Sjchandra#define ARIZONA_I2C_BUS 1 87198160Srrs 88198160Srrsstatic devclass_t xlr_i2c_devclass; 89198160Srrs 90198160Srrs/* 91198160Srrs * Device methods 92198160Srrs */ 93198160Srrsstatic int xlr_i2c_probe(device_t); 94198160Srrsstatic int xlr_i2c_attach(device_t); 95198160Srrsstatic int xlr_i2c_detach(device_t); 96198160Srrs 97198160Srrsstatic int xlr_i2c_start(device_t dev, u_char slave, int timeout); 98198160Srrsstatic int xlr_i2c_stop(device_t dev); 99198625Srrsstatic int xlr_i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay); 100216390Sjchandrastatic int xlr_i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout); 101216390Sjchandrastatic int xlr_i2c_callback(device_t dev, int index, caddr_t data); 102216390Sjchandrastatic int xlr_i2c_repeated_start(device_t dev, u_char slave, int timeout); 103216390Sjchandrastatic int xlr_i2c_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs); 104198160Srrs 105198625Srrsstruct xlr_i2c_softc { 106216390Sjchandra device_t dev; /* Self */ 107198625Srrs struct resource *mem_res; /* Memory resource */ 108198625Srrs volatile int flags; 109198625Srrs int sc_started; 110216390Sjchandra uint8_t i2cdev_addr; 111216390Sjchandra xlr_reg_t *iobase_i2c_regs; 112198625Srrs device_t iicbus; 113216390Sjchandra struct mtx sc_mtx; 114198160Srrs}; 115198160Srrs 116216390Sjchandrastatic void 117216390Sjchandraset_i2c_base(device_t dev) 118216390Sjchandra{ 119216390Sjchandra struct xlr_i2c_softc *sc; 120198160Srrs 121216390Sjchandra sc = device_get_softc(dev); 122216390Sjchandra if (device_get_unit(dev) == 0) 123216390Sjchandra sc->iobase_i2c_regs = xlr_io_mmio(XLR_IO_I2C_0_OFFSET); 124198625Srrs else 125216390Sjchandra sc->iobase_i2c_regs = xlr_io_mmio(XLR_IO_I2C_1_OFFSET); 126198160Srrs} 127198160Srrs 128198625Srrsstatic void 129216390Sjchandraxlr_i2c_dev_write(device_t dev, int reg, int value) 130198160Srrs{ 131216390Sjchandra struct xlr_i2c_softc *sc; 132216390Sjchandra 133216390Sjchandra sc = device_get_softc(dev); 134216390Sjchandra xlr_write_reg(sc->iobase_i2c_regs, reg, value); 135198625Srrs return; 136198160Srrs} 137198160Srrs 138198160Srrs 139198625Srrsstatic int 140216390Sjchandraxlr_i2c_dev_read(device_t dev, int reg) 141198160Srrs{ 142198625Srrs uint32_t val; 143216390Sjchandra struct xlr_i2c_softc *sc; 144198625Srrs 145216390Sjchandra sc = device_get_softc(dev); 146216390Sjchandra val = xlr_read_reg(sc->iobase_i2c_regs, reg); 147198625Srrs return ((int)val); 148198160Srrs} 149198160Srrs 150198160Srrs 151198160Srrsstatic int 152198160Srrsxlr_i2c_probe(device_t dev) 153198160Srrs{ 154216390Sjchandra device_set_desc(dev, "XLR/XLS I2C bus controller"); 155198160Srrs 156198160Srrs return (0); 157198160Srrs} 158198160Srrs 159198160Srrs 160198160Srrs/* 161198160Srrs * We add all the devices which we know about. 162198160Srrs * The generic attach routine will attach them if they are alive. 163198160Srrs */ 164198160Srrsstatic int 165198160Srrsxlr_i2c_attach(device_t dev) 166198160Srrs{ 167216390Sjchandra int rid; 168198625Srrs struct xlr_i2c_softc *sc; 169216390Sjchandra device_t tmpd; 170198160Srrs 171216390Sjchandra if(device_get_unit(dev)!=ARIZONA_I2C_BUS) { 172216390Sjchandra device_printf(dev, "unused iicbus instance\n"); 173216390Sjchandra return 0; 174216390Sjchandra } 175216390Sjchandra 176198625Srrs sc = device_get_softc(dev); 177216390Sjchandra set_i2c_base(dev); 178216390Sjchandra 179216390Sjchandra mtx_init(&sc->sc_mtx, "xlr_i2c", "xlr_i2c", MTX_DEF); 180216390Sjchandra 181216390Sjchandra sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); 182198625Srrs if (sc->mem_res == NULL) { 183198625Srrs printf("not able to allocate the bus resource\n"); 184198625Srrs } 185216390Sjchandra if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) { 186198625Srrs printf("could not allocate iicbus instance\n"); 187216390Sjchandra return -1; 188216390Sjchandra } 189216390Sjchandra if(xlr_board_info.xlr_i2c_device[I2C_RTC].enabled == 1) { 190323467Sian tmpd = device_add_child(sc->iicbus, "ds13rtc", 0); 191216390Sjchandra device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_RTC]); 192216390Sjchandra } 193216390Sjchandra if(xlr_board_info.xlr_i2c_device[I2C_THERMAL].enabled == 1) { 194216390Sjchandra tmpd = device_add_child(sc->iicbus, "max6657", 0); 195216390Sjchandra device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_THERMAL]); 196216390Sjchandra } 197216390Sjchandra if(xlr_board_info.xlr_i2c_device[I2C_EEPROM].enabled == 1) { 198216390Sjchandra tmpd = device_add_child(sc->iicbus, "at24co2n", 0); 199216390Sjchandra device_set_ivars(tmpd, &xlr_board_info.xlr_i2c_device[I2C_EEPROM]); 200216390Sjchandra } 201198160Srrs 202323467Sian /* 203323467Sian * The old ds1374 rtc driver only handled one chip type. The new 204323467Sian * ds13rtc driver handles all ds13xx chips, but must be told the chip 205323467Sian * type via hints. XLR historically hasn't had a standard hints file, 206323467Sian * so set up the hint now if it isn't already there. 207323467Sian */ 208323467Sian#define HINTNAME "hint.ds13rtc.0.compatible" 209323467Sian if (!testenv(HINTNAME)) 210323467Sian kern_setenv(HINTNAME, "dallas,ds1374"); 211323467Sian 212198160Srrs bus_generic_attach(dev); 213198160Srrs 214198625Srrs return (0); 215198160Srrs} 216198625Srrs 217198160Srrsstatic int 218198160Srrsxlr_i2c_detach(device_t dev) 219198160Srrs{ 220198160Srrs bus_generic_detach(dev); 221198625Srrs 222198160Srrs return (0); 223198160Srrs} 224198160Srrs 225198625Srrsstatic int 226198625Srrsxlr_i2c_start(device_t dev, u_char slave, int timeout) 227198160Srrs{ 228198625Srrs int error = 0; 229198625Srrs struct xlr_i2c_softc *sc; 230198160Srrs 231198625Srrs sc = device_get_softc(dev); 232216390Sjchandra mtx_lock(&sc->sc_mtx); 233198625Srrs sc->sc_started = 1; 234216390Sjchandra sc->i2cdev_addr = (slave >> 1); 235198625Srrs return error; 236198160Srrs 237198160Srrs} 238198160Srrs 239198625Srrsstatic int 240198625Srrsxlr_i2c_stop(device_t dev) 241198160Srrs{ 242198625Srrs int error = 0; 243216390Sjchandra struct xlr_i2c_softc *sc; 244198160Srrs 245216390Sjchandra sc = device_get_softc(dev); 246216390Sjchandra mtx_unlock(&sc->sc_mtx); 247198625Srrs return error; 248198160Srrs 249198160Srrs} 250198160Srrs 251198625Srrsstatic int 252198625Srrsxlr_i2c_read(device_t dev, char *buf, int len, int *read, int last, 253198625Srrs int delay) 254198160Srrs{ 255216390Sjchandra volatile uint32_t i2c_status = 0; 256216390Sjchandra int pos=0; 257216390Sjchandra int timeout = 0; 258216390Sjchandra 259216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR); 260216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len); 261198160Srrs 262216390Sjchandraretry: 263216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD); 264198160Srrs 265216390Sjchandra timeout = 0; 266216390Sjchandra while(1) { 267216390Sjchandra if(timeout++ > MAXTIME) 268216390Sjchandra return -1; 269216390Sjchandra 270216390Sjchandra i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS); 271216390Sjchandra if (i2c_status & XLR_I2C_RXRDY) 272216390Sjchandra buf[pos++] = (uint8_t) xlr_i2c_dev_read(dev, XLR_I2C_DATAIN); 273216390Sjchandra 274216390Sjchandra /* ACKERR -- bail */ 275216390Sjchandra if (i2c_status & XLR_I2C_ACK_ERR) 276216390Sjchandra return -1; /* ACK_ERROR */ 277216390Sjchandra 278216390Sjchandra /* LOST ARB or STARTERR -- repeat */ 279216390Sjchandra if (i2c_status & XLR_I2C_ARB_STARTERR) 280216390Sjchandra goto retry; 281216390Sjchandra 282216390Sjchandra /* Wait for busy bit to go away */ 283216390Sjchandra if (i2c_status & XLR_I2C_BUS_BUSY) 284216390Sjchandra continue; 285216390Sjchandra 286216390Sjchandra if (pos == len) 287216390Sjchandra break; 288216390Sjchandra } 289216390Sjchandra *read = pos; 290216390Sjchandra return 0; 291216390Sjchandra 292198160Srrs} 293198160Srrs 294198625Srrsstatic int 295216390Sjchandraxlr_i2c_write(device_t dev, const char *buf, int len, int *sent, int timeout /* us */ ) 296198160Srrs{ 297216390Sjchandra volatile uint32_t i2c_status = 0x00; 298216390Sjchandra uint8_t devaddr, addr; 299216390Sjchandra struct xlr_i2c_softc *sc; 300216390Sjchandra int pos; 301198160Srrs 302216390Sjchandra sc = device_get_softc(dev); 303198160Srrs 304216390Sjchandra /* the first byte of write is addr (of register in device) */ 305216390Sjchandra addr = buf[0]; 306216390Sjchandra devaddr = sc->i2cdev_addr; 307216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_ADDR, addr); 308216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_DEVADDR, devaddr); 309216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_CFG, XLR_I2C_CFG_ADDR); 310216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_BYTECNT, len - 1); 311216390Sjchandra 312216390Sjchandraretry: 313216390Sjchandra pos = 1; 314216390Sjchandra if (len == 1) /* there is no data only address */ 315216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_ND); 316216390Sjchandra else { 317216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_WR); 318216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]); 319198625Srrs } 320198160Srrs 321216390Sjchandra while (1) { 322216390Sjchandra i2c_status = xlr_i2c_dev_read(dev, XLR_I2C_STATUS); 323216390Sjchandra 324216390Sjchandra /* sdo empty send next byte */ 325216390Sjchandra if (i2c_status & XLR_I2C_SDOEMPTY) { 326216390Sjchandra pos++; 327216390Sjchandra xlr_i2c_dev_write(dev, XLR_I2C_DATAOUT, buf[pos]); 328216390Sjchandra } 329198160Srrs 330216390Sjchandra /* LOST ARB or STARTERR -- repeat */ 331216390Sjchandra if (i2c_status & XLR_I2C_ARB_STARTERR) 332216390Sjchandra goto retry; 333198160Srrs 334216390Sjchandra /* ACKERR -- bail */ 335216390Sjchandra if (i2c_status & XLR_I2C_ACK_ERR) { 336216390Sjchandra printf("ACK ERR : exiting\n "); 337216390Sjchandra return -1; 338216390Sjchandra } 339216390Sjchandra 340216390Sjchandra /* busy try again */ 341216390Sjchandra if (i2c_status & XLR_I2C_BUS_BUSY) 342216390Sjchandra continue; 343198625Srrs 344216390Sjchandra if (pos >= len) 345241844Seadler break; 346216390Sjchandra } 347216390Sjchandra *sent = len - 1; 348216390Sjchandra return 0; 349198160Srrs} 350198160Srrs 351216390Sjchandra 352216390Sjchandra 353198160Srrsstatic int 354216390Sjchandraxlr_i2c_callback(device_t dev, int index, caddr_t data) 355198160Srrs{ 356198625Srrs return 0; 357198160Srrs} 358198160Srrs 359198160Srrsstatic int 360198160Srrsxlr_i2c_repeated_start(device_t dev, u_char slave, int timeout) 361198160Srrs{ 362198625Srrs return 0; 363198160Srrs} 364198160Srrs 365216390Sjchandra/* 366216390Sjchandra * I2C bus transfer for RMI boards and devices. 367216390Sjchandra * Generic version of iicbus_transfer that calls the appropriate 368216390Sjchandra * routines to accomplish this. See note above about acceptable 369216390Sjchandra * buffer addresses. 370216390Sjchandra */ 371216390Sjchandraint 372216390Sjchandraxlr_i2c_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs) 373216390Sjchandra{ 374216390Sjchandra int i, error, lenread, lenwrote; 375216390Sjchandra u_char addr; 376216390Sjchandra 377216390Sjchandra addr = msgs[0].slave | LSB; 378216390Sjchandra error = xlr_i2c_start(bus, addr, 0); 379216390Sjchandra for (i = 0, error = 0; i < nmsgs && error == 0; i++) { 380216390Sjchandra if (msgs[i].flags & IIC_M_RD) { 381216390Sjchandra error = xlr_i2c_read((bus), msgs[i].buf, msgs[i].len, &lenread, IIC_LAST_READ, 0); 382216390Sjchandra } 383216390Sjchandra else { 384216390Sjchandra error = xlr_i2c_write((bus), msgs[i].buf, msgs[i].len, &lenwrote, 0); 385216390Sjchandra } 386216390Sjchandra } 387216390Sjchandra error = xlr_i2c_stop(bus); 388216390Sjchandra return (error); 389216390Sjchandra} 390198160Srrs 391216390Sjchandra 392198160Srrsstatic device_method_t xlr_i2c_methods[] = { 393198625Srrs /* device interface */ 394198625Srrs DEVMETHOD(device_probe, xlr_i2c_probe), 395198625Srrs DEVMETHOD(device_attach, xlr_i2c_attach), 396198625Srrs DEVMETHOD(device_detach, xlr_i2c_detach), 397198160Srrs 398198625Srrs /* iicbus interface */ 399198625Srrs DEVMETHOD(iicbus_callback, xlr_i2c_callback), 400198625Srrs DEVMETHOD(iicbus_repeated_start, xlr_i2c_repeated_start), 401198625Srrs DEVMETHOD(iicbus_start, xlr_i2c_start), 402198625Srrs DEVMETHOD(iicbus_stop, xlr_i2c_stop), 403198625Srrs DEVMETHOD(iicbus_write, xlr_i2c_write), 404198625Srrs DEVMETHOD(iicbus_read, xlr_i2c_read), 405216390Sjchandra DEVMETHOD(iicbus_transfer, xlr_i2c_transfer), 406198625Srrs {0, 0} 407198160Srrs}; 408198160Srrs 409198160Srrsstatic driver_t xlr_i2c_driver = { 410198625Srrs "xlr_i2c", 411198625Srrs xlr_i2c_methods, 412198625Srrs sizeof(struct xlr_i2c_softc), 413198160Srrs}; 414198160Srrs 415198160SrrsDRIVER_MODULE(xlr_i2c, iodi, xlr_i2c_driver, xlr_i2c_devclass, 0, 0); 416216390SjchandraDRIVER_MODULE(iicbus, xlr_i2c, iicbus_driver, iicbus_devclass, 0, 0); 417