Path: blob/main/sys/dev/clk/rockchip/rk3568_pmucru.c
39536 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2021, 2022 Soren Schmidt <[email protected]>4* Copyright (c) 2023, Emmanuel Vadot <[email protected]>5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR16* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* 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 CAUSED22* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#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>3536#include <dev/fdt/simplebus.h>3738#include <dev/ofw/ofw_bus.h>39#include <dev/ofw/ofw_bus_subr.h>4041#include <dev/clk/clk_div.h>42#include <dev/clk/clk_fixed.h>43#include <dev/clk/clk_mux.h>4445#include <dev/clk/rockchip/rk_cru.h>46#include <contrib/device-tree/include/dt-bindings/clock/rk3568-cru.h>474849#define CRU_PLLSEL_CON(x) ((x) * 0x20)50#define CRU_CLKSEL_CON(x) ((x) * 0x4 + 0x100)51#define CRU_CLKGATE_CON(x) ((x) * 0x4 + 0x180)5253/* PLL clock */54#define RK_PLL(_id, _name, _pnames, _off, _shift) \55{ \56.type = RK3328_CLK_PLL, \57.clk.pll = &(struct rk_clk_pll_def) { \58.clkdef.id = _id, \59.clkdef.name = _name, \60.clkdef.parent_names = _pnames, \61.clkdef.parent_cnt = nitems(_pnames), \62.clkdef.flags = CLK_NODE_STATIC_STRINGS, \63.base_offset = CRU_PLLSEL_CON(_off), \64.mode_reg = 0x80, \65.mode_shift = _shift, \66.rates = rk3568_pll_rates, \67}, \68}6970extern struct rk_clk_pll_rate rk3568_pll_rates[];7172/* Parent clock defines */73PLIST(mux_pll_p) = { "xin24m" };74PLIST(xin24m_32k_p) = { "xin24m", "clk_rtc_32k" };75PLIST(sclk_uart0_p) = { "sclk_uart0_div", "sclk_uart0_frac", "xin24m" };76PLIST(sclk_uart0_div_p) = { "ppll", "usb480m", "cpll", "gpll" };77PLIST(clk_rtc32k_pmu_p) = { "clk_32k_pvtm", "xin32k", "clk_osc0_div32k" };78PLIST(clk_usbphy0_ref_p) = { "clk_ref24m", "xin_osc0_usbphy0_g" };79PLIST(clk_usbphy1_ref_p) = { "clk_ref24m", "xin_osc0_usbphy1_g" };80PLIST(clk_mipidsiphy0_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy0_g" };81PLIST(clk_mipidsiphy1_ref_p) = { "clk_ref24m", "xin_osc0_mipidsiphy1_g" };82PLIST(clk_wifi_p) = { "clk_wifi_osc0", "clk_wifi_div" };83PLIST(clk_pciephy0_ref_p) = { "clk_pciephy0_osc0", "clk_pciephy0_div" };84PLIST(clk_pciephy1_ref_p) = { "clk_pciephy1_osc0", "clk_pciephy1_div" };85PLIST(clk_pciephy2_ref_p) = { "clk_pciephy2_osc0", "clk_pciephy2_div" };86PLIST(clk_hdmi_ref_p) = { "hpll", "hpll_ph0" };87PLIST(clk_pdpmu_p) = { "ppll", "gpll" };88PLIST(clk_pwm0_p) = { "xin24m", "clk_pdpmu" };8990/* CLOCKS */91static struct rk_clk rk3568_clks[] = {92/* External clocks */93LINK("xin24m"),94LINK("cpll"),95LINK("gpll"),96LINK("usb480m"),97LINK("clk_32k_pvtm"),9899/* Fixed clocks */100FFACT(0, "ppll_ph0", "ppll", 1, 2),101FFACT(0, "ppll_ph180", "ppll", 1, 2),102FFACT(0, "hpll_ph0", "hpll", 1, 2),103104/* PLL's */105RK_PLL(PLL_PPLL, "ppll", mux_pll_p, 0, 0),106RK_PLL(PLL_HPLL, "hpll", mux_pll_p, 2, 2),107108/* PMUCRU_PMUCLKSEL_CON00 */109CDIV(0, "xin_osc0_div_div", "xin24m", 0, 0, 0, 5),110MUX(0, "clk_rtc_32k_mux", clk_rtc32k_pmu_p, 0, 0, 6, 2),111112/* PMUCRU_PMUCLKSEL_CON01 */113FRACT(0, "clk_osc0_div32k", "xin24m", 0, 1),114115/* PMUCRU_PMUCLKSEL_CON02 */116CDIV(0, "pclk_pdpmu_pre", "clk_pdpmu", 0, 2, 0, 5),117MUX(CLK_PDPMU, "clk_pdpmu", clk_pdpmu_p, 0, 2, 15, 1),118119/* PMUCRU_PMUCLKSEL_CON03 */120CDIV(0, "clk_i2c0_div", "clk_pdpmu", 0, 3, 0, 7),121122/* PMUCRU_PMUCLKSEL_CON04 */123CDIV(0, "sclk_uart0_div_div", "sclk_uart0_div_sel", 0, 4, 0, 7),124MUX(0, "sclk_uart0_div_sel", sclk_uart0_div_p, 0, 4, 8, 2),125MUX(0, "sclk_uart0_mux", sclk_uart0_p, 0, 4, 10, 2),126127/* PMUCRU_PMUCLKSEL_CON05 */128FRACT(0, "sclk_uart0_frac_div", "sclk_uart0_div", 0, 5),129130/* PMUCRU_PMUCLKSEL_CON06 */131CDIV(0, "clk_pwm0_div", "clk_pwm0_sel", 0, 6, 0, 7),132MUX(0, "clk_pwm0_sel", clk_pwm0_p, 0, 6, 7, 1),133MUX(0, "dbclk_gpio0_sel", xin24m_32k_p, 0, 6, 15, 1),134135/* PMUCRU_PMUCLKSEL_CON07 */136CDIV(0, "clk_ref24m_div", "clk_pdpmu", 0, 7, 0, 6),137138/* PMUCRU_PMUCLKSEL_CON08 */139MUX(CLK_USBPHY0_REF, "clk_usbphy0_ref", clk_usbphy0_ref_p, 0, 8, 0, 1),140MUX(CLK_USBPHY1_REF, "clk_usbphy1_ref", clk_usbphy1_ref_p, 0, 8, 1, 1),141MUX(CLK_MIPIDSIPHY0_REF, "clk_mipidsiphy0_ref", clk_mipidsiphy0_ref_p, 0, 8, 2, 1),142MUX(CLK_MIPIDSIPHY1_REF, "clk_mipidsiphy1_ref", clk_mipidsiphy1_ref_p, 0, 8, 3, 1),143MUX(CLK_HDMI_REF, "clk_hdmi_ref", clk_hdmi_ref_p, 0, 8, 7, 1),144CDIV(0, "clk_wifi_div_div", "clk_pdpmu", 0, 8, 8, 6),145MUX(CLK_WIFI, "clk_wifi", clk_wifi_p, 0, 8, 15, 1),146147/* PMUCRU_PMUCLKSEL_CON09 */148CDIV(0, "clk_pciephy0_div_div", "ppll_ph0", 0, 9, 0, 3),149MUX(CLK_PCIEPHY0_REF, "clk_pciephy0_ref",150clk_pciephy0_ref_p, 0, 9, 3, 1),151CDIV(0, "clk_pciephy1_div_div", "ppll_ph0", 0, 9, 4, 3),152MUX(CLK_PCIEPHY1_REF, "clk_pciephy1_ref",153clk_pciephy1_ref_p, 0, 9, 7, 1),154CDIV(0, "clk_pciephy2_div_div", "ppll_ph0", 0, 9, 8, 3),155MUX(CLK_PCIEPHY2_REF, "clk_pciephy2_ref",156clk_pciephy2_ref_p, 0, 9, 11, 1),157};158159/* GATES */160static struct rk_cru_gate rk3568_gates[] = {161/* PMUCRU_PMUGATE_CON00 */162GATE(XIN_OSC0_DIV, "xin_osc0_div", "xin_osc0_div_div", 0, 0),163GATE(CLK_RTC_32K, "clk_rtc_32k", "clk_rtc_32k_mux", 0, 1),164GATE(PCLK_PDPMU, "pclk_pdpmu", "pclk_pdpmu_pre", 0, 2),165GATE(PCLK_PMU, "pclk_pmu", "pclk_pdpmu", 0, 6),166GATE(CLK_PMU, "clk_pmu", "xin24m", 0, 7),167168/* PMUCRU_PMUGATE_CON01 */169GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pdpmu", 1, 0),170GATE(CLK_I2C0, "clk_i2c0", "clk_i2c0_div", 1, 1),171GATE(PCLK_UART0, "pclk_uart0", "pclk_pdpmu", 1, 2),172GATE(CLK_UART0_DIV, "sclk_uart0_div", "sclk_uart0_div_div", 1, 3),173GATE(CLK_UART0_FRAC, "sclk_uart0_frac", "sclk_uart0_frac_div", 1, 4),174GATE(SCLK_UART0, "sclk_uart0", "sclk_uart0_mux", 1, 5),175GATE(PCLK_PWM0, "pclk_pwm0", "pclk_pdpmu", 1, 6),176GATE(CLK_PWM0, "clk_pwm0", "clk_pwm0_div", 1, 7),177GATE(CLK_CAPTURE_PWM0_NDFT, "clk_capture_pwm0_ndft", "xin24m", 1, 8),178GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pdpmu", 1, 9),179GATE(DBCLK_GPIO0, "dbclk_gpio0", "dbclk_gpio0_sel", 1, 10),180GATE(PCLK_PMUPVTM, "pclk_pmupvtm", "pclk_pdpmu", 1, 11),181GATE(CLK_PMUPVTM, "clk_pmupvtm", "xin24m", 1, 12),182GATE(CLK_CORE_PMUPVTM, "clk_core_pmupvtm", "xin24m", 1, 13),183184/* PMUCRU_PMUGATE_CON02 */185GATE(CLK_REF24M, "clk_ref24m", "clk_ref24m_div", 2, 0),186GATE(XIN_OSC0_USBPHY0_G, "xin_osc0_usbphy0_g", "xin24m", 2, 1),187GATE(XIN_OSC0_USBPHY1_G, "xin_osc0_usbphy1_g", "xin24m", 2, 2),188GATE(XIN_OSC0_MIPIDSIPHY0_G, "xin_osc0_mipidsiphy0_g", "xin24m", 2, 3),189GATE(XIN_OSC0_MIPIDSIPHY1_G, "xin_osc0_mipidsiphy1_g", "xin24m", 2, 4),190GATE(CLK_WIFI_DIV, "clk_wifi_div", "clk_wifi_div_div", 2, 5),191GATE(CLK_WIFI_OSC0, "clk_wifi_osc0", "xin24m", 2, 6),192GATE(CLK_PCIEPHY0_DIV, "clk_pciephy0_div", "clk_pciephy0_div_div", 2, 7),193GATE(CLK_PCIEPHY0_OSC0, "clk_pciephy0_osc0", "xin24m", 2, 8),194GATE(CLK_PCIEPHY1_DIV, "clk_pciephy1_div", "clk_pciephy1_div_div", 2, 9),195GATE(CLK_PCIEPHY1_OSC0, "clk_pciephy1_osc0", "xin24m", 2, 10),196GATE(CLK_PCIEPHY2_DIV, "clk_pciephy2_div", "clk_pciephy2_div_div", 2, 11),197GATE(CLK_PCIEPHY2_OSC0, "clk_pciephy2_osc0", "xin24m", 2, 12),198GATE(CLK_PCIE30PHY_REF_M, "clk_pcie30phy_ref_m", "ppll_ph0", 2, 13),199GATE(CLK_PCIE30PHY_REF_N, "clk_pcie30phy_ref_n", "ppll_ph180", 2, 14),200GATE(XIN_OSC0_EDPPHY_G, "xin_osc0_edpphy_g", "xin24m", 2, 15),201};202203static int204rk3568_pmucru_probe(device_t dev)205{206207if (!ofw_bus_status_okay(dev))208return (ENXIO);209210if (ofw_bus_is_compatible(dev, "rockchip,rk3568-pmucru")) {211device_set_desc(dev, "Rockchip RK3568 PMU Clock & Reset Unit");212return (BUS_PROBE_DEFAULT);213}214215return (ENXIO);216}217218static int219rk3568_pmucru_attach(device_t dev)220{221struct rk_cru_softc *sc;222223sc = device_get_softc(dev);224sc->dev = dev;225sc->clks = rk3568_clks;226sc->nclks = nitems(rk3568_clks);227sc->gates = rk3568_gates;228sc->ngates = nitems(rk3568_gates);229sc->reset_offset = 0x200;230sc->reset_num = 4;231232return (rk_cru_attach(dev));233}234235static device_method_t methods[] = {236/* Device interface */237DEVMETHOD(device_probe, rk3568_pmucru_probe),238DEVMETHOD(device_attach, rk3568_pmucru_attach),239240DEVMETHOD_END241};242243DEFINE_CLASS_1(rk3568_pmucru, rk3568_pmucru_driver, methods,244sizeof(struct rk_cru_softc), rk_cru_driver);245246EARLY_DRIVER_MODULE(rk3568_pmucru, simplebus, rk3568_pmucru_driver,2470, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);248249250