1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2003-2012 Broadcom Corporation 5 * All Rights Reserved 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD$"); 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37#include <sys/kernel.h> 38#include <sys/lock.h> 39#include <sys/module.h> 40#include <sys/mutex.h> 41#include <sys/rman.h> 42 43#include <machine/bus.h> 44 45#include <dev/iicbus/iicbus.h> 46#include <dev/iicbus/iiconf.h> 47 48#include "iicbus_if.h" 49#include "iicoc.h" 50 51devclass_t iicoc_devclass; 52 53DRIVER_MODULE(iicbus, iicoc, iicbus_driver, iicbus_devclass, 0, 0); 54 55static void 56iicoc_dev_write(device_t dev, int reg, int value) 57{ 58 struct iicoc_softc *sc; 59 60 sc = device_get_softc(dev); 61 bus_write_1(sc->mem_res, reg<<sc->reg_shift, value); 62} 63 64static int 65iicoc_dev_read(device_t dev, int reg) 66{ 67 uint8_t val; 68 struct iicoc_softc *sc; 69 70 sc = device_get_softc(dev); 71 val = bus_read_1(sc->mem_res, reg<<sc->reg_shift); 72 return (val); 73} 74 75static int 76iicoc_wait_on_status(device_t dev, uint8_t bit) 77{ 78 int tries = I2C_TIMEOUT; 79 uint8_t status; 80 81 do { 82 status = iicoc_dev_read(dev, OC_I2C_STATUS_REG); 83 } while ((status & bit) != 0 && --tries > 0); 84 85 return (tries == 0 ? -1: 0); 86} 87 88static int 89iicoc_rd_cmd(device_t dev, uint8_t cmd) 90{ 91 uint8_t data; 92 93 iicoc_dev_write(dev, OC_I2C_CMD_REG, cmd); 94 if (iicoc_wait_on_status(dev, OC_STATUS_TIP) < 0) { 95 device_printf(dev, "read: Timeout waiting for TIP clear.\n"); 96 return (-1); 97 } 98 data = iicoc_dev_read(dev, OC_I2C_DATA_REG); 99 return (data); 100} 101 102static int 103iicoc_wr_cmd(device_t dev, uint8_t data, uint8_t cmd) 104{ 105 106 iicoc_dev_write(dev, OC_I2C_DATA_REG, data); 107 iicoc_dev_write(dev, OC_I2C_CMD_REG, cmd); 108 if (iicoc_wait_on_status(dev, OC_STATUS_TIP) < 0) { 109 device_printf(dev, "write: Timeout waiting for TIP clear.\n"); 110 return (-1); 111 } 112 return (0); 113} 114 115static int 116iicoc_wr_ack_cmd(device_t dev, uint8_t data, uint8_t cmd) 117{ 118 119 if (iicoc_wr_cmd(dev, data, cmd) < 0) 120 return (-1); 121 122 if (iicoc_dev_read(dev, OC_I2C_STATUS_REG) & OC_STATUS_NACK) { 123 device_printf(dev, "write: I2C command ACK Error.\n"); 124 return (IIC_ENOACK); 125 } 126 return (0); 127} 128 129int 130iicoc_init(device_t dev) 131{ 132 struct iicoc_softc *sc; 133 int value; 134 135 sc = device_get_softc(dev); 136 value = iicoc_dev_read(dev, OC_I2C_CTRL_REG); 137 iicoc_dev_write(dev, OC_I2C_CTRL_REG, 138 value & ~(OC_CONTROL_EN | OC_CONTROL_IEN)); 139 value = (sc->clockfreq/(5 * sc->i2cfreq)) - 1; 140 iicoc_dev_write(dev, OC_I2C_PRESCALE_LO_REG, value & 0xff); 141 iicoc_dev_write(dev, OC_I2C_PRESCALE_HI_REG, value >> 8); 142 value = iicoc_dev_read(dev, OC_I2C_CTRL_REG); 143 iicoc_dev_write(dev, OC_I2C_CTRL_REG, value | OC_CONTROL_EN); 144 145 value = iicoc_dev_read(dev, OC_I2C_CTRL_REG); 146 /* return 0 on success, 1 on error */ 147 return ((value & OC_CONTROL_EN) == 0); 148} 149 150int 151iicoc_iicbus_start(device_t dev, u_char slave, int timeout) 152{ 153 int error = IIC_EBUSERR; 154 struct iicoc_softc *sc; 155 156 sc = device_get_softc(dev); 157 mtx_lock(&sc->sc_mtx); 158 sc->i2cdev_addr = (slave >> 1); 159 160 /* Verify the bus is idle */ 161 if (iicoc_wait_on_status(dev, OC_STATUS_BUSY) < 0) 162 goto i2c_stx_error; 163 164 /* Write Slave Address */ 165 if (iicoc_wr_ack_cmd(dev, slave, OC_COMMAND_START)) { 166 device_printf(dev, 167 "I2C write slave address [0x%x] failed.\n", slave); 168 error = IIC_ENOACK; 169 goto i2c_stx_error; 170 } 171 172 /* Verify Arbitration is not Lost */ 173 if (iicoc_dev_read(dev, OC_I2C_STATUS_REG) & OC_STATUS_AL) { 174 device_printf(dev, "I2C Bus Arbitration Lost, Aborting.\n"); 175 error = IIC_EBUSERR; 176 goto i2c_stx_error; 177 } 178 error = IIC_NOERR; 179 mtx_unlock(&sc->sc_mtx); 180 return (error); 181 182i2c_stx_error: 183 iicoc_dev_write(dev, OC_I2C_CMD_REG, OC_COMMAND_STOP); 184 iicoc_wait_on_status(dev, OC_STATUS_BUSY); /* wait for idle */ 185 mtx_unlock(&sc->sc_mtx); 186 return (error); 187} 188 189int 190iicoc_iicbus_stop(device_t dev) 191{ 192 int error = 0; 193 struct iicoc_softc *sc; 194 195 sc = device_get_softc(dev); 196 mtx_lock(&sc->sc_mtx); 197 iicoc_dev_write(dev, OC_I2C_CMD_REG, OC_COMMAND_STOP); 198 iicoc_wait_on_status(dev, OC_STATUS_BUSY); /* wait for idle */ 199 mtx_unlock(&sc->sc_mtx); 200 return (error); 201} 202 203int 204iicoc_iicbus_write(device_t dev, const char *buf, int len, int *sent, 205 int timeout) 206{ 207 uint8_t value; 208 int i; 209 210 value = buf[0]; 211 /* Write Slave Offset */ 212 if (iicoc_wr_ack_cmd(dev, value, OC_COMMAND_WRITE)) { 213 device_printf(dev, "I2C write slave offset failed.\n"); 214 goto i2c_tx_error; 215 } 216 217 for (i = 1; i < len; i++) { 218 /* Write data byte */ 219 value = buf[i]; 220 if (iicoc_wr_cmd(dev, value, OC_COMMAND_WRITE)) { 221 device_printf(dev, "I2C write data byte %d failed.\n", 222 i); 223 goto i2c_tx_error; 224 } 225 } 226 *sent = len; 227 return (IIC_NOERR); 228 229i2c_tx_error: 230 return (IIC_EBUSERR); 231} 232 233int 234iicoc_iicbus_read(device_t dev, char *buf, int len, int *read, int last, 235 int delay) 236{ 237 int data, i; 238 uint8_t cmd; 239 240 for (i = 0; i < len; i++) { 241 /* Read data byte */ 242 cmd = (i == len - 1) ? OC_COMMAND_RDNACK : OC_COMMAND_READ; 243 data = iicoc_rd_cmd(dev, cmd); 244 if (data < 0) { 245 device_printf(dev, 246 "I2C read data byte %d failed.\n", i); 247 goto i2c_rx_error; 248 } 249 buf[i] = (uint8_t)data; 250 } 251 252 *read = len; 253 return (IIC_NOERR); 254 255i2c_rx_error: 256 return (IIC_EBUSERR); 257} 258 259int 260iicoc_iicbus_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr) 261{ 262 int error; 263 struct iicoc_softc *sc; 264 265 sc = device_get_softc(dev); 266 mtx_lock(&sc->sc_mtx); 267 error = iicoc_init(dev); 268 mtx_unlock(&sc->sc_mtx); 269 return (error); 270} 271 272int 273iicoc_iicbus_repeated_start(device_t dev, u_char slave, int timeout) 274{ 275 276 return 0; 277} 278