1 /* $NetBSD: ti_prcm.h,v 1.4 2019/10/30 21:41:40 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_TI_PRCM_H 30 #define _ARM_TI_PRCM_H 31 32 #ifdef TI_PRCM_PRIVATE 33 34 #include <dev/clk/clk_backend.h> 35 36 struct ti_prcm_clk; 37 struct ti_prcm_softc; 38 39 enum ti_prcm_clktype { 40 TI_PRCM_UNKNOWN, 41 TI_PRCM_FIXED, 42 TI_PRCM_FIXED_FACTOR, 43 TI_PRCM_HWMOD, 44 }; 45 46 struct ti_prcm_fixed { 47 u_int rate; 48 }; 49 50 struct ti_prcm_fixed_factor { 51 u_int mult; 52 u_int div; 53 const char *parent; 54 }; 55 56 struct ti_prcm_hwmod { 57 bus_size_t reg; 58 uint32_t mask; 59 const char *parent; 60 u_int flags; 61 }; 62 63 #define TI_HWMOD_DISABLE_AUTOIDLE 0x01 64 65 struct ti_prcm_clk { 66 struct clk base; 67 enum ti_prcm_clktype type; 68 union { 69 struct ti_prcm_fixed fixed; 70 struct ti_prcm_fixed_factor fixed_factor; 71 struct ti_prcm_hwmod hwmod; 72 } u; 73 74 int (*enable)(struct ti_prcm_softc *, 75 struct ti_prcm_clk *, int); 76 u_int (*get_rate)(struct ti_prcm_softc *, 77 struct ti_prcm_clk *); 78 int (*set_rate)(struct ti_prcm_softc *, 79 struct ti_prcm_clk *, u_int); 80 const char * (*get_parent)(struct ti_prcm_softc *, 81 struct ti_prcm_clk *); 82 int (*set_parent)(struct ti_prcm_softc *, 83 struct ti_prcm_clk *, 84 const char *); 85 }; 86 87 int ti_prcm_attach(struct ti_prcm_softc *); 88 struct ti_prcm_clk *ti_prcm_clock_find(struct ti_prcm_softc *, const char *); 89 90 static inline u_int 91 ti_prcm_fixed_get_rate(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc) 92 { 93 KASSERT(tc->type == TI_PRCM_FIXED); 94 return tc->u.fixed.rate; 95 } 96 97 #define TI_PRCM_FIXED(_name, _rate) \ 98 { \ 99 .type = TI_PRCM_FIXED, .base.name = (_name), \ 100 .u.fixed.rate = (_rate), \ 101 .get_rate = ti_prcm_fixed_get_rate, \ 102 } 103 104 static inline u_int 105 ti_prcm_fixed_factor_get_rate(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc) 106 { 107 KASSERT(tc->type == TI_PRCM_FIXED_FACTOR); 108 struct ti_prcm_clk *tc_parent; 109 110 tc_parent = ti_prcm_clock_find(sc, tc->u.fixed_factor.parent); 111 KASSERT(tc_parent != NULL); 112 113 const u_int mult = tc->u.fixed_factor.mult; 114 const u_int div = tc->u.fixed_factor.div; 115 116 return (clk_get_rate(&tc_parent->base) * mult) / div; 117 } 118 119 static inline const char * 120 ti_prcm_fixed_factor_get_parent(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc) 121 { 122 KASSERT(tc->type == TI_PRCM_FIXED_FACTOR); 123 return tc->u.fixed_factor.parent; 124 } 125 126 #define TI_PRCM_FIXED_FACTOR(_name, _mult, _div, _parent) \ 127 { \ 128 .type = TI_PRCM_FIXED_FACTOR, .base.name = (_name), \ 129 .u.fixed_factor.mult = (_mult), \ 130 .u.fixed_factor.div = (_div), \ 131 .u.fixed_factor.parent = (_parent), \ 132 .get_rate = ti_prcm_fixed_factor_get_rate, \ 133 .get_parent = ti_prcm_fixed_factor_get_parent, \ 134 } 135 136 static inline const char * 137 ti_prcm_hwmod_get_parent(struct ti_prcm_softc *sc, struct ti_prcm_clk *tc) 138 { 139 KASSERT(tc->type == TI_PRCM_HWMOD); 140 return tc->u.hwmod.parent; 141 } 142 143 #define TI_PRCM_HWMOD(_name, _reg, _parent, _enable) \ 144 TI_PRCM_HWMOD_MASK(_name, _reg, 0, _parent, _enable, 0) 145 146 #define TI_PRCM_HWMOD_MASK(_name, _reg, _mask, _parent, _enable, _flags) \ 147 { \ 148 .type = TI_PRCM_HWMOD, .base.name = (_name), \ 149 .u.hwmod.reg = (_reg), \ 150 .u.hwmod.mask = (_mask), \ 151 .u.hwmod.flags = (_flags), \ 152 .u.hwmod.parent = (_parent), \ 153 .enable = (_enable), \ 154 .get_parent = ti_prcm_hwmod_get_parent, \ 155 } 156 157 struct ti_prcm_softc { 158 device_t sc_dev; 159 int sc_phandle; 160 bus_space_tag_t sc_bst; 161 bus_space_handle_t sc_bsh; 162 163 struct clk_domain sc_clkdom; 164 165 struct ti_prcm_clk *sc_clks; 166 u_int sc_nclks; 167 }; 168 169 #define PRCM_READ(sc, reg) \ 170 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg)) 171 #define PRCM_WRITE(sc, reg, val) \ 172 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val)) 173 174 #endif /* !TI_PRCM_PRIVATE */ 175 176 struct clk * ti_prcm_get_hwmod(const int, u_int); 177 int ti_prcm_enable_hwmod(const int, u_int); 178 179 #endif /* !_ARM_TI_PRCM_H */ 180