Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 358965d7 authored by Richard Woodruff's avatar Richard Woodruff Committed by Paul Walmsley
Browse files

OMAP3 clock: introduce DPLL4 Jtype



DPLL4 for 3630 introduces a changed block called j type dpll, requiring
special divisor bits and additional reg fields. To allow for silicons to
use this, this is introduced as a flag and is enabled for 3630 silicon.
OMAP4 also has j type dpll for usb.

Tested with 3630 ZOOM3 and OMAP3430 ZOOM2

Signed-off-by: default avatarRichard Woodruff <r-woodruff2@ti.com>
Signed-off-by: default avatarNishanth Menon <nm@ti.com>
Signed-off-by: default avatarVishwanath BS <Vishwanath.bs@ti.com>
[paul@pwsan.com: added some comments; updated copyrights and credits; fixed
 some style issues]
Signed-off-by: default avatarPaul Walmsley <paul@pwsan.com>
parent 91808a81
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -47,6 +47,10 @@
#define DPLL_LOW_POWER_BYPASS	0x5
#define DPLL_LOCKED		0x7

/* DPLL Type and DCO Selection Flags */
#define DPLL_J_TYPE		0x1
#define DPLL_NO_DCO_SEL		0x2

int omap2_clk_enable(struct clk *clk);
void omap2_clk_disable(struct clk *clk);
long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
+31 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@

/* Maximum DPLL multiplier, divider values for OMAP3 */
#define OMAP3_MAX_DPLL_MULT		2048
#define OMAP3630_MAX_JTYPE_DPLL_MULT	4095
#define OMAP3_MAX_DPLL_DIV		128

/*
@@ -529,7 +530,8 @@ static struct clk emu_core_alwon_ck = {
/* DPLL4 */
/* Supplies 96MHz, 54Mhz TV DAC, DSS fclk, CAM sensor clock, emul trace clk */
/* Type: DPLL */
static struct dpll_data dpll4_dd = {
static struct dpll_data dpll4_dd;
static struct dpll_data dpll4_dd_34xx __initdata = {
	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
	.mult_mask	= OMAP3430_PERIPH_DPLL_MULT_MASK,
	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
@@ -552,6 +554,29 @@ static struct dpll_data dpll4_dd = {
	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
};

static struct dpll_data dpll4_dd_3630 __initdata = {
	.mult_div1_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
	.mult_mask	= OMAP3630_PERIPH_DPLL_MULT_MASK,
	.div1_mask	= OMAP3430_PERIPH_DPLL_DIV_MASK,
	.clk_bypass	= &sys_ck,
	.clk_ref	= &sys_ck,
	.control_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
	.enable_mask	= OMAP3430_EN_PERIPH_DPLL_MASK,
	.modes		= (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
	.auto_recal_bit	= OMAP3430_EN_PERIPH_DPLL_DRIFTGUARD_SHIFT,
	.recal_en_bit	= OMAP3430_PERIPH_DPLL_RECAL_EN_SHIFT,
	.recal_st_bit	= OMAP3430_PERIPH_DPLL_ST_SHIFT,
	.autoidle_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_AUTOIDLE),
	.autoidle_mask	= OMAP3430_AUTO_PERIPH_DPLL_MASK,
	.idlest_reg	= OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
	.idlest_mask	= OMAP3430_ST_PERIPH_CLK_MASK,
	.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
	.min_divider	= 1,
	.max_divider	= OMAP3_MAX_DPLL_DIV,
	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE,
	.flags		= DPLL_J_TYPE
};

static struct clk dpll4_ck = {
	.name		= "dpll4_ck",
	.ops		= &omap3_clkops_noncore_dpll_ops,
@@ -3377,6 +3402,11 @@ int __init omap3xxx_clk_init(void)
				&clkops_omap36xx_pwrdn_with_hsdiv_wait_restore;
	}

	if (cpu_is_omap3630())
		dpll4_dd = dpll4_dd_3630;
	else
		dpll4_dd = dpll4_dd_34xx;

	clk_init(&omap2_clk_functions);

