Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / phy / broadcom / phy-bcm-sr-usb.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2016-2018 Broadcom
4  */
5
6 #include <linux/delay.h>
7 #include <linux/io.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/phy/phy.h>
11 #include <linux/platform_device.h>
12
13 enum bcm_usb_phy_version {
14         BCM_SR_USB_COMBO_PHY,
15         BCM_SR_USB_HS_PHY,
16 };
17
18 enum bcm_usb_phy_reg {
19         PLL_NDIV_FRAC,
20         PLL_NDIV_INT,
21         PLL_CTRL,
22         PHY_CTRL,
23         PHY_PLL_CTRL,
24 };
25
26 /* USB PHY registers */
27
28 static const u8 bcm_usb_combo_phy_ss[] = {
29         [PLL_CTRL]              = 0x18,
30         [PHY_CTRL]              = 0x14,
31 };
32
33 static const u8 bcm_usb_combo_phy_hs[] = {
34         [PLL_NDIV_FRAC] = 0x04,
35         [PLL_NDIV_INT]  = 0x08,
36         [PLL_CTRL]      = 0x0c,
37         [PHY_CTRL]      = 0x10,
38 };
39
40 #define HSPLL_NDIV_INT_VAL      0x13
41 #define HSPLL_NDIV_FRAC_VAL     0x1005
42
43 static const u8 bcm_usb_hs_phy[] = {
44         [PLL_NDIV_FRAC] = 0x0,
45         [PLL_NDIV_INT]  = 0x4,
46         [PLL_CTRL]      = 0x8,
47         [PHY_CTRL]      = 0xc,
48 };
49
50 enum pll_ctrl_bits {
51         PLL_RESETB,
52         SSPLL_SUSPEND_EN,
53         PLL_SEQ_START,
54         PLL_LOCK,
55         PLL_PDIV,
56 };
57
58 static const u8 u3pll_ctrl[] = {
59         [PLL_RESETB]            = 0,
60         [SSPLL_SUSPEND_EN]      = 1,
61         [PLL_SEQ_START]         = 2,
62         [PLL_LOCK]              = 3,
63 };
64
65 #define HSPLL_PDIV_MASK         0xF
66 #define HSPLL_PDIV_VAL          0x1
67
68 static const u8 u2pll_ctrl[] = {
69         [PLL_PDIV]      = 1,
70         [PLL_RESETB]    = 5,
71         [PLL_LOCK]      = 6,
72 };
73
74 enum bcm_usb_phy_ctrl_bits {
75         CORERDY,
76         AFE_LDO_PWRDWNB,
77         AFE_PLL_PWRDWNB,
78         AFE_BG_PWRDWNB,
79         PHY_ISO,
80         PHY_RESETB,
81         PHY_PCTL,
82 };
83
84 #define PHY_PCTL_MASK   0xffff
85 /*
86  * 0x0806 of PCTL_VAL has below bits set
87  * BIT-8 : refclk divider 1
88  * BIT-3:2: device mode; mode is not effect
89  * BIT-1: soft reset active low
90  */
91 #define HSPHY_PCTL_VAL  0x0806
92 #define SSPHY_PCTL_VAL  0x0006
93
94 static const u8 u3phy_ctrl[] = {
95         [PHY_RESETB]    = 1,
96         [PHY_PCTL]      = 2,
97 };
98
99 static const u8 u2phy_ctrl[] = {
100         [CORERDY]               = 0,
101         [AFE_LDO_PWRDWNB]       = 1,
102         [AFE_PLL_PWRDWNB]       = 2,
103         [AFE_BG_PWRDWNB]        = 3,
104         [PHY_ISO]               = 4,
105         [PHY_RESETB]            = 5,
106         [PHY_PCTL]              = 6,
107 };
108
109 struct bcm_usb_phy_cfg {
110         uint32_t type;
111         uint32_t version;
112         void __iomem *regs;
113         struct phy *phy;
114         const u8 *offset;
115 };
116
117 #define PLL_LOCK_RETRY_COUNT    1000
118
119 enum bcm_usb_phy_type {
120         USB_HS_PHY,
121         USB_SS_PHY,
122 };
123
124 #define NUM_BCM_SR_USB_COMBO_PHYS       2
125
126 static inline void bcm_usb_reg32_clrbits(void __iomem *addr, uint32_t clear)
127 {
128         writel(readl(addr) & ~clear, addr);
129 }
130
131 static inline void bcm_usb_reg32_setbits(void __iomem *addr, uint32_t set)
132 {
133         writel(readl(addr) | set, addr);
134 }
135
136 static int bcm_usb_pll_lock_check(void __iomem *addr, u32 bit)
137 {
138         int retry;
139         u32 rd_data;
140
141         retry = PLL_LOCK_RETRY_COUNT;
142         do {
143                 rd_data = readl(addr);
144                 if (rd_data & bit)
145                         return 0;
146                 udelay(1);
147         } while (--retry > 0);
148
149         pr_err("%s: FAIL\n", __func__);
150         return -ETIMEDOUT;
151 }
152
153 static int bcm_usb_ss_phy_init(struct bcm_usb_phy_cfg *phy_cfg)
154 {
155         int ret = 0;
156         void __iomem *regs = phy_cfg->regs;
157         const u8 *offset;
158         u32 rd_data;
159
160         offset = phy_cfg->offset;
161
162         /* Set pctl with mode and soft reset */
163         rd_data = readl(regs + offset[PHY_CTRL]);
164         rd_data &= ~(PHY_PCTL_MASK << u3phy_ctrl[PHY_PCTL]);
165         rd_data |= (SSPHY_PCTL_VAL << u3phy_ctrl[PHY_PCTL]);
166         writel(rd_data, regs + offset[PHY_CTRL]);
167
168         bcm_usb_reg32_clrbits(regs + offset[PLL_CTRL],
169                               BIT(u3pll_ctrl[SSPLL_SUSPEND_EN]));
170         bcm_usb_reg32_setbits(regs + offset[PLL_CTRL],
171                               BIT(u3pll_ctrl[PLL_SEQ_START]));
172         bcm_usb_reg32_setbits(regs + offset[PLL_CTRL],
173                               BIT(u3pll_ctrl[PLL_RESETB]));
174
175         /* Maximum timeout for PLL reset done */
176         msleep(30);
177
178         ret = bcm_usb_pll_lock_check(regs + offset[PLL_CTRL],
179                                      BIT(u3pll_ctrl[PLL_LOCK]));
180
181         return ret;
182 }
183
184 static int bcm_usb_hs_phy_init(struct bcm_usb_phy_cfg *phy_cfg)
185 {
186         int ret = 0;
187         void __iomem *regs = phy_cfg->regs;
188         const u8 *offset;
189         u32 rd_data;
190
191         offset = phy_cfg->offset;
192
193         writel(HSPLL_NDIV_INT_VAL, regs + offset[PLL_NDIV_INT]);
194         writel(HSPLL_NDIV_FRAC_VAL, regs + offset[PLL_NDIV_FRAC]);
195
196         rd_data = readl(regs + offset[PLL_CTRL]);
197         rd_data &= ~(HSPLL_PDIV_MASK << u2pll_ctrl[PLL_PDIV]);
198         rd_data |= (HSPLL_PDIV_VAL << u2pll_ctrl[PLL_PDIV]);
199         writel(rd_data, regs + offset[PLL_CTRL]);
200
201         /* Set Core Ready high */
202         bcm_usb_reg32_setbits(regs + offset[PHY_CTRL],
203                               BIT(u2phy_ctrl[CORERDY]));
204
205         /* Maximum timeout for Core Ready done */
206         msleep(30);
207
208         bcm_usb_reg32_setbits(regs + offset[PLL_CTRL],
209                               BIT(u2pll_ctrl[PLL_RESETB]));
210         bcm_usb_reg32_setbits(regs + offset[PHY_CTRL],
211                               BIT(u2phy_ctrl[PHY_RESETB]));
212
213
214         rd_data = readl(regs + offset[PHY_CTRL]);
215         rd_data &= ~(PHY_PCTL_MASK << u2phy_ctrl[PHY_PCTL]);
216         rd_data |= (HSPHY_PCTL_VAL << u2phy_ctrl[PHY_PCTL]);
217         writel(rd_data, regs + offset[PHY_CTRL]);
218
219         /* Maximum timeout for PLL reset done */
220         msleep(30);
221
222         ret = bcm_usb_pll_lock_check(regs + offset[PLL_CTRL],
223                                      BIT(u2pll_ctrl[PLL_LOCK]));
224
225         return ret;
226 }
227
228 static int bcm_usb_phy_reset(struct phy *phy)
229 {
230         struct bcm_usb_phy_cfg *phy_cfg = phy_get_drvdata(phy);
231         void __iomem *regs = phy_cfg->regs;
232         const u8 *offset;
233
234         offset = phy_cfg->offset;
235
236         if (phy_cfg->type == USB_HS_PHY) {
237                 bcm_usb_reg32_clrbits(regs + offset[PHY_CTRL],
238                                       BIT(u2phy_ctrl[CORERDY]));
239                 bcm_usb_reg32_setbits(regs + offset[PHY_CTRL],
240                                       BIT(u2phy_ctrl[CORERDY]));
241         }
242
243         return 0;
244 }
245
246 static int bcm_usb_phy_init(struct phy *phy)
247 {
248         struct bcm_usb_phy_cfg *phy_cfg = phy_get_drvdata(phy);
249         int ret = -EINVAL;
250
251         if (phy_cfg->type == USB_SS_PHY)
252                 ret = bcm_usb_ss_phy_init(phy_cfg);
253         else if (phy_cfg->type == USB_HS_PHY)
254                 ret = bcm_usb_hs_phy_init(phy_cfg);
255
256         return ret;
257 }
258
259 static struct phy_ops sr_phy_ops = {
260         .init           = bcm_usb_phy_init,
261         .reset          = bcm_usb_phy_reset,
262         .owner          = THIS_MODULE,
263 };
264
265 static struct phy *bcm_usb_phy_xlate(struct device *dev,
266                                      struct of_phandle_args *args)
267 {
268         struct bcm_usb_phy_cfg *phy_cfg;
269         int phy_idx;
270
271         phy_cfg = dev_get_drvdata(dev);
272         if (!phy_cfg)
273                 return ERR_PTR(-EINVAL);
274
275         if (phy_cfg->version == BCM_SR_USB_COMBO_PHY) {
276                 phy_idx = args->args[0];
277
278                 if (WARN_ON(phy_idx > 1))
279                         return ERR_PTR(-ENODEV);
280
281                 return phy_cfg[phy_idx].phy;
282         } else
283                 return phy_cfg->phy;
284 }
285
286 static int bcm_usb_phy_create(struct device *dev, struct device_node *node,
287                               void __iomem *regs, uint32_t version)
288 {
289         struct bcm_usb_phy_cfg *phy_cfg;
290         int idx;
291
292         if (version == BCM_SR_USB_COMBO_PHY) {
293                 phy_cfg = devm_kzalloc(dev, NUM_BCM_SR_USB_COMBO_PHYS *
294                                        sizeof(struct bcm_usb_phy_cfg),
295                                        GFP_KERNEL);
296                 if (!phy_cfg)
297                         return -ENOMEM;
298
299                 for (idx = 0; idx < NUM_BCM_SR_USB_COMBO_PHYS; idx++) {
300                         phy_cfg[idx].regs = regs;
301                         phy_cfg[idx].version = version;
302                         if (idx == 0) {
303                                 phy_cfg[idx].offset = bcm_usb_combo_phy_hs;
304                                 phy_cfg[idx].type = USB_HS_PHY;
305                         } else {
306                                 phy_cfg[idx].offset = bcm_usb_combo_phy_ss;
307                                 phy_cfg[idx].type = USB_SS_PHY;
308                         }
309                         phy_cfg[idx].phy = devm_phy_create(dev, node,
310                                                            &sr_phy_ops);
311                         if (IS_ERR(phy_cfg[idx].phy))
312                                 return PTR_ERR(phy_cfg[idx].phy);
313
314                         phy_set_drvdata(phy_cfg[idx].phy, &phy_cfg[idx]);
315                 }
316         } else if (version == BCM_SR_USB_HS_PHY) {
317                 phy_cfg = devm_kzalloc(dev, sizeof(struct bcm_usb_phy_cfg),
318                                        GFP_KERNEL);
319                 if (!phy_cfg)
320                         return -ENOMEM;
321
322                 phy_cfg->regs = regs;
323                 phy_cfg->version = version;
324                 phy_cfg->offset = bcm_usb_hs_phy;
325                 phy_cfg->type = USB_HS_PHY;
326                 phy_cfg->phy = devm_phy_create(dev, node, &sr_phy_ops);
327                 if (IS_ERR(phy_cfg->phy))
328                         return PTR_ERR(phy_cfg->phy);
329
330                 phy_set_drvdata(phy_cfg->phy, phy_cfg);
331         } else
332                 return -ENODEV;
333
334         dev_set_drvdata(dev, phy_cfg);
335
336         return 0;
337 }
338
339 static const struct of_device_id bcm_usb_phy_of_match[] = {
340         {
341                 .compatible = "brcm,sr-usb-combo-phy",
342                 .data = (void *)BCM_SR_USB_COMBO_PHY,
343         },
344         {
345                 .compatible = "brcm,sr-usb-hs-phy",
346                 .data = (void *)BCM_SR_USB_HS_PHY,
347         },
348         { /* sentinel */ },
349 };
350 MODULE_DEVICE_TABLE(of, bcm_usb_phy_of_match);
351
352 static int bcm_usb_phy_probe(struct platform_device *pdev)
353 {
354         struct device *dev = &pdev->dev;
355         struct device_node *dn = dev->of_node;
356         const struct of_device_id *of_id;
357         struct resource *res;
358         void __iomem *regs;
359         int ret;
360         enum bcm_usb_phy_version version;
361         struct phy_provider *phy_provider;
362
363         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
364         regs = devm_ioremap_resource(dev, res);
365         if (IS_ERR(regs))
366                 return PTR_ERR(regs);
367
368         of_id = of_match_node(bcm_usb_phy_of_match, dn);
369         if (of_id)
370                 version = (enum bcm_usb_phy_version)of_id->data;
371         else
372                 return -ENODEV;
373
374         ret = bcm_usb_phy_create(dev, dn, regs, version);
375         if (ret)
376                 return ret;
377
378         phy_provider = devm_of_phy_provider_register(dev, bcm_usb_phy_xlate);
379
380         return PTR_ERR_OR_ZERO(phy_provider);
381 }
382
383 static struct platform_driver bcm_usb_phy_driver = {
384         .driver = {
385                 .name = "phy-bcm-sr-usb",
386                 .of_match_table = bcm_usb_phy_of_match,
387         },
388         .probe = bcm_usb_phy_probe,
389 };
390 module_platform_driver(bcm_usb_phy_driver);
391
392 MODULE_AUTHOR("Broadcom");
393 MODULE_DESCRIPTION("Broadcom stingray USB Phy driver");
394 MODULE_LICENSE("GPL v2");