cpu-freq-core.h 8.8 KB
Newer Older
1
/* arch/arm/plat-samsung/include/plat/cpu-freq-core.h
2
 *
3
 * Copyright (c) 2006-2009 Simtec Electronics
4 5 6 7 8 9 10 11 12 13 14 15
 *	http://armlinux.simtec.co.uk/
 *	Ben Dooks <ben@simtec.co.uk>
 *
 * S3C CPU frequency scaling support - core support
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#include <plat/cpu-freq.h>

16 17
struct seq_file;

18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#define MAX_BANKS (8)
#define S3C2412_MAX_IO	(8)

/**
 * struct s3c2410_iobank_timing - IO bank timings for S3C2410 style timings
 * @bankcon: The cached version of settings in this structure.
 * @tacp:
 * @tacs: Time from address valid to nCS asserted.
 * @tcos: Time from nCS asserted to nOE or nWE asserted.
 * @tacc: Time that nOE or nWE is asserted.
 * @tcoh: Time nCS is held after nOE or nWE are released.
 * @tcah: Time address is held for after
 * @nwait_en: Whether nWAIT is enabled for this bank.
 *
 * This structure represents the IO timings for a S3C2410 style IO bank
 * used by the CPU frequency support if it needs to change the settings
 * of the IO.
 */
struct s3c2410_iobank_timing {
	unsigned long	bankcon;
	unsigned int	tacp;
	unsigned int	tacs;
	unsigned int	tcos;
	unsigned int	tacc;
	unsigned int	tcoh;		/* nCS hold afrer nOE/nWE */
	unsigned int	tcah;		/* Address hold after nCS */
	unsigned char	nwait_en;	/* nWait enabled for bank. */
};

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
/**
 * struct s3c2412_iobank_timing - io timings for PL092 (S3C2412) style IO
 * @idcy: The idle cycle time between transactions.
 * @wstrd: nCS release to end of read cycle.
 * @wstwr: nCS release to end of write cycle.
 * @wstoen: nCS assertion to nOE assertion time.
 * @wstwen: nCS assertion to nWE assertion time.
 * @wstbrd: Burst ready delay.
 * @smbidcyr: Register cache for smbidcyr value.
 * @smbwstrd: Register cache for smbwstrd value.
 * @smbwstwr: Register cache for smbwstwr value.
 * @smbwstoen: Register cache for smbwstoen value.
 * @smbwstwen: Register cache for smbwstwen value.
 * @smbwstbrd: Register cache for smbwstbrd value.
 *
 * Timing information for a IO bank on an S3C2412 or similar system which
 * uses a PL093 block.
 */
struct s3c2412_iobank_timing {
	unsigned int	idcy;
	unsigned int	wstrd;
	unsigned int	wstwr;
	unsigned int	wstoen;
	unsigned int	wstwen;
	unsigned int	wstbrd;

	/* register cache */
	unsigned char	smbidcyr;
	unsigned char	smbwstrd;
	unsigned char	smbwstwr;
	unsigned char	smbwstoen;
	unsigned char	smbwstwen;
	unsigned char	smbwstbrd;
};

82
union s3c_iobank {
83 84
	struct s3c2410_iobank_timing	*io_2410;
	struct s3c2412_iobank_timing	*io_2412;
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
};

/**
 * struct s3c_iotimings - Chip IO timings holder
 * @bank: The timings for each IO bank.
 */
struct s3c_iotimings {
	union s3c_iobank	bank[MAX_BANKS];
};

/**
 * struct s3c_plltab - PLL table information.
 * @vals: List of PLL values.
 * @size: Size of the PLL table @vals.
 */
struct s3c_plltab {
	struct s3c_pllval	*vals;
	int			 size;
};

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
/**
 * struct s3c_cpufreq_config - current cpu frequency configuration
 * @freq: The current settings for the core clocks.
 * @max: Maxium settings, derived from core, board and user settings.
 * @pll: The PLL table entry for the current PLL settings.
 * @divs: The divisor settings for the core clocks.
 * @info: The current core driver information.
 * @board: The information for the board we are running on.
 * @lock_pll: Set if the PLL settings cannot be changed.
 *
 * This is for the core drivers that need to know information about
 * the current settings and values. It should not be needed by any
 * device drivers.
*/
struct s3c_cpufreq_config {
	struct s3c_freq		freq;
	struct s3c_freq		max;
	struct cpufreq_frequency_table pll;
	struct s3c_clkdivs	divs;
	struct s3c_cpufreq_info *info;	/* for core, not drivers */
	struct s3c_cpufreq_board *board;

	unsigned int	lock_pll:1;
};

130 131 132 133 134 135 136 137
/**
 * struct s3c_cpufreq_info - Information for the CPU frequency driver.
 * @name: The name of this implementation.
 * @max: The maximum frequencies for the system.
 * @latency: Transition latency to give to cpufreq.
 * @locktime_m: The lock-time in uS for the MPLL.
 * @locktime_u: The lock-time in uS for the UPLL.
 * @locttime_bits: The number of bits each LOCKTIME field.
D
Daniel Mack 已提交
138
 * @need_pll: Set if this driver needs to change the PLL values to achieve
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
 *	any frequency changes. This is really only need by devices like the
 *	S3C2410 where there is no or limited divider between the PLL and the
 *	ARMCLK.
 * @resume_clocks: Update the clocks on resume.
 * @get_iotiming: Get the current IO timing data, mainly for use at start.
 * @set_iotiming: Update the IO timings from the cached copies calculated
 *	from the @calc_iotiming entry when changing the frequency.
 * @calc_iotiming: Calculate and update the cached copies of the IO timings
 *	from the newly calculated frequencies.
 * @calc_freqtable: Calculate (fill in) the given frequency table from the
 *	current frequency configuration. If the table passed in is NULL,
 *	then the return is the number of elements to be filled for allocation
 *	of the table.
 * @set_refresh: Set the memory refresh configuration.
 * @set_fvco: Set the PLL frequencies.
 * @set_divs: Update the clock divisors.
 * @calc_divs: Calculate the clock divisors.
 */
