1 /* 2 * (C) Copyright 2013 3 * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 * 7 * NOTE: This driver should be converted to driver model before June 2017. 8 * Please see doc/driver-model/i2c-howto.txt for instructions. 9 */ 10 11 #include <common.h> 12 #include <i2c.h> 13 #include <gdsys_fpga.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 #ifdef CONFIG_SYS_I2C_IHS_DUAL 18 #define I2C_SET_REG(fld, val) \ 19 do { \ 20 if (I2C_ADAP_HWNR & 0x10) \ 21 FPGA_SET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \ 22 else \ 23 FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \ 24 } while (0) 25 #else 26 #define I2C_SET_REG(fld, val) \ 27 FPGA_SET_REG(I2C_ADAP_HWNR, i2c0.fld, val) 28 #endif 29 30 #ifdef CONFIG_SYS_I2C_IHS_DUAL 31 #define I2C_GET_REG(fld, val) \ 32 do { \ 33 if (I2C_ADAP_HWNR & 0x10) \ 34 FPGA_GET_REG(I2C_ADAP_HWNR & 0xf, i2c1.fld, val); \ 35 else \ 36 FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val); \ 37 } while (0) 38 #else 39 #define I2C_GET_REG(fld, val) \ 40 FPGA_GET_REG(I2C_ADAP_HWNR, i2c0.fld, val) 41 #endif 42 43 enum { 44 I2CINT_ERROR_EV = 1 << 13, 45 I2CINT_TRANSMIT_EV = 1 << 14, 46 I2CINT_RECEIVE_EV = 1 << 15, 47 }; 48 49 enum { 50 I2CMB_WRITE = 1 << 10, 51 I2CMB_2BYTE = 1 << 11, 52 I2CMB_HOLD_BUS = 1 << 13, 53 I2CMB_NATIVE = 2 << 14, 54 }; 55 56 static int wait_for_int(bool read) 57 { 58 u16 val; 59 unsigned int ctr = 0; 60 61 I2C_GET_REG(interrupt_status, &val); 62 while (!(val & (I2CINT_ERROR_EV 63 | (read ? I2CINT_RECEIVE_EV : I2CINT_TRANSMIT_EV)))) { 64 udelay(10); 65 if (ctr++ > 5000) { 66 return 1; 67 } 68 I2C_GET_REG(interrupt_status, &val); 69 } 70 71 return (val & I2CINT_ERROR_EV) ? 1 : 0; 72 } 73 74 static int ihs_i2c_transfer(uchar chip, uchar *buffer, int len, bool read, 75 bool is_last) 76 { 77 u16 val; 78 79 I2C_SET_REG(interrupt_status, I2CINT_ERROR_EV 80 | I2CINT_RECEIVE_EV | I2CINT_TRANSMIT_EV); 81 I2C_GET_REG(interrupt_status, &val); 82 83 if (!read && len) { 84 val = buffer[0]; 85 86 if (len > 1) 87 val |= buffer[1] << 8; 88 I2C_SET_REG(write_mailbox_ext, val); 89 } 90 91 I2C_SET_REG(write_mailbox, 92 I2CMB_NATIVE 93 | (read ? 0 : I2CMB_WRITE) 94 | (chip << 1) 95 | ((len > 1) ? I2CMB_2BYTE : 0) 96 | (is_last ? 0 : I2CMB_HOLD_BUS)); 97 98 if (wait_for_int(read)) 99 return 1; 100 101 if (read) { 102 I2C_GET_REG(read_mailbox_ext, &val); 103 buffer[0] = val & 0xff; 104 if (len > 1) 105 buffer[1] = val >> 8; 106 } 107 108 return 0; 109 } 110 111 static int ihs_i2c_address(uchar chip, uint addr, int alen, bool hold_bus) 112 { 113 int shift = (alen-1) * 8; 114 115 while (alen) { 116 int transfer = min(alen, 2); 117 uchar buf[2]; 118 bool is_last = alen <= transfer; 119 120 buf[0] = addr >> shift; 121 if (alen > 1) 122 buf[1] = addr >> (shift - 8); 123 124 if (ihs_i2c_transfer(chip, buf, transfer, false, 125 hold_bus ? false : is_last)) 126 return 1; 127 128 shift -= 16; 129 alen -= transfer; 130 } 131 132 return 0; 133 } 134 135 static int ihs_i2c_access(struct i2c_adapter *adap, uchar chip, uint addr, 136 int alen, uchar *buffer, int len, bool read) 137 { 138 if (len <= 0) 139 return 1; 140 141 if (ihs_i2c_address(chip, addr, alen, len)) 142 return 1; 143 144 while (len) { 145 int transfer = min(len, 2); 146 147 if (ihs_i2c_transfer(chip, buffer, transfer, read, 148 len <= transfer)) 149 return 1; 150 151 buffer += transfer; 152 addr += transfer; 153 len -= transfer; 154 } 155 156 return 0; 157 } 158 159 160 static void ihs_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) 161 { 162 #ifdef CONFIG_SYS_I2C_INIT_BOARD 163 /* 164 * Call board specific i2c bus reset routine before accessing the 165 * environment, which might be in a chip on that bus. For details 166 * about this problem see doc/I2C_Edge_Conditions. 167 */ 168 i2c_init_board(); 169 #endif 170 } 171 172 static int ihs_i2c_probe(struct i2c_adapter *adap, uchar chip) 173 { 174 uchar buffer[2]; 175 176 if (ihs_i2c_transfer(chip, buffer, 0, true, true)) 177 return 1; 178 179 return 0; 180 } 181 182 static int ihs_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, 183 int alen, uchar *buffer, int len) 184 { 185 return ihs_i2c_access(adap, chip, addr, alen, buffer, len, true); 186 } 187 188 static int ihs_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, 189 int alen, uchar *buffer, int len) 190 { 191 return ihs_i2c_access(adap, chip, addr, alen, buffer, len, false); 192 } 193 194 static unsigned int ihs_i2c_set_bus_speed(struct i2c_adapter *adap, 195 unsigned int speed) 196 { 197 if (speed != adap->speed) 198 return 1; 199 return speed; 200 } 201 202 /* 203 * Register IHS i2c adapters 204 */ 205 #ifdef CONFIG_SYS_I2C_IHS_CH0 206 U_BOOT_I2C_ADAP_COMPLETE(ihs0, ihs_i2c_init, ihs_i2c_probe, 207 ihs_i2c_read, ihs_i2c_write, 208 ihs_i2c_set_bus_speed, 209 CONFIG_SYS_I2C_IHS_SPEED_0, 210 CONFIG_SYS_I2C_IHS_SLAVE_0, 0) 211 #ifdef CONFIG_SYS_I2C_IHS_DUAL 212 U_BOOT_I2C_ADAP_COMPLETE(ihs0_1, ihs_i2c_init, ihs_i2c_probe, 213 ihs_i2c_read, ihs_i2c_write, 214 ihs_i2c_set_bus_speed, 215 CONFIG_SYS_I2C_IHS_SPEED_0_1, 216 CONFIG_SYS_I2C_IHS_SLAVE_0_1, 16) 217 #endif 218 #endif 219 #ifdef CONFIG_SYS_I2C_IHS_CH1 220 U_BOOT_I2C_ADAP_COMPLETE(ihs1, ihs_i2c_init, ihs_i2c_probe, 221 ihs_i2c_read, ihs_i2c_write, 222 ihs_i2c_set_bus_speed, 223 CONFIG_SYS_I2C_IHS_SPEED_1, 224 CONFIG_SYS_I2C_IHS_SLAVE_1, 1) 225 #ifdef CONFIG_SYS_I2C_IHS_DUAL 226 U_BOOT_I2C_ADAP_COMPLETE(ihs1_1, ihs_i2c_init, ihs_i2c_probe, 227 ihs_i2c_read, ihs_i2c_write, 228 ihs_i2c_set_bus_speed, 229 CONFIG_SYS_I2C_IHS_SPEED_1_1, 230 CONFIG_SYS_I2C_IHS_SLAVE_1_1, 17) 231 #endif 232 #endif 233 #ifdef CONFIG_SYS_I2C_IHS_CH2 234 U_BOOT_I2C_ADAP_COMPLETE(ihs2, ihs_i2c_init, ihs_i2c_probe, 235 ihs_i2c_read, ihs_i2c_write, 236 ihs_i2c_set_bus_speed, 237 CONFIG_SYS_I2C_IHS_SPEED_2, 238 CONFIG_SYS_I2C_IHS_SLAVE_2, 2) 239 #ifdef CONFIG_SYS_I2C_IHS_DUAL 240 U_BOOT_I2C_ADAP_COMPLETE(ihs2_1, ihs_i2c_init, ihs_i2c_probe, 241 ihs_i2c_read, ihs_i2c_write, 242 ihs_i2c_set_bus_speed, 243 CONFIG_SYS_I2C_IHS_SPEED_2_1, 244 CONFIG_SYS_I2C_IHS_SLAVE_2_1, 18) 245 #endif 246 #endif 247 #ifdef CONFIG_SYS_I2C_IHS_CH3 248 U_BOOT_I2C_ADAP_COMPLETE(ihs3, ihs_i2c_init, ihs_i2c_probe, 249 ihs_i2c_read, ihs_i2c_write, 250 ihs_i2c_set_bus_speed, 251 CONFIG_SYS_I2C_IHS_SPEED_3, 252 CONFIG_SYS_I2C_IHS_SLAVE_3, 3) 253 #ifdef CONFIG_SYS_I2C_IHS_DUAL 254 U_BOOT_I2C_ADAP_COMPLETE(ihs3_1, ihs_i2c_init, ihs_i2c_probe, 255 ihs_i2c_read, ihs_i2c_write, 256 ihs_i2c_set_bus_speed, 257 CONFIG_SYS_I2C_IHS_SPEED_3_1, 258 CONFIG_SYS_I2C_IHS_SLAVE_3_1, 19) 259 #endif 260 #endif 261