1a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang/* 2a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * rz Core CPG Clocks 3a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * 4a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * Copyright (C) 2013 Ideas On Board SPRL 5a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com> 6a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * 7a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * This program is free software; you can redistribute it and/or modify 8a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * it under the terms of the GNU General Public License as published by 9a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * the Free Software Foundation; version 2 of the License. 10a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang */ 11a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 12a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#include <linux/clk-provider.h> 13a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#include <linux/init.h> 14a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#include <linux/kernel.h> 15a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#include <linux/of.h> 16a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#include <linux/of_address.h> 17a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#include <linux/slab.h> 18a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 19a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sangstruct rz_cpg { 20a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang struct clk_onecell_data data; 21a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang void __iomem *reg; 22a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang}; 23a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 24a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#define CPG_FRQCR 0x10 25a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang#define CPG_FRQCR2 0x14 26a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 27a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang/* ----------------------------------------------------------------------------- 28a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * Initialization 29a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang */ 30a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 31a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sangstatic struct clk * __init 32a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sangrz_cpg_register_clock(struct device_node *np, struct rz_cpg *cpg, const char *name) 33a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang{ 34a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang u32 val; 35a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang unsigned mult; 36a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang static const unsigned frqcr_tab[4] = { 3, 2, 0, 1 }; 37a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 38a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang if (strcmp(name, "pll") == 0) { 39a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang /* FIXME: cpg_mode should be read from GPIO. But no GPIO support yet */ 40a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang unsigned cpg_mode = 0; /* hardcoded to EXTAL for now */ 41a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang const char *parent_name = of_clk_get_parent_name(np, cpg_mode); 42a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 43a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang mult = cpg_mode ? (32 / 4) : 30; 44a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 45a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang return clk_register_fixed_factor(NULL, name, parent_name, 0, mult, 1); 46a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang } 47a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 48a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang /* If mapping regs failed, skip non-pll clocks. System will boot anyhow */ 49a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang if (!cpg->reg) 50a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang return ERR_PTR(-ENXIO); 51a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 52a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang /* FIXME:"i" and "g" are variable clocks with non-integer dividers (e.g. 2/3) 53a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * and the constraint that always g <= i. To get the rz platform started, 54a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang * let them run at fixed current speed and implement the details later. 55a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang */ 56a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang if (strcmp(name, "i") == 0) 57a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang val = (clk_readl(cpg->reg + CPG_FRQCR) >> 8) & 3; 58a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang else if (strcmp(name, "g") == 0) 59a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang val = clk_readl(cpg->reg + CPG_FRQCR2) & 3; 60a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang else 61a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang return ERR_PTR(-EINVAL); 62a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 63a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang mult = frqcr_tab[val]; 64a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang return clk_register_fixed_factor(NULL, name, "pll", 0, mult, 3); 65a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang} 66a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 67a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sangstatic void __init rz_cpg_clocks_init(struct device_node *np) 68a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang{ 69a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang struct rz_cpg *cpg; 70a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang struct clk **clks; 71a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang unsigned i; 72a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang int num_clks; 73a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 74a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang num_clks = of_property_count_strings(np, "clock-output-names"); 75a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang if (WARN(num_clks <= 0, "can't count CPG clocks\n")) 76a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang return; 77a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 78a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); 79a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL); 80a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang BUG_ON(!cpg || !clks); 81a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 82a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang cpg->data.clks = clks; 83a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang cpg->data.clk_num = num_clks; 84a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 85a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang cpg->reg = of_iomap(np, 0); 86a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 87a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang for (i = 0; i < num_clks; ++i) { 88a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang const char *name; 89a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang struct clk *clk; 90a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 91a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang of_property_read_string_index(np, "clock-output-names", i, &name); 92a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 93a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang clk = rz_cpg_register_clock(np, cpg, name); 94a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang if (IS_ERR(clk)) 95a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang pr_err("%s: failed to register %s %s clock (%ld)\n", 96a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang __func__, np->name, name, PTR_ERR(clk)); 97a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang else 98a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang cpg->data.clks[i] = clk; 99a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang } 100a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang 101a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); 102a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram Sang} 103a665962e8f4484647e7a19b4d6329d42ed8bc804Wolfram SangCLK_OF_DECLARE(rz_cpg_clks, "renesas,rz-cpg-clocks", rz_cpg_clocks_init); 104