Ejemplo n.º 1
0
static void do_event_scan(void)
{
	int error;
	do {
		memset(logdata, 0, rtas_error_log_max);
		error = rtas_call(event_scan, 4, 1, NULL,
				  RTAS_EVENT_SCAN_ALL_EVENTS, 0,
				  __pa(logdata), rtas_error_log_max);
		if (error == -1) {
			printk(KERN_ERR "event-scan failed\n");
			break;
		}

		if (error == 0)
			pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0);

	} while(error == 0);
}
Ejemplo n.º 2
0
/* ****************************************************************** */
static ssize_t ppc_rtas_clock_write(struct file *file,
		const char __user *buf, size_t count, loff_t *ppos)
{
	struct rtc_time tm;
	unsigned long nowtime;
	int error = parse_number(buf, count, &nowtime);
	if (error)
		return error;

	to_tm(nowtime, &tm);
	error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL,
			tm.tm_year, tm.tm_mon, tm.tm_mday,
			tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
	if (error)
		printk(KERN_WARNING "error: setting the clock returned: %s\n",
				ppc_rtas_process_error(error));
	return count;
}
Ejemplo n.º 3
0
/* ****************************************************************** */
static int ppc_rtas_clock_show(struct seq_file *m, void *v)
{
	int ret[8];
	int error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);

	if (error) {
		printk(KERN_WARNING "error: reading the clock returned: %s\n",
				ppc_rtas_process_error(error));
		seq_printf(m, "0");
	} else {
		unsigned int year, mon, day, hour, min, sec;
		year = ret[0]; mon  = ret[1]; day  = ret[2];
		hour = ret[3]; min  = ret[4]; sec  = ret[5];
		seq_printf(m, "%lu\n",
				mktime(year, mon, day, hour, min, sec));
	}
	return 0;
}
Ejemplo n.º 4
0
static void udbg_rtascon_putc(char c)
{
	int tries;

	if (!rtas.base)
		return;

	/* Add CRs before LFs */
	if (c == '\n')
		udbg_rtascon_putc('\r');

	/* if there is more than one character to be displayed, wait a bit */
	for (tries = 0; tries < 16; tries++) {
		if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0)
			break;
		udelay(1000);
	}
}
Ejemplo n.º 5
0
static void validate_flash(struct rtas_validate_flash_t *args_buf)
{
	int token = rtas_token("ibm,validate-flash-image");
	int update_results;
	s32 rc;	

	rc = 0;
	do {
		spin_lock(&rtas_data_buf_lock);
		memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE);
		rc = rtas_call(token, 2, 2, &update_results, 
			       (u32) __pa(rtas_data_buf), args_buf->buf_size);
		memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE);
		spin_unlock(&rtas_data_buf_lock);
	} while (rtas_busy_delay(rc));

	args_buf->status = rc;
	args_buf->update_results = update_results;
}
Ejemplo n.º 6
0
void
xics_disable_irq(
	u_int	virq
	)
{
	u_int		irq;
	unsigned long 	status;
	long 	        call_status;

	virq -= XICS_IRQ_OFFSET;
	irq = virt_irq_to_real(virq);
	call_status = rtas_call(ibm_int_off, 1, 1, (unsigned long*)&status, 
				irq);
	if( call_status != 0 ) {
		printk("xics_disable_irq: irq=%x: rtas_call failed, retn=%lx\n",
		       irq, call_status);
		return;
	}
}
Ejemplo n.º 7
0
static int ics_rtas_map(struct ics *ics, unsigned int virq)
{
	unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
	int status[2];
	int rc;

	if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
		return -EINVAL;

	/* Check if RTAS knows about this interrupt */
	rc = rtas_call(ibm_get_xive, 1, 3, status, hw_irq);
	if (rc)
		return -ENXIO;

	irq_set_chip_and_handler(virq, &ics_rtas_irq_chip, handle_fasteoi_irq);
	irq_set_chip_data(virq, &ics_rtas);

	return 0;
}
Ejemplo n.º 8
0
static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
{
	unsigned int i;
	unsigned long len;
	int done;
	unsigned long flags;
	char *p = buf;


	if (nvram_size == 0 || nvram_fetch == RTAS_UNKNOWN_SERVICE)
		return -ENODEV;

	if (*index >= nvram_size)
		return 0;

	i = *index;
	if (i + count > nvram_size)
		count = nvram_size - i;

	spin_lock_irqsave(&nvram_lock, flags);

	for (; count != 0; count -= len) {
		len = count;
		if (len > NVRW_CNT)
			len = NVRW_CNT;

		if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf),
			       len) != 0) || len != done) {
			spin_unlock_irqrestore(&nvram_lock, flags);
			return -EIO;
		}

		memcpy(p, nvram_buf, len);

		p += len;
		i += len;
	}

	spin_unlock_irqrestore(&nvram_lock, flags);

	*index = i;
	return p - buf;
}
Ejemplo n.º 9
0
static void manage_flash(struct rtas_manage_flash_t *args_buf)
{
	unsigned int wait_time;
	s32 rc;

	while (1) {
		rc = (s32) rtas_call(rtas_token("ibm,manage-flash-image"), 1, 
				1, NULL, (long) args_buf->op);
		if (rc == RTAS_RC_BUSY)
			udelay(1);
		else if (rtas_is_extended_busy(rc)) {
			wait_time = rtas_extended_busy_delay_time(rc);
			udelay(wait_time * 1000);
		} else
			break;
	}

	args_buf->status = rc;
}
Ejemplo n.º 10
0
int
rtas_errinjct_open(void)
{
	u32 ret[2];
	int open_token;
	int rc;

	/* The rc and open_token values are backwards due to a misprint in
	 * the RPA */ 
	open_token = rtas_call(rtas_token("ibm,open-errinjct"), 0, 2, (void *) &ret);
	rc = ret[0];

	if (rc < 0) {
		printk(KERN_WARNING "error: ibm,open-errinjct failed (%d)\n", rc);
		return rc;
	}

	return open_token;
}
Ejemplo n.º 11
0
/* ****************************************************************** */
static ssize_t ppc_rtas_tone_volume_write(struct file *file,
		const char __user *buf, size_t count, loff_t *ppos)
{
	unsigned long volume;
	int error = parse_number(buf, count, &volume);
	if (error)
		return error;

	if (volume > 100)
		volume = 100;
	
        rtas_tone_volume = volume; /* save it for later */
	error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL,
			TONE_VOLUME, 0, volume);
	if (error)
		printk(KERN_WARNING "error: setting tone volume returned: %s\n", 
				ppc_rtas_process_error(error));
	return count;
}
Ejemplo n.º 12
0
/**
 * wdrtas_set_interval - sets the watchdog interval
 * @interval: new interval
 *
 * returns 0 on success, <0 on failures
 *
 * wdrtas_set_interval sets the watchdog keepalive interval by calling the
 * RTAS function set-indicator (surveillance). The unit of interval is
 * seconds.
 */
