Jim Liu | b84426c | 2022-06-23 13:31:42 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
| 3 | * Copyright (c) 2021 Nuvoton Technology Corp. |
| 4 | */ |
| 5 | |
| 6 | #include <clk.h> |
| 7 | #include <dm.h> |
| 8 | #include <i2c.h> |
| 9 | #include <asm/io.h> |
| 10 | #include <linux/iopoll.h> |
| 11 | #include <asm/arch/gcr.h> |
| 12 | |
| 13 | #define I2C_FREQ_100K 100000 |
| 14 | #define NPCM_I2C_TIMEOUT_MS 10 |
| 15 | #define NPCM7XX_I2CSEGCTL_INIT_VAL 0x0333F000 |
| 16 | #define NPCM8XX_I2CSEGCTL_INIT_VAL 0x9333F000 |
| 17 | |
| 18 | /* SCLFRQ min/max field values */ |
| 19 | #define SCLFRQ_MIN 10 |
| 20 | #define SCLFRQ_MAX 511 |
| 21 | |
| 22 | /* SMBCTL1 */ |
| 23 | #define SMBCTL1_START BIT(0) |
| 24 | #define SMBCTL1_STOP BIT(1) |
| 25 | #define SMBCTL1_INTEN BIT(2) |
| 26 | #define SMBCTL1_ACK BIT(4) |
| 27 | #define SMBCTL1_STASTRE BIT(7) |
| 28 | |
| 29 | /* SMBCTL2 */ |
| 30 | #define SMBCTL2_ENABLE BIT(0) |
| 31 | |
| 32 | /* SMBCTL3 */ |
| 33 | #define SMBCTL3_SCL_LVL BIT(7) |
| 34 | #define SMBCTL3_SDA_LVL BIT(6) |
| 35 | |
| 36 | /* SMBCST */ |
| 37 | #define SMBCST_BB BIT(1) |
| 38 | #define SMBCST_TGSCL BIT(5) |
| 39 | |
| 40 | /* SMBST */ |
| 41 | #define SMBST_XMIT BIT(0) |
| 42 | #define SMBST_MASTER BIT(1) |
| 43 | #define SMBST_STASTR BIT(3) |
| 44 | #define SMBST_NEGACK BIT(4) |
| 45 | #define SMBST_BER BIT(5) |
| 46 | #define SMBST_SDAST BIT(6) |
| 47 | |
| 48 | /* SMBCST3 in bank0 */ |
| 49 | #define SMBCST3_EO_BUSY BIT(7) |
| 50 | |
| 51 | /* SMBFIF_CTS in bank1 */ |
| 52 | #define SMBFIF_CTS_CLR_FIFO BIT(6) |
| 53 | |
| 54 | #define SMBFIF_CTL_FIFO_EN BIT(4) |
| 55 | #define SMBCTL3_BNK_SEL BIT(5) |
| 56 | |
| 57 | enum { |
| 58 | I2C_ERR_NACK = 1, |
| 59 | I2C_ERR_BER, |
| 60 | I2C_ERR_TIMEOUT, |
| 61 | }; |
| 62 | |
| 63 | struct smb_bank0_regs { |
| 64 | u8 addr3; |
| 65 | u8 addr7; |
| 66 | u8 addr4; |
| 67 | u8 addr8; |
| 68 | u16 addr5; |
| 69 | u16 addr6; |
| 70 | u8 cst2; |
| 71 | u8 cst3; |
| 72 | u8 ctl4; |
| 73 | u8 ctl5; |
| 74 | u8 scllt; |
| 75 | u8 fif_ctl; |
| 76 | u8 sclht; |
| 77 | }; |
| 78 | |
| 79 | struct smb_bank1_regs { |
| 80 | u8 fif_cts; |
| 81 | u8 fair_per; |
| 82 | u16 txf_ctl; |
| 83 | u32 t_out; |
| 84 | u8 cst2; |
| 85 | u8 cst3; |
| 86 | u16 txf_sts; |
| 87 | u16 rxf_sts; |
| 88 | u8 rxf_ctl; |
| 89 | }; |
| 90 | |
| 91 | struct npcm_i2c_regs { |
| 92 | u16 sda; |
| 93 | u16 st; |
| 94 | u16 cst; |
| 95 | u16 ctl1; |
| 96 | u16 addr; |
| 97 | u16 ctl2; |
| 98 | u16 addr2; |
| 99 | u16 ctl3; |
| 100 | union { |
| 101 | struct smb_bank0_regs bank0; |
| 102 | struct smb_bank1_regs bank1; |
| 103 | }; |
| 104 | |
| 105 | }; |
| 106 | |
| 107 | struct npcm_i2c_bus { |
| 108 | struct npcm_i2c_regs *reg; |
| 109 | int num; |
| 110 | u32 apb_clk; |
| 111 | u32 freq; |
| 112 | bool started; |
| 113 | }; |
| 114 | |
| 115 | static void npcm_dump_regs(struct npcm_i2c_bus *bus) |
| 116 | { |
| 117 | struct npcm_i2c_regs *reg = bus->reg; |
| 118 | |
| 119 | printf("\n"); |
| 120 | printf("SMBST=0x%x\n", readb(®->st)); |
| 121 | printf("SMBCST=0x%x\n", readb(®->cst)); |
| 122 | printf("SMBCTL1=0x%x\n", readb(®->ctl1)); |
| 123 | printf("\n"); |
| 124 | } |
| 125 | |
| 126 | static int npcm_i2c_check_sda(struct npcm_i2c_bus *bus) |
| 127 | { |
| 128 | struct npcm_i2c_regs *reg = bus->reg; |
| 129 | ulong start_time; |
| 130 | int err = I2C_ERR_TIMEOUT; |
| 131 | u8 val; |
| 132 | |
| 133 | start_time = get_timer(0); |
| 134 | /* wait SDAST to be 1 */ |
| 135 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { |
| 136 | val = readb(®->st); |
| 137 | if (val & SMBST_NEGACK) { |
| 138 | err = I2C_ERR_NACK; |
| 139 | break; |
| 140 | } |
| 141 | if (val & SMBST_BER) { |
| 142 | err = I2C_ERR_BER; |
| 143 | break; |
| 144 | } |
| 145 | if (val & SMBST_SDAST) { |
| 146 | err = 0; |
| 147 | break; |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | if (err) |
| 152 | printf("%s: err %d\n", __func__, err); |
| 153 | |
| 154 | return err; |
| 155 | } |
| 156 | |
| 157 | static int npcm_i2c_send_start(struct npcm_i2c_bus *bus) |
| 158 | { |
| 159 | struct npcm_i2c_regs *reg = bus->reg; |
| 160 | ulong start_time; |
| 161 | int err = I2C_ERR_TIMEOUT; |
| 162 | |
| 163 | /* Generate START condition */ |
| 164 | setbits_8(®->ctl1, SMBCTL1_START); |
| 165 | |
| 166 | start_time = get_timer(0); |
| 167 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { |
| 168 | if (readb(®->st) & SMBST_BER) |
| 169 | return I2C_ERR_BER; |
| 170 | if (readb(®->st) & SMBST_MASTER) { |
| 171 | err = 0; |
| 172 | break; |
| 173 | } |
| 174 | } |
| 175 | bus->started = true; |
| 176 | |
| 177 | return err; |
| 178 | } |
| 179 | |
| 180 | static int npcm_i2c_send_stop(struct npcm_i2c_bus *bus, bool wait) |
| 181 | { |
| 182 | struct npcm_i2c_regs *reg = bus->reg; |
| 183 | ulong start_time; |
| 184 | int err = I2C_ERR_TIMEOUT; |
| 185 | |
| 186 | setbits_8(®->ctl1, SMBCTL1_STOP); |
| 187 | |
| 188 | /* Clear NEGACK, STASTR and BER bits */ |
| 189 | writeb(SMBST_STASTR | SMBST_NEGACK | SMBST_BER, ®->st); |
| 190 | |
| 191 | bus->started = false; |
| 192 | |
| 193 | if (!wait) |
| 194 | return 0; |
| 195 | |
| 196 | start_time = get_timer(0); |
| 197 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { |
| 198 | if ((readb(®->ctl1) & SMBCTL1_STOP) == 0) { |
| 199 | err = 0; |
| 200 | break; |
| 201 | } |
| 202 | } |
| 203 | if (err) { |
| 204 | printf("%s: err %d\n", __func__, err); |
| 205 | npcm_dump_regs(bus); |
| 206 | } |
| 207 | |
| 208 | return err; |
| 209 | } |
| 210 | |
| 211 | static void npcm_i2c_reset(struct npcm_i2c_bus *bus) |
| 212 | { |
| 213 | struct npcm_i2c_regs *reg = bus->reg; |
| 214 | |
| 215 | debug("%s: module %d\n", __func__, bus->num); |
| 216 | /* disable & enable SMB moudle */ |
| 217 | clrbits_8(®->ctl2, SMBCTL2_ENABLE); |
| 218 | setbits_8(®->ctl2, SMBCTL2_ENABLE); |
| 219 | |
| 220 | /* clear BB and status */ |
| 221 | writeb(SMBCST_BB, ®->cst); |
| 222 | writeb(0xff, ®->st); |
| 223 | |
| 224 | /* select bank 1 */ |
| 225 | setbits_8(®->ctl3, SMBCTL3_BNK_SEL); |
| 226 | /* Clear all fifo bits */ |
| 227 | writeb(SMBFIF_CTS_CLR_FIFO, ®->bank1.fif_cts); |
| 228 | |
| 229 | /* select bank 0 */ |
| 230 | clrbits_8(®->ctl3, SMBCTL3_BNK_SEL); |
| 231 | /* clear EOB bit */ |
| 232 | writeb(SMBCST3_EO_BUSY, ®->bank0.cst3); |
| 233 | /* single byte mode */ |
| 234 | clrbits_8(®->bank0.fif_ctl, SMBFIF_CTL_FIFO_EN); |
| 235 | |
| 236 | /* set POLL mode */ |
| 237 | writeb(0, ®->ctl1); |
| 238 | } |
| 239 | |
| 240 | static void npcm_i2c_recovery(struct npcm_i2c_bus *bus, u32 addr) |
| 241 | { |
| 242 | u8 val; |
| 243 | int iter = 27; |
| 244 | struct npcm_i2c_regs *reg = bus->reg; |
| 245 | int err; |
| 246 | |
| 247 | val = readb(®->ctl3); |
| 248 | /* Skip recovery, bus not stucked */ |
| 249 | if ((val & SMBCTL3_SCL_LVL) && (val & SMBCTL3_SDA_LVL)) |
| 250 | return; |
| 251 | |
| 252 | printf("Performing I2C bus %d recovery...\n", bus->num); |
| 253 | /* SCL/SDA are not releaed, perform recovery */ |
| 254 | while (1) { |
| 255 | /* toggle SCL line */ |
| 256 | writeb(SMBCST_TGSCL, ®->cst); |
| 257 | |
| 258 | udelay(20); |
| 259 | val = readb(®->ctl3); |
| 260 | if (val & SMBCTL3_SDA_LVL) |
| 261 | break; |
| 262 | if (iter-- == 0) |
| 263 | break; |
| 264 | } |
| 265 | |
| 266 | if (val & SMBCTL3_SDA_LVL) { |
| 267 | writeb((u8)((addr << 1) & 0xff), ®->sda); |
| 268 | err = npcm_i2c_send_start(bus); |
| 269 | if (!err) { |
| 270 | udelay(20); |
| 271 | npcm_i2c_send_stop(bus, false); |
| 272 | udelay(200); |
| 273 | printf("I2C bus %d recovery completed\n", |
| 274 | bus->num); |
| 275 | } else { |
| 276 | printf("%s: send START err %d\n", __func__, err); |
| 277 | } |
| 278 | } else { |
| 279 | printf("Fail to recover I2C bus %d\n", bus->num); |
| 280 | } |
| 281 | npcm_i2c_reset(bus); |
| 282 | } |
| 283 | |
| 284 | static int npcm_i2c_send_address(struct npcm_i2c_bus *bus, u8 addr, |
| 285 | bool stall) |
| 286 | { |
| 287 | struct npcm_i2c_regs *reg = bus->reg; |
| 288 | ulong start_time; |
| 289 | u8 val; |
| 290 | |
| 291 | /* Stall After Start Enable */ |
| 292 | if (stall) |
| 293 | setbits_8(®->ctl1, SMBCTL1_STASTRE); |
| 294 | |
| 295 | writeb(addr, ®->sda); |
| 296 | if (stall) { |
| 297 | start_time = get_timer(0); |
| 298 | while (get_timer(start_time) < NPCM_I2C_TIMEOUT_MS) { |
| 299 | if (readb(®->st) & SMBST_STASTR) |
| 300 | break; |
| 301 | |
| 302 | if (readb(®->st) & SMBST_BER) { |
| 303 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); |
| 304 | return I2C_ERR_BER; |
| 305 | } |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | /* check ACK */ |
| 310 | val = readb(®->st); |
| 311 | if (val & SMBST_NEGACK) { |
| 312 | debug("NACK on addr 0x%x\n", addr >> 1); |
| 313 | /* After a Stop condition, writing 1 to NEGACK clears it */ |
| 314 | return I2C_ERR_NACK; |
| 315 | } |
| 316 | if (val & SMBST_BER) |
| 317 | return I2C_ERR_BER; |
| 318 | |
| 319 | return 0; |
| 320 | } |
| 321 | |
| 322 | static int npcm_i2c_read_bytes(struct npcm_i2c_bus *bus, u8 *data, int len) |
| 323 | { |
| 324 | struct npcm_i2c_regs *reg = bus->reg; |
| 325 | u8 val; |
| 326 | int i; |
| 327 | int err = 0; |
| 328 | |
| 329 | if (len == 1) { |
| 330 | /* bus should be stalled before receiving last byte */ |
| 331 | setbits_8(®->ctl1, SMBCTL1_ACK); |
| 332 | |
| 333 | /* clear STASTRE if it is set */ |
| 334 | if (readb(®->ctl1) & SMBCTL1_STASTRE) { |
| 335 | writeb(SMBST_STASTR, ®->st); |
| 336 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); |
| 337 | } |
| 338 | npcm_i2c_check_sda(bus); |
| 339 | npcm_i2c_send_stop(bus, false); |
| 340 | *data = readb(®->sda); |
| 341 | /* this must be done to generate STOP condition */ |
| 342 | writeb(SMBST_NEGACK, ®->st); |
| 343 | } else { |
| 344 | for (i = 0; i < len; i++) { |
| 345 | /* |
| 346 | * When NEGACK bit is set to 1 after the transmission of a byte, |
| 347 | * SDAST is not set to 1. |
| 348 | */ |
| 349 | if (i != (len - 1)) { |
| 350 | err = npcm_i2c_check_sda(bus); |
| 351 | } else { |
| 352 | err = readb_poll_timeout(®->ctl1, val, |
| 353 | !(val & SMBCTL1_ACK), 100000); |
| 354 | if (err) { |
| 355 | printf("wait nack timeout\n"); |
| 356 | err = I2C_ERR_TIMEOUT; |
| 357 | npcm_dump_regs(bus); |
| 358 | } |
| 359 | } |
| 360 | if (err && err != I2C_ERR_TIMEOUT) |
| 361 | break; |
| 362 | if (i == (len - 2)) { |
| 363 | /* set NACK before last byte */ |
| 364 | setbits_8(®->ctl1, SMBCTL1_ACK); |
| 365 | } |
| 366 | if (i == (len - 1)) { |
| 367 | /* last byte, send STOP condition */ |
| 368 | npcm_i2c_send_stop(bus, false); |
| 369 | *data = readb(®->sda); |
| 370 | writeb(SMBST_NEGACK, ®->st); |
| 371 | break; |
| 372 | } |
| 373 | *data = readb(®->sda); |
| 374 | data++; |
| 375 | } |
| 376 | } |
| 377 | |
| 378 | return err; |
| 379 | } |
| 380 | |
| 381 | static int npcm_i2c_send_bytes(struct npcm_i2c_bus *bus, u8 *data, int len) |
| 382 | { |
| 383 | struct npcm_i2c_regs *reg = bus->reg; |
| 384 | u8 val; |
| 385 | int i; |
| 386 | int err = 0; |
| 387 | |
| 388 | val = readb(®->st); |
| 389 | if (val & SMBST_NEGACK) |
| 390 | return I2C_ERR_NACK; |
| 391 | else if (val & SMBST_BER) |
| 392 | return I2C_ERR_BER; |
| 393 | |
| 394 | /* clear STASTRE if it is set */ |
| 395 | if (readb(®->ctl1) & SMBCTL1_STASTRE) |
| 396 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); |
| 397 | |
| 398 | for (i = 0; i < len; i++) { |
| 399 | err = npcm_i2c_check_sda(bus); |
| 400 | if (err) |
| 401 | break; |
| 402 | writeb(*data, ®->sda); |
| 403 | data++; |
| 404 | } |
| 405 | npcm_i2c_check_sda(bus); |
| 406 | |
| 407 | return err; |
| 408 | } |
| 409 | |
| 410 | static int npcm_i2c_read(struct npcm_i2c_bus *bus, u32 addr, u8 *data, |
| 411 | u32 len) |
| 412 | { |
| 413 | struct npcm_i2c_regs *reg = bus->reg; |
| 414 | int err; |
| 415 | bool stall; |
| 416 | |
| 417 | if (len <= 0) |
| 418 | return -EINVAL; |
| 419 | |
| 420 | /* send START condition */ |
| 421 | err = npcm_i2c_send_start(bus); |
| 422 | if (err) { |
| 423 | debug("%s: send START err %d\n", __func__, err); |
| 424 | return err; |
| 425 | } |
| 426 | |
| 427 | stall = (len == 1) ? true : false; |
| 428 | /* send address byte */ |
| 429 | err = npcm_i2c_send_address(bus, (u8)(addr << 1) | 0x1, stall); |
| 430 | |
| 431 | if (!err && len) |
| 432 | npcm_i2c_read_bytes(bus, data, len); |
| 433 | |
| 434 | if (err == I2C_ERR_NACK) { |
| 435 | /* clear NACK */ |
| 436 | writeb(SMBST_NEGACK, ®->st); |
| 437 | } |
| 438 | |
| 439 | if (err) |
| 440 | debug("%s: err %d\n", __func__, err); |
| 441 | |
| 442 | return err; |
| 443 | } |
| 444 | |
| 445 | static int npcm_i2c_write(struct npcm_i2c_bus *bus, u32 addr, u8 *data, |
| 446 | u32 len) |
| 447 | { |
| 448 | struct npcm_i2c_regs *reg = bus->reg; |
| 449 | int err; |
| 450 | bool stall; |
| 451 | |
| 452 | /* send START condition */ |
| 453 | err = npcm_i2c_send_start(bus); |
| 454 | if (err) { |
| 455 | debug("%s: send START err %d\n", __func__, err); |
| 456 | return err; |
| 457 | } |
| 458 | |
| 459 | stall = (len == 0) ? true : false; |
| 460 | /* send address byte */ |
| 461 | err = npcm_i2c_send_address(bus, (u8)(addr << 1), stall); |
| 462 | |
| 463 | if (!err && len) |
| 464 | err = npcm_i2c_send_bytes(bus, data, len); |
| 465 | |
| 466 | /* clear STASTRE if it is set */ |
| 467 | if (stall) |
| 468 | clrbits_8(®->ctl1, SMBCTL1_STASTRE); |
| 469 | |
| 470 | if (err) |
| 471 | debug("%s: err %d\n", __func__, err); |
| 472 | |
| 473 | return err; |
| 474 | } |
| 475 | |
| 476 | static int npcm_i2c_xfer(struct udevice *dev, |
| 477 | struct i2c_msg *msg, int nmsgs) |
| 478 | { |
| 479 | struct npcm_i2c_bus *bus = dev_get_priv(dev); |
| 480 | struct npcm_i2c_regs *reg = bus->reg; |
| 481 | int ret = 0, err = 0; |
| 482 | |
| 483 | if (nmsgs < 1 || nmsgs > 2) { |
| 484 | printf("%s: commands not support\n", __func__); |
| 485 | return -EREMOTEIO; |
| 486 | } |
| 487 | /* clear ST register */ |
| 488 | writeb(0xFF, ®->st); |
| 489 | |
| 490 | for ( ; nmsgs > 0; nmsgs--, msg++) { |
| 491 | if (msg->flags & I2C_M_RD) |
| 492 | err = npcm_i2c_read(bus, msg->addr, msg->buf, |
| 493 | msg->len); |
| 494 | else |
| 495 | err = npcm_i2c_write(bus, msg->addr, msg->buf, |
| 496 | msg->len); |
| 497 | if (err) { |
| 498 | debug("i2c_xfer: error %d\n", err); |
| 499 | ret = -EREMOTEIO; |
| 500 | break; |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | if (bus->started) |
| 505 | npcm_i2c_send_stop(bus, true); |
| 506 | |
| 507 | if (err) |
| 508 | npcm_i2c_recovery(bus, msg->addr); |
| 509 | |
| 510 | return ret; |
| 511 | } |
| 512 | |
| 513 | static int npcm_i2c_init_clk(struct npcm_i2c_bus *bus, u32 bus_freq) |
| 514 | { |
| 515 | struct npcm_i2c_regs *reg = bus->reg; |
| 516 | u32 freq = bus->apb_clk; |
| 517 | u32 sclfrq; |
| 518 | u8 hldt, val; |
| 519 | |
Jim Liu | b84426c | 2022-06-23 13:31:42 +0800 | [diff] [blame] | 520 | /* SCLFRQ = T(SCL)/4/T(CLK) = FREQ(CLK)/4/FREQ(SCL) */ |
| 521 | sclfrq = freq / (bus_freq * 4); |
| 522 | if (sclfrq < SCLFRQ_MIN || sclfrq > SCLFRQ_MAX) |
| 523 | return -EINVAL; |
| 524 | |
| 525 | if (freq >= 40000000) |
| 526 | hldt = 17; |
| 527 | else if (freq >= 12500000) |
| 528 | hldt = 15; |
| 529 | else |
| 530 | hldt = 7; |
| 531 | |
| 532 | val = readb(®->ctl2) & 0x1; |
| 533 | val |= (sclfrq & 0x7F) << 1; |
| 534 | writeb(val, ®->ctl2); |
| 535 | |
| 536 | /* clear 400K_MODE bit */ |
| 537 | val = readb(®->ctl3) & 0xc; |
| 538 | val |= (sclfrq >> 7) & 0x3; |
| 539 | writeb(val, ®->ctl3); |
| 540 | |
| 541 | writeb(hldt, ®->bank0.ctl4); |
| 542 | |
| 543 | return 0; |
| 544 | } |
| 545 | |
| 546 | static int npcm_i2c_set_bus_speed(struct udevice *dev, |
| 547 | unsigned int speed) |
| 548 | { |
| 549 | struct npcm_i2c_bus *bus = dev_get_priv(dev); |
| 550 | |
| 551 | return npcm_i2c_init_clk(bus, speed); |
| 552 | } |
| 553 | |
| 554 | static int npcm_i2c_probe(struct udevice *dev) |
| 555 | { |
| 556 | struct npcm_i2c_bus *bus = dev_get_priv(dev); |
| 557 | struct npcm_gcr *gcr = (struct npcm_gcr *)NPCM_GCR_BA; |
| 558 | struct npcm_i2c_regs *reg; |
| 559 | u32 i2csegctl_val = dev_get_driver_data(dev); |
| 560 | struct clk clk; |
| 561 | int ret; |
| 562 | |
| 563 | ret = clk_get_by_index(dev, 0, &clk); |
| 564 | if (ret) { |
| 565 | printf("%s: ret %d\n", __func__, ret); |
| 566 | return ret; |
| 567 | } |
| 568 | bus->apb_clk = clk_get_rate(&clk); |
| 569 | if (bus->apb_clk <= 0) { |
| 570 | printf("%s: fail to get rate\n", __func__); |
| 571 | return -EINVAL; |
| 572 | } |
Jim Liu | b84426c | 2022-06-23 13:31:42 +0800 | [diff] [blame] | 573 | |
| 574 | bus->num = dev->seq_; |
| 575 | bus->reg = dev_read_addr_ptr(dev); |
| 576 | bus->freq = dev_read_u32_default(dev, "clock-frequency", 100000); |
| 577 | bus->started = false; |
| 578 | reg = bus->reg; |
| 579 | |
| 580 | if (npcm_i2c_init_clk(bus, bus->freq)) { |
| 581 | printf("%s: init_clk failed\n", __func__); |
| 582 | return -EINVAL; |
| 583 | } |
| 584 | |
| 585 | /* set initial i2csegctl value */ |
| 586 | writel(i2csegctl_val, &gcr->i2csegctl); |
| 587 | |
| 588 | /* enable SMB module */ |
| 589 | setbits_8(®->ctl2, SMBCTL2_ENABLE); |
| 590 | |
| 591 | /* select register bank 0 */ |
| 592 | clrbits_8(®->ctl3, SMBCTL3_BNK_SEL); |
| 593 | |
| 594 | /* single byte mode */ |
| 595 | clrbits_8(®->bank0.fif_ctl, SMBFIF_CTL_FIFO_EN); |
| 596 | |
| 597 | /* set POLL mode */ |
| 598 | writeb(0, ®->ctl1); |
| 599 | |
| 600 | printf("I2C bus %d ready. speed=%d, base=0x%x, apb=%u\n", |
| 601 | bus->num, bus->freq, (u32)(uintptr_t)bus->reg, bus->apb_clk); |
| 602 | |
| 603 | return 0; |
| 604 | } |
| 605 | |
| 606 | static const struct dm_i2c_ops nuvoton_i2c_ops = { |
| 607 | .xfer = npcm_i2c_xfer, |
| 608 | .set_bus_speed = npcm_i2c_set_bus_speed, |
| 609 | }; |
| 610 | |
| 611 | static const struct udevice_id nuvoton_i2c_of_match[] = { |
| 612 | { .compatible = "nuvoton,npcm845-i2c", .data = NPCM8XX_I2CSEGCTL_INIT_VAL}, |
| 613 | { .compatible = "nuvoton,npcm750-i2c", .data = NPCM7XX_I2CSEGCTL_INIT_VAL}, |
| 614 | {} |
| 615 | }; |
| 616 | |
| 617 | U_BOOT_DRIVER(npcm_i2c_bus) = { |
| 618 | .name = "npcm-i2c", |
| 619 | .id = UCLASS_I2C, |
| 620 | .of_match = nuvoton_i2c_of_match, |
| 621 | .probe = npcm_i2c_probe, |
| 622 | .priv_auto = sizeof(struct npcm_i2c_bus), |
| 623 | .ops = &nuvoton_i2c_ops, |
| 624 | }; |