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