Home | History | Annotate | Line # | Download | only in amlogic
meson_clk.h revision 1.3
      1 /* $NetBSD: meson_clk.h,v 1.3 2019/02/25 19:30:17 jmcneill Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2017-2019 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_MESON_CLK_H
     30 #define _ARM_MESON_CLK_H
     31 
     32 #include <dev/clk/clk_backend.h>
     33 #include <dev/fdt/syscon.h>
     34 
     35 struct meson_clk_softc;
     36 struct meson_clk_clk;
     37 struct meson_clk_reset;
     38 
     39 /*
     40  * Resets
     41  */
     42 
     43 struct meson_clk_reset {
     44 	bus_size_t	reg;
     45 	uint32_t	mask;
     46 };
     47 
     48 #define	MESON_CLK_RESET(_id, _reg, _bit)	\
     49 	[_id] = {				\
     50 		.reg = (_reg),			\
     51 		.mask = __BIT(_bit),		\
     52 	}
     53 
     54 /*
     55  * Clocks
     56  */
     57 
     58 enum meson_clk_clktype {
     59 	MESON_CLK_UNKNOWN,
     60 	MESON_CLK_FIXED,
     61 	MESON_CLK_GATE,
     62 	MESON_CLK_PLL,
     63 	MESON_CLK_MPLL,
     64 	MESON_CLK_DIV,
     65 	MESON_CLK_FIXED_FACTOR,
     66 	MESON_CLK_MUX,
     67 };
     68 
     69 /*
     70  * Fixed clocks
     71  */
     72 
     73 struct meson_clk_fixed {
     74 	u_int		rate;
     75 };
     76 
     77 u_int	meson_clk_fixed_get_rate(struct meson_clk_softc *, struct meson_clk_clk *);
     78 
     79 #define	MESON_CLK_FIXED(_id, _name, _rate)			\
     80 	[_id] = {						\
     81 		.type = MESON_CLK_FIXED,			\
     82 		.base.name = (_name),				\
     83 		.base.flags = 0,				\
     84 		.u.fixed.rate = (_rate),			\
     85 		.get_rate = meson_clk_fixed_get_rate,		\
     86 	}
     87 
     88 /*
     89  * Gate clocks
     90  */
     91 
     92 struct meson_clk_gate {
     93 	bus_size_t	reg;
     94 	uint32_t	mask;
     95 	const char	*parent;
     96 	uint32_t	flags;
     97 #define	MESON_CLK_GATE_SET_TO_DISABLE		__BIT(0)
     98 };
     99 
    100 int	meson_clk_gate_enable(struct meson_clk_softc *,
    101 			      struct meson_clk_clk *, int);
    102 const char *meson_clk_gate_get_parent(struct meson_clk_softc *,
    103 				      struct meson_clk_clk *);
    104 
    105 #define	MESON_CLK_GATE_FLAGS(_id, _name, _pname, _reg, _bit, _flags)	\
    106 	[_id] = {						\
    107 		.type = MESON_CLK_GATE,				\
    108 		.base.name = (_name),				\
    109 		.base.flags = CLK_SET_RATE_PARENT,		\
    110 		.u.gate.parent = (_pname),			\
    111 		.u.gate.reg = (_reg),				\
    112 		.u.gate.mask = __BIT(_bit),			\
    113 		.u.gate.flags = (_flags),			\
    114 		.enable = meson_clk_gate_enable,		\
    115 		.get_parent = meson_clk_gate_get_parent,	\
    116 	}
    117 
    118 #define	MESON_CLK_GATE(_id, _name, _pname, _reg, _bit)		\
    119 	MESON_CLK_GATE_FLAGS(_id, _name, _pname, _reg, _bit, 0)
    120 
    121 /*
    122  * Divider clocks
    123  */
    124 
    125 struct meson_clk_div {
    126 	bus_size_t	reg;
    127 	const char	*parent;
    128 	uint32_t	div;
    129 	uint32_t	flags;
    130 #define	MESON_CLK_DIV_POWER_OF_TWO	__BIT(0)
    131 #define	MESON_CLK_DIV_SET_RATE_PARENT	__BIT(1)
    132 #define	MESON_CLK_DIV_CPU_SCALE_TABLE	__BIT(2)
    133 };
    134 
    135 u_int	meson_clk_div_get_rate(struct meson_clk_softc *,
    136 			       struct meson_clk_clk *);
    137 int	meson_clk_div_set_rate(struct meson_clk_softc *,
    138 			       struct meson_clk_clk *, u_int);
    139 const char *meson_clk_div_get_parent(struct meson_clk_softc *,
    140 				     struct meson_clk_clk *);
    141 
    142 #define	MESON_CLK_DIV(_id, _name, _parent, _reg, _div, _flags)	\
    143 	[_id] = {						\
    144 		.type = MESON_CLK_DIV,				\
    145 		.base.name = (_name),				\
    146 		.u.div.reg = (_reg),				\
    147 		.u.div.parent = (_parent),			\
    148 		.u.div.div = (_div),				\
    149 		.u.div.flags = (_flags),			\
    150 		.get_rate = meson_clk_div_get_rate,		\
    151 		.set_rate = meson_clk_div_set_rate,		\
    152 		.get_parent = meson_clk_div_get_parent,		\
    153 	}
    154 
    155 /*
    156  * Fixed-factor clocks
    157  */
    158 
    159 struct meson_clk_fixed_factor {
    160 	const char	*parent;
    161 	u_int		div;
    162 	u_int		mult;
    163 };
    164 
    165 u_int	meson_clk_fixed_factor_get_rate(struct meson_clk_softc *,
    166 					struct meson_clk_clk *);
    167 int	meson_clk_fixed_factor_set_rate(struct meson_clk_softc *,
    168 					struct meson_clk_clk *, u_int);
    169 const char *meson_clk_fixed_factor_get_parent(struct meson_clk_softc *,
    170 					      struct meson_clk_clk *);
    171 
    172 #define	MESON_CLK_FIXED_FACTOR(_id, _name, _parent, _div, _mult)	\
    173 	[_id] = {							\
    174 		.type = MESON_CLK_FIXED_FACTOR,				\
    175 		.base.name = (_name),					\
    176 		.u.fixed_factor.parent = (_parent),			\
    177 		.u.fixed_factor.div = (_div),				\
    178 		.u.fixed_factor.mult = (_mult),				\
    179 		.get_rate = meson_clk_fixed_factor_get_rate,		\
    180 		.get_parent = meson_clk_fixed_factor_get_parent,	\
    181 		.set_rate = meson_clk_fixed_factor_set_rate,		\
    182 	}
    183 
    184 /*
    185  * Mux clocks
    186  */
    187 
    188 struct meson_clk_mux {
    189 	bus_size_t	reg;
    190 	const char	**parents;
    191 	u_int		nparents;
    192 	uint32_t	sel;
    193 	uint32_t	flags;
    194 };
    195 
    196 const char *meson_clk_mux_get_parent(struct meson_clk_softc *,
    197 			       struct meson_clk_clk *);
    198 
    199 #define	MESON_CLK_MUX(_id, _name, _parents, _reg, _sel, _flags)		\
    200 	[_id] = {							\
    201 		.type = MESON_CLK_MUX,					\
    202 		.base.name = (_name),					\
    203 		.base.flags = CLK_SET_RATE_PARENT,			\
    204 		.u.mux.parents = (_parents),				\
    205 		.u.mux.nparents = __arraycount(_parents),		\
    206 		.u.mux.reg = (_reg),					\
    207 		.u.mux.sel = (_sel),					\
    208 		.u.mux.flags = (_flags),				\
    209 		.get_parent = meson_clk_mux_get_parent,			\
    210 	}
    211 
    212 /*
    213  * PLL clocks
    214  */
    215 
    216 struct meson_clk_pll_reg {
    217 	bus_size_t	reg;
    218 	uint32_t	mask;
    219 };
    220 
    221 #define	MESON_CLK_PLL_REG(_reg, _mask)					\
    222 	{ .reg = (_reg), .mask = (_mask) }
    223 #define	MESON_CLK_PLL_REG_INVALID	MESON_CLK_PLL_REG(0,0)
    224 
    225 struct meson_clk_pll {
    226 	struct meson_clk_pll_reg	enable;
    227 	struct meson_clk_pll_reg	m;
    228 	struct meson_clk_pll_reg	n;
    229 	struct meson_clk_pll_reg	frac;
    230 	struct meson_clk_pll_reg	l;
    231 	struct meson_clk_pll_reg	reset;
    232 	const char			*parent;
    233 	uint32_t			flags;
    234 };
    235 
    236 u_int	meson_clk_pll_get_rate(struct meson_clk_softc *,
    237 			       struct meson_clk_clk *);
    238 const char *meson_clk_pll_get_parent(struct meson_clk_softc *,
    239 				     struct meson_clk_clk *);
    240 
    241 #define	MESON_CLK_PLL_RATE(_id, _name, _parent, _enable, _m, _n, _frac, _l,	\
    242 		      _reset, _setratefn, _flags)			\
    243 	[_id] = {							\
    244 		.type = MESON_CLK_PLL,					\
    245 		.base.name = (_name),					\
    246 		.u.pll.parent = (_parent),				\
    247 		.u.pll.enable = _enable,				\
    248 		.u.pll.m = _m,						\
    249 		.u.pll.n = _n,						\
    250 		.u.pll.frac = _frac,					\
    251 		.u.pll.l = _l,						\
    252 		.u.pll.reset = _reset,					\
    253 		.u.pll.flags = (_flags),				\
    254 		.set_rate = (_setratefn),				\
    255 		.get_rate = meson_clk_pll_get_rate,			\
    256 		.get_parent = meson_clk_pll_get_parent,			\
    257 	}
    258 
    259 #define	MESON_CLK_PLL(_id, _name, _parent, _enable, _m, _n, _frac, _l,	\
    260 		      _reset, _flags)					\
    261 	[_id] = {							\
    262 		.type = MESON_CLK_PLL,					\
    263 		.base.name = (_name),					\
    264 		.u.pll.parent = (_parent),				\
    265 		.u.pll.enable = _enable,				\
    266 		.u.pll.m = _m,						\
    267 		.u.pll.n = _n,						\
    268 		.u.pll.frac = _frac,					\
    269 		.u.pll.l = _l,						\
    270 		.u.pll.reset = _reset,					\
    271 		.u.pll.flags = (_flags),				\
    272 		.get_rate = meson_clk_pll_get_rate,			\
    273 		.get_parent = meson_clk_pll_get_parent,			\
    274 	}
    275 
    276 /*
    277  * MPLL clocks
    278  */
    279 
    280 struct meson_clk_mpll {
    281 	struct meson_clk_pll_reg	sdm;
    282 	struct meson_clk_pll_reg	sdm_enable;
    283 	struct meson_clk_pll_reg	n2;
    284 	struct meson_clk_pll_reg	ssen;
    285 	const char			*parent;
    286 	uint32_t			flags;
    287 };
    288 
    289 u_int	meson_clk_mpll_get_rate(struct meson_clk_softc *,
    290 				struct meson_clk_clk *);
    291 const char *meson_clk_mpll_get_parent(struct meson_clk_softc *,
    292 				      struct meson_clk_clk *);
    293 
    294 #define	MESON_CLK_MPLL(_id, _name, _parent, _sdm, _sdm_enable, _n2,	\
    295 		       _ssen, _flags)					\
    296 	[_id] = {							\
    297 		.type = MESON_CLK_MPLL,					\
    298 		.base.name = (_name),					\
    299 		.u.mpll.parent = (_parent),				\
    300 		.u.mpll.sdm = _sdm,					\
    301 		.u.mpll.sdm_enable = _sdm_enable,			\
    302 		.u.mpll.n2 = _n2,					\
    303 		.u.mpll.ssen = _ssen,					\
    304 		.u.mpll.flags = (_flags),				\
    305 		.get_rate = meson_clk_mpll_get_rate,			\
    306 		.get_parent = meson_clk_mpll_get_parent,		\
    307 	}
    308 
    309 
    310 
    311 struct meson_clk_clk {
    312 	struct clk	base;
    313 	enum meson_clk_clktype type;
    314 	union {
    315 		struct meson_clk_fixed fixed;
    316 		struct meson_clk_gate gate;
    317 		struct meson_clk_div div;
    318 		struct meson_clk_fixed_factor fixed_factor;
    319 		struct meson_clk_mux mux;
    320 		struct meson_clk_pll pll;
    321 		struct meson_clk_mpll mpll;
    322 	} u;
    323 
    324 	int		(*enable)(struct meson_clk_softc *,
    325 				  struct meson_clk_clk *, int);
    326 	u_int		(*get_rate)(struct meson_clk_softc *,
    327 				    struct meson_clk_clk *);
    328 	int		(*set_rate)(struct meson_clk_softc *,
    329 				    struct meson_clk_clk *, u_int);
    330 	u_int		(*round_rate)(struct meson_clk_softc *,
    331 				    struct meson_clk_clk *, u_int);
    332 	const char *	(*get_parent)(struct meson_clk_softc *,
    333 				      struct meson_clk_clk *);
    334 	int		(*set_parent)(struct meson_clk_softc *,
    335 				      struct meson_clk_clk *,
    336 				      const char *);
    337 };
    338 
    339 struct meson_clk_softc {
    340 	device_t		sc_dev;
    341 	int			sc_phandle;
    342 
    343 	bus_space_tag_t		sc_bst;
    344 	bus_space_handle_t	sc_bsh;
    345 
    346 	struct syscon		*sc_syscon;
    347 
    348 	struct clk_domain	sc_clkdom;
    349 
    350 	struct meson_clk_reset *sc_resets;
    351 	u_int			sc_nresets;
    352 
    353 	struct meson_clk_clk	*sc_clks;
    354 	u_int			sc_nclks;
    355 };
    356 
    357 void	meson_clk_attach(struct meson_clk_softc *);
    358 struct meson_clk_clk *meson_clk_clock_find(struct meson_clk_softc *,
    359 					   const char *);
    360 void	meson_clk_print(struct meson_clk_softc *);
    361 
    362 void	meson_clk_lock(struct meson_clk_softc *);
    363 void	meson_clk_unlock(struct meson_clk_softc *);
    364 uint32_t meson_clk_read(struct meson_clk_softc *, bus_size_t);
    365 void	meson_clk_write(struct meson_clk_softc *, bus_size_t, uint32_t);
    366 
    367 #define	CLK_LOCK	meson_clk_lock
    368 #define	CLK_UNLOCK	meson_clk_unlock
    369 #define	CLK_READ	meson_clk_read
    370 #define	CLK_WRITE	meson_clk_write
    371 
    372 #endif /* _ARM_MESON_CLK_H */
    373