Home | History | Annotate | Line # | Download | only in rockchip
      1 /* $NetBSD: rk_cru.h,v 1.11 2022/08/23 05:39:06 ryo Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2018 Jared McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #ifndef _ARM_RK_CRU_H
     30 #define _ARM_RK_CRU_H
     31 
     32 #include <dev/clk/clk_backend.h>
     33 #include <dev/fdt/syscon.h>
     34 
     35 struct rk_cru_softc;
     36 struct rk_cru_clk;
     37 
     38 /*
     39  * Clocks
     40  */
     41 
     42 enum rk_cru_clktype {
     43 	RK_CRU_UNKNOWN,
     44 	RK_CRU_PLL,
     45 	RK_CRU_ARM,
     46 	RK_CRU_COMPOSITE,
     47 	RK_CRU_GATE,
     48 	RK_CRU_MUX,
     49 };
     50 
     51 /* PLL clocks */
     52 
     53 struct rk_cru_pll_rate {
     54 	u_int			rate;
     55 	union {
     56 		struct { /* RK3328,3399 */
     57 			u_int	refdiv;
     58 			u_int	fbdiv;
     59 			u_int	postdiv1;
     60 			u_int	postdiv2;
     61 			u_int	dsmpd;
     62 			u_int	fracdiv;
     63 		};
     64 		struct { /* RK3588 */
     65 			u_int	p;
     66 			u_int	m;
     67 			u_int	s;
     68 			u_int	k;
     69 		};
     70 	};
     71 };
     72 
     73 #define	RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _fracdiv) \
     74 	{							\
     75 		.rate = (_rate),				\
     76 		.refdiv = (_refdiv),				\
     77 		.fbdiv = (_fbdiv),				\
     78 		.postdiv1 = (_postdiv1),			\
     79 		.postdiv2 = (_postdiv2),			\
     80 		.dsmpd = (_dsmpd),				\
     81 		.fracdiv = (_fracdiv),				\
     82 	}
     83 
     84 #define	RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \
     85 	{							\
     86 		.rate = (_rate),				\
     87 		.p = (_p),					\
     88 		.m = (_m),					\
     89 		.s = (_s),					\
     90 		.k = (_k),					\
     91 	}
     92 
     93 struct rk_cru_pll {
     94 	bus_size_t	con_base;
     95 	bus_size_t	mode_reg;
     96 	uint32_t	mode_mask;
     97 	uint32_t	lock_mask;
     98 	const struct rk_cru_pll_rate *rates;
     99 	u_int		nrates;
    100 	const char	**parents;
    101 	u_int		nparents;
    102 	u_int		flags;
    103 #define	RK_PLL_RK3288	0x01
    104 #define	RK_PLL_RK3588	0x02
    105 };
    106 
    107 u_int	rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
    108 int	rk_cru_pll_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
    109 const char *rk_cru_pll_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
    110 
    111 #define	RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, _flags) \
    112 	{							\
    113 		.id = (_id),					\
    114 		.type = RK_CRU_PLL,				\
    115 		.base.name = (_name),				\
    116 		.base.flags = 0,				\
    117 		.u.pll.parents = (_parents),			\
    118 		.u.pll.nparents = __arraycount(_parents),	\
    119 		.u.pll.con_base = (_con_base),			\
    120 		.u.pll.mode_reg = (_mode_reg),			\
    121 		.u.pll.mode_mask = (_mode_mask),		\
    122 		.u.pll.lock_mask = (_lock_mask),		\
    123 		.u.pll.rates = (_rates),			\
    124 		.u.pll.nrates = __arraycount(_rates),		\
    125 		.u.pll.flags = _flags,				\
    126 		.get_rate = rk_cru_pll_get_rate,		\
    127 		.set_rate = rk_cru_pll_set_rate,		\
    128 		.get_parent = rk_cru_pll_get_parent,		\
    129 	}
    130 
    131 #define	RK_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
    132 	RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, 0)
    133 
    134 #define	RK3288_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
    135 	RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, RK_PLL_RK3288)
    136 
    137 #define	RK3588_PLL(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
    138 	RK_PLL_FLAGS(_id, _name, _parents, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates, RK_PLL_RK3588)
    139 
    140 /* ARM clocks */
    141 
    142 struct rk_cru_arm_rate {
    143 	u_int		rate;
    144 	u_int		div;
    145 };
    146 
    147 #define	RK_ARM_RATE(_rate, _div)				\
    148 	{							\
    149 		.rate = (_rate),				\
    150 		.div = (_div),					\
    151 	}
    152 
    153 struct rk_regmaskval {
    154 	bus_size_t	reg;
    155 	uint32_t	mask;
    156 	uint32_t	val;
    157 };
    158 
    159 struct rk_cru_cpu_rate {
    160 	u_int			rate;
    161 	struct rk_regmaskval	divs[4];
    162 	struct rk_regmaskval	pre_muxs[3];
    163 	struct rk_regmaskval	post_muxs[3];
    164 };
    165 
    166 struct rk_regmask {
    167 	bus_size_t	reg;
    168 	uint32_t	mask;
    169 };
    170 
    171 struct rk_cru_arm {
    172 	bus_size_t	mux_reg;
    173 	uint32_t	mux_mask;
    174 	u_int		mux_main;
    175 	u_int		mux_alt;
    176 	struct rk_regmask divs[4];
    177 	const char	**parents;
    178 	u_int		nparents;
    179 	const struct rk_cru_arm_rate *rates;
    180 	const struct rk_cru_cpu_rate *cpurates;
    181 	u_int		nrates;
    182 };
    183 
    184 u_int	rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
    185 int	rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
    186 int	rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
    187 const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
    188 int	rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
    189 
    190 #define	RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \
    191 	{							\
    192 		.id = (_id),					\
    193 		.type = RK_CRU_ARM,				\
    194 		.base.name = (_name),				\
    195 		.base.flags = 0,				\
    196 		.u.arm.parents = (_parents),			\
    197 		.u.arm.nparents = __arraycount(_parents),	\
    198 		.u.arm.mux_reg = (_reg),			\
    199 		.u.arm.mux_mask = (_mux_mask),			\
    200 		.u.arm.mux_main = (_mux_main),			\
    201 		.u.arm.mux_alt = (_mux_alt),			\
    202 		.u.arm.divs[0].reg = (_reg),			\
    203 		.u.arm.divs[0].mask = (_div_mask),		\
    204 		.u.arm.rates = (_rates),			\
    205 		.u.arm.nrates = __arraycount(_rates),		\
    206 		.get_rate = rk_cru_arm_get_rate,		\
    207 		.set_rate = rk_cru_arm_set_rate,		\
    208 		.get_parent = rk_cru_arm_get_parent,		\
    209 		.set_parent = rk_cru_arm_set_parent,		\
    210 	}
    211 
    212 #define	_RK_CPU_COMMON_INITIALIZER(_id, _name, _parents,	\
    213     _mux_reg, _mux_mask, _mux_main, _mux_alt, _cpurates)	\
    214 	.id = (_id),						\
    215 	.type = RK_CRU_ARM,					\
    216 	.base.name = (_name),					\
    217 	.base.flags = 0,					\
    218 	.u.arm.parents = (_parents),				\
    219 	.u.arm.nparents = __arraycount(_parents),		\
    220 	.u.arm.mux_reg = (_mux_reg),				\
    221 	.u.arm.mux_mask = (_mux_mask),				\
    222 	.u.arm.mux_main = (_mux_main),				\
    223 	.u.arm.mux_alt = (_mux_alt),				\
    224 	.u.arm.cpurates = (_cpurates),				\
    225 	.u.arm.nrates = __arraycount(_cpurates),		\
    226 	.get_rate = rk_cru_arm_get_rate,			\
    227 	.set_rate = rk_cru_arm_set_rate,			\
    228 	.get_parent = rk_cru_arm_get_parent,			\
    229 	.set_parent = rk_cru_arm_set_parent
    230 
    231 #define	RK_CPU(_id, _name, _parents, _mux_reg, _mux_mask, _mux_main, _mux_alt, \
    232     _div_reg, _div_mask, _cpurates) \
    233 	{								\
    234 		_RK_CPU_COMMON_INITIALIZER(_id, _name, _parents,	\
    235 		    _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\
    236 		.u.arm.divs[0].reg = (_div_reg),			\
    237 		.u.arm.divs[0].mask = (_div_mask),			\
    238 	}
    239 
    240 #define	RK_CPU_CORE2(_id, _name, _parents,				\
    241     _mux_reg, _mux_mask, _mux_main, _mux_alt,				\
    242     _div0_reg, _div0_mask,						\
    243     _div1_reg, _div1_mask,						\
    244     _cpurates)								\
    245 	{								\
    246 		_RK_CPU_COMMON_INITIALIZER(_id, _name, _parents,	\
    247 		    _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\
    248 		.u.arm.divs[0].reg = (_div0_reg),			\
    249 		.u.arm.divs[0].mask = (_div0_mask),			\
    250 		.u.arm.divs[1].reg = (_div1_reg),			\
    251 		.u.arm.divs[1].mask = (_div1_mask),			\
    252 	}
    253 
    254 #define	RK_CPU_CORE4(_id, _name, _parents,				\
    255     _mux_reg, _mux_mask, _mux_main, _mux_alt,				\
    256     _div0_reg, _div0_mask,						\
    257     _div1_reg, _div1_mask,						\
    258     _div2_reg, _div2_mask,						\
    259     _div3_reg, _div3_mask,						\
    260     _cpurates)								\
    261 	{								\
    262 		_RK_CPU_COMMON_INITIALIZER(_id, _name, _parents,	\
    263 		    _mux_reg, _mux_mask, _mux_main, _mux_alt,_cpurates),\
    264 		.u.arm.divs[0].reg = (_div0_reg),			\
    265 		.u.arm.divs[0].mask = (_div0_mask),			\
    266 		.u.arm.divs[1].reg = (_div1_reg),			\
    267 		.u.arm.divs[1].mask = (_div1_mask),			\
    268 		.u.arm.divs[2].reg = (_div2_reg),			\
    269 		.u.arm.divs[2].mask = (_div2_mask),			\
    270 		.u.arm.divs[3].reg = (_div3_reg),			\
    271 		.u.arm.divs[3].mask = (_div3_mask),			\
    272 	}
    273 
    274 /* Composite clocks */
    275 
    276 struct rk_cru_composite {
    277 	bus_size_t	muxdiv_reg;
    278 	uint32_t	mux_mask;
    279 	uint32_t	div_mask;
    280 	bus_size_t	gate_reg;
    281 	uint32_t	gate_mask;
    282 	bus_size_t	frac_reg;
    283 	const char	**parents;
    284 	u_int		nparents;
    285 	u_int		flags;
    286 #define	RK_COMPOSITE_ROUND_DOWN		0x01
    287 #define	RK_COMPOSITE_SET_RATE_PARENT	0x02
    288 #define	RK_COMPOSITE_FRACDIV		0x04
    289 #define	RK_COMPOSITE_POW2		0x08
    290 #define	RK_COMPOSITE_HALFDIV		0x10
    291 };
    292 
    293 int	rk_cru_composite_enable(struct rk_cru_softc *, struct rk_cru_clk *, int);
    294 u_int	rk_cru_composite_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
    295 int	rk_cru_composite_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
    296 const char *rk_cru_composite_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
    297 int	rk_cru_composite_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
    298 
    299 #define	_RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _frac_reg, _flags) \
    300 	{							\
    301 		.id = (_id),					\
    302 		.type = RK_CRU_COMPOSITE,			\
    303 		.base.name = (_name),				\
    304 		.base.flags = 0,				\
    305 		.u.composite.parents = (_parents),		\
    306 		.u.composite.nparents = __arraycount(_parents),	\
    307 		.u.composite.muxdiv_reg = (_muxdiv_reg),	\
    308 		.u.composite.mux_mask = (_mux_mask),		\
    309 		.u.composite.div_mask = (_div_mask),		\
    310 		.u.composite.gate_reg = (_gate_reg),		\
    311 		.u.composite.gate_mask = (_gate_mask),		\
    312 		.u.composite.frac_reg = (_frac_reg),		\
    313 		.u.composite.flags = (_flags),			\
    314 		.enable = rk_cru_composite_enable,		\
    315 		.get_rate = rk_cru_composite_get_rate,		\
    316 		.set_rate = rk_cru_composite_set_rate,		\
    317 		.get_parent = rk_cru_composite_get_parent,	\
    318 		.set_parent = rk_cru_composite_set_parent,	\
    319 	}
    320 
    321 #define	RK_COMPOSITE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \
    322 	_RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, _flags)
    323 
    324 #define	RK_COMPOSITE_HALF(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \
    325 	_RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, 0, (_flags) | RK_COMPOSITE_HALFDIV)
    326 
    327 #define	RK_COMPOSITE_NOMUX(_id, _name, _parent, _div_reg, _div_mask, _gate_reg, _gate_mask, _flags) \
    328 	_RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, _gate_reg, _gate_mask, 0, _flags)
    329 
    330 #define	RK_COMPOSITE_NODIV(_id, _name, _parents, _muxdiv_reg, _mux_mask, _gate_reg, _gate_mask, _flags) \
    331 	_RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask,         0, _gate_reg, _gate_mask, 0, _flags)
    332 
    333 #define	RK_COMPOSITE_NOGATE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _flags) \
    334 	_RK_COMPOSITE_INIT(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, 0, 0, 0, _flags)
    335 
    336 #define	RK_COMPOSITE_FRAC(_id, _name, _parent, _frac_reg, _flags) \
    337 	_RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, 0, 0, 0, 0, 0, _frac_reg, (_flags) | RK_COMPOSITE_FRACDIV)
    338 
    339 #define	RK_DIV(_id, _name, _parent, _div_reg, _div_mask, _flags) \
    340 	_RK_COMPOSITE_INIT(_id, _name, (const char *[]){ _parent }, _div_reg, 0, _div_mask, 0, 0, 0, _flags)
    341 
    342 /* Gate clocks */
    343 
    344 struct rk_cru_gate {
    345 	bus_size_t	reg;
    346 	uint32_t	mask;
    347 	const char	*parent;
    348 };
    349 
    350 int	rk_cru_gate_enable(struct rk_cru_softc *,
    351 			   struct rk_cru_clk *, int);
    352 const char *rk_cru_gate_get_parent(struct rk_cru_softc *,
    353 				   struct rk_cru_clk *);
    354 
    355 #define	RK_GATE(_id, _name, _pname, _reg, _bit)			\
    356 	{							\
    357 		.id = (_id),					\
    358 		.type = RK_CRU_GATE,				\
    359 		.base.name = (_name),				\
    360 		.base.flags = CLK_SET_RATE_PARENT,		\
    361 		.u.gate.parent = (_pname),			\
    362 		.u.gate.reg = (_reg),				\
    363 		.u.gate.mask = __BIT(_bit),			\
    364 		.enable = rk_cru_gate_enable,			\
    365 		.get_parent = rk_cru_gate_get_parent,		\
    366 	}
    367 
    368 #define	RK_SECURE_GATE(_id, _name, _pname)			\
    369 	{							\
    370 		.id = (_id),					\
    371 		.type = RK_CRU_GATE,				\
    372 		.base.name = (_name),				\
    373 		.u.gate.parent = (_pname),			\
    374 		.get_parent = rk_cru_gate_get_parent,		\
    375 	}
    376 
    377 /* Mux clocks */
    378 
    379 struct rk_cru_mux {
    380 	bus_size_t	reg;
    381 	uint32_t	mask;
    382 	const char	**parents;
    383 	u_int		nparents;
    384 	u_int		flags;
    385 #define	RK_MUX_GRF			0x01
    386 };
    387 
    388 const char *rk_cru_mux_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
    389 int	rk_cru_mux_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
    390 
    391 #define	RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, _flags)	\
    392 	{							\
    393 		.id = (_id),					\
    394 		.type = RK_CRU_MUX,				\
    395 		.base.name = (_name),				\
    396 		.base.flags = CLK_SET_RATE_PARENT,		\
    397 		.u.mux.parents = (_parents),			\
    398 		.u.mux.nparents = __arraycount(_parents),	\
    399 		.u.mux.reg = (_reg),				\
    400 		.u.mux.mask = (_mask),				\
    401 		.u.mux.flags = (_flags),			\
    402 		.set_parent = rk_cru_mux_set_parent,		\
    403 		.get_parent = rk_cru_mux_get_parent,		\
    404 	}
    405 #define	RK_MUX(_id, _name, _parents, _reg, _mask)		\
    406 	RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, 0)
    407 #define	RK_MUXGRF(_id, _name, _parents, _reg, _mask)		\
    408 	RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, RK_MUX_GRF)
    409 
    410 /*
    411  * Rockchip clock definition
    412  */
    413 
    414 struct rk_cru_clk {
    415 	struct clk	base;
    416 	u_int		id;
    417 	enum rk_cru_clktype type;
    418 	union {
    419 		struct rk_cru_pll pll;
    420 		struct rk_cru_arm arm;
    421 		struct rk_cru_composite composite;
    422 		struct rk_cru_gate gate;
    423 		struct rk_cru_mux mux;
    424 	} u;
    425 
    426 	int		(*enable)(struct rk_cru_softc *,
    427 				  struct rk_cru_clk *, int);
    428 	u_int		(*get_rate)(struct rk_cru_softc *,
    429 				    struct rk_cru_clk *);
    430 	int		(*set_rate)(struct rk_cru_softc *,
    431 				    struct rk_cru_clk *, u_int);
    432 	u_int		(*round_rate)(struct rk_cru_softc *,
    433 				    struct rk_cru_clk *, u_int);
    434 	const char *	(*get_parent)(struct rk_cru_softc *,
    435 				      struct rk_cru_clk *);
    436 	int		(*set_parent)(struct rk_cru_softc *,
    437 				      struct rk_cru_clk *,
    438 				      const char *);
    439 };
    440 
    441 /*
    442  * Driver state
    443  */
    444 
    445 struct rk_cru_softc {
    446 	device_t		sc_dev;
    447 	int			sc_phandle;
    448 	bus_space_tag_t		sc_bst;
    449 	bus_space_handle_t	sc_bsh;
    450 	struct syscon		*sc_grf;
    451 
    452 	struct clk_domain	sc_clkdom;
    453 
    454 	struct rk_cru_clk	*sc_clks;
    455 	u_int			sc_nclks;
    456 
    457 	bus_size_t		sc_grf_soc_status;	/* for PLL lock */
    458 	bus_size_t		sc_softrst_base;
    459 };
    460 
    461 int	rk_cru_attach(struct rk_cru_softc *);
    462 struct rk_cru_clk *rk_cru_clock_find(struct rk_cru_softc *,
    463 				     const char *);
    464 void	rk_cru_print(struct rk_cru_softc *);
    465 
    466 #define CRU_READ(sc, reg)	\
    467 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
    468 #define CRU_WRITE(sc, reg, val)	\
    469 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
    470 
    471 #define	HAS_GRF(sc)	((sc)->sc_grf != NULL)
    472 
    473 #endif /* _ARM_RK_CRU_H */
    474