diff options
Diffstat (limited to 'board/freescale/common/ics307_clk.c')
| -rw-r--r-- | board/freescale/common/ics307_clk.c | 69 | 
1 files changed, 69 insertions, 0 deletions
| diff --git a/board/freescale/common/ics307_clk.c b/board/freescale/common/ics307_clk.c index 89d8810f7..6acbc361a 100644 --- a/board/freescale/common/ics307_clk.c +++ b/board/freescale/common/ics307_clk.c @@ -31,12 +31,81 @@  #include "pixis.h"  #endif +/* define for SYS CLK or CLK1Frequency */ +#define TTL		1 +#define CLK2		0 +#define CRYSTAL		0 +#define MAX_VDW		(511 + 8) +#define MAX_RDW		(127 + 2) +#define MIN_VDW		(4 + 8) +#define MIN_RDW		(1 + 2) +#define NUM_OD_SETTING	8 +/* + * These defines cover the industrial temperature range part, + * for commercial, change below to 400000 and 55000, respectively + */ +#define MAX_VCO		360000 +#define MIN_VCO		60000 +  /* decode S[0-2] to Output Divider (OD) */  static u8 ics307_s_to_od[] = {  	10, 2, 8, 4, 5, 7, 3, 6  };  /* + * Find one solution to generate required frequency for SYSCLK + * out_freq: KHz, required frequency to the SYSCLK + * the result will be retuned with component RDW, VDW, OD, TTL, + * CLK2 and crystal + */ +unsigned long ics307_sysclk_calculator(unsigned long out_freq) +{ +	const unsigned long input_freq = CONFIG_ICS307_REFCLK_HZ; +	unsigned long vdw, rdw, odp, s_vdw = 0, s_rdw = 0, s_odp = 0, od; +	unsigned long tmp_out, diff, result = 0; +	int found = 0; + +	for (odp = 0; odp < NUM_OD_SETTING; odp++) { +		od = ics307_s_to_od[odp]; +		if (od * out_freq < MIN_VCO || od * out_freq > MAX_VCO) +			continue; +		for (rdw = MIN_RDW; rdw <= MAX_RDW; rdw++) { +			/* Calculate the VDW */ +			vdw = out_freq * 1000 * od * rdw / (input_freq * 2); +			if (vdw > MAX_VDW) +				vdw = MAX_VDW; +			if (vdw < MIN_VDW) +				continue; +			/* Calculate the temp out frequency */ +			tmp_out = input_freq * 2 * vdw / (rdw * od * 1000); +			diff = MAX(out_freq, tmp_out) - MIN(out_freq, tmp_out); +			/* +			 * calculate the percent, the precision is 1/1000 +			 * If greater than 1/1000, continue +			 * otherwise, we think the solution is we required +			 */ +			if (diff * 1000 / out_freq > 1) +				continue; +			else { +				s_vdw = vdw; +				s_rdw = rdw; +				s_odp = odp; +				found = 1; +				break; +			} +		} +	} + +	if (found) +		result = (s_rdw - 2) | (s_vdw - 8) << 7 | s_odp << 16 | +			CLK2 << 19 | TTL << 21 | CRYSTAL << 22; + +	debug("ICS307-02: RDW: %ld, VDW: %ld, OD: %d\n", s_rdw - 2, s_vdw - 8, +			ics307_s_to_od[s_odp]); +	return result; +} + +/*   * Calculate frequency being generated by ICS307-02 clock chip based upon   * the control bytes being programmed into it.   */ |