1 /* 2 * Copyright (C) 2012 Sughosh Ganu <urwithsughosh@gmail.com> 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/io.h> 9 #include <clk.h> 10 #include <dm.h> 11 #include <dm/ofnode.h> 12 #include <generic-phy.h> 13 #include <reset.h> 14 #include "ohci.h" 15 #include <asm/arch/da8xx-usb.h> 16 17 struct da8xx_ohci { 18 ohci_t ohci; 19 struct clk *clocks; /* clock list */ 20 struct phy phy; 21 int clock_count; /* number of clock in clock list */ 22 }; 23 24 static int usb_phy_on(void) 25 { 26 unsigned long timeout; 27 28 clrsetbits_le32(&davinci_syscfg_regs->cfgchip2, 29 (CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | 30 CFGCHIP2_OTGPWRDN | CFGCHIP2_OTGMODE | 31 CFGCHIP2_REFFREQ | CFGCHIP2_USB1PHYCLKMUX), 32 (CFGCHIP2_SESENDEN | CFGCHIP2_VBDTCTEN | 33 CFGCHIP2_PHY_PLLON | CFGCHIP2_REFFREQ_24MHZ | 34 CFGCHIP2_USB2PHYCLKMUX | CFGCHIP2_USB1SUSPENDM)); 35 36 /* wait until the usb phy pll locks */ 37 timeout = get_timer(0); 38 while (get_timer(timeout) < 10) { 39 if (readl(&davinci_syscfg_regs->cfgchip2) & CFGCHIP2_PHYCLKGD) 40 return 1; 41 } 42 43 /* USB phy was not turned on */ 44 return 0; 45 } 46 47 static void usb_phy_off(void) 48 { 49 /* Power down the on-chip PHY. */ 50 clrsetbits_le32(&davinci_syscfg_regs->cfgchip2, 51 CFGCHIP2_PHY_PLLON | CFGCHIP2_USB1SUSPENDM, 52 CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN | 53 CFGCHIP2_RESET); 54 } 55 56 int usb_cpu_init(void) 57 { 58 /* enable psc for usb2.0 */ 59 lpsc_on(DAVINCI_LPSC_USB20); 60 61 /* enable psc for usb1.0 */ 62 lpsc_on(DAVINCI_LPSC_USB11); 63 64 /* start the on-chip usb phy and its pll */ 65 if (usb_phy_on()) 66 return 0; 67 68 return 1; 69 } 70 71 int usb_cpu_stop(void) 72 { 73 usb_phy_off(); 74 75 /* turn off the usb clock and assert the module reset */ 76 lpsc_disable(DAVINCI_LPSC_USB11); 77 lpsc_disable(DAVINCI_LPSC_USB20); 78 79 return 0; 80 } 81 82 int usb_cpu_init_fail(void) 83 { 84 return usb_cpu_stop(); 85 } 86 87 #if CONFIG_IS_ENABLED(DM_USB) 88 static int ohci_da8xx_probe(struct udevice *dev) 89 { 90 struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev); 91 struct da8xx_ohci *priv = dev_get_priv(dev); 92 int i, err, ret, clock_nb; 93 94 err = 0; 95 priv->clock_count = 0; 96 clock_nb = dev_count_phandle_with_args(dev, "clocks", "#clock-cells"); 97 98 if (clock_nb < 0) 99 return clock_nb; 100 101 if (clock_nb > 0) { 102 priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk), 103 GFP_KERNEL); 104 if (!priv->clocks) 105 return -ENOMEM; 106 107 for (i = 0; i < clock_nb; i++) { 108 err = clk_get_by_index(dev, i, &priv->clocks[i]); 109 if (err < 0) 110 break; 111 112 err = clk_enable(&priv->clocks[i]); 113 if (err) { 114 dev_err(dev, "failed to enable clock %d\n", i); 115 clk_free(&priv->clocks[i]); 116 goto clk_err; 117 } 118 priv->clock_count++; 119 } 120 } 121 122 err = usb_cpu_init(); 123 124 if (err) 125 goto clk_err; 126 127 err = ohci_register(dev, regs); 128 if (err) 129 goto phy_err; 130 131 return 0; 132 133 phy_err: 134 ret = usb_cpu_stop(); 135 if (ret) 136 dev_err(dev, "failed to shutdown usb phy\n"); 137 138 clk_err: 139 ret = clk_release_all(priv->clocks, priv->clock_count); 140 if (ret) 141 dev_err(dev, "failed to disable all clocks\n"); 142 143 return err; 144 } 145 146 static int ohci_da8xx_remove(struct udevice *dev) 147 { 148 struct da8xx_ohci *priv = dev_get_priv(dev); 149 int ret; 150 151 ret = ohci_deregister(dev); 152 if (ret) 153 return ret; 154 155 ret = usb_cpu_stop(); 156 if (ret) 157 return ret; 158 159 return clk_release_all(priv->clocks, priv->clock_count); 160 } 161 162 static const struct udevice_id da8xx_ohci_ids[] = { 163 { .compatible = "ti,da830-ohci" }, 164 { } 165 }; 166 167 U_BOOT_DRIVER(ohci_generic) = { 168 .name = "ohci-da8xx", 169 .id = UCLASS_USB, 170 .of_match = da8xx_ohci_ids, 171 .probe = ohci_da8xx_probe, 172 .remove = ohci_da8xx_remove, 173 .ops = &ohci_usb_ops, 174 .priv_auto_alloc_size = sizeof(struct da8xx_ohci), 175 .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE, 176 }; 177 #endif 178