164562Sgshapiro/*- 2261370Sgshapiro * Copyright (c) 2003-2012 Broadcom Corporation 364562Sgshapiro * All Rights Reserved 464562Sgshapiro * 564562Sgshapiro * Redistribution and use in source and binary forms, with or without 664562Sgshapiro * modification, are permitted provided that the following conditions 764562Sgshapiro * are met: 864562Sgshapiro * 964562Sgshapiro * 1. Redistributions of source code must retain the above copyright 1064562Sgshapiro * notice, this list of conditions and the following disclaimer. 1164562Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright 1264562Sgshapiro * notice, this list of conditions and the following disclaimer in 13266711Sgshapiro * the documentation and/or other materials provided with the 1464562Sgshapiro * distribution. 1564562Sgshapiro * 1664562Sgshapiro * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR 1764562Sgshapiro * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1864562Sgshapiro * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1964562Sgshapiro * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE 2090792Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2190792Sgshapiro * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2290792Sgshapiro * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 2390792Sgshapiro * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2464562Sgshapiro * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 2564562Sgshapiro * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 2664562Sgshapiro * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2764562Sgshapiro */ 2864562Sgshapiro 2964562Sgshapiro#include <sys/cdefs.h> 3064562Sgshapiro__FBSDID("$FreeBSD: releng/10.3/sys/dev/iicbus/iicoc.c 294490 2016-01-21 08:32:11Z dumbbell $"); 3164562Sgshapiro 3264562Sgshapiro#include <sys/param.h> 3364562Sgshapiro#include <sys/systm.h> 3464562Sgshapiro#include <sys/kernel.h> 3564562Sgshapiro#include <sys/lock.h> 3664562Sgshapiro#include <sys/module.h> 3764562Sgshapiro#include <sys/mutex.h> 3864562Sgshapiro#include <sys/bus.h> 3964562Sgshapiro#include <sys/rman.h> 4064562Sgshapiro 4164562Sgshapiro#include <machine/bus.h> 4264562Sgshapiro 4364562Sgshapiro#include <dev/iicbus/iiconf.h> 4490792Sgshapiro#include <dev/iicbus/iicbus.h> 4564562Sgshapiro#include <dev/iicbus/iicoc.h> 4664562Sgshapiro 4764562Sgshapiro#include <dev/pci/pcireg.h> 4864562Sgshapiro#include <dev/pci/pcivar.h> 4964562Sgshapiro 5064562Sgshapiro#include "iicbus_if.h" 5164562Sgshapiro 5264562Sgshapirostatic devclass_t iicoc_devclass; 5364562Sgshapiro 5464562Sgshapiro/* 5564562Sgshapiro * Device methods 5664562Sgshapiro */ 5764562Sgshapirostatic int iicoc_probe(device_t); 58132943Sgshapirostatic int iicoc_attach(device_t); 5964562Sgshapirostatic int iicoc_detach(device_t); 6064562Sgshapiro 6164562Sgshapirostatic int iicoc_start(device_t dev, u_char slave, int timeout); 6264562Sgshapirostatic int iicoc_stop(device_t dev); 6364562Sgshapirostatic int iicoc_read(device_t dev, char *buf, 6464562Sgshapiro int len, int *read, int last, int delay); 6564562Sgshapirostatic int iicoc_write(device_t dev, const char *buf, 6664562Sgshapiro int len, int *sent, int timeout); 6764562Sgshapirostatic int iicoc_repeated_start(device_t dev, u_char slave, int timeout); 6890792Sgshapiro 6964562Sgshapirostruct iicoc_softc { 7064562Sgshapiro device_t dev; /* Self */ 7164562Sgshapiro u_int reg_shift; /* Chip specific */ 7264562Sgshapiro u_int clockfreq; 7364562Sgshapiro u_int i2cfreq; 7464562Sgshapiro struct resource *mem_res; /* Memory resource */ 7564562Sgshapiro int mem_rid; 7664562Sgshapiro int sc_started; 7790792Sgshapiro uint8_t i2cdev_addr; 7864562Sgshapiro device_t iicbus; 7964562Sgshapiro struct mtx sc_mtx; 8064562Sgshapiro}; 8164562Sgshapiro 8264562Sgshapirostatic void 8364562Sgshapiroiicoc_dev_write(device_t dev, int reg, int value) 8464562Sgshapiro{ 8564562Sgshapiro struct iicoc_softc *sc; 8664562Sgshapiro 8764562Sgshapiro sc = device_get_softc(dev); 8864562Sgshapiro bus_write_1(sc->mem_res, reg<<sc->reg_shift, value); 8964562Sgshapiro} 9064562Sgshapiro 9164562Sgshapirostatic int 9264562Sgshapiroiicoc_dev_read(device_t dev, int reg) 9364562Sgshapiro{ 9464562Sgshapiro uint8_t val; 9564562Sgshapiro struct iicoc_softc *sc; 9664562Sgshapiro 9764562Sgshapiro sc = device_get_softc(dev); 9864562Sgshapiro val = bus_read_1(sc->mem_res, reg<<sc->reg_shift); 9964562Sgshapiro return (val); 10064562Sgshapiro} 10164562Sgshapiro 10264562Sgshapirostatic int 10364562Sgshapiroiicoc_wait_on_status(device_t dev, uint8_t bit) 10464562Sgshapiro{ 10564562Sgshapiro int tries = I2C_TIMEOUT; 10690792Sgshapiro uint8_t status; 10764562Sgshapiro 10864562Sgshapiro do { 10964562Sgshapiro status = iicoc_dev_read(dev, OC_I2C_STATUS_REG); 11064562Sgshapiro } while ((status & bit) != 0 && --tries > 0); 11164562Sgshapiro 11264562Sgshapiro return (tries == 0 ? -1: 0); 11390792Sgshapiro} 11490792Sgshapiro 11590792Sgshapirostatic int 11690792Sgshapiroiicoc_rd_cmd(device_t dev, uint8_t cmd) 11790792Sgshapiro{ 11890792Sgshapiro uint8_t data; 11990792Sgshapiro 12090792Sgshapiro iicoc_dev_write(dev, OC_I2C_CMD_REG, cmd); 12190792Sgshapiro if (iicoc_wait_on_status(dev, OC_STATUS_TIP) < 0) { 12290792Sgshapiro device_printf(dev, "read: Timeout waiting for TIP clear.\n"); 12364562Sgshapiro return (-1); 12464562Sgshapiro } 12564562Sgshapiro data = iicoc_dev_read(dev, OC_I2C_DATA_REG); 12664562Sgshapiro return (data); 12790792Sgshapiro} 12890792Sgshapiro 12964562Sgshapirostatic int 13064562Sgshapiroiicoc_wr_cmd(device_t dev, uint8_t data, uint8_t cmd) 13190792Sgshapiro{ 13290792Sgshapiro 13390792Sgshapiro iicoc_dev_write(dev, OC_I2C_DATA_REG, data); 13490792Sgshapiro iicoc_dev_write(dev, OC_I2C_CMD_REG, cmd); 13564562Sgshapiro if (iicoc_wait_on_status(dev, OC_STATUS_TIP) < 0) { 136 device_printf(dev, "write: Timeout waiting for TIP clear.\n"); 137 return (-1); 138 } 139 return (0); 140} 141 142static int 143iicoc_wr_ack_cmd(device_t dev, uint8_t data, uint8_t cmd) 144{ 145 if (iicoc_wr_cmd(dev, data, cmd) < 0) 146 return (-1); 147 148 if (iicoc_dev_read(dev, OC_I2C_STATUS_REG) & OC_STATUS_NACK) { 149 device_printf(dev, "write: I2C command ACK Error.\n"); 150 return (IIC_ENOACK); 151 } 152 return (0); 153} 154 155static int 156iicoc_init(device_t dev) 157{ 158 struct iicoc_softc *sc; 159 int value; 160 161 sc = device_get_softc(dev); 162 value = iicoc_dev_read(dev, OC_I2C_CTRL_REG); 163 iicoc_dev_write(dev, OC_I2C_CTRL_REG, 164 value & ~(OC_CONTROL_EN | OC_CONTROL_IEN)); 165 value = (sc->clockfreq/(5 * sc->i2cfreq)) - 1; 166 iicoc_dev_write(dev, OC_I2C_PRESCALE_LO_REG, value & 0xff); 167 iicoc_dev_write(dev, OC_I2C_PRESCALE_HI_REG, value >> 8); 168 value = iicoc_dev_read(dev, OC_I2C_CTRL_REG); 169 iicoc_dev_write(dev, OC_I2C_CTRL_REG, value | OC_CONTROL_EN); 170 171 value = iicoc_dev_read(dev, OC_I2C_CTRL_REG); 172 /* return 0 on success, 1 on error */ 173 return ((value & OC_CONTROL_EN) == 0); 174} 175 176static int 177iicoc_probe(device_t dev) 178{ 179 struct iicoc_softc *sc; 180 181 sc = device_get_softc(dev); 182 if ((pci_get_vendor(dev) == 0x184e) && 183 (pci_get_device(dev) == 0x1011)) { 184 sc->clockfreq = XLP_I2C_CLKFREQ; 185 sc->i2cfreq = XLP_I2C_FREQ; 186 sc->reg_shift = 2; 187 device_set_desc(dev, "Netlogic XLP I2C Controller"); 188 return (BUS_PROBE_DEFAULT); 189 } 190 return (ENXIO); 191} 192 193 194/* 195 * We add all the devices which we know about. 196 * The generic attach routine will attach them if they are alive. 197 */ 198static int 199iicoc_attach(device_t dev) 200{ 201 int bus; 202 struct iicoc_softc *sc; 203 204 sc = device_get_softc(dev); 205 bus = device_get_unit(dev); 206 207 sc->dev = dev; 208 mtx_init(&sc->sc_mtx, "iicoc", "iicoc", MTX_DEF); 209 sc->mem_rid = 0; 210 sc->mem_res = bus_alloc_resource(dev, 211 SYS_RES_MEMORY, &sc->mem_rid, 0ul, ~0ul, 0x100, RF_ACTIVE); 212 213 if (sc->mem_res == NULL) { 214 device_printf(dev, "Could not allocate bus resource.\n"); 215 return (-1); 216 } 217 iicoc_init(dev); 218 sc->iicbus = device_add_child(dev, "iicbus", -1); 219 if (sc->iicbus == NULL) { 220 device_printf(dev, "Could not allocate iicbus instance.\n"); 221 return (-1); 222 } 223 bus_generic_attach(dev); 224 225 return (0); 226} 227 228static int 229iicoc_detach(device_t dev) 230{ 231 bus_generic_detach(dev); 232 device_delete_children(dev); 233 234 return (0); 235} 236 237static int 238iicoc_start(device_t dev, u_char slave, int timeout) 239{ 240 int error = IIC_EBUSERR; 241 struct iicoc_softc *sc; 242 243 sc = device_get_softc(dev); 244 mtx_lock(&sc->sc_mtx); 245 sc->i2cdev_addr = (slave >> 1); 246 247 /* Verify the bus is idle */ 248 if (iicoc_wait_on_status(dev, OC_STATUS_BUSY) < 0) 249 goto i2c_stx_error; 250 251 /* Write Slave Address */ 252 if (iicoc_wr_ack_cmd(dev, slave, OC_COMMAND_START)) { 253 device_printf(dev, 254 "I2C write slave address [0x%x] failed.\n", slave); 255 error = IIC_ENOACK; 256 goto i2c_stx_error; 257 } 258 259 /* Verify Arbitration is not Lost */ 260 if (iicoc_dev_read(dev, OC_I2C_STATUS_REG) & OC_STATUS_AL) { 261 device_printf(dev, "I2C Bus Arbitration Lost, Aborting.\n"); 262 error = IIC_EBUSERR; 263 goto i2c_stx_error; 264 } 265 error = IIC_NOERR; 266 mtx_unlock(&sc->sc_mtx); 267 return (error); 268i2c_stx_error: 269 iicoc_dev_write(dev, OC_I2C_CMD_REG, OC_COMMAND_STOP); 270 iicoc_wait_on_status(dev, OC_STATUS_BUSY); /* wait for idle */ 271 mtx_unlock(&sc->sc_mtx); 272 return (error); 273} 274 275static int 276iicoc_stop(device_t dev) 277{ 278 int error = 0; 279 struct iicoc_softc *sc; 280 281 sc = device_get_softc(dev); 282 mtx_lock(&sc->sc_mtx); 283 iicoc_dev_write(dev, OC_I2C_CMD_REG, OC_COMMAND_STOP); 284 iicoc_wait_on_status(dev, OC_STATUS_BUSY); /* wait for idle */ 285 mtx_unlock(&sc->sc_mtx); 286 return (error); 287 288} 289 290static int 291iicoc_write(device_t dev, const char *buf, int len, 292 int *sent, int timeout /* us */ ) 293{ 294 uint8_t value; 295 int i; 296 297 value = buf[0]; 298 /* Write Slave Offset */ 299 if (iicoc_wr_ack_cmd(dev, value, OC_COMMAND_WRITE)) { 300 device_printf(dev, "I2C write slave offset failed.\n"); 301 goto i2c_tx_error; 302 } 303 304 for (i = 1; i < len; i++) { 305 /* Write data byte */ 306 value = buf[i]; 307 if (iicoc_wr_cmd(dev, value, OC_COMMAND_WRITE)) { 308 device_printf(dev, "I2C write data byte %d failed.\n", 309 i); 310 goto i2c_tx_error; 311 } 312 } 313 *sent = len; 314 return (IIC_NOERR); 315 316i2c_tx_error: 317 return (IIC_EBUSERR); 318} 319 320static int 321iicoc_read(device_t dev, char *buf, int len, int *read, int last, 322 int delay) 323{ 324 int data, i; 325 uint8_t cmd; 326 327 for (i = 0; i < len; i++) { 328 /* Read data byte */ 329 cmd = (i == len - 1) ? OC_COMMAND_RDNACK : OC_COMMAND_READ; 330 data = iicoc_rd_cmd(dev, cmd); 331 if (data < 0) { 332 device_printf(dev, 333 "I2C read data byte %d failed.\n", i); 334 goto i2c_rx_error; 335 } 336 buf[i] = (uint8_t)data; 337 } 338 339 *read = len; 340 return (IIC_NOERR); 341 342i2c_rx_error: 343 return (IIC_EBUSERR); 344} 345 346static int 347iicoc_reset(device_t dev, u_char speed, u_char addr, u_char *oldadr) 348{ 349 int error; 350 struct iicoc_softc *sc; 351 352 sc = device_get_softc(dev); 353 mtx_lock(&sc->sc_mtx); 354 error = iicoc_init(dev); 355 mtx_unlock(&sc->sc_mtx); 356 return (error); 357} 358 359static int 360iicoc_repeated_start(device_t dev, u_char slave, int timeout) 361{ 362 return 0; 363} 364 365static device_method_t iicoc_methods[] = { 366 /* device interface */ 367 DEVMETHOD(device_probe, iicoc_probe), 368 DEVMETHOD(device_attach, iicoc_attach), 369 DEVMETHOD(device_detach, iicoc_detach), 370 371 /* iicbus interface */ 372 DEVMETHOD(iicbus_callback, iicbus_null_callback), 373 DEVMETHOD(iicbus_repeated_start, iicoc_repeated_start), 374 DEVMETHOD(iicbus_start, iicoc_start), 375 DEVMETHOD(iicbus_stop, iicoc_stop), 376 DEVMETHOD(iicbus_reset, iicoc_reset), 377 DEVMETHOD(iicbus_write, iicoc_write), 378 DEVMETHOD(iicbus_read, iicoc_read), 379 DEVMETHOD(iicbus_transfer, iicbus_transfer_gen), 380 381 DEVMETHOD_END 382}; 383 384static driver_t iicoc_driver = { 385 "iicoc", 386 iicoc_methods, 387 sizeof(struct iicoc_softc), 388}; 389 390DRIVER_MODULE(iicoc, pci, iicoc_driver, iicoc_devclass, 0, 0); 391DRIVER_MODULE(iicbus, iicoc, iicbus_driver, iicbus_devclass, 0, 0); 392