1c3e25952SEmmanuel Vadot /*- 2c3e25952SEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3c3e25952SEmmanuel Vadot * 4c3e25952SEmmanuel Vadot * Copyright (c) 2019 Emmanuel Vadot <manu@FreeBSD.Org> 5c3e25952SEmmanuel Vadot * 6c3e25952SEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 7c3e25952SEmmanuel Vadot * modification, are permitted provided that the following conditions 8c3e25952SEmmanuel Vadot * are met: 9c3e25952SEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 10c3e25952SEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 11c3e25952SEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 12c3e25952SEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 13c3e25952SEmmanuel Vadot * documentation and/or other materials provided with the distribution. 14c3e25952SEmmanuel Vadot * 15c3e25952SEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16c3e25952SEmmanuel Vadot * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17c3e25952SEmmanuel Vadot * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18c3e25952SEmmanuel Vadot * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19c3e25952SEmmanuel Vadot * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20c3e25952SEmmanuel Vadot * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21c3e25952SEmmanuel Vadot * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22c3e25952SEmmanuel Vadot * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23c3e25952SEmmanuel Vadot * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24c3e25952SEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25c3e25952SEmmanuel Vadot * SUCH DAMAGE. 26c3e25952SEmmanuel Vadot */ 27c3e25952SEmmanuel Vadot 28c3e25952SEmmanuel Vadot /* 29c3e25952SEmmanuel Vadot * Rockchip USB2PHY 30c3e25952SEmmanuel Vadot */ 31c3e25952SEmmanuel Vadot 32c3e25952SEmmanuel Vadot #include <sys/cdefs.h> 33c3e25952SEmmanuel Vadot __FBSDID("$FreeBSD$"); 34c3e25952SEmmanuel Vadot 35c3e25952SEmmanuel Vadot #include <sys/param.h> 36c3e25952SEmmanuel Vadot #include <sys/systm.h> 37c3e25952SEmmanuel Vadot #include <sys/bus.h> 38c3e25952SEmmanuel Vadot #include <sys/rman.h> 39c3e25952SEmmanuel Vadot #include <sys/kernel.h> 40c3e25952SEmmanuel Vadot #include <sys/module.h> 41c3e25952SEmmanuel Vadot #include <sys/gpio.h> 42c3e25952SEmmanuel Vadot #include <machine/bus.h> 43c3e25952SEmmanuel Vadot 44c3e25952SEmmanuel Vadot #include <dev/fdt/fdt_common.h> 45c3e25952SEmmanuel Vadot #include <dev/ofw/ofw_bus.h> 46c3e25952SEmmanuel Vadot #include <dev/ofw/ofw_bus_subr.h> 47c3e25952SEmmanuel Vadot #include <dev/ofw/ofw_subr.h> 48c3e25952SEmmanuel Vadot 49c3e25952SEmmanuel Vadot #include <dev/extres/clk/clk.h> 50c3e25952SEmmanuel Vadot #include <dev/extres/phy/phy_usb.h> 51c3e25952SEmmanuel Vadot #include <dev/extres/regulator/regulator.h> 52c3e25952SEmmanuel Vadot #include <dev/extres/syscon/syscon.h> 53c3e25952SEmmanuel Vadot 54c3e25952SEmmanuel Vadot #include "clkdev_if.h" 55c3e25952SEmmanuel Vadot #include "syscon_if.h" 56c3e25952SEmmanuel Vadot 57c3e25952SEmmanuel Vadot struct rk_usb2phy_reg { 58c3e25952SEmmanuel Vadot uint32_t offset; 59c3e25952SEmmanuel Vadot uint32_t enable_mask; 60c3e25952SEmmanuel Vadot uint32_t disable_mask; 61c3e25952SEmmanuel Vadot }; 62c3e25952SEmmanuel Vadot 63c3e25952SEmmanuel Vadot struct rk_usb2phy_regs { 64c3e25952SEmmanuel Vadot struct rk_usb2phy_reg clk_ctl; 65c3e25952SEmmanuel Vadot }; 66c3e25952SEmmanuel Vadot 67c3e25952SEmmanuel Vadot struct rk_usb2phy_regs rk3399_regs = { 68c3e25952SEmmanuel Vadot .clk_ctl = { 69*79c6e0b3SSøren Schmidt .offset = 0x0000, 70c3e25952SEmmanuel Vadot /* bit 4 put pll in suspend */ 71c3e25952SEmmanuel Vadot .enable_mask = 0x100000, 72c3e25952SEmmanuel Vadot .disable_mask = 0x100010, 73c3e25952SEmmanuel Vadot } 74c3e25952SEmmanuel Vadot }; 75c3e25952SEmmanuel Vadot 76*79c6e0b3SSøren Schmidt struct rk_usb2phy_regs rk3568_regs = { 77*79c6e0b3SSøren Schmidt .clk_ctl = { 78*79c6e0b3SSøren Schmidt .offset = 0x0008, 79*79c6e0b3SSøren Schmidt .enable_mask = 0x100000, 80*79c6e0b3SSøren Schmidt /* bit 4 put pll in suspend */ 81*79c6e0b3SSøren Schmidt .disable_mask = 0x100010, 82*79c6e0b3SSøren Schmidt } 83*79c6e0b3SSøren Schmidt }; 84*79c6e0b3SSøren Schmidt 85c3e25952SEmmanuel Vadot static struct ofw_compat_data compat_data[] = { 86c3e25952SEmmanuel Vadot { "rockchip,rk3399-usb2phy", (uintptr_t)&rk3399_regs }, 87*79c6e0b3SSøren Schmidt { "rockchip,rk3568-usb2phy", (uintptr_t)&rk3568_regs }, 88c3e25952SEmmanuel Vadot { NULL, 0 } 89c3e25952SEmmanuel Vadot }; 90c3e25952SEmmanuel Vadot 91c3e25952SEmmanuel Vadot struct rk_usb2phy_softc { 92c3e25952SEmmanuel Vadot device_t dev; 93c3e25952SEmmanuel Vadot struct syscon *grf; 94c3e25952SEmmanuel Vadot regulator_t phy_supply; 95c3e25952SEmmanuel Vadot clk_t clk; 96c36e2d14SEmmanuel Vadot int mode; 97c3e25952SEmmanuel Vadot }; 98c3e25952SEmmanuel Vadot 99c3e25952SEmmanuel Vadot /* Phy class and methods. */ 100c3e25952SEmmanuel Vadot static int rk_usb2phy_enable(struct phynode *phynode, bool enable); 101c36e2d14SEmmanuel Vadot static int rk_usb2phy_get_mode(struct phynode *phy, int *mode); 102c36e2d14SEmmanuel Vadot static int rk_usb2phy_set_mode(struct phynode *phy, int mode); 103c3e25952SEmmanuel Vadot static phynode_method_t rk_usb2phy_phynode_methods[] = { 104c3e25952SEmmanuel Vadot PHYNODEMETHOD(phynode_enable, rk_usb2phy_enable), 105c36e2d14SEmmanuel Vadot PHYNODEMETHOD(phynode_usb_get_mode, rk_usb2phy_get_mode), 106c36e2d14SEmmanuel Vadot PHYNODEMETHOD(phynode_usb_set_mode, rk_usb2phy_set_mode), 107c3e25952SEmmanuel Vadot 108c3e25952SEmmanuel Vadot PHYNODEMETHOD_END 109c3e25952SEmmanuel Vadot }; 110c3e25952SEmmanuel Vadot 111c3e25952SEmmanuel Vadot DEFINE_CLASS_1(rk_usb2phy_phynode, rk_usb2phy_phynode_class, 112c3e25952SEmmanuel Vadot rk_usb2phy_phynode_methods, 113c3e25952SEmmanuel Vadot sizeof(struct phynode_usb_sc), phynode_usb_class); 114c3e25952SEmmanuel Vadot 115*79c6e0b3SSøren Schmidt enum RK_USBPHY { 116*79c6e0b3SSøren Schmidt RK_USBPHY_HOST = 0, 117*79c6e0b3SSøren Schmidt RK_USBPHY_OTG, 118c3e25952SEmmanuel Vadot }; 119c3e25952SEmmanuel Vadot 120c3e25952SEmmanuel Vadot static int 121c3e25952SEmmanuel Vadot rk_usb2phy_enable(struct phynode *phynode, bool enable) 122c3e25952SEmmanuel Vadot { 123c3e25952SEmmanuel Vadot struct rk_usb2phy_softc *sc; 124c3e25952SEmmanuel Vadot device_t dev; 125c3e25952SEmmanuel Vadot intptr_t phy; 126c3e25952SEmmanuel Vadot int error; 127c3e25952SEmmanuel Vadot 128c3e25952SEmmanuel Vadot dev = phynode_get_device(phynode); 129c3e25952SEmmanuel Vadot phy = phynode_get_id(phynode); 130c3e25952SEmmanuel Vadot sc = device_get_softc(dev); 131c3e25952SEmmanuel Vadot 132*79c6e0b3SSøren Schmidt if (phy != RK_USBPHY_HOST) 133c3e25952SEmmanuel Vadot return (ERANGE); 134c3e25952SEmmanuel Vadot 135c3e25952SEmmanuel Vadot if (sc->phy_supply) { 136c3e25952SEmmanuel Vadot if (enable) 137c3e25952SEmmanuel Vadot error = regulator_enable(sc->phy_supply); 138c3e25952SEmmanuel Vadot else 139c3e25952SEmmanuel Vadot error = regulator_disable(sc->phy_supply); 140c3e25952SEmmanuel Vadot if (error != 0) { 141c3e25952SEmmanuel Vadot device_printf(dev, "Cannot %sable the regulator\n", 142c3e25952SEmmanuel Vadot enable ? "En" : "Dis"); 143c3e25952SEmmanuel Vadot goto fail; 144c3e25952SEmmanuel Vadot } 145c3e25952SEmmanuel Vadot } 146c3e25952SEmmanuel Vadot 147c3e25952SEmmanuel Vadot return (0); 148c3e25952SEmmanuel Vadot fail: 149c3e25952SEmmanuel Vadot return (ENXIO); 150c3e25952SEmmanuel Vadot } 151c3e25952SEmmanuel Vadot 152c36e2d14SEmmanuel Vadot static int 153c36e2d14SEmmanuel Vadot rk_usb2phy_get_mode(struct phynode *phynode, int *mode) 154c36e2d14SEmmanuel Vadot { 155c36e2d14SEmmanuel Vadot struct rk_usb2phy_softc *sc; 156c36e2d14SEmmanuel Vadot intptr_t phy; 157c36e2d14SEmmanuel Vadot device_t dev; 158c36e2d14SEmmanuel Vadot 159c36e2d14SEmmanuel Vadot dev = phynode_get_device(phynode); 160c36e2d14SEmmanuel Vadot phy = phynode_get_id(phynode); 161c36e2d14SEmmanuel Vadot sc = device_get_softc(dev); 162c36e2d14SEmmanuel Vadot 163*79c6e0b3SSøren Schmidt if (phy != RK_USBPHY_HOST) 164c36e2d14SEmmanuel Vadot return (ERANGE); 165c36e2d14SEmmanuel Vadot 166c36e2d14SEmmanuel Vadot *mode = sc->mode; 167c36e2d14SEmmanuel Vadot 168c36e2d14SEmmanuel Vadot return (0); 169c36e2d14SEmmanuel Vadot } 170c36e2d14SEmmanuel Vadot 171c36e2d14SEmmanuel Vadot static int 172c36e2d14SEmmanuel Vadot rk_usb2phy_set_mode(struct phynode *phynode, int mode) 173c36e2d14SEmmanuel Vadot { 174c36e2d14SEmmanuel Vadot struct rk_usb2phy_softc *sc; 175c36e2d14SEmmanuel Vadot intptr_t phy; 176c36e2d14SEmmanuel Vadot device_t dev; 177c36e2d14SEmmanuel Vadot 178c36e2d14SEmmanuel Vadot dev = phynode_get_device(phynode); 179c36e2d14SEmmanuel Vadot phy = phynode_get_id(phynode); 180c36e2d14SEmmanuel Vadot sc = device_get_softc(dev); 181c36e2d14SEmmanuel Vadot 182*79c6e0b3SSøren Schmidt if (phy != RK_USBPHY_HOST) 183c36e2d14SEmmanuel Vadot return (ERANGE); 184c36e2d14SEmmanuel Vadot 185c36e2d14SEmmanuel Vadot sc->mode = mode; 186c36e2d14SEmmanuel Vadot 187c36e2d14SEmmanuel Vadot return (0); 188c36e2d14SEmmanuel Vadot } 189c36e2d14SEmmanuel Vadot 190c3e25952SEmmanuel Vadot /* Clock class and method */ 191c3e25952SEmmanuel Vadot struct rk_usb2phy_clk_sc { 192c3e25952SEmmanuel Vadot device_t clkdev; 193c3e25952SEmmanuel Vadot struct syscon *grf; 194c3e25952SEmmanuel Vadot struct rk_usb2phy_regs *regs; 195c3e25952SEmmanuel Vadot }; 196c3e25952SEmmanuel Vadot 197c3e25952SEmmanuel Vadot static int 198c3e25952SEmmanuel Vadot rk_usb2phy_clk_init(struct clknode *clk, device_t dev) 199c3e25952SEmmanuel Vadot { 200c3e25952SEmmanuel Vadot 201c3e25952SEmmanuel Vadot clknode_init_parent_idx(clk, 0); 202c3e25952SEmmanuel Vadot return (0); 203c3e25952SEmmanuel Vadot } 204c3e25952SEmmanuel Vadot 205c3e25952SEmmanuel Vadot static int 206c3e25952SEmmanuel Vadot rk_usb2phy_clk_set_gate(struct clknode *clk, bool enable) 207c3e25952SEmmanuel Vadot { 208c3e25952SEmmanuel Vadot struct rk_usb2phy_clk_sc *sc; 209c3e25952SEmmanuel Vadot 210c3e25952SEmmanuel Vadot sc = clknode_get_softc(clk); 211c3e25952SEmmanuel Vadot 212c3e25952SEmmanuel Vadot if (enable) 213c3e25952SEmmanuel Vadot SYSCON_WRITE_4(sc->grf, sc->regs->clk_ctl.offset, 214c3e25952SEmmanuel Vadot sc->regs->clk_ctl.enable_mask); 215c3e25952SEmmanuel Vadot else 216c3e25952SEmmanuel Vadot SYSCON_WRITE_4(sc->grf, sc->regs->clk_ctl.offset, 217c3e25952SEmmanuel Vadot sc->regs->clk_ctl.disable_mask); 218c3e25952SEmmanuel Vadot return (0); 219c3e25952SEmmanuel Vadot } 220c3e25952SEmmanuel Vadot 221c3e25952SEmmanuel Vadot static int 222c3e25952SEmmanuel Vadot rk_usb2phy_clk_recalc(struct clknode *clk, uint64_t *freq) 223c3e25952SEmmanuel Vadot { 224c3e25952SEmmanuel Vadot 225c3e25952SEmmanuel Vadot *freq = 480000000; 226c3e25952SEmmanuel Vadot 227c3e25952SEmmanuel Vadot return (0); 228c3e25952SEmmanuel Vadot } 229c3e25952SEmmanuel Vadot 230c3e25952SEmmanuel Vadot static clknode_method_t rk_usb2phy_clk_clknode_methods[] = { 231c3e25952SEmmanuel Vadot /* Device interface */ 232c3e25952SEmmanuel Vadot 233c3e25952SEmmanuel Vadot CLKNODEMETHOD(clknode_init, rk_usb2phy_clk_init), 234c3e25952SEmmanuel Vadot CLKNODEMETHOD(clknode_set_gate, rk_usb2phy_clk_set_gate), 235c3e25952SEmmanuel Vadot CLKNODEMETHOD(clknode_recalc_freq, rk_usb2phy_clk_recalc), 236c3e25952SEmmanuel Vadot CLKNODEMETHOD_END 237c3e25952SEmmanuel Vadot }; 238c3e25952SEmmanuel Vadot 239c3e25952SEmmanuel Vadot DEFINE_CLASS_1(rk_usb2phy_clk_clknode, rk_usb2phy_clk_clknode_class, 240c3e25952SEmmanuel Vadot rk_usb2phy_clk_clknode_methods, sizeof(struct rk_usb2phy_clk_sc), 241c3e25952SEmmanuel Vadot clknode_class); 242c3e25952SEmmanuel Vadot 243c3e25952SEmmanuel Vadot static int 244c3e25952SEmmanuel Vadot rk_usb2phy_clk_ofw_map(struct clkdom *clkdom, uint32_t ncells, 245c3e25952SEmmanuel Vadot phandle_t *cells, struct clknode **clk) 246c3e25952SEmmanuel Vadot { 247c3e25952SEmmanuel Vadot 248c3e25952SEmmanuel Vadot if (ncells != 0) 249c3e25952SEmmanuel Vadot return (ERANGE); 250c3e25952SEmmanuel Vadot 251c3e25952SEmmanuel Vadot *clk = clknode_find_by_id(clkdom, 0); 252c3e25952SEmmanuel Vadot 253c3e25952SEmmanuel Vadot if (*clk == NULL) 254c3e25952SEmmanuel Vadot return (ENXIO); 255c3e25952SEmmanuel Vadot return (0); 256c3e25952SEmmanuel Vadot } 257c3e25952SEmmanuel Vadot 258c3e25952SEmmanuel Vadot static int 259c3e25952SEmmanuel Vadot rk_usb2phy_export_clock(struct rk_usb2phy_softc *devsc) 260c3e25952SEmmanuel Vadot { 261c3e25952SEmmanuel Vadot struct clknode_init_def def; 262c3e25952SEmmanuel Vadot struct rk_usb2phy_clk_sc *sc; 263c3e25952SEmmanuel Vadot const char **clknames; 264c3e25952SEmmanuel Vadot struct clkdom *clkdom; 265c3e25952SEmmanuel Vadot struct clknode *clk; 266c3e25952SEmmanuel Vadot clk_t clk_parent; 267c3e25952SEmmanuel Vadot phandle_t node; 268c3e25952SEmmanuel Vadot phandle_t regs[2]; 269c3e25952SEmmanuel Vadot int i, nclocks, ncells, error; 270c3e25952SEmmanuel Vadot 271c3e25952SEmmanuel Vadot node = ofw_bus_get_node(devsc->dev); 272c3e25952SEmmanuel Vadot 273c3e25952SEmmanuel Vadot error = ofw_bus_parse_xref_list_get_length(node, "clocks", 274c3e25952SEmmanuel Vadot "#clock-cells", &ncells); 275c3e25952SEmmanuel Vadot if (error != 0 || ncells != 1) { 276c3e25952SEmmanuel Vadot device_printf(devsc->dev, "couldn't find parent clock\n"); 277c3e25952SEmmanuel Vadot return (ENXIO); 278c3e25952SEmmanuel Vadot } 279c3e25952SEmmanuel Vadot 280c3e25952SEmmanuel Vadot nclocks = ofw_bus_string_list_to_array(node, "clock-output-names", 281c3e25952SEmmanuel Vadot &clknames); 282c3e25952SEmmanuel Vadot if (nclocks != 1) 283c3e25952SEmmanuel Vadot return (ENXIO); 284c3e25952SEmmanuel Vadot 285c3e25952SEmmanuel Vadot clkdom = clkdom_create(devsc->dev); 286c3e25952SEmmanuel Vadot clkdom_set_ofw_mapper(clkdom, rk_usb2phy_clk_ofw_map); 287c3e25952SEmmanuel Vadot 288c3e25952SEmmanuel Vadot memset(&def, 0, sizeof(def)); 289c3e25952SEmmanuel Vadot def.id = 0; 290c3e25952SEmmanuel Vadot def.name = clknames[0]; 291c3e25952SEmmanuel Vadot def.parent_names = malloc(sizeof(char *) * ncells, M_OFWPROP, M_WAITOK); 292c3e25952SEmmanuel Vadot for (i = 0; i < ncells; i++) { 293c3e25952SEmmanuel Vadot error = clk_get_by_ofw_index(devsc->dev, 0, i, &clk_parent); 294c3e25952SEmmanuel Vadot if (error != 0) { 295c3e25952SEmmanuel Vadot device_printf(devsc->dev, "cannot get clock %d\n", error); 296c3e25952SEmmanuel Vadot return (ENXIO); 297c3e25952SEmmanuel Vadot } 298c3e25952SEmmanuel Vadot def.parent_names[i] = clk_get_name(clk_parent); 299c3e25952SEmmanuel Vadot clk_release(clk_parent); 300c3e25952SEmmanuel Vadot } 301c3e25952SEmmanuel Vadot def.parent_cnt = ncells; 302c3e25952SEmmanuel Vadot 303c3e25952SEmmanuel Vadot clk = clknode_create(clkdom, &rk_usb2phy_clk_clknode_class, &def); 304c3e25952SEmmanuel Vadot if (clk == NULL) { 305c3e25952SEmmanuel Vadot device_printf(devsc->dev, "cannot create clknode\n"); 306c3e25952SEmmanuel Vadot return (ENXIO); 307c3e25952SEmmanuel Vadot } 308c3e25952SEmmanuel Vadot 309c3e25952SEmmanuel Vadot sc = clknode_get_softc(clk); 310c3e25952SEmmanuel Vadot sc->clkdev = device_get_parent(devsc->dev); 311c3e25952SEmmanuel Vadot sc->grf = devsc->grf; 312c3e25952SEmmanuel Vadot sc->regs = (struct rk_usb2phy_regs *)ofw_bus_search_compatible(devsc->dev, compat_data)->ocd_data; 313*79c6e0b3SSøren Schmidt if (sc->regs->clk_ctl.offset == 0) { 314c3e25952SEmmanuel Vadot OF_getencprop(node, "reg", regs, sizeof(regs)); 315c3e25952SEmmanuel Vadot sc->regs->clk_ctl.offset = regs[0]; 316*79c6e0b3SSøren Schmidt } 317c3e25952SEmmanuel Vadot clknode_register(clkdom, clk); 318c3e25952SEmmanuel Vadot 319c3e25952SEmmanuel Vadot if (clkdom_finit(clkdom) != 0) { 320c3e25952SEmmanuel Vadot device_printf(devsc->dev, "cannot finalize clkdom initialization\n"); 321c3e25952SEmmanuel Vadot return (ENXIO); 322c3e25952SEmmanuel Vadot } 323c3e25952SEmmanuel Vadot 324c3e25952SEmmanuel Vadot if (bootverbose) 325c3e25952SEmmanuel Vadot clkdom_dump(clkdom); 326c3e25952SEmmanuel Vadot 327c3e25952SEmmanuel Vadot return (0); 328c3e25952SEmmanuel Vadot } 329c3e25952SEmmanuel Vadot 330c3e25952SEmmanuel Vadot static int 331c3e25952SEmmanuel Vadot rk_usb2phy_probe(device_t dev) 332c3e25952SEmmanuel Vadot { 333c3e25952SEmmanuel Vadot 334c3e25952SEmmanuel Vadot if (!ofw_bus_status_okay(dev)) 335c3e25952SEmmanuel Vadot return (ENXIO); 336c3e25952SEmmanuel Vadot 337c3e25952SEmmanuel Vadot if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 338c3e25952SEmmanuel Vadot return (ENXIO); 339c3e25952SEmmanuel Vadot 340*79c6e0b3SSøren Schmidt device_set_desc(dev, "Rockchip USB2PHY"); 341c3e25952SEmmanuel Vadot return (BUS_PROBE_DEFAULT); 342c3e25952SEmmanuel Vadot } 343c3e25952SEmmanuel Vadot 344c3e25952SEmmanuel Vadot static int 345c3e25952SEmmanuel Vadot rk_usb2phy_attach(device_t dev) 346c3e25952SEmmanuel Vadot { 347c3e25952SEmmanuel Vadot struct rk_usb2phy_softc *sc; 348c3e25952SEmmanuel Vadot struct phynode_init_def phy_init; 349c3e25952SEmmanuel Vadot struct phynode *phynode; 350c3e25952SEmmanuel Vadot phandle_t node, host; 351c3e25952SEmmanuel Vadot int err; 352c3e25952SEmmanuel Vadot 353c3e25952SEmmanuel Vadot sc = device_get_softc(dev); 354c3e25952SEmmanuel Vadot sc->dev = dev; 355c3e25952SEmmanuel Vadot node = ofw_bus_get_node(dev); 356c3e25952SEmmanuel Vadot 357*79c6e0b3SSøren Schmidt if (OF_hasprop(node, "rockchip,usbgrf")) { 358*79c6e0b3SSøren Schmidt if (syscon_get_by_ofw_property(dev, node, "rockchip,usbgrf", 359*79c6e0b3SSøren Schmidt &sc->grf)) { 360c3e25952SEmmanuel Vadot device_printf(dev, "Cannot get syscon handle\n"); 361c3e25952SEmmanuel Vadot return (ENXIO); 362c3e25952SEmmanuel Vadot } 363*79c6e0b3SSøren Schmidt } 364*79c6e0b3SSøren Schmidt else { 365*79c6e0b3SSøren Schmidt if (syscon_get_handle_default(dev, &sc->grf)) { 366*79c6e0b3SSøren Schmidt device_printf(dev, "Cannot get syscon handle\n"); 367*79c6e0b3SSøren Schmidt return (ENXIO); 368*79c6e0b3SSøren Schmidt } 369*79c6e0b3SSøren Schmidt } 370c3e25952SEmmanuel Vadot 371c3e25952SEmmanuel Vadot if (clk_get_by_ofw_name(dev, 0, "phyclk", &sc->clk) != 0) { 372c3e25952SEmmanuel Vadot device_printf(dev, "Cannot get clock\n"); 373c3e25952SEmmanuel Vadot return (ENXIO); 374c3e25952SEmmanuel Vadot } 375c3e25952SEmmanuel Vadot err = clk_enable(sc->clk); 376c3e25952SEmmanuel Vadot if (err != 0) { 377c3e25952SEmmanuel Vadot device_printf(dev, "Could not enable clock %s\n", 378c3e25952SEmmanuel Vadot clk_get_name(sc->clk)); 379c3e25952SEmmanuel Vadot return (ENXIO); 380c3e25952SEmmanuel Vadot } 381c3e25952SEmmanuel Vadot 382c3e25952SEmmanuel Vadot err = rk_usb2phy_export_clock(sc); 383c3e25952SEmmanuel Vadot if (err != 0) 384c3e25952SEmmanuel Vadot return (err); 385c3e25952SEmmanuel Vadot 386c3e25952SEmmanuel Vadot /* Only host is supported right now */ 387c3e25952SEmmanuel Vadot 388c3e25952SEmmanuel Vadot host = ofw_bus_find_child(node, "host-port"); 389c3e25952SEmmanuel Vadot if (host == 0) { 390c3e25952SEmmanuel Vadot device_printf(dev, "Cannot find host-port child node\n"); 391c3e25952SEmmanuel Vadot return (ENXIO); 392c3e25952SEmmanuel Vadot } 393c3e25952SEmmanuel Vadot 394c3e25952SEmmanuel Vadot if (!ofw_bus_node_status_okay(host)) { 395c3e25952SEmmanuel Vadot device_printf(dev, "host-port isn't okay\n"); 396c3e25952SEmmanuel Vadot return (0); 397c3e25952SEmmanuel Vadot } 398c3e25952SEmmanuel Vadot 399c3e25952SEmmanuel Vadot regulator_get_by_ofw_property(dev, host, "phy-supply", &sc->phy_supply); 400*79c6e0b3SSøren Schmidt phy_init.id = RK_USBPHY_HOST; 401c3e25952SEmmanuel Vadot phy_init.ofw_node = host; 402c3e25952SEmmanuel Vadot phynode = phynode_create(dev, &rk_usb2phy_phynode_class, &phy_init); 403c3e25952SEmmanuel Vadot if (phynode == NULL) { 404c3e25952SEmmanuel Vadot device_printf(dev, "failed to create host USB2PHY\n"); 405c3e25952SEmmanuel Vadot return (ENXIO); 406c3e25952SEmmanuel Vadot } 407c3e25952SEmmanuel Vadot if (phynode_register(phynode) == NULL) { 408c3e25952SEmmanuel Vadot device_printf(dev, "failed to register host USB2PHY\n"); 409c3e25952SEmmanuel Vadot return (ENXIO); 410c3e25952SEmmanuel Vadot } 411c3e25952SEmmanuel Vadot 412c3e25952SEmmanuel Vadot OF_device_register_xref(OF_xref_from_node(host), dev); 413c3e25952SEmmanuel Vadot 414c3e25952SEmmanuel Vadot return (0); 415c3e25952SEmmanuel Vadot } 416c3e25952SEmmanuel Vadot 417c3e25952SEmmanuel Vadot static device_method_t rk_usb2phy_methods[] = { 418c3e25952SEmmanuel Vadot /* Device interface */ 419c3e25952SEmmanuel Vadot DEVMETHOD(device_probe, rk_usb2phy_probe), 420c3e25952SEmmanuel Vadot DEVMETHOD(device_attach, rk_usb2phy_attach), 421c3e25952SEmmanuel Vadot 422c3e25952SEmmanuel Vadot DEVMETHOD_END 423c3e25952SEmmanuel Vadot }; 424c3e25952SEmmanuel Vadot 425c3e25952SEmmanuel Vadot static driver_t rk_usb2phy_driver = { 426c3e25952SEmmanuel Vadot "rk_usb2phy", 427c3e25952SEmmanuel Vadot rk_usb2phy_methods, 428c3e25952SEmmanuel Vadot sizeof(struct rk_usb2phy_softc) 429c3e25952SEmmanuel Vadot }; 430c3e25952SEmmanuel Vadot 431b2c1681aSJohn Baldwin EARLY_DRIVER_MODULE(rk_usb2phy, simplebus, rk_usb2phy_driver, 0, 0, 432b2c1681aSJohn Baldwin BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_MIDDLE); 433c3e25952SEmmanuel Vadot MODULE_VERSION(rk_usb2phy, 1); 434