]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/powerpc/cpu/mpc85xx/portals.c
ec3b2924b9d87c9651c5b25c9c1c2ca7974fa4c0
[karo-tx-uboot.git] / arch / powerpc / cpu / mpc85xx / portals.c
1 /*
2  * Copyright 2008-2011 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <libfdt.h>
9 #include <fdt_support.h>
10
11 #include <asm/processor.h>
12 #include <asm/io.h>
13
14 #include <asm/fsl_portals.h>
15 #include <asm/fsl_liodn.h>
16
17 #define MAX_BPORTALS (CONFIG_SYS_BMAN_CINH_SIZE / CONFIG_SYS_BMAN_SP_CINH_SIZE)
18 #define MAX_QPORTALS (CONFIG_SYS_QMAN_CINH_SIZE / CONFIG_SYS_QMAN_SP_CINH_SIZE)
19 static void inhibit_portals(void __iomem *addr, int max_portals,
20                         int arch_max_portals, int portal_cinh_size)
21 {
22         uint32_t val;
23         int i;
24
25         /* arch_max_portals is the maximum based on memory size. This includes
26          * the reserved memory in the SoC.  max_portals the number of physical
27          * portals in the SoC */
28         if (max_portals > arch_max_portals) {
29                 printf("ERROR: portal config error\n");
30                 max_portals = arch_max_portals;
31         }
32
33         for (i = 0; i < max_portals; i++) {
34                 out_be32(addr, -1);
35                 val = in_be32(addr);
36                 if (!val) {
37                         printf("ERROR: Stopped after %d portals\n", i);
38                         goto done;
39                 }
40                 addr += portal_cinh_size;
41         }
42 #ifdef DEBUG
43         printf("Cleared %d portals\n", i);
44 #endif
45 done:
46
47         return;
48 }
49
50 void setup_portals(void)
51 {
52         ccsr_qman_t *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
53         void __iomem *bpaddr = (void *)CONFIG_SYS_BMAN_CINH_BASE +
54                                 CONFIG_SYS_BMAN_SWP_ISDR_REG;
55         void __iomem *qpaddr = (void *)CONFIG_SYS_QMAN_CINH_BASE +
56                                 CONFIG_SYS_QMAN_SWP_ISDR_REG;
57 #ifdef CONFIG_FSL_CORENET
58         int i;
59
60         for (i = 0; i < CONFIG_SYS_QMAN_NUM_PORTALS; i++) {
61                 u8 sdest = qp_info[i].sdest;
62                 u16 fliodn = qp_info[i].fliodn;
63                 u16 dliodn = qp_info[i].dliodn;
64                 u16 liodn_off = qp_info[i].liodn_offset;
65
66                 out_be32(&qman->qcsp[i].qcsp_lio_cfg, (liodn_off << 16) |
67                                         dliodn);
68                 /* set frame liodn */
69                 out_be32(&qman->qcsp[i].qcsp_io_cfg, (sdest << 16) | fliodn);
70         }
71 #endif
72
73         /* Set the Qman initiator BAR to match the LAW (for DQRR stashing) */
74 #ifdef CONFIG_PHYS_64BIT
75         out_be32(&qman->qcsp_bare, (u32)(CONFIG_SYS_QMAN_MEM_PHYS >> 32));
76 #endif
77         out_be32(&qman->qcsp_bar, (u32)CONFIG_SYS_QMAN_MEM_PHYS);
78
79         /* Change default state of BMan ISDR portals to all 1s */
80         inhibit_portals(bpaddr, CONFIG_SYS_BMAN_NUM_PORTALS, MAX_BPORTALS,
81                         CONFIG_SYS_BMAN_SP_CINH_SIZE);
82         inhibit_portals(qpaddr, CONFIG_SYS_QMAN_NUM_PORTALS, MAX_QPORTALS,
83                         CONFIG_SYS_QMAN_SP_CINH_SIZE);
84 }
85
86 /* Update portal containter to match LAW setup of portal in phy map */
87 void fdt_portal(void *blob, const char *compat, const char *container,
88                         u64 addr, u32 size)
89 {
90         int off;
91
92         off = fdt_node_offset_by_compatible(blob, -1, compat);
93         if (off < 0)
94                 return ;
95
96         off = fdt_parent_offset(blob, off);
97         /* if non-zero assume we have a container */
98         if (off > 0) {
99                 char buf[60];
100                 const char *p, *name;
101                 u32 *range;
102                 int len;
103
104                 /* fixup ranges */
105                 range = fdt_getprop_w(blob, off, "ranges", &len);
106                 if (range == NULL) {
107                         printf("ERROR: container for %s has no ranges", compat);
108                         return ;
109                 }
110
111                 range[0] = 0;
112                 if (len == 16) {
113                         range[1] = addr >> 32;
114                         range[2] = addr & 0xffffffff;
115                         range[3] = size;
116                 } else {
117                         range[1] = addr & 0xffffffff;
118                         range[2] = size;
119                 }
120                 fdt_setprop_inplace(blob, off, "ranges", range, len);
121
122                 /* fixup the name */
123                 name = fdt_get_name(blob, off, &len);
124                 p = memchr(name, '@', len);
125
126                 if (p)
127                         len = p - name;
128
129                 /* if we are given a container name check it
130                  * against what we found, if it doesnt match exit out */
131                 if (container && (memcmp(container, name, len))) {
132                         printf("WARNING: container names didn't match %s %s\n",
133                                 container, name);
134                         return ;
135                 }
136
137                 memcpy(&buf, name, len);
138                 len += sprintf(&buf[len], "@%llx", addr);
139                 fdt_set_name(blob, off, buf);
140                 return ;
141         }
142
143         printf("ERROR: %s isn't in a container.  Not supported\n", compat);
144 }
145
146 static int fdt_qportal(void *blob, int off, int id, char *name,
147                        enum fsl_dpaa_dev dev, int create)
148 {
149         int childoff, dev_off, ret = 0;
150         uint32_t dev_handle;
151 #ifdef CONFIG_FSL_CORENET
152         int num;
153         u32 liodns[2];
154 #endif
155
156         childoff = fdt_subnode_offset(blob, off, name);
157         if (create) {
158                 char handle[64], *p;
159
160                 strncpy(handle, name, sizeof(handle));
161                 p = strchr(handle, '@');
162                 if (!strncmp(name, "fman", 4)) {
163                         *p = *(p + 1);
164                         p++;
165                 }
166                 *p = '\0';
167
168                 dev_off = fdt_path_offset(blob, handle);
169                 /* skip this node if alias is not found */
170                 if (dev_off == -FDT_ERR_BADPATH)
171                         return 0;
172                 if (dev_off < 0)
173                         return dev_off;
174
175                 if (childoff <= 0)
176                         childoff = fdt_add_subnode(blob, off, name);
177
178                 /* need to update the dev_off after adding a subnode */
179                 dev_off = fdt_path_offset(blob, handle);
180                 if (dev_off < 0)
181                         return dev_off;
182
183                 if (childoff > 0) {
184                         dev_handle = fdt_get_phandle(blob, dev_off);
185                         if (dev_handle <= 0) {
186                                 dev_handle = fdt_alloc_phandle(blob);
187                                 ret = fdt_set_phandle(blob, dev_off,
188                                                          dev_handle);
189                                 if (ret < 0)
190                                         return ret;
191                         }
192
193                         ret = fdt_setprop(blob, childoff, "dev-handle",
194                                           &dev_handle, sizeof(dev_handle));
195                         if (ret < 0)
196                                 return ret;
197
198 #ifdef CONFIG_FSL_CORENET
199                         num = get_dpaa_liodn(dev, &liodns[0], id);
200                         ret = fdt_setprop(blob, childoff, "fsl,liodn",
201                                           &liodns[0], sizeof(u32) * num);
202                         if (!strncmp(name, "pme", 3)) {
203                                 u32 pme_rev1, pme_rev2;
204                                 ccsr_pme_t *pme_regs =
205                                         (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
206
207                                 pme_rev1 = in_be32(&pme_regs->pm_ip_rev_1);
208                                 pme_rev2 = in_be32(&pme_regs->pm_ip_rev_2);
209                                 ret = fdt_setprop(blob, childoff,
210                                         "fsl,pme-rev1", &pme_rev1, sizeof(u32));
211                                 if (ret < 0)
212                                         return ret;
213                                 ret = fdt_setprop(blob, childoff,
214                                         "fsl,pme-rev2", &pme_rev2, sizeof(u32));
215                         }
216 #endif
217                 } else {
218                         return childoff;
219                 }
220         } else {
221                 if (childoff > 0)
222                         ret = fdt_del_node(blob, childoff);
223         }
224
225         return ret;
226 }
227
228 void fdt_fixup_qportals(void *blob)
229 {
230         int off, err;
231         unsigned int maj, min;
232         unsigned int ip_cfg;
233         ccsr_qman_t *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR;
234         u32 rev_1 = in_be32(&qman->ip_rev_1);
235         u32 rev_2 = in_be32(&qman->ip_rev_2);
236         char compat[64];
237         int compat_len;
238
239         maj = (rev_1 >> 8) & 0xff;
240         min = rev_1 & 0xff;
241         ip_cfg = rev_2 & 0xff;
242
243         compat_len = sprintf(compat, "fsl,qman-portal-%u.%u.%u",
244                                         maj, min, ip_cfg) + 1;
245         compat_len += sprintf(compat + compat_len, "fsl,qman-portal") + 1;
246
247         off = fdt_node_offset_by_compatible(blob, -1, "fsl,qman-portal");
248         while (off != -FDT_ERR_NOTFOUND) {
249 #ifdef CONFIG_FSL_CORENET
250                 u32 liodns[2];
251 #endif
252                 const int *ci = fdt_getprop(blob, off, "cell-index", NULL);
253                 int i = *ci;
254 #ifdef CONFIG_SYS_DPAA_FMAN
255                 int j;
256 #endif
257
258                 err = fdt_setprop(blob, off, "compatible", compat, compat_len);
259                 if (err < 0)
260                         goto err;
261
262 #ifdef CONFIG_FSL_CORENET
263                 liodns[0] = qp_info[i].dliodn;
264                 liodns[1] = qp_info[i].fliodn;
265
266                 err = fdt_setprop(blob, off, "fsl,liodn",
267                                   &liodns, sizeof(u32) * 2);
268                 if (err < 0)
269                         goto err;
270 #endif
271
272                 i++;
273
274                 err = fdt_qportal(blob, off, i, "crypto@0", FSL_HW_PORTAL_SEC,
275                                   IS_E_PROCESSOR(get_svr()));
276                 if (err < 0)
277                         goto err;
278
279 #ifdef CONFIG_FSL_CORENET
280 #ifdef CONFIG_SYS_DPAA_PME
281                 err = fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 1);
282                 if (err < 0)
283                         goto err;
284 #else
285                 fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 0);
286 #endif
287 #endif
288
289 #ifdef CONFIG_SYS_DPAA_FMAN
290                 for (j = 0; j < CONFIG_SYS_NUM_FMAN; j++) {
291                         char name[] = "fman@0";
292
293                         name[sizeof(name) - 2] = '0' + j;
294                         err = fdt_qportal(blob, off, i, name,
295                                           FSL_HW_PORTAL_FMAN1 + j, 1);
296                         if (err < 0)
297                                 goto err;
298                 }
299 #endif
300 #ifdef CONFIG_SYS_DPAA_RMAN
301                 err = fdt_qportal(blob, off, i, "rman@0",
302                                   FSL_HW_PORTAL_RMAN, 1);
303                 if (err < 0)
304                         goto err;
305 #endif
306
307 err:
308                 if (err < 0) {
309                         printf("ERROR: unable to create props for %s: %s\n",
310                                 fdt_get_name(blob, off, NULL), fdt_strerror(err));
311                         return;
312                 }
313
314                 off = fdt_node_offset_by_compatible(blob, off, "fsl,qman-portal");
315         }
316 }
317
318 void fdt_fixup_bportals(void *blob)
319 {
320         int off, err;
321         unsigned int maj, min;
322         unsigned int ip_cfg;
323         ccsr_bman_t *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR;
324         u32 rev_1 = in_be32(&bman->ip_rev_1);
325         u32 rev_2 = in_be32(&bman->ip_rev_2);
326         char compat[64];
327         int compat_len;
328
329         maj = (rev_1 >> 8) & 0xff;
330         min = rev_1 & 0xff;
331
332         ip_cfg = rev_2 & 0xff;
333
334         compat_len = sprintf(compat, "fsl,bman-portal-%u.%u.%u",
335                                  maj, min, ip_cfg) + 1;
336         compat_len += sprintf(compat + compat_len, "fsl,bman-portal") + 1;
337
338         off = fdt_node_offset_by_compatible(blob, -1, "fsl,bman-portal");
339         while (off != -FDT_ERR_NOTFOUND) {
340                 err = fdt_setprop(blob, off, "compatible", compat, compat_len);
341                 if (err < 0) {
342                         printf("ERROR: unable to create props for %s: %s\n",
343                                 fdt_get_name(blob, off, NULL),
344                                                  fdt_strerror(err));
345                         return;
346                 }
347
348                 off = fdt_node_offset_by_compatible(blob, off, "fsl,bman-portal");
349         }
350
351 }