source: rtems-libbsd/linux/drivers/soc/fsl/qbman/bman_ccsr.c @ cd089b9

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

Linux update to 4.11-rc5

Linux baseline a71c9a1c779f2499fb2afc0553e543f18aff6edf (4.11-rc5).

  • Property mode set to 100644
File size: 11.0 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
3#include <rtems/bsd/local/opt_dpaa.h>
4
5/* Copyright (c) 2009 - 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 "bman_priv.h"
36
37u16 bman_ip_rev;
38EXPORT_SYMBOL(bman_ip_rev);
39
40/* Register offsets */
41#define REG_FBPR_FPC            0x0800
42#define REG_ECSR                0x0a00
43#define REG_ECIR                0x0a04
44#define REG_EADR                0x0a08
45#define REG_EDATA(n)            (0x0a10 + ((n) * 0x04))
46#define REG_SBEC(n)             (0x0a80 + ((n) * 0x04))
47#define REG_IP_REV_1            0x0bf8
48#define REG_IP_REV_2            0x0bfc
49#define REG_FBPR_BARE           0x0c00
50#define REG_FBPR_BAR            0x0c04
51#define REG_FBPR_AR             0x0c10
52#define REG_SRCIDR              0x0d04
53#define REG_LIODNR              0x0d08
54#define REG_ERR_ISR             0x0e00
55#define REG_ERR_IER             0x0e04
56#define REG_ERR_ISDR            0x0e08
57
58/* Used by all error interrupt registers except 'inhibit' */
59#define BM_EIRQ_IVCI    0x00000010      /* Invalid Command Verb */
60#define BM_EIRQ_FLWI    0x00000008      /* FBPR Low Watermark */
61#define BM_EIRQ_MBEI    0x00000004      /* Multi-bit ECC Error */
62#define BM_EIRQ_SBEI    0x00000002      /* Single-bit ECC Error */
63#define BM_EIRQ_BSCN    0x00000001      /* pool State Change Notification */
64
65struct bman_hwerr_txt {
66        u32 mask;
67        const char *txt;
68};
69
70static const struct bman_hwerr_txt bman_hwerr_txts[] = {
71        { BM_EIRQ_IVCI, "Invalid Command Verb" },
72        { BM_EIRQ_FLWI, "FBPR Low Watermark" },
73        { BM_EIRQ_MBEI, "Multi-bit ECC Error" },
74        { BM_EIRQ_SBEI, "Single-bit ECC Error" },
75        { BM_EIRQ_BSCN, "Pool State Change Notification" },
76};
77
78/* Only trigger low water mark interrupt once only */
79#define BMAN_ERRS_TO_DISABLE BM_EIRQ_FLWI
80
81/* Pointer to the start of the BMan's CCSR space */
82static u32 __iomem *bm_ccsr_start;
83
84static inline u32 bm_ccsr_in(u32 offset)
85{
86        return ioread32be(bm_ccsr_start + offset/4);
87}
88static inline void bm_ccsr_out(u32 offset, u32 val)
89{
90        iowrite32be(val, bm_ccsr_start + offset/4);
91}
92
93static void bm_get_version(u16 *id, u8 *major, u8 *minor)
94{
95        u32 v = bm_ccsr_in(REG_IP_REV_1);
96        *id = (v >> 16);
97        *major = (v >> 8) & 0xff;
98        *minor = v & 0xff;
99}
100
101/* signal transactions for FBPRs with higher priority */
102#define FBPR_AR_RPRIO_HI BIT(30)
103
104static void bm_set_memory(u64 ba, u32 size)
105{
106        u32 exp = ilog2(size);
107        /* choke if size isn't within range */
108        DPAA_ASSERT(size >= 4096 && size <= 1024*1024*1024 &&
109                   is_power_of_2(size));
110        /* choke if '[e]ba' has lower-alignment than 'size' */
111        DPAA_ASSERT(!(ba & (size - 1)));
112        bm_ccsr_out(REG_FBPR_BARE, upper_32_bits(ba));
113        bm_ccsr_out(REG_FBPR_BAR, lower_32_bits(ba));
114        bm_ccsr_out(REG_FBPR_AR, exp - 1);
115}
116
117/*
118 * Location and size of BMan private memory
119 *
120 * Ideally we would use the DMA API to turn rmem->base into a DMA address
121 * (especially if iommu translations ever get involved).  Unfortunately, the
122 * DMA API currently does not allow mapping anything that is not backed with
123 * a struct page.
124 */
125#ifndef __rtems__
126static dma_addr_t fbpr_a;
127static size_t fbpr_sz;
128
129static int bman_fbpr(struct reserved_mem *rmem)
130{
131        fbpr_a = rmem->base;
132        fbpr_sz = rmem->size;
133
134        WARN_ON(!(fbpr_a && fbpr_sz));
135
136        return 0;
137}
138RESERVEDMEM_OF_DECLARE(bman_fbpr, "fsl,bman-fbpr", bman_fbpr);
139#else /* __rtems__ */
140static DPAA_NOCACHENOLOAD_ALIGNED_REGION(fbpr, 16777216);
141#define fbpr_a ((uintptr_t)&fbpr[0])
142#define fbpr_sz sizeof(fbpr)
143#endif /* __rtems__ */
144
145static irqreturn_t bman_isr(int irq, void *ptr)
146{
147        u32 isr_val, ier_val, ecsr_val, isr_mask, i;
148        struct device *dev = ptr;
149
150        ier_val = bm_ccsr_in(REG_ERR_IER);
151        isr_val = bm_ccsr_in(REG_ERR_ISR);
152        ecsr_val = bm_ccsr_in(REG_ECSR);
153        isr_mask = isr_val & ier_val;
154
155        if (!isr_mask)
156                return IRQ_NONE;
157
158        for (i = 0; i < ARRAY_SIZE(bman_hwerr_txts); i++) {
159                if (bman_hwerr_txts[i].mask & isr_mask) {
160#ifndef __rtems__
161                        dev_err_ratelimited(dev, "ErrInt: %s\n",
162                                            bman_hwerr_txts[i].txt);
163#endif /* __rtems__ */
164                        if (bman_hwerr_txts[i].mask & ecsr_val) {
165                                /* Re-arm error capture registers */
166                                bm_ccsr_out(REG_ECSR, ecsr_val);
167                        }
168                        if (bman_hwerr_txts[i].mask & BMAN_ERRS_TO_DISABLE) {
169                                dev_dbg(dev, "Disabling error 0x%x\n",
170                                        bman_hwerr_txts[i].mask);
171                                ier_val &= ~bman_hwerr_txts[i].mask;
172                                bm_ccsr_out(REG_ERR_IER, ier_val);
173                        }
174                }
175        }
176        bm_ccsr_out(REG_ERR_ISR, isr_val);
177
178        return IRQ_HANDLED;
179}
180
181static int fsl_bman_probe(struct platform_device *pdev)
182{
183        int ret, err_irq;
184        struct device *dev = &pdev->dev;
185        struct device_node *node = dev->of_node;
186#ifdef __rtems__
187        struct resource res_storage;
188#endif /* __rtems__ */
189        struct resource *res;
190        u16 id, bm_pool_cnt;
191        u8 major, minor;
192
193#ifndef __rtems__
194        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
195#else /* __rtems__ */
196        res = platform_get_resource(&res_storage, pdev, IORESOURCE_MEM, 0);
197#endif /* __rtems__ */
198        if (!res) {
199                dev_err(dev, "Can't get %s property 'IORESOURCE_MEM'\n",
200                        node->full_name);
201                return -ENXIO;
202        }
203        bm_ccsr_start = devm_ioremap(dev, res->start, resource_size(res));
204        if (!bm_ccsr_start)
205                return -ENXIO;
206
207        bm_get_version(&id, &major, &minor);
208        if (major == 1 && minor == 0) {
209                bman_ip_rev = BMAN_REV10;
210                bm_pool_cnt = BM_POOL_MAX;
211        } else if (major == 2 && minor == 0) {
212                bman_ip_rev = BMAN_REV20;
213                bm_pool_cnt = 8;
214        } else if (major == 2 && minor == 1) {
215                bman_ip_rev = BMAN_REV21;
216                bm_pool_cnt = BM_POOL_MAX;
217        } else {
218                dev_err(dev, "Unknown Bman version:%04x,%02x,%02x\n",
219                        id, major, minor);
220                return -ENODEV;
221        }
222
223        bm_set_memory(fbpr_a, fbpr_sz);
224
225        err_irq = platform_get_irq(pdev, 0);
226        if (err_irq <= 0) {
227                dev_info(dev, "Can't get %s IRQ\n", node->full_name);
228                return -ENODEV;
229        }
230        ret = devm_request_irq(dev, err_irq, bman_isr, IRQF_SHARED, "bman-err",
231                               dev);
232        if (ret)  {
233                dev_err(dev, "devm_request_irq() failed %d for '%s'\n",
234                        ret, node->full_name);
235                return ret;
236        }
237        /* Disable Buffer Pool State Change */
238        bm_ccsr_out(REG_ERR_ISDR, BM_EIRQ_BSCN);
239        /*
240         * Write-to-clear any stale bits, (eg. starvation being asserted prior
241         * to resource allocation during driver init).
242         */
243        bm_ccsr_out(REG_ERR_ISR, 0xffffffff);
244        /* Enable Error Interrupts */
245        bm_ccsr_out(REG_ERR_IER, 0xffffffff);
246
247        bm_bpalloc = devm_gen_pool_create(dev, 0, -1, "bman-bpalloc");
248        if (IS_ERR(bm_bpalloc)) {
249                ret = PTR_ERR(bm_bpalloc);
250                dev_err(dev, "bman-bpalloc pool init failed (%d)\n", ret);
251                return ret;
252        }
253
254        /* seed BMan resource pool */
255        ret = gen_pool_add(bm_bpalloc, DPAA_GENALLOC_OFF, bm_pool_cnt, -1);
256        if (ret) {
257                dev_err(dev, "Failed to seed BPID range [%d..%d] (%d)\n",
258                        0, bm_pool_cnt - 1, ret);
259                return ret;
260        }
261
262        return 0;
263};
264
265#ifndef __rtems__
266static const struct of_device_id fsl_bman_ids[] = {
267        {
268                .compatible = "fsl,bman",
269        },
270        {}
271};
272
273static struct platform_driver fsl_bman_driver = {
274        .driver = {
275                .name = KBUILD_MODNAME,
276                .of_match_table = fsl_bman_ids,
277                .suppress_bind_attrs = true,
278        },
279        .probe = fsl_bman_probe,
280};
281
282builtin_platform_driver(fsl_bman_driver);
283#else /* __rtems__ */
284#include <sys/types.h>
285#include <sys/kernel.h>
286#include <rtems.h>
287#include <bsp/fdt.h>
288#include <bsp/qoriq.h>
289#include <linux/of_address.h>
290#include <linux/of_irq.h>
291
292static struct bm_portal_config bman_configs[NR_CPUS];
293
294u16 bman_pool_max;
295
296SYSINIT_REFERENCE(irqs);
297
298static void
299bman_sysinit(void)
300{
301        const char *fdt = bsp_fdt_get();
302        struct device_node dn;
303        struct platform_device ofdev = {
304                .dev = {
305                        .of_node = &dn,
306                        .base = (uintptr_t)&qoriq
307                }
308        };
309        const char *name;
310        int cpu_count = (int)rtems_get_processor_count();
311        int cpu;
312        int ret;
313        int node;
314        int parent;
315
316        qoriq_reset_qman_and_bman();
317        qoriq_clear_ce_portal(&qoriq_bman_portal[0][0],
318            sizeof(qoriq_bman_portal[0]));
319        qoriq_clear_ci_portal(&qoriq_bman_portal[1][0],
320            sizeof(qoriq_bman_portal[1]));
321
322        memset(&dn, 0, sizeof(dn));
323
324        name = "fsl,bman";
325        node = fdt_node_offset_by_compatible(fdt, 0, name);
326        if (node < 0)
327                panic("bman: no bman in FDT");
328
329        dn.full_name = name;
330        dn.offset = node;
331        ret = fsl_bman_probe(&ofdev);
332        if (ret != 0)
333                panic("bman: probe failed");
334
335        name = "fsl,bman-portal";
336        node = fdt_node_offset_by_compatible(fdt, 0, name);
337        if (node < 0)
338                panic("bman: no portals in FDT");
339        parent = fdt_parent_offset(fdt, node);
340        if (parent < 0)
341                panic("bman: no parent of portals in FDT");
342        node = fdt_first_subnode(fdt, parent);
343
344        dn.full_name = name;
345        dn.offset = node;
346
347        for (cpu = 0; cpu < cpu_count; ++cpu) {
348                struct bm_portal_config *pcfg = &bman_configs[cpu];
349                struct bman_portal *portal;
350                struct resource res;
351
352                if (node < 0)
353                        panic("bman: missing portal in FDT");
354
355                ret = of_address_to_resource(&dn, 0, &res);
356                if (ret != 0)
357                        panic("bman: no portal CE address");
358                pcfg->addr_virt[0] = (__iomem void *)
359                    ((uintptr_t)&qoriq_bman_portal[0][0] + (uintptr_t)res.start);
360                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] >=
361                    (uintptr_t)&qoriq_bman_portal[0][0]);
362                BSD_ASSERT((uintptr_t)pcfg->addr_virt[0] <
363                    (uintptr_t)&qoriq_bman_portal[1][0]);
364
365                ret = of_address_to_resource(&dn, 1, &res);
366                if (ret != 0)
367                        panic("bman: no portal CI address");
368                pcfg->addr_virt[1] = (__iomem void *)
369                    ((uintptr_t)&qoriq_bman_portal[0][0] + (uintptr_t)res.start);
370                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] >=
371                    (uintptr_t)&qoriq_bman_portal[1][0]);
372                BSD_ASSERT((uintptr_t)pcfg->addr_virt[1] <
373                    (uintptr_t)&qoriq_bman_portal[2][0]);
374
375                pcfg->irq = of_irq_to_resource(&dn, 0, NULL);
376                if (pcfg->irq == NO_IRQ)
377                        panic("bman: no portal interrupt");
378
379                pcfg->cpu = cpu;
380
381                portal = bman_create_affine_portal(pcfg);
382                if (portal == NULL)
383                        panic("bman: cannot create portal");
384
385                bman_p_irqsource_add(portal, BM_PIRQ_RCRI);
386
387                node = fdt_next_subnode(fdt, node);
388                dn.offset = node;
389        }
390}
391SYSINIT(bman, SI_SUB_CPU, SI_ORDER_FIRST, bman_sysinit, NULL);
392#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.