1 /* 2 * Copyright 2014 Chen-Yu Tsai 3 * 4 * Chen-Yu Tsai <wens@csie.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <linux/clk.h> 18 #include <linux/clkdev.h> 19 #include <linux/clk-provider.h> 20 #include <linux/of.h> 21 #include <linux/of_address.h> 22 #include <linux/log2.h> 23 24 #include "clk-factors.h" 25 26 27 /** 28 * sun9i_a80_get_pll4_factors() - calculates n, p, m factors for PLL4 29 * PLL4 rate is calculated as follows 30 * rate = (parent_rate * n >> p) / (m + 1); 31 * parent_rate is always 24MHz 32 * 33 * p and m are named div1 and div2 in Allwinner's SDK 34 */ 35 36 static void sun9i_a80_get_pll4_factors(struct factors_request *req) 37 { 38 int n; 39 int m = 1; 40 int p = 1; 41 42 /* Normalize value to a 6 MHz multiple (24 MHz / 4) */ 43 n = DIV_ROUND_UP(req->rate, 6000000); 44 45 /* If n is too large switch to steps of 12 MHz */ 46 if (n > 255) { 47 m = 0; 48 n = (n + 1) / 2; 49 } 50 51 /* If n is still too large switch to steps of 24 MHz */ 52 if (n > 255) { 53 p = 0; 54 n = (n + 1) / 2; 55 } 56 57 /* n must be between 12 and 255 */ 58 if (n > 255) 59 n = 255; 60 else if (n < 12) 61 n = 12; 62 63 req->rate = ((24000000 * n) >> p) / (m + 1); 64 req->n = n; 65 req->m = m; 66 req->p = p; 67 } 68 69 static const struct clk_factors_config sun9i_a80_pll4_config = { 70 .mshift = 18, 71 .mwidth = 1, 72 .nshift = 8, 73 .nwidth = 8, 74 .pshift = 16, 75 .pwidth = 1, 76 }; 77 78 static const struct factors_data sun9i_a80_pll4_data __initconst = { 79 .enable = 31, 80 .table = &sun9i_a80_pll4_config, 81 .getter = sun9i_a80_get_pll4_factors, 82 }; 83 84 static DEFINE_SPINLOCK(sun9i_a80_pll4_lock); 85 86 static void __init sun9i_a80_pll4_setup(struct device_node *node) 87 { 88 void __iomem *reg; 89 90 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 91 if (IS_ERR(reg)) { 92 pr_err("Could not get registers for a80-pll4-clk: %s\n", 93 node->name); 94 return; 95 } 96 97 sunxi_factors_register(node, &sun9i_a80_pll4_data, 98 &sun9i_a80_pll4_lock, reg); 99 } 100 CLK_OF_DECLARE(sun9i_a80_pll4, "allwinner,sun9i-a80-pll4-clk", sun9i_a80_pll4_setup); 101 102 103 /** 104 * sun9i_a80_get_gt_factors() - calculates m factor for GT 105 * GT rate is calculated as follows 106 * rate = parent_rate / (m + 1); 107 */ 108 109 static void sun9i_a80_get_gt_factors(struct factors_request *req) 110 { 111 u32 div; 112 113 if (req->parent_rate < req->rate) 114 req->rate = req->parent_rate; 115 116 div = DIV_ROUND_UP(req->parent_rate, req->rate); 117 118 /* maximum divider is 4 */ 119 if (div > 4) 120 div = 4; 121 122 req->rate = req->parent_rate / div; 123 req->m = div; 124 } 125 126 static const struct clk_factors_config sun9i_a80_gt_config = { 127 .mshift = 0, 128 .mwidth = 2, 129 }; 130 131 static const struct factors_data sun9i_a80_gt_data __initconst = { 132 .mux = 24, 133 .muxmask = BIT(1) | BIT(0), 134 .table = &sun9i_a80_gt_config, 135 .getter = sun9i_a80_get_gt_factors, 136 }; 137 138 static DEFINE_SPINLOCK(sun9i_a80_gt_lock); 139 140 static void __init sun9i_a80_gt_setup(struct device_node *node) 141 { 142 void __iomem *reg; 143 struct clk *gt; 144 145 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 146 if (IS_ERR(reg)) { 147 pr_err("Could not get registers for a80-gt-clk: %s\n", 148 node->name); 149 return; 150 } 151 152 gt = sunxi_factors_register(node, &sun9i_a80_gt_data, 153 &sun9i_a80_gt_lock, reg); 154 155 /* The GT bus clock needs to be always enabled */ 156 __clk_get(gt); 157 clk_prepare_enable(gt); 158 } 159 CLK_OF_DECLARE(sun9i_a80_gt, "allwinner,sun9i-a80-gt-clk", sun9i_a80_gt_setup); 160 161 162 /** 163 * sun9i_a80_get_ahb_factors() - calculates p factor for AHB0/1/2 164 * AHB rate is calculated as follows 165 * rate = parent_rate >> p; 166 */ 167 168 static void sun9i_a80_get_ahb_factors(struct factors_request *req) 169 { 170 u32 _p; 171 172 if (req->parent_rate < req->rate) 173 req->rate = req->parent_rate; 174 175 _p = order_base_2(DIV_ROUND_UP(req->parent_rate, req->rate)); 176 177 /* maximum p is 3 */ 178 if (_p > 3) 179 _p = 3; 180 181 req->rate = req->parent_rate >> _p; 182 req->p = _p; 183 } 184 185 static const struct clk_factors_config sun9i_a80_ahb_config = { 186 .pshift = 0, 187 .pwidth = 2, 188 }; 189 190 static const struct factors_data sun9i_a80_ahb_data __initconst = { 191 .mux = 24, 192 .muxmask = BIT(1) | BIT(0), 193 .table = &sun9i_a80_ahb_config, 194 .getter = sun9i_a80_get_ahb_factors, 195 }; 196 197 static DEFINE_SPINLOCK(sun9i_a80_ahb_lock); 198 199 static void __init sun9i_a80_ahb_setup(struct device_node *node) 200 { 201 void __iomem *reg; 202 203 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 204 if (IS_ERR(reg)) { 205 pr_err("Could not get registers for a80-ahb-clk: %s\n", 206 node->name); 207 return; 208 } 209 210 sunxi_factors_register(node, &sun9i_a80_ahb_data, 211 &sun9i_a80_ahb_lock, reg); 212 } 213 CLK_OF_DECLARE(sun9i_a80_ahb, "allwinner,sun9i-a80-ahb-clk", sun9i_a80_ahb_setup); 214 215 216 static const struct factors_data sun9i_a80_apb0_data __initconst = { 217 .mux = 24, 218 .muxmask = BIT(0), 219 .table = &sun9i_a80_ahb_config, 220 .getter = sun9i_a80_get_ahb_factors, 221 }; 222 223 static DEFINE_SPINLOCK(sun9i_a80_apb0_lock); 224 225 static void __init sun9i_a80_apb0_setup(struct device_node *node) 226 { 227 void __iomem *reg; 228 229 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 230 if (IS_ERR(reg)) { 231 pr_err("Could not get registers for a80-apb0-clk: %s\n", 232 node->name); 233 return; 234 } 235 236 sunxi_factors_register(node, &sun9i_a80_apb0_data, 237 &sun9i_a80_apb0_lock, reg); 238 } 239 CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-clk", sun9i_a80_apb0_setup); 240 241 242 /** 243 * sun9i_a80_get_apb1_factors() - calculates m, p factors for APB1 244 * APB1 rate is calculated as follows 245 * rate = (parent_rate >> p) / (m + 1); 246 */ 247 248 static void sun9i_a80_get_apb1_factors(struct factors_request *req) 249 { 250 u32 div; 251 252 if (req->parent_rate < req->rate) 253 req->rate = req->parent_rate; 254 255 div = DIV_ROUND_UP(req->parent_rate, req->rate); 256 257 /* Highest possible divider is 256 (p = 3, m = 31) */ 258 if (div > 256) 259 div = 256; 260 261 req->p = order_base_2(div); 262 req->m = (req->parent_rate >> req->p) - 1; 263 req->rate = (req->parent_rate >> req->p) / (req->m + 1); 264 } 265 266 static const struct clk_factors_config sun9i_a80_apb1_config = { 267 .mshift = 0, 268 .mwidth = 5, 269 .pshift = 16, 270 .pwidth = 2, 271 }; 272 273 static const struct factors_data sun9i_a80_apb1_data __initconst = { 274 .mux = 24, 275 .muxmask = BIT(0), 276 .table = &sun9i_a80_apb1_config, 277 .getter = sun9i_a80_get_apb1_factors, 278 }; 279 280 static DEFINE_SPINLOCK(sun9i_a80_apb1_lock); 281 282 static void __init sun9i_a80_apb1_setup(struct device_node *node) 283 { 284 void __iomem *reg; 285 286 reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 287 if (IS_ERR(reg)) { 288 pr_err("Could not get registers for a80-apb1-clk: %s\n", 289 node->name); 290 return; 291 } 292 293 sunxi_factors_register(node, &sun9i_a80_apb1_data, 294 &sun9i_a80_apb1_lock, reg); 295 } 296 CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-clk", sun9i_a80_apb1_setup); 297