struct s3c_cpufreq_info {
	const char		*name;
	struct s3c_freq		max;

	unsigned int		latency;

	unsigned int		locktime_m;
	unsigned int		locktime_u;
	unsigned char		locktime_bits;

	unsigned int		need_pll:1;

	/* driver routines */

	void		(*resume_clocks)(void);

	int		(*get_iotiming)(struct s3c_cpufreq_config *cfg,
					struct s3c_iotimings *timings);

	void		(*set_iotiming)(struct s3c_cpufreq_config *cfg,
					struct s3c_iotimings *timings);

	int		(*calc_iotiming)(struct s3c_cpufreq_config *cfg,
					 struct s3c_iotimings *timings);

	int		(*calc_freqtable)(struct s3c_cpufreq_config *cfg,
					  struct cpufreq_frequency_table *t,
					  size_t table_size);

186 187 188 189
	void		(*debug_io_show)(struct seq_file *seq,
					 struct s3c_cpufreq_config *cfg,
					 union s3c_iobank *iob);

190 191 192 193 194 195 196 197
	void		(*set_refresh)(struct s3c_cpufreq_config *cfg);
	void		(*set_fvco)(struct s3c_cpufreq_config *cfg);
	void		(*set_divs)(struct s3c_cpufreq_config *cfg);
	int		(*calc_divs)(struct s3c_cpufreq_config *cfg);
};

extern int s3c_cpufreq_register(struct s3c_cpufreq_info *info);

198 199
extern int s3c_plltab_register(struct cpufreq_frequency_table *plls,
			       unsigned int plls_no);
200

201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
/* exports and utilities for debugfs */
extern struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void);
extern struct s3c_iotimings *s3c_cpufreq_getiotimings(void);

extern void s3c2410_iotiming_debugfs(struct seq_file *seq,
				     struct s3c_cpufreq_config *cfg,
				     union s3c_iobank *iob);

extern void s3c2412_iotiming_debugfs(struct seq_file *seq,
				     struct s3c_cpufreq_config *cfg,
				     union s3c_iobank *iob);

#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
#define s3c_cpufreq_debugfs_call(x) x
#else
#define s3c_cpufreq_debugfs_call(x) NULL
#endif

219 220 221 222 223 224 225
/* Useful utility functions. */

extern struct clk *s3c_cpufreq_clk_get(struct device *, const char *);

/* S3C2410 and compatible exported functions */

extern void s3c2410_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg);
226
extern void s3c2410_set_fvco(struct s3c_cpufreq_config *cfg);
227

228
#ifdef CONFIG_S3C2410_IOTIMING
229 230 231 232 233 234 235 236
extern int s3c2410_iotiming_calc(struct s3c_cpufreq_config *cfg,
				 struct s3c_iotimings *iot);

extern int s3c2410_iotiming_get(struct s3c_cpufreq_config *cfg,
				struct s3c_iotimings *timings);

extern void s3c2410_iotiming_set(struct s3c_cpufreq_config *cfg,
				 struct s3c_iotimings *iot);
237 238 239 240 241
#else
#define s3c2410_iotiming_calc NULL
#define s3c2410_iotiming_get NULL
#define s3c2410_iotiming_set NULL
#endif /* CONFIG_S3C2410_IOTIMING */
242

243 244 245 246 247 248 249 250 251 252 253 254 255 256
/* S3C2412 compatible routines */

extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
				struct s3c_iotimings *timings);

extern int s3c2412_iotiming_get(struct s3c_cpufreq_config *cfg,
				struct s3c_iotimings *timings);

extern int s3c2412_iotiming_calc(struct s3c_cpufreq_config *cfg,
				 struct s3c_iotimings *iot);

extern void s3c2412_iotiming_set(struct s3c_cpufreq_config *cfg,
				 struct s3c_iotimings *iot);

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUG
#define s3c_freq_dbg(x...) printk(KERN_INFO x)
#else
#define s3c_freq_dbg(x...) do { if (0) printk(x); } while (0)
#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUG */

#ifdef CONFIG_CPU_FREQ_S3C24XX_IODEBUG
#define s3c_freq_iodbg(x...) printk(KERN_INFO x)
#else
#define s3c_freq_iodbg(x...) do { if (0) printk(x); } while (0)
#endif /* CONFIG_CPU_FREQ_S3C24XX_IODEBUG */

static inline int s3c_cpufreq_addfreq(struct cpufreq_frequency_table *table,
				      int index, size_t table_size,
				      unsigned int freq)
{
	if (index < 0)
		return index;

	if (table) {
		if (index >= table_size)
			return -ENOMEM;

		s3c_freq_dbg("%s: { %d = %u kHz }\n",
			     __func__, index, freq);

		table[index].index = index;
		table[index].frequency = freq;
	}

	return index + 1;
}