Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / phy / phy-npcm-usb.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2021 Nuvoton Technology Corp.
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <generic-phy.h>
9 #include <regmap.h>
10 #include <reset.h>
11 #include <syscon.h>
12 #include <dm/device_compat.h>
13 #include <linux/bitfield.h>
14 #include <linux/delay.h>
15
16 /* GCR Register Offsets */
17 #define GCR_INTCR3      0x9C
18 #define GCR_USB1PHYCTL  0x140
19 #define GCR_USB2PHYCTL  0x144
20 #define GCR_USB3PHYCTL  0x148
21
22 /* USBnPHYCTL bit fields */
23 #define PHYCTL_RS       BIT(28)
24
25 #define USBPHY2SW       GENMASK(13, 12)
26 #define USBPHY3SW       GENMASK(15, 14)
27
28 #define USBPHY2SW_DEV9_PHY1     FIELD_PREP(USBPHY2SW, 0)
29 #define USBPHY2SW_HOST1         FIELD_PREP(USBPHY2SW, 1)
30 #define USBPHY2SW_DEV9_PHY2     FIELD_PREP(USBPHY2SW, 3)
31 #define USBPHY3SW_DEV8_PHY1     FIELD_PREP(USBPHY3SW, 0)
32 #define USBPHY3SW_HOST2         FIELD_PREP(USBPHY3SW, 1)
33 #define USBPHY3SW_DEV8_PHY3     FIELD_PREP(USBPHY3SW, 3)
34
35 enum controller_id {
36         UDC0_7,
37         UDC8,
38         UDC9,
39         USBH1,
40         USBH2,
41 };
42
43 enum phy_id {
44         PHY1 = 1,
45         PHY2,
46         PHY3,
47 };
48
49 /* Phy Switch Settings */
50 #define USBDPHY1        ((PHY1 << 8) | UDC0_7)  /* Connect UDC0~7 to PHY1 */
51 #define USBD8PHY1       ((PHY1 << 8) | UDC8)    /* Connect UDC8 to PHY1 */
52 #define USBD9PHY1       ((PHY1 << 8) | UDC9)    /* Connect UDC9 to PHY1 */
53 #define USBD9PHY2       ((PHY2 << 8) | UDC9)    /* Connect UDC9 to PHY2 */
54 #define USBH1PHY2       ((PHY2 << 8) | USBH1)   /* Connect USBH1 to PHY2 */
55 #define USBD8PHY3       ((PHY3 << 8) | UDC8)    /* Connect UDC8 to PHY3 */
56 #define USBH2PHY3       ((PHY3 << 8) | USBH2)   /* Connect USBH2 to PHY3 */
57
58 struct npcm_usbphy {
59         struct regmap *syscon;
60         u8 id;
61         u16 phy_switch; /* (phy_id << 8) | controller_id */
62 };
63
64 static int npcm_usb_phy_init(struct phy *phy)
65 {
66         struct npcm_usbphy *priv = dev_get_priv(phy->dev);
67         struct reset_ctl reset;
68         int ret;
69
70         ret = reset_get_by_index(phy->dev, 0, &reset);
71         if (ret && ret != -ENOENT && ret != -ENOTSUPP) {
72                 dev_err(phy->dev, "can't get phy reset ctrl (err %d)", ret);
73                 return ret;
74         }
75
76         /* setup PHY switch */
77         switch (priv->phy_switch) {
78         case USBD8PHY1:
79                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY3SW,
80                                    USBPHY3SW_DEV8_PHY1);
81                 break;
82         case USBD8PHY3:
83                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY3SW,
84                                    USBPHY3SW_DEV8_PHY3);
85                 break;
86         case USBD9PHY1:
87                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY2SW,
88                                    USBPHY2SW_DEV9_PHY1);
89                 break;
90         case USBD9PHY2:
91                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY2SW,
92                                    USBPHY2SW_DEV9_PHY2);
93                 break;
94         case USBH1PHY2:
95                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY2SW,
96                                    USBPHY2SW_HOST1);
97                 break;
98         case USBH2PHY3:
99                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY3SW,
100                                    USBPHY3SW_HOST2);
101                 break;
102         default:
103                 break;
104         }
105         /* reset phy */
106         if (reset_valid(&reset))
107                 reset_assert(&reset);
108
109         /* Wait for PHY clocks to stablize for 50us or more */
110         udelay(100);
111
112         /* release phy from reset */
113         if (reset_valid(&reset))
114                 reset_deassert(&reset);
115
116         /* PHY RS bit should be set after reset */
117         switch (priv->id) {
118         case PHY1:
119                 regmap_update_bits(priv->syscon, GCR_USB1PHYCTL, PHYCTL_RS, PHYCTL_RS);
120                 break;
121         case PHY2:
122                 regmap_update_bits(priv->syscon, GCR_USB2PHYCTL, PHYCTL_RS, PHYCTL_RS);
123                 break;
124         case PHY3:
125                 regmap_update_bits(priv->syscon, GCR_USB3PHYCTL, PHYCTL_RS, PHYCTL_RS);
126                 break;
127         default:
128                 break;
129         }
130
131         return 0;
132 }
133
134 static int npcm_usb_phy_exit(struct phy *phy)
135 {
136         struct npcm_usbphy *priv = dev_get_priv(phy->dev);
137
138         /* set PHY switch to default state */
139         switch (priv->phy_switch) {
140         case USBD8PHY1:
141         case USBD8PHY3:
142                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY3SW,
143                                    USBPHY3SW_HOST2);
144                 break;
145         case USBD9PHY1:
146         case USBD9PHY2:
147                 regmap_update_bits(priv->syscon, GCR_INTCR3, USBPHY2SW,
148                                    USBPHY2SW_HOST1);
149                 break;
150         default:
151                 break;
152         }
153         return 0;
154 }
155
156 static int  npcm_usb_phy_xlate(struct phy *phy, struct ofnode_phandle_args *args)
157 {
158         struct npcm_usbphy *priv = dev_get_priv(phy->dev);
159         u16 phy_switch;
160
161         if (args->args_count < 1 || args->args[0] > USBH2)
162                 return -EINVAL;
163
164         phy_switch = (priv->id << 8) | args->args[0];
165         switch (phy_switch) {
166         case USBD9PHY1:
167         case USBH2PHY3:
168         case USBD8PHY3:
169                 if (!IS_ENABLED(CONFIG_ARCH_NPCM8XX))
170                         return -EINVAL;
171         case USBDPHY1:
172         case USBD8PHY1:
173         case USBD9PHY2:
174         case USBH1PHY2:
175                 priv->phy_switch = phy_switch;
176                 return 0;
177         default:
178                 return -EINVAL;
179         }
180 }
181
182 static int npcm_usb_phy_probe(struct udevice *dev)
183 {
184         struct npcm_usbphy *priv = dev_get_priv(dev);
185
186         priv->syscon = syscon_regmap_lookup_by_phandle(dev->parent, "syscon");
187         if (IS_ERR(priv->syscon)) {
188                 dev_err(dev, "%s: unable to get syscon\n", __func__);
189                 return PTR_ERR(priv->syscon);
190         }
191         priv->id = dev_read_u32_default(dev, "reg", -1);
192
193         return 0;
194 }
195
196 static const struct udevice_id npcm_phy_ids[] = {
197         { .compatible = "nuvoton,npcm845-usb-phy",},
198         { .compatible = "nuvoton,npcm750-usb-phy",},
199         { }
200 };
201
202 static struct phy_ops npcm_phy_ops = {
203         .init = npcm_usb_phy_init,
204         .exit = npcm_usb_phy_exit,
205         .of_xlate = npcm_usb_phy_xlate,
206 };
207
208 U_BOOT_DRIVER(npcm_phy) = {
209         .name   = "npcm-usb-phy",
210         .id     = UCLASS_PHY,
211         .of_match = npcm_phy_ids,
212         .ops = &npcm_phy_ops,
213         .probe          = npcm_usb_phy_probe,
214         .priv_auto      = sizeof(struct npcm_usbphy),
215 };