source: rtems-libbsd/rtemsbsd/sys/powerpc/compat.c @ 44fca38

55-freebsd-126-freebsd-12
Last change on this file since 44fca38 was 44fca38, checked in by Sebastian Huber <sebastian.huber@…>, on 01/17/18 at 13:14:10

linux/of.h: Add of_read_number()

Update #3277.

  • Property mode set to 100644
File size: 9.5 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2#include <rtems/bsd/local/opt_dpaa.h>
3
4/*
5 * Copyright (c) 2015 embedded brains GmbH
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include <linux/slab.h>
31
32MALLOC_DEFINE(M_KMALLOC, "kmalloc", "Linux kmalloc compatibility");
33
34#include <bsp/fdt.h>
35
36#include <linux/of.h>
37
38const void *
39of_get_property(const struct device_node *dn, const char *name, int *len)
40{
41        const void *fdt = bsp_fdt_get();
42
43        return (fdt_getprop(fdt, dn->offset, name, len));
44}
45
46int
47of_property_read_u32_array(const struct device_node *dn, const char *name,
48    u32 *vals, size_t n)
49{
50        const u32 *prop_vals;
51        int len;
52
53        prop_vals = of_get_property(dn, name, &len);
54        if (prop_vals == NULL) {
55                return (-EINVAL);
56        }
57
58        if (len != n * sizeof(*vals)) {
59                return (-EOVERFLOW);
60        }
61
62        while (n > 0) {
63                *vals = fdt32_to_cpu(*prop_vals);
64                ++vals;
65                ++prop_vals;
66                --n;
67        }
68
69        return (0);
70}
71
72bool
73of_device_is_available(const struct device_node *dn)
74{
75        const char *status;
76        int len;
77
78        status = of_get_property(dn, "status", &len);
79        return (status == NULL ||
80            (len > 0 && (strcmp(status, "okay") == 0 ||
81            strcmp(status, "ok") == 0)));
82}
83
84int
85of_device_is_compatible(const struct device_node *dn, const char *name)
86{
87        const void *fdt = bsp_fdt_get();
88
89        return (fdt_node_check_compatible(fdt, dn->offset, name) == 0);
90}
91
92struct device_node *
93of_find_compatible_node(struct device_node *dns, const struct device_node *dn,
94    const char *type, const char *compatible)
95{
96        const void *fdt = bsp_fdt_get();
97        int node;
98
99        (void)type;
100
101        if (dn != NULL) {
102                node = dn->offset;
103        } else {
104                node = 0;
105        }
106
107        memset(dns, 0, sizeof(*dns));
108
109        while (1) {
110                int err;
111
112                node = fdt_next_node(fdt, node, NULL);
113                if (node < 0)
114                        return (NULL);
115
116                err = fdt_node_check_compatible(fdt, node, compatible);
117                if (err == 0) {
118                        dns->offset = node;
119                        return (dns);
120                }
121        }
122}
123
124uint64_t
125of_read_number(const uint32_t *cell, int size)
126{
127        uint64_t number;
128
129        number = 0;
130
131        while (size > 0) {
132                number = (number << 32) | fdt32_to_cpu(*cell);
133                ++cell;
134                --size;
135        }
136
137        return (number);
138}
139
140struct device_node *
141of_parse_phandle(struct device_node *dns, struct device_node *dn,
142    const char *phandle_name, int index)
143{
144        const void *fdt = bsp_fdt_get();
145        const fdt32_t *phandle;
146        int node;
147        int len;
148
149        phandle = fdt_getprop(fdt, dn->offset, phandle_name, &len);
150        if (phandle == NULL || (len / (int) sizeof(*phandle)) <= index) {
151                return (NULL);
152        }
153
154        node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(phandle[index]));
155        if (node < 0) {
156                return (NULL);
157        }
158
159        dns->offset = node;
160        dns->full_name = NULL;
161        return (dns);
162}
163
164int
165of_count_phandle_with_args(struct device_node *dn, const char *list_name,
166    const char *cells_name)
167{
168        const void *fdt = bsp_fdt_get();
169        const fdt32_t *phandle;
170        int len;
171
172        BSD_ASSERT(cells_name == NULL);
173
174        phandle = fdt_getprop(fdt, dn->offset, list_name, &len);
175        if (phandle == NULL) {
176                return (-ENOENT);
177        }
178
179        return (len / (int)sizeof(*phandle));
180}
181
182#include <linux/of_address.h>
183#include <linux/of_irq.h>
184
185static int
186get_cells(const void *fdt, int node, const char *name)
187{
188        const fdt32_t *c;
189        int len;
190        int val;
191
192        do {
193                c = fdt_getprop(fdt, node, name, &len);
194                if (c != NULL) {
195                        if (len != sizeof(*c))
196                                return (-EINVAL);
197                        val = fdt32_to_cpu(*c);
198                        if (val <= 0 ||
199                            val > sizeof(resource_size_t) / sizeof(*c))
200                                return (-EINVAL);
201                        return (val);
202                }
203                node = fdt_parent_offset(fdt, node);
204        } while (node >= 0);
205
206        return (-EINVAL);
207}
208
209static int
210get_address_cells(const void *fdt, int node)
211{
212
213        return (get_cells(fdt, node, "#address-cells"));
214}
215
216static int
217get_size_cells(const void *fdt, int node)
218{
219
220        return (get_cells(fdt, node, "#size-cells"));
221}
222
223int
224of_n_addr_cells(struct device_node *dn)
225{
226
227        return (get_address_cells(bsp_fdt_get(), dn->offset));
228}
229
230int
231of_n_size_cells(struct device_node *dn)
232{
233
234        return (get_size_cells(bsp_fdt_get(), dn->offset));
235}
236
237int
238of_address_to_resource(struct device_node *dn, int index,
239    struct resource *res)
240{
241        const void *fdt = bsp_fdt_get();
242        int ac;
243        int sc;
244        int len;
245        const fdt32_t *p;
246        int i;
247
248        memset(res, 0, sizeof(*res));
249
250        ac = get_address_cells(fdt, dn->offset);
251        if (ac < 0)
252                return (-EINVAL);
253
254        sc = get_size_cells(fdt, dn->offset);
255        if (sc < 0)
256                return (-EINVAL);
257
258        p = fdt_getprop(fdt, dn->offset, "reg", &len);
259        if (p == NULL)
260                return (-EINVAL);
261
262        len /= sizeof(*p);
263        i = index * (ac + sc);
264        if (i + ac + sc > len)
265                return (-EINVAL);
266
267        while (ac > 0) {
268                res->start = (res->start << 32) | fdt32_to_cpu(p[i]);
269                ++i;
270                --ac;
271        }
272
273        while (sc > 0) {
274                res->end = (res->end << 32) | fdt32_to_cpu(p[i]);
275                ++i;
276                --sc;
277        }
278        res->end += res->start;
279
280        return (0);
281}
282
283int
284of_irq_to_resource(struct device_node *dn, int index,
285    struct resource *res)
286{
287        const void *fdt = bsp_fdt_get();
288        int len;
289        const fdt32_t *p;
290        int i;
291        int irq;
292
293        if (res != NULL)
294                memset(res, 0, sizeof(*res));
295
296        p = fdt_getprop(fdt, dn->offset, "interrupts", &len);
297        if (p == NULL)
298                return (-EINVAL);
299
300        i = index * 16;
301        if (i + 16 > len)
302                return (-EINVAL);
303
304        irq = (int)fdt32_to_cpu(p[i / sizeof(*p)]);
305#ifdef __PPC__
306        /* FIXME */
307        irq -= 16;
308#endif
309
310        if (res != NULL) {
311                res->start = irq;
312                res->end = irq;
313        }
314
315        return (irq);
316}
317
318#include <linux/of_net.h>
319#include <linux/if_ether.h>
320#include <linux/phy.h>
321
322static const char * const phy_modes[] = {
323        [PHY_INTERFACE_MODE_MII]        = "mii",
324        [PHY_INTERFACE_MODE_GMII]       = "gmii",
325        [PHY_INTERFACE_MODE_SGMII]      = "sgmii",
326        [PHY_INTERFACE_MODE_TBI]        = "tbi",
327        [PHY_INTERFACE_MODE_REVMII]     = "rev-mii",
328        [PHY_INTERFACE_MODE_RMII]       = "rmii",
329        [PHY_INTERFACE_MODE_RGMII]      = "rgmii",
330        [PHY_INTERFACE_MODE_RGMII_ID]   = "rgmii-id",
331        [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid",
332        [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
333        [PHY_INTERFACE_MODE_RTBI]       = "rtbi",
334        [PHY_INTERFACE_MODE_SMII]       = "smii",
335        [PHY_INTERFACE_MODE_XGMII]      = "xgmii",
336        [PHY_INTERFACE_MODE_MOCA]       = "moca",
337        [PHY_INTERFACE_MODE_QSGMII]     = "qsgmii"
338};
339
340int
341of_get_phy_mode(struct device_node *dn)
342{
343        const void *fdt = bsp_fdt_get();
344        int len;
345        const char *p;
346        int i;
347
348        p = fdt_getprop(fdt, dn->offset, "phy-mode", &len);
349
350        if (p == NULL) {
351                p = fdt_getprop(fdt, dn->offset, "phy-connection-type", &len);
352        }
353
354        if (p == NULL) {
355                return (-ENODEV);
356        }
357
358        for (i = 0; i < ARRAY_SIZE(phy_modes); i++) {
359                if (phy_modes[i] != NULL && strcmp(p, phy_modes[i]) == 0) {
360                        return (i);
361                }
362        }
363
364        return (-ENODEV);
365}
366
367static const void *
368get_mac_address(struct device_node *dn, const char *name)
369{
370        const void *fdt = bsp_fdt_get();
371        int len;
372        const fdt32_t *p;
373
374        p = fdt_getprop(fdt, dn->offset, name, &len);
375        if (p == NULL || len != ETH_ALEN) {
376                return (NULL);
377        }
378
379        return (p);
380}
381
382const void *
383of_get_mac_address(struct device_node *dn)
384{
385        const void *addr;
386
387        addr = get_mac_address(dn, "mac-address");
388        if (addr != NULL) {
389                return addr;
390        }
391
392        return get_mac_address(dn, "local-mac-address");
393}
394
395#include <linux/interrupt.h>
396
397struct arg_wrapper {
398        irq_handler_t handler;
399        unsigned int irq;
400        void *arg;
401};
402
403static void
404handler_wrapper(void *arg)
405{
406        struct arg_wrapper *aw = arg;
407
408        (*aw->handler)(aw->irq, aw->arg);
409}
410
411int __must_check
412request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
413    const char *name, void *arg)
414{
415        struct arg_wrapper *aw;
416        rtems_status_code sc;
417
418        aw = kmalloc(sizeof(*aw), GFP_KERNEL);
419        if (aw == NULL)
420                return (-ENOMEM);
421
422        aw->handler = handler;
423        aw->irq = irq;
424        aw->arg = arg;
425        sc = rtems_interrupt_server_handler_install(RTEMS_ID_NONE, irq, name,
426            RTEMS_INTERRUPT_SHARED, handler_wrapper, aw);
427        if (sc != RTEMS_SUCCESSFUL)
428                return (-EINVAL);
429
430        return (0);
431}
432
433#include <linux/bitrev.h>
434
435const uint8_t bitrev_nibbles[16] = {
436        0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
437};
438
439#include <linux/platform_device.h>
440
441struct resource *
442platform_get_resource(struct resource *res, struct platform_device *pdev,
443    unsigned int type, unsigned int num)
444{
445        struct device_node *dn;
446        int ret;
447
448        dn = pdev->dev.of_node;
449
450        switch (type) {
451        case IORESOURCE_MEM:
452                ret = of_address_to_resource(dn, num, res);
453                if (ret == 0)
454                        return res;
455        case IORESOURCE_IRQ:
456                ret = of_irq_to_resource(dn, num, res);
457                if (ret >= 0)
458                        return res;
459        default:
460                break;
461        }
462
463        return (NULL);
464}
465
466int platform_get_irq(struct platform_device *pdev, unsigned int num)
467{
468        struct resource res_storage;
469        struct resource *res;
470
471        res = platform_get_resource(&res_storage, pdev, IORESOURCE_IRQ, num);
472        return (res != NULL ? res->start : -ENXIO);
473}
Note: See TracBrowser for help on using the repository browser.