From patchwork Wed Jul 21 10:51:49 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raffaele Recalcati X-Patchwork-Id: 116551 Received: from arroyo.ext.ti.com (arroyo.ext.ti.com [192.94.94.40]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o72FZv7f015517 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 2 Aug 2010 15:36:33 GMT Received: from dlep35.itg.ti.com ([157.170.170.118]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id o72FWxlU022966 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 2 Aug 2010 10:32:59 -0500 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep35.itg.ti.com (8.13.7/8.13.7) with ESMTP id o72FWw46022606; Mon, 2 Aug 2010 10:32:58 -0500 (CDT) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id B7DB08062C; Mon, 2 Aug 2010 10:32:56 -0500 (CDT) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp52.itg.ti.com (dflp52.itg.ti.com [128.247.22.96]) by linux.omap.com (Postfix) with ESMTP id A359D80626 for ; Wed, 21 Jul 2010 05:51:55 -0500 (CDT) Received: from red.ext.ti.com (localhost [127.0.0.1]) by dflp52.itg.ti.com (8.13.7/8.13.7) with ESMTP id o6LApsMi002735 for ; Wed, 21 Jul 2010 05:51:55 -0500 (CDT) Received: from psmtp.com (na3sys009amx164.postini.com [74.125.149.90]) by red.ext.ti.com (8.13.7/8.13.7) with SMTP id o6LAprcI031851 for ; Wed, 21 Jul 2010 05:51:54 -0500 Received: from source ([74.125.82.47]) by na3sys009amx164.postini.com ([74.125.148.10]) with SMTP; Wed, 21 Jul 2010 03:51:54 PDT Received: by wwb34 with SMTP id 34so784984wwb.4 for ; Wed, 21 Jul 2010 03:51:52 -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; bh=DKveYN9wETnb8Ue9BSgEU0GLFnOShHZ4cZywtJLpfMA=; b=mPjV+UsuK+1phLjI1xXQcGNzLmoXpVw9MyrlbkCvPm98TZdJc31SLBmea71oPdWlPW x0YeIhZfuEsRa8mV1ntpAsmUqdGNxokjcOxUCmXXaZKbkh6ajSrbz50RKurbo3S8ekPY RIDTQ1s0xhba+ATPSLgYXWTbe+HeOVZr1HeFc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer; b=vWofgZsNzHxFoZQ3K9R8K4yEI3OG3fb22rHBGtJmSDL6JC27vCzfdSlHP7Y3ynhtPr oHCf4yD/uAaRBEkRcx56s3CYv5Ez/09t5e7lwPUF7kHaRhpHwgFt5AtmzNUloHc+5gHk uCS3qvsBXsqnHRMMqQo9qi4I9CCdCjlOCJb+Y= Received: by 10.227.147.213 with SMTP id m21mr2177849wbv.46.1279709512745; Wed, 21 Jul 2010 03:51:52 -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 a1sm51690186wbb.2.2010.07.21.03.51.50 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 21 Jul 2010 03:51:51 -0700 (PDT) From: Raffaele Recalcati To: davinci-linux-open-source@linux.davincidsp.com Subject: [PATCH v2] DaVinci: dm365: Added clockout2 management. Date: Wed, 21 Jul 2010 12:51:49 +0200 Message-Id: <1279709510-6213-1-git-send-email-lamiaposta71@gmail.com> X-Mailer: git-send-email 1.7.0.4 X-pstn-neptune: 0/0/0.00/0 X-pstn-levels: (S:35.11842/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-Mailman-Approved-At: Mon, 02 Aug 2010 10:32:52 -0500 Cc: Raffaele Recalcati , Miguel Aguilar 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]); Mon, 02 Aug 2010 15:36:33 +0000 (UTC) diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index f29a526..6e45808 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -254,7 +254,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 +270,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) @@ -293,26 +301,33 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate) struct pll_data *pll; unsigned long input; unsigned ratio = 0; + struct clk *parent = clk; + + /* searching the right ancestor (pll1_clk or pll2_clk) */ + while (parent->parent->parent) + parent = parent->parent; + if (parent == clk) + return -EPERM; /* If this is the PLL base clock, wrong function to call */ if (clk->pll_data) return 0; /* There must be a parent... */ - if (WARN_ON(!clk->parent)) + if (WARN_ON(!parent)) return 0; /* ... the parent must be a PLL... */ - if (WARN_ON(!clk->parent->pll_data)) + if (WARN_ON(!parent->pll_data)) return 0; /* ... and this clock must have a divider. */ if (WARN_ON(!clk->div_reg)) return 0; - pll = clk->parent->pll_data; + pll = parent->pll_data; - input = clk->parent->rate; + input = parent->rate; /* If pre-PLL, source clock is before the multiplier and divider(s) */ if (clk->flags & PRE_PLL) @@ -343,6 +358,7 @@ int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate) return 0; } +EXPORT_SYMBOL(davinci_set_sysclk_rate); static unsigned long clk_leafclk_recalc(struct clk *clk) { diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h index a717d98..df36d73 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 diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 42fd4a4..902e9a0 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c @@ -40,6 +40,11 @@ #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 static struct pll_data pll1_data = { .num = 1, @@ -124,6 +129,7 @@ static struct clk pll1_sysclk6 = { .parent = &pll1_clk, .flags = CLK_PLL, .div_reg = PLLDIV6, + .set_rate = davinci_set_sysclk_rate, }; static struct clk pll1_sysclk7 = { @@ -145,6 +151,14 @@ static struct clk pll1_sysclk9 = { .parent = &pll1_clk, .flags = CLK_PLL, .div_reg = PLLDIV9, + .set_rate = davinci_set_sysclk_rate, +}; + +static struct clk clkout2_clk = { + .name = "clkout2", + .parent = &pll1_sysclk9, + .flags = CLK_PLL, + .set_rate = dm365_clkout2_set_rate, }; static struct clk pll2_clk = { @@ -421,6 +435,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), @@ -657,6 +672,48 @@ static struct resource dm365_spi0_resources[] = { }, }; +int dm365_clkout2_set_rate(unsigned long rate) +{ + int ret = -EINVAL; + int i, err, min_err, i_min_err; + u32 regval; + struct clk *clk; + static void __iomem *system_module_base; + + clk = &clkout2_clk; + system_module_base = ioremap(DAVINCI_SYSTEM_MODULE_BASE, SZ_4K); + regval = __raw_readl(system_module_base + PERI_CLKCTL); + + /* check all possibilities to get best fitting for the required freq */ + i_min_err = min_err = INT_MAX; + for (i = 0x0F; i > 0; i--) { + if (clk->parent->set_rate) { + ret = clk_set_rate(clk->parent, rate * i) ; + err = clk_get_rate(clk->parent) - rate * i; + if (min_err > abs(err)) { + min_err = abs(err); + i_min_err = i; + } + } + } + ret = clk_set_rate(clk->parent, rate * i_min_err) ; + if (ret) + return ret; + + /* setup DIV1 value */ + regval &= ~(0x0F << 3); + regval |= (i_min_err - 1) << 3; + + /* to make changes work stop CLOCKOUT & start it again */ + regval |= 1 << CLOCKOUT2EN; + __raw_writel(regval, system_module_base + PERI_CLKCTL); + regval &= ~(1 << CLOCKOUT2EN); + __raw_writel(regval, system_module_base + PERI_CLKCTL); + + return ret; +} +EXPORT_SYMBOL(dm365_clkout2_set_rate); + static struct platform_device dm365_spi0_device = { .name = "spi_davinci", .id = 0, diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h index ea5df3b..f59741f 100644 --- a/arch/arm/mach-davinci/include/mach/dm365.h +++ b/arch/arm/mach-davinci/include/mach/dm365.h @@ -49,4 +49,5 @@ void dm365_init_spi0(unsigned chipselect_mask, struct spi_board_info *info, unsigned len); void dm365_set_vpfe_config(struct vpfe_config *cfg); +int dm365_clkout2_set_rate(unsigned long rate); #endif /* __ASM_ARCH_DM365_H */