source: rtems-libbsd/linux/drivers/soc/fsl/qbman/qman_portal.c @ 721b1c1

55-freebsd-126-freebsd-12
Last change on this file since 721b1c1 was 721b1c1, checked in by Sebastian Huber <sebastian.huber@…>, on 05/17/17 at 07:25:39

qbman: Fix platform_get_irq() error checks

  • Property mode set to 100644
File size: 12.2 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3#include <rtems/bsd/local/opt_dpaa.h>
4
5/* Copyright 2008 - 2016 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#undef dev_crit
39#undef dev_info
40#define dev_crit(dev, fmt, ...) printf(fmt, ##__VA_ARGS__)
41#define dev_info dev_crit
42#endif /* __rtems__ */
43
44#ifndef __rtems__
45struct qman_portal *qman_dma_portal;
46EXPORT_SYMBOL(qman_dma_portal);
47#endif /* __rtems__ */
48
49/* Enable portal interupts (as opposed to polling mode) */
50#define CONFIG_FSL_DPA_PIRQ_SLOW  1
51#define CONFIG_FSL_DPA_PIRQ_FAST  1
52
53#ifndef __rtems__
54static struct cpumask portal_cpus;
55/* protect qman global registers and global data shared among portals */
56static DEFINE_SPINLOCK(qman_lock);
57#endif /* __rtems__ */
58
59static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
60{
61#ifdef CONFIG_FSL_PAMU
62        struct device *dev = pcfg->dev;
63        int window_count = 1;
64        struct iommu_domain_geometry geom_attr;
65        struct pamu_stash_attribute stash_attr;
66        int ret;
67
68        pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
69        if (!pcfg->iommu_domain) {
70                dev_err(dev, "%s(): iommu_domain_alloc() failed", __func__);
71                goto no_iommu;
72        }
73        geom_attr.aperture_start = 0;
74        geom_attr.aperture_end =
75                ((dma_addr_t)1 << min(8 * sizeof(dma_addr_t), (size_t)36)) - 1;
76        geom_attr.force_aperture = true;
77        ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_GEOMETRY,
78                                    &geom_attr);
79        if (ret < 0) {
80                dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__,
81                        ret);
82                goto out_domain_free;
83        }
84        ret = iommu_domain_set_attr(pcfg->iommu_domain, DOMAIN_ATTR_WINDOWS,
85                                    &window_count);
86        if (ret < 0) {
87                dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__,
88                        ret);
89                goto out_domain_free;
90        }
91        stash_attr.cpu = cpu;
92        stash_attr.cache = PAMU_ATTR_CACHE_L1;
93        ret = iommu_domain_set_attr(pcfg->iommu_domain,
94                                    DOMAIN_ATTR_FSL_PAMU_STASH,
95                                    &stash_attr);
96        if (ret < 0) {
97                dev_err(dev, "%s(): iommu_domain_set_attr() = %d",
98                        __func__, ret);
99                goto out_domain_free;
100        }
101        ret = iommu_domain_window_enable(pcfg->iommu_domain, 0, 0, 1ULL << 36,
102                                         IOMMU_READ | IOMMU_WRITE);
103        if (ret < 0) {
104                dev_err(dev, "%s(): iommu_domain_window_enable() = %d",
105                        __func__, ret);
106                goto out_domain_free;
107        }
108        ret = iommu_attach_device(pcfg->iommu_domain, dev);
109        if (ret < 0) {
110                dev_err(dev, "%s(): iommu_device_attach() = %d", __func__,
111                        ret);
112                goto out_domain_free;
113        }
114        ret = iommu_domain_set_attr(pcfg->iommu_domain,
115                                    DOMAIN_ATTR_FSL_PAMU_ENABLE,
116                                    &window_count);
117        if (ret < 0) {
118                dev_err(dev, "%s(): iommu_domain_set_attr() = %d", __func__,
119                        ret);
120                goto out_detach_device;
121        }
122
123no_iommu:
124#endif
125        qman_set_sdest(pcfg->channel, cpu);
126
127        return;
128
129#ifdef CONFIG_FSL_PAMU
130out_detach_device:
131        iommu_detach_device(pcfg->iommu_domain, NULL);
132out_domain_free:
133        iommu_domain_free(pcfg->iommu_domain);
134        pcfg->iommu_domain = NULL;
135#endif
136}
137
138static struct qman_portal *init_pcfg(struct qm_portal_config *pcfg)
139{
140        struct qman_portal *p;
141        u32 irq_sources = 0;
142
143        /* We need the same LIODN offset for all portals */
144        qman_liodn_fixup(pcfg->channel);
145
146#ifndef __rtems__
147        pcfg->iommu_domain = NULL;
148#endif /* __rtems__ */
149        portal_set_cpu(pcfg, pcfg->cpu);
150        p = qman_create_affine_portal(pcfg, NULL);
151        if (!p) {
152                dev_crit(pcfg->dev, "%s: Portal failure on cpu %d\n",
153                         __func__, pcfg->cpu);
154                return NULL;
155        }
156
157        /* Determine what should be interrupt-vs-poll driven */
158#ifdef CONFIG_FSL_DPA_PIRQ_SLOW
159        irq_sources |= QM_PIRQ_EQCI | QM_PIRQ_EQRI | QM_PIRQ_MRI |
160                       QM_PIRQ_CSCI;
161#endif
162#ifdef CONFIG_FSL_DPA_PIRQ_FAST
163        irq_sources |= QM_PIRQ_DQRI;
164#endif
165        qman_p_irqsource_add(p, irq_sources);
166
167#ifndef __rtems__
168        spin_lock(&qman_lock);
169        if (cpumask_equal(&portal_cpus, cpu_possible_mask)) {
170                /* all assigned portals are initialized now */
171                qman_init_cgr_all();
172        }
173
174        if (!qman_dma_portal)
175                qman_dma_portal = p;
176
177        spin_unlock(&qman_lock);
178#endif /* __rtems__ */
179
180        dev_info(pcfg->dev, "Portal initialised, cpu %d\n", pcfg->cpu);
181
182        return p;
183}
184
185static void qman_portal_update_sdest(const struct qm_portal_config *pcfg,
186                                                        unsigned int cpu)
187{
188#ifdef CONFIG_FSL_PAMU /* TODO */
189        struct pamu_stash_attribute stash_attr;
190        int ret;
191
192        if (pcfg->iommu_domain) {
193                stash_attr.cpu = cpu;
194                stash_attr.cache = PAMU_ATTR_CACHE_L1;
195                ret = iommu_domain_set_attr(pcfg->iommu_domain,
196                                DOMAIN_ATTR_FSL_PAMU_STASH, &stash_attr);
197                if (ret < 0) {
198                        dev_err(pcfg->dev,
199                                "Failed to update pamu stash setting\n");
200                        return;
201                }
202        }
203#endif
204        qman_set_sdest(pcfg->channel, cpu);
205}
206
207#ifndef __rtems__
208static int qman_offline_cpu(unsigned int cpu)
209{
210        struct qman_portal *p;
211        const struct qm_portal_config *pcfg;
212
213        p = affine_portals[cpu];
214        if (p) {
215                pcfg = qman_get_qm_portal_config(p);
216                if (pcfg) {
217                        irq_set_affinity(pcfg->irq, cpumask_of(0));
218                        qman_portal_update_sdest(pcfg, 0);
219                }
220        }
221        return 0;
222}
223
224static int qman_online_cpu(unsigned int cpu)
225{
226        struct qman_portal *p;
227        const struct qm_portal_config *pcfg;
228
229        p = affine_portals[cpu];
230        if (p) {
231                pcfg = qman_get_qm_portal_config(p);
232                if (pcfg) {
233                        irq_set_affinity(pcfg->irq, cpumask_of(cpu));
234                        qman_portal_update_sdest(pcfg, cpu);
235                }
236        }
237        return 0;
238}
239
240static int qman_portal_probe(struct platform_device *pdev)
241{
242        struct device *dev = &pdev->dev;
243        struct device_node *node = dev->of_node;
244        struct qm_portal_config *pcfg;
245        struct resource *addr_phys[2];
246        void __iomem *va;
247        int irq, cpu, err;
248        u32 val;
249
250        pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
251        if (!pcfg)
252                return -ENOMEM;
253
254        pcfg->dev = dev;
255
256        addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
257                                             DPAA_PORTAL_CE);
258        if (!addr_phys[0]) {
259                dev_err(dev, "Can't get %s property 'reg::CE'\n",
260                        node->full_name);
261                return -ENXIO;
262        }
263
264        addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
265                                             DPAA_PORTAL_CI);
266        if (!addr_phys[1]) {
267                dev_err(dev, "Can't get %s property 'reg::CI'\n",
268                        node->full_name);
269                return -ENXIO;
270        }
271
272        err = of_property_read_u32(node, "cell-index", &val);
273        if (err) {
274                dev_err(dev, "Can't get %s property 'cell-index'\n",
275                        node->full_name);
276                return err;
277        }
278        pcfg->channel = val;
279        pcfg->cpu = -1;
280        irq = platform_get_irq(pdev, 0);
281        if (irq < 0) {
282                dev_err(dev, "Can't get %s IRQ\n", node->full_name);
283                return -ENXIO;
284        }
285        pcfg->irq = irq;
286
287        va = ioremap_prot(addr_phys[0]->start, resource_size(addr_phys[0]), 0);
288        if (!va) {
289                dev_err(dev, "ioremap::CE failed\n");
290                goto err_ioremap1;
291        }
292
293        pcfg->addr_virt[DPAA_PORTAL_CE] = va;
294
295        va = ioremap_prot(addr_phys[1]->start, resource_size(addr_phys[1]),
296                          _PAGE_GUARDED | _PAGE_NO_CACHE);
297        if (!va) {
298                dev_err(dev, "ioremap::CI failed\n");
299                goto err_ioremap2;
300        }
301
302        pcfg->addr_virt[DPAA_PORTAL_CI] = va;
303
304        pcfg->pools = qm_get_pools_sdqcr();
305
306        spin_lock(&qman_lock);
307        cpu = cpumask_next_zero(-1, &portal_cpus);
308        if (cpu >= nr_cpu_ids) {
309                /* unassigned portal, skip init */
310                spin_unlock(&qman_lock);
311                return 0;
312        }
313
314        cpumask_set_cpu(cpu, &portal_cpus);
315        spin_unlock(&qman_lock);
316        pcfg->cpu = cpu;
317
318        if (dma_set_mask(dev, DMA_BIT_MASK(40))) {
319                dev_err(dev, "dma_set_mask() failed\n");
320                goto err_portal_init;
321        }
322
323        if (!init_pcfg(pcfg)) {
324                dev_err(dev, "portal init failed\n");
325                goto err_portal_init;
326        }
327
328        /* clear irq affinity if assigned cpu is offline */
329        if (!cpu_online(cpu))
330                qman_offline_cpu(cpu);
331
332        return 0;
333
334err_portal_init:
335        iounmap(pcfg->addr_virt[DPAA_PORTAL_CI]);
336err_ioremap2:
337        iounmap(pcfg->addr_virt[DPAA_PORTAL_CE]);
338err_ioremap1:
339        return -ENXIO;
340}
341
342static const struct of_device_id qman_portal_ids[] = {
343        {
344                .compatible = "fsl,qman-portal",
345        },
346        {}
347};
348MODULE_DEVICE_TABLE(of, qman_portal_ids);
349
350static struct platform_driver qman_portal_driver = {
351        .driver = {
352                .name = KBUILD_MODNAME,
353                .of_match_table = qman_portal_ids,
354        },
355        .probe = qman_portal_probe,
356};
357
358static int __init qman_portal_driver_register(struct platform_driver *drv)
359{
360        int ret;
361
362        ret = platform_driver_register(drv);
363        if (ret < 0)
364                return ret;
365
366        ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
367                                        "soc/qman_portal:online",
368                                        qman_online_cpu, qman_offline_cpu);
369        if (ret < 0) {
370                pr_err("qman: failed to register hotplug callbacks.\n");
371                platform_driver_unregister(drv);
372                return ret;
373        }
374        return 0;
375}
376
377module_driver(qman_portal_driver,
378              qman_portal_driver_register, platform_driver_unregister);
379#else /* __rtems__ */
380#include <bsp/fdt.h>
381#include <linux/of_address.h>
382#include <linux/of_irq.h>
383
384static struct qm_portal_config qman_configs[NR_CPUS];
385
386void
387qman_sysinit_portals(void)
388{
389        const char *fdt = bsp_fdt_get();
390        struct device_node dn;
391        const char *name;
392        int cpu_count = (int)rtems_get_processor_count();
393        int cpu;
394        int ret;
395        int node;
396        int parent;
397
398        memset(&dn, 0, sizeof(dn));
399
400        name = "fsl,qman-portal";
401        node = fdt_node_offset_by_compatible(fdt, 0, name);
402        if (node < 0)
403                panic("qman: no portals in FDT");
404        parent = fdt_parent_offset(fdt, node);
405        if (parent < 0)
406                panic("qman: no parent of portals in FDT");
407        node = fdt_first_subnode(fdt, parent);
408
409        dn.full_name = name;
410        dn.offset = node;
411
412        qoriq_clear_ce_portal(&qoriq_qman_portal[0][0],
413            sizeof(qoriq_qman_portal[0]));
414        qoriq_clear_ci_portal(&qoriq_qman_portal[1][0],
415            sizeof(qoriq_qman_portal[1]));
416
417        for (cpu = 0; cpu < cpu_count; ++cpu) {
418                struct qm_portal_config *pcfg = &qman_configs[cpu];
419                struct qman_portal *portal;
420                struct resource res;
421                u32 val;
422
423                if (node < 0)
424                        panic("qman: missing portal in FDT");
425
426                ret = of_address_to_resource(&dn, 0, &res);
427                if (ret != 0)
428                        panic("qman: no portal CE address");
429                pcfg->addr_virt[0] = (__iomem void *)
430                    ((uintptr_t)&qoriq_qman_portal[0][0] + (uintptr_t)res.start);
431                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] >=
432                    (uintptr_t)&qoriq_qman_portal[0][0]);
433                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] <
434                    (uintptr_t)&qoriq_qman_portal[1][0]);
435
436                ret = of_address_to_resource(&dn, 1, &res);
437                if (ret != 0)
438                        panic("qman: no portal CI address");
439                pcfg->addr_virt[1] = (__iomem void *)
440                    ((uintptr_t)&qoriq_qman_portal[0][0] + (uintptr_t)res.start);
441                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] >=
442                    (uintptr_t)&qoriq_qman_portal[1][0]);
443                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] <
444                    (uintptr_t)&qoriq_qman_portal[2][0]);
445
446                ret = of_property_read_u32(&dn, "cell-index", &val);
447                if (ret != 0)
448                        panic("qman: no cell-index");
449                pcfg->channel = val;
450
451                pcfg->irq = of_irq_to_resource(&dn, 0, NULL);
452                if (pcfg->irq == NO_IRQ)
453                        panic("qman: no portal interrupt");
454
455                pcfg->cpu = cpu;
456                pcfg->pools = qm_get_pools_sdqcr();
457
458                portal = init_pcfg(pcfg);
459                if (portal == NULL)
460                        panic("qman: cannot create portal");
461
462                qman_portal_update_sdest(pcfg, cpu);
463
464                node = fdt_next_subnode(fdt, node);
465                dn.offset = node;
466        }
467
468        /* all assigned portals are initialized now */
469        qman_init_cgr_all();
470}
471#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.