From nobody Sun May 12 17:07:48 2024 Delivered-To: importer2@patchew.org Received-SPF: pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org ARC-Seal: i=1; a=rsa-sha256; t=1621931788; cv=none; d=zohomail.com; s=zohoarc; b=oDVuRwgazAEPT66qzsEgecfDAnh/I6SIDNFb8II+4rHGD/nKIvyPV8HW4rlGGg1Y3pNQ21f2KI6bd3Hopph66s853HGceVRv+4I3yidFAp3dRve+48WbgC6z6mSzQNJBzqHyB4WfvW4He/DqMWw4ocm8YTGr4oZKN5E2g2ur0W4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1621931788; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:MIME-Version:Message-ID:References:Subject:To; bh=wkqz8l/kzNTGOmCWZqEF+Tc5t6aa2zv3K0aPoinZ46g=; b=CtNnLUOY7NsnZkiPuHIVIo+OdsWHLXfi/lWl2zwmxPQ6QQopO8Iv6nNyWcq8BBcTNrrH205iGa6UpSFkVzQnLXALWFfoK5eWTuVIzIyL4dyw9XXzAcTxYXgswSMl1p0iW3gXVgx7L5H9jjAbiBc8Z0HlAIpE9jfFfKEw+c1hjKY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mx.zohomail.com with SMTP id 162193178855569.76467768822624; Tue, 25 May 2021 01:36:28 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231922AbhEYIh4 (ORCPT ); Tue, 25 May 2021 04:37:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51430 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231590AbhEYIhw (ORCPT ); Tue, 25 May 2021 04:37:52 -0400 Received: from forward103j.mail.yandex.net (forward103j.mail.yandex.net [IPv6:2a02:6b8:0:801:2::106]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA476C061574 for ; Tue, 25 May 2021 01:36:21 -0700 (PDT) Received: from iva8-4db386e07e2e.qloud-c.yandex.net (iva8-4db386e07e2e.qloud-c.yandex.net [IPv6:2a02:6b8:c0c:951e:0:640:4db3:86e0]) by forward103j.mail.yandex.net (Yandex) with ESMTP id 4D48A6742072; Tue, 25 May 2021 11:36:17 +0300 (MSK) Received: from iva8-174eb672ffa9.qloud-c.yandex.net (iva8-174eb672ffa9.qloud-c.yandex.net [2a02:6b8:c0c:b995:0:640:174e:b672]) by iva8-4db386e07e2e.qloud-c.yandex.net (mxback/Yandex) with ESMTP id 4GQnb5OCDo-aGJ0cKjl; Tue, 25 May 2021 11:36:17 +0300 Received: by iva8-174eb672ffa9.qloud-c.yandex.net (smtp/Yandex) with ESMTPSA id 7BolJOt5tl-aFLqf3dR; Tue, 25 May 2021 11:36:15 +0300 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (Client certificate not present) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=maquefel.me; s=mail; t=1621931777; bh=wkqz8l/kzNTGOmCWZqEF+Tc5t6aa2zv3K0aPoinZ46g=; h=In-Reply-To:References:Date:Subject:To:From:Message-Id:Cc; b=a8DAPBgP32k0+Mv9WuKk4ZaTJJz8OdcOMLbi9iTTceHsquDEBJ0kPQ5MyPQf/Pope YmqsI15bag+MA7jyKzYXykotiWy1UqEllRSAvqzCl/DOcTPQIi5pyLATz29ds3YvH+ EyFelP/9FALkPHCm0Jxv5e0QxEp08MAollZ8GqjM= Authentication-Results: iva8-4db386e07e2e.qloud-c.yandex.net; dkim=pass header.i=@maquefel.me From: Nikita Shubin Cc: Nikita Shubin , Russell King , Hartley Sweeten , Alexander Sverdlin , Arnd Bergmann , Linus Walleij , Ard Biesheuvel , Mike Rapoport , Gregory Fong , Geert Uytterhoeven , YiFei Zhu , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/1] ep93xx: clock: convert in-place to COMMON_CLK Date: Tue, 25 May 2021 11:33:39 +0300 Message-Id: <20210525083340.27722-2-nikita.shubin@maquefel.me> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210525083340.27722-1-nikita.shubin@maquefel.me> References: <20210525083340.27722-1-nikita.shubin@maquefel.me> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Converted in-place without moving file to drivers/clk. tested on ts7250 (EP9302). Only setting rate and change parent tested for, as they are missing on ts7250: - video - I2S - ADC/KEYPAD - PWM Only video and I2S clock are interesting, as they are GATE + double DIV + MUX, all other are pretty much common but require ep93xx_syscon_swlocked_write to set registers. --- arch/arm/Kconfig | 2 +- arch/arm/mach-ep93xx/clock.c | 989 ++++++++++++++++++++--------------- arch/arm/mach-ep93xx/core.c | 2 +- arch/arm/mach-ep93xx/soc.h | 42 +- 4 files changed, 593 insertions(+), 442 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2fae14857dcf..4a1a8957aa1b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -354,7 +354,7 @@ config ARCH_EP93XX select CLKSRC_MMIO select CPU_ARM920T select GPIOLIB - select HAVE_LEGACY_CLK + select COMMON_CLK help This enables support for the Cirrus EP93xx series of CPUs. =20 diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 2810eb5b2aca..f728eb96a288 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -16,6 +16,7 @@ #include #include #include +#include #include =20 #include "hardware.h" @@ -24,348 +25,194 @@ =20 #include "soc.h" =20 -struct clk { - struct clk *parent; - unsigned long rate; - int users; - int sw_locked; - void __iomem *enable_reg; - u32 enable_mask; - - unsigned long (*get_rate)(struct clk *clk); - int (*set_rate)(struct clk *clk, unsigned long rate); -}; - - -static unsigned long get_uart_rate(struct clk *clk); - -static int set_keytchclk_rate(struct clk *clk, unsigned long rate); -static int set_div_rate(struct clk *clk, unsigned long rate); -static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate); -static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate); +static DEFINE_SPINLOCK(clk_lock); =20 -static struct clk clk_xtali =3D { - .rate =3D EP93XX_EXT_CLK_RATE, -}; -static struct clk clk_uart1 =3D { - .parent =3D &clk_xtali, - .sw_locked =3D 1, - .enable_reg =3D EP93XX_SYSCON_DEVCFG, - .enable_mask =3D EP93XX_SYSCON_DEVCFG_U1EN, - .get_rate =3D get_uart_rate, -}; -static struct clk clk_uart2 =3D { - .parent =3D &clk_xtali, - .sw_locked =3D 1, - .enable_reg =3D EP93XX_SYSCON_DEVCFG, - .enable_mask =3D EP93XX_SYSCON_DEVCFG_U2EN, - .get_rate =3D get_uart_rate, -}; -static struct clk clk_uart3 =3D { - .parent =3D &clk_xtali, - .sw_locked =3D 1, - .enable_reg =3D EP93XX_SYSCON_DEVCFG, - .enable_mask =3D EP93XX_SYSCON_DEVCFG_U3EN, - .get_rate =3D get_uart_rate, -}; -static struct clk clk_pll1 =3D { - .parent =3D &clk_xtali, -}; -static struct clk clk_f =3D { - .parent =3D &clk_pll1, -}; -static struct clk clk_h =3D { - .parent =3D &clk_pll1, -}; -static struct clk clk_p =3D { - .parent =3D &clk_pll1, -}; -static struct clk clk_pll2 =3D { - .parent =3D &clk_xtali, -}; -static struct clk clk_usb_host =3D { - .parent =3D &clk_pll2, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_USH_EN, -}; -static struct clk clk_keypad =3D { - .parent =3D &clk_xtali, - .sw_locked =3D 1, - .enable_reg =3D EP93XX_SYSCON_KEYTCHCLKDIV, - .enable_mask =3D EP93XX_SYSCON_KEYTCHCLKDIV_KEN, - .set_rate =3D set_keytchclk_rate, -}; -static struct clk clk_adc =3D { - .parent =3D &clk_xtali, - .sw_locked =3D 1, - .enable_reg =3D EP93XX_SYSCON_KEYTCHCLKDIV, - .enable_mask =3D EP93XX_SYSCON_KEYTCHCLKDIV_TSEN, - .set_rate =3D set_keytchclk_rate, -}; -static struct clk clk_spi =3D { - .parent =3D &clk_xtali, - .rate =3D EP93XX_EXT_CLK_RATE, -}; -static struct clk clk_pwm =3D { - .parent =3D &clk_xtali, - .rate =3D EP93XX_EXT_CLK_RATE, -}; +static char fclk_divisors[] =3D { 1, 2, 4, 8, 16, 1, 1, 1 }; +static char hclk_divisors[] =3D { 1, 2, 4, 5, 6, 8, 16, 32 }; +static char pclk_divisors[] =3D { 1, 2, 4, 8 }; =20 -static struct clk clk_video =3D { - .sw_locked =3D 1, - .enable_reg =3D EP93XX_SYSCON_VIDCLKDIV, - .enable_mask =3D EP93XX_SYSCON_CLKDIV_ENABLE, - .set_rate =3D set_div_rate, -}; +static char adc_divisors[] =3D { 16, 4 }; +static char sclk_divisors[] =3D { 2, 4 }; +static char lrclk_divisors[] =3D { 32, 64, 128 }; =20 -static struct clk clk_i2s_mclk =3D { - .sw_locked =3D 1, - .enable_reg =3D EP93XX_SYSCON_I2SCLKDIV, - .enable_mask =3D EP93XX_SYSCON_CLKDIV_ENABLE, - .set_rate =3D set_div_rate, +static const char * const mux_parents[] =3D { + "xtali", + "pll1", + "pll2" }; =20 -static struct clk clk_i2s_sclk =3D { - .sw_locked =3D 1, - .parent =3D &clk_i2s_mclk, - .enable_reg =3D EP93XX_SYSCON_I2SCLKDIV, - .enable_mask =3D EP93XX_SYSCON_I2SCLKDIV_SENA, - .set_rate =3D set_i2s_sclk_rate, -}; +/* + * PLL rate =3D 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^= PS + */ +static unsigned long calc_pll_rate(unsigned long long rate, u32 config_wor= d) +{ + int i; =20 -static struct clk clk_i2s_lrclk =3D { - .sw_locked =3D 1, - .parent =3D &clk_i2s_sclk, - .enable_reg =3D EP93XX_SYSCON_I2SCLKDIV, - .enable_mask =3D EP93XX_SYSCON_I2SCLKDIV_SENA, - .set_rate =3D set_i2s_lrclk_rate, -}; + rate *=3D ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ + rate *=3D ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ + do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ + for (i =3D 0; i < ((config_word >> 16) & 3); i++) /* PS */ + rate >>=3D 1; =20 -/* DMA Clocks */ -static struct clk clk_m2p0 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P0, -}; -static struct clk clk_m2p1 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P1, -}; -static struct clk clk_m2p2 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P2, -}; -static struct clk clk_m2p3 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P3, -}; -static struct clk clk_m2p4 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P4, -}; -static struct clk clk_m2p5 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P5, -}; -static struct clk clk_m2p6 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P6, -}; -static struct clk clk_m2p7 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P7, -}; -static struct clk clk_m2p8 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P8, -}; -static struct clk clk_m2p9 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2P9, -}; -static struct clk clk_m2m0 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2M0, -}; -static struct clk clk_m2m1 =3D { - .parent =3D &clk_h, - .enable_reg =3D EP93XX_SYSCON_PWRCNT, - .enable_mask =3D EP93XX_SYSCON_PWRCNT_DMA_M2M1, -}; + return (unsigned long)rate; +} =20 -#define INIT_CK(dev,con,ck) \ - { .dev_id =3D dev, .con_id =3D con, .clk =3D ck } - -static struct clk_lookup clocks[] =3D { - INIT_CK(NULL, "xtali", &clk_xtali), - INIT_CK("apb:uart1", NULL, &clk_uart1), - INIT_CK("apb:uart2", NULL, &clk_uart2), - INIT_CK("apb:uart3", NULL, &clk_uart3), - INIT_CK(NULL, "pll1", &clk_pll1), - INIT_CK(NULL, "fclk", &clk_f), - INIT_CK(NULL, "hclk", &clk_h), - INIT_CK(NULL, "apb_pclk", &clk_p), - INIT_CK(NULL, "pll2", &clk_pll2), - INIT_CK("ohci-platform", NULL, &clk_usb_host), - INIT_CK("ep93xx-keypad", NULL, &clk_keypad), - INIT_CK("ep93xx-adc", NULL, &clk_adc), - INIT_CK("ep93xx-fb", NULL, &clk_video), - INIT_CK("ep93xx-spi.0", NULL, &clk_spi), - INIT_CK("ep93xx-i2s", "mclk", &clk_i2s_mclk), - INIT_CK("ep93xx-i2s", "sclk", &clk_i2s_sclk), - INIT_CK("ep93xx-i2s", "lrclk", &clk_i2s_lrclk), - INIT_CK(NULL, "pwm_clk", &clk_pwm), - INIT_CK(NULL, "m2p0", &clk_m2p0), - INIT_CK(NULL, "m2p1", &clk_m2p1), - INIT_CK(NULL, "m2p2", &clk_m2p2), - INIT_CK(NULL, "m2p3", &clk_m2p3), - INIT_CK(NULL, "m2p4", &clk_m2p4), - INIT_CK(NULL, "m2p5", &clk_m2p5), - INIT_CK(NULL, "m2p6", &clk_m2p6), - INIT_CK(NULL, "m2p7", &clk_m2p7), - INIT_CK(NULL, "m2p8", &clk_m2p8), - INIT_CK(NULL, "m2p9", &clk_m2p9), - INIT_CK(NULL, "m2m0", &clk_m2m0), - INIT_CK(NULL, "m2m1", &clk_m2m1), +struct clk_psc { + struct clk_hw hw; + void __iomem *reg; + u8 bit_idx; + u32 mask; + u8 shift; + u8 width; + char *div; + u8 num_div; + spinlock_t *lock; }; =20 -static DEFINE_SPINLOCK(clk_lock); +#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw) =20 -static void __clk_enable(struct clk *clk) +static int ep93xx_clk_is_enabled(struct clk_hw *hw) { - if (!clk->users++) { - if (clk->parent) - __clk_enable(clk->parent); - - if (clk->enable_reg) { - u32 v; - - v =3D __raw_readl(clk->enable_reg); - v |=3D clk->enable_mask; - if (clk->sw_locked) - ep93xx_syscon_swlocked_write(v, clk->enable_reg); - else - __raw_writel(v, clk->enable_reg); - } - } + struct clk_psc *psc =3D to_clk_psc(hw); + u32 val =3D readl(psc->reg); + + return (val & BIT(psc->bit_idx)) ? 1 : 0; } =20 -int clk_enable(struct clk *clk) +static int ep93xx_clk_enable(struct clk_hw *hw) { - unsigned long flags; + struct clk_psc *psc =3D to_clk_psc(hw); + unsigned long flags =3D 0; + u32 val; =20 - if (!clk) - return -EINVAL; + if (psc->lock) + spin_lock_irqsave(psc->lock, flags); + + val =3D __raw_readl(psc->reg); + val |=3D BIT(psc->bit_idx); + + ep93xx_syscon_swlocked_write(val, psc->reg); =20 - spin_lock_irqsave(&clk_lock, flags); - __clk_enable(clk); - spin_unlock_irqrestore(&clk_lock, flags); + if (psc->lock) + spin_unlock_irqrestore(psc->lock, flags); =20 return 0; } -EXPORT_SYMBOL(clk_enable); =20 -static void __clk_disable(struct clk *clk) +static void ep93xx_clk_disable(struct clk_hw *hw) { - if (!--clk->users) { - if (clk->enable_reg) { - u32 v; - - v =3D __raw_readl(clk->enable_reg); - v &=3D ~clk->enable_mask; - if (clk->sw_locked) - ep93xx_syscon_swlocked_write(v, clk->enable_reg); - else - __raw_writel(v, clk->enable_reg); - } + struct clk_psc *psc =3D to_clk_psc(hw); + unsigned long flags =3D 0; + u32 val; =20 - if (clk->parent) - __clk_disable(clk->parent); - } -} + if (psc->lock) + spin_lock_irqsave(psc->lock, flags); =20 -void clk_disable(struct clk *clk) -{ - unsigned long flags; + val =3D __raw_readl(psc->reg); + val &=3D ~BIT(psc->bit_idx); =20 - if (!clk) - return; + ep93xx_syscon_swlocked_write(val, psc->reg); =20 - spin_lock_irqsave(&clk_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&clk_lock, flags); + if (psc->lock) + spin_unlock_irqrestore(psc->lock, flags); } -EXPORT_SYMBOL(clk_disable); =20 -static unsigned long get_uart_rate(struct clk *clk) -{ - unsigned long rate =3D clk_get_rate(clk->parent); - u32 value; +static const struct clk_ops clk_ep93xx_gate_ops =3D { + .enable =3D ep93xx_clk_enable, + .disable =3D ep93xx_clk_disable, + .is_enabled =3D ep93xx_clk_is_enabled, +}; =20 - value =3D __raw_readl(EP93XX_SYSCON_PWRCNT); - if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD) - return rate; - else - return rate / 2; +static struct clk_hw *ep93xx_clk_register_gate(const char *name, + const char *parent_name, + void __iomem *reg, + u8 bit_idx) +{ + struct clk_init_data init; + struct clk_psc *psc; + struct clk *clk; + + psc =3D kzalloc(sizeof(*psc), GFP_KERNEL); + if (!psc) + return ERR_PTR(-ENOMEM); + + init.name =3D name; + init.ops =3D &clk_ep93xx_gate_ops; + init.flags =3D CLK_SET_RATE_PARENT; + init.parent_names =3D (parent_name ? &parent_name : NULL); + init.num_parents =3D (parent_name ? 1 : 0); + + psc->reg =3D reg; + psc->bit_idx =3D bit_idx; + psc->hw.init =3D &init; + psc->lock =3D &clk_lock; + + clk =3D clk_register(NULL, &psc->hw); + if (IS_ERR(clk)) + kfree(psc); + + return &psc->hw; } =20 -unsigned long clk_get_rate(struct clk *clk) +static u8 ep93xx_mux_get_parent(struct clk_hw *hw) { - if (clk->get_rate) - return clk->get_rate(clk); + struct clk_psc *psc =3D to_clk_psc(hw); + u32 val =3D __raw_readl(psc->reg); =20 - return clk->rate; + if (!(val & EP93XX_SYSCON_CLKDIV_ESEL)) + return 0; + + if (!(val & EP93XX_SYSCON_CLKDIV_PSEL)) + return 1; + + return 2; } -EXPORT_SYMBOL(clk_get_rate); =20 -static int set_keytchclk_rate(struct clk *clk, unsigned long rate) +static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index) { + struct clk_psc *psc =3D to_clk_psc(hw); + unsigned long flags =3D 0; u32 val; - u32 div_bit; =20 - val =3D __raw_readl(clk->enable_reg); + if (index >=3D ARRAY_SIZE(mux_parents)) + return -EINVAL; =20 - /* - * The Key Matrix and ADC clocks are configured using the same - * System Controller register. The clock used will be either - * 1/4 or 1/16 the external clock rate depending on the - * EP93XX_SYSCON_KEYTCHCLKDIV_KDIV/EP93XX_SYSCON_KEYTCHCLKDIV_ADIV - * bit being set or cleared. - */ - div_bit =3D clk->enable_mask >> 15; + if (psc->lock) + spin_lock_irqsave(psc->lock, flags); =20 - if (rate =3D=3D EP93XX_KEYTCHCLK_DIV4) - val |=3D div_bit; - else if (rate =3D=3D EP93XX_KEYTCHCLK_DIV16) - val &=3D ~div_bit; - else - return -EINVAL; + val =3D __raw_readl(psc->reg); + val &=3D ~(EP93XX_SYSCON_CLKDIV_ESEL | EP93XX_SYSCON_CLKDIV_PSEL); + + + if (index !=3D 0) { + val |=3D EP93XX_SYSCON_CLKDIV_ESEL; + val |=3D (index - 1) ? EP93XX_SYSCON_CLKDIV_PSEL : 0; + } + + ep93xx_syscon_swlocked_write(val, psc->reg); + + if (psc->lock) + spin_unlock_irqrestore(psc->lock, flags); =20 - ep93xx_syscon_swlocked_write(val, clk->enable_reg); - clk->rate =3D rate; return 0; } =20 -static int calc_clk_div(struct clk *clk, unsigned long rate, - int *psel, int *esel, int *pdiv, int *div) +static bool _is_best(unsigned long rate, unsigned long now, + unsigned long best) { - struct clk *mclk; - unsigned long max_rate, actual_rate, mclk_rate, rate_err =3D -1; - int i, found =3D 0, __div =3D 0, __pdiv =3D 0; + return abs(rate - now) < abs(rate - best); +} =20 - /* Don't exceed the maximum rate */ - max_rate =3D max3(clk_pll1.rate / 4, clk_pll2.rate / 4, clk_xtali.rate / = 4); - rate =3D min(rate, max_rate); +static int ep93xx_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long rate =3D req->rate; + struct clk *parent_best =3D 0; + unsigned long __parent_rate; + unsigned long best_rate =3D 0, actual_rate, mclk_rate; + unsigned long parent_rate_best; + int __div =3D 0, __pdiv =3D 0; + int i; =20 /* * Try the two pll's and the external clock @@ -376,213 +223,517 @@ static int calc_clk_div(struct clk *clk, unsigned l= ong rate, * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf * */ - for (i =3D 0; i < 3; i++) { - if (i =3D=3D 0) - mclk =3D &clk_xtali; - else if (i =3D=3D 1) - mclk =3D &clk_pll1; - else - mclk =3D &clk_pll2; - mclk_rate =3D mclk->rate * 2; + for (i =3D 0; i < ARRAY_SIZE(mux_parents); i++) { + struct clk *parent =3D clk_get_sys(mux_parents[i], NULL); + + __parent_rate =3D clk_get_rate(parent); + mclk_rate =3D __parent_rate * 2; =20 /* Try each predivider value */ for (__pdiv =3D 4; __pdiv <=3D 6; __pdiv++) { __div =3D mclk_rate / (rate * __pdiv); - if (__div < 2 || __div > 127) + if (__div < 2 || __div > 127) { + pr_info("%s : continue __div=3D%d", __func__, __div); continue; + } + + actual_rate =3D DIV_ROUND_UP_ULL((u64)mclk_rate, (__pdiv * __div)); =20 - actual_rate =3D mclk_rate / (__pdiv * __div); - - if (!found || abs(actual_rate - rate) < rate_err) { - *pdiv =3D __pdiv - 3; - *div =3D __div; - *psel =3D (i =3D=3D 2); - *esel =3D (i !=3D 0); - clk->parent =3D mclk; - clk->rate =3D actual_rate; - rate_err =3D abs(actual_rate - rate); - found =3D 1; + if (_is_best(rate, actual_rate, best_rate)) { + best_rate =3D actual_rate; + parent_rate_best =3D __parent_rate; + parent_best =3D parent; } } } =20 - if (!found) + if (!parent_best) return -EINVAL; =20 + req->best_parent_rate =3D parent_rate_best; + req->best_parent_hw =3D __clk_get_hw(parent_best); + req->rate =3D best_rate; + return 0; } =20 -static int set_div_rate(struct clk *clk, unsigned long rate) +static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) { - int err, psel =3D 0, esel =3D 0, pdiv =3D 0, div =3D 0; - u32 val; - - err =3D calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div); - if (err) - return err; + struct clk_psc *psc =3D to_clk_psc(hw); + unsigned long rate =3D 0; + u32 val =3D __raw_readl(psc->reg); + int __pdiv =3D ((val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & 0x03); + int __div =3D val & 0x7f; =20 - /* Clear the esel, psel, pdiv and div bits */ - val =3D __raw_readl(clk->enable_reg); - val &=3D ~0x7fff; + if (__div > 0) + rate =3D (parent_rate * 2) / ((__pdiv + 3) * __div); =20 - /* Set the new esel, psel, pdiv and div bits for the new clock rate */ - val |=3D (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) | - (psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) | - (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div; - ep93xx_syscon_swlocked_write(val, clk->enable_reg); - return 0; + return rate; } =20 -static int set_i2s_sclk_rate(struct clk *clk, unsigned long rate) +static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { - unsigned val =3D __raw_readl(clk->enable_reg); - - if (rate =3D=3D clk_i2s_mclk.rate / 2) - ep93xx_syscon_swlocked_write(val & ~EP93XX_I2SCLKDIV_SDIV,=20 - clk->enable_reg); - else if (rate =3D=3D clk_i2s_mclk.rate / 4) - ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_SDIV,=20 - clk->enable_reg); - else + struct clk_psc *psc =3D to_clk_psc(hw); + int pdiv =3D 0, div =3D 0; + unsigned long best_rate =3D 0, actual_rate, mclk_rate, rate_err =3D -1; + int found =3D 0, __div =3D 0, __pdiv =3D 0; + u32 val =3D __raw_readl(psc->reg); + + mclk_rate =3D parent_rate * 2; + + for (__pdiv =3D 4; __pdiv <=3D 6; __pdiv++) { + __div =3D mclk_rate / (rate * __pdiv); + if (__div < 2 || __div > 127) + continue; + + actual_rate =3D mclk_rate / (__pdiv * __div); + + if (!found || abs(actual_rate - rate) < rate_err) { + pdiv =3D __pdiv - 3; + div =3D __div; + best_rate =3D actual_rate; + rate_err =3D abs(actual_rate - rate); + found =3D 1; + } + } + + if (!found) return -EINVAL; =20 - clk_i2s_sclk.rate =3D rate; + /* Clear old dividers */ + val &=3D ~0x37f; + + /* Set the new pdiv and div bits for the new clock rate */ + val |=3D (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div; + + ep93xx_syscon_swlocked_write(val, psc->reg); + return 0; } =20 -static int set_i2s_lrclk_rate(struct clk *clk, unsigned long rate) -{ - unsigned val =3D __raw_readl(clk->enable_reg) &=20 - ~EP93XX_I2SCLKDIV_LRDIV_MASK; -=09 - if (rate =3D=3D clk_i2s_sclk.rate / 32) - ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV32, - clk->enable_reg); - else if (rate =3D=3D clk_i2s_sclk.rate / 64) - ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV64, - clk->enable_reg); - else if (rate =3D=3D clk_i2s_sclk.rate / 128) - ep93xx_syscon_swlocked_write(val | EP93XX_I2SCLKDIV_LRDIV128, - clk->enable_reg); - else - return -EINVAL; +static const struct clk_ops clk_ddiv_ops =3D { + .enable =3D ep93xx_clk_enable, + .disable =3D ep93xx_clk_disable, + .is_enabled =3D ep93xx_clk_is_enabled, + .get_parent =3D ep93xx_mux_get_parent, + .set_parent =3D ep93xx_mux_set_parent_lock, + .determine_rate =3D ep93xx_mux_determine_rate, + .recalc_rate =3D ep93xx_ddiv_recalc_rate, + .set_rate =3D ep93xx_ddiv_set_rate, +}; =20 - clk_i2s_lrclk.rate =3D rate; - return 0; +static struct clk_hw *clk_hw_register_ddiv(const char *name, + void __iomem *reg, + u8 bit_idx) +{ + struct clk_init_data init; + struct clk_psc *psc; + struct clk *clk; + + psc =3D kzalloc(sizeof(*psc), GFP_KERNEL); + if (!psc) + return ERR_PTR(-ENOMEM); + + init.name =3D name; + init.ops =3D &clk_ddiv_ops; + init.flags =3D 0; + init.parent_names =3D mux_parents; + init.num_parents =3D ARRAY_SIZE(mux_parents); + + psc->reg =3D reg; + psc->bit_idx =3D bit_idx; + psc->lock =3D &clk_lock; + psc->hw.init =3D &init; + + clk =3D clk_register(NULL, &psc->hw); + if (IS_ERR(clk)) + kfree(psc); + + return &psc->hw; } =20 -int clk_set_rate(struct clk *clk, unsigned long rate) +static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) { - if (clk->set_rate) - return clk->set_rate(clk, rate); + struct clk_psc *psc =3D to_clk_psc(hw); + u32 val =3D __raw_readl(psc->reg); + u8 index =3D (val & psc->mask) >> psc->shift; + + if (index > psc->num_div) + return 0; =20 - return -EINVAL; + return DIV_ROUND_UP_ULL(parent_rate, psc->div[index]); } -EXPORT_SYMBOL(clk_set_rate); =20 -long clk_round_rate(struct clk *clk, unsigned long rate) +static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) { - WARN_ON(clk); - return 0; + struct clk_psc *psc =3D to_clk_psc(hw); + unsigned long best =3D 0, now, maxdiv; + int i; + + maxdiv =3D psc->div[psc->num_div - 1]; + + for (i =3D 0; i < psc->num_div; i++) { + if ((rate * psc->div[i]) =3D=3D *parent_rate) + return DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]); + + now =3D DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]); + + if (_is_best(rate, now, best)) + best =3D now; + } + + if (!best) + best =3D DIV_ROUND_UP_ULL(*parent_rate, maxdiv); + + return best; } -EXPORT_SYMBOL(clk_round_rate); =20 -int clk_set_parent(struct clk *clk, struct clk *parent) +static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { - WARN_ON(clk); + struct clk_psc *psc =3D to_clk_psc(hw); + u32 val =3D __raw_readl(psc->reg) & ~psc->mask; + int i; + + for (i =3D 0; i < psc->num_div; i++) + if (rate =3D=3D parent_rate / psc->div[i]) { + val |=3D i << psc->shift; + break; + } + + if (i =3D=3D psc->num_div) + return -EINVAL; + + ep93xx_syscon_swlocked_write(val, psc->reg); + return 0; } -EXPORT_SYMBOL(clk_set_parent); =20 -struct clk *clk_get_parent(struct clk *clk) +static const struct clk_ops ep93xx_div_ops =3D { + .enable =3D ep93xx_clk_enable, + .disable =3D ep93xx_clk_disable, + .is_enabled =3D ep93xx_clk_is_enabled, + .recalc_rate =3D ep93xx_div_recalc_rate, + .round_rate =3D ep93xx_div_round_rate, + .set_rate =3D ep93xx_div_set_rate, +}; + +static struct clk_hw *clk_hw_register_div(const char *name, + const char *parent_name, + void __iomem *reg, + u8 enable_bit, + u8 shift, + u8 width, + char *clk_divisors, + u8 num_div) { - return clk->parent; + struct clk_init_data init; + struct clk_psc *psc; + struct clk *clk; + + psc =3D kzalloc(sizeof(*psc), GFP_KERNEL); + if (!psc) + return ERR_PTR(-ENOMEM); + + init.name =3D name; + init.ops =3D &ep93xx_div_ops; + init.flags =3D 0; + init.parent_names =3D (parent_name ? &parent_name : NULL); + init.num_parents =3D 1; + + psc->reg =3D reg; + psc->bit_idx =3D enable_bit; + psc->mask =3D GENMASK(shift + width - 1, shift); + psc->shift =3D shift; + psc->div =3D clk_divisors; + psc->num_div =3D num_div; + psc->lock =3D &clk_lock; + psc->hw.init =3D &init; + + clk =3D clk_register(NULL, &psc->hw); + if (IS_ERR(clk)) + kfree(psc); + + return &psc->hw; } -EXPORT_SYMBOL(clk_get_parent); =20 +struct ep93xx_gate { + unsigned int bit; + const char *dev_id; + const char *con_id; +}; =20 -static char fclk_divisors[] =3D { 1, 2, 4, 8, 16, 1, 1, 1 }; -static char hclk_divisors[] =3D { 1, 2, 4, 5, 6, 8, 16, 32 }; -static char pclk_divisors[] =3D { 1, 2, 4, 8 }; +static struct ep93xx_gate ep93xx_uarts[] =3D { + {EP93XX_SYSCON_DEVCFG_U1EN, "apb:uart1", NULL}, + {EP93XX_SYSCON_DEVCFG_U2EN, "apb:uart2", NULL}, + {EP93XX_SYSCON_DEVCFG_U3EN, "apb:uart3", NULL}, +}; =20 -/* - * PLL rate =3D 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^= PS - */ -static unsigned long calc_pll_rate(u32 config_word) +static void __init ep93xx_uart_clock_init(void) { - unsigned long long rate; - int i; + unsigned int i; + struct clk_hw *hw; + u32 value; + unsigned int clk_uart_div; =20 - rate =3D clk_xtali.rate; - rate *=3D ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ - rate *=3D ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ - do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ - for (i =3D 0; i < ((config_word >> 16) & 3); i++) /* PS */ - rate >>=3D 1; + value =3D __raw_readl(EP93XX_SYSCON_PWRCNT); + if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD) + clk_uart_div =3D 1; + else + clk_uart_div =3D 2; =20 - return (unsigned long)rate; + hw =3D clk_hw_register_fixed_factor(NULL, "uart", "xtali", 0, 1, clk_uart= _div); + + /* parenting uart gate clocks to uart clock */ + for (i =3D 0; i < ARRAY_SIZE(ep93xx_uarts); i++) { + hw =3D ep93xx_clk_register_gate(ep93xx_uarts[i].dev_id, + "uart", + EP93XX_SYSCON_DEVCFG, + ep93xx_uarts[i].bit); + + clk_hw_register_clkdev(hw, NULL, ep93xx_uarts[i].dev_id); + } } =20 +static struct ep93xx_gate ep93xx_dmas[] =3D { + {EP93XX_SYSCON_PWRCNT_DMA_M2P0, NULL, "m2p0"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P1, NULL, "m2p1"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P2, NULL, "m2p2"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P3, NULL, "m2p3"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P4, NULL, "m2p4"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P5, NULL, "m2p5"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P6, NULL, "m2p6"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P7, NULL, "m2p7"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P8, NULL, "m2p8"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2P9, NULL, "m2p9"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2M0, NULL, "m2m0"}, + {EP93XX_SYSCON_PWRCNT_DMA_M2M1, NULL, "m2m1"}, +}; + static void __init ep93xx_dma_clock_init(void) { - clk_m2p0.rate =3D clk_h.rate; - clk_m2p1.rate =3D clk_h.rate; - clk_m2p2.rate =3D clk_h.rate; - clk_m2p3.rate =3D clk_h.rate; - clk_m2p4.rate =3D clk_h.rate; - clk_m2p5.rate =3D clk_h.rate; - clk_m2p6.rate =3D clk_h.rate; - clk_m2p7.rate =3D clk_h.rate; - clk_m2p8.rate =3D clk_h.rate; - clk_m2p9.rate =3D clk_h.rate; - clk_m2m0.rate =3D clk_h.rate; - clk_m2m1.rate =3D clk_h.rate; + unsigned int i; + struct clk_hw *hw; + int ret; + + for (i =3D 0; i < ARRAY_SIZE(ep93xx_dmas); i++) { + hw =3D clk_hw_register_gate(NULL, ep93xx_dmas[i].con_id, + "hclk", 0, + EP93XX_SYSCON_PWRCNT, + ep93xx_dmas[i].bit, + 0, + &clk_lock); + + ret =3D clk_hw_register_clkdev(hw, ep93xx_dmas[i].con_id, NULL); + if (ret) + pr_err("%s: failed to register lookup %s\n", + __func__, ep93xx_dmas[i].con_id); + } } =20 static int __init ep93xx_clock_init(void) { u32 value; + struct clk_hw *hw; + unsigned long clk_pll1_rate; + unsigned long clk_f_rate; + unsigned long clk_h_rate; + unsigned long clk_p_rate; + unsigned long clk_pll2_rate; + unsigned int clk_f_div; + unsigned int clk_h_div; + unsigned int clk_p_div; + unsigned int clk_usb_div; + unsigned long clk_spi_div; + + hw =3D clk_hw_register_fixed_rate(NULL, "xtali", NULL, 0, EP93XX_EXT_CLK_= RATE); + clk_hw_register_clkdev(hw, NULL, "xtali"); =20 /* Determine the bootloader configured pll1 rate */ value =3D __raw_readl(EP93XX_SYSCON_CLKSET1); if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1)) - clk_pll1.rate =3D clk_xtali.rate; + clk_pll1_rate =3D EP93XX_EXT_CLK_RATE; else - clk_pll1.rate =3D calc_pll_rate(value); + clk_pll1_rate =3D calc_pll_rate(EP93XX_EXT_CLK_RATE, value); + + hw =3D clk_hw_register_fixed_rate(NULL, "pll1", "xtali", 0, clk_pll1_rate= ); + clk_hw_register_clkdev(hw, NULL, "pll1"); =20 /* Initialize the pll1 derived clocks */ - clk_f.rate =3D clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7]; - clk_h.rate =3D clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7]; - clk_p.rate =3D clk_h.rate / pclk_divisors[(value >> 18) & 0x3]; + clk_f_div =3D fclk_divisors[(value >> 25) & 0x7]; + clk_h_div =3D hclk_divisors[(value >> 20) & 0x7]; + clk_p_div =3D pclk_divisors[(value >> 18) & 0x3]; + + hw =3D clk_hw_register_fixed_factor(NULL, "fclk", "pll1", 0, 1, clk_f_div= ); + clk_f_rate =3D clk_get_rate(hw->clk); + hw =3D clk_hw_register_fixed_factor(NULL, "hclk", "pll1", 0, 1, clk_h_div= ); + clk_h_rate =3D clk_get_rate(hw->clk); + hw =3D clk_hw_register_fixed_factor(NULL, "pclk", "hclk", 0, 1, clk_p_div= ); + clk_p_rate =3D clk_get_rate(hw->clk); + + clk_hw_register_clkdev(hw, "apb_pclk", NULL); + ep93xx_dma_clock_init(); =20 /* Determine the bootloader configured pll2 rate */ value =3D __raw_readl(EP93XX_SYSCON_CLKSET2); if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2)) - clk_pll2.rate =3D clk_xtali.rate; + clk_pll2_rate =3D EP93XX_EXT_CLK_RATE; else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN) - clk_pll2.rate =3D calc_pll_rate(value); + clk_pll2_rate =3D calc_pll_rate(EP93XX_EXT_CLK_RATE, value); else - clk_pll2.rate =3D 0; + clk_pll2_rate =3D 0; + + hw =3D clk_hw_register_fixed_rate(NULL, "pll2", "xtali", 0, clk_pll2_rate= ); + clk_hw_register_clkdev(hw, NULL, "pll2"); =20 /* Initialize the pll2 derived clocks */ - clk_usb_host.rate =3D clk_pll2.rate / (((value >> 28) & 0xf) + 1); + + /* + * These four bits set the divide ratio between the PLL2 + * output and the USB clock. + * 0000 - Divide by 1 + * 0001 - Divide by 2 + * 0010 - Divide by 3 + * 0011 - Divide by 4 + * 0100 - Divide by 5 + * 0101 - Divide by 6 + * 0110 - Divide by 7 + * 0111 - Divide by 8 + * 1000 - Divide by 9 + * 1001 - Divide by 10 + * 1010 - Divide by 11 + * 1011 - Divide by 12 + * 1100 - Divide by 13 + * 1101 - Divide by 14 + * 1110 - Divide by 15 + * 1111 - Divide by 1 + * On power-on-reset these bits are reset to 0000b. + */ + + clk_usb_div =3D (((value >> 28) & 0xf) + 1); + hw =3D clk_hw_register_fixed_factor(NULL, "usb_clk", "pll2", 0, 1, clk_us= b_div); + hw =3D clk_hw_register_gate(NULL, "ohci-platform", + "usb_clk", 0, + EP93XX_SYSCON_PWRCNT, + EP93XX_SYSCON_PWRCNT_USH_EN, + 0, + &clk_lock); + clk_hw_register_clkdev(hw, NULL, "ohci-platform"); =20 /* * EP93xx SSP clock rate was doubled in version E2. For more information * see: * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf */ + clk_spi_div =3D 1; if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2) - clk_spi.rate /=3D 2; + clk_spi_div =3D 2; + hw =3D clk_hw_register_fixed_factor(NULL, "ep93xx-spi.0", "xtali", 0, 1, = clk_spi_div); + clk_hw_register_clkdev(hw, NULL, "ep93xx-spi.0"); + + /* pwm clock */ + hw =3D clk_hw_register_fixed_factor(NULL, "pwm_clk", "xtali", 0, 1, 1); + clk_hw_register_clkdev(hw, "pwm_clk", NULL); =20 pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n", - clk_pll1.rate / 1000000, clk_pll2.rate / 1000000); + clk_pll1_rate / 1000000, clk_pll2_rate / 1000000); pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", - clk_f.rate / 1000000, clk_h.rate / 1000000, - clk_p.rate / 1000000); + clk_f_rate / 1000000, clk_h_rate / 1000000, + clk_p_rate / 1000000); + + + ep93xx_uart_clock_init(); + + /* touchscreen/adc clock */ + hw =3D clk_hw_register_div("ep93xx-adc", + "xtali", + EP93XX_SYSCON_KEYTCHCLKDIV, + EP93XX_SYSCON_KEYTCHCLKDIV_TSEN, + EP93XX_SYSCON_KEYTCHCLKDIV_ADIV, + 1, + adc_divisors, + ARRAY_SIZE(adc_divisors)); + + clk_hw_register_clkdev(hw, NULL, "ep93xx-adc"); + + /* keypad clock */ + hw =3D clk_hw_register_div("ep93xx-keypad", + "xtali", + EP93XX_SYSCON_KEYTCHCLKDIV, + EP93XX_SYSCON_KEYTCHCLKDIV_KEN, + EP93XX_SYSCON_KEYTCHCLKDIV_KDIV, + 1, + adc_divisors, + ARRAY_SIZE(adc_divisors)); + + clk_hw_register_clkdev(hw, NULL, "ep93xx-keypad"); + + /* On reset PDIV and VDIV is set to zero, while PDIV zero + * means clock disable, VDIV shouldn't be zero. + * So i set both dividers to minimum. + */ + /* ENA - Enable CLK divider. */ + /* PDIV - 00 - Disable clock */ + /* VDIV - at least 2 */ + /* Check and enable video clk registers */ + value =3D __raw_readl(EP93XX_SYSCON_VIDCLKDIV); + value |=3D (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2; + ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_VIDCLKDIV); + + /* check and enable i2s clk registers */ + value =3D __raw_readl(EP93XX_SYSCON_I2SCLKDIV); + value |=3D (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2; + ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_I2SCLKDIV); + + /* video clk */ + hw =3D clk_hw_register_ddiv("ep93xx-fb", + EP93XX_SYSCON_VIDCLKDIV, + EP93XX_SYSCON_CLKDIV_ENABLE); + + clk_hw_register_clkdev(hw, NULL, "ep93xx-fb"); + + /* i2s clk */ + hw =3D clk_hw_register_ddiv("mclk", + EP93XX_SYSCON_I2SCLKDIV, + EP93XX_SYSCON_CLKDIV_ENABLE); + + clk_hw_register_clkdev(hw, "mclk", "ep93xx-i2s"); + + /* i2s sclk */ +#define EP93XX_I2SCLKDIV_SDIV_SHIFT 16 +#define EP93XX_I2SCLKDIV_SDIV_WIDTH 1 + hw =3D clk_hw_register_div("sclk", + "mclk", + EP93XX_SYSCON_I2SCLKDIV, + EP93XX_SYSCON_I2SCLKDIV_SENA, + EP93XX_I2SCLKDIV_SDIV_SHIFT, + EP93XX_I2SCLKDIV_SDIV_WIDTH, + sclk_divisors, + ARRAY_SIZE(sclk_divisors)); + + clk_hw_register_clkdev(hw, "sclk", "ep93xx-i2s"); + + /* i2s lrclk */ +#define EP93XX_I2SCLKDIV_LRDIV32_SHIFT 17 +#define EP93XX_I2SCLKDIV_LRDIV32_WIDTH 3 + hw =3D clk_hw_register_div("lrclk", + "sclk", + EP93XX_SYSCON_I2SCLKDIV, + EP93XX_SYSCON_I2SCLKDIV_SENA, + EP93XX_I2SCLKDIV_LRDIV32_SHIFT, + EP93XX_I2SCLKDIV_LRDIV32_WIDTH, + lrclk_divisors, + ARRAY_SIZE(lrclk_divisors)); + + clk_hw_register_clkdev(hw, "lrclk", "ep93xx-i2s"); + + /* IrDa clk uses same pattern but no init code presents in original clock= driver */ =20 - clkdev_add_table(clocks, ARRAY_SIZE(clocks)); return 0; } postcore_initcall(ep93xx_clock_init); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 6fb19a393fd2..bbb79f263331 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -214,7 +214,7 @@ static int ep93xx_ohci_power_on(struct platform_device = *pdev) return PTR_ERR(ep93xx_ohci_host_clock); } =20 - return clk_enable(ep93xx_ohci_host_clock); + return clk_prepare_enable(ep93xx_ohci_host_clock); } =20 static void ep93xx_ohci_power_off(struct platform_device *pdev) diff --git a/arch/arm/mach-ep93xx/soc.h b/arch/arm/mach-ep93xx/soc.h index f2dace1c9154..94ef7f275f94 100644 --- a/arch/arm/mach-ep93xx/soc.h +++ b/arch/arm/mach-ep93xx/soc.h @@ -111,19 +111,19 @@ #define EP93XX_SYSCON_PWRCNT EP93XX_SYSCON_REG(0x04) #define EP93XX_SYSCON_PWRCNT_FIR_EN (1<<31) #define EP93XX_SYSCON_PWRCNT_UARTBAUD (1<<29) -#define EP93XX_SYSCON_PWRCNT_USH_EN (1<<28) -#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 (1<<27) -#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 (1<<26) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 (1<<25) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 (1<<24) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 (1<<23) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 (1<<22) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 (1<<21) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 (1<<20) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 (1<<19) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 (1<<18) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 (1<<17) -#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 (1<<16) +#define EP93XX_SYSCON_PWRCNT_USH_EN 28 +#define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27 +#define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17 +#define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16 #define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08) #define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c) #define EP93XX_SYSCON_CLKSET1 EP93XX_SYSCON_REG(0x20) @@ -139,13 +139,13 @@ #define EP93XX_SYSCON_DEVCFG_GONK (1<<27) #define EP93XX_SYSCON_DEVCFG_TONG (1<<26) #define EP93XX_SYSCON_DEVCFG_MONG (1<<25) -#define EP93XX_SYSCON_DEVCFG_U3EN (1<<24) +#define EP93XX_SYSCON_DEVCFG_U3EN 24 #define EP93XX_SYSCON_DEVCFG_CPENA (1<<23) #define EP93XX_SYSCON_DEVCFG_A2ONG (1<<22) #define EP93XX_SYSCON_DEVCFG_A1ONG (1<<21) -#define EP93XX_SYSCON_DEVCFG_U2EN (1<<20) +#define EP93XX_SYSCON_DEVCFG_U2EN 20 #define EP93XX_SYSCON_DEVCFG_EXVC (1<<19) -#define EP93XX_SYSCON_DEVCFG_U1EN (1<<18) +#define EP93XX_SYSCON_DEVCFG_U1EN 18 #define EP93XX_SYSCON_DEVCFG_TIN (1<<17) #define EP93XX_SYSCON_DEVCFG_HC3IN (1<<15) #define EP93XX_SYSCON_DEVCFG_HC3EN (1<<14) @@ -163,12 +163,12 @@ #define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) #define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) #define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84) -#define EP93XX_SYSCON_CLKDIV_ENABLE (1<<15) +#define EP93XX_SYSCON_CLKDIV_ENABLE 15 #define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) #define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) #define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 #define EP93XX_SYSCON_I2SCLKDIV EP93XX_SYSCON_REG(0x8c) -#define EP93XX_SYSCON_I2SCLKDIV_SENA (1<<31) +#define EP93XX_SYSCON_I2SCLKDIV_SENA 31 #define EP93XX_SYSCON_I2SCLKDIV_ORIDE (1<<29) #define EP93XX_SYSCON_I2SCLKDIV_SPOL (1<<19) #define EP93XX_I2SCLKDIV_SDIV (1 << 16) @@ -177,9 +177,9 @@ #define EP93XX_I2SCLKDIV_LRDIV128 (2 << 17) #define EP93XX_I2SCLKDIV_LRDIV_MASK (3 << 17) #define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) -#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) -#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) -#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN (1<<15) +#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31 +#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16 +#define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15 #define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0) #define EP93XX_SYSCON_SYSCFG EP93XX_SYSCON_REG(0x9c) #define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000) --=20 2.26.2