static int
wdrtas_set_interval(int interval)
{
	long result;
	static int print_msg = 10;

	/* rtas uses minutes */
	interval = (interval + 59) / 60;

	result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
			   WDRTAS_SURVEILLANCE_IND, 0, interval);
	if ( (result < 0) && (print_msg) ) {
		printk(KERN_ERR "wdrtas: setting the watchdog to %i "
		       "timeout failed: %li\n", interval, result);
		print_msg--;
	}

	return result;
}
Ejemplo n.º 13
0
/**
 * smp_startup_cpu() - start the given cpu
 *
 * At boot time, there is nothing to do for primary threads which were
 * started from Open Firmware.  For anything else, call RTAS with the
 * appropriate start location.
 *
 * Returns:
 *	0	- failure
 *	1	- success
 */
static inline int __devinit smp_startup_cpu(unsigned int lcpu)
{
	int status;
	unsigned long start_here = __pa((u32)*((unsigned long *)
					       generic_secondary_smp_init));
	unsigned int pcpu;
	int start_cpu;

	if (cpumask_test_cpu(lcpu, of_spin_mask))
		/* Already started by OF and sitting in spin loop */
		return 1;

	pcpu = get_hard_smp_processor_id(lcpu);

	/* Check to see if the CPU out of FW already for kexec */
	if (smp_query_cpu_stopped(pcpu) == QCSS_NOT_STOPPED){
		cpumask_set_cpu(lcpu, of_spin_mask);
		return 1;
	}

	/* Fixup atomic count: it exited inside IRQ handler. */
	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;

	if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE)
		goto out;

	/* 
	 * If the RTAS start-cpu token does not exist then presume the
	 * cpu is already spinning.
	 */
	start_cpu = rtas_token("start-cpu");
	if (start_cpu == RTAS_UNKNOWN_SERVICE)
		return 1;

	status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, pcpu);
	if (status != 0) {
		printk(KERN_ERR "start-cpu failed: %i\n", status);
		return 0;
	}

