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/mips/ingenic/jz4780_clock.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  * Copyright 2015 Alexander Kabaev <kan@FreeBSD.org>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 /*
   28  * Ingenic JZ4780 CGU driver.
   29  *
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/conf.h>
   38 #include <sys/bus.h>
   39 #include <sys/kernel.h>
   40 #include <sys/module.h>
   41 #include <sys/lock.h>
   42 #include <sys/mutex.h>
   43 #include <sys/resource.h>
   44 #include <sys/rman.h>
   45 
   46 #include <machine/bus.h>
   47 
   48 #include <dev/fdt/fdt_common.h>
   49 #include <dev/ofw/ofw_bus.h>
   50 #include <dev/ofw/ofw_bus_subr.h>
   51 
   52 #include <mips/ingenic/jz4780_clk.h>
   53 #include <mips/ingenic/jz4780_regs.h>
   54 #include <mips/ingenic/jz4780_clock.h>
   55 
   56 #include "clkdev_if.h"
   57 
   58 #include <gnu/dts/include/dt-bindings/clock/jz4780-cgu.h>
   59 
   60 /**********************************************************************
   61  *  JZ4780 CGU clock domain
   62  **********************************************************************/
   63 struct jz4780_clock_softc {
   64         device_t        dev;
   65         struct resource *res[1];
   66         struct mtx      mtx;
   67         struct clkdom   *clkdom;
   68 };
   69 
   70 static struct resource_spec jz4780_clock_spec[] = {
   71         { SYS_RES_MEMORY, 0, RF_ACTIVE },
   72         { -1, 0 }
   73 };
   74 
   75 struct jz4780_clk_pll_def {
   76         uint16_t   clk_id;
   77         uint16_t   clk_reg;
   78         const char *clk_name;
   79         const char *clk_pname[1];
   80 };
   81 
   82 #define PLL(_id, cname, pname, reg) {           \
   83         .clk_id         = _id,                  \
   84         .clk_reg        = reg,                  \
   85         .clk_name       = cname,                \
   86         .clk_pname[0]   = pname,                \
   87 }
   88 
   89 struct jz4780_clk_gate_def {
   90         uint16_t   clk_id;
   91         uint16_t   clk_bit;
   92         const char *clk_name;
   93         const char *clk_pname[1];
   94 };
   95 
   96 #define GATE(_id, cname, pname, bit) {          \
   97         .clk_id         = _id,                  \
   98         .clk_bit        = bit,                  \
   99         .clk_name       = cname,                \
  100         .clk_pname[0]   = pname,                \
  101 }
  102 
  103 #define MUX(reg, shift, bits, map)                      \
  104     .clk_mux.mux_reg = (reg),                           \
  105     .clk_mux.mux_shift = (shift),                       \
  106     .clk_mux.mux_bits = (bits),                         \
  107     .clk_mux.mux_map = (map),
  108 #define NO_MUX
  109 
  110 #define DIV(reg, shift, lg, bits, ce, st, bb)           \
  111     .clk_div.div_reg = (reg),                           \
  112     .clk_div.div_shift = (shift),                       \
  113     .clk_div.div_bits = (bits),                         \
  114     .clk_div.div_lg = (lg),                             \
  115     .clk_div.div_ce_bit = (ce),                         \
  116     .clk_div.div_st_bit = (st),                         \
  117     .clk_div.div_busy_bit = (bb),
  118 #define NO_DIV                                          \
  119 
  120 #define GATEBIT(bit)                                    \
  121     .clk_gate_bit = (bit),
  122 #define NO_GATE                                         \
  123     .clk_gate_bit = (-1),
  124 
  125 #define PLIST(pnames...)                                \
  126     .clk_pnames = { pnames },
  127 
  128 #define GENCLK(id, name, type, parents, mux, div, gt) { \
  129         .clk_id         = id,                           \
  130         .clk_type       = type,                         \
  131         .clk_name       = name,                         \
  132         parents                                         \
  133         mux                                             \
  134         div                                             \
  135         gt                                              \
  136 }
  137 
  138 /* PLL definitions */
  139 static struct jz4780_clk_pll_def pll_clks[] = {
  140         PLL(JZ4780_CLK_APLL, "apll", "ext", JZ_CPAPCR),
  141         PLL(JZ4780_CLK_MPLL, "mpll", "ext", JZ_CPMPCR),
  142         PLL(JZ4780_CLK_EPLL, "epll", "ext", JZ_CPEPCR),
  143         PLL(JZ4780_CLK_VPLL, "vpll", "ext", JZ_CPVPCR),
  144 };
  145 
  146 /* OTG PHY clock (reuse gate def structure */
  147 static struct jz4780_clk_gate_def otg_clks[] = {
  148         GATE(JZ4780_CLK_OTGPHY, "otg_phy",      "ext", 0),
  149 };
  150 
  151 static const struct jz4780_clk_descr gen_clks[] = {
  152         GENCLK(JZ4780_CLK_SCLKA, "sclk_a", CLK_MASK_MUX,
  153             PLIST("apll", "ext", "rtc"),
  154             MUX(JZ_CPCCR, 30, 2, 0x7),
  155             NO_DIV,
  156             NO_GATE
  157         ),
  158 
  159         GENCLK(JZ4780_CLK_CPUMUX, "cpumux", CLK_MASK_MUX,
  160             PLIST("sclk_a", "mpll", "epll"),
  161             MUX(JZ_CPCCR, 28, 2, 0x7),
  162             NO_DIV,
  163             NO_GATE
  164         ),
  165 
  166         GENCLK(JZ4780_CLK_CPU, "cpu", CLK_MASK_DIV,
  167             PLIST("cpumux"),
  168             NO_MUX,
  169             DIV(JZ_CPCCR, 0, 0, 4, 22, -1, -1),
  170             NO_GATE
  171         ),
  172 
  173         GENCLK(JZ4780_CLK_L2CACHE, "l2cache", CLK_MASK_DIV,
  174             PLIST("cpumux"),
  175             NO_MUX,
  176             DIV(JZ_CPCCR, 4, 0, 4, -1, -1, -1),
  177             NO_GATE
  178         ),
  179 
  180         GENCLK(JZ4780_CLK_AHB0, "ahb0", CLK_MASK_MUX | CLK_MASK_DIV,
  181             PLIST("sclk_a", "mpll", "epll"),
  182             MUX(JZ_CPCCR, 26, 2, 0x7),
  183             DIV(JZ_CPCCR, 8, 0, 4, 21, -1, -1),
  184             NO_GATE
  185         ),
  186 
  187         GENCLK(JZ4780_CLK_AHB2PMUX, "ahb2_apb_mux", CLK_MASK_MUX,
  188             PLIST("sclk_a", "mpll", "rtc"),
  189             MUX(JZ_CPCCR, 24, 2, 0x7),
  190             NO_DIV,
  191             NO_GATE
  192         ),
  193 
  194         GENCLK(JZ4780_CLK_AHB2, "ahb2", CLK_MASK_DIV,
  195             PLIST("ahb2_apb_mux"),
  196             NO_MUX,
  197             DIV(JZ_CPCCR, 12, 0, 4, 20, -1, -1),
  198             NO_GATE
  199         ),
  200 
  201         GENCLK(JZ4780_CLK_PCLK, "pclk", CLK_MASK_DIV,
  202             PLIST("ahb2_apb_mux"),
  203             NO_MUX,
  204             DIV(JZ_CPCCR, 16, 0, 4, 20, -1, -1),
  205             NO_GATE
  206         ),
  207 
  208         GENCLK(JZ4780_CLK_DDR, "ddr", CLK_MASK_MUX | CLK_MASK_DIV,
  209             PLIST("sclk_a", "mpll"),
  210             MUX(JZ_DDCDR, 30, 2, 0x6),
  211             DIV(JZ_DDCDR, 0, 0, 4, 29, 28, 27),
  212             NO_GATE
  213         ),
  214 
  215         GENCLK(JZ4780_CLK_VPU, "vpu", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
  216             PLIST("sclk_a", "mpll", "epll"),
  217             MUX(JZ_VPUCDR, 30, 2, 0xe),
  218             DIV(JZ_VPUCDR, 0, 0, 4, 29, 28, 27),
  219             GATEBIT(32 + 2)
  220         ),
  221 
  222         GENCLK(JZ4780_CLK_I2SPLL, "i2s_pll", CLK_MASK_MUX | CLK_MASK_DIV,
  223             PLIST("sclk_a", "epll"),
  224             MUX(JZ_I2SCDR, 30, 1, 0xc),
  225             DIV(JZ_I2SCDR, 0, 0, 8, 29, 28, 27),
  226             NO_GATE
  227         ),
  228 
  229         GENCLK(JZ4780_CLK_I2S, "i2s", CLK_MASK_MUX,
  230             PLIST("ext", "i2s_pll"),
  231             MUX(JZ_I2SCDR, 31, 1, 0xc),
  232             NO_DIV,
  233             NO_GATE
  234         ),
  235 
  236         GENCLK(JZ4780_CLK_LCD0PIXCLK, "lcd0pixclk", CLK_MASK_MUX | CLK_MASK_DIV,
  237             PLIST("sclk_a", "mpll", "vpll"),
  238             MUX(JZ_LP0CDR, 30, 2, 0xe),
  239             DIV(JZ_LP0CDR, 0, 0, 8, 28, 27, 26),
  240             NO_GATE
  241         ),
  242 
  243         GENCLK(JZ4780_CLK_LCD1PIXCLK, "lcd1pixclk", CLK_MASK_MUX | CLK_MASK_DIV,
  244             PLIST("sclk_a", "mpll", "vpll"),
  245             MUX(JZ_LP1CDR, 30, 2, 0xe),
  246             DIV(JZ_LP1CDR, 0, 0, 8, 28, 27, 26),
  247             NO_GATE
  248         ),
  249 
  250         GENCLK(JZ4780_CLK_MSCMUX, "msc_mux", CLK_MASK_MUX,
  251             PLIST("sclk_a", "mpll"),
  252             MUX(JZ_MSC0CDR, 30, 2, 0x6),
  253             NO_DIV,
  254             NO_GATE
  255         ),
  256 
  257         GENCLK(JZ4780_CLK_MSC0, "msc0", CLK_MASK_DIV | CLK_MASK_GATE,
  258             PLIST("msc_mux"),
  259             NO_MUX,
  260             DIV(JZ_MSC0CDR, 0, 1, 8, 29, 28, 27),
  261             GATEBIT(3)
  262         ),
  263 
  264         GENCLK(JZ4780_CLK_MSC1, "msc1", CLK_MASK_DIV | CLK_MASK_GATE,
  265             PLIST("msc_mux"),
  266             NO_MUX,
  267             DIV(JZ_MSC1CDR, 0, 1, 8, 29, 28, 27),
  268             GATEBIT(11)
  269         ),
  270 
  271         GENCLK(JZ4780_CLK_MSC2, "msc2", CLK_MASK_DIV | CLK_MASK_GATE,
  272             PLIST("msc_mux"),
  273             NO_MUX,
  274             DIV(JZ_MSC2CDR, 0, 1, 8, 29, 28, 27),
  275             GATEBIT(12)
  276         ),
  277 
  278         GENCLK(JZ4780_CLK_UHC, "uhc", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
  279             PLIST("sclk_a", "mpll", "epll", "otg_phy"),
  280             MUX(JZ_UHCCDR, 30, 2, 0xf),
  281             DIV(JZ_UHCCDR, 0, 0, 8, 29, 28, 27),
  282             GATEBIT(24)
  283         ),
  284 
  285         GENCLK(JZ4780_CLK_SSIPLL, "ssi_pll", CLK_MASK_MUX | CLK_MASK_DIV,
  286             PLIST("sclk_a", "mpll"),
  287             MUX(JZ_SSICDR, 30, 1, 0xc),
  288             DIV(JZ_SSICDR, 0, 0, 8, 29, 28, 27),
  289             NO_GATE
  290         ),
  291 
  292         GENCLK(JZ4780_CLK_SSI, "ssi", CLK_MASK_MUX,
  293             PLIST("ext", "ssi_pll"),
  294             MUX(JZ_SSICDR, 31, 1, 0xc),
  295             NO_DIV,
  296             NO_GATE
  297         ),
  298 
  299         GENCLK(JZ4780_CLK_CIMMCLK, "cim_mclk", CLK_MASK_MUX | CLK_MASK_DIV,
  300             PLIST("sclk_a", "mpll"),
  301             MUX(JZ_CIMCDR, 31, 1, 0xc),
  302             DIV(JZ_CIMCDR, 0, 0, 8, 30, 29, 28),
  303             NO_GATE
  304         ),
  305 
  306         GENCLK(JZ4780_CLK_PCMPLL, "pcm_pll", CLK_MASK_MUX | CLK_MASK_DIV,
  307             PLIST("sclk_a", "mpll", "epll", "vpll"),
  308             MUX(JZ_PCMCDR, 29, 2, 0xf),
  309             DIV(JZ_PCMCDR, 0, 0, 8, 28, 27, 26),
  310             NO_GATE
  311         ),
  312 
  313         GENCLK(JZ4780_CLK_PCM, "pcm", CLK_MASK_MUX | CLK_MASK_GATE,
  314             PLIST("ext", "pcm_pll"),
  315             MUX(JZ_PCMCDR, 31, 1, 0xc),
  316             NO_DIV,
  317             GATEBIT(32 + 3)
  318         ),
  319 
  320         GENCLK(JZ4780_CLK_GPU, "gpu", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
  321             PLIST("sclk_a", "mpll", "epll"),
  322             MUX(JZ_GPUCDR, 30, 2, 0x7),
  323             DIV(JZ_GPUCDR, 0, 0, 4, 29, 28, 27),
  324             GATEBIT(32 + 4)
  325         ),
  326 
  327         GENCLK(JZ4780_CLK_HDMI, "hdmi", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
  328             PLIST("sclk_a", "mpll", "vpll"),
  329             MUX(JZ_HDMICDR, 30, 2, 0xe),
  330             DIV(JZ_HDMICDR, 0, 0, 8, 29, 28, 26),
  331             GATEBIT(32 + 9)
  332         ),
  333 
  334         GENCLK(JZ4780_CLK_BCH, "bch", CLK_MASK_MUX | CLK_MASK_DIV | CLK_MASK_GATE,
  335             PLIST("sclk_a", "mpll", "epll"),
  336             MUX(JZ_BCHCDR, 30, 2, 0x7),
  337             DIV(JZ_BCHCDR, 0, 0, 4, 29, 28, 27),
  338             GATEBIT(1)
  339         ),
  340 };
  341 
  342 static struct jz4780_clk_gate_def gate_clks[] = {
  343         GATE(JZ4780_CLK_NEMC,   "nemc",         "ahb2", 0),
  344         GATE(JZ4780_CLK_OTG0,   "otg0",         "ext",  2),
  345         GATE(JZ4780_CLK_SSI0,   "ssi0",         "ssi",  4),
  346         GATE(JZ4780_CLK_SMB0,   "smb0",         "pclk", 5),
  347         GATE(JZ4780_CLK_SMB1,   "smb1",         "pclk", 6),
  348         GATE(JZ4780_CLK_SCC,    "scc",          "ext",  7),
  349         GATE(JZ4780_CLK_AIC,    "aic",          "ext",  8),
  350         GATE(JZ4780_CLK_TSSI0,  "tssi0",        "ext",  9),
  351         GATE(JZ4780_CLK_OWI,    "owi",          "ext",  10),
  352         GATE(JZ4780_CLK_KBC,    "kbc",          "ext",  13),
  353         GATE(JZ4780_CLK_SADC,   "sadc",         "ext",  14),
  354         GATE(JZ4780_CLK_UART0,  "uart0",        "ext",  15),
  355         GATE(JZ4780_CLK_UART1,  "uart1",        "ext",  16),
  356         GATE(JZ4780_CLK_UART2,  "uart2",        "ext",  17),
  357         GATE(JZ4780_CLK_UART3,  "uart3",        "ext",  18),
  358         GATE(JZ4780_CLK_SSI1,   "ssi1",         "ssi",  19),
  359         GATE(JZ4780_CLK_SSI2,   "ssi2",         "ssi",  20),
  360         GATE(JZ4780_CLK_PDMA,   "pdma",         "ext",  21),
  361         GATE(JZ4780_CLK_GPS,    "gps",          "ext",  22),
  362         GATE(JZ4780_CLK_MAC,    "mac",          "ext",  23),
  363         GATE(JZ4780_CLK_SMB2,   "smb2",         "pclk", 25),
  364         GATE(JZ4780_CLK_CIM,    "cim",          "ext",  26),
  365         GATE(JZ4780_CLK_LCD,    "lcd",          "ext",  28),
  366         GATE(JZ4780_CLK_TVE,    "tve",          "lcd",  27),
  367         GATE(JZ4780_CLK_IPU,    "ipu",          "ext",  29),
  368         GATE(JZ4780_CLK_DDR0,   "ddr0",         "ddr",  30),
  369         GATE(JZ4780_CLK_DDR1,   "ddr1",         "ddr",  31),
  370         GATE(JZ4780_CLK_SMB3,   "smb3",         "pclk", 32 + 0),
  371         GATE(JZ4780_CLK_TSSI1,  "tssi1",        "ext",  32 + 1),
  372         GATE(JZ4780_CLK_COMPRESS, "compress",   "ext",  32 + 5),
  373         GATE(JZ4780_CLK_AIC1,   "aic1",         "ext",  32 + 6),
  374         GATE(JZ4780_CLK_GPVLC,  "gpvlc",        "ext",  32 + 7),
  375         GATE(JZ4780_CLK_OTG1,   "otg1",         "ext",  32 + 8),
  376         GATE(JZ4780_CLK_UART4,  "uart4",        "ext",  32 + 10),
  377         GATE(JZ4780_CLK_AHBMON, "ahb_mon",      "ext",  32 + 11),
  378         GATE(JZ4780_CLK_SMB4,   "smb4",         "pclk", 32 + 12),
  379         GATE(JZ4780_CLK_DES,    "des",          "ext",  32 + 13),
  380         GATE(JZ4780_CLK_X2D,    "x2d",          "ext",  32 + 14),
  381         GATE(JZ4780_CLK_CORE1,  "core1",        "cpu",  32 + 15),
  382 };
  383 
  384 static int
  385 jz4780_clock_register(struct jz4780_clock_softc *sc)
  386 {
  387         int i, ret;
  388 
  389         /* Register PLLs */
  390         for (i = 0; i < nitems(pll_clks); i++) {
  391                 struct clknode_init_def clkdef;
  392 
  393                 clkdef.id = pll_clks[i].clk_id;
  394                 clkdef.name = __DECONST(char *, pll_clks[i].clk_name);
  395                 clkdef.parent_names = pll_clks[i].clk_pname;
  396                 clkdef.parent_cnt = 1;
  397                 clkdef.flags = CLK_NODE_STATIC_STRINGS;
  398 
  399                 ret = jz4780_clk_pll_register(sc->clkdom, &clkdef, &sc->mtx,
  400                     sc->res[0], pll_clks[i].clk_reg);
  401                 if (ret != 0)
  402                         return (ret);
  403         }
  404 
  405         /* Register OTG clock */
  406         for (i = 0; i < nitems(otg_clks); i++) {
  407                 struct clknode_init_def clkdef;
  408 
  409                 clkdef.id = otg_clks[i].clk_id;
  410                 clkdef.name = __DECONST(char *, otg_clks[i].clk_name);
  411                 clkdef.parent_names = otg_clks[i].clk_pname;
  412                 clkdef.parent_cnt = 1;
  413                 clkdef.flags = CLK_NODE_STATIC_STRINGS;
  414 
  415                 ret = jz4780_clk_otg_register(sc->clkdom, &clkdef, &sc->mtx,
  416                     sc->res[0]);
  417                 if (ret != 0)
  418                         return (ret);
  419         }
  420 
  421         /* Register muxes and divisors */
  422         for (i = 0; i < nitems(gen_clks); i++) {
  423                 ret = jz4780_clk_gen_register(sc->clkdom, &gen_clks[i],
  424                     &sc->mtx, sc->res[0]);
  425                 if (ret != 0)
  426                         return (ret);
  427         }
  428 
  429         /* Register simple gates */
  430         for (i = 0; i < nitems(gate_clks); i++) {
  431                 struct clk_gate_def gatedef;
  432 
  433                 gatedef.clkdef.id = gate_clks[i].clk_id;
  434                 gatedef.clkdef.name = __DECONST(char *, gate_clks[i].clk_name);
  435                 gatedef.clkdef.parent_names = gate_clks[i].clk_pname;
  436                 gatedef.clkdef.parent_cnt = 1;
  437                 gatedef.clkdef.flags = CLK_NODE_STATIC_STRINGS;
  438 
  439                 if (gate_clks[i].clk_bit < 32) {
  440                         gatedef.offset = JZ_CLKGR0;
  441                         gatedef.shift = gate_clks[i].clk_bit;
  442                 } else {
  443                         gatedef.offset = JZ_CLKGR1;
  444                         gatedef.shift = gate_clks[i].clk_bit - 32;
  445                 }
  446                 gatedef.mask = 1;
  447                 gatedef.on_value = 0;
  448                 gatedef.off_value = 1;
  449                 gatedef.gate_flags = 0;
  450 
  451                 ret = clknode_gate_register(sc->clkdom, &gatedef);
  452                 if (ret != 0)
  453                         return (ret);
  454 
  455         }
  456 
  457         return (0);
  458 }
  459 
  460 static int
  461 jz4780_clock_fixup(struct jz4780_clock_softc *sc)
  462 {
  463         struct clknode *clk_uhc;
  464         int ret;
  465 
  466         /*
  467          * Make UHC mux use MPLL as the source. It defaults to OTG_PHY
  468          * and that somehow just does not work.
  469          */
  470         clkdom_xlock(sc->clkdom);
  471 
  472         /* Assume the worst */
  473         ret = ENXIO;
  474 
  475         clk_uhc = clknode_find_by_id(sc->clkdom, JZ4780_CLK_UHC);
  476         if (clk_uhc != NULL) {
  477                 ret = clknode_set_parent_by_name(clk_uhc, "mpll");
  478                 if (ret != 0)
  479                         device_printf(sc->dev,
  480                             "unable to reparent uhc clock\n");
  481                 else
  482                         ret = clknode_set_freq(clk_uhc, 48000000, 0, 0);
  483                 if (ret != 0)
  484                         device_printf(sc->dev, "unable to init uhc clock\n");
  485         } else
  486                 device_printf(sc->dev, "unable to lookup uhc clock\n");
  487 
  488         clkdom_unlock(sc->clkdom);
  489         return (ret);
  490 }
  491 
  492 #define CGU_LOCK(sc)            mtx_lock(&(sc)->mtx)
  493 #define CGU_UNLOCK(sc)          mtx_unlock(&(sc)->mtx)
  494 #define CGU_LOCK_INIT(sc)       \
  495     mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),        \
  496     "jz4780-cgu", MTX_DEF)
  497 #define CGU_LOCK_DESTROY(sc)    mtx_destroy(&(sc)->mtx);
  498 
  499 #define CSR_WRITE_4(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
  500 #define CSR_READ_4(sc, reg)             bus_read_4((sc)->res[0], (reg))
  501 
  502 static int
  503 jz4780_clock_probe(device_t dev)
  504 {
  505 
  506         if (!ofw_bus_status_okay(dev))
  507                 return (ENXIO);
  508 
  509         if (!ofw_bus_is_compatible(dev, "ingenic,jz4780-cgu"))
  510                 return (ENXIO);
  511 
  512         device_set_desc(dev, "Ingenic jz4780 CGU");
  513 
  514         return (BUS_PROBE_DEFAULT);
  515 }
  516 
  517 static int
  518 jz4780_clock_attach(device_t dev)
  519 {
  520         struct jz4780_clock_softc *sc;
  521 
  522         sc = device_get_softc(dev);
  523         if (bus_alloc_resources(dev, jz4780_clock_spec, sc->res)) {
  524                 device_printf(dev, "could not allocate resources for device\n");
  525                 return (ENXIO);
  526         }
  527 
  528         sc->dev = dev;
  529         CGU_LOCK_INIT(sc);
  530 
  531         sc->clkdom = clkdom_create(dev);
  532         if (sc->clkdom == NULL)
  533                 goto fail;
  534         if (jz4780_clock_register(sc) != 0)
  535                 goto fail;
  536         if (clkdom_finit(sc->clkdom) != 0)
  537                 goto fail;
  538         if (jz4780_clock_fixup(sc) != 0)
  539                 goto fail;
  540         if (bootverbose)
  541                 clkdom_dump(sc->clkdom);
  542 
  543         return (0);
  544 fail:
  545         bus_release_resources(dev, jz4780_clock_spec, sc->res);
  546         CGU_LOCK_DESTROY(sc);
  547 
  548         return (ENXIO);
  549 }
  550 
  551 static int
  552 jz4780_clock_detach(device_t dev)
  553 {
  554         struct jz4780_clock_softc *sc;
  555 
  556         sc = device_get_softc(dev);
  557         bus_release_resources(dev, jz4780_clock_spec, sc->res);
  558         CGU_LOCK_DESTROY(sc);
  559 
  560         return (0);
  561 }
  562 
  563 static int
  564 jz4780_clock_write_4(device_t dev, bus_addr_t addr, uint32_t val)
  565 {
  566         struct jz4780_clock_softc *sc;
  567 
  568         sc = device_get_softc(dev);
  569         CSR_WRITE_4(sc, addr, val);
  570         return (0);
  571 }
  572 
  573 static int
  574 jz4780_clock_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
  575 {
  576         struct jz4780_clock_softc *sc;
  577 
  578         sc = device_get_softc(dev);
  579         *val = CSR_READ_4(sc, addr);
  580         return (0);
  581 }
  582 
  583 static int
  584 jz4780_clock_modify_4(device_t dev, bus_addr_t addr, uint32_t clear_mask,
  585     uint32_t set_mask)
  586 {
  587         struct jz4780_clock_softc *sc;
  588         uint32_t val;
  589 
  590         sc = device_get_softc(dev);
  591         val = CSR_READ_4(sc, addr);
  592         val &= ~clear_mask;
  593         val |= set_mask;
  594         CSR_WRITE_4(sc, addr, val);
  595         return (0);
  596 }
  597 
  598 static void
  599 jz4780_clock_device_lock(device_t dev)
  600 {
  601         struct jz4780_clock_softc *sc;
  602 
  603         sc = device_get_softc(dev);
  604         CGU_LOCK(sc);
  605 }
  606 
  607 static void
  608 jz4780_clock_device_unlock(device_t dev)
  609 {
  610         struct jz4780_clock_softc *sc;
  611 
  612         sc = device_get_softc(dev);
  613         CGU_UNLOCK(sc);
  614 }
  615 
  616 static device_method_t jz4780_clock_methods[] = {
  617         /* Device interface */
  618         DEVMETHOD(device_probe,         jz4780_clock_probe),
  619         DEVMETHOD(device_attach,        jz4780_clock_attach),
  620         DEVMETHOD(device_detach,        jz4780_clock_detach),
  621 
  622         /* Clock device interface */
  623         DEVMETHOD(clkdev_write_4,       jz4780_clock_write_4),
  624         DEVMETHOD(clkdev_read_4,        jz4780_clock_read_4),
  625         DEVMETHOD(clkdev_modify_4,      jz4780_clock_modify_4),
  626         DEVMETHOD(clkdev_device_lock,   jz4780_clock_device_lock),
  627         DEVMETHOD(clkdev_device_unlock, jz4780_clock_device_unlock),
  628 
  629         DEVMETHOD_END
  630 };
  631 
  632 static driver_t jz4780_clock_driver = {
  633         "cgu",
  634         jz4780_clock_methods,
  635         sizeof(struct jz4780_clock_softc),
  636 };
  637 
  638 static devclass_t jz4780_clock_devclass;
  639 
  640 EARLY_DRIVER_MODULE(jz4780_clock, simplebus, jz4780_clock_driver,
  641     jz4780_clock_devclass, 0, 0,  BUS_PASS_CPU + BUS_PASS_ORDER_LATE);
  642 
  643 static int
  644 jz4780_ehci_clk_config(struct jz4780_clock_softc *sc)
  645 {
  646         clk_t phy_clk, ext_clk;
  647         uint64_t phy_freq;
  648         int err;
  649 
  650         phy_clk = NULL;
  651         ext_clk = NULL;
  652         err = -1;
  653 
  654         /* Set phy timing by copying it from ext */
  655         if (clk_get_by_id(sc->dev, sc->clkdom, JZ4780_CLK_OTGPHY,
  656             &phy_clk) != 0)
  657                 goto done;
  658         if (clk_get_parent(phy_clk, &ext_clk) != 0)
  659                 goto done;
  660         if (clk_get_freq(ext_clk, &phy_freq) != 0)
  661                 goto done;
  662         if (clk_set_freq(phy_clk, phy_freq, 0) != 0)
  663                 goto done;
  664         err = 0;
  665 done:
  666         clk_release(ext_clk);
  667         clk_release(phy_clk);
  668 
  669         return (err);
  670 }
  671 
  672 int
  673 jz4780_ohci_enable(void)
  674 {
  675         device_t dev;
  676         struct jz4780_clock_softc *sc;
  677         uint32_t reg;
  678 
  679         dev = devclass_get_device(jz4780_clock_devclass, 0);
  680         if (dev == NULL)
  681                 return (-1);
  682 
  683         sc = device_get_softc(dev);
  684         CGU_LOCK(sc);
  685 
  686         /* Do not force port1 to suspend mode */
  687         reg = CSR_READ_4(sc, JZ_OPCR);
  688         reg |= OPCR_SPENDN1;
  689         CSR_WRITE_4(sc, JZ_OPCR, reg);
  690 
  691         CGU_UNLOCK(sc);
  692         return (0);
  693 }
  694 
  695 int
  696 jz4780_ehci_enable(void)
  697 {
  698         device_t dev;
  699         struct jz4780_clock_softc *sc;
  700         uint32_t reg;
  701 
  702         dev = devclass_get_device(jz4780_clock_devclass, 0);
  703         if (dev == NULL)
  704                 return (-1);
  705 
  706         sc = device_get_softc(dev);
  707 
  708         /*
  709          * EHCI should use MPPL as a parent, but Linux configures OTG
  710          * clock anyway. Follow their lead blindly.
  711          */
  712         if (jz4780_ehci_clk_config(sc) != 0)
  713                 return (-1);
  714 
  715         CGU_LOCK(sc);
  716 
  717         /* Enable OTG, should not be necessary since we use PLL clock */
  718         reg = CSR_READ_4(sc, JZ_USBPCR);
  719         reg &= ~(PCR_OTG_DISABLE);
  720         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  721 
  722         /* Do not force port1 to suspend mode */
  723         reg = CSR_READ_4(sc, JZ_OPCR);
  724         reg |= OPCR_SPENDN1;
  725         CSR_WRITE_4(sc, JZ_OPCR, reg);
  726 
  727         /* D- pulldown */
  728         reg = CSR_READ_4(sc, JZ_USBPCR1);
  729         reg |= PCR_DMPD1;
  730         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  731 
  732         /* D+ pulldown */
  733         reg = CSR_READ_4(sc, JZ_USBPCR1);
  734         reg |= PCR_DPPD1;
  735         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  736 
  737         /* 16 bit bus witdth for port 1*/
  738         reg = CSR_READ_4(sc, JZ_USBPCR1);
  739         reg |= PCR_WORD_I_F1 | PCR_WORD_I_F0;
  740         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  741 
  742         /* Reset USB */
  743         reg = CSR_READ_4(sc, JZ_USBPCR);
  744         reg |= PCR_POR;
  745         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  746         DELAY(1);
  747         reg = CSR_READ_4(sc, JZ_USBPCR);
  748         reg &= ~(PCR_POR);
  749         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  750 
  751         /* Soft-reset USB */
  752         reg = CSR_READ_4(sc, JZ_SRBC);
  753         reg |= SRBC_UHC_SR;
  754         CSR_WRITE_4(sc, JZ_SRBC, reg);
  755         /* 300ms */
  756         DELAY(300*hz/1000);
  757 
  758         reg = CSR_READ_4(sc, JZ_SRBC);
  759         reg &= ~(SRBC_UHC_SR);
  760         CSR_WRITE_4(sc, JZ_SRBC, reg);
  761 
  762         /* 300ms */
  763         DELAY(300*hz/1000);
  764 
  765         CGU_UNLOCK(sc);
  766         return (0);
  767 }
  768 
  769 #define USBRESET_DETECT_TIME    0x96
  770 
  771 int
  772 jz4780_otg_enable(void)
  773 {
  774         device_t dev;
  775         struct jz4780_clock_softc *sc;
  776         uint32_t reg;
  777 
  778         dev = devclass_get_device(jz4780_clock_devclass, 0);
  779         if (dev == NULL)
  780                 return (-1);
  781 
  782         sc = device_get_softc(dev);
  783 
  784         CGU_LOCK(sc);
  785 
  786         /* Select Synopsys OTG mode */
  787         reg = CSR_READ_4(sc, JZ_USBPCR1);
  788         reg |= PCR_SYNOPSYS;
  789 
  790         /* Set UTMI bus width to 16 bit */
  791         reg |= PCR_WORD_I_F0 | PCR_WORD_I_F1;
  792         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  793 
  794         /* Blah */
  795         reg = CSR_READ_4(sc, JZ_USBVBFIL);
  796         reg = REG_SET(reg, USBVBFIL_IDDIGFIL, 0);
  797         reg = REG_SET(reg, USBVBFIL_USBVBFIL, 0);
  798         CSR_WRITE_4(sc, JZ_USBVBFIL, reg);
  799 
  800         /* Setup reset detect time */
  801         reg = CSR_READ_4(sc, JZ_USBRDT);
  802         reg = REG_SET(reg, USBRDT_USBRDT, USBRESET_DETECT_TIME);
  803         reg |= USBRDT_VBFIL_LD_EN;
  804         CSR_WRITE_4(sc, JZ_USBRDT, reg);
  805 
  806         /* Setup USBPCR bits */
  807         reg = CSR_READ_4(sc, JZ_USBPCR);
  808         reg |= PCR_USB_MODE;
  809         reg |= PCR_COMMONONN;
  810         reg |= PCR_VBUSVLDEXT;
  811         reg |= PCR_VBUSVLDEXTSEL;
  812         reg &= ~(PCR_OTG_DISABLE);
  813         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  814 
  815         /* Reset USB */
  816         reg = CSR_READ_4(sc, JZ_USBPCR);
  817         reg |= PCR_POR;
  818         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  819         DELAY(1000);
  820         reg = CSR_READ_4(sc, JZ_USBPCR);
  821         reg &= ~(PCR_POR);
  822         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  823 
  824         /* Unsuspend OTG port */
  825         reg = CSR_READ_4(sc, JZ_OPCR);
  826         reg |= OPCR_SPENDN0;
  827         CSR_WRITE_4(sc, JZ_OPCR, reg);
  828 
  829         CGU_UNLOCK(sc);
  830         return (0);
  831 }

Cache object: 433480d68eef27e22a2403997d35691b


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