1 /* 2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 */ 10 11 #include <linux/clk-provider.h> 12 #include <linux/clkdev.h> 13 #include <linux/clk/at91_pmc.h> 14 #include <linux/of.h> 15 #include <linux/of_address.h> 16 #include <linux/io.h> 17 18 #include "pmc.h" 19 20 #define PERIPHERAL_MAX 64 21 22 #define PERIPHERAL_AT91RM9200 0 23 #define PERIPHERAL_AT91SAM9X5 1 24 25 #define PERIPHERAL_ID_MIN 2 26 #define PERIPHERAL_ID_MAX 31 27 #define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX)) 28 29 #define PERIPHERAL_RSHIFT_MASK 0x3 30 #define PERIPHERAL_RSHIFT(val) (((val) >> 16) & PERIPHERAL_RSHIFT_MASK) 31 32 #define PERIPHERAL_MAX_SHIFT 3 33 34 struct clk_peripheral { 35 struct clk_hw hw; 36 struct at91_pmc *pmc; 37 u32 id; 38 }; 39 40 #define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw) 41 42 struct clk_sam9x5_peripheral { 43 struct clk_hw hw; 44 struct at91_pmc *pmc; 45 struct clk_range range; 46 u32 id; 47 u32 div; 48 bool auto_div; 49 }; 50 51 #define to_clk_sam9x5_peripheral(hw) \ 52 container_of(hw, struct clk_sam9x5_peripheral, hw) 53 54 static int clk_peripheral_enable(struct clk_hw *hw) 55 { 56 struct clk_peripheral *periph = to_clk_peripheral(hw); 57 struct at91_pmc *pmc = periph->pmc; 58 int offset = AT91_PMC_PCER; 59 u32 id = periph->id; 60 61 if (id < PERIPHERAL_ID_MIN) 62 return 0; 63 if (id > PERIPHERAL_ID_MAX) 64 offset = AT91_PMC_PCER1; 65 pmc_write(pmc, offset, PERIPHERAL_MASK(id)); 66 return 0; 67 } 68 69 static void clk_peripheral_disable(struct clk_hw *hw) 70 { 71 struct clk_peripheral *periph = to_clk_peripheral(hw); 72 struct at91_pmc *pmc = periph->pmc; 73 int offset = AT91_PMC_PCDR; 74 u32 id = periph->id; 75 76 if (id < PERIPHERAL_ID_MIN) 77 return; 78 if (id > PERIPHERAL_ID_MAX) 79 offset = AT91_PMC_PCDR1; 80 pmc_write(pmc, offset, PERIPHERAL_MASK(id)); 81 } 82 83 static int clk_peripheral_is_enabled(struct clk_hw *hw) 84 { 85 struct clk_peripheral *periph = to_clk_peripheral(hw); 86 struct at91_pmc *pmc = periph->pmc; 87 int offset = AT91_PMC_PCSR; 88 u32 id = periph->id; 89 90 if (id < PERIPHERAL_ID_MIN) 91 return 1; 92 if (id > PERIPHERAL_ID_MAX) 93 offset = AT91_PMC_PCSR1; 94 return !!(pmc_read(pmc, offset) & PERIPHERAL_MASK(id)); 95 } 96 97 static const struct clk_ops peripheral_ops = { 98 .enable = clk_peripheral_enable, 99 .disable = clk_peripheral_disable, 100 .is_enabled = clk_peripheral_is_enabled, 101 }; 102 103 static struct clk * __init 104 at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name, 105 const char *parent_name, u32 id) 106 { 107 struct clk_peripheral *periph; 108 struct clk *clk = NULL; 109 struct clk_init_data init; 110 111 if (!pmc || !name || !parent_name || id > PERIPHERAL_ID_MAX) 112 return ERR_PTR(-EINVAL); 113 114 periph = kzalloc(sizeof(*periph), GFP_KERNEL); 115 if (!periph) 116 return ERR_PTR(-ENOMEM); 117 118 init.name = name; 119 init.ops = &peripheral_ops; 120 init.parent_names = (parent_name ? &parent_name : NULL); 121 init.num_parents = (parent_name ? 1 : 0); 122 init.flags = 0; 123 124 periph->id = id; 125 periph->hw.init = &init; 126 periph->pmc = pmc; 127 128 clk = clk_register(NULL, &periph->hw); 129 if (IS_ERR(clk)) 130 kfree(periph); 131 132 return clk; 133 } 134 135 static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph) 136 { 137 struct clk_hw *parent; 138 unsigned long parent_rate; 139 int shift = 0; 140 141 if (!periph->auto_div) 142 return; 143 144 if (periph->range.max) { 145 parent = clk_hw_get_parent_by_index(&periph->hw, 0); 146 parent_rate = clk_hw_get_rate(parent); 147 if (!parent_rate) 148 return; 149 150 for (; shift < PERIPHERAL_MAX_SHIFT; shift++) { 151 if (parent_rate >> shift <= periph->range.max) 152 break; 153 } 154 } 155 156 periph->auto_div = false; 157 periph->div = shift; 158 } 159 160 static int clk_sam9x5_peripheral_enable(struct clk_hw *hw) 161 { 162 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); 163 struct at91_pmc *pmc = periph->pmc; 164 165 if (periph->id < PERIPHERAL_ID_MIN) 166 return 0; 167 168 pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) | 169 AT91_PMC_PCR_CMD | 170 AT91_PMC_PCR_DIV(periph->div) | 171 AT91_PMC_PCR_EN); 172 return 0; 173 } 174 175 static void clk_sam9x5_peripheral_disable(struct clk_hw *hw) 176 { 177 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); 178 struct at91_pmc *pmc = periph->pmc; 179 180 if (periph->id < PERIPHERAL_ID_MIN) 181 return; 182 183 pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) | 184 AT91_PMC_PCR_CMD); 185 } 186 187 static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw) 188 { 189 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); 190 struct at91_pmc *pmc = periph->pmc; 191 int ret; 192 193 if (periph->id < PERIPHERAL_ID_MIN) 194 return 1; 195 196 pmc_lock(pmc); 197 pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID)); 198 ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN); 199 pmc_unlock(pmc); 200 201 return ret; 202 } 203 204 static unsigned long 205 clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw, 206 unsigned long parent_rate) 207 { 208 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); 209 struct at91_pmc *pmc = periph->pmc; 210 u32 tmp; 211 212 if (periph->id < PERIPHERAL_ID_MIN) 213 return parent_rate; 214 215 pmc_lock(pmc); 216 pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID)); 217 tmp = pmc_read(pmc, AT91_PMC_PCR); 218 pmc_unlock(pmc); 219 220 if (tmp & AT91_PMC_PCR_EN) { 221 periph->div = PERIPHERAL_RSHIFT(tmp); 222 periph->auto_div = false; 223 } else { 224 clk_sam9x5_peripheral_autodiv(periph); 225 } 226 227 return parent_rate >> periph->div; 228 } 229 230 static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw, 231 unsigned long rate, 232 unsigned long *parent_rate) 233 { 234 int shift = 0; 235 unsigned long best_rate; 236 unsigned long best_diff; 237 unsigned long cur_rate = *parent_rate; 238 unsigned long cur_diff; 239 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); 240 241 if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) 242 return *parent_rate; 243 244 if (periph->range.max) { 245 for (; shift <= PERIPHERAL_MAX_SHIFT; shift++) { 246 cur_rate = *parent_rate >> shift; 247 if (cur_rate <= periph->range.max) 248 break; 249 } 250 } 251 252 if (rate >= cur_rate) 253 return cur_rate; 254 255 best_diff = cur_rate - rate; 256 best_rate = cur_rate; 257 for (; shift <= PERIPHERAL_MAX_SHIFT; shift++) { 258 cur_rate = *parent_rate >> shift; 259 if (cur_rate < rate) 260 cur_diff = rate - cur_rate; 261 else 262 cur_diff = cur_rate - rate; 263 264 if (cur_diff < best_diff) { 265 best_diff = cur_diff; 266 best_rate = cur_rate; 267 } 268 269 if (!best_diff || cur_rate < rate) 270 break; 271 } 272 273 return best_rate; 274 } 275 276 static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw, 277 unsigned long rate, 278 unsigned long parent_rate) 279 { 280 int shift; 281 struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw); 282 if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) { 283 if (parent_rate == rate) 284 return 0; 285 else 286 return -EINVAL; 287 } 288 289 if (periph->range.max && rate > periph->range.max) 290 return -EINVAL; 291 292 for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) { 293 if (parent_rate >> shift == rate) { 294 periph->auto_div = false; 295 periph->div = shift; 296 return 0; 297 } 298 } 299 300 return -EINVAL; 301 } 302 303 static const struct clk_ops sam9x5_peripheral_ops = { 304 .enable = clk_sam9x5_peripheral_enable, 305 .disable = clk_sam9x5_peripheral_disable, 306 .is_enabled = clk_sam9x5_peripheral_is_enabled, 307 .recalc_rate = clk_sam9x5_peripheral_recalc_rate, 308 .round_rate = clk_sam9x5_peripheral_round_rate, 309 .set_rate = clk_sam9x5_peripheral_set_rate, 310 }; 311 312 static struct clk * __init 313 at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name, 314 const char *parent_name, u32 id, 315 const struct clk_range *range) 316 { 317 struct clk_sam9x5_peripheral *periph; 318 struct clk *clk = NULL; 319 struct clk_init_data init; 320 321 if (!pmc || !name || !parent_name) 322 return ERR_PTR(-EINVAL); 323 324 periph = kzalloc(sizeof(*periph), GFP_KERNEL); 325 if (!periph) 326 return ERR_PTR(-ENOMEM); 327 328 init.name = name; 329 init.ops = &sam9x5_peripheral_ops; 330 init.parent_names = (parent_name ? &parent_name : NULL); 331 init.num_parents = (parent_name ? 1 : 0); 332 init.flags = 0; 333 334 periph->id = id; 335 periph->hw.init = &init; 336 periph->div = 0; 337 periph->pmc = pmc; 338 periph->auto_div = true; 339 periph->range = *range; 340 341 clk = clk_register(NULL, &periph->hw); 342 if (IS_ERR(clk)) 343 kfree(periph); 344 else 345 clk_sam9x5_peripheral_autodiv(periph); 346 347 return clk; 348 } 349 350 static void __init 351 of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type) 352 { 353 int num; 354 u32 id; 355 struct clk *clk; 356 const char *parent_name; 357 const char *name; 358 struct device_node *periphclknp; 359 360 parent_name = of_clk_get_parent_name(np, 0); 361 if (!parent_name) 362 return; 363 364 num = of_get_child_count(np); 365 if (!num || num > PERIPHERAL_MAX) 366 return; 367 368 for_each_child_of_node(np, periphclknp) { 369 if (of_property_read_u32(periphclknp, "reg", &id)) 370 continue; 371 372 if (id >= PERIPHERAL_MAX) 373 continue; 374 375 if (of_property_read_string(np, "clock-output-names", &name)) 376 name = periphclknp->name; 377 378 if (type == PERIPHERAL_AT91RM9200) { 379 clk = at91_clk_register_peripheral(pmc, name, 380 parent_name, id); 381 } else { 382 struct clk_range range = CLK_RANGE(0, 0); 383 384 of_at91_get_clk_range(periphclknp, 385 "atmel,clk-output-range", 386 &range); 387 388 clk = at91_clk_register_sam9x5_peripheral(pmc, name, 389 parent_name, 390 id, &range); 391 } 392 393 if (IS_ERR(clk)) 394 continue; 395 396 of_clk_add_provider(periphclknp, of_clk_src_simple_get, clk); 397 } 398 } 399 400 void __init of_at91rm9200_clk_periph_setup(struct device_node *np, 401 struct at91_pmc *pmc) 402 { 403 of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91RM9200); 404 } 405 406 void __init of_at91sam9x5_clk_periph_setup(struct device_node *np, 407 struct at91_pmc *pmc) 408 { 409 of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91SAM9X5); 410 } 411