blob: b4271b4be9f31a380299f571bf1a134ffb83516e [file] [log] [blame]
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
4 * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
5 */
6
Patrick Delaunay81313352021-04-27 11:02:19 +02007#define LOG_CATEGORY UCLASS_USB_GADGET_GENERIC
8
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +01009#include <common.h>
10#include <dm.h>
11#include <dm/device-internal.h>
12#include <linux/usb/gadget.h>
13
Jean-Jacques Hiblotdb994e02018-12-21 09:50:21 +010014#if CONFIG_IS_ENABLED(DM_USB_GADGET)
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +010015#define MAX_UDC_DEVICES 4
16static struct udevice *dev_array[MAX_UDC_DEVICES];
Marek Vasutb3972032023-09-01 11:49:47 +020017
18int udc_device_get_by_index(int index, struct udevice **udev)
19{
20 struct udevice *dev = NULL;
21 int ret;
22
23 ret = uclass_get_device_by_seq(UCLASS_USB_GADGET_GENERIC, index, &dev);
24 if (!ret && dev) {
25 *udev = dev;
26 return 0;
27 }
28
29 ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, index, &dev);
30 if (!ret && dev) {
31 *udev = dev;
32 return 0;
33 }
34
35 pr_err("No USB device found\n");
36 return -ENODEV;
37}
38
39int udc_device_put(struct udevice *udev)
40{
41#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
42 return device_remove(udev, DM_REMOVE_NORMAL);
43#else
44 return -ENOSYS;
45#endif
46}
47
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +010048int usb_gadget_initialize(int index)
49{
50 int ret;
51 struct udevice *dev = NULL;
52
53 if (index < 0 || index >= ARRAY_SIZE(dev_array))
54 return -EINVAL;
55 if (dev_array[index])
56 return 0;
Marek Vasutb3972032023-09-01 11:49:47 +020057 ret = udc_device_get_by_index(index, &dev);
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +010058 if (!dev || ret) {
Marek Vasutb3972032023-09-01 11:49:47 +020059 pr_err("No USB device found\n");
60 return -ENODEV;
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +010061 }
62 dev_array[index] = dev;
63 return 0;
64}
65
66int usb_gadget_release(int index)
67{
68#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
69 int ret;
70 if (index < 0 || index >= ARRAY_SIZE(dev_array))
71 return -EINVAL;
72
Marek Vasutb3972032023-09-01 11:49:47 +020073 ret = device_remove(dev_array[index]);
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +010074 if (!ret)
75 dev_array[index] = NULL;
76 return ret;
77#else
Simon Glass12fb7492021-03-25 10:26:05 +130078 return -ENOSYS;
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +010079#endif
80}
81
82int usb_gadget_handle_interrupts(int index)
83{
84 if (index < 0 || index >= ARRAY_SIZE(dev_array))
85 return -EINVAL;
86 return dm_usb_gadget_handle_interrupts(dev_array[index]);
87}
Marek Vasutb3972032023-09-01 11:49:47 +020088#else
89/* Backwards hardware compatibility -- switch to DM_USB_GADGET */
90static int legacy_index;
91int udc_device_get_by_index(int index, struct udevice **udev)
92{
93 legacy_index = index;
94 return board_usb_init(index, USB_INIT_DEVICE);
95}
96
97int udc_device_put(struct udevice *udev)
98{
99 return board_usb_cleanup(legacy_index, USB_INIT_DEVICE);
100}
Jean-Jacques Hiblotdb994e02018-12-21 09:50:21 +0100101#endif
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +0100102
Marek Vasutb3972032023-09-01 11:49:47 +0200103#if CONFIG_IS_ENABLED(DM)
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +0100104UCLASS_DRIVER(usb_gadget_generic) = {
105 .id = UCLASS_USB_GADGET_GENERIC,
Jean-Jacques Hiblot2934dc12018-12-15 17:43:27 +0100106 .name = "usb",
107 .flags = DM_UC_FLAG_SEQ_ALIAS,
Jean-Jacques Hiblot9dc0d5c2018-11-29 10:52:46 +0100108};
Marek Vasutb3972032023-09-01 11:49:47 +0200109#endif