imx23_usbc.c revision 1.1
11.1Syurix/* $NetBSD $ */ 21.1Syurix 31.1Syurix/*- 41.1Syurix * Copyright (c) 2026 The NetBSD Foundation, Inc. 51.1Syurix * All rights reserved. 61.1Syurix * 71.1Syurix * This code is derived from software contributed to The NetBSD Foundation 81.1Syurix * by Yuri Honegger. 91.1Syurix * 101.1Syurix * Redistribution and use in source and binary forms, with or without 111.1Syurix * modification, are permitted provided that the following conditions 121.1Syurix * are met: 131.1Syurix * 1. Redistributions of source code must retain the above copyright 141.1Syurix * notice, this list of conditions and the following disclaimer. 151.1Syurix * 2. Redistributions in binary form must reproduce the above copyright 161.1Syurix * notice, this list of conditions and the following disclaimer in the 171.1Syurix * documentation and/or other materials provided with the distribution. 181.1Syurix * 191.1Syurix * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 201.1Syurix * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 211.1Syurix * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221.1Syurix * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 231.1Syurix * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 241.1Syurix * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 251.1Syurix * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 261.1Syurix * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 271.1Syurix * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 281.1Syurix * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 291.1Syurix * POSSIBILITY OF SUCH DAMAGE. 301.1Syurix */ 311.1Syurix 321.1Syurix/* 331.1Syurix * USB controller driver for the imx23. 341.1Syurix */ 351.1Syurix 361.1Syurix#include <sys/device.h> 371.1Syurix 381.1Syurix#include <dev/fdt/fdtvar.h> 391.1Syurix 401.1Syurix#include <dev/usb/usb.h> 411.1Syurix#include <dev/usb/usbdi.h> 421.1Syurix#include <dev/usb/usbdivar.h> 431.1Syurix#include <dev/usb/usb_mem.h> 441.1Syurix/* must be after the other USB includes */ 451.1Syurix#include <dev/usb/ehcireg.h> 461.1Syurix#include <dev/usb/ehcivar.h> 471.1Syurix 481.1Syurix#include <arm/fdt/arm_fdtvar.h> 491.1Syurix#include <arm/imx/imxusbvar.h> 501.1Syurix#include <arm/imx/imxusbreg.h> 511.1Syurix#include <arm/imx/imx23var.h> 521.1Syurix 531.1Syurixstruct imx23_imxusbc_softc { 541.1Syurix struct imxusbc_softc sc_imxusbc; /* Must be first */ 551.1Syurix int sc_phandle; 561.1Syurix}; 571.1Syurix 581.1Syurixstatic int imx23_usbc_match(device_t, cfdata_t, void *); 591.1Syurixstatic void imx23_usbc_attach(device_t, device_t, void *); 601.1Syurix 611.1Syurixstatic void imx23_usbc_init(struct imxehci_softc *, uintptr_t); 621.1Syurixstatic void * imx23_usbc_intr_establish(struct imxehci_softc *, uintptr_t); 631.1Syurix 641.1SyurixCFATTACH_DECL_NEW(imxusbc, sizeof(struct imx23_imxusbc_softc), 651.1Syurix imx23_usbc_match, imx23_usbc_attach, NULL, NULL); 661.1Syurix 671.1Syurixstatic const struct device_compatible_entry compat_data[] = { 681.1Syurix { .compat = "fsl,imx23-usb" }, 691.1Syurix DEVICE_COMPAT_EOL 701.1Syurix}; 711.1Syurix 721.1Syurixstatic int 731.1Syuriximx23_usbc_match(device_t parent, cfdata_t cf, void *aux) 741.1Syurix{ 751.1Syurix struct fdt_attach_args * const faa = aux; 761.1Syurix 771.1Syurix return of_compatible_match(faa->faa_phandle, compat_data); 781.1Syurix} 791.1Syurix 801.1Syurixstatic void 811.1Syuriximx23_usbc_attach(device_t parent, device_t self, void *aux) 821.1Syurix{ 831.1Syurix struct imx23_imxusbc_softc * const sc = device_private(self); 841.1Syurix struct fdt_attach_args * const faa = aux; 851.1Syurix const int phandle = faa->faa_phandle; 861.1Syurix 871.1Syurix sc->sc_phandle = phandle; 881.1Syurix 891.1Syurix sc->sc_imxusbc.sc_dev = self; 901.1Syurix sc->sc_imxusbc.sc_iot = faa->faa_bst; 911.1Syurix 921.1Syurix bus_addr_t addr; 931.1Syurix bus_size_t size; 941.1Syurix if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) { 951.1Syurix aprint_error(": couldn't get register address\n"); 961.1Syurix return; 971.1Syurix } 981.1Syurix if (bus_space_map(faa->faa_bst, addr, size, 0, 991.1Syurix &sc->sc_imxusbc.sc_ioh)) { 1001.1Syurix aprint_error(": couldn't map registers\n"); 1011.1Syurix return; 1021.1Syurix } 1031.1Syurix 1041.1Syurix /* Enable external USB chip. */ 1051.1Syurix struct fdtbus_regulator *vbus_reg = 1061.1Syurix fdtbus_regulator_acquire(phandle, "vbus-supply"); 1071.1Syurix if(vbus_reg == NULL){ 1081.1Syurix aprint_error(": couldn't get vbus regulator\n"); 1091.1Syurix return; 1101.1Syurix } 1111.1Syurix fdtbus_regulator_enable(vbus_reg); 1121.1Syurix 1131.1Syurix sc->sc_imxusbc.sc_ehci_size = IMXUSB_EHCI_SIZE; 1141.1Syurix sc->sc_imxusbc.sc_ehci_offset = IMXUSB_EHCI_SIZE; 1151.1Syurix sc->sc_imxusbc.sc_init_md_hook = imx23_usbc_init; 1161.1Syurix sc->sc_imxusbc.sc_intr_establish_md_hook = imx23_usbc_intr_establish; 1171.1Syurix sc->sc_imxusbc.sc_setup_md_hook = NULL; 1181.1Syurix 1191.1Syurix aprint_normal("\n"); 1201.1Syurix 1211.1Syurix /* attach OTG/EHCI host controllers */ 1221.1Syurix struct imxusbc_attach_args iaa; 1231.1Syurix iaa.aa_iot = sc->sc_imxusbc.sc_iot; 1241.1Syurix iaa.aa_ioh = sc->sc_imxusbc.sc_ioh; 1251.1Syurix iaa.aa_dmat = faa->faa_dmat; 1261.1Syurix iaa.aa_unit = 0; /* only one unit on the imx23 */ 1271.1Syurix iaa.aa_irq = -1; /* we establish it directly from FDT in the hook */ 1281.1Syurix config_found(self, &iaa, NULL, CFARGS_NONE); 1291.1Syurix} 1301.1Syurix 1311.1Syurixstatic void 1321.1Syuriximx23_usbc_init(struct imxehci_softc *sc, uintptr_t data) 1331.1Syurix{ 1341.1Syurix sc->sc_iftype = IMXUSBC_IF_UTMI; 1351.1Syurix} 1361.1Syurix 1371.1Syurixstatic void * 1381.1Syuriximx23_usbc_intr_establish(struct imxehci_softc *sc, uintptr_t data) 1391.1Syurix{ 1401.1Syurix struct imx23_imxusbc_softc *ifsc = (struct imx23_imxusbc_softc *) 1411.1Syurix sc->sc_usbc; 1421.1Syurix ehci_softc_t *hsc = &sc->sc_hsc; 1431.1Syurix void *ih; 1441.1Syurix 1451.1Syurix char intrstr[128]; 1461.1Syurix if (!fdtbus_intr_str(ifsc->sc_phandle, 0, intrstr, sizeof(intrstr))) { 1471.1Syurix aprint_error_dev(sc->sc_dev, "failed to decode interrupt\n"); 1481.1Syurix return NULL; 1491.1Syurix } 1501.1Syurix ih = fdtbus_intr_establish_xname(ifsc->sc_phandle, 0, IPL_USB, 1511.1Syurix FDT_INTR_MPSAFE, ehci_intr, hsc, 1521.1Syurix device_xname(sc->sc_dev)); 1531.1Syurix if (ih == NULL) { 1541.1Syurix aprint_error_dev(sc->sc_dev, 1551.1Syurix "failed to establish interrupt on %s\n", 1561.1Syurix intrstr); 1571.1Syurix return NULL; 1581.1Syurix } 1591.1Syurix aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr); 1601.1Syurix 1611.1Syurix return ih; 1621.1Syurix}