From patchwork Mon Oct 22 11:52:05 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hatim Ali X-Patchwork-Id: 12396 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 094DB23EF8 for ; Mon, 22 Oct 2012 11:58:14 +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 AF0C1A19432 for ; Mon, 22 Oct 2012 11:58:13 +0000 (UTC) Received: by mail-ie0-f180.google.com with SMTP id e10so3276484iej.11 for ; Mon, 22 Oct 2012 04:58:13 -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=sPkp8E9BGNFhuhwE+2ZkkqMoyWpgrh+iiNgDn6hhaJ0=; b=Ns7MU+qbWE3Z9Ti8+7Y0hpHbrfiZHpktV+Jr6LMDlY5w8DtJQyayYzGaFrj6NDG/1q USBdvHx1R1Su8NN3UYLF7PNXtaI8uzbGvLH7p5pxgbgFZneh7wS3s2y9siipl1G9VCbH LsgFB52y/qrUwbdq2RQZKM6tNvdGfvVjMqTYMALcBN5qp9/cdTFqSU4L8C1iS73PCAo0 em6K3/xiK1ARKTSIs2ltDtOoqthWsG6plV9c9GT7MD5FeF9GSpWQoiPSdZVfjeNA90r1 j3o6D7OXc5OySVmcceEaHUmilcPJMtI1VKzxIfqO9V+DdLOV+51SLp9Tqe6Ad/K40UHu xrMA== Received: by 10.50.168.37 with SMTP id zt5mr8746488igb.57.1350907093399; Mon, 22 Oct 2012 04:58:13 -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 n20csp218535igt; Mon, 22 Oct 2012 04:58:12 -0700 (PDT) Received: by 10.68.226.136 with SMTP id rs8mr29263575pbc.153.1350907091901; Mon, 22 Oct 2012 04:58:11 -0700 (PDT) Received: from mailout2.samsung.com (mailout2.samsung.com. [203.254.224.25]) by mx.google.com with ESMTP id yl9si13558987pbc.2.2012.10.22.04.58.11; Mon, 22 Oct 2012 04:58:11 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of hatim.rv@samsung.com designates 203.254.224.25 as permitted sender) client-ip=203.254.224.25; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of hatim.rv@samsung.com designates 203.254.224.25 as permitted sender) smtp.mail=hatim.rv@samsung.com Received: from epcpsbgm1.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout2.samsung.com (Oracle Communications Messaging Server 7u4-24.01(7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0MCA0088UMKAESQ0@mailout2.samsung.com> for patches@linaro.org; Mon, 22 Oct 2012 20:58:10 +0900 (KST) Received: from epcpsbgm1.samsung.com ( [172.20.52.125]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 51.DD.01231.2D435805; Mon, 22 Oct 2012 20:58:10 +0900 (KST) X-AuditID: cbfee61a-b7fa66d0000004cf-17-508534d2d8f4 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id 01.DD.01231.2D435805; Mon, 22 Oct 2012 20:58:10 +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 <0MCA006A7MH2ZQ10@mmp1.samsung.com> for patches@linaro.org; Mon, 22 Oct 2012 20:58:10 +0900 (KST) From: Hatim Ali To: u-boot@lists.denx.de Cc: sjg@chromium.org, promsoft@gmail.com, patches@linaro.org Subject: [PATCH 2/6 V7] EXYNOS: Add clock for SPI. Date: Mon, 22 Oct 2012 17:22:05 +0530 Message-id: <1350906729-23749-3-git-send-email-hatim.rv@samsung.com> X-Mailer: git-send-email 1.7.2.3 In-reply-to: <1350906729-23749-1-git-send-email-hatim.rv@samsung.com> References: <1350906729-23749-1-git-send-email-hatim.rv@samsung.com> DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFrrNLMWRmVeSWpSXmKPExsWyRsSkVveSSWuAwbfLmhZTDn9hcWD0uHNt D1sAYxSXTUpqTmZZapG+XQJXxr6d25kKNmhUHHl2hrGBcYtCFyMnh4SAiUT3g14WCFtM4sK9 9WxdjFwcQgJLGSU+/T7HDFN0/8dsdojEIkaJjy9uQlUtYpI4fbWdFaSKTUBNYv3rTjYQW0RA QuJX/1VGEJtZwEZiSc89IJuDQ1jASOL8bTWQMIuAqsTk+5vANvMKuEhcmvWWFWKZgsSrG2vZ QWxOAVeJ+/0drCCtQkA183sVIVoFJL5NPsQCEpYQkJXYdIAZ5BoJgctsEkvXfIUaIylxcMUN lgmMwgsYGVYxiqYWJBcUJ6XnGuoVJ+YWl+al6yXn525iBIbg6X/PpHYwrmywOMQowMGoxMOr odAaIMSaWFZcmXuIUYKDWUmE94oYUIg3JbGyKrUoP76oNCe1+BCjD9AlE5mlRJPzgfGRVxJv aGxibmpsamlkZGZqikNYSZy32SMlQEggPbEkNTs1tSC1CGYcEwenVANjTDTTtrwZXVInxS1m CGRJ+/CYHVNaV8ByVLr6npb/is5t58rPvOIKVxQ89dwoZp2DMVNn9NWwD1bf5YoYPmpPXD+n TeNew2OvwkteanqX1v0+/+L9/NNGe/g5j9i2RAgE/f0b6rk6Uq2N43XbFmFRzcA3f+PfGGVl 3PCtyd3WPav0nswdNlYlluKMREMt5qLiRACY5JGHbgIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupikeLIzCtJLcpLzFFi42I5/e+xgO4lk9YAg58LlCymHP7C4sDocefa HrYAxqgGRpuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxUWyUXnwBdt8wc oLFKCmWJOaVAoYDE4mIlfTtME0JD3HQtYBojdH1DguB6jAzQQMIaxox9O7czFWzQqDjy7Axj A+MWhS5GTg4JAROJ+z9ms0PYYhIX7q1n62Lk4hASWMQo8fHFTRiHSeL01XZWkCo2ATWJ9a87 2UBsEQEJiV/9VxlBbGYBG4klPfeAbA4OYQEjifO31UDCLAKqEpPvb2IBsXkFXCQuzXrLCrFM QeLVjbVgizkFXCXu93ewgrQKAdXM71WcwMi7gJFhFaNoakFyQXFSeq6hXnFibnFpXrpecn7u JkZwgD+T2sG4ssHiEKMAB6MSD6+GQmuAEGtiWXFl7iFGCQ5mJRHeK2JAId6UxMqq1KL8+KLS nNTiQ4w+QEdNZJYSTc4HRl9eSbyhsYm5qbGppYmFiZklDmElcd5mj5QAIYH0xJLU7NTUgtQi mHFMHJxSDYxrGIq+rpi8sV0/4pVFvuiH6Bbmm5uv/1mW4lZld5SPRe9lVAuPWcIl/aC0b19/ r7Hcqyx/uqh06aJlsw6rvp0s+XunX/GpOTO2/ip1SXk2UbjXfv+uyQ9TDxzv2bFrxqXOmTw9 n/h/Fiyukn1gp2sY7LOXa+0blg0uD/Mq51R4nbjOGuH+/NgMJZbijERDLeai4kQATlJQjp0C AAA= X-CFilter-Loop: Reflected X-Gm-Message-State: ALoCoQm3QtJJdkXhPaOmmWHLUA9eVAgn2FgAlmZKYgTyLN1uMb4ZOhGRcM7HPUuqclnOlOXfu0wy 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 Signed-off-by: Hatim Ali Acked-by: Simon Glass --- Changes since v4: Added Signed-off-by of James Miller Changes since v5: Incorporated review comments by Minkyu Kang Changes since v6: Based on the review by Minkyu Kang, moved the include periph.h define to clock.c file diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 4f3b451..e6c46da 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -25,6 +25,7 @@ #include #include #include +#include /* exynos4: return pll clock frequency */ static unsigned long exynos4_get_pll_clk(int pllreg) @@ -732,6 +733,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_set_spi_clk(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 +920,11 @@ void set_mipi_clk(void) if (cpu_is_exynos4()) exynos4_set_mipi_clk(); } + +int set_spi_clk(int periph_id, unsigned int rate) +{ + if (cpu_is_exynos5()) + return exynos5_set_spi_clk(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..c0a3455 100644 --- a/arch/arm/include/asm/arch-exynos/clk.h +++ b/arch/arm/include/asm/arch-exynos/clk.h @@ -38,5 +38,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 set_spi_clk(int periph_id, unsigned int rate); #endif