blob: 642819b1f672e808cac6cc9f4db0f0e0b00965a0 [file] [log] [blame]
Shawn Linaa2bd2e2021-01-15 18:01:21 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Rockchip PCIE3.0 phy driver
4 *
5 * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
6 */
7
8#include <common.h>
9#include <clk.h>
10#include <dm.h>
11#include <generic-phy.h>
12#include <regmap.h>
13#include <reset-uclass.h>
14#include <syscon.h>
15#include <asm/io.h>
16#include <dm/device_compat.h>
17#include <dm/lists.h>
18
Jonas Karlmanb7ca8842023-08-02 19:28:33 +000019/* Register for RK3568 */
20#define GRF_PCIE30PHY_CON1 0x4
21#define GRF_PCIE30PHY_CON6 0x18
22#define GRF_PCIE30PHY_CON9 0x24
23#define GRF_PCIE30PHY_DA_OCM (BIT(15) | BIT(31))
24#define GRF_PCIE30PHY_STATUS0 0x80
25#define GRF_PCIE30PHY_WR_EN (0xf << 16)
26#define SRAM_INIT_DONE(reg) (reg & BIT(14))
27
28#define RK3568_BIFURCATION_LANE_0_1 BIT(0)
Shawn Linaa2bd2e2021-01-15 18:01:21 +080029
30/**
31 * struct rockchip_p3phy_priv - RK DW PCIe PHY state
32 *
33 * @mmio: The base address of PHY internal registers
34 * @phy_grf: The regmap for controlling pipe signal
35 * @p30phy: The reset signal for PHY
Jonas Karlman6153aed2023-08-02 19:04:29 +000036 * @clks: The clocks for PHY
Jonas Karlmanb7ca8842023-08-02 19:28:33 +000037 * @num_lanes: The number of lane to controller mappings
38 * @lanes: The lane to controller mapping
Shawn Linaa2bd2e2021-01-15 18:01:21 +080039 */
40struct rockchip_p3phy_priv {
41 void __iomem *mmio;
42 struct regmap *phy_grf;
43 struct reset_ctl p30phy;
Jonas Karlman6153aed2023-08-02 19:04:29 +000044 struct clk_bulk clks;
Jonas Karlmanb7ca8842023-08-02 19:28:33 +000045 int num_lanes;
46 u32 lanes[4];
Shawn Linaa2bd2e2021-01-15 18:01:21 +080047};
48
Jonas Karlmana10080c2023-08-02 19:04:30 +000049struct rockchip_p3phy_ops {
50 int (*phy_init)(struct phy *phy);
51};
52
53static int rockchip_p3phy_rk3568_init(struct phy *phy)
54{
55 struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
Jonas Karlmanb7ca8842023-08-02 19:28:33 +000056 bool bifurcation = false;
57 int ret;
58 u32 reg;
Jonas Karlmana10080c2023-08-02 19:04:30 +000059
60 /* Deassert PCIe PMA output clamp mode */
Jonas Karlmanb7ca8842023-08-02 19:28:33 +000061 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9, GRF_PCIE30PHY_DA_OCM);
62
63 for (int i = 0; i < priv->num_lanes; i++) {
64 if (priv->lanes[i] > 1)
65 bifurcation = true;
66 }
67
68 /* Set bifurcation if needed, and it doesn't care RC/EP */
69 if (bifurcation) {
70 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
71 GRF_PCIE30PHY_WR_EN | RK3568_BIFURCATION_LANE_0_1);
72 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON1,
73 GRF_PCIE30PHY_DA_OCM);
74 } else {
75 regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON6,
76 GRF_PCIE30PHY_WR_EN & ~RK3568_BIFURCATION_LANE_0_1);
77 }
Jonas Karlmana10080c2023-08-02 19:04:30 +000078
79 reset_deassert(&priv->p30phy);
80 udelay(1);
81
Jonas Karlmanb7ca8842023-08-02 19:28:33 +000082 ret = regmap_read_poll_timeout(priv->phy_grf,
83 GRF_PCIE30PHY_STATUS0,
84 reg, SRAM_INIT_DONE(reg),
85 0, 500);
86 if (ret)
87 dev_err(phy->dev, "lock failed 0x%x\n", reg);
88
89 return ret;
Jonas Karlmana10080c2023-08-02 19:04:30 +000090}
91
92static const struct rockchip_p3phy_ops rk3568_ops = {
93 .phy_init = rockchip_p3phy_rk3568_init,
94};
95
Shawn Linaa2bd2e2021-01-15 18:01:21 +080096static int rochchip_p3phy_init(struct phy *phy)
97{
Jonas Karlmana10080c2023-08-02 19:04:30 +000098 struct rockchip_p3phy_ops *ops =
99 (struct rockchip_p3phy_ops *)dev_get_driver_data(phy->dev);
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800100 struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
101 int ret;
102
Jonas Karlman6153aed2023-08-02 19:04:29 +0000103 ret = clk_enable_bulk(&priv->clks);
104 if (ret)
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800105 return ret;
106
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800107 reset_assert(&priv->p30phy);
108 udelay(1);
109
Jonas Karlmana10080c2023-08-02 19:04:30 +0000110 ret = ops->phy_init(phy);
111 if (ret)
112 clk_disable_bulk(&priv->clks);
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800113
Jonas Karlmana10080c2023-08-02 19:04:30 +0000114 return ret;
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800115}
116
117static int rochchip_p3phy_exit(struct phy *phy)
118{
119 struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
120
Jonas Karlman6153aed2023-08-02 19:04:29 +0000121 clk_disable_bulk(&priv->clks);
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800122 reset_assert(&priv->p30phy);
123
124 return 0;
125}
126
127static int rockchip_p3phy_probe(struct udevice *dev)
128{
129 struct rockchip_p3phy_priv *priv = dev_get_priv(dev);
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800130 int ret;
131
Johan Jonker8d5d8e02023-03-13 01:32:04 +0100132 priv->mmio = dev_read_addr_ptr(dev);
133 if (!priv->mmio)
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800134 return -EINVAL;
135
Jonas Karlman6153aed2023-08-02 19:04:29 +0000136 priv->phy_grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,phy-grf");
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800137 if (IS_ERR(priv->phy_grf)) {
138 dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
139 return PTR_ERR(priv->phy_grf);
140 }
141
Jonas Karlmanb7ca8842023-08-02 19:28:33 +0000142 ret = dev_read_size(dev, "data-lanes");
143 if (ret > 0) {
144 priv->num_lanes = ret / sizeof(u32);
145 if (priv->num_lanes < 2 ||
146 priv->num_lanes > ARRAY_SIZE(priv->lanes)) {
147 dev_err(dev, "unsupported data-lanes property size\n");
148 return -EINVAL;
149 }
150
151 ret = dev_read_u32_array(dev, "data-lanes", priv->lanes,
152 priv->num_lanes);
153 if (ret) {
154 dev_err(dev, "failed to read data-lanes property\n");
155 return ret;
156 }
157 }
158
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800159 ret = reset_get_by_name(dev, "phy", &priv->p30phy);
160 if (ret) {
161 dev_err(dev, "no phy reset control specified\n");
162 return ret;
163 }
164
Jonas Karlman6153aed2023-08-02 19:04:29 +0000165 ret = clk_get_bulk(dev, &priv->clks);
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800166 if (ret) {
Jonas Karlman6153aed2023-08-02 19:04:29 +0000167 dev_err(dev, "failed to get clocks\n");
168 return ret;
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800169 }
170
171 return 0;
172}
173
174static struct phy_ops rochchip_p3phy_ops = {
175 .init = rochchip_p3phy_init,
176 .exit = rochchip_p3phy_exit,
177};
178
179static const struct udevice_id rockchip_p3phy_of_match[] = {
Jonas Karlmana10080c2023-08-02 19:04:30 +0000180 {
181 .compatible = "rockchip,rk3568-pcie3-phy",
182 .data = (ulong)&rk3568_ops,
183 },
Shawn Linaa2bd2e2021-01-15 18:01:21 +0800184 { },
185};
186
187U_BOOT_DRIVER(rockchip_pcie3phy) = {
188 .name = "rockchip_pcie3phy",
189 .id = UCLASS_PHY,
190 .of_match = rockchip_p3phy_of_match,
191 .ops = &rochchip_p3phy_ops,
192 .probe = rockchip_p3phy_probe,
193 .priv_auto = sizeof(struct rockchip_p3phy_priv),
194};