1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) IBM Corporation 2023 */ 3 4 #include <linux/device.h> 5 #include <linux/fsi.h> 6 #include <linux/i2c.h> 7 #include <linux/module.h> 8 #include <linux/mod_devicetable.h> 9 #include <linux/mutex.h> 10 11 #include "fsi-master-i2cr.h" 12 13 #define CREATE_TRACE_POINTS 14 #include <trace/events/fsi_master_i2cr.h> 15 16 #define I2CR_ADDRESS_CFAM(a) ((a) >> 2) 17 #define I2CR_INITIAL_PARITY true 18 19 #define I2CR_STATUS_CMD 0x60002 20 #define I2CR_STATUS_ERR BIT_ULL(61) 21 #define I2CR_ERROR_CMD 0x60004 22 #define I2CR_LOG_CMD 0x60008 23 24 static const u8 i2cr_cfam[] = { 25 0xc0, 0x02, 0x0d, 0xa6, 26 0x80, 0x01, 0x10, 0x02, 27 0x80, 0x01, 0x10, 0x02, 28 0x80, 0x01, 0x10, 0x02, 29 0x80, 0x01, 0x80, 0x52, 30 0x80, 0x01, 0x10, 0x02, 31 0x80, 0x01, 0x10, 0x02, 32 0x80, 0x01, 0x10, 0x02, 33 0x80, 0x01, 0x10, 0x02, 34 0x80, 0x01, 0x22, 0x2d, 35 0x00, 0x00, 0x00, 0x00, 36 0xde, 0xad, 0xc0, 0xde 37 }; 38 39 static bool i2cr_check_parity32(u32 v, bool parity) 40 { 41 u32 i; 42 43 for (i = 0; i < 32; ++i) { 44 if (v & (1u << i)) 45 parity = !parity; 46 } 47 48 return parity; 49 } 50 51 static bool i2cr_check_parity64(u64 v) 52 { 53 u32 i; 54 bool parity = I2CR_INITIAL_PARITY; 55 56 for (i = 0; i < 64; ++i) { 57 if (v & (1llu << i)) 58 parity = !parity; 59 } 60 61 return parity; 62 } 63 64 static u32 i2cr_get_command(u32 address, bool parity) 65 { 66 address <<= 1; 67 68 if (i2cr_check_parity32(address, parity)) 69 address |= 1; 70 71 return address; 72 } 73 74 static int i2cr_transfer(struct i2c_client *client, u32 command, u64 *data) 75 { 76 struct i2c_msg msgs[2]; 77 int ret; 78 79 msgs[0].addr = client->addr; 80 msgs[0].flags = 0; 81 msgs[0].len = sizeof(command); 82 msgs[0].buf = (__u8 *)&command; 83 msgs[1].addr = client->addr; 84 msgs[1].flags = I2C_M_RD; 85 msgs[1].len = sizeof(*data); 86 msgs[1].buf = (__u8 *)data; 87 88 ret = i2c_transfer(client->adapter, msgs, 2); 89 if (ret == 2) 90 return 0; 91 92 trace_i2cr_i2c_error(client, command, ret); 93 94 if (ret < 0) 95 return ret; 96 97 return -EIO; 98 } 99 100 static int i2cr_check_status(struct i2c_client *client) 101 { 102 u64 status; 103 int ret; 104 105 ret = i2cr_transfer(client, I2CR_STATUS_CMD, &status); 106 if (ret) 107 return ret; 108 109 if (status & I2CR_STATUS_ERR) { 110 u32 buf[3] = { 0, 0, 0 }; 111 u64 error; 112 u64 log; 113 114 i2cr_transfer(client, I2CR_ERROR_CMD, &error); 115 i2cr_transfer(client, I2CR_LOG_CMD, &log); 116 117 trace_i2cr_status_error(client, status, error, log); 118 119 buf[0] = I2CR_STATUS_CMD; 120 i2c_master_send(client, (const char *)buf, sizeof(buf)); 121 122 buf[0] = I2CR_ERROR_CMD; 123 i2c_master_send(client, (const char *)buf, sizeof(buf)); 124 125 buf[0] = I2CR_LOG_CMD; 126 i2c_master_send(client, (const char *)buf, sizeof(buf)); 127 128 dev_err(&client->dev, "status:%016llx error:%016llx log:%016llx\n", status, error, 129 log); 130 return -EREMOTEIO; 131 } 132 133 trace_i2cr_status(client, status); 134 return 0; 135 } 136 137 int fsi_master_i2cr_read(struct fsi_master_i2cr *i2cr, u32 addr, u64 *data) 138 { 139 u32 command = i2cr_get_command(addr, I2CR_INITIAL_PARITY); 140 int ret; 141 142 mutex_lock(&i2cr->lock); 143 144 ret = i2cr_transfer(i2cr->client, command, data); 145 if (ret) 146 goto unlock; 147 148 ret = i2cr_check_status(i2cr->client); 149 if (ret) 150 goto unlock; 151 152 trace_i2cr_read(i2cr->client, command, data); 153 154 unlock: 155 mutex_unlock(&i2cr->lock); 156 return ret; 157 } 158 EXPORT_SYMBOL_GPL(fsi_master_i2cr_read); 159 160 int fsi_master_i2cr_write(struct fsi_master_i2cr *i2cr, u32 addr, u64 data) 161 { 162 u32 buf[3] = { 0 }; 163 int ret; 164 165 buf[0] = i2cr_get_command(addr, i2cr_check_parity64(data)); 166 memcpy(&buf[1], &data, sizeof(data)); 167 168 mutex_lock(&i2cr->lock); 169 170 ret = i2c_master_send(i2cr->client, (const char *)buf, sizeof(buf)); 171 if (ret == sizeof(buf)) { 172 ret = i2cr_check_status(i2cr->client); 173 if (!ret) 174 trace_i2cr_write(i2cr->client, buf[0], data); 175 } else { 176 trace_i2cr_i2c_error(i2cr->client, buf[0], ret); 177 178 if (ret >= 0) 179 ret = -EIO; 180 } 181 182 mutex_unlock(&i2cr->lock); 183 return ret; 184 } 185 EXPORT_SYMBOL_GPL(fsi_master_i2cr_write); 186 187 static int i2cr_read(struct fsi_master *master, int link, uint8_t id, uint32_t addr, void *val, 188 size_t size) 189 { 190 struct fsi_master_i2cr *i2cr = container_of(master, struct fsi_master_i2cr, master); 191 u64 data; 192 size_t i; 193 int ret; 194 195 if (link || id || (addr & 0xffff0000) || !(size == 1 || size == 2 || size == 4)) 196 return -EINVAL; 197 198 /* 199 * The I2CR doesn't have CFAM or FSI slave address space - only the 200 * engines. In order for this to work with the FSI core, we need to 201 * emulate at minimum the CFAM config table so that the appropriate 202 * engines are discovered. 203 */ 204 if (addr < 0xc00) { 205 if (addr > sizeof(i2cr_cfam) - 4) 206 addr = (addr & 0x3) + (sizeof(i2cr_cfam) - 4); 207 208 memcpy(val, &i2cr_cfam[addr], size); 209 return 0; 210 } 211 212 ret = fsi_master_i2cr_read(i2cr, I2CR_ADDRESS_CFAM(addr), &data); 213 if (ret) 214 return ret; 215 216 /* 217 * FSI core expects up to 4 bytes BE back, while I2CR replied with LE 218 * bytes on the wire. 219 */ 220 for (i = 0; i < size; ++i) 221 ((u8 *)val)[i] = ((u8 *)&data)[7 - i]; 222 223 return 0; 224 } 225 226 static int i2cr_write(struct fsi_master *master, int link, uint8_t id, uint32_t addr, 227 const void *val, size_t size) 228 { 229 struct fsi_master_i2cr *i2cr = container_of(master, struct fsi_master_i2cr, master); 230 u64 data = 0; 231 size_t i; 232 233 if (link || id || (addr & 0xffff0000) || !(size == 1 || size == 2 || size == 4)) 234 return -EINVAL; 235 236 /* I2CR writes to CFAM or FSI slave address are a successful no-op. */ 237 if (addr < 0xc00) 238 return 0; 239 240 /* 241 * FSI core passes up to 4 bytes BE, while the I2CR expects LE bytes on 242 * the wire. 243 */ 244 for (i = 0; i < size; ++i) 245 ((u8 *)&data)[7 - i] = ((u8 *)val)[i]; 246 247 return fsi_master_i2cr_write(i2cr, I2CR_ADDRESS_CFAM(addr), data); 248 } 249 250 static void i2cr_release(struct device *dev) 251 { 252 struct fsi_master_i2cr *i2cr = to_fsi_master_i2cr(to_fsi_master(dev)); 253 254 of_node_put(dev->of_node); 255 256 kfree(i2cr); 257 } 258 259 static int i2cr_probe(struct i2c_client *client) 260 { 261 struct fsi_master_i2cr *i2cr; 262 int ret; 263 264 i2cr = kzalloc(sizeof(*i2cr), GFP_KERNEL); 265 if (!i2cr) 266 return -ENOMEM; 267 268 /* Only one I2CR on any given I2C bus (fixed I2C device address) */ 269 i2cr->master.idx = client->adapter->nr; 270 dev_set_name(&i2cr->master.dev, "i2cr%d", i2cr->master.idx); 271 i2cr->master.dev.parent = &client->dev; 272 i2cr->master.dev.of_node = of_node_get(dev_of_node(&client->dev)); 273 i2cr->master.dev.release = i2cr_release; 274 275 i2cr->master.n_links = 1; 276 i2cr->master.read = i2cr_read; 277 i2cr->master.write = i2cr_write; 278 279 mutex_init(&i2cr->lock); 280 i2cr->client = client; 281 282 ret = fsi_master_register(&i2cr->master); 283 if (ret) 284 return ret; 285 286 i2c_set_clientdata(client, i2cr); 287 return 0; 288 } 289 290 static void i2cr_remove(struct i2c_client *client) 291 { 292 struct fsi_master_i2cr *i2cr = i2c_get_clientdata(client); 293 294 fsi_master_unregister(&i2cr->master); 295 } 296 297 static const struct of_device_id i2cr_ids[] = { 298 { .compatible = "ibm,i2cr-fsi-master" }, 299 { } 300 }; 301 MODULE_DEVICE_TABLE(of, i2cr_ids); 302 303 static struct i2c_driver i2cr_driver = { 304 .probe = i2cr_probe, 305 .remove = i2cr_remove, 306 .driver = { 307 .name = "fsi-master-i2cr", 308 .of_match_table = i2cr_ids, 309 }, 310 }; 311 312 module_i2c_driver(i2cr_driver) 313 314 MODULE_AUTHOR("Eddie James <eajames@linux.ibm.com>"); 315 MODULE_DESCRIPTION("IBM I2C Responder virtual FSI master driver"); 316 MODULE_LICENSE("GPL"); 317