aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--os/hal/platforms/STM32/sdc_lld.c66
-rw-r--r--os/hal/platforms/STM32/sdc_lld.h12
-rw-r--r--os/hal/src/sdc.c2
3 files changed, 80 insertions, 0 deletions
diff --git a/os/hal/platforms/STM32/sdc_lld.c b/os/hal/platforms/STM32/sdc_lld.c
index 48f8561f9..25c7b6897 100644
--- a/os/hal/platforms/STM32/sdc_lld.c
+++ b/os/hal/platforms/STM32/sdc_lld.c
@@ -120,6 +120,72 @@ void sdc_lld_stop(SDCDriver *sdcp) {
}
/**
+ * @brief Starts the SDIO clock and sets it to init mode (400KHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_start_clk(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ /* Initial clock setting: 400KHz, 1bit mode.*/
+ SDIO->CLKCR = STM32_SDIO_DIV_LS;
+ SDIO->POWER |= SDIO_POWER_PWRCTRL_0 | SDIO_POWER_PWRCTRL_1;
+ SDIO->CLKCR |= SDIO_CLKCR_CLKEN;
+}
+
+/**
+ * @brief Sets the SDIO clock to data mode (25MHz or less).
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_set_data_clk(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ SDIO->CLKCR = (SDIO->CLKCR & 0xFFFFFF00) | STM32_SDIO_DIV_HS;
+}
+
+/**
+ * @brief Stops the SDIO clock.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_stop_clk(SDCDriver *sdcp) {
+
+ (void)sdcp;
+ SDIO->CLKCR = 0;
+ SDIO->POWER = 0;
+}
+
+/**
+ * @brief Switches the bus to 4 bits mode.
+ *
+ * @param[in] sdcp pointer to the @p SDCDriver object
+ *
+ * @notapi
+ */
+void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode) {
+ uint32_t clk = SDIO->CLKCR & ~SDIO_CLKCR_WIDBUS;
+
+ (void)sdcp;
+ switch (mode) {
+ case SDC_MODE_1BIT:
+ SDIO->CLKCR = clk;
+ break;
+ case SDC_MODE_4BIT:
+ SDIO->CLKCR = clk | SDIO_CLKCR_WIDBUS_0;
+ break;
+ case SDC_MODE_8BIT:
+ SDIO->CLKCR = clk | SDIO_CLKCR_WIDBUS_1;
+ }
+}
+
+/**
* @brief Sends an SDIO command with no response expected.
*
* @param[in] sdcp pointer to the @p SDCDriver object
diff --git a/os/hal/platforms/STM32/sdc_lld.h b/os/hal/platforms/STM32/sdc_lld.h
index 012fdb1c7..8ed64a5b0 100644
--- a/os/hal/platforms/STM32/sdc_lld.h
+++ b/os/hal/platforms/STM32/sdc_lld.h
@@ -89,6 +89,14 @@
/* Driver data structures and types. */
/*===========================================================================*/
+/**
+ * @brief Type of SDIO bus mode.
+ */
+typedef enum {
+ SDC_MODE_1BIT = 0,
+ SDC_MODE_4BIT,
+ SDC_MODE_8BIT
+} sdcbusmode_t;
/**
* @brief Type of a structure representing an SDC driver.
@@ -136,6 +144,10 @@ extern "C" {
void sdc_lld_init(void);
void sdc_lld_start(SDCDriver *sdcp);
void sdc_lld_stop(SDCDriver *sdcp);
+ void sdc_lld_set_init_clk(SDCDriver *sdcp);
+ void sdc_lld_set_data_clk(SDCDriver *sdcp);
+ void sdc_lld_stop_clk(SDCDriver *sdcp);
+ void sdc_lld_set_bus_mode(SDCDriver *sdcp, sdcbusmode_t mode);
void sdc_lld_send_cmd_none(SDCDriver *sdcp, uint8_t cmd, uint32_t arg);
bool_t sdc_lld_send_cmd_short(SDCDriver *sdcp, uint8_t cmd, uint32_t arg,
uint32_t *resp);
diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c
index 33f2b3612..701071b8b 100644
--- a/os/hal/src/sdc.c
+++ b/os/hal/src/sdc.c
@@ -135,6 +135,8 @@ bool_t sdcConnect(SDCDriver *sdcp) {
sdcp->state = SDC_INITNG;
chSysUnlock();
+ sdc_lld_start_clk(sdcp);
+
sdcp->state = SDC_ACTIVE;
return FALSE;
}