From patchwork Fri Apr 5 11:08:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kishon Vijay Abraham I X-Patchwork-Id: 161839 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp298180jan; Fri, 5 Apr 2019 04:09:56 -0700 (PDT) X-Google-Smtp-Source: APXvYqy25aYBI+9uCLvP3y4QT+8e+R+HvFsCrHQml/s6DoOdfIz+rOub1GoB01fVR6+d0YWtKx2S X-Received: by 2002:a17:902:8a81:: with SMTP id p1mr12404091plo.106.1554462596790; Fri, 05 Apr 2019 04:09:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554462596; cv=none; d=google.com; s=arc-20160816; b=e8aZ6d4xDeQ1Oi/Ler6jU3FbUJZTsDk4ehPxXTMB1aOLl1hdBw0Tdrgzbvic/B2fOU k/SnXpsC95Jw9MhZVDyueRbeyxBJIbuI1fMPnO+2tSF8C74E4V00sEV1JE45sc3+qQEl 56BSQUxHpwHWm3kaxeHh7yqLc4EpLua1hKIsDDrFXsZbHfvcJDQWaCQp9Xhbx/6bq1FY n052bM7DFrH194tCgrb+Q7CngK71L/pRPoUFCsT43jWtP4lfb0MrZD4Z0FaIUuOVnh+F 86myT1sKVj/8kpyo9I4B7GbyIdg4ubAQrqDYGfon+LqA/hib8RqK8dEce6FaSyJRyVnm 1usg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=oDbAxlo5amvJMQUQxS+7VwIFzrToPotQk/rweutAbVM=; b=WQP0NjozQsMZQ71InM3H7s+rj9Zc/G/0DmI5WZt9t5RsRVw4gyTKkyOQK40gB+j7/8 zyco3WUmp3Oj7WEE1PuK4bPraioYFW5Y0/kiUOKLM6TzqTFDKspuAVJzsNoSGlggkh05 pyUORNJ7Wakm/0kC8gqztWbkQN+SMgFNwF0SpeYI9ErUxask7A0ggxf9h1BbbhZMVWkE HYoRcy4FXT1z5/jMnE2hwxNzISnVH8EUI/valEhONpOUY3YMG/EI9oNP/RMhqIn5jstl UKC5Das+z9DwiWEw3vvl8tC7DsISzBqdzp+BheldV8uDR7vp8kBon7yCT57Eo3bDkDO7 HHaA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b="MtAlc/3b"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u10si18430123pgh.255.2019.04.05.04.09.56; Fri, 05 Apr 2019 04:09:56 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b="MtAlc/3b"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731091AbfDELJz (ORCPT + 31 others); Fri, 5 Apr 2019 07:09:55 -0400 Received: from lelv0143.ext.ti.com ([198.47.23.248]:50358 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731036AbfDELJy (ORCPT ); Fri, 5 Apr 2019 07:09:54 -0400 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id x35B9onU129305; Fri, 5 Apr 2019 06:09:50 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1554462590; bh=oDbAxlo5amvJMQUQxS+7VwIFzrToPotQk/rweutAbVM=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=MtAlc/3bPRGscMAZPz3Ts55GkN4mz17NUaDByM8x8OOZSMJr6bCBgzYFQ+749+EN/ dtQEDj8w/wWtlQKD2+fGHeuuO+oHqse+7uHDdOxPBfYyPI5Tx8hb2kVFSvSFSnnYdv IwMiZdNHXF56JBWF1XX9u4MnoeU46TtJNgHozIVU= Received: from DLEE109.ent.ti.com (dlee109.ent.ti.com [157.170.170.41]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x35B9ojF029595 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 5 Apr 2019 06:09:50 -0500 Received: from DLEE103.ent.ti.com (157.170.170.33) by DLEE109.ent.ti.com (157.170.170.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5; Fri, 5 Apr 2019 06:09:49 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DLEE103.ent.ti.com (157.170.170.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1713.5 via Frontend Transport; Fri, 5 Apr 2019 06:09:49 -0500 Received: from a0393678ub.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by lelv0327.itg.ti.com (8.15.2/8.15.2) with ESMTP id x35B9aS5100251; Fri, 5 Apr 2019 06:09:47 -0500 From: Kishon Vijay Abraham I To: Rob Herring , Kishon Vijay Abraham I , CC: Mark Rutland , , Subject: [PATCH v4 5/5] phy: ti: am654-serdes: Support all clksel values Date: Fri, 5 Apr 2019 16:38:34 +0530 Message-ID: <20190405110834.13083-6-kishon@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190405110834.13083-1-kishon@ti.com> References: <20190405110834.13083-1-kishon@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Roger Quadros Add support to select all 16 CLKSEL combinations that are shown in "SerDes Reference Clock Distribution" in AM65 TRM. Signed-off-by: Roger Quadros Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/ti/phy-am654-serdes.c | 132 +++++++++++++++++++----------- 1 file changed, 83 insertions(+), 49 deletions(-) -- 2.17.1 diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c index 4817c67abbbb..d3769200cb9b 100644 --- a/drivers/phy/ti/phy-am654-serdes.c +++ b/drivers/phy/ti/phy-am654-serdes.c @@ -58,13 +58,14 @@ #define SERDES_NUM_CLOCKS 3 +#define AM654_SERDES_CTRL_CLKSEL_MASK GENMASK(7, 4) +#define AM654_SERDES_CTRL_CLKSEL_SHIFT 4 + struct serdes_am654_clk_mux { struct clk_hw hw; struct regmap *regmap; unsigned int reg; - int *table; - u32 mask; - u8 shift; + int clk_id; struct clk_init_data clk_data; }; @@ -282,31 +283,52 @@ static const struct phy_ops ops = { .owner = THIS_MODULE, }; +#define SERDES_NUM_MUX_COMBINATIONS 16 + +#define LICLK 0 +#define EXT_REFCLK 1 +#define RICLK 2 + +static const int +serdes_am654_mux_table[SERDES_NUM_MUX_COMBINATIONS][SERDES_NUM_CLOCKS] = { + /* + * Each combination maps to one of + * "Figure 12-1986. SerDes Reference Clock Distribution" + * in TRM. + */ + /* Parent of CMU refclk, Left output, Right output + * either of EXT_REFCLK, LICLK, RICLK + */ + { EXT_REFCLK, EXT_REFCLK, EXT_REFCLK }, /* 0000 */ + { RICLK, EXT_REFCLK, EXT_REFCLK }, /* 0001 */ + { EXT_REFCLK, RICLK, LICLK }, /* 0010 */ + { RICLK, RICLK, EXT_REFCLK }, /* 0011 */ + { LICLK, EXT_REFCLK, EXT_REFCLK }, /* 0100 */ + { EXT_REFCLK, EXT_REFCLK, EXT_REFCLK }, /* 0101 */ + { LICLK, RICLK, LICLK }, /* 0110 */ + { EXT_REFCLK, RICLK, LICLK }, /* 0111 */ + { EXT_REFCLK, EXT_REFCLK, LICLK }, /* 1000 */ + { RICLK, EXT_REFCLK, LICLK }, /* 1001 */ + { EXT_REFCLK, RICLK, EXT_REFCLK }, /* 1010 */ + { RICLK, RICLK, EXT_REFCLK }, /* 1011 */ + { LICLK, EXT_REFCLK, LICLK }, /* 1100 */ + { EXT_REFCLK, EXT_REFCLK, LICLK }, /* 1101 */ + { LICLK, RICLK, EXT_REFCLK }, /* 1110 */ + { EXT_REFCLK, RICLK, EXT_REFCLK }, /* 1111 */ +}; + static u8 serdes_am654_clk_mux_get_parent(struct clk_hw *hw) { struct serdes_am654_clk_mux *mux = to_serdes_am654_clk_mux(hw); - unsigned int num_parents = clk_hw_get_num_parents(hw); struct regmap *regmap = mux->regmap; unsigned int reg = mux->reg; unsigned int val; - int i; regmap_read(regmap, reg, &val); - val >>= mux->shift; - val &= mux->mask; - - for (i = 0; i < num_parents; i++) - if (mux->table[i] == val) - return i; - - /* - * No parent? This should never happen! - * Verify if we set a valid parent in serdes_am654_clk_register() - */ - WARN(1, "Failed to find the parent of %s clock\n", hw->init->name); + val &= AM654_SERDES_CTRL_CLKSEL_MASK; + val >>= AM654_SERDES_CTRL_CLKSEL_SHIFT; - /* Make the parent lookup to fail */ - return num_parents; + return serdes_am654_mux_table[val][mux->clk_id]; } static int serdes_am654_clk_mux_set_parent(struct clk_hw *hw, u8 index) @@ -314,16 +336,52 @@ static int serdes_am654_clk_mux_set_parent(struct clk_hw *hw, u8 index) struct serdes_am654_clk_mux *mux = to_serdes_am654_clk_mux(hw); struct regmap *regmap = mux->regmap; unsigned int reg = mux->reg; - int val; + int clk_id = mux->clk_id; + int parents[SERDES_NUM_CLOCKS]; + const int *p; + u32 val; + int found, i; int ret; - val = mux->table[index]; + /* get existing setting */ + regmap_read(regmap, reg, &val); + val &= AM654_SERDES_CTRL_CLKSEL_MASK; + val >>= AM654_SERDES_CTRL_CLKSEL_SHIFT; + + for (i = 0; i < SERDES_NUM_CLOCKS; i++) + parents[i] = serdes_am654_mux_table[val][i]; + + /* change parent of this clock. others left intact */ + parents[clk_id] = index; + + /* Find the match */ + for (val = 0; val < SERDES_NUM_MUX_COMBINATIONS; val++) { + p = serdes_am654_mux_table[val]; + found = 1; + for (i = 0; i < SERDES_NUM_CLOCKS; i++) { + if (parents[i] != p[i]) { + found = 0; + break; + } + } + + if (found) + break; + } - if (val == -1) + if (!found) { + /* + * This can never happen, unless we missed + * a valid combination in serdes_am654_mux_table. + */ + WARN(1, "Failed to find the parent of %s clock\n", + hw->init->name); return -EINVAL; + } - val <<= mux->shift; - ret = regmap_update_bits(regmap, reg, mux->mask << mux->shift, val); + val <<= AM654_SERDES_CTRL_CLKSEL_SHIFT; + ret = regmap_update_bits(regmap, reg, AM654_SERDES_CTRL_CLKSEL_MASK, + val); return ret; } @@ -333,21 +391,6 @@ static const struct clk_ops serdes_am654_clk_mux_ops = { .get_parent = serdes_am654_clk_mux_get_parent, }; -static int mux_table[SERDES_NUM_CLOCKS][3] = { - /* - * The entries represent values for selecting between - * {left input, external reference clock, right input} - * Only one of Left Output or Right Output should be used since - * both left and right output clock uses the same bits and modifying - * one clock will impact the other. - */ - { BIT(2), 0, BIT(0) }, /* Mux of CMU refclk */ - { -1, BIT(3), BIT(1) }, /* Mux of Left Output */ - { BIT(1), BIT(3) | BIT(1), -1 }, /* Mux of Right Output */ -}; - -static int mux_mask[SERDES_NUM_CLOCKS] = { 0x5, 0xa, 0xa }; - static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, const char *clock_name, int clock_num) { @@ -407,20 +450,11 @@ static int serdes_am654_clk_register(struct serdes_am654 *am654_phy, init->num_parents = num_parents; init->name = clock_name; - mux->table = mux_table[clock_num]; mux->regmap = regmap; mux->reg = reg; - mux->shift = 4; - mux->mask = mux_mask[clock_num]; + mux->clk_id = clock_num; mux->hw.init = init; - /* - * setup a sane default so get_parent() call evaluates - * to a valid parent. Index 1 is the safest choice as - * the default as it is valid value for all of serdes's - * output clocks. - */ - serdes_am654_clk_mux_set_parent(&mux->hw, 1); clk = devm_clk_register(dev, &mux->hw); if (IS_ERR(clk)) return PTR_ERR(clk);