1*4448ddbaSkettenis /* $OpenBSD: rkcomphy.c,v 1.2 2023/04/27 08:56:39 kettenis Exp $ */
2e1414c50Skettenis /*
3e1414c50Skettenis * Copyright (c) 2023 Mark Kettenis <kettenis@openbsd.org>
4e1414c50Skettenis *
5e1414c50Skettenis * Permission to use, copy, modify, and distribute this software for any
6e1414c50Skettenis * purpose with or without fee is hereby granted, provided that the above
7e1414c50Skettenis * copyright notice and this permission notice appear in all copies.
8e1414c50Skettenis *
9e1414c50Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10e1414c50Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11e1414c50Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12e1414c50Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13e1414c50Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14e1414c50Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15e1414c50Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16e1414c50Skettenis */
17e1414c50Skettenis
18e1414c50Skettenis #include <sys/param.h>
19e1414c50Skettenis #include <sys/systm.h>
20e1414c50Skettenis #include <sys/device.h>
21e1414c50Skettenis
22e1414c50Skettenis #include <machine/intr.h>
23e1414c50Skettenis #include <machine/bus.h>
24e1414c50Skettenis #include <machine/fdt.h>
25e1414c50Skettenis
26e1414c50Skettenis #include <dev/ofw/openfirm.h>
27e1414c50Skettenis #include <dev/ofw/ofw_clock.h>
28e1414c50Skettenis #include <dev/ofw/ofw_misc.h>
29e1414c50Skettenis #include <dev/ofw/fdt.h>
30e1414c50Skettenis
31*4448ddbaSkettenis /*
32*4448ddbaSkettenis * WARNING: Most (but not all!) of the register numbers in the Linux
33*4448ddbaSkettenis * driver are off-by-one! This driver uses 0-based register numbers
34*4448ddbaSkettenis * like in the TRM.
35*4448ddbaSkettenis */
36*4448ddbaSkettenis
37e1414c50Skettenis /* Combo PHY registers */
38e1414c50Skettenis #define COMBO_PIPE_PHY_REG(idx) ((idx) * 4)
39e1414c50Skettenis /* REG_005 */
40e1414c50Skettenis #define COMBO_PIPE_PHY_PLL_DIV_MASK (0x3 << 6)
41e1414c50Skettenis #define COMBO_PIPE_PHY_PLL_DIV_2 (0x1 << 6)
42e1414c50Skettenis /* REG_006 */
43e1414c50Skettenis #define COMBO_PIPE_PHY_TX_RTERM_50OHM (0x8 << 4)
44e1414c50Skettenis #define COMBO_PIPE_PHY_RX_RTERM_44OHM (0xf << 4)
45e1414c50Skettenis /* REG_010 */
46e1414c50Skettenis #define COMBO_PIPE_PHY_SU_TRIM_0_7 0xf0
47e1414c50Skettenis /* REG_011 */
48e1414c50Skettenis #define COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE 4
49e1414c50Skettenis /* REG_014 */
50e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_CNT_LO_MASK (0x3 << 6)
51e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_CNT_LO_VALUE (0x1 << 6)
52e1414c50Skettenis #define COMBO_PIPE_PHY_CTLE_EN (1 << 0)
53e1414c50Skettenis /* REG_015 */
54e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_CNT_HI_MASK (0xff << 0)
55e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_CNT_HI_VALUE (0x5f << 0)
56e1414c50Skettenis /* REG_017 */
57e1414c50Skettenis #define COMBO_PIPE_PHY_PLL_LOOP 0x32
58*4448ddbaSkettenis /* REG_027 */
59*4448ddbaSkettenis #define COMBO_PIPE_PHY_RX_TRIM_RK3588 0x4c
60e1414c50Skettenis /* REG_031 */
61e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_DIR_MASK (0x3 << 4)
62e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_DIR_DOWN (0x1 << 4)
63e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_OFFSET_MASK (0x3 << 6)
64e1414c50Skettenis #define COMBO_PIPE_PHY_SSC_OFFSET_500PPM (0x1 << 6)
65e1414c50Skettenis /* REG_032 */
66e1414c50Skettenis #define COMBO_PIPE_PHY_PLL_KVCO_MASK (0x7 << 2)
67e1414c50Skettenis #define COMBO_PIPE_PHY_PLL_KVCO_VALUE (0x2 << 2)
68*4448ddbaSkettenis #define COMBO_PIPE_PHY_PLL_KVCO_VALUE_RK3588 (0x4 << 2)
69e1414c50Skettenis
70e1414c50Skettenis /* GRF registers */
71e1414c50Skettenis #define PIPE_GRF_PIPE_CON0 0x0000
72e1414c50Skettenis
73*4448ddbaSkettenis /* PHP GRF registers (for RK3588) */
74*4448ddbaSkettenis #define PHP_GRF_PCIESEL_CON 0x0100
75*4448ddbaSkettenis
76e1414c50Skettenis /* PHY GRF registers */
77e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_CON(idx) ((idx) * 4)
78e1414c50Skettenis /* CON0 */
79e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_MODE_PCIE 0x003f0000
80e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_MODE_USB 0x003f0004
81e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_MODE_SATA 0x003f0019
82e1414c50Skettenis /* CON1 */
83e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_CLK_24M 0x60000000
84e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_CLK_25M 0x60002000
85e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_CLK_100M 0x60004000
86e1414c50Skettenis /* CON2 */
87e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_TXCOMP_SEL_CTRL 0x80000000
88e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_TXCOMP_SEL_GRF 0x80008000
89e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_TXELEC_SEL_CTRL 0x10000000
90e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_TXELEC_SEL_GRF 0x10001000
91e1414c50Skettenis /* CON3 */
92e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_SEL_PCIE 0x60000000
93e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_SEL_USB 0x60002000
94e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_SEL_SATA 0x60004000
95e1414c50Skettenis /* STATUS1 */
96e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_STATUS1 0x34
97e1414c50Skettenis #define PIPE_PHY_GRF_PIPE_PHYSTATUS (1 << 6)
98e1414c50Skettenis
99e1414c50Skettenis #define HREAD4(sc, reg) \
100e1414c50Skettenis (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
101e1414c50Skettenis #define HWRITE4(sc, reg, val) \
102e1414c50Skettenis bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
103e1414c50Skettenis #define HSET4(sc, reg, bits) \
104e1414c50Skettenis HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
105e1414c50Skettenis #define HCLR4(sc, reg, bits) \
106e1414c50Skettenis HWRITE4((sc), (reg), HREAD4((sc), (reg)) & ~(bits))
107e1414c50Skettenis
108e1414c50Skettenis struct rkcomphy_softc {
109e1414c50Skettenis struct device sc_dev;
110e1414c50Skettenis bus_space_tag_t sc_iot;
111e1414c50Skettenis bus_space_handle_t sc_ioh;
112e1414c50Skettenis
113e1414c50Skettenis struct phy_device sc_pd;
114e1414c50Skettenis };
115e1414c50Skettenis
116e1414c50Skettenis int rkcomphy_match(struct device *, void *, void *);
117e1414c50Skettenis void rkcomphy_attach(struct device *, struct device *, void *);
118e1414c50Skettenis
119e1414c50Skettenis const struct cfattach rkcomphy_ca = {
120e1414c50Skettenis sizeof (struct rkcomphy_softc), rkcomphy_match, rkcomphy_attach
121e1414c50Skettenis };
122e1414c50Skettenis
123e1414c50Skettenis struct cfdriver rkcomphy_cd = {
124e1414c50Skettenis NULL, "rkcomphy", DV_DULL
125e1414c50Skettenis };
126e1414c50Skettenis
127*4448ddbaSkettenis int rkcomphy_rk3568_enable(void *, uint32_t *);
128*4448ddbaSkettenis int rkcomphy_rk3588_enable(void *, uint32_t *);
129e1414c50Skettenis
130e1414c50Skettenis int
rkcomphy_match(struct device * parent,void * match,void * aux)131e1414c50Skettenis rkcomphy_match(struct device *parent, void *match, void *aux)
132e1414c50Skettenis {
133e1414c50Skettenis struct fdt_attach_args *faa = aux;
134*4448ddbaSkettenis int node = faa->fa_node;
135e1414c50Skettenis
136*4448ddbaSkettenis return OF_is_compatible(node, "rockchip,rk3568-naneng-combphy") ||
137*4448ddbaSkettenis OF_is_compatible(node, "rockchip,rk3588-naneng-combphy");
138e1414c50Skettenis }
139e1414c50Skettenis
140e1414c50Skettenis void
rkcomphy_attach(struct device * parent,struct device * self,void * aux)141e1414c50Skettenis rkcomphy_attach(struct device *parent, struct device *self, void *aux)
142e1414c50Skettenis {
143e1414c50Skettenis struct rkcomphy_softc *sc = (struct rkcomphy_softc *)self;
144e1414c50Skettenis struct fdt_attach_args *faa = aux;
145e1414c50Skettenis
146e1414c50Skettenis if (faa->fa_nreg < 1) {
147e1414c50Skettenis printf(": no registers\n");
148e1414c50Skettenis return;
149e1414c50Skettenis }
150e1414c50Skettenis
151e1414c50Skettenis sc->sc_iot = faa->fa_iot;
152e1414c50Skettenis if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
153e1414c50Skettenis faa->fa_reg[0].size, 0, &sc->sc_ioh)) {
154e1414c50Skettenis printf(": can't map registers\n");
155e1414c50Skettenis return;
156e1414c50Skettenis }
157e1414c50Skettenis
158e1414c50Skettenis reset_assert_all(faa->fa_node);
159e1414c50Skettenis
160e1414c50Skettenis printf("\n");
161e1414c50Skettenis
162e1414c50Skettenis sc->sc_pd.pd_node = faa->fa_node;
163e1414c50Skettenis sc->sc_pd.pd_cookie = sc;
164*4448ddbaSkettenis if (OF_is_compatible(faa->fa_node, "rockchip,rk3568-naneng-combphy"))
165*4448ddbaSkettenis sc->sc_pd.pd_enable = rkcomphy_rk3568_enable;
166*4448ddbaSkettenis else
167*4448ddbaSkettenis sc->sc_pd.pd_enable = rkcomphy_rk3588_enable;
168e1414c50Skettenis phy_register(&sc->sc_pd);
169e1414c50Skettenis }
170e1414c50Skettenis
171e1414c50Skettenis void
rkcomphy_rk3568_pll_tune(struct rkcomphy_softc * sc)172*4448ddbaSkettenis rkcomphy_rk3568_pll_tune(struct rkcomphy_softc *sc)
173e1414c50Skettenis {
174e1414c50Skettenis uint32_t reg;
175e1414c50Skettenis
176e1414c50Skettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(32));
177e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_PLL_KVCO_MASK;
178e1414c50Skettenis reg |= COMBO_PIPE_PHY_PLL_KVCO_VALUE;
179e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(32), reg);
180e1414c50Skettenis
181e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(11), COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE);
182e1414c50Skettenis
183e1414c50Skettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(5));
184e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_PLL_DIV_MASK;
185e1414c50Skettenis reg |= COMBO_PIPE_PHY_PLL_DIV_2;
186e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(5), reg);
187e1414c50Skettenis
188e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(17), COMBO_PIPE_PHY_PLL_LOOP);
189e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(10), COMBO_PIPE_PHY_SU_TRIM_0_7);
190e1414c50Skettenis }
191e1414c50Skettenis
192e1414c50Skettenis int
rkcomphy_rk3568_enable(void * cookie,uint32_t * cells)193*4448ddbaSkettenis rkcomphy_rk3568_enable(void *cookie, uint32_t *cells)
194e1414c50Skettenis {
195e1414c50Skettenis struct rkcomphy_softc *sc = cookie;
196e1414c50Skettenis struct regmap *rm, *phy_rm;
197e1414c50Skettenis int node = sc->sc_pd.pd_node;
198e1414c50Skettenis uint32_t type = cells[0];
199e1414c50Skettenis uint32_t freq, grf, phy_grf, reg;
200e1414c50Skettenis int stat, timo;
201e1414c50Skettenis
202e1414c50Skettenis /* We only support PCIe, SATA and USB 3 for now. */
203e1414c50Skettenis switch (type) {
204e1414c50Skettenis case PHY_TYPE_PCIE:
205e1414c50Skettenis case PHY_TYPE_SATA:
206e1414c50Skettenis case PHY_TYPE_USB3:
207e1414c50Skettenis break;
208e1414c50Skettenis default:
209e1414c50Skettenis return EINVAL;
210e1414c50Skettenis }
211e1414c50Skettenis
212e1414c50Skettenis grf = OF_getpropint(node, "rockchip,pipe-grf", 0);
213e1414c50Skettenis rm = regmap_byphandle(grf);
214e1414c50Skettenis if (rm == NULL)
215e1414c50Skettenis return ENXIO;
216e1414c50Skettenis
217e1414c50Skettenis phy_grf = OF_getpropint(node, "rockchip,pipe-phy-grf", 0);
218e1414c50Skettenis phy_rm = regmap_byphandle(phy_grf);
219e1414c50Skettenis if (phy_rm == NULL)
220e1414c50Skettenis return ENXIO;
221e1414c50Skettenis
222e1414c50Skettenis clock_set_assigned(node);
223e1414c50Skettenis clock_enable_all(node);
224e1414c50Skettenis
225e1414c50Skettenis if (type == PHY_TYPE_PCIE || type == PHY_TYPE_USB3) {
226e1414c50Skettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(31));
227e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_SSC_OFFSET_MASK;
228e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_SSC_DIR_MASK;
229e1414c50Skettenis reg |= COMBO_PIPE_PHY_SSC_DIR_DOWN;
230e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(31), reg);
231e1414c50Skettenis }
232e1414c50Skettenis
233e1414c50Skettenis if (type == PHY_TYPE_SATA || type == PHY_TYPE_USB3) {
234e1414c50Skettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(14));
235e1414c50Skettenis reg |= COMBO_PIPE_PHY_CTLE_EN;
236e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(14), reg);
237e1414c50Skettenis }
238e1414c50Skettenis
239e1414c50Skettenis switch (type) {
240e1414c50Skettenis case PHY_TYPE_PCIE:
241e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff1000);
242e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0000);
243e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff0101);
244e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff0200);
245e1414c50Skettenis break;
246e1414c50Skettenis case PHY_TYPE_SATA:
247e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(6),
248e1414c50Skettenis COMBO_PIPE_PHY_TX_RTERM_50OHM |
249e1414c50Skettenis COMBO_PIPE_PHY_RX_RTERM_44OHM);
250e1414c50Skettenis
251e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff0119);
252e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0040);
253e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff80c3);
254e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff4407);
255e1414c50Skettenis regmap_write_4(rm, PIPE_GRF_PIPE_CON0, 0xffff2220);
256e1414c50Skettenis break;
257e1414c50Skettenis case PHY_TYPE_USB3:
258*4448ddbaSkettenis rkcomphy_rk3568_pll_tune(sc);
259e1414c50Skettenis
260e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0),
261e1414c50Skettenis PIPE_PHY_GRF_PIPE_MODE_USB);
262e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2),
263e1414c50Skettenis PIPE_PHY_GRF_PIPE_TXCOMP_SEL_CTRL);
264e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2),
265e1414c50Skettenis PIPE_PHY_GRF_PIPE_TXELEC_SEL_CTRL);
266e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3),
267e1414c50Skettenis PIPE_PHY_GRF_PIPE_SEL_USB);
268e1414c50Skettenis break;
269e1414c50Skettenis }
270e1414c50Skettenis
271e1414c50Skettenis freq = clock_get_frequency(node, "ref");
272e1414c50Skettenis switch (freq) {
273e1414c50Skettenis case 24000000:
274e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
275e1414c50Skettenis PIPE_PHY_GRF_PIPE_CLK_24M);
276e1414c50Skettenis if (type == PHY_TYPE_SATA || type == PHY_TYPE_USB3) {
277e1414c50Skettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(14));
278e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_SSC_CNT_LO_MASK;
279e1414c50Skettenis reg |= COMBO_PIPE_PHY_SSC_CNT_LO_VALUE;
280e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(14), reg);
281e1414c50Skettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(15));
282e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_SSC_CNT_HI_MASK;
283e1414c50Skettenis reg |= COMBO_PIPE_PHY_SSC_CNT_HI_VALUE;
284e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(15), reg);
285e1414c50Skettenis }
286e1414c50Skettenis break;
287e1414c50Skettenis case 25000000:
288e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
289e1414c50Skettenis PIPE_PHY_GRF_PIPE_CLK_25M);
290e1414c50Skettenis break;
291e1414c50Skettenis case 100000000:
292e1414c50Skettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
293e1414c50Skettenis PIPE_PHY_GRF_PIPE_CLK_100M);
294e1414c50Skettenis switch (type) {
295e1414c50Skettenis case PHY_TYPE_PCIE:
296*4448ddbaSkettenis rkcomphy_rk3568_pll_tune(sc);
297e1414c50Skettenis break;
298e1414c50Skettenis case PHY_TYPE_SATA:
299e1414c50Skettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(31));
300e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_SSC_OFFSET_MASK;
301e1414c50Skettenis reg |= COMBO_PIPE_PHY_SSC_OFFSET_500PPM;
302e1414c50Skettenis reg &= ~COMBO_PIPE_PHY_SSC_DIR_MASK;
303e1414c50Skettenis reg |= COMBO_PIPE_PHY_SSC_DIR_DOWN;
304e1414c50Skettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(31), reg);
305e1414c50Skettenis break;
306e1414c50Skettenis }
307e1414c50Skettenis break;
308e1414c50Skettenis }
309e1414c50Skettenis
310e1414c50Skettenis reset_deassert_all(node);
311e1414c50Skettenis
312e1414c50Skettenis if (type == PHY_TYPE_USB3) {
313e1414c50Skettenis for (timo = 100; timo > 0; timo--) {
314e1414c50Skettenis stat = regmap_read_4(phy_rm,
315e1414c50Skettenis PIPE_PHY_GRF_PIPE_STATUS1);
316e1414c50Skettenis if ((stat & PIPE_PHY_GRF_PIPE_PHYSTATUS) == 0)
317e1414c50Skettenis break;
318e1414c50Skettenis delay(10);
319e1414c50Skettenis }
320e1414c50Skettenis if (timo == 0) {
321e1414c50Skettenis printf("%s: timeout\n", sc->sc_dev.dv_xname);
322e1414c50Skettenis return ETIMEDOUT;
323e1414c50Skettenis }
324e1414c50Skettenis }
325e1414c50Skettenis
326e1414c50Skettenis return 0;
327e1414c50Skettenis }
328*4448ddbaSkettenis
329*4448ddbaSkettenis void
rkcomphy_rk3588_pll_tune(struct rkcomphy_softc * sc)330*4448ddbaSkettenis rkcomphy_rk3588_pll_tune(struct rkcomphy_softc *sc)
331*4448ddbaSkettenis {
332*4448ddbaSkettenis uint32_t reg;
333*4448ddbaSkettenis
334*4448ddbaSkettenis reg = HREAD4(sc, COMBO_PIPE_PHY_REG(32));
335*4448ddbaSkettenis reg &= ~COMBO_PIPE_PHY_PLL_KVCO_MASK;
336*4448ddbaSkettenis reg |= COMBO_PIPE_PHY_PLL_KVCO_VALUE_RK3588;
337*4448ddbaSkettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(32), reg);
338*4448ddbaSkettenis
339*4448ddbaSkettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(11), COMBO_PIPE_PHY_PLL_LPF_ADJ_VALUE);
340*4448ddbaSkettenis
341*4448ddbaSkettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(27), COMBO_PIPE_PHY_RX_TRIM_RK3588);
342*4448ddbaSkettenis HWRITE4(sc, COMBO_PIPE_PHY_REG(10), COMBO_PIPE_PHY_SU_TRIM_0_7);
343*4448ddbaSkettenis }
344*4448ddbaSkettenis
345*4448ddbaSkettenis int
rkcomphy_rk3588_enable(void * cookie,uint32_t * cells)346*4448ddbaSkettenis rkcomphy_rk3588_enable(void *cookie, uint32_t *cells)
347*4448ddbaSkettenis {
348*4448ddbaSkettenis struct rkcomphy_softc *sc = cookie;
349*4448ddbaSkettenis struct regmap *rm, *phy_rm;
350*4448ddbaSkettenis int node = sc->sc_pd.pd_node;
351*4448ddbaSkettenis uint32_t type = cells[0];
352*4448ddbaSkettenis uint32_t freq, grf, phy_grf;
353*4448ddbaSkettenis
354*4448ddbaSkettenis /* We only support PCIe for now. */
355*4448ddbaSkettenis switch (type) {
356*4448ddbaSkettenis case PHY_TYPE_PCIE:
357*4448ddbaSkettenis break;
358*4448ddbaSkettenis default:
359*4448ddbaSkettenis return EINVAL;
360*4448ddbaSkettenis }
361*4448ddbaSkettenis
362*4448ddbaSkettenis grf = OF_getpropint(node, "rockchip,pipe-grf", 0);
363*4448ddbaSkettenis rm = regmap_byphandle(grf);
364*4448ddbaSkettenis if (rm == NULL)
365*4448ddbaSkettenis return ENXIO;
366*4448ddbaSkettenis
367*4448ddbaSkettenis phy_grf = OF_getpropint(node, "rockchip,pipe-phy-grf", 0);
368*4448ddbaSkettenis phy_rm = regmap_byphandle(phy_grf);
369*4448ddbaSkettenis if (phy_rm == NULL)
370*4448ddbaSkettenis return ENXIO;
371*4448ddbaSkettenis
372*4448ddbaSkettenis clock_set_assigned(node);
373*4448ddbaSkettenis clock_enable_all(node);
374*4448ddbaSkettenis
375*4448ddbaSkettenis switch (type) {
376*4448ddbaSkettenis case PHY_TYPE_PCIE:
377*4448ddbaSkettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(0), 0xffff1000);
378*4448ddbaSkettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1), 0xffff0000);
379*4448ddbaSkettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(2), 0xffff0101);
380*4448ddbaSkettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(3), 0xffff0200);
381*4448ddbaSkettenis regmap_write_4(rm, PHP_GRF_PCIESEL_CON, 0x00010000);
382*4448ddbaSkettenis regmap_write_4(rm, PHP_GRF_PCIESEL_CON, 0x00020000);
383*4448ddbaSkettenis break;
384*4448ddbaSkettenis }
385*4448ddbaSkettenis
386*4448ddbaSkettenis freq = clock_get_frequency(node, "ref");
387*4448ddbaSkettenis switch (freq) {
388*4448ddbaSkettenis case 25000000:
389*4448ddbaSkettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
390*4448ddbaSkettenis PIPE_PHY_GRF_PIPE_CLK_25M);
391*4448ddbaSkettenis break;
392*4448ddbaSkettenis case 100000000:
393*4448ddbaSkettenis regmap_write_4(phy_rm, PIPE_PHY_GRF_PIPE_CON(1),
394*4448ddbaSkettenis PIPE_PHY_GRF_PIPE_CLK_100M);
395*4448ddbaSkettenis switch (type) {
396*4448ddbaSkettenis case PHY_TYPE_PCIE:
397*4448ddbaSkettenis rkcomphy_rk3588_pll_tune(sc);
398*4448ddbaSkettenis break;
399*4448ddbaSkettenis }
400*4448ddbaSkettenis }
401*4448ddbaSkettenis
402*4448ddbaSkettenis reset_deassert_all(node);
403*4448ddbaSkettenis
404*4448ddbaSkettenis return 0;
405*4448ddbaSkettenis }
406