From: Jacky Chou <jacky_chou@aspeedtech.com>
To: Vinod Koul <vkoul@kernel.org>,
Neil Armstrong <neil.armstrong@linaro.org>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>, Joel Stanley <joel@jms.id.au>,
"Andrew Jeffery" <andrew@codeconstruct.com.au>,
Manivannan Sadhasivam <mani@kernel.org>,
Ryan Chen <ryan_chen@aspeedtech.com>,
Billy Tsai <billy_tsai@aspeedtech.com>
Cc: <linux-aspeed@lists.ozlabs.org>, <linux-phy@lists.infradead.org>,
<devicetree@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>,
Jacky Chou <jacky_chou@aspeedtech.com>
Subject: [PATCH 2/3] phy: aspeed: Add ASPEED PCIe PHY driver
Date: Thu, 8 Oct 2026 19:28:20 +0800 [thread overview]
Message-ID: <20261008-aspeed_pcie_phy-v1-2-96764937aef0@aspeedtech.com> (raw)
In-Reply-To: <20261008-aspeed_pcie_phy-v1-0-96764937aef0@aspeedtech.com>
Introduce support for Aspeed PCIe PHY controller available in
AST2600/2700.
Signed-off-by: Jacky Chou <jacky_chou@aspeedtech.com>
---
drivers/phy/aspeed/Kconfig | 12 +-
drivers/phy/aspeed/Makefile | 1 +
drivers/phy/aspeed/phy-aspeed-pcie.c | 237 +++++++++++++++++++++++++++++++++++
3 files changed, 249 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/aspeed/Kconfig b/drivers/phy/aspeed/Kconfig
index 7b5f48db2be8..b5903cf06268 100644
--- a/drivers/phy/aspeed/Kconfig
+++ b/drivers/phy/aspeed/Kconfig
@@ -1,9 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-only
-
#
# PHY drivers for ASPEED
#
+config PHY_ASPEED_PCIE
+ tristate "ASPEED PCIe PHY driver"
+ select GENERIC_PHY
+ depends on (ARCH_ASPEED || COMPILE_TEST)
+ help
+ This option enables support for the ASPEED PCIe PHY driver.
+ The driver provides the necessary interface to control and
+ configure the PCIe PHY hardware found on ASPEED SoCs.
+ It is required for proper operation of PCIe devices on
+ platforms using ASPEED chips.
+
config PHY_ASPEED_USB3
tristate "ASPEED USB3 PHY driver"
select GENERIC_PHY
diff --git a/drivers/phy/aspeed/Makefile b/drivers/phy/aspeed/Makefile
index d96d9d73a009..9d43790fdda8 100644
--- a/drivers/phy/aspeed/Makefile
+++ b/drivers/phy/aspeed/Makefile
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PHY_ASPEED_PCIE) += phy-aspeed-pcie.o
obj-$(CONFIG_PHY_ASPEED_USB3) += phy-aspeed-usb3.o
diff --git a/drivers/phy/aspeed/phy-aspeed-pcie.c b/drivers/phy/aspeed/phy-aspeed-pcie.c
new file mode 100644
index 000000000000..eb300887b644
--- /dev/null
+++ b/drivers/phy/aspeed/phy-aspeed-pcie.c
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2025 Aspeed Technology Inc.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/pcie.h>
+#include <linux/phy/phy.h>
+
+/* AST2600 PCIe Host Controller Registers */
+#define PEHR_GLOBAL 0x30
+#define AST2600_PORT_TYPE_MASK GENMASK(5, 4)
+#define AST2600_PORT_TYPE(x) FIELD_PREP(AST2600_PORT_TYPE_MASK, x)
+#define PEHR_LOCK 0x7c
+#define PCIE_UNLOCK 0xa8
+
+/* AST2700 PEHR */
+#define PEHR_MISC_58 0x58
+#define LOCAL_SCALE_SUP BIT(0)
+#define PEHR_MISC_5C 0x5c
+#define CONFIG_RC_DEVICE BIT(30)
+#define PEHR_MISC_60 0x60
+#define AST2700_PORT_TYPE_MASK GENMASK(7, 4)
+#define PORT_TYPE_ROOT 0x4
+#define PEHR_MISC_70 0x70
+#define POSTED_DATA_CREDITS(x) FIELD_PREP(GENMASK(15, 0), x)
+#define POSTED_HEADER_CREDITS(x) FIELD_PREP(GENMASK(27, 16), x)
+#define PEHR_MISC_78 0x78
+#define COMPLETION_DATA_CREDITS(x) FIELD_PREP(GENMASK(15, 0), x)
+#define COMPLETION_HEADER_CREDITS(x) FIELD_PREP(GENMASK(27, 16), x)
+#define PEHR_MISC_278 0x278
+#define SET_TO_DOWNSTREAM BIT(22)
+#define ASSERT_INTERNAL_RESET BIT(31)
+#define PEHR_MISC_280 0x280
+#define SEL_INTERNAL_RESET BIT(0)
+
+/**
+ * struct aspeed_pcie_phy - PCIe PHY information
+ * @dev: pointer to device structure
+ * @reg: PCIe host register base address
+ * @clk: PCIe reference clock
+ * @phy: pointer to PHY structure
+ * @platform: platform specific information
+ */
+struct aspeed_pcie_phy {
+ struct device *dev;
+ void __iomem *reg;
+ struct clk *clk;
+ struct phy *phy;
+ const struct aspeed_pcie_phy_platform *platform;
+};
+
+/**
+ * struct aspeed_pcie_phy_platform - Platform information
+ * @phy_ops: phy operations
+ */
+struct aspeed_pcie_phy_platform {
+ const struct phy_ops *phy_ops;
+};
+
+static int ast2600_phy_init(struct phy *phy)
+{
+ struct aspeed_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_prepare_enable(pcie_phy->clk);
+ if (ret)
+ return ret;
+
+ writel(PCIE_UNLOCK, pcie_phy->reg + PEHR_LOCK);
+
+ return 0;
+}
+
+static int ast2600_phy_exit(struct phy *phy)
+{
+ struct aspeed_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(pcie_phy->clk);
+
+ return 0;
+}
+
+static int ast2600_phy_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ struct aspeed_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+
+ switch (submode) {
+ case PHY_MODE_PCIE_RC:
+ writel(AST2600_PORT_TYPE(0x3), pcie_phy->reg + PEHR_GLOBAL);
+ break;
+ default:
+ dev_err(&phy->dev, "Unsupported submode %d\n", submode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct phy_ops ast2600_phy_ops = {
+ .init = ast2600_phy_init,
+ .exit = ast2600_phy_exit,
+ .set_mode = ast2600_phy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static int ast2700_phy_init(struct phy *phy)
+{
+ struct aspeed_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+
+ return clk_prepare_enable(pcie_phy->clk);
+}
+
+static int ast2700_phy_exit(struct phy *phy)
+{
+ struct aspeed_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(pcie_phy->clk);
+
+ return 0;
+}
+
+static int ast2700_phy_set_mode(struct phy *phy, enum phy_mode mode,
+ int submode)
+{
+ struct aspeed_pcie_phy *pcie_phy = phy_get_drvdata(phy);
+ u32 cfg_val;
+
+ switch (submode) {
+ case PHY_MODE_PCIE_RC:
+ writel(0, pcie_phy->reg + PEHR_MISC_278);
+ writel(SEL_INTERNAL_RESET, pcie_phy->reg + PEHR_MISC_280);
+ writel(POSTED_DATA_CREDITS(0xc0) | POSTED_HEADER_CREDITS(0xa),
+ pcie_phy->reg + PEHR_MISC_70);
+ writel(COMPLETION_DATA_CREDITS(0x30) | COMPLETION_HEADER_CREDITS(0x8),
+ pcie_phy->reg + PEHR_MISC_78);
+ writel(LOCAL_SCALE_SUP, pcie_phy->reg + PEHR_MISC_58);
+ writel(CONFIG_RC_DEVICE, pcie_phy->reg + PEHR_MISC_5C);
+ cfg_val = readl(pcie_phy->reg + PEHR_MISC_60);
+ FIELD_MODIFY(AST2700_PORT_TYPE_MASK, &cfg_val,
+ PORT_TYPE_ROOT);
+ writel(cfg_val, pcie_phy->reg + PEHR_MISC_60);
+ writel(ASSERT_INTERNAL_RESET | SET_TO_DOWNSTREAM,
+ pcie_phy->reg + PEHR_MISC_278);
+ break;
+ default:
+ dev_err(&phy->dev, "Unsupported submode %d\n", submode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct phy_ops ast2700_phy_ops = {
+ .init = ast2700_phy_init,
+ .exit = ast2700_phy_exit,
+ .set_mode = ast2700_phy_set_mode,
+ .owner = THIS_MODULE,
+};
+
+static const struct aspeed_pcie_phy_platform pcie_phy_ast2600 = {
+ .phy_ops = &ast2600_phy_ops,
+};
+
+static const struct aspeed_pcie_phy_platform pcie_phy_ast2700 = {
+ .phy_ops = &ast2700_phy_ops,
+};
+
+static int aspeed_pcie_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct aspeed_pcie_phy *pcie_phy;
+ const struct aspeed_pcie_phy_platform *md;
+
+ md = of_device_get_match_data(dev);
+ if (!md)
+ return -ENODEV;
+
+ pcie_phy = devm_kzalloc(dev, sizeof(*pcie_phy), GFP_KERNEL);
+ if (!pcie_phy)
+ return -ENOMEM;
+
+ pcie_phy->reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pcie_phy->reg))
+ return PTR_ERR(pcie_phy->reg);
+
+ pcie_phy->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(pcie_phy->clk))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->clk),
+ "failed to get clock\n");
+
+ pcie_phy->dev = dev;
+ pcie_phy->platform = md;
+
+ pcie_phy->phy = devm_phy_create(dev, dev->of_node,
+ pcie_phy->platform->phy_ops);
+ if (IS_ERR(pcie_phy->phy))
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),
+ "failed to create PHY\n");
+
+ phy_set_drvdata(pcie_phy->phy, pcie_phy);
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id aspeed_pcie_phy_of_match_table[] = {
+ {
+ .compatible = "aspeed,ast2600-pcie-phy",
+ .data = &pcie_phy_ast2600,
+ },
+ {
+ .compatible = "aspeed,ast2700-pcie-phy",
+ .data = &pcie_phy_ast2700,
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, aspeed_pcie_phy_of_match_table);
+
+static struct platform_driver aspeed_pcie_driver = {
+ .probe = aspeed_pcie_phy_probe,
+ .driver = {
+ .name = "aspeed-pcie-phy",
+ .of_match_table = aspeed_pcie_phy_of_match_table,
+ },
+};
+
+module_platform_driver(aspeed_pcie_driver);
+
+MODULE_AUTHOR("Jacky Chou <jacky_chou@aspeedtech.com>");
+MODULE_DESCRIPTION("ASPEED PCIe PHY");
+MODULE_LICENSE("GPL");
--
2.34.1
next prev parent reply other threads:[~2026-10-08 11:28 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-08 11:28 [PATCH 0/3] phy: aspeed: Add ASPEED PCIe PHY support Jacky Chou
2026-10-08 11:28 ` [PATCH 1/3] dt-bindings: phy: aspeed: Add ASPEED PCIe PHY Jacky Chou
2026-10-09 10:31 ` Krzysztof Kozlowski
2026-10-08 11:28 ` Jacky Chou [this message]
2026-10-08 11:39 ` [PATCH 2/3] phy: aspeed: Add ASPEED PCIe PHY driver sashiko-bot
2026-10-08 21:40 ` kernel test robot
2026-10-09 6:52 ` kernel test robot
2026-10-09 10:33 ` Krzysztof Kozlowski
2026-10-08 11:28 ` [PATCH 3/3] MAINTAINERS: " Jacky Chou
2026-10-09 10:32 ` [PATCH 0/3] phy: aspeed: Add ASPEED PCIe PHY support Krzysztof Kozlowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261008-aspeed_pcie_phy-v1-2-96764937aef0@aspeedtech.com \
--to=jacky_chou@aspeedtech.com \
--cc=andrew@codeconstruct.com.au \
--cc=billy_tsai@aspeedtech.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=joel@jms.id.au \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-aspeed@lists.ozlabs.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-phy@lists.infradead.org \
--cc=mani@kernel.org \
--cc=neil.armstrong@linaro.org \
--cc=robh@kernel.org \
--cc=ryan_chen@aspeedtech.com \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox