1 /* $NetBSD: tegra_xusbpad.c,v 1.2 2015/12/13 17:39:19 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2015 Jared D. McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: tegra_xusbpad.c,v 1.2 2015/12/13 17:39:19 jmcneill Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/bus.h> 34 #include <sys/device.h> 35 #include <sys/intr.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 39 #include <arm/nvidia/tegra_reg.h> 40 #include <arm/nvidia/tegra_xusbpadreg.h> 41 #include <arm/nvidia/tegra_var.h> 42 43 #include <dev/fdt/fdtvar.h> 44 45 static int tegra_xusbpad_match(device_t, cfdata_t, void *); 46 static void tegra_xusbpad_attach(device_t, device_t, void *); 47 48 struct tegra_xusbpad_softc { 49 device_t sc_dev; 50 bus_space_tag_t sc_bst; 51 bus_space_handle_t sc_bsh; 52 }; 53 54 static struct tegra_xusbpad_softc *xusbpad_softc = NULL; 55 56 CFATTACH_DECL_NEW(tegra_xusbpad, sizeof(struct tegra_xusbpad_softc), 57 tegra_xusbpad_match, tegra_xusbpad_attach, NULL, NULL); 58 59 static int 60 tegra_xusbpad_match(device_t parent, cfdata_t cf, void *aux) 61 { 62 const char * const compatible[] = 63 { "nvidia,tegra124-xusb-padctl", NULL }; 64 struct fdt_attach_args * const faa = aux; 65 66 return of_match_compatible(faa->faa_phandle, compatible); 67 } 68 69 static void 70 tegra_xusbpad_attach(device_t parent, device_t self, void *aux) 71 { 72 struct tegra_xusbpad_softc * const sc = device_private(self); 73 struct fdt_attach_args * const faa = aux; 74 bus_addr_t addr; 75 bus_size_t size; 76 int error; 77 78 if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) { 79 aprint_error(": couldn't get registers\n"); 80 return; 81 } 82 83 sc->sc_dev = self; 84 sc->sc_bst = faa->faa_bst; 85 error = bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh); 86 if (error) { 87 aprint_error(": couldn't map %#llx: %d", (uint64_t)addr, error); 88 return; 89 } 90 91 KASSERT(xusbpad_softc == NULL); 92 xusbpad_softc = sc; 93 94 aprint_naive("\n"); 95 aprint_normal(": XUSB PADCTL\n"); 96 } 97 98 static void 99 tegra_xusbpad_get_bs(bus_space_tag_t *pbst, bus_space_handle_t *pbsh) 100 { 101 if (xusbpad_softc) { 102 *pbst = xusbpad_softc->sc_bst; 103 *pbsh = xusbpad_softc->sc_bsh; 104 } else { 105 *pbst = &armv7_generic_bs_tag; 106 bus_space_subregion(*pbst, tegra_apb_bsh, 107 TEGRA_XUSB_PADCTL_OFFSET, TEGRA_XUSB_PADCTL_SIZE, pbsh); 108 } 109 } 110 111 void 112 tegra_xusbpad_sata_enable(void) 113 { 114 bus_space_tag_t bst; 115 bus_space_handle_t bsh; 116 int retry; 117 118 tegra_xusbpad_get_bs(&bst, &bsh); 119 120 tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_USB3_PAD_MUX_REG, 121 __SHIFTIN(XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0_SATA, 122 XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0) | 123 XUSB_PADCTL_USB3_PAD_MUX_FORCE_SATA_PAD_IDDQ_DISABLE_MASK0, 124 XUSB_PADCTL_USB3_PAD_MUX_SATA_PAD_LANE0); 125 126 tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_REG, 127 0, 128 XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ | 129 XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD); 130 tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG, 131 0, 132 XUSB_PADCTL_IOPHY_PLL_S0_CTL1_IDDQ | 133 XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PWR_OVRD); 134 tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG, 135 XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE, 0); 136 tegra_reg_set_clear(bst, bsh, XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG, 137 XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST, 0); 138 139 for (retry = 1000; retry > 0; retry--) { 140 const uint32_t v = bus_space_read_4(bst, bsh, 141 XUSB_PADCTL_IOPHY_PLL_S0_CTL1_REG); 142 if (v & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) 143 break; 144 delay(100); 145 } 146 if (retry == 0) { 147 printf("WARNING: SATA PHY power-on failed\n"); 148 } 149 } 150