	for (c = omap3xxx_clks; c < omap3xxx_clks + ARRAY_SIZE(omap3xxx_clks); c++)
+1 −0
Original line number Diff line number Diff line
@@ -980,6 +980,7 @@ static struct dpll_data dpll_usb_dd = {
	.max_multiplier	= OMAP4430_MAX_DPLL_MULT,
	.max_divider	= OMAP4430_MAX_DPLL_DIV,
	.min_divider	= 1,
	.flags		= DPLL_J_TYPE | DPLL_NO_DCO_SEL
};


+5 −0
Original line number Diff line number Diff line
@@ -531,8 +531,13 @@
/* CM_CLKSEL2_PLL */
#define OMAP3430_PERIPH_DPLL_MULT_SHIFT			8
#define OMAP3430_PERIPH_DPLL_MULT_MASK			(0x7ff << 8)
#define OMAP3630_PERIPH_DPLL_MULT_MASK			(0xfff << 8)
#define OMAP3430_PERIPH_DPLL_DIV_SHIFT			0
#define OMAP3430_PERIPH_DPLL_DIV_MASK			(0x7f << 0)
#define OMAP3630_PERIPH_DPLL_DCO_SEL_SHIFT		21
#define OMAP3630_PERIPH_DPLL_DCO_SEL_MASK		(0x7 << 21)
#define OMAP3630_PERIPH_DPLL_SD_DIV_SHIFT		24
#define OMAP3630_PERIPH_DPLL_SD_DIV_MASK		(0xff << 24)

/* CM_CLKSEL3_PLL */
#define OMAP3430_DIV_96M_SHIFT				0
+63 −4
Original line number Diff line number Diff line
/*
 * OMAP3/4 - specific DPLL control functions
 *
 * Copyright (C) 2009 Texas Instruments, Inc.
 * Copyright (C) 2009 Nokia Corporation
 * Copyright (C) 2009-2010 Texas Instruments, Inc.
 * Copyright (C) 2009-2010 Nokia Corporation
 *
 * Written by Paul Walmsley
 * Testing and integration fixes by Jouni Högander
 * Testing and integration fixes by Jouni Högander
 *
 * 36xx support added by Vishwanath BS, Richard Woodruff, and Nishanth
 * Menon
 *
 * Parts of this code are based on code written by
 * Richard Woodruff, Tony Lindgren, Tuukka Tikkanen, Karthik Dasu
@@ -225,6 +228,47 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
	return 0;
}

/**
 * lookup_dco_sddiv -  Set j-type DPLL4 compensation variables
 * @clk: pointer to a DPLL struct clk
 * @dco: digital control oscillator selector
 * @sd_div: target sigma-delta divider
 * @m: DPLL multiplier to set
 * @n: DPLL divider to set
 *
 * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
 *
 * XXX This code is not needed for 3430/AM35xx; can it be optimized
 * out in non-multi-OMAP builds for those chips?
 */
static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
			     u8 n)
{
	unsigned long fint, clkinp, sd; /* watch out for overflow */
	int mod1, mod2;

	clkinp = clk->parent->rate;
	fint = (clkinp / n) * m;

	if (fint < 1000000000)
		*dco = 2;
	else
		*dco = 4;
	/*
	 * target sigma-delta to near 250MHz
	 * sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
	 */
	clkinp /= 100000; /* shift from MHz to 10*Hz for 38.4 and 19.2 */
	mod1 = (clkinp * m) % (250 * n);
	sd = (clkinp * m) / (250 * n);
	mod2 = sd % 10;
	sd /= 10;

	if (mod1 || mod2)
		sd++;
	*sd_div = sd;
}

/*
 * _omap3_noncore_dpll_program - set non-core DPLL M,N values directly
 * @clk: struct clk * of DPLL to set
@@ -259,6 +303,21 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
	v &= ~(dd->mult_mask | dd->div1_mask);
	v |= m << __ffs(dd->mult_mask);
	v |= (n - 1) << __ffs(dd->div1_mask);

	/*
	 * XXX This code is not needed for 3430/AM35XX; can it be optimized
	 * out in non-multi-OMAP builds for those chips?
	 */
	if ((dd->flags & DPLL_J_TYPE) && !(dd->flags & DPLL_NO_DCO_SEL)) {
		u8 dco, sd_div;
		lookup_dco_sddiv(clk, &dco, &sd_div, m, n);
		/* XXX This probably will need revision for OMAP4 */
		v &= ~(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK
			| OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
		v |= dco << __ffs(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK);
		v |= sd_div << __ffs(OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
	}

	__raw_writel(v, dd->mult_div1_reg);

	/* We let the clock framework set the other output dividers later */
@@ -536,7 +595,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)

	v = __raw_readl(dd->control_reg) & dd->enable_mask;
	v >>= __ffs(dd->enable_mask);
	if (v != OMAP3XXX_EN_DPLL_LOCKED)
	if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
		rate = clk->parent->rate;
	else
		rate = clk->parent->rate * 2;
Loading