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