1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2021-2022 Linaro Ltd. 4 * Copyright (C) 2018-2020 The Linux Foundation 5 */ 6 7 #include <linux/bits.h> 8 #include <linux/i2c.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/mutex.h> 12 #include <linux/regmap.h> 13 #include <linux/usb/typec_dp.h> 14 #include <linux/usb/typec_mux.h> 15 16 #define FSA4480_SWITCH_ENABLE 0x04 17 #define FSA4480_SWITCH_SELECT 0x05 18 #define FSA4480_SWITCH_STATUS1 0x07 19 #define FSA4480_SLOW_L 0x08 20 #define FSA4480_SLOW_R 0x09 21 #define FSA4480_SLOW_MIC 0x0a 22 #define FSA4480_SLOW_SENSE 0x0b 23 #define FSA4480_SLOW_GND 0x0c 24 #define FSA4480_DELAY_L_R 0x0d 25 #define FSA4480_DELAY_L_MIC 0x0e 26 #define FSA4480_DELAY_L_SENSE 0x0f 27 #define FSA4480_DELAY_L_AGND 0x10 28 #define FSA4480_RESET 0x1e 29 #define FSA4480_MAX_REGISTER 0x1f 30 31 #define FSA4480_ENABLE_DEVICE BIT(7) 32 #define FSA4480_ENABLE_SBU GENMASK(6, 5) 33 #define FSA4480_ENABLE_USB GENMASK(4, 3) 34 35 #define FSA4480_SEL_SBU_REVERSE GENMASK(6, 5) 36 #define FSA4480_SEL_USB GENMASK(4, 3) 37 38 struct fsa4480 { 39 struct i2c_client *client; 40 41 /* used to serialize concurrent change requests */ 42 struct mutex lock; 43 44 struct typec_switch_dev *sw; 45 struct typec_mux_dev *mux; 46 47 struct regmap *regmap; 48 49 u8 cur_enable; 50 u8 cur_select; 51 }; 52 53 static const struct regmap_config fsa4480_regmap_config = { 54 .reg_bits = 8, 55 .val_bits = 8, 56 .max_register = FSA4480_MAX_REGISTER, 57 /* Accesses only done under fsa4480->lock */ 58 .disable_locking = true, 59 }; 60 61 static int fsa4480_switch_set(struct typec_switch_dev *sw, 62 enum typec_orientation orientation) 63 { 64 struct fsa4480 *fsa = typec_switch_get_drvdata(sw); 65 u8 new_sel; 66 67 mutex_lock(&fsa->lock); 68 new_sel = FSA4480_SEL_USB; 69 if (orientation == TYPEC_ORIENTATION_REVERSE) 70 new_sel |= FSA4480_SEL_SBU_REVERSE; 71 72 if (new_sel == fsa->cur_select) 73 goto out_unlock; 74 75 if (fsa->cur_enable & FSA4480_ENABLE_SBU) { 76 /* Disable SBU output while re-configuring the switch */ 77 regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, 78 fsa->cur_enable & ~FSA4480_ENABLE_SBU); 79 80 /* 35us to allow the SBU switch to turn off */ 81 usleep_range(35, 1000); 82 } 83 84 regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, new_sel); 85 fsa->cur_select = new_sel; 86 87 if (fsa->cur_enable & FSA4480_ENABLE_SBU) { 88 regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable); 89 90 /* 15us to allow the SBU switch to turn on again */ 91 usleep_range(15, 1000); 92 } 93 94 out_unlock: 95 mutex_unlock(&fsa->lock); 96 97 return 0; 98 } 99 100 static int fsa4480_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state) 101 { 102 struct fsa4480 *fsa = typec_mux_get_drvdata(mux); 103 u8 new_enable; 104 105 mutex_lock(&fsa->lock); 106 107 new_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB; 108 if (state->mode >= TYPEC_DP_STATE_A) 109 new_enable |= FSA4480_ENABLE_SBU; 110 111 if (new_enable == fsa->cur_enable) 112 goto out_unlock; 113 114 regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, new_enable); 115 fsa->cur_enable = new_enable; 116 117 if (new_enable & FSA4480_ENABLE_SBU) { 118 /* 15us to allow the SBU switch to turn off */ 119 usleep_range(15, 1000); 120 } 121 122 out_unlock: 123 mutex_unlock(&fsa->lock); 124 125 return 0; 126 } 127 128 static int fsa4480_probe(struct i2c_client *client) 129 { 130 struct device *dev = &client->dev; 131 struct typec_switch_desc sw_desc = { }; 132 struct typec_mux_desc mux_desc = { }; 133 struct fsa4480 *fsa; 134 135 fsa = devm_kzalloc(dev, sizeof(*fsa), GFP_KERNEL); 136 if (!fsa) 137 return -ENOMEM; 138 139 fsa->client = client; 140 mutex_init(&fsa->lock); 141 142 fsa->regmap = devm_regmap_init_i2c(client, &fsa4480_regmap_config); 143 if (IS_ERR(fsa->regmap)) 144 return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n"); 145 146 fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB; 147 fsa->cur_select = FSA4480_SEL_USB; 148 149 /* set default settings */ 150 regmap_write(fsa->regmap, FSA4480_SLOW_L, 0x00); 151 regmap_write(fsa->regmap, FSA4480_SLOW_R, 0x00); 152 regmap_write(fsa->regmap, FSA4480_SLOW_MIC, 0x00); 153 regmap_write(fsa->regmap, FSA4480_SLOW_SENSE, 0x00); 154 regmap_write(fsa->regmap, FSA4480_SLOW_GND, 0x00); 155 regmap_write(fsa->regmap, FSA4480_DELAY_L_R, 0x00); 156 regmap_write(fsa->regmap, FSA4480_DELAY_L_MIC, 0x00); 157 regmap_write(fsa->regmap, FSA4480_DELAY_L_SENSE, 0x00); 158 regmap_write(fsa->regmap, FSA4480_DELAY_L_AGND, 0x09); 159 regmap_write(fsa->regmap, FSA4480_SWITCH_SELECT, fsa->cur_select); 160 regmap_write(fsa->regmap, FSA4480_SWITCH_ENABLE, fsa->cur_enable); 161 162 sw_desc.drvdata = fsa; 163 sw_desc.fwnode = dev_fwnode(dev); 164 sw_desc.set = fsa4480_switch_set; 165 166 fsa->sw = typec_switch_register(dev, &sw_desc); 167 if (IS_ERR(fsa->sw)) 168 return dev_err_probe(dev, PTR_ERR(fsa->sw), "failed to register typec switch\n"); 169 170 mux_desc.drvdata = fsa; 171 mux_desc.fwnode = dev_fwnode(dev); 172 mux_desc.set = fsa4480_mux_set; 173 174 fsa->mux = typec_mux_register(dev, &mux_desc); 175 if (IS_ERR(fsa->mux)) { 176 typec_switch_unregister(fsa->sw); 177 return dev_err_probe(dev, PTR_ERR(fsa->mux), "failed to register typec mux\n"); 178 } 179 180 i2c_set_clientdata(client, fsa); 181 return 0; 182 } 183 184 static int fsa4480_remove(struct i2c_client *client) 185 { 186 struct fsa4480 *fsa = i2c_get_clientdata(client); 187 188 typec_mux_unregister(fsa->mux); 189 typec_switch_unregister(fsa->sw); 190 191 return 0; 192 } 193 194 static const struct i2c_device_id fsa4480_table[] = { 195 { "fsa4480" }, 196 { } 197 }; 198 MODULE_DEVICE_TABLE(i2c, fsa4480_table); 199 200 static const struct of_device_id fsa4480_of_table[] = { 201 { .compatible = "fcs,fsa4480" }, 202 { } 203 }; 204 MODULE_DEVICE_TABLE(of, fsa4480_of_table); 205 206 static struct i2c_driver fsa4480_driver = { 207 .driver = { 208 .name = "fsa4480", 209 .of_match_table = fsa4480_of_table, 210 }, 211 .probe_new = fsa4480_probe, 212 .remove = fsa4480_remove, 213 .id_table = fsa4480_table, 214 }; 215 module_i2c_driver(fsa4480_driver); 216 217 MODULE_DESCRIPTION("ON Semiconductor FSA4480 driver"); 218 MODULE_LICENSE("GPL v2"); 219