source: rtems-libbsd/rtemsbsd/sys/powerpc/compat.c @ 26ce2ac

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

linux/of.h: Add of_n_size_cells()

Update #3277.

  • Property mode set to 100644
File size: 9.3 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
124struct device_node *
125of_parse_phandle(struct device_node *dns, struct device_node *dn,
126    const char *phandle_name, int index)
127{
128        const void *fdt = bsp_fdt_get();
129        const fdt32_t *phandle;
130        int node;
131        int len;
132
133        phandle = fdt_getprop(fdt, dn->offset, phandle_name, &len);
134        if (phandle == NULL || (len / (int) sizeof(*phandle)) <= index) {
135                return (NULL);
136        }
137
138        node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(phandle[index]));
139        if (node < 0) {
140                return (NULL);
141        }
142
143        dns->offset = node;
144        dns->full_name = NULL;
145        return (dns);
146}
147
148int
149of_count_phandle_with_args(struct device_node *dn, const char *list_name,
150    const char *cells_name)
151{
152        const void *fdt = bsp_fdt_get();
153        const fdt32_t *phandle;
154        int len;
155
156        BSD_ASSERT(cells_name == NULL);
157
158        phandle = fdt_getprop(fdt, dn->offset, list_name, &len);
159        if (phandle == NULL) {
160                return (-ENOENT);
161        }
162
163        return (len / (int)sizeof(*phandle));
164}
165
166#include <linux/of_address.h>
167#include <linux/of_irq.h>
168
169static int
170get_cells(const void *fdt, int node, const char *name)
171{
172        const fdt32_t *c;
173        int len;
174        int val;
175
176        do {
177                c = fdt_getprop(fdt, node, name, &len);
178                if (c != NULL) {
179                        if (len != sizeof(*c))
180                                return (-EINVAL);
181                        val = fdt32_to_cpu(*c);
182                        if (val <= 0 ||
183                            val > sizeof(resource_size_t) / sizeof(*c))
184                                return (-EINVAL);
185                        return (val);
186                }
187                node = fdt_parent_offset(fdt, node);
188        } while (node >= 0);
189
190        return (-EINVAL);
191}
192
193static int
194get_address_cells(const void *fdt, int node)
195{
196
197        return (get_cells(fdt, node, "#address-cells"));
198}
199
200static int
201get_size_cells(const void *fdt, int node)
202{
203
204        return (get_cells(fdt, node, "#size-cells"));
205}
206
207int
208of_n_addr_cells(struct device_node *dn)
209{
210
211        return (get_address_cells(bsp_fdt_get(), dn->offset));
212}
213
214int
215of_n_size_cells(struct device_node *dn)
216{
217
218        return (get_size_cells(bsp_fdt_get(), dn->offset));
219}
220
221int
222of_address_to_resource(struct device_node *dn, int index,
223    struct resource *res)
224{
225        const void *fdt = bsp_fdt_get();
226        int ac;
227        int sc;
228        int len;
229        const fdt32_t *p;
230        int i;
231
232        memset(res, 0, sizeof(*res));
233
234        ac = get_address_cells(fdt, dn->offset);
235        if (ac < 0)
236                return (-EINVAL);
237
238        sc = get_size_cells(fdt, dn->offset);
239        if (sc < 0)
240                return (-EINVAL);
241
242        p = fdt_getprop(fdt, dn->offset, "reg", &len);
243        if (p == NULL)
244                return (-EINVAL);
245
246        len /= sizeof(*p);
247        i = index * (ac + sc);
248        if (i + ac + sc > len)
249                return (-EINVAL);
250
251        while (ac > 0) {
252                res->start = (res->start << 32) | fdt32_to_cpu(p[i]);
253                ++i;
254                --ac;
255        }
256
257        while (sc > 0) {
258                res->end = (res->end << 32) | fdt32_to_cpu(p[i]);
259                ++i;
260                --sc;
261        }
262        res->end += res->start;
263
264        return (0);
265}
266
267int
268of_irq_to_resource(struct device_node *dn, int index,
269    struct resource *res)
270{
271        const void *fdt = bsp_fdt_get();
272        int len;
273        const fdt32_t *p;
274        int i;
275        int irq;
276
277        if (res != NULL)
278                memset(res, 0, sizeof(*res));
279
280        p = fdt_getprop(fdt, dn->offset, "interrupts", &len);
281        if (p == NULL)
282                return (-EINVAL);
283
284        i = index * 16;
285        if (i + 16 > len)
286                return (-EINVAL);
287
288        irq = (int)fdt32_to_cpu(p[i / sizeof(*p)]);
289#ifdef __PPC__
290        /* FIXME */
291        irq -= 16;
292#endif
293
294        if (res != NULL) {
295                res->start = irq;
296                res->end = irq;
297        }
298
299        return (irq);
300}
301
302#include <linux/of_net.h>
303#include <linux/if_ether.h>
304#include <linux/phy.h>
305
306static const char * const phy_modes[] = {
307        [PHY_INTERFACE_MODE_MII]        = "mii",
308        [PHY_INTERFACE_MODE_GMII]       = "gmii",
309        [PHY_INTERFACE_MODE_SGMII]      = "sgmii",
310        [PHY_INTERFACE_MODE_TBI]        = "tbi",
311        [PHY_INTERFACE_MODE_REVMII]     = "rev-mii",
312        [PHY_INTERFACE_MODE_RMII]       = "rmii",
313        [PHY_INTERFACE_MODE_RGMII]      = "rgmii",
314        [PHY_INTERFACE_MODE_RGMII_ID]   = "rgmii-id",
315        [PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid",
316        [PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
317        [PHY_INTERFACE_MODE_RTBI]       = "rtbi",
318        [PHY_INTERFACE_MODE_SMII]       = "smii",
319        [PHY_INTERFACE_MODE_XGMII]      = "xgmii",
320        [PHY_INTERFACE_MODE_MOCA]       = "moca",
321        [PHY_INTERFACE_MODE_QSGMII]     = "qsgmii"
322};
323
324int
325of_get_phy_mode(struct device_node *dn)
326{
327        const void *fdt = bsp_fdt_get();
328        int len;
329        const char *p;
330        int i;
331
332        p = fdt_getprop(fdt, dn->offset, "phy-mode", &len);
333
334        if (p == NULL) {
335                p = fdt_getprop(fdt, dn->offset, "phy-connection-type", &len);
336        }
337
338        if (p == NULL) {
339                return (-ENODEV);
340        }
341
342        for (i = 0; i < ARRAY_SIZE(phy_modes); i++) {
343                if (phy_modes[i] != NULL && strcmp(p, phy_modes[i]) == 0) {
344                        return (i);
345                }
346        }
347
348        return (-ENODEV);
349}
350
351static const void *
352get_mac_address(struct device_node *dn, const char *name)
353{
354        const void *fdt = bsp_fdt_get();
355        int len;
356        const fdt32_t *p;
357
358        p = fdt_getprop(fdt, dn->offset, name, &len);
359        if (p == NULL || len != ETH_ALEN) {
360                return (NULL);
361        }
362
363        return (p);
364}
365
366const void *
367of_get_mac_address(struct device_node *dn)
368{
369        const void *addr;
370
371        addr = get_mac_address(dn, "mac-address");
372        if (addr != NULL) {
373                return addr;
374        }
375
376        return get_mac_address(dn, "local-mac-address");
377}
378
379#include <linux/interrupt.h>
380
381struct arg_wrapper {
382        irq_handler_t handler;
383        unsigned int irq;
384        void *arg;
385};
386
387static void
388handler_wrapper(void *arg)
389{
390        struct arg_wrapper *aw = arg;
391
392        (*aw->handler)(aw->irq, aw->arg);
393}
394
395int __must_check
396request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
397    const char *name, void *arg)
398{
399        struct arg_wrapper *aw;
400        rtems_status_code sc;
401
402        aw = kmalloc(sizeof(*aw), GFP_KERNEL);
403        if (aw == NULL)
404                return (-ENOMEM);
405
406        aw->handler = handler;
407        aw->irq = irq;
408        aw->arg = arg;
409        sc = rtems_interrupt_server_handler_install(RTEMS_ID_NONE, irq, name,
410            RTEMS_INTERRUPT_SHARED, handler_wrapper, aw);
411        if (sc != RTEMS_SUCCESSFUL)
412                return (-EINVAL);
413
414        return (0);
415}
416
417#include <linux/bitrev.h>
418
419const uint8_t bitrev_nibbles[16] = {
420        0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
421};
422
423#include <linux/platform_device.h>
424
425struct resource *
426platform_get_resource(struct resource *res, struct platform_device *pdev,
427    unsigned int type, unsigned int num)
428{
429        struct device_node *dn;
430        int ret;
431
432        dn = pdev->dev.of_node;
433
434        switch (type) {
435        case IORESOURCE_MEM:
436                ret = of_address_to_resource(dn, num, res);
437                if (ret == 0)
438                        return res;
439        case IORESOURCE_IRQ:
440                ret = of_irq_to_resource(dn, num, res);
441                if (ret >= 0)
442                        return res;
443        default:
444                break;
445        }
446
447        return (NULL);
448}
449
450int platform_get_irq(struct platform_device *pdev, unsigned int num)
451{
452        struct resource res_storage;
453        struct resource *res;
454
455        res = platform_get_resource(&res_storage, pdev, IORESOURCE_IRQ, num);
456        return (res != NULL ? res->start : -ENXIO);
457}
Note: See TracBrowser for help on using the repository browser.