0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/usb/pd_vdo.h>
0010
0011 #include "bus.h"
0012 #include "class.h"
0013 #include "mux.h"
0014
0015 static inline int
0016 typec_altmode_set_mux(struct altmode *alt, unsigned long conf, void *data)
0017 {
0018 struct typec_mux_state state;
0019
0020 if (!alt->mux)
0021 return 0;
0022
0023 state.alt = &alt->adev;
0024 state.mode = conf;
0025 state.data = data;
0026
0027 return typec_mux_set(alt->mux, &state);
0028 }
0029
0030 static int typec_altmode_set_state(struct typec_altmode *adev,
0031 unsigned long conf, void *data)
0032 {
0033 bool is_port = is_typec_port(adev->dev.parent);
0034 struct altmode *port_altmode;
0035
0036 port_altmode = is_port ? to_altmode(adev) : to_altmode(adev)->partner;
0037
0038 return typec_altmode_set_mux(port_altmode, conf, data);
0039 }
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 int typec_altmode_notify(struct typec_altmode *adev,
0058 unsigned long conf, void *data)
0059 {
0060 bool is_port;
0061 struct altmode *altmode;
0062 struct altmode *partner;
0063 int ret;
0064
0065 if (!adev)
0066 return 0;
0067
0068 altmode = to_altmode(adev);
0069
0070 if (!altmode->partner)
0071 return -ENODEV;
0072
0073 is_port = is_typec_port(adev->dev.parent);
0074 partner = altmode->partner;
0075
0076 ret = typec_altmode_set_mux(is_port ? altmode : partner, conf, data);
0077 if (ret)
0078 return ret;
0079
0080 if (partner->adev.ops && partner->adev.ops->notify)
0081 return partner->adev.ops->notify(&partner->adev, conf, data);
0082
0083 return 0;
0084 }
0085 EXPORT_SYMBOL_GPL(typec_altmode_notify);
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 int typec_altmode_enter(struct typec_altmode *adev, u32 *vdo)
0098 {
0099 struct altmode *partner = to_altmode(adev)->partner;
0100 struct typec_altmode *pdev = &partner->adev;
0101 int ret;
0102
0103 if (!adev || adev->active)
0104 return 0;
0105
0106 if (!pdev->ops || !pdev->ops->enter)
0107 return -EOPNOTSUPP;
0108
0109 if (is_typec_port(pdev->dev.parent) && !pdev->active)
0110 return -EPERM;
0111
0112
0113 ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL);
0114 if (ret)
0115 return ret;
0116
0117
0118 return pdev->ops->enter(pdev, vdo);
0119 }
0120 EXPORT_SYMBOL_GPL(typec_altmode_enter);
0121
0122
0123
0124
0125
0126
0127
0128 int typec_altmode_exit(struct typec_altmode *adev)
0129 {
0130 struct altmode *partner = to_altmode(adev)->partner;
0131 struct typec_altmode *pdev = &partner->adev;
0132 int ret;
0133
0134 if (!adev || !adev->active)
0135 return 0;
0136
0137 if (!pdev->ops || !pdev->ops->enter)
0138 return -EOPNOTSUPP;
0139
0140
0141 ret = typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL);
0142 if (ret)
0143 return ret;
0144
0145
0146 return pdev->ops->exit(pdev);
0147 }
0148 EXPORT_SYMBOL_GPL(typec_altmode_exit);
0149
0150
0151
0152
0153
0154
0155
0156
0157 void typec_altmode_attention(struct typec_altmode *adev, u32 vdo)
0158 {
0159 struct typec_altmode *pdev = &to_altmode(adev)->partner->adev;
0160
0161 if (pdev->ops && pdev->ops->attention)
0162 pdev->ops->attention(pdev, vdo);
0163 }
0164 EXPORT_SYMBOL_GPL(typec_altmode_attention);
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177 int typec_altmode_vdm(struct typec_altmode *adev,
0178 const u32 header, const u32 *vdo, int count)
0179 {
0180 struct typec_altmode *pdev;
0181 struct altmode *altmode;
0182
0183 if (!adev)
0184 return 0;
0185
0186 altmode = to_altmode(adev);
0187
0188 if (!altmode->partner)
0189 return -ENODEV;
0190
0191 pdev = &altmode->partner->adev;
0192
0193 if (!pdev->ops || !pdev->ops->vdm)
0194 return -EOPNOTSUPP;
0195
0196 return pdev->ops->vdm(pdev, header, vdo, count);
0197 }
0198 EXPORT_SYMBOL_GPL(typec_altmode_vdm);
0199
0200 const struct typec_altmode *
0201 typec_altmode_get_partner(struct typec_altmode *adev)
0202 {
0203 if (!adev || !to_altmode(adev)->partner)
0204 return NULL;
0205
0206 return &to_altmode(adev)->partner->adev;
0207 }
0208 EXPORT_SYMBOL_GPL(typec_altmode_get_partner);
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221 struct typec_altmode *typec_altmode_get_plug(struct typec_altmode *adev,
0222 enum typec_plug_index index)
0223 {
0224 struct altmode *port = to_altmode(adev)->partner;
0225
0226 if (port->plug[index]) {
0227 get_device(&port->plug[index]->adev.dev);
0228 return &port->plug[index]->adev;
0229 }
0230
0231 return NULL;
0232 }
0233 EXPORT_SYMBOL_GPL(typec_altmode_get_plug);
0234
0235
0236
0237
0238
0239 void typec_altmode_put_plug(struct typec_altmode *plug)
0240 {
0241 if (plug)
0242 put_device(&plug->dev);
0243 }
0244 EXPORT_SYMBOL_GPL(typec_altmode_put_plug);
0245
0246 int __typec_altmode_register_driver(struct typec_altmode_driver *drv,
0247 struct module *module)
0248 {
0249 if (!drv->probe)
0250 return -EINVAL;
0251
0252 drv->driver.owner = module;
0253 drv->driver.bus = &typec_bus;
0254
0255 return driver_register(&drv->driver);
0256 }
0257 EXPORT_SYMBOL_GPL(__typec_altmode_register_driver);
0258
0259 void typec_altmode_unregister_driver(struct typec_altmode_driver *drv)
0260 {
0261 driver_unregister(&drv->driver);
0262 }
0263 EXPORT_SYMBOL_GPL(typec_altmode_unregister_driver);
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 struct typec_altmode *typec_match_altmode(struct typec_altmode **altmodes,
0279 size_t n, u16 svid, u8 mode)
0280 {
0281 int i;
0282
0283 for (i = 0; i < n; i++) {
0284 if (!altmodes[i])
0285 break;
0286 if (altmodes[i]->svid == svid && altmodes[i]->mode == mode)
0287 return altmodes[i];
0288 }
0289
0290 return NULL;
0291 }
0292 EXPORT_SYMBOL_GPL(typec_match_altmode);
0293
0294
0295
0296 static ssize_t
0297 description_show(struct device *dev, struct device_attribute *attr, char *buf)
0298 {
0299 struct typec_altmode *alt = to_typec_altmode(dev);
0300
0301 return sprintf(buf, "%s\n", alt->desc ? alt->desc : "");
0302 }
0303 static DEVICE_ATTR_RO(description);
0304
0305 static struct attribute *typec_attrs[] = {
0306 &dev_attr_description.attr,
0307 NULL
0308 };
0309 ATTRIBUTE_GROUPS(typec);
0310
0311 static int typec_match(struct device *dev, struct device_driver *driver)
0312 {
0313 struct typec_altmode_driver *drv = to_altmode_driver(driver);
0314 struct typec_altmode *altmode = to_typec_altmode(dev);
0315 const struct typec_device_id *id;
0316
0317 for (id = drv->id_table; id->svid; id++)
0318 if (id->svid == altmode->svid &&
0319 (id->mode == TYPEC_ANY_MODE || id->mode == altmode->mode))
0320 return 1;
0321 return 0;
0322 }
0323
0324 static int typec_uevent(struct device *dev, struct kobj_uevent_env *env)
0325 {
0326 struct typec_altmode *altmode = to_typec_altmode(dev);
0327
0328 if (add_uevent_var(env, "SVID=%04X", altmode->svid))
0329 return -ENOMEM;
0330
0331 if (add_uevent_var(env, "MODE=%u", altmode->mode))
0332 return -ENOMEM;
0333
0334 return add_uevent_var(env, "MODALIAS=typec:id%04Xm%02X",
0335 altmode->svid, altmode->mode);
0336 }
0337
0338 static int typec_altmode_create_links(struct altmode *alt)
0339 {
0340 struct device *port_dev = &alt->partner->adev.dev;
0341 struct device *dev = &alt->adev.dev;
0342 int err;
0343
0344 err = sysfs_create_link(&dev->kobj, &port_dev->kobj, "port");
0345 if (err)
0346 return err;
0347
0348 err = sysfs_create_link(&port_dev->kobj, &dev->kobj, "partner");
0349 if (err)
0350 sysfs_remove_link(&dev->kobj, "port");
0351
0352 return err;
0353 }
0354
0355 static void typec_altmode_remove_links(struct altmode *alt)
0356 {
0357 sysfs_remove_link(&alt->partner->adev.dev.kobj, "partner");
0358 sysfs_remove_link(&alt->adev.dev.kobj, "port");
0359 }
0360
0361 static int typec_probe(struct device *dev)
0362 {
0363 struct typec_altmode_driver *drv = to_altmode_driver(dev->driver);
0364 struct typec_altmode *adev = to_typec_altmode(dev);
0365 struct altmode *altmode = to_altmode(adev);
0366 int ret;
0367
0368
0369 if (!altmode->partner)
0370 return -ENODEV;
0371
0372 ret = typec_altmode_create_links(altmode);
0373 if (ret) {
0374 dev_warn(dev, "failed to create symlinks\n");
0375 return ret;
0376 }
0377
0378 ret = drv->probe(adev);
0379 if (ret)
0380 typec_altmode_remove_links(altmode);
0381
0382 return ret;
0383 }
0384
0385 static void typec_remove(struct device *dev)
0386 {
0387 struct typec_altmode_driver *drv = to_altmode_driver(dev->driver);
0388 struct typec_altmode *adev = to_typec_altmode(dev);
0389 struct altmode *altmode = to_altmode(adev);
0390
0391 typec_altmode_remove_links(altmode);
0392
0393 if (drv->remove)
0394 drv->remove(to_typec_altmode(dev));
0395
0396 if (adev->active) {
0397 WARN_ON(typec_altmode_set_state(adev, TYPEC_STATE_SAFE, NULL));
0398 typec_altmode_update_active(adev, false);
0399 }
0400
0401 adev->desc = NULL;
0402 adev->ops = NULL;
0403 }
0404
0405 struct bus_type typec_bus = {
0406 .name = "typec",
0407 .dev_groups = typec_groups,
0408 .match = typec_match,
0409 .uevent = typec_uevent,
0410 .probe = typec_probe,
0411 .remove = typec_remove,
0412 };