Home | History | Annotate | Line # | Download | only in rockchip
rk_cru.h revision 1.1
      1 /* $NetBSD: rk_cru.h,v 1.1 2018/06/16 00:19:04 jmcneill 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 
     34 struct rk_cru_softc;
     35 struct rk_cru_clk;
     36 
     37 /*
     38  * Clocks
     39  */
     40 
     41 enum rk_cru_clktype {
     42 	RK_CRU_UNKNOWN,
     43 	RK_CRU_PLL,
     44 	RK_CRU_ARM,
     45 	RK_CRU_COMPOSITE,
     46 	RK_CRU_GATE,
     47 	RK_CRU_MUX,
     48 };
     49 
     50 /* PLL clocks */
     51 
     52 struct rk_cru_pll_rate {
     53 	u_int		rate;
     54 	u_int		refdiv;
     55 	u_int		fbdiv;
     56 	u_int		postdiv1;
     57 	u_int		postdiv2;
     58 	u_int		dsmpd;
     59 	u_int		fracdiv;
     60 };
     61 
     62 #define	RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _fracdiv) \
     63 	{							\
     64 		.rate = (_rate),				\
     65 		.refdiv = (_refdiv),				\
     66 		.fbdiv = (_fbdiv),				\
     67 		.postdiv1 = (_postdiv1),			\
     68 		.postdiv2 = (_postdiv2),			\
     69 		.dsmpd = (_dsmpd),				\
     70 		.fracdiv = (_fracdiv),				\
     71 	}
     72 
     73 struct rk_cru_pll {
     74 	bus_size_t	con_base;
     75 	bus_size_t	mode_reg;
     76 	uint32_t	mode_mask;
     77 	uint32_t	lock_mask;
     78 	const struct rk_cru_pll_rate *rates;
     79 	u_int		nrates;
     80 	const char	*parent;
     81 };
     82 
     83 u_int	rk_cru_pll_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
     84 int	rk_cru_pll_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
     85 const char *rk_cru_pll_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
     86 
     87 #define	RK_PLL(_id, _name, _parent, _con_base, _mode_reg, _mode_mask, _lock_mask, _rates) \
     88 	{							\
     89 		.id = (_id),					\
     90 		.type = RK_CRU_PLL,				\
     91 		.base.name = (_name),				\
     92 		.base.flags = 0,				\
     93 		.u.pll.parent = (_parent),			\
     94 		.u.pll.con_base = (_con_base),			\
     95 		.u.pll.mode_reg = (_mode_reg),			\
     96 		.u.pll.mode_mask = (_mode_mask),		\
     97 		.u.pll.lock_mask = (_lock_mask),		\
     98 		.u.pll.rates = (_rates),			\
     99 		.u.pll.nrates = __arraycount(_rates),		\
    100 		.get_rate = rk_cru_pll_get_rate,		\
    101 		.set_rate = rk_cru_pll_set_rate,		\
    102 		.get_parent = rk_cru_pll_get_parent,		\
    103 	}
    104 
    105 /* ARM clocks */
    106 
    107 struct rk_cru_arm_rate {
    108 	u_int		rate;
    109 	u_int		div;
    110 };
    111 
    112 #define	RK_ARM_RATE(_rate, _div)				\
    113 	{							\
    114 		.rate = (_rate),				\
    115 		.div = (_div),					\
    116 	}
    117 
    118 struct rk_cru_arm {
    119 	bus_size_t	reg;
    120 	uint32_t	mux_mask;
    121 	u_int		mux_main;
    122 	u_int		mux_alt;
    123 	uint32_t	div_mask;
    124 	const char	**parents;
    125 	u_int		nparents;
    126 	const struct rk_cru_arm_rate *rates;
    127 	u_int		nrates;
    128 };
    129 
    130 u_int	rk_cru_arm_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
    131 int	rk_cru_arm_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
    132 const char *rk_cru_arm_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
    133 int	rk_cru_arm_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
    134 
    135 #define	RK_ARM(_id, _name, _parents, _reg, _mux_mask, _mux_main, _mux_alt, _div_mask, _rates) \
    136 	{							\
    137 		.id = (_id),					\
    138 		.type = RK_CRU_ARM,				\
    139 		.base.name = (_name),				\
    140 		.base.flags = 0,				\
    141 		.u.arm.parents = (_parents),			\
    142 		.u.arm.nparents = __arraycount(_parents),	\
    143 		.u.arm.reg = (_reg),				\
    144 		.u.arm.mux_mask = (_mux_mask),			\
    145 		.u.arm.mux_main = (_mux_main),			\
    146 		.u.arm.mux_alt = (_mux_alt),			\
    147 		.u.arm.div_mask = (_div_mask),			\
    148 		.u.arm.rates = (_rates),			\
    149 		.u.arm.nrates = __arraycount(_rates),		\
    150 		.get_rate = rk_cru_arm_get_rate,		\
    151 		.set_rate = rk_cru_arm_set_rate,		\
    152 		.get_parent = rk_cru_arm_get_parent,		\
    153 		.set_parent = rk_cru_arm_set_parent,		\
    154 	}
    155 
    156 /* Composite clocks */
    157 
    158 struct rk_cru_composite {
    159 	bus_size_t	muxdiv_reg;
    160 	uint32_t	mux_mask;
    161 	uint32_t	div_mask;
    162 	bus_size_t	gate_reg;
    163 	uint32_t	gate_mask;
    164 	const char	**parents;
    165 	u_int		nparents;
    166 	u_int		flags;
    167 #define	RK_COMPOSITE_ROUND_DOWN		0x01
    168 };
    169 
    170 int	rk_cru_composite_enable(struct rk_cru_softc *, struct rk_cru_clk *, int);
    171 u_int	rk_cru_composite_get_rate(struct rk_cru_softc *, struct rk_cru_clk *);
    172 int	rk_cru_composite_set_rate(struct rk_cru_softc *, struct rk_cru_clk *, u_int);
    173 const char *rk_cru_composite_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
    174 int	rk_cru_composite_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
    175 
    176 #define	RK_COMPOSITE(_id, _name, _parents, _muxdiv_reg, _mux_mask, _div_mask, _gate_reg, _gate_mask, _flags) \
    177 	{							\
    178 		.id = (_id),					\
    179 		.type = RK_CRU_COMPOSITE,			\
    180 		.base.name = (_name),				\
    181 		.base.flags = 0,				\
    182 		.u.composite.parents = (_parents),		\
    183 		.u.composite.nparents = __arraycount(_parents),	\
    184 		.u.composite.muxdiv_reg = (_muxdiv_reg),	\
    185 		.u.composite.mux_mask = (_mux_mask),		\
    186 		.u.composite.div_mask = (_div_mask),		\
    187 		.u.composite.gate_reg = (_gate_reg),		\
    188 		.u.composite.gate_mask = (_gate_mask),		\
    189 		.u.composite.flags = (_flags),			\
    190 		.enable = rk_cru_composite_enable,		\
    191 		.get_rate = rk_cru_composite_get_rate,		\
    192 		.set_rate = rk_cru_composite_set_rate,		\
    193 		.get_parent = rk_cru_composite_get_parent,	\
    194 		.set_parent = rk_cru_composite_set_parent,	\
    195 	}
    196 
    197 /* Gate clocks */
    198 
    199 struct rk_cru_gate {
    200 	bus_size_t	reg;
    201 	uint32_t	mask;
    202 	const char	*parent;
    203 };
    204 
    205 int	rk_cru_gate_enable(struct rk_cru_softc *,
    206 			   struct rk_cru_clk *, int);
    207 const char *rk_cru_gate_get_parent(struct rk_cru_softc *,
    208 				   struct rk_cru_clk *);
    209 
    210 #define	RK_GATE(_id, _name, _pname, _reg, _bit)			\
    211 	{							\
    212 		.id = (_id),					\
    213 		.type = RK_CRU_GATE,				\
    214 		.base.name = (_name),				\
    215 		.base.flags = CLK_SET_RATE_PARENT,		\
    216 		.u.gate.parent = (_pname),			\
    217 		.u.gate.reg = (_reg),				\
    218 		.u.gate.mask = __BIT(_bit),			\
    219 		.enable = rk_cru_gate_enable,			\
    220 		.get_parent = rk_cru_gate_get_parent,		\
    221 	}
    222 
    223 /* Mux clocks */
    224 
    225 struct rk_cru_mux {
    226 	bus_size_t	reg;
    227 	uint32_t	mask;
    228 	const char	**parents;
    229 	u_int		nparents;
    230 	u_int		flags;
    231 #define	RK_MUX_GRF			0x01
    232 };
    233 
    234 const char *rk_cru_mux_get_parent(struct rk_cru_softc *, struct rk_cru_clk *);
    235 int	rk_cru_mux_set_parent(struct rk_cru_softc *, struct rk_cru_clk *, const char *);
    236 
    237 #define	RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, _flags)	\
    238 	{							\
    239 		.id = (_id),					\
    240 		.type = RK_CRU_MUX,				\
    241 		.base.name = (_name),				\
    242 		.base.flags = CLK_SET_RATE_PARENT,		\
    243 		.u.mux.parents = (_parents),			\
    244 		.u.mux.nparents = __arraycount(_parents),	\
    245 		.u.mux.reg = (_reg),				\
    246 		.u.mux.mask = (_mask),				\
    247 		.u.mux.flags = (_flags),			\
    248 		.set_parent = rk_cru_mux_set_parent,		\
    249 		.get_parent = rk_cru_mux_get_parent,		\
    250 	}
    251 #define	RK_MUX(_id, _name, _parents, _reg, _mask)		\
    252 	RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, 0)
    253 #define	RK_MUXGRF(_id, _name, _parents, _reg, _mask)		\
    254 	RK_MUX_FLAGS(_id, _name, _parents, _reg, _mask, RK_MUX_GRF)
    255 
    256 /*
    257  * Rockchip clock definition
    258  */
    259 
    260 struct rk_cru_clk {
    261 	struct clk	base;
    262 	u_int		id;
    263 	enum rk_cru_clktype type;
    264 	union {
    265 		struct rk_cru_pll pll;
    266 		struct rk_cru_arm arm;
    267 		struct rk_cru_composite composite;
    268 		struct rk_cru_gate gate;
    269 		struct rk_cru_mux mux;
    270 	} u;
    271 
    272 	int		(*enable)(struct rk_cru_softc *,
    273 				  struct rk_cru_clk *, int);
    274 	u_int		(*get_rate)(struct rk_cru_softc *,
    275 				    struct rk_cru_clk *);
    276 	int		(*set_rate)(struct rk_cru_softc *,
    277 				    struct rk_cru_clk *, u_int);
    278 	u_int		(*round_rate)(struct rk_cru_softc *,
    279 				    struct rk_cru_clk *, u_int);
    280 	const char *	(*get_parent)(struct rk_cru_softc *,
    281 				      struct rk_cru_clk *);
    282 	int		(*set_parent)(struct rk_cru_softc *,
    283 				      struct rk_cru_clk *,
    284 				      const char *);
    285 };
    286 
    287 /*
    288  * Driver state
    289  */
    290 
    291 struct rk_cru_softc {
    292 	device_t		sc_dev;
    293 	int			sc_phandle;
    294 	bus_space_tag_t		sc_bst;
    295 	bus_space_handle_t	sc_bsh;
    296 	bus_space_handle_t	sc_bsh_grf;
    297 
    298 	struct clk_domain	sc_clkdom;
    299 
    300 	struct rk_cru_clk	*sc_clks;
    301 	u_int			sc_nclks;
    302 };
    303 
    304 int	rk_cru_attach(struct rk_cru_softc *);
    305 struct rk_cru_clk *rk_cru_clock_find(struct rk_cru_softc *,
    306 				     const char *);
    307 void	rk_cru_print(struct rk_cru_softc *);
    308 
    309 #define CRU_READ(sc, reg)	\
    310 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
    311 #define CRU_WRITE(sc, reg, val)	\
    312 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
    313 
    314 #define	GRF_READ(sc, reg)	\
    315 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh_grf, (reg))
    316 #define GRF_WRITE(sc, reg, val)	\
    317 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh_grf, (reg), (val))
    318 
    319 #define	HAS_GRF(sc)	((sc)->sc_bsh_grf != 0)
    320 
    321 #endif /* _ARM_RK_CRU_H */
    322