0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/i2c.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/mutex.h>
0012 #include <linux/usb/typec_dp.h>
0013 #include <linux/usb/typec_mux.h>
0014
0015 #define PI3USB30532_CONF 0x00
0016
0017 #define PI3USB30532_CONF_OPEN 0x00
0018 #define PI3USB30532_CONF_SWAP 0x01
0019 #define PI3USB30532_CONF_4LANE_DP 0x02
0020 #define PI3USB30532_CONF_USB3 0x04
0021 #define PI3USB30532_CONF_USB3_AND_2LANE_DP 0x06
0022
0023 struct pi3usb30532 {
0024 struct i2c_client *client;
0025 struct mutex lock;
0026 struct typec_switch_dev *sw;
0027 struct typec_mux_dev *mux;
0028 u8 conf;
0029 };
0030
0031 static int pi3usb30532_set_conf(struct pi3usb30532 *pi, u8 new_conf)
0032 {
0033 int ret = 0;
0034
0035 if (pi->conf == new_conf)
0036 return 0;
0037
0038 ret = i2c_smbus_write_byte_data(pi->client, PI3USB30532_CONF, new_conf);
0039 if (ret) {
0040 dev_err(&pi->client->dev, "Error writing conf: %d\n", ret);
0041 return ret;
0042 }
0043
0044 pi->conf = new_conf;
0045 return 0;
0046 }
0047
0048 static int pi3usb30532_sw_set(struct typec_switch_dev *sw,
0049 enum typec_orientation orientation)
0050 {
0051 struct pi3usb30532 *pi = typec_switch_get_drvdata(sw);
0052 u8 new_conf;
0053 int ret;
0054
0055 mutex_lock(&pi->lock);
0056 new_conf = pi->conf;
0057
0058 switch (orientation) {
0059 case TYPEC_ORIENTATION_NONE:
0060 new_conf = PI3USB30532_CONF_OPEN;
0061 break;
0062 case TYPEC_ORIENTATION_NORMAL:
0063 new_conf &= ~PI3USB30532_CONF_SWAP;
0064 break;
0065 case TYPEC_ORIENTATION_REVERSE:
0066 new_conf |= PI3USB30532_CONF_SWAP;
0067 break;
0068 }
0069
0070 ret = pi3usb30532_set_conf(pi, new_conf);
0071 mutex_unlock(&pi->lock);
0072
0073 return ret;
0074 }
0075
0076 static int
0077 pi3usb30532_mux_set(struct typec_mux_dev *mux, struct typec_mux_state *state)
0078 {
0079 struct pi3usb30532 *pi = typec_mux_get_drvdata(mux);
0080 u8 new_conf;
0081 int ret;
0082
0083 mutex_lock(&pi->lock);
0084 new_conf = pi->conf;
0085
0086 switch (state->mode) {
0087 case TYPEC_STATE_SAFE:
0088 new_conf = (new_conf & PI3USB30532_CONF_SWAP) |
0089 PI3USB30532_CONF_OPEN;
0090 break;
0091 case TYPEC_STATE_USB:
0092 new_conf = (new_conf & PI3USB30532_CONF_SWAP) |
0093 PI3USB30532_CONF_USB3;
0094 break;
0095 case TYPEC_DP_STATE_C:
0096 case TYPEC_DP_STATE_E:
0097 new_conf = (new_conf & PI3USB30532_CONF_SWAP) |
0098 PI3USB30532_CONF_4LANE_DP;
0099 break;
0100 case TYPEC_DP_STATE_D:
0101 new_conf = (new_conf & PI3USB30532_CONF_SWAP) |
0102 PI3USB30532_CONF_USB3_AND_2LANE_DP;
0103 break;
0104 default:
0105 break;
0106 }
0107
0108 ret = pi3usb30532_set_conf(pi, new_conf);
0109 mutex_unlock(&pi->lock);
0110
0111 return ret;
0112 }
0113
0114 static int pi3usb30532_probe(struct i2c_client *client)
0115 {
0116 struct device *dev = &client->dev;
0117 struct typec_switch_desc sw_desc = { };
0118 struct typec_mux_desc mux_desc = { };
0119 struct pi3usb30532 *pi;
0120 int ret;
0121
0122 pi = devm_kzalloc(dev, sizeof(*pi), GFP_KERNEL);
0123 if (!pi)
0124 return -ENOMEM;
0125
0126 pi->client = client;
0127 mutex_init(&pi->lock);
0128
0129 ret = i2c_smbus_read_byte_data(client, PI3USB30532_CONF);
0130 if (ret < 0) {
0131 dev_err(dev, "Error reading config register %d\n", ret);
0132 return ret;
0133 }
0134 pi->conf = ret;
0135
0136 sw_desc.drvdata = pi;
0137 sw_desc.fwnode = dev->fwnode;
0138 sw_desc.set = pi3usb30532_sw_set;
0139
0140 pi->sw = typec_switch_register(dev, &sw_desc);
0141 if (IS_ERR(pi->sw)) {
0142 dev_err(dev, "Error registering typec switch: %ld\n",
0143 PTR_ERR(pi->sw));
0144 return PTR_ERR(pi->sw);
0145 }
0146
0147 mux_desc.drvdata = pi;
0148 mux_desc.fwnode = dev->fwnode;
0149 mux_desc.set = pi3usb30532_mux_set;
0150
0151 pi->mux = typec_mux_register(dev, &mux_desc);
0152 if (IS_ERR(pi->mux)) {
0153 typec_switch_unregister(pi->sw);
0154 dev_err(dev, "Error registering typec mux: %ld\n",
0155 PTR_ERR(pi->mux));
0156 return PTR_ERR(pi->mux);
0157 }
0158
0159 i2c_set_clientdata(client, pi);
0160 return 0;
0161 }
0162
0163 static int pi3usb30532_remove(struct i2c_client *client)
0164 {
0165 struct pi3usb30532 *pi = i2c_get_clientdata(client);
0166
0167 typec_mux_unregister(pi->mux);
0168 typec_switch_unregister(pi->sw);
0169 return 0;
0170 }
0171
0172 static const struct i2c_device_id pi3usb30532_table[] = {
0173 { "pi3usb30532" },
0174 { }
0175 };
0176 MODULE_DEVICE_TABLE(i2c, pi3usb30532_table);
0177
0178 static struct i2c_driver pi3usb30532_driver = {
0179 .driver = {
0180 .name = "pi3usb30532",
0181 },
0182 .probe_new = pi3usb30532_probe,
0183 .remove = pi3usb30532_remove,
0184 .id_table = pi3usb30532_table,
0185 };
0186
0187 module_i2c_driver(pi3usb30532_driver);
0188
0189 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0190 MODULE_DESCRIPTION("Pericom PI3USB30532 Type-C mux driver");
0191 MODULE_LICENSE("GPL");