~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/arch/powerpc/cpu/mpc85xx/liodn.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/immap_85xx.h>
 
12
#include <asm/io.h>
 
13
#include <asm/processor.h>
 
14
#include <asm/fsl_portals.h>
 
15
#include <asm/fsl_liodn.h>
 
16
 
 
17
int get_dpaa_liodn(enum fsl_dpaa_dev dpaa_dev, u32 *liodns, int liodn_offset)
 
18
{
 
19
        liodns[0] = liodn_bases[dpaa_dev].id[0] + liodn_offset;
 
20
 
 
21
        if (liodn_bases[dpaa_dev].num_ids == 2)
 
22
                liodns[1] = liodn_bases[dpaa_dev].id[1] + liodn_offset;
 
23
 
 
24
        return liodn_bases[dpaa_dev].num_ids;
 
25
}
 
26
 
 
27
#ifdef CONFIG_SYS_SRIO
 
28
static void set_srio_liodn(struct srio_liodn_id_table *tbl, int size)
 
29
{
 
30
        int i;
 
31
 
 
32
        for (i = 0; i < size; i++) {
 
33
                unsigned long reg_off = tbl[i].reg_offset[0];
 
34
                out_be32((u32 *)reg_off, tbl[i].id[0]);
 
35
 
 
36
                if (tbl[i].num_ids == 2) {
 
37
                        reg_off = tbl[i].reg_offset[1];
 
38
                        out_be32((u32 *)reg_off, tbl[i].id[1]);
 
39
                }
 
40
        }
 
41
}
 
42
#endif
 
43
 
 
44
static void set_liodn(struct liodn_id_table *tbl, int size)
 
45
{
 
46
        int i;
 
47
 
 
48
        for (i = 0; i < size; i++) {
 
49
                u32 liodn;
 
50
                if (tbl[i].num_ids == 2) {
 
51
                        liodn = (tbl[i].id[0] << 16) | tbl[i].id[1];
 
52
                } else {
 
53
                        liodn = tbl[i].id[0];
 
54
                }
 
55
 
 
56
                out_be32((volatile u32 *)(tbl[i].reg_offset), liodn);
 
57
        }
 
58
}
 
59
 
 
60
static void setup_sec_liodn_base(void)
 
61
{
 
62
        ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
 
63
        u32 base;
 
64
 
 
65
        if (!IS_E_PROCESSOR(get_svr()))
 
66
                return;
 
67
 
 
68
        /* QILCR[QSLOM] */
 
69
        out_be32(&sec->qilcr_ms, 0x3ff<<16);
 
70
 
 
71
        base = (liodn_bases[FSL_HW_PORTAL_SEC].id[0] << 16) |
 
72
                liodn_bases[FSL_HW_PORTAL_SEC].id[1];
 
73
 
 
74
        out_be32(&sec->qilcr_ls, base);
 
75
}
 
76
 
 
77
#ifdef CONFIG_SYS_DPAA_FMAN
 
78
static void setup_fman_liodn_base(enum fsl_dpaa_dev dev,
 
79
                                  struct liodn_id_table *tbl, int size)
 
80
{
 
81
        int i;
 
82
        ccsr_fman_t *fm;
 
83
        u32 base;
 
84
 
 
85
        switch(dev) {
 
86
        case FSL_HW_PORTAL_FMAN1:
 
87
                fm = (void *)CONFIG_SYS_FSL_FM1_ADDR;
 
88
                break;
 
89
 
 
90
#if (CONFIG_SYS_NUM_FMAN == 2)
 
91
        case FSL_HW_PORTAL_FMAN2:
 
92
                fm = (void *)CONFIG_SYS_FSL_FM2_ADDR;
 
93
                break;
 
94
#endif
 
95
        default:
 
96
                printf("Error: Invalid device type to %s\n", __FUNCTION__);
 
97
                return ;
 
98
        }
 
99
 
 
100
        base = (liodn_bases[dev].id[0] << 16) | liodn_bases[dev].id[0];
 
101
 
 
102
        /* setup all bases the same */
 
103
        for (i = 0; i < 32; i++) {
 
104
                out_be32(&fm->fm_dma.fmdmplr[i], base);
 
105
        }
 
106
 
 
107
        /* update tbl to ... */
 
108
        for (i = 0; i < size; i++)
 
109
                tbl[i].id[0] += liodn_bases[dev].id[0];
 
110
}
 
111
#endif
 
112
 
 
113
static void setup_pme_liodn_base(void)
 
114
{
 
115
#ifdef CONFIG_SYS_DPAA_PME
 
116
        ccsr_pme_t *pme = (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR;
 
117
        u32 base = (liodn_bases[FSL_HW_PORTAL_PME].id[0] << 16) |
 
118
                        liodn_bases[FSL_HW_PORTAL_PME].id[1];
 
119
 
 
120
        out_be32(&pme->liodnbr, base);
 
121
#endif
 
122
}
 
123
 
 
124
#ifdef CONFIG_SYS_FSL_RAID_ENGINE
 
125
static void setup_raide_liodn_base(void)
 
126
{
 
127
        struct ccsr_raide *raide = (void *)CONFIG_SYS_FSL_RAID_ENGINE_ADDR;
 
128
 
 
129
        /* setup raid engine liodn base for data/desc ; both set to 47 */
 
130
        u32 base = (liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0] << 16) |
 
131
                        liodn_bases[FSL_HW_PORTAL_RAID_ENGINE].id[0];
 
132
 
 
133
        out_be32(&raide->liodnbr, base);
 
134
}
 
135
#endif
 
136
 
 
137
#ifdef CONFIG_SYS_DPAA_RMAN
 
138
static void set_rman_liodn(struct liodn_id_table *tbl, int size)
 
139
{
 
140
        int i;
 
141
        struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
 
142
 
 
143
        for (i = 0; i < size; i++) {
 
144
                /* write the RMan block number */
 
145
                out_be32(&rman->mmitar, i);
 
146
                /* write the liodn offset corresponding to the block */
 
147
                out_be32((u32 *)(tbl[i].reg_offset), tbl[i].id[0]);
 
148
        }
 
149
}
 
150
 
 
151
static void setup_rman_liodn_base(struct liodn_id_table *tbl, int size)
 
152
{
 
153
        int i;
 
154
        struct ccsr_rman *rman = (void *)CONFIG_SYS_FSL_CORENET_RMAN_ADDR;
 
155
        u32 base = liodn_bases[FSL_HW_PORTAL_RMAN].id[0];
 
156
 
 
157
        out_be32(&rman->mmliodnbr, base);
 
158
 
 
159
        /* update liodn offset */
 
160
        for (i = 0; i < size; i++)
 
161
                tbl[i].id[0] += base;
 
162
}
 
163
#endif
 
164
 
 
165
void set_liodns(void)
 
166
{
 
167
        /* setup general liodn offsets */
 
168
        set_liodn(liodn_tbl, liodn_tbl_sz);
 
169
 
 
170
#ifdef CONFIG_SYS_SRIO
 
171
        /* setup SRIO port liodns */
 
172
        set_srio_liodn(srio_liodn_tbl, srio_liodn_tbl_sz);
 
173
#endif
 
174
 
 
175
        /* setup SEC block liodn bases & offsets if we have one */
 
176
        if (IS_E_PROCESSOR(get_svr())) {
 
177
                set_liodn(sec_liodn_tbl, sec_liodn_tbl_sz);
 
178
                setup_sec_liodn_base();
 
179
        }
 
180
 
 
181
        /* setup FMAN block(s) liodn bases & offsets if we have one */
 
182
#ifdef CONFIG_SYS_DPAA_FMAN
 
183
        set_liodn(fman1_liodn_tbl, fman1_liodn_tbl_sz);
 
184
        setup_fman_liodn_base(FSL_HW_PORTAL_FMAN1, fman1_liodn_tbl,
 
185
                                fman1_liodn_tbl_sz);
 
186
 
 
187
#if (CONFIG_SYS_NUM_FMAN == 2)
 
188
        set_liodn(fman2_liodn_tbl, fman2_liodn_tbl_sz);
 
189
        setup_fman_liodn_base(FSL_HW_PORTAL_FMAN2, fman2_liodn_tbl,
 
190
                                fman2_liodn_tbl_sz);
 
191
#endif
 
192
#endif
 
193
        /* setup PME liodn base */
 
194
        setup_pme_liodn_base();
 
195
 
 
196
#ifdef CONFIG_SYS_FSL_RAID_ENGINE
 
197
        /* raid engine ccr addr code for liodn */
 
198
        set_liodn(raide_liodn_tbl, raide_liodn_tbl_sz);
 
199
        setup_raide_liodn_base();
 
200
#endif
 
201
 
 
202
#ifdef CONFIG_SYS_DPAA_RMAN
 
203
        /* setup RMan liodn offsets */
 
204
        set_rman_liodn(rman_liodn_tbl, rman_liodn_tbl_sz);
 
205
        /* setup RMan liodn base */
 
206
        setup_rman_liodn_base(rman_liodn_tbl, rman_liodn_tbl_sz);
 
207
#endif
 
208
}
 
