Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  mailbox.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Mailbox interface for Wilco Embedded Controller
 *
 * Copyright 2018 Google LLC
 *
 * The Wilco EC is similar to a typical ChromeOS embedded controller.
 * It uses the same MEC based low-level communication and a similar
 * protocol, but with some important differences.  The EC firmware does
 * not support the same mailbox commands so it is not registered as a
 * cros_ec device type.
 *
 * Most messages follow a standard format, but there are some exceptions
 * and an interface is provided to do direct/raw transactions that do not
 * make assumptions about byte placement.
 */


#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/platform_data/wilco-ec.h>
#include <linux/platform_device.h>

#include "../cros_ec_lpc_mec.h"

/* Version of mailbox interface */
#define EC_MAILBOX_VERSION  0

/* Command to start mailbox transaction */
#define EC_MAILBOX_START_COMMAND 0xda

/* Version of EC protocol */
#define EC_MAILBOX_PROTO_VERSION 3

/* Number of header bytes to be counted as data bytes */
#define EC_MAILBOX_DATA_EXTRA  2

/* Maximum timeout */
#define EC_MAILBOX_TIMEOUT  HZ

/* EC response flags */
#define EC_CMDR_DATA  BIT(0) /* Data ready for host to read */
#define EC_CMDR_PENDING  BIT(1) /* Write pending to EC */
#define EC_CMDR_BUSY  BIT(2) /* EC is busy processing a command */
#define EC_CMDR_CMD  BIT(3) /* Last host write was a command */

/**
 * wilco_ec_response_timed_out() - Wait for EC response.
 * @ec: EC device.
 *
 * Return: true if EC timed out, false if EC did not time out.
 */

static bool wilco_ec_response_timed_out(struct wilco_ec_device *ec)
{
 unsigned long timeout = jiffies + EC_MAILBOX_TIMEOUT;

 do {
  if (!(inb(ec->io_command->start) &
        (EC_CMDR_PENDING | EC_CMDR_BUSY)))
   return false;
  usleep_range(100, 200);
 } while (time_before(jiffies, timeout));

 return true;
}

/**
 * wilco_ec_checksum() - Compute 8-bit checksum over data range.
 * @data: Data to checksum.
 * @size: Number of bytes to checksum.
 *
 * Return: 8-bit checksum of provided data.
 */

static u8 wilco_ec_checksum(const void *data, size_t size)
{
 u8 *data_bytes = (u8 *)data;
 u8 checksum = 0;
 size_t i;

 for (i = 0; i < size; i++)
  checksum += data_bytes[i];

 return checksum;
}

/**
 * wilco_ec_prepare() - Prepare the request structure for the EC.
 * @msg: EC message with request information.
 * @rq: EC request structure to fill.
 */

static void wilco_ec_prepare(struct wilco_ec_message *msg,
        struct wilco_ec_request *rq)
{
 memset(rq, 0, sizeof(*rq));
 rq->struct_version = EC_MAILBOX_PROTO_VERSION;
 rq->mailbox_id = msg->type;
 rq->mailbox_version = EC_MAILBOX_VERSION;
 rq->data_size = msg->request_size;

 /* Checksum header and data */
 rq->checksum = wilco_ec_checksum(rq, sizeof(*rq));
 rq->checksum += wilco_ec_checksum(msg->request_data, msg->request_size);
 rq->checksum = -rq->checksum;
}

/**
 * wilco_ec_transfer() - Perform actual data transfer.
 * @ec: EC device.
 * @msg: EC message data for request and response.
 * @rq: Filled in request structure
 *
 * Context: ec->mailbox_lock should be held while using this function.
 * Return: number of bytes received or negative error code on failure.
 */

static int wilco_ec_transfer(struct wilco_ec_device *ec,
        struct wilco_ec_message *msg,
        struct wilco_ec_request *rq)
{
 struct wilco_ec_response *rs;
 int ret;
 u8 flag;

 /* Write request header, then data */
 ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq);
 if (ret < 0)
  return ret;
 ret = cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size,
           msg->request_data);
 if (ret < 0)
  return ret;

 /* Start the command */
 outb(EC_MAILBOX_START_COMMAND, ec->io_command->start);

 /* For some commands (eg shutdown) the EC will not respond, that's OK */
 if (msg->flags & WILCO_EC_FLAG_NO_RESPONSE) {
  dev_dbg(ec->dev, "EC does not respond to this command\n");
  return 0;
 }

 /* Wait for it to complete */
 if (wilco_ec_response_timed_out(ec)) {
  dev_dbg(ec->dev, "response timed out\n");
  return -ETIMEDOUT;
 }

 /* Check result */
 flag = inb(ec->io_data->start);
 if (flag) {
  dev_dbg(ec->dev, "bad response: 0x%02x\n", flag);
  return -EIO;
 }

 /* Read back response */
 rs = ec->data_buffer;
 ret = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0,
           sizeof(*rs) + EC_MAILBOX_DATA_SIZE,
           (u8 *)rs);
 if (ret < 0)
  return ret;
 if (ret) {
  dev_dbg(ec->dev, "bad packet checksum 0x%02x\n", rs->checksum);
  return -EBADMSG;
 }

 if (rs->result) {
  dev_dbg(ec->dev, "EC reported failure: 0x%02x\n", rs->result);
  return -EBADMSG;
 }

 if (rs->data_size != EC_MAILBOX_DATA_SIZE) {
  dev_dbg(ec->dev, "unexpected packet size (%u != %u)\n",
   rs->data_size, EC_MAILBOX_DATA_SIZE);
  return -EMSGSIZE;
 }

 if (rs->data_size < msg->response_size) {
  dev_dbg(ec->dev, "EC didn't return enough data (%u < %zu)\n",
   rs->data_size, msg->response_size);
  return -EMSGSIZE;
 }

 memcpy(msg->response_data, rs->data, msg->response_size);

 return rs->data_size;
}

/**
 * wilco_ec_mailbox() - Send EC request and receive EC response.
 * @ec: EC device.
 * @msg: EC message data for request and response.
 *
 * On entry msg->type, msg->request_size, and msg->request_data should all be
 * filled in. If desired, msg->flags can be set.
 *
 * If a response is expected, msg->response_size should be set, and
 * msg->response_data should point to a buffer with enough space. On exit
 * msg->response_data will be filled.
 *
 * Return: number of bytes received or negative error code on failure.
 */

int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg)
{
 struct wilco_ec_request *rq;
 int ret;

 dev_dbg(ec->dev, "type=%04x flags=%02x rslen=%zu rqlen=%zu\n",
  msg->type, msg->flags, msg->response_size, msg->request_size);

 mutex_lock(&ec->mailbox_lock);
 /* Prepare request packet */
 rq = ec->data_buffer;
 wilco_ec_prepare(msg, rq);

 ret = wilco_ec_transfer(ec, msg, rq);
 mutex_unlock(&ec->mailbox_lock);

 return ret;

}
EXPORT_SYMBOL_GPL(wilco_ec_mailbox);

Messung V0.5
C=89 H=90 G=89

¤ Dauer der Verarbeitung: 0.0 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge