summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2015-07-25 02:14:13 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-07-30 19:57:55 +0000
commit5b71b33aba6cb0108a864cc7000918b8f06b139a (patch)
treeaa49a59a306d91b189e9fcdddc3bbb0e2deba628
parent9008c7a4fd131a96ccb0078a46ec545cff2f43b1 (diff)
downloadchrome-ec-5b71b33aba6cb0108a864cc7000918b8f06b139a.tar.gz
common: change interface to SPI flash
Allow more than one SPI master. Add CONFIG variables to address the system SPI flash. To have SPI master ports, spi_ports array must be defined. BRANCH=smaug TEST=compile BUG=chrome-os-partner:42304 Change-Id: Id43869f648965c1582b7be1c7fb3a38f175fda95 Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/288512 Commit-Queue: David James <davidjames@chromium.org>
-rw-r--r--board/cyan/board.c7
-rw-r--r--board/cyan/board.h3
-rw-r--r--board/discovery-stm32f072/board.c11
-rw-r--r--board/discovery-stm32f072/board.h5
-rw-r--r--board/glados/board.c7
-rw-r--r--board/glados/board.h3
-rw-r--r--board/glower/board.c7
-rw-r--r--board/glower/board.h3
-rw-r--r--board/kunimitsu/board.c7
-rw-r--r--board/kunimitsu/board.h3
-rw-r--r--board/mec1322_evb/board.c7
-rw-r--r--board/mec1322_evb/board.h3
-rw-r--r--board/npcx_evb/board.c8
-rw-r--r--board/npcx_evb/board.h1
-rw-r--r--board/ryu/board.c14
-rw-r--r--board/ryu/board.h5
-rw-r--r--board/strago/board.c7
-rw-r--r--board/strago/board.h3
-rw-r--r--chip/it83xx/spi.c8
-rw-r--r--chip/lm4/spi.c44
-rw-r--r--chip/mec1322/lfw/ec_lfw.c15
-rw-r--r--chip/mec1322/spi.c76
-rw-r--r--chip/mec1322/system.c2
-rw-r--r--chip/npcx/spi.c51
-rw-r--r--chip/stm32/build.mk2
-rw-r--r--chip/stm32/spi_master.c120
-rw-r--r--chip/stm32/usb_spi.c3
-rw-r--r--common/spi_flash.c37
-rw-r--r--include/config.h15
-rw-r--r--include/spi.h57
30 files changed, 351 insertions, 183 deletions
diff --git a/board/cyan/board.c b/board/cyan/board.c
index 524263a295..5d315b0e5f 100644
--- a/board/cyan/board.c
+++ b/board/cyan/board.c
@@ -21,6 +21,7 @@
#include "power.h"
#include "power_button.h"
#include "registers.h"
+#include "spi.h"
#include "switch.h"
#include "task.h"
#include "temp_sensor.h"
@@ -56,6 +57,12 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* SPI devices */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_PVT_CS0 },
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
const enum gpio_signal hibernate_wake_pins[] = {
GPIO_POWER_BUTTON_L,
};
diff --git a/board/cyan/board.h b/board/cyan/board.h
index 16716759df..404390e800 100644
--- a/board/cyan/board.h
+++ b/board/cyan/board.h
@@ -44,8 +44,7 @@
#define CONFIG_CHARGER_INPUT_CURRENT 2240
#define CONFIG_CHARGER_DISCHARGE_ON_AC
-#define CONFIG_SPI_PORT 1
-#define CONFIG_SPI_CS_GPIO GPIO_PVT_CS0
+#define CONFIG_SPI_FLASH_PORT 1
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_SIZE 524288
/* TODO: Add flash protect support for the SPI part cyan actually has */
diff --git a/board/discovery-stm32f072/board.c b/board/discovery-stm32f072/board.c
index 0ce00c9368..7aa9a70555 100644
--- a/board/discovery-stm32f072/board.c
+++ b/board/discovery-stm32f072/board.c
@@ -144,6 +144,13 @@ BUILD_ASSERT(ARRAY_SIZE(usb_strings) == USB_STR_COUNT);
* Support SPI bridging over USB, this requires usb_spi_board_enable and
* usb_spi_board_disable to be defined to enable and disable the SPI bridge.
*/
+
+/* SPI devices */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
void usb_spi_board_enable(struct usb_spi_config const *config)
{
/* Remap SPI2 to DMA channels 6 and 7 */
@@ -162,12 +169,12 @@ void usb_spi_board_enable(struct usb_spi_config const *config)
STM32_RCC_APB1RSTR |= STM32_RCC_PB1_SPI2;
STM32_RCC_APB1RSTR &= ~STM32_RCC_PB1_SPI2;
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
}
void usb_spi_board_disable(struct usb_spi_config const *config)
{
- spi_enable(0);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 0);
/* Disable clocks to SPI2 module */
STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_SPI2;
diff --git a/board/discovery-stm32f072/board.h b/board/discovery-stm32f072/board.h
index ef839bfc49..2e57167604 100644
--- a/board/discovery-stm32f072/board.h
+++ b/board/discovery-stm32f072/board.h
@@ -49,8 +49,9 @@
#define CONFIG_USB_GPIO
/* Enable control of SPI over USB */
-#define CONFIG_SPI_MASTER_PORT 2
-#define CONFIG_SPI_CS_GPIO GPIO_SPI_CS
+#define CONFIG_SPI_MASTER
+#define CONFIG_SPI_FLASH_PORT 0 /* First SPI master port */
+
#define CONFIG_USB_SPI
diff --git a/board/glados/board.c b/board/glados/board.c
index 9a8d17f8bf..27ae0e274f 100644
--- a/board/glados/board.c
+++ b/board/glados/board.c
@@ -20,6 +20,7 @@
#include "pi3usb9281.h"
#include "power.h"
#include "power_button.h"
+#include "spi.h"
#include "switch.h"
#include "task.h"
#include "temp_sensor.h"
@@ -136,6 +137,12 @@ const struct i2c_port_t i2c_ports[] = {
#endif
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* SPI devices */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_PVT_CS0},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
const enum gpio_signal hibernate_wake_pins[] = {
GPIO_AC_PRESENT,
GPIO_LID_OPEN,
diff --git a/board/glados/board.h b/board/glados/board.h
index 95f0572500..6ad08d3b44 100644
--- a/board/glados/board.h
+++ b/board/glados/board.h
@@ -63,8 +63,7 @@
#define CONFIG_USBC_VCONN
#define CONFIG_SCI_GPIO GPIO_PCH_SCI_L
-#define CONFIG_SPI_PORT 1
-#define CONFIG_SPI_CS_GPIO GPIO_PVT_CS0
+#define CONFIG_SPI_FLASH_PORT 1
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_SIZE 524288
#define CONFIG_SPI_FLASH_W25Q64
diff --git a/board/glower/board.c b/board/glower/board.c
index 6d5bc33699..8f6e139aab 100644
--- a/board/glower/board.c
+++ b/board/glower/board.c
@@ -12,6 +12,7 @@
#include "power.h"
#include "power_button.h"
#include "registers.h"
+#include "spi.h"
#include "switch.h"
#include "util.h"
@@ -45,6 +46,12 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* SPI devices */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_PVT_CS0},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
const enum gpio_signal hibernate_wake_pins[] = {
GPIO_POWER_BUTTON_L,
};
diff --git a/board/glower/board.h b/board/glower/board.h
index 9d1de7f575..982c205501 100644
--- a/board/glower/board.h
+++ b/board/glower/board.h
@@ -54,8 +54,7 @@
/* 512kb SPI flash */
#define CONFIG_SPI_FLASH_SIZE 0x00080000
#define CONFIG_SPI_FLASH_W25X40
-#define CONFIG_SPI_PORT 1
-#define CONFIG_SPI_CS_GPIO GPIO_PVT_CS0
+#define CONFIG_SPI_FLASH_PORT 1
#define CONFIG_CMD_FLASH
#define CONFIG_CMD_SPI_FLASH
diff --git a/board/kunimitsu/board.c b/board/kunimitsu/board.c
index ff739e1a42..04dbadade1 100644
--- a/board/kunimitsu/board.c
+++ b/board/kunimitsu/board.c
@@ -26,6 +26,7 @@
#include "pi3usb9281.h"
#include "power.h"
#include "power_button.h"
+#include "spi.h"
#include "switch.h"
#include "task.h"
#include "temp_sensor.h"
@@ -132,6 +133,12 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* SPI devices */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_PVT_CS0},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
const enum gpio_signal hibernate_wake_pins[] = {
GPIO_AC_PRESENT,
GPIO_LID_OPEN,
diff --git a/board/kunimitsu/board.h b/board/kunimitsu/board.h
index 1c4e4fbcdc..238a006bcc 100644
--- a/board/kunimitsu/board.h
+++ b/board/kunimitsu/board.h
@@ -57,8 +57,7 @@
#define CONFIG_USBC_VCONN
#define CONFIG_SCI_GPIO GPIO_PCH_SCI_L
-#define CONFIG_SPI_PORT 1
-#define CONFIG_SPI_CS_GPIO GPIO_PVT_CS0
+#define CONFIG_SPI_FLASH_PORT 0
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_SIZE 524288
#define CONFIG_SPI_FLASH_W25Q64
diff --git a/board/mec1322_evb/board.c b/board/mec1322_evb/board.c
index 55bed1a5cb..99236b0299 100644
--- a/board/mec1322_evb/board.c
+++ b/board/mec1322_evb/board.c
@@ -10,6 +10,7 @@
#include "gpio.h"
#include "i2c.h"
#include "registers.h"
+#include "spi.h"
#include "util.h"
#define GPIO_KB_INPUT GPIO_INPUT
@@ -45,6 +46,12 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* SPI master ports */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_SHD_CS0},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
const enum gpio_signal hibernate_wake_pins[] = {
GPIO_S1,
};
diff --git a/board/mec1322_evb/board.h b/board/mec1322_evb/board.h
index 991e52e667..25b20618f7 100644
--- a/board/mec1322_evb/board.h
+++ b/board/mec1322_evb/board.h
@@ -15,8 +15,7 @@
#define CONFIG_ADC
#define CONFIG_SPI_FLASH_SIZE 0x00800000
#define CONFIG_SPI_FLASH_W25Q64
-#define CONFIG_SPI_PORT 0
-#define CONFIG_SPI_CS_GPIO GPIO_SHD_CS0
+#define CONFIG_SPI_FLASH_PORT 0
/* Modules we want to exclude */
#undef CONFIG_EEPROM
diff --git a/board/npcx_evb/board.c b/board/npcx_evb/board.c
index 9523c3b937..8b3a72304d 100644
--- a/board/npcx_evb/board.c
+++ b/board/npcx_evb/board.c
@@ -23,6 +23,7 @@
#include "pwm.h"
#include "pwm_chip.h"
#include "registers.h"
+#include "spi.h"
#include "switch.h"
#include "temp_sensor.h"
#include "temp_sensor_chip.h"
@@ -115,6 +116,13 @@ const struct i2c_port_t i2c_ports[] = {
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
/******************************************************************************/
+/* SPI devices */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_CS_L},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
+/******************************************************************************/
/* Keyboard scan setting */
struct keyboard_scan_config keyscan_config = {
.output_settle_us = 40,
diff --git a/board/npcx_evb/board.h b/board/npcx_evb/board.h
index f4059151fc..1553edba3f 100644
--- a/board/npcx_evb/board.h
+++ b/board/npcx_evb/board.h
@@ -20,6 +20,7 @@
/* Optional features */
#define CONFIG_SYSTEM_UNLOCKED /* Allow dangerous commands for testing */
+#define CONFIG_SPI_FLASH_PORT 0
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_SIZE 0x00800000 /* 8MB spi flash */
#define CONFIG_SPI_FLASH_W25Q64
diff --git a/board/ryu/board.c b/board/ryu/board.c
index e9540fb143..91c8fa750f 100644
--- a/board/ryu/board.c
+++ b/board/ryu/board.c
@@ -289,6 +289,12 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* SPI devices */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_SPI_FLASH_NSS},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
/* Sensor mutex */
static struct mutex g_mutex;
@@ -484,7 +490,7 @@ void usb_spi_board_enable(struct usb_spi_config const *config)
/* Configure SPI GPIOs */
gpio_config_module(MODULE_SPI_MASTER, 1);
- gpio_set_flags(GPIO_SPI_FLASH_NSS, GPIO_OUT_HIGH);
+ gpio_set_flags(SPI_FLASH_DEVICE->gpio_cs, GPIO_OUT_HIGH);
/* Set all four SPI pins to high speed */
STM32_GPIO_OSPEEDR(GPIO_B) |= 0xf03c0000;
@@ -499,12 +505,12 @@ void usb_spi_board_enable(struct usb_spi_config const *config)
/* Enable SPI LDO to power the flash chip */
gpio_set_level(GPIO_VDDSPI_EN, 1);
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
}
void usb_spi_board_disable(struct usb_spi_config const *config)
{
- spi_enable(0);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 0);
/* Disable SPI LDO */
gpio_set_level(GPIO_VDDSPI_EN, 0);
@@ -514,7 +520,7 @@ void usb_spi_board_disable(struct usb_spi_config const *config)
/* Release SPI GPIOs */
gpio_config_module(MODULE_SPI_MASTER, 0);
- gpio_set_flags(GPIO_SPI_FLASH_NSS, GPIO_INPUT);
+ gpio_set_flags(SPI_FLASH_DEVICE->gpio_cs, GPIO_INPUT);
/* Release AP from reset */
gpio_set_level(GPIO_PMIC_WARM_RESET_L, 1);
diff --git a/board/ryu/board.h b/board/ryu/board.h
index 83c612e3f1..8bb3494c2f 100644
--- a/board/ryu/board.h
+++ b/board/ryu/board.h
@@ -135,10 +135,9 @@
/* Enable console over USB */
#define CONFIG_USB_CONSOLE
+#define CONFIG_SPI_MASTER
/* Enable control of SPI over USB */
-#define CONFIG_SPI_MASTER_PORT 2
-#define CONFIG_SPI_CS_GPIO GPIO_SPI_FLASH_NSS
-
+#define CONFIG_SPI_FLASH_PORT 0 /* First SPI master port */
#define CONFIG_USB_SPI
/* Enable Case Closed Debugging */
diff --git a/board/strago/board.c b/board/strago/board.c
index 783b2152bb..24c8fabef0 100644
--- a/board/strago/board.c
+++ b/board/strago/board.c
@@ -30,6 +30,7 @@
#include "pwm.h"
#include "pwm_chip.h"
#include "registers.h"
+#include "spi.h"
#include "temp_sensor.h"
#include "temp_sensor_chip.h"
#include "thermal.h"
@@ -125,6 +126,12 @@ const struct i2c_port_t i2c_ports[] = {
};
const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
+/* SPI master ports */
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_PVT_CS0},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
const enum gpio_signal hibernate_wake_pins[] = {
GPIO_AC_PRESENT,
GPIO_LID_OPEN,
diff --git a/board/strago/board.h b/board/strago/board.h
index 04828dc73f..4a5e783b73 100644
--- a/board/strago/board.h
+++ b/board/strago/board.h
@@ -46,8 +46,7 @@
#define CONFIG_USBC_SS_MUX
#define CONFIG_USBC_VCONN
-#define CONFIG_SPI_PORT 1
-#define CONFIG_SPI_CS_GPIO GPIO_PVT_CS0
+#define CONFIG_SPI_FLASH_PORT 1
#define CONFIG_SPI_FLASH
#define CONFIG_SPI_FLASH_SIZE 524288
#define CONFIG_SPI_FLASH_W25Q64
diff --git a/chip/it83xx/spi.c b/chip/it83xx/spi.c
index 12955c80e3..83eff6efe7 100644
--- a/chip/it83xx/spi.c
+++ b/chip/it83xx/spi.c
@@ -72,7 +72,8 @@ static void sspi_transmission_end(void)
IT83XX_SSPI_SPISTS = 0x02;
}
-int spi_enable(int enable)
+/* We assume only one SPI port in the chip, one SPI device */
+int spi_enable(int port, int enable)
{
if (enable) {
/*
@@ -96,7 +97,8 @@ int spi_enable(int enable)
return EC_SUCCESS;
}
-int spi_transaction(const uint8_t *txdata, int txlen,
+int spi_transaction(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen)
{
int idx;
@@ -152,6 +154,6 @@ static void sspi_init(void)
IT83XX_SSPI_SPICTRL2 |= 0x02;
/* Disabling spi module */
- spi_enable(0);
+ spi_enable(NULL, 0);
}
DECLARE_HOOK(HOOK_INIT, sspi_init, HOOK_PRIO_DEFAULT);
diff --git a/chip/lm4/spi.c b/chip/lm4/spi.c
index f6afd7cbd8..b0b92d86e6 100644
--- a/chip/lm4/spi.c
+++ b/chip/lm4/spi.c
@@ -19,14 +19,23 @@
#define CPRINTS(format, args...) cprints(CC_SPI, format, ## args)
-int spi_enable(int enable)
+int spi_enable(int port, int enable)
{
+ int i;
+
if (enable) {
gpio_config_module(MODULE_SPI, 1);
- /* Don't use the SSI0 frame output. CS# is a GPIO so we can
- * keep it low during an entire transaction. */
- gpio_set_flags(GPIO_SPI_CS_L, GPIO_OUTPUT);
- gpio_set_level(GPIO_SPI_CS_L, 1);
+ for (i = 0; i < spi_devices_used; i++) {
+ if (spi_devices[i].port != port)
+ continue;
+ /*
+ * Don't use the SSI0 frame output.
+ * CS# is a GPIO so we can keep it low during an entire
+ * transaction.
+ */
+ gpio_set_flags(spi_device[i]->gpio_cs, GPIO_OUTPUT);
+ gpio_set_level(spi_device[i]->gpio_cs, 1);
+ }
/* Enable SSI port */
LM4_SSI_CR1(0) |= 0x02;
@@ -34,9 +43,13 @@ int spi_enable(int enable)
/* Disable SSI port */
LM4_SSI_CR1(0) &= ~0x02;
- /* Make sure CS# is deselected */
- gpio_set_level(GPIO_SPI_CS_L, 1);
- gpio_set_flags(GPIO_SPI_CS_L, GPIO_ODR_HIGH);
+ for (i = 0; i < spi_devices_used; i++) {
+ if (spi_devices[i].port != port)
+ continue;
+ /* Make sure CS# is deselected */
+ gpio_set_level(spi_device[i]->gpio_cs, 1);
+ gpio_set_flags(spi_device->gpio_cs[i], GPIO_ODR_HIGH);
+ }
gpio_config_module(MODULE_SPI, 0);
}
@@ -45,7 +58,8 @@ int spi_enable(int enable)
}
-int spi_transaction(const uint8_t *txdata, int txlen,
+int spi_transaction(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen)
{
int totallen = txlen + rxlen;
@@ -59,7 +73,7 @@ int spi_transaction(const uint8_t *txdata, int txlen,
/* Start transaction. Need to do this explicitly because the LM4
* SSI controller pulses its frame select every byte, and the EEPROM
* wants the chip select held low during the entire transaction. */
- gpio_set_level(GPIO_SPI_CS_L, 0);
+ gpio_set_level(spi_device->gpio_cs, 0);
while (rxcount < totallen) {
/* Handle received bytes if any. We just checked rxcount <
@@ -89,7 +103,7 @@ int spi_transaction(const uint8_t *txdata, int txlen,
}
/* End transaction */
- gpio_set_level(GPIO_SPI_CS_L, 1);
+ gpio_set_level(spi_device->gpio_cs, 1);
return EC_SUCCESS;
}
@@ -120,7 +134,7 @@ static int spi_init(void)
/* Ensure the SPI port is disabled. This keeps us from interfering
* with the main chipset when we're not explicitly using the SPI
* bus. */
- spi_enable(0);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 0);
return EC_SUCCESS;
}
@@ -136,7 +150,7 @@ static int printrx(const char *desc, const uint8_t *txdata, int txlen,
int rv;
int i;
- rv = spi_transaction(txdata, txlen, rxdata, rxlen);
+ rv = spi_transaction(SPI_FLASH_DEVICE, txdata, txlen, rxdata, rxlen);
if (rv)
return rv;
@@ -156,7 +170,7 @@ static int command_spirom(int argc, char **argv)
uint8_t txsr1[] = {0x05};
uint8_t txsr2[] = {0x35};
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
printrx("Man/Dev ID", txmandev, sizeof(txmandev), 2);
printrx("JEDEC ID", txjedec, sizeof(txjedec), 3);
@@ -164,7 +178,7 @@ static int command_spirom(int argc, char **argv)
printrx("Status reg 1", txsr1, sizeof(txsr1), 1);
printrx("Status reg 2", txsr2, sizeof(txsr2), 1);
- spi_enable(0);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 0);
return EC_SUCCESS;
}
diff --git a/chip/mec1322/lfw/ec_lfw.c b/chip/mec1322/lfw/ec_lfw.c
index 1b9e1c4be2..43cd7c2b0b 100644
--- a/chip/mec1322/lfw/ec_lfw.c
+++ b/chip/mec1322/lfw/ec_lfw.c
@@ -36,6 +36,13 @@ const struct int_vector_t hdr_int_vect = {
&fault_handler /* Bus fault handler */
};
+/* SPI devices - from glados/board.c*/
+const struct spi_device_t spi_devices[] = {
+ { CONFIG_SPI_FLASH_PORT, 0, GPIO_PVT_CS0},
+};
+const unsigned int spi_devices_used = ARRAY_SIZE(spi_devices);
+
+
void timer_init()
{
uint32_t val = 0;
@@ -79,7 +86,7 @@ static int spi_flash_readloc(uint8_t *buf_usr,
if (offset + bytes > CONFIG_SPI_FLASH_SIZE)
return EC_ERROR_INVAL;
- return spi_transaction(cmd, 4, buf_usr, bytes);
+ return spi_transaction(SPI_FLASH_DEVICE, cmd, 4, buf_usr, bytes);
}
int spi_image_load(uint32_t offset)
@@ -90,9 +97,7 @@ int spi_image_load(uint32_t offset)
memset((void *)buf, 0xFF, (CONFIG_FW_IMAGE_SIZE - 4));
for (i = 0; i < CONFIG_FW_IMAGE_SIZE; i += SPI_CHUNK_SIZE)
- spi_flash_readloc(&buf[i],
- offset + i,
- SPI_CHUNK_SIZE);
+ spi_flash_readloc(&buf[i], offset + i, SPI_CHUNK_SIZE);
return 0;
@@ -239,7 +244,7 @@ void lfw_main()
dma_init();
uart_init();
system_init();
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
uart_puts("littlefw");
uart_puts(version_data.version);
diff --git a/chip/mec1322/spi.c b/chip/mec1322/spi.c
index bbd6e36a34..61d04028a3 100644
--- a/chip/mec1322/spi.c
+++ b/chip/mec1322/spi.c
@@ -22,7 +22,7 @@
#define SPI_BYTE_TRANSFER_TIMEOUT_US (3 * MSEC)
#define SPI_BYTE_TRANSFER_POLL_INTERVAL_US 100
-#define SPI_DMA_CHANNEL (MEC1322_DMAC_SPI0_RX + CONFIG_SPI_PORT * 2)
+#define SPI_DMA_CHANNEL(port) (MEC1322_DMAC_SPI0_RX + (port) * 2)
/* only regular image needs mutex, LFW does not have scheduling */
/* TODO: Move SPI locking to common code */
@@ -30,17 +30,19 @@
static struct mutex spi_mutex;
#endif
-static const struct dma_option spi_rx_option = {
- SPI_DMA_CHANNEL, (void *)&MEC1322_SPI_RD(CONFIG_SPI_PORT),
- MEC1322_DMA_XFER_SIZE(1)
+static const struct dma_option spi_rx_option[] = {
+ {
+ SPI_DMA_CHANNEL(0), (void *)&MEC1322_SPI_RD(0),
+ MEC1322_DMA_XFER_SIZE(1)
+ },
};
-static int wait_byte(void)
+static int wait_byte(const int port)
{
timestamp_t deadline;
deadline.val = get_time().val + SPI_BYTE_TRANSFER_TIMEOUT_US;
- while ((MEC1322_SPI_SR(CONFIG_SPI_PORT) & 0x3) != 0x3) {
+ while ((MEC1322_SPI_SR(port) & 0x3) != 0x3) {
if (timestamp_expired(deadline, NULL))
return EC_ERROR_TIMEOUT;
usleep(SPI_BYTE_TRANSFER_POLL_INTERVAL_US);
@@ -48,76 +50,80 @@ static int wait_byte(void)
return EC_SUCCESS;
}
-static int spi_tx(const uint8_t *txdata, int txlen)
+static int spi_tx(const int port, const uint8_t *txdata, int txlen)
{
int i;
int ret = EC_SUCCESS;
uint8_t dummy __attribute__((unused)) = 0;
for (i = 0; i < txlen; ++i) {
- MEC1322_SPI_TD(CONFIG_SPI_PORT) = txdata[i];
- ret = wait_byte();
+ MEC1322_SPI_TD(port) = txdata[i];
+ ret = wait_byte(port);
if (ret != EC_SUCCESS)
return ret;
- dummy = MEC1322_SPI_RD(CONFIG_SPI_PORT);
+ dummy = MEC1322_SPI_RD(port);
}
return ret;
}
-int spi_transaction_async(const uint8_t *txdata, int txlen,
+int spi_transaction_async(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen)
{
+ int port = spi_device->port;
int ret = EC_SUCCESS;
- gpio_set_level(CONFIG_SPI_CS_GPIO, 0);
+ gpio_set_level(spi_device->gpio_cs, 0);
/* Disable auto read */
- MEC1322_SPI_CR(CONFIG_SPI_PORT) &= ~(1 << 5);
+ MEC1322_SPI_CR(port) &= ~(1 << 5);
- ret = spi_tx(txdata, txlen);
+ ret = spi_tx(port, txdata, txlen);
if (ret != EC_SUCCESS)
return ret;
/* Enable auto read */
- MEC1322_SPI_CR(CONFIG_SPI_PORT) |= 1 << 5;
+ MEC1322_SPI_CR(port) |= 1 << 5;
if (rxlen != 0) {
- dma_start_rx(&spi_rx_option, rxlen, rxdata);
- MEC1322_SPI_TD(CONFIG_SPI_PORT) = 0;
+ dma_start_rx(&spi_rx_option[port], rxlen, rxdata);
+ MEC1322_SPI_TD(port) = 0;
}
return ret;
}
-int spi_transaction_flush(void)
+int spi_transaction_flush(const struct spi_device_t *spi_device)
{
- int ret = dma_wait(SPI_DMA_CHANNEL);
+ int port = spi_device->port;
+ int ret = dma_wait(SPI_DMA_CHANNEL(port));
uint8_t dummy __attribute__((unused)) = 0;
timestamp_t deadline;
/* Disable auto read */
- MEC1322_SPI_CR(CONFIG_SPI_PORT) &= ~(1 << 5);
+ MEC1322_SPI_CR(port) &= ~(1 << 5);
deadline.val = get_time().val + SPI_BYTE_TRANSFER_TIMEOUT_US;
/* Wait for FIFO empty SPISR_TXBE */
- while ((MEC1322_SPI_SR(CONFIG_SPI_PORT) & 0x01) != 0x1) {
+ while ((MEC1322_SPI_SR(port) & 0x01) != 0x1) {
if (timestamp_expired(deadline, NULL))
return EC_ERROR_TIMEOUT;
usleep(SPI_BYTE_TRANSFER_POLL_INTERVAL_US);
}
- dma_disable(SPI_DMA_CHANNEL);
- dma_clear_isr(SPI_DMA_CHANNEL);
- if (MEC1322_SPI_SR(CONFIG_SPI_PORT) & 0x2)
- dummy = MEC1322_SPI_RD(CONFIG_SPI_PORT);
+ dma_disable(SPI_DMA_CHANNEL(port));
+ dma_clear_isr(SPI_DMA_CHANNEL(port));
+ if (MEC1322_SPI_SR(port) & 0x2)
+ dummy = MEC1322_SPI_RD(port);
- gpio_set_level(CONFIG_SPI_CS_GPIO, 1);
+ gpio_set_level(spi_device->gpio_cs, 1);
return ret;
}
-int spi_transaction(const uint8_t *txdata, int txlen,
+int spi_transaction(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen)
{
int ret;
@@ -125,10 +131,10 @@ int spi_transaction(const uint8_t *txdata, int txlen,
#ifndef LFW
mutex_lock(&spi_mutex);
#endif
- ret = spi_transaction_async(txdata, txlen, rxdata, rxlen);
+ ret = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen);
if (ret)
return ret;
- ret = spi_transaction_flush();
+ ret = spi_transaction_flush(spi_device);
#ifndef LFW
mutex_unlock(&spi_mutex);
@@ -136,25 +142,25 @@ int spi_transaction(const uint8_t *txdata, int txlen,
return ret;
}
-int spi_enable(int enable)
+int spi_enable(int port, int enable)
{
if (enable) {
gpio_config_module(MODULE_SPI, 1);
/* Set enable bit in SPI_AR */
- MEC1322_SPI_AR(CONFIG_SPI_PORT) |= 0x1;
+ MEC1322_SPI_AR(port) |= 0x1;
/* Set SPDIN to 0 -> Full duplex */
- MEC1322_SPI_CR(CONFIG_SPI_PORT) &= ~(0x3 << 2);
+ MEC1322_SPI_CR(port) &= ~(0x3 << 2);
/* Set CLKPOL, TCLKPH, RCLKPH to 0 */
- MEC1322_SPI_CC(CONFIG_SPI_PORT) &= ~0x7;
+ MEC1322_SPI_CC(port) &= ~0x7;
/* Set LSBF to 0 -> MSB first */
- MEC1322_SPI_CR(CONFIG_SPI_PORT) &= ~0x1;
+ MEC1322_SPI_CR(port) &= ~0x1;
} else {
/* Clear enable bit in SPI_AR */
- MEC1322_SPI_AR(CONFIG_SPI_PORT) &= ~0x1;
+ MEC1322_SPI_AR(port) &= ~0x1;
gpio_config_module(MODULE_SPI, 0);
}
diff --git a/chip/mec1322/system.c b/chip/mec1322/system.c
index e7b8b43b6b..acbbe0320f 100644
--- a/chip/mec1322/system.c
+++ b/chip/mec1322/system.c
@@ -88,7 +88,7 @@ void system_pre_init(void)
/* Deassert nSIO_RESET */
MEC1322_PCR_PWR_RST_CTL &= ~(1 << 0);
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
}
void _system_reset(int flags, int wake_from_hibernate)
diff --git a/chip/npcx/spi.c b/chip/npcx/spi.c
index 82a1b31dbb..b3d6ec07d7 100644
--- a/chip/npcx/spi.c
+++ b/chip/npcx/spi.c
@@ -68,29 +68,43 @@ DECLARE_HOOK(HOOK_FREQ_CHANGE, spi_freq_changed, HOOK_PRIO_FIRST);
/**
* Set SPI enabled.
*
+ * @spi_port port to act on. Only one port supported, one gpio.
* @param enable enabled flag
* @return success
*/
-int spi_enable(int enable)
+int spi_enable(int port, int enable)
{
+ int i;
+ enum gpio_signal gpio;
+
if (enable) {
/* Enabling spi module for gpio configuration */
gpio_config_module(MODULE_SPI, 1);
/* GPIO No SPI Select */
CLEAR_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP);
- /* Make sure CS# is a GPIO output mode. */
- gpio_set_flags(GPIO_SPI_CS_L, GPIO_OUTPUT);
- /* Make sure CS# is deselected */
- gpio_set_level(GPIO_SPI_CS_L, 1);
+ for (i = 0; i < spi_devices_used; i++) {
+ if (spi_devices[i].port != port)
+ continue;
+ gpio = spi_devices[i].gpio_cs;
+ /* Make sure CS# is a GPIO output mode. */
+ gpio_set_flags(gpio, GPIO_OUTPUT);
+ /* Make sure CS# is deselected */
+ gpio_set_level(gpio, 1);
+ }
/* Enabling spi module */
SET_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN);
} else {
/* Disabling spi module */
CLEAR_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_SPIEN);
- /* Make sure CS# is deselected */
- gpio_set_level(GPIO_SPI_CS_L, 1);
- gpio_set_flags(GPIO_SPI_CS_L, GPIO_ODR_HIGH);
+ for (i = 0; i < spi_devices_used; i++) {
+ if (spi_devices[i].port != port)
+ continue;
+ gpio = spi_devices[i].gpio_cs;
+ /* Make sure CS# is deselected */
+ gpio_set_level(gpio, 1);
+ gpio_set_flags(gpio, GPIO_ODR_HIGH);
+ }
/* Disabling spi module for gpio configuration */
gpio_config_module(MODULE_SPI, 0);
/* GPIO No SPI Select */
@@ -103,6 +117,7 @@ int spi_enable(int enable)
/**
* Flush an SPI transaction and receive data from slave.
*
+ * @param spi_device device to talk to
* @param txdata transfer data
* @param txlen transfer length
* @param rxdata receive data
@@ -110,19 +125,21 @@ int spi_enable(int enable)
* @return success
* @notes set master transaction mode in npcx chip
*/
-int spi_transaction(const uint8_t *txdata, int txlen,
+int spi_transaction(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen)
{
int i = 0;
+ enum gpio_signal gpio = spi_device->gpio_cs;
/* Make sure CS# is a GPIO output mode. */
- gpio_set_flags(GPIO_SPI_CS_L, GPIO_OUTPUT);
+ gpio_set_flags(gpio, GPIO_OUTPUT);
/* Make sure CS# is deselected */
- gpio_set_level(GPIO_SPI_CS_L, 1);
+ gpio_set_level(gpio, 1);
/* Cleaning junk data in the buffer */
clear_databuf();
/* Assert CS# to start transaction */
- gpio_set_level(GPIO_SPI_CS_L, 0);
+ gpio_set_level(gpio, 0);
CPRINTS("NPCX_SPI_DATA=%x", NPCX_SPI_DATA);
CPRINTS("NPCX_SPI_CTL1=%x", NPCX_SPI_CTL1);
CPRINTS("NPCX_SPI_STAT=%x", NPCX_SPI_STAT);
@@ -156,7 +173,7 @@ int spi_transaction(const uint8_t *txdata, int txlen,
CPRINTS("rxdata[i]=%x", rxdata[i]);
}
/* Deassert CS# (high) to end transaction */
- gpio_set_level(GPIO_SPI_CS_L, 1);
+ gpio_set_level(gpio, 1);
return EC_SUCCESS;
}
@@ -174,7 +191,7 @@ static void spi_init(void)
CGC_MODE_RUN | CGC_MODE_SLEEP);
/* Disabling spi module */
- spi_enable(0);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 0);
/* Disabling spi irq */
CLEAR_BIT(NPCX_SPI_CTL1, NPCX_SPI_CTL1_EIR);
@@ -208,7 +225,7 @@ static int printrx(const char *desc, const uint8_t *txdata, int txlen,
int rv;
int i;
- rv = spi_transaction(txdata, txlen, rxdata, rxlen);
+ rv = spi_transaction(SPI_FLASH_DEVICE, txdata, txlen, rxdata, rxlen);
if (rv)
return rv;
@@ -228,7 +245,7 @@ static int command_spirom(int argc, char **argv)
uint8_t txsr1[] = {0x05};
uint8_t txsr2[] = {0x35};
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
printrx("Man/Dev ID", txmandev, sizeof(txmandev), 2);
printrx("JEDEC ID", txjedec, sizeof(txjedec), 3);
@@ -236,7 +253,7 @@ static int command_spirom(int argc, char **argv)
printrx("Status reg 1", txsr1, sizeof(txsr1), 1);
printrx("Status reg 2", txsr2, sizeof(txsr2), 1);
- spi_enable(0);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 0);
return EC_SUCCESS;
}
diff --git a/chip/stm32/build.mk b/chip/stm32/build.mk
index 8ec6191397..72be7eb6d4 100644
--- a/chip/stm32/build.mk
+++ b/chip/stm32/build.mk
@@ -30,7 +30,7 @@ chip-y=dma.o
chip-$(CONFIG_COMMON_RUNTIME)+=system.o
chip-y+=jtag-$(CHIP_FAMILY).o clock-$(CHIP_FAMILY).o
chip-$(CONFIG_SPI)+=spi.o
-chip-$(CONFIG_SPI_MASTER_PORT)+=spi_master.o
+chip-$(CONFIG_SPI_MASTER)+=spi_master.o
chip-$(CONFIG_COMMON_GPIO)+=gpio.o gpio-$(CHIP_FAMILY).o
chip-$(CONFIG_COMMON_TIMER)+=hwtimer$(TIMER_TYPE).o
chip-$(CONFIG_I2C)+=i2c-$(CHIP_FAMILY).o
diff --git a/chip/stm32/spi_master.c b/chip/stm32/spi_master.c
index ab95ca6594..858fede3f0 100644
--- a/chip/stm32/spi_master.c
+++ b/chip/stm32/spi_master.c
@@ -14,38 +14,50 @@
#include "timer.h"
#include "util.h"
-#define SPI_REG_ADDR CONCAT3(STM32_SPI, CONFIG_SPI_MASTER_PORT, _BASE)
-#define SPI_REG ((stm32_spi_regs_t *)SPI_REG_ADDR)
-#define DMAC_SPI_TX CONCAT3(STM32_DMAC_SPI, CONFIG_SPI_MASTER_PORT, _TX)
-#define DMAC_SPI_RX CONCAT3(STM32_DMAC_SPI, CONFIG_SPI_MASTER_PORT, _RX)
+/* The second (and third if available) SPI port are used as master */
+static stm32_spi_regs_t *SPI_REGS[] = {
+ STM32_SPI2_REGS,
+};
#define SPI_TRANSACTION_TIMEOUT_USEC (800 * MSEC)
/* Default DMA channel options */
-static const struct dma_option dma_tx_option = {
- DMAC_SPI_TX, (void *)&SPI_REG->dr,
- STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT
+static const struct dma_option dma_tx_option[] = {
+ {
+ STM32_DMAC_SPI2_TX, (void *)&STM32_SPI2_REGS->dr,
+ STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT
+ },
};
-static const struct dma_option dma_rx_option = {
- DMAC_SPI_RX, (void *)&SPI_REG->dr,
- STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT
+static const struct dma_option dma_rx_option[] = {
+ {
+ STM32_DMAC_SPI2_RX, (void *)&STM32_SPI2_REGS->dr,
+ STM32_DMA_CCR_MSIZE_8_BIT | STM32_DMA_CCR_PSIZE_8_BIT
+ },
};
-static uint8_t spi_enabled;
+static uint8_t spi_enabled[ARRAY_SIZE(SPI_REGS)];
/**
* Initialize SPI module, registers, and clocks
+ *
+ * - port: which port to initialize.
*/
-static int spi_master_initialize(void)
+static int spi_master_initialize(int port)
{
- stm32_spi_regs_t *spi = SPI_REG;
+ int i, div = 0;
+
+ stm32_spi_regs_t *spi = SPI_REGS[port];
/*
* Set SPI master, baud rate, and software slave control.
- * Set SPI clock rate to DIV2R = 24 MHz
* */
- spi->cr1 = STM32_SPI_CR1_MSTR | STM32_SPI_CR1_SSM | STM32_SPI_CR1_SSI;
+ for (i = 0; i < spi_devices_used; i++)
+ if ((spi_devices[i].port == port) &&
+ (div < spi_devices[i].div))
+ div = spi_devices[i].div;
+ spi->cr1 = STM32_SPI_CR1_MSTR | STM32_SPI_CR1_SSM | STM32_SPI_CR1_SSI |
+ (div << 3);
/*
* Configure 8-bit datasize, set FRXTH, enable DMA,
@@ -57,11 +69,15 @@ static int spi_master_initialize(void)
/* Enable SPI */
spi->cr1 |= STM32_SPI_CR1_SPE;
- /* Drive SS high */
- gpio_set_level(CONFIG_SPI_CS_GPIO, 1);
+ for (i = 0; i < spi_devices_used; i++) {
+ if (spi_devices[i].port != port)
+ continue;
+ /* Drive SS high */
+ gpio_set_level(spi_devices[i].gpio_cs, 1);
+ }
/* Set flag */
- spi_enabled = 1;
+ spi_enabled[port] = 1;
return EC_SUCCESS;
}
@@ -69,18 +85,19 @@ static int spi_master_initialize(void)
/**
* Shutdown SPI module
*/
-static int spi_master_shutdown(void)
+static int spi_master_shutdown(int port)
{
int rv = EC_SUCCESS;
- stm32_spi_regs_t *spi = SPI_REG;
+
+ stm32_spi_regs_t *spi = SPI_REGS[port];
char dummy __attribute__((unused));
/* Set flag */
- spi_enabled = 0;
+ spi_enabled[port] = 0;
/* Disable DMA streams */
- dma_disable(dma_tx_option.channel);
- dma_disable(dma_rx_option.channel);
+ dma_disable(dma_tx_option[port].channel);
+ dma_disable(dma_rx_option[port].channel);
/* Disable SPI */
spi->cr1 &= ~STM32_SPI_CR1_SPE;
@@ -95,39 +112,40 @@ static int spi_master_shutdown(void)
return rv;
}
-int spi_enable(int enable)
+int spi_enable(int port, int enable)
{
- if (enable == spi_enabled)
+ if (enable == spi_enabled[port])
return EC_SUCCESS;
if (enable)
- return spi_master_initialize();
+ return spi_master_initialize(port);
else
- return spi_master_shutdown();
+ return spi_master_shutdown(port);
}
-static int spi_dma_start(const uint8_t *txdata, uint8_t *rxdata, int len)
+static int spi_dma_start(int port, const uint8_t *txdata,
+ uint8_t *rxdata, int len)
{
stm32_dma_chan_t *txdma;
/* Set up RX DMA */
- dma_start_rx(&dma_rx_option, len, rxdata);
+ dma_start_rx(&dma_rx_option[port], len, rxdata);
/* Set up TX DMA */
- txdma = dma_get_channel(dma_tx_option.channel);
- dma_prepare_tx(&dma_tx_option, len, txdata);
+ txdma = dma_get_channel(dma_tx_option[port].channel);
+ dma_prepare_tx(&dma_tx_option[port], len, txdata);
dma_go(txdma);
return EC_SUCCESS;
}
-static int spi_dma_wait(void)
+static int spi_dma_wait(int port)
{
timestamp_t timeout;
- stm32_spi_regs_t *spi = SPI_REG;
+ stm32_spi_regs_t *spi = SPI_REGS[port];
int rv = EC_SUCCESS;
/* Wait for DMA transmission to complete */
- rv = dma_wait(dma_tx_option.channel);
+ rv = dma_wait(dma_tx_option[port].channel);
if (rv)
return rv;
@@ -138,10 +156,10 @@ static int spi_dma_wait(void)
return EC_ERROR_TIMEOUT;
/* Disable TX DMA */
- dma_disable(dma_tx_option.channel);
+ dma_disable(dma_tx_option[port].channel);
/* Wait for DMA reception to complete */
- rv = dma_wait(dma_rx_option.channel);
+ rv = dma_wait(dma_rx_option[port].channel);
if (rv)
return rv;
@@ -152,16 +170,19 @@ static int spi_dma_wait(void)
return EC_ERROR_TIMEOUT;
/* Disable RX DMA */
- dma_disable(dma_rx_option.channel);
+ dma_disable(dma_rx_option[port].channel);
return rv;
}
-int spi_transaction_async(const uint8_t *txdata, int txlen,
+int spi_transaction_async(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen)
{
int rv = EC_SUCCESS;
- stm32_spi_regs_t *spi = SPI_REG;
+ int port = spi_device->port;
+
+ stm32_spi_regs_t *spi = SPI_REGS[port];
char *buf;
rv = shared_mem_acquire(MAX(txlen, rxlen), &buf);
@@ -169,22 +190,22 @@ int spi_transaction_async(const uint8_t *txdata, int txlen,
return rv;
/* Drive SS low */
- gpio_set_level(CONFIG_SPI_CS_GPIO, 0);
+ gpio_set_level(spi_device->gpio_cs, 0);
/* Clear out the FIFO. */
while (spi->sr & STM32_SPI_SR_FRLVL)
(void) (uint8_t) spi->dr;
- rv = spi_dma_start(txdata, buf, txlen);
+ rv = spi_dma_start(port, txdata, buf, txlen);
if (rv != EC_SUCCESS)
goto err_free;
- rv = spi_dma_wait();
+ rv = spi_dma_wait(port);
if (rv != EC_SUCCESS)
goto err_free;
if (rxlen) {
- rv = spi_dma_start(buf, rxdata, rxlen);
+ rv = spi_dma_start(port, buf, rxdata, rxlen);
if (rv != EC_SUCCESS)
goto err_free;
}
@@ -194,23 +215,24 @@ err_free:
return rv;
}
-int spi_transaction_flush(void)
+int spi_transaction_flush(const struct spi_device_t *spi_device)
{
- int rv = spi_dma_wait();
+ int rv = spi_dma_wait(spi_device->port);
/* Drive SS high */
- gpio_set_level(CONFIG_SPI_CS_GPIO, 1);
+ gpio_set_level(spi_device->gpio_cs, 1);
return rv;
}
-int spi_transaction(const uint8_t *txdata, int txlen,
+int spi_transaction(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen)
{
int rv;
- rv = spi_transaction_async(txdata, txlen, rxdata, rxlen);
- rv |= spi_transaction_flush();
+ rv = spi_transaction_async(spi_device, txdata, txlen, rxdata, rxlen);
+ rv |= spi_transaction_flush(spi_device);
return rv;
}
diff --git a/chip/stm32/usb_spi.c b/chip/stm32/usb_spi.c
index c81f01ac23..3998b429d2 100644
--- a/chip/stm32/usb_spi.c
+++ b/chip/stm32/usb_spi.c
@@ -98,7 +98,8 @@ void usb_spi_deferred(struct usb_spi_config const *config)
config->buffer[0] = USB_SPI_READ_COUNT_INVALID;
} else {
config->buffer[0] = usb_spi_map_error(
- spi_transaction((uint8_t *)(config->buffer + 1),
+ spi_transaction(SPI_FLASH_DEVICE,
+ (uint8_t *)(config->buffer + 1),
write_count,
(uint8_t *)(config->buffer + 1),
read_count));
diff --git a/common/spi_flash.c b/common/spi_flash.c
index 417f97dfd1..2407f9120d 100644
--- a/common/spi_flash.c
+++ b/common/spi_flash.c
@@ -59,7 +59,7 @@ int spi_flash_wait(void)
static int spi_flash_write_enable(void)
{
uint8_t cmd = SPI_FLASH_WRITE_ENABLE;
- return spi_transaction(&cmd, 1, NULL, 0);
+ return spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, NULL, 0);
}
/**
@@ -71,7 +71,7 @@ uint8_t spi_flash_get_status1(void)
uint8_t cmd = SPI_FLASH_READ_SR1;
uint8_t resp;
- if (spi_transaction(&cmd, 1, &resp, 1) != EC_SUCCESS)
+ if (spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, &resp, 1) != EC_SUCCESS)
return -1;
return resp;
@@ -91,7 +91,7 @@ uint8_t spi_flash_get_status2(void)
return 0;
#endif
- if (spi_transaction(&cmd, 1, &resp, 1) != EC_SUCCESS)
+ if (spi_transaction(SPI_FLASH_DEVICE, &cmd, 1, &resp, 1) != EC_SUCCESS)
return -1;
return resp;
@@ -127,9 +127,9 @@ int spi_flash_set_status(int reg1, int reg2)
#endif
if (reg2 == -1)
- rv = spi_transaction(cmd, 2, NULL, 0);
+ rv = spi_transaction(SPI_FLASH_DEVICE, cmd, 2, NULL, 0);
else
- rv = spi_transaction(cmd, 3, NULL, 0);
+ rv = spi_transaction(SPI_FLASH_DEVICE, cmd, 3, NULL, 0);
if (rv)
return rv;
@@ -158,7 +158,7 @@ int spi_flash_read(uint8_t *buf_usr, unsigned int offset, unsigned int bytes)
if (offset + bytes > CONFIG_SPI_FLASH_SIZE)
return EC_ERROR_INVAL;
- return spi_transaction(cmd, 4, buf_usr, bytes);
+ return spi_transaction(SPI_FLASH_DEVICE, cmd, 4, buf_usr, bytes);
}
/**
@@ -198,7 +198,7 @@ static int spi_flash_erase_block(unsigned int offset, unsigned int block)
cmd[2] = (offset >> 8) & 0xFF;
cmd[3] = offset & 0xFF;
- rv = spi_transaction(cmd, 4, NULL, 0);
+ rv = spi_transaction(SPI_FLASH_DEVICE, cmd, 4, NULL, 0);
if (rv)
return rv;
@@ -294,7 +294,8 @@ int spi_flash_write(unsigned int offset, unsigned int bytes,
buf[2] = (offset) >> 8;
buf[3] = offset;
- rv = spi_transaction(buf, 4 + write_size, NULL, 0);
+ rv = spi_transaction(SPI_FLASH_DEVICE,
+ buf, 4 + write_size, NULL, 0);
if (rv)
return rv;
@@ -316,7 +317,8 @@ uint32_t spi_flash_get_jedec_id(void)
uint8_t cmd = SPI_FLASH_JEDEC_ID;
uint32_t resp;
- if (spi_transaction(&cmd, 1, (uint8_t *)&resp, 4) != EC_SUCCESS)
+ if (spi_transaction(SPI_FLASH_DEVICE,
+ &cmd, 1, (uint8_t *)&resp, 4) != EC_SUCCESS)
return -1;
return resp;
@@ -332,7 +334,8 @@ uint64_t spi_flash_get_unique_id(void)
uint8_t cmd[5] = {SPI_FLASH_UNIQUE_ID, 0, 0, 0, 0};
uint64_t resp;
- if (spi_transaction(cmd, 5, (uint8_t *)&resp, 8) != EC_SUCCESS)
+ if (spi_transaction(SPI_FLASH_DEVICE,
+ cmd, 5, (uint8_t *)&resp, 8) != EC_SUCCESS)
return -1;
return resp;
@@ -459,7 +462,7 @@ static int command_spi_flashinfo(int argc, char **argv)
uint64_t unique;
int rv;
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
/* Wait for previous operation to complete */
rv = spi_flash_wait();
@@ -497,7 +500,7 @@ static int command_spi_flasherase(int argc, char **argv)
if (rv)
return rv;
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
/* Chip has protection */
if (spi_flash_check_protect(offset, bytes))
@@ -533,7 +536,7 @@ static int command_spi_flashwrite(int argc, char **argv)
if (rv)
return rv;
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
/* Chip has protection */
if (spi_flash_check_protect(offset, bytes))
@@ -586,7 +589,7 @@ static int command_spi_flashread(int argc, char **argv)
if (rv)
return rv;
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
/* Can't read past size of memory */
if (offset + bytes > CONFIG_SPI_FLASH_SIZE)
@@ -635,7 +638,7 @@ DECLARE_CONSOLE_COMMAND(spi_flashread, command_spi_flashread,
static int command_spi_flashread_sr(int argc, char **argv)
{
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
ccprintf("Status Register 1: 0x%02x\n", spi_flash_get_status1());
ccprintf("Status Register 2: 0x%02x\n", spi_flash_get_status2());
@@ -656,7 +659,7 @@ static int command_spi_flashwrite_sr(int argc, char **argv)
if (rv)
return rv;
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
/* Wait for previous operation to complete */
rv = spi_flash_wait();
@@ -686,7 +689,7 @@ static int command_spi_flashprotect(int argc, char **argv)
if (rv)
return rv;
- spi_enable(1);
+ spi_enable(CONFIG_SPI_FLASH_PORT, 1);
/* Wait for previous operation to complete */
rv = spi_flash_wait();
diff --git a/include/config.h b/include/config.h
index 2c463bec8b..07e55516b9 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1349,7 +1349,7 @@
/* Support smbus interface */
#undef CONFIG_SMBUS
-/* Support SPI master interfaces */
+/* Support SPI interfaces */
#undef CONFIG_SPI
/*
@@ -1360,12 +1360,12 @@
*/
#undef CONFIG_SPS
-/* Define SPI chip select GPIO pin. */
-#undef CONFIG_SPI_CS_GPIO
-
/* Support SPI flash */
#undef CONFIG_SPI_FLASH
+/* Define the SPI port to use to access the flash */
+#undef CONFIG_SPI_FLASH_PORT
+
/* Support W25Q64 SPI flash */
#undef CONFIG_SPI_FLASH_W25Q64
@@ -1378,11 +1378,8 @@
/* Size (bytes) of SPI flash memory */
#undef CONFIG_SPI_FLASH_SIZE
-/* SPI module port used for master interface */
-#undef CONFIG_SPI_MASTER_PORT
-
-/* SPI module port. */
-#undef CONFIG_SPI_PORT
+/* SPI master feature */
+#undef CONFIG_SPI_MASTER
/* Support testing SPI slave controller driver. */
#undef CONFIG_SPS_TEST
diff --git a/include/spi.h b/include/spi.h
index d62c1420ca..21629ddd4d 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -27,26 +27,69 @@ enum spi_clock_mode {
SPI_CLOCK_MODE3 = 3
};
-/* Enable / disable the SPI port. When the port is disabled, all its I/O lines
- * are high-Z so the EC won't interfere with other devices on the SPI bus. */
-int spi_enable(int enable);
+struct spi_device_t {
+ /*
+ * SPI port the device is connected to.
+ * On some architecture, this is SPI master port index,
+ * on other the SPI port index directly.
+ */
+ uint8_t port;
+
+ /*
+ * Clock divisor to talk to SPI device.
+ * If several devices share the same port, we select the lowest speed.
+ */
+ uint8_t div;
+
+ /* gpio used for chip selection. */
+ enum gpio_signal gpio_cs;
+};
+
+extern const struct spi_device_t spi_devices[];
+extern const unsigned int spi_devices_used;
+
+/*
+ * The first port in spi_ports define the port to access the SPI flash.
+ * The first gpio defines the CS GPIO to access the flash,
+ * if used.
+ */
+#define SPI_FLASH_DEVICE (&spi_devices[0])
+
+/*
+ * Enable / disable the SPI port. When the port is disabled, all its I/O lines
+ * are high-Z so the EC won't interfere with other devices on the SPI bus.
+ *
+ * @param port port id to work on.
+ * @param enable 1 to enable the port, 0 to disable it.
+ */
+int spi_enable(int port, int enable);
/* Issue a SPI transaction. Assumes SPI port has already been enabled.
+ *
* Transmits <txlen> bytes from <txdata>, throwing away the corresponding
* received data, then transmits <rxlen> dummy bytes, saving the received data
- * in <rxdata>. */
-int spi_transaction(const uint8_t *txdata, int txlen,
+ * in <rxdata>.
+ *
+ * @param spi_device the SPI device to use
+ * @param txdata buffer to transmit
+ * @param txlen number of bytes in txdata.
+ * @param rxdata receive buffer.
+ * @param rxlen number of bytes in rxdata.
+ */
+int spi_transaction(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen);
/* Similar to spi_transaction(), but hands over to DMA for reading response.
* Must call spi_transaction_flush() after this to make sure the response is
* received.
*/
-int spi_transaction_async(const uint8_t *txdata, int txlen,
+int spi_transaction_async(const struct spi_device_t *spi_device,
+ const uint8_t *txdata, int txlen,
uint8_t *rxdata, int rxlen);
/* Wait for async response received */
-int spi_transaction_flush(void);
+int spi_transaction_flush(const struct spi_device_t *spi_device);
#ifdef CONFIG_SPI
/**