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/clk/rk3568_pmucru.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
    3  *
    4  * Copyright (c) 2021, 2022 Soren Schmidt <sos@deepcore.dk>
    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 ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * 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/param.h>
   29 #include <sys/systm.h>
   30 #include <sys/bus.h>
   31 #include <sys/rman.h>
   32 #include <sys/kernel.h>
   33 #include <sys/module.h>
   34 #include <machine/bus.h>
   35 
   36 #include <dev/fdt/simplebus.h>
   37 
   38 #include <dev/ofw/ofw_bus.h>
   39 #include <dev/ofw/ofw_bus_subr.h>
   40 
   41 #include <dev/extres/clk/clk_div.h>
   42 #include <dev/extres/clk/clk_fixed.h>
   43 #include <dev/extres/clk/clk_mux.h>
   44 
   45 #include <arm64/rockchip/clk/rk_cru.h>
   46 #include <contrib/device-tree/include/dt-bindings/clock/rk3568-cru.h>
   47 
   48 
   49 #define RK3568_PLLSEL_CON(x)            ((x) * 0x20)
   50 #define RK3568_CLKSEL_CON(x)            ((x) * 0x4 + 0x100)
   51 #define RK3568_CLKGATE_CON(x)           ((x) * 0x4 + 0x180)
   52 #define RK3568_SOFTRST_CON(x)           ((x) * 0x4 + 0x200)
   53 
   54 #define PNAME(_name)    static const char *_name[]
   55 
   56 /* PLL clock */
   57 #define RK_PLL(_id, _name, _pnames, _off, _shift)                       \
   58 {                                                                       \
   59         .type = RK3328_CLK_PLL,                                         \
   60         .clk.pll = &(struct rk_clk_pll_def) {                           \
   61                 .clkdef.id = _id,                                       \
   62                 .clkdef.name = _name,                                   \
   63                 .clkdef.parent_names = _pnames,                         \
   64                 .clkdef.parent_cnt = nitems(_pnames),                   \
   65                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
   66                 .base_offset = RK3568_PLLSEL_CON(_off),                 \
   67                 .mode_reg = 0x80,                                       \
   68                 .mode_shift = _shift,                                   \
   69                 .rates = rk3568_pll_rates,                              \
   70         },                                                              \
   71 }
   72 
   73 /* Composite */
   74 #define RK_COMPOSITE(_id, _name, _pnames, _o, _ms, _mw, _ds, _dw, _go, _gw, _f)\
   75 {                                                                       \
   76         .type = RK_CLK_COMPOSITE,                                       \
   77         .clk.composite = &(struct rk_clk_composite_def) {               \
   78                 .clkdef.id = _id,                                       \
   79                 .clkdef.name = _name,                                   \
   80                 .clkdef.parent_names = _pnames,                         \
   81                 .clkdef.parent_cnt = nitems(_pnames),                   \
   82                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
   83                 .muxdiv_offset = RK3568_CLKSEL_CON(_o),                 \
   84                 .mux_shift = _ms,                                       \
   85                 .mux_width = _mw,                                       \
   86                 .div_shift = _ds,                                       \
   87                 .div_width = _dw,                                       \
   88                 .gate_offset = RK3568_CLKGATE_CON(_go),                 \
   89                 .gate_shift = _gw,                                      \
   90                 .flags = RK_CLK_COMPOSITE_HAVE_MUX |                    \
   91                          RK_CLK_COMPOSITE_HAVE_GATE | _f,               \
   92         },                                                              \
   93 }
   94 
   95 /* Composite no mux */
   96 #define RK_COMPNOMUX(_id, _name, _pname, _o, _ds, _dw, _go, _gw, _f)    \
   97 {                                                                       \
   98         .type = RK_CLK_COMPOSITE,                                       \
   99         .clk.composite = &(struct rk_clk_composite_def) {               \
  100                 .clkdef.id = _id,                                       \
  101                 .clkdef.name = _name,                                   \
  102                 .clkdef.parent_names = (const char *[]){_pname},        \
  103                 .clkdef.parent_cnt = 1,                                 \
  104                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
  105                 .muxdiv_offset = RK3568_CLKSEL_CON(_o),                 \
  106                 .div_shift = _ds,                                       \
  107                 .div_width = _dw,                                       \
  108                 .gate_offset = RK3568_CLKGATE_CON(_go),                 \
  109                 .gate_shift = _gw,                                      \
  110                 .flags = RK_CLK_COMPOSITE_HAVE_GATE | _f,               \
  111                 },                                                      \
  112 }
  113 
  114 /* Fixed factor mux/div */
  115 #define RK_FACTOR(_id, _name, _pname, _mult, _div)                      \
  116 {                                                                       \
  117         .type = RK_CLK_FIXED,                                           \
  118         .clk.fixed = &(struct clk_fixed_def) {                          \
  119                 .clkdef.id = _id,                                       \
  120                 .clkdef.name = _name,                                   \
  121                 .clkdef.parent_names = (const char *[]){_pname},        \
  122                 .clkdef.parent_cnt = 1,                                 \
  123                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
  124                 .mult = _mult,                                          \
  125                 .div = _div,                                            \
  126         },                                                              \
  127 }
  128 
  129 /* Fractional */
  130 #define RK_FRACTION(_id, _name, _pname, _o, _go, _gw, _f)               \
  131 {                                                                       \
  132         .type = RK_CLK_FRACT,                                           \
  133         .clk.fract = &(struct rk_clk_fract_def) {                       \
  134                 .clkdef.id = _id,                                       \
  135                 .clkdef.name = _name,                                   \
  136                 .clkdef.parent_names = (const char *[]){_pname},        \
  137                 .clkdef.parent_cnt = 1,                                 \
  138                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
  139                 .offset = RK3568_CLKSEL_CON(_o),                        \
  140                 .gate_offset = RK3568_CLKGATE_CON(_go),                 \
  141                 .gate_shift = _gw,                                      \
  142                 .flags = RK_CLK_FRACT_HAVE_GATE | _f,                   \
  143         },                                                              \
  144 }
  145 
  146 /* Multiplexer */
  147 #define RK_MUX(_id, _name, _pnames, _o, _ms, _mw, _f)                   \
  148 {                                                                       \
  149         .type = RK_CLK_MUX,                                             \
  150         .clk.mux = &(struct rk_clk_mux_def) {                           \
  151                 .clkdef.id = _id,                                       \
  152                 .clkdef.name = _name,                                   \
  153                 .clkdef.parent_names = _pnames,                         \
  154                 .clkdef.parent_cnt = nitems(_pnames),                   \
  155                 .clkdef.flags = CLK_NODE_STATIC_STRINGS,                \
  156                 .offset = RK3568_CLKSEL_CON(_o),                        \
  157                 .shift = _ms,                                           \
  158                 .width = _mw,                                           \
  159                 .mux_flags = _f,                                        \
  160         },                                                              \
  161 }
  162 
  163 #define RK_GATE(_id, _name, _pname, _o, _s)                             \
  164 {                                                                       \
  165         .id = _id,                                                      \
  166         .name = _name,                                                  \
  167         .parent_name = _pname,                                          \
  168         .offset = RK3568_CLKGATE_CON(_o),                               \
  169         .shift = _s,                                                    \
  170 }
  171 
  172 extern struct rk_clk_pll_rate rk3568_pll_rates[];
  173 
  174 /* Parent clock defines */
  175 PNAME(mux_pll_p) = { "xin24m" };
  176 PNAME(xin24m_32k_p) = { "xin24m", "clk_rtc_32k" };
  177 PNAME(sclk_uart0_p) = { "sclk_uart0_div", "sclk_uart0_frac", "xin24m" };
  178 PNAME(clk_rtc32k_pmu_p) = { "clk_32k_pvtm", "xin32k", "clk_rtc32k_frac" };
  179 PNAME(ppll_usb480m_cpll_gpll_p) = { "ppll", "usb480m", "cpll", "gpll"};
  180 PNAME(clk_usbphy0_ref_p) = { "clk_ref24m", "xin_osc0_usbphy0_g" };
  181 PNAME(clk_usbphy1_ref_p) = { "clk_ref24m", "xin_osc0_usbphy1_g" };
  182 PNAME(clk_mipidsiphy0_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy0_g" };
  183 PNAME(clk_mipidsiphy1_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy1_g" };
  184 PNAME(clk_wifi_p) = { "clk_wifi_osc0", "clk_wifi_div" };
  185 PNAME(clk_pciephy0_ref_p) = { "clk_pciephy0_osc0", "clk_pciephy0_div" };
  186 PNAME(clk_pciephy1_ref_p) = { "clk_pciephy1_osc0", "clk_pciephy1_div" };
  187 PNAME(clk_pciephy2_ref_p) = { "clk_pciephy2_osc0", "clk_pciephy2_div" };
  188 PNAME(clk_hdmi_ref_p) = { "hpll", "hpll_ph0" };
  189 PNAME(clk_pdpmu_p) = { "ppll", "gpll" };
  190 PNAME(clk_pwm0_p) = { "xin24m", "clk_pdpmu" };
  191 
  192 /* CLOCKS */
  193 static struct rk_clk rk3568_clks[] = {
  194         /* External clocks */
  195         LINK("xin24m"),
  196         LINK("cpll"),
  197         LINK("gpll"),
  198         LINK("usb480m"),
  199         LINK("clk_32k_pvtm"),
  200 
  201         /* SRC_CLK */
  202         RK_MUX(CLK_RTC_32K, "clk_rtc_32k", clk_rtc32k_pmu_p, 0, 6, 2, 0),
  203         RK_MUX(0, "sclk_uart0_mux", sclk_uart0_p, 4, 10, 2, 0),
  204 
  205         /* PLL's */
  206         RK_PLL(PLL_PPLL, "ppll", mux_pll_p, 0, 0),
  207         RK_PLL(PLL_HPLL, "hpll", mux_pll_p, 2, 2),
  208 
  209         /* PD_PMU */
  210         RK_FACTOR(0, "ppll_ph0", "ppll", 1, 2),
  211         RK_FACTOR(0, "ppll_ph180", "ppll", 1, 2),
  212         RK_FACTOR(0, "hpll_ph0", "hpll", 1, 2),
  213         RK_MUX(CLK_PDPMU, "clk_pdpmu", clk_pdpmu_p, 2, 15, 1, 0),
  214         RK_COMPNOMUX(PCLK_PDPMU, "pclk_pdpmu", "clk_pdpmu", 2, 0, 5, 0, 2, 0),
  215         RK_COMPNOMUX(CLK_I2C0, "clk_i2c0", "clk_pdpmu", 3, 0, 7, 1, 1, 0),
  216         RK_FRACTION(CLK_RTC32K_FRAC, "clk_rtc32k_frac", "xin24m", 1, 0, 1, 0),
  217         RK_COMPNOMUX(XIN_OSC0_DIV, "xin_osc0_div", "xin24m", 0, 0, 5, 0, 0, 0),
  218         RK_COMPOSITE(CLK_UART0_DIV, "sclk_uart0_div",
  219             ppll_usb480m_cpll_gpll_p, 4, 8, 2, 0, 7, 1, 3, 0),
  220         RK_FRACTION(CLK_UART0_FRAC, "sclk_uart0_frac",
  221             "sclk_uart0_div", 5, 1, 4, 0),
  222         RK_MUX(DBCLK_GPIO0, "dbclk_gpio0_c", xin24m_32k_p, 6, 15, 1, 0),
  223         RK_COMPOSITE(CLK_PWM0, "clk_pwm0", clk_pwm0_p, 6, 7, 1, 0, 7, 1, 7, 0),
  224         RK_COMPNOMUX(CLK_REF24M, "clk_ref24m", "clk_pdpmu", 7, 0, 6, 2, 0, 0),
  225         RK_MUX(CLK_USBPHY0_REF, "clk_usbphy0_ref",
  226             clk_usbphy0_ref_p, 8, 0, 1, 0),
  227         RK_MUX(CLK_USBPHY1_REF, "clk_usbphy1_ref",
  228             clk_usbphy1_ref_p, 8, 1, 1, 0),
  229         RK_MUX(CLK_MIPIDSIPHY0_REF, "clk_mipidsiphy0_ref",
  230             clk_mipidsiphy0_ref_p, 8, 2, 1, 0),
  231         RK_MUX(CLK_MIPIDSIPHY1_REF, "clk_mipidsiphy1_ref",
  232             clk_mipidsiphy1_ref_p, 8, 3, 1, 0),
  233         RK_COMPNOMUX(CLK_WIFI_DIV, "clk_wifi_div",
  234             "clk_pdpmu", 8, 8, 6, 2, 5, 0),
  235         RK_MUX(CLK_WIFI, "clk_wifi", clk_wifi_p, 8, 15, 1, 0),
  236         RK_COMPNOMUX(CLK_PCIEPHY0_DIV, "clk_pciephy0_div",
  237             "ppll_ph0", 9, 0, 3, 2, 7, 0),
  238         RK_MUX(CLK_PCIEPHY0_REF, "clk_pciephy0_ref",
  239             clk_pciephy0_ref_p, 9, 3, 1, 0),
  240         RK_COMPNOMUX(CLK_PCIEPHY1_DIV, "clk_pciephy1_div",
  241             "ppll_ph0", 9, 4, 3, 2, 9, 0),
  242         RK_MUX(CLK_PCIEPHY1_REF, "clk_pciephy1_ref",
  243             clk_pciephy1_ref_p, 9, 7, 1, 0),
  244         RK_COMPNOMUX(CLK_PCIEPHY2_DIV, "clk_pciephy2_div",
  245             "ppll_ph0", 9, 8, 3, 2, 11, 0),
  246         RK_MUX(CLK_PCIEPHY2_REF, "clk_pciephy2_ref",
  247             clk_pciephy2_ref_p, 9, 11, 1, 0),
  248         RK_MUX(CLK_HDMI_REF, "clk_hdmi_ref", clk_hdmi_ref_p, 8, 7, 1, 0),
  249 };
  250 
  251 /* GATES */
  252 static struct rk_cru_gate rk3568_gates[] = {
  253         RK_GATE(PCLK_PMU, "pclk_pmu", "pclk_pdpmu", 0, 6),
  254         RK_GATE(DBCLK_GPIO0, "dbclk_gpio0", "dbclk_gpio0_c", 1, 10),
  255         RK_GATE(CLK_PMU, "clk_pmu", "xin24m", 0, 7),
  256         RK_GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pdpmu", 1, 0),
  257         RK_GATE(PCLK_UART0, "pclk_uart0", "pclk_pdpmu", 1, 2),
  258         RK_GATE(SCLK_UART0, "sclk_uart0", "sclk_uart0_mux", 1, 5),
  259         RK_GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pdpmu", 1, 9),
  260         RK_GATE(PCLK_PWM0, "pclk_pwm0", "pclk_pdpmu", 1, 6),
  261         RK_GATE(CLK_CAPTURE_PWM0_NDFT, "clk_capture_pwm0_ndft", "xin24m", 1, 8),
  262         RK_GATE(PCLK_PMUPVTM, "pclk_pmupvtm", "pclk_pdpmu", 1, 11),
  263         RK_GATE(CLK_PMUPVTM, "clk_pmupvtm", "xin24m", 1, 12),
  264         RK_GATE(CLK_CORE_PMUPVTM, "clk_core_pmupvtm", "xin24m", 1, 13),
  265         RK_GATE(XIN_OSC0_USBPHY0_G, "xin_osc0_usbphy0_g", "xin24m", 2, 1),
  266         RK_GATE(XIN_OSC0_USBPHY1_G, "xin_osc0_usbphy1_g", "xin24m", 2, 2),
  267         RK_GATE(XIN_OSC0_MIPIDSIPHY0_G, "xin_osc0_mipidsiphy0_g",
  268             "xin24m", 2, 3),
  269         RK_GATE(XIN_OSC0_MIPIDSIPHY1_G, "xin_osc0_mipidsiphy1_g",
  270             "xin24m", 2, 4),
  271         RK_GATE(CLK_WIFI_OSC0, "clk_wifi_osc0", "xin24m", 2, 6),
  272         RK_GATE(CLK_PCIEPHY0_OSC0, "clk_pciephy0_osc0", "xin24m", 2, 8),
  273         RK_GATE(CLK_PCIEPHY1_OSC0, "clk_pciephy1_osc0", "xin24m", 2, 10),
  274         RK_GATE(CLK_PCIEPHY2_OSC0, "clk_pciephy2_osc0", "xin24m", 2, 12),
  275         RK_GATE(CLK_PCIE30PHY_REF_M, "clk_pcie30phy_ref_m", "ppll_ph0", 2, 13),
  276         RK_GATE(CLK_PCIE30PHY_REF_N, "clk_pcie30phy_ref_n", "ppll_ph180", 2,14),
  277         RK_GATE(XIN_OSC0_EDPPHY_G, "xin_osc0_edpphy_g", "xin24m", 2, 15),
  278 };
  279 
  280 static int
  281 rk3568_pmucru_probe(device_t dev)
  282 {
  283 
  284         if (!ofw_bus_status_okay(dev))
  285                 return (ENXIO);
  286 
  287         if (ofw_bus_is_compatible(dev, "rockchip,rk3568-pmucru")) {
  288                 device_set_desc(dev, "Rockchip RK3568 PMU Clock & Reset Unit");
  289                 return (BUS_PROBE_DEFAULT);
  290         }
  291 
  292         return (ENXIO);
  293 }
  294 
  295 static int
  296 rk3568_pmucru_attach(device_t dev)
  297 {
  298         struct rk_cru_softc *sc;
  299 
  300         sc = device_get_softc(dev);
  301         sc->dev = dev;
  302         sc->clks = rk3568_clks;
  303         sc->nclks = nitems(rk3568_clks);
  304         sc->gates = rk3568_gates;
  305         sc->ngates = nitems(rk3568_gates);
  306         sc->reset_offset = 0x200;
  307         sc->reset_num = 4;
  308 
  309         return (rk_cru_attach(dev));
  310 }
  311 
  312 static device_method_t methods[] = {
  313         /* Device interface */
  314         DEVMETHOD(device_probe,         rk3568_pmucru_probe),
  315         DEVMETHOD(device_attach,        rk3568_pmucru_attach),
  316 
  317         DEVMETHOD_END
  318 };
  319 
  320 DEFINE_CLASS_1(rk3568_pmucru, rk3568_pmucru_driver, methods,
  321     sizeof(struct rk_cru_softc), rk_cru_driver);
  322 
  323 EARLY_DRIVER_MODULE(rk3568_pmucru, simplebus, rk3568_pmucru_driver,
  324     0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);

Cache object: 4eb4c241344d01ed74f0322828a142ca


[ 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.