162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * misc.c: Miscellaneous prom functions that don't belong 462306a36Sopenharmony_ci * anywhere else. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/types.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/sched.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <asm/openprom.h> 1562306a36Sopenharmony_ci#include <asm/oplib.h> 1662306a36Sopenharmony_ci#include <asm/auxio.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciextern void restore_current(void); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ciDEFINE_SPINLOCK(prom_lock); 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* Reset and reboot the machine with the command 'bcommand'. */ 2362306a36Sopenharmony_civoid 2462306a36Sopenharmony_ciprom_reboot(char *bcommand) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci unsigned long flags; 2762306a36Sopenharmony_ci spin_lock_irqsave(&prom_lock, flags); 2862306a36Sopenharmony_ci (*(romvec->pv_reboot))(bcommand); 2962306a36Sopenharmony_ci /* Never get here. */ 3062306a36Sopenharmony_ci restore_current(); 3162306a36Sopenharmony_ci spin_unlock_irqrestore(&prom_lock, flags); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* Forth evaluate the expression contained in 'fstring'. */ 3562306a36Sopenharmony_civoid 3662306a36Sopenharmony_ciprom_feval(char *fstring) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci unsigned long flags; 3962306a36Sopenharmony_ci if(!fstring || fstring[0] == 0) 4062306a36Sopenharmony_ci return; 4162306a36Sopenharmony_ci spin_lock_irqsave(&prom_lock, flags); 4262306a36Sopenharmony_ci if(prom_vers == PROM_V0) 4362306a36Sopenharmony_ci (*(romvec->pv_fortheval.v0_eval))(strlen(fstring), fstring); 4462306a36Sopenharmony_ci else 4562306a36Sopenharmony_ci (*(romvec->pv_fortheval.v2_eval))(fstring); 4662306a36Sopenharmony_ci restore_current(); 4762306a36Sopenharmony_ci spin_unlock_irqrestore(&prom_lock, flags); 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ciEXPORT_SYMBOL(prom_feval); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Drop into the prom, with the chance to continue with the 'go' 5262306a36Sopenharmony_ci * prom command. 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_civoid 5562306a36Sopenharmony_ciprom_cmdline(void) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci unsigned long flags; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci spin_lock_irqsave(&prom_lock, flags); 6062306a36Sopenharmony_ci (*(romvec->pv_abort))(); 6162306a36Sopenharmony_ci restore_current(); 6262306a36Sopenharmony_ci spin_unlock_irqrestore(&prom_lock, flags); 6362306a36Sopenharmony_ci set_auxio(AUXIO_LED, 0); 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* Drop into the prom, but completely terminate the program. 6762306a36Sopenharmony_ci * No chance of continuing. 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_civoid __noreturn 7062306a36Sopenharmony_ciprom_halt(void) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci unsigned long flags; 7362306a36Sopenharmony_ciagain: 7462306a36Sopenharmony_ci spin_lock_irqsave(&prom_lock, flags); 7562306a36Sopenharmony_ci (*(romvec->pv_halt))(); 7662306a36Sopenharmony_ci /* Never get here. */ 7762306a36Sopenharmony_ci restore_current(); 7862306a36Sopenharmony_ci spin_unlock_irqrestore(&prom_lock, flags); 7962306a36Sopenharmony_ci goto again; /* PROM is out to get me -DaveM */ 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_citypedef void (*sfunc_t)(void); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* Set prom sync handler to call function 'funcp'. */ 8562306a36Sopenharmony_civoid 8662306a36Sopenharmony_ciprom_setsync(sfunc_t funcp) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci if(!funcp) return; 8962306a36Sopenharmony_ci *romvec->pv_synchook = funcp; 9062306a36Sopenharmony_ci} 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci/* Get the idprom and stuff it into buffer 'idbuf'. Returns the 9362306a36Sopenharmony_ci * format type. 'num_bytes' is the number of bytes that your idbuf 9462306a36Sopenharmony_ci * has space for. Returns 0xff on error. 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_ciunsigned char 9762306a36Sopenharmony_ciprom_get_idprom(char *idbuf, int num_bytes) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci int len; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci len = prom_getproplen(prom_root_node, "idprom"); 10262306a36Sopenharmony_ci if((len>num_bytes) || (len==-1)) return 0xff; 10362306a36Sopenharmony_ci if(!prom_getproperty(prom_root_node, "idprom", idbuf, num_bytes)) 10462306a36Sopenharmony_ci return idbuf[0]; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci return 0xff; 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* Get the major prom version number. */ 11062306a36Sopenharmony_ciint 11162306a36Sopenharmony_ciprom_version(void) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci return romvec->pv_romvers; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci/* Get the prom plugin-revision. */ 11762306a36Sopenharmony_ciint 11862306a36Sopenharmony_ciprom_getrev(void) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci return prom_rev; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci/* Get the prom firmware print revision. */ 12462306a36Sopenharmony_ciint 12562306a36Sopenharmony_ciprom_getprev(void) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci return prom_prev; 12862306a36Sopenharmony_ci} 129