1 /* $OpenBSD: mpfiic.c,v 1.1 2022/02/16 13:07:36 visa Exp $ */ 2 3 /* 4 * Copyright (c) 2022 Visa Hankala 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 * Driver for PolarFire SoC MSS I2C controller. 21 */ 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/device.h> 26 #include <sys/malloc.h> 27 28 #include <machine/bus.h> 29 #include <machine/fdt.h> 30 31 #define _I2C_PRIVATE 32 #include <dev/i2c/i2cvar.h> 33 34 #include <dev/ofw/fdt.h> 35 #include <dev/ofw/openfirm.h> 36 #include <dev/ofw/ofw_clock.h> 37 #include <dev/ofw/ofw_misc.h> 38 39 #define I2C_CTRL 0x0000 40 #define I2C_CTRL_CR2 (1 << 7) 41 #define I2C_CTRL_ENS1 (1 << 6) 42 #define I2C_CTRL_STA (1 << 5) 43 #define I2C_CTRL_STO (1 << 4) 44 #define I2C_CTRL_SI (1 << 3) 45 #define I2C_CTRL_AA (1 << 2) 46 #define I2C_CTRL_CR1 (1 << 1) 47 #define I2C_CTRL_CR0 (1 << 0) 48 #define I2C_STATUS 0x0004 49 #define I2C_DATA 0x0008 50 #define I2C_SLAVE0ADR 0x000c 51 #define I2C_SMBUS 0x0010 52 #define I2C_FREQ 0x0014 53 #define I2C_GLITCHREG 0x0018 54 #define I2C_SLAVE1ADR 0x001c 55 56 #define I2C_STATUS_START 0x08 57 #define I2C_STATUS_RESTART 0x10 58 #define I2C_STATUS_SLAW_ACK 0x18 59 #define I2C_STATUS_DATAW_ACK 0x28 60 #define I2C_STATUS_LOSTARB 0x38 61 #define I2C_STATUS_SLAR_ACK 0x40 62 #define I2C_STATUS_DATAR_ACK 0x50 63 #define I2C_STATUS_DATAR_NACK 0x58 64 #define I2C_STATUS_IDLE 0xf8 65 66 struct mpfiic_softc { 67 struct device sc_dev; 68 bus_space_tag_t sc_iot; 69 bus_space_handle_t sc_ioh; 70 int sc_node; 71 72 struct i2c_bus sc_i2c_bus; 73 struct i2c_controller sc_i2c_tag; 74 struct rwlock sc_i2c_lock; 75 76 uint32_t sc_bus_freq; /* in Hz */ 77 uint8_t sc_ctrl; 78 uint8_t sc_start_sent; 79 }; 80 81 #define HREAD4(sc, reg) \ 82 (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) 83 #define HWRITE4(sc, reg, val) \ 84 bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) 85 86 int mpfiic_match(struct device *, void *, void*); 87 void mpfiic_attach(struct device *, struct device *, void *); 88 89 int mpfiic_i2c_acquire_bus(void *, int); 90 void mpfiic_i2c_release_bus(void *, int); 91 int mpfiic_i2c_send_start(void *, int); 92 int mpfiic_i2c_send_stop(void *, int); 93 int mpfiic_i2c_initiate_xfer(void *, i2c_addr_t, int); 94 int mpfiic_i2c_read_byte(void *, uint8_t *, int); 95 int mpfiic_i2c_write_byte(void *, uint8_t, int); 96 void mpfiic_i2c_scan(struct device *, struct i2cbus_attach_args *, void *); 97 98 int mpfiic_wait(struct mpfiic_softc *, uint8_t); 99 100 const struct cfattach mpfiic_ca = { 101 sizeof(struct mpfiic_softc), mpfiic_match, mpfiic_attach 102 }; 103 104 struct cfdriver mpfiic_cd = { 105 NULL, "mpfiic", DV_DULL 106 }; 107 108 static struct { 109 uint32_t div; 110 uint32_t cr; 111 } mpfiic_clk_divs[] = { 112 #ifdef notused 113 /* BCLK */ 114 { 8, I2C_CTRL_CR2 | I2C_CTRL_CR1 | I2C_CTRL_CR0 }, 115 #endif 116 /* PCLK */ 117 { 60, I2C_CTRL_CR2 | I2C_CTRL_CR1 }, 118 { 120, I2C_CTRL_CR2 | I2C_CTRL_CR0 }, 119 { 160, I2C_CTRL_CR1 | I2C_CTRL_CR0 }, 120 { 192, I2C_CTRL_CR1 }, 121 { 224, I2C_CTRL_CR0 }, 122 { 256, 0 }, 123 { 960, I2C_CTRL_CR2 }, 124 }; 125 126 int 127 mpfiic_match(struct device *parent, void *match, void *aux) 128 { 129 struct fdt_attach_args *faa = aux; 130 131 if (faa->fa_nreg < 1) 132 return 0; 133 return OF_is_compatible(faa->fa_node, "microchip,mpfs-i2c"); 134 } 135 136 void 137 mpfiic_attach(struct device *parent, struct device *self, void *aux) 138 { 139 struct i2cbus_attach_args iba; 140 struct fdt_attach_args *faa = aux; 141 struct mpfiic_softc *sc = (struct mpfiic_softc *)self; 142 uint32_t i, bus_freq, clock_freq; 143 144 sc->sc_node = faa->fa_node; 145 sc->sc_iot = faa->fa_iot; 146 147 clock_freq = clock_get_frequency(sc->sc_node, NULL); 148 bus_freq = OF_getpropint(sc->sc_node, "clock-frequency", 100000); 149 150 /* Determine clock divider, assumes PCLK. */ 151 for (i = 0; i < nitems(mpfiic_clk_divs) - 1; i++) { 152 if (clock_freq / mpfiic_clk_divs[i].div <= bus_freq) 153 break; 154 } 155 sc->sc_bus_freq = clock_freq / mpfiic_clk_divs[i].div; 156 sc->sc_ctrl = mpfiic_clk_divs[i].cr | I2C_CTRL_ENS1; 157 158 if (sc->sc_bus_freq == 0) { 159 printf(": invalid bus frequency\n"); 160 return; 161 } 162 163 if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, faa->fa_reg[0].size, 164 0, &sc->sc_ioh) != 0) { 165 printf(": can't map registers\n"); 166 return; 167 } 168 169 clock_enable_all(sc->sc_node); 170 171 /* Initialize the device. */ 172 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl); 173 HWRITE4(sc, I2C_CTRL, 0); 174 175 /* Disable slave address comparison. */ 176 HWRITE4(sc, I2C_SLAVE0ADR, 0); 177 HWRITE4(sc, I2C_SLAVE1ADR, 0); 178 179 /* Disable SMBus logic, operate in standard I2C mode. */ 180 HWRITE4(sc, I2C_SMBUS, 0); 181 182 printf("\n"); 183 184 rw_init(&sc->sc_i2c_lock, "iiclk"); 185 sc->sc_i2c_tag.ic_cookie = sc; 186 sc->sc_i2c_tag.ic_acquire_bus = mpfiic_i2c_acquire_bus; 187 sc->sc_i2c_tag.ic_release_bus = mpfiic_i2c_release_bus; 188 sc->sc_i2c_tag.ic_send_start = mpfiic_i2c_send_start; 189 sc->sc_i2c_tag.ic_send_stop = mpfiic_i2c_send_stop; 190 sc->sc_i2c_tag.ic_initiate_xfer = mpfiic_i2c_initiate_xfer; 191 sc->sc_i2c_tag.ic_read_byte = mpfiic_i2c_read_byte; 192 sc->sc_i2c_tag.ic_write_byte = mpfiic_i2c_write_byte; 193 194 memset(&iba, 0, sizeof(iba)); 195 iba.iba_name = "iic"; 196 iba.iba_tag = &sc->sc_i2c_tag; 197 iba.iba_bus_scan = mpfiic_i2c_scan; 198 iba.iba_bus_scan_arg = &sc->sc_node; 199 config_found(self, &iba, iicbus_print); 200 201 sc->sc_i2c_bus.ib_node = faa->fa_node; 202 sc->sc_i2c_bus.ib_ic = &sc->sc_i2c_tag; 203 i2c_register(&sc->sc_i2c_bus); 204 } 205 206 int 207 mpfiic_i2c_acquire_bus(void *arg, int flags) 208 { 209 struct mpfiic_softc *sc = arg; 210 211 if (cold || (flags & I2C_F_POLL)) 212 return 0; 213 214 return rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR); 215 } 216 217 void 218 mpfiic_i2c_release_bus(void *arg, int flags) 219 { 220 struct mpfiic_softc *sc = arg; 221 222 if (cold || (flags & I2C_F_POLL)) 223 return; 224 225 rw_exit(&sc->sc_i2c_lock); 226 } 227 228 int 229 mpfiic_i2c_send_start(void *cookie, int flags) 230 { 231 struct mpfiic_softc *sc = cookie; 232 int error; 233 uint8_t nstatus; 234 235 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | I2C_CTRL_STA); 236 237 if (sc->sc_start_sent) 238 nstatus = I2C_STATUS_RESTART; 239 else 240 nstatus = I2C_STATUS_START; 241 error = mpfiic_wait(sc, nstatus); 242 if (error != 0) 243 return error; 244 245 sc->sc_start_sent = 1; 246 247 return 0; 248 } 249 250 int 251 mpfiic_i2c_send_stop(void *cookie, int flags) 252 { 253 struct mpfiic_softc *sc = cookie; 254 255 sc->sc_start_sent = 0; 256 257 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | I2C_CTRL_STO); 258 259 /* Let a few bus clock cycles pass. */ 260 delay(4 * 1000000 / sc->sc_bus_freq); 261 262 /* Disable the device. This resets the state machine. */ 263 HWRITE4(sc, I2C_CTRL, 0); 264 265 return 0; 266 } 267 268 int 269 mpfiic_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) 270 { 271 struct mpfiic_softc *sc = cookie; 272 int error; 273 uint8_t mode, nstatus; 274 275 if (addr >= 0x80) 276 return EINVAL; 277 278 error = mpfiic_i2c_send_start(sc, flags); 279 if (error != 0) 280 return error; 281 282 if (flags & I2C_F_READ) { 283 mode = 0x01; 284 nstatus = I2C_STATUS_SLAR_ACK; 285 } else { 286 mode = 0x00; 287 nstatus = I2C_STATUS_SLAW_ACK; 288 } 289 290 HWRITE4(sc, I2C_DATA, (addr << 1) | mode); 291 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl); 292 293 return mpfiic_wait(sc, nstatus); 294 } 295 296 int 297 mpfiic_i2c_read_byte(void *cookie, uint8_t *datap, int flags) 298 { 299 struct mpfiic_softc *sc = cookie; 300 int error; 301 uint8_t ack = 0, nstatus; 302 303 if ((flags & I2C_F_LAST) == 0) 304 ack = I2C_CTRL_AA; 305 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl | ack); 306 307 if (flags & I2C_F_LAST) 308 nstatus = I2C_STATUS_DATAR_NACK; 309 else 310 nstatus = I2C_STATUS_DATAR_ACK; 311 error = mpfiic_wait(sc, nstatus); 312 if (error != 0) 313 return error; 314 315 *datap = HREAD4(sc, I2C_DATA); 316 317 if (flags & I2C_F_STOP) 318 error = mpfiic_i2c_send_stop(sc, flags); 319 320 return error; 321 } 322 323 int 324 mpfiic_i2c_write_byte(void *cookie, uint8_t data, int flags) 325 { 326 struct mpfiic_softc *sc = cookie; 327 int error; 328 329 HWRITE4(sc, I2C_DATA, data); 330 HWRITE4(sc, I2C_CTRL, sc->sc_ctrl); 331 332 error = mpfiic_wait(sc, I2C_STATUS_DATAW_ACK); 333 if (error != 0) 334 return error; 335 336 if (flags & I2C_F_STOP) 337 error = mpfiic_i2c_send_stop(sc, flags); 338 339 return error; 340 } 341 342 void 343 mpfiic_i2c_scan(struct device *self, struct i2cbus_attach_args *iba, void *arg) 344 { 345 struct i2c_attach_args ia; 346 char status[32]; 347 char *compat; 348 uint32_t reg[1]; 349 int iba_node = *(int *)arg; 350 int len, node; 351 352 for (node = OF_child(iba_node); node != 0; node = OF_peer(node)) { 353 memset(status, 0, sizeof(status)); 354 if (OF_getprop(node, "status", status, sizeof(status)) > 0 && 355 strcmp(status, "disabled") == 0) 356 continue; 357 358 memset(reg, 0, sizeof(reg)); 359 if (OF_getprop(node, "reg", ®, sizeof(reg)) != sizeof(reg)) 360 continue; 361 362 len = OF_getproplen(node, "compatible"); 363 if (len <= 0) 364 continue; 365 366 compat = malloc(len, M_TEMP, M_WAITOK); 367 OF_getprop(node, "compatible", compat, len); 368 369 memset(&ia, 0, sizeof(ia)); 370 ia.ia_tag = iba->iba_tag; 371 ia.ia_addr = bemtoh32(®[0]); 372 ia.ia_name = compat; 373 ia.ia_namelen = len; 374 ia.ia_cookie = &node; 375 config_found(self, &ia, iic_print); 376 377 free(compat, M_TEMP, len); 378 } 379 } 380 381 int 382 mpfiic_wait(struct mpfiic_softc *sc, uint8_t nstatus) 383 { 384 int timeout; 385 uint8_t ctrl, status; 386 387 for (timeout = 100000; timeout > 0; timeout--) { 388 ctrl = HREAD4(sc, I2C_CTRL); 389 if (ctrl & I2C_CTRL_SI) 390 break; 391 delay(1); 392 } 393 if (timeout == 0) 394 return ETIMEDOUT; 395 396 status = HREAD4(sc, I2C_STATUS); 397 if (status != nstatus) 398 return EIO; 399 400 return 0; 401 } 402