source: rtems-libbsd/linux/drivers/soc/fsl/qbman/qman_portal.c @ 28ee86a

55-freebsd-126-freebsd-12
Last change on this file since 28ee86a was 28ee86a, checked in by Sebastian Huber <sebastian.huber@…>, on 04/27/16 at 09:58:19

Import DPAA driver snapshot

Imported from Freescale Linux repository

git://git.freescale.com/ppc/upstream/linux.git

commit 2774c204cd8bfc56a200ff4dcdfc9cdf5b6fc161.

Linux compatibility layer is partly from FreeBSD.

  • Property mode set to 100644
File size: 22.6 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3#include <rtems/bsd/local/opt_dpaa.h>
4
5/* Copyright 2008 - 2015 Freescale Semiconductor, Inc.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *     * Redistributions of source code must retain the above copyright
10 *       notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above copyright
12 *       notice, this list of conditions and the following disclaimer in the
13 *       documentation and/or other materials provided with the distribution.
14 *     * Neither the name of Freescale Semiconductor nor the
15 *       names of its contributors may be used to endorse or promote products
16 *       derived from this software without specific prior written permission.
17 *
18 * ALTERNATIVELY, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") as published by the Free Software
20 * Foundation, either version 2 of that License or (at your option) any
21 * later version.
22 *
23 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include "qman_priv.h"
36#ifdef __rtems__
37#include <bsp/qoriq.h>
38#endif /* __rtems__ */
39
40/* Enable portal interupts (as opposed to polling mode) */
41#define CONFIG_FSL_DPA_PIRQ_SLOW  1
42#define CONFIG_FSL_DPA_PIRQ_FAST  1
43
44/* Global variable containing revision id (even on non-control plane systems
45 * where CCSR isn't available) */
46u16 qman_ip_rev;
47EXPORT_SYMBOL(qman_ip_rev);
48u16 qm_channel_pool1 = QMAN_CHANNEL_POOL1;
49EXPORT_SYMBOL(qm_channel_pool1);
50u16 qm_channel_caam = QMAN_CHANNEL_CAAM;
51EXPORT_SYMBOL(qm_channel_caam);
52u16 qm_channel_pme = QMAN_CHANNEL_PME;
53EXPORT_SYMBOL(qm_channel_pme);
54u16 qm_channel_dce = QMAN_CHANNEL_DCE;
55EXPORT_SYMBOL(qm_channel_dce);
56u16 qman_portal_max;
57EXPORT_SYMBOL(qman_portal_max);
58
59#ifndef __rtems__
60/* For these variables, and the portal-initialisation logic, the
61 * comments in bman_driver.c apply here so won't be repeated. */
62static struct qman_portal *shared_portals[NR_CPUS];
63static int num_shared_portals;
64static int shared_portals_idx;
65static LIST_HEAD(unused_pcfgs);
66#endif /* __rtems__ */
67
68/* A SDQCR mask comprising all the available/visible pool channels */
69static u32 pools_sdqcr;
70
71#define STR_ERR_NOPROP      "No '%s' property in node %s\n"
72#define STR_ERR_CELL        "'%s' is not a %d-cell range in node %s\n"
73#define STR_FQID_RANGE      "fsl,fqid-range"
74#define STR_POOL_CHAN_RANGE "fsl,pool-channel-range"
75#define STR_CGRID_RANGE      "fsl,cgrid-range"
76
77/* A "fsl,fqid-range" node; release the given range to the allocator */
78static __init int fsl_fqid_range_init(struct device_node *node)
79{
80        int ret;
81        const u32 *range = of_get_property(node, STR_FQID_RANGE, &ret);
82
83        if (!range) {
84                pr_err(STR_ERR_NOPROP, STR_FQID_RANGE, node->full_name);
85                return -EINVAL;
86        }
87        if (ret != 8) {
88                pr_err(STR_ERR_CELL, STR_FQID_RANGE, 2, node->full_name);
89                return -EINVAL;
90        }
91        qman_seed_fqid_range(range[0], range[1]);
92        pr_info("FQID allocator includes range %d:%d\n",
93                range[0], range[1]);
94        return 0;
95}
96
97/* A "fsl,pool-channel-range" node; add to the SDQCR mask only */
98static __init int fsl_pool_channel_range_sdqcr(struct device_node *node)
99{
100        int ret;
101        const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret);
102
103        if (!chanid) {
104                pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name);
105                return -EINVAL;
106        }
107        if (ret != 8) {
108                pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name);
109                return -EINVAL;
110        }
111        for (ret = 0; ret < chanid[1]; ret++)
112                pools_sdqcr |= QM_SDQCR_CHANNELS_POOL_CONV(chanid[0] + ret);
113        return 0;
114}
115
116/* A "fsl,pool-channel-range" node; release the given range to the allocator */
117static __init int fsl_pool_channel_range_init(struct device_node *node)
118{
119        int ret;
120        const u32 *chanid = of_get_property(node, STR_POOL_CHAN_RANGE, &ret);
121
122        if (!chanid) {
123                pr_err(STR_ERR_NOPROP, STR_POOL_CHAN_RANGE, node->full_name);
124                return -EINVAL;
125        }
126        if (ret != 8) {
127                pr_err(STR_ERR_CELL, STR_POOL_CHAN_RANGE, 1, node->full_name);
128                return -EINVAL;
129        }
130        qman_seed_pool_range(chanid[0], chanid[1]);
131        pr_info("Pool channel allocator includes range %d:%d\n",
132                chanid[0], chanid[1]);
133        return 0;
134}
135
136/* A "fsl,cgrid-range" node; release the given range to the allocator */
137static __init int fsl_cgrid_range_init(struct device_node *node)
138{
139        struct qman_cgr cgr;
140        int ret, errors = 0;
141        const u32 *range = of_get_property(node, STR_CGRID_RANGE, &ret);
142
143        if (!range) {
144                pr_err(STR_ERR_NOPROP, STR_CGRID_RANGE, node->full_name);
145                return -EINVAL;
146        }
147        if (ret != 8) {
148                pr_err(STR_ERR_CELL, STR_CGRID_RANGE, 2, node->full_name);
149                return -EINVAL;
150        }
151        qman_seed_cgrid_range(range[0], range[1]);
152        pr_info("CGRID allocator includes range %d:%d\n",
153                range[0], range[1]);
154        for (cgr.cgrid = 0; cgr.cgrid < __CGR_NUM; cgr.cgrid++) {
155                ret = qman_modify_cgr(&cgr, QMAN_CGR_FLAG_USE_INIT, NULL);
156                if (ret)
157                        errors++;
158        }
159        if (errors)
160                pr_err("Warning: %d error%s while initialising CGRs %d:%d\n",
161                        errors, (errors > 1) ? "s" : "", range[0], range[1]);
162        return 0;
163}
164
165static void qman_get_ip_revision(struct device_node *dn)
166{
167#ifdef __rtems__
168        struct device_node of_dns;
169#endif /* __rtems__ */
170        u16 ip_rev = 0;
171
172        for_each_compatible_node(dn, NULL, "fsl,qman-portal") {
173                if (!of_device_is_available(dn))
174                        continue;
175                if (of_device_is_compatible(dn, "fsl,qman-portal-1.0") ||
176                        of_device_is_compatible(dn, "fsl,qman-portal-1.0.0")) {
177                        pr_err("Rev1.0 on P4080 rev1 is not supported!\n");
178                        BUG_ON(1);
179                } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.1") ||
180                        of_device_is_compatible(dn, "fsl,qman-portal-1.1.0")) {
181                        ip_rev = QMAN_REV11;
182                        qman_portal_max = 10;
183                } else if (of_device_is_compatible(dn, "fsl,qman-portal-1.2") ||
184                        of_device_is_compatible(dn, "fsl,qman-portal-1.2.0")) {
185                        ip_rev = QMAN_REV12;
186                        qman_portal_max = 10;
187                } else if (of_device_is_compatible(dn, "fsl,qman-portal-2.0") ||
188                        of_device_is_compatible(dn, "fsl,qman-portal-2.0.0")) {
189                        ip_rev = QMAN_REV20;
190                        qman_portal_max = 3;
191                } else if (of_device_is_compatible(dn,
192                                                "fsl,qman-portal-3.0.0")) {
193                        ip_rev = QMAN_REV30;
194                        qman_portal_max = 50;
195                } else if (of_device_is_compatible(dn,
196                                                "fsl,qman-portal-3.0.1")) {
197                        ip_rev = QMAN_REV30;
198                        qman_portal_max = 25;
199                } else if (of_device_is_compatible(dn,
200                                                "fsl,qman-portal-3.1.0")) {
201                        ip_rev = QMAN_REV31;
202                        qman_portal_max = 50;
203                } else if (of_device_is_compatible(dn,
204                                                "fsl,qman-portal-3.1.1")) {
205                        ip_rev = QMAN_REV31;
206                        qman_portal_max = 25;
207                } else if (of_device_is_compatible(dn,
208                                                "fsl,qman-portal-3.1.2")) {
209                        ip_rev = QMAN_REV31;
210                        qman_portal_max = 18;
211                } else if (of_device_is_compatible(dn,
212                                                "fsl,qman-portal-3.1.3")) {
213                        ip_rev = QMAN_REV31;
214                        qman_portal_max = 10;
215                } else {
216                        pr_warn("Unknown version in portal node, default to rev1.1\n");
217                        ip_rev = QMAN_REV11;
218                        qman_portal_max = 10;
219                }
220
221                if (!qman_ip_rev) {
222                        if (ip_rev) {
223                                qman_ip_rev = ip_rev;
224                        } else {
225                                pr_warn("Unknown version, default to rev1.1\n");
226                                qman_ip_rev = QMAN_REV11;
227                        }
228                } else if (ip_rev && (qman_ip_rev != ip_rev))
229                        pr_warn("Revision = 0x%04x, but portal '%s' has 0x%04x\n",
230                                qman_ip_rev, dn->full_name, ip_rev);
231                if (qman_ip_rev == ip_rev)
232                        break;
233        }
234}
235
236#ifndef __rtems__
237/* Parse a portal node, perform generic mapping duties and return the config. It
238 * is not known at this stage for what purpose (or even if) the portal will be
239 * used. */
240static struct qm_portal_config * __init parse_pcfg(struct device_node *node)
241{
242        struct qm_portal_config *pcfg;
243        const u32 *channel;
244        int irq, ret;
245        struct resource res;
246
247        pcfg = kzalloc(sizeof(*pcfg), GFP_KERNEL);
248        if (!pcfg)
249                return NULL;
250
251        /*
252         * This is a *horrible hack*, but the IOMMU/PAMU driver needs a
253         * 'struct device' in order to get the PAMU stashing setup and the QMan
254         * portal [driver] won't function at all without ring stashing
255         *
256         * Making the QMan portal driver nice and proper is part of the
257         * upstreaming effort
258         */
259        pcfg->dev.bus = &platform_bus_type;
260        pcfg->dev.of_node = node;
261#ifdef CONFIG_IOMMU_API
262        pcfg->dev.archdata.iommu_domain = NULL;
263#endif
264
265        ret = of_address_to_resource(node, DPA_PORTAL_CE,
266                                &pcfg->addr_phys[DPA_PORTAL_CE]);
267        if (ret) {
268                pr_err("Can't get %s property 'reg::CE'\n", node->full_name);
269                goto err;
270        }
271        ret = of_address_to_resource(node, DPA_PORTAL_CI,
272                                &pcfg->addr_phys[DPA_PORTAL_CI]);
273        if (ret) {
274                pr_err("Can't get %s property 'reg::CI'\n", node->full_name);
275                goto err;
276        }
277
278        channel = of_get_property(node, "fsl,qman-channel-id", &ret);
279        if (!channel || (ret != 4)) {
280                pr_err("Can't get %s property 'fsl,qman-channel-id'\n",
281                       node->full_name);
282                goto err;
283        }
284        pcfg->public_cfg.channel = *channel;
285        pcfg->public_cfg.cpu = -1;
286        irq = irq_of_parse_and_map(node, 0);
287        if (irq == NO_IRQ) {
288                pr_err("Can't get %s property 'interrupts'\n", node->full_name);
289                goto err;
290        }
291        pcfg->public_cfg.irq = irq;
292#ifdef CONFIG_FSL_QMAN_CONFIG
293        /* We need the same LIODN offset for all portals */
294        qman_liodn_fixup(pcfg->public_cfg.channel);
295#endif
296
297        pcfg->addr_virt[DPA_PORTAL_CE] = ioremap_prot(
298                                pcfg->addr_phys[DPA_PORTAL_CE].start,
299                                resource_size(&pcfg->addr_phys[DPA_PORTAL_CE]),
300                                0);
301        pcfg->addr_virt[DPA_PORTAL_CI] = ioremap_prot(
302                                pcfg->addr_phys[DPA_PORTAL_CI].start,
303                                resource_size(&pcfg->addr_phys[DPA_PORTAL_CI]),
304                                _PAGE_GUARDED | _PAGE_NO_CACHE);
305
306        return pcfg;
307err:
308        kfree(pcfg);
309        return NULL;
310}
311
312static struct qm_portal_config *get_pcfg(struct list_head *list)
313{
314        struct qm_portal_config *pcfg;
315
316        if (list_empty(list))
317                return NULL;
318        pcfg = list_entry(list->prev, struct qm_portal_config, list);
319        list_del(&pcfg->list);
320        return pcfg;
321}
322#endif /* __rtems__ */
323
324static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
325{
326#ifdef CONFIG_FSL_PAMU
327        int ret;
328        int window_count = 1;
329        struct iommu_domain_geometry geom_attr;
330        struct pamu_stash_attribute stash_attr;
331
332        pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
333        if (!pcfg->iommu_domain) {
334                pr_err("%s(): iommu_domain_alloc() failed", __func__);
335                goto _no_iommu;
336        }
337        geom_attr.aperture_start = 0;
338        geom_attr.aperture_end =
339                ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1;
340        geom_attr.force_aperture = true;
341        ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY,
342                                    &geom_attr);
343        if (ret < 0) {
344                pr_err("%s(): iommu_domain_set_attr() = %d", __func__, ret);
345                goto _iommu_domain_free;
346        }
347        ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS,
348                                    &window_count);
349        if (ret < 0) {
350                pr_err("%s(): iommu_domain_set_attr() = %d", __func__, ret);
351                goto _iommu_domain_free;
352        }
353        stash_attr.cpu = cpu;
354        stash_attr.cache = PAMU_ATTR_CACHE_L1;
355        ret = iommu_domain_set_attr(pcfg->iommu_domain,
356                                    DOMAIN_ATTR_FSL_PAMU_STASH,
357                                    &stash_attr);
358        if (ret < 0) {
359                pr_err("%s(): iommu_domain_set_attr() = %d",
360                           __func__, ret);
361                goto _iommu_domain_free;
362        }
363        ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36,
364                                         IOMMU_READ | IOMMU_WRITE);
365        if (ret < 0) {
366                pr_err("%s(): iommu_domain_window_enable() = %d",
367                           __func__, ret);
368                goto _iommu_domain_free;
369        }
370        ret = iommu_attach_device(pcfg->iommu_domain, &pcfg->dev);
371        if (ret < 0) {
372                pr_err("%s(): iommu_device_attach() = %d",
373                           __func__, ret);
374                goto _iommu_domain_free;
375        }
376        ret = iommu_domain_set_attr(pcfg->iommu_domain,
377                                    DOMAIN_ATTR_FSL_PAMU_ENABLE,
378                                    &window_count);
379        if (ret < 0) {
380                pr_err("%s(): iommu_domain_set_attr() = %d",
381                           __func__, ret);
382                goto _iommu_detach_device;
383        }
384
385_no_iommu:
386#endif
387#ifdef CONFIG_FSL_QMAN_CONFIG
388        if (qman_set_sdest(pcfg->public_cfg.channel, cpu))
389#endif
390                pr_warn("Failed to set the stash request queue\n");
391
392        return;
393
394#ifdef CONFIG_FSL_PAMU
395_iommu_detach_device:
396        iommu_detach_device(pcfg->iommu_domain, NULL);
397_iommu_domain_free:
398        iommu_domain_free(pcfg->iommu_domain);
399        pcfg->iommu_domain = NULL;
400#endif
401}
402
403static struct qman_portal *init_pcfg(struct qm_portal_config *pcfg)
404{
405        struct qman_portal *p;
406
407#ifndef __rtems__
408        pcfg->iommu_domain = NULL;
409#endif /* __rtems__ */
410        portal_set_cpu(pcfg, pcfg->public_cfg.cpu);
411        p = qman_create_affine_portal(pcfg, NULL);
412        if (p) {
413                u32 irq_sources = 0;
414                /* Determine what should be interrupt-vs-poll driven */
415#ifdef CONFIG_FSL_DPA_PIRQ_SLOW
416                irq_sources |= QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI |
417                               QM_PIRQ_CSCI;
418#endif
419#ifdef CONFIG_FSL_DPA_PIRQ_FAST
420                irq_sources |= QM_PIRQ_DQRI;
421#endif
422                qman_p_irqsource_add(p, irq_sources);
423                pr_info("Portal %sinitialised, cpu %d\n",
424#ifndef __rtems__
425                        pcfg->public_cfg.is_shared ? "(shared) " : "",
426#else /* __rtems__ */
427                        "",
428#endif /* __rtems__ */
429                        pcfg->public_cfg.cpu);
430        } else
431                pr_crit("Portal failure on cpu %d\n", pcfg->public_cfg.cpu);
432        return p;
433}
434
435#ifndef __rtems__
436static void init_slave(int cpu)
437{
438        struct qman_portal *p;
439        struct cpumask oldmask = *tsk_cpus_allowed(current);
440
441        set_cpus_allowed_ptr(current, get_cpu_mask(cpu));
442        p = qman_create_affine_slave(shared_portals[shared_portals_idx++], cpu);
443        if (!p)
444                pr_err("Slave portal failure on cpu %d\n", cpu);
445        else
446                pr_info("Portal (slave) initialised, cpu %d\n", cpu);
447        set_cpus_allowed_ptr(current, &oldmask);
448        if (shared_portals_idx >= num_shared_portals)
449                shared_portals_idx = 0;
450}
451
452static struct cpumask want_unshared __initdata;
453static struct cpumask want_shared __initdata;
454
455static int __init parse_qportals(char *str)
456{
457        return parse_portals_bootarg(str, &want_shared, &want_unshared,
458                                     "qportals");
459}
460__setup("qportals=", parse_qportals);
461
462static void qman_portal_update_sdest(const struct qm_portal_config *pcfg,
463                                                        unsigned int cpu)
464{
465        struct pamu_stash_attribute stash_attr;
466        int ret;
467
468        if (pcfg->iommu_domain) {
469                stash_attr.cpu = cpu;
470                stash_attr.cache = PAMU_ATTR_CACHE_L1;
471                ret = iommu_domain_set_attr(pcfg->iommu_domain,
472                                DOMAIN_ATTR_FSL_PAMU_STASH, &stash_attr);
473                if (ret < 0) {
474                        pr_err("Failed to update pamu stash setting\n");
475                        return;
476                }
477        }
478#ifdef CONFIG_FSL_QMAN_CONFIG
479        if (qman_set_sdest(pcfg->public_cfg.channel, cpu))
480#endif
481                pr_warn("Failed to update portal's stash request queue\n");
482}
483
484static void qman_offline_cpu(unsigned int cpu)
485{
486        struct qman_portal *p;
487        const struct qm_portal_config *pcfg;
488
489        p = (struct qman_portal *)affine_portals[cpu];
490        if (p) {
491                pcfg = qman_get_qm_portal_config(p);
492                if (pcfg) {
493                        irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(0));
494                        qman_portal_update_sdest(pcfg, 0);
495                }
496        }
497}
498#endif /* __rtems__ */
499
500#ifdef CONFIG_HOTPLUG_CPU
501static void qman_online_cpu(unsigned int cpu)
502{
503        struct qman_portal *p;
504        const struct qm_portal_config *pcfg;
505
506        p = (struct qman_portal *)affine_portals[cpu];
507        if (p) {
508                pcfg = qman_get_qm_portal_config(p);
509                if (pcfg) {
510                        irq_set_affinity(pcfg->public_cfg.irq, cpumask_of(cpu));
511                        qman_portal_update_sdest(pcfg, cpu);
512                }
513        }
514}
515
516static int qman_hotplug_cpu_callback(struct notifier_block *nfb,
517                                     unsigned long action, void *hcpu)
518{
519        unsigned int cpu = (unsigned long)hcpu;
520
521        switch (action) {
522        case CPU_ONLINE:
523        case CPU_ONLINE_FROZEN:
524                qman_online_cpu(cpu);
525                break;
526        case CPU_DOWN_PREPARE:
527        case CPU_DOWN_PREPARE_FROZEN:
528                qman_offline_cpu(cpu);
529        default:
530                break;
531        }
532        return NOTIFY_OK;
533}
534
535static struct notifier_block qman_hotplug_cpu_notifier = {
536        .notifier_call = qman_hotplug_cpu_callback,
537};
538#endif /* CONFIG_HOTPLUG_CPU */
539
540#ifdef __rtems__
541#include <bsp/fdt.h>
542static struct qm_portal_config qman_configs[NR_CPUS];
543static void
544qman_init_portals(void)
545{
546        const char *fdt = bsp_fdt_get();
547        struct device_node dn;
548        const char *name;
549        int cpu_count = (int)rtems_get_processor_count();
550        int cpu;
551        int ret;
552        int node;
553        int parent;
554
555        memset(&dn, 0, sizeof(dn));
556
557        name = "fsl,qman-portal";
558        node = fdt_node_offset_by_compatible(fdt, 0, name);
559        if (node < 0)
560                panic("qman: no portals in FDT");
561        parent = fdt_parent_offset(fdt, node);
562        if (parent < 0)
563                panic("qman: no parent of portals in FDT");
564        node = fdt_first_subnode(fdt, parent);
565
566        dn.full_name = name;
567        dn.offset = node;
568
569        qoriq_clear_ce_portal(&qoriq_qman_portal[0][0],
570            sizeof(qoriq_qman_portal[0]));
571        qoriq_clear_ci_portal(&qoriq_qman_portal[1][0],
572            sizeof(qoriq_qman_portal[1]));
573
574        for (cpu = 0; cpu < cpu_count; ++cpu) {
575                struct qm_portal_config *pcfg = &qman_configs[cpu];
576                struct qman_portal *portal;
577                struct resource res;
578                const u32 *channel;
579
580                if (node < 0)
581                        panic("qman: missing portal in FDT");
582
583                ret = of_address_to_resource(&dn, 0, &res);
584                if (ret != 0)
585                        panic("qman: no portal CE address");
586                pcfg->addr_virt[0] = (__iomem void *)
587                    ((uintptr_t)&qoriq_qman_portal[0][0] + (uintptr_t)res.start);
588                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] >=
589                    (uintptr_t)&qoriq_qman_portal[0][0]);
590                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] <
591                    (uintptr_t)&qoriq_qman_portal[1][0]);
592
593                ret = of_address_to_resource(&dn, 1, &res);
594                if (ret != 0)
595                        panic("qman: no portal CI address");
596                pcfg->addr_virt[1] = (__iomem void *)
597                    ((uintptr_t)&qoriq_qman_portal[0][0] + (uintptr_t)res.start);
598                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] >=
599                    (uintptr_t)&qoriq_qman_portal[1][0]);
600                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] <
601                    (uintptr_t)&qoriq_qman_portal[2][0]);
602
603                pcfg->public_cfg.irq = of_irq_to_resource(&dn, 0, NULL);
604                if (pcfg->public_cfg.irq == NO_IRQ)
605                        panic("qman: no portal interrupt");
606
607                channel = of_get_property(&dn, "fsl,qman-channel-id", &ret);
608                if (channel == NULL || ret != 4)
609                        panic("qman: no portal channel ID");
610                pcfg->public_cfg.channel = *channel;
611
612                pcfg->public_cfg.cpu = cpu;
613                pcfg->public_cfg.pools = pools_sdqcr;
614
615                portal = init_pcfg(pcfg);
616                if (portal == NULL)
617                        panic("qman: cannot create portal");
618
619                node = fdt_next_subnode(fdt, node);
620                dn.offset = node;
621        }
622}
623#endif /* __rtems__ */
624#ifndef __rtems__
625__init int qman_init(void)
626{
627        struct cpumask slave_cpus;
628        struct cpumask unshared_cpus = *cpu_none_mask;
629        struct cpumask shared_cpus = *cpu_none_mask;
630        LIST_HEAD(unshared_pcfgs);
631        LIST_HEAD(shared_pcfgs);
632        struct device_node *dn;
633        struct qm_portal_config *pcfg;
634        struct qman_portal *p;
635        int cpu, ret;
636        struct cpumask offline_cpus;
637
638        /* Initialise the QMan (CCSR) device */
639        for_each_compatible_node(dn, NULL, "fsl,qman") {
640                if (!qman_init_ccsr(dn))
641                        pr_info("Err interrupt handler present\n");
642                else
643                        pr_err("CCSR setup failed\n");
644        }
645#else /* __rtems__ */
646int
647qman_init(struct device_node *dn)
648{
649        struct device_node of_dns;
650        int ret;
651#endif /* __rtems__ */
652#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
653        /* Setup lookup table for FQ demux */
654        ret = qman_setup_fq_lookup_table(qman_fqd_size()/64);
655        if (ret)
656                return ret;
657#endif
658
659        /* Get qman ip revision */
660        qman_get_ip_revision(dn);
661        if ((qman_ip_rev & 0xff00) >= QMAN_REV30) {
662                qm_channel_pool1 = QMAN_CHANNEL_POOL1_REV3;
663                qm_channel_caam = QMAN_CHANNEL_CAAM_REV3;
664                qm_channel_pme = QMAN_CHANNEL_PME_REV3;
665        }
666
667        /* Parse pool channels into the SDQCR mask. (Must happen before portals
668         * are initialised.) */
669        for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") {
670                ret = fsl_pool_channel_range_sdqcr(dn);
671                if (ret)
672                        return ret;
673        }
674
675#ifndef __rtems__
676        memset(affine_portals, 0, sizeof(void *) * num_possible_cpus());
677        /* Initialise portals. See bman_driver.c for comments */
678        for_each_compatible_node(dn, NULL, "fsl,qman-portal") {
679                if (!of_device_is_available(dn))
680                        continue;
681                pcfg = parse_pcfg(dn);
682                if (pcfg) {
683                        pcfg->public_cfg.pools = pools_sdqcr;
684                        list_add_tail(&pcfg->list, &unused_pcfgs);
685                }
686        }
687        for_each_possible_cpu(cpu) {
688                if (cpumask_test_cpu(cpu, &want_shared)) {
689                        pcfg = get_pcfg(&unused_pcfgs);
690                        if (!pcfg)
691                                break;
692                        pcfg->public_cfg.cpu = cpu;
693                        list_add_tail(&pcfg->list, &shared_pcfgs);
694                        cpumask_set_cpu(cpu, &shared_cpus);
695                }
696                if (cpumask_test_cpu(cpu, &want_unshared)) {
697                        if (cpumask_test_cpu(cpu, &shared_cpus))
698                                continue;
699                        pcfg = get_pcfg(&unused_pcfgs);
700                        if (!pcfg)
701                                break;
702                        pcfg->public_cfg.cpu = cpu;
703                        list_add_tail(&pcfg->list, &unshared_pcfgs);
704                        cpumask_set_cpu(cpu, &unshared_cpus);
705                }
706        }
707        if (list_empty(&shared_pcfgs) && list_empty(&unshared_pcfgs)) {
708                for_each_possible_cpu(cpu) {
709                        pcfg = get_pcfg(&unused_pcfgs);
710                        if (!pcfg)
711                                break;
712                        pcfg->public_cfg.cpu = cpu;
713                        list_add_tail(&pcfg->list, &unshared_pcfgs);
714                        cpumask_set_cpu(cpu, &unshared_cpus);
715                }
716        }
717        cpumask_andnot(&slave_cpus, cpu_possible_mask, &shared_cpus);
718        cpumask_andnot(&slave_cpus, &slave_cpus, &unshared_cpus);
719        if (cpumask_empty(&slave_cpus)) {
720                if (!list_empty(&shared_pcfgs)) {
721                        cpumask_or(&unshared_cpus, &unshared_cpus,
722                                   &shared_cpus);
723                        cpumask_clear(&shared_cpus);
724                        list_splice_tail(&shared_pcfgs, &unshared_pcfgs);
725                        INIT_LIST_HEAD(&shared_pcfgs);
726                }
727        } else {
728                if (list_empty(&shared_pcfgs)) {
729                        pcfg = get_pcfg(&unshared_pcfgs);
730                        if (!pcfg) {
731                                pr_crit("No portals available!\n");
732                                return 0;
733                        }
734                        cpumask_clear_cpu(pcfg->public_cfg.cpu, &unshared_cpus);
735                        cpumask_set_cpu(pcfg->public_cfg.cpu, &shared_cpus);
736                        list_add_tail(&pcfg->list, &shared_pcfgs);
737                }
738        }
739        list_for_each_entry(pcfg, &unshared_pcfgs, list) {
740                pcfg->public_cfg.is_shared = 0;
741                p = init_pcfg(pcfg);
742        }
743        list_for_each_entry(pcfg, &shared_pcfgs, list) {
744                pcfg->public_cfg.is_shared = 1;
745                p = init_pcfg(pcfg);
746                if (p)
747                        shared_portals[num_shared_portals++] = p;
748        }
749        if (!cpumask_empty(&slave_cpus))
750                for_each_cpu(cpu, &slave_cpus)
751                        init_slave(cpu);
752#else /* __rtems__ */
753        qman_init_portals();
754#endif /* __rtems__ */
755        pr_info("Portals initialised\n");
756#ifndef __rtems__
757        cpumask_andnot(&offline_cpus, cpu_possible_mask, cpu_online_mask);
758        for_each_cpu(cpu, &offline_cpus)
759                qman_offline_cpu(cpu);
760#endif /* __rtems__ */
761#ifdef CONFIG_HOTPLUG_CPU
762        register_hotcpu_notifier(&qman_hotplug_cpu_notifier);
763#endif
764        return 0;
765}
766
767__init int qman_resource_init(void)
768{
769#ifdef __rtems__
770        struct device_node of_dns;
771#endif /* __rtems__ */
772        struct device_node *dn;
773        int ret;
774
775        /* Initialise FQID allocation ranges */
776        for_each_compatible_node(dn, NULL, "fsl,fqid-range") {
777                ret = fsl_fqid_range_init(dn);
778                if (ret)
779                        return ret;
780        }
781        /* Initialise CGRID allocation ranges */
782        for_each_compatible_node(dn, NULL, "fsl,cgrid-range") {
783                ret = fsl_cgrid_range_init(dn);
784                if (ret)
785                        return ret;
786        }
787        /* Parse pool channels into the allocator. (Must happen after portals
788         * are initialised.) */
789        for_each_compatible_node(dn, NULL, "fsl,pool-channel-range") {
790                ret = fsl_pool_channel_range_init(dn);
791                if (ret)
792                        return ret;
793        }
794
795        return 0;
796}
Note: See TracBrowser for help on using the repository browser.