mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-01 21:02:27 +00:00
Add support for 1-wire protocol and power adapter LEDs
BUG=chrome-os-partner:7498
TEST=powerled {off, red, yellow, green}
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Change-Id: I48beaad94d75c0ec30a969ea4b0e35f54e052085
This commit is contained in:
@@ -30,7 +30,6 @@ const struct gpio_info gpio_list[GPIO_COUNT] = {
|
||||
{"LID_SWITCHn", LM4_GPIO_K, (1<<5), GPIO_INT_BOTH,
|
||||
power_button_interrupt},
|
||||
/* Other inputs */
|
||||
{"POWER_ONEWIRE", LM4_GPIO_H, (1<<2), 0, NULL},
|
||||
{"THERMAL_DATA_READYn", LM4_GPIO_B, (1<<4), 0, NULL},
|
||||
{"AC_PRESENT", LM4_GPIO_H, (1<<3), 0, NULL},
|
||||
{"PCH_BKLTEN", LM4_GPIO_J, (1<<3), GPIO_INT_BOTH,
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#define __BOARD_H
|
||||
|
||||
/* Optional features */
|
||||
#define CONFIG_ONEWIRE
|
||||
#define CONFIG_PECI
|
||||
#define CONFIG_TMP006
|
||||
#define CONFIG_POWER_LED
|
||||
#define CONFIG_PSTORE
|
||||
#define CONFIG_TMP006
|
||||
|
||||
/* 66.667 Mhz clock frequency */
|
||||
#define CPU_CLOCK 66666667
|
||||
@@ -110,7 +112,6 @@ enum gpio_signal {
|
||||
/* Inputs with interrupt handlers are first for efficiency */
|
||||
GPIO_POWER_BUTTONn = 0, /* Power button */
|
||||
GPIO_LID_SWITCHn, /* Lid switch */
|
||||
GPIO_POWER_ONEWIRE, /* 1-wire interface to power adapter LEDs */
|
||||
GPIO_THERMAL_DATA_READYn, /* Data ready from I2C thermal sensor */
|
||||
/* Other inputs */
|
||||
GPIO_AC_PRESENT, /* AC power present */
|
||||
|
||||
@@ -13,6 +13,7 @@ chip-y+=clock.o gpio.o system.o uart.o
|
||||
chip-y+=watchdog.o eeprom.o hwtimer.o
|
||||
chip-$(CONFIG_FLASH)+=flash.o
|
||||
chip-$(CONFIG_LPC)+=lpc.o
|
||||
chip-$(CONFIG_ONEWIRE)+=onewire.o
|
||||
chip-$(CONFIG_PECI)+=peci.o
|
||||
chip-$(CONFIG_PWM)+=pwm.o
|
||||
chip-$(CONFIG_TEMP_SENSOR)+=chip_temp_sensor.o
|
||||
|
||||
140
chip/lm4/onewire.c
Normal file
140
chip/lm4/onewire.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* 1-wire interface module for Chrome EC */
|
||||
|
||||
#include "board.h"
|
||||
#include "gpio.h"
|
||||
#include "timer.h"
|
||||
#include "registers.h"
|
||||
|
||||
#define ONEWIRE_PIN (1<<2) /* One-wire pin mask (on GPIO H) */
|
||||
|
||||
/* Standard speed; all timings padded by 2 usec for safety.
|
||||
*
|
||||
* Note that these timing are actually _longer_ than legacy 1-wire standard
|
||||
* speed because we're running the 1-wire bus at 3.3V instead of 5V. */
|
||||
#define T_RSTL 602 /* Reset low pulse; 600-960 us */
|
||||
#define T_MSP 72 /* Presence detect sample time; 70-75 us */
|
||||
#define T_RSTH (68 + 260 + 5 + 2) /* Reset high; tPDHmax + tPDLmax + tRECmin */
|
||||
#define T_SLOT 70 /* Timeslot; >67 us */
|
||||
#define T_W0L 63 /* Write 0 low; 62-120 us */
|
||||
#define T_W1L 7 /* Write 1 low; 5-15 us */
|
||||
#define T_RL 7 /* Read low; 5-15 us */
|
||||
#define T_MSR 9 /* Read sample time; <15 us. Must be at least 200 ns after
|
||||
* T_RL since that's how long the signal takes to be pulled
|
||||
* up on our board. */
|
||||
|
||||
|
||||
/* Output low on the bus for <usec> us, then switch back to open-drain input */
|
||||
static void output0(int usec)
|
||||
{
|
||||
LM4_GPIO_DIR(LM4_GPIO_H) |= ONEWIRE_PIN;
|
||||
LM4_GPIO_DATA(LM4_GPIO_H, ONEWIRE_PIN) = 0;
|
||||
udelay(usec);
|
||||
LM4_GPIO_DIR(LM4_GPIO_H) &= ~ONEWIRE_PIN;
|
||||
}
|
||||
|
||||
|
||||
/* Read the signal line */
|
||||
static int readline(void)
|
||||
{
|
||||
return LM4_GPIO_DATA(LM4_GPIO_H, ONEWIRE_PIN) ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/* Read a bit */
|
||||
static int readbit(void)
|
||||
{
|
||||
int bit;
|
||||
|
||||
/* Output low */
|
||||
output0(T_RL);
|
||||
|
||||
/* Delay to let slave release the line if it wants to send a 1-bit */
|
||||
udelay(T_MSR - T_RL);
|
||||
|
||||
/* Read bit */
|
||||
bit = readline();
|
||||
|
||||
/* Delay to end of timeslot */
|
||||
udelay(T_SLOT - T_MSR);
|
||||
return bit;
|
||||
}
|
||||
|
||||
|
||||
/* Write a bit */
|
||||
static void writebit(int bit)
|
||||
{
|
||||
if (bit) {
|
||||
output0(T_W1L);
|
||||
udelay(T_SLOT - T_W1L);
|
||||
} else {
|
||||
output0(T_W0L);
|
||||
udelay(T_SLOT - T_W0L);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int onewire_reset(void)
|
||||
{
|
||||
/* Start transaction with master reset pulse */
|
||||
output0(T_RSTL);
|
||||
|
||||
/* Wait for presence detect sample time */
|
||||
udelay(T_MSP);
|
||||
/* Alternately, we could poll waiting for a 1-bit indicating our pulse
|
||||
* has let go, then poll up to max time waiting for a 0-bit indicating
|
||||
* the slave has responded. */
|
||||
if (readline() != 0)
|
||||
return EC_ERROR_UNKNOWN;
|
||||
|
||||
/* Wait for end of presence pulse */
|
||||
/* Alternately, we could poll waiting for a 1-bit */
|
||||
udelay(T_RSTH - T_MSP);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int onewire_read(void)
|
||||
{
|
||||
int data = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
data |= readbit() << i; /* LSB first */
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
void onewire_write(int data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
writebit((data >> i) & 0x01); /* LSB first */
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Initialization */
|
||||
|
||||
/* Configures GPIOs for the module. */
|
||||
static void configure_gpio(void)
|
||||
{
|
||||
/* Configure 1-wire pin as open-drain GPIO */
|
||||
gpio_set_alternate_function(LM4_GPIO_H, ONEWIRE_PIN, 0);
|
||||
LM4_GPIO_ODR(LM4_GPIO_H) |= ONEWIRE_PIN;
|
||||
}
|
||||
|
||||
|
||||
int onewire_init(void)
|
||||
{
|
||||
/* Configure GPIOs */
|
||||
configure_gpio();
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
@@ -20,6 +20,7 @@ common-$(CONFIG_TASK_THERMAL)+=thermal.o thermal_commands.o
|
||||
common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o temp_sensor_commands.o
|
||||
common-$(CONFIG_TMP006)+=tmp006.o
|
||||
common-$(CONFIG_LIGHTBAR)+=leds.o
|
||||
common-$(CONFIG_POWER_LED)+=power_led.o
|
||||
|
||||
# Board driver modules
|
||||
common-$(CONFIG_CHARGER_BQ24725)+=charger_bq24725.o
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "keyboard_scan.h"
|
||||
#include "lpc.h"
|
||||
#include "memory_commands.h"
|
||||
#include "onewire.h"
|
||||
#include "peci.h"
|
||||
#include "port80.h"
|
||||
#include "power_button.h"
|
||||
@@ -93,6 +94,9 @@ int main(void)
|
||||
#endif
|
||||
adc_init();
|
||||
usb_charge_init();
|
||||
#ifdef CONFIG_ONEWIRE
|
||||
onewire_init();
|
||||
#endif
|
||||
#ifdef CONFIG_CHARGER
|
||||
charger_init();
|
||||
#endif
|
||||
|
||||
100
common/power_led.c
Normal file
100
common/power_led.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/* 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);
|
||||
32
include/onewire.h
Normal file
32
include/onewire.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* 1-wire interface for Chrome EC */
|
||||
|
||||
/* Note that 1-wire communication is VERY latency-sensitive. If these
|
||||
* functions are run at low priority, communication may be garbled. However,
|
||||
* these functions are also slow enough (~1ms per call) that it's really not
|
||||
* desirable to put them at high priority. So make sure you check the
|
||||
* confirmation code from the slave for any communication, and retry a few
|
||||
* times in case of failure. */
|
||||
|
||||
#ifndef __CROS_EC_ONEWIRE_H
|
||||
#define __CROS_EC_ONEWIRE_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Initialize the module. */
|
||||
int onewire_init(void);
|
||||
|
||||
/* Reset the 1-wire bus. Returns error if presence detect fails. */
|
||||
int onewire_reset(void);
|
||||
|
||||
/* Read a byte from the 1-wire bus. Returns the byte. */
|
||||
int onewire_read(void);
|
||||
|
||||
/* Write a byte to the 1-wire bus. */
|
||||
void onewire_write(int data);
|
||||
|
||||
#endif /* __CROS_EC_ONEWIRE_H */
|
||||
24
include/power_led.h
Normal file
24
include/power_led.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* Power LED control for Chrome EC */
|
||||
|
||||
#ifndef __CROS_EC_POWER_LED_H
|
||||
#define __CROS_EC_POWER_LED_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
enum powerled_color {
|
||||
POWERLED_OFF = 0,
|
||||
POWERLED_RED,
|
||||
POWERLED_YELLOW,
|
||||
POWERLED_GREEN,
|
||||
POWERLED_COLOR_COUNT /* Number of colors, not a color itself */
|
||||
};
|
||||
|
||||
/* Set the power adapter LED to the specified color. */
|
||||
int powerled_set(enum powerled_color color);
|
||||
|
||||
#endif /* __CROS_EC_POWER_LED_H */
|
||||
Reference in New Issue
Block a user