out:
	return 1;
}
Ejemplo n.º 14
0
static ssize_t scanlog_write(struct file * file, const char * buf,
			     size_t count, loff_t *ppos)
{
	unsigned long status;

	if (buf) {
		if (strncmp(buf, "reset", 5) == 0) {
			DEBUG("reset scanlog\n");
			status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, NULL, 0);
			DEBUG("rtas returns %ld\n", status);
		} else if (strncmp(buf, "debugon", 7) == 0) {
			printk(KERN_ERR "scanlog: debug on\n");
			scanlog_debug = 1;
		} else if (strncmp(buf, "debugoff", 8) == 0) {
			printk(KERN_ERR "scanlog: debug off\n");
			scanlog_debug = 0;
		}
	}
	return count;
}
Ejemplo n.º 15
0
void rtas_os_term(char *str)
{
	int status;

	if (RTAS_UNKNOWN_SERVICE == rtas_token("ibm,os-term"))
		return;

	snprintf(rtas_os_term_buf, 2048, "OS panic: %s", str);

	do {
		status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL,
				   __pa(rtas_os_term_buf));

		if (status == RTAS_BUSY)
			udelay(1);
		else if (status != 0)
			printk(KERN_EMERG "ibm,os-term call failed %d\n",
			       status);
	} while (status == RTAS_BUSY);
}
Ejemplo n.º 16
0
void
rtas_configure_bridge(struct pci_dn *pdn)
{
	int config_addr;
	int rc;

	/* Use PE configuration address, if present */
	config_addr = pdn->eeh_config_addr;
	if (pdn->eeh_pe_config_addr)
		config_addr = pdn->eeh_pe_config_addr;

	rc = rtas_call(ibm_configure_bridge,3,1, NULL,
	               config_addr,
	               BUID_HI(pdn->phb->buid),
	               BUID_LO(pdn->phb->buid));
	if (rc) {
		printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n",
		        rc, pdn->node->full_name);
	}
}
Ejemplo n.º 17
0
Archivo: smp.c Proyecto: 168519/linux
/* Query where a cpu is now.  Return codes #defined in plpar_wrappers.h */
int smp_query_cpu_stopped(unsigned int pcpu)
{
	int cpu_status, status;
	int qcss_tok = rtas_token("query-cpu-stopped-state");

	if (qcss_tok == RTAS_UNKNOWN_SERVICE) {
		printk_once(KERN_INFO
			"Firmware doesn't support query-cpu-stopped-state\n");
		return QCSS_HARDWARE_ERROR;
	}

	status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu);
	if (status != 0) {
		printk(KERN_ERR
		       "RTAS query-cpu-stopped-state failed: %i\n", status);
		return status;
	}

	return cpu_status;
}
Ejemplo n.º 18
0
/**
 * pseries_eeh_set_option - Initialize EEH or MMIO/DMA reenable
 * @dn: device node
 * @option: operation to be issued
 *
 * The function is used to control the EEH functionality globally.
 * Currently, following options are support according to PAPR:
 * Enable EEH, Disable EEH, Enable MMIO and Enable DMA
 */
