usb: ehci: add rockchip relinquishing port quirk support
[firefly-linux-kernel-4.4.55.git] / drivers / usb / phy / class-dual-role.c
1 /*
2  * class-dual-role.c
3  *
4  * Copyright (C) 2015 Google, Inc.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #include <linux/ctype.h>
18 #include <linux/device.h>
19 #include <linux/usb/class-dual-role.h>
20 #include <linux/err.h>
21 #include <linux/init.h>
22 #include <linux/module.h>
23 #include <linux/slab.h>
24 #include <linux/stat.h>
25 #include <linux/types.h>
26
27 #define DUAL_ROLE_NOTIFICATION_TIMEOUT 2000
28
29 static ssize_t dual_role_store_property(struct device *dev,
30                                         struct device_attribute *attr,
31                                         const char *buf, size_t count);
32 static ssize_t dual_role_show_property(struct device *dev,
33                                        struct device_attribute *attr,
34                                        char *buf);
35
36 #define DUAL_ROLE_ATTR(_name)                           \
37 {                                                       \
38         .attr = { .name = #_name },                     \
39         .show = dual_role_show_property,                \
40         .store = dual_role_store_property,              \
41 }
42
43 static struct device_attribute dual_role_attrs[] = {
44         DUAL_ROLE_ATTR(supported_modes),
45         DUAL_ROLE_ATTR(mode),
46         DUAL_ROLE_ATTR(power_role),
47         DUAL_ROLE_ATTR(data_role),
48         DUAL_ROLE_ATTR(powers_vconn),
49 };
50
51 struct class *dual_role_class;
52 EXPORT_SYMBOL_GPL(dual_role_class);
53
54 static struct device_type dual_role_dev_type;
55
56 static char *kstrdupcase(const char *str, gfp_t gfp, bool to_upper)
57 {
58         char *ret, *ustr;
59
60         ustr = ret = kmalloc(strlen(str) + 1, gfp);
61
62         if (!ret)
63                 return NULL;
64
65         while (*str)
66                 *ustr++ = to_upper ? toupper(*str++) : tolower(*str++);
67
68         *ustr = 0;
69
70         return ret;
71 }
72
73 static void dual_role_changed_work(struct work_struct *work)
74 {
75         struct dual_role_phy_instance *dual_role =
76             container_of(work, struct dual_role_phy_instance,
77                          changed_work);
78
79         dev_dbg(&dual_role->dev, "%s\n", __func__);
80         kobject_uevent(&dual_role->dev.kobj, KOBJ_CHANGE);
81 }
82
83 void dual_role_instance_changed(struct dual_role_phy_instance *dual_role)
84 {
85         dev_dbg(&dual_role->dev, "%s\n", __func__);
86         pm_wakeup_event(&dual_role->dev, DUAL_ROLE_NOTIFICATION_TIMEOUT);
87         schedule_work(&dual_role->changed_work);
88 }
89 EXPORT_SYMBOL_GPL(dual_role_instance_changed);
90
91 int dual_role_get_property(struct dual_role_phy_instance *dual_role,
92                            enum dual_role_property prop,
93                            unsigned int *val)
94 {
95         return dual_role->desc->get_property(dual_role, prop, val);
96 }
97 EXPORT_SYMBOL_GPL(dual_role_get_property);
98
99 int dual_role_set_property(struct dual_role_phy_instance *dual_role,
100                            enum dual_role_property prop,
101                            const unsigned int *val)
102 {
103         if (!dual_role->desc->set_property)
104                 return -ENODEV;
105
106         return dual_role->desc->set_property(dual_role, prop, val);
107 }
108 EXPORT_SYMBOL_GPL(dual_role_set_property);
109
110 int dual_role_property_is_writeable(struct dual_role_phy_instance *dual_role,
111                                     enum dual_role_property prop)
112 {
113         if (!dual_role->desc->property_is_writeable)
114                 return -ENODEV;
115
116         return dual_role->desc->property_is_writeable(dual_role, prop);
117 }
118 EXPORT_SYMBOL_GPL(dual_role_property_is_writeable);
119
120 static void dual_role_dev_release(struct device *dev)
121 {
122         struct dual_role_phy_instance *dual_role =
123             container_of(dev, struct dual_role_phy_instance, dev);
124         pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
125         kfree(dual_role);
126 }
127
128 static struct dual_role_phy_instance *__must_check
129 __dual_role_register(struct device *parent,
130                      const struct dual_role_phy_desc *desc)
131 {
132         struct device *dev;
133         struct dual_role_phy_instance *dual_role;
134         int rc;
135
136         dual_role = kzalloc(sizeof(*dual_role), GFP_KERNEL);
137         if (!dual_role)
138                 return ERR_PTR(-ENOMEM);
139
140         dev = &dual_role->dev;
141
142         device_initialize(dev);
143
144         dev->class = dual_role_class;
145         dev->type = &dual_role_dev_type;
146         dev->parent = parent;
147         dev->release = dual_role_dev_release;
148         dev_set_drvdata(dev, dual_role);
149         dual_role->desc = desc;
150
151         rc = dev_set_name(dev, "%s", desc->name);
152         if (rc)
153                 goto dev_set_name_failed;
154
155         INIT_WORK(&dual_role->changed_work, dual_role_changed_work);
156
157         rc = device_init_wakeup(dev, true);
158         if (rc)
159                 goto wakeup_init_failed;
160
161         rc = device_add(dev);
162         if (rc)
163                 goto device_add_failed;
164
165         dual_role_instance_changed(dual_role);
166
167         return dual_role;
168
169 device_add_failed:
170         device_init_wakeup(dev, false);
171 wakeup_init_failed:
172 dev_set_name_failed:
173         put_device(dev);
174         kfree(dual_role);
175
176         return ERR_PTR(rc);
177 }
178
179 static void dual_role_instance_unregister(struct dual_role_phy_instance
180                                           *dual_role)
181 {
182         cancel_work_sync(&dual_role->changed_work);
183         device_init_wakeup(&dual_role->dev, false);
184         device_unregister(&dual_role->dev);
185 }
186
187 static void devm_dual_role_release(struct device *dev, void *res)
188 {
189         struct dual_role_phy_instance **dual_role = res;
190
191         dual_role_instance_unregister(*dual_role);
192 }
193
194 struct dual_role_phy_instance *__must_check
195 devm_dual_role_instance_register(struct device *parent,
196                                  const struct dual_role_phy_desc *desc)
197 {
198         struct dual_role_phy_instance **ptr, *dual_role;
199
200         ptr = devres_alloc(devm_dual_role_release, sizeof(*ptr), GFP_KERNEL);
201
202         if (!ptr)
203                 return ERR_PTR(-ENOMEM);
204         dual_role = __dual_role_register(parent, desc);
205         if (IS_ERR(dual_role)) {
206                 devres_free(ptr);
207         } else {
208                 *ptr = dual_role;
209                 devres_add(parent, ptr);
210         }
211         return dual_role;
212 }
213 EXPORT_SYMBOL_GPL(devm_dual_role_instance_register);
214
215 static int devm_dual_role_match(struct device *dev, void *res, void *data)
216 {
217         struct dual_role_phy_instance **r = res;
218
219         if (WARN_ON(!r || !*r))
220                 return 0;
221
222         return *r == data;
223 }
224
225 void devm_dual_role_instance_unregister(struct device *dev,
226                                         struct dual_role_phy_instance
227                                         *dual_role)
228 {
229         int rc;
230
231         rc = devres_release(dev, devm_dual_role_release,
232                             devm_dual_role_match, dual_role);
233         WARN_ON(rc);
234 }
235 EXPORT_SYMBOL_GPL(devm_dual_role_instance_unregister);
236
237 void *dual_role_get_drvdata(struct dual_role_phy_instance *dual_role)
238 {
239         return dual_role->drv_data;
240 }
241 EXPORT_SYMBOL_GPL(dual_role_get_drvdata);
242
243 /***************** Device attribute functions **************************/
244
245 /* port type */
246 static char *supported_modes_text[] = {
247         "ufp dfp", "dfp", "ufp"
248 };
249
250 /* current mode */
251 static char *mode_text[] = {
252         "ufp", "dfp", "none"
253 };
254
255 /* Power role */
256 static char *pr_text[] = {
257         "source", "sink", "none"
258 };
259
260 /* Data role */
261 static char *dr_text[] = {
262         "host", "device", "none"
263 };
264
265 /* Vconn supply */
266 static char *vconn_supply_text[] = {
267         "n", "y"
268 };
269
270 static ssize_t dual_role_show_property(struct device *dev,
271                                        struct device_attribute *attr, char *buf)
272 {
273         ssize_t ret = 0;
274         struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev);
275         const ptrdiff_t off = attr - dual_role_attrs;
276         unsigned int value;
277
278         if (off == DUAL_ROLE_PROP_SUPPORTED_MODES) {
279                 value = dual_role->desc->supported_modes;
280         } else {
281                 ret = dual_role_get_property(dual_role, off, &value);
282
283                 if (ret < 0) {
284                         if (ret == -ENODATA)
285                                 dev_dbg(dev,
286                                         "driver has no data for `%s' property\n",
287                                         attr->attr.name);
288                         else if (ret != -ENODEV)
289                                 dev_err(dev,
290                                         "driver failed to report `%s' property: %zd\n",
291                                         attr->attr.name, ret);
292                         return ret;
293                 }
294         }
295
296         if (off == DUAL_ROLE_PROP_SUPPORTED_MODES) {
297                 BUILD_BUG_ON(DUAL_ROLE_PROP_SUPPORTED_MODES_TOTAL !=
298                         ARRAY_SIZE(supported_modes_text));
299                 if (value < DUAL_ROLE_PROP_SUPPORTED_MODES_TOTAL)
300                         return snprintf(buf, PAGE_SIZE, "%s\n",
301                                         supported_modes_text[value]);
302                 else
303                         return -EIO;
304         } else if (off == DUAL_ROLE_PROP_MODE) {
305                 BUILD_BUG_ON(DUAL_ROLE_PROP_MODE_TOTAL !=
306                         ARRAY_SIZE(mode_text));
307                 if (value < DUAL_ROLE_PROP_MODE_TOTAL)
308                         return snprintf(buf, PAGE_SIZE, "%s\n",
309                                         mode_text[value]);
310                 else
311                         return -EIO;
312         } else if (off == DUAL_ROLE_PROP_PR) {
313                 BUILD_BUG_ON(DUAL_ROLE_PROP_PR_TOTAL != ARRAY_SIZE(pr_text));
314                 if (value < DUAL_ROLE_PROP_PR_TOTAL)
315                         return snprintf(buf, PAGE_SIZE, "%s\n",
316                                         pr_text[value]);
317                 else
318                         return -EIO;
319         } else if (off == DUAL_ROLE_PROP_DR) {
320                 BUILD_BUG_ON(DUAL_ROLE_PROP_DR_TOTAL != ARRAY_SIZE(dr_text));
321                 if (value < DUAL_ROLE_PROP_DR_TOTAL)
322                         return snprintf(buf, PAGE_SIZE, "%s\n",
323                                         dr_text[value]);
324                 else
325                         return -EIO;
326         } else if (off == DUAL_ROLE_PROP_VCONN_SUPPLY) {
327                 BUILD_BUG_ON(DUAL_ROLE_PROP_VCONN_SUPPLY_TOTAL !=
328                                 ARRAY_SIZE(vconn_supply_text));
329                 if (value < DUAL_ROLE_PROP_VCONN_SUPPLY_TOTAL)
330                         return snprintf(buf, PAGE_SIZE, "%s\n",
331                                         vconn_supply_text[value]);
332                 else
333                         return -EIO;
334         } else
335                 return -EIO;
336 }
337
338 static ssize_t dual_role_store_property(struct device *dev,
339                                         struct device_attribute *attr,
340                                         const char *buf, size_t count)
341 {
342         ssize_t ret;
343         struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev);
344         const ptrdiff_t off = attr - dual_role_attrs;
345         unsigned int value;
346         int total, i;
347         char *dup_buf, **text_array;
348         bool result = false;
349
350         dup_buf = kstrdupcase(buf, GFP_KERNEL, false);
351         switch (off) {
352         case DUAL_ROLE_PROP_MODE:
353                 total = DUAL_ROLE_PROP_MODE_TOTAL;
354                 text_array = mode_text;
355                 break;
356         case DUAL_ROLE_PROP_PR:
357                 total = DUAL_ROLE_PROP_PR_TOTAL;
358                 text_array = pr_text;
359                 break;
360         case DUAL_ROLE_PROP_DR:
361                 total = DUAL_ROLE_PROP_DR_TOTAL;
362                 text_array = dr_text;
363                 break;
364         case DUAL_ROLE_PROP_VCONN_SUPPLY:
365                 ret = strtobool(dup_buf, &result);
366                 value = result;
367                 if (!ret)
368                         goto setprop;
369         default:
370                 ret = -EINVAL;
371                 goto error;
372         }
373
374         for (i = 0; i <= total; i++) {
375                 if (i == total) {
376                         ret = -ENOTSUPP;
377                         goto error;
378                 }
379                 if (!strncmp(*(text_array + i), dup_buf,
380                              strlen(*(text_array + i)))) {
381                         value = i;
382                         break;
383                 }
384         }
385
386 setprop:
387         ret = dual_role->desc->set_property(dual_role, off, &value);
388
389 error:
390         kfree(dup_buf);
391
392         if (ret < 0)
393                 return ret;
394
395         return count;
396 }
397
398 static umode_t dual_role_attr_is_visible(struct kobject *kobj,
399                                          struct attribute *attr, int attrno)
400 {
401         struct device *dev = container_of(kobj, struct device, kobj);
402         struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev);
403         umode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
404         int i;
405
406         if (attrno == DUAL_ROLE_PROP_SUPPORTED_MODES)
407                 return mode;
408
409         for (i = 0; i < dual_role->desc->num_properties; i++) {
410                 int property = dual_role->desc->properties[i];
411
412                 if (property == attrno) {
413                         if (dual_role->desc->property_is_writeable &&
414                             dual_role_property_is_writeable(dual_role, property)
415                             > 0)
416                                 mode |= S_IWUSR;
417
418                         return mode;
419                 }
420         }
421
422         return 0;
423 }
424
425 static struct attribute *__dual_role_attrs[ARRAY_SIZE(dual_role_attrs) + 1];
426
427 static struct attribute_group dual_role_attr_group = {
428         .attrs = __dual_role_attrs,
429         .is_visible = dual_role_attr_is_visible,
430 };
431
432 static const struct attribute_group *dual_role_attr_groups[] = {
433         &dual_role_attr_group,
434         NULL,
435 };
436
437 void dual_role_init_attrs(struct device_type *dev_type)
438 {
439         int i;
440
441         dev_type->groups = dual_role_attr_groups;
442
443         for (i = 0; i < ARRAY_SIZE(dual_role_attrs); i++)
444                 __dual_role_attrs[i] = &dual_role_attrs[i].attr;
445 }
446
447 int dual_role_uevent(struct device *dev, struct kobj_uevent_env *env)
448 {
449         struct dual_role_phy_instance *dual_role = dev_get_drvdata(dev);
450         int ret = 0, j;
451         char *prop_buf;
452         char *attrname;
453
454         dev_dbg(dev, "uevent\n");
455
456         if (!dual_role || !dual_role->desc) {
457                 dev_dbg(dev, "No dual_role phy yet\n");
458                 return ret;
459         }
460
461         dev_dbg(dev, "DUAL_ROLE_NAME=%s\n", dual_role->desc->name);
462
463         ret = add_uevent_var(env, "DUAL_ROLE_NAME=%s", dual_role->desc->name);
464         if (ret)
465                 return ret;
466
467         prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
468         if (!prop_buf)
469                 return -ENOMEM;
470
471         for (j = 0; j < dual_role->desc->num_properties; j++) {
472                 struct device_attribute *attr;
473                 char *line;
474
475                 attr = &dual_role_attrs[dual_role->desc->properties[j]];
476
477                 ret = dual_role_show_property(dev, attr, prop_buf);
478                 if (ret == -ENODEV || ret == -ENODATA) {
479                         ret = 0;
480                         continue;
481                 }
482
483                 if (ret < 0)
484                         goto out;
485                 line = strnchr(prop_buf, PAGE_SIZE, '\n');
486                 if (line)
487                         *line = 0;
488
489                 attrname = kstrdupcase(attr->attr.name, GFP_KERNEL, true);
490                 if (!attrname)
491                         ret = -ENOMEM;
492
493                 dev_dbg(dev, "prop %s=%s\n", attrname, prop_buf);
494
495                 ret = add_uevent_var(env, "DUAL_ROLE_%s=%s", attrname,
496                                      prop_buf);
497                 kfree(attrname);
498                 if (ret)
499                         goto out;
500         }
501
502 out:
503         free_page((unsigned long)prop_buf);
504
505         return ret;
506 }
507
508 /******************* Module Init ***********************************/
509
510 static int __init dual_role_class_init(void)
511 {
512         dual_role_class = class_create(THIS_MODULE, "dual_role_usb");
513
514         if (IS_ERR(dual_role_class))
515                 return PTR_ERR(dual_role_class);
516
517         dual_role_class->dev_uevent = dual_role_uevent;
518         dual_role_init_attrs(&dual_role_dev_type);
519
520         return 0;
521 }
522
523 static void __exit dual_role_class_exit(void)
524 {
525         class_destroy(dual_role_class);
526 }
527
528 subsys_initcall(dual_role_class_init);
529 module_exit(dual_role_class_exit);