exynos5: Implement booting from SDMMC media
This patch augments the alternative CBFS media source implementation for Exynos5250 and Exynos5420 to allow booting from SDMMC devices (such as an SD or uSD card reader, if available). It also moves MMC initialization for the Snow, Pit and Kirby boards from romstage to ramstage (mainboard_init) to prevent it from interfering with the IROM during SDMMC boot. BUG=chrome-os-partner:18733 TEST=cros_write_firmware -i /build/<board>/firmware/image.bin -w sd:. (or simply dd if=<imagefile> of=/dev/sdX seek=1) Change-Id: Ic4adef80c28262d084a53c28ec59aa7ac3af50c8 Signed-off-by: Julius Werner <jwerner@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/66154
This commit is contained in:
parent
3c6afef30c
commit
08de13b724
12 changed files with 204 additions and 63 deletions
|
|
@ -24,6 +24,8 @@
|
|||
#include <string.h>
|
||||
#include <console/console.h>
|
||||
#include "alternate_cbfs.h"
|
||||
#include "cpu.h"
|
||||
#include "power.h"
|
||||
#include "spi.h"
|
||||
|
||||
/* This allows USB A-A firmware upload from a compatible host in four parts:
|
||||
|
|
@ -53,7 +55,7 @@ static int usb_cbfs_open(struct cbfs_media *media)
|
|||
return 0;
|
||||
|
||||
if (!irom_load_usb()) {
|
||||
printk(BIOS_ERR, "Unable to load CBFS image via USB!\n");
|
||||
printk(BIOS_EMERG, "Unable to load CBFS image via USB!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -70,6 +72,45 @@ static int usb_cbfs_open(struct cbfs_media *media)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SDMMC works very similar to USB A-A: we copy the CBFS image into memory
|
||||
* and read it from there. While SDMMC would also allow direct block by block
|
||||
* on-demand reading, we might run into problems if we call back into the IROM
|
||||
* in very late boot stages (e.g. after initializing/changing MMC clocks)... so
|
||||
* this seems like a safer approach. It also makes it easy to pass our image
|
||||
* down to payloads.
|
||||
*/
|
||||
static int sdmmc_cbfs_open(struct cbfs_media *media)
|
||||
{
|
||||
#ifdef __PRE_RAM__
|
||||
/*
|
||||
* In the bootblock, we just copy the small part that fits in the buffer
|
||||
* and hope that it's enough (since the romstage is currently always the
|
||||
* first component in the image, this should work out). In the romstage,
|
||||
* we copy until our buffer is full (currently 12M) to avoid the pain of
|
||||
* figuring out the true image size from in here. Since this is mainly a
|
||||
* developer/debug boot mode, those shortcomings should be bearable.
|
||||
*/
|
||||
const u32 count = alternate_cbfs_size / 512;
|
||||
static int first_run = 1;
|
||||
int (*irom_load_sdmmc)(u32 start, u32 count, void *dst) =
|
||||
*irom_sdmmc_read_blocks_ptr;
|
||||
|
||||
if (!first_run)
|
||||
return 0;
|
||||
|
||||
if (!irom_load_sdmmc(1, count, alternate_cbfs_buffer)) {
|
||||
printk(BIOS_EMERG, "Unable to load CBFS image from SDMMC!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "SDMMC read successful, CBFS image should now be"
|
||||
" at %p\n", alternate_cbfs_buffer);
|
||||
first_run = 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
|
||||
|
||||
static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
|
||||
|
|
@ -90,6 +131,19 @@ static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset,
|
|||
static void *alternate_cbfs_unmap(struct cbfs_media *media,
|
||||
const void *buffer) { return 0; }
|
||||
|
||||
static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
|
||||
{
|
||||
printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
|
||||
|
||||
media->open = sdmmc_cbfs_open;
|
||||
media->close = alternate_cbfs_close;
|
||||
media->read = alternate_cbfs_read;
|
||||
media->map = alternate_cbfs_map;
|
||||
media->unmap = alternate_cbfs_unmap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
|
||||
{
|
||||
printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
|
||||
|
|
@ -108,8 +162,16 @@ int init_default_cbfs_media(struct cbfs_media *media)
|
|||
if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
|
||||
return initialize_exynos_usb_cbfs_media(media);
|
||||
|
||||
/* TODO: implement SDMMC (and possibly other) boot mode */
|
||||
|
||||
return initialize_exynos_spi_cbfs_media(media,
|
||||
(void*)CONFIG_CBFS_CACHE_ADDRESS, CONFIG_CBFS_CACHE_SIZE);
|
||||
switch (samsung_get_base_power()->om_stat & OM_STAT_MASK) {
|
||||
case OM_STAT_SDMMC:
|
||||
return initialize_exynos_sdmmc_cbfs_media(media);
|
||||
case OM_STAT_SPI:
|
||||
return initialize_exynos_spi_cbfs_media(media,
|
||||
(void*)CONFIG_CBFS_CACHE_ADDRESS,
|
||||
CONFIG_CBFS_CACHE_SIZE);
|
||||
default:
|
||||
printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
|
||||
samsung_get_base_power()->om_stat);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@ void * * const irom_load_image_from_usb_ptr = (void * *)0x02020070;
|
|||
#define SECONDARY_BASE_BOOT_USB 0xfeed0002
|
||||
u32 * const iram_secondary_base = (u32 *)0x02020018;
|
||||
|
||||
/* Values pulled from U-Boot, I think the manual is wrong here (for SPI) */
|
||||
#define OM_STAT_SDMMC 0x4
|
||||
#define OM_STAT_EMMC 0x8
|
||||
#define OM_STAT_SPI 0x14
|
||||
#define OM_STAT_MASK 0x7f
|
||||
|
||||
#if defined(__BOOT_BLOCK__)
|
||||
/* A small space in IRAM to hold the romstage-only image */
|
||||
void * const alternate_cbfs_buffer = (void *)CONFIG_CBFS_CACHE_ADDRESS;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ void power_enable_hw_thermal_trip(void);
|
|||
/* Power Management Unit register map */
|
||||
struct exynos5_power {
|
||||
/* Add registers as and when required */
|
||||
uint8_t reserved1[0x0400];
|
||||
uint32_t om_stat; /* 0x0000 */
|
||||
uint8_t reserved1[0x03fc];
|
||||
uint32_t sw_reset; /* 0x0400 */
|
||||
uint8_t reserved2[0x0304];
|
||||
uint32_t usb_host_phy_ctrl; /* 0x0708 */
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include <arch/cache.h>
|
||||
#include <console/console.h>
|
||||
#include "alternate_cbfs.h"
|
||||
#include "cpu.h"
|
||||
#include "power.h"
|
||||
#include "spi.h"
|
||||
|
||||
/* This allows USB A-A firmware upload from a compatible host in four parts:
|
||||
|
|
@ -56,7 +58,7 @@ static int usb_cbfs_open(struct cbfs_media *media)
|
|||
dcache_mmu_disable();
|
||||
if (!irom_load_usb()) {
|
||||
dcache_mmu_enable();
|
||||
printk(BIOS_ERR, "Unable to load CBFS image via USB!\n");
|
||||
printk(BIOS_EMERG, "Unable to load CBFS image via USB!\n");
|
||||
return -1;
|
||||
}
|
||||
dcache_mmu_enable();
|
||||
|
|
@ -74,6 +76,48 @@ static int usb_cbfs_open(struct cbfs_media *media)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SDMMC works very similar to USB A-A: we copy the CBFS image into memory
|
||||
* and read it from there. While SDMMC would also allow direct block by block
|
||||
* on-demand reading, we might run into problems if we call back into the IROM
|
||||
* in very late boot stages (e.g. after initializing/changing MMC clocks)... so
|
||||
* this seems like a safer approach. It also makes it easy to pass our image
|
||||
* down to payloads.
|
||||
*/
|
||||
static int sdmmc_cbfs_open(struct cbfs_media *media)
|
||||
{
|
||||
#ifdef __PRE_RAM__
|
||||
/*
|
||||
* In the bootblock, we just copy the small part that fits in the buffer
|
||||
* and hope that it's enough (since the romstage is currently always the
|
||||
* first component in the image, this should work out). In the romstage,
|
||||
* we copy until our buffer is full (currently 12M) to avoid the pain of
|
||||
* figuring out the true image size from in here. Since this is mainly a
|
||||
* developer/debug boot mode, those shortcomings should be bearable.
|
||||
*/
|
||||
const u32 count = alternate_cbfs_size / 512;
|
||||
static int first_run = 1;
|
||||
int (*irom_load_sdmmc)(u32 start, u32 count, void *dst) =
|
||||
*irom_sdmmc_read_blocks_ptr;
|
||||
|
||||
if (!first_run)
|
||||
return 0;
|
||||
|
||||
dcache_mmu_disable();
|
||||
if (!irom_load_sdmmc(1, count, alternate_cbfs_buffer)) {
|
||||
dcache_mmu_enable();
|
||||
printk(BIOS_EMERG, "Unable to load CBFS image from SDMMC!\n");
|
||||
return -1;
|
||||
}
|
||||
dcache_mmu_enable();
|
||||
|
||||
printk(BIOS_DEBUG, "SDMMC read successful, CBFS image should now be"
|
||||
" at %p\n", alternate_cbfs_buffer);
|
||||
first_run = 0;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
|
||||
|
||||
static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
|
||||
|
|
@ -94,6 +138,19 @@ static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset,
|
|||
static void *alternate_cbfs_unmap(struct cbfs_media *media,
|
||||
const void *buffer) { return 0; }
|
||||
|
||||
static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
|
||||
{
|
||||
printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
|
||||
|
||||
media->open = sdmmc_cbfs_open;
|
||||
media->close = alternate_cbfs_close;
|
||||
media->read = alternate_cbfs_read;
|
||||
media->map = alternate_cbfs_map;
|
||||
media->unmap = alternate_cbfs_unmap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
|
||||
{
|
||||
printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
|
||||
|
|
@ -112,8 +169,16 @@ int init_default_cbfs_media(struct cbfs_media *media)
|
|||
if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
|
||||
return initialize_exynos_usb_cbfs_media(media);
|
||||
|
||||
/* TODO: implement SDMMC (and possibly other) boot mode */
|
||||
|
||||
return initialize_exynos_spi_cbfs_media(media,
|
||||
(void*)CONFIG_CBFS_CACHE_ADDRESS, CONFIG_CBFS_CACHE_SIZE);
|
||||
switch (samsung_get_base_power()->om_stat & OM_STAT_MASK) {
|
||||
case OM_STAT_SDMMC:
|
||||
return initialize_exynos_sdmmc_cbfs_media(media);
|
||||
case OM_STAT_SPI:
|
||||
return initialize_exynos_spi_cbfs_media(media,
|
||||
(void*)CONFIG_CBFS_CACHE_ADDRESS,
|
||||
CONFIG_CBFS_CACHE_SIZE);
|
||||
default:
|
||||
printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
|
||||
samsung_get_base_power()->om_stat);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CPU_SAMSUNG_EXYNOS5250_ALTERNATE_CBFS_H
|
||||
#define CPU_SAMSUNG_EXYNOS5250_ALTERNATE_CBFS_H
|
||||
#ifndef CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H
|
||||
#define CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H
|
||||
|
||||
/* These are pointers to function pointers. Double indirection! */
|
||||
void * * const irom_sdmmc_read_blocks_ptr = (void * *)0x02020030;
|
||||
|
|
@ -30,6 +30,12 @@ void * * const irom_load_image_from_usb_ptr = (void * *)0x02020070;
|
|||
#define SECONDARY_BASE_BOOT_USB 0xfeed0002
|
||||
u32 * const iram_secondary_base = (u32 *)0x02020018;
|
||||
|
||||
/* Values pulled from U-Boot, I think the manual is wrong here (for SPI) */
|
||||
#define OM_STAT_SDMMC 0x4
|
||||
#define OM_STAT_EMMC 0x8
|
||||
#define OM_STAT_SPI 0x14
|
||||
#define OM_STAT_MASK 0x7f
|
||||
|
||||
#if defined(__BOOT_BLOCK__)
|
||||
/* A small space in IRAM to hold the romstage-only image */
|
||||
void * const alternate_cbfs_buffer = (void *)CONFIG_CBFS_CACHE_ADDRESS;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ void power_enable_hw_thermal_trip(void);
|
|||
/* Power Management Unit register map */
|
||||
struct exynos5_power {
|
||||
/* Add registers as and when required */
|
||||
uint8_t reserved1[0x0400];
|
||||
uint32_t om_stat; /* 0x0000 */
|
||||
uint8_t reserved1[0x03fc];
|
||||
uint32_t sw_reset; /* 0x0400 */
|
||||
uint8_t reserved2[0x0304];
|
||||
uint32_t usb_host_phy_ctrl; /* 0x0708 */
|
||||
|
|
|
|||
|
|
@ -323,6 +323,19 @@ static void disable_usb30_pll(void)
|
|||
gpio_direction_output(usb3_pll_l, 0);
|
||||
}
|
||||
|
||||
static void setup_storage(void)
|
||||
{
|
||||
/* MMC0: Fixed, 8 bit mode, connected with GPIO. */
|
||||
if (clock_set_dwmci(PERIPH_ID_SDMMC0))
|
||||
printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
|
||||
exynos_pinmux_sdmmc0();
|
||||
|
||||
/* MMC2: Removable, 4 bit mode, no GPIO. */
|
||||
/* (Must be after romstage to avoid breaking SDMMC boot.) */
|
||||
clock_set_dwmci(PERIPH_ID_SDMMC2);
|
||||
exynos_pinmux_sdmmc2();
|
||||
}
|
||||
|
||||
static void gpio_init(void)
|
||||
{
|
||||
/* Set up the I2C busses. */
|
||||
|
|
@ -352,6 +365,7 @@ static void mainboard_init(device_t dev)
|
|||
void *fb_addr = (void *)(get_fb_base_kb() * KiB);
|
||||
|
||||
gpio_init();
|
||||
setup_storage();
|
||||
tmu_init(&exynos5420_tmu_info);
|
||||
|
||||
/* Clock Gating all the unused IP's to save power */
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@
|
|||
#include <drivers/maxim/max77802/max77802.h>
|
||||
#include <device/i2c.h>
|
||||
|
||||
#define MMC0_GPIO_PIN (58)
|
||||
|
||||
#define PMIC_I2C_BUS 4
|
||||
|
||||
struct pmic_write
|
||||
|
|
@ -110,18 +108,6 @@ static int setup_power(int is_resume)
|
|||
return error;
|
||||
}
|
||||
|
||||
static void setup_storage(void)
|
||||
{
|
||||
/* MMC0: Fixed, 8 bit mode, connected with GPIO. */
|
||||
if (clock_set_dwmci(PERIPH_ID_SDMMC0))
|
||||
printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
|
||||
exynos_pinmux_sdmmc0();
|
||||
|
||||
/* MMC2: Removable, 4 bit mode, no GPIO. */
|
||||
clock_set_dwmci(PERIPH_ID_SDMMC2);
|
||||
exynos_pinmux_sdmmc2();
|
||||
}
|
||||
|
||||
static void setup_ec(void)
|
||||
{
|
||||
/* SPI2 (EC) is slower and needs to work in half-duplex mode with
|
||||
|
|
@ -285,7 +271,6 @@ void main(void)
|
|||
wakeup();
|
||||
}
|
||||
|
||||
setup_storage();
|
||||
setup_gpio();
|
||||
setup_ec();
|
||||
|
||||
|
|
|
|||
|
|
@ -330,6 +330,19 @@ static void disable_usb30_pll(void)
|
|||
gpio_direction_output(usb3_pll_l, 0);
|
||||
}
|
||||
|
||||
static void setup_storage(void)
|
||||
{
|
||||
/* MMC0: Fixed, 8 bit mode, connected with GPIO. */
|
||||
if (clock_set_dwmci(PERIPH_ID_SDMMC0))
|
||||
printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
|
||||
exynos_pinmux_sdmmc0();
|
||||
|
||||
/* MMC2: Removable, 4 bit mode, no GPIO. */
|
||||
/* (Must be after romstage to avoid breaking SDMMC boot.) */
|
||||
clock_set_dwmci(PERIPH_ID_SDMMC2);
|
||||
exynos_pinmux_sdmmc2();
|
||||
}
|
||||
|
||||
static void gpio_init(void)
|
||||
{
|
||||
/* Set up the I2C busses. */
|
||||
|
|
@ -380,6 +393,7 @@ static void mainboard_init(device_t dev)
|
|||
void *fb_addr = (void *)(get_fb_base_kb() * KiB);
|
||||
|
||||
gpio_init();
|
||||
setup_storage();
|
||||
tmu_init(&exynos5420_tmu_info);
|
||||
|
||||
/* Clock Gating all the unused IP's to save power */
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@
|
|||
#include <drivers/maxim/max77802/max77802.h>
|
||||
#include <device/i2c.h>
|
||||
|
||||
#define MMC0_GPIO_PIN (58)
|
||||
|
||||
#define PMIC_I2C_BUS 4
|
||||
|
||||
struct pmic_write
|
||||
|
|
@ -110,18 +108,6 @@ static int setup_power(int is_resume)
|
|||
return error;
|
||||
}
|
||||
|
||||
static void setup_storage(void)
|
||||
{
|
||||
/* MMC0: Fixed, 8 bit mode, connected with GPIO. */
|
||||
if (clock_set_dwmci(PERIPH_ID_SDMMC0))
|
||||
printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
|
||||
exynos_pinmux_sdmmc0();
|
||||
|
||||
/* MMC2: Removable, 4 bit mode, no GPIO. */
|
||||
clock_set_dwmci(PERIPH_ID_SDMMC2);
|
||||
exynos_pinmux_sdmmc2();
|
||||
}
|
||||
|
||||
static void setup_ec(void)
|
||||
{
|
||||
/* SPI2 (EC) is slower and needs to work in half-duplex mode with
|
||||
|
|
@ -285,7 +271,6 @@ void main(void)
|
|||
wakeup();
|
||||
}
|
||||
|
||||
setup_storage();
|
||||
setup_gpio();
|
||||
setup_ec();
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include "exynos5250.h"
|
||||
|
||||
#define MMC0_GPIO_PIN (58)
|
||||
|
||||
/* convenient shorthand (in MB) */
|
||||
#define DRAM_START (CONFIG_SYS_SDRAM_BASE >> 20)
|
||||
#define DRAM_SIZE CONFIG_DRAM_SIZE_MB
|
||||
|
|
@ -179,6 +181,24 @@ static void disable_usb30_pll(void)
|
|||
gpio_direction_output(usb3_pll_l, 0);
|
||||
}
|
||||
|
||||
static void setup_storage(void)
|
||||
{
|
||||
/* MMC0: Fixed, 8 bit mode, connected with GPIO. */
|
||||
if (clock_set_mshci(PERIPH_ID_SDMMC0))
|
||||
printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
|
||||
if (gpio_direction_output(MMC0_GPIO_PIN, 1)) {
|
||||
printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__);
|
||||
}
|
||||
gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE);
|
||||
gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X);
|
||||
exynos_pinmux_sdmmc0();
|
||||
|
||||
/* MMC2: Removable, 4 bit mode, no GPIO. */
|
||||
/* (Must be after romstage to avoid breaking SDMMC boot.) */
|
||||
clock_set_mshci(PERIPH_ID_SDMMC2);
|
||||
exynos_pinmux_sdmmc2();
|
||||
}
|
||||
|
||||
static void gpio_init(void)
|
||||
{
|
||||
/* Set up the I2C busses. */
|
||||
|
|
@ -217,6 +237,7 @@ static void mainboard_init(device_t dev)
|
|||
void *fb_addr = (void *)(get_fb_base_kb() * KiB);
|
||||
|
||||
gpio_init();
|
||||
setup_storage();
|
||||
|
||||
i2c_init(TPS65090_BUS, I2C_0_SPEED, I2C_SLAVE);
|
||||
i2c_init(7, I2C_0_SPEED, I2C_SLAVE);
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
#include "exynos5250.h"
|
||||
|
||||
#define PMIC_BUS 0
|
||||
#define MMC0_GPIO_PIN (58)
|
||||
|
||||
static void setup_power(int is_resume)
|
||||
{
|
||||
|
|
@ -97,23 +96,6 @@ static void setup_power(int is_resume)
|
|||
}
|
||||
}
|
||||
|
||||
static void setup_storage(void)
|
||||
{
|
||||
/* MMC0: Fixed, 8 bit mode, connected with GPIO. */
|
||||
if (clock_set_mshci(PERIPH_ID_SDMMC0))
|
||||
printk(BIOS_CRIT, "%s: Failed to set MMC0 clock.\n", __func__);
|
||||
if (gpio_direction_output(MMC0_GPIO_PIN, 1)) {
|
||||
printk(BIOS_CRIT, "%s: Unable to power on MMC0.\n", __func__);
|
||||
}
|
||||
gpio_set_pull(MMC0_GPIO_PIN, GPIO_PULL_NONE);
|
||||
gpio_set_drv(MMC0_GPIO_PIN, GPIO_DRV_4X);
|
||||
exynos_pinmux_sdmmc0();
|
||||
|
||||
/* MMC2: Removable, 4 bit mode, no GPIO. */
|
||||
clock_set_mshci(PERIPH_ID_SDMMC2);
|
||||
exynos_pinmux_sdmmc2();
|
||||
}
|
||||
|
||||
static void setup_graphics(void)
|
||||
{
|
||||
exynos_pinmux_dphpd();
|
||||
|
|
@ -191,7 +173,6 @@ void main(void)
|
|||
wakeup();
|
||||
}
|
||||
|
||||
setup_storage();
|
||||
setup_gpio();
|
||||
setup_graphics();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue