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