Example #1
0
static int
mv_rtc_settime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct mv_rtc_softc *sc;
	uint32_t val;

	sc = device_get_softc(dev);

	/* Resolution: 1 sec */
	if (ts->tv_nsec >= 500000000)
		ts->tv_sec++;
	ts->tv_nsec = 0;
	clock_ts_to_ct(ts, &ct);

	val = TOBCD(ct.sec) | (TOBCD(ct.min) << 8) |
	    (TOBCD(ct.hour) << 16) | (TOBCD( ct.dow + 1) << 24);
	mv_rtc_reg_write(sc, MV_RTC_TIME_REG, val);

	val = TOBCD(ct.day) | (TOBCD(ct.mon) << 8) |
	    (TOBCD(ct.year - YEAR_BASE) << 16);
	mv_rtc_reg_write(sc, MV_RTC_DATE_REG, val);

	return (0);
}
Example #2
0
int
as3722_rtc_settime(device_t dev, struct timespec *ts)
{
	struct as3722_softc *sc;
	struct clocktime ct;
	uint8_t buf[6];
	int rv;

	sc = device_get_softc(dev);
	clock_ts_to_ct(ts, &ct);

	if (ct.year < AS3722_RTC_START_YEAR)
		return (EINVAL);

	buf[0] = bin2bcd(ct.sec);
	buf[1] = bin2bcd(ct.min);
	buf[2] = bin2bcd(ct.hour);
	buf[3] = bin2bcd(ct.day);
	buf[4] = bin2bcd(ct.mon);
	buf[5] = bin2bcd(ct.year - AS3722_RTC_START_YEAR);

	rv = as3722_write_buf(sc, AS3722_RTC_SECOND, buf, 6);
	if (rv != 0) {
		device_printf(sc->dev, "Failed to write RTC data\n");
		return (rv);
	}
	return (0);
}
Example #3
0
static int
ds1307_settime(device_t dev, struct timespec *ts)
{
	int error;
	struct clocktime ct;
	struct ds1307_softc *sc;
	uint8_t data[8];

	sc = device_get_softc(dev);
	/* Accuracy is only one second. */
	if (ts->tv_nsec >= 500000000)
		ts->tv_sec++;
	ts->tv_nsec = 0;
	clock_ts_to_ct(ts, &ct);
	memset(data, 0, sizeof(data));
	data[0] = DS1307_SECS;
	data[DS1307_SECS + 1] = TOBCD(ct.sec);
	data[DS1307_MINS + 1] = TOBCD(ct.min);
	data[DS1307_HOUR + 1] = TOBCD(ct.hour);
	data[DS1307_DATE + 1] = TOBCD(ct.day);
	data[DS1307_WEEKDAY + 1] = ct.dow;
	data[DS1307_MONTH + 1] = TOBCD(ct.mon);
	data[DS1307_YEAR + 1] = TOBCD(ct.year % 100);
	/* Write the time back to RTC. */
	error = ds1307_write(dev, sc->sc_addr, data, sizeof(data));
	if (error != 0)
		device_printf(dev, "cannot write to RTC.\n");

	return (error);
}
Example #4
0
static int
efirtc_settime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct efi_tm tm;

	/*
	 * We request a timespec with no resolution-adjustment so that we can
	 * apply it ourselves based on whether or not the clock zeroes the
	 * sub-second part of the time when setting the time.
	 */
	ts->tv_sec -= utc_offset();
	if (!efirtc_zeroes_subseconds)
		timespecadd(ts, &efirtc_resadj);
	
	clock_ts_to_ct(ts, &ct);
	clock_dbgprint_ct(dev, CLOCK_DBG_WRITE, &ct);

	bzero(&tm, sizeof(tm));
	tm.tm_sec = ct.sec;
	tm.tm_min = ct.min;
	tm.tm_hour = ct.hour;
	tm.tm_mday = ct.day;
	tm.tm_mon = ct.mon;
	tm.tm_year = ct.year;
	tm.tm_nsec = ct.nsec;

	return (efi_set_time(&tm));
}
Example #5
0
static int
atrtc_settime(device_t dev __unused, struct timespec *ts)
{
	struct clocktime ct;

	clock_ts_to_ct(ts, &ct);

	/* Disable RTC updates and interrupts. */
	writertc(RTC_STATUSB, RTCSB_HALT | RTCSB_24HR);

	writertc(RTC_SEC, bin2bcd(ct.sec)); 		/* Write back Seconds */
	writertc(RTC_MIN, bin2bcd(ct.min)); 		/* Write back Minutes */
	writertc(RTC_HRS, bin2bcd(ct.hour));		/* Write back Hours   */

	writertc(RTC_WDAY, ct.dow + 1);			/* Write back Weekday */
	writertc(RTC_DAY, bin2bcd(ct.day));		/* Write back Day */
	writertc(RTC_MONTH, bin2bcd(ct.mon));           /* Write back Month   */
	writertc(RTC_YEAR, bin2bcd(ct.year % 100));	/* Write back Year    */
#ifdef USE_RTC_CENTURY
	writertc(RTC_CENTURY, bin2bcd(ct.year / 100));	/* ... and Century    */
#endif

	/* Reenable RTC updates and interrupts. */
	writertc(RTC_STATUSB, rtc_statusb);
	rtcin(RTC_INTR);
	return (0);
}
Example #6
0
static int
opal_settime(device_t dev, struct timespec *ts)
{
	int rv;
	struct clocktime ct;
	uint32_t ymd = 0;
	uint64_t hmsm = 0;

	clock_ts_to_ct(ts, &ct);

	ymd |= (uint32_t)bin2bcd(ct.day);
	ymd |= ((uint32_t)bin2bcd(ct.mon) << 8);
	ymd |= ((uint32_t)bin2bcd32(ct.year) << 16);

	hmsm |= ((uint64_t)bin2bcd32(ct.nsec/1000) << 16);
	hmsm |= ((uint64_t)bin2bcd(ct.sec) << 40);
	hmsm |= ((uint64_t)bin2bcd(ct.min) << 48);
	hmsm |= ((uint64_t)bin2bcd(ct.hour) << 56);

	hmsm = htobe64(hmsm);
	ymd = htobe32(ymd);

	do {
		rv = opal_call(OPAL_RTC_WRITE, vtophys(&ymd), vtophys(&hmsm));
		if (rv == OPAL_BUSY_EVENT) {
			rv = opal_call(OPAL_POLL_EVENTS, 0);
			pause("opalrtc", 1);
		}
	} while (rv == OPAL_BUSY_EVENT);

	if (rv != OPAL_SUCCESS)
		return (ENXIO);

	return (0);
}
Example #7
0
static int
aw_rtc_settime(device_t dev, struct timespec *ts)
{
	struct aw_rtc_softc *sc  = device_get_softc(dev);
	struct clocktime ct;
	uint32_t clk, rdate, rtime;

	/* RTC resolution is 1 sec */
	if (ts->tv_nsec >= HALF_OF_SEC_NS)
		ts->tv_sec++;
	ts->tv_nsec = 0;

	clock_ts_to_ct(ts, &ct);
	
	if ((ct.year < YEAR_MIN) || (ct.year > YEAR_MAX)) {
		device_printf(dev, "could not set time, year out of range\n");
		return (EINVAL);
	}

	for (clk = 0; RTC_READ(sc, LOSC_CTRL_REG) & LOSC_BUSY_MASK; clk++) {
		if (clk > RTC_TIMEOUT) {
			device_printf(dev, "could not set time, RTC busy\n");
			return (EINVAL);
		}
		DELAY(1);
	}
	/* reset time register to avoid unexpected date increment */
	RTC_WRITE(sc, sc->rtc_time, 0);

	rdate = SET_DAY_VALUE(ct.day) | SET_MON_VALUE(ct.mon) |
		SET_YEAR_VALUE(ct.year - YEAR_OFFSET) | 
		SET_LEAP_VALUE(IS_LEAP_YEAR(ct.year));
			
	rtime = SET_SEC_VALUE(ct.sec) | SET_MIN_VALUE(ct.min) |
		SET_HOUR_VALUE(ct.hour);

	for (clk = 0; RTC_READ(sc, LOSC_CTRL_REG) & LOSC_BUSY_MASK; clk++) {
		if (clk > RTC_TIMEOUT) {
			device_printf(dev, "could not set date, RTC busy\n");
			return (EINVAL);
		}
		DELAY(1);
	}
	RTC_WRITE(sc, sc->rtc_date, rdate);

	for (clk = 0; RTC_READ(sc, LOSC_CTRL_REG) & LOSC_BUSY_MASK; clk++) {
		if (clk > RTC_TIMEOUT) {
			device_printf(dev, "could not set time, RTC busy\n");
			return (EINVAL);
		}
		DELAY(1);
	}
	RTC_WRITE(sc, sc->rtc_time, rtime);

	DELAY(RTC_TIMEOUT);

	return (0);
}
Example #8
0
/*
 * Board-specific RTC write
 * Time returned is in seconds from epoch (Jan 1 1970 at 00:00:00 UTC)
 */
