Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/rockchip/clk/px30_cru.c
- This file was added.
/*- | |||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2021 Roger Pau Monné <royger@freebsd.org> | |||||
* Copyright (c) 2018 Emmanuel Vadot <manu@freebsd.org> | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | |||||
* modification, are permitted provided that the following conditions | |||||
* are met: | |||||
* 1. Redistributions of source code must retain the above copyright | |||||
* notice, this list of conditions and the following disclaimer. | |||||
* 2. Redistributions in binary form must reproduce the above copyright | |||||
* notice, this list of conditions and the following disclaimer in the | |||||
* documentation and/or other materials provided with the distribution. | |||||
* | |||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||
* SUCH DAMAGE. | |||||
* | |||||
* $FreeBSD$ | |||||
*/ | |||||
#include <sys/cdefs.h> | |||||
__FBSDID("$FreeBSD$"); | |||||
#include <sys/param.h> | |||||
#include <sys/systm.h> | |||||
#include <sys/bus.h> | |||||
#include <sys/rman.h> | |||||
#include <sys/kernel.h> | |||||
#include <sys/module.h> | |||||
#include <machine/bus.h> | |||||
#include <dev/fdt/simplebus.h> | |||||
#include <dev/ofw/ofw_bus.h> | |||||
#include <dev/ofw/ofw_bus_subr.h> | |||||
#include <dev/extres/clk/clk_div.h> | |||||
#include <dev/extres/clk/clk_fixed.h> | |||||
#include <dev/extres/clk/clk_mux.h> | |||||
#include <arm64/rockchip/clk/rk_cru.h> | |||||
/* GATES */ | |||||
#define HCLK_SDMMC 247 | |||||
#define HCLK_USB 248 | |||||
#define HCLK_HOST 259 | |||||
#define PCLK_I2C0 334 | |||||
#define PCLK_I2C1 335 | |||||
#define PCLK_I2C2 336 | |||||
#define PCLK_I2C3 337 | |||||
static struct rk_cru_gate gates[] = { | |||||
/* CRU_CLKGATE_CON0 */ | |||||
CRU_GATE(0, "apll_core", "apll", 0x200, 0) | |||||
CRU_GATE(0, "gpll_core", "gpll", 0x200, 0) | |||||
/* CRU_CLKGATE_CON6 */ | |||||
CRU_GATE(0, "hclk_sdmmc_pre", "hclk_peri_pre", 0x218, 12) | |||||
/* CRU_CLKGATE_CON7 */ | |||||
CRU_GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_sdmmc_pre", 0x21c, 1) | |||||
CRU_GATE(HCLK_USB, "hclk_usb", "hclk_peri_pre", 0x21c, 2) | |||||
CRU_GATE(HCLK_HOST, "hclk_host", "hclk_usb", 0x21c, 6) | |||||
/* CRU_CLKGATE_CON14 */ | |||||
CRU_GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus_pre", 0x238, 10) | |||||
CRU_GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus_pre", 0x238, 11) | |||||
CRU_GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus_pre", 0x238, 12) | |||||
CRU_GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus_pre", 0x238, 13) | |||||
}; | |||||
/* | |||||
* PLLs | |||||
*/ | |||||
#define PLL_APLL 1 | |||||
#define PLL_DPLL 2 | |||||
#define PLL_CPLL 3 | |||||
#define PLL_GPLL 4 | |||||
#define PLL_NPLL 5 | |||||
static struct rk_clk_pll_rate pll_rates[] = { | |||||
{ | |||||
.freq = 1608000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 67, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1584000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 66, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1560000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 65, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1536000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 64, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1512000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 63, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1488000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 62, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1464000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 61, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1440000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 60, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1416000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 59, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1392000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 58, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1368000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 57, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1344000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 56, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1320000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 55, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1296000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 54, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1272000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 53, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1248000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 52, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1200000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 50, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1188000000, | |||||
.refdiv = 2, | |||||
.fbdiv = 99, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1104000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 46, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1100000000, | |||||
.refdiv = 12, | |||||
.fbdiv = 550, | |||||
.postdiv1 = 1, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1008000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 84, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 1000000000, | |||||
.refdiv = 6, | |||||
.fbdiv = 500, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 984000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 82, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 960000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 80, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 936000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 78, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 912000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 76, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 900000000, | |||||
.refdiv = 4, | |||||
.fbdiv = 300, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 888000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 74, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 864000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 72, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 840000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 70, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 816000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 68, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 800000000, | |||||
.refdiv = 6, | |||||
.fbdiv = 400, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 700000000, | |||||
.refdiv = 6, | |||||
.fbdiv = 350, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 696000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 58, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 600000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 75, | |||||
.postdiv1 = 3, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 594000000, | |||||
.refdiv = 2, | |||||
.fbdiv = 99, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 504000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 63, | |||||
.postdiv1 = 3, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 500000000, | |||||
.refdiv = 6, | |||||
.fbdiv = 250, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 1, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 408000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 68, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 2, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 312000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 52, | |||||
.postdiv1 = 2, | |||||
.postdiv2 = 2, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 216000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 72, | |||||
.postdiv1 = 4, | |||||
.postdiv2 = 2, | |||||
.dsmpd = 1, | |||||
}, | |||||
{ | |||||
.freq = 96000000, | |||||
.refdiv = 1, | |||||
.fbdiv = 64, | |||||
.postdiv1 = 4, | |||||
.postdiv2 = 4, | |||||
.dsmpd = 1, | |||||
}, | |||||
{}, | |||||
}; | |||||
static const char *pll_parents[] = {"xin24m"}; | |||||
static struct rk_clk_pll_def apll = { | |||||
.clkdef = { | |||||
.id = PLL_APLL, | |||||
.name = "apll", | |||||
.parent_names = pll_parents, | |||||
.parent_cnt = nitems(pll_parents), | |||||
}, | |||||
.base_offset = 0, | |||||
.mode_reg = 0xa0, | |||||
.mode_shift = 0, | |||||
.rates = pll_rates, | |||||
}; | |||||
static struct rk_clk_pll_def dpll = { | |||||
.clkdef = { | |||||
.id = PLL_DPLL, | |||||
.name = "dpll", | |||||
.parent_names = pll_parents, | |||||
.parent_cnt = nitems(pll_parents), | |||||
}, | |||||
.base_offset = 0x20, | |||||
.mode_reg = 0xa0, | |||||
.mode_shift = 4, | |||||
}; | |||||
static struct rk_clk_pll_def cpll = { | |||||
.clkdef = { | |||||
.id = PLL_CPLL, | |||||
.name = "cpll", | |||||
.parent_names = pll_parents, | |||||
.parent_cnt = nitems(pll_parents), | |||||
}, | |||||
.base_offset = 0x40, | |||||
.mode_reg = 0xa0, | |||||
.mode_shift = 2, | |||||
.rates = pll_rates, | |||||
}; | |||||
static struct rk_clk_pll_def npll = { | |||||
.clkdef = { | |||||
.id = PLL_NPLL, | |||||
.name = "npll", | |||||
.parent_names = pll_parents, | |||||
.parent_cnt = nitems(pll_parents), | |||||
}, | |||||
.base_offset = 0x60, | |||||
.mode_reg = 0xa0, | |||||
.mode_shift = 6, | |||||
.rates = pll_rates, | |||||
}; | |||||
#define ACLK_BUS_PRE 171 | |||||
static const char *aclk_bus_pre_parents[] = {"gpll", "cpll"}; | |||||
static struct rk_clk_composite_def aclk_bus_pre = { | |||||
.clkdef = { | |||||
.id = ACLK_BUS_PRE, | |||||
.name = "aclk_bus_pre", | |||||
.parent_names = aclk_bus_pre_parents, | |||||
.parent_cnt = nitems(aclk_bus_pre_parents), | |||||
}, | |||||
/* CRU_CLKSEL_CON23 */ | |||||
.muxdiv_offset = 0x15c, | |||||
.mux_shift = 15, | |||||
.mux_width = 1, | |||||
.div_shift = 8, | |||||
.div_width = 5, | |||||
/* CRU_CLKGATE_CON8 */ | |||||
.gate_offset = 0x220, | |||||
.gate_shift = 7, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
#define PX30_FREQ(f) { .freq = f, .div = 1 } | |||||
static struct rk_clk_armclk_rates armclk_rates[] = { | |||||
PX30_FREQ(1608000000), | |||||
PX30_FREQ(1584000000), | |||||
PX30_FREQ(1560000000), | |||||
PX30_FREQ(1536000000), | |||||
PX30_FREQ(1512000000), | |||||
PX30_FREQ(1488000000), | |||||
PX30_FREQ(1464000000), | |||||
PX30_FREQ(1440000000), | |||||
PX30_FREQ(1416000000), | |||||
PX30_FREQ(1392000000), | |||||
PX30_FREQ(1368000000), | |||||
PX30_FREQ(1344000000), | |||||
PX30_FREQ(1320000000), | |||||
PX30_FREQ(1296000000), | |||||
PX30_FREQ(1272000000), | |||||
PX30_FREQ(1248000000), | |||||
PX30_FREQ(1224000000), | |||||
PX30_FREQ(1200000000), | |||||
PX30_FREQ(1104000000), | |||||
PX30_FREQ(1008000000), | |||||
PX30_FREQ(912000000), | |||||
PX30_FREQ(816000000), | |||||
PX30_FREQ(696000000), | |||||
PX30_FREQ(600000000), | |||||
PX30_FREQ(408000000), | |||||
PX30_FREQ(312000000), | |||||
PX30_FREQ(216000000), | |||||
PX30_FREQ(96000000), | |||||
}; | |||||
#define ARMCLK 7 | |||||
static const char *armclk_parents[] = {"apll", "gpll"}; | |||||
static struct rk_clk_armclk_def armclk = { | |||||
.clkdef = { | |||||
.id = ARMCLK, | |||||
.name = "armclk", | |||||
.parent_names = armclk_parents, | |||||
.parent_cnt = nitems(armclk_parents), | |||||
}, | |||||
.muxdiv_offset = 0x100, | |||||
.mux_shift = 7, | |||||
.mux_width = 1, | |||||
.div_shift = 0, | |||||
.div_width = 4, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX, | |||||
.main_parent = 0, /* apll */ | |||||
.alt_parent = 1, /* gpll */ | |||||
.rates = armclk_rates, | |||||
.nrates = nitems(armclk_rates), | |||||
}; | |||||
/* CRU_CLKSEL_CON24 */ | |||||
#define PCLK_BUS_PRE 320 | |||||
#define HCLK_BUS_PRE 240 | |||||
static const char *hclk_bus_pre_parents[] = {"aclk_bus_pre"}; | |||||
static struct rk_clk_composite_def hclk_bus_pre = { | |||||
.clkdef = { | |||||
.id = HCLK_BUS_PRE, | |||||
.name = "hclk_bus_pre", | |||||
.parent_names = hclk_bus_pre_parents, | |||||
.parent_cnt = nitems(hclk_bus_pre_parents), | |||||
}, | |||||
.muxdiv_offset = 0x160, | |||||
.div_shift = 0, | |||||
.div_width = 5, | |||||
.gate_offset = 0x220, | |||||
.gate_shift = 8, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
static const char *pclk_bus_pre_parents[] = {"aclk_bus_pre"}; | |||||
static struct rk_clk_composite_def pclk_bus_pre = { | |||||
.clkdef = { | |||||
.id = PCLK_BUS_PRE, | |||||
.name = "pclk_bus_pre", | |||||
.parent_names = pclk_bus_pre_parents, | |||||
.parent_cnt = nitems(pclk_bus_pre_parents), | |||||
}, | |||||
.muxdiv_offset = 0x160, | |||||
.div_shift = 8, | |||||
.div_width = 2, | |||||
.gate_offset = 0x220, | |||||
.gate_shift = 9, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
/* CRU_CLKSEL_CON54 */ | |||||
#define SCLK_TSADC 44 | |||||
static const char *clk_tsadc_parents[] = {"xin24m"}; | |||||
static struct rk_clk_composite_def clk_tsadc = { | |||||
.clkdef = { | |||||
.id = SCLK_TSADC, | |||||
.name = "clk_tsadc", | |||||
.parent_names = clk_tsadc_parents, | |||||
.parent_cnt = nitems(clk_tsadc_parents), | |||||
}, | |||||
.muxdiv_offset = 0x1d8, | |||||
.div_shift = 0, | |||||
.div_width = 11, | |||||
.gate_offset = 0x230, | |||||
.gate_shift = 9, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
/* CRU_CLKSEL_CON14 */ | |||||
#define ACLK_PERI_PRE 176 | |||||
#define HCLK_PERI_PRE 245 | |||||
static const char *aclk_peri_pre_parents[] = {"gpll", "cpll"}; | |||||
static struct rk_clk_composite_def aclk_peri_pre = { | |||||
.clkdef = { | |||||
.id = ACLK_PERI_PRE, | |||||
.name = "aclk_peri_pre", | |||||
.parent_names = aclk_peri_pre_parents, | |||||
.parent_cnt = nitems(aclk_peri_pre_parents), | |||||
}, | |||||
.muxdiv_offset = 0x138, | |||||
.div_shift = 0, | |||||
.div_width = 5, | |||||
.gate_offset = 0x214, | |||||
.gate_shift = 8, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
static const char *hclk_peri_pre_parents[] = {"aclk_peri_pre"}; | |||||
static struct rk_clk_composite_def hclk_peri_pre = { | |||||
.clkdef = { | |||||
.id = HCLK_PERI_PRE, | |||||
.name = "hclk_peri_pre", | |||||
.parent_names = hclk_peri_pre_parents, | |||||
.parent_cnt = nitems(hclk_peri_pre_parents), | |||||
}, | |||||
/* CRU_CLKSEL_CON14 */ | |||||
.muxdiv_offset = 0x160, | |||||
.div_shift = 8, | |||||
.div_width = 5, | |||||
}; | |||||
/* CRU_CLKSEL_CON16 */ | |||||
#define SCLK_SDMMC 59 | |||||
static const char *mmc_parents[] = {"gpll", "cpll", "npll", "xin24m"}; | |||||
static struct rk_clk_composite_def sdmmc = { | |||||
.clkdef = { | |||||
.id = SCLK_SDMMC, | |||||
.name = "clk_sdmmc", | |||||
.parent_names = mmc_parents, | |||||
.parent_cnt = nitems(mmc_parents), | |||||
}, | |||||
.muxdiv_offset = 0x140, | |||||
.mux_shift = 14, | |||||
.mux_width = 2, | |||||
.div_shift = 0, | |||||
.div_width = 8, | |||||
/* CRU_CLKGATE_CON6 */ | |||||
.gate_offset = 0x218, | |||||
.gate_shift = 15, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
/* CRU_CLKSEL_CON18 */ | |||||
#define SCLK_SDIO 56 | |||||
static struct rk_clk_composite_def sdio = { | |||||
.clkdef = { | |||||
.id = SCLK_SDIO, | |||||
.name = "clk_sdio", | |||||
.parent_names = mmc_parents, | |||||
.parent_cnt = nitems(mmc_parents), | |||||
}, | |||||
.muxdiv_offset = 0x148, | |||||
.mux_shift = 14, | |||||
.mux_width = 2, | |||||
.div_shift = 0, | |||||
.div_width = 8, | |||||
/* CRU_CLKGATE_CON6 */ | |||||
.gate_offset = 0x218, | |||||
.gate_shift = 9, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
/* CRU_CLKSEL_CON20 */ | |||||
#define SCLK_EMMC 57 | |||||
static struct rk_clk_composite_def emmc = { | |||||
.clkdef = { | |||||
.id = SCLK_EMMC, | |||||
.name = "clk_emmc", | |||||
.parent_names = mmc_parents, | |||||
.parent_cnt = nitems(mmc_parents), | |||||
}, | |||||
.muxdiv_offset = 0x150, | |||||
.mux_shift = 14, | |||||
.mux_width = 2, | |||||
.div_shift = 0, | |||||
.div_width = 8, | |||||
/* CRU_CLKGATE_CON6 */ | |||||
.gate_offset = 0x218, | |||||
.gate_shift = 6, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
/* CRU_CLKSEL_CON49 */ | |||||
#define SCLK_I2C0 29 | |||||
#define SCLK_I2C1 30 | |||||
static const char *i2c_parents[] = {"gpll", "xin24m"}; | |||||
static struct rk_clk_composite_def i2c0 = { | |||||
.clkdef = { | |||||
.id = SCLK_I2C0, | |||||
.name = "clk_i2c0", | |||||
.parent_names = i2c_parents, | |||||
.parent_cnt = nitems(i2c_parents), | |||||
}, | |||||
.muxdiv_offset = 0x1c4, | |||||
.mux_shift = 7, | |||||
.mux_width = 1, | |||||
.div_shift = 0, | |||||
.div_width = 7, | |||||
/* CRU_CLKGATE_CON12 */ | |||||
.gate_offset = 0x230, | |||||
.gate_shift = 0, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
static struct rk_clk_composite_def i2c1 = { | |||||
.clkdef = { | |||||
.id = SCLK_I2C1, | |||||
.name = "clk_i2c1", | |||||
.parent_names = i2c_parents, | |||||
.parent_cnt = nitems(i2c_parents), | |||||
}, | |||||
.muxdiv_offset = 0x1c4, | |||||
.mux_shift = 15, | |||||
.mux_width = 1, | |||||
.div_shift = 8, | |||||
.div_width = 7, | |||||
/* CRU_CLKGATE_CON12 */ | |||||
.gate_offset = 0x230, | |||||
.gate_shift = 1, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
/* CRU_CLKSEL_CON50 */ | |||||
#define SCLK_I2C2 31 | |||||
#define SCLK_I2C3 32 | |||||
static struct rk_clk_composite_def i2c2 = { | |||||
.clkdef = { | |||||
.id = SCLK_I2C2, | |||||
.name = "clk_i2c2", | |||||
.parent_names = i2c_parents, | |||||
.parent_cnt = nitems(i2c_parents), | |||||
}, | |||||
.muxdiv_offset = 0x18c, | |||||
.mux_shift = 7, | |||||
.mux_width = 1, | |||||
.div_shift = 0, | |||||
.div_width = 7, | |||||
/* CRU_CLKGATE_CON12 */ | |||||
.gate_offset = 0x230, | |||||
.gate_shift = 2, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
static struct rk_clk_composite_def i2c3 = { | |||||
.clkdef = { | |||||
.id = SCLK_I2C3, | |||||
.name = "clk_i2c3", | |||||
.parent_names = i2c_parents, | |||||
.parent_cnt = nitems(i2c_parents), | |||||
}, | |||||
.muxdiv_offset = 0x18c, | |||||
.mux_shift = 15, | |||||
.mux_width = 1, | |||||
.div_shift = 8, | |||||
.div_width = 7, | |||||
/* CRU_CLKGATE_CON12 */ | |||||
.gate_offset = 0x230, | |||||
.gate_shift = 3, | |||||
.flags = RK_CLK_COMPOSITE_HAVE_MUX | RK_CLK_COMPOSITE_HAVE_GATE, | |||||
}; | |||||
static struct rk_clk clks[] = { | |||||
{ | |||||
.type = RK3328_CLK_PLL, | |||||
.clk.pll = &apll | |||||
}, | |||||
{ | |||||
.type = RK3328_CLK_PLL, | |||||
.clk.pll = &dpll | |||||
}, | |||||
{ | |||||
.type = RK3328_CLK_PLL, | |||||
.clk.pll = &cpll | |||||
}, | |||||
{ | |||||
.type = RK3328_CLK_PLL, | |||||
.clk.pll = &npll | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &aclk_bus_pre | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &hclk_bus_pre | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &pclk_bus_pre | |||||
}, | |||||
{ | |||||
.type = RK_CLK_ARMCLK, | |||||
.clk.armclk = &armclk, | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &clk_tsadc, | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &aclk_peri_pre, | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &hclk_peri_pre, | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &sdmmc | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &sdio | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &emmc | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &i2c0 | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &i2c1 | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &i2c2 | |||||
}, | |||||
{ | |||||
.type = RK_CLK_COMPOSITE, | |||||
.clk.composite = &i2c3 | |||||
}, | |||||
}; | |||||
extern bool pmucru_attached; | |||||
static int | |||||
probe(device_t dev) | |||||
{ | |||||
if (!ofw_bus_status_okay(dev)) | |||||
return (ENXIO); | |||||
//printf("probe cru\n"); | |||||
if (ofw_bus_is_compatible(dev, "rockchip,px30-cru") && | |||||
/* XXX: CRU depends on the GPLL clock declared in PMUCRU. */ | |||||
pmucru_attached) { | |||||
device_set_desc(dev, "Rockchip PX30 Clock and Reset Unit"); | |||||
return (BUS_PROBE_DEFAULT); | |||||
} | |||||
return (ENXIO); | |||||
} | |||||
static int | |||||
attach(device_t dev) | |||||
{ | |||||
struct rk_cru_softc *sc; | |||||
sc = device_get_softc(dev); | |||||
sc->dev = dev; | |||||
sc->gates = gates; | |||||
sc->ngates = nitems(gates); | |||||
sc->clks = clks; | |||||
sc->nclks = nitems(clks); | |||||
sc->reset_offset = 0x300; | |||||
sc->reset_num = 184; | |||||
return (rk_cru_attach(dev)); | |||||
} | |||||
static device_method_t methods[] = { | |||||
/* Device interface */ | |||||
DEVMETHOD(device_probe, probe), | |||||
DEVMETHOD(device_attach, attach), | |||||
DEVMETHOD_END | |||||
}; | |||||
static devclass_t devclass; | |||||
DEFINE_CLASS_1(px30_cru, px30_cru_driver, methods, | |||||
sizeof(struct rk_cru_softc), rk_cru_driver); | |||||
EARLY_DRIVER_MODULE(px30_cru, simplebus, px30_cru_driver, | |||||
devclass, 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); |