1*0b303a9fSandvar /* $Id: imx23_usb.c,v 1.7 2024/01/15 17:29:27 andvar Exp $ */
294de0730Smatt
394de0730Smatt /*
494de0730Smatt * Copyright (c) 2013 The NetBSD Foundation, Inc.
594de0730Smatt * All rights reserved.
694de0730Smatt *
794de0730Smatt * This code is derived from software contributed to The NetBSD Foundation
894de0730Smatt * by Petri Laakso.
994de0730Smatt *
1094de0730Smatt * Redistribution and use in source and binary forms, with or without
1194de0730Smatt * modification, are permitted provided that the following conditions
1294de0730Smatt * are met:
1394de0730Smatt * 1. Redistributions of source code must retain the above copyright
1494de0730Smatt * notice, this list of conditions and the following disclaimer.
1594de0730Smatt * 2. Redistributions in binary form must reproduce the above copyright
1694de0730Smatt * notice, this list of conditions and the following disclaimer in the
1794de0730Smatt * documentation and/or other materials provided with the distribution.
1894de0730Smatt *
1994de0730Smatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2094de0730Smatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2194de0730Smatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2294de0730Smatt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2394de0730Smatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2494de0730Smatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2594de0730Smatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2694de0730Smatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2794de0730Smatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2894de0730Smatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2994de0730Smatt * POSSIBILITY OF SUCH DAMAGE.
3094de0730Smatt */
3194de0730Smatt
3294de0730Smatt #include <sys/param.h>
3394de0730Smatt #include <sys/types.h>
3494de0730Smatt #include <sys/bus.h>
3594de0730Smatt #include <sys/errno.h>
3694de0730Smatt
3794de0730Smatt #include <arm/pic/picvar.h>
3894de0730Smatt
3994de0730Smatt #include <dev/usb/usb.h>
4094de0730Smatt #include <dev/usb/usbdi.h>
4194de0730Smatt #include <dev/usb/usbdivar.h>
4294de0730Smatt #include <dev/usb/usb_mem.h>
4394de0730Smatt #include <dev/usb/ehcireg.h>
4494de0730Smatt #include <dev/usb/ehcivar.h>
4594de0730Smatt #include <arm/imx/imxusbvar.h>
4605ac7a10Shkenken #include <arm/imx/imxusbreg.h>
4794de0730Smatt
4894de0730Smatt #include <arm/mainbus/mainbus.h>
4994de0730Smatt
5094de0730Smatt #include <arm/imx/imx23_clkctrlvar.h>
5194de0730Smatt #include <arm/imx/imx23_digctlvar.h>
5294de0730Smatt #include <arm/imx/imx23_pinctrlvar.h>
5394de0730Smatt #include <arm/imx/imx23var.h>
5494de0730Smatt
5594de0730Smatt #include "locators.h"
5694de0730Smatt
5794de0730Smatt struct imx23_usb_softc {
5805ac7a10Shkenken struct imxusbc_softc sc_imxusbc; /* Must be first */
5994de0730Smatt };
6094de0730Smatt
6194de0730Smatt static int imx23_usb_match(device_t, cfdata_t, void *);
6294de0730Smatt static void imx23_usb_attach(device_t, device_t, void *);
6394de0730Smatt static int imx23_usb_activate(device_t, enum devact);
6494de0730Smatt
6594de0730Smatt static int imxusbc_search(device_t, cfdata_t, const int *, void *);
66*0b303a9fSandvar static void imx23_usb_init(struct imxehci_softc *, uintptr_t);
6794de0730Smatt
6894de0730Smatt CFATTACH_DECL3_NEW(imxusbc,
6994de0730Smatt sizeof(struct imx23_usb_softc),
7094de0730Smatt imx23_usb_match,
7194de0730Smatt imx23_usb_attach,
7294de0730Smatt NULL,
7394de0730Smatt imx23_usb_activate,
7494de0730Smatt NULL,
7594de0730Smatt NULL,
7694de0730Smatt 0
7794de0730Smatt );
7894de0730Smatt
7994de0730Smatt #define AHB_USB 0x80080000
8094de0730Smatt #define AHB_USB_SIZE 0x40000
8194de0730Smatt
8294de0730Smatt static int
imx23_usb_match(device_t parent,cfdata_t match,void * aux)8394de0730Smatt imx23_usb_match(device_t parent, cfdata_t match, void *aux)
8494de0730Smatt {
8594de0730Smatt struct ahb_attach_args *aa = aux;
8694de0730Smatt
8794de0730Smatt if ((aa->aa_addr == AHB_USB) && (aa->aa_size == AHB_USB_SIZE))
8894de0730Smatt return 1;
8994de0730Smatt
9094de0730Smatt return 0;
9194de0730Smatt }
9294de0730Smatt
9394de0730Smatt static void
imx23_usb_attach(device_t parent,device_t self,void * aux)9494de0730Smatt imx23_usb_attach(device_t parent, device_t self, void *aux)
9594de0730Smatt {
9694de0730Smatt struct imxusbc_softc *sc = device_private(self);
9794de0730Smatt
9805ac7a10Shkenken sc->sc_dev = self;
9994de0730Smatt sc->sc_iot = &imx23_bus_space;
10005ac7a10Shkenken sc->sc_ehci_size = IMXUSB_EHCI_SIZE;
10105ac7a10Shkenken sc->sc_ehci_offset = IMXUSB_EHCI_SIZE;
10205ac7a10Shkenken
10305ac7a10Shkenken sc->sc_init_md_hook = imx23_usb_init;
10405ac7a10Shkenken sc->sc_intr_establish_md_hook = NULL;
10505ac7a10Shkenken sc->sc_setup_md_hook = NULL;
10694de0730Smatt
10794de0730Smatt if (bus_space_map(sc->sc_iot, AHB_USB, AHB_USB_SIZE, 0, &sc->sc_ioh)) {
10894de0730Smatt aprint_error_dev(sc->sc_dev, "Unable to map bus space");
10994de0730Smatt return;
11094de0730Smatt }
11194de0730Smatt
11294de0730Smatt /* Enable PLL outputs for USB PHY. */
11394de0730Smatt clkctrl_en_usb();
11494de0730Smatt
11594de0730Smatt /* Enable external USB chip. */
11668bc6eb1Sskrll imx23_pinctrl_en_usb();
11794de0730Smatt
11894de0730Smatt /* USB clock on. */
11994de0730Smatt digctl_usb_clkgate(0);
12094de0730Smatt
12194de0730Smatt aprint_normal("\n");
12294de0730Smatt
12394de0730Smatt /* attach OTG/EHCI host controllers */
1242685996bSthorpej config_search(self, NULL,
125c7fb772bSthorpej CFARGS(.search = imxusbc_search));
12694de0730Smatt
12794de0730Smatt return;
12894de0730Smatt }
12994de0730Smatt
13094de0730Smatt static int
imx23_usb_activate(device_t self,enum devact act)13194de0730Smatt imx23_usb_activate(device_t self, enum devact act)
13294de0730Smatt {
13394de0730Smatt return EOPNOTSUPP;
13494de0730Smatt }
13594de0730Smatt
13694de0730Smatt static int
imxusbc_search(device_t parent,cfdata_t cf,const int * ldesc,void * aux)13794de0730Smatt imxusbc_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
13894de0730Smatt {
13994de0730Smatt struct imxusbc_softc *sc = device_private(parent);
14094de0730Smatt struct imxusbc_attach_args aa;
14194de0730Smatt
14294de0730Smatt aa.aa_iot = sc->sc_iot;
14394de0730Smatt aa.aa_ioh = sc->sc_ioh;
14494de0730Smatt aa.aa_dmat = &imx23_bus_dma_tag;
14594de0730Smatt aa.aa_unit = cf->cf_loc[IMXUSBCCF_UNIT];
14694de0730Smatt aa.aa_irq = cf->cf_loc[IMXUSBCCF_IRQ];
14794de0730Smatt
1482685996bSthorpej if (config_probe(parent, cf, &aa))
149c7fb772bSthorpej config_attach(parent, cf, &aa, NULL, CFARGS_NONE);
15094de0730Smatt
15194de0730Smatt return 0;
15294de0730Smatt }
15394de0730Smatt
15494de0730Smatt static
imx23_usb_init(struct imxehci_softc * sc,uintptr_t data)1551b53f886Sbouyer void imx23_usb_init(struct imxehci_softc *sc, uintptr_t data)
15694de0730Smatt {
15794de0730Smatt
15894de0730Smatt sc->sc_iftype = IMXUSBC_IF_UTMI;
15994de0730Smatt
16094de0730Smatt return;
16194de0730Smatt }
162