blob: 5bd03bb8586a380d20275c7921e28f0bb667823e [file] [log] [blame]
/*
* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*/
/*
* Implementation of APIs provided by firmware and exported to vboot_reference.
* They includes debug output, memory allocation, timer and delay, etc.
*/
#include <common.h>
#include <asm/global_data.h>
#include <malloc.h>
#include <cros/common.h>
#include <cros/cros_init.h>
#include <cros/hda_codec.h>
#include <cros/power_management.h>
#include <sound.h>
/* Import the definition of vboot_wrapper interfaces. */
#include <vboot_api.h>
DECLARE_GLOBAL_DATA_PTR;
#define UINT32_MAX (~0UL)
#define TICKS_PER_MSEC (CONFIG_SYS_HZ / 1000)
#define MAX_MSEC_PER_LOOP ((uint32_t)((UINT32_MAX / TICKS_PER_MSEC) / 2))
static void system_abort(void)
{
/* Wait for 3 seconds to let users see error messages and reboot. */
VbExSleepMs(3000);
cold_reboot();
}
void *cros_memalign_cache(size_t n)
{
static unsigned int dcache_line_size;
if (!dcache_line_size) {
/* Select cache line size based on available information */
#ifdef CONFIG_ARM
dcache_line_size = dcache_get_line_size();
#elif defined CACHE_LINE_SIZE
dcache_line_size = CACHE_LINE_SIZE;
#else
dcache_line_size = __BIGGEST_ALIGNMENT__;
#endif
}
return memalign(dcache_line_size, n);
}
void VbExError(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
system_abort();
}
void VbExDebug(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
}
void *VbExMalloc(size_t size)
{
void *ptr = cros_memalign_cache(size);
if (!ptr) {
VbExError("Internal malloc error.");
}
return ptr;
}
void VbExFree(void *ptr)
{
free(ptr);
}
void VbExSleepMs(uint32_t msec)
{
uint32_t delay, start;
/*
* Can't use entire UINT32_MAX range in the max delay, because it
* pushes get_timer() too close to wraparound. So use /2.
*/
while(msec > MAX_MSEC_PER_LOOP) {
VbExSleepMs(MAX_MSEC_PER_LOOP);
msec -= MAX_MSEC_PER_LOOP;
}
delay = msec * TICKS_PER_MSEC;
start = get_timer(0);
while (get_timer(start) < delay)
udelay(100);
}
VbError_t VbExBeep(uint32_t msec, uint32_t frequency)
{
#if defined(CONFIG_SYS_COREBOOT)
if (frequency)
enable_beep(frequency);
else
disable_beep();
if (msec > 0) {
VbExSleepMs(msec);
disable_beep();
}
return VBERROR_SUCCESS;
#elif defined CONFIG_SOUND
int ret;
VBDEBUG("About to beep for %d ms at %d Hz.\n", msec, frequency);
if (!msec || !frequency) {
if (msec)
VbExSleepMs(msec);
return VBERROR_NO_BACKGROUND_SOUND;
}
ret = sound_init(gd->fdt_blob);
if (ret) {
VbExError("Failed to initialize sound.\n");
return VBERROR_NO_SOUND;
}
ret = sound_play(msec, frequency);
if (ret) {
VbExError("Failed to play beep.\n");
return VBERROR_NO_SOUND;
}
return VBERROR_SUCCESS;
#else
/* TODO Implement it later. */
VbExSleepMs(msec);
VBDEBUG("Beep!\n");
return VBERROR_NO_SOUND;
#endif
}
int Memcmp(const void *src1, const void *src2, size_t n)
{
return memcmp(src1, src2, n);
}
void *Memcpy(void *dest, const void *src, uint64_t n)
{
return memcpy(dest, src, (size_t) n);
}
void *Memset(void *d, const uint8_t c, uint64_t n)
{
return memset(d, c, n);
}