Index: sys/arm64/conf/std.rockchip =================================================================== --- sys/arm64/conf/std.rockchip +++ sys/arm64/conf/std.rockchip @@ -6,6 +6,8 @@ options SOC_ROCKCHIP_RK3328 options SOC_ROCKCHIP_RK3399 options SOC_ROCKCHIP_RK3568 +options SOC_ROCKCHIP_RK3308 + # GPIO / PINCTRL device dwgpio # Synopsys DesignWare APB GPIO Controller Index: sys/arm64/rockchip/clk/rk3308_cru.c =================================================================== --- /dev/null +++ sys/arm64/rockchip/clk/rk3308_cru.c @@ -0,0 +1,722 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + + +#define RK3308_PLLSEL_CON(x) ((x) * 0x20) +#define RK3308_CLKSEL_CON(x) ((x) * 0x4 + 0x100) +#define RK3308_CLKGATE_CON(x) ((x) * 0x4 + 0x300) +#define RK3308_GLB_SRST_FST 0xb8 +#define RK3308_SOFTRST_CON(x) ((x) * 0x4 + 0x400) +#define RK3308_MODE_CON 0xa0 +#define RK3308_SDMMC_CON0 0x480 +#define RK3308_SDMMC_CON1 0x484 +#define RK3308_SDIO_CON0 0x488 +#define RK3308_SDIO_CON1 0x48c +#define RK3308_EMMC_CON0 0x490 +#define RK3308_EMMC_CON1 0x494 + + +#define PNAME(_name) static const char *_name[] + + +#define RK_PLLRATE(_hz, _ref, _fb, _post1, _post2, _dspd) \ +{ \ + .freq = _hz, \ + .refdiv = _ref, \ + .fbdiv = _fb, \ + .postdiv1 = _post1, \ + .postdiv2 = _post2, \ + .dsmpd = _dspd, \ +} + +/* PLL clock */ +#define RK_PLL(_id, _name, _pnames, _off, _shift) \ +{ \ + .type = RK3328_CLK_PLL, \ + .clk.pll = &(struct rk_clk_pll_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = _pnames, \ + .clkdef.parent_cnt = nitems(_pnames), \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .base_offset = RK3308_PLLSEL_CON(_off), \ + .mode_reg = 0xc0, \ + .mode_shift = _shift, \ + .rates = rk3308_pll_rates, \ + }, \ +} + +/* Clock for ARM core(s) */ +#define RK_ARMDIV(_id, _nm, _pn, _r, _off, _ds, _dw, _ms, _mw, _mp, _ap)\ +{ \ + .type = RK_CLK_ARMCLK, \ + .clk.armclk = &(struct rk_clk_armclk_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _nm, \ + .clkdef.parent_names = _pn, \ + .clkdef.parent_cnt = nitems(_pn), \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .muxdiv_offset = RK3308_CLKSEL_CON(_off), \ + .mux_shift = _ms, \ + .mux_width = _mw, \ + .div_shift = _ds, \ + .div_width = _dw, \ + .main_parent = _mp, \ + .alt_parent = _ap, \ + .rates = _r, \ + .nrates = nitems(_r), \ + }, \ +} + +/* Composite */ +#define RK_COMPOSITE(_id, _name, _pnames, _o, _ms, _mw, _ds, _dw, _go, _gw,_f)\ +{ \ + .type = RK_CLK_COMPOSITE, \ + .clk.composite = &(struct rk_clk_composite_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = _pnames, \ + .clkdef.parent_cnt = nitems(_pnames), \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .muxdiv_offset = RK3308_CLKSEL_CON(_o), \ + .mux_shift = _ms, \ + .mux_width = _mw, \ + .div_shift = _ds, \ + .div_width = _dw, \ + .gate_offset = RK3308_CLKGATE_CON(_go), \ + .gate_shift = _gw, \ + .flags = RK_CLK_COMPOSITE_HAVE_MUX | \ + RK_CLK_COMPOSITE_HAVE_GATE | _f, \ + }, \ +} + +/* Composite no mux */ +#define RK_COMPNOMUX(_id, _name, _pname, _o, _ds, _dw, _go, _gw, _f) \ +{ \ + .type = RK_CLK_COMPOSITE, \ + .clk.composite = &(struct rk_clk_composite_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = (const char *[]){_pname}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .muxdiv_offset = RK3308_CLKSEL_CON(_o), \ + .div_shift = _ds, \ + .div_width = _dw, \ + .gate_offset = RK3308_CLKGATE_CON(_go), \ + .gate_shift = _gw, \ + .flags = RK_CLK_COMPOSITE_HAVE_GATE | _f, \ + }, \ +} + +/* Composite no div */ +#define RK_COMPNODIV(_id, _name, _pnames, _o, _ms, _mw, _go, _gw, _f) \ +{ \ + .type = RK_CLK_COMPOSITE, \ + .clk.composite = &(struct rk_clk_composite_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = _pnames, \ + .clkdef.parent_cnt = nitems(_pnames), \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .muxdiv_offset = RK3308_CLKSEL_CON(_o), \ + .mux_shift = _ms, \ + .mux_width = _mw, \ + .gate_offset = RK3308_CLKGATE_CON(_go), \ + .gate_shift = _gw, \ + .flags = RK_CLK_COMPOSITE_HAVE_MUX | \ + RK_CLK_COMPOSITE_HAVE_GATE | _f, \ + }, \ +} + +/* Composite div only */ +#define RK_COMPDIV(_id, _name, _pname, _o, _ds, _dw, _f) \ +{ \ + .type = RK_CLK_COMPOSITE, \ + .clk.composite = &(struct rk_clk_composite_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = (const char *[]){_pname}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .muxdiv_offset = RK3308_CLKSEL_CON(_o), \ + .div_shift = _ds, \ + .div_width = _dw, \ + .flags = _f, \ + }, \ +} + + +/* Fixed factor mux/div */ +#define RK_FACTOR(_id, _name, _pname, _mult, _div) \ +{ \ + .type = RK_CLK_FIXED, \ + .clk.fixed = &(struct clk_fixed_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = (const char *[]){_pname}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .mult = _mult, \ + .div = _div, \ + }, \ +} + + +#define RK_FACTOR_GATE(_id, cname, pname,f, fm, fd, go, gb, gf) \ + { \ + .type = RK_CLK_COMPOSITE, \ + .clk.composite = &(struct rk_clk_composite_def) { \ + .clkdef.id = _id, \ + .clkdef.name = cname, \ + .clkdef.parent_names = (const char *[]){ pname }, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .div_shift = fm, \ + .div_width = fd, \ + .gate_offset = go, \ + .gate_shift = gb, \ + .flags = RK_CLK_FRACT_HAVE_GATE | gf, \ + }, \ +} +/* Fractional */ +#define RK_FRACTION(_id, _name, _pname, _o, _go, _gw, _f) \ +{ \ + .type = RK_CLK_FRACT, \ + .clk.fract = &(struct rk_clk_fract_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = (const char *[]){_pname}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .offset = RK3308_CLKSEL_CON(_o), \ + .gate_offset = RK3308_CLKGATE_CON(_go), \ + .gate_shift = _gw, \ + .flags = RK_CLK_FRACT_HAVE_GATE | _f, \ + }, \ +} + +/* Multiplexer */ +#define RK_MUX(_id, _name, _pnames, _o, _ms, _mw, _f) \ +{ \ + .type = RK_CLK_MUX, \ + .clk.mux = &(struct rk_clk_mux_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = _pnames, \ + .clkdef.parent_cnt = nitems(_pnames), \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .offset = RK3308_CLKSEL_CON(_o), \ + .shift = _ms, \ + .width = _mw, \ + .mux_flags = _f, \ + }, \ +} + +#define RK_GATE(_id, _name, _pname, _o, _s) \ +{ \ + .id = _id, \ + .name = _name, \ + .parent_name = _pname, \ + .offset = RK3308_CLKGATE_CON(_o), \ + .shift = _s, \ +} +#define RK_MMC(_id, _name, _pname, _o, _ds) \ +{ \ + .type = RK_CLK_COMPOSITE, \ + .clk.composite = &(struct rk_clk_composite_def) { \ + .clkdef.id = _id, \ + .clkdef.name = _name, \ + .clkdef.parent_names = (const char *[]){_pname}, \ + .clkdef.parent_cnt = 1, \ + .clkdef.flags = CLK_NODE_STATIC_STRINGS, \ + .muxdiv_offset = RK3308_CLKSEL_CON(_o), \ + .div_shift = _ds, \ + }, \ +} + +struct rk_clk_pll_rate rk3308_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd */ + RK_PLLRATE(1608000000, 1, 67, 1, 1, 1), + RK_PLLRATE(1584000000, 1, 66, 1, 1, 1), + RK_PLLRATE(1560000000, 1, 65, 1, 1, 1), + RK_PLLRATE(1536000000, 1, 64, 1, 1, 1), + RK_PLLRATE(1512000000, 1, 63, 1, 1, 1), + RK_PLLRATE(1488000000, 1, 62, 1, 1, 1), + RK_PLLRATE(1464000000, 1, 61, 1, 1, 1), + RK_PLLRATE(1440000000, 1, 60, 1, 1, 1), + RK_PLLRATE(1416000000, 1, 59, 1, 1, 1), + RK_PLLRATE(1392000000, 1, 58, 1, 1, 1), + RK_PLLRATE(1368000000, 1, 57, 1, 1, 1), + RK_PLLRATE(1344000000, 1, 56, 1, 1, 1), + RK_PLLRATE(1320000000, 1, 55, 1, 1, 1), + RK_PLLRATE(1296000000, 1, 54, 1, 1, 1), + RK_PLLRATE(1272000000, 1, 53, 1, 1, 1), + RK_PLLRATE(1248000000, 1, 52, 1, 1, 1), + RK_PLLRATE(1200000000, 1, 50, 1, 1, 1), + RK_PLLRATE(1188000000, 2, 99, 1, 1, 1), + RK_PLLRATE(1104000000, 1, 46, 1, 1, 1), + RK_PLLRATE(1100000000, 12, 550, 1, 1, 1), + RK_PLLRATE(1008000000, 1, 84, 2, 1, 1), + RK_PLLRATE(1000000000, 6, 500, 2, 1, 1), + RK_PLLRATE(984000000, 1, 82, 2, 1, 1), + RK_PLLRATE(960000000, 1, 80, 2, 1, 1), + RK_PLLRATE(936000000, 1, 78, 2, 1, 1), + RK_PLLRATE(912000000, 1, 76, 2, 1, 1), + RK_PLLRATE(900000000, 4, 300, 2, 1, 1), + RK_PLLRATE(888000000, 1, 74, 2, 1, 1), + RK_PLLRATE(864000000, 1, 72, 2, 1, 1), + RK_PLLRATE(840000000, 1, 70, 2, 1, 1), + RK_PLLRATE(816000000, 1, 68, 2, 1, 1), + RK_PLLRATE(800000000, 6, 400, 2, 1, 1), + RK_PLLRATE(700000000, 6, 350, 2, 1, 1), + RK_PLLRATE(696000000, 1, 58, 2, 1, 1), + RK_PLLRATE(624000000, 1, 52, 2, 1, 1), + RK_PLLRATE(600000000, 1, 75, 3, 1, 1), + RK_PLLRATE(594000000, 2, 99, 2, 1, 1), + RK_PLLRATE(504000000, 1, 63, 3, 1, 1), + RK_PLLRATE(500000000, 6, 250, 2, 1, 1), + RK_PLLRATE(408000000, 1, 68, 2, 2, 1), + RK_PLLRATE(312000000, 1, 52, 2, 2, 1), + RK_PLLRATE(216000000, 1, 72, 4, 2, 1), + RK_PLLRATE(96000000, 1, 64, 4, 4, 1), + { /* sentinel */ }, +}; + +static struct rk_clk_armclk_rates rk3308_armclk_rates[] = { + {1608000000, 1}, + {1512000000, 1}, + {1488000000, 1}, + {1416000000, 1}, + {1392000000, 1}, + {1296000000, 1}, + {1200000000, 1}, + {1104000000, 1}, + {1008000000, 1}, + {912000000, 1}, + {816000000, 1}, + {696000000, 1}, + {600000000, 1}, + {408000000, 1}, + {312000000, 1}, + {216000000, 1}, + {96000000, 1}, + {}, +}; + +/* Parent clock defines */ +PNAME(mux_pll_p) = { "xin24m" }; +PNAME(mux_usb480m_p) = { "xin24m", "usb480m_phy", "clk_rtc32k" }; +PNAME(mux_armclk_p) = { "apll_core", "vpll0_core", "vpll1_core" }; +PNAME(mux_dpll_vpll0_p) = { "dpll", "vpll0" }; +PNAME(mux_dpll_vpll0_xin24m_p) = { "dpll", "vpll0", "xin24m" }; +PNAME(mux_dpll_vpll0_vpll1_p) = { "dpll", "vpll0", "vpll1" }; +PNAME(mux_dpll_vpll0_vpll1_xin24m_p) = { "dpll", "vpll0", "vpll1", "xin24m" }; +PNAME(mux_dpll_vpll0_vpll1_usb480m_xin24m_p) = { "dpll", "vpll0", "vpll1", "usb480m", "xin24m" }; +PNAME(mux_vpll0_vpll1_p) = { "vpll0", "vpll1" }; +PNAME(mux_vpll0_vpll1_xin24m_p) = { "vpll0", "vpll1", "xin24m" }; +PNAME(mux_uart0_p) = { "clk_uart0_src", "dummy", "clk_uart0_frac" }; +PNAME(mux_uart1_p) = { "clk_uart1_src", "dummy", "clk_uart1_frac" }; +PNAME(mux_uart2_p) = { "clk_uart2_src", "dummy", "clk_uart2_frac" }; +PNAME(mux_uart3_p) = { "clk_uart3_src", "dummy", "clk_uart3_frac" }; +PNAME(mux_uart4_p) = { "clk_uart4_src", "dummy", "clk_uart4_frac" }; +PNAME(mux_dclk_vop_p) = { "dclk_vop_src", "dclk_vop_frac", "xin24m" }; +PNAME(mux_nandc_p) = { "clk_nandc_div", "clk_nandc_div50" }; +PNAME(mux_sdmmc_p) = { "clk_sdmmc_div", "clk_sdmmc_div50" }; +PNAME(mux_sdio_p) = { "clk_sdio_div", "clk_sdio_div50" }; +PNAME(mux_emmc_p) = { "clk_emmc_div", "clk_emmc_div50" }; +PNAME(mux_mac_p) = { "clk_mac_src", "mac_clkin" }; +PNAME(mux_mac_rmii_sel_p) = { "clk_mac_rx_tx_div20", "clk_mac_rx_tx_div2" }; +PNAME(mux_ddrstdby_p) = { "clk_ddrphy1x_out", "clk_ddr_stdby_div4" }; +PNAME(mux_rtc32k_p) = { "xin32k", "clk_pvtm_32k", "clk_rtc32k_frac", "clk_rtc32k_div" }; +PNAME(mux_usbphy_ref_p) = { "xin24m", "clk_usbphy_ref_src" }; +PNAME(mux_wifi_src_p) = { "clk_wifi_dpll", "clk_wifi_vpll0" }; +PNAME(mux_wifi_p) = { "clk_wifi_osc", "clk_wifi_src" }; +PNAME(mux_pdm_p) = { "clk_pdm_src", "clk_pdm_frac" }; +PNAME(mux_i2s0_8ch_tx_p) = { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "mclk_i2s0_8ch_in" }; +PNAME(mux_i2s0_8ch_tx_rx_p) = { "clk_i2s0_8ch_tx_mux", "clk_i2s0_8ch_rx_mux"}; +PNAME(mux_i2s0_8ch_tx_out_p) = { "clk_i2s0_8ch_tx", "xin12m" }; +PNAME(mux_i2s0_8ch_rx_p) = { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "mclk_i2s0_8ch_in" }; +PNAME(mux_i2s0_8ch_rx_tx_p) = { "clk_i2s0_8ch_rx_mux", "clk_i2s0_8ch_tx_mux"}; +PNAME(mux_i2s1_8ch_tx_p) = { "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_frac", "mclk_i2s1_8ch_in" }; +PNAME(mux_i2s1_8ch_tx_rx_p) = { "clk_i2s1_8ch_tx_mux", "clk_i2s1_8ch_rx_mux"}; +PNAME(mux_i2s1_8ch_tx_out_p) = { "clk_i2s1_8ch_tx", "xin12m" }; +PNAME(mux_i2s1_8ch_rx_p) = { "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_frac", "mclk_i2s1_8ch_in" }; +PNAME(mux_i2s1_8ch_rx_tx_p) = { "clk_i2s1_8ch_rx_mux", "clk_i2s1_8ch_tx_mux"}; +PNAME(mux_i2s2_8ch_tx_p) = { "clk_i2s2_8ch_tx_src", "clk_i2s2_8ch_tx_frac", "mclk_i2s2_8ch_in" }; +PNAME(mux_i2s2_8ch_tx_rx_p) = { "clk_i2s2_8ch_tx_mux", "clk_i2s2_8ch_rx_mux"}; +PNAME(mux_i2s2_8ch_tx_out_p) = { "clk_i2s2_8ch_tx", "xin12m" }; +PNAME(mux_i2s2_8ch_rx_p) = { "clk_i2s2_8ch_rx_src", "clk_i2s2_8ch_rx_frac", "mclk_i2s2_8ch_in" }; +PNAME(mux_i2s2_8ch_rx_tx_p) = { "clk_i2s2_8ch_rx_mux", "clk_i2s2_8ch_tx_mux"}; +PNAME(mux_i2s3_8ch_tx_p) = { "clk_i2s3_8ch_tx_src", "clk_i2s3_8ch_tx_frac", "mclk_i2s3_8ch_in" }; +PNAME(mux_i2s3_8ch_tx_rx_p) = { "clk_i2s3_8ch_tx_mux", "clk_i2s3_8ch_rx_mux"}; +PNAME(mux_i2s3_8ch_tx_out_p) = { "clk_i2s3_8ch_tx", "xin12m" }; +PNAME(mux_i2s3_8ch_rx_p) = { "clk_i2s3_8ch_rx_src", "clk_i2s3_8ch_rx_frac", "mclk_i2s3_8ch_in" }; +PNAME(mux_i2s3_8ch_rx_tx_p) = { "clk_i2s3_8ch_rx_mux", "clk_i2s3_8ch_tx_mux"}; +PNAME(mux_i2s0_2ch_p) = { "clk_i2s0_2ch_src", "clk_i2s0_2ch_frac", "mclk_i2s0_2ch_in" }; +PNAME(mux_i2s0_2ch_out_p) = { "clk_i2s0_2ch", "xin12m" }; +PNAME(mux_i2s1_2ch_p) = { "clk_i2s1_2ch_src", "clk_i2s1_2ch_frac", "mclk_i2s1_2ch_in"}; +PNAME(mux_i2s1_2ch_out_p) = { "clk_i2s1_2ch", "xin12m" }; +PNAME(mux_spdif_tx_src_p) = { "clk_spdif_tx_div", "clk_spdif_tx_div50" }; +PNAME(mux_spdif_tx_p) = { "clk_spdif_tx_src", "clk_spdif_tx_frac", "mclk_i2s0_2ch_in" }; +PNAME(mux_spdif_rx_src_p) = { "clk_spdif_rx_div", "clk_spdif_rx_div50" }; +PNAME(mux_spdif_rx_p) = { "clk_spdif_rx_src", "clk_spdif_rx_frac" }; +/* CLOCKS */ +static struct rk_clk rk3308_clks[] = { + /* External clocks */ + LINK("xin24m"), + LINK("clk_rtc_32k"), + LINK("usb480m_phy"), +// LINK("jtag_clkin"), + LINK("clk_ddrphy1x_out"), + LINK("clk_pvtm_32k"), + LINK("xin32k"), + LINK("mclk_i2s0_8ch_in"), + LINK("mclk_i2s1_8ch_in"), // SOS SCRU + LINK("mclk_i2s2_8ch_in"), + LINK("mclk_i2s3_8ch_in"), + LINK("mclk_i2s0_2ch_in"), + LINK("mclk_i2s1_2ch_in"), + LINK("mac_clkin"), + LINK("dummy"), + /* PLL's */ + RK_PLL(PLL_APLL, "apll", mux_pll_p, 0, 0), + RK_PLL(PLL_DPLL, "dpll", mux_pll_p, 1, 2), + RK_PLL(PLL_VPLL0, "vpll0", mux_pll_p, 2, 4), + RK_PLL(PLL_VPLL1, "vpll1", mux_pll_p, 3, 6), + RK_ARMDIV(ARMCLK, "armclk", mux_armclk_p, rk3308_armclk_rates, 0, 0, 5,6, 1, 0, 1), + RK_MUX(USB480M, "usb480m", mux_usb480m_p, RK3308_MODE_CON, 8, 2, 0), + RK_FACTOR(0, "xin12m", "xin24m", 1, 2), + RK_COMPNOMUX(0, "pclk_core_dbg", "armclk", 0, 8, 4, 0, 2, 0), + RK_COMPNOMUX(0, "aclk_core", "armclk", 0, 12, 3, 0, 1, 0), + RK_COMPNODIV(ACLK_BUS_SRC, "clk_bus_src", mux_dpll_vpll0_vpll1_p, 5, 6, 2, 1, 0, 0), + RK_COMPNOMUX(PCLK_BUS, "pclk_bus", "clk_bus_src", 6, 8, 5, 1, 3, 0), + RK_COMPNOMUX(HCLK_BUS, "hclk_bus", "clk_bus_src", 6, 0, 5, 1, 2, 0), + RK_COMPNOMUX(ACLK_BUS, "aclk_bus", "clk_bus_src", 5, 0, 5, 1, 1, 0), + RK_COMPOSITE(0, "clk_uart0_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 10, 13, 3, 0, 5, 1, 9, 0), + RK_FRACTION(0, "clk_uart0_frac", "clk_uart0_src", 12, 1, 11, 0), + RK_MUX(0, "clk_uart0_mux", mux_uart0_p, 11, 14, 2, 0), + RK_COMPOSITE(0, "clk_uart1_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 13, 13, 3, 0, 5, 1, 13, 0), + RK_FRACTION(0, "clk_uart1_frac", "clk_uart1_src", 15, 1, 15, 0), + RK_MUX(0, "clk_uart1_mux", mux_uart1_p, 14, 14, 2, 0), + RK_COMPOSITE(0, "clk_uart2_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 16, 13, 3, 0, 5, 2, 1, 0), + RK_FRACTION(0, "clk_uart2_frac", "clk_uart2_src", 18, 2, 3, 0), + RK_MUX(0, "clk_uart2_mux", mux_uart2_p, 17, 14, 2, 0), + RK_COMPOSITE(0, "clk_uart3_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 19, 13, 3, 0, 5, 2, 5, 0), + RK_FRACTION(0, "clk_uart3_frac", "clk_uart3_src", 21, 2, 7, 0), + RK_MUX(0, "clk_uart3_mux", mux_uart3_p, 20, 14, 2, 0), + RK_COMPOSITE(0, "clk_uart4_src", mux_dpll_vpll0_vpll1_usb480m_xin24m_p, 22, 13, 3, 0, 5, 2, 9, 0), + RK_FRACTION(0, "clk_uart4_frac", "clk_uart4_src", 24, 2, 11, 0), + RK_MUX(0, "clk_uart4_mux", mux_uart4_p, 23, 14, 2, 0), + RK_COMPOSITE(SCLK_I2C0, "clk_i2c0", mux_dpll_vpll0_xin24m_p, 25, 14, 2, 0, 7, 2, 13, 0), + RK_COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_dpll_vpll0_xin24m_p, 26, 14, 2, 0, 7, 2, 14, 0), + RK_COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_dpll_vpll0_xin24m_p, 27, 14, 2, 0, 7, 2, 15, 0), + RK_COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_dpll_vpll0_xin24m_p, 28, 14, 2, 0, 7, 3, 0, 0), + RK_COMPOSITE(SCLK_PWM0, "clk_pwm0", mux_dpll_vpll0_xin24m_p, 29, 14, 2, 0, 7, 3, 1, 0), + RK_COMPOSITE(SCLK_PWM1, "clk_pwm1", mux_dpll_vpll0_xin24m_p, 74, 14, 2, 0, 7, 15, 0, 0), + RK_COMPOSITE(SCLK_PWM2, "clk_pwm2", mux_dpll_vpll0_xin24m_p, 75, 14, 2, 0, 7, 15, 1, 0), + RK_COMPOSITE(SCLK_SPI0, "clk_spi0", mux_dpll_vpll0_xin24m_p, 30, 14, 2, 0, 7, 3, 2, 0), + RK_COMPOSITE(SCLK_SPI1, "clk_spi1", mux_dpll_vpll0_xin24m_p, 31, 14, 2, 0, 7, 3, 3, 0), + RK_COMPOSITE(SCLK_SPI2, "clk_spi2", mux_dpll_vpll0_xin24m_p, 32, 14, 2, 0, 7, 3, 4, 0), + RK_COMPNOMUX(SCLK_TSADC, "clk_tsadc", "xin24m", 33, 0, 11, 3, 5, 0), + RK_COMPNOMUX(SCLK_SARADC, "clk_saradc", "xin24m", 34, 0, 11, 3, 6, 0), + RK_COMPNOMUX(SCLK_OTP, "clk_otp", "xin24m", 35, 0, 4, 3, 7, 0), + RK_COMPNOMUX(SCLK_OTP_USR, "clk_otp_usr", "clk_otp", 35, 4, 2, 3, 8, 0), + RK_COMPOSITE(SCLK_CRYPTO, "clk_crypto", mux_dpll_vpll0_vpll1_p, 7, 6, 2, 0, 5, 1, 4, 0), + RK_COMPOSITE(SCLK_CRYPTO_APK, "clk_crypto_apk", mux_dpll_vpll0_vpll1_p, 7, 14, 2, 8, 5, 1, 5, 0), + RK_COMPOSITE(0, "dclk_vop_src", mux_dpll_vpll0_vpll1_p, 8, 10, 2, 0, 8, 1, 6, 0), + RK_FRACTION(0, "dclk_vop_frac", "dclk_vop_src", 9, 1, 7, 0), + RK_MUX(0, "dclk_vop_mux", mux_dclk_vop_p, 8, 14, 2, 0), + RK_COMPNODIV(ACLK_PERI_SRC, "clk_peri_src", mux_dpll_vpll0_vpll1_p, 36, 6, 2, 8, 0, 0), + RK_COMPNOMUX(ACLK_PERI, "aclk_peri", "clk_peri_src", 36, 0, 5, 8, 1, 0), + RK_COMPNOMUX(HCLK_PERI, "hclk_peri", "clk_peri_src", 37, 0, 5, 8, 2, 0), + RK_COMPNOMUX(PCLK_PERI, "pclk_peri", "clk_peri_src", 37, 8, 5, 8, 3, 0), + RK_COMPOSITE(SCLK_NANDC_DIV, "clk_nandc_div", mux_dpll_vpll0_vpll1_p, 38, 6, 2, 0, 5, 8, 4, 0), + RK_COMPOSITE(SCLK_NANDC_DIV50, "clk_nandc_div50", mux_dpll_vpll0_vpll1_p, 38, 6, 2, 0, 5, 8, 4, 0), + RK_COMPNODIV(SCLK_NANDC, "clk_nandc", mux_nandc_p, 38, 15, 1, 8, 5, 0), + RK_COMPOSITE(SCLK_SDMMC_DIV, "clk_sdmmc_div", mux_dpll_vpll0_vpll1_xin24m_p, 39, 8, 2, 0, 8, 8, 6, 0), + RK_COMPOSITE(SCLK_SDMMC_DIV50, "clk_sdmmc_div50", mux_dpll_vpll0_vpll1_xin24m_p, 39, 8, 2, 0, 8, 8, 6, 0), + RK_COMPNODIV(SCLK_SDMMC, "clk_sdmmc", mux_sdmmc_p, 39, 15, 1, 8, 7, 0), +// RK_MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "clk_sdmmc", RK3308_SDMMC_CON0, 1), +// RK_MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "clk_sdmmc", RK3308_SDMMC_CON1, 1), + RK_COMPOSITE(SCLK_SDIO_DIV, "clk_sdio_div", mux_dpll_vpll0_vpll1_xin24m_p, 40, 8, 2, 0, 8, 8, 8, 0), + RK_COMPOSITE(SCLK_SDIO_DIV50, "clk_sdio_div50", mux_dpll_vpll0_vpll1_xin24m_p, 40, 8, 2, 0, 8, 8, 8, 0), + RK_COMPNODIV(SCLK_SDIO, "clk_sdio", mux_sdio_p, 40, 15, 1, 8, 9, 0), +// RK_MMC(SCLK_SDIO_DRV, "sdio_drv", "clk_sdio", RK3308_SDIO_CON0, 1), +// RK_MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "clk_sdio", RK3308_SDIO_CON1, 1), + RK_COMPOSITE(SCLK_EMMC_DIV, "clk_emmc_div", mux_dpll_vpll0_vpll1_xin24m_p, 41, 8, 2, 0, 8, 8, 10, 0), + RK_COMPOSITE(SCLK_EMMC_DIV50, "clk_emmc_div50", mux_dpll_vpll0_vpll1_xin24m_p, 41, 8, 2, 0, 8, 8, 10, 0), + RK_COMPNODIV(SCLK_EMMC, "clk_emmc", mux_emmc_p, 41, 15, 1, 8, 11, 0), +// RK_MMC(SCLK_EMMC_DRV, "emmc_drv", "clk_emmc", RK3308_EMMC_CON0, 1), +// RK_MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "clk_emmc", RK3308_EMMC_CON1, 1), + RK_COMPOSITE(SCLK_SFC, "clk_sfc", mux_dpll_vpll0_vpll1_p, 42, 14, 2, 0, 7, 8, 12, 0), + RK_MUX(SCLK_RTC32K, "clk_rtc32k", mux_rtc32k_p, 2, 8, 2, 0), + RK_COMPOSITE(SCLK_MAC_SRC, "clk_mac_src", mux_dpll_vpll0_vpll1_p, 43, 6, 2, 0, 5, 8, 14, 0), + RK_MUX(SCLK_MAC, "clk_mac", mux_mac_p, 43, 14, 1, 0), + RK_FACTOR(0, "clk_mac_rx_tx_div2", "clk_mac_rx_tx", 1, 2), + RK_FACTOR(0, "clk_mac_rx_tx_div20", "clk_mac_rx_tx", 1, 20), + RK_MUX(SCLK_MAC_RMII, "clk_mac_rmii_sel", mux_mac_rmii_sel_p, 43, 15, 1, 0), + RK_COMPOSITE(SCLK_OWIRE, "clk_owire", mux_dpll_vpll0_xin24m_p, 44, 14, 2, 8, 6, 8, 15, 0), + RK_COMPOSITE(SCLK_DDRCLK, "clk_ddrphy4x_src", mux_dpll_vpll0_vpll1_p, 1, 6, 2, 0, 3, 0, 10, 0), + RK_FACTOR_GATE(0, "clk_ddr_stdby_div4", "clk_ddrphy4x",0,1, 4, 0, 13,0), + RK_COMPNODIV(0, "clk_ddrstdby", mux_ddrstdby_p, 1, 8, 1, 4, 14, 0), + RK_FRACTION(0, "clk_rtc32k_frac", "xin24m", 3, 4, 3, 0), + RK_MUX(0, "clk_rtc32k_div_src", mux_vpll0_vpll1_p, 2, 10, 1, 0), + RK_COMPNOMUX(0, "clk_rtc32k_div", "clk_rtc32k_div_src", 4, 0, 16, 4, 2, 0), + RK_COMPOSITE(0, "clk_usbphy_ref_src", mux_dpll_vpll0_p, 72, 6, 1, 0, 6, 4, 7, 0), + RK_COMPNODIV(SCLK_USBPHY_REF, "clk_usbphy_ref", mux_usbphy_ref_p, 72, 7, 1, 4, 8, 0), + RK_COMPOSITE(0, "clk_wifi_src", mux_wifi_src_p, 44, 6, 1, 0, 6, 4, 0, 0), + RK_COMPNODIV(SCLK_WIFI, "clk_wifi", mux_wifi_p, 44, 7, 1, 4, 1, 0), + RK_COMPNODIV(0, "clk_audio_src", mux_vpll0_vpll1_xin24m_p, 45, 6, 2, 10, 0, 0), + RK_COMPNOMUX(HCLK_AUDIO, "hclk_audio", "clk_audio_src", 45, 0, 5, 10, 1, 0), + RK_COMPNOMUX(PCLK_AUDIO, "pclk_audio", "clk_audio_src", 45, 8, 5, 10, 2, 0), + RK_COMPOSITE(0, "clk_pdm_src", mux_vpll0_vpll1_xin24m_p, 46, 8, 2, 0, 7, 10, 3, 0), + RK_FRACTION(0, "clk_pdm_frac", "clk_pdm_src", 47, 10, 4, 0), + RK_MUX(0, "clk_pdm_mux", mux_pdm_p, 46, 15, 1, 0), + RK_COMPOSITE(SCLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 52, 8, 2, 0, 7, 10, 12, 0), + RK_FRACTION(0, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_src", 53, 10, 13, 0), + RK_COMPNODIV(SCLK_I2S0_8CH_TX, "clk_i2s0_8ch_tx", mux_i2s0_8ch_tx_rx_p, 52, 12, 1, 10, 14, 0), + RK_COMPNODIV(SCLK_I2S0_8CH_TX_OUT, "clk_i2s0_8ch_tx_out", mux_i2s0_8ch_tx_out_p, 52, 15, 1, 10, 15, 0), + RK_COMPOSITE(SCLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 54, 8, 2, 0, 7, 11, 0, 0), + RK_FRACTION(0, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_src", 55, 11, 1, 0), + RK_COMPNODIV(SCLK_I2S0_8CH_RX, "clk_i2s0_8ch_rx", mux_i2s0_8ch_rx_tx_p, 54, 12, 1, 11, 2, 0), + RK_COMPOSITE(SCLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 56, 8, 2, 0, 7, 11, 4, 0), + RK_FRACTION(0, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_src", 57, 11, 5, 0), + RK_COMPNODIV(SCLK_I2S1_8CH_TX, "clk_i2s1_8ch_tx", mux_i2s1_8ch_tx_rx_p, 56, 12, 1, 11, 6, 0), + RK_COMPNODIV(SCLK_I2S1_8CH_TX_OUT, "clk_i2s1_8ch_tx_out", mux_i2s1_8ch_tx_out_p, 56, 15, 1, 11, 7, 0), + RK_COMPOSITE(SCLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 58, 8, 2, 0, 7, 11, 8, 0), + RK_FRACTION(0, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_src", 59, 11, 9, 0), + RK_COMPNODIV(SCLK_I2S1_8CH_RX, "clk_i2s1_8ch_rx", mux_i2s1_8ch_rx_tx_p, 58, 12, 1, 11, 10, 0), + RK_COMPOSITE(SCLK_I2S2_8CH_TX_SRC, "clk_i2s2_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 60, 8, 2, 0, 7, 11, 12, 0), + RK_FRACTION(0, "clk_i2s2_8ch_tx_frac", "clk_i2s2_8ch_tx_src", 61, 11, 13, 0), + RK_COMPNODIV(SCLK_I2S2_8CH_TX, "clk_i2s2_8ch_tx", mux_i2s2_8ch_tx_rx_p, 60, 12, 1, 11, 14, 0), + RK_COMPNODIV(SCLK_I2S2_8CH_TX_OUT, "clk_i2s2_8ch_tx_out", mux_i2s2_8ch_tx_out_p, 60, 15, 1, 11, 15, 0), + RK_COMPOSITE(SCLK_I2S2_8CH_RX_SRC, "clk_i2s2_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 62, 8, 2, 0, 7, 12, 0, 0), + RK_FRACTION(0, "clk_i2s2_8ch_rx_frac", "clk_i2s2_8ch_rx_src", 63, 12, 1, 0), + RK_COMPNODIV(SCLK_I2S2_8CH_RX, "clk_i2s2_8ch_rx", mux_i2s2_8ch_rx_tx_p, 62, 12, 1, 12, 2, 0), + RK_COMPOSITE(SCLK_I2S3_8CH_TX_SRC, "clk_i2s3_8ch_tx_src", mux_vpll0_vpll1_xin24m_p, 64, 8, 2, 0, 7, 12, 4, 0), + RK_FRACTION(0, "clk_i2s3_8ch_tx_frac", "clk_i2s3_8ch_tx_src", 65, 12, 5, 0), + RK_COMPNODIV(SCLK_I2S3_8CH_TX, "clk_i2s3_8ch_tx", mux_i2s3_8ch_tx_rx_p, 64, 12, 1, 12, 6, 0), + RK_COMPNODIV(SCLK_I2S3_8CH_TX_OUT, "clk_i2s3_8ch_tx_out", mux_i2s3_8ch_tx_out_p, 64, 15, 1, 12, 7, 0), + RK_COMPOSITE(SCLK_I2S3_8CH_RX_SRC, "clk_i2s3_8ch_rx_src", mux_vpll0_vpll1_xin24m_p, 66, 8, 2, 0, 7, 12, 8, 0), + RK_FRACTION(0, "clk_i2s3_8ch_rx_frac", "clk_i2s3_8ch_rx_src", 67, 12, 9, 0), + RK_COMPNODIV(SCLK_I2S3_8CH_RX, "clk_i2s3_8ch_rx", mux_i2s3_8ch_rx_tx_p, 66, 12, 1, 12, 10, 0), + RK_COMPOSITE(SCLK_I2S0_2CH_SRC, "clk_i2s0_2ch_src", mux_vpll0_vpll1_xin24m_p, 68, 8, 2, 0, 7, 12, 12, 0), + RK_FRACTION(0, "clk_i2s0_2ch_frac", "clk_i2s0_2ch_src", 69, 12, 13, 0), + RK_COMPNODIV(SCLK_I2S0_2CH_OUT, "clk_i2s0_2ch_out", mux_i2s0_2ch_out_p, 68, 15, 1, 12, 15, 0), + RK_COMPOSITE(SCLK_I2S1_2CH_SRC, "clk_i2s1_2ch_src", mux_vpll0_vpll1_xin24m_p, 70, 8, 2, 0, 7, 13, 0, 0), + RK_FRACTION(0, "clk_i2s1_2ch_frac", "clk_i2s1_2ch_src", 71, 13, 1, 0), + RK_COMPNODIV(SCLK_I2S1_2CH_OUT, "clk_i2s1_2ch_out", mux_i2s1_2ch_out_p, 70, 15, 1, 13, 3, 0), + RK_COMPOSITE(SCLK_SPDIF_TX_DIV, "clk_spdif_tx_div", mux_vpll0_vpll1_xin24m_p, 48, 8, 2, 0, 7, 10, 6, 0), + RK_COMPOSITE(SCLK_SPDIF_TX_DIV50, "clk_spdif_tx_div50", mux_vpll0_vpll1_xin24m_p, 48, 8, 2, 0, 7, 10, 6, 0), + RK_MUX(0, "clk_spdif_tx_src", mux_spdif_tx_src_p, 48, 12, 1, 0), + RK_FRACTION(0, "clk_spdif_tx_frac", "clk_spdif_tx_src", 49, 10, 7, 0), + RK_COMPOSITE(SCLK_SPDIF_RX_DIV, "clk_spdif_rx_div", mux_vpll0_vpll1_xin24m_p, 50, 8, 2, 0, 7, 10, 9, 0), + RK_COMPOSITE(SCLK_SPDIF_RX_DIV50, "clk_spdif_rx_div50", mux_vpll0_vpll1_xin24m_p, 50, 8, 2, 0, 7, 10, 9, 0), + RK_MUX(0, "clk_spdif_rx_src", mux_spdif_rx_src_p, 50, 14, 1, 0), + RK_FRACTION(0, "clk_spdif_rx_frac", "clk_spdif_rx_src", 51, 10, 10, 0), + RK_FACTOR(ACLK_DMAC0, "aclk_dmac0", "aclk_bus", 1, 1), + RK_FACTOR(ACLK_DMAC1, "aclk_dmac1", "aclk_bus", 1, 1), + RK_FACTOR(PCLK_WDT, "pclk_wdt", "pclk_bus", 1, 1), + RK_MUX(SCLK_I2S0_8CH_TX_MUX, "clk_i2s0_8ch_tx_mux", mux_i2s0_8ch_tx_p, 52, 10, 2, 0), + RK_MUX(SCLK_I2S0_8CH_RX_MUX, "clk_i2s0_8ch_rx_mux", mux_i2s0_8ch_rx_p, 54, 10, 2, 0), + RK_MUX(SCLK_I2S1_8CH_TX_MUX, "clk_i2s1_8ch_tx_mux", mux_i2s1_8ch_tx_p, 56, 10, 2, 0), + RK_MUX(SCLK_I2S1_8CH_RX_MUX, "clk_i2s1_8ch_rx_mux", mux_i2s1_8ch_rx_p, 58, 10, 2, 0), + RK_MUX(SCLK_I2S2_8CH_TX_MUX, "clk_i2s2_8ch_tx_mux", mux_i2s2_8ch_tx_p, 60, 10, 2, 0), + RK_MUX(SCLK_I2S2_8CH_RX_MUX, "clk_i2s2_8ch_rx_mux", mux_i2s2_8ch_rx_p, 62, 10, 2, 0), + RK_MUX(SCLK_I2S3_8CH_TX_MUX, "clk_i2s3_8ch_tx_mux", mux_i2s3_8ch_tx_p, 64, 10, 2, 0), + RK_MUX(SCLK_I2S3_8CH_RX_MUX, "clk_i2s3_8ch_rx_mux", mux_i2s3_8ch_rx_p, 66, 10, 2, 0), + RK_MUX(0, "clk_i2s0_2ch_mux", mux_i2s0_2ch_p, 68, 10, 2, 0), + RK_MUX(0, "clk_i2s1_2ch_mux", mux_i2s1_2ch_p, 70, 10, 2, 0), + RK_MUX(0, "clk_spdif_tx_mux", mux_spdif_tx_p, 48, 14, 2, 0), + RK_MUX(0, "clk_spdif_rx_mux", mux_spdif_rx_p, 50, 15, 1, 0), +}; + +/* GATES */ +static struct rk_cru_gate rk3308_gates[] = { + RK_GATE(0, "apll_core", "apll", 0, 0), + RK_GATE(0, "vpll0_core", "vpll0", 0, 0), + RK_GATE(0, "vpll1_core", "vpll1", 0, 0), +// RK_GATE(0, "clk_jtag", "jtag_clkin", 0, 3), + RK_GATE(SCLK_PVTM_CORE, "clk_pvtm_core", "xin24m", 0, 4), + RK_GATE(PCLK_DDR, "pclk_ddr", "pclk_bus", 4, 15), + RK_GATE(SCLK_UART0, "clk_uart0", "clk_uart0_mux", 1, 12), + RK_GATE(SCLK_UART1, "clk_uart1", "clk_uart1_mux", 2, 0), + RK_GATE(SCLK_UART2, "clk_uart2", "clk_uart2_mux", 2, 4), + RK_GATE(SCLK_UART3, "clk_uart3", "clk_uart3_mux", 2, 8), + RK_GATE(SCLK_UART4, "clk_uart4", "clk_uart4_mux", 2, 12), + RK_GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 3, 10), + RK_GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 3, 11), + RK_GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 3, 12), + RK_GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 3, 13), + RK_GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 3, 14), + RK_GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 3, 15), + RK_GATE(SCLK_CPU_BOOST, "clk_cpu_boost", "xin24m", 3, 9), + RK_GATE(DCLK_VOP, "dclk_vop", "dclk_vop_mux", 1, 8), + RK_GATE(SCLK_OTG_ADP, "clk_otg_adp", "clk_rtc32k", 8, 13), + RK_GATE(SCLK_MAC_REF, "clk_mac_ref", "clk_mac", 9, 1), + RK_GATE(SCLK_MAC_RX_TX, "clk_mac_rx_tx", "clk_mac", 9, 0), + RK_GATE(0, "clk_ddr_mon_timer", "xin24m", 0, 12), + RK_GATE(0, "clk_ddr_mon", "clk_ddrphy1x_out", 4, 10), + RK_GATE(0, "clk_ddr_upctrl", "clk_ddrphy1x_out", 4, 11), + RK_GATE(0, "clk_ddr_msch", "clk_ddrphy1x_out", 4, 12), + RK_GATE(0, "clk_ddr_msch_peribus", "clk_ddrphy1x_out", 4, 13), + RK_GATE(0, "clk_ddrphy4x", "clk_ddrphy4x_src", 0, 11), + RK_GATE(PCLK_PMU, "pclk_pmu", "pclk_bus", 4, 5), + RK_GATE(SCLK_PMU, "clk_pmu", "pclk_bus", 4, 6), + RK_GATE(0, "clk_wifi_dpll", "dpll", 15, 2), + RK_GATE(0, "clk_wifi_vpll0", "vpll0", 15, 3), + RK_GATE(0, "clk_wifi_osc", "xin24m", 15, 4), + RK_GATE(SCLK_PVTM_PMU, "clk_pvtm_pmu", "xin24m", 4, 4), + RK_GATE(SCLK_PDM, "clk_pdm", "clk_pdm_mux", 10, 5), + RK_GATE(SCLK_I2S0_8CH_RX_OUT, "clk_i2s0_8ch_rx_out", "clk_i2s0_8ch_rx", 11, 3), + RK_GATE(SCLK_I2S1_8CH_RX_OUT, "clk_i2s1_8ch_rx_out", "clk_i2s1_8ch_rx", 11, 11), + RK_GATE(SCLK_I2S2_8CH_RX_OUT, "clk_i2s2_8ch_rx_out", "clk_i2s2_8ch_rx", 12, 3), + RK_GATE(SCLK_I2S3_8CH_RX_OUT, "clk_i2s3_8ch_rx_out", "clk_i2s3_8ch_rx", 12, 11), + RK_GATE(SCLK_I2S0_2CH, "clk_i2s0_2ch", "clk_i2s0_2ch_mux", 12, 14), + RK_GATE(SCLK_I2S1_2CH, "clk_i2s1_2ch", "clk_i2s1_2ch_mux", 13, 2), + RK_GATE(SCLK_SPDIF_TX, "clk_spdif_tx", "clk_spdif_tx_mux", 10, 8), + RK_GATE(SCLK_SPDIF_RX, "clk_spdif_rx", "clk_spdif_rx_mux", 10, 11), + RK_GATE(0, "aclk_core_niu", "aclk_core", 0, 5), + RK_GATE(0, "pclk_core_dbg_niu", "aclk_core", 0, 6), + RK_GATE(0, "pclk_core_dbg_daplite", "pclk_core_dbg", 0, 7), + RK_GATE(0, "aclk_core_perf", "pclk_core_dbg", 0, 8), + RK_GATE(0, "pclk_core_grf", "pclk_core_dbg", 0, 9), + RK_GATE(0, "aclk_peri_niu", "aclk_peri", 9, 2), + RK_GATE(0, "aclk_peribus_niu", "aclk_peri", 9, 3), + RK_GATE(ACLK_MAC, "aclk_mac", "aclk_peri", 9, 4), + RK_GATE(0, "hclk_peri_niu", "hclk_peri", 9, 5), + RK_GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 9, 6), + RK_GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 9, 7), + RK_GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 9, 8), + RK_GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 9, 9), + RK_GATE(HCLK_SFC, "hclk_sfc", "hclk_peri", 9, 10), + RK_GATE(HCLK_OTG, "hclk_otg", "hclk_peri", 9, 11), + RK_GATE(HCLK_HOST, "hclk_host", "hclk_peri", 9, 12), + RK_GATE(HCLK_HOST_ARB, "hclk_host_arb", "hclk_peri", 9, 13), + RK_GATE(0, "pclk_peri_niu", "pclk_peri", 9, 14), + RK_GATE(PCLK_MAC, "pclk_mac", "pclk_peri", 9, 15), + RK_GATE(0, "hclk_audio_niu", "hclk_audio", 14, 0), + RK_GATE(HCLK_PDM, "hclk_pdm", "hclk_audio", 14, 1), + RK_GATE(HCLK_SPDIFTX, "hclk_spdiftx", "hclk_audio", 14, 2), + RK_GATE(HCLK_SPDIFRX, "hclk_spdifrx", "hclk_audio", 14, 3), + RK_GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio", 14, 4), + RK_GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_audio", 14, 5), + RK_GATE(HCLK_I2S2_8CH, "hclk_i2s2_8ch", "hclk_audio", 14, 6), + RK_GATE(HCLK_I2S3_8CH, "hclk_i2s3_8ch", "hclk_audio", 14, 7), + RK_GATE(HCLK_I2S0_2CH, "hclk_i2s0_2ch", "hclk_audio", 14, 8), + RK_GATE(HCLK_I2S1_2CH, "hclk_i2s1_2ch", "hclk_audio", 14, 9), + RK_GATE(HCLK_VAD, "hclk_vad", "hclk_audio", 14, 10), + RK_GATE(0, "pclk_audio_niu", "pclk_audio", 14, 11), + RK_GATE(PCLK_ACODEC, "pclk_acodec", "pclk_audio", 14, 12), + RK_GATE(0, "aclk_bus_niu", "aclk_bus", 5, 0), + RK_GATE(0, "aclk_intmem", "aclk_bus", 5, 1), + RK_GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_bus", 5, 2), + RK_GATE(ACLK_VOP, "aclk_vop", "aclk_bus", 5, 3), + RK_GATE(0, "aclk_gic", "aclk_bus", 5, 4), + RK_GATE(0, "hclk_bus_niu", "hclk_bus", 5, 5), + RK_GATE(0, "hclk_rom", "hclk_bus", 5, 6), + RK_GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_bus", 5, 7), + RK_GATE(HCLK_VOP, "hclk_vop", "hclk_bus", 5, 8), + RK_GATE(0, "pclk_bus_niu", "pclk_bus", 5, 9), + RK_GATE(PCLK_UART0, "pclk_uart0", "pclk_bus", 5, 10), + RK_GATE(PCLK_UART1, "pclk_uart1", "pclk_bus", 5, 11), + RK_GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 5, 12), + RK_GATE(PCLK_UART3, "pclk_uart3", "pclk_bus", 5, 13), + RK_GATE(PCLK_UART4, "pclk_uart4", "pclk_bus", 5, 14), + RK_GATE(PCLK_I2C0, "pclk_i2c0", "pclk_bus", 5, 15), + RK_GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 6, 0), + RK_GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus", 6, 1), + RK_GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus", 6, 2), + RK_GATE(PCLK_PWM0, "pclk_pwm0", "pclk_bus", 6, 3), + RK_GATE(PCLK_SPI0, "pclk_spi0", "pclk_bus", 6, 4), + RK_GATE(PCLK_SPI1, "pclk_spi1", "pclk_bus", 6, 5), + RK_GATE(PCLK_SPI2, "pclk_spi2", "pclk_bus", 6, 6), + RK_GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 6, 7), + RK_GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus", 6, 8), + RK_GATE(PCLK_TIMER, "pclk_timer", "pclk_bus", 6, 9), + RK_GATE(PCLK_OTP_NS, "pclk_otp_ns", "pclk_bus", 6, 10), + RK_GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_bus", 6, 12), + RK_GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus", 6, 13), + RK_GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus", 6, 14), + RK_GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus", 6, 15), + RK_GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_bus", 7, 0), + RK_GATE(PCLK_SGRF, "pclk_sgrf", "pclk_bus", 7, 1), + RK_GATE(PCLK_GRF, "pclk_grf", "pclk_bus", 7, 2), + RK_GATE(PCLK_USBSD_DET, "pclk_usbsd_det", "pclk_bus", 7, 3), + RK_GATE(PCLK_DDR_UPCTL, "pclk_ddr_upctl", "pclk_bus", 7, 4), + RK_GATE(PCLK_DDR_MON, "pclk_ddr_mon", "pclk_bus", 7, 5), + RK_GATE(PCLK_DDRPHY, "pclk_ddrphy", "pclk_bus", 7, 6), + RK_GATE(PCLK_DDR_STDBY, "pclk_ddr_stdby", "pclk_bus", 7, 7), + RK_GATE(PCLK_USB_GRF, "pclk_usb_grf", "pclk_bus", 7, 8), + RK_GATE(PCLK_CRU, "pclk_cru", "pclk_bus", 7, 9), + RK_GATE(PCLK_OTP_PHY, "pclk_otp_phy", "pclk_bus", 7, 10), + RK_GATE(PCLK_CPU_BOOST, "pclk_cpu_boost", "pclk_bus", 7, 11), + RK_GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 7, 12), + RK_GATE(PCLK_PWM2, "pclk_pwm2", "pclk_bus", 7, 13), + RK_GATE(PCLK_CAN, "pclk_can", "pclk_bus", 7, 14), + RK_GATE(PCLK_OWIRE, "pclk_owire", "pclk_bus", 7, 15), +}; + + +static int +rk3308_cru_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (ofw_bus_is_compatible(dev, "rockchip,rk3308-cru")) { + device_set_desc(dev, "Rockchip RK3308 Clock & Reset Unit"); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +rk3308_cru_attach(device_t dev) +{ + struct rk_cru_softc *sc; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->clks = rk3308_clks; + sc->nclks = nitems(rk3308_clks); + sc->gates = rk3308_gates; + sc->ngates = nitems(rk3308_gates); + sc->reset_offset = 0x400; + sc->reset_num = 478; + + return (rk_cru_attach(dev)); +} + +static device_method_t methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, rk3308_cru_probe), + DEVMETHOD(device_attach, rk3308_cru_attach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(rk3308_cru, rk3308_cru_driver, methods, + sizeof(struct rk_cru_softc), rk_cru_driver); + +EARLY_DRIVER_MODULE(rk3308_cru, simplebus, rk3308_cru_driver, + 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE); Index: sys/arm64/rockchip/if_dwc_rk.c =================================================================== --- sys/arm64/rockchip/if_dwc_rk.c +++ sys/arm64/rockchip/if_dwc_rk.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2018 Emmanuel Vadot * @@ -103,6 +103,13 @@ #define SOC_CON6_GMAC_RXCLK_DLY_ENA (1 << 15) #define SOC_CON6_RX_DL_CFG_SHIFT 8 +/* RK3308 registers */ +#define RK3308_GRF_MAC_CON0 0x04a0 +#define RK3308_MAC_SPEED_100M ((0x1 << 0) << 16 | (0x1 << 0)) +#define RK3308_MAC_SPEED_10M ((0x1 << 0) << 16 | (0x0 << 0)) +#define RK3308_INTF_SEL_RMII ((0x1 << 4) << 16 | (0x1 << 4)) + + struct if_dwc_rk_softc; typedef void (*if_dwc_rk_set_delaysfn_t)(struct if_dwc_rk_softc *); @@ -147,9 +154,13 @@ static void rk3399_set_delays(struct if_dwc_rk_softc *sc); static int rk3399_set_speed(struct if_dwc_rk_softc *sc, int speed); +static int rk3308_set_speed(struct if_dwc_rk_softc *sc, int speed); +static void rk3308_set_phy_mode(struct if_dwc_rk_softc *sc); + static struct if_dwc_rk_ops rk3288_ops = { }; + static struct if_dwc_rk_ops rk3328_ops = { .set_delays = rk3328_set_delays, .set_speed = rk3328_set_speed, @@ -162,10 +173,17 @@ .set_speed = rk3399_set_speed, }; +static struct if_dwc_rk_ops rk3308_ops = { + .set_speed = rk3308_set_speed, + .set_phy_mode = rk3308_set_phy_mode, +}; + static struct ofw_compat_data compat_data[] = { {"rockchip,rk3288-gmac", (uintptr_t)&rk3288_ops}, {"rockchip,rk3328-gmac", (uintptr_t)&rk3328_ops}, {"rockchip,rk3399-gmac", (uintptr_t)&rk3399_ops}, + {"rockchip,rk3308-gmac", (uintptr_t)&rk3308_ops}, + {"rockchip,rk3308-mac", (uintptr_t)&rk3308_ops}, {NULL, 0} }; @@ -337,6 +355,46 @@ ((SOC_CON5_GMAC_CLK_SEL_MASK << 16) | reg)); return (0); } +static int +rk3308_set_speed(struct if_dwc_rk_softc *sc, int speed) +{ + uint32_t reg; + + switch (sc->base.phy_mode) { + case PHY_MODE_RGMII: + break; + case PHY_MODE_RMII: + switch (speed) { + case IFM_100_TX: + reg = RK3308_INTF_SEL_RMII | RK3308_MAC_SPEED_100M; + break; + case IFM_10_T: + reg = RK3308_INTF_SEL_RMII | RK3308_MAC_SPEED_10M; + break; + default: + device_printf(sc->base.dev, "unsupported RMII media %u\n", speed); + return (-1); + } + + SYSCON_WRITE_4(sc->grf, RK3308_GRF_MAC_CON0, reg); + break; + } + + return (0); +} + +static void +rk3308_set_phy_mode(struct if_dwc_rk_softc *sc) +{ + switch (sc->base.phy_mode) { + case PHY_MODE_RGMII: + break; + case PHY_MODE_RMII: + SYSCON_WRITE_4(sc->grf, RK3308_GRF_MAC_CON0,RK3308_INTF_SEL_RMII); + + break; + } +} static int if_dwc_rk_sysctl_delays(SYSCTL_HANDLER_ARGS) @@ -407,6 +465,8 @@ if (error != 0) { device_printf(dev, "could not find clock stmmaceth\n"); return (error); + } else { +// clk_set_freq(sc->clk_stmmaceth, 50000000, 0); } if (clk_get_by_ofw_name(dev, 0, "mac_clk_rx", &sc->mac_clk_rx) != 0) { @@ -440,7 +500,6 @@ device_printf(sc->base.dev, "could not get clk_mac_refout clock\n"); sc->clk_mac_refout = NULL; } - clk_set_freq(sc->clk_stmmaceth, 50000000, 0); } } @@ -464,8 +523,9 @@ if (sc->clk_mac_refout) clk_enable(sc->clk_mac_refout); } - if (sc->clk_phy) + if (sc->clk_phy) { clk_enable(sc->clk_phy); + } if (sc->aclk_mac) clk_enable(sc->aclk_mac); if (sc->pclk_mac) @@ -615,9 +675,11 @@ DEVMETHOD_END }; +static devclass_t dwc_rk_devclass; + extern driver_t dwc_driver; DEFINE_CLASS_1(dwc, dwc_rk_driver, if_dwc_rk_methods, sizeof(struct if_dwc_rk_softc), dwc_driver); -DRIVER_MODULE(dwc_rk, simplebus, dwc_rk_driver, 0, 0); +DRIVER_MODULE(dwc_rk, simplebus, dwc_rk_driver, dwc_rk_devclass, 0, 0); MODULE_DEPEND(dwc_rk, dwc, 1, 1, 1); Index: sys/arm64/rockchip/rk_grf.c =================================================================== --- sys/arm64/rockchip/rk_grf.c +++ sys/arm64/rockchip/rk_grf.c @@ -55,6 +55,7 @@ {"rockchip,rk3568-pipe-grf", 1}, {"rockchip,rk3568-pipe-phy-grf", 1}, {"rockchip,rk3568-pcie3-phy-grf", 1}, + {"rockchip,rk3308-grf", 1}, {NULL, 0} }; Index: sys/arm64/rockchip/rk_pinctrl.c =================================================================== --- sys/arm64/rockchip/rk_pinctrl.c +++ sys/arm64/rockchip/rk_pinctrl.c @@ -1004,11 +1004,195 @@ .get_bias_value = rk3568_get_bias_value, }; +static struct rk_pinctrl_gpio rk3308_gpio_bank[] = { + RK_GPIO(0, "gpio0"), + RK_GPIO(1, "gpio1"), + RK_GPIO(2, "gpio2"), + RK_GPIO(3, "gpio3"), + RK_GPIO(4, "gpio4"), + +}; + +static struct rk_pinctrl_bank rk3308_iomux_bank[] = { + /* bank sub offs nbits */ + RK_IOMUX(0, 0, 0x0000, 2), + RK_IOMUX(0, 1, 0x0004, 2), + RK_IOMUX(0, 2, 0x0008, 2), + RK_IOMUX(0, 3, 0x000C, 2), + RK_IOMUX(1, 0, 0x0010, 2), + RK_IOMUX(1, 1, 0x0014, 2), + RK_IOMUX(1, 2, 0x0018, 2), + RK_IOMUX(1, 3, 0x001C, 2), + RK_IOMUX(2, 0, 0x0020, 2), + RK_IOMUX(2, 1, 0x0024, 2), + RK_IOMUX(2, 2, 0x0028, 2), + RK_IOMUX(2, 3, 0x002C, 2), + RK_IOMUX(3, 0, 0x0030, 2), + RK_IOMUX(3, 1, 0x0034, 2), + RK_IOMUX(3, 2, 0x0038, 2), + RK_IOMUX(3, 3, 0x003C, 2), + RK_IOMUX(4, 0, 0x0040, 2), + RK_IOMUX(4, 1, 0x0044, 2), + RK_IOMUX(4, 2, 0x0048, 2), + RK_IOMUX(4, 3, 0x004C, 2), +}; +#define RK_PINFIX_MS(bank,pin,reg,bit,mask) RK_PINFIX(bank,pin,reg,bit,(mask << bit)) +static struct rk_pinctrl_pin_fixup rk3308_pin_fixup[] = { + /* bank pin reg bit mask */ + RK_PINFIX_MS(1, 14, 0x28, 12, 0xf), + RK_PINFIX_MS(1, 15, 0x2c, 0, 0x3), + RK_PINFIX_MS(1, 18, 0x30, 4, 0xf), + RK_PINFIX_MS(1, 19, 0x30, 8, 0xf), + RK_PINFIX_MS(1, 20, 0x30, 12, 0xf), + RK_PINFIX_MS(1, 21, 0x34, 0, 0xf), + RK_PINFIX_MS(1, 22, 0x34, 4, 0xf), + RK_PINFIX_MS(1, 23, 0x34, 8, 0xf), + RK_PINFIX_MS(2, 2, 0x40, 4, 0x3), + RK_PINFIX_MS(2, 3, 0x40, 6, 0x3), + RK_PINFIX_MS(2, 16, 0x50, 0, 0x3), + RK_PINFIX_MS(3, 10, 0x68, 4, 0x3), + RK_PINFIX_MS(3, 11, 0x68, 6, 0x3), + RK_PINFIX_MS(3, 12, 0x68, 8, 0xf), + RK_PINFIX_MS(3, 13, 0x68, 12, 0xf), +}; +static struct rk_pinctrl_pin_drive rk3308_pin_drive[] = { + /* bank sub offs val ma */ + RK_PINDRIVE(0, 0, 0x100, 0, 2), + RK_PINDRIVE(0, 0, 0x100, 1, 4), + RK_PINDRIVE(0, 0, 0x100, 2, 8), + RK_PINDRIVE(0, 0, 0x100, 3, 12), + + RK_PINDRIVE(0, 1, 0x104, 0, 2), + RK_PINDRIVE(0, 1, 0x104, 1, 4), + RK_PINDRIVE(0, 1, 0x104, 2, 8), + RK_PINDRIVE(0, 1, 0x104, 3, 12), + + RK_PINDRIVE(0, 2, 0x108, 0, 2), + RK_PINDRIVE(0, 2, 0x108, 1, 4), + RK_PINDRIVE(0, 2, 0x108, 2, 8), + RK_PINDRIVE(0, 2, 0x108, 3, 12), + + RK_PINDRIVE(0, 3, 0x10C, 0, 2), + RK_PINDRIVE(0, 3, 0x10C, 1, 4), + RK_PINDRIVE(0, 3, 0x10C, 2, 8), + RK_PINDRIVE(0, 3, 0x10C, 3, 12), + + RK_PINDRIVE(1, 0, 0x110, 0, 2), + RK_PINDRIVE(1, 0, 0x110, 1, 4), + RK_PINDRIVE(1, 0, 0x110, 2, 8), + RK_PINDRIVE(1, 0, 0x110, 3, 12), + + RK_PINDRIVE(1, 1, 0x114, 0, 2), + RK_PINDRIVE(1, 1, 0x114, 1, 4), + RK_PINDRIVE(1, 1, 0x114, 2, 8), + RK_PINDRIVE(1, 1, 0x114, 3, 12), + + RK_PINDRIVE(1, 2, 0x118, 0, 2), + RK_PINDRIVE(1, 2, 0x118, 1, 4), + RK_PINDRIVE(1, 2, 0x118, 2, 8), + RK_PINDRIVE(1, 2, 0x118, 3, 12), + + RK_PINDRIVE(1, 3, 0x11C, 0, 2), + RK_PINDRIVE(1, 3, 0x11C, 1, 4), + RK_PINDRIVE(1, 3, 0x11C, 2, 8), + RK_PINDRIVE(1, 3, 0x11C, 3, 12), + + RK_PINDRIVE(2, 0, 0x120, 0, 2), + RK_PINDRIVE(2, 0, 0x120, 1, 4), + RK_PINDRIVE(2, 0, 0x120, 2, 8), + RK_PINDRIVE(2, 0, 0x120, 3, 12), + + RK_PINDRIVE(2, 1, 0x124, 0, 2), + RK_PINDRIVE(2, 1, 0x124, 1, 4), + RK_PINDRIVE(2, 1, 0x124, 2, 8), + RK_PINDRIVE(2, 1, 0x124, 3, 12), + + RK_PINDRIVE(2, 2, 0x128, 0, 2), + RK_PINDRIVE(2, 2, 0x128, 1, 4), + RK_PINDRIVE(2, 2, 0x128, 2, 8), + RK_PINDRIVE(2, 2, 0x128, 3, 12), + + RK_PINDRIVE(2, 3, 0x12C, 0, 2), + RK_PINDRIVE(2, 3, 0x12C, 1, 4), + RK_PINDRIVE(2, 3, 0x12C, 2, 8), + RK_PINDRIVE(2, 3, 0x12C, 3, 12), + + RK_PINDRIVE(3, 0, 0x130, 0, 2), + RK_PINDRIVE(3, 0, 0x130, 1, 4), + RK_PINDRIVE(3, 0, 0x130, 2, 8), + RK_PINDRIVE(3, 0, 0x130, 3, 12), + + RK_PINDRIVE(3, 1, 0x134, 0, 2), + RK_PINDRIVE(3, 1, 0x134, 1, 4), + RK_PINDRIVE(3, 1, 0x134, 2, 8), + RK_PINDRIVE(3, 1, 0x134, 3, 12), + + RK_PINDRIVE(3, 2, 0x138, 0, 2), + RK_PINDRIVE(3, 2, 0x138, 1, 4), + RK_PINDRIVE(3, 2, 0x138, 2, 8), + RK_PINDRIVE(3, 2, 0x138, 3, 12), + + RK_PINDRIVE(3, 3, 0x13C, 0, 2), + RK_PINDRIVE(3, 3, 0x13C, 1, 4), + RK_PINDRIVE(3, 3, 0x13C, 2, 8), + RK_PINDRIVE(3, 3, 0x13C, 3, 12), + + RK_PINDRIVE(4, 0, 0x140, 0, 2), + RK_PINDRIVE(4, 0, 0x140, 1, 4), + RK_PINDRIVE(4, 0, 0x140, 2, 8), + RK_PINDRIVE(4, 0, 0x140, 4, 12), + + RK_PINDRIVE(4, 1, 0x144, 0, 2), + RK_PINDRIVE(4, 1, 0x144, 1, 4), + RK_PINDRIVE(4, 1, 0x144, 2, 8), + RK_PINDRIVE(4, 1, 0x144, 4, 12), + + RK_PINDRIVE(4, 2, 0x148, 0, 2), + RK_PINDRIVE(4, 2, 0x148, 1, 4), + RK_PINDRIVE(4, 2, 0x148, 2, 8), + RK_PINDRIVE(4, 2, 0x148, 4, 12), + + RK_PINDRIVE(4, 4, 0x14C, 0, 2), + RK_PINDRIVE(4, 4, 0x14C, 1, 4), + RK_PINDRIVE(4, 4, 0x14C, 2, 8), + RK_PINDRIVE(4, 4, 0x14C, 4, 12), + +}; + +static uint32_t +rk3308_get_pd_offset(struct rk_pinctrl_softc *sc, uint32_t bank) +{ + return (0xA0); +} + +static struct syscon * +rk3308_get_syscon(struct rk_pinctrl_softc *sc, uint32_t bank) +{ + return (sc->grf); +} + +struct rk_pinctrl_conf rk3308_conf = { + .iomux_conf = rk3308_iomux_bank, + .iomux_nbanks = nitems(rk3308_iomux_bank), + .pin_fixup = rk3308_pin_fixup, + .npin_fixup = nitems(rk3308_pin_fixup), + .pin_drive = rk3308_pin_drive, + .npin_drive = nitems(rk3308_pin_drive), + .gpio_bank = rk3308_gpio_bank, + .ngpio_bank = nitems(rk3308_gpio_bank), + .get_pd_offset = rk3308_get_pd_offset, + .get_syscon = rk3308_get_syscon, + .parse_bias = rk3288_parse_bias, + .resolv_bias_value = rk3288_resolv_bias_value, + .get_bias_value = rk3288_get_bias_value, +}; + static struct ofw_compat_data compat_data[] = { {"rockchip,rk3288-pinctrl", (uintptr_t)&rk3288_conf}, {"rockchip,rk3328-pinctrl", (uintptr_t)&rk3328_conf}, {"rockchip,rk3399-pinctrl", (uintptr_t)&rk3399_conf}, {"rockchip,rk3568-pinctrl", (uintptr_t)&rk3568_conf}, + {"rockchip,rk3308-pinctrl", (uintptr_t)&rk3308_conf}, {NULL, 0} }; Index: sys/arm64/rockchip/rk_pwm.c =================================================================== --- sys/arm64/rockchip/rk_pwm.c +++ sys/arm64/rockchip/rk_pwm.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2018 Emmanuel Vadot * Copyright (c) 2019 Brandon Bergren @@ -100,6 +100,7 @@ static struct ofw_compat_data compat_data[] = { { "rockchip,rk3288-pwm", 1 }, + { "rockchip,rk3328-pwm", 1 }, { "rockchip,rk3399-pwm", 1 }, { NULL, 0 } }; @@ -398,5 +399,7 @@ sizeof(struct rk_pwm_softc), }; -DRIVER_MODULE(rk_pwm, simplebus, rk_pwm_driver, 0, 0); +static devclass_t rk_pwm_devclass; + +EARLY_DRIVER_MODULE(rk_pwm, simplebus, rk_pwm_driver, rk_pwm_devclass, 0, 0,BUS_PASS_BUS + BUS_PASS_ORDER_LATE); SIMPLEBUS_PNP_INFO(compat_data); Index: sys/arm64/rockchip/rk_spi.c =================================================================== --- sys/arm64/rockchip/rk_spi.c +++ sys/arm64/rockchip/rk_spi.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2019 Oleksandr Tymoshenko * @@ -92,7 +92,7 @@ static struct ofw_compat_data compat_data[] = { { "rockchip,rk3328-spi", 1 }, { "rockchip,rk3399-spi", 1 }, - { "rockchip,rk3568-spi", 1 }, + { "rockchip,rk3308-spi", 1 }, { NULL, 0 } }; @@ -475,7 +475,9 @@ sizeof(struct rk_spi_softc), }; -DRIVER_MODULE(rk_spi, simplebus, rk_spi_driver, 0, 0); -DRIVER_MODULE(ofw_spibus, rk_spi, ofw_spibus_driver, 0, 0); +static devclass_t rk_spi_devclass; + +DRIVER_MODULE(rk_spi, simplebus, rk_spi_driver, rk_spi_devclass, 0, 0); +DRIVER_MODULE(ofw_spibus, rk_spi, ofw_spibus_driver, ofw_spibus_devclass, 0, 0); MODULE_DEPEND(rk_spi, ofw_spibus, 1, 1, 1); OFWBUS_PNP_INFO(compat_data); Index: sys/arm64/rockchip/rk_tsadc.c =================================================================== --- sys/arm64/rockchip/rk_tsadc.c +++ sys/arm64/rockchip/rk_tsadc.c @@ -262,6 +262,7 @@ } }; + static struct rk_calib_entry rk3399_calib_data[] = { {402, -40000}, {410, -35000}, @@ -375,11 +376,33 @@ } }; +static struct tsensor rk3308_tsensors[] = { + { .channel = 0, .id = 0, .name = "CPU"}, + { .channel = 1, .id = 1, .name = "GPU"}, +}; + +static struct tsadc_conf rk3308_tsadc_conf = { + .version = TSADC_V2, + .q_sel_ntc = 1, + .shutdown_temp = 95000, + .shutdown_mode = 0, /* CRU */ + .shutdown_pol = 0, /* Low */ + .tsensors = rk3308_tsensors, + .ntsensors = nitems(rk3308_tsensors), + .calib_info = { + .table = rk3328_calib_data, + .nentries = nitems(rk3328_calib_data), + } +}; + + static struct ofw_compat_data compat_data[] = { {"rockchip,rk3288-tsadc", (uintptr_t)&rk3288_tsadc_conf}, {"rockchip,rk3328-tsadc", (uintptr_t)&rk3328_tsadc_conf}, + {"rockchip,rk3308-tsadc", (uintptr_t)&rk3328_tsadc_conf}, {"rockchip,rk3399-tsadc", (uintptr_t)&rk3399_tsadc_conf}, {"rockchip,rk3568-tsadc", (uintptr_t)&rk3568_tsadc_conf}, + {"rockchip,rk3308-tsadc", (uintptr_t)&rk3308_tsadc_conf}, {NULL, 0} }; Index: sys/arm64/rockchip/rk_usb2phy.c =================================================================== --- sys/arm64/rockchip/rk_usb2phy.c +++ sys/arm64/rockchip/rk_usb2phy.c @@ -81,10 +81,19 @@ .disable_mask = 0x100010, } }; +struct rk_usb2phy_regs rk3308_regs = { + .clk_ctl = { + .offset = 0x0108, + .enable_mask = 0x100000, + /* bit 4 put pll in suspend */ + .disable_mask = 0x100010, + } +}; static struct ofw_compat_data compat_data[] = { { "rockchip,rk3399-usb2phy", (uintptr_t)&rk3399_regs }, { "rockchip,rk3568-usb2phy", (uintptr_t)&rk3568_regs }, + { "rockchip,rk3308-usb2phy", (uintptr_t)&rk3308_regs }, { NULL, 0 } }; Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -1709,6 +1709,7 @@ dev/extres/regulator/regulator.c optional regulator dev/extres/regulator/regulator_bus.c optional regulator fdt dev/extres/regulator/regulator_fixed.c optional regulator +dev/extres/regulator/regulator_pwm.c optional regulator fdt dev/extres/syscon/syscon.c optional syscon dev/extres/syscon/syscon_generic.c optional syscon fdt dev/extres/syscon/syscon_if.m optional syscon Index: sys/conf/files.arm64 =================================================================== --- sys/conf/files.arm64 +++ sys/conf/files.arm64 @@ -690,6 +690,7 @@ arm64/rockchip/clk/rk3399_pmucru.c optional fdt soc_rockchip_rk3399 arm64/rockchip/clk/rk3568_cru.c optional fdt soc_rockchip_rk3568 arm64/rockchip/clk/rk3568_pmucru.c optional fdt soc_rockchip_rk3568 +arm64/rockchip/clk/rk3308_cru.c optional fdt soc_rockchip_rk3308 # Xilinx arm/xilinx/uart_dev_cdnc.c optional uart soc_xilinx_zynq fdt Index: sys/dev/extres/regulator/regulator_pwm.h =================================================================== --- /dev/null +++ sys/dev/extres/regulator/regulator_pwm.h @@ -0,0 +1,16 @@ +#ifndef _DEV_EXTRES_REGULATOR_PWM_H_ +#define _DEV_EXTRES_REGULATOR_PWM_H_ + +#include +#include + +struct regnode_pwm_init_def { + struct regnode_init_def reg_init_def; + bool gpio_open_drain; + struct gpiobus_pin *gpio_pin; +}; + +int regnode_pwm_register(device_t dev, + struct regnode_pwm_init_def *init_def); + +#endif /*_DEV_EXTRES_REGULATOR_PWM_H_*/ Index: sys/dev/extres/regulator/regulator_pwm.c =================================================================== --- /dev/null +++ sys/dev/extres/regulator/regulator_pwm.c @@ -0,0 +1,560 @@ +#include +__FBSDID("$FreeBSD$"); + +#include "opt_platform.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef FDT +#include +#include +#include +#include "pwmbus_if.h" +#endif +#include +#include +#include + +#include "regdev_if.h" + +MALLOC_DEFINE(M_PWMREGULATOR, "pwmregulator", "PWM regulator"); + +/* GPIO list for shared pins. */ +typedef TAILQ_HEAD(gpio_list, gpio_entry) gpio_list_t; +struct gpio_entry { + TAILQ_ENTRY(gpio_entry) link; + struct gpiobus_pin gpio_pin; + int use_cnt; + int enable_cnt; + bool always_on; +}; +static gpio_list_t gpio_list = TAILQ_HEAD_INITIALIZER(gpio_list); +static struct mtx gpio_list_mtx; +MTX_SYSINIT(gpio_list_lock, &gpio_list_mtx, "Regulator GPIO lock", MTX_DEF); + +struct regnode_pwm_sc { + struct regnode_std_param *param; + bool gpio_open_drain; + struct gpio_entry *gpio_entry; +}; + +static int regnode_pwm_init(struct regnode *regnode); +static int regnode_pwm_enable(struct regnode *regnode, bool enable, + int *udelay); +static int regnode_pwm_status(struct regnode *regnode, int *status); +static int regnode_pwm_stop(struct regnode *regnode, int *udelay); +static int regnode_pwm_get_voltage(struct regnode *regnode, int *uvolt); +static int regnode_pwm_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt,int *udelay); + +static regnode_method_t regnode_pwm_methods[] = { + /* Regulator interface */ + REGNODEMETHOD(regnode_init, regnode_pwm_init), + REGNODEMETHOD(regnode_enable, regnode_pwm_enable), + REGNODEMETHOD(regnode_status, regnode_pwm_status), + REGNODEMETHOD(regnode_stop, regnode_pwm_stop), + REGNODEMETHOD(regnode_get_voltage, regnode_pwm_get_voltage), + REGNODEMETHOD(regnode_set_voltage, regnode_pwm_set_voltage), + REGNODEMETHOD(regnode_check_voltage, regnode_method_check_voltage), + REGNODEMETHOD_END +}; +DEFINE_CLASS_1(regnode_pwm, regnode_pwm_class, regnode_pwm_methods, + sizeof(struct regnode_pwm_sc), regnode_class); + +/* + * GPIO list functions. + * Two or more regulators can share single GPIO pins, so we must track all + * GPIOs in gpio_list. + * The GPIO pin is registerd and reseved for first consumer, all others share + * gpio_entry with it. + */ +static struct gpio_entry * +regnode_get_gpio_entry(struct gpiobus_pin *gpio_pin) +{ + struct gpio_entry *entry, *tmp; + device_t busdev; + int rv; + + busdev = GPIO_GET_BUS(gpio_pin->dev); + if (busdev == NULL) + return (NULL); + entry = malloc(sizeof(struct gpio_entry), M_PWMREGULATOR, + M_WAITOK | M_ZERO); + + mtx_lock(&gpio_list_mtx); + + TAILQ_FOREACH(tmp, &gpio_list, link) { + if (tmp->gpio_pin.dev == gpio_pin->dev && + tmp->gpio_pin.pin == gpio_pin->pin) { + tmp->use_cnt++; + mtx_unlock(&gpio_list_mtx); + free(entry, M_PWMREGULATOR); + return (tmp); + } + } + + /* Reserve pin. */ + /* XXX Can we call gpiobus_acquire_pin() with gpio_list_mtx held? */ + rv = gpiobus_acquire_pin(busdev, gpio_pin->pin); + if (rv != 0) { + mtx_unlock(&gpio_list_mtx); + free(entry, M_PWMREGULATOR); + return (NULL); + } + /* Everything is OK, build new entry and insert it to list. */ + entry->gpio_pin = *gpio_pin; + entry->use_cnt = 1; + TAILQ_INSERT_TAIL(&gpio_list, entry, link); + + mtx_unlock(&gpio_list_mtx); + return (entry); +} + +#ifdef FDT +#include +struct regpwm_softc +{ + device_t dev; + bool attach_done; + struct regnode_pwm_init_def init_def; + phandle_t gpio_prodxref; + pcell_t *gpio_cells; + int gpio_ncells; + struct gpiobus_pin gpio_pin; + pwm_channel_t channel; + uint32_t sc_dutycycle_unit; + uint32_t sc_dutycycle_range[2]; +}; +#endif +/* + * Regulator class implementation. + */ +static int +regnode_pwm_init(struct regnode *regnode) +{ + device_t dev; + struct regnode_pwm_sc *sc; + struct gpiobus_pin *pin; + uint32_t flags; + int rv; + + sc = regnode_get_softc(regnode); + dev = regnode_get_device(regnode); + sc->param = regnode_get_stdparam(regnode); + if (sc->gpio_entry == NULL) + return (0); + pin = &sc->gpio_entry->gpio_pin; + + flags = GPIO_PIN_OUTPUT; + if (sc->gpio_open_drain) + flags |= GPIO_PIN_OPENDRAIN; + if (sc->param->boot_on || sc->param->always_on) { + rv = GPIO_PIN_SET(pin->dev, pin->pin, sc->param->enable_active_high); + if (rv != 0) { + device_printf(dev, "Cannot set GPIO pin: %d\n", + pin->pin); + return (rv); + } + } + + rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags); + if (rv != 0) { + device_printf(dev, "Cannot configure GPIO pin: %d\n", pin->pin); + return (rv); + } + + return (0); +} + +/* + * Enable/disable regulator. + * Take shared GPIO pins in account + */ +static int +regnode_pwm_enable(struct regnode *regnode, bool enable, int *udelay) +{ + device_t dev; + struct regnode_pwm_sc *sc; + struct gpiobus_pin *pin; + int rv; + + sc = regnode_get_softc(regnode); + dev = regnode_get_device(regnode); + + *udelay = 0; + if (sc->gpio_entry == NULL) + return (0); + pin = &sc->gpio_entry->gpio_pin; + if (enable) { + sc->gpio_entry->enable_cnt++; + if (sc->gpio_entry->enable_cnt > 1) + return (0); + } else { + KASSERT(sc->gpio_entry->enable_cnt > 0, + ("Invalid enable count")); + sc->gpio_entry->enable_cnt--; + if (sc->gpio_entry->enable_cnt >= 1) + return (0); + } + if (sc->gpio_entry->always_on && !enable) + return (0); + if (!sc->param->enable_active_high) + enable = !enable; + rv = GPIO_PIN_SET(pin->dev, pin->pin, enable); + if (rv != 0) { + device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin); + return (rv); + } + *udelay = sc->param->enable_delay; + return (0); +} + +/* + * Stop (physicaly shutdown) regulator. + * Take shared GPIO pins in account + */ +static int +regnode_pwm_stop(struct regnode *regnode, int *udelay) +{ + device_t dev; + struct regnode_pwm_sc *sc; + struct gpiobus_pin *pin; + int rv; + + sc = regnode_get_softc(regnode); + dev = regnode_get_device(regnode); + + *udelay = 0; + if (sc->gpio_entry == NULL) + return (0); + if (sc->gpio_entry->always_on) + return (0); + pin = &sc->gpio_entry->gpio_pin; + if (sc->gpio_entry->enable_cnt > 0) { + /* Other regulator(s) are enabled. */ + /* XXXX Any diagnostic message? Or error? */ + return (0); + } + rv = GPIO_PIN_SET(pin->dev, pin->pin, + sc->param->enable_active_high ? false: true); + if (rv != 0) { + device_printf(dev, "Cannot set GPIO pin: %d\n", pin->pin); + return (rv); + } + *udelay = sc->param->enable_delay; + return (0); +} + +static int +regnode_pwm_status(struct regnode *regnode, int *status) +{ + struct regnode_pwm_sc *sc; + struct gpiobus_pin *pin; + uint32_t val; + int rv; + + sc = regnode_get_softc(regnode); + + *status = 0; + if (sc->gpio_entry == NULL) { + *status = REGULATOR_STATUS_ENABLED; + return (0); + } + pin = &sc->gpio_entry->gpio_pin; + + rv = GPIO_PIN_GET(pin->dev, pin->pin, &val); + if (rv == 0) { + if (!sc->param->enable_active_high ^ (val != 0)) + *status = REGULATOR_STATUS_ENABLED; + } + return (rv); +} +static int +regnode_pwm_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt, int * udelay) +{ + struct regnode_pwm_sc *sc; + struct regpwm_softc *dsc; + int32_t x0, x1, y0, y1; + int32_t x, y; + bool enabled; + + sc = regnode_get_softc(regnode); + dsc = device_get_softc(regnode_get_device(regnode)); + PWMBUS_CHANNEL_IS_ENABLED(dsc->channel->dev,dsc->channel->channel, &enabled); + if(!enabled) + return 0; + + x0 = sc->param->min_uvolt; + x1 = sc->param->max_uvolt; + y0 = dsc->sc_dutycycle_range[0]; + y1 = dsc->sc_dutycycle_range[1]; + x = min_uvolt; + y = y0 + (x - x0) * (y1 - y0) / (x1 - x0); + dsc->channel->duty = (y * dsc->channel->period) / dsc->sc_dutycycle_unit; + PWMBUS_CHANNEL_CONFIG(dsc->channel->dev,dsc->channel->channel, + dsc->channel->period, dsc->channel->duty); + return 0; +} + +static int +regnode_pwm_get_voltage(struct regnode *regnode, int *uvolt) +{ + struct regnode_pwm_sc *sc; + struct regpwm_softc *dsc; + int32_t x0, x1, y0, y1; + int32_t x, y; + bool enabled; + + sc = regnode_get_softc(regnode); + dsc = device_get_softc(regnode_get_device(regnode)); + PWMBUS_CHANNEL_IS_ENABLED(dsc->channel->dev,dsc->channel->channel, &enabled); + if(!enabled) + return 0; + + PWMBUS_CHANNEL_GET_CONFIG(dsc->channel->dev,dsc->channel->channel, + (u_int *) &dsc->channel->period, (u_int *)&dsc->channel->duty); + + x0 = dsc->sc_dutycycle_range[0]; + x1 = dsc->sc_dutycycle_range[1]; + y0 = sc->param->min_uvolt; + y1 = sc->param->max_uvolt; + x = (dsc->channel->duty * dsc->sc_dutycycle_unit) / dsc->channel->period; + y = y0 + (x - x0) * (y1 - y0) / (x1 - x0); + + *uvolt = y; + return (0); +} + +int +regnode_pwm_register(device_t dev, struct regnode_pwm_init_def *init_def) +{ + struct regnode *regnode; + struct regnode_pwm_sc *sc; + + regnode = regnode_create(dev, ®node_pwm_class, + &init_def->reg_init_def); + if (regnode == NULL) { + device_printf(dev, "Cannot create regulator.\n"); + return(ENXIO); + } + sc = regnode_get_softc(regnode); + sc->gpio_open_drain = init_def->gpio_open_drain; + if (init_def->gpio_pin != NULL) { + sc->gpio_entry = regnode_get_gpio_entry(init_def->gpio_pin); + if (sc->gpio_entry == NULL) + return(ENXIO); + } + regnode = regnode_register(regnode); + if (regnode == NULL) { + device_printf(dev, "Cannot register regulator.\n"); + return(ENXIO); + } + + if (sc->gpio_entry != NULL) + sc->gpio_entry->always_on |= sc->param->always_on; + + return (0); +} + +/* + * OFW Driver implementation. + */ +#ifdef FDT +static struct ofw_compat_data compat_data[] = { + {"pwm-regulator", 1}, + {NULL, 0}, +}; + +static int +regpwm_get_gpio(struct regpwm_softc * sc) +{ + device_t busdev; + phandle_t node; + + int rv; + + if (sc->gpio_prodxref == 0) + return (0); + + node = ofw_bus_get_node(sc->dev); + + /* Test if controller exist. */ + sc->gpio_pin.dev = OF_device_from_xref(sc->gpio_prodxref); + if (sc->gpio_pin.dev == NULL) + return (ENODEV); + + /* Test if GPIO bus already exist. */ + busdev = GPIO_GET_BUS(sc->gpio_pin.dev); + if (busdev == NULL) + return (ENODEV); + + rv = gpio_map_gpios(sc->gpio_pin.dev, node, + OF_node_from_xref(sc->gpio_prodxref), sc->gpio_ncells, + sc->gpio_cells, &(sc->gpio_pin.pin), &(sc->gpio_pin.flags)); + if (rv != 0) { + device_printf(sc->dev, "Cannot map the gpio property.\n"); + return (ENXIO); + } + sc->init_def.gpio_pin = &sc->gpio_pin; + return (0); +} + +static int +regpwm_parse_fdt(struct regpwm_softc * sc) +{ + phandle_t node; + int rv; + int len; + struct regnode_init_def *init_def; + + node = ofw_bus_get_node(sc->dev); + init_def = &sc->init_def.reg_init_def; + + rv = regulator_parse_ofw_stdparam(sc->dev, node, init_def); + if (rv != 0) { + device_printf(sc->dev, "Cannot parse standard parameters.\n"); + return(rv); + } + len = OF_getproplen(node, "pwms"); + if (len <= 4) { + device_printf(sc->dev, ": no pwms property\n"); + return ENXIO; + } + + if (OF_getproplen(node, "voltage-tables") > 0) { + device_printf(sc->dev, ": voltage table mode unsupported\n"); + return ENXIO; + } + + if (init_def->std_param.min_uvolt > init_def->std_param.max_uvolt) { + device_printf(sc->dev, "min_uvolt > max_uvolt\n"); + return (ENXIO); + } + rv = pwm_get_by_ofw_propidx(sc->dev, node, "pwms", 0, &sc->channel); + if (rv != 0) { + device_printf(sc->dev, "Cannot map pwm channel %d\n", rv); + return (ENXIO); + } + + rv = OF_getencprop(node, "pwm-dutycycle-unit", &sc->sc_dutycycle_unit, + sizeof(sc->sc_dutycycle_unit)); + if(rv <= 0) sc->sc_dutycycle_unit = 100; + sc->sc_dutycycle_range[0] = 0; + sc->sc_dutycycle_range[1] = 100; + rv = OF_getencprop(node, "pwm-dutycycle-range", + sc->sc_dutycycle_range, sizeof(sc->sc_dutycycle_range)); +// device_printf(sc->dev,"%x %x\n",sc->sc_dutycycle_range[0],sc->sc_dutycycle_range[1]); + /* PWM regulator uses 'startup-delay-us' property for enable_delay */ +/* + if (!OF_hasprop(node, "gpio")) + return (0); + rv = ofw_bus_parse_xref_list_alloc(node, "gpio", "#gpio-cells", 0, + &sc->gpio_prodxref, &sc->gpio_ncells, &sc->gpio_cells); + if (rv != 0) { + sc->gpio_prodxref = 0; + device_printf(sc->dev, "Malformed gpio property\n"); + return (ENXIO); + } +*/ + return (0); +} + +static void +regpwm_new_pass(device_t dev) +{ + struct regpwm_softc * sc; + int rv; + + sc = device_get_softc(dev); + bus_generic_new_pass(dev); + + if (sc->attach_done) + return; + + /* Try to get and configure GPIO. */ + rv = regpwm_get_gpio(sc); + if (rv != 0) + return; + + /* Register regulator. */ + regnode_pwm_register(sc->dev, &sc->init_def); + sc->attach_done = true; +} + +static int +regpwm_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_search_compatible(dev, compat_data)->ocd_data) + return (ENXIO); + + device_set_desc(dev, "PWM Regulator"); + return (BUS_PROBE_DEFAULT); +} + +static int +regpwm_detach(device_t dev) +{ + + /* This device is always present. */ + return (EBUSY); +} + +static int +regpwm_attach(device_t dev) +{ + struct regpwm_softc * sc; + int rv; + + sc = device_get_softc(dev); + sc->dev = dev; + + /* Parse FDT data. */ + rv = regpwm_parse_fdt(sc); + if (rv != 0) + return(ENXIO); + + /* Fill reset of init. */ + sc->init_def.reg_init_def.id = 1; + sc->init_def.reg_init_def.flags = REGULATOR_FLAGS_STATIC; + + /* Try to get and configure GPIO. */ + rv = regpwm_get_gpio(sc); + if (rv != 0) + return (bus_generic_attach(dev)); + + /* Register regulator. */ + regnode_pwm_register(sc->dev, &sc->init_def); + sc->attach_done = true; + + return (bus_generic_attach(dev)); +} + +static device_method_t regpwm_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, regpwm_probe), + DEVMETHOD(device_attach, regpwm_attach), + DEVMETHOD(device_detach, regpwm_detach), + /* Bus interface */ + DEVMETHOD(bus_new_pass, regpwm_new_pass), + /* Regdev interface */ + DEVMETHOD(regdev_map, regdev_default_ofw_map), + + DEVMETHOD_END +}; + +static devclass_t regpwm_devclass; +DEFINE_CLASS_0(regpwm, regpwm_driver, regpwm_methods, + sizeof(struct regpwm_softc)); +EARLY_DRIVER_MODULE(regpwm, simplebus, regpwm_driver, + regpwm_devclass, 0, 0, BUS_PASS_BUS); + +#endif /* FDT */