1 // SPDX-License-Identifier: GPL-2.0+
3 * Mediatek MT7621 PCI PHY Driver
4 * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com>
7 #include <dt-bindings/phy/phy.h>
8 #include <linux/bitops.h>
9 #include <linux/module.h>
10 #include <linux/of_address.h>
11 #include <linux/of_device.h>
12 #include <linux/phy/phy.h>
13 #include <linux/platform_device.h>
14 #include <linux/regmap.h>
15 #include <linux/sys_soc.h>
17 #include <ralink_regs.h>
19 #define RG_PE1_PIPE_REG 0x02c
20 #define RG_PE1_PIPE_RST BIT(12)
21 #define RG_PE1_PIPE_CMD_FRC BIT(4)
23 #define RG_P0_TO_P1_WIDTH 0x100
24 #define RG_PE1_H_LCDDS_REG 0x49c
25 #define RG_PE1_H_LCDDS_PCW GENMASK(30, 0)
26 #define RG_PE1_H_LCDDS_PCW_VAL(x) ((0x7fffffff & (x)) << 0)
28 #define RG_PE1_FRC_H_XTAL_REG 0x400
29 #define RG_PE1_FRC_H_XTAL_TYPE BIT(8)
30 #define RG_PE1_H_XTAL_TYPE GENMASK(10, 9)
31 #define RG_PE1_H_XTAL_TYPE_VAL(x) ((0x3 & (x)) << 9)
33 #define RG_PE1_FRC_PHY_REG 0x000
34 #define RG_PE1_FRC_PHY_EN BIT(4)
35 #define RG_PE1_PHY_EN BIT(5)
37 #define RG_PE1_H_PLL_REG 0x490
38 #define RG_PE1_H_PLL_BC GENMASK(23, 22)
39 #define RG_PE1_H_PLL_BC_VAL(x) ((0x3 & (x)) << 22)
40 #define RG_PE1_H_PLL_BP GENMASK(21, 18)
41 #define RG_PE1_H_PLL_BP_VAL(x) ((0xf & (x)) << 18)
42 #define RG_PE1_H_PLL_IR GENMASK(15, 12)
43 #define RG_PE1_H_PLL_IR_VAL(x) ((0xf & (x)) << 12)
44 #define RG_PE1_H_PLL_IC GENMASK(11, 8)
45 #define RG_PE1_H_PLL_IC_VAL(x) ((0xf & (x)) << 8)
46 #define RG_PE1_H_PLL_PREDIV GENMASK(7, 6)
47 #define RG_PE1_H_PLL_PREDIV_VAL(x) ((0x3 & (x)) << 6)
48 #define RG_PE1_PLL_DIVEN GENMASK(3, 1)
49 #define RG_PE1_PLL_DIVEN_VAL(x) ((0x7 & (x)) << 1)
51 #define RG_PE1_H_PLL_FBKSEL_REG 0x4bc
52 #define RG_PE1_H_PLL_FBKSEL GENMASK(5, 4)
53 #define RG_PE1_H_PLL_FBKSEL_VAL(x) ((0x3 & (x)) << 4)
55 #define RG_PE1_H_LCDDS_SSC_PRD_REG 0x4a4
56 #define RG_PE1_H_LCDDS_SSC_PRD GENMASK(15, 0)
57 #define RG_PE1_H_LCDDS_SSC_PRD_VAL(x) ((0xffff & (x)) << 0)
59 #define RG_PE1_H_LCDDS_SSC_DELTA_REG 0x4a8
60 #define RG_PE1_H_LCDDS_SSC_DELTA GENMASK(11, 0)
61 #define RG_PE1_H_LCDDS_SSC_DELTA_VAL(x) ((0xfff & (x)) << 0)
62 #define RG_PE1_H_LCDDS_SSC_DELTA1 GENMASK(27, 16)
63 #define RG_PE1_H_LCDDS_SSC_DELTA1_VAL(x) ((0xff & (x)) << 16)
65 #define RG_PE1_LCDDS_CLK_PH_INV_REG 0x4a0
66 #define RG_PE1_LCDDS_CLK_PH_INV BIT(5)
68 #define RG_PE1_H_PLL_BR_REG 0x4ac
69 #define RG_PE1_H_PLL_BR GENMASK(18, 16)
70 #define RG_PE1_H_PLL_BR_VAL(x) ((0x7 & (x)) << 16)
72 #define RG_PE1_MSTCKDIV_REG 0x414
73 #define RG_PE1_MSTCKDIV GENMASK(7, 6)
74 #define RG_PE1_MSTCKDIV_VAL(x) ((0x3 & (x)) << 6)
76 #define RG_PE1_FRC_MSTCKDIV BIT(5)
81 * struct mt7621_pci_phy_instance - Mt7621 Pcie PHY device
82 * @phy: pointer to the kernel PHY device
83 * @port_base: base register
84 * @index: internal ID to identify the Mt7621 PCIe PHY
86 struct mt7621_pci_phy_instance
{
88 void __iomem
*port_base
;
93 * struct mt7621_pci_phy - Mt7621 Pcie PHY core
94 * @dev: pointer to device
95 * @regmap: kernel regmap pointer
96 * @phys: pointer to Mt7621 PHY device
97 * @nphys: number of PHY devices for this core
98 * @bypass_pipe_rst: mark if 'mt7621_bypass_pipe_rst'
99 * needs to be executed. Depends on chip revision.
101 struct mt7621_pci_phy
{
103 struct regmap
*regmap
;
104 struct mt7621_pci_phy_instance
**phys
;
106 bool bypass_pipe_rst
;
109 static inline u32
phy_read(struct mt7621_pci_phy
*phy
, u32 reg
)
113 regmap_read(phy
->regmap
, reg
, &val
);
118 static inline void phy_write(struct mt7621_pci_phy
*phy
, u32 val
, u32 reg
)
120 regmap_write(phy
->regmap
, reg
, val
);
123 static void mt7621_bypass_pipe_rst(struct mt7621_pci_phy
*phy
,
124 struct mt7621_pci_phy_instance
*instance
)
126 u32 offset
= (instance
->index
!= 1) ?
127 RG_PE1_PIPE_REG
: RG_PE1_PIPE_REG
+ RG_P0_TO_P1_WIDTH
;
130 reg
= phy_read(phy
, offset
);
131 reg
&= ~(RG_PE1_PIPE_RST
| RG_PE1_PIPE_CMD_FRC
);
132 reg
|= (RG_PE1_PIPE_RST
| RG_PE1_PIPE_CMD_FRC
);
133 phy_write(phy
, reg
, offset
);
136 static void mt7621_set_phy_for_ssc(struct mt7621_pci_phy
*phy
,
137 struct mt7621_pci_phy_instance
*instance
)
139 struct device
*dev
= phy
->dev
;
140 u32 reg
= rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG0
);
144 reg
= (reg
>> 6) & 0x7;
145 /* Set PCIe Port PHY to disable SSC */
146 /* Debug Xtal Type */
147 val
= phy_read(phy
, RG_PE1_FRC_H_XTAL_REG
);
148 val
&= ~(RG_PE1_FRC_H_XTAL_TYPE
| RG_PE1_H_XTAL_TYPE
);
149 val
|= RG_PE1_FRC_H_XTAL_TYPE
;
150 val
|= RG_PE1_H_XTAL_TYPE_VAL(0x00);
151 phy_write(phy
, val
, RG_PE1_FRC_H_XTAL_REG
);
154 offset
= (instance
->index
!= 1) ?
155 RG_PE1_FRC_PHY_REG
: RG_PE1_FRC_PHY_REG
+ RG_P0_TO_P1_WIDTH
;
156 val
= phy_read(phy
, offset
);
157 val
&= ~(RG_PE1_FRC_PHY_EN
| RG_PE1_PHY_EN
);
158 val
|= RG_PE1_FRC_PHY_EN
;
159 phy_write(phy
, val
, offset
);
161 /* Set Pre-divider ratio (for host mode) */
162 val
= phy_read(phy
, RG_PE1_H_PLL_REG
);
163 val
&= ~(RG_PE1_H_PLL_PREDIV
);
165 if (reg
<= 5 && reg
>= 3) { /* 40MHz Xtal */
166 val
|= RG_PE1_H_PLL_PREDIV_VAL(0x01);
167 phy_write(phy
, val
, RG_PE1_H_PLL_REG
);
168 dev_info(dev
, "Xtal is 40MHz\n");
169 } else { /* 25MHz | 20MHz Xtal */
170 val
|= RG_PE1_H_PLL_PREDIV_VAL(0x00);
171 phy_write(phy
, val
, RG_PE1_H_PLL_REG
);
173 dev_info(dev
, "Xtal is 25MHz\n");
175 /* Select feedback clock */
176 val
= phy_read(phy
, RG_PE1_H_PLL_FBKSEL_REG
);
177 val
&= ~(RG_PE1_H_PLL_FBKSEL
);
178 val
|= RG_PE1_H_PLL_FBKSEL_VAL(0x01);
179 phy_write(phy
, val
, RG_PE1_H_PLL_FBKSEL_REG
);
181 /* DDS NCPO PCW (for host mode) */
182 val
= phy_read(phy
, RG_PE1_H_LCDDS_SSC_PRD_REG
);
183 val
&= ~(RG_PE1_H_LCDDS_SSC_PRD
);
184 val
|= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18000000);
185 phy_write(phy
, val
, RG_PE1_H_LCDDS_SSC_PRD_REG
);
187 /* DDS SSC dither period control */
188 val
= phy_read(phy
, RG_PE1_H_LCDDS_SSC_PRD_REG
);
189 val
&= ~(RG_PE1_H_LCDDS_SSC_PRD
);
190 val
|= RG_PE1_H_LCDDS_SSC_PRD_VAL(0x18d);
191 phy_write(phy
, val
, RG_PE1_H_LCDDS_SSC_PRD_REG
);
193 /* DDS SSC dither amplitude control */
194 val
= phy_read(phy
, RG_PE1_H_LCDDS_SSC_DELTA_REG
);
195 val
&= ~(RG_PE1_H_LCDDS_SSC_DELTA
|
196 RG_PE1_H_LCDDS_SSC_DELTA1
);
197 val
|= RG_PE1_H_LCDDS_SSC_DELTA_VAL(0x4a);
198 val
|= RG_PE1_H_LCDDS_SSC_DELTA1_VAL(0x4a);
199 phy_write(phy
, val
, RG_PE1_H_LCDDS_SSC_DELTA_REG
);
201 dev_info(dev
, "Xtal is 20MHz\n");
205 /* DDS clock inversion */
206 val
= phy_read(phy
, RG_PE1_LCDDS_CLK_PH_INV_REG
);
207 val
&= ~(RG_PE1_LCDDS_CLK_PH_INV
);
208 val
|= RG_PE1_LCDDS_CLK_PH_INV
;
209 phy_write(phy
, val
, RG_PE1_LCDDS_CLK_PH_INV_REG
);
212 val
= phy_read(phy
, RG_PE1_H_PLL_REG
);
213 val
&= ~(RG_PE1_H_PLL_BC
| RG_PE1_H_PLL_BP
| RG_PE1_H_PLL_IR
|
214 RG_PE1_H_PLL_IC
| RG_PE1_PLL_DIVEN
);
215 val
|= RG_PE1_H_PLL_BC_VAL(0x02);
216 val
|= RG_PE1_H_PLL_BP_VAL(0x06);
217 val
|= RG_PE1_H_PLL_IR_VAL(0x02);
218 val
|= RG_PE1_H_PLL_IC_VAL(0x01);
219 val
|= RG_PE1_PLL_DIVEN_VAL(0x02);
220 phy_write(phy
, val
, RG_PE1_H_PLL_REG
);
222 val
= phy_read(phy
, RG_PE1_H_PLL_BR_REG
);
223 val
&= ~(RG_PE1_H_PLL_BR
);
224 val
|= RG_PE1_H_PLL_BR_VAL(0x00);
225 phy_write(phy
, val
, RG_PE1_H_PLL_BR_REG
);
227 if (reg
<= 5 && reg
>= 3) { /* 40MHz Xtal */
228 /* set force mode enable of da_pe1_mstckdiv */
229 val
= phy_read(phy
, RG_PE1_MSTCKDIV_REG
);
230 val
&= ~(RG_PE1_MSTCKDIV
| RG_PE1_FRC_MSTCKDIV
);
231 val
|= (RG_PE1_MSTCKDIV_VAL(0x01) | RG_PE1_FRC_MSTCKDIV
);
232 phy_write(phy
, val
, RG_PE1_MSTCKDIV_REG
);
236 static int mt7621_pci_phy_init(struct phy
*phy
)
238 struct mt7621_pci_phy_instance
*instance
= phy_get_drvdata(phy
);
239 struct mt7621_pci_phy
*mphy
= dev_get_drvdata(phy
->dev
.parent
);
241 if (mphy
->bypass_pipe_rst
)
242 mt7621_bypass_pipe_rst(mphy
, instance
);
244 mt7621_set_phy_for_ssc(mphy
, instance
);
249 static int mt7621_pci_phy_power_on(struct phy
*phy
)
251 struct mt7621_pci_phy_instance
*instance
= phy_get_drvdata(phy
);
252 struct mt7621_pci_phy
*mphy
= dev_get_drvdata(phy
->dev
.parent
);
253 u32 offset
= (instance
->index
!= 1) ?
254 RG_PE1_FRC_PHY_REG
: RG_PE1_FRC_PHY_REG
+ RG_P0_TO_P1_WIDTH
;
257 /* Enable PHY and disable force mode */
258 val
= phy_read(mphy
, offset
);
259 val
&= ~(RG_PE1_FRC_PHY_EN
| RG_PE1_PHY_EN
);
260 val
|= (RG_PE1_FRC_PHY_EN
| RG_PE1_PHY_EN
);
261 phy_write(mphy
, val
, offset
);
266 static int mt7621_pci_phy_power_off(struct phy
*phy
)
268 struct mt7621_pci_phy_instance
*instance
= phy_get_drvdata(phy
);
269 struct mt7621_pci_phy
*mphy
= dev_get_drvdata(phy
->dev
.parent
);
270 u32 offset
= (instance
->index
!= 1) ?
271 RG_PE1_FRC_PHY_REG
: RG_PE1_FRC_PHY_REG
+ RG_P0_TO_P1_WIDTH
;
275 val
= phy_read(mphy
, offset
);
276 val
&= ~(RG_PE1_FRC_PHY_EN
| RG_PE1_PHY_EN
);
277 val
|= RG_PE1_FRC_PHY_EN
;
278 phy_write(mphy
, val
, offset
);
283 static int mt7621_pci_phy_exit(struct phy
*phy
)
288 static const struct phy_ops mt7621_pci_phy_ops
= {
289 .init
= mt7621_pci_phy_init
,
290 .exit
= mt7621_pci_phy_exit
,
291 .power_on
= mt7621_pci_phy_power_on
,
292 .power_off
= mt7621_pci_phy_power_off
,
293 .owner
= THIS_MODULE
,
296 static struct phy
*mt7621_pcie_phy_of_xlate(struct device
*dev
,
297 struct of_phandle_args
*args
)
299 struct mt7621_pci_phy
*mt7621_phy
= dev_get_drvdata(dev
);
301 if (args
->args_count
== 0)
302 return mt7621_phy
->phys
[0]->phy
;
304 if (WARN_ON(args
->args
[0] >= MAX_PHYS
))
305 return ERR_PTR(-ENODEV
);
307 return mt7621_phy
->phys
[args
->args
[0]]->phy
;
310 static const struct soc_device_attribute mt7621_pci_quirks_match
[] = {
311 { .soc_id
= "mt7621", .revision
= "E2" }
314 static const struct regmap_config mt7621_pci_phy_regmap_config
= {
318 .max_register
= 0x700,
321 static int mt7621_pci_phy_probe(struct platform_device
*pdev
)
323 struct device
*dev
= &pdev
->dev
;
324 const struct soc_device_attribute
*attr
;
325 struct phy_provider
*provider
;
326 struct mt7621_pci_phy
*phy
;
327 struct resource
*res
;
329 void __iomem
*port_base
;
331 phy
= devm_kzalloc(dev
, sizeof(*phy
), GFP_KERNEL
);
335 phy
->nphys
= MAX_PHYS
;
336 phy
->phys
= devm_kcalloc(dev
, phy
->nphys
,
337 sizeof(*phy
->phys
), GFP_KERNEL
);
341 attr
= soc_device_match(mt7621_pci_quirks_match
);
343 phy
->bypass_pipe_rst
= true;
346 platform_set_drvdata(pdev
, phy
);
348 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
350 dev_err(dev
, "failed to get address resource\n");
354 port_base
= devm_ioremap_resource(dev
, res
);
355 if (IS_ERR(port_base
)) {
356 dev_err(dev
, "failed to remap phy regs\n");
357 return PTR_ERR(port_base
);
360 phy
->regmap
= devm_regmap_init_mmio(phy
->dev
, port_base
,
361 &mt7621_pci_phy_regmap_config
);
362 if (IS_ERR(phy
->regmap
))
363 return PTR_ERR(phy
->regmap
);
365 for (port
= 0; port
< MAX_PHYS
; port
++) {
366 struct mt7621_pci_phy_instance
*instance
;
369 instance
= devm_kzalloc(dev
, sizeof(*instance
), GFP_KERNEL
);
373 phy
->phys
[port
] = instance
;
375 pphy
= devm_phy_create(dev
, dev
->of_node
, &mt7621_pci_phy_ops
);
377 dev_err(dev
, "failed to create phy\n");
381 instance
->port_base
= port_base
;
382 instance
->phy
= pphy
;
383 instance
->index
= port
;
384 phy_set_drvdata(pphy
, instance
);
387 provider
= devm_of_phy_provider_register(dev
, mt7621_pcie_phy_of_xlate
);
389 return PTR_ERR_OR_ZERO(provider
);
392 static const struct of_device_id mt7621_pci_phy_ids
[] = {
393 { .compatible
= "mediatek,mt7621-pci-phy" },
396 MODULE_DEVICE_TABLE(of
, mt7621_pci_ids
);
398 static struct platform_driver mt7621_pci_phy_driver
= {
399 .probe
= mt7621_pci_phy_probe
,
401 .name
= "mt7621-pci-phy",
402 .of_match_table
= of_match_ptr(mt7621_pci_phy_ids
),
406 static int __init
mt7621_pci_phy_drv_init(void)
408 return platform_driver_register(&mt7621_pci_phy_driver
);
411 module_init(mt7621_pci_phy_drv_init
);
413 MODULE_AUTHOR("Sergio Paracuellos <sergio.paracuellos@gmail.com>");
414 MODULE_DESCRIPTION("MediaTek MT7621 PCIe PHY driver");
415 MODULE_LICENSE("GPL v2");