162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/sh/kernel/cpu/sh2a/clock-sh7203.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * SH7203 support for the clock framework 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2007 Kieran Bingham (MPC-Data Ltd) 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Based on clock-sh7263.c 1062306a36Sopenharmony_ci * Copyright (C) 2006 Yoshinori Sato 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Based on clock-sh4.c 1362306a36Sopenharmony_ci * Copyright (C) 2005 Paul Mundt 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci#include <linux/init.h> 1662306a36Sopenharmony_ci#include <linux/kernel.h> 1762306a36Sopenharmony_ci#include <asm/clock.h> 1862306a36Sopenharmony_ci#include <asm/freq.h> 1962306a36Sopenharmony_ci#include <asm/io.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic const int pll1rate[]={8,12,16,0}; 2262306a36Sopenharmony_cistatic const int pfc_divisors[]={1,2,3,4,6,8,12}; 2362306a36Sopenharmony_ci#define ifc_divisors pfc_divisors 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic unsigned int pll2_mult; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic void master_clk_init(struct clk *clk) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci clk->rate *= pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0003] * pll2_mult; 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic struct sh_clk_ops sh7203_master_clk_ops = { 3362306a36Sopenharmony_ci .init = master_clk_init, 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic unsigned long module_clk_recalc(struct clk *clk) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci int idx = (__raw_readw(FREQCR) & 0x0007); 3962306a36Sopenharmony_ci return clk->parent->rate / pfc_divisors[idx]; 4062306a36Sopenharmony_ci} 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic struct sh_clk_ops sh7203_module_clk_ops = { 4362306a36Sopenharmony_ci .recalc = module_clk_recalc, 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistatic unsigned long bus_clk_recalc(struct clk *clk) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci int idx = (__raw_readw(FREQCR) & 0x0007); 4962306a36Sopenharmony_ci return clk->parent->rate / pfc_divisors[idx-2]; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic struct sh_clk_ops sh7203_bus_clk_ops = { 5362306a36Sopenharmony_ci .recalc = bus_clk_recalc, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic struct sh_clk_ops sh7203_cpu_clk_ops = { 5762306a36Sopenharmony_ci .recalc = followparent_recalc, 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic struct sh_clk_ops *sh7203_clk_ops[] = { 6162306a36Sopenharmony_ci &sh7203_master_clk_ops, 6262306a36Sopenharmony_ci &sh7203_module_clk_ops, 6362306a36Sopenharmony_ci &sh7203_bus_clk_ops, 6462306a36Sopenharmony_ci &sh7203_cpu_clk_ops, 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_civoid __init arch_init_clk_ops(struct sh_clk_ops **ops, int idx) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci if (test_mode_pin(MODE_PIN1)) 7062306a36Sopenharmony_ci pll2_mult = 4; 7162306a36Sopenharmony_ci else if (test_mode_pin(MODE_PIN0)) 7262306a36Sopenharmony_ci pll2_mult = 2; 7362306a36Sopenharmony_ci else 7462306a36Sopenharmony_ci pll2_mult = 1; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (idx < ARRAY_SIZE(sh7203_clk_ops)) 7762306a36Sopenharmony_ci *ops = sh7203_clk_ops[idx]; 7862306a36Sopenharmony_ci} 79