blob: 3611814b66cbce889caf8b3ba208c39277e32551 [file] [log] [blame]
Hung-Te Lin0ee70622013-06-26 19:42:12 +08001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Hung-Te Lin0ee70622013-06-26 19:42:12 +080014 */
15
16#include <console/console.h>
David Hendricks767d2452014-09-27 20:04:49 -070017#include <delay.h>
Hung-Te Lin0ee70622013-06-26 19:42:12 +080018#include "ec.h"
19#include "ec_commands.h"
Gabe Black967058f2014-03-21 21:32:12 -070020#include <spi-generic.h>
21#include <timer.h>
22
Julius Werner93b51e72016-10-03 12:52:55 -070023/* This is assuming that this driver is not used on x86. If that changes, this
24 might need to become a CAR_GLOBAL or maybe even more complicated. */
25static struct stopwatch cs_cooldown_sw;
26static const long cs_cooldown_us = 200;
27
Gabe Black967058f2014-03-21 21:32:12 -070028static const uint8_t EcFramingByte = 0xec;
Hung-Te Lin0ee70622013-06-26 19:42:12 +080029
Aaron Durbin82827272014-08-06 14:34:57 -050030#define PROTO3_MAX_PACKET_SIZE 268
31
32static uint8_t req_buf[PROTO3_MAX_PACKET_SIZE];
33static uint8_t resp_buf[PROTO3_MAX_PACKET_SIZE];
34
35void *crosec_get_buffer(size_t size, int req)
36{
37 if (size > PROTO3_MAX_PACKET_SIZE) {
38 printk(BIOS_DEBUG, "Proto v3 buffer request too large: %zu!\n",
39 size);
40 return NULL;
41 }
42
43 if (req)
44 return req_buf;
45 else
46 return resp_buf;
47}
48
49static int crosec_spi_io(size_t req_size, size_t resp_size, void *context)
Hung-Te Lin0ee70622013-06-26 19:42:12 +080050{
51 struct spi_slave *slave = (struct spi_slave *)context;
Julius Werner93b51e72016-10-03 12:52:55 -070052 int ret = 0;
Hung-Te Lin0ee70622013-06-26 19:42:12 +080053
Jonathan Neuschäferc9660752017-09-19 15:19:54 +020054 /* Wait minimum delay between CS assertions. */
55 stopwatch_wait_until_expired(&cs_cooldown_sw);
56
Hung-Te Lin0ee70622013-06-26 19:42:12 +080057 spi_claim_bus(slave);
Hung-Te Lin0ee70622013-06-26 19:42:12 +080058
David Hendricks767d2452014-09-27 20:04:49 -070059 /* Allow EC to ramp up clock after being awaken.
60 * See chrome-os-partner:32223 for more details. */
61 udelay(CONFIG_EC_GOOGLE_CHROMEEC_SPI_WAKEUP_DELAY_US);
62
Aaron Durbin82827272014-08-06 14:34:57 -050063 if (spi_xfer(slave, req_buf, req_size, NULL, 0)) {
Gabe Black967058f2014-03-21 21:32:12 -070064 printk(BIOS_ERR, "%s: Failed to send request.\n", __func__);
Julius Werner93b51e72016-10-03 12:52:55 -070065 ret = -1;
66 goto out;
Hung-Te Lin0ee70622013-06-26 19:42:12 +080067 }
68
Gabe Black967058f2014-03-21 21:32:12 -070069 uint8_t byte;
Aaron Durbin48691112014-09-23 16:30:53 -050070 struct stopwatch sw;
71 // Wait 1s for a framing byte.
72 stopwatch_init_usecs_expire(&sw, USECS_PER_SEC);
Gabe Black967058f2014-03-21 21:32:12 -070073 while (1) {
74 if (spi_xfer(slave, NULL, 0, &byte, sizeof(byte))) {
75 printk(BIOS_ERR, "%s: Failed to receive byte.\n",
76 __func__);
Julius Werner93b51e72016-10-03 12:52:55 -070077 ret = -1;
78 goto out;
Gabe Black967058f2014-03-21 21:32:12 -070079 }
80 if (byte == EcFramingByte)
81 break;
82
Aaron Durbin48691112014-09-23 16:30:53 -050083 if (stopwatch_expired(&sw)) {
Gabe Black967058f2014-03-21 21:32:12 -070084 printk(BIOS_ERR,
85 "%s: Timeout waiting for framing byte.\n",
86 __func__);
Julius Werner93b51e72016-10-03 12:52:55 -070087 ret = -1;
88 goto out;
Gabe Black967058f2014-03-21 21:32:12 -070089 }
90 }
91
Aaron Durbin82827272014-08-06 14:34:57 -050092 if (spi_xfer(slave, NULL, 0, resp_buf, resp_size)) {
Gabe Black967058f2014-03-21 21:32:12 -070093 printk(BIOS_ERR, "%s: Failed to receive response.\n", __func__);
Julius Werner93b51e72016-10-03 12:52:55 -070094 ret = -1;
Gabe Black967058f2014-03-21 21:32:12 -070095 }
96
Julius Werner93b51e72016-10-03 12:52:55 -070097out:
Gabe Black967058f2014-03-21 21:32:12 -070098 spi_release_bus(slave);
Julius Werner93b51e72016-10-03 12:52:55 -070099 stopwatch_init_usecs_expire(&cs_cooldown_sw, cs_cooldown_us);
100 return ret;
Hung-Te Lin0ee70622013-06-26 19:42:12 +0800101}
102
103int google_chromeec_command(struct chromeec_command *cec_command)
104{
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800105 static int done = 0;
106 static struct spi_slave slave;
107
108 if (!done) {
109 if (spi_setup_slave(CONFIG_EC_GOOGLE_CHROMEEC_SPI_BUS,
110 CONFIG_EC_GOOGLE_CHROMEEC_SPI_CHIP, &slave))
111 return -1;
Julius Werner93b51e72016-10-03 12:52:55 -0700112 stopwatch_init(&cs_cooldown_sw);
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800113 done = 1;
Julius Werner93b51e72016-10-03 12:52:55 -0700114 }
Furquan Shaikh36b81af2016-12-01 01:02:44 -0800115 return crosec_command_proto(cec_command, crosec_spi_io, &slave);
Hung-Te Lin0ee70622013-06-26 19:42:12 +0800116}
117
118#ifndef __PRE_RAM__
119u8 google_chromeec_get_event(void)
120{
121 printk(BIOS_ERR, "%s: Not supported.\n", __func__);
122 return 0;
123}
124#endif