^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * tree.c: Basic device tree traversal/scanning for the Linux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * prom library.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/openprom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/oplib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) extern void restore_current(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static char promlib_buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Internal version of prom_getchild that does not alter return values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static phandle __prom_getchild(phandle node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) phandle cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) spin_lock_irqsave(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) cnode = prom_nodeops->no_child(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) restore_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) spin_unlock_irqrestore(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /* Return the child of node 'node' or zero if no this node has no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * direct descendent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) phandle prom_getchild(phandle node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) phandle cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if ((s32)node == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) cnode = __prom_getchild(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (cnode == 0 || (s32)cnode == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) EXPORT_SYMBOL(prom_getchild);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Internal version of prom_getsibling that does not alter return values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static phandle __prom_getsibling(phandle node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) phandle cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) spin_lock_irqsave(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) cnode = prom_nodeops->no_nextnode(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) restore_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) spin_unlock_irqrestore(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return cnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Return the next sibling of node 'node' or zero if no more siblings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * at this level of depth in the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) phandle prom_getsibling(phandle node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) phandle sibnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if ((s32)node == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) sibnode = __prom_getsibling(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (sibnode == 0 || (s32)sibnode == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return sibnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) EXPORT_SYMBOL(prom_getsibling);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /* Return the length in bytes of property 'prop' at node 'node'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Return -1 on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int prom_getproplen(phandle node, const char *prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if((!node) || (!prop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) spin_lock_irqsave(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ret = prom_nodeops->no_proplen(node, prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) restore_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) spin_unlock_irqrestore(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) EXPORT_SYMBOL(prom_getproplen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) /* Acquire a property 'prop' at node 'node' and place it in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * 'buffer' which has a size of 'bufsize'. If the acquisition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * was successful the length will be returned, else -1 is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int prom_getproperty(phandle node, const char *prop, char *buffer, int bufsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int plen, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) plen = prom_getproplen(node, prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if((plen > bufsize) || (plen == 0) || (plen == -1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Ok, things seem all right. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) spin_lock_irqsave(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) ret = prom_nodeops->no_getprop(node, prop, buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) restore_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) spin_unlock_irqrestore(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) EXPORT_SYMBOL(prom_getproperty);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) /* Acquire an integer property and return its value. Returns -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int prom_getint(phandle node, char *prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int intprop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) return intprop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) EXPORT_SYMBOL(prom_getint);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* Acquire an integer property, upon error return the passed default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * integer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) int prom_getintdefault(phandle node, char *property, int deflt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) retval = prom_getint(node, property);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) if(retval == -1) return deflt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) EXPORT_SYMBOL(prom_getintdefault);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* Acquire a boolean property, 1=TRUE 0=FALSE. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) int prom_getbool(phandle node, char *prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) retval = prom_getproplen(node, prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if(retval == -1) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) EXPORT_SYMBOL(prom_getbool);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* Acquire a property whose value is a string, returns a null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * string on error. The char pointer is the user supplied string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) void prom_getstring(phandle node, char *prop, char *user_buf, int ubuf_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) len = prom_getproperty(node, prop, user_buf, ubuf_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if(len != -1) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) user_buf[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) EXPORT_SYMBOL(prom_getstring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* Search siblings at 'node_start' for a node with name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * 'nodename'. Return node if successful, zero if not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) phandle prom_searchsiblings(phandle node_start, char *nodename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) phandle thisnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) for(thisnode = node_start; thisnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) thisnode=prom_getsibling(thisnode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) error = prom_getproperty(thisnode, "name", promlib_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) sizeof(promlib_buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* Should this ever happen? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if(error == -1) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if(strcmp(nodename, promlib_buf)==0) return thisnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) EXPORT_SYMBOL(prom_searchsiblings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) /* Interal version of nextprop that does not alter return values. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static char *__prom_nextprop(phandle node, char * oprop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) char *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) spin_lock_irqsave(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) prop = prom_nodeops->no_nextprop(node, oprop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) restore_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) spin_unlock_irqrestore(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) /* Return the property type string after property type 'oprop'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * at node 'node' . Returns empty string if no more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * property types for this node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) char *prom_nextprop(phandle node, char *oprop, char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (node == 0 || (s32)node == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return __prom_nextprop(node, oprop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) EXPORT_SYMBOL(prom_nextprop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) phandle prom_finddevice(char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) char nbuf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) char *s = name, *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) phandle node = prom_root_node, node2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned int which_io, phys_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct linux_prom_registers reg[PROMREG_MAX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) while (*s++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (!*s) return node; /* path '.../' is legal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) node = prom_getchild(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (d = nbuf; *s != 0 && *s != '@' && *s != '/';)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) *d++ = *s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *d = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) node = prom_searchsiblings(node, nbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (!node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (*s == '@') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (isxdigit(s[1]) && s[2] == ',') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) which_io = simple_strtoul(s+1, NULL, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) phys_addr = simple_strtoul(s+3, &d, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (d != s + 3 && (!*d || *d == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) && d <= s + 3 + 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) node2 = node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) while (node2 && (s32)node2 != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) node = node2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) node2 = prom_getsibling(node2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (!node2 || (s32)node2 == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) node2 = prom_searchsiblings(prom_getsibling(node2), nbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) while (*s != 0 && *s != '/') s++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) EXPORT_SYMBOL(prom_finddevice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Set property 'pname' at node 'node' to value 'value' which has a length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * of 'size' bytes. Return the number of bytes the prom accepted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) int prom_setprop(phandle node, const char *pname, char *value, int size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if ((pname == NULL) || (value == NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) spin_lock_irqsave(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) ret = prom_nodeops->no_setprop(node, pname, value, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) restore_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) spin_unlock_irqrestore(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) EXPORT_SYMBOL(prom_setprop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) phandle prom_inst2pkg(int inst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) phandle node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) spin_lock_irqsave(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) node = (*romvec->pv_v2devops.v2_inst2pkg)(inst);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) restore_current();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) spin_unlock_irqrestore(&prom_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if ((s32)node == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) return node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }