1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * MISC driver for TI MUSB Glue. 4 * 5 * (C) Copyright 2016 6 * Texas Instruments Incorporated, <www.ti.com> 7 */ 8 #include <common.h> 9 #include <command.h> 10 #include <console.h> 11 #include <dm.h> 12 #include <linux/usb/otg.h> 13 #include <dm/device-internal.h> 14 #include <dm/lists.h> 15 16 #include <asm/io.h> 17 #include <asm/omap_musb.h> 18 #include "musb_uboot.h" 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 #if CONFIG_IS_ENABLED(DM_USB) 23 /* USB 2.0 PHY Control */ 24 #define CM_PHY_PWRDN (1 << 0) 25 #define CM_PHY_OTG_PWRDN (1 << 1) 26 #define OTGVDET_EN (1 << 19) 27 #define OTGSESSENDEN (1 << 20) 28 29 #define AM335X_USB0_CTRL 0x0 30 #define AM335X_USB1_CTRL 0x8 31 32 static void ti_musb_set_phy_power(struct udevice *dev, u8 on) 33 { 34 struct ti_musb_platdata *platdata = dev_get_platdata(dev); 35 36 if (!platdata->ctrl_mod_base) 37 return; 38 39 if (on) { 40 clrsetbits_le32(platdata->ctrl_mod_base, 41 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN, 42 OTGVDET_EN | OTGSESSENDEN); 43 } else { 44 clrsetbits_le32(platdata->ctrl_mod_base, 0, 45 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN); 46 } 47 } 48 49 #if CONFIG_IS_ENABLED(OF_CONTROL) 50 51 static int ti_musb_get_usb_index(int node) 52 { 53 const void *fdt = gd->fdt_blob; 54 int i = 0; 55 char path[64]; 56 const char *alias_path; 57 char alias[16]; 58 59 fdt_get_path(fdt, node, path, sizeof(path)); 60 61 do { 62 snprintf(alias, sizeof(alias), "usb%d", i); 63 alias_path = fdt_get_alias(fdt, alias); 64 if (alias_path == NULL) { 65 debug("USB index not found\n"); 66 return -ENOENT; 67 } 68 69 if (!strcmp(path, alias_path)) 70 return i; 71 72 i++; 73 } while (alias_path); 74 75 return -ENOENT; 76 } 77 78 static int ti_musb_ofdata_to_platdata(struct udevice *dev) 79 { 80 struct ti_musb_platdata *platdata = dev_get_platdata(dev); 81 const void *fdt = gd->fdt_blob; 82 int node = dev_of_offset(dev); 83 int phys; 84 int ctrl_mod; 85 int usb_index; 86 struct musb_hdrc_config *musb_config; 87 88 platdata->base = (void *)devfdt_get_addr_index(dev, 1); 89 90 phys = fdtdec_lookup_phandle(fdt, node, "phys"); 91 ctrl_mod = fdtdec_lookup_phandle(fdt, phys, "ti,ctrl_mod"); 92 platdata->ctrl_mod_base = (void *)fdtdec_get_addr(fdt, ctrl_mod, "reg"); 93 usb_index = ti_musb_get_usb_index(node); 94 switch (usb_index) { 95 case 1: 96 platdata->ctrl_mod_base += AM335X_USB1_CTRL; 97 break; 98 case 0: 99 platdata->ctrl_mod_base += AM335X_USB0_CTRL; 100 break; 101 default: 102 break; 103 } 104 105 musb_config = malloc(sizeof(struct musb_hdrc_config)); 106 memset(musb_config, 0, sizeof(struct musb_hdrc_config)); 107 108 musb_config->multipoint = fdtdec_get_int(fdt, node, 109 "mentor,multipoint", -1); 110 if (musb_config->multipoint < 0) { 111 pr_err("MUSB multipoint DT entry missing\n"); 112 return -ENOENT; 113 } 114 115 musb_config->dyn_fifo = 1; 116 117 musb_config->num_eps = fdtdec_get_int(fdt, node, "mentor,num-eps", 118 -1); 119 if (musb_config->num_eps < 0) { 120 pr_err("MUSB num-eps DT entry missing\n"); 121 return -ENOENT; 122 } 123 124 musb_config->ram_bits = fdtdec_get_int(fdt, node, "mentor,ram-bits", 125 -1); 126 if (musb_config->ram_bits < 0) { 127 pr_err("MUSB ram-bits DT entry missing\n"); 128 return -ENOENT; 129 } 130 131 platdata->plat.config = 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 141 return 0; 142 } 143 #endif 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 int ret; 151 152 priv->desc_before_addr = true; 153 154 host->host = musb_init_controller(&platdata->plat, 155 NULL, 156 platdata->base); 157 if (!host->host) 158 return -EIO; 159 160 ti_musb_set_phy_power(dev, 1); 161 ret = musb_lowlevel_init(host); 162 163 return ret; 164 } 165 166 static int ti_musb_host_remove(struct udevice *dev) 167 { 168 struct musb_host_data *host = dev_get_priv(dev); 169 170 musb_stop(host->host); 171 ti_musb_set_phy_power(dev, 0); 172 173 return 0; 174 } 175 176 #if CONFIG_IS_ENABLED(OF_CONTROL) 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 #endif 195 196 U_BOOT_DRIVER(ti_musb_host) = { 197 .name = "ti-musb-host", 198 .id = UCLASS_USB, 199 #if CONFIG_IS_ENABLED(OF_CONTROL) 200 .ofdata_to_platdata = ti_musb_host_ofdata_to_platdata, 201 #endif 202 .probe = ti_musb_host_probe, 203 .remove = ti_musb_host_remove, 204 .ops = &musb_usb_ops, 205 .platdata_auto_alloc_size = sizeof(struct ti_musb_platdata), 206 .priv_auto_alloc_size = sizeof(struct musb_host_data), 207 }; 208 209 #if CONFIG_IS_ENABLED(DM_USB_GADGET) 210 struct ti_musb_peripheral { 211 struct musb *periph; 212 }; 213 214 #if CONFIG_IS_ENABLED(OF_CONTROL) 215 static int ti_musb_peripheral_ofdata_to_platdata(struct udevice *dev) 216 { 217 struct ti_musb_platdata *platdata = dev_get_platdata(dev); 218 const void *fdt = gd->fdt_blob; 219 int node = dev_of_offset(dev); 220 int ret; 221 222 ret = ti_musb_ofdata_to_platdata(dev); 223 if (ret) { 224 pr_err("platdata dt parse error\n"); 225 return ret; 226 } 227 platdata->plat.mode = MUSB_PERIPHERAL; 228 229 return 0; 230 } 231 #endif 232 233 int dm_usb_gadget_handle_interrupts(struct udevice *dev) 234 { 235 struct ti_musb_peripheral *priv = dev_get_priv(dev); 236 237 priv->periph->isr(0, priv->periph); 238 239 return 0; 240 } 241 242 static int ti_musb_peripheral_probe(struct udevice *dev) 243 { 244 struct ti_musb_peripheral *priv = dev_get_priv(dev); 245 struct ti_musb_platdata *platdata = dev_get_platdata(dev); 246 int ret; 247 248 priv->periph = musb_init_controller(&platdata->plat, 249 NULL, 250 platdata->base); 251 if (!priv->periph) 252 return -EIO; 253 254 ti_musb_set_phy_power(dev, 1); 255 musb_gadget_setup(priv->periph); 256 return usb_add_gadget_udc((struct device *)dev, &priv->periph->g); 257 } 258 259 static int ti_musb_peripheral_remove(struct udevice *dev) 260 { 261 struct ti_musb_peripheral *priv = dev_get_priv(dev); 262 263 usb_del_gadget_udc(&priv->periph->g); 264 ti_musb_set_phy_power(dev, 0); 265 266 return 0; 267 } 268 269 U_BOOT_DRIVER(ti_musb_peripheral) = { 270 .name = "ti-musb-peripheral", 271 .id = UCLASS_USB_GADGET_GENERIC, 272 #if CONFIG_IS_ENABLED(OF_CONTROL) 273 .ofdata_to_platdata = ti_musb_peripheral_ofdata_to_platdata, 274 #endif 275 .probe = ti_musb_peripheral_probe, 276 .remove = ti_musb_peripheral_remove, 277 .ops = &musb_usb_ops, 278 .platdata_auto_alloc_size = sizeof(struct ti_musb_platdata), 279 .priv_auto_alloc_size = sizeof(struct ti_musb_peripheral), 280 .flags = DM_FLAG_PRE_RELOC, 281 }; 282 #endif 283 284 #if CONFIG_IS_ENABLED(OF_CONTROL) 285 static int ti_musb_wrapper_bind(struct udevice *parent) 286 { 287 const void *fdt = gd->fdt_blob; 288 int node; 289 int ret; 290 291 for (node = fdt_first_subnode(fdt, dev_of_offset(parent)); node > 0; 292 node = fdt_next_subnode(fdt, node)) { 293 struct udevice *dev; 294 const char *name = fdt_get_name(fdt, node, NULL); 295 enum usb_dr_mode dr_mode; 296 struct driver *drv; 297 298 if (strncmp(name, "usb@", 4)) 299 continue; 300 301 dr_mode = usb_get_dr_mode(node); 302 switch (dr_mode) { 303 case USB_DR_MODE_PERIPHERAL: 304 /* Bind MUSB device */ 305 ret = device_bind_driver_to_node(parent, 306 "ti-musb-peripheral", 307 name, 308 offset_to_ofnode(node), 309 &dev); 310 if (ret) 311 pr_err("musb - not able to bind usb peripheral node\n"); 312 break; 313 case USB_DR_MODE_HOST: 314 /* Bind MUSB host */ 315 ret = device_bind_driver_to_node(parent, 316 "ti-musb-host", 317 name, 318 offset_to_ofnode(node), 319 &dev); 320 if (ret) 321 pr_err("musb - not able to bind usb host node\n"); 322 break; 323 default: 324 break; 325 }; 326 } 327 return 0; 328 } 329 330 static const struct udevice_id ti_musb_ids[] = { 331 { .compatible = "ti,am33xx-usb" }, 332 { } 333 }; 334 335 U_BOOT_DRIVER(ti_musb_wrapper) = { 336 .name = "ti-musb-wrapper", 337 .id = UCLASS_MISC, 338 .of_match = ti_musb_ids, 339 .bind = ti_musb_wrapper_bind, 340 }; 341 #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ 342 343 #endif /* CONFIG_IS_ENABLED(DM_USB) */ 344