From patchwork Fri Jun 11 10:19:50 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raffaele Recalcati X-Patchwork-Id: 105552 Received: from comal.ext.ti.com (comal.ext.ti.com [198.47.26.152]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o5BAOVwH018312 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 11 Jun 2010 10:25:07 GMT Received: from dlep36.itg.ti.com ([157.170.170.91]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id o5BAMWtq014448 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 11 Jun 2010 05:22:32 -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 o5BAMWAJ011899; Fri, 11 Jun 2010 05:22:32 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 9FF7F80626; Fri, 11 Jun 2010 05:22:30 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp53.itg.ti.com (dflp53.itg.ti.com [128.247.5.6]) by linux.omap.com (Postfix) with ESMTP id 995BF80628 for ; Fri, 11 Jun 2010 05:20:19 -0500 (CDT) Received: from white.ext.ti.com (localhost [127.0.0.1]) by dflp53.itg.ti.com (8.13.8/8.13.8) with ESMTP id o5BAKJ1V009399 for ; Fri, 11 Jun 2010 05:20:19 -0500 (CDT) Received: from psmtp.com (na3sys009amx221.postini.com [74.125.149.61]) by white.ext.ti.com (8.13.7/8.13.7) with SMTP id o5BAKIFW017766 for ; Fri, 11 Jun 2010 05:20:18 -0500 Received: from source ([74.125.82.45]) by na3sys009amx221.postini.com ([74.125.148.13]) with SMTP; Fri, 11 Jun 2010 03:20:18 PDT Received: by mail-ww0-f45.google.com with SMTP id 13so674388wwb.4 for ; Fri, 11 Jun 2010 03:20:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=frkNT3VBYnyyG6Z79fvih/sm17JsRZ1suskOBD8q4S8=; b=MAW2K1kbu7Q9HOQm8Nf0VgsCdXmRdLZzpfrxN6f0q1uylDPhW4pRKWPunUL1kyVIIf UFFe0auD32Mz43nzm55cbZU5wCpGUGbza/vBfrm8JWlaLWV6hIpGjtxQVQdJiSfbOIrT K/FqdhLTbA3gVVEjwur3IWjTA16YxMrEupaW0= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=W0nhS4UnQmdvH2/Fee8/eLMJHHuhZlrFTir4zKxO7ucn2IgB3+HomAQzJF4HiNKfYL u3EW3JiP/HpBEtVM2T9qdisG59rbW7n+oEgnTlCUmeXOyQ6w9bdD18jc1UJ4xnhViPO7 5tNKs8POfHU5iiS5Ycxko+eHlAIcNc8fvYRRg= Received: by 10.227.145.144 with SMTP id d16mr1625541wbv.64.1276251617697; Fri, 11 Jun 2010 03:20:17 -0700 (PDT) Received: from localhost.localdomain (host81-90-static.72-81-b.business.telecomitalia.it [81.72.90.81]) by mx.google.com with ESMTPS id p17sm530613wbe.14.2010.06.11.03.20.15 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 11 Jun 2010 03:20:16 -0700 (PDT) From: Raffaele Recalcati To: davinci-linux-open-source@linux.davincidsp.com Subject: [PATCH 10/14] DaVinci: dm365: Added clokout2 management and set_sysclk_rate Date: Fri, 11 Jun 2010 12:19:50 +0200 Message-Id: <1276251594-5936-10-git-send-email-lamiaposta71@gmail.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1276251594-5936-1-git-send-email-lamiaposta71@gmail.com> References: <1276251594-5936-1-git-send-email-lamiaposta71@gmail.com> X-pstn-neptune: 0/0/0.00/0 X-pstn-levels: (S:53.18232/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] Cc: Raffaele Recalcati 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: , MIME-Version: 1.0 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]); Fri, 11 Jun 2010 10:25:08 +0000 (UTC) diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 054c303..464c289 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -144,6 +144,69 @@ int clk_set_rate(struct clk *clk, unsigned long rate) } EXPORT_SYMBOL(clk_set_rate); +int clkout2_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; + struct clk *parent = clk; + + if (clk == NULL || IS_ERR(clk)) + return ret; + if (!cpu_is_davinci_dm365()) + return -ENODEV; + + while (parent->parent->parent) + parent = parent->parent; + + parent = clk->parent; + + if (parent == clk) + return -EPERM; + + pll = parent->pll_data; + regval = __raw_readl(IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + + PERI_CLKCTL)); + + i_min_err = min_err = INT_MAX; + for (i = 0x0F; 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 &= ~(0x0F << 3); + regval |= (i-1) << 3; + regval |= 1 << CLOCKOUT2EN; + __raw_writel(regval, IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + + PERI_CLKCTL)); + rate *= i; + + spin_lock_irqsave(&clockfw_lock, flags); + if (ret == 0) { + if (clk->recalc) + clk->rate = clk->recalc(clk); + propagate_rate(clk); + regval &= ~(1 << CLOCKOUT2EN); + __raw_writel(regval, IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + + PERI_CLKCTL)); + } else + return -EINVAL; + spin_unlock_irqrestore(&clockfw_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clkout2_set_rate); + int clk_set_parent(struct clk *clk, struct clk *parent) { unsigned long flags; @@ -254,7 +317,15 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) u32 v, plldiv; struct pll_data *pll; unsigned long rate = clk->rate; + struct clk *parent = clk; + + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + while (parent->parent->parent) + parent = parent->parent; + if (parent == clk) + return -EPERM; /* If this is the PLL base clock, no more calculations needed */ if (clk->pll_data) return rate; @@ -262,13 +333,13 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) if (WARN_ON(!clk->parent)) return rate; - rate = clk->parent->rate; + rate = parent->rate; + /* Otherwise, the parent must be a PLL */ - if (WARN_ON(!clk->parent->pll_data)) + if (WARN_ON(!parent->pll_data)) return rate; - - pll = clk->parent->pll_data; + pll = parent->pll_data; /* If pre-PLL, source clock is before the multiplier and divider(s) */ if (clk->flags & PRE_PLL) @@ -286,6 +357,7 @@ static unsigned long clk_sysclk_recalc(struct clk *clk) return rate; } +EXPORT_SYMBOL(clk_sysclk_recalc); static unsigned long clk_leafclk_recalc(struct clk *clk) { @@ -433,6 +505,39 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, } EXPORT_SYMBOL(davinci_set_pllrate); +int set_sysclk_rate(struct clk *clk, unsigned long rate) +{ + u32 clk_freq_min, clk_freq_max, plldiv; + struct pll_data *pll; + struct clk *parent = clk; + + while (parent->parent->parent) + parent = parent->parent; + if (parent == clk) + return -EPERM; + + clk_freq_max = parent->rate; + pll = parent->pll_data; + if (clk->flags & PRE_PLL) + clk_freq_max = pll->input_rate; + + if (!clk->div_reg) + return -EPERM; + + 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 >> 1)) + plldiv--; + __raw_writel(plldiv & 0x1F, pll->base + clk->div_reg); + __raw_writel(plldiv | 0x8000, pll->base + clk->div_reg); + clk->rate = rate; + return 0; +} +EXPORT_SYMBOL(set_sysclk_rate); + int __init davinci_clk_init(struct clk_lookup *clocks) { struct clk_lookup *c; diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index 01e3648..74ba65f 100644 --- a/arch/arm/mach-davinci/clock.h +++ b/arch/arm/mach-davinci/clock.h @@ -50,6 +50,11 @@ #define PLLDIV_EN BIT(15) #define PLLDIV_RATIO_MASK 0x1f +#define PERI_CLKCTL 0x48 +#define CLOCKOUT2EN 2 +#define CLOCKOUT1EN 1 +#define CLOCKOUT0EN 0 + /* * OMAP-L138 system reference guide recommends a wait for 4 OSCIN/CLKIN * cycles to ensure that the PLLC has switched to bypass mode. Delay of 1us @@ -95,6 +100,14 @@ 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); @@ -121,6 +134,7 @@ int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv, extern struct platform_device davinci_wdt_device; extern void davinci_watchdog_reset(struct platform_device *); +int set_sysclk_rate(struct clk *clk, unsigned long rate); #endif diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index e4ead0a..40aab63 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -40,6 +40,15 @@ #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 + + static struct pll_data pll1_data = { .num = 1, @@ -124,6 +133,7 @@ static struct clk pll1_sysclk6 = { .parent = &pll1_clk, .flags = CLK_PLL, .div_reg = PLLDIV6, + .set_rate = set_sysclk_rate, }; static struct clk pll1_sysclk7 = { @@ -147,6 +157,15 @@ static struct clk pll1_sysclk9 = { .div_reg = PLLDIV9, }; +static struct clk clkout2_clk = { + .name = "clkout2", + .parent = &pll1_sysclk9, + .flags = CLK_PLL, + .div_reg = PLLDIV9, + .set_rate = set_sysclk_rate, +}; + + static struct clk pll2_clk = { .name = "pll2", .parent = &ref_clk, @@ -421,6 +440,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 +487,6 @@ static struct clk_lookup dm365_clks[] = { /*----------------------------------------------------------------------*/ -#define INTMUX 0x18 -#define EVTMUX 0x1c - static const struct mux_config dm365_pins[] = { #ifdef CONFIG_DAVINCI_MUX diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h index a3b0402..4296080 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 clkout2_set_rate(struct clk *clk, unsigned long rate); + + #endif