132351a28SPaul Mundt /* 232351a28SPaul Mundt * arch/sh/kernel/cpu/sh4a/clock-sh7785.c 332351a28SPaul Mundt * 432351a28SPaul Mundt * SH7785 support for the clock framework 532351a28SPaul Mundt * 6a77b5ac0SPaul Mundt * Copyright (C) 2007 - 2009 Paul Mundt 732351a28SPaul Mundt * 832351a28SPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 932351a28SPaul Mundt * License. See the file "COPYING" in the main directory of this archive 1032351a28SPaul Mundt * for more details. 1132351a28SPaul Mundt */ 1232351a28SPaul Mundt #include <linux/init.h> 1332351a28SPaul Mundt #include <linux/kernel.h> 14a77b5ac0SPaul Mundt #include <linux/clk.h> 15a77b5ac0SPaul Mundt #include <linux/io.h> 16cc96eaceSPaul Mundt #include <linux/cpufreq.h> 1732351a28SPaul Mundt #include <asm/clock.h> 1832351a28SPaul Mundt #include <asm/freq.h> 1932351a28SPaul Mundt 20a77b5ac0SPaul Mundt static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18, 21a77b5ac0SPaul Mundt 24, 32, 36, 48 }; 22a77b5ac0SPaul Mundt struct clk_priv { 23a77b5ac0SPaul Mundt unsigned int shift; 24cc96eaceSPaul Mundt 25cc96eaceSPaul Mundt /* allowable divisor bitmap */ 26cc96eaceSPaul Mundt unsigned long div_bitmap; 27cc96eaceSPaul Mundt 28cc96eaceSPaul Mundt /* Supportable frequencies + termination entry */ 29cc96eaceSPaul Mundt struct cpufreq_frequency_table freq_table[ARRAY_SIZE(div2)+1]; 30a77b5ac0SPaul Mundt }; 3132351a28SPaul Mundt 32cc96eaceSPaul Mundt #define FRQMR_CLK_DATA(_name, _shift, _div_bitmap) \ 33cc96eaceSPaul Mundt static struct clk_priv _name##_data = { \ 34cc96eaceSPaul Mundt .shift = _shift, \ 35cc96eaceSPaul Mundt .div_bitmap = _div_bitmap, \ 36cc96eaceSPaul Mundt \ 37cc96eaceSPaul Mundt .freq_table[0] = { \ 38cc96eaceSPaul Mundt .index = 0, \ 39cc96eaceSPaul Mundt .frequency = CPUFREQ_TABLE_END, \ 40cc96eaceSPaul Mundt }, \ 41cc96eaceSPaul Mundt } 42a77b5ac0SPaul Mundt 43cc96eaceSPaul Mundt FRQMR_CLK_DATA(pfc, 0, 0x0f80); 44cc96eaceSPaul Mundt FRQMR_CLK_DATA(s3fc, 4, 0x0ff0); 45cc96eaceSPaul Mundt FRQMR_CLK_DATA(s2fc, 8, 0x0030); 46cc96eaceSPaul Mundt FRQMR_CLK_DATA(mfc, 12, 0x000c); 47cc96eaceSPaul Mundt FRQMR_CLK_DATA(bfc, 16, 0x0fe0); 48cc96eaceSPaul Mundt FRQMR_CLK_DATA(sfc, 20, 0x000c); 49cc96eaceSPaul Mundt FRQMR_CLK_DATA(ufc, 24, 0x000c); 50cc96eaceSPaul Mundt FRQMR_CLK_DATA(ifc, 28, 0x000e); 51a77b5ac0SPaul Mundt 52cc96eaceSPaul Mundt static unsigned long frqmr_recalc(struct clk *clk) 5332351a28SPaul Mundt { 54a77b5ac0SPaul Mundt struct clk_priv *data = clk->priv; 55a77b5ac0SPaul Mundt unsigned int idx; 56a77b5ac0SPaul Mundt 57a77b5ac0SPaul Mundt idx = (__raw_readl(FRQMR1) >> data->shift) & 0x000f; 58a77b5ac0SPaul Mundt 59*c9904dd1SMagnus Damm return clk->parent->rate / div2[idx]; 6032351a28SPaul Mundt } 6132351a28SPaul Mundt 62cc96eaceSPaul Mundt static void frqmr_build_rate_table(struct clk *clk) 63cc96eaceSPaul Mundt { 64cc96eaceSPaul Mundt struct clk_priv *data = clk->priv; 65cc96eaceSPaul Mundt int i, entry; 66cc96eaceSPaul Mundt 67cc96eaceSPaul Mundt for (i = entry = 0; i < ARRAY_SIZE(div2); i++) { 68cc96eaceSPaul Mundt if ((data->div_bitmap & (1 << i)) == 0) 69cc96eaceSPaul Mundt continue; 70cc96eaceSPaul Mundt 71cc96eaceSPaul Mundt data->freq_table[entry].index = entry; 72cc96eaceSPaul Mundt data->freq_table[entry].frequency = 73*c9904dd1SMagnus Damm clk->parent->rate / div2[i]; 74cc96eaceSPaul Mundt 75cc96eaceSPaul Mundt entry++; 76cc96eaceSPaul Mundt } 77cc96eaceSPaul Mundt 78cc96eaceSPaul Mundt if (entry == 0) { 79cc96eaceSPaul Mundt pr_warning("clkfwk: failed to build frequency table " 80cc96eaceSPaul Mundt "for \"%s\" clk!\n", clk->name); 81cc96eaceSPaul Mundt return; 82cc96eaceSPaul Mundt } 83cc96eaceSPaul Mundt 84cc96eaceSPaul Mundt /* Termination entry */ 85cc96eaceSPaul Mundt data->freq_table[entry].index = entry; 86cc96eaceSPaul Mundt data->freq_table[entry].frequency = CPUFREQ_TABLE_END; 87cc96eaceSPaul Mundt } 88cc96eaceSPaul Mundt 89cc96eaceSPaul Mundt static long frqmr_round_rate(struct clk *clk, unsigned long rate) 90cc96eaceSPaul Mundt { 91cc96eaceSPaul Mundt struct clk_priv *data = clk->priv; 92cc96eaceSPaul Mundt unsigned long rate_error, rate_error_prev = ~0UL; 93cc96eaceSPaul Mundt unsigned long rate_best_fit = rate; 94cc96eaceSPaul Mundt unsigned long highest, lowest; 95cc96eaceSPaul Mundt int i; 96cc96eaceSPaul Mundt 97cc96eaceSPaul Mundt highest = lowest = 0; 98cc96eaceSPaul Mundt 99cc96eaceSPaul Mundt for (i = 0; data->freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { 100cc96eaceSPaul Mundt unsigned long freq = data->freq_table[i].frequency; 101cc96eaceSPaul Mundt 102cc96eaceSPaul Mundt if (freq == CPUFREQ_ENTRY_INVALID) 103cc96eaceSPaul Mundt continue; 104cc96eaceSPaul Mundt 105cc96eaceSPaul Mundt if (freq > highest) 106cc96eaceSPaul Mundt highest = freq; 107cc96eaceSPaul Mundt if (freq < lowest) 108cc96eaceSPaul Mundt lowest = freq; 109cc96eaceSPaul Mundt 110cc96eaceSPaul Mundt rate_error = abs(freq - rate); 111cc96eaceSPaul Mundt if (rate_error < rate_error_prev) { 112cc96eaceSPaul Mundt rate_best_fit = freq; 113cc96eaceSPaul Mundt rate_error_prev = rate_error; 114cc96eaceSPaul Mundt } 115cc96eaceSPaul Mundt 116cc96eaceSPaul Mundt if (rate_error == 0) 117cc96eaceSPaul Mundt break; 118cc96eaceSPaul Mundt } 119cc96eaceSPaul Mundt 120cc96eaceSPaul Mundt if (rate >= highest) 121cc96eaceSPaul Mundt rate_best_fit = highest; 122cc96eaceSPaul Mundt if (rate <= lowest) 123cc96eaceSPaul Mundt rate_best_fit = lowest; 124cc96eaceSPaul Mundt 125cc96eaceSPaul Mundt return rate_best_fit; 126cc96eaceSPaul Mundt } 127cc96eaceSPaul Mundt 128a77b5ac0SPaul Mundt static struct clk_ops frqmr_clk_ops = { 129cc96eaceSPaul Mundt .recalc = frqmr_recalc, 130cc96eaceSPaul Mundt .build_rate_table = frqmr_build_rate_table, 131cc96eaceSPaul Mundt .round_rate = frqmr_round_rate, 13232351a28SPaul Mundt }; 13332351a28SPaul Mundt 134*c9904dd1SMagnus Damm static unsigned long pll_recalc(struct clk *clk) 135*c9904dd1SMagnus Damm { 136*c9904dd1SMagnus Damm /* 137*c9904dd1SMagnus Damm * XXX: PLL1 multiplier is locked for the default clock mode, 138*c9904dd1SMagnus Damm * when mode pin detection and configuration support is added, 139*c9904dd1SMagnus Damm * select the multiplier dynamically. 140*c9904dd1SMagnus Damm */ 141*c9904dd1SMagnus Damm return clk->parent->rate * 36; 142*c9904dd1SMagnus Damm } 143*c9904dd1SMagnus Damm 144*c9904dd1SMagnus Damm static struct clk_ops pll_clk_ops = { 145*c9904dd1SMagnus Damm .recalc = pll_recalc, 146*c9904dd1SMagnus Damm }; 147*c9904dd1SMagnus Damm 14832351a28SPaul Mundt /* 149a77b5ac0SPaul Mundt * Default rate for the root input clock, reset this with clk_set_rate() 150a77b5ac0SPaul Mundt * from the platform code. 15132351a28SPaul Mundt */ 152a77b5ac0SPaul Mundt static struct clk extal_clk = { 153a77b5ac0SPaul Mundt .name = "extal", 154a77b5ac0SPaul Mundt .id = -1, 155a77b5ac0SPaul Mundt .rate = 33333333, 156a77b5ac0SPaul Mundt }; 157a77b5ac0SPaul Mundt 158*c9904dd1SMagnus Damm static struct clk pll_clk = { 159*c9904dd1SMagnus Damm .name = "pll_clk", 160*c9904dd1SMagnus Damm .id = -1, 161*c9904dd1SMagnus Damm .ops = &pll_clk_ops, 162*c9904dd1SMagnus Damm .parent = &extal_clk, 163*c9904dd1SMagnus Damm .flags = CLK_ENABLE_ON_INIT, 164*c9904dd1SMagnus Damm }; 165*c9904dd1SMagnus Damm 166a77b5ac0SPaul Mundt static struct clk cpu_clk = { 167a77b5ac0SPaul Mundt .name = "cpu_clk", /* Ick */ 168a77b5ac0SPaul Mundt .id = -1, 169a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 170*c9904dd1SMagnus Damm .parent = &pll_clk, 171a77b5ac0SPaul Mundt .flags = CLK_ENABLE_ON_INIT, 172a77b5ac0SPaul Mundt .priv = &ifc_data, 173a77b5ac0SPaul Mundt }; 174a77b5ac0SPaul Mundt 175a77b5ac0SPaul Mundt static struct clk shyway_clk = { 176a77b5ac0SPaul Mundt .name = "shyway_clk", /* SHck */ 177a77b5ac0SPaul Mundt .id = -1, 178a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 179*c9904dd1SMagnus Damm .parent = &pll_clk, 180a77b5ac0SPaul Mundt .flags = CLK_ENABLE_ON_INIT, 181a77b5ac0SPaul Mundt .priv = &sfc_data, 182a77b5ac0SPaul Mundt }; 183a77b5ac0SPaul Mundt 184a77b5ac0SPaul Mundt static struct clk peripheral_clk = { 185a77b5ac0SPaul Mundt .name = "peripheral_clk", /* Pck */ 186a77b5ac0SPaul Mundt .id = -1, 187a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 188*c9904dd1SMagnus Damm .parent = &pll_clk, 189a77b5ac0SPaul Mundt .flags = CLK_ENABLE_ON_INIT, 190a77b5ac0SPaul Mundt .priv = &pfc_data, 191a77b5ac0SPaul Mundt }; 192a77b5ac0SPaul Mundt 193a77b5ac0SPaul Mundt static struct clk ddr_clk = { 194a77b5ac0SPaul Mundt .name = "ddr_clk", /* DDRck */ 195a77b5ac0SPaul Mundt .id = -1, 196a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 197*c9904dd1SMagnus Damm .parent = &pll_clk, 198a77b5ac0SPaul Mundt .flags = CLK_ENABLE_ON_INIT, 199a77b5ac0SPaul Mundt .priv = &mfc_data, 200a77b5ac0SPaul Mundt }; 201a77b5ac0SPaul Mundt 202a77b5ac0SPaul Mundt static struct clk bus_clk = { 203a77b5ac0SPaul Mundt .name = "bus_clk", /* Bck */ 204a77b5ac0SPaul Mundt .id = -1, 205a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 206*c9904dd1SMagnus Damm .parent = &pll_clk, 207a77b5ac0SPaul Mundt .flags = CLK_ENABLE_ON_INIT, 208a77b5ac0SPaul Mundt .priv = &bfc_data, 209a77b5ac0SPaul Mundt }; 210a77b5ac0SPaul Mundt 211a77b5ac0SPaul Mundt static struct clk ga_clk = { 212a77b5ac0SPaul Mundt .name = "ga_clk", /* GAck */ 213a77b5ac0SPaul Mundt .id = -1, 214a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 215*c9904dd1SMagnus Damm .parent = &pll_clk, 216a77b5ac0SPaul Mundt .priv = &s2fc_data, 217a77b5ac0SPaul Mundt }; 218a77b5ac0SPaul Mundt 219a77b5ac0SPaul Mundt static struct clk du_clk = { 220a77b5ac0SPaul Mundt .name = "du_clk", /* DUck */ 221a77b5ac0SPaul Mundt .id = -1, 222a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 223*c9904dd1SMagnus Damm .parent = &pll_clk, 224a77b5ac0SPaul Mundt .priv = &s3fc_data, 225a77b5ac0SPaul Mundt }; 226a77b5ac0SPaul Mundt 227a77b5ac0SPaul Mundt static struct clk umem_clk = { 228a77b5ac0SPaul Mundt .name = "umem_clk", /* uck */ 229a77b5ac0SPaul Mundt .id = -1, 230a77b5ac0SPaul Mundt .ops = &frqmr_clk_ops, 231*c9904dd1SMagnus Damm .parent = &pll_clk, 232a77b5ac0SPaul Mundt .flags = CLK_ENABLE_ON_INIT, 233a77b5ac0SPaul Mundt .priv = &ufc_data, 234a77b5ac0SPaul Mundt }; 235a77b5ac0SPaul Mundt 236a77b5ac0SPaul Mundt static struct clk *clks[] = { 237a77b5ac0SPaul Mundt &extal_clk, 238*c9904dd1SMagnus Damm &pll_clk, 239a77b5ac0SPaul Mundt &cpu_clk, 240a77b5ac0SPaul Mundt ­way_clk, 241a77b5ac0SPaul Mundt &peripheral_clk, 242a77b5ac0SPaul Mundt &ddr_clk, 243a77b5ac0SPaul Mundt &bus_clk, 244a77b5ac0SPaul Mundt &ga_clk, 245a77b5ac0SPaul Mundt &du_clk, 246a77b5ac0SPaul Mundt &umem_clk, 24732351a28SPaul Mundt }; 24832351a28SPaul Mundt 249549b5e35SPaul Mundt static int mstpcr_clk_enable(struct clk *clk) 250549b5e35SPaul Mundt { 251549b5e35SPaul Mundt __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), 252549b5e35SPaul Mundt clk->enable_reg); 253549b5e35SPaul Mundt return 0; 254549b5e35SPaul Mundt } 255549b5e35SPaul Mundt 256549b5e35SPaul Mundt static void mstpcr_clk_disable(struct clk *clk) 257549b5e35SPaul Mundt { 258549b5e35SPaul Mundt __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), 259549b5e35SPaul Mundt clk->enable_reg); 260549b5e35SPaul Mundt } 261549b5e35SPaul Mundt 262549b5e35SPaul Mundt static struct clk_ops mstpcr_clk_ops = { 263549b5e35SPaul Mundt .enable = mstpcr_clk_enable, 264549b5e35SPaul Mundt .disable = mstpcr_clk_disable, 265549b5e35SPaul Mundt .recalc = followparent_recalc, 266549b5e35SPaul Mundt }; 267549b5e35SPaul Mundt 268549b5e35SPaul Mundt #define MSTPCR0 0xffc80030 269549b5e35SPaul Mundt #define MSTPCR1 0xffc80034 270549b5e35SPaul Mundt 271549b5e35SPaul Mundt #define CLK(_name, _id, _parent, _enable_reg, \ 272549b5e35SPaul Mundt _enable_bit, _flags) \ 273549b5e35SPaul Mundt { \ 274549b5e35SPaul Mundt .name = _name, \ 275549b5e35SPaul Mundt .id = _id, \ 276549b5e35SPaul Mundt .parent = _parent, \ 277549b5e35SPaul Mundt .enable_reg = (void __iomem *)_enable_reg, \ 278549b5e35SPaul Mundt .enable_bit = _enable_bit, \ 279549b5e35SPaul Mundt .flags = _flags, \ 280549b5e35SPaul Mundt .ops = &mstpcr_clk_ops, \ 281549b5e35SPaul Mundt } 282549b5e35SPaul Mundt 283549b5e35SPaul Mundt static struct clk mstpcr_clks[] = { 284549b5e35SPaul Mundt /* MSTPCR0 */ 285549b5e35SPaul Mundt CLK("scif_fck", 5, &peripheral_clk, MSTPCR0, 29, 0), 286549b5e35SPaul Mundt CLK("scif_fck", 4, &peripheral_clk, MSTPCR0, 28, 0), 287549b5e35SPaul Mundt CLK("scif_fck", 3, &peripheral_clk, MSTPCR0, 27, 0), 288549b5e35SPaul Mundt CLK("scif_fck", 2, &peripheral_clk, MSTPCR0, 26, 0), 289549b5e35SPaul Mundt CLK("scif_fck", 1, &peripheral_clk, MSTPCR0, 25, 0), 290549b5e35SPaul Mundt CLK("scif_fck", 0, &peripheral_clk, MSTPCR0, 24, 0), 291549b5e35SPaul Mundt CLK("ssi_fck", 1, &peripheral_clk, MSTPCR0, 21, 0), 292549b5e35SPaul Mundt CLK("ssi_fck", 0, &peripheral_clk, MSTPCR0, 20, 0), 293549b5e35SPaul Mundt CLK("hac_fck", 1, &peripheral_clk, MSTPCR0, 17, 0), 294549b5e35SPaul Mundt CLK("hac_fck", 0, &peripheral_clk, MSTPCR0, 16, 0), 295549b5e35SPaul Mundt CLK("mmcif_fck", -1, &peripheral_clk, MSTPCR0, 13, 0), 296549b5e35SPaul Mundt CLK("flctl_fck", -1, &peripheral_clk, MSTPCR0, 12, 0), 297549b5e35SPaul Mundt CLK("tmu345_fck", -1, &peripheral_clk, MSTPCR0, 9, 0), 298549b5e35SPaul Mundt CLK("tmu012_fck", -1, &peripheral_clk, MSTPCR0, 8, 0), 299549b5e35SPaul Mundt CLK("siof_fck", -1, &peripheral_clk, MSTPCR0, 3, 0), 300549b5e35SPaul Mundt CLK("hspi_fck", -1, &peripheral_clk, MSTPCR0, 2, 0), 301549b5e35SPaul Mundt 302549b5e35SPaul Mundt /* MSTPCR1 */ 303549b5e35SPaul Mundt CLK("hudi_fck", -1, NULL, MSTPCR1, 19, 0), 304549b5e35SPaul Mundt CLK("ubc_fck", -1, NULL, MSTPCR1, 17, 0), 305549b5e35SPaul Mundt CLK("dmac_11_6_fck", -1, NULL, MSTPCR1, 5, 0), 306549b5e35SPaul Mundt CLK("dmac_5_0_fck", -1, NULL, MSTPCR1, 4, 0), 307549b5e35SPaul Mundt CLK("gdta_fck", -1, NULL, MSTPCR1, 0, 0), 308549b5e35SPaul Mundt }; 309549b5e35SPaul Mundt 3109fe5ee0eSPaul Mundt int __init arch_clk_init(void) 31132351a28SPaul Mundt { 312f5c84cf5SPaul Mundt int i, ret = 0; 31332351a28SPaul Mundt 314a77b5ac0SPaul Mundt for (i = 0; i < ARRAY_SIZE(clks); i++) 315a77b5ac0SPaul Mundt ret |= clk_register(clks[i]); 316549b5e35SPaul Mundt for (i = 0; i < ARRAY_SIZE(mstpcr_clks); i++) 317549b5e35SPaul Mundt ret |= clk_register(&mstpcr_clks[i]); 31832351a28SPaul Mundt 319f5c84cf5SPaul Mundt return ret; 32032351a28SPaul Mundt } 321