^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* prom_common.c: OF device tree support common code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Paul Mackerras August 1996.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1996-2005 Paul Mackerras.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * {engebret|bergner}@us.ibm.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Adapted for sparc by David S. Miller davem@davemloft.net
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/of_pdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "prom.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct device_node *of_console_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) EXPORT_SYMBOL(of_console_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) char *of_console_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) EXPORT_SYMBOL(of_console_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) char *of_console_options;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) EXPORT_SYMBOL(of_console_options);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int of_getintprop_default(struct device_node *np, const char *name, int def)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) prop = of_find_property(np, name, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (!prop || len != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return def;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return *(int *) prop->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) EXPORT_SYMBOL(of_getintprop_default);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) DEFINE_MUTEX(of_set_property_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) EXPORT_SYMBOL(of_set_property_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int of_set_property(struct device_node *dp, const char *name, void *val, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct property **prevp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void *new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) new_val = kmemdup(val, len, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) if (!new_val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) err = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) mutex_lock(&of_set_property_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) raw_spin_lock_irqsave(&devtree_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) prevp = &dp->properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) while (*prevp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct property *prop = *prevp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (!strcasecmp(prop->name, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) void *old_val = prop->value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ret = prom_setprop(dp->phandle, name, val, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (ret >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) prop->value = new_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) prop->length = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (OF_IS_DYNAMIC(prop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) kfree(old_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) OF_MARK_DYNAMIC(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) prevp = &(*prevp)->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) raw_spin_unlock_irqrestore(&devtree_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mutex_unlock(&of_set_property_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* XXX Upate procfs if necessary... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) EXPORT_SYMBOL(of_set_property);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) int of_find_in_proplist(const char *list, const char *match, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) while (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!strcmp(list, match))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) l = strlen(list) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) list += l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) len -= l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) EXPORT_SYMBOL(of_find_in_proplist);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * SPARC32 and SPARC64's prom_nextprop() do things differently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * here, despite sharing the same interface. SPARC32 doesn't fill in 'buf',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * returning NULL on an error. SPARC64 fills in 'buf', but sets it to an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * empty string upon error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) static int __init handle_nextprop_quirks(char *buf, const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (!name || strlen(name) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #ifdef CONFIG_SPARC32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) strcpy(buf, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int __init prom_common_nextprop(phandle node, char *prev, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) buf[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) name = prom_nextprop(node, prev, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return handle_nextprop_quirks(buf, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) unsigned int prom_early_allocated __initdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static struct of_pdt_ops prom_sparc_ops __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .nextprop = prom_common_nextprop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .getproplen = prom_getproplen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .getproperty = prom_getproperty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) .getchild = prom_getchild,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .getsibling = prom_getsibling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) void __init prom_build_devicetree(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) of_pdt_build_devicetree(prom_root_node, &prom_sparc_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) of_console_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) pr_info("PROM: Built device tree with %u bytes of memory.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) prom_early_allocated);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }