Skip to content

Commit 2c3242b

Browse files
committed
sdhc: spi: power up with bus locked
Lock the SPI bus from access by other devices before applying power. Keep the bus locked until the initial 74 clocks and CMD0 are sent to the card. This prevents the card from incorrectly deciding that it should be in SD mode due to bus traffic to other devices while it is going through the init sequence. Signed-off-by: Jordan Yates <[email protected]>
1 parent 1e3c94e commit 2c3242b

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

drivers/sdhc/sdhc_spi.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ struct sdhc_spi_data {
104104
uint8_t scratch[MAX_CMD_READ];
105105
};
106106

107+
static int sdhc_spi_send_cmd(const struct device *dev, struct sdhc_command *cmd, bool data_present);
108+
107109
/* Receives a block of bytes */
108110
static int sdhc_spi_rx(const struct device *spi_dev, struct spi_config *spi_cfg,
109111
uint8_t *buf, int len)
@@ -149,7 +151,7 @@ static int sdhc_spi_init_card(const struct device *dev)
149151
const struct sdhc_spi_config *config = dev->config;
150152
struct sdhc_spi_data *data = dev->data;
151153
struct spi_config *spi_cfg = data->spi_cfg;
152-
int ret, ret2;
154+
int ret;
153155

154156
if (spi_cfg->frequency == 0) {
155157
/* Use default 400KHZ frequency */
@@ -164,15 +166,31 @@ static int sdhc_spi_init_card(const struct device *dev)
164166
/* the initial 74 clocks must be sent while CS is high */
165167
spi_cfg->operation |= SPI_CS_ACTIVE_HIGH;
166168
ret = sdhc_spi_rx(config->spi_dev, spi_cfg, data->scratch, 10);
169+
spi_cfg->operation &= ~SPI_CS_ACTIVE_HIGH;
170+
171+
/* Send CMD0 immediately to force the transition to SPI mode before bus is unlocked.
172+
* Failing to do this can result in the SD card seeing transactions to other devices
173+
* on the same SPI bus and incorrectly deciding that it should be in SD mode.
174+
*/
175+
if (ret == 0) {
176+
struct sdhc_command cmd0 = {
177+
.opcode = SD_GO_IDLE_STATE,
178+
.arg = 0,
179+
.response_type = (SD_RSP_TYPE_NONE | SD_SPI_RSP_TYPE_R1),
180+
.timeout_ms = 1000,
181+
.retries = 1,
182+
};
183+
184+
ret = sdhc_spi_send_cmd(dev, &cmd0, false);
185+
}
167186

168187
/* Release lock on SPI bus */
169-
ret2 = spi_release(config->spi_dev, spi_cfg);
170-
spi_cfg->operation &= ~SPI_CS_ACTIVE_HIGH;
188+
(void)spi_release(config->spi_dev, spi_cfg);
171189

172190
/* Release request for SPI bus to be active */
173191
(void)pm_device_runtime_put(config->spi_dev);
174192

175-
return ret ? ret : ret2;
193+
return ret;
176194
}
177195

178196
/* Checks if SPI SD card is sending busy signal */
@@ -728,7 +746,11 @@ static int sdhc_spi_set_io(const struct device *dev, struct sdhc_io *ios)
728746
if (data->power_mode != ios->power_mode) {
729747
if (ios->power_mode == SDHC_POWER_ON) {
730748
if (cfg->pwr_gpio.port) {
749+
LOG_DBG("Locking SPI bus");
750+
(void)spi_acquire(cfg->spi_dev, data->spi_cfg);
751+
731752
if (gpio_pin_set_dt(&cfg->pwr_gpio, 1)) {
753+
(void)spi_release(cfg->spi_dev, data->spi_cfg);
732754
return -EIO;
733755
}
734756

@@ -741,7 +763,7 @@ static int sdhc_spi_set_io(const struct device *dev, struct sdhc_io *ios)
741763
LOG_INF("Powered up");
742764
}
743765

744-
/* Send 74 clock cycles to start card */
766+
/* Initialisation sequence for SPI mode */
745767
if (sdhc_spi_init_card(dev) != 0) {
746768
LOG_ERR("Card SCLK init sequence failed");
747769
return -EIO;

0 commit comments

Comments
 (0)