1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright (c) 2006-2007 Simtec Electronics 4*4882a593Smuzhiyun * http://armlinux.simtec.co.uk/ 5*4882a593Smuzhiyun * Ben Dooks <ben@simtec.co.uk> 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * S3C CPU frequency scaling support - driver and board 8*4882a593Smuzhiyun */ 9*4882a593Smuzhiyun #ifndef __LINUX_SOC_SAMSUNG_S3C_CPU_FREQ_H 10*4882a593Smuzhiyun #define __LINUX_SOC_SAMSUNG_S3C_CPU_FREQ_H 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #include <linux/cpufreq.h> 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun struct s3c_cpufreq_info; 15*4882a593Smuzhiyun struct s3c_cpufreq_board; 16*4882a593Smuzhiyun struct s3c_iotimings; 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun /** 19*4882a593Smuzhiyun * struct s3c_freq - frequency information (mainly for core drivers) 20*4882a593Smuzhiyun * @fclk: The FCLK frequency in Hz. 21*4882a593Smuzhiyun * @armclk: The ARMCLK frequency in Hz. 22*4882a593Smuzhiyun * @hclk_tns: HCLK cycle time in 10ths of nano-seconds. 23*4882a593Smuzhiyun * @hclk: The HCLK frequency in Hz. 24*4882a593Smuzhiyun * @pclk: The PCLK frequency in Hz. 25*4882a593Smuzhiyun * 26*4882a593Smuzhiyun * This contains the frequency information about the current configuration 27*4882a593Smuzhiyun * mainly for the core drivers to ensure we do not end up passing about 28*4882a593Smuzhiyun * a large number of parameters. 29*4882a593Smuzhiyun * 30*4882a593Smuzhiyun * The @hclk_tns field is a useful cache for the parts of the drivers that 31*4882a593Smuzhiyun * need to calculate IO timings and suchlike. 32*4882a593Smuzhiyun */ 33*4882a593Smuzhiyun struct s3c_freq { 34*4882a593Smuzhiyun unsigned long fclk; 35*4882a593Smuzhiyun unsigned long armclk; 36*4882a593Smuzhiyun unsigned long hclk_tns; /* in 10ths of ns */ 37*4882a593Smuzhiyun unsigned long hclk; 38*4882a593Smuzhiyun unsigned long pclk; 39*4882a593Smuzhiyun }; 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun /** 42*4882a593Smuzhiyun * struct s3c_cpufreq_freqs - s3c cpufreq notification information. 43*4882a593Smuzhiyun * @freqs: The cpufreq setting information. 44*4882a593Smuzhiyun * @old: The old clock settings. 45*4882a593Smuzhiyun * @new: The new clock settings. 46*4882a593Smuzhiyun * @pll_changing: Set if the PLL is changing. 47*4882a593Smuzhiyun * 48*4882a593Smuzhiyun * Wrapper 'struct cpufreq_freqs' so that any drivers receiving the 49*4882a593Smuzhiyun * notification can use this information that is not provided by just 50*4882a593Smuzhiyun * having the core frequency alone. 51*4882a593Smuzhiyun * 52*4882a593Smuzhiyun * The pll_changing flag is used to indicate if the PLL itself is 53*4882a593Smuzhiyun * being set during this change. This is important as the clocks 54*4882a593Smuzhiyun * will temporarily be set to the XTAL clock during this time, so 55*4882a593Smuzhiyun * drivers may want to close down their output during this time. 56*4882a593Smuzhiyun * 57*4882a593Smuzhiyun * Note, this is not being used by any current drivers and therefore 58*4882a593Smuzhiyun * may be removed in the future. 59*4882a593Smuzhiyun */ 60*4882a593Smuzhiyun struct s3c_cpufreq_freqs { 61*4882a593Smuzhiyun struct cpufreq_freqs freqs; 62*4882a593Smuzhiyun struct s3c_freq old; 63*4882a593Smuzhiyun struct s3c_freq new; 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun unsigned int pll_changing:1; 66*4882a593Smuzhiyun }; 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun #define to_s3c_cpufreq(_cf) container_of(_cf, struct s3c_cpufreq_freqs, freqs) 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun /** 71*4882a593Smuzhiyun * struct s3c_clkdivs - clock divisor information 72*4882a593Smuzhiyun * @p_divisor: Divisor from FCLK to PCLK. 73*4882a593Smuzhiyun * @h_divisor: Divisor from FCLK to HCLK. 74*4882a593Smuzhiyun * @arm_divisor: Divisor from FCLK to ARMCLK (not all CPUs). 75*4882a593Smuzhiyun * @dvs: Non-zero if using DVS mode for ARMCLK. 76*4882a593Smuzhiyun * 77*4882a593Smuzhiyun * Divisor settings for the core clocks. 78*4882a593Smuzhiyun */ 79*4882a593Smuzhiyun struct s3c_clkdivs { 80*4882a593Smuzhiyun int p_divisor; 81*4882a593Smuzhiyun int h_divisor; 82*4882a593Smuzhiyun int arm_divisor; 83*4882a593Smuzhiyun unsigned char dvs; 84*4882a593Smuzhiyun }; 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun #define PLLVAL(_m, _p, _s) (((_m) << 12) | ((_p) << 4) | (_s)) 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun /** 89*4882a593Smuzhiyun * struct s3c_pllval - PLL value entry. 90*4882a593Smuzhiyun * @freq: The frequency for this entry in Hz. 91*4882a593Smuzhiyun * @pll_reg: The PLL register setting for this PLL value. 92*4882a593Smuzhiyun */ 93*4882a593Smuzhiyun struct s3c_pllval { 94*4882a593Smuzhiyun unsigned long freq; 95*4882a593Smuzhiyun unsigned long pll_reg; 96*4882a593Smuzhiyun }; 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun /** 99*4882a593Smuzhiyun * struct s3c_cpufreq_board - per-board cpu frequency informatin 100*4882a593Smuzhiyun * @refresh: The SDRAM refresh period in nanoseconds. 101*4882a593Smuzhiyun * @auto_io: Set if the IO timing settings should be generated from the 102*4882a593Smuzhiyun * initialisation time hardware registers. 103*4882a593Smuzhiyun * @need_io: Set if the board has external IO on any of the chipselect 104*4882a593Smuzhiyun * lines that will require the hardware timing registers to be 105*4882a593Smuzhiyun * updated on a clock change. 106*4882a593Smuzhiyun * @max: The maxium frequency limits for the system. Any field that 107*4882a593Smuzhiyun * is left at zero will use the CPU's settings. 108*4882a593Smuzhiyun * 109*4882a593Smuzhiyun * This contains the board specific settings that affect how the CPU 110*4882a593Smuzhiyun * drivers chose settings. These include the memory refresh and IO 111*4882a593Smuzhiyun * timing information. 112*4882a593Smuzhiyun * 113*4882a593Smuzhiyun * Registration depends on the driver being used, the ARMCLK only 114*4882a593Smuzhiyun * implementation does not currently need this but the older style 115*4882a593Smuzhiyun * driver requires this to be available. 116*4882a593Smuzhiyun */ 117*4882a593Smuzhiyun struct s3c_cpufreq_board { 118*4882a593Smuzhiyun unsigned int refresh; 119*4882a593Smuzhiyun unsigned int auto_io:1; /* automatically init io timings. */ 120*4882a593Smuzhiyun unsigned int need_io:1; /* set if needs io timing support. */ 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun /* any non-zero field in here is taken as an upper limit. */ 123*4882a593Smuzhiyun struct s3c_freq max; /* frequency limits */ 124*4882a593Smuzhiyun }; 125*4882a593Smuzhiyun 126*4882a593Smuzhiyun /* Things depending on frequency scaling. */ 127*4882a593Smuzhiyun #ifdef CONFIG_ARM_S3C_CPUFREQ 128*4882a593Smuzhiyun #define __init_or_cpufreq 129*4882a593Smuzhiyun #else 130*4882a593Smuzhiyun #define __init_or_cpufreq __init 131*4882a593Smuzhiyun #endif 132*4882a593Smuzhiyun 133*4882a593Smuzhiyun /* Board functions */ 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun #ifdef CONFIG_ARM_S3C_CPUFREQ 136*4882a593Smuzhiyun extern int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board); 137*4882a593Smuzhiyun #else 138*4882a593Smuzhiyun s3c_cpufreq_setboard(struct s3c_cpufreq_board * board)139*4882a593Smuzhiyunstatic inline int s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) 140*4882a593Smuzhiyun { 141*4882a593Smuzhiyun return 0; 142*4882a593Smuzhiyun } 143*4882a593Smuzhiyun #endif /* CONFIG_ARM_S3C_CPUFREQ */ 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun #endif 146