From patchwork Wed Feb 6 11:07:50 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: 157617 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp6277034jaa; Wed, 6 Feb 2019 03:08:42 -0800 (PST) X-Google-Smtp-Source: AHgI3IbiX+/Hf6MPV81vg6VymWJj28jvCasgpSfGDG070604mFfUXeMaTS7oM3z6032oXnrhYAXU X-Received: by 2002:a63:1c53:: with SMTP id c19mr9165895pgm.296.1549451322745; Wed, 06 Feb 2019 03:08:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549451322; cv=none; d=google.com; s=arc-20160816; b=pl3NTxAIhwGa7hEUOAJrGG+hfNcZ8439ylEu8t5l2SalI685eS06BxFt3DdsWTXeIB hsXaDDPg094mwK8JZGg8WK0G9JVYSMtBG8ibqTBnHgx5p67GJMhDvkDW4c1MMXk2FmQm KerK1vrvktk1/stb+cjlIP6DiWnDhXbWZ4/P2trhw5TVRr0Y7Gv3I+id5vf6+EX9pc5t 4omGwmBnpklt73LKkS/wjeuxtzFlfFqkZ+FjwpIAi0C4Cg9p55GprM0F/8PTFRQDwst0 rNl6ROMAWxSdFUO64sQl4wW8Y4z6BtYgBpmttM9P1RcYuGFk+MDdSXPHfy3ykoSwct9W Djfg== 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=JcIZCr2ZoDLLnRrlQJdSZpB3Xsnkta8Ze+j4FMA3BL0=; b=vdcgTp3HtNgJyj1qhKpS7RJyFncOokToNGu1rGy2T0p3yYlVZCv2+hXj/OZvPOeyuK zWrnoaVeV7JmEfRwX42+Zad19WDBxLMvJk35XrTImwYv1nuz/59JBMeWcAPep1CpJNUC Z9HewTHDfsag3MhOE38DqNQRw04ADv6dDGmgVI7jQEOSG6A8JouME6Z6L3j3902XnMAa aBR9c/Upt7Yy7N6NGwW+kpP21aNGN4I763JeDU1Quy5iHsb25QTRtHMQ0uWesckAndcK AjnAlTZkJddIpRTc0d7txiAEhng2EaeQK4TyTHABAic93PD1p9XppkHplREcGQU/OG1C Y61w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=Vquy3WCO; 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 h91si5688201pld.411.2019.02.06.03.08.42; Wed, 06 Feb 2019 03:08:42 -0800 (PST) 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=Vquy3WCO; 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 S1729644AbfBFLIl (ORCPT + 31 others); Wed, 6 Feb 2019 06:08:41 -0500 Received: from lelv0143.ext.ti.com ([198.47.23.248]:33516 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726708AbfBFLIj (ORCPT ); Wed, 6 Feb 2019 06:08:39 -0500 Received: from lelv0266.itg.ti.com ([10.180.67.225]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id x16B8bw7103484; Wed, 6 Feb 2019 05:08:37 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1549451317; bh=JcIZCr2ZoDLLnRrlQJdSZpB3Xsnkta8Ze+j4FMA3BL0=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=Vquy3WCOAHbGiOAM6abAhmZgQkiwMmrHl3IDdFMnE7Num/Q1BVYj2fWlpjwsSh+Qi i0hiNBDUhSy6Ut3lGTAjQwmgtwRiHmzOaPVhVzcOnVwyQ+prE/YM+Kj8o4gCor/LFh 8FWBp0vF0HnunKJ6nZVMzs9dluyR6j7U0IorBELY= Received: from DLEE109.ent.ti.com (dlee109.ent.ti.com [157.170.170.41]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x16B8b7Y111780 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 6 Feb 2019 05:08:37 -0600 Received: from DLEE108.ent.ti.com (157.170.170.38) 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.1591.10; Wed, 6 Feb 2019 05:08:37 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE108.ent.ti.com (157.170.170.38) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Wed, 6 Feb 2019 05:08:36 -0600 Received: from a0393678ub.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id x16B8WaZ024645; Wed, 6 Feb 2019 05:08:35 -0600 From: Kishon Vijay Abraham I To: Kishon Vijay Abraham I , Rob Herring CC: Roger Quadros , , Subject: [PATCH v2 1/4] phy: core: Add *release* phy_ops invoked when the consumer relinquishes PHY Date: Wed, 6 Feb 2019 16:37:50 +0530 Message-ID: <20190206110753.28738-2-kishon@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190206110753.28738-1-kishon@ti.com> References: <20190206110753.28738-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 19b05e824ee4..d4bd85afdc91 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 e8e118d70fd7..feb8dce54ac2 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -63,6 +63,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 reliquishes the PHY * @owner: the module owner containing the ops */ struct phy_ops { @@ -104,6 +105,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 Wed Feb 6 11:07:51 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: 157618 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp6277076jaa; Wed, 6 Feb 2019 03:08:45 -0800 (PST) X-Google-Smtp-Source: AHgI3IZmXKrBOxAUpUd/pJJt9C2z+Stxab5zM1fNWA0C2LjUy8JHpdihl99CAtV2AIq3NjgVXNZL X-Received: by 2002:a17:902:8ec9:: with SMTP id x9mr10258417plo.27.1549451324965; Wed, 06 Feb 2019 03:08:44 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549451324; cv=none; d=google.com; s=arc-20160816; b=qILG0N5USZRWcjOhWdQ05S8MRfAMMUu9DuXqgmF2WxHH6wVyBAs8Pubxo4vkkFS4FQ 4Z7btmZycZaZQabonka1zzXTy+IJgGqVg8RR9/8Kl+7M8QMYFjhRM5ptbGRWFvfxpLDI Xq/+lepPQ87wWIer1uFVHHuEoTzoNky6oF6XHqIsFtnD1b26nelslgyrL6IdEESS1LdB 4b9lEl4s6w0v33ZUtNLzzMXNwjzKNLF6z0CT9T4tq+sIYonikPKI8cnEvfGFe06ekDxJ Z81RX1Ku5Az44YBLQydaSY1Q1GzGaYcr9vQTKxVk/38ck9DcHxTDRrFROQI2wBLeAxW4 370g== 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=QbjnrCOwfvbyve0jHgDFi86DKkrVu+fyy4HtOfhZMps=; b=Mf1olPVlB5FqogsGo+Yznkc7OfiBs3PH0AFWCg451ynlewIlAzZWgqbUi7poyoxa/2 Mruk+0PFvpbIPaL2jzWI12ieYUnet1hHJFqbp9ibaaO4GvynabeOxGTgzfM3Xx2durwJ Ip9FDuRGKIVrENIUg/CwwMwdC1AduJqcxROvLvqu5O3y+wH755cWFKLOb6s0dg+DHrVh Tv8MPZyz2GM5KHgyJj5LSqAYUNEk0sHXqSe5eDp7t/LiT1lTAwYTHMc8u/8lhwuV9uZ7 BbOVGbxWWFmeVXxRq6jGj/O5FixOO1jFbLxD8uR4iCYD9IMM8ZwC9W3paBRLiFcUtpxT eFIg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=EJetejEO; 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 r14si5401726pgh.39.2019.02.06.03.08.44; Wed, 06 Feb 2019 03:08:44 -0800 (PST) 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=EJetejEO; 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 S1729751AbfBFLIm (ORCPT + 31 others); Wed, 6 Feb 2019 06:08:42 -0500 Received: from lelv0143.ext.ti.com ([198.47.23.248]:33520 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729155AbfBFLIk (ORCPT ); Wed, 6 Feb 2019 06:08:40 -0500 Received: from fllv0035.itg.ti.com ([10.64.41.0]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id x16B8dH7103492; Wed, 6 Feb 2019 05:08:39 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1549451319; bh=QbjnrCOwfvbyve0jHgDFi86DKkrVu+fyy4HtOfhZMps=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=EJetejEOOvfBYgSFiAIAkQ3eQ+YAPxVoAvnppalLyc8NmvMEJfxYSv+e4ts88hGds fqOVXycJh2qHZAKiPexgtyJUm/I9GKR9htLxmxE4nsv9EMOTxp98W/HE4grDhhiV/M NSf5HOou9xdlVORtnR4Owo5DHh6deSmu9NSuPams= Received: from DLEE105.ent.ti.com (dlee105.ent.ti.com [157.170.170.35]) by fllv0035.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x16B8dXf015369 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 6 Feb 2019 05:08:39 -0600 Received: from DLEE102.ent.ti.com (157.170.170.32) by DLEE105.ent.ti.com (157.170.170.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Wed, 6 Feb 2019 05:08:38 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE102.ent.ti.com (157.170.170.32) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Wed, 6 Feb 2019 05:08:38 -0600 Received: from a0393678ub.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id x16B8Waa024645; Wed, 6 Feb 2019 05:08:37 -0600 From: Kishon Vijay Abraham I To: Kishon Vijay Abraham I , Rob Herring CC: Roger Quadros , , Subject: [PATCH v2 2/4] phy: core: Invoke pm_runtime_get_*/pm_runtime_put_* before invoking reset callback Date: Wed, 6 Feb 2019 16:37:51 +0530 Message-ID: <20190206110753.28738-3-kishon@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190206110753.28738-1-kishon@ti.com> References: <20190206110753.28738-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 d4bd85afdc91..fb66f93cd61c 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 Wed Feb 6 11:07:52 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: 157619 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp6277115jaa; Wed, 6 Feb 2019 03:08:46 -0800 (PST) X-Google-Smtp-Source: AHgI3IaW2TUCqPuQhfwfyExuEJJn7eKm4WvhNPRvTzbQ4+Zs94fot1Afr4gEgaZ6QprfQIjOQ4LV X-Received: by 2002:a63:6e8c:: with SMTP id j134mr1532566pgc.230.1549451326741; Wed, 06 Feb 2019 03:08:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549451326; cv=none; d=google.com; s=arc-20160816; b=W/b9KzoTk5e9EBcuE/LGspOMmHR7bY/09Wcu3n7UQ3zUIvOwhlpC8E859wQPDnzo6O 1GMtkvS0ijHxxhivq92NDRrjUGtBvPvtm1BG9I4gxn3iRoYxdwBIjhsrA1M2tNCtGG90 NXSBauRXNEoazfR4BlpRpzXIivfrizlsbohwy6lHDAyokB2ZvskufwNQYRjl75QGPOna QWMV9ciowVCTzv9Z2g1AUlv8QA6KQ+T0G5ZS/meEiP7CmXn5FvAnV259cgApkFJRa9W2 2ov0HbeRSfZRCxq/vFFS+eiAU6k8jy1GdswUAtEL30C4qr4FtBvwXWBIXcazq0AmbW6R 2uYg== 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=GUh9FXpXcAI6DF2YdGQGzCD19/FTKxOn8DpjbDpT3V4=; b=X4WGge/Ly2OKs+Gqb8WshppL0JCLciRp9tp57gUbgOJhvlePcbymvhuW/+5Bf20vno LhUN8e1uy1Jt5JEZpkwRDRJruRK5s83BF/sbscwykVyHQH6fYW/zTUNclixR2vbwKnb6 BRYbM7rQKaqo1fr3fnRV69T4/B9JtEKGAe5o91qT8+5c8KZt+eT3N0l39g0w40YP3np6 gpzPQrRig+VJhxRj+QLhUM++UYizoYd+4YdxhSM91fFQVlCLwfXQPqvAOwO1rg79t5XD vbCYtkU7WSAy+x51r7JDOcqFhikZ1g6o5aEJCiUwjW+57pGTJxr4M0nuzZf10oGaKduh N28w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=GCgvDGfd; 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 r14si5401726pgh.39.2019.02.06.03.08.46; Wed, 06 Feb 2019 03:08:46 -0800 (PST) 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=GCgvDGfd; 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 S1729775AbfBFLIp (ORCPT + 31 others); Wed, 6 Feb 2019 06:08:45 -0500 Received: from lelv0142.ext.ti.com ([198.47.23.249]:40168 "EHLO lelv0142.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729744AbfBFLIm (ORCPT ); Wed, 6 Feb 2019 06:08:42 -0500 Received: from lelv0266.itg.ti.com ([10.180.67.225]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id x16B8ftu021540; Wed, 6 Feb 2019 05:08:41 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1549451321; bh=GUh9FXpXcAI6DF2YdGQGzCD19/FTKxOn8DpjbDpT3V4=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=GCgvDGfds6Adzb43JM33/lekvJqnTpNvApi1Li78owGmr5bMQCbPTf7TYJz04GFd6 I8viApH9yWIjv17HOcCJkmuzX5/N1PmgkFwZkZybC1MNz+7xJc4FKKgOky5UgTOp3R TWQY8YCkRpJ67Y7kdWUG6T2RaPBr6fT3kGE95E+c= Received: from DFLE107.ent.ti.com (dfle107.ent.ti.com [10.64.6.28]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x16B8fN6111797 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 6 Feb 2019 05:08:41 -0600 Received: from DFLE107.ent.ti.com (10.64.6.28) by DFLE107.ent.ti.com (10.64.6.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Wed, 6 Feb 2019 05:08:40 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DFLE107.ent.ti.com (10.64.6.28) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Wed, 6 Feb 2019 05:08:40 -0600 Received: from a0393678ub.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id x16B8Wab024645; Wed, 6 Feb 2019 05:08:39 -0600 From: Kishon Vijay Abraham I To: Kishon Vijay Abraham I , Rob Herring CC: Roger Quadros , , Subject: [PATCH v2 3/4] dt-bindings: phy: ti: Add dt binding documentation for SERDES in AM654x SoC Date: Wed, 6 Feb 2019 16:37:52 +0530 Message-ID: <20190206110753.28738-4-kishon@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190206110753.28738-1-kishon@ti.com> References: <20190206110753.28738-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 --- .../devicetree/bindings/phy/ti-phy.txt | 77 +++++++++++++++++++ include/dt-bindings/phy/phy-am654-serdes.h | 13 ++++ 2 files changed, 90 insertions(+) create mode 100644 include/dt-bindings/phy/phy-am654-serdes.h -- 2.17.1 diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt index 57dfda8a7a1d..fc2fff6b2c37 100644 --- a/Documentation/devicetree/bindings/phy/ti-phy.txt +++ b/Documentation/devicetree/bindings/phy/ti-phy.txt @@ -132,3 +132,80 @@ sata_phy: phy@4a096000 { syscon-pllreset = <&scm_conf 0x3fc>; #phy-cells = <0>; }; + + +TI AM654 SERDES + +Required properties: + - compatible: Should be "ti,phy-am654-serdes" + - reg : Address and length of the register set for the device. + - reg-names: Should be "serdes" which corresponds to the register space + populated in "reg". + - #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 + - 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 + +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>; + status = "disabled"; +}; 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 Wed Feb 6 11:07:53 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: 157620 Delivered-To: patch@linaro.org Received: by 2002:a02:48:0:0:0:0:0 with SMTP id 69csp6277181jaa; Wed, 6 Feb 2019 03:08:50 -0800 (PST) X-Google-Smtp-Source: AHgI3IaEQx/HitYAmzozRS9Dhtv2JKXDggsaF0NXyM7rmKxPjDHvxZREklbLTg1LDJHiuiiTgcAU X-Received: by 2002:a65:6116:: with SMTP id z22mr8964116pgu.265.1549451330643; Wed, 06 Feb 2019 03:08:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549451330; cv=none; d=google.com; s=arc-20160816; b=rP2Cmgi1oY1fZzjAZQKWx5L5BdfNghtzlY09GiWlDrgA3YUwX/XrFS09nrnJEwfI2r qBoFEf7UQBphqujNL/RFtLfqOwfjbG90s3hbR9aaLohBrWYXWl85ZTLuhomi1S6SzTAZ C8fhjPIdNv9rvohtJ08oSr6/UX7zpXIaSQAuXRlCT5LBPEkWcUZlF1AmIV59L4lP9SJV uay7pbfdTrPvsoGzW6Zcs1QsNVnxnGrls33xMyqC7DaDWKfYcfOmMvludI47+Sxu7g0+ 7usTJFWbMSWII7Y5AwS4csQqktmvFJwmeCgfT8/S6sV7x+FMZSF7P9xOYZcQgJDtHixO 0tFw== 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=hHvDHyJhCOPV3g/sNWjNZOCKOUD1ChYdMFhtyB20YKc=; b=VHY0ClSN6Od+oErCtLbKFwdX34/R1CFlGsotaEiQstWP1MztPKsdOdzHXpJ7hLBtNE oJHB3B+30WmF3qpsngHk79MFcdvHR0zRIvqdw/zcNI4LlQ7+giOhUgkXG0Cmttcy3DAp 0lZkWEOghUY2MfbVmK6KTJALtxmwoJuz2F8oyzsE6WP0BD1ek2l7xLGfTNd+jISdfiVd 8K20UXgSkyo7VAv+0cMiV2jB/kir2aqwZLJADOSiSira11hweZBGzudhvQyW37vNUKGp mjlRQsbzldO6AjkV5M9K2l15a/G+sDp5AOpnRfx1SrVP/Csylr01sPBt2jz15Zpnvssm t9tw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b="l3U23o/B"; 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 j21si5925207pfn.277.2019.02.06.03.08.50; Wed, 06 Feb 2019 03:08:50 -0800 (PST) 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="l3U23o/B"; 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 S1729811AbfBFLIs (ORCPT + 31 others); Wed, 6 Feb 2019 06:08:48 -0500 Received: from lelv0142.ext.ti.com ([198.47.23.249]:40172 "EHLO lelv0142.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729771AbfBFLIo (ORCPT ); Wed, 6 Feb 2019 06:08:44 -0500 Received: from lelv0265.itg.ti.com ([10.180.67.224]) by lelv0142.ext.ti.com (8.15.2/8.15.2) with ESMTP id x16B8hCS021546; Wed, 6 Feb 2019 05:08:43 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1549451323; bh=hHvDHyJhCOPV3g/sNWjNZOCKOUD1ChYdMFhtyB20YKc=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=l3U23o/BuL5ZLILWpIDwI/ehNIBsUqjqO/8yon8ZcUB1t2+OzsGmFdfEWpRYHhvqI GQBsS9x8N+7mKuYS/4xLo3VqAeVMiA91E53brh+h772h3APgZcNwFRGuhdC7LvJGJ3 +qIjCUnZAgzTiikgT10wfItwlhKM5lcG+H4iqKXg= Received: from DFLE102.ent.ti.com (dfle102.ent.ti.com [10.64.6.23]) by lelv0265.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x16B8hf6105113 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 6 Feb 2019 05:08:43 -0600 Received: from DFLE104.ent.ti.com (10.64.6.25) by DFLE102.ent.ti.com (10.64.6.23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Wed, 6 Feb 2019 05:08:42 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DFLE104.ent.ti.com (10.64.6.25) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Wed, 6 Feb 2019 05:08:42 -0600 Received: from a0393678ub.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id x16B8Wac024645; Wed, 6 Feb 2019 05:08:41 -0600 From: Kishon Vijay Abraham I To: Kishon Vijay Abraham I , Rob Herring CC: Roger Quadros , , Subject: [PATCH v2 4/4] phy: ti: Add a new SERDES driver for TI's AM654x SoC Date: Wed, 6 Feb 2019 16:37:53 +0530 Message-ID: <20190206110753.28738-5-kishon@ti.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190206110753.28738-1-kishon@ti.com> References: <20190206110753.28738-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 | 11 + drivers/phy/ti/Makefile | 1 + drivers/phy/ti/phy-am654-serdes.c | 539 ++++++++++++++++++++++++++++++ 3 files changed, 551 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 f137e0107764..6357c32de115 100644 --- a/drivers/phy/ti/Kconfig +++ b/drivers/phy/ti/Kconfig @@ -20,6 +20,17 @@ 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 + 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 bea8f25a137a..bff901eb0ecc 100644 --- a/drivers/phy/ti/Makefile +++ b/drivers/phy/ti/Makefile @@ -6,4 +6,5 @@ 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 diff --git a/drivers/phy/ti/phy-am654-serdes.c b/drivers/phy/ti/phy-am654-serdes.c new file mode 100644 index 000000000000..dfbd2d48503d --- /dev/null +++ b/drivers/phy/ti/phy-am654-serdes.c @@ -0,0 +1,539 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * PCIe SERDES driver for AM654x SoC + * + * Copyright (C) 2018 Texas Instruments + * Author: Kishon Vijay Abraham I + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CMU_R07C 0x7c +#define CMU_MASTER_CDN_O BIT(24) + +#define COMLANE_R138 0xb38 +#define CONFIG_VERSION_REG_MASK GENMASK(23, 16) +#define CONFIG_VERSION_REG_SHIFT 16 +#define VERSION 0x70 + +#define COMLANE_R190 0xb90 +#define L1_MASTER_CDN_O BIT(9) + +#define COMLANE_R194 0xb94 +#define CMU_OK_I_0 BIT(19) + +#define SERDES_CTRL 0x1fd0 +#define POR_EN BIT(29) + +#define WIZ_LANEXCTL_STS 0x1fe0 +#define TX0_ENABLE_OVL BIT(31) +#define TX0_ENABLE_MASK GENMASK(30, 29) +#define TX0_ENABLE_SHIFT 29 +#define TX0_DISABLE_STATE 0x0 +#define TX0_SLEEP_STATE 0x1 +#define TX0_SNOOZE_STATE 0x2 +#define TX0_ENABLE_STATE 0x3 +#define RX0_ENABLE_OVL BIT(15) +#define RX0_ENABLE_MASK GENMASK(14, 13) +#define RX0_ENABLE_SHIFT 13 +#define RX0_DISABLE_STATE 0x0 +#define RX0_SLEEP_STATE 0x1 +#define RX0_SNOOZE_STATE 0x2 +#define RX0_ENABLE_STATE 0x3 + +#define WIZ_PLL_CTRL 0x1ff4 +#define PLL_ENABLE_OVL BIT(31) +#define PLL_ENABLE_MASK GENMASK(30, 29) +#define PLL_ENABLE_SHIFT 29 +#define PLL_DISABLE_STATE 0x0 +#define PLL_SLEEP_STATE 0x1 +#define PLL_SNOOZE_STATE 0x2 +#define PLL_ENABLE_STATE 0x3 +#define PLL_OK BIT(28) + +#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, +}; + +struct serdes_am654 { + struct regmap *regmap; + 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) +{ + u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK; + u32 val = PLL_ENABLE_OVL | (PLL_ENABLE_STATE << PLL_ENABLE_SHIFT); + + regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, val); + + return regmap_read_poll_timeout(phy->regmap, WIZ_PLL_CTRL, val, + val & PLL_OK, 1000, PLL_LOCK_TIME); +} + +static void serdes_am654_disable_pll(struct serdes_am654 *phy) +{ + u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK; + + regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, PLL_ENABLE_OVL); +} + +static int serdes_am654_enable_txrx(struct serdes_am654 *phy) +{ + u32 mask; + u32 val; + + /* Enable TX */ + mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK; + val = TX0_ENABLE_OVL | (TX0_ENABLE_STATE << TX0_ENABLE_SHIFT); + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val); + + /* Enable RX */ + mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK; + val = RX0_ENABLE_OVL | (RX0_ENABLE_STATE << RX0_ENABLE_SHIFT); + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val); + + return 0; +} + +static int serdes_am654_disable_txrx(struct serdes_am654 *phy) +{ + u32 mask; + + /* Disable TX */ + mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK; + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, TX0_ENABLE_OVL); + + /* Disable RX */ + mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK; + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, RX0_ENABLE_OVL); + + 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_read_poll_timeout(phy->regmap, COMLANE_R194, val, + val & CMU_OK_I_0, 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); + u32 mask; + u32 val; + + mask = CONFIG_VERSION_REG_MASK; + val = VERSION << CONFIG_VERSION_REG_SHIFT; + regmap_update_bits(phy->regmap, COMLANE_R138, mask, val); + + val = CMU_MASTER_CDN_O; + regmap_update_bits(phy->regmap, CMU_R07C, val, val); + + val = L1_MASTER_CDN_O; + regmap_update_bits(phy->regmap, COMLANE_R190, val, val); + + return 0; +} + +static int serdes_am654_reset(struct phy *x) +{ + struct serdes_am654 *phy = phy_get_drvdata(x); + u32 val; + + val = POR_EN; + regmap_update_bits(phy->regmap, SERDES_CTRL, val, val); + mdelay(1); + regmap_update_bits(phy->regmap, SERDES_CTRL, val, 0); + + 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_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; + struct resource *res; + 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; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "serdes"); + base = devm_ioremap_resource(dev, res); + 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; + + 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_ALIAS("platform:phy-am654"); +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("TI AM654x SERDES driver"); +MODULE_LICENSE("GPL v2");