Add EC component for SMSC MEC1308/1310

Change-Id: I92109fb633a1a3090b4b1767dd119b8c8a1b5f81
Signed-off-by: Duncan Laurie <dlaurie@google.com>
Signed-off-by: Stefan Reinauer <reinauer@google.com>
Reviewed-on: http://review.coreboot.org/828
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
Stefan Reinauer 2012-03-30 17:06:43 -07:00 committed by Stefan Reinauer
parent b0dd1d91f4
commit 020b22a5c4
12 changed files with 725 additions and 1 deletions

View File

@ -1,2 +1,3 @@
source src/ec/acpi/Kconfig
source src/ec/lenovo/Kconfig
source src/ec/smsc/Kconfig

View File

@ -1,2 +1,2 @@
subdirs-$(CONFIG_EC_ACPI) += acpi
subdirs-y += lenovo
subdirs-y += lenovo smsc

1
src/ec/smsc/Kconfig Normal file
View File

@ -0,0 +1 @@
source src/ec/smsc/mec1308/Kconfig

1
src/ec/smsc/Makefile.inc Normal file
View File

@ -0,0 +1 @@
subdirs-$(CONFIG_EC_SMSC_MEC1308) += mec1308

View File

@ -0,0 +1,4 @@
config EC_SMSC_MEC1308
bool
help
Shared memory mailbox interface to SMSC MEC1308 Embedded Controller.

View File

@ -0,0 +1,2 @@
driver-y += ec.c
smm-y += ec.c

View File

@ -0,0 +1,38 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
// Scope (EC0)
Device (AC)
{
Name (_HID, "ACPI0003")
Name (_PCL, Package () { \_SB })
Method (_PSR)
{
Return (ACEX)
}
Method (_STA)
{
Return (0x0F)
}
}

View File

@ -0,0 +1,196 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
/*
* The mainboard must define strings in the root scope to
* report device-specific battery information to the OS.
*
* BATM: Model
* BATS: Serial
* BATV: Vendor
*/
// Scope (EC0)
Device (BAT0)
{
Name (_HID, EISAID ("PNP0C0A"))
Name (_UID, 1)
Name (_PCL, Package () { \_SB })
Name (PBIF, Package () {
0x00000001, // Power Unit: mAh
0xFFFFFFFF, // Design Capacity
0xFFFFFFFF, // Last Full Charge Capacity
0x00000001, // Battery Technology: Rechargeable
0xFFFFFFFF, // Design Voltage
0x00000003, // Design Capacity of Warning
0xFFFFFFFF, // Design Capacity of Low
0x00000001, // Capacity Granularity 1
0x00000001, // Capacity Granularity 2
"", // Model Number
"", // Serial Number
"LION", // Battery Type
"" // OEM Information
})
Name (PBST, Package () {
0x00000000, // Battery State
0xFFFFFFFF, // Battery Present Rate
0xFFFFFFFF, // Battery Remaining Capacity
0xFFFFFFFF, // Battery Present Voltage
})
Name (BSTP, Zero)
// Workaround for full battery status, enabled by default
Name (BFWK, One)
// Method to enable full battery workaround
Method (BFWE)
{
Store (One, BFWK)
}
// Method to disable full battery workaround
Method (BFWD)
{
Store (Zero, BFWK)
}
// Swap bytes in a word
Method (SWAB, 1, NotSerialized)
{
ShiftRight (Arg0, 8, Local0)
ShiftLeft (Arg0, 8, Local1)
And (Local1, 0xFF00, Local1)
Or (Local0, Local1, Local0)
If (LEqual (Local0, 0xFFFF)) {
Store (0xFFFFFFFF, Local0)
}
Return (Local0)
}
Method (_STA, 0, Serialized)
{
If (BTEX) {
Return (0x1F)
} Else {
Return (0x0F)
}
}
Method (_BIF, 0, Serialized)
{
// Update fields from EC
Store (SWAB (BTDA), Index (PBIF, 1))
Store (SWAB (BTDF), Index (PBIF, 2))
Store (SWAB (BTDV), Index (PBIF, 4))
Store (SWAB (BTDL), Index (PBIF, 6))
// Get battery info from mainboard
Store (\BATM, Index (PBIF, 9))
Store (\BATS, Index (PBIF, 10))
Store (\BATV, Index (PBIF, 12))
Return (PBIF)
}
Method (_BST, 0, Serialized)
{
//
// 0: BATTERY STATE
//
// bit 0 = discharging
// bit 1 = charging
// bit 2 = critical level
//
// Get battery state from EC
Store (BTST, Local0)
Store (Zero, Local1)
// Check if AC is present
If (ACEX) {
// Set only charging/discharging bits
And (Local0, 0x03, Local1)
} Else {
// Always discharging when on battery power
Store (0x01, Local1)
}
// Flag if the battery level is critical
And (Local0, 0x04, Local4)
Or (Local1, Local4, Local1)
Store (Local1, Index (PBST, 0))
// Notify if battery state has changed since last time
If (LNotEqual (Local1, BSTP)) {
Store (Local1, BSTP)
Notify (BAT0, 0x80)
}
//
// 1: BATTERY PRESENT RATE
//
Store (SWAB (BTPR), Local1)
If (LAnd (LNotEqual (Local1, 0xFFFFFFFF),
LGreaterEqual (Local1, 0x8000))) {
Xor (Local1, 0xFFFF, Local1)
Increment (Local1)
}
Store (Local1, Index (PBST, 1))
//
// 2: BATTERY REMAINING CAPACITY
//
Store (SWAB (BTRA), Local1)
If (LAnd (LNotEqual (Local1, 0xFFFFFFFF),
LGreaterEqual (Local1, 0x8000))) {
Xor (Local1, 0xFFFF, Local1)
Increment (Local1)
}
If (LAnd (BFWK, LAnd (ACEX, LNot (Local0)))) {
// On AC power and battery is neither charging
// nor discharging. Linux expects a full battery
// to report same capacity as last full charge.
// https://bugzilla.kernel.org/show_bug.cgi?id=12632
Store (SWAB (BTDF), Local2)
// See if within ~3% of full
ShiftRight (Local2, 5, Local3)
If (LAnd (LGreater (Local1, Subtract (Local2, Local3)),
LLess (Local1, Add (Local2, Local3))))
{
Store (Local2, Local1)
}
}
Store (Local1, Index (PBST, 2))
//
// 3: BATTERY PRESENT VOLTAGE
//
Store (SWAB (BTVO), Index (PBST, 3))
Return (PBST)
}
}

View File

@ -0,0 +1,272 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* The mainboard must define a PNOT method to handle power
* state notifications and Notify CPU device objects to
* re-evaluate their _PPC and _CST tables.
*/
Device (EC0)
{
Name (_HID, EISAID ("PNP0C09"))
Name (_UID, 1)
Name (_GPE, EC_GPE) // GPE for Runtime SCI
OperationRegion (ERAM, EmbeddedControl, 0x00, 0xff)
Field (ERAM, ByteAcc, Lock, Preserve)
{
Offset (0x80),
BTEX, 1, // Battery Exists
, 1,
ACEX, 1, // AC Exists
, 5,
Offset (0x83),
LIDS, 1, // Lid Switch State
, 7,
BTST, 8, // Battery State
Offset (0xA2),
BTRA, 16, // Battery Remaining Capacity
BTPR, 16, // Battery Present Rate
BTVO, 16, // Battery Present Voltage
Offset (0xB0),
BTDA, 16, // Battery Design Capacity
BTDF, 16, // Battery Last Full Charge Capacity
BTDV, 16, // Battery Design Voltage
BTDL, 16, // Battery Design Low
Offset (0xC0),
CPUT, 8, // CPU Temperature
Offset (0xCA),
FSL0, 1, // Fan Speed Level 0
FSL1, 1, // Fan Speed Level 1
FSL2, 1, // Fan Speed Level 2
FSL3, 1, // Fan Speed Level 3
FSL4, 1, // Fan Speed Level 4
, 2,
FCOS, 1, // Fan Speed OS Control
}
Method (_CRS, 0, NotSerialized)
{
Name (ECMD, ResourceTemplate()
{
IO (Decode16, 0x62, 0x62, 0, 1)
IO (Decode16, 0x66, 0x66, 0, 1)
})
Return (ECMD)
}
Method (_REG, 2, NotSerialized)
{
// Initialize AC power state
Store (ACEX, \PWRS)
// Initialize LID switch state
Store (LIDS, \LIDS)
// Enable OS control of fan speed
Store (One, FCOS)
// Force a read of CPU temperature
Store (CPUT, Local0)
}
PowerResource (FNP0, 0, 0)
{
Method (_STA) { Return (FSL0) }
Method (_ON) {
If (FCOS) {
Store (One, FSL0)
Store (0, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
Method (_OFF) {
If (FCOS) {
Store (Zero, FSL0)
Store (1, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
}
PowerResource (FNP1, 0, 0)
{
Method (_STA) { Return (FSL1) }
Method (_ON) {
If (FCOS) {
Store (One, FSL1)
Store (1, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
Method (_OFF) {
If (FCOS) {
Store (Zero, FSL1)
Store (2, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
}
PowerResource (FNP2, 0, 0)
{
Method (_STA) { Return (FSL2) }
Method (_ON) {
If (FCOS) {
Store (One, FSL2)
Store (2, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
Method (_OFF) {
If (FCOS) {
Store (Zero, FSL2)
Store (3, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
}
PowerResource (FNP3, 0, 0)
{
Method (_STA) { Return (FSL3) }
Method (_ON) {
If (FCOS) {
Store (One, FSL3)
Store (3, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
Method (_OFF) {
If (FCOS) {
Store (Zero, FSL3)
Store (4, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
}
PowerResource (FNP4, 0, 0)
{
Method (_STA) { Return (FSL4) }
Method (_ON) {
If (FCOS) {
Store (One, FSL4)
Store (4, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
Method (_OFF) {
If (FCOS) {
Store (Zero, FSL4)
Store (5, \FLVL)
Notify (\_TZ.THRM, 0x81)
}
}
}
Device (FAN0)
{
Name (_HID, EISAID ("PNP0C0B"))
Name (_UID, 0)
Name (_PR0, Package () { FNP0 })
}
Device (FAN1)
{
Name (_HID, EISAID ("PNP0C0B"))
Name (_UID, 1)
Name (_PR0, Package () { FNP1 })
}
Device (FAN2)
{
Name (_HID, EISAID ("PNP0C0B"))
Name (_UID, 2)
Name (_PR0, Package () { FNP2 })
}
Device (FAN3)
{
Name (_HID, EISAID ("PNP0C0B"))
Name (_UID, 3)
Name (_PR0, Package () { FNP3 })
}
Device (FAN4)
{
Name (_HID, EISAID ("PNP0C0B"))
Name (_UID, 4)
Name (_PR0, Package () { FNP4 })
}
// AC Power Connected
Method (_Q51, 0, NotSerialized)
{
Store (One, \PWRS)
Notify (AC, 0x80)
\PNOT ()
}
// AC Power Removed
Method (_Q52, 0, NotSerialized)
{
Store (Zero, \PWRS)
Notify (AC, 0x80)
\PNOT ()
}
// Battery State Change
Method (_Q53, 0, NotSerialized)
{
Notify (BAT0, 0x80)
Notify (BAT0, 0x81)
}
// Battery State Change
Method (_Q54, 0, NotSerialized)
{
Notify (BAT0, 0x80)
Notify (BAT0, 0x81)
}
// Power State Change
Method (_Q55, 0, NotSerialized)
{
\PNOT ()
}
// Lid Switch Event
Method (_Q5E, 0, NotSerialized)
{
Store (LIDS, \LIDS)
Notify (\_SB.LID0, 0x80)
}
// Lid Switch Event
Method (_Q5F, 0, NotSerialized)
{
Store (LIDS, \LIDS)
Notify (\_SB.LID0, 0x80)
}
#include "ac.asl"
#include "battery.asl"
}

View File

@ -0,0 +1,33 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#ifndef _EC_SMSC_MEC1308_CHIP_H
#define _EC_SMSC_MEC1308_CHIP_H
struct ec_smsc_mec1308_config
{
u16 mailbox_port;
};
struct chip_operations;
extern struct chip_operations ec_smsc_mec1308_ops;
#endif /* _EC_SMSC_MEC1308_CHIP_H */

135
src/ec/smsc/mec1308/ec.c Normal file
View File

@ -0,0 +1,135 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of
* the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
#include <console/console.h>
#include <device/device.h>
#include <arch/io.h>
#include <delay.h>
#include "ec.h"
#include "chip.h"
static u16 ec_cmd_reg = 0;
static u16 ec_data_reg = 0;
static inline u8 __ec_read(u8 addr)
{
outb(addr, ec_cmd_reg);
return inb(ec_data_reg);
}
static inline void __ec_write(u8 addr, u8 data)
{
outb(addr, ec_cmd_reg);
outb(data, ec_data_reg);
}
static int ec_ready(void)
{
u16 timeout = EC_TIMEOUT;
if (!ec_cmd_reg || !ec_data_reg) {
printk(BIOS_DEBUG, "Invalid ports: cmd=0x%x data=0x%x\n",
ec_cmd_reg, ec_data_reg);
return -1;
}
while (__ec_read(EC_MAILBOX_COMMAND) != 0 && --timeout) {
udelay(10);
if ((timeout & 0xff) == 0)
printk(BIOS_SPEW, ".");
}
if (!timeout) {
printk(BIOS_DEBUG, "Timeout waiting for EC to be ready.\n");
return -1;
}
return 0;
}
int send_ec_command(u8 command)
{
if (ec_ready() < 0)
return -1;
__ec_write(EC_MAILBOX_COMMAND, command);
return ec_ready();
}
int send_ec_command_data(u8 command, u8 data)
{
if (ec_ready() < 0)
return -1;
__ec_write(EC_MAILBOX_DATA, data);
__ec_write(EC_MAILBOX_COMMAND, command);
return ec_ready();
}
u8 read_ec_command_byte(u8 command)
{
send_ec_command(command);
return __ec_read(EC_MAILBOX_DATA);
}
u8 ec_read(u8 addr)
{
if (send_ec_command_data(EC_RAM_READ, addr) < 0)
return 0;
return __ec_read(EC_MAILBOX_DATA);
}
int ec_write(u8 addr, u8 data)
{
if (ec_ready() < 0)
return -1;
__ec_write(EC_MAILBOX_DATA, addr);
__ec_write(EC_MAILBOX_DATA_H, data);
__ec_write(EC_MAILBOX_COMMAND, EC_RAM_WRITE);
return ec_ready();
}
void ec_set_bit(u8 addr, u8 bit)
{
ec_write(addr, ec_read(addr) | (1 << bit));
}
void ec_clr_bit(u8 addr, u8 bit)
{
ec_write(addr, ec_read(addr) & ~(1 << bit));
}
void ec_set_ports(u16 cmd_reg, u16 data_reg)
{
ec_cmd_reg = cmd_reg;
ec_data_reg = data_reg;
}
static void mec1308_enable(device_t dev)
{
struct ec_smsc_mec1308_config *conf = dev->chip_info;
if (conf->mailbox_port) {
ec_cmd_reg = conf->mailbox_port;
ec_data_reg = conf->mailbox_port + 1;
}
}
struct chip_operations ec_smsc_mec1308_ops = {
CHIP_NAME("SMSC MEC1308 EC Mailbox Interface")
.enable_dev = mec1308_enable
};

41
src/ec/smsc/mec1308/ec.h Normal file
View File

@ -0,0 +1,41 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2011 The Chromium OS Authors. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Mailbox EC communication interface for SMSC MEC1308 Embedded Controller.
*/
#ifndef _EC_SMSC_MEC1308_EC_H
#define _EC_SMSC_MEC1308_EC_H
#define EC_TIMEOUT 0xfff
#define EC_MAILBOX_COMMAND 0x82 // Send a command
#define EC_MAILBOX_DATA 0x84 // Send data with a command
#define EC_MAILBOX_DATA_H 0x85 // Send data with a command
#define EC_RAM_READ 0x88 // Read from RAM
#define EC_RAM_WRITE 0x89 // Write to RAM
int send_ec_command(u8 command);
int send_ec_command_data(u8 command, u8 data);
u8 read_ec_command_byte(u8 command);
u8 ec_read(u8 addr);
int ec_write(u8 addr, u8 data);
void ec_set_bit(u8 addr, u8 bit);
void ec_clr_bit(u8 addr, u8 bit);
void ec_set_ports(u16 cmd_reg, u16 data_reg);
#endif /* _EC_SMSC_MEC1308_EC_H */