int cvmx_rtc_ds1337_write(uint32_t time)
{
    struct clocktime ct;
    struct timespec ts;
    int       i, rc, retry;
    uint8_t   reg[8];
    uint8_t   sec;

    ts.tv_sec = time;
    ts.tv_nsec = 0;

    clock_ts_to_ct(&ts, &ct);

    if (validate_ct_struct(&ct))
    {
	cvmx_dprintf("Error: RTC was passed wrong calendar values, write failed\n");
	goto ct_invalid;
    }

    reg[0] = bin2bcd(ct.sec);
    reg[1] = bin2bcd(ct.min);
    reg[2] = bin2bcd(ct.hour);       /* Force 0..23 format even if using AM/PM */
    reg[3] = bin2bcd(ct.dow);
    reg[4] = bin2bcd(ct.day);
    reg[5] = bin2bcd(ct.mon);
    if (ct.year >= 2000)             /* Set century bit*/
    {
	reg[5] |= 0x80;
    }
    reg[6] = bin2bcd(ct.year % 100);

    /* Lockless write: detects the infrequent roll-over and retries */
    for(retry=0; retry<2; retry++)
    {
	rc = 0;
	for(i=0; i<7; i++)
	{
	    rc |= cvmx_twsi_write8(CVMX_RTC_DS1337_ADDR, i, reg[i]);
	}

	sec = cvmx_twsi_read8(CVMX_RTC_DS1337_ADDR, 0x0);
	if ((sec & 0xf) == (reg[0] & 0xf))
	    break; /* Time did not roll-over, value is correct */
    }

    return (rc ? -1 : 0);

 ct_invalid:
    return -1;
}
/*
 * Set the time of day clock based on the value of the struct timespec arg.
 * Return 0 on success, an error number otherwise.
 */
int
mc146818_settime(device_t dev, struct timespec *ts)
{
	struct mc146818_softc *sc;
	struct clocktime ct;
	int cent, year;

	sc = device_get_softc(dev);

	/* Accuracy is only one second. */
	if (ts->tv_nsec >= 500000000)
		ts->tv_sec++;
	ts->tv_nsec = 0;
	clock_ts_to_ct(ts, &ct);

	mtx_lock_spin(&sc->sc_mtx);
	/* Disable RTC updates and interrupts (if enabled). */
	(*sc->sc_mcwrite)(dev, MC_REGB,
	    ((sc->sc_regb & (MC_REGB_BINARY | MC_REGB_24HR)) | MC_REGB_SET));

#define	TOREG(x)	((sc->sc_flag & MC146818_BCD) ? TOBCD(x) : (x))

	(*sc->sc_mcwrite)(dev, MC_SEC, TOREG(ct.sec));
	(*sc->sc_mcwrite)(dev, MC_MIN, TOREG(ct.min));
	(*sc->sc_mcwrite)(dev, MC_HOUR, TOREG(ct.hour));
	/* Map dow from 0 - 6 to 1 - 7. */
	(*sc->sc_mcwrite)(dev, MC_DOW, TOREG(ct.dow + 1));
	(*sc->sc_mcwrite)(dev, MC_DOM, TOREG(ct.day));
	(*sc->sc_mcwrite)(dev, MC_MONTH, TOREG(ct.mon));

	year = ct.year - sc->sc_year0;
	if (sc->sc_flag & MC146818_NO_CENT_ADJUST) {
		cent = year / 100;
		(*sc->sc_setcent)(dev, cent);
		year -= cent * 100;
	} else if (year > 99)
		year -= 100;
	(*sc->sc_mcwrite)(dev, MC_YEAR, TOREG(year));

	/* Reenable RTC updates and interrupts. */
	(*sc->sc_mcwrite)(dev, MC_REGB, sc->sc_regb);
	mtx_unlock_spin(&sc->sc_mtx);

#undef TOREG

	return (0);
}
Example #10
0
/*
 * Set the time of day clock based on the value of the struct timespec arg.
 * Return 0 on success, an error number otherwise.
 */
static int
at91_rtc_settime(device_t dev, struct timespec *ts)
{
	struct at91_rtc_softc *sc;
	struct clocktime ct;
	int rv;

	sc = device_get_softc(dev);
	clock_ts_to_ct(ts, &ct);

	/*
	 * Can't set the clock unless a second has elapsed since we last did so.
	 */
	while ((RD4(sc, RTC_SR) & RTC_SR_SECEV) == 0)
		cpu_spinwait();

	/*
	 * Stop the clocks for an update; wait until hardware is ready.
	 * Clear the update-ready status after it gets asserted (the manual says
	 * to do this before updating the value registers).
	 */
	WR4(sc, RTC_CR, RTC_CR_UPDCAL | RTC_CR_UPDTIM);
	while ((RD4(sc, RTC_SR) & RTC_SR_ACKUPD) == 0)
		cpu_spinwait();
	WR4(sc, RTC_SCCR, RTC_SR_ACKUPD);

	/*
	 * Set the values in the hardware, then check whether the hardware was
	 * happy with them so we can return the correct status.
	 */
	WR4(sc, RTC_TIMR, RTC_TIMR_MK(ct.hour, ct.min, ct.sec));
	WR4(sc, RTC_CALR, RTC_CALR_MK(ct.year, ct.mon, ct.day, ct.dow+1));

	if (RD4(sc, RTC_VER) & (RTC_VER_NVTIM | RTC_VER_NVCAL))
		rv = EINVAL;
	else
		rv = 0;

	/*
	 * Restart the clocks (turn off the update bits).
	 * Clear the second-event bit (because the manual says to).
	 */
	WR4(sc, RTC_CR, RD4(sc, RTC_CR) & ~(RTC_CR_UPDCAL | RTC_CR_UPDTIM));
	WR4(sc, RTC_SCCR, RTC_SR_SECEV);

	return (0);
}
Example #11
0
/*
 * Set the time of day clock based on the value of the struct timespec arg.
 * Return 0 on success, an error number otherwise.
 */
int
ds1553_settime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct ds1553_softc *sc;
	uint8_t control;

	sc = device_get_softc(dev);
	bzero(&ct, sizeof(struct clocktime));

	/* Accuracy is only one second. */
	if (ts->tv_nsec >= 500000000)
		ts->tv_sec++;
	ts->tv_nsec = 0;
	clock_ts_to_ct(ts, &ct);

	ct.year -= sc->year_offset;

	mtx_lock_spin(&sc->sc_mtx);

	/* Halt updates to external registers */
	control = (*sc->sc_read)(dev, DS1553_OFF_CONTROL) | DS1553_BIT_WRITE;
	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);

	(*sc->sc_write)(dev, DS1553_OFF_SECONDS, TOBCD(ct.sec) &
	    DS1553_MASK_SECONDS);
	(*sc->sc_write)(dev, DS1553_OFF_MINUTES, TOBCD(ct.min) &
	    DS1553_MASK_MINUTES);
	(*sc->sc_write)(dev, DS1553_OFF_HOURS, TOBCD(ct.hour) &
	    DS1553_MASK_HOUR);
	(*sc->sc_write)(dev, DS1553_OFF_DAYOFWEEK, TOBCD(ct.dow + 1) &
	    DS1553_MASK_DAYOFWEEK);
	(*sc->sc_write)(dev, DS1553_OFF_DATE, TOBCD(ct.day) &
	    DS1553_MASK_DATE);
	(*sc->sc_write)(dev, DS1553_OFF_MONTH, TOBCD(ct.mon) &
	    DS1553_MASK_MONTH);
	(*sc->sc_write)(dev, DS1553_OFF_YEAR, TOBCD(ct.year));

	/* Resume updates to external registers */
	control &= ~DS1553_BIT_WRITE;
	(*sc->sc_write)(dev, DS1553_OFF_CONTROL, control);

	mtx_unlock_spin(&sc->sc_mtx);

	return (0);
}
Example #12
0
static int
pcf2123_rtc_settime(device_t dev, struct timespec *ts)
{
    struct clocktime ct;
    struct pcf2123_rtc_softc *sc;
    struct spi_command cmd;
    unsigned char rxTimedate[8];
    unsigned char txTimedate[8];
    int err;

    sc = device_get_softc(dev);

    /* Resolution: 1 sec */
    if (ts->tv_nsec >= 500000000)
        ts->tv_sec++;
    ts->tv_nsec = 0;
    clock_ts_to_ct(ts, &ct);

    memset(&cmd, 0, sizeof(cmd));
    memset(rxTimedate, 0, sizeof(rxTimedate));
    memset(txTimedate, 0, sizeof(txTimedate));

    /* Start reading from seconds */
    cmd.rx_cmd = rxTimedate;
    cmd.tx_cmd = txTimedate;
    cmd.rx_cmd_sz = sizeof(rxTimedate);
    cmd.tx_cmd_sz = sizeof(txTimedate);

    /*
     * Counter is stopped when access to time registers is in progress
     * So there is no need to stop/start counter
     */
    txTimedate[0] = PCF2123_WRITE(PCF2123_REG_SECONDS);
    txTimedate[1] = TOBCD(ct.sec);
    txTimedate[2] = TOBCD(ct.min);
    txTimedate[3] = TOBCD(ct.hour);
    txTimedate[4] = TOBCD(ct.day);
    txTimedate[5] = TOBCD(ct.dow);
    txTimedate[6] = TOBCD(ct.mon);
    txTimedate[7] = TOBCD(ct.year - YEAR_BASE);

    err = SPIBUS_TRANSFER(device_get_parent(dev), dev, &cmd);
    DELAY(PCF2123_DELAY);

    return (err);
}
Example #13
0
static int
nexus_settime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	struct efi_tm tm;

	efi_get_time(&tm);

	clock_ts_to_ct(ts, &ct);
	tm.tm_nsec = ts->tv_nsec;
	tm.tm_sec = ct.sec;
	tm.tm_min = ct.min;
	tm.tm_hour = ct.hour;
	tm.tm_year = ct.year;
	tm.tm_mon = ct.mon;
	tm.tm_mday = ct.day;
	return (efi_set_time(&tm));
}
Example #14
0
static int
rtas_settime(device_t dev, struct timespec *ts)
{
    struct clocktime ct;
    cell_t token, status;
    int error;

    token = rtas_token_lookup("set-time-of-day");
    if (token == -1)
        return (ENXIO);

    clock_ts_to_ct(ts, &ct);
    error = rtas_call_method(token, 7, 1, ct.year, ct.mon, ct.day, ct.hour,
                             ct.min, ct.sec, ct.nsec, &status);
    if (error < 0)
        return (ENXIO);
    if (status != 0)
        return (((int)status < 0) ? ENXIO : EAGAIN);

    return (0);
}
Example #15
0
static int
pcf8563_settime(device_t dev, struct timespec *ts)
{
	struct clocktime ct;
	uint8_t val[PCF8563_NCLOCKREGS];
	struct iic_msg msgs[] = {
		{ 0, IIC_M_WR, PCF8563_NCLOCKREGS - 1, &val[PCF8563_R_CS2] }
	};
	struct pcf8563_softc *sc;
	int error;

	sc = device_get_softc(dev);
	val[PCF8563_R_CS2] = PCF8563_R_SECOND;	/* abuse */
	/* Accuracy is only one second. */
	if (ts->tv_nsec >= 500000000)
		ts->tv_sec++;
	ts->tv_nsec = 0;
	clock_ts_to_ct(ts, &ct);
	val[PCF8563_R_SECOND] = TOBCD(ct.sec);
	val[PCF8563_R_MINUTE] = TOBCD(ct.min);
	val[PCF8563_R_HOUR] = TOBCD(ct.hour);
	val[PCF8563_R_DAY] = TOBCD(ct.day);
	val[PCF8563_R_WEEKDAY] = ct.dow;
	val[PCF8563_R_MONTH] = TOBCD(ct.mon);
	val[PCF8563_R_YEAR] = TOBCD(ct.year % 100);
	if ((sc->sc_flags & PCF8563_CPOL) != 0) {
		if (ct.year >= 100 + sc->sc_year0)
			val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C;
	} else if (ct.year < 100 + sc->sc_year0)
			val[PCF8563_R_MONTH] |= PCF8563_R_MONTH_C;

	msgs[0].slave = sc->sc_addr;
	error = iicbus_transfer(dev, msgs, nitems(msgs));
	if (error != 0)
		device_printf(dev, "%s: cannot write RTC\n", __func__);

	return (error);
}
Example #16
0
static int
s3c2xx0_rtc_settime(device_t dev, struct timespec *ts)
{
	struct s3c2xx0_rtc_softc *sc;
	struct clocktime ct;

	sc = device_get_softc(dev);

	/* Resolution: 1 sec */
	if (ts->tv_nsec >= 500000000)
		ts->tv_sec++;
	ts->tv_nsec = 0;
	clock_ts_to_ct(ts, &ct);

	bus_write_1(sc->mem_res, RTC_BCDSEC, TOBCD(ct.sec));
	bus_write_1(sc->mem_res, RTC_BCDMIN, TOBCD(ct.min));
	bus_write_1(sc->mem_res, RTC_BCDHOUR, TOBCD(ct.hour));
	bus_write_1(sc->mem_res, RTC_BCDDATE, TOBCD(ct.day));
	bus_write_1(sc->mem_res, RTC_BCDDAY, TOBCD(ct.dow));
	bus_write_1(sc->mem_res, RTC_BCDMON, TOBCD(ct.mon));
	bus_write_1(sc->mem_res, RTC_BCDYEAR, TOBCD(ct.year - YEAR_BASE));

	return (0);
}
Example #17
0
static int
load_fw(struct tegra_xhci_softc *sc)
{
	const struct firmware *fw;
	const struct tegra_xusb_fw_hdr *fw_hdr;
	vm_paddr_t fw_paddr, fw_base;
	vm_offset_t fw_vaddr;
	vm_size_t fw_size;
	uint32_t code_tags, code_size;
	struct clocktime fw_clock;
	struct timespec	fw_timespec;
	int i;

	/* Reset ARU */
	FPCI_WR4(sc, XUSB_CFG_ARU_RST, ARU_RST_RESET);
	DELAY(3000);

	/* Check if FALCON already runs */
	if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO) != 0) {
		device_printf(sc->dev,
		    "XUSB CPU is already loaded, CPUCTL: 0x%08X\n",
			 CSB_RD4(sc, XUSB_FALCON_CPUCTL));
		return (0);
	}

	fw = firmware_get(sc->fw_name);
	if (fw == NULL) {
		device_printf(sc->dev, "Cannot read xusb firmware\n");
		return (ENOENT);
	}

	/* Allocate uncached memory and copy firmware into. */
	fw_hdr = (const struct tegra_xusb_fw_hdr *)fw->data;
	fw_size = fw_hdr->fwimg_len;

	fw_vaddr = kmem_alloc_contig(kernel_arena, fw_size,
	    M_WAITOK, 0, -1UL, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE);
	fw_paddr = vtophys(fw_vaddr);
	fw_hdr = (const struct tegra_xusb_fw_hdr *)fw_vaddr;
	memcpy((void *)fw_vaddr, fw->data, fw_size);

	firmware_put(fw, FIRMWARE_UNLOAD);
	sc->fw_vaddr = fw_vaddr;
	sc->fw_size = fw_size;

	/* Setup firmware physical address and size. */
	fw_base = fw_paddr + sizeof(*fw_hdr);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_ATTR, fw_size);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_LO, fw_base & 0xFFFFFFFF);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_ILOAD_BASE_HI, (uint64_t)fw_base >> 32);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_APMAP, APMAP_BOOTPATH);

	/* Invalidate full L2IMEM context. */
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG,
	    L2IMEMOP_INVALIDATE_ALL);

	/* Program load of L2IMEM by boot code. */
	code_tags = howmany(fw_hdr->boot_codetag, XUSB_CSB_IMEM_BLOCK_SIZE);
	code_size = howmany(fw_hdr->boot_codesize, XUSB_CSB_IMEM_BLOCK_SIZE);
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_SIZE,
	    L2IMEMOP_SIZE_OFFSET(code_tags) |
	    L2IMEMOP_SIZE_SIZE(code_size));

	/* Execute L2IMEM boot code fetch. */
	CSB_WR4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_TRIG,
	    L2IMEMOP_LOAD_LOCKED_RESULT);

	/* Program FALCON auto-fill range and block count */
	CSB_WR4(sc, XUSB_FALCON_IMFILLCTL, code_size);
	CSB_WR4(sc, XUSB_FALCON_IMFILLRNG1,
	    IMFILLRNG1_TAG_LO(code_tags) |
	    IMFILLRNG1_TAG_HI(code_tags + code_size));

	CSB_WR4(sc, XUSB_FALCON_DMACTL, 0);
	/* Wait for CPU */
	for (i = 500; i > 0; i--) {
		if (CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT) &
		     L2IMEMOP_RESULT_VLD)
			break;
		DELAY(100);
	}
	if (i <= 0) {
		device_printf(sc->dev, "Timedout while wating for DMA, "
		    "state: 0x%08X\n",
		    CSB_RD4(sc, XUSB_CSB_MEMPOOL_L2IMEMOP_RESULT));
		return (ETIMEDOUT);
	}

	/* Boot FALCON cpu */
	CSB_WR4(sc, XUSB_FALCON_BOOTVEC, fw_hdr->boot_codetag);
	CSB_WR4(sc, XUSB_FALCON_CPUCTL, CPUCTL_STARTCPU);

	/* Wait for CPU */
	for (i = 50; i > 0; i--) {
		if (CSB_RD4(sc, XUSB_FALCON_CPUCTL) == CPUCTL_STOPPED)
			break;
		DELAY(100);
	}
	if (i <= 0) {
		device_printf(sc->dev, "Timedout while wating for FALCON cpu, "
		    "state: 0x%08X\n", CSB_RD4(sc, XUSB_FALCON_CPUCTL));
		return (ETIMEDOUT);
	}

	fw_timespec.tv_sec = fw_hdr->fwimg_created_time;
	fw_timespec.tv_nsec = 0;
	clock_ts_to_ct(&fw_timespec, &fw_clock);
	device_printf(sc->dev,
	    " Falcon firmware version: %02X.%02X.%04X,"
	    " (%d/%d/%d %d:%02d:%02d UTC)\n",
	    (fw_hdr->version_id >> 24) & 0xFF,(fw_hdr->version_id >> 15) & 0xFF,
	    fw_hdr->version_id & 0xFFFF,
	    fw_clock.day, fw_clock.mon, fw_clock.year,
	    fw_clock.hour, fw_clock.min, fw_clock.sec);

	return (0);
}