1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun // 3*4882a593Smuzhiyun // Copyright (c) 2009 Simtec Electronics 4*4882a593Smuzhiyun // http://armlinux.simtec.co.uk/ 5*4882a593Smuzhiyun // Ben Dooks <ben@simtec.co.uk> 6*4882a593Smuzhiyun // 7*4882a593Smuzhiyun // S3C24XX CPU Frequency scaling - utils for S3C2410/S3C2440/S3C2442 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #include <linux/kernel.h> 10*4882a593Smuzhiyun #include <linux/errno.h> 11*4882a593Smuzhiyun #include <linux/cpufreq.h> 12*4882a593Smuzhiyun #include <linux/io.h> 13*4882a593Smuzhiyun #include <linux/clk.h> 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun #include "map.h" 16*4882a593Smuzhiyun #include "regs-clock.h" 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun #include <linux/soc/samsung/s3c-cpufreq-core.h> 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun #include "regs-mem-s3c24xx.h" 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun /** 23*4882a593Smuzhiyun * s3c2410_cpufreq_setrefresh - set SDRAM refresh value 24*4882a593Smuzhiyun * @cfg: The frequency configuration 25*4882a593Smuzhiyun * 26*4882a593Smuzhiyun * Set the SDRAM refresh value appropriately for the configured 27*4882a593Smuzhiyun * frequency. 28*4882a593Smuzhiyun */ s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config * cfg)29*4882a593Smuzhiyunvoid s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg) 30*4882a593Smuzhiyun { 31*4882a593Smuzhiyun struct s3c_cpufreq_board *board = cfg->board; 32*4882a593Smuzhiyun unsigned long refresh; 33*4882a593Smuzhiyun unsigned long refval; 34*4882a593Smuzhiyun 35*4882a593Smuzhiyun /* Reduce both the refresh time (in ns) and the frequency (in MHz) 36*4882a593Smuzhiyun * down to ensure that we do not overflow 32 bit numbers. 37*4882a593Smuzhiyun * 38*4882a593Smuzhiyun * This should work for HCLK up to 133MHz and refresh period up 39*4882a593Smuzhiyun * to 30usec. 40*4882a593Smuzhiyun */ 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun refresh = (cfg->freq.hclk / 100) * (board->refresh / 10); 43*4882a593Smuzhiyun refresh = DIV_ROUND_UP(refresh, (1000 * 1000)); /* apply scale */ 44*4882a593Smuzhiyun refresh = (1 << 11) + 1 - refresh; 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun s3c_freq_dbg("%s: refresh value %lu\n", __func__, refresh); 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun refval = __raw_readl(S3C2410_REFRESH); 49*4882a593Smuzhiyun refval &= ~((1 << 12) - 1); 50*4882a593Smuzhiyun refval |= refresh; 51*4882a593Smuzhiyun __raw_writel(refval, S3C2410_REFRESH); 52*4882a593Smuzhiyun } 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun /** 55*4882a593Smuzhiyun * s3c2410_set_fvco - set the PLL value 56*4882a593Smuzhiyun * @cfg: The frequency configuration 57*4882a593Smuzhiyun */ s3c2410_set_fvco(struct s3c_cpufreq_config * cfg)58*4882a593Smuzhiyunvoid s3c2410_set_fvco(struct s3c_cpufreq_config *cfg) 59*4882a593Smuzhiyun { 60*4882a593Smuzhiyun if (!IS_ERR(cfg->mpll)) 61*4882a593Smuzhiyun clk_set_rate(cfg->mpll, cfg->pll.frequency); 62*4882a593Smuzhiyun } 63*4882a593Smuzhiyun 64*4882a593Smuzhiyun #if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442) s3c2440_read_camdivn(void)65*4882a593Smuzhiyunu32 s3c2440_read_camdivn(void) 66*4882a593Smuzhiyun { 67*4882a593Smuzhiyun return __raw_readl(S3C2440_CAMDIVN); 68*4882a593Smuzhiyun } 69*4882a593Smuzhiyun s3c2440_write_camdivn(u32 camdiv)70*4882a593Smuzhiyunvoid s3c2440_write_camdivn(u32 camdiv) 71*4882a593Smuzhiyun { 72*4882a593Smuzhiyun __raw_writel(camdiv, S3C2440_CAMDIVN); 73*4882a593Smuzhiyun } 74*4882a593Smuzhiyun #endif 75*4882a593Smuzhiyun s3c24xx_read_clkdivn(void)76*4882a593Smuzhiyunu32 s3c24xx_read_clkdivn(void) 77*4882a593Smuzhiyun { 78*4882a593Smuzhiyun return __raw_readl(S3C2410_CLKDIVN); 79*4882a593Smuzhiyun } 80*4882a593Smuzhiyun s3c24xx_write_clkdivn(u32 clkdiv)81*4882a593Smuzhiyunvoid s3c24xx_write_clkdivn(u32 clkdiv) 82*4882a593Smuzhiyun { 83*4882a593Smuzhiyun __raw_writel(clkdiv, S3C2410_CLKDIVN); 84*4882a593Smuzhiyun } 85*4882a593Smuzhiyun s3c24xx_read_mpllcon(void)86*4882a593Smuzhiyunu32 s3c24xx_read_mpllcon(void) 87*4882a593Smuzhiyun { 88*4882a593Smuzhiyun return __raw_readl(S3C2410_MPLLCON); 89*4882a593Smuzhiyun } 90*4882a593Smuzhiyun s3c24xx_write_locktime(u32 locktime)91*4882a593Smuzhiyunvoid s3c24xx_write_locktime(u32 locktime) 92*4882a593Smuzhiyun { 93*4882a593Smuzhiyun return __raw_writel(locktime, S3C2410_LOCKTIME); 94*4882a593Smuzhiyun } 95