static int pseries_eeh_set_option(struct device_node *dn, int option)
{
	int ret = 0;
	struct eeh_dev *edev;
	const u32 *reg;
	int config_addr;

	edev = of_node_to_eeh_dev(dn);

	/*
	 * When we're enabling or disabling EEH functioality on
	 * the particular PE, the PE config address is possibly
	 * unavailable. Therefore, we have to figure it out from
	 * the FDT node.
	 */
	switch (option) {
	case EEH_OPT_DISABLE:
	case EEH_OPT_ENABLE:
		reg = of_get_property(dn, "reg", NULL);
		config_addr = reg[0];
		break;

	case EEH_OPT_THAW_MMIO:
	case EEH_OPT_THAW_DMA:
		config_addr = edev->config_addr;
		if (edev->pe_config_addr)
			config_addr = edev->pe_config_addr;
		break;

	default:
		pr_err("%s: Invalid option %d\n",
			__func__, option);
		return -EINVAL;
	}

	ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
			config_addr, BUID_HI(edev->phb->buid),
			BUID_LO(edev->phb->buid), option);

	return ret;
}
Ejemplo n.º 19
0
/* ****************************************************************** */
static int ppc_rtas_sensors_show(struct seq_file *m, void *v)
{
	int i,j;
	int state, error;
	int get_sensor_state = rtas_token("get-sensor-state");

	seq_printf(m, "RTAS (RunTime Abstraction Services) Sensor Information\n");
	seq_printf(m, "Sensor\t\tValue\t\tCondition\tLocation\n");
	seq_printf(m, "********************************************************\n");

	if (ppc_rtas_find_all_sensors() != 0) {
		seq_printf(m, "\nNo sensors are available\n");
		return 0;
	}

	for (i=0; i<sensors.quant; i++) {
		struct individual_sensor *p = &sensors.sensor[i];
		char rstr[64];
		const char *loc;
		int llen, offs;

		sprintf (rstr, SENSOR_PREFIX"%04d", p->token);
		loc = of_get_property(rtas_node, rstr, &llen);

		/* A sensor may have multiple instances */
		for (j = 0, offs = 0; j <= p->quant; j++) {
			error =	rtas_call(get_sensor_state, 2, 2, &state, 
				  	  p->token, j);

			ppc_rtas_process_sensor(m, p, state, error, loc);
			seq_putc(m, '\n');
			if (loc) {
				offs += strlen(loc) + 1;
				loc += strlen(loc) + 1;
				if (offs >= llen)
					loc = NULL;
			}
		}
	}
	return 0;
}
Ejemplo n.º 20
0
Archivo: rtas.c Proyecto: 710leo/LVS
static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_when_done)
{
	u16 slb_size = mmu_slb_size;
	int rc = H_MULTI_THREADS_ACTIVE;
	int cpu;

	slb_set_size(SLB_MIN_SIZE);
	printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id());

	while (rc == H_MULTI_THREADS_ACTIVE && !data->done) {
		rc = rtas_call(data->token, 0, 1, NULL);
		if (rc && rc != H_MULTI_THREADS_ACTIVE)
			printk(KERN_DEBUG "ibm,suspend-me returned %d\n", rc);
	}

	smp_rmb();
	if (rc || data->error)
		slb_set_size(slb_size);

	if (data->error)
		rc = data->error;

	data->error = rc;

	if (wake_when_done) {
		smp_wmb();
		data->done = 1;

		/* Ensure data->done is seen on all CPUs that are about to wake up
		 as a result of the H_PROD below */
		mb();

		for_each_online_cpu(cpu)
			plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
	}

	if (atomic_dec_return(&data->working) == 0)
		complete(data->complete);

	return rc;
}
Ejemplo n.º 21
0
Archivo: dlpar.c Proyecto: 3null/linux
int dlpar_release_drc(u32 drc_index)
{
	int dr_status, rc;

	rc = rtas_call(rtas_token("get-sensor-state"), 2, 2, &dr_status,
		       DR_ENTITY_SENSE, drc_index);
	if (rc || dr_status != DR_ENTITY_PRESENT)
		return -1;

	rc = rtas_set_indicator(ISOLATION_STATE, drc_index, ISOLATE);
	if (rc)
		return rc;

	rc = rtas_set_indicator(ALLOCATION_STATE, drc_index, ALLOC_UNUSABLE);
	if (rc) {
		rtas_set_indicator(ISOLATION_STATE, drc_index, UNISOLATE);
		return rc;
	}

	return 0;
}
Ejemplo n.º 22
0
static ssize_t read_nvram(struct file *file, char *buf,
			  size_t count, loff_t *ppos)
{
	unsigned int i;
	unsigned long len;
	char *p = buf;

	if (verify_area(VERIFY_WRITE, buf, count))
		return -EFAULT;
	if (*ppos >= rtas_nvram_size)
		return 0;
	for (i = *ppos; count > 0 && i < rtas_nvram_size; ++i, ++p, --count) {
		if ((rtas_call(nvram_fetch, 3, 2, &len, i, __pa(nvram_buf), 1) != 0) ||
		    len != 1)
			return -EIO;
		if (__put_user(nvram_buf[0], p))
			return -EFAULT;
	}
	*ppos = i;
	return p - buf;
}
Ejemplo n.º 23
0
/* ****************************************************************** */
static ssize_t ppc_rtas_poweron_write(struct file *file,
		const char __user *buf, size_t count, loff_t *ppos)
{
	struct rtc_time tm;
	unsigned long nowtime;
	int error = parse_number(buf, count, &nowtime);
	if (error)
		return error;

	power_on_time = nowtime; /* save the time */

	to_tm(nowtime, &tm);

	error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL, 
			tm.tm_year, tm.tm_mon, tm.tm_mday, 
			tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
	if (error)
		printk(KERN_WARNING "error: setting poweron time returned: %s\n", 
				ppc_rtas_process_error(error));
	return count;
}
Ejemplo n.º 24
0
static unsigned char chrp_nvram_read(int addr)
{
	unsigned int done;
	unsigned long flags;
	unsigned char ret;

	if (addr >= nvram_size) {
		printk(KERN_DEBUG "%s: read addr %d > nvram_size %u\n",
		       current->comm, addr, nvram_size);
		return 0xff;
	}
	spin_lock_irqsave(&nvram_lock, flags);
	if ((rtas_call(rtas_token("nvram-fetch"), 3, 2, &done, addr,
		       __pa(nvram_buf), 1) != 0) || 1 != done)
		ret = 0xff;
	else
		ret = nvram_buf[0];
	spin_unlock_irqrestore(&nvram_lock, flags);

	return ret;
}
Ejemplo n.º 25
0
static ssize_t scanlog_write(struct file * file, const char __user * buf,
			     size_t count, loff_t *ppos)
{
	char stkbuf[20];
	int status;

	if (count > 19) count = 19;
	if (copy_from_user (stkbuf, buf, count)) {
		return -EFAULT;
	}
	stkbuf[count] = 0;

	if (buf) {
		if (strncmp(stkbuf, "reset", 5) == 0) {
			pr_debug("scanlog: reset scanlog\n");
			status = rtas_call(ibm_scan_log_dump, 2, 1, NULL, 0, 0);
			pr_debug("scanlog: rtas returns %d\n", status);
		}
	}
	return count;
}
Ejemplo n.º 26
0
/*
 * Handle hardware error interrupts.
 *
 * RTAS check-exception is called to collect data on the exception.  If
 * the error is deemed recoverable, we log a warning and return.
 * For nonrecoverable errors, an error is logged and we stop all processing
 * as quickly as possible in order to prevent propagation of the failure.
 */
