1 1.17 thorpej /* $NetBSD: ausmbus_psc.c,v 1.17 2025/09/15 13:23:02 thorpej Exp $ */ 2 1.1 shige 3 1.1 shige /*- 4 1.1 shige * Copyright (c) 2006 Shigeyuki Fukushima. 5 1.1 shige * All rights reserved. 6 1.1 shige * 7 1.1 shige * Written by Shigeyuki Fukushima. 8 1.1 shige * 9 1.1 shige * Redistribution and use in source and binary forms, with or without 10 1.1 shige * modification, are permitted provided that the following conditions 11 1.1 shige * are met: 12 1.1 shige * 1. Redistributions of source code must retain the above copyright 13 1.1 shige * notice, this list of conditions and the following disclaimer. 14 1.1 shige * 2. Redistributions in binary form must reproduce the above 15 1.1 shige * copyright notice, this list of conditions and the following 16 1.1 shige * disclaimer in the documentation and/or other materials provided 17 1.1 shige * with the distribution. 18 1.1 shige * 3. The name of the author may not be used to endorse or promote 19 1.1 shige * products derived from this software without specific prior 20 1.1 shige * written permission. 21 1.1 shige * 22 1.1 shige * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 23 1.1 shige * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 1.1 shige * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 1.1 shige * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 26 1.1 shige * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 1.1 shige * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 28 1.1 shige * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 1.1 shige * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 30 1.1 shige * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 1.1 shige * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 1.1 shige * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 1.1 shige */ 34 1.1 shige 35 1.1 shige #include <sys/cdefs.h> 36 1.17 thorpej __KERNEL_RCSID(0, "$NetBSD: ausmbus_psc.c,v 1.17 2025/09/15 13:23:02 thorpej Exp $"); 37 1.1 shige 38 1.1 shige #include "locators.h" 39 1.1 shige 40 1.1 shige #include <sys/param.h> 41 1.1 shige #include <sys/systm.h> 42 1.1 shige #include <sys/device.h> 43 1.1 shige #include <sys/errno.h> 44 1.1 shige 45 1.10 dyoung #include <sys/bus.h> 46 1.1 shige #include <machine/cpu.h> 47 1.1 shige 48 1.1 shige #include <mips/alchemy/dev/aupscreg.h> 49 1.1 shige #include <mips/alchemy/dev/aupscvar.h> 50 1.3 shige #include <mips/alchemy/dev/ausmbus_pscreg.h> 51 1.1 shige 52 1.1 shige #include <dev/i2c/i2cvar.h> 53 1.1 shige #include <dev/i2c/i2c_bitbang.h> 54 1.1 shige 55 1.1 shige struct ausmbus_softc { 56 1.11 kiyohara device_t sc_dev; 57 1.1 shige 58 1.1 shige /* protocol comoon fields */ 59 1.1 shige struct aupsc_controller sc_ctrl; 60 1.1 shige 61 1.1 shige /* protocol specific fields */ 62 1.1 shige struct i2c_controller sc_i2c; 63 1.1 shige i2c_addr_t sc_smbus_slave_addr; 64 1.1 shige int sc_smbus_timeout; 65 1.1 shige }; 66 1.1 shige 67 1.1 shige #define ausmbus_reg_read(sc, reg) \ 68 1.1 shige bus_space_read_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush, reg) 69 1.1 shige #define ausmbus_reg_write(sc, reg, val) \ 70 1.4 shige bus_space_write_4(sc->sc_ctrl.psc_bust, sc->sc_ctrl.psc_bush, reg, \ 71 1.4 shige val); \ 72 1.4 shige delay(100); 73 1.1 shige 74 1.11 kiyohara static int ausmbus_match(device_t, struct cfdata *, void *); 75 1.11 kiyohara static void ausmbus_attach(device_t, device_t, void *); 76 1.1 shige 77 1.11 kiyohara CFATTACH_DECL_NEW(ausmbus, sizeof(struct ausmbus_softc), 78 1.1 shige ausmbus_match, ausmbus_attach, NULL, NULL); 79 1.1 shige 80 1.16 andvar /* functions for i2c_controller */ 81 1.1 shige static int ausmbus_acquire_bus(void *, int); 82 1.1 shige static void ausmbus_release_bus(void *, int); 83 1.1 shige static int ausmbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, 84 1.1 shige const void *cmd, size_t cmdlen, void *vbuf, 85 1.1 shige size_t buflen, int flags); 86 1.1 shige 87 1.1 shige /* subroutine functions for i2c_controller */ 88 1.9 pgoyette static int ausmbus_quick_write(struct ausmbus_softc *); 89 1.9 pgoyette static int ausmbus_quick_read(struct ausmbus_softc *); 90 1.1 shige static int ausmbus_receive_1(struct ausmbus_softc *, uint8_t *); 91 1.1 shige static int ausmbus_read_1(struct ausmbus_softc *, uint8_t, uint8_t *); 92 1.5 kiyohara static int ausmbus_read_2(struct ausmbus_softc *, uint8_t, uint16_t *); 93 1.1 shige static int ausmbus_send_1(struct ausmbus_softc *, uint8_t); 94 1.1 shige static int ausmbus_write_1(struct ausmbus_softc *, uint8_t, uint8_t); 95 1.5 kiyohara static int ausmbus_write_2(struct ausmbus_softc *, uint8_t, uint16_t); 96 1.1 shige static int ausmbus_wait_mastertx(struct ausmbus_softc *sc); 97 1.1 shige static int ausmbus_wait_masterrx(struct ausmbus_softc *sc); 98 1.1 shige static int ausmbus_initiate_xfer(void *, i2c_addr_t, int); 99 1.1 shige static int ausmbus_read_byte(void *arg, uint8_t *vp, int flags); 100 1.1 shige static int ausmbus_write_byte(void *arg, uint8_t v, int flags); 101 1.1 shige 102 1.1 shige 103 1.1 shige static int 104 1.11 kiyohara ausmbus_match(device_t parent, struct cfdata *cf, void *aux) 105 1.1 shige { 106 1.1 shige struct aupsc_attach_args *aa = (struct aupsc_attach_args *)aux; 107 1.1 shige 108 1.1 shige if (strcmp(aa->aupsc_name, cf->cf_name) != 0) 109 1.1 shige return 0; 110 1.1 shige 111 1.1 shige return 1; 112 1.1 shige } 113 1.1 shige 114 1.1 shige static void 115 1.11 kiyohara ausmbus_attach(device_t parent, device_t self, void *aux) 116 1.1 shige { 117 1.11 kiyohara struct ausmbus_softc *sc = device_private(self); 118 1.1 shige struct aupsc_attach_args *aa = (struct aupsc_attach_args *)aux; 119 1.1 shige 120 1.1 shige aprint_normal(": Alchemy PSC SMBus protocol\n"); 121 1.1 shige 122 1.11 kiyohara sc->sc_dev = self; 123 1.11 kiyohara 124 1.1 shige /* Initialize PSC */ 125 1.1 shige sc->sc_ctrl = aa->aupsc_ctrl; 126 1.1 shige 127 1.1 shige /* Initialize i2c_controller for SMBus */ 128 1.13 thorpej iic_tag_init(&sc->sc_i2c); 129 1.1 shige sc->sc_i2c.ic_cookie = sc; 130 1.1 shige sc->sc_i2c.ic_acquire_bus = ausmbus_acquire_bus; 131 1.1 shige sc->sc_i2c.ic_release_bus = ausmbus_release_bus; 132 1.1 shige sc->sc_i2c.ic_exec = ausmbus_exec; 133 1.1 shige sc->sc_smbus_timeout = 10; 134 1.7 kiyohara 135 1.17 thorpej iicbus_attach(self, &sc->sc_i2c); 136 1.1 shige } 137 1.1 shige 138 1.1 shige static int 139 1.1 shige ausmbus_acquire_bus(void *arg, int flags) 140 1.1 shige { 141 1.1 shige struct ausmbus_softc *sc = arg; 142 1.1 shige uint32_t v; 143 1.1 shige 144 1.1 shige /* Select SMBus Protocol & Enable PSC */ 145 1.1 shige sc->sc_ctrl.psc_enable(sc, AUPSC_SEL_SMBUS); 146 1.1 shige v = ausmbus_reg_read(sc, AUPSC_SMBSTAT); 147 1.1 shige if ((v & SMBUS_STAT_SR) == 0) { 148 1.1 shige /* PSC is not ready */ 149 1.1 shige return -1; 150 1.1 shige } 151 1.1 shige 152 1.1 shige /* Setup SMBus Configuration register */ 153 1.1 shige v = SMBUS_CFG_DD; /* Disable DMA */ 154 1.1 shige v |= SMBUS_CFG_RT_SET(SMBUS_CFG_RT_FIFO8); /* Rx FIFO 8data */ 155 1.1 shige v |= SMBUS_CFG_TT_SET(SMBUS_CFG_TT_FIFO8); /* Tx FIFO 8data */ 156 1.1 shige v |= SMBUS_CFG_DIV_SET(SMBUS_CFG_DIV8); /* pscn_mainclk/8 */ 157 1.1 shige v &= ~SMBUS_CFG_SFM; /* Standard Mode */ 158 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBCFG, v); 159 1.1 shige 160 1.1 shige /* Setup SMBus Protocol Timing register */ 161 1.1 shige v = SMBUS_TMR_TH_SET(SMBUS_TMR_STD_TH) 162 1.1 shige | SMBUS_TMR_PS_SET(SMBUS_TMR_STD_PS) 163 1.1 shige | SMBUS_TMR_PU_SET(SMBUS_TMR_STD_PU) 164 1.1 shige | SMBUS_TMR_SH_SET(SMBUS_TMR_STD_SH) 165 1.1 shige | SMBUS_TMR_SU_SET(SMBUS_TMR_STD_SU) 166 1.1 shige | SMBUS_TMR_CL_SET(SMBUS_TMR_STD_CL) 167 1.1 shige | SMBUS_TMR_CH_SET(SMBUS_TMR_STD_CH); 168 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBTMR, v); 169 1.1 shige 170 1.1 shige /* Setup SMBus Mask register */ 171 1.1 shige v = SMBUS_MSK_ALLMASK; 172 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBMSK, v); 173 1.1 shige 174 1.1 shige /* SMBus Enable */ 175 1.1 shige v = ausmbus_reg_read(sc, AUPSC_SMBCFG); 176 1.1 shige v |= SMBUS_CFG_DE; 177 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBCFG, v); 178 1.1 shige v = ausmbus_reg_read(sc, AUPSC_SMBSTAT); 179 1.1 shige if ((v & SMBUS_STAT_SR) == 0) { 180 1.1 shige /* SMBus is not ready */ 181 1.1 shige return -1; 182 1.1 shige } 183 1.1 shige 184 1.1 shige #ifdef AUSMBUS_PSC_DEBUG 185 1.1 shige aprint_normal("AuSMBus enabled.\n"); 186 1.1 shige aprint_normal("AuSMBus smbconfig: 0x%08x\n", 187 1.1 shige ausmbus_reg_read(sc, AUPSC_SMBCFG)); 188 1.1 shige aprint_normal("AuSMBus smbstatus: 0x%08x\n", 189 1.1 shige ausmbus_reg_read(sc, AUPSC_SMBSTAT)); 190 1.1 shige aprint_normal("AuSMBus smbtmr : 0x%08x\n", 191 1.1 shige ausmbus_reg_read(sc, AUPSC_SMBTMR)); 192 1.1 shige aprint_normal("AuSMBus smbmask : 0x%08x\n", 193 1.1 shige ausmbus_reg_read(sc, AUPSC_SMBMSK)); 194 1.1 shige #endif 195 1.1 shige 196 1.1 shige return 0; 197 1.1 shige } 198 1.1 shige 199 1.1 shige static void 200 1.1 shige ausmbus_release_bus(void *arg, int flags) 201 1.1 shige { 202 1.1 shige struct ausmbus_softc *sc = arg; 203 1.1 shige 204 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBCFG, 0); 205 1.1 shige sc->sc_ctrl.psc_disable(sc); 206 1.1 shige 207 1.1 shige return; 208 1.1 shige } 209 1.1 shige 210 1.1 shige static int 211 1.1 shige ausmbus_exec(void *cookie, i2c_op_t op, i2c_addr_t addr, const void *vcmd, 212 1.1 shige size_t cmdlen, void *vbuf, size_t buflen, int flags) 213 1.1 shige { 214 1.1 shige struct ausmbus_softc *sc = (struct ausmbus_softc *)cookie; 215 1.1 shige const uint8_t *cmd = vcmd; 216 1.1 shige 217 1.1 shige sc->sc_smbus_slave_addr = addr; 218 1.1 shige 219 1.1 shige /* Receive byte */ 220 1.1 shige if ((I2C_OP_READ_P(op)) && (cmdlen == 0) && (buflen == 1)) { 221 1.5 kiyohara return ausmbus_receive_1(sc, (uint8_t *)vbuf); 222 1.1 shige } 223 1.1 shige 224 1.1 shige /* Read byte */ 225 1.1 shige if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 1)) { 226 1.5 kiyohara return ausmbus_read_1(sc, *cmd, (uint8_t *)vbuf); 227 1.5 kiyohara } 228 1.5 kiyohara 229 1.5 kiyohara /* Read word */ 230 1.5 kiyohara if ((I2C_OP_READ_P(op)) && (cmdlen == 1) && (buflen == 2)) { 231 1.5 kiyohara return ausmbus_read_2(sc, *cmd, (uint16_t *)vbuf); 232 1.1 shige } 233 1.1 shige 234 1.9 pgoyette /* Read quick */ 235 1.9 pgoyette if ((I2C_OP_READ_P(op)) && (cmdlen == 0) && (buflen == 0)) { 236 1.9 pgoyette return ausmbus_quick_read(sc); 237 1.9 pgoyette } 238 1.9 pgoyette 239 1.1 shige /* Send byte */ 240 1.1 shige if ((I2C_OP_WRITE_P(op)) && (cmdlen == 0) && (buflen == 1)) { 241 1.5 kiyohara return ausmbus_send_1(sc, *((uint8_t *)vbuf)); 242 1.1 shige } 243 1.1 shige 244 1.1 shige /* Write byte */ 245 1.1 shige if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 1)) { 246 1.5 kiyohara return ausmbus_write_1(sc, *cmd, *((uint8_t *)vbuf)); 247 1.5 kiyohara } 248 1.5 kiyohara 249 1.5 kiyohara /* Write word */ 250 1.5 kiyohara if ((I2C_OP_WRITE_P(op)) && (cmdlen == 1) && (buflen == 2)) { 251 1.5 kiyohara return ausmbus_write_2(sc, *cmd, *((uint16_t *)vbuf)); 252 1.1 shige } 253 1.1 shige 254 1.9 pgoyette /* Write quick */ 255 1.9 pgoyette if ((I2C_OP_WRITE_P(op)) && (cmdlen == 0) && (buflen == 0)) { 256 1.9 pgoyette return ausmbus_quick_write(sc); 257 1.9 pgoyette } 258 1.9 pgoyette 259 1.1 shige /* 260 1.7 kiyohara * XXX: TODO Please Support other protocols defined in SMBus 2.0 261 1.1 shige * - Process call 262 1.1 shige * - Block write/read 263 1.1 shige * - Clock write-block read process cal 264 1.1 shige * - SMBus host notify protocol 265 1.9 pgoyette * 266 1.9 pgoyette * - Read quick and write quick have not been tested! 267 1.1 shige */ 268 1.1 shige 269 1.1 shige return -1; 270 1.1 shige } 271 1.1 shige 272 1.1 shige static int 273 1.1 shige ausmbus_receive_1(struct ausmbus_softc *sc, uint8_t *vp) 274 1.1 shige { 275 1.1 shige int error; 276 1.1 shige 277 1.1 shige error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_READ); 278 1.1 shige if (error != 0) { 279 1.1 shige return error; 280 1.1 shige } 281 1.1 shige error = ausmbus_read_byte(sc, vp, I2C_F_STOP); 282 1.1 shige if (error != 0) { 283 1.1 shige return error; 284 1.1 shige } 285 1.1 shige 286 1.1 shige return 0; 287 1.1 shige } 288 1.1 shige 289 1.1 shige static int 290 1.1 shige ausmbus_read_1(struct ausmbus_softc *sc, uint8_t cmd, uint8_t *vp) 291 1.1 shige { 292 1.1 shige int error; 293 1.1 shige 294 1.1 shige error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_WRITE); 295 1.1 shige if (error != 0) { 296 1.1 shige return error; 297 1.1 shige } 298 1.1 shige 299 1.1 shige error = ausmbus_write_byte(sc, cmd, I2C_F_READ); 300 1.1 shige if (error != 0) { 301 1.1 shige return error; 302 1.1 shige } 303 1.1 shige 304 1.1 shige error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_READ); 305 1.1 shige if (error != 0) { 306 1.1 shige return error; 307 1.1 shige } 308 1.1 shige 309 1.1 shige error = ausmbus_read_byte(sc, vp, I2C_F_STOP); 310 1.1 shige if (error != 0) { 311 1.1 shige return error; 312 1.1 shige } 313 1.1 shige 314 1.1 shige return 0; 315 1.1 shige } 316 1.1 shige 317 1.1 shige static int 318 1.5 kiyohara ausmbus_read_2(struct ausmbus_softc *sc, uint8_t cmd, uint16_t *vp) 319 1.5 kiyohara { 320 1.5 kiyohara int error; 321 1.5 kiyohara uint8_t high, low; 322 1.5 kiyohara 323 1.5 kiyohara error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_WRITE); 324 1.5 kiyohara if (error != 0) { 325 1.5 kiyohara return error; 326 1.5 kiyohara } 327 1.5 kiyohara 328 1.5 kiyohara error = ausmbus_write_byte(sc, cmd, I2C_F_READ); 329 1.5 kiyohara if (error != 0) { 330 1.5 kiyohara return error; 331 1.5 kiyohara } 332 1.5 kiyohara 333 1.5 kiyohara error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_READ); 334 1.5 kiyohara if (error != 0) { 335 1.5 kiyohara return error; 336 1.5 kiyohara } 337 1.5 kiyohara 338 1.5 kiyohara error = ausmbus_read_byte(sc, &low, 0); 339 1.5 kiyohara if (error != 0) { 340 1.5 kiyohara return error; 341 1.5 kiyohara } 342 1.5 kiyohara 343 1.5 kiyohara error = ausmbus_read_byte(sc, &high, I2C_F_STOP); 344 1.5 kiyohara if (error != 0) { 345 1.5 kiyohara return error; 346 1.5 kiyohara } 347 1.5 kiyohara 348 1.5 kiyohara *vp = (high << 8) | low; 349 1.5 kiyohara 350 1.5 kiyohara return 0; 351 1.5 kiyohara } 352 1.5 kiyohara 353 1.5 kiyohara static int 354 1.1 shige ausmbus_send_1(struct ausmbus_softc *sc, uint8_t val) 355 1.1 shige { 356 1.1 shige int error; 357 1.1 shige 358 1.1 shige error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_WRITE); 359 1.1 shige if (error != 0) { 360 1.1 shige return error; 361 1.1 shige } 362 1.1 shige 363 1.1 shige error = ausmbus_write_byte(sc, val, I2C_F_STOP); 364 1.1 shige if (error != 0) { 365 1.1 shige return error; 366 1.1 shige } 367 1.1 shige 368 1.1 shige return 0; 369 1.1 shige } 370 1.1 shige 371 1.1 shige static int 372 1.1 shige ausmbus_write_1(struct ausmbus_softc *sc, uint8_t cmd, uint8_t val) 373 1.1 shige { 374 1.1 shige int error; 375 1.1 shige 376 1.1 shige error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_WRITE); 377 1.1 shige if (error != 0) { 378 1.1 shige return error; 379 1.1 shige } 380 1.1 shige 381 1.1 shige error = ausmbus_write_byte(sc, cmd, 0); 382 1.1 shige if (error != 0) { 383 1.1 shige return error; 384 1.1 shige } 385 1.1 shige 386 1.1 shige error = ausmbus_write_byte(sc, val, I2C_F_STOP); 387 1.1 shige if (error != 0) { 388 1.1 shige return error; 389 1.1 shige } 390 1.1 shige 391 1.1 shige return 0; 392 1.1 shige } 393 1.1 shige 394 1.1 shige static int 395 1.5 kiyohara ausmbus_write_2(struct ausmbus_softc *sc, uint8_t cmd, uint16_t val) 396 1.5 kiyohara { 397 1.5 kiyohara int error; 398 1.5 kiyohara uint8_t high, low; 399 1.5 kiyohara 400 1.5 kiyohara high = (val >> 8) & 0xff; 401 1.5 kiyohara low = val & 0xff; 402 1.5 kiyohara 403 1.5 kiyohara error = ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, I2C_F_WRITE); 404 1.5 kiyohara if (error != 0) { 405 1.5 kiyohara return error; 406 1.5 kiyohara } 407 1.5 kiyohara 408 1.5 kiyohara error = ausmbus_write_byte(sc, cmd, 0); 409 1.5 kiyohara if (error != 0) { 410 1.5 kiyohara return error; 411 1.5 kiyohara } 412 1.5 kiyohara 413 1.5 kiyohara error = ausmbus_write_byte(sc, low, 0); 414 1.5 kiyohara if (error != 0) { 415 1.5 kiyohara return error; 416 1.5 kiyohara } 417 1.5 kiyohara 418 1.5 kiyohara error = ausmbus_write_byte(sc, high, I2C_F_STOP); 419 1.5 kiyohara if (error != 0) { 420 1.5 kiyohara return error; 421 1.5 kiyohara } 422 1.5 kiyohara 423 1.5 kiyohara return 0; 424 1.5 kiyohara } 425 1.5 kiyohara 426 1.9 pgoyette /* 427 1.9 pgoyette * XXX The quick_write() and quick_read() routines have not been tested! 428 1.9 pgoyette */ 429 1.9 pgoyette static int 430 1.9 pgoyette ausmbus_quick_write(struct ausmbus_softc *sc) 431 1.9 pgoyette { 432 1.9 pgoyette return ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, 433 1.9 pgoyette I2C_F_STOP | I2C_F_WRITE); 434 1.9 pgoyette } 435 1.9 pgoyette 436 1.9 pgoyette static int 437 1.9 pgoyette ausmbus_quick_read(struct ausmbus_softc *sc) 438 1.9 pgoyette { 439 1.9 pgoyette return ausmbus_initiate_xfer(sc, sc->sc_smbus_slave_addr, 440 1.9 pgoyette I2C_F_STOP | I2C_F_READ); 441 1.9 pgoyette } 442 1.9 pgoyette 443 1.5 kiyohara static int 444 1.1 shige ausmbus_wait_mastertx(struct ausmbus_softc *sc) 445 1.1 shige { 446 1.1 shige uint32_t v; 447 1.1 shige int timeout; 448 1.1 shige int txerr = 0; 449 1.1 shige 450 1.1 shige timeout = sc->sc_smbus_timeout; 451 1.1 shige 452 1.1 shige do { 453 1.1 shige v = ausmbus_reg_read(sc, AUPSC_SMBEVNT); 454 1.1 shige #ifdef AUSMBUS_PSC_DEBUG 455 1.1 shige aprint_normal("AuSMBus: ausmbus_wait_mastertx(): psc_smbevnt=0x%08x\n", v); 456 1.1 shige #endif 457 1.1 shige if ((v & SMBUS_EVNT_TU) != 0) 458 1.1 shige break; 459 1.1 shige if ((v & SMBUS_EVNT_MD) != 0) 460 1.1 shige break; 461 1.1 shige if ((v & (SMBUS_EVNT_DN | SMBUS_EVNT_AN | SMBUS_EVNT_AL)) 462 1.1 shige != 0) { 463 1.1 shige txerr = 1; 464 1.1 shige break; 465 1.1 shige } 466 1.1 shige timeout--; 467 1.1 shige delay(1); 468 1.1 shige } while (timeout > 0); 469 1.1 shige 470 1.1 shige if (txerr != 0) { 471 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBEVNT, 472 1.1 shige SMBUS_EVNT_DN | SMBUS_EVNT_AN | SMBUS_EVNT_AL); 473 1.1 shige #ifdef AUSMBUS_PSC_DEBUG 474 1.1 shige aprint_normal("AuSMBus: ausmbus_wait_mastertx(): Tx error\n"); 475 1.1 shige #endif 476 1.1 shige return -1; 477 1.1 shige } 478 1.1 shige 479 1.1 shige /* Reset Event TU (Tx Underflow) */ 480 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBEVNT, SMBUS_EVNT_TU | SMBUS_EVNT_MD); 481 1.1 shige 482 1.1 shige #ifdef AUSMBUS_PSC_DEBUG 483 1.1 shige v = ausmbus_reg_read(sc, AUPSC_SMBEVNT); 484 1.1 shige aprint_normal("AuSMBus: ausmbus_wait_mastertx(): psc_smbevnt=0x%08x (reset)\n", v); 485 1.1 shige #endif 486 1.1 shige return 0; 487 1.1 shige } 488 1.1 shige 489 1.1 shige static int 490 1.1 shige ausmbus_wait_masterrx(struct ausmbus_softc *sc) 491 1.1 shige { 492 1.1 shige uint32_t v; 493 1.1 shige int timeout; 494 1.1 shige timeout = sc->sc_smbus_timeout; 495 1.1 shige 496 1.1 shige if (ausmbus_wait_mastertx(sc) != 0) 497 1.1 shige return -1; 498 1.1 shige 499 1.1 shige do { 500 1.1 shige v = ausmbus_reg_read(sc, AUPSC_SMBSTAT); 501 1.1 shige #ifdef AUSMBUS_PSC_DEBUG 502 1.1 shige aprint_normal("AuSMBus: ausmbus_wait_masterrx(): psc_smbstat=0x%08x\n", v); 503 1.1 shige #endif 504 1.1 shige if ((v & SMBUS_STAT_RE) == 0) 505 1.1 shige break; 506 1.1 shige timeout--; 507 1.1 shige delay(1); 508 1.1 shige } while (timeout > 0); 509 1.1 shige 510 1.1 shige return 0; 511 1.1 shige } 512 1.1 shige 513 1.1 shige static int 514 1.1 shige ausmbus_initiate_xfer(void *arg, i2c_addr_t addr, int flags) 515 1.1 shige { 516 1.1 shige struct ausmbus_softc *sc = arg; 517 1.1 shige uint32_t v; 518 1.1 shige 519 1.1 shige /* Tx/Rx Slave Address */ 520 1.1 shige v = (addr << 1) & SMBUS_TXRX_ADDRDATA; 521 1.7 kiyohara if ((flags & I2C_F_READ) != 0) 522 1.1 shige v |= 1; 523 1.9 pgoyette if ((flags & I2C_F_STOP) != 0) 524 1.9 pgoyette v |= SMBUS_TXRX_STP; 525 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBTXRX, v); 526 1.1 shige 527 1.1 shige /* Master Start */ 528 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBPCR, SMBUS_PCR_MS); 529 1.1 shige 530 1.1 shige if (ausmbus_wait_mastertx(sc) != 0) 531 1.1 shige return -1; 532 1.1 shige 533 1.1 shige return 0; 534 1.1 shige } 535 1.1 shige 536 1.1 shige static int 537 1.1 shige ausmbus_read_byte(void *arg, uint8_t *vp, int flags) 538 1.1 shige { 539 1.1 shige struct ausmbus_softc *sc = arg; 540 1.1 shige uint32_t v; 541 1.1 shige 542 1.1 shige if ((flags & I2C_F_STOP) != 0) { 543 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBTXRX, SMBUS_TXRX_STP); 544 1.1 shige } else { 545 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBTXRX, 0); 546 1.1 shige } 547 1.1 shige 548 1.1 shige if (ausmbus_wait_masterrx(sc) != 0) 549 1.1 shige return -1; 550 1.1 shige 551 1.1 shige v = ausmbus_reg_read(sc, AUPSC_SMBTXRX); 552 1.1 shige *vp = v & SMBUS_TXRX_ADDRDATA; 553 1.1 shige 554 1.1 shige return 0; 555 1.1 shige } 556 1.1 shige 557 1.1 shige static int 558 1.1 shige ausmbus_write_byte(void *arg, uint8_t v, int flags) 559 1.1 shige { 560 1.1 shige struct ausmbus_softc *sc = arg; 561 1.1 shige 562 1.1 shige if ((flags & I2C_F_STOP) != 0) { 563 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBTXRX, (v | SMBUS_TXRX_STP)); 564 1.1 shige } else if ((flags & I2C_F_READ) != 0) { 565 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBTXRX, (v | SMBUS_TXRX_RSR)); 566 1.1 shige } else { 567 1.1 shige ausmbus_reg_write(sc, AUPSC_SMBTXRX, v); 568 1.1 shige } 569 1.1 shige 570 1.1 shige if (ausmbus_wait_mastertx(sc) != 0) 571 1.1 shige return -1; 572 1.1 shige 573 1.1 shige return 0; 574 1.1 shige } 575