1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * sh73a0 Core CPG Clocks 4 * 5 * Copyright (C) 2014 Ulrich Hecht 6 */ 7 8 #include <linux/clk-provider.h> 9 #include <linux/clk/renesas.h> 10 #include <linux/init.h> 11 #include <linux/kernel.h> 12 #include <linux/of.h> 13 #include <linux/of_address.h> 14 #include <linux/slab.h> 15 #include <linux/spinlock.h> 16 17 struct sh73a0_cpg { 18 struct clk_onecell_data data; 19 spinlock_t lock; 20 void __iomem *reg; 21 }; 22 23 #define CPG_FRQCRA 0x00 24 #define CPG_FRQCRB 0x04 25 #define CPG_SD0CKCR 0x74 26 #define CPG_SD1CKCR 0x78 27 #define CPG_SD2CKCR 0x7c 28 #define CPG_PLLECR 0xd0 29 #define CPG_PLL0CR 0xd8 30 #define CPG_PLL1CR 0x28 31 #define CPG_PLL2CR 0x2c 32 #define CPG_PLL3CR 0xdc 33 #define CPG_CKSCR 0xc0 34 #define CPG_DSI0PHYCR 0x6c 35 #define CPG_DSI1PHYCR 0x70 36 37 #define CLK_ENABLE_ON_INIT BIT(0) 38 39 struct div4_clk { 40 const char *name; 41 const char *parent; 42 unsigned int reg; 43 unsigned int shift; 44 }; 45 46 static const struct div4_clk div4_clks[] = { 47 { "zg", "pll0", CPG_FRQCRA, 16 }, 48 { "m3", "pll1", CPG_FRQCRA, 12 }, 49 { "b", "pll1", CPG_FRQCRA, 8 }, 50 { "m1", "pll1", CPG_FRQCRA, 4 }, 51 { "m2", "pll1", CPG_FRQCRA, 0 }, 52 { "zx", "pll1", CPG_FRQCRB, 12 }, 53 { "hp", "pll1", CPG_FRQCRB, 4 }, 54 { NULL, NULL, 0, 0 }, 55 }; 56 57 static const struct clk_div_table div4_div_table[] = { 58 { 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 }, 59 { 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 }, 60 { 12, 7 }, { 0, 0 } 61 }; 62 63 static const struct clk_div_table z_div_table[] = { 64 /* ZSEL == 0 */ 65 { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 }, 66 { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 }, 67 { 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 }, 68 /* ZSEL == 1 */ 69 { 16, 2 }, { 17, 3 }, { 18, 4 }, { 19, 6 }, { 20, 8 }, { 21, 12 }, 70 { 22, 16 }, { 24, 24 }, { 27, 48 }, { 0, 0 } 71 }; 72 73 static struct clk * __init 74 sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg, 75 const char *name) 76 { 77 const struct clk_div_table *table = NULL; 78 unsigned int shift, reg, width; 79 const char *parent_name = NULL; 80 unsigned int mult = 1; 81 unsigned int div = 1; 82 83 if (!strcmp(name, "main")) { 84 /* extal1, extal1_div2, extal2, extal2_div2 */ 85 u32 parent_idx = (readl(cpg->reg + CPG_CKSCR) >> 28) & 3; 86 87 parent_name = of_clk_get_parent_name(np, parent_idx >> 1); 88 div = (parent_idx & 1) + 1; 89 } else if (!strncmp(name, "pll", 3)) { 90 void __iomem *enable_reg = cpg->reg; 91 u32 enable_bit = name[3] - '0'; 92 93 parent_name = "main"; 94 switch (enable_bit) { 95 case 0: 96 enable_reg += CPG_PLL0CR; 97 break; 98 case 1: 99 enable_reg += CPG_PLL1CR; 100 break; 101 case 2: 102 enable_reg += CPG_PLL2CR; 103 break; 104 case 3: 105 enable_reg += CPG_PLL3CR; 106 break; 107 default: 108 return ERR_PTR(-EINVAL); 109 } 110 if (readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) { 111 mult = ((readl(enable_reg) >> 24) & 0x3f) + 1; 112 /* handle CFG bit for PLL1 and PLL2 */ 113 if (enable_bit == 1 || enable_bit == 2) 114 if (readl(enable_reg) & BIT(20)) 115 mult *= 2; 116 } 117 } else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) { 118 u32 phy_no = name[3] - '0'; 119 void __iomem *dsi_reg = cpg->reg + 120 (phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR); 121 122 parent_name = phy_no ? "dsi1pck" : "dsi0pck"; 123 mult = __raw_readl(dsi_reg); 124 if (!(mult & 0x8000)) 125 mult = 1; 126 else 127 mult = (mult & 0x3f) + 1; 128 } else if (!strcmp(name, "z")) { 129 parent_name = "pll0"; 130 table = z_div_table; 131 reg = CPG_FRQCRB; 132 shift = 24; 133 width = 5; 134 } else { 135 const struct div4_clk *c; 136 137 for (c = div4_clks; c->name; c++) { 138 if (!strcmp(name, c->name)) { 139 parent_name = c->parent; 140 table = div4_div_table; 141 reg = c->reg; 142 shift = c->shift; 143 width = 4; 144 break; 145 } 146 } 147 if (!c->name) 148 return ERR_PTR(-EINVAL); 149 } 150 151 if (!table) { 152 return clk_register_fixed_factor(NULL, name, parent_name, 0, 153 mult, div); 154 } else { 155 return clk_register_divider_table(NULL, name, parent_name, 0, 156 cpg->reg + reg, shift, width, 0, 157 table, &cpg->lock); 158 } 159 } 160 161 static void __init sh73a0_cpg_clocks_init(struct device_node *np) 162 { 163 struct sh73a0_cpg *cpg; 164 struct clk **clks; 165 unsigned int i; 166 int num_clks; 167 168 num_clks = of_property_count_strings(np, "clock-output-names"); 169 if (num_clks < 0) { 170 pr_err("%s: failed to count clocks\n", __func__); 171 return; 172 } 173 174 cpg = kzalloc(sizeof(*cpg), GFP_KERNEL); 175 clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL); 176 if (cpg == NULL || clks == NULL) { 177 /* We're leaking memory on purpose, there's no point in cleaning 178 * up as the system won't boot anyway. 179 */ 180 return; 181 } 182 183 spin_lock_init(&cpg->lock); 184 185 cpg->data.clks = clks; 186 cpg->data.clk_num = num_clks; 187 188 cpg->reg = of_iomap(np, 0); 189 if (WARN_ON(cpg->reg == NULL)) 190 return; 191 192 /* Set SDHI clocks to a known state */ 193 writel(0x108, cpg->reg + CPG_SD0CKCR); 194 writel(0x108, cpg->reg + CPG_SD1CKCR); 195 writel(0x108, cpg->reg + CPG_SD2CKCR); 196 197 for (i = 0; i < num_clks; ++i) { 198 const char *name; 199 struct clk *clk; 200 201 of_property_read_string_index(np, "clock-output-names", i, 202 &name); 203 204 clk = sh73a0_cpg_register_clock(np, cpg, name); 205 if (IS_ERR(clk)) 206 pr_err("%s: failed to register %pOFn %s clock (%ld)\n", 207 __func__, np, name, PTR_ERR(clk)); 208 else 209 cpg->data.clks[i] = clk; 210 } 211 212 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); 213 } 214 CLK_OF_DECLARE(sh73a0_cpg_clks, "renesas,sh73a0-cpg-clocks", 215 sh73a0_cpg_clocks_init); 216