From patchwork Wed May 3 03:09:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 9708741 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0C77B60351 for ; Wed, 3 May 2017 03:09:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F1AA828557 for ; Wed, 3 May 2017 03:09:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E67762857D; Wed, 3 May 2017 03:09:40 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7BCA828557 for ; Wed, 3 May 2017 03:09:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751898AbdECDJk (ORCPT ); Tue, 2 May 2017 23:09:40 -0400 Received: from mirror2.csie.ntu.edu.tw ([140.112.30.76]:43334 "EHLO wens.csie.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751303AbdECDJd (ORCPT ); Tue, 2 May 2017 23:09:33 -0400 Received: by wens.csie.org (Postfix, from userid 1000) id 781505FEA5; Wed, 3 May 2017 11:09:30 +0800 (CST) From: Chen-Yu Tsai To: Maxime Ripard , Michael Turquette , Stephen Boyd , Rob Herring , Mark Rutland Cc: Chen-Yu Tsai , linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com Subject: [PATCH v2 3/8] clk: sunxi-ng: Add class of phase clocks supporting MMC new timing modes Date: Wed, 3 May 2017 11:09:24 +0800 Message-Id: <20170503030929.28763-4-wens@csie.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170503030929.28763-1-wens@csie.org> References: <20170503030929.28763-1-wens@csie.org> Sender: linux-clk-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-clk@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The MMC clocks on newer SoCs, such as the A83T and H3, support the "new timing mode". Under this mode, the output of the clock is divided by 2, and the clock delays no longer apply. Due to how the clock tree is modeled and setup, we need to model this function in two places, the master mmc clock and the two child phase clocks. In the mmc clock, we can easily model the mode bit as an extra variable post-divider. In the phase clocks, we check the bit and return -ENOTSUPP if the bit is set, signaling that the phase clocks are not to be used. This patch introduces a class of phase clocks that checks the timing mode bit. Signed-off-by: Chen-Yu Tsai --- drivers/clk/sunxi-ng/ccu_phase.c | 47 ++++++++++++++++++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu_phase.h | 16 ++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu_phase.c b/drivers/clk/sunxi-ng/ccu_phase.c index 400c58ad72fd..e6ff7551c855 100644 --- a/drivers/clk/sunxi-ng/ccu_phase.c +++ b/drivers/clk/sunxi-ng/ccu_phase.c @@ -8,6 +8,7 @@ * the License, or (at your option) any later version. */ +#include #include #include @@ -124,3 +125,49 @@ const struct clk_ops ccu_phase_ops = { .get_phase = ccu_phase_get_phase, .set_phase = ccu_phase_set_phase, }; + +/* + * The MMC clocks on newer SoCs support the "new timing mode". Under + * this mode, the output of the clock is divided by 2, and the clock + * delays no longer apply. + * + * Due to how the clock tree is modeled and setup, we need to model + * this function in two places, the master mmc clock and the two + * child phase clocks. In the mmc clock, we can easily model the + * mode bit as an extra variable post-divider. In the phase clocks, + * we check the bit and return -ENOTSUPP if the bit is set, signaling + * that the phase clocks are not to be used. + * + * We do not support runtime configuration of the modes. Instead a + * mode is enforced at CCU probe time. + */ +#define CCU_MMC_NEW_TIMING_MODE BIT(30) + +static int ccu_phase_mmc_new_timing_get_phase(struct clk_hw *hw) +{ + struct ccu_phase *phase = hw_to_ccu_phase(hw); + u32 reg; + + reg = readl(phase->common.base + phase->common.reg); + if (reg & CCU_MMC_NEW_TIMING_MODE) + return -ENOTSUPP; + + return ccu_phase_get_phase(hw); +} + +static int ccu_phase_mmc_new_timing_set_phase(struct clk_hw *hw, int degrees) +{ + struct ccu_phase *phase = hw_to_ccu_phase(hw); + u32 reg; + + reg = readl(phase->common.base + phase->common.reg); + if (reg & CCU_MMC_NEW_TIMING_MODE) + return -ENOTSUPP; + + return ccu_phase_set_phase(hw, degrees); +} + +const struct clk_ops ccu_phase_mmc_new_timing_ops = { + .get_phase = ccu_phase_mmc_new_timing_get_phase, + .set_phase = ccu_phase_mmc_new_timing_set_phase, +}; diff --git a/drivers/clk/sunxi-ng/ccu_phase.h b/drivers/clk/sunxi-ng/ccu_phase.h index 75a091a4c565..c514d1798cdd 100644 --- a/drivers/clk/sunxi-ng/ccu_phase.h +++ b/drivers/clk/sunxi-ng/ccu_phase.h @@ -38,6 +38,20 @@ struct ccu_phase { } \ } +#define SUNXI_CCU_PHASE_MMC_NEW_TIMING(_struct, _name, _parent, _reg, \ + _shift, _width, _flags) \ + struct ccu_phase _struct = { \ + .shift = _shift, \ + .width = _width, \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &ccu_phase_mmc_new_timing_ops, \ + _flags), \ + } \ + } + static inline struct ccu_phase *hw_to_ccu_phase(struct clk_hw *hw) { struct ccu_common *common = hw_to_ccu_common(hw); @@ -47,4 +61,6 @@ static inline struct ccu_phase *hw_to_ccu_phase(struct clk_hw *hw) extern const struct clk_ops ccu_phase_ops; +extern const struct clk_ops ccu_phase_mmc_new_timing_ops; + #endif /* _CCU_PHASE_H_ */