Home | History | Annotate | Line # | Download | only in sunxi
sunxi_ccu.h revision 1.7
      1 /* $NetBSD: sunxi_ccu.h,v 1.7 2017/07/17 23:26:17 jmcneill Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2017 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_SUNXI_CCU_H
     30 #define _ARM_SUNXI_CCU_H
     31 
     32 #include <dev/clk/clk_backend.h>
     33 
     34 struct sunxi_ccu_softc;
     35 struct sunxi_ccu_clk;
     36 struct sunxi_ccu_reset;
     37 
     38 /*
     39  * Resets
     40  */
     41 
     42 struct sunxi_ccu_reset {
     43 	bus_size_t	reg;
     44 	uint32_t	mask;
     45 };
     46 
     47 #define	SUNXI_CCU_RESET(_id, _reg, _bit)	\
     48 	[_id] = {				\
     49 		.reg = (_reg),			\
     50 		.mask = __BIT(_bit),		\
     51 	}
     52 
     53 /*
     54  * Clocks
     55  */
     56 
     57 enum sunxi_ccu_clktype {
     58 	SUNXI_CCU_UNKNOWN,
     59 	SUNXI_CCU_GATE,
     60 	SUNXI_CCU_NM,
     61 	SUNXI_CCU_NKMP,
     62 	SUNXI_CCU_PREDIV,
     63 	SUNXI_CCU_DIV,
     64 	SUNXI_CCU_PHASE,
     65 };
     66 
     67 struct sunxi_ccu_gate {
     68 	bus_size_t	reg;
     69 	uint32_t	mask;
     70 	const char	*parent;
     71 };
     72 
     73 int	sunxi_ccu_gate_enable(struct sunxi_ccu_softc *,
     74 			      struct sunxi_ccu_clk *, int);
     75 const char *sunxi_ccu_gate_get_parent(struct sunxi_ccu_softc *,
     76 				      struct sunxi_ccu_clk *);
     77 
     78 #define	SUNXI_CCU_GATE(_id, _name, _pname, _reg, _bit)		\
     79 	[_id] = {						\
     80 		.type = SUNXI_CCU_GATE,				\
     81 		.base.name = (_name),				\
     82 		.u.gate.parent = (_pname),			\
     83 		.u.gate.reg = (_reg),				\
     84 		.u.gate.mask = __BIT(_bit),			\
     85 		.enable = sunxi_ccu_gate_enable,		\
     86 		.get_parent = sunxi_ccu_gate_get_parent,	\
     87 	}
     88 
     89 struct sunxi_ccu_nkmp {
     90 	bus_size_t	reg;
     91 	const char	*parent;
     92 	uint32_t	n;
     93 	uint32_t	k;
     94 	uint32_t	m;
     95 	uint32_t	p;
     96 	uint32_t	lock;
     97 	uint32_t	enable;
     98 	uint32_t	flags;
     99 #define	SUNXI_CCU_NKMP_DIVIDE_BY_TWO	__BIT(0)
    100 #define	SUNXI_CCU_NKMP_FACTOR_N_EXACT	__BIT(1)
    101 };
    102 
    103 int	sunxi_ccu_nkmp_enable(struct sunxi_ccu_softc *,
    104 			      struct sunxi_ccu_clk *, int);
    105 u_int	sunxi_ccu_nkmp_get_rate(struct sunxi_ccu_softc *,
    106 				struct sunxi_ccu_clk *);
    107 int	sunxi_ccu_nkmp_set_rate(struct sunxi_ccu_softc *,
    108 				struct sunxi_ccu_clk *, u_int);
    109 const char *sunxi_ccu_nkmp_get_parent(struct sunxi_ccu_softc *,
    110 				      struct sunxi_ccu_clk *);
    111 
    112 #define	SUNXI_CCU_NKMP(_id, _name, _parent, _reg, _n, _k, _m,	\
    113 		       _p, _enable, _flags)			\
    114 	[_id] = {						\
    115 		.type = SUNXI_CCU_NKMP,				\
    116 		.base.name = (_name),				\
    117 		.u.nkmp.reg = (_reg),				\
    118 		.u.nkmp.parent = (_parent),			\
    119 		.u.nkmp.n = (_n),				\
    120 		.u.nkmp.k = (_k),				\
    121 		.u.nkmp.m = (_m),				\
    122 		.u.nkmp.p = (_p),				\
    123 		.u.nkmp.enable = (_enable),			\
    124 		.u.nkmp.flags = (_flags),			\
    125 		.enable = sunxi_ccu_nkmp_enable,		\
    126 		.get_rate = sunxi_ccu_nkmp_get_rate,		\
    127 		.set_rate = sunxi_ccu_nkmp_set_rate,		\
    128 		.get_parent = sunxi_ccu_nkmp_get_parent,	\
    129 	}
    130 
    131 struct sunxi_ccu_nm {
    132 	bus_size_t	reg;
    133 	const char	**parents;
    134 	u_int		nparents;
    135 	uint32_t	n;
    136 	uint32_t	m;
    137 	uint32_t	sel;
    138 	uint32_t	enable;
    139 	uint32_t	flags;
    140 #define	SUNXI_CCU_NM_POWER_OF_TWO	__BIT(0)
    141 #define	SUNXI_CCU_NM_ROUND_DOWN		__BIT(1)
    142 };
    143 
    144 int	sunxi_ccu_nm_enable(struct sunxi_ccu_softc *,
    145 			    struct sunxi_ccu_clk *, int);
    146 u_int	sunxi_ccu_nm_get_rate(struct sunxi_ccu_softc *,
    147 			      struct sunxi_ccu_clk *);
    148 int	sunxi_ccu_nm_set_rate(struct sunxi_ccu_softc *,
    149 			      struct sunxi_ccu_clk *, u_int);
    150 int	sunxi_ccu_nm_set_parent(struct sunxi_ccu_softc *,
    151 				struct sunxi_ccu_clk *,
    152 				const char *);
    153 const char *sunxi_ccu_nm_get_parent(struct sunxi_ccu_softc *,
    154 				    struct sunxi_ccu_clk *);
    155 
    156 #define	SUNXI_CCU_NM(_id, _name, _parents, _reg, _n, _m, _sel,	\
    157 		     _enable, _flags)				\
    158 	[_id] = {						\
    159 		.type = SUNXI_CCU_NM,				\
    160 		.base.name = (_name),				\
    161 		.u.nm.reg = (_reg),				\
    162 		.u.nm.parents = (_parents),			\
    163 		.u.nm.nparents = __arraycount(_parents),	\
    164 		.u.nm.n = (_n),					\
    165 		.u.nm.m = (_m),					\
    166 		.u.nm.sel = (_sel),				\
    167 		.u.nm.enable = (_enable),			\
    168 		.u.nm.flags = (_flags),				\
    169 		.enable = sunxi_ccu_nm_enable,			\
    170 		.get_rate = sunxi_ccu_nm_get_rate,		\
    171 		.set_rate = sunxi_ccu_nm_set_rate,		\
    172 		.set_parent = sunxi_ccu_nm_set_parent,		\
    173 		.get_parent = sunxi_ccu_nm_get_parent,		\
    174 	}
    175 
    176 struct sunxi_ccu_div {
    177 	bus_size_t	reg;
    178 	const char	**parents;
    179 	u_int		nparents;
    180 	uint32_t	div;
    181 	uint32_t	sel;
    182 	uint32_t	flags;
    183 #define	SUNXI_CCU_DIV_POWER_OF_TWO	__BIT(0)
    184 #define	SUNXI_CCU_DIV_ZERO_IS_ONE	__BIT(1)
    185 };
    186 
    187 u_int	sunxi_ccu_div_get_rate(struct sunxi_ccu_softc *,
    188 			       struct sunxi_ccu_clk *);
    189 int	sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *,
    190 			       struct sunxi_ccu_clk *, u_int);
    191 int	sunxi_ccu_div_set_parent(struct sunxi_ccu_softc *,
    192 			         struct sunxi_ccu_clk *,
    193 			         const char *);
    194 const char *sunxi_ccu_div_get_parent(struct sunxi_ccu_softc *,
    195 				     struct sunxi_ccu_clk *);
    196 
    197 #define	SUNXI_CCU_DIV(_id, _name, _parents, _reg, _div,		\
    198 		      _sel, _flags)				\
    199 	[_id] = {						\
    200 		.type = SUNXI_CCU_DIV,				\
    201 		.base.name = (_name),				\
    202 		.u.div.reg = (_reg),				\
    203 		.u.div.parents = (_parents),			\
    204 		.u.div.nparents = __arraycount(_parents),	\
    205 		.u.div.div = (_div),				\
    206 		.u.div.sel = (_sel),				\
    207 		.u.div.flags = (_flags),			\
    208 		.get_rate = sunxi_ccu_div_get_rate,		\
    209 		.set_rate = sunxi_ccu_div_set_rate,		\
    210 		.set_parent = sunxi_ccu_div_set_parent,		\
    211 		.get_parent = sunxi_ccu_div_get_parent,		\
    212 	}
    213 
    214 struct sunxi_ccu_prediv {
    215 	bus_size_t	reg;
    216 	const char	**parents;
    217 	u_int		nparents;
    218 	uint32_t	prediv;
    219 	uint32_t	prediv_sel;
    220 	uint32_t	div;
    221 	uint32_t	sel;
    222 	uint32_t	flags;
    223 #define	SUNXI_CCU_PREDIV_POWER_OF_TWO	__BIT(0)
    224 #define	SUNXI_CCU_PREDIV_DIVIDE_BY_TWO	__BIT(1)
    225 };
    226 
    227 u_int	sunxi_ccu_prediv_get_rate(struct sunxi_ccu_softc *,
    228 				  struct sunxi_ccu_clk *);
    229 int	sunxi_ccu_prediv_set_rate(struct sunxi_ccu_softc *,
    230 				  struct sunxi_ccu_clk *, u_int);
    231 int	sunxi_ccu_prediv_set_parent(struct sunxi_ccu_softc *,
    232 				    struct sunxi_ccu_clk *,
    233 				    const char *);
    234 const char *sunxi_ccu_prediv_get_parent(struct sunxi_ccu_softc *,
    235 					struct sunxi_ccu_clk *);
    236 
    237 #define	SUNXI_CCU_PREDIV(_id, _name, _parents, _reg, _prediv,	\
    238 		     _prediv_sel, _div, _sel, _flags)		\
    239 	[_id] = {						\
    240 		.type = SUNXI_CCU_PREDIV,			\
    241 		.base.name = (_name),				\
    242 		.u.prediv.reg = (_reg),				\
    243 		.u.prediv.parents = (_parents),			\
    244 		.u.prediv.nparents = __arraycount(_parents),	\
    245 		.u.prediv.prediv = (_prediv),			\
    246 		.u.prediv.prediv_sel = (_prediv_sel),		\
    247 		.u.prediv.div = (_div),				\
    248 		.u.prediv.sel = (_sel),				\
    249 		.u.prediv.flags = (_flags),			\
    250 		.get_rate = sunxi_ccu_prediv_get_rate,		\
    251 		.set_rate = sunxi_ccu_prediv_set_rate,		\
    252 		.set_parent = sunxi_ccu_prediv_set_parent,	\
    253 		.get_parent = sunxi_ccu_prediv_get_parent,	\
    254 	}
    255 
    256 struct sunxi_ccu_phase {
    257 	bus_size_t	reg;
    258 	const char	*parent;
    259 	uint32_t	mask;
    260 };
    261 
    262 u_int	sunxi_ccu_phase_get_rate(struct sunxi_ccu_softc *,
    263 				 struct sunxi_ccu_clk *);
    264 int	sunxi_ccu_phase_set_rate(struct sunxi_ccu_softc *,
    265 				 struct sunxi_ccu_clk *, u_int);
    266 const char *sunxi_ccu_phase_get_parent(struct sunxi_ccu_softc *,
    267 				       struct sunxi_ccu_clk *);
    268 
    269 #define	SUNXI_CCU_PHASE(_id, _name, _parent, _reg, _mask)	\
    270 	[_id] = {						\
    271 		.type = SUNXI_CCU_PHASE,			\
    272 		.base.name = (_name),				\
    273 		.u.phase.reg = (_reg),				\
    274 		.u.phase.parent = (_parent),			\
    275 		.u.phase.mask = (_mask),			\
    276 		.get_rate = sunxi_ccu_phase_get_rate,		\
    277 		.set_rate = sunxi_ccu_phase_set_rate,		\
    278 		.get_parent = sunxi_ccu_phase_get_parent,	\
    279 	}
    280 
    281 struct sunxi_ccu_clk {
    282 	struct clk	base;
    283 	enum sunxi_ccu_clktype type;
    284 	union {
    285 		struct sunxi_ccu_gate gate;
    286 		struct sunxi_ccu_nm nm;
    287 		struct sunxi_ccu_nkmp nkmp;
    288 		struct sunxi_ccu_prediv prediv;
    289 		struct sunxi_ccu_div div;
    290 		struct sunxi_ccu_phase phase;
    291 	} u;
    292 
    293 	int		(*enable)(struct sunxi_ccu_softc *,
    294 				  struct sunxi_ccu_clk *, int);
    295 	u_int		(*get_rate)(struct sunxi_ccu_softc *,
    296 				    struct sunxi_ccu_clk *);
    297 	int		(*set_rate)(struct sunxi_ccu_softc *,
    298 				    struct sunxi_ccu_clk *, u_int);
    299 	const char *	(*get_parent)(struct sunxi_ccu_softc *,
    300 				      struct sunxi_ccu_clk *);
    301 	int		(*set_parent)(struct sunxi_ccu_softc *,
    302 				      struct sunxi_ccu_clk *,
    303 				      const char *);
    304 };
    305 
    306 struct sunxi_ccu_softc {
    307 	device_t		sc_dev;
    308 	int			sc_phandle;
    309 	bus_space_tag_t		sc_bst;
    310 	bus_space_handle_t	sc_bsh;
    311 
    312 	struct clk_domain	sc_clkdom;
    313 
    314 	struct sunxi_ccu_reset *sc_resets;
    315 	u_int			sc_nresets;
    316 
    317 	struct sunxi_ccu_clk	*sc_clks;
    318 	u_int			sc_nclks;
    319 };
    320 
    321 int	sunxi_ccu_attach(struct sunxi_ccu_softc *);
    322 struct sunxi_ccu_clk *sunxi_ccu_clock_find(struct sunxi_ccu_softc *,
    323 					   const char *);
    324 void	sunxi_ccu_print(struct sunxi_ccu_softc *);
    325 
    326 #define CCU_READ(sc, reg)	\
    327 	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
    328 #define CCU_WRITE(sc, reg, val)	\
    329 	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
    330 
    331 #endif /* _ARM_SUNXI_CCU_H */
    332