imx23_usbc.c revision 1.2
1/* $NetBSD $ */ 2 3/*- 4 * Copyright (c) 2026 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Yuri Honegger. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * USB controller driver for the imx23. 34 */ 35 36#include <sys/device.h> 37 38#include <dev/fdt/fdtvar.h> 39 40#include <dev/usb/usb.h> 41#include <dev/usb/usbdi.h> 42#include <dev/usb/usbdivar.h> 43#include <dev/usb/usb_mem.h> 44/* must be after the other USB includes */ 45#include <dev/usb/ehcireg.h> 46#include <dev/usb/ehcivar.h> 47 48#include <arm/fdt/arm_fdtvar.h> 49#include <arm/imx/imxusbvar.h> 50#include <arm/imx/imxusbreg.h> 51#include <arm/imx/imx23var.h> 52 53struct imx23_imxusbc_softc { 54 struct imxusbc_softc sc_imxusbc; /* Must be first */ 55 int sc_phandle; 56}; 57 58static int imx23_usbc_match(device_t, cfdata_t, void *); 59static void imx23_usbc_attach(device_t, device_t, void *); 60 61static void imx23_usbc_init(struct imxehci_softc *, uintptr_t); 62static void * imx23_usbc_intr_establish(struct imxehci_softc *, uintptr_t); 63 64CFATTACH_DECL_NEW(imxusbc, sizeof(struct imx23_imxusbc_softc), 65 imx23_usbc_match, imx23_usbc_attach, NULL, NULL); 66 67static const struct device_compatible_entry compat_data[] = { 68 { .compat = "fsl,imx23-usb" }, 69 DEVICE_COMPAT_EOL 70}; 71 72static int 73imx23_usbc_match(device_t parent, cfdata_t cf, void *aux) 74{ 75 struct fdt_attach_args * const faa = aux; 76 77 return of_compatible_match(faa->faa_phandle, compat_data); 78} 79 80static void 81imx23_usbc_attach(device_t parent, device_t self, void *aux) 82{ 83 struct imx23_imxusbc_softc * const sc = device_private(self); 84 struct fdt_attach_args * const faa = aux; 85 const int phandle = faa->faa_phandle; 86 87 sc->sc_phandle = phandle; 88 89 sc->sc_imxusbc.sc_dev = self; 90 sc->sc_imxusbc.sc_iot = faa->faa_bst; 91 92 bus_addr_t addr; 93 bus_size_t size; 94 if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 95 aprint_error(": couldn't get register address\n"); 96 return; 97 } 98 if (bus_space_map(faa->faa_bst, addr, size, 0, 99 &sc->sc_imxusbc.sc_ioh)) { 100 aprint_error(": couldn't map registers\n"); 101 return; 102 } 103 104 /* Enable external USB chip. */ 105 struct fdtbus_regulator *vbus_reg = 106 fdtbus_regulator_acquire(phandle, "vbus-supply"); 107 if(vbus_reg == NULL){ 108 aprint_error(": couldn't get vbus regulator\n"); 109 return; 110 } 111 fdtbus_regulator_enable(vbus_reg); 112 113 sc->sc_imxusbc.sc_ehci_size = IMXUSB_EHCI_SIZE; 114 sc->sc_imxusbc.sc_ehci_offset = IMXUSB_EHCI_SIZE; 115 sc->sc_imxusbc.sc_init_md_hook = imx23_usbc_init; 116 sc->sc_imxusbc.sc_intr_establish_md_hook = imx23_usbc_intr_establish; 117 sc->sc_imxusbc.sc_setup_md_hook = NULL; 118 119 aprint_normal("\n"); 120 121 /* attach OTG/EHCI host controllers */ 122 struct imxusbc_attach_args iaa; 123 iaa.aa_iot = sc->sc_imxusbc.sc_iot; 124 iaa.aa_ioh = sc->sc_imxusbc.sc_ioh; 125 iaa.aa_dmat = faa->faa_dmat; 126 iaa.aa_unit = 0; /* only one unit on the imx23 */ 127 iaa.aa_irq = -1; /* we establish it directly from FDT in the hook */ 128 config_found(self, &iaa, NULL, CFARGS_NONE); 129} 130 131static void 132imx23_usbc_init(struct imxehci_softc *sc, uintptr_t data) 133{ 134 sc->sc_iftype = IMXUSBC_IF_UTMI; 135} 136 137static void * 138imx23_usbc_intr_establish(struct imxehci_softc *sc, uintptr_t data) 139{ 140 struct imx23_imxusbc_softc *ifsc = (struct imx23_imxusbc_softc *) 141 sc->sc_usbc; 142 ehci_softc_t *hsc = &sc->sc_hsc; 143 void *ih; 144 145 char intrstr[128]; 146 if (!fdtbus_intr_str(ifsc->sc_phandle, 0, intrstr, sizeof(intrstr))) { 147 aprint_error_dev(sc->sc_dev, "failed to decode interrupt\n"); 148 return NULL; 149 } 150 ih = fdtbus_intr_establish_xname(ifsc->sc_phandle, 0, IPL_USB, 151 FDT_INTR_MPSAFE, ehci_intr, hsc, 152 device_xname(sc->sc_dev)); 153 if (ih == NULL) { 154 aprint_error_dev(sc->sc_dev, 155 "failed to establish interrupt on %s\n", 156 intrstr); 157 return NULL; 158 } 159 aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr); 160 161 return ih; 162} 163