static irqreturn_t ras_error_interrupt(int irq, void *dev_id)
{
	struct rtas_error_log *rtas_elog;
	int status;
	int fatal;

	spin_lock(&ras_log_buf_lock);

	status = rtas_call(ras_check_exception_token, 6, 1, NULL,
			   RTAS_VECTOR_EXTERNAL_INTERRUPT,
			   virq_to_hw(irq),
			   RTAS_INTERNAL_ERROR, 1 /* Time Critical */,
			   __pa(&ras_log_buf),
				rtas_get_error_log_max());

	rtas_elog = (struct rtas_error_log *)ras_log_buf;

	if (status == 0 &&
	    rtas_error_severity(rtas_elog) >= RTAS_SEVERITY_ERROR_SYNC)
		fatal = 1;
	else
		fatal = 0;

	/* format and print the extended information */
	log_error(ras_log_buf, ERR_TYPE_RTAS_LOG, fatal);

	if (fatal) {
		pr_emerg("Fatal hardware error reported by firmware");
		pr_emerg("Check RTAS error log for details");
		pr_emerg("Immediate power off");
		emergency_sync();
		kernel_power_off();
	} else {
		pr_err("Recoverable hardware error reported by firmware");
	}

	spin_unlock(&ras_log_buf_lock);
	return IRQ_HANDLED;
}
Ejemplo n.º 27
0
int
rtas_set_power_level(int powerdomain, int level, int *setlevel)
{
	int token = rtas_token("set-power-level");
	unsigned int wait_time;
	int rc;

	if (token == RTAS_UNKNOWN_SERVICE)
		return RTAS_UNKNOWN_OP;

	while (1) {
		rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
		if (rc == RTAS_BUSY)
			udelay(1);
		else if (rtas_is_extended_busy(rc)) {
			wait_time = rtas_extended_busy_delay_time(rc);
			udelay(wait_time * 1000);
		} else
			break;
	}
	return rc;
}
Ejemplo n.º 28
0
int
rtas_get_sensor(int sensor, int index, int *state)
{
	int token = rtas_token("get-sensor-state");
	unsigned int wait_time;
	int rc;

	if (token == RTAS_UNKNOWN_SERVICE)
		return RTAS_UNKNOWN_OP;

	while (1) {
		rc = rtas_call(token, 2, 2, state, sensor, index);
		if (rc == RTAS_BUSY)
			udelay(1);
		else if (rtas_is_extended_busy(rc)) {
			wait_time = rtas_extended_busy_delay_time(rc);
			udelay(wait_time * 1000);
		} else
			break;
	}
	return rc;
}
Ejemplo n.º 29
0
/**
 * read_slot_reset_state - Read the reset state of a device node's slot
 * @dn: device node to read
 * @rets: array to return results in
 */
