mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-01-22 01:30:35 -05:00
echoplayer: enable SD card using sdmmc_host
Enable pullups on SDMMC CMD/DATx lines and set output speed to medium. Using HIGH and VERYHIGH speeds seems to cause data corruption, with frequent CRC failures. Change-Id: I732d19e03a2a857453755b68b6749497eafaef70
This commit is contained in:
parent
141b4a223f
commit
6a8989f347
5 changed files with 138 additions and 3 deletions
|
|
@ -2038,6 +2038,7 @@ target/arm/stm32/echoplayer/button-echoplayer.c
|
|||
target/arm/stm32/echoplayer/clock-echoplayer.c
|
||||
target/arm/stm32/echoplayer/lcd-echoplayer.c
|
||||
target/arm/stm32/echoplayer/power-echoplayer.c
|
||||
target/arm/stm32/echoplayer/sdmmc-echoplayer.c
|
||||
target/arm/stm32/echoplayer/system-echoplayer.c
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@
|
|||
#define STORAGE_WANTS_ALIGN
|
||||
#define STORAGE_NEEDS_BOUNCE_BUFFER
|
||||
|
||||
/* One SD card slot */
|
||||
#define SDMMC_HOST_NUM_SD_CONTROLLERS 1
|
||||
|
||||
/* RTC settings */
|
||||
#define CONFIG_RTC RTC_STM32H743
|
||||
#define HAVE_RTC_ALARM
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "regs/stm32h743/rcc.h"
|
||||
#include "regs/stm32h743/syscfg.h"
|
||||
|
||||
#define PLL1Q_FREQ 48000000
|
||||
|
||||
/* Flag to use VOS0 */
|
||||
#define STM32H743_USE_VOS0 (CPU_FREQ > 400000000)
|
||||
|
||||
|
|
@ -44,6 +46,8 @@ static void init_pll(void)
|
|||
"HSE frequency not correct");
|
||||
_Static_assert(LCD_DOTCLOCK_FREQ == 6199200,
|
||||
"PLL3 parameters not correct for dot clock");
|
||||
_Static_assert(PLL1Q_FREQ == 48000000,
|
||||
"PLL1Q parameters not correct");
|
||||
|
||||
/*
|
||||
* Use HSE/4 input for PLL1
|
||||
|
|
@ -76,7 +80,7 @@ static void init_pll(void)
|
|||
reg_writef(RCC_PLL1DIVR,
|
||||
DIVN(80 - 1), /* 6 * 80 = 480 MHz */
|
||||
DIVP(1 - 1), /* 480 / 1 = 480 MHz */
|
||||
DIVQ(8 - 1), /* 480 / 8 = 60 MHz */
|
||||
DIVQ(10 - 1), /* 480 / 10 = 48 MHz */
|
||||
DIVR(1 - 1));
|
||||
|
||||
reg_writef(RCC_PLL3FRACR, FRACN(1468));
|
||||
|
|
@ -159,6 +163,7 @@ static void init_lse(void)
|
|||
|
||||
static void init_periph_clock(void)
|
||||
{
|
||||
reg_writef(RCC_D1CCIPR, SDMMCSEL_V(PLL1Q));
|
||||
reg_writef(RCC_D2CCIP1R, SPI45SEL_V(HSE));
|
||||
|
||||
/* Enable AXI SRAM in sleep mode to allow DMA'ing out of it */
|
||||
|
|
@ -189,6 +194,11 @@ void stm_target_clock_enable(enum stm_clock clock, bool enable)
|
|||
reg_writef(RCC_APB3LPENR, LTDCEN(enable));
|
||||
break;
|
||||
|
||||
case STM_CLOCK_SDMMC1_KER:
|
||||
reg_writef(RCC_AHB3ENR, SDMMC1EN(enable));
|
||||
reg_writef(RCC_AHB3LPENR, SDMMC1EN(enable));
|
||||
break;
|
||||
|
||||
default:
|
||||
panicf("%s: unsupported clock %d", __func__, (int)clock);
|
||||
break;
|
||||
|
|
@ -202,6 +212,9 @@ size_t stm_target_clock_get_frequency(enum stm_clock clock)
|
|||
case STM_CLOCK_SPI5_KER:
|
||||
return STM32_HSE_FREQ;
|
||||
|
||||
case STM_CLOCK_SDMMC1_KER:
|
||||
return PLL1Q_FREQ;
|
||||
|
||||
default:
|
||||
panicf("%s: unsupported clock %d", __func__, (int)clock);
|
||||
return 0;
|
||||
|
|
|
|||
116
firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c
Normal file
116
firmware/target/arm/stm32/echoplayer/sdmmc-echoplayer.c
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2025 by Aidan MacDonald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#include "sdmmc_host.h"
|
||||
#include "sdmmc-stm32h7.h"
|
||||
#include "gpio-stm32h7.h"
|
||||
#include "nvic-arm.h"
|
||||
#include "regs/stm32h743/sdmmc.h"
|
||||
|
||||
/* 300ms poll interval */
|
||||
#define SDCARD_POLL_TICKS (300 * HZ / 1000)
|
||||
|
||||
static struct sdmmc_host sdmmc1;
|
||||
static struct stm32h7_sdmmc_controller sdmmc1_ctl;
|
||||
|
||||
static const struct sdmmc_controller_ops sdmmc_ops = {
|
||||
.set_power_enabled = stm32h7_sdmmc_set_power_enabled,
|
||||
.set_bus_width = stm32h7_sdmmc_set_bus_width,
|
||||
.set_bus_clock = stm32h7_sdmmc_set_bus_clock,
|
||||
.submit_command = stm32h7_sdmmc_submit_command,
|
||||
.abort_command = stm32h7_sdmmc_abort_command,
|
||||
};
|
||||
|
||||
static const struct sdmmc_host_config sdmmc_config INITDATA_ATTR = {
|
||||
.type = STORAGE_SD,
|
||||
.bus_voltages = SDMMC_BUS_VOLTAGE_3V2_3V3 |
|
||||
SDMMC_BUS_VOLTAGE_3V3_3V4,
|
||||
.bus_widths = SDMMC_BUS_WIDTH_1BIT |
|
||||
SDMMC_BUS_WIDTH_4BIT,
|
||||
.bus_clocks = SDMMC_BUS_CLOCK_400KHZ |
|
||||
SDMMC_BUS_CLOCK_25MHZ |
|
||||
SDMMC_BUS_CLOCK_50MHZ,
|
||||
.is_removable = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* simple SD insertion poller
|
||||
*/
|
||||
struct sdmmc_poll
|
||||
{
|
||||
struct sdmmc_host *host;
|
||||
bool is_inserted;
|
||||
|
||||
bool last_state;
|
||||
bool curr_state;
|
||||
};
|
||||
|
||||
static bool is_sdcard_inserted(void)
|
||||
{
|
||||
return gpio_get_level(GPIO_SDMMC_DETECT) == 0;
|
||||
}
|
||||
|
||||
static int poll_sdcard_inserted(struct timeout *tmo)
|
||||
{
|
||||
struct sdmmc_poll *poll = (void *)tmo->data;
|
||||
|
||||
poll->last_state = poll->curr_state;
|
||||
poll->curr_state = is_sdcard_inserted();
|
||||
|
||||
if (!poll->curr_state && poll->is_inserted)
|
||||
{
|
||||
poll->is_inserted = false;
|
||||
sdmmc_host_set_medium_present(poll->host, false);
|
||||
}
|
||||
else if (poll->curr_state && !poll->is_inserted &&
|
||||
poll->curr_state == poll->last_state)
|
||||
{
|
||||
poll->is_inserted = true;
|
||||
sdmmc_host_set_medium_present(poll->host, true);
|
||||
}
|
||||
|
||||
return SDCARD_POLL_TICKS;
|
||||
}
|
||||
|
||||
static struct timeout sdcard_poll_timeout;
|
||||
static struct sdmmc_poll sdcard_poll;
|
||||
|
||||
void sdmmc_host_target_init(void)
|
||||
{
|
||||
/* Initialize controller */
|
||||
stm32h7_sdmmc_init(&sdmmc1_ctl, ITA_SDMMC1, STM_CLOCK_SDMMC1_KER,
|
||||
stm32h7_reset_sdmmc1, NULL);
|
||||
nvic_enable_irq(NVIC_IRQN_SDMMC1);
|
||||
|
||||
/* Initialize card detect polling */
|
||||
sdcard_poll.host = &sdmmc1;
|
||||
sdcard_poll.is_inserted = is_sdcard_inserted();
|
||||
timeout_register(&sdcard_poll_timeout, poll_sdcard_inserted,
|
||||
SDCARD_POLL_TICKS, (intptr_t)&sdcard_poll);
|
||||
|
||||
/* Initialize SD/MMC host driver */
|
||||
sdmmc_host_init(&sdmmc1, &sdmmc_config, &sdmmc_ops, &sdmmc1_ctl);
|
||||
sdmmc_host_init_medium_present(&sdmmc1, sdcard_poll.is_inserted);
|
||||
}
|
||||
|
||||
void sdmmc1_irq_handler(void)
|
||||
{
|
||||
stm32h7_sdmmc_irq_handler(&sdmmc1_ctl);
|
||||
}
|
||||
|
|
@ -32,7 +32,8 @@
|
|||
#define F_ULPI GPIOF_FUNCTION(10, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED)
|
||||
#define F_MCO1 GPIOF_FUNCTION(0, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED)
|
||||
#define F_I2C1 GPIOF_FUNCTION(4, GPIO_TYPE_OPEN_DRAIN, GPIO_SPEED_LOW, GPIO_PULL_DISABLED)
|
||||
#define F_SDMMC1 GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED)
|
||||
#define F_SDMMC1 GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_UP)
|
||||
#define F_SDMMC1CK GPIOF_FUNCTION(12, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_MEDIUM, GPIO_PULL_DISABLED)
|
||||
#define F_SAI1 GPIOF_FUNCTION(6, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED)
|
||||
#define F_SPI5 GPIOF_FUNCTION(5, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED)
|
||||
#define F_LCD_AF14 GPIOF_FUNCTION(14, GPIO_TYPE_PUSH_PULL, GPIO_SPEED_VERYHIGH, GPIO_PULL_DISABLED)
|
||||
|
|
@ -93,7 +94,8 @@ static const struct pingroup_setting pingroups[] = {
|
|||
/* I2C1 */
|
||||
STM_DEFPINS(GPIO_B, 0x00c0, F_I2C1),
|
||||
/* SDMMC1 */
|
||||
STM_DEFPINS(GPIO_C, 0x1f00, F_SDMMC1),
|
||||
STM_DEFPINS(GPIO_C, 0x1000, F_SDMMC1CK),
|
||||
STM_DEFPINS(GPIO_C, 0x0f00, F_SDMMC1),
|
||||
STM_DEFPINS(GPIO_D, 0x0004, F_SDMMC1),
|
||||
/* SAI1 */
|
||||
STM_DEFPINS(GPIO_E, 0x007c, F_SAI1),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue