From patchwork Mon Jun 7 10:16:11 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raffaele Recalcati X-Patchwork-Id: 104685 Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o57ALBBI009983 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 7 Jun 2010 10:21:47 GMT Received: from dlep36.itg.ti.com ([157.170.170.91]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id o57AJWvj019001 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 7 Jun 2010 05:19:33 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep36.itg.ti.com (8.13.8/8.13.8) with ESMTP id o57AJVJs013549; Mon, 7 Jun 2010 05:19:32 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 9D7CB80626; Mon, 7 Jun 2010 05:19:31 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp51.itg.ti.com (dflp51.itg.ti.com [128.247.22.94]) by linux.omap.com (Postfix) with ESMTP id AC8D580632 for ; Mon, 7 Jun 2010 05:16:23 -0500 (CDT) Received: from red.ext.ti.com (localhost [127.0.0.1]) by dflp51.itg.ti.com (8.13.7/8.13.7) with ESMTP id o57AGNEg000824 for ; Mon, 7 Jun 2010 05:16:23 -0500 (CDT) Received: from psmtp.com (na3sys009amx228.postini.com [74.125.149.112]) by red.ext.ti.com (8.13.7/8.13.7) with SMTP id o57AGMrp002603 for ; Mon, 7 Jun 2010 05:16:22 -0500 Received: from source ([209.85.214.173]) by na3sys009amx228.postini.com ([74.125.148.10]) with SMTP; Mon, 07 Jun 2010 10:16:22 GMT Received: by mail-iw0-f173.google.com with SMTP id 41so3308425iwn.4 for ; Mon, 07 Jun 2010 03:16:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:date:message-id :subject:from:to:content-type; bh=5nineKfcmf1JJDNlkGlSwvBXspQUDS7SbVnTSolN+/A=; b=tJi5duUR0vb+g8Mt7E17Mtv/xYN5KQsPYec0Psta6nR2CKqYX/dUWJr+PIzu4hrNfN W/jo0xp2TxC16czZ51HyOBOSwJyKRp4F44CWzoi+7upBBOpUynr071YcgmUA19anMKNj z8E5e06guG1gSDAIEL7713xhXIKnL/RQHDvCA= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=K91nUlfENKiSNuaiRADuWMDfhegBT8uEImvXHs3ZHEfw/LaNcnweXyAM1+30nkfQIB Y2nNuqF/aOgf4CIlXRb1czNGf762nY33fCU1laRVc4vx7O1Z0uIBZx9qp9s2htvDJ4nT 58aBjgpwQKMtyqeLbfMN87ACTJn7a7qeEHBBA= MIME-Version: 1.0 Received: by 10.231.169.195 with SMTP id a3mr6680874ibz.40.1275905771714; Mon, 07 Jun 2010 03:16:11 -0700 (PDT) Received: by 10.231.172.16 with HTTP; Mon, 7 Jun 2010 03:16:11 -0700 (PDT) Date: Mon, 7 Jun 2010 12:16:11 +0200 Message-ID: Subject: [PATCH 10/12] DaVinci: dm365: Added clokout2 management From: Raffaele Recalcati To: davinci-linux-open-source X-pstn-neptune: 0/0/0.00/0 X-pstn-levels: (S:66.71969/99.90000 CV:99.9000 FC:95.5390 LC:95.5390 R:95.9108 P:95.9108 M:97.0282 C:98.6951 ) X-pstn-settings: 2 (0.5000:0.5000) s cv gt3 gt2 gt1 r p m c X-pstn-addresses: from [db-null] X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com X-Greylist: Sender succeeded STARTTLS authentication, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 07 Jun 2010 10:21:48 +0000 (UTC) diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 054c303..f561b73 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -144,6 +144,68 @@ int clk_set_rate(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL(clk_set_rate); + +int clkout_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long flags; + int ret = -EINVAL; + int i, err, min_err, i_min_err; + u32 regval; + struct pll_data *pll; + + + if (clk == NULL || IS_ERR(clk)) + return ret; + pll = clk->parent->pll_data; + regval = __raw_readl(IO_ADDRESS(clk->sec_div_reg)); + + if (clk->sec_div_reg) + { + i_min_err = min_err = INT_MAX; + for (i=clk->sec_div_reg_max; i>0; i--) + { + if (clk->set_rate) + { + ret = clk_set_rate(clk, rate * i) ; + err = clk_get_rate(clk) - rate * i; + if (abs(min_err) > abs(err)) + { + min_err = err; + i_min_err = i; + } + } + } + i = i_min_err; + ret = clk->set_rate(clk, rate * i) ; + + regval &= ~(clk->sec_div_reg_max << clk->sec_div_reg_shift); + regval |= (i-1) << clk->sec_div_reg_shift; + __raw_writel(regval, IO_ADDRESS(clk->sec_div_reg)); + regval = __raw_readl( IO_ADDRESS(clk->out_enable_reg)); + regval |= 1 << clk->out_enable_bit; + __raw_writel(regval, IO_ADDRESS(clk->out_enable_reg)); + rate *= i; + } + else + { + if (clk->set_rate) + ret = clk->set_rate(clk, rate); + } + + spin_lock_irqsave(&clockfw_lock, flags); + if (ret == 0) { + if (clk->recalc) + clk->rate = clk->recalc(clk); + propagate_rate(clk); + regval &= ~(1 << clk->out_enable_bit); + __raw_writel(regval, IO_ADDRESS(clk->out_enable_reg)); + } + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clkout_set_rate); + int clk_set_parent(struct clk *clk, struct clk *parent) { unsigned long flags; diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 01e3648..1ca14e7 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -95,6 +95,12 @@ struct clk { struct list_head childnode; /* parent's child list node */ struct pll_data *pll_data; u32 div_reg; + u32 sec_div_reg; + u32 sec_div_reg_max; + u32 sec_div_reg_shift; + u32 out_enable_reg; + u32 out_enable_bit; + unsigned long (*recalc) (struct clk *); int (*set_rate) (struct clk *clk, unsigned long rate); int (*round_rate) (struct clk *clk, unsigned long rate); diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index e4ead0a..9968c37 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -40,6 +40,21 @@ #include "mux.h" #define DM365_REF_FREQ 24000000 /* 24 MHz on the DM365 EVM */ +#define PINMUX0 0x00 +#define PINMUX1 0x04 +#define PINMUX2 0x08 +#define PINMUX3 0x0c +#define PINMUX4 0x10 +#define INTMUX 0x18 +#define EVTMUX 0x1c +#define PERI_CLKCTL 0x48 +#define CLOCKOUT2EN 2 +#define CLOCKOUT1EN 1 +#define CLOCKOUT0EN 0 + + +int dm365_set_pll1_rate(struct clk *clk, unsigned long rate); + static struct pll_data pll1_data = { .num = 1, @@ -147,6 +162,20 @@ static struct clk pll1_sysclk9 = { .div_reg = PLLDIV9, }; +static struct clk clkout2_clk = { + .name = "clkout2", + .parent = &pll1_clk, + .flags = CLK_PLL, + .div_reg = PLLDIV9, + .sec_div_reg = DAVINCI_SYSTEM_MODULE_BASE + PERI_CLKCTL, + .sec_div_reg_max = 0x0F, + .sec_div_reg_shift = 3, + .out_enable_reg = DAVINCI_SYSTEM_MODULE_BASE + PERI_CLKCTL, + .out_enable_bit = CLOCKOUT2EN, + .set_rate = dm365_set_pll1_rate, +}; + + static struct clk pll2_clk = { .name = "pll2", .parent = &ref_clk, @@ -421,6 +450,7 @@ static struct clk_lookup dm365_clks[] = { CLK(NULL, "pll1_sysclk7", &pll1_sysclk7), CLK(NULL, "pll1_sysclk8", &pll1_sysclk8), CLK(NULL, "pll1_sysclk9", &pll1_sysclk9), + CLK(NULL, "clkout2", &clkout2_clk), CLK(NULL, "pll2", &pll2_clk), CLK(NULL, "pll2_aux", &pll2_aux_clk), CLK(NULL, "clkout1", &clkout1_clk), @@ -467,9 +497,6 @@ static struct clk_lookup dm365_clks[] = { /*----------------------------------------------------------------------*/ -#define INTMUX 0x18 -#define EVTMUX 0x1c - static const struct mux_config dm365_pins[] = { #ifdef CONFIG_DAVINCI_MUX @@ -657,6 +684,31 @@ static struct resource dm365_spi0_resources[] = { }, }; +int dm365_set_pll1_rate(struct clk *clk, unsigned long rate) +{ + unsigned int prediv, mult, postdiv; + u32 clk_freq_min, clk_freq_max, plldiv; + + prediv = ioread32(IO_ADDRESS(DAVINCI_PLL1_BASE + PREDIV)) & 0x1F; + mult = ioread32(IO_ADDRESS(DAVINCI_PLL1_BASE + PLLM)) & 0x3FF; + postdiv = ioread32(IO_ADDRESS(DAVINCI_PLL1_BASE + POSTDIV)) & 0x1F; + + clk_freq_max = DM365_REF_FREQ * 2 * mult / ( (prediv + 1) * (postdiv + 1) ); + clk_freq_min = clk_freq_max / 0x20; + + if ( (rate < clk_freq_min) || (rate > clk_freq_max) ) + return -EINVAL; + + plldiv = clk_freq_max / rate ; + if ( (clk_freq_max % rate) < (rate/2)) + plldiv--; + iowrite32(plldiv & 0x1F, IO_ADDRESS(DAVINCI_PLL1_BASE + clk->div_reg)); + iowrite32(plldiv | 0x8000, IO_ADDRESS(DAVINCI_PLL1_BASE + clk->div_reg)); + clk->rate = rate; + + return 0; +} + static struct platform_device dm365_spi0_device = { .name = "spi_davinci", .id = 0, diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h index a3b0402..e249269 100644 --- a/arch/arm/mach-davinci/include/mach/clock.h +++ b/arch/arm/mach-davinci/include/mach/clock.h @@ -18,4 +18,7 @@ struct clk; extern int clk_register(struct clk *clk); extern void clk_unregister(struct clk *clk); +int clkout_set_rate(struct clk *clk, unsigned long rate); + + #endif