1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2018 Arm Ltd. 4 * Author: Liviu Dudau <liviu.dudau@foss.arm.com> 5 * 6 */ 7 8 #include <common.h> 9 #include <dm.h> 10 #include <errno.h> 11 #include <i2c.h> 12 #include <asm/io.h> 13 #include <clk.h> 14 #include <linux/io.h> 15 16 #define I2C_CONTROL_REG 0x00 17 #define I2C_SET_REG 0x00 18 #define I2C_CLEAR_REG 0x04 19 20 #define SCL BIT(0) 21 #define SDA BIT(1) 22 23 struct versatile_i2c_priv { 24 phys_addr_t base; 25 u32 delay; 26 }; 27 28 static inline void versatile_sda_set(struct versatile_i2c_priv *priv, u8 state) 29 { 30 writel(SDA, priv->base + (state ? I2C_SET_REG : I2C_CLEAR_REG)); 31 udelay(priv->delay); 32 } 33 34 static inline int versatile_sda_get(struct versatile_i2c_priv *priv) 35 { 36 int v = !!(readl(priv->base + I2C_CONTROL_REG) & SDA); 37 38 udelay(priv->delay); 39 return v; 40 } 41 42 static inline void versatile_scl_set(struct versatile_i2c_priv *priv, u8 state) 43 { 44 writel(SCL, priv->base + (state ? I2C_SET_REG : I2C_CLEAR_REG)); 45 udelay(priv->delay); 46 } 47 48 static inline int versatile_scl_get(struct versatile_i2c_priv *priv) 49 { 50 int v = !!(readl(priv->base + I2C_CONTROL_REG) & SCL); 51 52 udelay(priv->delay); 53 return v; 54 } 55 56 /* start: SDA goes from high to low while SCL is high */ 57 static void versatile_i2c_start(struct versatile_i2c_priv *priv) 58 { 59 udelay(priv->delay); 60 versatile_sda_set(priv, 1); 61 versatile_scl_set(priv, 1); 62 versatile_sda_set(priv, 0); 63 } 64 65 /* stop: SDA goes from low to high while SCL is high */ 66 static void versatile_i2c_stop(struct versatile_i2c_priv *priv) 67 { 68 versatile_scl_set(priv, 0); 69 versatile_sda_set(priv, 0); 70 versatile_scl_set(priv, 1); 71 versatile_sda_set(priv, 1); 72 } 73 74 /* read a bit from the SDA line (data or ACK/NACK) */ 75 static u8 versatile_i2c_read_bit(struct versatile_i2c_priv *priv) 76 { 77 versatile_scl_set(priv, 0); 78 versatile_sda_set(priv, 1); 79 versatile_scl_set(priv, 1); 80 udelay(priv->delay); 81 return (u8)versatile_sda_get(priv); 82 } 83 84 /* write a bit on the SDA line */ 85 static void versatile_i2c_write_bit(struct versatile_i2c_priv *priv, u8 bit) 86 { 87 versatile_scl_set(priv, 0); 88 versatile_sda_set(priv, bit); 89 versatile_scl_set(priv, 1); 90 udelay(priv->delay); 91 } 92 93 /* send a reset sequence of 9 clocks with SDA high */ 94 static void versatile_i2c_reset_bus(struct versatile_i2c_priv *priv) 95 { 96 int i; 97 98 for (i = 0; i < 9; i++) 99 versatile_i2c_write_bit(priv, 1); 100 101 versatile_i2c_stop(priv); 102 } 103 104 /* write byte without start/stop sequence */ 105 static int versatile_i2c_write_byte(struct versatile_i2c_priv *priv, u8 byte) 106 { 107 u8 nak, i; 108 109 for (i = 0; i < 8; i++) { 110 versatile_i2c_write_bit(priv, byte & 0x80); 111 byte <<= 1; 112 } 113 114 /* read ACK */ 115 nak = versatile_i2c_read_bit(priv); 116 versatile_scl_set(priv, 0); 117 118 return nak; /* not a nack is an ack */ 119 } 120 121 static int versatile_i2c_read_byte(struct versatile_i2c_priv *priv, 122 u8 *byte, u8 ack) 123 { 124 u8 i; 125 126 *byte = 0; 127 for (i = 0; i < 8; i++) { 128 *byte <<= 1; 129 *byte |= versatile_i2c_read_bit(priv); 130 } 131 /* write the nack */ 132 versatile_i2c_write_bit(priv, ack); 133 134 return 0; 135 } 136 137 static int versatile_i2c_send_slave_addr(struct versatile_i2c_priv *priv, 138 struct i2c_msg *msg) 139 { 140 u8 addr; 141 int ret; 142 143 if (msg->flags & I2C_M_TEN) { 144 /* 10-bit address, send extended address code first */ 145 addr = 0xf0 | ((msg->addr >> 7) & 0x06); 146 ret = versatile_i2c_write_byte(priv, addr); 147 if (ret) { 148 versatile_i2c_stop(priv); 149 return -EIO; 150 } 151 152 /* remaining bits */ 153 ret = versatile_i2c_write_byte(priv, msg->addr & 0xff); 154 if (ret) { 155 versatile_i2c_stop(priv); 156 return -EIO; 157 } 158 /* reads need to resend the addr */ 159 if (msg->flags & I2C_M_RD) { 160 versatile_i2c_start(priv); 161 addr |= 1; 162 ret = versatile_i2c_write_byte(priv, addr); 163 if (ret) { 164 versatile_i2c_stop(priv); 165 return -EIO; 166 } 167 } 168 } else { 169 /* normal 7-bit address */ 170 addr = msg->addr << 1; 171 if (msg->flags & I2C_M_RD) 172 addr |= 1; 173 ret = versatile_i2c_write_byte(priv, addr); 174 if (ret) { 175 versatile_i2c_stop(priv); 176 return -EIO; 177 } 178 } 179 180 return 0; 181 } 182 183 static int versatile_i2c_message_xfer(struct versatile_i2c_priv *priv, 184 struct i2c_msg *msg) 185 { 186 int i, ret; 187 u8 ack; 188 189 versatile_i2c_start(priv); 190 if (versatile_i2c_send_slave_addr(priv, msg)) 191 return -EIO; 192 193 for (i = 0; i < msg->len; i++) { 194 if (msg->flags & I2C_M_RD) { 195 ack = (msg->len - i - 1) == 0 ? 1 : 0; 196 ret = versatile_i2c_read_byte(priv, &msg->buf[i], ack); 197 } else { 198 ret = versatile_i2c_write_byte(priv, msg->buf[i]); 199 } 200 201 if (ret) 202 break; 203 } 204 205 versatile_i2c_stop(priv); 206 207 return ret; 208 } 209 210 static int versatile_i2c_xfer(struct udevice *bus, 211 struct i2c_msg *msg, int nmsgs) 212 { 213 struct versatile_i2c_priv *priv = dev_get_priv(bus); 214 int ret; 215 216 for ( ; nmsgs > 0; nmsgs--, msg++) { 217 ret = versatile_i2c_message_xfer(priv, msg); 218 if (ret) 219 return -EREMOTEIO; 220 } 221 222 return 0; 223 } 224 225 static int versatile_i2c_chip_probe(struct udevice *bus, 226 uint chip, uint chip_flags) 227 { 228 /* probe the presence of a slave by writing a 0-size message */ 229 struct i2c_msg msg = { .addr = chip, .flags = chip_flags, 230 .len = 0, .buf = NULL }; 231 struct versatile_i2c_priv *priv = dev_get_priv(bus); 232 233 return versatile_i2c_message_xfer(priv, &msg); 234 } 235 236 static int versatile_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) 237 { 238 struct versatile_i2c_priv *priv = dev_get_priv(bus); 239 240 priv->delay = 1000000 / (speed << 2); 241 242 versatile_i2c_reset_bus(priv); 243 244 return 0; 245 } 246 247 static int versatile_i2c_probe(struct udevice *dev) 248 { 249 struct versatile_i2c_priv *priv = dev_get_priv(dev); 250 251 priv->base = (phys_addr_t)dev_read_addr(dev); 252 priv->delay = 25; /* 25us * 4 = 100kHz */ 253 /* 254 * U-Boot still doesn't assign automatically 255 * sequence numbers to devices 256 */ 257 dev->req_seq = 1; 258 259 return 0; 260 } 261 262 static const struct dm_i2c_ops versatile_i2c_ops = { 263 .xfer = versatile_i2c_xfer, 264 .probe_chip = versatile_i2c_chip_probe, 265 .set_bus_speed = versatile_i2c_set_bus_speed, 266 }; 267 268 static const struct udevice_id versatile_i2c_of_match[] = { 269 { .compatible = "arm,versatile-i2c" }, 270 { } 271 }; 272 273 U_BOOT_DRIVER(versatile_i2c) = { 274 .name = "i2c-bus-versatile", 275 .id = UCLASS_I2C, 276 .of_match = versatile_i2c_of_match, 277 .probe = versatile_i2c_probe, 278 .priv_auto_alloc_size = sizeof(struct versatile_i2c_priv), 279 .ops = &versatile_i2c_ops, 280 }; 281