diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2015-07-25 02:14:13 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-07-30 19:57:55 +0000 |
commit | 5b71b33aba6cb0108a864cc7000918b8f06b139a (patch) | |
tree | aa49a59a306d91b189e9fcdddc3bbb0e2deba628 | |
parent | 9008c7a4fd131a96ccb0078a46ec545cff2f43b1 (diff) | |
download | chrome-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.c | 7 | ||||
-rw-r--r-- | board/cyan/board.h | 3 | ||||
-rw-r--r-- | board/discovery-stm32f072/board.c | 11 | ||||
-rw-r--r-- | board/discovery-stm32f072/board.h | 5 | ||||
-rw-r--r-- | board/glados/board.c | 7 | ||||
-rw-r--r-- | board/glados/board.h | 3 | ||||
-rw-r--r-- | board/glower/board.c | 7 | ||||
-rw-r--r-- | board/glower/board.h | 3 | ||||
-rw-r--r-- | board/kunimitsu/board.c | 7 | ||||
-rw-r--r-- | board/kunimitsu/board.h | 3 | ||||
-rw-r--r-- | board/mec1322_evb/board.c | 7 | ||||
-rw-r--r-- | board/mec1322_evb/board.h | 3 | ||||
-rw-r--r-- | board/npcx_evb/board.c | 8 | ||||
-rw-r--r-- | board/npcx_evb/board.h | 1 | ||||
-rw-r--r-- | board/ryu/board.c | 14 | ||||
-rw-r--r-- | board/ryu/board.h | 5 | ||||
-rw-r--r-- | board/strago/board.c | 7 | ||||
-rw-r--r-- | board/strago/board.h | 3 | ||||
-rw-r--r-- | chip/it83xx/spi.c | 8 | ||||
-rw-r--r-- | chip/lm4/spi.c | 44 | ||||
-rw-r--r-- | chip/mec1322/lfw/ec_lfw.c | 15 | ||||
-rw-r--r-- | chip/mec1322/spi.c | 76 | ||||
-rw-r--r-- | chip/mec1322/system.c | 2 | ||||
-rw-r--r-- | chip/npcx/spi.c | 51 | ||||
-rw-r--r-- | chip/stm32/build.mk | 2 | ||||
-rw-r--r-- | chip/stm32/spi_master.c | 120 | ||||
-rw-r--r-- | chip/stm32/usb_spi.c | 3 | ||||
-rw-r--r-- | common/spi_flash.c | 37 | ||||
-rw-r--r-- | include/config.h | 15 | ||||
-rw-r--r-- | include/spi.h | 57 |
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 /** |