1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2022, Microchip 4 */ 5 6 #ifndef __DRIVERS_I2C_H 7 #define __DRIVERS_I2C_H 8 9 #include <kernel/dt_driver.h> 10 #include <libfdt.h> 11 #include <tee_api_types.h> 12 13 /** 14 * DEFINE_I2C_DEV_DRIVER - Declare an I2C driver 15 * 16 * @__name: I2C device driver name 17 * @__match_table: match table associated to the driver 18 * @__i2c_probe: I2C probe function with the following prototype: 19 * TEE_Result (*probe)(struct i2c_dev *i2c_dev, const void *fdt, 20 * int node, const void *compat_data); 21 */ 22 #define DEFINE_I2C_DEV_DRIVER(__name, __match_table, __i2c_probe) \ 23 static TEE_Result __name ## _probe_i2c_dev(const void *fdt, int node, \ 24 const void *compat_data) \ 25 { \ 26 struct i2c_dev *i2c_dev = NULL; \ 27 TEE_Result res = TEE_ERROR_GENERIC; \ 28 \ 29 res = i2c_dt_get_dev(fdt, node, &i2c_dev); \ 30 if (res) \ 31 return res; \ 32 return __i2c_probe(i2c_dev, fdt, node, compat_data); \ 33 } \ 34 DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ 35 .name = # __name, \ 36 .type = DT_DRIVER_I2C, \ 37 .match_table = __match_table, \ 38 .probe = __name ## _probe_i2c_dev, \ 39 } 40 41 #define I2C_SMBUS_MAX_BUF_SIZE 32 42 43 enum i2c_smbus_dir { 44 I2C_SMBUS_READ, 45 I2C_SMBUS_WRITE, 46 }; 47 48 enum i2c_smbus_protocol { 49 I2C_SMBUS_PROTO_BYTE, 50 /* 51 * Like block but does not insert "count" in sent data, useful for 52 * EEPROM read for instance which is not SMBus but requires such 53 * sequence. 54 */ 55 I2C_SMBUS_PROTO_BLOCK_RAW, 56 }; 57 58 struct i2c_ctrl; 59 60 /** 61 * struct i2c_dev - I2C device 62 * 63 * @ctrl: I2C controller associated to the device 64 * @addr: device address on the I2C bus 65 */ 66 struct i2c_dev { 67 struct i2c_ctrl *ctrl; 68 uint16_t addr; 69 }; 70 71 /** 72 * struct i2c_ctrl_ops - Operations provided by I2C controller drivers 73 * 74 * @read: I2C read operation 75 * @write: I2C write operation 76 * @smbus: SMBus protocol operation 77 */ 78 struct i2c_ctrl_ops { 79 TEE_Result (*read)(struct i2c_dev *i2c_dev, uint8_t *buf, size_t len); 80 TEE_Result (*write)(struct i2c_dev *i2c_dev, const uint8_t *buf, 81 size_t len); 82 TEE_Result (*smbus)(struct i2c_dev *i2c_dev, enum i2c_smbus_dir dir, 83 enum i2c_smbus_protocol proto, uint8_t cmd_code, 84 uint8_t *buf, size_t len); 85 }; 86 87 /** 88 * struct i2c_ctrl - I2C controller 89 * 90 * @ops: Operations associated to the I2C controller 91 */ 92 struct i2c_ctrl { 93 const struct i2c_ctrl_ops *ops; 94 }; 95 96 #ifdef CFG_DRIVERS_I2C 97 /** 98 * i2c_create_dev - Create and i2c_dev struct from device-tree 99 * 100 * @i2c_ctrl: Controller to be used with this device 101 * @fdt: Device-tree to work on 102 * @node: Node to work on in @fdt provided device-tree 103 * 104 * Return an i2c_dev struct filled from device-tree description 105 */ 106 struct i2c_dev *i2c_create_dev(struct i2c_ctrl *i2c_ctrl, const void *fdt, 107 int node); 108 109 /** 110 * i2c_write() - Execute an I2C write on the I2C bus 111 * 112 * @i2c_dev: I2C device used for writing 113 * @buf: Buffer of data to be written 114 * @len: Length of data to be written 115 * 116 * Return a TEE_Result compliant value 117 */ 118 static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev, const uint8_t *buf, 119 size_t len) 120 { 121 if (!i2c_dev->ctrl->ops->write) 122 return TEE_ERROR_NOT_SUPPORTED; 123 124 return i2c_dev->ctrl->ops->write(i2c_dev, buf, len); 125 } 126 127 /** 128 * i2c_read() - Execute an I2C read on the I2C bus 129 * 130 * @i2c_dev: I2C device used for reading 131 * @buf: Buffer containing the read data 132 * @len: Length of data to be read 133 * 134 * Return a TEE_Result compliant value 135 */ 136 static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev, uint8_t *buf, 137 size_t len) 138 { 139 if (!i2c_dev->ctrl->ops->read) 140 return TEE_ERROR_NOT_SUPPORTED; 141 142 return i2c_dev->ctrl->ops->read(i2c_dev, buf, len); 143 } 144 145 /** 146 * i2c_smbus_raw() - Execute a raw SMBUS request 147 * 148 * @i2c_dev: I2C device used for SMBus operation 149 * @dir: Direction for the SMBus transfer 150 * @proto: SMBus Protocol to be executed 151 * @cmd_code: Command code 152 * @buf: Buffer used for read/write operation 153 * @len: Length of buffer to be read/write 154 * 155 * Return a TEE_Result compliant value 156 */ 157 static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev, 158 enum i2c_smbus_dir dir, 159 enum i2c_smbus_protocol proto, 160 uint8_t cmd_code, uint8_t *buf, 161 size_t len) 162 { 163 if (!i2c_dev->ctrl->ops->smbus) 164 return TEE_ERROR_NOT_SUPPORTED; 165 166 if (len > I2C_SMBUS_MAX_BUF_SIZE) 167 return TEE_ERROR_BAD_PARAMETERS; 168 169 return i2c_dev->ctrl->ops->smbus(i2c_dev, dir, proto, cmd_code, buf, 170 len); 171 } 172 173 /** 174 * i2c_dt_get_dev - Get an I2C device from a DT node 175 * 176 * @fdt: Device tree to work on 177 * @nodeoffset: Node offset of the I2C bus consumer 178 * @i2c_dev: Output I2C bus device upon success 179 * 180 * Return TEE_SUCCESS in case of success 181 * Return TEE_ERROR_DEFER_DRIVER_INIT if I2C controller is not initialized 182 * Return TEE_ERROR_ITEM_NOT_FOUND if the I2C controller node does not exist 183 * Return a TEE_Result compliant code in case of error 184 */ 185 static inline TEE_Result i2c_dt_get_dev(const void *fdt, int nodeoffset, 186 struct i2c_dev **i2c_dev) 187 { 188 TEE_Result res = TEE_ERROR_GENERIC; 189 190 *i2c_dev = dt_driver_device_from_parent(fdt, nodeoffset, DT_DRIVER_I2C, 191 &res); 192 return res; 193 } 194 #else 195 static inline TEE_Result i2c_write(struct i2c_dev *i2c_dev __unused, 196 const uint8_t *buf __unused, 197 size_t len __unused) 198 { 199 return TEE_ERROR_NOT_SUPPORTED; 200 } 201 202 static inline TEE_Result i2c_read(struct i2c_dev *i2c_dev __unused, 203 uint8_t *buf __unused, size_t len __unused) 204 { 205 return TEE_ERROR_NOT_SUPPORTED; 206 } 207 208 static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev __unused, 209 enum i2c_smbus_dir dir __unused, 210 enum i2c_smbus_protocol proto __unused, 211 uint8_t cmd_code __unused, 212 uint8_t *buf __unused, 213 size_t len __unused) 214 { 215 return TEE_ERROR_NOT_SUPPORTED; 216 } 217 218 static inline TEE_Result i2c_dt_get_dev(const void *fdt __unused, 219 int nodeoffset __unused, 220 struct i2c_dev **i2c_dev) 221 { 222 *i2c_dev = NULL; 223 return TEE_ERROR_NOT_SUPPORTED; 224 } 225 #endif 226 227 /** 228 * i2c_dt_get_func - Typedef of function to get I2C bus device from 229 * devicetree properties 230 * 231 * @args: Pointer to devicetree description of the I2C bus device to parse 232 * @data: Pointer to data given at i2c_dt_register_provider() call 233 * @res: Output result code of the operation: 234 * TEE_SUCCESS in case of success 235 * TEE_ERROR_DEFER_DRIVER_INIT if I2C controller is not initialized 236 * Any TEE_Result compliant code in case of error. 237 * 238 * Returns a struct i2c pointer pointing to a I2C bus device matching 239 * the devicetree description or NULL if invalid description in which case 240 * @res provides the error code. 241 */ 242 typedef struct i2c_dev *(*i2c_dt_get_func)(struct dt_pargs *args, void *data, 243 TEE_Result *res); 244 245 /** 246 * i2c_dt_register_provider - Register a I2C controller provider and add all the 247 * child nodes of this controller in the DT probe list. 248 * 249 * @fdt: Device tree to work on 250 * @nodeoffset: Node offset of the I2C controller 251 * @get_dt_i2c: Callback to match the I2C controller with a struct i2c 252 * @data: Data which will be passed to the get_dt_i2c callback 253 * Returns TEE_Result value 254 */ 255 static inline 256 TEE_Result i2c_register_provider(const void *fdt, int nodeoffset, 257 i2c_dt_get_func get_dt_i2c, void *data) 258 { 259 int subnode = -1; 260 TEE_Result res = TEE_ERROR_GENERIC; 261 262 res = dt_driver_register_provider(fdt, nodeoffset, 263 (get_of_device_func)get_dt_i2c, 264 data, DT_DRIVER_I2C); 265 if (res) 266 return res; 267 268 fdt_for_each_subnode(subnode, fdt, nodeoffset) 269 dt_driver_maybe_add_probe_node(fdt, subnode); 270 271 return TEE_SUCCESS; 272 } 273 274 /** 275 * i2c_smbus_read_byte_data() - Execute a read byte SMBus protocol operation 276 * 277 * @i2c_dev: I2C device used for SMBus operation 278 * @cmd_code: Command code to read 279 * @byte: Returned byte value read from device 280 * 281 * Return a TEE_Result compliant value 282 */ 283 static inline TEE_Result i2c_smbus_read_byte_data(struct i2c_dev *i2c_dev, 284 uint8_t cmd_code, 285 uint8_t *byte) 286 { 287 return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BYTE, 288 cmd_code, byte, 1); 289 } 290 291 /** 292 * i2c_smbus_write_byte_data() - Execute a write byte SMBus protocol operation 293 * 294 * @i2c_dev: I2C device used for SMBus operation 295 * @cmd_code: Command code for write operation 296 * @byte: Byte to be written to the device 297 * 298 * Return a TEE_Result compliant value 299 */ 300 static inline TEE_Result i2c_smbus_write_byte_data(struct i2c_dev *i2c_dev, 301 uint8_t cmd_code, 302 uint8_t byte) 303 { 304 return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE, I2C_SMBUS_PROTO_BYTE, 305 cmd_code, &byte, 1); 306 } 307 308 /** 309 * i2c_bus_read_block_raw() - Execute a non-standard SMBus raw block read. 310 * This does not insert the "count" of byte to be written unlike the SMBus block 311 * read operation. 312 * 313 * @i2c_dev: I2C device used for SMBus operation 314 * @cmd_code: Command code for read operation 315 * @buf: Buffer of data read from device 316 * @len: Length of data to be read from the device 317 * 318 * Return a TEE_Result compliant value 319 */ 320 static inline TEE_Result i2c_bus_read_block_raw(struct i2c_dev *i2c_dev, 321 uint8_t cmd_code, uint8_t *buf, 322 size_t len) 323 { 324 return i2c_smbus_raw(i2c_dev, I2C_SMBUS_READ, I2C_SMBUS_PROTO_BLOCK_RAW, 325 cmd_code, buf, len); 326 } 327 328 /** 329 * i2c_bus_write_block_raw() - Execute a non-standard SMBus raw block write. 330 * This does not insert the "count" of byte to be written unlike the SMBus block 331 * write operation. 332 * 333 * @i2c_dev: I2C device used for SMBus operation 334 * @cmd_code: Command code for write operation 335 * @buf: Buffer of data to be written to the device 336 * @len: Length of data to be written to the device 337 * 338 * Return a TEE_Result compliant value 339 */ 340 static inline TEE_Result i2c_bus_write_block_raw(struct i2c_dev *i2c_dev, 341 uint8_t cmd_code, 342 uint8_t *buf, size_t len) 343 { 344 return i2c_smbus_raw(i2c_dev, I2C_SMBUS_WRITE, 345 I2C_SMBUS_PROTO_BLOCK_RAW, cmd_code, buf, len); 346 } 347 348 #endif 349