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