233857ad7a13ae4ee73ac08c7f965afe987eb922
[platform/kernel/u-boot.git] / drivers / usb / musb-new / ti-musb.c
1 /*
2  * MISC driver for TI MUSB Glue.
3  *
4  * (C) Copyright 2016
5  *     Texas Instruments Incorporated, <www.ti.com>
6  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9 #include <common.h>
10 #include <command.h>
11 #include <console.h>
12 #include <dm.h>
13 #include <linux/usb/otg.h>
14 #include <dm/device-internal.h>
15 #include <dm/lists.h>
16
17 #include <asm/io.h>
18 #include <asm/omap_musb.h>
19 #include "musb_uboot.h"
20
21 DECLARE_GLOBAL_DATA_PTR;
22
23 #ifdef CONFIG_DM_USB
24
25 /* USB 2.0 PHY Control */
26 #define CM_PHY_PWRDN                    (1 << 0)
27 #define CM_PHY_OTG_PWRDN                (1 << 1)
28 #define OTGVDET_EN                      (1 << 19)
29 #define OTGSESSENDEN                    (1 << 20)
30
31 #define AM335X_USB1_CTRL        0x8
32
33 struct ti_musb_platdata {
34         void *base;
35         void *ctrl_mod_base;
36         struct musb_hdrc_platform_data plat;
37         struct musb_hdrc_config musb_config;
38         struct omap_musb_board_data otg_board_data;
39 };
40
41 static int ti_musb_get_usb_index(int node)
42 {
43         const void *fdt = gd->fdt_blob;
44         int i = 0;
45         char path[64];
46         const char *alias_path;
47         char alias[16];
48
49         fdt_get_path(fdt, node, path, sizeof(path));
50
51         do {
52                 snprintf(alias, sizeof(alias), "usb%d", i);
53                 alias_path = fdt_get_alias(fdt, alias);
54                 if (alias_path == NULL) {
55                         debug("USB index not found\n");
56                         return -ENOENT;
57                 }
58
59                 if (!strcmp(path, alias_path))
60                         return i;
61
62                 i++;
63         } while (alias_path);
64
65         return -ENOENT;
66 }
67
68 static void ti_musb_set_phy_power(struct udevice *dev, u8 on)
69 {
70         struct ti_musb_platdata *platdata = dev_get_platdata(dev);
71
72         if (on) {
73                 clrsetbits_le32(platdata->ctrl_mod_base,
74                                 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN,
75                                 OTGVDET_EN | OTGSESSENDEN);
76         } else {
77                 clrsetbits_le32(platdata->ctrl_mod_base, 0,
78                                 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
79         }
80 }
81
82 static int ti_musb_ofdata_to_platdata(struct udevice *dev)
83 {
84         struct ti_musb_platdata *platdata = dev_get_platdata(dev);
85         const void *fdt = gd->fdt_blob;
86         int node = dev_of_offset(dev);
87         int phys;
88         int ctrl_mod;
89         int usb_index;
90
91         platdata->base = (void *)devfdt_get_addr_index(dev, 1);
92
93         phys = fdtdec_lookup_phandle(fdt, node, "phys");
94         ctrl_mod = fdtdec_lookup_phandle(fdt, phys, "ti,ctrl_mod");
95         platdata->ctrl_mod_base = (void *)fdtdec_get_addr(fdt, ctrl_mod, "reg");
96         usb_index = ti_musb_get_usb_index(node);
97         switch (usb_index) {
98         case 1:
99                 platdata->ctrl_mod_base += AM335X_USB1_CTRL;
100         case 0:
101         default:
102                 break;
103         }
104
105         platdata->musb_config.multipoint = fdtdec_get_int(fdt, node,
106                                                           "mentor,multipoint",
107                                                           -1);
108         if (platdata->musb_config.multipoint < 0) {
109                 pr_err("MUSB multipoint DT entry missing\n");
110                 return -ENOENT;
111         }
112
113         platdata->musb_config.dyn_fifo = 1;
114
115         platdata->musb_config.num_eps = fdtdec_get_int(fdt, node,
116                                                        "mentor,num-eps", -1);
117         if (platdata->musb_config.num_eps < 0) {
118                 pr_err("MUSB num-eps DT entry missing\n");
119                 return -ENOENT;
120         }
121
122         platdata->musb_config.ram_bits = fdtdec_get_int(fdt, node,
123                                                         "mentor,ram-bits", -1);
124         if (platdata->musb_config.ram_bits < 0) {
125                 pr_err("MUSB ram-bits DT entry missing\n");
126                 return -ENOENT;
127         }
128
129         platdata->otg_board_data.set_phy_power = ti_musb_set_phy_power;
130         platdata->otg_board_data.dev = dev;
131         platdata->plat.config = &platdata->musb_config;
132
133         platdata->plat.power = fdtdec_get_int(fdt, node, "mentor,power", -1);
134         if (platdata->plat.power < 0) {
135                 pr_err("MUSB mentor,power DT entry missing\n");
136                 return -ENOENT;
137         }
138
139         platdata->plat.platform_ops = &musb_dsps_ops;
140         platdata->plat.board_data = &platdata->otg_board_data;
141
142         return 0;
143 }
144
145 static int ti_musb_host_probe(struct udevice *dev)
146 {
147         struct musb_host_data *host = dev_get_priv(dev);
148         struct ti_musb_platdata *platdata = dev_get_platdata(dev);
149         struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
150         struct omap_musb_board_data *otg_board_data;
151         int ret;
152
153         priv->desc_before_addr = true;
154
155         otg_board_data = &platdata->otg_board_data;
156
157         host->host = musb_init_controller(&platdata->plat,
158                                           (struct device *)otg_board_data,
159                                           platdata->base);
160         if (!host->host)
161                 return -EIO;
162
163         ret = musb_lowlevel_init(host);
164
165         return ret;
166 }
167
168 static int ti_musb_host_remove(struct udevice *dev)
169 {
170         struct musb_host_data *host = dev_get_priv(dev);
171
172         musb_stop(host->host);
173
174         return 0;
175 }
176
177 static int ti_musb_host_ofdata_to_platdata(struct udevice *dev)
178 {
179         struct ti_musb_platdata *platdata = dev_get_platdata(dev);
180         const void *fdt = gd->fdt_blob;
181         int node = dev_of_offset(dev);
182         int ret;
183
184         ret = ti_musb_ofdata_to_platdata(dev);
185         if (ret) {
186                 pr_err("platdata dt parse error\n");
187                 return ret;
188         }
189
190         platdata->plat.mode = MUSB_HOST;
191
192         return 0;
193 }
194
195 U_BOOT_DRIVER(ti_musb_host) = {
196         .name   = "ti-musb-host",
197         .id     = UCLASS_USB,
198         .ofdata_to_platdata = ti_musb_host_ofdata_to_platdata,
199         .probe = ti_musb_host_probe,
200         .remove = ti_musb_host_remove,
201         .ops    = &musb_usb_ops,
202         .platdata_auto_alloc_size = sizeof(struct ti_musb_platdata),
203         .priv_auto_alloc_size = sizeof(struct musb_host_data),
204 };
205
206 static int ti_musb_wrapper_bind(struct udevice *parent)
207 {
208         const void *fdt = gd->fdt_blob;
209         int node;
210         int ret;
211
212         for (node = fdt_first_subnode(fdt, dev_of_offset(parent)); node > 0;
213              node = fdt_next_subnode(fdt, node)) {
214                 struct udevice *dev;
215                 const char *name = fdt_get_name(fdt, node, NULL);
216                 enum usb_dr_mode dr_mode;
217                 struct driver *drv;
218
219                 if (strncmp(name, "usb@", 4))
220                         continue;
221
222                 dr_mode = usb_get_dr_mode(node);
223                 switch (dr_mode) {
224                 case USB_DR_MODE_PERIPHERAL:
225                         /* Bind MUSB device */
226                         break;
227                 case USB_DR_MODE_HOST:
228                         /* Bind MUSB host */
229                         ret = device_bind_driver_to_node(parent, "ti-musb-host",
230                                         name, offset_to_ofnode(node), &dev);
231                         if (ret) {
232                                 pr_err("musb - not able to bind usb host node\n");
233                                 return ret;
234                         }
235                         break;
236                 default:
237                         break;
238                 };
239         }
240         return 0;
241 }
242
243 static const struct udevice_id ti_musb_ids[] = {
244         { .compatible = "ti,am33xx-usb" },
245         { }
246 };
247
248 U_BOOT_DRIVER(ti_musb_wrapper) = {
249         .name   = "ti-musb-wrapper",
250         .id     = UCLASS_MISC,
251         .of_match = ti_musb_ids,
252         .bind = ti_musb_wrapper_bind,
253 };
254
255 #endif /* CONFIG_DM_USB */