1*031ed2faSVipin KUMAR /* 2*031ed2faSVipin KUMAR * (C) Copyright 2009 3*031ed2faSVipin KUMAR * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. 4*031ed2faSVipin KUMAR * 5*031ed2faSVipin KUMAR * See file CREDITS for list of people who contributed to this 6*031ed2faSVipin KUMAR * project. 7*031ed2faSVipin KUMAR * 8*031ed2faSVipin KUMAR * This program is free software; you can redistribute it and/or 9*031ed2faSVipin KUMAR * modify it under the terms of the GNU General Public License as 10*031ed2faSVipin KUMAR * published by the Free Software Foundation; either version 2 of 11*031ed2faSVipin KUMAR * the License, or (at your option) any later version. 12*031ed2faSVipin KUMAR * 13*031ed2faSVipin KUMAR * This program is distributed in the hope that it will be useful, 14*031ed2faSVipin KUMAR * but WITHOUT ANY WARRANTY; without even the implied warranty of 15*031ed2faSVipin KUMAR * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16*031ed2faSVipin KUMAR * GNU General Public License for more details. 17*031ed2faSVipin KUMAR * 18*031ed2faSVipin KUMAR * You should have received a copy of the GNU General Public License 19*031ed2faSVipin KUMAR * along with this program; if not, write to the Free Software 20*031ed2faSVipin KUMAR * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21*031ed2faSVipin KUMAR * MA 02111-1307 USA 22*031ed2faSVipin KUMAR */ 23*031ed2faSVipin KUMAR 24*031ed2faSVipin KUMAR #include <common.h> 25*031ed2faSVipin KUMAR #include <asm/io.h> 26*031ed2faSVipin KUMAR #include <asm/arch/hardware.h> 27*031ed2faSVipin KUMAR #include "designware_i2c.h" 28*031ed2faSVipin KUMAR 29*031ed2faSVipin KUMAR static struct i2c_regs *const i2c_regs_p = 30*031ed2faSVipin KUMAR (struct i2c_regs *)CONFIG_SYS_I2C_BASE; 31*031ed2faSVipin KUMAR 32*031ed2faSVipin KUMAR /* 33*031ed2faSVipin KUMAR * set_speed - Set the i2c speed mode (standard, high, fast) 34*031ed2faSVipin KUMAR * @i2c_spd: required i2c speed mode 35*031ed2faSVipin KUMAR * 36*031ed2faSVipin KUMAR * Set the i2c speed mode (standard, high, fast) 37*031ed2faSVipin KUMAR */ 38*031ed2faSVipin KUMAR static void set_speed(int i2c_spd) 39*031ed2faSVipin KUMAR { 40*031ed2faSVipin KUMAR unsigned int cntl; 41*031ed2faSVipin KUMAR unsigned int hcnt, lcnt; 42*031ed2faSVipin KUMAR unsigned int high, low; 43*031ed2faSVipin KUMAR 44*031ed2faSVipin KUMAR cntl = (readl(&i2c_regs_p->ic_con) & (~IC_CON_SPD_MSK)); 45*031ed2faSVipin KUMAR 46*031ed2faSVipin KUMAR switch (i2c_spd) { 47*031ed2faSVipin KUMAR case IC_SPEED_MODE_MAX: 48*031ed2faSVipin KUMAR cntl |= IC_CON_SPD_HS; 49*031ed2faSVipin KUMAR high = MIN_HS_SCL_HIGHTIME; 50*031ed2faSVipin KUMAR low = MIN_HS_SCL_LOWTIME; 51*031ed2faSVipin KUMAR break; 52*031ed2faSVipin KUMAR 53*031ed2faSVipin KUMAR case IC_SPEED_MODE_STANDARD: 54*031ed2faSVipin KUMAR cntl |= IC_CON_SPD_SS; 55*031ed2faSVipin KUMAR high = MIN_SS_SCL_HIGHTIME; 56*031ed2faSVipin KUMAR low = MIN_SS_SCL_LOWTIME; 57*031ed2faSVipin KUMAR break; 58*031ed2faSVipin KUMAR 59*031ed2faSVipin KUMAR case IC_SPEED_MODE_FAST: 60*031ed2faSVipin KUMAR default: 61*031ed2faSVipin KUMAR cntl |= IC_CON_SPD_FS; 62*031ed2faSVipin KUMAR high = MIN_FS_SCL_HIGHTIME; 63*031ed2faSVipin KUMAR low = MIN_FS_SCL_LOWTIME; 64*031ed2faSVipin KUMAR break; 65*031ed2faSVipin KUMAR } 66*031ed2faSVipin KUMAR 67*031ed2faSVipin KUMAR writel(cntl, &i2c_regs_p->ic_con); 68*031ed2faSVipin KUMAR 69*031ed2faSVipin KUMAR hcnt = (IC_CLK * high) / NANO_TO_MICRO; 70*031ed2faSVipin KUMAR writel(hcnt, &i2c_regs_p->ic_fs_scl_hcnt); 71*031ed2faSVipin KUMAR 72*031ed2faSVipin KUMAR lcnt = (IC_CLK * low) / NANO_TO_MICRO; 73*031ed2faSVipin KUMAR writel(lcnt, &i2c_regs_p->ic_fs_scl_lcnt); 74*031ed2faSVipin KUMAR } 75*031ed2faSVipin KUMAR 76*031ed2faSVipin KUMAR /* 77*031ed2faSVipin KUMAR * i2c_set_bus_speed - Set the i2c speed 78*031ed2faSVipin KUMAR * @speed: required i2c speed 79*031ed2faSVipin KUMAR * 80*031ed2faSVipin KUMAR * Set the i2c speed. 81*031ed2faSVipin KUMAR */ 82*031ed2faSVipin KUMAR void i2c_set_bus_speed(int speed) 83*031ed2faSVipin KUMAR { 84*031ed2faSVipin KUMAR if (speed >= I2C_MAX_SPEED) 85*031ed2faSVipin KUMAR set_speed(IC_SPEED_MODE_MAX); 86*031ed2faSVipin KUMAR else if (speed >= I2C_FAST_SPEED) 87*031ed2faSVipin KUMAR set_speed(IC_SPEED_MODE_FAST); 88*031ed2faSVipin KUMAR else 89*031ed2faSVipin KUMAR set_speed(IC_SPEED_MODE_STANDARD); 90*031ed2faSVipin KUMAR } 91*031ed2faSVipin KUMAR 92*031ed2faSVipin KUMAR /* 93*031ed2faSVipin KUMAR * i2c_get_bus_speed - Gets the i2c speed 94*031ed2faSVipin KUMAR * 95*031ed2faSVipin KUMAR * Gets the i2c speed. 96*031ed2faSVipin KUMAR */ 97*031ed2faSVipin KUMAR int i2c_get_bus_speed(void) 98*031ed2faSVipin KUMAR { 99*031ed2faSVipin KUMAR u32 cntl; 100*031ed2faSVipin KUMAR 101*031ed2faSVipin KUMAR cntl = (readl(&i2c_regs_p->ic_con) & IC_CON_SPD_MSK); 102*031ed2faSVipin KUMAR 103*031ed2faSVipin KUMAR if (cntl == IC_CON_SPD_HS) 104*031ed2faSVipin KUMAR return I2C_MAX_SPEED; 105*031ed2faSVipin KUMAR else if (cntl == IC_CON_SPD_FS) 106*031ed2faSVipin KUMAR return I2C_FAST_SPEED; 107*031ed2faSVipin KUMAR else if (cntl == IC_CON_SPD_SS) 108*031ed2faSVipin KUMAR return I2C_STANDARD_SPEED; 109*031ed2faSVipin KUMAR 110*031ed2faSVipin KUMAR return 0; 111*031ed2faSVipin KUMAR } 112*031ed2faSVipin KUMAR 113*031ed2faSVipin KUMAR /* 114*031ed2faSVipin KUMAR * i2c_init - Init function 115*031ed2faSVipin KUMAR * @speed: required i2c speed 116*031ed2faSVipin KUMAR * @slaveadd: slave address for the device 117*031ed2faSVipin KUMAR * 118*031ed2faSVipin KUMAR * Initialization function. 119*031ed2faSVipin KUMAR */ 120*031ed2faSVipin KUMAR void i2c_init(int speed, int slaveadd) 121*031ed2faSVipin KUMAR { 122*031ed2faSVipin KUMAR unsigned int enbl; 123*031ed2faSVipin KUMAR 124*031ed2faSVipin KUMAR /* Disable i2c */ 125*031ed2faSVipin KUMAR enbl = readl(&i2c_regs_p->ic_enable); 126*031ed2faSVipin KUMAR enbl &= ~IC_ENABLE_0B; 127*031ed2faSVipin KUMAR writel(enbl, &i2c_regs_p->ic_enable); 128*031ed2faSVipin KUMAR 129*031ed2faSVipin KUMAR writel((IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM), &i2c_regs_p->ic_con); 130*031ed2faSVipin KUMAR writel(IC_RX_TL, &i2c_regs_p->ic_rx_tl); 131*031ed2faSVipin KUMAR writel(IC_TX_TL, &i2c_regs_p->ic_tx_tl); 132*031ed2faSVipin KUMAR i2c_set_bus_speed(speed); 133*031ed2faSVipin KUMAR writel(IC_STOP_DET, &i2c_regs_p->ic_intr_mask); 134*031ed2faSVipin KUMAR writel(slaveadd, &i2c_regs_p->ic_sar); 135*031ed2faSVipin KUMAR 136*031ed2faSVipin KUMAR /* Enable i2c */ 137*031ed2faSVipin KUMAR enbl = readl(&i2c_regs_p->ic_enable); 138*031ed2faSVipin KUMAR enbl |= IC_ENABLE_0B; 139*031ed2faSVipin KUMAR writel(enbl, &i2c_regs_p->ic_enable); 140*031ed2faSVipin KUMAR } 141*031ed2faSVipin KUMAR 142*031ed2faSVipin KUMAR /* 143*031ed2faSVipin KUMAR * i2c_setaddress - Sets the target slave address 144*031ed2faSVipin KUMAR * @i2c_addr: target i2c address 145*031ed2faSVipin KUMAR * 146*031ed2faSVipin KUMAR * Sets the target slave address. 147*031ed2faSVipin KUMAR */ 148*031ed2faSVipin KUMAR static void i2c_setaddress(unsigned int i2c_addr) 149*031ed2faSVipin KUMAR { 150*031ed2faSVipin KUMAR writel(i2c_addr, &i2c_regs_p->ic_tar); 151*031ed2faSVipin KUMAR } 152*031ed2faSVipin KUMAR 153*031ed2faSVipin KUMAR /* 154*031ed2faSVipin KUMAR * i2c_flush_rxfifo - Flushes the i2c RX FIFO 155*031ed2faSVipin KUMAR * 156*031ed2faSVipin KUMAR * Flushes the i2c RX FIFO 157*031ed2faSVipin KUMAR */ 158*031ed2faSVipin KUMAR static void i2c_flush_rxfifo(void) 159*031ed2faSVipin KUMAR { 160*031ed2faSVipin KUMAR while (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) 161*031ed2faSVipin KUMAR readl(&i2c_regs_p->ic_cmd_data); 162*031ed2faSVipin KUMAR } 163*031ed2faSVipin KUMAR 164*031ed2faSVipin KUMAR /* 165*031ed2faSVipin KUMAR * i2c_wait_for_bb - Waits for bus busy 166*031ed2faSVipin KUMAR * 167*031ed2faSVipin KUMAR * Waits for bus busy 168*031ed2faSVipin KUMAR */ 169*031ed2faSVipin KUMAR static int i2c_wait_for_bb(void) 170*031ed2faSVipin KUMAR { 171*031ed2faSVipin KUMAR unsigned long start_time_bb = get_timer(0); 172*031ed2faSVipin KUMAR 173*031ed2faSVipin KUMAR while ((readl(&i2c_regs_p->ic_status) & IC_STATUS_MA) || 174*031ed2faSVipin KUMAR !(readl(&i2c_regs_p->ic_status) & IC_STATUS_TFE)) { 175*031ed2faSVipin KUMAR 176*031ed2faSVipin KUMAR /* Evaluate timeout */ 177*031ed2faSVipin KUMAR if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB)) 178*031ed2faSVipin KUMAR return 1; 179*031ed2faSVipin KUMAR } 180*031ed2faSVipin KUMAR 181*031ed2faSVipin KUMAR return 0; 182*031ed2faSVipin KUMAR } 183*031ed2faSVipin KUMAR 184*031ed2faSVipin KUMAR /* check parameters for i2c_read and i2c_write */ 185*031ed2faSVipin KUMAR static int check_params(uint addr, int alen, uchar *buffer, int len) 186*031ed2faSVipin KUMAR { 187*031ed2faSVipin KUMAR if (buffer == NULL) { 188*031ed2faSVipin KUMAR printf("Buffer is invalid\n"); 189*031ed2faSVipin KUMAR return 1; 190*031ed2faSVipin KUMAR } 191*031ed2faSVipin KUMAR 192*031ed2faSVipin KUMAR if (alen > 1) { 193*031ed2faSVipin KUMAR printf("addr len %d not supported\n", alen); 194*031ed2faSVipin KUMAR return 1; 195*031ed2faSVipin KUMAR } 196*031ed2faSVipin KUMAR 197*031ed2faSVipin KUMAR if (addr + len > 256) { 198*031ed2faSVipin KUMAR printf("address out of range\n"); 199*031ed2faSVipin KUMAR return 1; 200*031ed2faSVipin KUMAR } 201*031ed2faSVipin KUMAR 202*031ed2faSVipin KUMAR return 0; 203*031ed2faSVipin KUMAR } 204*031ed2faSVipin KUMAR 205*031ed2faSVipin KUMAR static int i2c_xfer_init(uchar chip, uint addr) 206*031ed2faSVipin KUMAR { 207*031ed2faSVipin KUMAR if (i2c_wait_for_bb()) { 208*031ed2faSVipin KUMAR printf("Timed out waiting for bus\n"); 209*031ed2faSVipin KUMAR return 1; 210*031ed2faSVipin KUMAR } 211*031ed2faSVipin KUMAR 212*031ed2faSVipin KUMAR i2c_setaddress(chip); 213*031ed2faSVipin KUMAR writel(addr, &i2c_regs_p->ic_cmd_data); 214*031ed2faSVipin KUMAR 215*031ed2faSVipin KUMAR return 0; 216*031ed2faSVipin KUMAR } 217*031ed2faSVipin KUMAR 218*031ed2faSVipin KUMAR static int i2c_xfer_finish(void) 219*031ed2faSVipin KUMAR { 220*031ed2faSVipin KUMAR ulong start_stop_det = get_timer(0); 221*031ed2faSVipin KUMAR 222*031ed2faSVipin KUMAR while (1) { 223*031ed2faSVipin KUMAR if ((readl(&i2c_regs_p->ic_raw_intr_stat) & IC_STOP_DET)) { 224*031ed2faSVipin KUMAR readl(&i2c_regs_p->ic_clr_stop_det); 225*031ed2faSVipin KUMAR break; 226*031ed2faSVipin KUMAR } else if (get_timer(start_stop_det) > I2C_STOPDET_TO) { 227*031ed2faSVipin KUMAR break; 228*031ed2faSVipin KUMAR } 229*031ed2faSVipin KUMAR } 230*031ed2faSVipin KUMAR 231*031ed2faSVipin KUMAR if (i2c_wait_for_bb()) { 232*031ed2faSVipin KUMAR printf("Timed out waiting for bus\n"); 233*031ed2faSVipin KUMAR return 1; 234*031ed2faSVipin KUMAR } 235*031ed2faSVipin KUMAR 236*031ed2faSVipin KUMAR i2c_flush_rxfifo(); 237*031ed2faSVipin KUMAR 238*031ed2faSVipin KUMAR /* Wait for read/write operation to complete on actual memory */ 239*031ed2faSVipin KUMAR udelay(10000); 240*031ed2faSVipin KUMAR 241*031ed2faSVipin KUMAR return 0; 242*031ed2faSVipin KUMAR } 243*031ed2faSVipin KUMAR 244*031ed2faSVipin KUMAR /* 245*031ed2faSVipin KUMAR * i2c_read - Read from i2c memory 246*031ed2faSVipin KUMAR * @chip: target i2c address 247*031ed2faSVipin KUMAR * @addr: address to read from 248*031ed2faSVipin KUMAR * @alen: 249*031ed2faSVipin KUMAR * @buffer: buffer for read data 250*031ed2faSVipin KUMAR * @len: no of bytes to be read 251*031ed2faSVipin KUMAR * 252*031ed2faSVipin KUMAR * Read from i2c memory. 253*031ed2faSVipin KUMAR */ 254*031ed2faSVipin KUMAR int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) 255*031ed2faSVipin KUMAR { 256*031ed2faSVipin KUMAR unsigned long start_time_rx; 257*031ed2faSVipin KUMAR 258*031ed2faSVipin KUMAR if (check_params(addr, alen, buffer, len)) 259*031ed2faSVipin KUMAR return 1; 260*031ed2faSVipin KUMAR 261*031ed2faSVipin KUMAR if (i2c_xfer_init(chip, addr)) 262*031ed2faSVipin KUMAR return 1; 263*031ed2faSVipin KUMAR 264*031ed2faSVipin KUMAR start_time_rx = get_timer(0); 265*031ed2faSVipin KUMAR while (len) { 266*031ed2faSVipin KUMAR writel(IC_CMD, &i2c_regs_p->ic_cmd_data); 267*031ed2faSVipin KUMAR 268*031ed2faSVipin KUMAR if (readl(&i2c_regs_p->ic_status) & IC_STATUS_RFNE) { 269*031ed2faSVipin KUMAR *buffer++ = (uchar)readl(&i2c_regs_p->ic_cmd_data); 270*031ed2faSVipin KUMAR len--; 271*031ed2faSVipin KUMAR start_time_rx = get_timer(0); 272*031ed2faSVipin KUMAR 273*031ed2faSVipin KUMAR } else if (get_timer(start_time_rx) > I2C_BYTE_TO) { 274*031ed2faSVipin KUMAR printf("Timed out. i2c read Failed\n"); 275*031ed2faSVipin KUMAR return 1; 276*031ed2faSVipin KUMAR } 277*031ed2faSVipin KUMAR } 278*031ed2faSVipin KUMAR 279*031ed2faSVipin KUMAR return i2c_xfer_finish(); 280*031ed2faSVipin KUMAR } 281*031ed2faSVipin KUMAR 282*031ed2faSVipin KUMAR /* 283*031ed2faSVipin KUMAR * i2c_write - Write to i2c memory 284*031ed2faSVipin KUMAR * @chip: target i2c address 285*031ed2faSVipin KUMAR * @addr: address to read from 286*031ed2faSVipin KUMAR * @alen: 287*031ed2faSVipin KUMAR * @buffer: buffer for read data 288*031ed2faSVipin KUMAR * @len: no of bytes to be read 289*031ed2faSVipin KUMAR * 290*031ed2faSVipin KUMAR * Write to i2c memory. 291*031ed2faSVipin KUMAR */ 292*031ed2faSVipin KUMAR int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) 293*031ed2faSVipin KUMAR { 294*031ed2faSVipin KUMAR int nb = len; 295*031ed2faSVipin KUMAR unsigned long start_time_tx; 296*031ed2faSVipin KUMAR 297*031ed2faSVipin KUMAR if (check_params(addr, alen, buffer, len)) 298*031ed2faSVipin KUMAR return 1; 299*031ed2faSVipin KUMAR 300*031ed2faSVipin KUMAR if (i2c_xfer_init(chip, addr)) 301*031ed2faSVipin KUMAR return 1; 302*031ed2faSVipin KUMAR 303*031ed2faSVipin KUMAR start_time_tx = get_timer(0); 304*031ed2faSVipin KUMAR while (len) { 305*031ed2faSVipin KUMAR if (readl(&i2c_regs_p->ic_status) & IC_STATUS_TFNF) { 306*031ed2faSVipin KUMAR writel(*buffer, &i2c_regs_p->ic_cmd_data); 307*031ed2faSVipin KUMAR buffer++; 308*031ed2faSVipin KUMAR len--; 309*031ed2faSVipin KUMAR start_time_tx = get_timer(0); 310*031ed2faSVipin KUMAR 311*031ed2faSVipin KUMAR } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) { 312*031ed2faSVipin KUMAR printf("Timed out. i2c write Failed\n"); 313*031ed2faSVipin KUMAR return 1; 314*031ed2faSVipin KUMAR } 315*031ed2faSVipin KUMAR } 316*031ed2faSVipin KUMAR 317*031ed2faSVipin KUMAR return i2c_xfer_finish(); 318*031ed2faSVipin KUMAR } 319*031ed2faSVipin KUMAR 320*031ed2faSVipin KUMAR /* 321*031ed2faSVipin KUMAR * i2c_probe - Probe the i2c chip 322*031ed2faSVipin KUMAR */ 323*031ed2faSVipin KUMAR int i2c_probe(uchar chip) 324*031ed2faSVipin KUMAR { 325*031ed2faSVipin KUMAR u32 tmp; 326*031ed2faSVipin KUMAR 327*031ed2faSVipin KUMAR /* 328*031ed2faSVipin KUMAR * Try to read the first location of the chip. 329*031ed2faSVipin KUMAR */ 330*031ed2faSVipin KUMAR return i2c_read(chip, 0, 1, (uchar *)&tmp, 1); 331*031ed2faSVipin KUMAR } 332