1*c6d9fdbcSPankaj Gupta /* 2*c6d9fdbcSPankaj Gupta * Copyright 2016-2020 NXP 3*c6d9fdbcSPankaj Gupta * 4*c6d9fdbcSPankaj Gupta * SPDX-License-Identifier: BSD-3-Clause 5*c6d9fdbcSPankaj Gupta * 6*c6d9fdbcSPankaj Gupta */ 7*c6d9fdbcSPankaj Gupta 8*c6d9fdbcSPankaj Gupta #include <errno.h> 9*c6d9fdbcSPankaj Gupta #include <stdint.h> 10*c6d9fdbcSPankaj Gupta #include <stdio.h> 11*c6d9fdbcSPankaj Gupta #include <stdlib.h> 12*c6d9fdbcSPankaj Gupta 13*c6d9fdbcSPankaj Gupta #include <common/debug.h> 14*c6d9fdbcSPankaj Gupta #include <drivers/delay_timer.h> 15*c6d9fdbcSPankaj Gupta #include "i2c.h" 16*c6d9fdbcSPankaj Gupta #include <nxp_timer.h> 17*c6d9fdbcSPankaj Gupta 18*c6d9fdbcSPankaj Gupta static uintptr_t g_nxp_i2c_addr; 19*c6d9fdbcSPankaj Gupta 20*c6d9fdbcSPankaj Gupta void i2c_init(uintptr_t nxp_i2c_addr) 21*c6d9fdbcSPankaj Gupta { 22*c6d9fdbcSPankaj Gupta struct ls_i2c *ccsr_i2c = (void *)nxp_i2c_addr; 23*c6d9fdbcSPankaj Gupta 24*c6d9fdbcSPankaj Gupta g_nxp_i2c_addr = nxp_i2c_addr; 25*c6d9fdbcSPankaj Gupta /* Presume workaround for erratum a009203 applied */ 26*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, I2C_CR_DIS); 27*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->fd, I2C_FD_CONSERV); 28*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->sr, I2C_SR_RST); 29*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, I2C_CR_EN); 30*c6d9fdbcSPankaj Gupta } 31*c6d9fdbcSPankaj Gupta 32*c6d9fdbcSPankaj Gupta static int wait_for_state(struct ls_i2c *ccsr_i2c, 33*c6d9fdbcSPankaj Gupta unsigned char state, unsigned char mask) 34*c6d9fdbcSPankaj Gupta { 35*c6d9fdbcSPankaj Gupta unsigned char sr; 36*c6d9fdbcSPankaj Gupta uint64_t start_time = get_timer_val(0); 37*c6d9fdbcSPankaj Gupta uint64_t timer; 38*c6d9fdbcSPankaj Gupta 39*c6d9fdbcSPankaj Gupta do { 40*c6d9fdbcSPankaj Gupta sr = i2c_in(&ccsr_i2c->sr); 41*c6d9fdbcSPankaj Gupta if (sr & I2C_SR_AL) { 42*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->sr, sr); 43*c6d9fdbcSPankaj Gupta WARN("I2C arbitration lost\n"); 44*c6d9fdbcSPankaj Gupta return -EIO; 45*c6d9fdbcSPankaj Gupta } 46*c6d9fdbcSPankaj Gupta if ((sr & mask) == state) { 47*c6d9fdbcSPankaj Gupta return (int)sr; 48*c6d9fdbcSPankaj Gupta } 49*c6d9fdbcSPankaj Gupta 50*c6d9fdbcSPankaj Gupta timer = get_timer_val(start_time); 51*c6d9fdbcSPankaj Gupta if (timer > I2C_TIMEOUT) 52*c6d9fdbcSPankaj Gupta break; 53*c6d9fdbcSPankaj Gupta mdelay(1); 54*c6d9fdbcSPankaj Gupta } while (1); 55*c6d9fdbcSPankaj Gupta WARN("I2C: Timeout waiting for state 0x%x, sr = 0x%x\n", state, sr); 56*c6d9fdbcSPankaj Gupta 57*c6d9fdbcSPankaj Gupta return -ETIMEDOUT; 58*c6d9fdbcSPankaj Gupta } 59*c6d9fdbcSPankaj Gupta 60*c6d9fdbcSPankaj Gupta static int tx_byte(struct ls_i2c *ccsr_i2c, unsigned char c) 61*c6d9fdbcSPankaj Gupta { 62*c6d9fdbcSPankaj Gupta int ret; 63*c6d9fdbcSPankaj Gupta 64*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->sr, I2C_SR_IF); 65*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->dr, c); 66*c6d9fdbcSPankaj Gupta ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF); 67*c6d9fdbcSPankaj Gupta if (ret < 0) { 68*c6d9fdbcSPankaj Gupta WARN("%s: state error\n", __func__); 69*c6d9fdbcSPankaj Gupta return ret; 70*c6d9fdbcSPankaj Gupta } 71*c6d9fdbcSPankaj Gupta if (ret & I2C_SR_RX_NAK) { 72*c6d9fdbcSPankaj Gupta WARN("%s: nodev\n", __func__); 73*c6d9fdbcSPankaj Gupta return -ENODEV; 74*c6d9fdbcSPankaj Gupta } 75*c6d9fdbcSPankaj Gupta 76*c6d9fdbcSPankaj Gupta return 0; 77*c6d9fdbcSPankaj Gupta } 78*c6d9fdbcSPankaj Gupta 79*c6d9fdbcSPankaj Gupta static int gen_stop(struct ls_i2c *ccsr_i2c) 80*c6d9fdbcSPankaj Gupta { 81*c6d9fdbcSPankaj Gupta unsigned char cr; 82*c6d9fdbcSPankaj Gupta int ret; 83*c6d9fdbcSPankaj Gupta 84*c6d9fdbcSPankaj Gupta cr = i2c_in(&ccsr_i2c->cr); 85*c6d9fdbcSPankaj Gupta cr &= ~(I2C_CR_MA | I2C_CR_TX); 86*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, cr); 87*c6d9fdbcSPankaj Gupta ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB); 88*c6d9fdbcSPankaj Gupta if (ret < 0) { 89*c6d9fdbcSPankaj Gupta WARN("I2C: Generating stop failed.\n"); 90*c6d9fdbcSPankaj Gupta } 91*c6d9fdbcSPankaj Gupta return ret; 92*c6d9fdbcSPankaj Gupta } 93*c6d9fdbcSPankaj Gupta 94*c6d9fdbcSPankaj Gupta static int i2c_write_addr(struct ls_i2c *ccsr_i2c, unsigned char chip, 95*c6d9fdbcSPankaj Gupta int addr, int alen) 96*c6d9fdbcSPankaj Gupta { 97*c6d9fdbcSPankaj Gupta int ret; 98*c6d9fdbcSPankaj Gupta unsigned char cr; 99*c6d9fdbcSPankaj Gupta 100*c6d9fdbcSPankaj Gupta if (alen != 1) { 101*c6d9fdbcSPankaj Gupta WARN("I2C: Unsupported address len [%d]\n", alen); 102*c6d9fdbcSPankaj Gupta return -EIO; 103*c6d9fdbcSPankaj Gupta } 104*c6d9fdbcSPankaj Gupta 105*c6d9fdbcSPankaj Gupta if (i2c_in(&ccsr_i2c->ad) == (chip << 1)) { 106*c6d9fdbcSPankaj Gupta WARN("I2C: slave address same as self\n"); 107*c6d9fdbcSPankaj Gupta return -ENODEV; 108*c6d9fdbcSPankaj Gupta } 109*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->sr, I2C_SR_IF); 110*c6d9fdbcSPankaj Gupta ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB); 111*c6d9fdbcSPankaj Gupta if (ret < 0) { 112*c6d9fdbcSPankaj Gupta return ret; 113*c6d9fdbcSPankaj Gupta } 114*c6d9fdbcSPankaj Gupta 115*c6d9fdbcSPankaj Gupta cr = i2c_in(&ccsr_i2c->cr); 116*c6d9fdbcSPankaj Gupta cr |= I2C_CR_MA; 117*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, cr); 118*c6d9fdbcSPankaj Gupta ret = wait_for_state(ccsr_i2c, I2C_SR_BB, I2C_SR_BB); 119*c6d9fdbcSPankaj Gupta if (ret < 0) { 120*c6d9fdbcSPankaj Gupta return ret; 121*c6d9fdbcSPankaj Gupta } 122*c6d9fdbcSPankaj Gupta 123*c6d9fdbcSPankaj Gupta VERBOSE("Before writing chip %d\n", chip); 124*c6d9fdbcSPankaj Gupta cr |= I2C_CR_TX | I2C_CR_TX_NAK; 125*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, cr); 126*c6d9fdbcSPankaj Gupta ret = tx_byte(ccsr_i2c, chip << 1); 127*c6d9fdbcSPankaj Gupta if (ret < 0) { 128*c6d9fdbcSPankaj Gupta gen_stop(ccsr_i2c); 129*c6d9fdbcSPankaj Gupta return ret; 130*c6d9fdbcSPankaj Gupta } 131*c6d9fdbcSPankaj Gupta 132*c6d9fdbcSPankaj Gupta VERBOSE("Before writing addr\n"); 133*c6d9fdbcSPankaj Gupta while (alen--) { 134*c6d9fdbcSPankaj Gupta ret = tx_byte(ccsr_i2c, (addr >> (alen << 3)) & 0xff); 135*c6d9fdbcSPankaj Gupta if (ret < 0) { 136*c6d9fdbcSPankaj Gupta gen_stop(ccsr_i2c); 137*c6d9fdbcSPankaj Gupta return ret; 138*c6d9fdbcSPankaj Gupta } 139*c6d9fdbcSPankaj Gupta } 140*c6d9fdbcSPankaj Gupta 141*c6d9fdbcSPankaj Gupta return 0; 142*c6d9fdbcSPankaj Gupta } 143*c6d9fdbcSPankaj Gupta 144*c6d9fdbcSPankaj Gupta static int read_data(struct ls_i2c *ccsr_i2c, unsigned char chip, 145*c6d9fdbcSPankaj Gupta unsigned char *buf, int len) 146*c6d9fdbcSPankaj Gupta { 147*c6d9fdbcSPankaj Gupta int i; 148*c6d9fdbcSPankaj Gupta int ret; 149*c6d9fdbcSPankaj Gupta unsigned char cr; 150*c6d9fdbcSPankaj Gupta 151*c6d9fdbcSPankaj Gupta cr = i2c_in(&ccsr_i2c->cr); 152*c6d9fdbcSPankaj Gupta cr &= ~(I2C_CR_TX | I2C_CR_TX_NAK); 153*c6d9fdbcSPankaj Gupta if (len == 1) { 154*c6d9fdbcSPankaj Gupta cr |= I2C_CR_TX_NAK; 155*c6d9fdbcSPankaj Gupta } 156*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, cr); 157*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->sr, I2C_SR_IF); 158*c6d9fdbcSPankaj Gupta i2c_in(&ccsr_i2c->dr); /* dummy read */ 159*c6d9fdbcSPankaj Gupta for (i = 0; i < len; i++) { 160*c6d9fdbcSPankaj Gupta ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF); 161*c6d9fdbcSPankaj Gupta if (ret < 0) { 162*c6d9fdbcSPankaj Gupta gen_stop(ccsr_i2c); 163*c6d9fdbcSPankaj Gupta return ret; 164*c6d9fdbcSPankaj Gupta } 165*c6d9fdbcSPankaj Gupta if (i == (len - 1)) { 166*c6d9fdbcSPankaj Gupta gen_stop(ccsr_i2c); 167*c6d9fdbcSPankaj Gupta } else if (i == (len - 2)) { 168*c6d9fdbcSPankaj Gupta /* Updating the command to send 169*c6d9fdbcSPankaj Gupta * No ACK. 170*c6d9fdbcSPankaj Gupta */ 171*c6d9fdbcSPankaj Gupta cr = i2c_in(&ccsr_i2c->cr); 172*c6d9fdbcSPankaj Gupta cr |= I2C_CR_TX_NAK; 173*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, cr); 174*c6d9fdbcSPankaj Gupta } 175*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->sr, I2C_SR_IF); 176*c6d9fdbcSPankaj Gupta buf[i] = i2c_in(&ccsr_i2c->dr); 177*c6d9fdbcSPankaj Gupta } 178*c6d9fdbcSPankaj Gupta 179*c6d9fdbcSPankaj Gupta return 0; 180*c6d9fdbcSPankaj Gupta } 181*c6d9fdbcSPankaj Gupta 182*c6d9fdbcSPankaj Gupta static int write_data(struct ls_i2c *ccsr_i2c, unsigned char chip, 183*c6d9fdbcSPankaj Gupta const unsigned char *buf, int len) 184*c6d9fdbcSPankaj Gupta { 185*c6d9fdbcSPankaj Gupta int i; 186*c6d9fdbcSPankaj Gupta int ret; 187*c6d9fdbcSPankaj Gupta 188*c6d9fdbcSPankaj Gupta for (i = 0; i < len; i++) { 189*c6d9fdbcSPankaj Gupta ret = tx_byte(ccsr_i2c, buf[i]); 190*c6d9fdbcSPankaj Gupta if (ret < 0) { 191*c6d9fdbcSPankaj Gupta break; 192*c6d9fdbcSPankaj Gupta } 193*c6d9fdbcSPankaj Gupta } 194*c6d9fdbcSPankaj Gupta ret = gen_stop(ccsr_i2c); 195*c6d9fdbcSPankaj Gupta 196*c6d9fdbcSPankaj Gupta return ret; 197*c6d9fdbcSPankaj Gupta } 198*c6d9fdbcSPankaj Gupta 199*c6d9fdbcSPankaj Gupta 200*c6d9fdbcSPankaj Gupta int i2c_read(unsigned char chip, int addr, int alen, 201*c6d9fdbcSPankaj Gupta unsigned char *buf, int len) 202*c6d9fdbcSPankaj Gupta { 203*c6d9fdbcSPankaj Gupta int ret; 204*c6d9fdbcSPankaj Gupta unsigned char cr; 205*c6d9fdbcSPankaj Gupta struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; 206*c6d9fdbcSPankaj Gupta 207*c6d9fdbcSPankaj Gupta ret = i2c_write_addr(ccsr_i2c, chip, addr, alen); 208*c6d9fdbcSPankaj Gupta if (ret < 0) { 209*c6d9fdbcSPankaj Gupta gen_stop(ccsr_i2c); 210*c6d9fdbcSPankaj Gupta return ret; 211*c6d9fdbcSPankaj Gupta } 212*c6d9fdbcSPankaj Gupta 213*c6d9fdbcSPankaj Gupta cr = i2c_in(&ccsr_i2c->cr); 214*c6d9fdbcSPankaj Gupta cr |= I2C_CR_RSTA; 215*c6d9fdbcSPankaj Gupta i2c_out(&ccsr_i2c->cr, cr); 216*c6d9fdbcSPankaj Gupta 217*c6d9fdbcSPankaj Gupta ret = tx_byte(ccsr_i2c, (chip << 1) | 1); 218*c6d9fdbcSPankaj Gupta if (ret < 0) { 219*c6d9fdbcSPankaj Gupta gen_stop(ccsr_i2c); 220*c6d9fdbcSPankaj Gupta return ret; 221*c6d9fdbcSPankaj Gupta } 222*c6d9fdbcSPankaj Gupta 223*c6d9fdbcSPankaj Gupta return read_data(ccsr_i2c, chip, buf, len); 224*c6d9fdbcSPankaj Gupta } 225*c6d9fdbcSPankaj Gupta 226*c6d9fdbcSPankaj Gupta int i2c_write(unsigned char chip, int addr, int alen, 227*c6d9fdbcSPankaj Gupta const unsigned char *buf, int len) 228*c6d9fdbcSPankaj Gupta { 229*c6d9fdbcSPankaj Gupta int ret; 230*c6d9fdbcSPankaj Gupta struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; 231*c6d9fdbcSPankaj Gupta 232*c6d9fdbcSPankaj Gupta ret = i2c_write_addr(ccsr_i2c, chip, addr, alen); 233*c6d9fdbcSPankaj Gupta if (ret < 0) { 234*c6d9fdbcSPankaj Gupta return ret; 235*c6d9fdbcSPankaj Gupta } 236*c6d9fdbcSPankaj Gupta 237*c6d9fdbcSPankaj Gupta return write_data(ccsr_i2c, chip, buf, len); 238*c6d9fdbcSPankaj Gupta } 239*c6d9fdbcSPankaj Gupta 240*c6d9fdbcSPankaj Gupta int i2c_probe_chip(unsigned char chip) 241*c6d9fdbcSPankaj Gupta { 242*c6d9fdbcSPankaj Gupta int ret; 243*c6d9fdbcSPankaj Gupta struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; 244*c6d9fdbcSPankaj Gupta 245*c6d9fdbcSPankaj Gupta ret = i2c_write_addr(ccsr_i2c, chip, 0, 0); 246*c6d9fdbcSPankaj Gupta if (ret < 0) { 247*c6d9fdbcSPankaj Gupta WARN("write addr failed\n"); 248*c6d9fdbcSPankaj Gupta return ret; 249*c6d9fdbcSPankaj Gupta } 250*c6d9fdbcSPankaj Gupta 251*c6d9fdbcSPankaj Gupta ret = gen_stop(ccsr_i2c); 252*c6d9fdbcSPankaj Gupta if (ret < 0) { 253*c6d9fdbcSPankaj Gupta WARN("I2C: Probe not complete.\n"); 254*c6d9fdbcSPankaj Gupta } 255*c6d9fdbcSPankaj Gupta 256*c6d9fdbcSPankaj Gupta return ret; 257*c6d9fdbcSPankaj Gupta } 258