From patchwork Fri Sep 29 13:09:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Hecht X-Patchwork-Id: 9978043 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 37E6160329 for ; Fri, 29 Sep 2017 13:13:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 237F62987C for ; Fri, 29 Sep 2017 13:13:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1857F2987E; Fri, 29 Sep 2017 13:13:12 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id F074C2987C for ; Fri, 29 Sep 2017 13:13:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=pkjC3eefsVigHqgvC3x7SZ4QVLKtRBR5319dOqgcRxA=; b=g0Tt6IzuOihaJ+1cZERJOYOFIm oq2IymXhHfj0lb2pC7sQlRsvYgMF450BBFeMP2XCMSpr+pL8iUEAnVUE4lioA5xSQXiUZ8PQXMEp/ +92Hmou5EqtqJRe/obvnrhjbdIxl1G2zOsEhbX5IrXER15sTp/laNDmNg+XMaCp0R+37kh5Ww9FgS i8AdMPy/TMpISl8UwGRhqetFfpWwDyWFSu7DzmUBPZR2FIZQCClosVEpJV+PaOGzTjpe4yfJHs54Y 4Q36JxbvTcvV+rdD+vur+90LxI8K7ANci3eXedoWs8F50d0Wy+REZbB59Xbh5IskG/5irlbQXwxGA cESQuuTg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1dxv6H-0001Nu-RO; Fri, 29 Sep 2017 13:13:05 +0000 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1dxv3L-0006Dl-Jj; Fri, 29 Sep 2017 13:10:22 +0000 Received: by mail-wm0-x241.google.com with SMTP id i124so3164804wmf.3; Fri, 29 Sep 2017 06:09:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=QEkbP61RlaSSRR7MGARfJfToxd26RCpCetAozHb4OnQ=; b=GB3DTnABkUUn3Jdp4i9NB0GXKxdHSUcg43jYaretcXmvpAFKGzjznkQftpIfg34HqC 2mRYy9dj8gKsjdKVbA1vOpHd3ygPU1ll5/cx0rAEDPOWO6aAQcvc/xu6rAZDTHIVcFrB QeEC/J8cg+rR1Qu+BcsLnhq+MFQ8el/gPm2ntoF73tjeZB6sOXUdXNGlOd8avC+aDkBH hz9QDa51Ryf3gZ5j3yYZsp6AKdQ47DWRYRYc63Yrbh7+BWmKgNQcdNNg+BmLFc/RHAVy jaNso+f/LucngY49MOoNO89gzjSEIl6LVN34VneIXlYJ5F+Pzc0jyA9YCcQX7+1tMo3w DEjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=QEkbP61RlaSSRR7MGARfJfToxd26RCpCetAozHb4OnQ=; b=oeMS5ozt8tuUwsxPlFwQL3lZJdzL9N+yFt6JLh/BbvIeakbYn3fYUTYJX8qmW6YKpt L0xKLuIqhATE6AutAyLwEt/SI/06bRM4Jh62D2gindVTrhO74Mdd4pmcNmbnkH+HJyEf WL7P/Q1cwms385hL77Z7X8IWpv4VJknvIgFTLqTAWfeNLPqp78KPmQRalMqCtsWOOOg2 P9EKfqj3eZvt9CUZ22gVS5nSnWvg4RpVzeRCHn+H7BpwbwGHh0k5yMqrD8Aj7cPKjcl0 V8x5D0holncNG7FTxV30rjoEuww/zFsB5zKZwrOqKeta+0/eoRQfTNWYE2A5wv4o5omq Y+pw== X-Gm-Message-State: AMCzsaUzZeRPwmHf8mzyI3qEaSa4SyzbCFqtVWWJxMRzQlyiCp7QMZ4U 7Gw6NN4Z5NYfl+kKaJYf8A== X-Google-Smtp-Source: AOwi7QBJlCU00wVCFC9rVwcrKc7hiiJBuvWrAPRwoj6PH2td1cXbb4s+kWvYYErMcuOLYRHAV8tQjg== X-Received: by 10.28.174.80 with SMTP id x77mr4381925wme.83.1506690581013; Fri, 29 Sep 2017 06:09:41 -0700 (PDT) Received: from groucho.site (ipbcc0ce42.dynamic.kabel-deutschland.de. [188.192.206.66]) by smtp.gmail.com with ESMTPSA id i8sm3423834wra.56.2017.09.29.06.09.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 29 Sep 2017 06:09:40 -0700 (PDT) From: Ulrich Hecht To: magnus.damm@gmail.com, laurent.pinchart@ideasonboard.com, jacopo@jmondi.org Subject: [RFC 03/11] platform/chrome: ChromeOS firmware interface driver Date: Fri, 29 Sep 2017 15:09:05 +0200 Message-Id: <1506690553-27357-4-git-send-email-ulrich.hecht+renesas@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1506690553-27357-1-git-send-email-ulrich.hecht+renesas@gmail.com> References: <1506690553-27357-1-git-send-email-ulrich.hecht+renesas@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170929_061004_611041_17ED68BD X-CRM114-Status: GOOD ( 23.36 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ulrich Hecht , linux-mediatek@lists.infradead.org, dri-devel@lists.freedesktop.org, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Ported from chromeos-3.18 kernel. Signed-off-by: Ulrich Hecht --- drivers/platform/chrome/Kconfig | 18 +++ drivers/platform/chrome/Makefile | 2 + drivers/platform/chrome/chromeos.c | 120 +++++++++++++++ drivers/platform/chrome/chromeos.h | 61 ++++++++ drivers/platform/chrome/chromeos_arm.c | 264 +++++++++++++++++++++++++++++++++ drivers/platform/chrome/elog.h | 186 +++++++++++++++++++++++ include/linux/chromeos_platform.h | 27 ++++ 7 files changed, 678 insertions(+) create mode 100644 drivers/platform/chrome/chromeos.c create mode 100644 drivers/platform/chrome/chromeos.h create mode 100644 drivers/platform/chrome/chromeos_arm.c create mode 100644 drivers/platform/chrome/elog.h create mode 100644 include/linux/chromeos_platform.h diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 0ad6e29..f8b1876 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -14,6 +14,24 @@ menuconfig CHROME_PLATFORMS if CHROME_PLATFORMS +config CHROMEOS + bool + depends on CHROMEOS_OF_FIRMWARE || (NVRAM && ACPI_CHROMEOS) + + ---help--- + Provides abstracted interfaces to the firmware features provided on + ChromeOS devices. It depends on a lowlevel driver to implement the + firmware interface on the platform. + +config CHROMEOS_OF_FIRMWARE + bool "ChromeOS firmware interface driver" + depends on OF + select CHROMEOS + ---help--- + This driver provides an interface to ChromeOS firmware. + + Say Y here if you are building for a ChromeOS device. + config CHROMEOS_LAPTOP tristate "Chrome OS Laptop" depends on I2C && DMI && X86 diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index 66c345c..f10a7b6 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -1,4 +1,6 @@ +obj-$(CONFIG_CHROMEOS) += chromeos.o +obj-$(CONFIG_CHROMEOS_OF_FIRMWARE) += chromeos_arm.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o cros_ec_devs-objs := cros_ec_dev.o cros_ec_sysfs.o \ diff --git a/drivers/platform/chrome/chromeos.c b/drivers/platform/chrome/chromeos.c new file mode 100644 index 0000000..8b01630 --- /dev/null +++ b/drivers/platform/chrome/chromeos.c @@ -0,0 +1,120 @@ +/* + * ChromeOS platform support code. Glue layer between higher level functions + * and per-platform firmware interfaces. + * + * Copyright (C) 2010 The Chromium OS Authors + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include "chromeos.h" + +static struct chromeos_vbc *chromeos_vbc_ptr; + +static int vbc_read(u8 *buf, int buf_size); +static int vbc_write_byte(unsigned offset, u8 value); + +/* the following defines are copied from + * vboot_reference:firmware/lib/vboot_nvstorage.c. + */ +#define RECOVERY_OFFSET 2 +#define VBNV_RECOVERY_RW_INVALID_OS 0x43 + +int chromeos_set_need_recovery(void) +{ + if (!chromeos_legacy_set_need_recovery()) + return 0; + + return vbc_write_byte(RECOVERY_OFFSET, VBNV_RECOVERY_RW_INVALID_OS); +} +EXPORT_SYMBOL(chromeos_set_need_recovery); + +/* + * Lifted from vboot_reference:firmware/lib/vboot_nvstorage.c and formatted. + * + * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A table-based + * algorithm would be faster, but for only 15 bytes isn't worth the code size. + */ +static u8 crc8(const u8 *data, int len) +{ + unsigned crc = 0; + int i, j; + + for (j = len; j; j--, data++) { + crc ^= (*data << 8); + for (i = 8; i; i--) { + if (crc & 0x8000) + crc ^= (0x1070 << 3); + crc <<= 1; + } + } + return (u8)(crc >> 8); +} + +static int vbc_write_byte(unsigned offset, u8 value) +{ + u8 buf[MAX_VBOOT_CONTEXT_BUFFER_SIZE]; + ssize_t size; + + if (!chromeos_vbc_ptr) + return -ENOSYS; + + size = vbc_read(buf, sizeof(buf)); + if (size <= 0) + return -EINVAL; + + if (offset >= (size - 1)) + return -EINVAL; + + if (buf[offset] == value) + return 0; + + buf[offset] = value; + buf[size - 1] = crc8(buf, size - 1); + + return chromeos_vbc_ptr->write(buf, size); +} + +/* + * Read vboot context and verify it. If everything checks out, return number + * of bytes in the vboot context buffer, -1 on any error (uninitialized + * subsystem, corrupted crc8 value, not enough room in the buffer, etc.). + */ +static int vbc_read(u8 *buf, int buf_size) +{ + ssize_t size; + + if (!chromeos_vbc_ptr) + return -ENOSYS; + + size = chromeos_vbc_ptr->read(buf, buf_size); + if (size <= 0) + return -1; + + if (buf[size - 1] != crc8(buf, size - 1)) { + pr_err("%s: vboot context contents corrupted\n", __func__); + return -1; + } + return size; +} + +int chromeos_vbc_register(struct chromeos_vbc *chromeos_vbc) +{ + chromeos_vbc_ptr = chromeos_vbc; + return 0; +} diff --git a/drivers/platform/chrome/chromeos.h b/drivers/platform/chrome/chromeos.h new file mode 100644 index 0000000..8f4384a --- /dev/null +++ b/drivers/platform/chrome/chromeos.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 The Chromium OS Authors + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _DRIVERS_PLATFORM_CHROMEOS_H +#define _DRIVERS_PLATFORM_CHROMEOS_H + +#define MAX_VBOOT_CONTEXT_BUFFER_SIZE 64 /* Should be enough for anything. */ + +#ifdef CONFIG_ACPI_CHROMEOS +extern int chromeos_legacy_set_need_recovery(void); +#else +static inline int chromeos_legacy_set_need_recovery(void) { return -ENODEV; } +#endif + +struct chromeos_vbc { + /** + * Read vboot context to buffer + * + * @param buf Pointer to buffer for storing vboot context + * @param count Size of buffer + * @return on success, the number of bytes read is returned and + * on error, -err is returned. + */ + ssize_t (*read)(void *buf, size_t count); + + /** + * Write vboot context from buffer + * + * @param buf Pointer to buffer of new vboot context content + * @param count Size of buffer + * @return on success, the number of bytes written is returned and + * on error, -err is returned. + */ + ssize_t (*write)(const void *buf, size_t count); + + const char *name; +}; + +/** + * Register chromeos_vbc callbacks. + * + * @param chromeos_vbc Pointer to struct holding callbacks + * @return on success, return 0, on error, -err is returned. + */ +int chromeos_vbc_register(struct chromeos_vbc *chromeos_vbc); + +#endif /* _DRIVERS_PLATFORM_CHROMEOS_H */ diff --git a/drivers/platform/chrome/chromeos_arm.c b/drivers/platform/chrome/chromeos_arm.c new file mode 100644 index 0000000..337e24d --- /dev/null +++ b/drivers/platform/chrome/chromeos_arm.c @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2011 The Chromium OS Authors + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define pr_fmt(fmt) "chromeos_arm: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chromeos.h" +#include "elog.h" + +struct chromeos_arm_elog_panic_buffer { + uint32_t start; + uint32_t size; + void __iomem *virt_addr; + struct notifier_block nb; +}; + +/* + * Update the checksum at the last byte + */ +static void elog_update_checksum(struct event_header *event, u8 checksum) +{ + u8 *event_data = (u8 *)event; + event_data[event->length - 1] = checksum; +} + +/* + * Simple byte checksum for events + */ +static u8 elog_checksum_event(struct event_header *event) +{ + u8 index, checksum = 0; + u8 *data = (u8 *)event; + + for (index = 0; index < event->length; index++) + checksum += data[index]; + return checksum; +} + +/* + * Populate timestamp in event header with current time + */ +static void elog_fill_timestamp(struct event_header *event) +{ + struct timeval timeval; + struct tm time; + + do_gettimeofday(&timeval); + time_to_tm(timeval.tv_sec, 0, &time); + + event->second = bin2bcd(time.tm_sec); + event->minute = bin2bcd(time.tm_min); + event->hour = bin2bcd(time.tm_hour); + event->day = bin2bcd(time.tm_mday); + event->month = bin2bcd(time.tm_mon + 1); + event->year = bin2bcd(time.tm_year % 100); +} + +/* + * Fill out an event structure with space for the data and checksum. + */ +void elog_prepare_event(struct event_header *event, u8 event_type, void *data, + u8 data_size) +{ + event->type = event_type; + event->length = sizeof(*event) + data_size + 1; + elog_fill_timestamp(event); + + if (data_size) + memcpy(&event[1], data, data_size); + + /* Zero the checksum byte and then compute checksum */ + elog_update_checksum(event, 0); + elog_update_checksum(event, -(elog_checksum_event(event))); +} + +static int chromeos_arm_elog_panic(struct notifier_block *this, + unsigned long p_event, void *ptr) +{ + struct chromeos_arm_elog_panic_buffer *buf; + uint32_t reason = ELOG_SHUTDOWN_PANIC; + const u8 data_size = sizeof(reason); + union { + struct event_header hdr; + u8 bytes[sizeof(struct event_header) + data_size + 1]; + } event; + + buf = container_of(this, struct chromeos_arm_elog_panic_buffer, nb); + elog_prepare_event(&event.hdr, ELOG_TYPE_OS_EVENT, &reason, data_size); + memcpy_toio(buf->virt_addr, event.bytes, sizeof(event.bytes)); + + return NOTIFY_DONE; +} + +static int chromeos_arm_panic_init(struct platform_device *pdev, u32 start, + u32 size) +{ + int ret = -EINVAL; + struct chromeos_arm_elog_panic_buffer *buf; + + buf = kmalloc(sizeof(*buf), GFP_KERNEL); + if (!buf) { + dev_err(&pdev->dev, "failed to allocate panic notifier.\n"); + ret = -ENOMEM; + goto fail1; + } + + buf->start = start; + buf->size = size; + buf->nb.notifier_call = chromeos_arm_elog_panic; + + if (!request_mem_region(start, size, "elog panic event")) { + dev_err(&pdev->dev, "failed to request panic event buffer.\n"); + goto fail2; + } + + buf->virt_addr = ioremap(start, size); + if (!buf->virt_addr) { + dev_err(&pdev->dev, "failed to map panic event buffer.\n"); + goto fail3; + } + + atomic_notifier_chain_register(&panic_notifier_list, &buf->nb); + + platform_set_drvdata(pdev, buf); + + return 0; + +fail3: + release_mem_region(start, size); +fail2: + kfree(buf); +fail1: + return ret; +} + +static int dt_gpio_init(struct platform_device *pdev, const char *of_list_name, + const char *gpio_desc_name, const char *sysfs_name) +{ + int gpio, err, active_low; + enum of_gpio_flags flags; + struct device_node *np = pdev->dev.of_node; + + gpio = of_get_named_gpio_flags(np, of_list_name, 0, &flags); + if (!gpio_is_valid(gpio)) { + dev_err(&pdev->dev, "invalid %s descriptor\n", of_list_name); + return -EINVAL; + } + + err = gpio_request_one(gpio, GPIOF_DIR_IN, gpio_desc_name); + if (err) + return err; + + active_low = !!(flags & OF_GPIO_ACTIVE_LOW); +// err = gpio_sysfs_set_active_low(gpio, active_low); +// if (err) +// return err; + + gpio_export(gpio, 0); + gpio_export_link(&pdev->dev, sysfs_name, gpio); + return 0; +} + +static int chromeos_arm_probe(struct platform_device *pdev) +{ + int err; + u32 elog_panic_event[2]; + struct device_node *np = pdev->dev.of_node; + + if (!np) { + err = -ENODEV; + goto err; + } + + err = dt_gpio_init(pdev, "write-protect-gpio", + "firmware-write-protect", "write-protect"); + if (err) + goto err; + err = dt_gpio_init(pdev, "recovery-switch", + "firmware-recovery-switch", "recovery-switch"); + err = dt_gpio_init(pdev, "developer-switch", + "firmware-developer-switch", "developer-switch"); + + if (!of_property_read_u32_array(np, "elog-panic-event", + elog_panic_event, + ARRAY_SIZE(elog_panic_event))) { + err = chromeos_arm_panic_init(pdev, elog_panic_event[0], + elog_panic_event[1]); + if (err) + goto err; + } + + dev_info(&pdev->dev, "chromeos system detected\n"); + + err = 0; +err: + of_node_put(np); + + return err; +} + +static int chromeos_arm_remove(struct platform_device *pdev) +{ + struct chromeos_arm_elog_panic_buffer *buf; + + buf = platform_get_drvdata(pdev); + platform_set_drvdata(pdev, NULL); + if (buf) { + atomic_notifier_chain_unregister(&panic_notifier_list, + &buf->nb); + release_mem_region(buf->start, buf->size); + iounmap(buf->virt_addr); + kfree(buf); + } + return 0; +} + +static struct platform_driver chromeos_arm_driver = { + .probe = chromeos_arm_probe, + .remove = chromeos_arm_remove, + .driver = { + .name = "chromeos_arm", + }, +}; + +static int __init chromeos_arm_init(void) +{ + struct device_node *fw_dn; + struct platform_device *pdev; + + fw_dn = of_find_compatible_node(NULL, NULL, "chromeos-firmware"); + if (!fw_dn) + return -ENODEV; + + pdev = platform_device_register_simple("chromeos_arm", -1, NULL, 0); + pdev->dev.of_node = fw_dn; + + platform_driver_register(&chromeos_arm_driver); + + return 0; +} +subsys_initcall(chromeos_arm_init); diff --git a/drivers/platform/chrome/elog.h b/drivers/platform/chrome/elog.h new file mode 100644 index 0000000..84b005f --- /dev/null +++ b/drivers/platform/chrome/elog.h @@ -0,0 +1,186 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2012 The ChromiumOS 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 ELOG_H_ +#define ELOG_H_ + +/* SMI command code for GSMI event logging */ +#define ELOG_GSMI_APM_CNT 0xEF + +#define MAX_EVENT_SIZE 0x7F + +/* End of log */ +#define ELOG_TYPE_EOL 0xFF + +/* + * Standard SMBIOS event log types below 0x80 + */ +#define ELOG_TYPE_UNDEFINED_EVENT 0x00 +#define ELOG_TYPE_SINGLE_BIT_ECC_MEM_ERR 0x01 +#define ELOG_TYPE_MULTI_BIT_ECC_MEM_ERR 0x02 +#define ELOG_TYPE_MEM_PARITY_ERR 0x03 +#define ELOG_TYPE_BUS_TIMEOUT 0x04 +#define ELOG_TYPE_IO_CHECK 0x05 +#define ELOG_TYPE_SW_NMI 0x06 +#define ELOG_TYPE_POST_MEM_RESIZE 0x07 +#define ELOG_TYPE_POST_ERR 0x08 +#define ELOG_TYPE_PCI_PERR 0x09 +#define ELOG_TYPE_PCI_SERR 0x0A +#define ELOG_TYPE_CPU_FAIL 0x0B +#define ELOG_TYPE_EISA_TIMEOUT 0x0C +#define ELOG_TYPE_CORRECTABLE_MEMLOG_DIS 0x0D +#define ELOG_TYPE_LOG_DISABLED 0x0E +#define ELOG_TYPE_UNDEFINED_EVENT2 0x0F +#define ELOG_TYPE_SYS_LIMIT_EXCEED 0x10 +#define ELOG_TYPE_ASYNC_HW_TIMER_EXPIRED 0x11 +#define ELOG_TYPE_SYS_CONFIG_INFO 0x12 +#define ELOG_TYPE_HDD_INFO 0x13 +#define ELOG_TYPE_SYS_RECONFIG 0x14 +#define ELOG_TYPE_CPU_ERROR 0x15 +#define ELOG_TYPE_LOG_CLEAR 0x16 +#define ELOG_TYPE_BOOT 0x17 + +/* + * Extended defined OEM event types start at 0x80 + */ + +/* OS/kernel events */ +#define ELOG_TYPE_OS_EVENT 0x81 +#define ELOG_SHUTDOWN_CLEAN 0 /* Clean Shutdown */ +#define ELOG_SHUTDOWN_NMIWDT 1 /* NMI Watchdog */ +#define ELOG_SHUTDOWN_PANIC 2 /* Panic */ +#define ELOG_SHUTDOWN_OOPS 3 /* Oops */ +#define ELOG_SHUTDOWN_DIE 4 /* Die - No longer meaningful */ +#define ELOG_SHUTDOWN_MCE 5 /* Machine Check */ +#define ELOG_SHUTDOWN_SOFTWDT 6 /* Software Watchdog */ +#define ELOG_SHUTDOWN_MBE 7 /* Uncorrected ECC */ +#define ELOG_SHUTDOWN_TRIPLE 8 /* Triple Fault */ +#define ELOG_SHUTDOWN_THERMAL 9 /* Critical Thermal Threshold */ + +/* Last event from coreboot */ +#define ELOG_TYPE_OS_BOOT 0x90 + +/* Embedded controller event */ +#define ELOG_TYPE_EC_EVENT 0x91 +#define EC_EVENT_LID_CLOSED 0x01 +#define EC_EVENT_LID_OPEN 0x02 +#define EC_EVENT_POWER_BUTTON 0x03 +#define EC_EVENT_AC_CONNECTED 0x04 +#define EC_EVENT_AC_DISCONNECTED 0x05 +#define EC_EVENT_BATTERY_LOW 0x06 +#define EC_EVENT_BATTERY_CRITICAL 0x07 +#define EC_EVENT_BATTERY 0x08 +#define EC_EVENT_THERMAL_THRESHOLD 0x09 +#define EC_EVENT_THERMAL_OVERLOAD 0x0a +#define EC_EVENT_THERMAL 0x0b +#define EC_EVENT_USB_CHARGER 0x0c +#define EC_EVENT_KEY_PRESSED 0x0d +#define EC_EVENT_INTERFACE_READY 0x0e +#define EC_EVENT_KEYBOARD_RECOVERY 0x0f +#define EC_EVENT_THERMAL_SHUTDOWN 0x10 +#define EC_EVENT_BATTERY_SHUTDOWN 0x11 +#define EC_EVENT_FAN_ERROR 0x12 + +/* Power */ +#define ELOG_TYPE_POWER_FAIL 0x92 +#define ELOG_TYPE_SUS_POWER_FAIL 0x93 +#define ELOG_TYPE_PWROK_FAIL 0x94 +#define ELOG_TYPE_SYS_PWROK_FAIL 0x95 +#define ELOG_TYPE_POWER_ON 0x96 +#define ELOG_TYPE_POWER_BUTTON 0x97 +#define ELOG_TYPE_POWER_BUTTON_OVERRIDE 0x98 + +/* Reset */ +#define ELOG_TYPE_RESET_BUTTON 0x99 +#define ELOG_TYPE_SYSTEM_RESET 0x9a +#define ELOG_TYPE_RTC_RESET 0x9b +#define ELOG_TYPE_TCO_RESET 0x9c + +/* Sleep/Wake */ +#define ELOG_TYPE_ACPI_ENTER 0x9d +#define ELOG_TYPE_ACPI_WAKE 0x9e +#define ELOG_TYPE_WAKE_SOURCE 0x9f +#define ELOG_WAKE_SOURCE_PCIE 0x00 +#define ELOG_WAKE_SOURCE_PME 0x01 +#define ELOG_WAKE_SOURCE_PME_INTERNAL 0x02 +#define ELOG_WAKE_SOURCE_RTC 0x03 +#define ELOG_WAKE_SOURCE_GPIO 0x04 +#define ELOG_WAKE_SOURCE_SMBUS 0x05 +#define ELOG_WAKE_SOURCE_PWRBTN 0x06 +struct elog_event_data_wake { + u8 source; + u32 instance; +} __packed; + +/* Chrome OS related events */ +#define ELOG_TYPE_CROS_DEVELOPER_MODE 0xa0 +#define ELOG_TYPE_CROS_RECOVERY_MODE 0xa1 +#define ELOG_CROS_RECOVERY_MODE_BUTTON 0x02 + +/* Management Engine Events */ +#define ELOG_TYPE_MANAGEMENT_ENGINE 0xa2 +#define ELOG_TYPE_MANAGEMENT_ENGINE_EXT 0xa4 +struct elog_event_data_me_extended { + u8 current_working_state; + u8 operation_state; + u8 operation_mode; + u8 error_code; + u8 progress_code; + u8 current_pmevent; + u8 current_state; +} __packed; + +/* Last post code from previous boot */ +#define ELOG_TYPE_LAST_POST_CODE 0xa3 + +/* EC Shutdown Reason */ +#define ELOG_TYPE_EC_SHUTDOWN 0xa5 + +/* ARM/generic versions of sleep/wake */ +#define ELOG_TYPE_SLEEP 0xa7 +#define ELOG_TYPE_WAKE 0xa8 + +/* ELOG header */ +struct elog_header { + u32 magic; + u8 version; + u8 header_size; + u8 reserved[2]; +} __packed; + +/* ELOG related constants */ +#define ELOG_SIGNATURE 0x474f4c45 /* 'ELOG' */ +#define ELOG_VERSION 1 + +/* SMBIOS event log header */ +struct event_header { + u8 type; + u8 length; + u8 year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; +} __packed; + +extern void elog_prepare_event(struct event_header *event, u8 event_type, + void *data, u8 data_size); + +#endif /* ELOG_H_ */ diff --git a/include/linux/chromeos_platform.h b/include/linux/chromeos_platform.h new file mode 100644 index 0000000..32c4510 --- /dev/null +++ b/include/linux/chromeos_platform.h @@ -0,0 +1,27 @@ +#ifndef _LINUX_CHROMEOS_PLATFORM_H +#define _LINUX_CHROMEOS_PLATFORM_H + +#include +#include + +#ifdef CONFIG_CHROMEOS +/* + * ChromeOS platform support code. Glue layer between higher level functions + * and per-platform firmware interfaces. + */ + +/* + * Set the taint bit telling firmware that the currently running side needs + * recovery (or reinstall). + */ +extern int chromeos_set_need_recovery(void); + +#else + +static inline int chromeos_set_need_recovery(void) +{ + return -ENODEV; +} +#endif /* CONFIG_CHROMEOS */ + +#endif /* _LINUX_CHROMEOS_PLATFORM_H */