209
 
 
210
#ifdef CONFIG_SYS_SRIO
 
211
static void fdt_fixup_srio_liodn(void *blob, struct srio_liodn_id_table *tbl)
 
212
{
 
213
        int i, srio_off;
 
214
 
 
215
        /* search for srio node, if doesn't exist just return - nothing todo */
 
216
        srio_off = fdt_node_offset_by_compatible(blob, -1, "fsl,srio");
 
217
        if (srio_off < 0)
 
218
                return ;
 
219
 
 
220
        for (i = 0; i < srio_liodn_tbl_sz; i++) {
 
221
                int off, portid = tbl[i].portid;
 
222
 
 
223
                off = fdt_node_offset_by_prop_value(blob, srio_off,
 
224
                         "cell-index", &portid, 4);
 
225
                if (off >= 0) {
 
226
                        off = fdt_setprop(blob, off, "fsl,liodn",
 
227
                                &tbl[i].id[0],
 
228
                                sizeof(u32) * tbl[i].num_ids);
 
229
                        if (off > 0)
 
230
                                printf("WARNING unable to set fsl,liodn for "
 
231
                                        "fsl,srio port %d: %s\n",
 
232
                                        portid, fdt_strerror(off));
 
233
                } else {
 
234
                        debug("WARNING: couldn't set fsl,liodn for srio: %s.\n",
 
235
                                fdt_strerror(off));
 
236
                }
 
237
        }
 
238
}
 
239
#endif
 
240
 
 
241
#define CONFIG_SYS_MAX_PCI_EPS          8
 
242
 
 
243
static void fdt_fixup_pci_liodn_offsets(void *fdt, const char *compat,
 
244
                                        int ep_liodn_start)
 
245
{
 
246
        int off, pci_idx = 0, pci_cnt = 0, i, rc;
 
247
        const uint32_t *base_liodn;
 
248
        uint32_t liodn_offs[CONFIG_SYS_MAX_PCI_EPS + 1] = { 0 };
 
249
 
 
250
        /*
 
251
         * Count the number of pci nodes.
 
252
         * It's needed later when the interleaved liodn offsets are generated.
 
253
         */
 
254
        off = fdt_node_offset_by_compatible(fdt, -1, compat);
 
255
        while (off != -FDT_ERR_NOTFOUND) {
 
256
                pci_cnt++;
 
257
                off = fdt_node_offset_by_compatible(fdt, off, compat);
 
258
        }
 
259
 
 
260
        for (off = fdt_node_offset_by_compatible(fdt, -1, compat);
 
261
             off != -FDT_ERR_NOTFOUND;
 
262
             off = fdt_node_offset_by_compatible(fdt, off, compat)) {
 
263
                base_liodn = fdt_getprop(fdt, off, "fsl,liodn", &rc);
 
264
                if (!base_liodn) {
 
265
                        char path[64];
 
266
 
 
267
                        if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
 
268
                                strcpy(path, "(unknown)");
 
269
                        printf("WARNING Could not get liodn of node %s: %s\n",
 
270
                               path, fdt_strerror(rc));
 
271
                        continue;
 
272
                }
 
273
                for (i = 0; i < CONFIG_SYS_MAX_PCI_EPS; i++)
 
274
                        liodn_offs[i + 1] = ep_liodn_start +
 
275
                                        i * pci_cnt + pci_idx - *base_liodn;
 
276
                rc = fdt_setprop(fdt, off, "fsl,liodn-offset-list",
 
277
                                 liodn_offs, sizeof(liodn_offs));
 
278
                if (rc) {
 
279
                        char path[64];
 
280
 
 
281
                        if (fdt_get_path(fdt, off, path, sizeof(path)) < 0)
 
282
                                strcpy(path, "(unknown)");
 
283
                        printf("WARNING Unable to set fsl,liodn-offset-list for "
 
284
                               "node %s: %s\n", path, fdt_strerror(rc));
 
285
                        continue;
 
286
                }
 
287
                pci_idx++;
 
288
        }
 
289
}
 
