The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/arm64/rockchip/rk_usbphy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD$");
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/bus.h>
   34 #include <sys/gpio.h>
   35 #include <sys/kernel.h>
   36 #include <sys/module.h>
   37 #include <sys/malloc.h>
   38 #include <sys/rman.h>
   39 
   40 #include <machine/bus.h>
   41 
   42 #include <dev/extres/clk/clk.h>
   43 #include <dev/extres/hwreset/hwreset.h>
   44 #include <dev/extres/phy/phy_usb.h>
   45 #include <dev/extres/regulator/regulator.h>
   46 #include <dev/extres/syscon/syscon.h>
   47 #include <dev/ofw/ofw_bus.h>
   48 #include <dev/ofw/ofw_bus_subr.h>
   49 
   50 #include <dev/extres/syscon/syscon.h>
   51 #include <dev/fdt/simple_mfd.h>
   52 #include "phynode_if.h"
   53 #include "phynode_usb_if.h"
   54 #include "syscon_if.h"
   55 
   56 
   57 
   58 /* Phy registers */
   59 #define UOC_CON0                        0x00
   60 #define  UOC_CON0_SIDDQ                         (1 << 13)
   61 #define  UOC_CON0_DISABLE                       (1 <<  4)
   62 #define  UOC_CON0_COMMON_ON_N                   (1 <<  0)
   63 
   64 #define UOC_CON2                        0x08
   65 #define  UOC_CON2_SOFT_CON_SEL                  (1 << 2)
   66 
   67 #define UOC_CON3                        0x0c
   68 
   69 
   70 #define WR4(_sc, _r, _v)        bus_write_4((_sc)->mem_res, (_r), (_v))
   71 #define RD4(_sc, _r)            bus_read_4((_sc)->mem_res, (_r))
   72 
   73 
   74 static struct ofw_compat_data compat_data[] = {
   75         {"rockchip,rk3288-usb-phy",     1},
   76         {NULL,                          0},
   77 };
   78 
   79 struct rk_usbphy_softc {
   80         device_t                dev;
   81 };
   82 
   83 struct rk_phynode_sc {
   84         struct phynode_usb_sc   usb_sc;
   85         uint32_t                base;
   86         int                     mode;
   87         clk_t                   clk;
   88         hwreset_t               hwreset;
   89         regulator_t             supply_vbus;
   90         struct syscon           *syscon;
   91 };
   92 
   93 static int
   94 rk_phynode_phy_enable(struct phynode *phy, bool enable)
   95 {
   96         struct rk_phynode_sc *sc;
   97         int rv;
   98 
   99         sc = phynode_get_softc(phy);
  100 
  101         rv = SYSCON_MODIFY_4(sc->syscon,
  102             sc->base + UOC_CON0,
  103             UOC_CON0_SIDDQ << 16 | UOC_CON0_SIDDQ,
  104             enable ? 0 : UOC_CON0_SIDDQ);
  105 
  106         return (rv);
  107 
  108 }
  109 
  110 static int
  111 rk_phynode_get_mode(struct phynode *phynode, int *mode)
  112 {
  113         struct rk_phynode_sc *sc;
  114 
  115         sc = phynode_get_softc(phynode);
  116         *mode = sc->mode;
  117         return (0);
  118 }
  119 
  120 static int
  121 rk_phynode_set_mode(struct phynode *phynode, int mode)
  122 {
  123         struct rk_phynode_sc *sc;
  124 
  125         sc = phynode_get_softc(phynode);
  126         sc->mode = mode;
  127 
  128         return (0);
  129 }
  130 
  131 
  132  /* Phy controller class and methods. */
  133 static phynode_method_t rk_phynode_methods[] = {
  134         PHYNODEUSBMETHOD(phynode_enable,        rk_phynode_phy_enable),
  135         PHYNODEMETHOD(phynode_usb_get_mode,     rk_phynode_get_mode),
  136         PHYNODEMETHOD(phynode_usb_set_mode,     rk_phynode_set_mode),
  137         PHYNODEUSBMETHOD_END
  138 };
  139 DEFINE_CLASS_1(rk_phynode, rk_phynode_class, rk_phynode_methods,
  140     sizeof(struct rk_phynode_sc), phynode_usb_class);
  141 
  142 static int
  143 rk_usbphy_init_phy(struct rk_usbphy_softc *sc, phandle_t node)
  144 {
  145         struct phynode *phynode;
  146         struct phynode_init_def phy_init;
  147         struct rk_phynode_sc *phy_sc;
  148         int rv;
  149         uint32_t base;
  150         clk_t clk;
  151         hwreset_t hwreset;
  152         regulator_t supply_vbus;
  153         struct syscon *syscon;
  154 
  155         clk = NULL;
  156         hwreset = NULL;
  157         supply_vbus = NULL;
  158 
  159         rv = OF_getencprop(node, "reg", &base, sizeof(base));
  160         if (rv <= 0) {
  161                 device_printf(sc->dev, "cannot get 'reg' property.\n");
  162                 goto fail;
  163         }
  164 
  165         /* FDT resources. All are optional. */
  166         rv = clk_get_by_ofw_name(sc->dev, node, "phyclk", &clk);
  167         if (rv != 0 && rv != ENOENT) {
  168                 device_printf(sc->dev, "cannot get 'phyclk' clock.\n");
  169                 goto fail;
  170         }
  171         rv = hwreset_get_by_ofw_name(sc->dev, node, "phy-reset", &hwreset);
  172         if (rv != 0 && rv != ENOENT) {
  173                 device_printf(sc->dev, "Cannot get 'phy-reset' reset\n");
  174                 goto fail;
  175         }
  176         rv = regulator_get_by_ofw_property(sc->dev, node, "vbus-supply",
  177              &supply_vbus);
  178         if (rv != 0 && rv != ENOENT) {
  179                 device_printf(sc->dev,  "Cannot get 'vbus' regulator.\n");
  180                 goto fail;
  181         }
  182 
  183         rv = SYSCON_GET_HANDLE(sc->dev, &syscon);
  184         if (rv != 0) {
  185                 device_printf(sc->dev, "Cannot get parent syscon\n");
  186                 goto fail;
  187         }
  188 
  189         /* Init HW resources */
  190         if (hwreset != NULL) {
  191                 rv = hwreset_assert(hwreset);
  192                 if (rv != 0) {
  193                         device_printf(sc->dev, "Cannot assert reset\n");
  194                         goto fail;
  195                 }
  196         }
  197         if (clk != NULL) {
  198                 rv = clk_enable(clk);
  199                 if (rv != 0) {
  200                         device_printf(sc->dev,
  201                              "Cannot enable 'phyclk' clock.\n");
  202                         goto fail;
  203                 }
  204         }
  205 
  206         if (hwreset != NULL) {
  207                 rv = hwreset_deassert(hwreset);
  208                 if (rv != 0) {
  209                         device_printf(sc->dev, "Cannot deassert reset\n");
  210                         goto fail;
  211                 }
  212         }
  213 
  214         /* Create and register phy. */
  215         bzero(&phy_init, sizeof(phy_init));
  216         phy_init.id = 1;
  217         phy_init.ofw_node = node;
  218         phynode = phynode_create(sc->dev, &rk_phynode_class, &phy_init);
  219         if (phynode == NULL) {
  220                 device_printf(sc->dev, "Cannot create phy.\n");
  221                 return (ENXIO);
  222         }
  223 
  224         phy_sc = phynode_get_softc(phynode);
  225         phy_sc->base = base;
  226         phy_sc->clk = clk;
  227         phy_sc->hwreset = hwreset;
  228         phy_sc->supply_vbus = supply_vbus;
  229         phy_sc->syscon = syscon;
  230         if (phynode_register(phynode) == NULL) {
  231                 device_printf(sc->dev, "Cannot register phy.\n");
  232                 return (ENXIO);
  233         }
  234         /* XXX It breaks boot */
  235         /* rk_phynode_phy_enable(phynode, 1); */
  236         return (0);
  237 
  238 fail:
  239         if (supply_vbus != NULL)
  240                  regulator_release(supply_vbus);
  241         if (clk != NULL)
  242                  clk_release(clk);
  243         if (hwreset != NULL)
  244                  hwreset_release(hwreset);
  245 
  246         return (ENXIO);
  247 }
  248 
  249 static int
  250 rk_usbphy_probe(device_t dev)
  251 {
  252 
  253         if (!ofw_bus_status_okay(dev))
  254                 return (ENXIO);
  255 
  256         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
  257                 return (ENXIO);
  258 
  259         device_set_desc(dev, "RockChip USB Phy");
  260         return (BUS_PROBE_DEFAULT);
  261 }
  262 
  263 static int
  264 rk_usbphy_attach(device_t dev)
  265 {
  266         struct rk_usbphy_softc *sc;
  267         phandle_t node, child;
  268         int rv;
  269 
  270         sc = device_get_softc(dev);
  271         sc->dev = dev;
  272         node = ofw_bus_get_node(sc->dev);
  273 
  274         /* Attach child devices */
  275         for (child = OF_child(node); child > 0; child = OF_peer(child)) {
  276                 rv = rk_usbphy_init_phy(sc, child);
  277                 if (rv != 0)
  278                         goto fail;
  279         }
  280         return (bus_generic_attach(dev));
  281 
  282 fail:
  283         return (ENXIO);
  284 }
  285 
  286 static int
  287 rk_usbphy_detach(device_t dev)
  288 {
  289         return (0);
  290 }
  291 
  292 static device_method_t rk_usbphy_methods[] = {
  293         /* Device interface */
  294         DEVMETHOD(device_probe,                 rk_usbphy_probe),
  295         DEVMETHOD(device_attach,                rk_usbphy_attach),
  296         DEVMETHOD(device_detach,                rk_usbphy_detach),
  297         DEVMETHOD_END
  298 };
  299 
  300 static DEFINE_CLASS_0(rk_usbphy, rk_usbphy_driver, rk_usbphy_methods,
  301     sizeof(struct rk_usbphy_softc));
  302 EARLY_DRIVER_MODULE(rk_usbphy, simplebus, rk_usbphy_driver, NULL, NULL,
  303     BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);

Cache object: 33b6182a2209800b11acdc229834608a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.