1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Nuvoton NCT6694 I2C adapter driver based on USB interface. 4 * 5 * Copyright (C) 2025 Nuvoton Technology Corp. 6 */ 7 8 #include <linux/i2c.h> 9 #include <linux/idr.h> 10 #include <linux/kernel.h> 11 #include <linux/mfd/nct6694.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 15 /* 16 * USB command module type for NCT6694 I2C controller. 17 * This defines the module type used for communication with the NCT6694 18 * I2C controller over the USB interface. 19 */ 20 #define NCT6694_I2C_MOD 0x03 21 22 /* Command 00h - I2C Deliver */ 23 #define NCT6694_I2C_DELIVER 0x00 24 #define NCT6694_I2C_DELIVER_SEL 0x00 25 26 #define NCT6694_I2C_MAX_XFER_SIZE 64 27 #define NCT6694_I2C_MAX_DEVS 6 28 29 static unsigned char br_reg[NCT6694_I2C_MAX_DEVS] = {[0 ... (NCT6694_I2C_MAX_DEVS - 1)] = 0xFF}; 30 31 module_param_array(br_reg, byte, NULL, 0644); 32 MODULE_PARM_DESC(br_reg, 33 "I2C Baudrate register per adapter: (0=25K, 1=50K, 2=100K, 3=200K, 4=400K, 5=800K, 6=1M), default=2"); 34 35 enum nct6694_i2c_baudrate { 36 NCT6694_I2C_BR_25K = 0, 37 NCT6694_I2C_BR_50K, 38 NCT6694_I2C_BR_100K, 39 NCT6694_I2C_BR_200K, 40 NCT6694_I2C_BR_400K, 41 NCT6694_I2C_BR_800K, 42 NCT6694_I2C_BR_1M 43 }; 44 45 struct __packed nct6694_i2c_deliver { 46 u8 port; 47 u8 br; 48 u8 addr; 49 u8 w_cnt; 50 u8 r_cnt; 51 u8 rsv[11]; 52 u8 write_data[NCT6694_I2C_MAX_XFER_SIZE]; 53 u8 read_data[NCT6694_I2C_MAX_XFER_SIZE]; 54 }; 55 56 struct nct6694_i2c_data { 57 struct device *dev; 58 struct nct6694 *nct6694; 59 struct i2c_adapter adapter; 60 struct nct6694_i2c_deliver deliver; 61 unsigned char port; 62 unsigned char br; 63 }; 64 65 static int nct6694_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 66 { 67 struct nct6694_i2c_data *data = adap->algo_data; 68 struct nct6694_i2c_deliver *deliver = &data->deliver; 69 static const struct nct6694_cmd_header cmd_hd = { 70 .mod = NCT6694_I2C_MOD, 71 .cmd = NCT6694_I2C_DELIVER, 72 .sel = NCT6694_I2C_DELIVER_SEL, 73 .len = cpu_to_le16(sizeof(*deliver)) 74 }; 75 int ret, i; 76 77 for (i = 0; i < num; i++) { 78 struct i2c_msg *msg_temp = &msgs[i]; 79 80 memset(deliver, 0, sizeof(*deliver)); 81 82 deliver->port = data->port; 83 deliver->br = data->br; 84 deliver->addr = i2c_8bit_addr_from_msg(msg_temp); 85 if (msg_temp->flags & I2C_M_RD) { 86 deliver->r_cnt = msg_temp->len; 87 ret = nct6694_write_msg(data->nct6694, &cmd_hd, deliver); 88 if (ret < 0) 89 return ret; 90 91 memcpy(msg_temp->buf, deliver->read_data, msg_temp->len); 92 } else { 93 deliver->w_cnt = msg_temp->len; 94 memcpy(deliver->write_data, msg_temp->buf, msg_temp->len); 95 ret = nct6694_write_msg(data->nct6694, &cmd_hd, deliver); 96 if (ret < 0) 97 return ret; 98 } 99 } 100 101 return num; 102 } 103 104 static u32 nct6694_i2c_func(struct i2c_adapter *adapter) 105 { 106 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 107 } 108 109 static const struct i2c_adapter_quirks nct6694_i2c_quirks = { 110 .max_read_len = NCT6694_I2C_MAX_XFER_SIZE, 111 .max_write_len = NCT6694_I2C_MAX_XFER_SIZE, 112 }; 113 114 static const struct i2c_algorithm nct6694_i2c_algo = { 115 .xfer = nct6694_i2c_xfer, 116 .functionality = nct6694_i2c_func, 117 }; 118 119 static int nct6694_i2c_set_baudrate(struct nct6694_i2c_data *data) 120 { 121 if (data->port >= NCT6694_I2C_MAX_DEVS) { 122 dev_err(data->dev, "Invalid I2C port index %d\n", data->port); 123 return -EINVAL; 124 } 125 126 if (br_reg[data->port] > NCT6694_I2C_BR_1M) { 127 dev_warn(data->dev, "Invalid baudrate %d for I2C%d, using 100K\n", 128 br_reg[data->port], data->port); 129 br_reg[data->port] = NCT6694_I2C_BR_100K; 130 } 131 132 data->br = br_reg[data->port]; 133 134 return 0; 135 } 136 137 static void nct6694_i2c_ida_free(void *d) 138 { 139 struct nct6694_i2c_data *data = d; 140 struct nct6694 *nct6694 = data->nct6694; 141 142 ida_free(&nct6694->i2c_ida, data->port); 143 } 144 145 static int nct6694_i2c_probe(struct platform_device *pdev) 146 { 147 struct device *dev = &pdev->dev; 148 struct nct6694 *nct6694 = dev_get_drvdata(dev->parent); 149 struct nct6694_i2c_data *data; 150 int ret; 151 152 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 153 if (!data) 154 return -ENOMEM; 155 156 data->dev = dev; 157 data->nct6694 = nct6694; 158 159 ret = ida_alloc(&nct6694->i2c_ida, GFP_KERNEL); 160 if (ret < 0) 161 return ret; 162 data->port = ret; 163 164 ret = devm_add_action_or_reset(dev, nct6694_i2c_ida_free, data); 165 if (ret) 166 return ret; 167 168 ret = nct6694_i2c_set_baudrate(data); 169 if (ret) 170 return ret; 171 172 sprintf(data->adapter.name, "NCT6694 I2C Adapter %d", data->port); 173 data->adapter.owner = THIS_MODULE; 174 data->adapter.algo = &nct6694_i2c_algo; 175 data->adapter.quirks = &nct6694_i2c_quirks; 176 data->adapter.dev.parent = dev; 177 data->adapter.algo_data = data; 178 179 platform_set_drvdata(pdev, data); 180 181 return devm_i2c_add_adapter(dev, &data->adapter); 182 } 183 184 static struct platform_driver nct6694_i2c_driver = { 185 .driver = { 186 .name = "nct6694-i2c", 187 }, 188 .probe = nct6694_i2c_probe, 189 }; 190 191 module_platform_driver(nct6694_i2c_driver); 192 193 MODULE_DESCRIPTION("USB-I2C adapter driver for NCT6694"); 194 MODULE_AUTHOR("Ming Yu <tmyu0@nuvoton.com>"); 195 MODULE_LICENSE("GPL"); 196 MODULE_ALIAS("platform:nct6694-i2c"); 197