1*f001abf4Smacallan /* $NetBSD: sunxi_ccu.h,v 1.24 2024/09/16 23:37:13 macallan Exp $ */ 2a07e90f3Sjmcneill 3a07e90f3Sjmcneill /*- 4a07e90f3Sjmcneill * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca> 5a07e90f3Sjmcneill * All rights reserved. 6a07e90f3Sjmcneill * 7a07e90f3Sjmcneill * Redistribution and use in source and binary forms, with or without 8a07e90f3Sjmcneill * modification, are permitted provided that the following conditions 9a07e90f3Sjmcneill * are met: 10a07e90f3Sjmcneill * 1. Redistributions of source code must retain the above copyright 11a07e90f3Sjmcneill * notice, this list of conditions and the following disclaimer. 12a07e90f3Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright 13a07e90f3Sjmcneill * notice, this list of conditions and the following disclaimer in the 14a07e90f3Sjmcneill * documentation and/or other materials provided with the distribution. 15a07e90f3Sjmcneill * 16a07e90f3Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17a07e90f3Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18a07e90f3Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19a07e90f3Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20a07e90f3Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21a07e90f3Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22a07e90f3Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23a07e90f3Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24a07e90f3Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25a07e90f3Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26a07e90f3Sjmcneill * SUCH DAMAGE. 27a07e90f3Sjmcneill */ 28a07e90f3Sjmcneill 29a07e90f3Sjmcneill #ifndef _ARM_SUNXI_CCU_H 30a07e90f3Sjmcneill #define _ARM_SUNXI_CCU_H 31a07e90f3Sjmcneill 32a07e90f3Sjmcneill #include <dev/clk/clk_backend.h> 33a07e90f3Sjmcneill 34a07e90f3Sjmcneill struct sunxi_ccu_softc; 35a07e90f3Sjmcneill struct sunxi_ccu_clk; 36a07e90f3Sjmcneill struct sunxi_ccu_reset; 37a07e90f3Sjmcneill 38a07e90f3Sjmcneill /* 39a07e90f3Sjmcneill * Resets 40a07e90f3Sjmcneill */ 41a07e90f3Sjmcneill 42a07e90f3Sjmcneill struct sunxi_ccu_reset { 43a07e90f3Sjmcneill bus_size_t reg; 44a07e90f3Sjmcneill uint32_t mask; 45a07e90f3Sjmcneill }; 46a07e90f3Sjmcneill 47a07e90f3Sjmcneill #define SUNXI_CCU_RESET(_id, _reg, _bit) \ 48a07e90f3Sjmcneill [_id] = { \ 49a07e90f3Sjmcneill .reg = (_reg), \ 50a07e90f3Sjmcneill .mask = __BIT(_bit), \ 51a07e90f3Sjmcneill } 52a07e90f3Sjmcneill 53a07e90f3Sjmcneill /* 54a07e90f3Sjmcneill * Clocks 55a07e90f3Sjmcneill */ 56a07e90f3Sjmcneill 57a07e90f3Sjmcneill enum sunxi_ccu_clktype { 58a07e90f3Sjmcneill SUNXI_CCU_UNKNOWN, 59a07e90f3Sjmcneill SUNXI_CCU_GATE, 60a07e90f3Sjmcneill SUNXI_CCU_NM, 6111d415cdSjmcneill SUNXI_CCU_NKMP, 6211d415cdSjmcneill SUNXI_CCU_PREDIV, 63ddb9dd9cSjmcneill SUNXI_CCU_DIV, 64deeed1ddSjmcneill SUNXI_CCU_PHASE, 65a5198ca0Sjmcneill SUNXI_CCU_FIXED_FACTOR, 66a1f84860Sbouyer SUNXI_CCU_FRACTIONAL, 67c26e3874Sjmcneill SUNXI_CCU_MUX, 68a07e90f3Sjmcneill }; 69a07e90f3Sjmcneill 70a07e90f3Sjmcneill struct sunxi_ccu_gate { 71a07e90f3Sjmcneill bus_size_t reg; 72a07e90f3Sjmcneill uint32_t mask; 73a07e90f3Sjmcneill const char *parent; 74a07e90f3Sjmcneill }; 75a07e90f3Sjmcneill 76a07e90f3Sjmcneill int sunxi_ccu_gate_enable(struct sunxi_ccu_softc *, 77a07e90f3Sjmcneill struct sunxi_ccu_clk *, int); 78a07e90f3Sjmcneill const char *sunxi_ccu_gate_get_parent(struct sunxi_ccu_softc *, 79a07e90f3Sjmcneill struct sunxi_ccu_clk *); 80a07e90f3Sjmcneill 81a07e90f3Sjmcneill #define SUNXI_CCU_GATE(_id, _name, _pname, _reg, _bit) \ 82a07e90f3Sjmcneill [_id] = { \ 83a07e90f3Sjmcneill .type = SUNXI_CCU_GATE, \ 84a07e90f3Sjmcneill .base.name = (_name), \ 85ecf61253Sjmcneill .base.flags = CLK_SET_RATE_PARENT, \ 86a07e90f3Sjmcneill .u.gate.parent = (_pname), \ 87a07e90f3Sjmcneill .u.gate.reg = (_reg), \ 88a07e90f3Sjmcneill .u.gate.mask = __BIT(_bit), \ 89a07e90f3Sjmcneill .enable = sunxi_ccu_gate_enable, \ 90a07e90f3Sjmcneill .get_parent = sunxi_ccu_gate_get_parent, \ 91a07e90f3Sjmcneill } 92a07e90f3Sjmcneill 93ecf61253Sjmcneill struct sunxi_ccu_nkmp_tbl { 94ecf61253Sjmcneill u_int rate; 95ecf61253Sjmcneill uint32_t n; 96ecf61253Sjmcneill uint32_t k; 97ecf61253Sjmcneill uint32_t m; 98ecf61253Sjmcneill uint32_t p; 99ecf61253Sjmcneill }; 100ecf61253Sjmcneill 10111d415cdSjmcneill struct sunxi_ccu_nkmp { 10211d415cdSjmcneill bus_size_t reg; 10311d415cdSjmcneill const char *parent; 10411d415cdSjmcneill uint32_t n; 10511d415cdSjmcneill uint32_t k; 10611d415cdSjmcneill uint32_t m; 10711d415cdSjmcneill uint32_t p; 10811d415cdSjmcneill uint32_t lock; 10911d415cdSjmcneill uint32_t enable; 11011d415cdSjmcneill uint32_t flags; 111ecf61253Sjmcneill const struct sunxi_ccu_nkmp_tbl *table; 11268166010Sjmcneill #define SUNXI_CCU_NKMP_DIVIDE_BY_TWO __BIT(0) 1136685c529Sjmcneill #define SUNXI_CCU_NKMP_FACTOR_N_EXACT __BIT(1) 114b3e175fcSjmcneill #define SUNXI_CCU_NKMP_SCALE_CLOCK __BIT(2) 115b3e175fcSjmcneill #define SUNXI_CCU_NKMP_FACTOR_P_POW2 __BIT(3) 1166dec99e3Sjmcneill #define SUNXI_CCU_NKMP_FACTOR_N_ZERO_IS_ONE __BIT(4) 1174681bc70Sjmcneill #define SUNXI_CCU_NKMP_FACTOR_P_X4 __BIT(5) 11811d415cdSjmcneill }; 11911d415cdSjmcneill 12011d415cdSjmcneill int sunxi_ccu_nkmp_enable(struct sunxi_ccu_softc *, 12111d415cdSjmcneill struct sunxi_ccu_clk *, int); 12211d415cdSjmcneill u_int sunxi_ccu_nkmp_get_rate(struct sunxi_ccu_softc *, 12311d415cdSjmcneill struct sunxi_ccu_clk *); 12411d415cdSjmcneill int sunxi_ccu_nkmp_set_rate(struct sunxi_ccu_softc *, 12511d415cdSjmcneill struct sunxi_ccu_clk *, u_int); 12611d415cdSjmcneill const char *sunxi_ccu_nkmp_get_parent(struct sunxi_ccu_softc *, 12711d415cdSjmcneill struct sunxi_ccu_clk *); 12811d415cdSjmcneill 129ecf61253Sjmcneill #define SUNXI_CCU_NKMP_TABLE(_id, _name, _parent, _reg, _n, _k, _m, \ 130ecf61253Sjmcneill _p, _enable, _lock, _tbl, _flags) \ 13111d415cdSjmcneill [_id] = { \ 13211d415cdSjmcneill .type = SUNXI_CCU_NKMP, \ 13311d415cdSjmcneill .base.name = (_name), \ 13411d415cdSjmcneill .u.nkmp.reg = (_reg), \ 13511d415cdSjmcneill .u.nkmp.parent = (_parent), \ 13611d415cdSjmcneill .u.nkmp.n = (_n), \ 13711d415cdSjmcneill .u.nkmp.k = (_k), \ 13811d415cdSjmcneill .u.nkmp.m = (_m), \ 13911d415cdSjmcneill .u.nkmp.p = (_p), \ 14011d415cdSjmcneill .u.nkmp.enable = (_enable), \ 14111d415cdSjmcneill .u.nkmp.flags = (_flags), \ 142ecf61253Sjmcneill .u.nkmp.lock = (_lock), \ 143ecf61253Sjmcneill .u.nkmp.table = (_tbl), \ 14411d415cdSjmcneill .enable = sunxi_ccu_nkmp_enable, \ 14511d415cdSjmcneill .get_rate = sunxi_ccu_nkmp_get_rate, \ 14611d415cdSjmcneill .set_rate = sunxi_ccu_nkmp_set_rate, \ 14711d415cdSjmcneill .get_parent = sunxi_ccu_nkmp_get_parent, \ 14811d415cdSjmcneill } 14911d415cdSjmcneill 150ecf61253Sjmcneill #define SUNXI_CCU_NKMP(_id, _name, _parent, _reg, _n, _k, _m, \ 151ecf61253Sjmcneill _p, _enable, _flags) \ 152ecf61253Sjmcneill SUNXI_CCU_NKMP_TABLE(_id, _name, _parent, _reg, _n, _k, _m, \ 153ecf61253Sjmcneill _p, _enable, 0, NULL, _flags) 154ecf61253Sjmcneill 155ecf61253Sjmcneill 156a07e90f3Sjmcneill struct sunxi_ccu_nm { 157a07e90f3Sjmcneill bus_size_t reg; 158a07e90f3Sjmcneill const char **parents; 159a07e90f3Sjmcneill u_int nparents; 160a07e90f3Sjmcneill uint32_t n; 161a07e90f3Sjmcneill uint32_t m; 162a07e90f3Sjmcneill uint32_t sel; 16311d415cdSjmcneill uint32_t enable; 164a07e90f3Sjmcneill uint32_t flags; 165a07e90f3Sjmcneill #define SUNXI_CCU_NM_POWER_OF_TWO __BIT(0) 16611d415cdSjmcneill #define SUNXI_CCU_NM_ROUND_DOWN __BIT(1) 167c68d93beSjmcneill #define SUNXI_CCU_NM_DIVIDE_BY_TWO __BIT(2) 168a07e90f3Sjmcneill }; 169a07e90f3Sjmcneill 17011d415cdSjmcneill int sunxi_ccu_nm_enable(struct sunxi_ccu_softc *, 17111d415cdSjmcneill struct sunxi_ccu_clk *, int); 172a07e90f3Sjmcneill u_int sunxi_ccu_nm_get_rate(struct sunxi_ccu_softc *, 173a07e90f3Sjmcneill struct sunxi_ccu_clk *); 174a07e90f3Sjmcneill int sunxi_ccu_nm_set_rate(struct sunxi_ccu_softc *, 175a07e90f3Sjmcneill struct sunxi_ccu_clk *, u_int); 176a07e90f3Sjmcneill int sunxi_ccu_nm_set_parent(struct sunxi_ccu_softc *, 177a07e90f3Sjmcneill struct sunxi_ccu_clk *, 178a07e90f3Sjmcneill const char *); 179a07e90f3Sjmcneill const char *sunxi_ccu_nm_get_parent(struct sunxi_ccu_softc *, 180a07e90f3Sjmcneill struct sunxi_ccu_clk *); 181a07e90f3Sjmcneill 182a07e90f3Sjmcneill #define SUNXI_CCU_NM(_id, _name, _parents, _reg, _n, _m, _sel, \ 18311d415cdSjmcneill _enable, _flags) \ 184a07e90f3Sjmcneill [_id] = { \ 185a07e90f3Sjmcneill .type = SUNXI_CCU_NM, \ 186a07e90f3Sjmcneill .base.name = (_name), \ 187a07e90f3Sjmcneill .u.nm.reg = (_reg), \ 188a07e90f3Sjmcneill .u.nm.parents = (_parents), \ 189a07e90f3Sjmcneill .u.nm.nparents = __arraycount(_parents), \ 190a07e90f3Sjmcneill .u.nm.n = (_n), \ 191a07e90f3Sjmcneill .u.nm.m = (_m), \ 192a07e90f3Sjmcneill .u.nm.sel = (_sel), \ 19311d415cdSjmcneill .u.nm.enable = (_enable), \ 194a07e90f3Sjmcneill .u.nm.flags = (_flags), \ 19511d415cdSjmcneill .enable = sunxi_ccu_nm_enable, \ 19611d415cdSjmcneill .get_rate = sunxi_ccu_nm_get_rate, \ 19711d415cdSjmcneill .set_rate = sunxi_ccu_nm_set_rate, \ 198a07e90f3Sjmcneill .set_parent = sunxi_ccu_nm_set_parent, \ 199a07e90f3Sjmcneill .get_parent = sunxi_ccu_nm_get_parent, \ 200a07e90f3Sjmcneill } 201a07e90f3Sjmcneill 202ddb9dd9cSjmcneill struct sunxi_ccu_div { 203ddb9dd9cSjmcneill bus_size_t reg; 204ddb9dd9cSjmcneill const char **parents; 205ddb9dd9cSjmcneill u_int nparents; 206ddb9dd9cSjmcneill uint32_t div; 207ddb9dd9cSjmcneill uint32_t sel; 208607cd651Sjmcneill uint32_t enable; 209ddb9dd9cSjmcneill uint32_t flags; 210ddb9dd9cSjmcneill #define SUNXI_CCU_DIV_POWER_OF_TWO __BIT(0) 211ddb9dd9cSjmcneill #define SUNXI_CCU_DIV_ZERO_IS_ONE __BIT(1) 212607cd651Sjmcneill #define SUNXI_CCU_DIV_TIMES_TWO __BIT(2) 213df83149aSjmcneill #define SUNXI_CCU_DIV_SET_RATE_PARENT __BIT(3) 214ddb9dd9cSjmcneill }; 215ddb9dd9cSjmcneill 216607cd651Sjmcneill int sunxi_ccu_div_enable(struct sunxi_ccu_softc *, 217607cd651Sjmcneill struct sunxi_ccu_clk *, int); 218ddb9dd9cSjmcneill u_int sunxi_ccu_div_get_rate(struct sunxi_ccu_softc *, 219ddb9dd9cSjmcneill struct sunxi_ccu_clk *); 220ddb9dd9cSjmcneill int sunxi_ccu_div_set_rate(struct sunxi_ccu_softc *, 221ddb9dd9cSjmcneill struct sunxi_ccu_clk *, u_int); 222ddb9dd9cSjmcneill int sunxi_ccu_div_set_parent(struct sunxi_ccu_softc *, 223ddb9dd9cSjmcneill struct sunxi_ccu_clk *, 224ddb9dd9cSjmcneill const char *); 225ddb9dd9cSjmcneill const char *sunxi_ccu_div_get_parent(struct sunxi_ccu_softc *, 226ddb9dd9cSjmcneill struct sunxi_ccu_clk *); 227ddb9dd9cSjmcneill 228ddb9dd9cSjmcneill #define SUNXI_CCU_DIV(_id, _name, _parents, _reg, _div, \ 229ddb9dd9cSjmcneill _sel, _flags) \ 230607cd651Sjmcneill SUNXI_CCU_DIV_GATE(_id, _name, _parents, _reg, _div, \ 231607cd651Sjmcneill _sel, 0, _flags) 232607cd651Sjmcneill 233607cd651Sjmcneill #define SUNXI_CCU_DIV_GATE(_id, _name, _parents, _reg, _div, \ 234607cd651Sjmcneill _sel, _enable, _flags) \ 235ddb9dd9cSjmcneill [_id] = { \ 236ddb9dd9cSjmcneill .type = SUNXI_CCU_DIV, \ 237ddb9dd9cSjmcneill .base.name = (_name), \ 238ddb9dd9cSjmcneill .u.div.reg = (_reg), \ 239ddb9dd9cSjmcneill .u.div.parents = (_parents), \ 240ddb9dd9cSjmcneill .u.div.nparents = __arraycount(_parents), \ 241ddb9dd9cSjmcneill .u.div.div = (_div), \ 242ddb9dd9cSjmcneill .u.div.sel = (_sel), \ 243607cd651Sjmcneill .u.div.enable = (_enable), \ 244ddb9dd9cSjmcneill .u.div.flags = (_flags), \ 245607cd651Sjmcneill .enable = sunxi_ccu_div_enable, \ 246ddb9dd9cSjmcneill .get_rate = sunxi_ccu_div_get_rate, \ 247ddb9dd9cSjmcneill .set_rate = sunxi_ccu_div_set_rate, \ 248ddb9dd9cSjmcneill .set_parent = sunxi_ccu_div_set_parent, \ 249ddb9dd9cSjmcneill .get_parent = sunxi_ccu_div_get_parent, \ 250ddb9dd9cSjmcneill } 251ddb9dd9cSjmcneill 252db6d41fbSbouyer /* special case of the div model for display clocks */ 253db6d41fbSbouyer int sunxi_ccu_lcdxch0_set_rate(struct sunxi_ccu_softc *, 254db6d41fbSbouyer struct sunxi_ccu_clk *, struct sunxi_ccu_clk *, 255db6d41fbSbouyer struct sunxi_ccu_clk *, u_int); 256db6d41fbSbouyer u_int sunxi_ccu_lcdxch0_round_rate(struct sunxi_ccu_softc *, 257db6d41fbSbouyer struct sunxi_ccu_clk *, struct sunxi_ccu_clk *, 258db6d41fbSbouyer struct sunxi_ccu_clk *, u_int); 259db6d41fbSbouyer 260db6d41fbSbouyer int sunxi_ccu_lcdxch1_set_rate(struct sunxi_ccu_softc *sc, 261db6d41fbSbouyer struct sunxi_ccu_clk *clk, struct sunxi_ccu_clk *pclk, 262db6d41fbSbouyer struct sunxi_ccu_clk *pclk_x2, u_int); 263db6d41fbSbouyer 26411d415cdSjmcneill struct sunxi_ccu_prediv { 26511d415cdSjmcneill bus_size_t reg; 26611d415cdSjmcneill const char **parents; 26711d415cdSjmcneill u_int nparents; 26811d415cdSjmcneill uint32_t prediv; 26911d415cdSjmcneill uint32_t prediv_sel; 27069b44ac7Sjmcneill uint32_t prediv_fixed; 27111d415cdSjmcneill uint32_t div; 27211d415cdSjmcneill uint32_t sel; 27311d415cdSjmcneill uint32_t flags; 27411d415cdSjmcneill #define SUNXI_CCU_PREDIV_POWER_OF_TWO __BIT(0) 2751e6185e4Sjmcneill #define SUNXI_CCU_PREDIV_DIVIDE_BY_TWO __BIT(1) 27611d415cdSjmcneill }; 27711d415cdSjmcneill 27811d415cdSjmcneill u_int sunxi_ccu_prediv_get_rate(struct sunxi_ccu_softc *, 27911d415cdSjmcneill struct sunxi_ccu_clk *); 28011d415cdSjmcneill int sunxi_ccu_prediv_set_rate(struct sunxi_ccu_softc *, 28111d415cdSjmcneill struct sunxi_ccu_clk *, u_int); 28211d415cdSjmcneill int sunxi_ccu_prediv_set_parent(struct sunxi_ccu_softc *, 28311d415cdSjmcneill struct sunxi_ccu_clk *, 28411d415cdSjmcneill const char *); 28511d415cdSjmcneill const char *sunxi_ccu_prediv_get_parent(struct sunxi_ccu_softc *, 28611d415cdSjmcneill struct sunxi_ccu_clk *); 28711d415cdSjmcneill 28811d415cdSjmcneill #define SUNXI_CCU_PREDIV(_id, _name, _parents, _reg, _prediv, \ 28911d415cdSjmcneill _prediv_sel, _div, _sel, _flags) \ 29069b44ac7Sjmcneill SUNXI_CCU_PREDIV_FIXED(_id, _name, _parents, _reg, _prediv, \ 29169b44ac7Sjmcneill _prediv_sel, 0, _div, _sel, _flags) 29269b44ac7Sjmcneill 29369b44ac7Sjmcneill #define SUNXI_CCU_PREDIV_FIXED(_id, _name, _parents, _reg, _prediv, \ 29469b44ac7Sjmcneill _prediv_sel, _prediv_fixed, _div, _sel, _flags) \ 29511d415cdSjmcneill [_id] = { \ 29611d415cdSjmcneill .type = SUNXI_CCU_PREDIV, \ 29711d415cdSjmcneill .base.name = (_name), \ 29811d415cdSjmcneill .u.prediv.reg = (_reg), \ 29911d415cdSjmcneill .u.prediv.parents = (_parents), \ 30011d415cdSjmcneill .u.prediv.nparents = __arraycount(_parents), \ 30111d415cdSjmcneill .u.prediv.prediv = (_prediv), \ 30211d415cdSjmcneill .u.prediv.prediv_sel = (_prediv_sel), \ 30369b44ac7Sjmcneill .u.prediv.prediv_fixed = (_prediv_fixed), \ 30411d415cdSjmcneill .u.prediv.div = (_div), \ 30511d415cdSjmcneill .u.prediv.sel = (_sel), \ 30611d415cdSjmcneill .u.prediv.flags = (_flags), \ 30711d415cdSjmcneill .get_rate = sunxi_ccu_prediv_get_rate, \ 30811d415cdSjmcneill .set_rate = sunxi_ccu_prediv_set_rate, \ 30911d415cdSjmcneill .set_parent = sunxi_ccu_prediv_set_parent, \ 31011d415cdSjmcneill .get_parent = sunxi_ccu_prediv_get_parent, \ 31111d415cdSjmcneill } 31211d415cdSjmcneill 313deeed1ddSjmcneill struct sunxi_ccu_phase { 314deeed1ddSjmcneill bus_size_t reg; 315deeed1ddSjmcneill const char *parent; 316deeed1ddSjmcneill uint32_t mask; 317deeed1ddSjmcneill }; 318deeed1ddSjmcneill 319deeed1ddSjmcneill u_int sunxi_ccu_phase_get_rate(struct sunxi_ccu_softc *, 320deeed1ddSjmcneill struct sunxi_ccu_clk *); 321deeed1ddSjmcneill int sunxi_ccu_phase_set_rate(struct sunxi_ccu_softc *, 322deeed1ddSjmcneill struct sunxi_ccu_clk *, u_int); 323deeed1ddSjmcneill const char *sunxi_ccu_phase_get_parent(struct sunxi_ccu_softc *, 324deeed1ddSjmcneill struct sunxi_ccu_clk *); 325deeed1ddSjmcneill 326deeed1ddSjmcneill #define SUNXI_CCU_PHASE(_id, _name, _parent, _reg, _mask) \ 327deeed1ddSjmcneill [_id] = { \ 328deeed1ddSjmcneill .type = SUNXI_CCU_PHASE, \ 329deeed1ddSjmcneill .base.name = (_name), \ 330deeed1ddSjmcneill .u.phase.reg = (_reg), \ 331deeed1ddSjmcneill .u.phase.parent = (_parent), \ 332deeed1ddSjmcneill .u.phase.mask = (_mask), \ 333deeed1ddSjmcneill .get_rate = sunxi_ccu_phase_get_rate, \ 334deeed1ddSjmcneill .set_rate = sunxi_ccu_phase_set_rate, \ 335deeed1ddSjmcneill .get_parent = sunxi_ccu_phase_get_parent, \ 336deeed1ddSjmcneill } 337deeed1ddSjmcneill 338a5198ca0Sjmcneill struct sunxi_ccu_fixed_factor { 339a5198ca0Sjmcneill const char *parent; 340a5198ca0Sjmcneill u_int div; 341a5198ca0Sjmcneill u_int mult; 342a5198ca0Sjmcneill }; 343a5198ca0Sjmcneill 344a5198ca0Sjmcneill u_int sunxi_ccu_fixed_factor_get_rate(struct sunxi_ccu_softc *, 345a5198ca0Sjmcneill struct sunxi_ccu_clk *); 346aac64003Sjmcneill int sunxi_ccu_fixed_factor_set_rate(struct sunxi_ccu_softc *, 347aac64003Sjmcneill struct sunxi_ccu_clk *, u_int); 348a5198ca0Sjmcneill const char *sunxi_ccu_fixed_factor_get_parent(struct sunxi_ccu_softc *, 349a5198ca0Sjmcneill struct sunxi_ccu_clk *); 350a5198ca0Sjmcneill 351a5198ca0Sjmcneill #define SUNXI_CCU_FIXED_FACTOR(_id, _name, _parent, _div, _mult) \ 352a5198ca0Sjmcneill [_id] = { \ 353a5198ca0Sjmcneill .type = SUNXI_CCU_FIXED_FACTOR, \ 354a5198ca0Sjmcneill .base.name = (_name), \ 355a5198ca0Sjmcneill .u.fixed_factor.parent = (_parent), \ 356a5198ca0Sjmcneill .u.fixed_factor.div = (_div), \ 357a5198ca0Sjmcneill .u.fixed_factor.mult = (_mult), \ 358a5198ca0Sjmcneill .get_rate = sunxi_ccu_fixed_factor_get_rate, \ 359a5198ca0Sjmcneill .get_parent = sunxi_ccu_fixed_factor_get_parent, \ 360aac64003Sjmcneill .set_rate = sunxi_ccu_fixed_factor_set_rate, \ 361a5198ca0Sjmcneill } 362a5198ca0Sjmcneill 363a1f84860Sbouyer struct sunxi_ccu_fractional { 364a1f84860Sbouyer bus_size_t reg; 365a1f84860Sbouyer const char *parent; 366a1f84860Sbouyer uint32_t m; 367a1f84860Sbouyer uint32_t m_min; 368a1f84860Sbouyer uint32_t m_max; 369db6d41fbSbouyer uint32_t div_en; 370a1f84860Sbouyer uint32_t frac_sel; 371a1f84860Sbouyer uint32_t frac[2]; 372a1f84860Sbouyer uint32_t prediv; 373cf80abdeSjmcneill uint32_t prediv_val; 374a1f84860Sbouyer uint32_t enable; 375cf80abdeSjmcneill uint32_t flags; 376cf80abdeSjmcneill #define SUNXI_CCU_FRACTIONAL_PLUSONE __BIT(0) 377a9d03646Sjmcneill #define SUNXI_CCU_FRACTIONAL_SET_ENABLE __BIT(1) 378a1f84860Sbouyer }; 379a1f84860Sbouyer 380a1f84860Sbouyer int sunxi_ccu_fractional_enable(struct sunxi_ccu_softc *, 381a1f84860Sbouyer struct sunxi_ccu_clk *, int); 382a1f84860Sbouyer u_int sunxi_ccu_fractional_get_rate(struct sunxi_ccu_softc *, 383a1f84860Sbouyer struct sunxi_ccu_clk *); 384a1f84860Sbouyer int sunxi_ccu_fractional_set_rate(struct sunxi_ccu_softc *, 385a1f84860Sbouyer struct sunxi_ccu_clk *, u_int); 386db6d41fbSbouyer u_int sunxi_ccu_fractional_round_rate(struct sunxi_ccu_softc *, 387db6d41fbSbouyer struct sunxi_ccu_clk *, u_int); 388a1f84860Sbouyer const char *sunxi_ccu_fractional_get_parent(struct sunxi_ccu_softc *, 389a1f84860Sbouyer struct sunxi_ccu_clk *); 390a1f84860Sbouyer 391a1f84860Sbouyer #define SUNXI_CCU_FRACTIONAL(_id, _name, _parent, _reg, _m, _m_min, _m_max, \ 392cf80abdeSjmcneill _div_en, _frac_sel, _frac0, _frac1, _prediv, _prediv_val, \ 393cf80abdeSjmcneill _enable, _flags) \ 394a1f84860Sbouyer [_id] = { \ 395a1f84860Sbouyer .type = SUNXI_CCU_FRACTIONAL, \ 396a1f84860Sbouyer .base.name = (_name), \ 397a1f84860Sbouyer .u.fractional.reg = (_reg), \ 398a1f84860Sbouyer .u.fractional.parent = (_parent), \ 399a1f84860Sbouyer .u.fractional.m = (_m), \ 400a1f84860Sbouyer .u.fractional.m_min = (_m_min), \ 401a1f84860Sbouyer .u.fractional.m_max = (_m_max), \ 402a1f84860Sbouyer .u.fractional.prediv = (_prediv), \ 403cf80abdeSjmcneill .u.fractional.prediv_val = (_prediv_val), \ 404db6d41fbSbouyer .u.fractional.div_en = (_div_en), \ 405a1f84860Sbouyer .u.fractional.frac_sel = (_frac_sel), \ 406a1f84860Sbouyer .u.fractional.frac[0] = (_frac0), \ 407a1f84860Sbouyer .u.fractional.frac[1] = (_frac1), \ 408a1f84860Sbouyer .u.fractional.enable = (_enable), \ 409b770b2aaSjakllsch .u.fractional.flags = (_flags), \ 410a1f84860Sbouyer .enable = sunxi_ccu_fractional_enable, \ 411a1f84860Sbouyer .get_rate = sunxi_ccu_fractional_get_rate, \ 412a1f84860Sbouyer .set_rate = sunxi_ccu_fractional_set_rate, \ 413db6d41fbSbouyer .round_rate = sunxi_ccu_fractional_round_rate, \ 414a1f84860Sbouyer .get_parent = sunxi_ccu_fractional_get_parent, \ 415a1f84860Sbouyer } 416a1f84860Sbouyer 417c26e3874Sjmcneill struct sunxi_ccu_mux { 418c26e3874Sjmcneill bus_size_t reg; 419c26e3874Sjmcneill const char **parents; 420c26e3874Sjmcneill u_int nparents; 421c26e3874Sjmcneill uint32_t sel; 422c26e3874Sjmcneill uint32_t flags; 423c26e3874Sjmcneill }; 424c26e3874Sjmcneill 425c26e3874Sjmcneill int sunxi_ccu_mux_set_parent(struct sunxi_ccu_softc *, 426c26e3874Sjmcneill struct sunxi_ccu_clk *, 427c26e3874Sjmcneill const char *); 428c26e3874Sjmcneill const char *sunxi_ccu_mux_get_parent(struct sunxi_ccu_softc *, 429c26e3874Sjmcneill struct sunxi_ccu_clk *); 430c26e3874Sjmcneill 431c26e3874Sjmcneill #define SUNXI_CCU_MUX(_id, _name, _parents, _reg, _sel, _flags) \ 432c26e3874Sjmcneill [_id] = { \ 433c26e3874Sjmcneill .type = SUNXI_CCU_MUX, \ 434c26e3874Sjmcneill .base.name = (_name), \ 435*f001abf4Smacallan .base.flags = CLK_SET_RATE_PARENT, \ 436c26e3874Sjmcneill .u.mux.reg = (_reg), \ 437c26e3874Sjmcneill .u.mux.parents = (_parents), \ 438c26e3874Sjmcneill .u.mux.nparents = __arraycount(_parents), \ 439c26e3874Sjmcneill .u.mux.sel = (_sel), \ 440c26e3874Sjmcneill .u.mux.flags = (_flags), \ 441c26e3874Sjmcneill .set_parent = sunxi_ccu_mux_set_parent, \ 442c26e3874Sjmcneill .get_parent = sunxi_ccu_mux_get_parent, \ 443c26e3874Sjmcneill } 444c26e3874Sjmcneill 445c26e3874Sjmcneill 446a07e90f3Sjmcneill struct sunxi_ccu_clk { 447a07e90f3Sjmcneill struct clk base; 448a07e90f3Sjmcneill enum sunxi_ccu_clktype type; 449a07e90f3Sjmcneill union { 450a07e90f3Sjmcneill struct sunxi_ccu_gate gate; 451a07e90f3Sjmcneill struct sunxi_ccu_nm nm; 45211d415cdSjmcneill struct sunxi_ccu_nkmp nkmp; 45311d415cdSjmcneill struct sunxi_ccu_prediv prediv; 454ddb9dd9cSjmcneill struct sunxi_ccu_div div; 455deeed1ddSjmcneill struct sunxi_ccu_phase phase; 456a5198ca0Sjmcneill struct sunxi_ccu_fixed_factor fixed_factor; 457a1f84860Sbouyer struct sunxi_ccu_fractional fractional; 458c26e3874Sjmcneill struct sunxi_ccu_mux mux; 459a07e90f3Sjmcneill } u; 460a07e90f3Sjmcneill 461a07e90f3Sjmcneill int (*enable)(struct sunxi_ccu_softc *, 462a07e90f3Sjmcneill struct sunxi_ccu_clk *, int); 463a07e90f3Sjmcneill u_int (*get_rate)(struct sunxi_ccu_softc *, 464a07e90f3Sjmcneill struct sunxi_ccu_clk *); 465a07e90f3Sjmcneill int (*set_rate)(struct sunxi_ccu_softc *, 466a07e90f3Sjmcneill struct sunxi_ccu_clk *, u_int); 467db6d41fbSbouyer u_int (*round_rate)(struct sunxi_ccu_softc *, 468db6d41fbSbouyer struct sunxi_ccu_clk *, u_int); 469a07e90f3Sjmcneill const char * (*get_parent)(struct sunxi_ccu_softc *, 470a07e90f3Sjmcneill struct sunxi_ccu_clk *); 471a07e90f3Sjmcneill int (*set_parent)(struct sunxi_ccu_softc *, 472a07e90f3Sjmcneill struct sunxi_ccu_clk *, 473a07e90f3Sjmcneill const char *); 474a07e90f3Sjmcneill }; 475a07e90f3Sjmcneill 476a07e90f3Sjmcneill struct sunxi_ccu_softc { 477a07e90f3Sjmcneill device_t sc_dev; 478a07e90f3Sjmcneill int sc_phandle; 479a07e90f3Sjmcneill bus_space_tag_t sc_bst; 480a07e90f3Sjmcneill bus_space_handle_t sc_bsh; 481a07e90f3Sjmcneill 482a07e90f3Sjmcneill struct clk_domain sc_clkdom; 483a07e90f3Sjmcneill 484a07e90f3Sjmcneill struct sunxi_ccu_reset *sc_resets; 485a07e90f3Sjmcneill u_int sc_nresets; 486a07e90f3Sjmcneill 487a07e90f3Sjmcneill struct sunxi_ccu_clk *sc_clks; 488a07e90f3Sjmcneill u_int sc_nclks; 489a07e90f3Sjmcneill }; 490a07e90f3Sjmcneill 491a07e90f3Sjmcneill int sunxi_ccu_attach(struct sunxi_ccu_softc *); 492a07e90f3Sjmcneill struct sunxi_ccu_clk *sunxi_ccu_clock_find(struct sunxi_ccu_softc *, 493a07e90f3Sjmcneill const char *); 494a07e90f3Sjmcneill void sunxi_ccu_print(struct sunxi_ccu_softc *); 495a07e90f3Sjmcneill 496a07e90f3Sjmcneill #define CCU_READ(sc, reg) \ 497a07e90f3Sjmcneill bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 498a07e90f3Sjmcneill #define CCU_WRITE(sc, reg, val) \ 499a07e90f3Sjmcneill bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 500a07e90f3Sjmcneill 501a07e90f3Sjmcneill #endif /* _ARM_SUNXI_CCU_H */ 502