static int read_slot_reset_state(struct pci_dn *pdn, int rets[])
{
	int token, outputs;
	int config_addr;

	if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
		token = ibm_read_slot_reset_state2;
		outputs = 4;
	} else {
		token = ibm_read_slot_reset_state;
		rets[2] = 0; /* fake PE Unavailable info */
		outputs = 3;
	}

	/* Use PE configuration address, if present */
	config_addr = pdn->eeh_config_addr;
	if (pdn->eeh_pe_config_addr)
		config_addr = pdn->eeh_pe_config_addr;

	return rtas_call(token, 3, outputs, rets, config_addr,
			 BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
}
Ejemplo n.º 30
0
void rtas_get_rtc_time(struct rtc_time *rtc_tm)
{
        int ret[8];
	int error;
	unsigned int wait_time;
	u64 max_wait_tb;

	max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT;
	do {
		error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret);

		wait_time = rtas_busy_delay_time(error);
		if (wait_time) {
			if (in_interrupt()) {
				memset(rtc_tm, 0, sizeof(struct rtc_time));
				printk_ratelimited(KERN_WARNING
						   "error: reading clock "
						   "would delay interrupt\n");
				return;	/*                   */
			}
			msleep(wait_time);
		}
	} while (wait_time && (get_tb() < max_wait_tb));

	if (error != 0) {
		printk_ratelimited(KERN_WARNING
				   "error: reading the clock failed (%d)\n",
				   error);
		return;
        }

	rtc_tm->tm_sec = ret[5];
	rtc_tm->tm_min = ret[4];
	rtc_tm->tm_hour = ret[3];
	rtc_tm->tm_mday = ret[2];
	rtc_tm->tm_mon = ret[1] - 1;
	rtc_tm->tm_year = ret[0] - 1900;
}