290
 
 
291
static void fdt_fixup_liodn_tbl(void *blob, struct liodn_id_table *tbl, int sz)
 
292
{
 
293
        int i;
 
294
 
 
295
        for (i = 0; i < sz; i++) {
 
296
                int off;
 
297
 
 
298
                if (tbl[i].compat == NULL)
 
299
                        continue;
 
300
 
 
301
                off = fdt_node_offset_by_compat_reg(blob,
 
302
                                tbl[i].compat, tbl[i].compat_offset);
 
303
                if (off >= 0) {
 
304
                        off = fdt_setprop(blob, off, "fsl,liodn",
 
305
                                &tbl[i].id[0],
 
306
                                sizeof(u32) * tbl[i].num_ids);
 
307
                        if (off > 0)
 
308
                                printf("WARNING unable to set fsl,liodn for "
 
309
                                        "%s: %s\n",
 
310
                                        tbl[i].compat, fdt_strerror(off));
 
311
                } else {
 
312
                        debug("WARNING: could not set fsl,liodn for %s: %s.\n",
 
313
                                        tbl[i].compat, fdt_strerror(off));
 
314
                }
 
315
        }
 
316
}
 
317
 
 
318
void fdt_fixup_liodn(void *blob)
 
319
{
 
320
#ifdef CONFIG_SYS_SRIO
 
321
        fdt_fixup_srio_liodn(blob, srio_liodn_tbl);
 
322
#endif
 
323
 
 
324
        fdt_fixup_liodn_tbl(blob, liodn_tbl, liodn_tbl_sz);
 
325
#ifdef CONFIG_SYS_DPAA_FMAN
 
326
        fdt_fixup_liodn_tbl(blob, fman1_liodn_tbl, fman1_liodn_tbl_sz);
 
327
#if (CONFIG_SYS_NUM_FMAN == 2)
 
328
        fdt_fixup_liodn_tbl(blob, fman2_liodn_tbl, fman2_liodn_tbl_sz);
 
329
#endif
 
330
#endif
 
331
        fdt_fixup_liodn_tbl(blob, sec_liodn_tbl, sec_liodn_tbl_sz);
 
332
 
 
333
#ifdef CONFIG_SYS_FSL_RAID_ENGINE
 
334
        fdt_fixup_liodn_tbl(blob, raide_liodn_tbl, raide_liodn_tbl_sz);
 
335
#endif
 
336
 
 
337
#ifdef CONFIG_SYS_DPAA_RMAN
 
338
        fdt_fixup_liodn_tbl(blob, rman_liodn_tbl, rman_liodn_tbl_sz);
 
339
#endif
 
340
 
 
341
        ccsr_pcix_t *pcix = (ccsr_pcix_t *)CONFIG_SYS_PCIE1_ADDR;
 
342
        int pci_ver = pcix->ipver1 & 0xffff, liodn_base = 0;
 
343
 
 
344
        if (pci_ver >= 0x0204) {
 
345
                if (pci_ver >= 0x0300)
 
346
                        liodn_base = 1024;
 
347
                else
 
348
                        liodn_base = 256;
 
349
        }
 
350
 
 
351
        if (liodn_base) {
 
352
                char compat[32];
 
353
 
 
354
                sprintf(compat, "fsl,qoriq-pcie-v%d.%d",
 
355
                        (pci_ver & 0xff00) >> 8, pci_ver & 0xff);
 
356
                fdt_fixup_pci_liodn_offsets(blob, compat, liodn_base);
 
357
                fdt_fixup_pci_liodn_offsets(blob, "fsl,qoriq-pcie", liodn_base);
 
358
        }
 
359
}