arm: mach-k3: Enable dcache in SPL
[oweals/u-boot.git] / drivers / usb / common / fsl-dt-fixup.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc.
4  *
5  * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
6  *
7  * Author: Tor Krill tor@excito.com
8  */
9
10 #include <common.h>
11 #include <usb.h>
12 #include <asm/io.h>
13 #include <hwconfig.h>
14 #include <fsl_errata.h>
15 #include <fsl_usb.h>
16 #include <fdt_support.h>
17
18 #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
19 #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
20 #endif
21
22 /* USB Controllers */
23 #define FSL_USB2_MPH    "fsl-usb2-mph"
24 #define FSL_USB2_DR     "fsl-usb2-dr"
25 #define CHIPIDEA_USB2   "chipidea,usb2"
26 #define SNPS_DWC3       "snps,dwc3"
27
28 static const char * const compat_usb_fsl[] = {
29         FSL_USB2_MPH,
30         FSL_USB2_DR,
31         SNPS_DWC3,
32         NULL
33 };
34
35 static int fdt_usb_get_node_type(void *blob, int start_offset,
36                                  int *node_offset, const char **node_type)
37 {
38         int i;
39         int ret = -ENOENT;
40
41         for (i = 0; compat_usb_fsl[i]; i++) {
42                 *node_offset = fdt_node_offset_by_compatible
43                                         (blob, start_offset,
44                                          compat_usb_fsl[i]);
45                 if (*node_offset >= 0) {
46                         *node_type = compat_usb_fsl[i];
47                         ret = 0;
48                         break;
49                 }
50         }
51
52         return ret;
53 }
54
55 static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
56                                        const char *phy_type, int start_offset)
57 {
58         const char *prop_mode = "dr_mode";
59         const char *prop_type = "phy_type";
60         const char *node_type = NULL;
61         int node_offset;
62         int err;
63
64         err = fdt_usb_get_node_type(blob, start_offset,
65                                     &node_offset, &node_type);
66         if (err < 0)
67                 return err;
68
69         if (mode) {
70                 err = fdt_setprop(blob, node_offset, prop_mode, mode,
71                                   strlen(mode) + 1);
72                 if (err < 0)
73                         printf("WARNING: could not set %s for %s: %s.\n",
74                                prop_mode, node_type, fdt_strerror(err));
75         }
76
77         if (phy_type) {
78                 err = fdt_setprop(blob, node_offset, prop_type, phy_type,
79                                   strlen(phy_type) + 1);
80                 if (err < 0)
81                         printf("WARNING: could not set %s for %s: %s.\n",
82                                prop_type, node_type, fdt_strerror(err));
83         }
84
85         return node_offset;
86 }
87
88 static int fsl_fdt_fixup_usb_erratum(void *blob, const char *prop_erratum,
89                                      const char *controller_type,
90                                      int start_offset)
91 {
92         int node_offset, err;
93         const char *node_type = NULL;
94         const char *node_name = NULL;
95
96         err = fdt_usb_get_node_type(blob, start_offset,
97                                     &node_offset, &node_type);
98         if (err < 0)
99                 return err;
100
101         if (!strcmp(node_type, FSL_USB2_MPH) || !strcmp(node_type, FSL_USB2_DR))
102                 node_name = CHIPIDEA_USB2;
103         else
104                 node_name = node_type;
105         if (strcmp(node_name, controller_type))
106                 return err;
107
108         err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0);
109         if (err < 0) {
110                 printf("ERROR: could not set %s for %s: %s.\n",
111                        prop_erratum, node_type, fdt_strerror(err));
112         }
113
114         return node_offset;
115 }
116
117 static int fsl_fdt_fixup_erratum(int *usb_erratum_off, void *blob,
118                                  const char *controller_type, char *str,
119                                  bool (*has_erratum)(void))
120 {
121         char buf[32] = {0};
122
123         snprintf(buf, sizeof(buf), "fsl,usb-erratum-%s", str);
124         if (!has_erratum())
125                 return -EINVAL;
126         *usb_erratum_off = fsl_fdt_fixup_usb_erratum(blob, buf, controller_type,
127                                                      *usb_erratum_off);
128         if (*usb_erratum_off < 0)
129                 return -ENOSPC;
130         debug("Adding USB erratum %s\n", str);
131         return 0;
132 }
133
134 void fsl_fdt_fixup_dr_usb(void *blob, bd_t *bd)
135 {
136         static const char * const modes[] = { "host", "peripheral", "otg" };
137         static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" };
138         int usb_erratum_a006261_off = -1;
139         int usb_erratum_a007075_off = -1;
140         int usb_erratum_a007792_off = -1;
141         int usb_erratum_a005697_off = -1;
142         int usb_erratum_a008751_off = -1;
143         int usb_mode_off = -1;
144         int usb_phy_off = -1;
145         char str[5];
146         int i, j;
147         int ret;
148
149         for (i = 1; i <= CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
150                 const char *dr_mode_type = NULL;
151                 const char *dr_phy_type = NULL;
152                 int mode_idx = -1, phy_idx = -1;
153
154                 snprintf(str, 5, "%s%d", "usb", i);
155                 if (hwconfig(str)) {
156                         for (j = 0; j < ARRAY_SIZE(modes); j++) {
157                                 if (hwconfig_subarg_cmp(str, "dr_mode",
158                                                         modes[j])) {
159                                         mode_idx = j;
160                                         break;
161                                 }
162                         }
163
164                         for (j = 0; j < ARRAY_SIZE(phys); j++) {
165                                 if (hwconfig_subarg_cmp(str, "phy_type",
166                                                         phys[j])) {
167                                         phy_idx = j;
168                                         break;
169                                 }
170                         }
171
172                         if (mode_idx < 0 && phy_idx < 0) {
173                                 printf("WARNING: invalid phy or mode\n");
174                                 return;
175                         }
176
177                         if (mode_idx > -1)
178                                 dr_mode_type = modes[mode_idx];
179
180                         if (phy_idx > -1)
181                                 dr_phy_type = phys[phy_idx];
182                 }
183
184                 if (has_dual_phy())
185                         dr_phy_type = phys[2];
186
187                 usb_mode_off = fdt_fixup_usb_mode_phy_type(blob,
188                                                            dr_mode_type, NULL,
189                                                            usb_mode_off);
190
191                 if (usb_mode_off < 0)
192                         return;
193
194                 usb_phy_off = fdt_fixup_usb_mode_phy_type(blob,
195                                                           NULL, dr_phy_type,
196                                                           usb_phy_off);
197
198                 if (usb_phy_off < 0)
199                         return;
200
201                 ret = fsl_fdt_fixup_erratum(&usb_erratum_a006261_off, blob,
202                                             CHIPIDEA_USB2, "a006261",
203                                             has_erratum_a006261);
204                 if (ret == -ENOSPC)
205                         return;
206                 ret = fsl_fdt_fixup_erratum(&usb_erratum_a007075_off, blob,
207                                             CHIPIDEA_USB2, "a007075",
208                                             has_erratum_a007075);
209                 if (ret == -ENOSPC)
210                         return;
211                 ret = fsl_fdt_fixup_erratum(&usb_erratum_a007792_off, blob,
212                                             CHIPIDEA_USB2, "a007792",
213                                             has_erratum_a007792);
214                 if (ret == -ENOSPC)
215                         return;
216                 ret = fsl_fdt_fixup_erratum(&usb_erratum_a005697_off, blob,
217                                             CHIPIDEA_USB2, "a005697",
218                                             has_erratum_a005697);
219                 if (ret == -ENOSPC)
220                         return;
221                 ret = fsl_fdt_fixup_erratum(&usb_erratum_a008751_off, blob,
222                                             SNPS_DWC3, "a008751",
223                                             has_erratum_a008751);
224                 if (ret == -ENOSPC)
225                         return;
226
227         }
228 }