Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }