mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-08 08:31:52 +00:00
BUG=chrome-os-partner:7498
TEST=powerled {off, red, yellow, green}
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Change-Id: I48beaad94d75c0ec30a969ea4b0e35f54e052085
101 lines
2.5 KiB
C
101 lines
2.5 KiB
C
/* Copyright (c) 2012 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.
|
|
*/
|
|
|
|
/* Power LED control for Chrome EC */
|
|
|
|
#include "console.h"
|
|
#include "onewire.h"
|
|
#include "power_led.h"
|
|
#include "timer.h"
|
|
#include "uart.h"
|
|
#include "util.h"
|
|
|
|
#define POWERLED_RETRIES 10
|
|
|
|
static const uint8_t led_masks[POWERLED_COLOR_COUNT] = {0xff, 0xfe, 0xfc, 0xfd};
|
|
static const char * const color_names[POWERLED_COLOR_COUNT] = {
|
|
"off", "red", "yellow", "green"};
|
|
|
|
|
|
/* Set the power LED GPIO controller outputs to the specified mask. */
|
|
static int powerled_set_mask(int mask)
|
|
{
|
|
int rv;
|
|
|
|
/* Reset the 1-wire bus */
|
|
rv = onewire_reset();
|
|
if (rv)
|
|
return rv;
|
|
|
|
/* Skip ROM, since only one device */
|
|
onewire_write(0xcc);
|
|
|
|
/* Write and turn on the LEDs */
|
|
onewire_write(0x5a);
|
|
onewire_write(mask);
|
|
onewire_write(~mask); /* Repeat inverted */
|
|
|
|
rv = onewire_read(); /* Confirmation byte */
|
|
if (rv != 0xaa)
|
|
return EC_ERROR_UNKNOWN;
|
|
|
|
/* The next byte is a read-back of the chip status. Since we're only
|
|
* using lines as outputs, we can ignore it. */
|
|
return EC_SUCCESS;
|
|
}
|
|
|
|
|
|
int powerled_set(enum powerled_color color)
|
|
{
|
|
int rv = EC_SUCCESS;
|
|
int i;
|
|
|
|
/* 1-wire communication can fail for timing reasons in the current
|
|
* system. We have a limited timing window to send/receive bits, but
|
|
* we can't disable interrupts for the rest of the system to guarantee
|
|
* we hit that window. Instead, simply retry the low-level command a
|
|
* few times. */
|
|
for (i = 0; i < POWERLED_RETRIES; i++) {
|
|
rv = powerled_set_mask(led_masks[color]);
|
|
if (rv == EC_SUCCESS)
|
|
break;
|
|
|
|
/* Sleep for a bit between tries. This gives the 1-wire GPIO
|
|
* chip time to recover from the failed attempt, and allows
|
|
* lower-priority tasks a chance to run. */
|
|
usleep(100);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/* Console commands */
|
|
|
|
static int command_powerled(int argc, char **argv)
|
|
{
|
|
int i = POWERLED_COLOR_COUNT;
|
|
|
|
/* Pick a color, any color... */
|
|
if (argc >= 1) {
|
|
for (i = 0; i < POWERLED_COLOR_COUNT; i++) {
|
|
if (!strcasecmp(argv[1], color_names[i]))
|
|
break;
|
|
}
|
|
}
|
|
if (i >= POWERLED_COLOR_COUNT) {
|
|
uart_puts("Please specify a color:");
|
|
for (i = 0; i < POWERLED_COLOR_COUNT; i++)
|
|
uart_printf(" %s", color_names[i]);
|
|
uart_puts("\n");
|
|
return EC_ERROR_INVAL;
|
|
}
|
|
|
|
uart_printf("Setting power LED to %s...\n", color_names[i]);
|
|
return powerled_set(i);
|
|
}
|
|
DECLARE_CONSOLE_COMMAND(powerled, command_powerled);
|