18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * arch/sh/kernel/cpu/sh2a/clock-sh7203.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * SH7203 support for the clock framework 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2007 Kieran Bingham (MPC-Data Ltd) 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Based on clock-sh7263.c 108c2ecf20Sopenharmony_ci * Copyright (C) 2006 Yoshinori Sato 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Based on clock-sh4.c 138c2ecf20Sopenharmony_ci * Copyright (C) 2005 Paul Mundt 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci#include <linux/init.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <asm/clock.h> 188c2ecf20Sopenharmony_ci#include <asm/freq.h> 198c2ecf20Sopenharmony_ci#include <asm/io.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic const int pll1rate[]={8,12,16,0}; 228c2ecf20Sopenharmony_cistatic const int pfc_divisors[]={1,2,3,4,6,8,12}; 238c2ecf20Sopenharmony_ci#define ifc_divisors pfc_divisors 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic unsigned int pll2_mult; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic void master_clk_init(struct clk *clk) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * pll2_mult; 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic struct sh_clk_ops sh7203_master_clk_ops = { 338c2ecf20Sopenharmony_ci .init = master_clk_init, 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic unsigned long module_clk_recalc(struct clk *clk) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci int idx = (__raw_readw(FREQCR) & 0x0007); 398c2ecf20Sopenharmony_ci return clk->parent->rate / pfc_divisors[idx]; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic struct sh_clk_ops sh7203_module_clk_ops = { 438c2ecf20Sopenharmony_ci .recalc = module_clk_recalc, 448c2ecf20Sopenharmony_ci}; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic unsigned long bus_clk_recalc(struct clk *clk) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci int idx = (__raw_readw(FREQCR) & 0x0007); 498c2ecf20Sopenharmony_ci return clk->parent->rate / pfc_divisors[idx-2]; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic struct sh_clk_ops sh7203_bus_clk_ops = { 538c2ecf20Sopenharmony_ci .recalc = bus_clk_recalc, 548c2ecf20Sopenharmony_ci}; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic struct sh_clk_ops sh7203_cpu_clk_ops = { 578c2ecf20Sopenharmony_ci .recalc = followparent_recalc, 588c2ecf20Sopenharmony_ci}; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistatic struct sh_clk_ops *sh7203_clk_ops[] = { 618c2ecf20Sopenharmony_ci &sh7203_master_clk_ops, 628c2ecf20Sopenharmony_ci &sh7203_module_clk_ops, 638c2ecf20Sopenharmony_ci &sh7203_bus_clk_ops, 648c2ecf20Sopenharmony_ci &sh7203_cpu_clk_ops, 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_civoid __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci if (test_mode_pin(MODE_PIN1)) 708c2ecf20Sopenharmony_ci pll2_mult = 4; 718c2ecf20Sopenharmony_ci else if (test_mode_pin(MODE_PIN0)) 728c2ecf20Sopenharmony_ci pll2_mult = 2; 738c2ecf20Sopenharmony_ci else 748c2ecf20Sopenharmony_ci pll2_mult = 1; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (idx < ARRAY_SIZE(sh7203_clk_ops)) 778c2ecf20Sopenharmony_ci *ops = sh7203_clk_ops[idx]; 788c2ecf20Sopenharmony_ci} 79