Merge tag 'drm-intel-next-fixes-2024-01-19' of git://anongit.freedesktop.org/drm...
[linux-2.6-microblaze.git] / drivers / phy / qualcomm / phy-qcom-eusb2-repeater.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2023, Linaro Limited
4  */
5
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/regulator/consumer.h>
9 #include <linux/regmap.h>
10 #include <linux/of.h>
11 #include <linux/phy/phy.h>
12
13 /* eUSB2 status registers */
14 #define EUSB2_RPTR_STATUS               0x08
15 #define RPTR_OK                         BIT(7)
16
17 /* eUSB2 control registers */
18 #define EUSB2_EN_CTL1                   0x46
19 #define EUSB2_RPTR_EN                   BIT(7)
20
21 #define EUSB2_FORCE_EN_5                0xe8
22 #define F_CLK_19P2M_EN                  BIT(6)
23
24 #define EUSB2_FORCE_VAL_5               0xeD
25 #define V_CLK_19P2M_EN                  BIT(6)
26
27 #define EUSB2_TUNE_USB2_CROSSOVER       0x50
28 #define EUSB2_TUNE_IUSB2                0x51
29 #define EUSB2_TUNE_RES_FSDIF            0x52
30 #define EUSB2_TUNE_HSDISC               0x53
31 #define EUSB2_TUNE_SQUELCH_U            0x54
32 #define EUSB2_TUNE_USB2_SLEW            0x55
33 #define EUSB2_TUNE_USB2_EQU             0x56
34 #define EUSB2_TUNE_USB2_PREEM           0x57
35 #define EUSB2_TUNE_USB2_HS_COMP_CUR     0x58
36 #define EUSB2_TUNE_EUSB_SLEW            0x59
37 #define EUSB2_TUNE_EUSB_EQU             0x5A
38 #define EUSB2_TUNE_EUSB_HS_COMP_CUR     0x5B
39
40 #define QCOM_EUSB2_REPEATER_INIT_CFG(r, v)      \
41         {                                       \
42                 .reg = r,                       \
43                 .val = v,                       \
44         }
45
46 enum reg_fields {
47         F_TUNE_EUSB_HS_COMP_CUR,
48         F_TUNE_EUSB_EQU,
49         F_TUNE_EUSB_SLEW,
50         F_TUNE_USB2_HS_COMP_CUR,
51         F_TUNE_USB2_PREEM,
52         F_TUNE_USB2_EQU,
53         F_TUNE_USB2_SLEW,
54         F_TUNE_SQUELCH_U,
55         F_TUNE_HSDISC,
56         F_TUNE_RES_FSDIF,
57         F_TUNE_IUSB2,
58         F_TUNE_USB2_CROSSOVER,
59         F_NUM_TUNE_FIELDS,
60
61         F_FORCE_VAL_5 = F_NUM_TUNE_FIELDS,
62         F_FORCE_EN_5,
63
64         F_EN_CTL1,
65
66         F_RPTR_STATUS,
67         F_NUM_FIELDS,
68 };
69
70 static struct reg_field eusb2_repeater_tune_reg_fields[F_NUM_FIELDS] = {
71         [F_TUNE_EUSB_HS_COMP_CUR] = REG_FIELD(EUSB2_TUNE_EUSB_HS_COMP_CUR, 0, 1),
72         [F_TUNE_EUSB_EQU] = REG_FIELD(EUSB2_TUNE_EUSB_EQU, 0, 1),
73         [F_TUNE_EUSB_SLEW] = REG_FIELD(EUSB2_TUNE_EUSB_SLEW, 0, 1),
74         [F_TUNE_USB2_HS_COMP_CUR] = REG_FIELD(EUSB2_TUNE_USB2_HS_COMP_CUR, 0, 1),
75         [F_TUNE_USB2_PREEM] = REG_FIELD(EUSB2_TUNE_USB2_PREEM, 0, 2),
76         [F_TUNE_USB2_EQU] = REG_FIELD(EUSB2_TUNE_USB2_EQU, 0, 1),
77         [F_TUNE_USB2_SLEW] = REG_FIELD(EUSB2_TUNE_USB2_SLEW, 0, 1),
78         [F_TUNE_SQUELCH_U] = REG_FIELD(EUSB2_TUNE_SQUELCH_U, 0, 2),
79         [F_TUNE_HSDISC] = REG_FIELD(EUSB2_TUNE_HSDISC, 0, 2),
80         [F_TUNE_RES_FSDIF] = REG_FIELD(EUSB2_TUNE_RES_FSDIF, 0, 2),
81         [F_TUNE_IUSB2] = REG_FIELD(EUSB2_TUNE_IUSB2, 0, 3),
82         [F_TUNE_USB2_CROSSOVER] = REG_FIELD(EUSB2_TUNE_USB2_CROSSOVER, 0, 2),
83
84         [F_FORCE_VAL_5] = REG_FIELD(EUSB2_FORCE_VAL_5, 0, 7),
85         [F_FORCE_EN_5] = REG_FIELD(EUSB2_FORCE_EN_5, 0, 7),
86
87         [F_EN_CTL1] = REG_FIELD(EUSB2_EN_CTL1, 0, 7),
88
89         [F_RPTR_STATUS] = REG_FIELD(EUSB2_RPTR_STATUS, 0, 7),
90 };
91
92 struct eusb2_repeater_cfg {
93         const u32 *init_tbl;
94         int init_tbl_num;
95         const char * const *vreg_list;
96         int num_vregs;
97 };
98
99 struct eusb2_repeater {
100         struct device *dev;
101         struct regmap_field *regs[F_NUM_FIELDS];
102         struct phy *phy;
103         struct regulator_bulk_data *vregs;
104         const struct eusb2_repeater_cfg *cfg;
105         enum phy_mode mode;
106 };
107
108 static const char * const pm8550b_vreg_l[] = {
109         "vdd18", "vdd3",
110 };
111
112 static const u32 pm8550b_init_tbl[F_NUM_TUNE_FIELDS] = {
113         [F_TUNE_IUSB2] = 0x8,
114         [F_TUNE_SQUELCH_U] = 0x3,
115         [F_TUNE_USB2_PREEM] = 0x5,
116 };
117
118 static const struct eusb2_repeater_cfg pm8550b_eusb2_cfg = {
119         .init_tbl       = pm8550b_init_tbl,
120         .init_tbl_num   = ARRAY_SIZE(pm8550b_init_tbl),
121         .vreg_list      = pm8550b_vreg_l,
122         .num_vregs      = ARRAY_SIZE(pm8550b_vreg_l),
123 };
124
125 static int eusb2_repeater_init_vregs(struct eusb2_repeater *rptr)
126 {
127         int num = rptr->cfg->num_vregs;
128         struct device *dev = rptr->dev;
129         int i;
130
131         rptr->vregs = devm_kcalloc(dev, num, sizeof(*rptr->vregs), GFP_KERNEL);
132         if (!rptr->vregs)
133                 return -ENOMEM;
134
135         for (i = 0; i < num; i++)
136                 rptr->vregs[i].supply = rptr->cfg->vreg_list[i];
137
138         return devm_regulator_bulk_get(dev, num, rptr->vregs);
139 }
140
141 static int eusb2_repeater_init(struct phy *phy)
142 {
143         struct reg_field *regfields = eusb2_repeater_tune_reg_fields;
144         struct eusb2_repeater *rptr = phy_get_drvdata(phy);
145         struct device_node *np = rptr->dev->of_node;
146         u32 init_tbl[F_NUM_TUNE_FIELDS] = { 0 };
147         u8 override;
148         u32 val;
149         int ret;
150         int i;
151
152         ret = regulator_bulk_enable(rptr->cfg->num_vregs, rptr->vregs);
153         if (ret)
154                 return ret;
155
156         regmap_field_update_bits(rptr->regs[F_EN_CTL1], EUSB2_RPTR_EN, EUSB2_RPTR_EN);
157
158         for (i = 0; i < F_NUM_TUNE_FIELDS; i++) {
159                 if (init_tbl[i]) {
160                         regmap_field_update_bits(rptr->regs[i], init_tbl[i], init_tbl[i]);
161                 } else {
162                         /* Write 0 if there's no value set */
163                         u32 mask = GENMASK(regfields[i].msb, regfields[i].lsb);
164
165                         regmap_field_update_bits(rptr->regs[i], mask, 0);
166                 }
167         }
168         memcpy(init_tbl, rptr->cfg->init_tbl, sizeof(init_tbl));
169
170         if (!of_property_read_u8(np, "qcom,tune-usb2-amplitude", &override))
171                 init_tbl[F_TUNE_IUSB2] = override;
172
173         if (!of_property_read_u8(np, "qcom,tune-usb2-disc-thres", &override))
174                 init_tbl[F_TUNE_HSDISC] = override;
175
176         if (!of_property_read_u8(np, "qcom,tune-usb2-preem", &override))
177                 init_tbl[F_TUNE_USB2_PREEM] = override;
178
179         for (i = 0; i < F_NUM_TUNE_FIELDS; i++)
180                 regmap_field_update_bits(rptr->regs[i], init_tbl[i], init_tbl[i]);
181
182         ret = regmap_field_read_poll_timeout(rptr->regs[F_RPTR_STATUS],
183                                              val, val & RPTR_OK, 10, 5);
184         if (ret)
185                 dev_err(rptr->dev, "initialization timed-out\n");
186
187         return ret;
188 }
189
190 static int eusb2_repeater_set_mode(struct phy *phy,
191                                    enum phy_mode mode, int submode)
192 {
193         struct eusb2_repeater *rptr = phy_get_drvdata(phy);
194
195         switch (mode) {
196         case PHY_MODE_USB_HOST:
197                 /*
198                  * CM.Lx is prohibited when repeater is already into Lx state as
199                  * per eUSB 1.2 Spec. Below implement software workaround until
200                  * PHY and controller is fixing seen observation.
201                  */
202                 regmap_field_update_bits(rptr->regs[F_FORCE_EN_5],
203                                          F_CLK_19P2M_EN, F_CLK_19P2M_EN);
204                 regmap_field_update_bits(rptr->regs[F_FORCE_VAL_5],
205                                          V_CLK_19P2M_EN, V_CLK_19P2M_EN);
206                 break;
207         case PHY_MODE_USB_DEVICE:
208                 /*
209                  * In device mode clear host mode related workaround as there
210                  * is no repeater reset available, and enable/disable of
211                  * repeater doesn't clear previous value due to shared
212                  * regulators (say host <-> device mode switch).
213                  */
214                 regmap_field_update_bits(rptr->regs[F_FORCE_EN_5],
215                                          F_CLK_19P2M_EN, 0);
216                 regmap_field_update_bits(rptr->regs[F_FORCE_VAL_5],
217                                          V_CLK_19P2M_EN, 0);
218                 break;
219         default:
220                 return -EINVAL;
221         }
222
223         return 0;
224 }
225
226 static int eusb2_repeater_exit(struct phy *phy)
227 {
228         struct eusb2_repeater *rptr = phy_get_drvdata(phy);
229
230         return regulator_bulk_disable(rptr->cfg->num_vregs, rptr->vregs);
231 }
232
233 static const struct phy_ops eusb2_repeater_ops = {
234         .init           = eusb2_repeater_init,
235         .exit           = eusb2_repeater_exit,
236         .set_mode       = eusb2_repeater_set_mode,
237         .owner          = THIS_MODULE,
238 };
239
240 static int eusb2_repeater_probe(struct platform_device *pdev)
241 {
242         struct eusb2_repeater *rptr;
243         struct device *dev = &pdev->dev;
244         struct phy_provider *phy_provider;
245         struct device_node *np = dev->of_node;
246         struct regmap *regmap;
247         int i, ret;
248         u32 res;
249
250         rptr = devm_kzalloc(dev, sizeof(*rptr), GFP_KERNEL);
251         if (!rptr)
252                 return -ENOMEM;
253
254         rptr->dev = dev;
255         dev_set_drvdata(dev, rptr);
256
257         rptr->cfg = of_device_get_match_data(dev);
258         if (!rptr->cfg)
259                 return -EINVAL;
260
261         regmap = dev_get_regmap(dev->parent, NULL);
262         if (!regmap)
263                 return -ENODEV;
264
265         ret = of_property_read_u32(np, "reg", &res);
266         if (ret < 0)
267                 return ret;
268
269         for (i = 0; i < F_NUM_FIELDS; i++)
270                 eusb2_repeater_tune_reg_fields[i].reg += res;
271
272         ret = devm_regmap_field_bulk_alloc(dev, regmap, rptr->regs,
273                                            eusb2_repeater_tune_reg_fields,
274                                            F_NUM_FIELDS);
275         if (ret)
276                 return ret;
277
278         ret = eusb2_repeater_init_vregs(rptr);
279         if (ret < 0) {
280                 dev_err(dev, "unable to get supplies\n");
281                 return ret;
282         }
283
284         rptr->phy = devm_phy_create(dev, np, &eusb2_repeater_ops);
285         if (IS_ERR(rptr->phy)) {
286                 dev_err(dev, "failed to create PHY: %d\n", ret);
287                 return PTR_ERR(rptr->phy);
288         }
289
290         phy_set_drvdata(rptr->phy, rptr);
291
292         phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
293         if (IS_ERR(phy_provider))
294                 return PTR_ERR(phy_provider);
295
296         dev_info(dev, "Registered Qcom-eUSB2 repeater\n");
297
298         return 0;
299 }
300
301 static void eusb2_repeater_remove(struct platform_device *pdev)
302 {
303         struct eusb2_repeater *rptr = platform_get_drvdata(pdev);
304
305         if (!rptr)
306                 return;
307
308         eusb2_repeater_exit(rptr->phy);
309 }
310
311 static const struct of_device_id eusb2_repeater_of_match_table[] = {
312         {
313                 .compatible = "qcom,pm8550b-eusb2-repeater",
314                 .data = &pm8550b_eusb2_cfg,
315         },
316         { },
317 };
318 MODULE_DEVICE_TABLE(of, eusb2_repeater_of_match_table);
319
320 static struct platform_driver eusb2_repeater_driver = {
321         .probe          = eusb2_repeater_probe,
322         .remove_new     = eusb2_repeater_remove,
323         .driver = {
324                 .name   = "qcom-eusb2-repeater",
325                 .of_match_table = eusb2_repeater_of_match_table,
326         },
327 };
328
329 module_platform_driver(eusb2_repeater_driver);
330
331 MODULE_DESCRIPTION("Qualcomm PMIC eUSB2 Repeater driver");
332 MODULE_LICENSE("GPL");