From patchwork Tue Oct 16 10:58:42 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hatim Ali X-Patchwork-Id: 12268 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 488E4214A95 for ; Tue, 16 Oct 2012 11:04:20 +0000 (UTC) Received: from mail-ie0-f180.google.com (mail-ie0-f180.google.com [209.85.223.180]) by fiordland.canonical.com (Postfix) with ESMTP id CDDE9A18F8A for ; Tue, 16 Oct 2012 11:04:19 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id e10so9240475iej.11 for ; Tue, 16 Oct 2012 04:04:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:x-auditid :from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :dlp-filter:x-mtr:x-brightmail-tracker:x-brightmail-tracker :x-cfilter-loop:x-gm-message-state; bh=+Du0AEYLCjOhmFKLv7fiIcRXML3rI4mS/PhNWc5VRlM=; b=egbIYlaCL6FepMvWQJ1Y3pO0MmD3cZHqnFwzGhs9brMucN8ktbWlsEL9MmZ2ISLNau dLrr57rOU45qsEB2ENJeA0Rx4iq/gqeXtTjbJIxHLC69OF0H3+AJLK43fqA8NRlSlOma sz8Q4Oeu+VCDZHVWcsidkLS/pHx14B5vM3LBgG4/Kj8/6m7xrc6LWzqlE9m5vMdp62L3 UWN+yvs98neB/rKWJwO8TvAfPtjuWqMev58k2WQJYRMPSQDtk65Kw/06OTqDuvd8V33m QPtyUH7T8vAInpB9RDOMRNojXzMTrr1E+9UsgzvF+G6f6IOHdj2pFibXn2/IIjat+z2p j+NQ== Received: by 10.50.168.37 with SMTP id zt5mr11398720igb.57.1350385459590; Tue, 16 Oct 2012 04:04:19 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.50.67.148 with SMTP id n20csp708987igt; Tue, 16 Oct 2012 04:04:19 -0700 (PDT) Received: by 10.66.88.4 with SMTP id bc4mr40642918pab.42.1350385458784; Tue, 16 Oct 2012 04:04:18 -0700 (PDT) Received: from mailout3.samsung.com (mailout3.samsung.com. [203.254.224.33]) by mx.google.com with ESMTP id mo5si26276101pbc.178.2012.10.16.04.04.18; Tue, 16 Oct 2012 04:04:18 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of hatim.rv@samsung.com designates 203.254.224.33 as permitted sender) client-ip=203.254.224.33; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of hatim.rv@samsung.com designates 203.254.224.33 as permitted sender) smtp.mail=hatim.rv@samsung.com Received: from epcpsbgm1.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout3.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MBZ001TZG356DX0@mailout3.samsung.com> for patches@linaro.org; Tue, 16 Oct 2012 20:04:17 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.124]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id C6.A0.07865.13F3D705; Tue, 16 Oct 2012 20:04:17 +0900 (KST) X-AuditID: cbfee61a-b7f976d000001eb9-54-507d3f318c0c Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 66.A0.07865.13F3D705; Tue, 16 Oct 2012 20:04:17 +0900 (KST) Received: from hatim-linux.sisodomain.com ([107.108.73.95]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0MBZ0099QFZTVV60@mmp1.samsung.com> for patches@linaro.org; Tue, 16 Oct 2012 20:04:17 +0900 (KST) From: Hatim Ali To: u-boot@lists.denx.de Cc: promsoft@gmail.com, patches@linaro.org, sjg@chromium.org Subject: [PATCH 2/6 V5] EXYNOS: Add clock for SPI. Date: Tue, 16 Oct 2012 16:28:42 +0530 Message-id: <1350385126-19312-3-git-send-email-hatim.rv@samsung.com> X-Mailer: git-send-email 1.7.2.3 In-reply-to: <1350385126-19312-1-git-send-email-hatim.rv@samsung.com> References: <1350385126-19312-1-git-send-email-hatim.rv@samsung.com> DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrLLMWRmVeSWpSXmKPExsWyRsSkRtfQvjbA4G6zssWUw19YHBg97lzb wxbAGMVlk5Kak1mWWqRvl8CV0f94F1tBk0bF3oZlzA2MfQpdjJwcEgImEhcnzmOEsMUkLtxb z9bFyMUhJLCUUeLDjBWMMEVTn85kh0gsYpRY0HEIxmGSePSxnxWkik1ATWL96042EFtEQELi V/9VsG5mARuJz5cng9nCAkYSu1tngNWzCKhKXNt1AKyeV8BFYs/ehawQ2xQkXt1Yyw5icwq4 Sjxa1wHWKwRUc+riJEaIXgGJb5MPsXQxcgDVy0psOsAMco+EwGU2iT9vT7NAzJGUOLjiBssE RuEFjAyrGEVTC5ILipPScw31ihNzi0vz0vWS83M3MQLD8PS/Z1I7GFc2WBxiFOBgVOLhzXCu CRBiTSwrrsw9xCjBwawkwqtqWxsgxJuSWFmVWpQfX1Sak1p8iNEH6JKJzFKiyfnAGMkriTc0 NjE3NTa1NDIyMzXFIawkztvskRIgJJCeWJKanZpakFoEM46Jg1OqgbH83amj51nr/9nunjtt 1ae9cqvLmULjv5/aoL5InV/gg5C8/l2vSbPX/t4SdidS5WVp0i+xs2eT0g9Jt1Y33pZRPZKQ sOkAJ3NjhjSDcmmzPPcy5bo+PpYb9We+TnK7pXnNJ7lDXFO/652wQGpnW3lmqf4DLtsjsY33 JAKu3pQ78NutKbRvuRJLcUaioRZzUXEiAP3Gs0lwAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFuphkeLIzCtJLcpLzFFi42I5/e+xgK6hfW2AwdotIhZTDn9hcWD0uHNt D1sAY1QDo01GamJKapFCal5yfkpmXrqtkndwvHO8qZmBoa6hpYW5kkJeYm6qrZKLT4CuW2YO 0FglhbLEnFKgUEBicbGSvh2mCaEhbroWMI0Rur4hQXA9RgZoIGENY0b/411sBU0aFXsbljE3 MPYpdDFyckgImEhMfTqTHcIWk7hwbz1bFyMXh5DAIkaJBR2H2KEcJolHH/tZQarYBNQk1r/u ZAOxRQQkJH71X2UEsZkFbCQ+X54MZgsLGEnsbp0BVs8ioCpxbdcBsHpeAReJPXsXskJsU5B4 dWMt2GZOAVeJR+s6wHqFgGpOXZzEOIGRdwEjwypG0dSC5ILipPRcQ73ixNzi0rx0veT83E2M 4CB/JrWDcWWDxSFGAQ5GJR7eDOeaACHWxLLiytxDjBIczEoivKq2tQFCvCmJlVWpRfnxRaU5 qcWHGH2ArprILCWanA+MwLySeENjE3NTY1NLEwsTM0scwkrivM0eKQFCAumJJanZqakFqUUw 45g4OKUaGM/fW89t49u9jkX7yqFDhpnH9ZZs/t/NeiP93/JniSfY+tUaDS5rpR96xVfpzt48 qWHJlT17b0+yemX/z6Q7xnyLzLxNlyuTc5hEDwlKv/bx41S/Z2M875apzwG501ln8uL/H/Kd tF59msgS5s+rZk7akxqWXX2mv2PTu3Me+vsDshjOeV8/cE6JpTgj0VCLuag4EQDC9YENnwIA AA== X-CFilter-Loop: Reflected X-Gm-Message-State: ALoCoQl2zPobCq+PvKNLWyEL4+bKsu7hjysuVN2N1q13PmXqxkJg0Cqu+1m1rH9qYlLt+7omY0h0 From: Rajeshwari Shinde This patch adds api to calculate and set the clock for SPI channels Signed-off-by: James Miller Signed-off-by: Simon Glass Signed-off-by: Rajeshwari Shinde --- Changes since v4: Added Signed-off-by of James Miller arch/arm/cpu/armv7/exynos/clock.c | 124 ++++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-exynos/clk.h | 4 +- 2 files changed, 127 insertions(+), 1 deletions(-) diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 4f3b451..44dff2b 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -732,6 +732,122 @@ static unsigned long exynos5_get_i2c_clk(void) return aclk_66; } +/** + * Linearly searches for the most accurate main and fine stage clock scalars + * (divisors) for a specified target frequency and scalar bit sizes by checking + * all multiples of main_scalar_bits values. Will always return scalars up to or + * slower than target. + * + * @param main_scalar_bits Number of main scalar bits, must be > 0 and < 32 + * @param fine_scalar_bits Number of fine scalar bits, must be > 0 and < 32 + * @param input_freq Clock frequency to be scaled in Hz + * @param target_freq Desired clock frequency in Hz + * @param best_fine_scalar Pointer to store the fine stage divisor + * + * @return best_main_scalar Main scalar for desired frequency or -1 if none + * found + */ +static int clock_calc_best_scalar(unsigned int main_scaler_bits, + unsigned int fine_scalar_bits, unsigned int input_rate, + unsigned int target_rate, unsigned int *best_fine_scalar) +{ + int i; + int best_main_scalar = -1; + unsigned int best_error = target_rate; + const unsigned int cap = (1 << fine_scalar_bits) - 1; + const unsigned int loops = 1 << main_scaler_bits; + + debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate, + target_rate, cap); + + assert(best_fine_scalar != NULL); + assert(main_scaler_bits <= fine_scalar_bits); + + *best_fine_scalar = 1; + + if (input_rate == 0 || target_rate == 0) + return -1; + + if (target_rate >= input_rate) + return 1; + + for (i = 1; i <= loops; i++) { + const unsigned int effective_div = max(min(input_rate / i / + target_rate, cap), 1); + const unsigned int effective_rate = input_rate / i / + effective_div; + const int error = target_rate - effective_rate; + + debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div, + effective_rate, error); + + if (error >= 0 && error <= best_error) { + best_error = error; + best_main_scalar = i; + *best_fine_scalar = effective_div; + } + } + + return best_main_scalar; +} + +static int exynos5_spi_set_clock_rate(enum periph_id periph_id, + unsigned int rate) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + int main; + unsigned int fine; + unsigned shift, pre_shift; + unsigned mask = 0xff; + u32 *reg; + + main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); + if (main < 0) { + debug("%s: Cannot set clock rate for periph %d", + __func__, periph_id); + return -1; + } + main = main - 1; + fine = fine - 1; + + switch (periph_id) { + case PERIPH_ID_SPI0: + reg = &clk->div_peric1; + shift = 0; + pre_shift = 8; + break; + case PERIPH_ID_SPI1: + reg = &clk->div_peric1; + shift = 16; + pre_shift = 24; + break; + case PERIPH_ID_SPI2: + reg = &clk->div_peric2; + shift = 0; + pre_shift = 8; + break; + case PERIPH_ID_SPI3: + reg = &clk->sclk_div_isp; + shift = 0; + pre_shift = 4; + break; + case PERIPH_ID_SPI4: + reg = &clk->sclk_div_isp; + shift = 12; + pre_shift = 16; + break; + default: + debug("%s: Unsupported peripheral ID %d\n", __func__, + periph_id); + return -1; + } + clrsetbits_le32(reg, mask << shift, (main & mask) << shift); + clrsetbits_le32(reg, mask << pre_shift, (fine & mask) << pre_shift); + + return 0; +} + unsigned long get_pll_clk(int pllreg) { if (cpu_is_exynos5()) @@ -803,3 +919,11 @@ void set_mipi_clk(void) if (cpu_is_exynos4()) exynos4_set_mipi_clk(); } + +int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate) +{ + if (cpu_is_exynos5()) + return exynos5_spi_set_clock_rate(periph_id, rate); + else + return 0; +} diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h index 5529025..4e51402 100644 --- a/arch/arm/include/asm/arch-exynos/clk.h +++ b/arch/arm/include/asm/arch-exynos/clk.h @@ -22,6 +22,8 @@ #ifndef __ASM_ARM_ARCH_CLK_H_ #define __ASM_ARM_ARCH_CLK_H_ +#include + #define APLL 0 #define MPLL 1 #define EPLL 2 @@ -38,5 +40,5 @@ void set_mmc_clk(int dev_index, unsigned int div); unsigned long get_lcd_clk(void); void set_lcd_clk(void); void set_mipi_clk(void); - +int spi_set_clock_rate(enum periph_id periph_id, unsigned int rate); #endif