From patchwork Fri Apr 5 11:08:30 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: 161836 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp298019jan; Fri, 5 Apr 2019 04:09:47 -0700 (PDT) X-Google-Smtp-Source: APXvYqxWCfAL8anQ8vrOKEbOUauS70vdn0Hc3UBJn36mvRQtnS1bFDfQoqf8HKRYGjagQR837kIU X-Received: by 2002:a63:5a1d:: with SMTP id o29mr11347565pgb.320.1554462587910; Fri, 05 Apr 2019 04:09:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554462587; cv=none; d=google.com; s=arc-20160816; b=Vq/j5MkYj4KvbXISZ3imQQsFnmKfTVuuSgoJpcIkNjjMTdxxM49up6nbkOdXNUDfAu JmnEpxbS1yYTDpC19xGsCmEuSfa89ZLDpf264iq2h7jwxSHz/OvDB7j1YpngpD/IR/US NoZ6ZOO104KCgYL6igzUYV2gkZGg+a+y1rfobRRgCNnefRuwjlsR6s7KqTQJc4hNyKGt t9iyxQh/VPZADU8ekV1IjIiTJJePY5EvUEmsAe/+6xHgfbW4StzyYAMWkYzI4jp2u9nN 3jn9GLYxCy/hXnVoGRCf0JBxgHCOkXWH0Uf0MZKYRy8oV4lmUVQRD4Oz86irYbHWmAUi xSYw== 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=uf3kjAaOPFCPxUbTLMm7tK0cexSLaZI+4gMmasE/zBA=; b=SOHVDa9ff/jzqlPJbwNiFLvSv5cfjEHUg7uQTrMSEzSohEPQrFNxYFblmTN0JYZxj8 6AbkbMtjkUeVDQ1/fhdU9A6rLLnV/EWoq++SbjizTqSM0SQ5rfchEWzt6/y57D/PF+PM W0osaGpIRfvn+eOR12E5a7rF/g7RNGtf00idG3MwhmZCTlwXzcYzUh8c/KnUhUakRbgl yXeK6U6mzXfMxt8ZTKGv2hWGC46uRqQf+24Nw4BweqDHIRqE3DMNJnvPQ5Nd/2JKLI83 vWn+T6VPu1n/Juwcm6iHLI5L+RxNMJchshT4HFK2fqMvvJHIRL3H3c7AWxg4v8Bi7g2u 5TGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b="A7RG/o+6"; 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 f1si17818452pgv.418.2019.04.05.04.09.47; Fri, 05 Apr 2019 04:09:47 -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="A7RG/o+6"; 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 S1730886AbfDELJq (ORCPT + 31 others); Fri, 5 Apr 2019 07:09:46 -0400 Received: from fllv0016.ext.ti.com ([198.47.19.142]:38488 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730497AbfDELJp (ORCPT ); Fri, 5 Apr 2019 07:09:45 -0400 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id x35B9fst045330; Fri, 5 Apr 2019 06:09:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1554462581; bh=uf3kjAaOPFCPxUbTLMm7tK0cexSLaZI+4gMmasE/zBA=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=A7RG/o+6qLPiouMf9ms10RcnWIncfVTvp6VDvYAxVlu+v6WysLYoyvmn4hLcRTvfL Q5/1s09ndi8EGB5dv6cc2xBCYiFbj82e4VIaB5mmK4BoNccGo0+hmpjLhE5ePB6GuG QfZtprTpY2VQNK9n3NCGNDuMn4diQvWx7OR3tjxQ= Received: from DFLE101.ent.ti.com (dfle101.ent.ti.com [10.64.6.22]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x35B9fkW029475 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 5 Apr 2019 06:09:41 -0500 Received: from DFLE108.ent.ti.com (10.64.6.29) by DFLE101.ent.ti.com (10.64.6.22) 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:40 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE108.ent.ti.com (10.64.6.29) 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:40 -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 x35B9aS1100251; Fri, 5 Apr 2019 06:09:39 -0500 From: Kishon Vijay Abraham I To: Rob Herring , Kishon Vijay Abraham I , CC: Mark Rutland , , Subject: [PATCH v4 1/5] phy: core: Add *release* phy_ops invoked when the consumer relinquishes PHY Date: Fri, 5 Apr 2019 16:38:30 +0530 Message-ID: <20190405110834.13083-2-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 Add a new phy_ops *release* invoked when the consumer relinquishes the PHY using phy_put/devm_phy_put. The initializations done by the PHY driver in of_xlate call back can be can be cleaned up here. Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-core.c | 5 +++++ include/linux/phy/phy.h | 2 ++ 2 files changed, 7 insertions(+) -- 2.17.1 diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index cb38f6e8614c..b9a4ebf35dd3 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -564,6 +564,11 @@ void phy_put(struct phy *phy) if (!phy || IS_ERR(phy)) return; + mutex_lock(&phy->mutex); + if (phy->ops->release) + phy->ops->release(phy); + mutex_unlock(&phy->mutex); + module_put(phy->ops->owner); put_device(&phy->dev); } diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 3f350e2749fe..ef13aea1d370 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -64,6 +64,7 @@ union phy_configure_opts { * @set_mode: set the mode of the phy * @reset: resetting the phy * @calibrate: calibrate the phy + * @release: ops to be performed while the consumer relinquishes the PHY * @owner: the module owner containing the ops */ struct phy_ops { @@ -105,6 +106,7 @@ struct phy_ops { union phy_configure_opts *opts); int (*reset)(struct phy *phy); int (*calibrate)(struct phy *phy); + void (*release)(struct phy *phy); struct module *owner; }; From patchwork Fri Apr 5 11:08:31 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: 161837 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp298064jan; Fri, 5 Apr 2019 04:09:50 -0700 (PDT) X-Google-Smtp-Source: APXvYqw6HOxeSEPPTXi7lyhij6qk4Mfx4GQcfSbd4gDkr4O8y/DEl1tWGlJFk0EpjNj+bWUy/1TP X-Received: by 2002:a63:7e10:: with SMTP id z16mr4745181pgc.40.1554462590323; Fri, 05 Apr 2019 04:09:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554462590; cv=none; d=google.com; s=arc-20160816; b=VT+SHzdaV57d146pm1le1CsnF92CtrbZjPJKLcRFVzgJw74RSF+t+azc9b2PoyNoKO F4LZtjZGPh2iA1d7I8ehjZh7Q72oJcuy9fCnxIv4bClTHlHxRn13jO4KYbF1WvpUFJ5h oHqmLNTBspQCg1Xn9M/t6TRgGzUC4WpH+13THHJl4gi2R0SWxv0sRWzDU8L9KOumhM5y a+6iSiJocilVU/GxlVKDoOh1nqXkY6pmdOYkPMrsqotte6WKJDH6VV4zZJaFAFqSR6rZ uisfYvfqG28puXIVNFn7iQrLQUu0tbTeZf5qCq1XKkWsMC9TX8DmAHat+g3RGMts3zCg 833A== 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=/QInjG/03abJVlZotne87DnL13Y9btTLzIL3PeoAEIk=; b=cPk/44/l0wf1qI6rhPmQJE+OYQo/gm0Zl/ec6V/DTtZgGitTVZyIYZnmNYPufB5ibs I1tA0p9Tm+nRLVPXx1SwBXTxC0UhjI3yKc7K8UBPZLJ+zuwVHC4oNITKJ2EIZJDcjR3L sQK6akqVFzI2/jeWBDl/StbcQoEgppDauUOo73zIhgJFyKRyizlXlEkYZ8qLot7GTIXy AIHf2F+Nf658b7pMqbEj6X9PIitSoD6U/Jw2jOv73fhWlbvZpfqbQ2Ze5gxDXJVAF3FH +40wrTqVL+6LbKocRVQulyYEC3DKtWI0SwrhPYIAdoJb+vQ+nIOimyo7KAa0rDKoa1Tx KN9A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=KgrmUA3s; 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 w7si16977445pgs.230.2019.04.05.04.09.50; Fri, 05 Apr 2019 04:09:50 -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=KgrmUA3s; 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 S1730975AbfDELJt (ORCPT + 31 others); Fri, 5 Apr 2019 07:09:49 -0400 Received: from lelv0143.ext.ti.com ([198.47.23.248]:50344 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730497AbfDELJr (ORCPT ); Fri, 5 Apr 2019 07:09:47 -0400 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id x35B9hoB129252; Fri, 5 Apr 2019 06:09:43 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1554462583; bh=/QInjG/03abJVlZotne87DnL13Y9btTLzIL3PeoAEIk=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=KgrmUA3sMtHCUW24sYcBUpAVLH4LEqw5rj/e/2nN7XqB+RugNI6acaAmjuSSjAFtc RkMNFfS543jdS5YhntqYZuXmepcqgY4xNE+4YSgmMf1pj0LV2UN2bvC1ktoIjSJNzS kvKvXpMwkbOo5P2wkm+Q/dg0Kq7x9Ou7DoF1rlkk= Received: from DFLE103.ent.ti.com (dfle103.ent.ti.com [10.64.6.24]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x35B9hbr019994 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 5 Apr 2019 06:09:43 -0500 Received: from DFLE105.ent.ti.com (10.64.6.26) by DFLE103.ent.ti.com (10.64.6.24) 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:42 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE105.ent.ti.com (10.64.6.26) 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:42 -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 x35B9aS2100251; Fri, 5 Apr 2019 06:09:41 -0500 From: Kishon Vijay Abraham I To: Rob Herring , Kishon Vijay Abraham I , CC: Mark Rutland , , Subject: [PATCH v4 2/5] phy: core: Invoke pm_runtime_get_*/pm_runtime_put_* before invoking reset callback Date: Fri, 5 Apr 2019 16:38:31 +0530 Message-ID: <20190405110834.13083-3-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 PHY drivers may try to access PHY registers in the ->reset() callback. Invoke phy_pm_runtime_get_sync() before invoking the ->reset() callback so that the PHY drivers don't have to enable clocks by themselves before accessing PHY registers. Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/phy-core.c | 6 ++++++ 1 file changed, 6 insertions(+) -- 2.17.1 diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index b9a4ebf35dd3..c147ba843f0b 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -384,10 +384,16 @@ int phy_reset(struct phy *phy) if (!phy || !phy->ops->reset) return 0; + ret = phy_pm_runtime_get_sync(phy); + if (ret < 0 && ret != -ENOTSUPP) + return ret; + mutex_lock(&phy->mutex); ret = phy->ops->reset(phy); mutex_unlock(&phy->mutex); + phy_pm_runtime_put(phy); + return ret; } EXPORT_SYMBOL_GPL(phy_reset); From patchwork Fri Apr 5 11:08:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kishon Vijay Abraham I X-Patchwork-Id: 161838 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp298120jan; Fri, 5 Apr 2019 04:09:53 -0700 (PDT) X-Google-Smtp-Source: APXvYqw69PerG54o/D91/U5ShjW6WNC+dG/Ib0BO2YzRzABYtQbaVPK/zqyWI32FMr+eM0R23Yu9 X-Received: by 2002:aa7:8694:: with SMTP id d20mr11969995pfo.81.1554462593099; Fri, 05 Apr 2019 04:09:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554462593; cv=none; d=google.com; s=arc-20160816; b=h7mlAI/P8Fs8rWBSaEcNyIerq0xdTzY1hXi5cqrgLTFfcD2qGwifWkznOU+GX1kem6 uRtkgsavhffvgb9t5yeAMR4I/XOhv0J3jvtp5BpCr0orI7w0/sLcjHR9ozf7cMiZ/cqp uncW6TNbXovB/rRKu8NMzmNj71bXx9zVqsoBpDxpiC21DeODIvR9mX5ZNMiqFKiDLAln LZETLBOo2P9MFaOIRfL2r1C6qxk8Ab0YhHFEH/J9Jz7geqrOH9JUgvX97b5GRyeBfAss qiohCeiYRED23d49p2DJkqUbJjzf2RD0Df7lYHIhgHO7Gl7BCD7JpaV6+iIdCd66WDY9 l+0A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=09NfpQBBcuRlAxaBWRtoet4oO0ojA9XKaxiPm5ReBS4=; b=ovmmUCuPfrQ8EuyBTneokESx37ncC08bjJPl/OcIw4x3SC7fPwD2Gf5/C9ZSH1xXHc RUKCynOynLIImakIlaO7UKLtfOekOvyi2R09TXzJAKBwLGl0GEUF6+1NRD9O0OPKKSwb trzUuR8qH4Kp0C97QoyPFSMQmVRX79xMKq5vYQae2wP/2GmW4vsKOBXeQ6R25CCJo4H+ S3fnAy/nuCxImM2L/DjxsTzC5+IFxhA3kdt+AvTBXdJw/I/clLLnon9O64Sbip0j5O2/ 5FB2mR3rywxXz5auzAqITUf8KaQoR9PGr355csEI6Ky1agfkZ981R/e2sbnjlDVB1Noq kMGw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=Sbw7sGw2; 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 w7si16977445pgs.230.2019.04.05.04.09.52; Fri, 05 Apr 2019 04:09:53 -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=Sbw7sGw2; 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 S1731033AbfDELJv (ORCPT + 31 others); Fri, 5 Apr 2019 07:09:51 -0400 Received: from fllv0016.ext.ti.com ([198.47.19.142]:38502 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730927AbfDELJu (ORCPT ); Fri, 5 Apr 2019 07:09:50 -0400 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id x35B9jWw045354; Fri, 5 Apr 2019 06:09:45 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1554462585; bh=09NfpQBBcuRlAxaBWRtoet4oO0ojA9XKaxiPm5ReBS4=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=Sbw7sGw2vXgu2KZtpC7tYv0RLsD00/leKDXa4wb60JrD8y5xHRC5mInpwe3rj6oQl nEHaPOjwgsS/ozhIVTfQqZlkYQbPefdDLIntMPl32GbwwdooHPSlj1+ClvQfhg53cY xhY/meiYbBcZqilESdAe5qLwE3UliNW2QkFUadUY= Received: from DFLE100.ent.ti.com (dfle100.ent.ti.com [10.64.6.21]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x35B9jx1020039 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 5 Apr 2019 06:09:45 -0500 Received: from DFLE101.ent.ti.com (10.64.6.22) by DFLE100.ent.ti.com (10.64.6.21) 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:45 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE101.ent.ti.com (10.64.6.22) 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:45 -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 x35B9aS3100251; Fri, 5 Apr 2019 06:09:43 -0500 From: Kishon Vijay Abraham I To: Rob Herring , Kishon Vijay Abraham I , CC: Mark Rutland , , Subject: [PATCH v4 3/5] dt-bindings: phy: ti: Add dt binding documentation for SERDES in AM654x SoC Date: Fri, 5 Apr 2019 16:38:32 +0530 Message-ID: <20190405110834.13083-4-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 AM654x has two SERDES instances. Each instance has three input clocks (left input, externel reference clock and right input) and two output clocks (left output and right output) in addition to a PLL mux clock which the SERDES uses for Clock Multiplier Unit (CMU refclock). The PLL mux clock can select from one of the three input clocks. The right output can select between left input and external reference clock while the left output can select between the right input and external reference clock. The left and right input reference clock of SERDES0 and SERDES1 respectively are connected to the SoC clock. In the case of two lane SERDES personality card, the left input of SERDES1 is connected to the right output of SERDES0 in a chained fashion. See section "Reference Clock Distribution" of AM65x Sitara Processors TRM (SPRUID7 – April 2018) for more details. Add dt-binding documentation in order to represent all these different configurations in device tree. Signed-off-by: Kishon Vijay Abraham I --- .../bindings/phy/ti,phy-am654-serdes.txt | 82 +++++++++++++++++++ include/dt-bindings/phy/phy-am654-serdes.h | 13 +++ 2 files changed, 95 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt create mode 100644 include/dt-bindings/phy/phy-am654-serdes.h -- 2.17.1 diff --git a/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt b/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt new file mode 100644 index 000000000000..64b286d2d398 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/ti,phy-am654-serdes.txt @@ -0,0 +1,82 @@ +TI AM654 SERDES + +Required properties: + - compatible: Should be "ti,phy-am654-serdes" + - reg : Address and length of the register set for the device. + - #phy-cells: determine the number of cells that should be given in the + phandle while referencing this phy. Should be "2". The 1st cell + corresponds to the phy type (should be one of the types specified in + include/dt-bindings/phy/phy.h) and the 2nd cell should be the serdes + lane function. + If SERDES0 is referenced 2nd cell should be: + 0 - USB3 + 1 - PCIe0 Lane0 + 2 - ICSS2 SGMII Lane0 + If SERDES1 is referenced 2nd cell should be: + 0 - PCIe1 Lane0 + 1 - PCIe0 Lane1 + 2 - ICSS2 SGMII Lane1 + - power-domains: As documented by the generic PM domain bindings in + Documentation/devicetree/bindings/power/power_domain.txt. + - clocks: List of clock-specifiers representing the input to the SERDES. + Should have 3 items representing the left input clock, external + reference clock and right input clock in that order. + - clock-output-names: List of clock names for each of the clock outputs of + SERDES. Should have 3 items for CMU reference clock, + left output clock and right output clock in that order. + - assigned-clocks: As defined in + Documentation/devicetree/bindings/clock/clock-bindings.txt + - assigned-clock-parents: As defined in + Documentation/devicetree/bindings/clock/clock-bindings.txt + - #clock-cells: Should be <1> to choose between the 3 output clocks. + Defined in Documentation/devicetree/bindings/clock/clock-bindings.txt + + The following macros are defined in dt-bindings/phy/phy-am654-serdes.h + for selecting the correct reference clock. This can be used while + specifying the clocks created by SERDES. + => AM654_SERDES_CMU_REFCLK + => AM654_SERDES_LO_REFCLK + => AM654_SERDES_RO_REFCLK + + - mux-controls: Phandle to the multiplexer that is used to select the lane + function. See #phy-cells above to see the multiplex values. + +Example: + +Example for SERDES0 is given below. It has 3 clock inputs; +left input reference clock as indicated by <&k3_clks 153 4>, external +reference clock as indicated by <&k3_clks 153 1> and right input +reference clock as indicated by <&serdes1 AM654_SERDES_LO_REFCLK>. (The +right input of SERDES0 is connected to the left output of SERDES1). + +SERDES0 registers 3 clock outputs as indicated in clock-output-names. The +first refers to the CMU reference clock, second refers to the left output +reference clock and the third refers to the right output reference clock. + +The assigned-clocks and assigned-clock-parents is used here to set the +parent of left input reference clock to MAINHSDIV_CLKOUT4 and parent of +CMU reference clock to left input reference clock. + +serdes0: serdes@900000 { + compatible = "ti,phy-am654-serdes"; + reg = <0x0 0x900000 0x0 0x2000>; + reg-names = "serdes"; + #phy-cells = <2>; + power-domains = <&k3_pds 153>; + clocks = <&k3_clks 153 4>, <&k3_clks 153 1>, + <&serdes1 AM654_SERDES_LO_REFCLK>; + clock-output-names = "serdes0_cmu_refclk", "serdes0_lo_refclk", + "serdes0_ro_refclk"; + assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>; + assigned-clock-parents = <&k3_clks 153 8>, <&k3_clks 153 4>; + ti,serdes-clk = <&serdes0_clk>; + mux-controls = <&serdes_mux 0>; + #clock-cells = <1>; +}; + +Example for PCIe consumer node using the SERDES PHY specifier is given below. +&pcie0_rc { + num-lanes = <2>; + phys = <&serdes0 PHY_TYPE_PCIE 1>, <&serdes1 PHY_TYPE_PCIE 1>; + phy-names = "pcie-phy0", "pcie-phy1"; +}; diff --git a/include/dt-bindings/phy/phy-am654-serdes.h b/include/dt-bindings/phy/phy-am654-serdes.h new file mode 100644 index 000000000000..e8d901729ed9 --- /dev/null +++ b/include/dt-bindings/phy/phy-am654-serdes.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides constants for AM654 SERDES. + */ + +#ifndef _DT_BINDINGS_AM654_SERDES +#define _DT_BINDINGS_AM654_SERDES + +#define AM654_SERDES_CMU_REFCLK 0 +#define AM654_SERDES_LO_REFCLK 1 +#define AM654_SERDES_RO_REFCLK 2 + +#endif /* _DT_BINDINGS_AM654_SERDES */ From patchwork Fri Apr 5 11:08:33 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: 161840 Delivered-To: patch@linaro.org Received: by 2002:a02:c6d8:0:0:0:0:0 with SMTP id r24csp298242jan; Fri, 5 Apr 2019 04:10:00 -0700 (PDT) X-Google-Smtp-Source: APXvYqzb3BIdO472EIackSJvwZfV1ua0ITX/yvzqJWyDWpY2OSN60LAGu5uzBWeI2UDGex1otlMq X-Received: by 2002:a62:1e06:: with SMTP id e6mr11838913pfe.168.1554462600902; Fri, 05 Apr 2019 04:10:00 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554462600; cv=none; d=google.com; s=arc-20160816; b=Zh3uxQ20CCQqaMNUgdEaBhM9pt46xK0y9whyeTd2ZW8i3vWdyXsBWGZCPwtbR6VdVO ol1AhLcPxiqIalgIvo7p22yyRBjbBaqr4SVoN8ZphaHV7tKiZBc7ygNpiiGOu0jMAqnu qbgqqUmZePhTm5ugMSsFVrDSJ5GHWoN49djwZS5twjxMn3dLuwTRenM3SGoC+n2llEC+ qyDYUc89kJbqZgtgfdRbdmJ71xkjW4zu4i3Vvw4jCuNEntRrzyoi5oCcSFUZLJl1BeBT TNAOf5wb7PttR4SI57iHaZQn+sRDVQ0/e8bzWR1w99rYPm5DUeuUG9pX9iYIm5U+qNcv n8tQ== 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=ock39msnvgOCBQyIhlr3bi3AZKgl2K2V0sK1UfbJFpQ=; b=cwtEIwpTdrmsVXVZbccwyjfI8rogfPW84eHiHbtRjT6t/y3Z+jlusTq5J/1zvPcA+D 6GamFaaVJ010AIWrLzQwKp8WFq3rySaFi+CfgP+VrtK9UH1xLFKmiTqJCULPMv5ZopeE vDosFvGh2E6s49foVc9tV1p0GXYNSw2xI9inM2tRNmrDP/J/6BJfgx43YTCyscidvIhm uoZ5NrSdKqY4P6ZnYXuqIAYgnvsncrTOM9R2ox79FsDzf8P6cZiDW4ZT2odFz7YHOkwv upGUYefmqz0yeW0UICedjtc7YHjx1KeyYVT4Z1BGbi1xQHp9Y0J2NWjhpJ1NmILDuoCC x5UA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=IbLetkvO; 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 h18si17525206pgj.47.2019.04.05.04.10.00; Fri, 05 Apr 2019 04:10:00 -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=IbLetkvO; 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 S1731069AbfDELJy (ORCPT + 31 others); Fri, 5 Apr 2019 07:09:54 -0400 Received: from fllv0016.ext.ti.com ([198.47.19.142]:38512 "EHLO fllv0016.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730497AbfDELJw (ORCPT ); Fri, 5 Apr 2019 07:09:52 -0400 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by fllv0016.ext.ti.com (8.15.2/8.15.2) with ESMTP id x35B9lSj045380; Fri, 5 Apr 2019 06:09:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1554462587; bh=ock39msnvgOCBQyIhlr3bi3AZKgl2K2V0sK1UfbJFpQ=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=IbLetkvODQKyxAxgQ/S4cmtl4jGf6gaAsZy3hw6WroydOxef/p6GECOG9QpklU3GH 8gi39UHsZFz1kOMa+zfSR5kMX7v7p7GuwgQO/TnInltOngvgErPjsBFDtMqvp0E6WX c/jbb6u9y0UuOtLe+WRO5YtYds1gQbNZ8t401rEQ= Received: from DFLE113.ent.ti.com (dfle113.ent.ti.com [10.64.6.34]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x35B9lTK029567 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 5 Apr 2019 06:09:47 -0500 Received: from DFLE109.ent.ti.com (10.64.6.30) by DFLE113.ent.ti.com (10.64.6.34) 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:47 -0500 Received: from lelv0327.itg.ti.com (10.180.67.183) by DFLE109.ent.ti.com (10.64.6.30) 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:47 -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 x35B9aS4100251; Fri, 5 Apr 2019 06:09:45 -0500 From: Kishon Vijay Abraham I To: Rob Herring , Kishon Vijay Abraham I , CC: Mark Rutland , , Subject: [PATCH v4 4/5] phy: ti: Add a new SERDES driver for TI's AM654x SoC Date: Fri, 5 Apr 2019 16:38:33 +0530 Message-ID: <20190405110834.13083-5-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 Add a new SERDES driver for TI's AM654x SoC which configures the SERDES only for PCIe. Support fo USB3 will be added later. SERDES in am654x has three input clocks (left input, externel reference clock and right input) and two output clocks (left output and right output) in addition to a PLL mux clock which the SERDES uses for Clock Multiplier Unit (CMU refclock). The PLL mux clock can select from one of the three input clocks. The right output can select between left input and external reference clock while the left output can select between the right input and external reference clock. The driver has support to select PLL mux and left/right output mux as specified in device tree. [rogerq@ti.com: Fix boot lockup caused by accessing a structure member (hw->init) allocated in stack of probe() and accessed in get_parent] [rogerq@ti.com: Fix "Failed to find the parent" warnings] Signed-off-by: Roger Quadros Signed-off-by: Kishon Vijay Abraham I --- drivers/phy/ti/Kconfig | 12 + drivers/phy/ti/Makefile | 1 + drivers/phy/ti/phy-am654-serdes.c | 624 ++++++++++++++++++++++++++++++ 3 files changed, 637 insertions(+) create mode 100644 drivers/phy/ti/phy-am654-serdes.c -- 2.17.1 diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig index 7cdc35f8c862..6931c87235b9 100644 --- a/drivers/phy/ti/Kconfig +++ b/drivers/phy/ti/Kconfig @@ -20,6 +20,18 @@ config PHY_DM816X_USB help Enable this for dm816x USB to work. +config PHY_AM654_SERDES + tristate "TI AM654 SERDES support" + depends on OF && ARCH_K3 || COMPILE_TEST + depends on COMMON_CLK + select GENERIC_PHY + select MULTIPLEXER + select REGMAP_MMIO + select MUX_MMIO + help + This option enables support for TI AM654 SerDes PHY used for + PCIe. + config OMAP_CONTROL_PHY tristate "OMAP CONTROL PHY Driver" depends on ARCH_OMAP2PLUS || COMPILE_TEST diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile index 368de8e1548d..601bbd88f35e 100644 --- a/drivers/phy/ti/Makefile +++ b/drivers/phy/ti/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o +obj-$(CONFIG_PHY_AM654_SERDES) += phy-am654-serdes.o obj-$(CONFIG_PHY_TI_GMII_SEL) += phy-gmii-sel.o obj-$(CONFIG_PHY_TI_KEYSTONE_SERDES) += phy-keystone-serdes.o diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c new file mode 100644 index 000000000000..4817c67abbbb --- /dev/null +++ b/drivers/phy/ti/phy-am654-serdes.c @@ -0,0 +1,624 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * PCIe SERDES driver for AM654x SoC + * + * Copyright (C) 2018 - 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Author: Kishon Vijay Abraham I + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMU_R07C 0x7c + +#define COMLANE_R138 0xb38 +#define VERSION 0x70 + +#define COMLANE_R190 0xb90 + +#define COMLANE_R194 0xb94 + +#define SERDES_CTRL 0x1fd0 + +#define WIZ_LANEXCTL_STS 0x1fe0 +#define TX0_DISABLE_STATE 0x4 +#define TX0_SLEEP_STATE 0x5 +#define TX0_SNOOZE_STATE 0x6 +#define TX0_ENABLE_STATE 0x7 + +#define RX0_DISABLE_STATE 0x4 +#define RX0_SLEEP_STATE 0x5 +#define RX0_SNOOZE_STATE 0x6 +#define RX0_ENABLE_STATE 0x7 + +#define WIZ_PLL_CTRL 0x1ff4 +#define PLL_DISABLE_STATE 0x4 +#define PLL_SLEEP_STATE 0x5 +#define PLL_SNOOZE_STATE 0x6 +#define PLL_ENABLE_STATE 0x7 + +#define PLL_LOCK_TIME 100000 /* in microseconds */ +#define SLEEP_TIME 100 /* in microseconds */ + +#define LANE_USB3 0x0 +#define LANE_PCIE0_LANE0 0x1 + +#define LANE_PCIE1_LANE0 0x0 +#define LANE_PCIE0_LANE1 0x1 + +#define SERDES_NUM_CLOCKS 3 + +struct serdes_am654_clk_mux { + struct clk_hw hw; + struct regmap *regmap; + unsigned int reg; + int *table; + u32 mask; + u8 shift; + struct clk_init_data clk_data; +}; + +#define to_serdes_am654_clk_mux(_hw) \ + container_of(_hw, struct serdes_am654_clk_mux, hw) + +static struct regmap_config serdes_am654_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .fast_io = true, +}; + +static const struct reg_field cmu_master_cdn_o = REG_FIELD(CMU_R07C, 24, 24); +static const struct reg_field config_version = REG_FIELD(COMLANE_R138, 16, 23); +static const struct reg_field l1_master_cdn_o = REG_FIELD(COMLANE_R190, 9, 9); +static const struct reg_field cmu_ok_i_0 = REG_FIELD(COMLANE_R194, 19, 19); +static const struct reg_field por_en = REG_FIELD(SERDES_CTRL, 29, 29); +static const struct reg_field tx0_enable = REG_FIELD(WIZ_LANEXCTL_STS, 29, 31); +static const struct reg_field rx0_enable = REG_FIELD(WIZ_LANEXCTL_STS, 13, 15); +static const struct reg_field pll_enable = REG_FIELD(WIZ_PLL_CTRL, 29, 31); +static const struct reg_field pll_ok = REG_FIELD(WIZ_PLL_CTRL, 28, 28); + +struct serdes_am654 { + struct regmap *regmap; + struct regmap_field *cmu_master_cdn_o; + struct regmap_field *config_version; + struct regmap_field *l1_master_cdn_o; + struct regmap_field *cmu_ok_i_0; + struct regmap_field *por_en; + struct regmap_field *tx0_enable; + struct regmap_field *rx0_enable; + struct regmap_field *pll_enable; + struct regmap_field *pll_ok; + + struct device *dev; + struct mux_control *control; + bool busy; + u32 type; + struct device_node *of_node; + struct clk_onecell_data clk_data; + struct clk *clks[SERDES_NUM_CLOCKS]; +}; + +static int serdes_am654_enable_pll(struct serdes_am654 *phy) +{ + int ret; + u32 val; + + ret = regmap_field_write(phy->pll_enable, PLL_ENABLE_STATE); + if (ret) + return ret; + + return regmap_field_read_poll_timeout(phy->pll_ok, val, val, 1000, + PLL_LOCK_TIME); +} + +static void serdes_am654_disable_pll(struct serdes_am654 *phy) +{ + struct device *dev = phy->dev; + int ret; + + ret = regmap_field_write(phy->pll_enable, PLL_DISABLE_STATE); + if (ret) + dev_err(dev, "Failed to disable PLL\n"); +} + +static int serdes_am654_enable_txrx(struct serdes_am654 *phy) +{ + int ret; + + /* Enable TX */ + ret = regmap_field_write(phy->tx0_enable, TX0_ENABLE_STATE); + if (ret) + return ret; + + /* Enable RX */ + ret = regmap_field_write(phy->rx0_enable, RX0_ENABLE_STATE); + if (ret) + return ret; + + return 0; +} + +static int serdes_am654_disable_txrx(struct serdes_am654 *phy) +{ + int ret; + + /* Disable TX */ + ret = regmap_field_write(phy->tx0_enable, TX0_DISABLE_STATE); + if (ret) + return ret; + + /* Disable RX */ + ret = regmap_field_write(phy->rx0_enable, RX0_DISABLE_STATE); + if (ret) + return ret; + + return 0; +} + +static int serdes_am654_power_on(struct phy *x) +{ + struct serdes_am654 *phy = phy_get_drvdata(x); + struct device *dev = phy->dev; + int ret; + u32 val; + + ret = serdes_am654_enable_pll(phy); + if (ret) { + dev_err(dev, "Failed to enable PLL\n"); + return ret; + } + + ret = serdes_am654_enable_txrx(phy); + if (ret) { + dev_err(dev, "Failed to enable TX RX\n"); + return ret; + } + + return regmap_field_read_poll_timeout(phy->cmu_ok_i_0, val, val, + SLEEP_TIME, PLL_LOCK_TIME); +} + +static int serdes_am654_power_off(struct phy *x) +{ + struct serdes_am654 *phy = phy_get_drvdata(x); + + serdes_am654_disable_txrx(phy); + serdes_am654_disable_pll(phy); + + return 0; +} + +static int serdes_am654_init(struct phy *x) +{ + struct serdes_am654 *phy = phy_get_drvdata(x); + int ret; + + ret = regmap_field_write(phy->config_version, VERSION); + if (ret) + return ret; + + ret = regmap_field_write(phy->cmu_master_cdn_o, 0x1); + if (ret) + return ret; + + ret = regmap_field_write(phy->l1_master_cdn_o, 0x1); + if (ret) + return ret; + + return 0; +} + +static int serdes_am654_reset(struct phy *x) +{ + struct serdes_am654 *phy = phy_get_drvdata(x); + int ret; + + ret = regmap_field_write(phy->por_en, 0x1); + if (ret) + return ret; + + mdelay(1); + + ret = regmap_field_write(phy->por_en, 0x0); + if (ret) + return ret; + + return 0; +} + +static void serdes_am654_release(struct phy *x) +{ + struct serdes_am654 *phy = phy_get_drvdata(x); + + phy->type = PHY_NONE; + phy->busy = false; + mux_control_deselect(phy->control); +} + +struct phy *serdes_am654_xlate(struct device *dev, struct of_phandle_args + *args) +{ + struct serdes_am654 *am654_phy; + struct phy *phy; + int ret; + + phy = of_phy_simple_xlate(dev, args); + if (IS_ERR(phy)) + return phy; + + am654_phy = phy_get_drvdata(phy); + if (am654_phy->busy) + return ERR_PTR(-EBUSY); + + ret = mux_control_select(am654_phy->control, args->args[1]); + if (ret) { + dev_err(dev, "Failed to select SERDES Lane Function\n"); + return ERR_PTR(ret); + } + + am654_phy->busy = true; + am654_phy->type = args->args[0]; + + return phy; +} + +static const struct phy_ops ops = { + .reset = serdes_am654_reset, + .init = serdes_am654_init, + .power_on = serdes_am654_power_on, + .power_off = serdes_am654_power_off, + .release = serdes_am654_release, + .owner = THIS_MODULE, +}; + +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); + + /* Make the parent lookup to fail */ + return num_parents; +} + +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 ret; + + val = mux->table[index]; + + if (val == -1) + return -EINVAL; + + val <<= mux->shift; + ret = regmap_update_bits(regmap, reg, mux->mask << mux->shift, val); + + return ret; +} + +static const struct clk_ops serdes_am654_clk_mux_ops = { + .set_parent = serdes_am654_clk_mux_set_parent, + .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) +{ + struct device_node *node = am654_phy->of_node; + struct device *dev = am654_phy->dev; + struct serdes_am654_clk_mux *mux; + struct device_node *regmap_node; + const char **parent_names; + struct clk_init_data *init; + unsigned int num_parents; + struct regmap *regmap; + const __be32 *addr; + unsigned int reg; + struct clk *clk; + + mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL); + if (!mux) + return -ENOMEM; + + init = &mux->clk_data; + + regmap_node = of_parse_phandle(node, "ti,serdes-clk", 0); + of_node_put(regmap_node); + if (!regmap_node) { + dev_err(dev, "Fail to get serdes-clk node\n"); + return -ENODEV; + } + + regmap = syscon_node_to_regmap(regmap_node->parent); + if (IS_ERR(regmap)) { + dev_err(dev, "Fail to get Syscon regmap\n"); + return PTR_ERR(regmap); + } + + num_parents = of_clk_get_parent_count(node); + if (num_parents < 2) { + dev_err(dev, "SERDES clock must have parents\n"); + return -EINVAL; + } + + parent_names = devm_kzalloc(dev, (sizeof(char *) * num_parents), + GFP_KERNEL); + if (!parent_names) + return -ENOMEM; + + of_clk_parent_fill(node, parent_names, num_parents); + + addr = of_get_address(regmap_node, 0, NULL, NULL); + if (!addr) + return -EINVAL; + + reg = be32_to_cpu(*addr); + + init->ops = &serdes_am654_clk_mux_ops; + init->flags = CLK_SET_RATE_NO_REPARENT; + init->parent_names = parent_names; + 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->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); + + am654_phy->clks[clock_num] = clk; + + return 0; +} + +static const struct of_device_id serdes_am654_id_table[] = { + { + .compatible = "ti,phy-am654-serdes", + }, + {} +}; +MODULE_DEVICE_TABLE(of, serdes_am654_id_table); + +static int serdes_am654_regfield_init(struct serdes_am654 *am654_phy) +{ + struct regmap *regmap = am654_phy->regmap; + struct device *dev = am654_phy->dev; + + am654_phy->cmu_master_cdn_o = devm_regmap_field_alloc(dev, regmap, + cmu_master_cdn_o); + if (IS_ERR(am654_phy->cmu_master_cdn_o)) { + dev_err(dev, "CMU_MASTER_CDN_O reg field init failed\n"); + return PTR_ERR(am654_phy->cmu_master_cdn_o); + } + + am654_phy->config_version = devm_regmap_field_alloc(dev, regmap, + config_version); + if (IS_ERR(am654_phy->config_version)) { + dev_err(dev, "CONFIG_VERSION reg field init failed\n"); + return PTR_ERR(am654_phy->config_version); + } + + am654_phy->l1_master_cdn_o = devm_regmap_field_alloc(dev, regmap, + l1_master_cdn_o); + if (IS_ERR(am654_phy->l1_master_cdn_o)) { + dev_err(dev, "L1_MASTER_CDN_O reg field init failed\n"); + return PTR_ERR(am654_phy->l1_master_cdn_o); + } + + am654_phy->cmu_ok_i_0 = devm_regmap_field_alloc(dev, regmap, + cmu_ok_i_0); + if (IS_ERR(am654_phy->cmu_ok_i_0)) { + dev_err(dev, "CMU_OK_I_0 reg field init failed\n"); + return PTR_ERR(am654_phy->cmu_ok_i_0); + } + + am654_phy->por_en = devm_regmap_field_alloc(dev, regmap, por_en); + if (IS_ERR(am654_phy->por_en)) { + dev_err(dev, "POR_EN reg field init failed\n"); + return PTR_ERR(am654_phy->por_en); + } + + am654_phy->tx0_enable = devm_regmap_field_alloc(dev, regmap, + tx0_enable); + if (IS_ERR(am654_phy->tx0_enable)) { + dev_err(dev, "TX0_ENABLE reg field init failed\n"); + return PTR_ERR(am654_phy->tx0_enable); + } + + am654_phy->rx0_enable = devm_regmap_field_alloc(dev, regmap, + rx0_enable); + if (IS_ERR(am654_phy->rx0_enable)) { + dev_err(dev, "RX0_ENABLE reg field init failed\n"); + return PTR_ERR(am654_phy->rx0_enable); + } + + am654_phy->pll_enable = devm_regmap_field_alloc(dev, regmap, + pll_enable); + if (IS_ERR(am654_phy->pll_enable)) { + dev_err(dev, "PLL_ENABLE reg field init failed\n"); + return PTR_ERR(am654_phy->pll_enable); + } + + am654_phy->pll_ok = devm_regmap_field_alloc(dev, regmap, pll_ok); + if (IS_ERR(am654_phy->pll_ok)) { + dev_err(dev, "PLL_OK reg field init failed\n"); + return PTR_ERR(am654_phy->pll_ok); + } + + return 0; +} + +static int serdes_am654_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct clk_onecell_data *clk_data; + struct serdes_am654 *am654_phy; + struct mux_control *control; + const char *clock_name; + struct regmap *regmap; + void __iomem *base; + struct phy *phy; + int ret; + int i; + + am654_phy = devm_kzalloc(dev, sizeof(*am654_phy), GFP_KERNEL); + if (!am654_phy) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + regmap = devm_regmap_init_mmio(dev, base, &serdes_am654_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "Failed to initialize regmap\n"); + return PTR_ERR(regmap); + } + + control = devm_mux_control_get(dev, NULL); + if (IS_ERR(control)) + return PTR_ERR(control); + + am654_phy->dev = dev; + am654_phy->of_node = node; + am654_phy->regmap = regmap; + am654_phy->control = control; + am654_phy->type = PHY_NONE; + + ret = serdes_am654_regfield_init(am654_phy); + if (ret) { + dev_err(dev, "Failed to initialize regfields\n"); + return ret; + } + + platform_set_drvdata(pdev, am654_phy); + + for (i = 0; i < SERDES_NUM_CLOCKS; i++) { + ret = of_property_read_string_index(node, "clock-output-names", + i, &clock_name); + if (ret) { + dev_err(dev, "Failed to get clock name\n"); + return ret; + } + + ret = serdes_am654_clk_register(am654_phy, clock_name, i); + if (ret) { + dev_err(dev, "Failed to initialize clock %s\n", + clock_name); + return ret; + } + } + + clk_data = &am654_phy->clk_data; + clk_data->clks = am654_phy->clks; + clk_data->clk_num = SERDES_NUM_CLOCKS; + ret = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (ret) + return ret; + + pm_runtime_enable(dev); + + phy = devm_phy_create(dev, NULL, &ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + phy_set_drvdata(phy, am654_phy); + phy_provider = devm_of_phy_provider_register(dev, serdes_am654_xlate); + if (IS_ERR(phy_provider)) { + ret = PTR_ERR(phy_provider); + goto clk_err; + } + + return 0; + +clk_err: + of_clk_del_provider(node); + + return ret; +} + +static int serdes_am654_remove(struct platform_device *pdev) +{ + struct serdes_am654 *am654_phy = platform_get_drvdata(pdev); + struct device_node *node = am654_phy->of_node; + + pm_runtime_disable(&pdev->dev); + of_clk_del_provider(node); + + return 0; +} + +static struct platform_driver serdes_am654_driver = { + .probe = serdes_am654_probe, + .remove = serdes_am654_remove, + .driver = { + .name = "phy-am654", + .of_match_table = serdes_am654_id_table, + }, +}; +module_platform_driver(serdes_am654_driver); + +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TI AM654x SERDES driver"); +MODULE_LICENSE("GPL v2"); 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);