Skip to content

Commit

Permalink
disk: sdhc: spi: leave SPI CS GPIO handling to the SPI controller driver
Browse files Browse the repository at this point in the history
Leave the SPI CS GPIO handling to the SPI controller driver and make SPI
CS GPIO optional for SDHC disk access via SPI.

The SPI SDHC implementation relies on SPI_HOLD_ON_CS so we need to
explicitly release the SPI controller driver after ending transmissions
to force the CS line to be de-asserted.

Fixes zephyrproject-rtos#27444.

Signed-off-by: Henrik Brix Andersen <[email protected]>
  • Loading branch information
henrikbrixandersen authored and ioannisg committed Aug 25, 2020
1 parent 5c85e2c commit c64e0ce
Showing 1 changed file with 23 additions and 32 deletions.
55 changes: 23 additions & 32 deletions subsys/disk/disk_access_spi_sdhc.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ LOG_MODULE_REGISTER(sdhc_spi, CONFIG_DISK_LOG_LEVEL);
/* Clock speed used after initialisation */
#define SDHC_SPI_SPEED 4000000

#if !DT_NODE_HAS_STATUS(DT_INST(0, zephyr_mmc_spi_slot), okay)
#define SPI_SDHC_NODE DT_INST(0, zephyr_mmc_spi_slot)

#if !DT_NODE_HAS_STATUS(SPI_SDHC_NODE, okay)
#warning NO SDHC slot specified on board
#else
struct sdhc_spi_data {
struct device *spi;
struct spi_config cfg;
struct device *cs;
uint32_t pin;
gpio_dt_flags_t flags;

#if DT_SPI_DEV_HAS_CS_GPIOS(SPI_SDHC_NODE)
struct spi_cs_control cs;
#endif
bool high_capacity;
uint32_t sector_count;
uint8_t status;
Expand Down Expand Up @@ -69,12 +70,6 @@ static int sdhc_spi_trace(struct sdhc_spi_data *data, int dir, int err,
return err;
}

/* Asserts or deasserts chip select */
static void sdhc_spi_set_cs(struct sdhc_spi_data *data, int value)
{
gpio_pin_set(data->cs, data->pin, value);
}

/* Receives a fixed number of bytes */
static int sdhc_spi_rx_bytes(struct sdhc_spi_data *data, uint8_t *buf, int len)
{
Expand Down Expand Up @@ -460,12 +455,9 @@ static int sdhc_spi_recover(struct sdhc_spi_data *data)
/* Attempts to return the card to idle mode */
static int sdhc_spi_go_idle(struct sdhc_spi_data *data)
{
sdhc_spi_set_cs(data, 1);

/* Write the initial >= 74 clocks */
sdhc_spi_tx(data, sdhc_ones, 10);

sdhc_spi_set_cs(data, 0);
spi_release(data->spi, &data->cfg);

return sdhc_spi_cmd_r1_idle(data, SDHC_GO_IDLE_STATE, 0);
}
Expand Down Expand Up @@ -673,8 +665,6 @@ static int sdhc_spi_read(struct sdhc_spi_data *data,
addr = sector * SDMMC_DEFAULT_BLOCK_SIZE;
}

sdhc_spi_set_cs(data, 0);

/* Send the start read command */
err = sdhc_spi_cmd_r1(data, SDHC_READ_MULTIPLE_BLOCK, addr);
if (err != 0) {
Expand All @@ -698,7 +688,7 @@ static int sdhc_spi_read(struct sdhc_spi_data *data,
err = sdhc_spi_skip_until_ready(data);

error:
sdhc_spi_set_cs(data, 1);
spi_release(data->spi, &data->cfg);

return err;
}
Expand All @@ -714,8 +704,6 @@ static int sdhc_spi_write(struct sdhc_spi_data *data,
return err;
}

sdhc_spi_set_cs(data, 0);

/* Write the blocks one-by-one */
for (; count != 0U; count--) {
/* Translate sector number to data address.
Expand Down Expand Up @@ -755,7 +743,7 @@ static int sdhc_spi_write(struct sdhc_spi_data *data,

err = 0;
error:
sdhc_spi_set_cs(data, 1);
spi_release(data->spi, &data->cfg);

return err;
}
Expand All @@ -766,22 +754,25 @@ static int sdhc_spi_init(struct device *dev)
{
struct sdhc_spi_data *data = dev->data;

data->spi = device_get_binding(DT_BUS_LABEL(DT_INST(0, zephyr_mmc_spi_slot)));
data->spi = device_get_binding(DT_BUS_LABEL(SPI_SDHC_NODE));

data->cfg.frequency = SDHC_SPI_INITIAL_SPEED;
data->cfg.operation = SPI_WORD_SET(8) | SPI_HOLD_ON_CS;
data->cfg.slave = DT_REG_ADDR(DT_INST(0, zephyr_mmc_spi_slot));
data->cs = device_get_binding(
DT_SPI_DEV_CS_GPIOS_LABEL(DT_INST(0, zephyr_mmc_spi_slot)));
__ASSERT_NO_MSG(data->cs != NULL);
data->cfg.slave = DT_REG_ADDR(SPI_SDHC_NODE);

data->pin = DT_SPI_DEV_CS_GPIOS_PIN(DT_INST(0, zephyr_mmc_spi_slot));
data->flags = DT_SPI_DEV_CS_GPIOS_FLAGS(DT_INST(0, zephyr_mmc_spi_slot));
#if DT_SPI_DEV_HAS_CS_GPIOS(SPI_SDHC_NODE)
data->cs.gpio_dev =
device_get_binding(DT_SPI_DEV_CS_GPIOS_LABEL(SPI_SDHC_NODE));
__ASSERT_NO_MSG(data->cs.gpio_dev != NULL);

data->cs.gpio_pin = DT_SPI_DEV_CS_GPIOS_PIN(SPI_SDHC_NODE);
data->cs.gpio_dt_flags = DT_SPI_DEV_CS_GPIOS_FLAGS(SPI_SDHC_NODE);
data->cfg.cs = &data->cs;
#endif

disk_spi_sdhc_init(dev);

return gpio_pin_configure(data->cs, data->pin,
GPIO_OUTPUT_INACTIVE | data->flags);
return 0;
}

static int disk_spi_sdhc_access_status(struct disk_info *disk)
Expand Down Expand Up @@ -866,7 +857,7 @@ static int disk_spi_sdhc_access_init(struct disk_info *disk)
int err;

err = sdhc_spi_detect(data);
sdhc_spi_set_cs(data, 1);
spi_release(data->spi, &data->cfg);

return err;
}
Expand Down Expand Up @@ -898,7 +889,7 @@ static int disk_spi_sdhc_init(struct device *dev)
static struct sdhc_spi_data sdhc_spi_data_0;

DEVICE_AND_API_INIT(sdhc_spi_0,
DT_LABEL(DT_INST(0, zephyr_mmc_spi_slot)),
DT_LABEL(SPI_SDHC_NODE),
sdhc_spi_init, &sdhc_spi_data_0, NULL,
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, NULL);
#endif

0 comments on commit c64e0ce

Please sign in to comment.