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 <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         return (0);
  457 }
  458 
  459 static int
  460 jz4780_clock_fixup(struct jz4780_clock_softc *sc)
  461 {
  462         struct clknode *clk_uhc;
  463         int ret;
  464 
  465         /*
  466          * Make UHC mux use MPLL as the source. It defaults to OTG_PHY
  467          * and that somehow just does not work.
  468          */
  469         clkdom_xlock(sc->clkdom);
  470 
  471         /* Assume the worst */
  472         ret = ENXIO;
  473 
  474         clk_uhc = clknode_find_by_id(sc->clkdom, JZ4780_CLK_UHC);
  475         if (clk_uhc != NULL) {
  476                 ret = clknode_set_parent_by_name(clk_uhc, "mpll");
  477                 if (ret != 0)
  478                         device_printf(sc->dev,
  479                             "unable to reparent uhc clock\n");
  480                 else
  481                         ret = clknode_set_freq(clk_uhc, 48000000, 0, 0);
  482                 if (ret != 0)
  483                         device_printf(sc->dev, "unable to init uhc clock\n");
  484         } else
  485                 device_printf(sc->dev, "unable to lookup uhc clock\n");
  486 
  487         clkdom_unlock(sc->clkdom);
  488         return (ret);
  489 }
  490 
  491 #define CGU_LOCK(sc)            mtx_lock(&(sc)->mtx)
  492 #define CGU_UNLOCK(sc)          mtx_unlock(&(sc)->mtx)
  493 #define CGU_LOCK_INIT(sc)       \
  494     mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),        \
  495     "jz4780-cgu", MTX_DEF)
  496 #define CGU_LOCK_DESTROY(sc)    mtx_destroy(&(sc)->mtx);
  497 
  498 #define CSR_WRITE_4(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
  499 #define CSR_READ_4(sc, reg)             bus_read_4((sc)->res[0], (reg))
  500 
  501 static int
  502 jz4780_clock_probe(device_t dev)
  503 {
  504 
  505         if (!ofw_bus_status_okay(dev))
  506                 return (ENXIO);
  507 
  508         if (!ofw_bus_is_compatible(dev, "ingenic,jz4780-cgu"))
  509                 return (ENXIO);
  510 
  511         device_set_desc(dev, "Ingenic jz4780 CGU");
  512 
  513         return (BUS_PROBE_DEFAULT);
  514 }
  515 
  516 static int
  517 jz4780_clock_attach(device_t dev)
  518 {
  519         struct jz4780_clock_softc *sc;
  520 
  521         sc = device_get_softc(dev);
  522         if (bus_alloc_resources(dev, jz4780_clock_spec, sc->res)) {
  523                 device_printf(dev, "could not allocate resources for device\n");
  524                 return (ENXIO);
  525         }
  526 
  527         sc->dev = dev;
  528         CGU_LOCK_INIT(sc);
  529 
  530         sc->clkdom = clkdom_create(dev);
  531         if (sc->clkdom == NULL)
  532                 goto fail;
  533         if (jz4780_clock_register(sc) != 0)
  534                 goto fail;
  535         if (clkdom_finit(sc->clkdom) != 0)
  536                 goto fail;
  537         if (jz4780_clock_fixup(sc) != 0)
  538                 goto fail;
  539         if (bootverbose)
  540                 clkdom_dump(sc->clkdom);
  541 
  542         return (0);
  543 fail:
  544         bus_release_resources(dev, jz4780_clock_spec, sc->res);
  545         CGU_LOCK_DESTROY(sc);
  546 
  547         return (ENXIO);
  548 }
  549 
  550 static int
  551 jz4780_clock_detach(device_t dev)
  552 {
  553         struct jz4780_clock_softc *sc;
  554 
  555         sc = device_get_softc(dev);
  556         bus_release_resources(dev, jz4780_clock_spec, sc->res);
  557         CGU_LOCK_DESTROY(sc);
  558 
  559         return (0);
  560 }
  561 
  562 static int
  563 jz4780_clock_write_4(device_t dev, bus_addr_t addr, uint32_t val)
  564 {
  565         struct jz4780_clock_softc *sc;
  566 
  567         sc = device_get_softc(dev);
  568         CSR_WRITE_4(sc, addr, val);
  569         return (0);
  570 }
  571 
  572 static int
  573 jz4780_clock_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
  574 {
  575         struct jz4780_clock_softc *sc;
  576 
  577         sc = device_get_softc(dev);
  578         *val = CSR_READ_4(sc, addr);
  579         return (0);
  580 }
  581 
  582 static int
  583 jz4780_clock_modify_4(device_t dev, bus_addr_t addr, uint32_t clear_mask,
  584     uint32_t set_mask)
  585 {
  586         struct jz4780_clock_softc *sc;
  587         uint32_t val;
  588 
  589         sc = device_get_softc(dev);
  590         val = CSR_READ_4(sc, addr);
  591         val &= ~clear_mask;
  592         val |= set_mask;
  593         CSR_WRITE_4(sc, addr, val);
  594         return (0);
  595 }
  596 
  597 static void
  598 jz4780_clock_device_lock(device_t dev)
  599 {
  600         struct jz4780_clock_softc *sc;
  601 
  602         sc = device_get_softc(dev);
  603         CGU_LOCK(sc);
  604 }
  605 
  606 static void
  607 jz4780_clock_device_unlock(device_t dev)
  608 {
  609         struct jz4780_clock_softc *sc;
  610 
  611         sc = device_get_softc(dev);
  612         CGU_UNLOCK(sc);
  613 }
  614 
  615 static device_method_t jz4780_clock_methods[] = {
  616         /* Device interface */
  617         DEVMETHOD(device_probe,         jz4780_clock_probe),
  618         DEVMETHOD(device_attach,        jz4780_clock_attach),
  619         DEVMETHOD(device_detach,        jz4780_clock_detach),
  620 
  621         /* Clock device interface */
  622         DEVMETHOD(clkdev_write_4,       jz4780_clock_write_4),
  623         DEVMETHOD(clkdev_read_4,        jz4780_clock_read_4),
  624         DEVMETHOD(clkdev_modify_4,      jz4780_clock_modify_4),
  625         DEVMETHOD(clkdev_device_lock,   jz4780_clock_device_lock),
  626         DEVMETHOD(clkdev_device_unlock, jz4780_clock_device_unlock),
  627 
  628         DEVMETHOD_END
  629 };
  630 
  631 static driver_t jz4780_clock_driver = {
  632         "cgu",
  633         jz4780_clock_methods,
  634         sizeof(struct jz4780_clock_softc),
  635 };
  636 
  637 static devclass_t jz4780_clock_devclass;
  638 
  639 EARLY_DRIVER_MODULE(jz4780_clock, simplebus, jz4780_clock_driver,
  640     jz4780_clock_devclass, 0, 0,  BUS_PASS_CPU + BUS_PASS_ORDER_LATE);
  641 
  642 static int
  643 jz4780_ehci_clk_config(struct jz4780_clock_softc *sc)
  644 {
  645         clk_t phy_clk, ext_clk;
  646         uint64_t phy_freq;
  647         int err;
  648 
  649         phy_clk = NULL;
  650         ext_clk = NULL;
  651         err = -1;
  652 
  653         /* Set phy timing by copying it from ext */
  654         if (clk_get_by_id(sc->dev, sc->clkdom, JZ4780_CLK_OTGPHY,
  655             &phy_clk) != 0)
  656                 goto done;
  657         if (clk_get_parent(phy_clk, &ext_clk) != 0)
  658                 goto done;
  659         if (clk_get_freq(ext_clk, &phy_freq) != 0)
  660                 goto done;
  661         if (clk_set_freq(phy_clk, phy_freq, 0) != 0)
  662                 goto done;
  663         err = 0;
  664 done:
  665         clk_release(ext_clk);
  666         clk_release(phy_clk);
  667 
  668         return (err);
  669 }
  670 
  671 int
  672 jz4780_ohci_enable(void)
  673 {
  674         device_t dev;
  675         struct jz4780_clock_softc *sc;
  676         uint32_t reg;
  677 
  678         dev = devclass_get_device(jz4780_clock_devclass, 0);
  679         if (dev == NULL)
  680                 return (-1);
  681 
  682         sc = device_get_softc(dev);
  683         CGU_LOCK(sc);
  684 
  685         /* Do not force port1 to suspend mode */
  686         reg = CSR_READ_4(sc, JZ_OPCR);
  687         reg |= OPCR_SPENDN1;
  688         CSR_WRITE_4(sc, JZ_OPCR, reg);
  689 
  690         CGU_UNLOCK(sc);
  691         return (0);
  692 }
  693 
  694 int
  695 jz4780_ehci_enable(void)
  696 {
  697         device_t dev;
  698         struct jz4780_clock_softc *sc;
  699         uint32_t reg;
  700 
  701         dev = devclass_get_device(jz4780_clock_devclass, 0);
  702         if (dev == NULL)
  703                 return (-1);
  704 
  705         sc = device_get_softc(dev);
  706 
  707         /*
  708          * EHCI should use MPPL as a parent, but Linux configures OTG
  709          * clock anyway. Follow their lead blindly.
  710          */
  711         if (jz4780_ehci_clk_config(sc) != 0)
  712                 return (-1);
  713 
  714         CGU_LOCK(sc);
  715 
  716         /* Enable OTG, should not be necessary since we use PLL clock */
  717         reg = CSR_READ_4(sc, JZ_USBPCR);
  718         reg &= ~(PCR_OTG_DISABLE);
  719         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  720 
  721         /* Do not force port1 to suspend mode */
  722         reg = CSR_READ_4(sc, JZ_OPCR);
  723         reg |= OPCR_SPENDN1;
  724         CSR_WRITE_4(sc, JZ_OPCR, reg);
  725 
  726         /* D- pulldown */
  727         reg = CSR_READ_4(sc, JZ_USBPCR1);
  728         reg |= PCR_DMPD1;
  729         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  730 
  731         /* D+ pulldown */
  732         reg = CSR_READ_4(sc, JZ_USBPCR1);
  733         reg |= PCR_DPPD1;
  734         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  735 
  736         /* 16 bit bus witdth for port 1*/
  737         reg = CSR_READ_4(sc, JZ_USBPCR1);
  738         reg |= PCR_WORD_I_F1 | PCR_WORD_I_F0;
  739         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  740 
  741         /* Reset USB */
  742         reg = CSR_READ_4(sc, JZ_USBPCR);
  743         reg |= PCR_POR;
  744         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  745         DELAY(1);
  746         reg = CSR_READ_4(sc, JZ_USBPCR);
  747         reg &= ~(PCR_POR);
  748         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  749 
  750         /* Soft-reset USB */
  751         reg = CSR_READ_4(sc, JZ_SRBC);
  752         reg |= SRBC_UHC_SR;
  753         CSR_WRITE_4(sc, JZ_SRBC, reg);
  754         /* 300ms */
  755         DELAY(300*hz/1000);
  756 
  757         reg = CSR_READ_4(sc, JZ_SRBC);
  758         reg &= ~(SRBC_UHC_SR);
  759         CSR_WRITE_4(sc, JZ_SRBC, reg);
  760 
  761         /* 300ms */
  762         DELAY(300*hz/1000);
  763 
  764         CGU_UNLOCK(sc);
  765         return (0);
  766 }
  767 
  768 #define USBRESET_DETECT_TIME    0x96
  769 
  770 int
  771 jz4780_otg_enable(void)
  772 {
  773         device_t dev;
  774         struct jz4780_clock_softc *sc;
  775         uint32_t reg;
  776 
  777         dev = devclass_get_device(jz4780_clock_devclass, 0);
  778         if (dev == NULL)
  779                 return (-1);
  780 
  781         sc = device_get_softc(dev);
  782 
  783         CGU_LOCK(sc);
  784 
  785         /* Select Synopsys OTG mode */
  786         reg = CSR_READ_4(sc, JZ_USBPCR1);
  787         reg |= PCR_SYNOPSYS;
  788 
  789         /* Set UTMI bus width to 16 bit */
  790         reg |= PCR_WORD_I_F0 | PCR_WORD_I_F1;
  791         CSR_WRITE_4(sc, JZ_USBPCR1, reg);
  792 
  793         /* Blah */
  794         reg = CSR_READ_4(sc, JZ_USBVBFIL);
  795         reg = REG_SET(reg, USBVBFIL_IDDIGFIL, 0);
  796         reg = REG_SET(reg, USBVBFIL_USBVBFIL, 0);
  797         CSR_WRITE_4(sc, JZ_USBVBFIL, reg);
  798 
  799         /* Setup reset detect time */
  800         reg = CSR_READ_4(sc, JZ_USBRDT);
  801         reg = REG_SET(reg, USBRDT_USBRDT, USBRESET_DETECT_TIME);
  802         reg |= USBRDT_VBFIL_LD_EN;
  803         CSR_WRITE_4(sc, JZ_USBRDT, reg);
  804 
  805         /* Setup USBPCR bits */
  806         reg = CSR_READ_4(sc, JZ_USBPCR);
  807         reg |= PCR_USB_MODE;
  808         reg |= PCR_COMMONONN;
  809         reg |= PCR_VBUSVLDEXT;
  810         reg |= PCR_VBUSVLDEXTSEL;
  811         reg &= ~(PCR_OTG_DISABLE);
  812         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  813 
  814         /* Reset USB */
  815         reg = CSR_READ_4(sc, JZ_USBPCR);
  816         reg |= PCR_POR;
  817         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  818         DELAY(1000);
  819         reg = CSR_READ_4(sc, JZ_USBPCR);
  820         reg &= ~(PCR_POR);
  821         CSR_WRITE_4(sc, JZ_USBPCR, reg);
  822 
  823         /* Unsuspend OTG port */
  824         reg = CSR_READ_4(sc, JZ_OPCR);
  825         reg |= OPCR_SPENDN0;
  826         CSR_WRITE_4(sc, JZ_OPCR, reg);
  827 
  828         CGU_UNLOCK(sc);
  829         return (0);
  830 }

Cache object: 57a3250348d22eb008b93a0c95c93b30


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