Home | History | Annotate | Line # | Download | only in starfive
      1  1.3  skrll /* $NetBSD: jh71x0_usb.c,v 1.3 2024/09/18 08:31:50 skrll Exp $ */
      2  1.1  skrll 
      3  1.1  skrll /*-
      4  1.1  skrll  * Copyright (c) 2023 The NetBSD Foundation, Inc.
      5  1.1  skrll  * All rights reserved.
      6  1.1  skrll  *
      7  1.1  skrll  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  skrll  * by Nick Hudson
      9  1.1  skrll  *
     10  1.1  skrll  * Redistribution and use in source and binary forms, with or without
     11  1.1  skrll  * modification, are permitted provided that the following conditions
     12  1.1  skrll  * are met:
     13  1.1  skrll  * 1. Redistributions of source code must retain the above copyright
     14  1.1  skrll  *    notice, this list of conditions and the following disclaimer.
     15  1.1  skrll  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  skrll  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  skrll  *    documentation and/or other materials provided with the distribution.
     18  1.1  skrll  *
     19  1.1  skrll  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.1  skrll  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.1  skrll  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.1  skrll  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.1  skrll  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.1  skrll  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.1  skrll  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.1  skrll  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.1  skrll  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.1  skrll  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.1  skrll  * POSSIBILITY OF SUCH DAMAGE.
     30  1.1  skrll  */
     31  1.1  skrll 
     32  1.1  skrll #include <sys/cdefs.h>
     33  1.3  skrll __KERNEL_RCSID(0, "$NetBSD: jh71x0_usb.c,v 1.3 2024/09/18 08:31:50 skrll Exp $");
     34  1.1  skrll 
     35  1.1  skrll #include <sys/param.h>
     36  1.1  skrll 
     37  1.1  skrll 
     38  1.1  skrll #include <dev/fdt/fdtvar.h>
     39  1.1  skrll #include <dev/fdt/syscon.h>
     40  1.1  skrll 
     41  1.1  skrll struct jh71x0_usb_softc {
     42  1.1  skrll 	device_t		sc_dev;
     43  1.1  skrll 	bus_space_tag_t		sc_bst;
     44  1.1  skrll 	bus_space_handle_t	sc_bsh;
     45  1.1  skrll 	int			sc_phandle;
     46  1.1  skrll 
     47  1.1  skrll 	int			sc_syscon_phandle;
     48  1.1  skrll 	const struct syscon	*sc_syscon;
     49  1.1  skrll };
     50  1.1  skrll 
     51  1.1  skrll 
     52  1.3  skrll #define RD4(sc, reg)							       \
     53  1.1  skrll 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
     54  1.3  skrll #define WR4(sc, reg, val)						       \
     55  1.1  skrll 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
     56  1.1  skrll 
     57  1.1  skrll 
     58  1.1  skrll /* Register definitions */
     59  1.1  skrll 
     60  1.1  skrll #define JH7100_USB0			0x20
     61  1.1  skrll #define JH7100_USB0_MODE_STRAP_MASK	__BITS(2, 0)
     62  1.1  skrll #define JH7100_USB0_MODE_STRAP_HOST	2
     63  1.1  skrll 
     64  1.1  skrll #define JH7100_USB3			0x2c
     65  1.1  skrll #define JH7100_USB3_UTMI_IDDIG		__BIT(21)
     66  1.1  skrll 
     67  1.1  skrll #define JH7100_USB7			0x3c
     68  1.1  skrll #define JH7100_USB7_SSRX_SEL		__BIT(18)
     69  1.1  skrll #define JH7100_USB7_SSTX_SEL		__BIT(19)
     70  1.1  skrll #define JH7100_USB7_PLL_EN		__BIT(23)
     71  1.1  skrll #define JH7100_USB7_EQ_EN		__BIT(25)
     72  1.1  skrll 
     73  1.1  skrll #define JH7110_STRAP_HOST		__BIT(17)
     74  1.1  skrll #define JH7110_STRAP_DEVICE		__BIT(18)
     75  1.1  skrll #define JH7110_STRAP_MASK		__BITS(18, 16)
     76  1.1  skrll 
     77  1.1  skrll #define JH7110_SUSPENDM_HOST		__BIT(19)
     78  1.1  skrll #define JH7110_SUSPENDM_MASK		__BIT(19)
     79  1.1  skrll 
     80  1.1  skrll #define JH7110_MISC_CFG_MASK		__BITS(23, 20)
     81  1.1  skrll #define JH7110_SUSPENDM_BYPS		__BIT(20)
     82  1.1  skrll #define JH7110_PLL_EN			__BIT(22)
     83  1.1  skrll #define JH7110_REFCLK_MODE		__BIT(23)
     84  1.1  skrll 
     85  1.1  skrll 
     86  1.1  skrll 
     87  1.1  skrll enum usb_dr_mode {
     88  1.1  skrll 	USB_DR_MODE_UNKNOWN,
     89  1.1  skrll 	USB_DR_MODE_HOST,
     90  1.1  skrll 	USB_DR_MODE_PERIPHERAL,
     91  1.1  skrll 	USB_DR_MODE_OTG,
     92  1.1  skrll };
     93  1.1  skrll 
     94  1.1  skrll static inline void
     95  1.1  skrll jh71x0_syscon_update(struct jh71x0_usb_softc *sc, bus_size_t off,
     96  1.1  skrll     uint32_t clr, uint32_t set)
     97  1.1  skrll {
     98  1.1  skrll 	syscon_lock(sc->sc_syscon);
     99  1.1  skrll 	const uint32_t old = syscon_read_4(sc->sc_syscon, off);
    100  1.1  skrll 	const uint32_t new = (old & ~clr) | set;
    101  1.1  skrll 	if (old != new) {
    102  1.1  skrll 		syscon_write_4(sc->sc_syscon, off, new);
    103  1.1  skrll 	}
    104  1.1  skrll 	syscon_unlock(sc->sc_syscon);
    105  1.1  skrll }
    106  1.1  skrll 
    107  1.1  skrll static int
    108  1.1  skrll jh7100_usb_init(struct jh71x0_usb_softc *sc, const u_int *syscon_data )
    109  1.1  skrll {
    110  1.1  skrll 	enum usb_dr_mode mode = USB_DR_MODE_HOST;
    111  1.1  skrll 
    112  1.1  skrll 	switch (mode) {
    113  1.1  skrll 	case USB_DR_MODE_HOST:
    114  1.1  skrll 		jh71x0_syscon_update(sc, JH7100_USB0,
    115  1.1  skrll 		    JH7100_USB0_MODE_STRAP_MASK, JH7100_USB0_MODE_STRAP_HOST);
    116  1.1  skrll 		jh71x0_syscon_update(sc, JH7100_USB7,
    117  1.1  skrll 		    JH7100_USB7_PLL_EN, JH7100_USB7_PLL_EN);
    118  1.1  skrll 		jh71x0_syscon_update(sc, JH7100_USB7,
    119  1.1  skrll 		    JH7100_USB7_EQ_EN, JH7100_USB7_EQ_EN);
    120  1.1  skrll 		jh71x0_syscon_update(sc, JH7100_USB7,
    121  1.1  skrll 		    JH7100_USB7_SSRX_SEL, JH7100_USB7_SSRX_SEL);
    122  1.1  skrll 		jh71x0_syscon_update(sc, JH7100_USB7,
    123  1.1  skrll 		    JH7100_USB7_SSTX_SEL, JH7100_USB7_SSTX_SEL);
    124  1.1  skrll 		jh71x0_syscon_update(sc, JH7100_USB3,
    125  1.1  skrll 		    JH7100_USB3_UTMI_IDDIG, JH7100_USB3_UTMI_IDDIG);
    126  1.1  skrll 		break;
    127  1.1  skrll 	default:
    128  1.1  skrll 		break;
    129  1.1  skrll 	}
    130  1.1  skrll 
    131  1.1  skrll 	return 0;
    132  1.1  skrll }
    133  1.1  skrll 
    134  1.1  skrll static int
    135  1.1  skrll jh7110_usb_init(struct jh71x0_usb_softc *sc, const u_int *syscon_data)
    136  1.1  skrll {
    137  1.1  skrll 	enum usb_dr_mode mode = USB_DR_MODE_HOST;
    138  1.1  skrll 	bus_size_t usb_mode = be32dec(&syscon_data[1]);
    139  1.1  skrll 
    140  1.1  skrll 	jh71x0_syscon_update(sc, usb_mode, JH7110_MISC_CFG_MASK,
    141  1.1  skrll 	    JH7110_SUSPENDM_BYPS | JH7110_PLL_EN | JH7110_REFCLK_MODE);
    142  1.1  skrll 
    143  1.1  skrll 	switch (mode) {
    144  1.1  skrll 	case USB_DR_MODE_HOST:
    145  1.1  skrll 		jh71x0_syscon_update(sc, usb_mode, JH7110_STRAP_MASK, JH7110_STRAP_HOST);
    146  1.1  skrll 		jh71x0_syscon_update(sc, usb_mode, JH7110_SUSPENDM_MASK, JH7110_SUSPENDM_HOST);
    147  1.1  skrll 		break;
    148  1.1  skrll 
    149  1.1  skrll 	case USB_DR_MODE_PERIPHERAL:
    150  1.1  skrll 		jh71x0_syscon_update(sc, usb_mode, JH7110_STRAP_MASK, JH7110_STRAP_DEVICE);
    151  1.1  skrll 		jh71x0_syscon_update(sc, usb_mode, JH7110_SUSPENDM_MASK, 0);
    152  1.1  skrll 		break;
    153  1.1  skrll 	default:
    154  1.1  skrll 		break;
    155  1.1  skrll 	}
    156  1.1  skrll 
    157  1.1  skrll 	return 0;
    158  1.1  skrll }
    159  1.1  skrll 
    160  1.1  skrll struct jh71x0_usb_config {
    161  1.1  skrll 	int (*jhuc_init)(struct jh71x0_usb_softc *, const u_int *);
    162  1.1  skrll 	const char *jhuc_syscon;
    163  1.1  skrll 	size_t jhuc_sclen;
    164  1.1  skrll };
    165  1.1  skrll 
    166  1.1  skrll struct jh71x0_usb_config jh7100_usb_data = {
    167  1.1  skrll 	.jhuc_init = jh7100_usb_init,
    168  1.1  skrll 	.jhuc_syscon = "starfive,syscon",
    169  1.1  skrll 	.jhuc_sclen = 1 * sizeof(uint32_t),
    170  1.1  skrll };
    171  1.1  skrll 
    172  1.1  skrll struct jh71x0_usb_config jh7110_usb_data = {
    173  1.1  skrll 	.jhuc_init = jh7110_usb_init,
    174  1.1  skrll 	.jhuc_syscon = "starfive,stg-syscon",
    175  1.1  skrll 	.jhuc_sclen = 2 * sizeof(uint32_t),
    176  1.1  skrll };
    177  1.1  skrll 
    178  1.1  skrll /* Compat string(s) */
    179  1.1  skrll static const struct device_compatible_entry compat_data[] = {
    180  1.1  skrll 	{ .compat = "starfive,jh7100-usb", .data = &jh7100_usb_data },
    181  1.1  skrll 	{ .compat = "starfive,jh7110-usb", .data = &jh7110_usb_data },
    182  1.1  skrll 	DEVICE_COMPAT_EOL
    183  1.1  skrll };
    184  1.1  skrll 
    185  1.1  skrll static int
    186  1.1  skrll jh71x0_usb_match(device_t parent, cfdata_t cf, void *aux)
    187  1.1  skrll {
    188  1.1  skrll 	struct fdt_attach_args * const faa = aux;
    189  1.1  skrll 
    190  1.1  skrll 	return of_compatible_match(faa->faa_phandle, compat_data);
    191  1.1  skrll }
    192  1.1  skrll 
    193  1.1  skrll static void
    194  1.1  skrll jh71x0_usb_attach(device_t parent, device_t self, void *aux)
    195  1.1  skrll {
    196  1.1  skrll 	struct jh71x0_usb_softc *sc = device_private(self);
    197  1.1  skrll 	struct fdt_attach_args * const faa = aux;
    198  1.1  skrll 	const int phandle = faa->faa_phandle;
    199  1.1  skrll 
    200  1.1  skrll 	sc->sc_dev = self;
    201  1.1  skrll 	sc->sc_phandle = phandle;
    202  1.1  skrll 	sc->sc_bst = faa->faa_bst;
    203  1.1  skrll 
    204  1.1  skrll 	const struct jh71x0_usb_config *jhuc =
    205  1.1  skrll 	    of_compatible_lookup(sc->sc_phandle, compat_data)->data;
    206  1.1  skrll 
    207  1.1  skrll 	int len;
    208  1.1  skrll 	const u_int *syscon_data =
    209  1.1  skrll 	    fdtbus_get_prop(phandle, jhuc->jhuc_syscon, &len);
    210  1.1  skrll 	if (syscon_data == NULL) {
    211  1.1  skrll 		aprint_error(": couldn't get '%s' property\n",
    212  1.1  skrll 		    jhuc->jhuc_syscon);
    213  1.1  skrll 		return;
    214  1.1  skrll 	}
    215  1.1  skrll 	if (len != jhuc->jhuc_sclen) {
    216  1.1  skrll 		aprint_error(": incorrect syscon data (len = %u)\n",
    217  1.1  skrll 		    len);
    218  1.1  skrll 		return;
    219  1.1  skrll 	}
    220  1.1  skrll 
    221  1.1  skrll 	int syscon_phandle =
    222  1.1  skrll 	    fdtbus_get_phandle_from_native(be32dec(&syscon_data[0]));
    223  1.1  skrll 
    224  1.1  skrll 	sc->sc_syscon = fdtbus_syscon_lookup(syscon_phandle);
    225  1.1  skrll 	if (sc->sc_syscon == NULL) {
    226  1.1  skrll 		aprint_error(": couldn't get syscon\n");
    227  1.1  skrll 		return;
    228  1.1  skrll 	}
    229  1.1  skrll 
    230  1.1  skrll 	jhuc->jhuc_init(sc, syscon_data);
    231  1.1  skrll 
    232  1.1  skrll 	aprint_naive("\n");
    233  1.1  skrll 	aprint_normal(": USB\n");
    234  1.1  skrll 
    235  1.2  skrll 	for (int child = OF_child(phandle); child; child = OF_peer(child)) {
    236  1.2  skrll 		if (!fdtbus_status_okay(child))
    237  1.2  skrll 			continue;
    238  1.1  skrll 		fdt_add_child(parent, child, faa, 0);
    239  1.2  skrll 	}
    240  1.1  skrll 
    241  1.1  skrll 	//fdtbus_register_phy_controller(self, phandle, &XXX_usbphy_funcs);
    242  1.1  skrll 
    243  1.1  skrll }
    244  1.1  skrll 
    245  1.1  skrll 
    246  1.1  skrll CFATTACH_DECL_NEW(jh71x0_usb, sizeof(struct jh71x0_usb_softc),
    247  1.1  skrll 	jh71x0_usb_match, jh71x0_usb_attach, NULL, NULL);
    248