12e192b24SSimon Glass /* 22e192b24SSimon Glass * Command for mmc_spi setup. 32e192b24SSimon Glass * 42e192b24SSimon Glass * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> 52e192b24SSimon Glass * Licensed under the GPL-2 or later. 62e192b24SSimon Glass */ 72e192b24SSimon Glass 82e192b24SSimon Glass #include <common.h> 92e192b24SSimon Glass #include <mmc.h> 102e192b24SSimon Glass #include <spi.h> 112e192b24SSimon Glass 122e192b24SSimon Glass #ifndef CONFIG_MMC_SPI_BUS 132e192b24SSimon Glass # define CONFIG_MMC_SPI_BUS 0 142e192b24SSimon Glass #endif 152e192b24SSimon Glass #ifndef CONFIG_MMC_SPI_CS 162e192b24SSimon Glass # define CONFIG_MMC_SPI_CS 1 172e192b24SSimon Glass #endif 182e192b24SSimon Glass /* in SPI mode, MMC speed limit is 20MHz, while SD speed limit is 25MHz */ 192e192b24SSimon Glass #ifndef CONFIG_MMC_SPI_SPEED 202e192b24SSimon Glass # define CONFIG_MMC_SPI_SPEED 25000000 212e192b24SSimon Glass #endif 222e192b24SSimon Glass /* MMC and SD specs only seem to care that sampling is on the 232e192b24SSimon Glass * rising edge ... meaning SPI modes 0 or 3. So either SPI mode 242e192b24SSimon Glass * should be legit. We'll use mode 0 since the steady state is 0, 252e192b24SSimon Glass * which is appropriate for hotplugging, unless the platform data 262e192b24SSimon Glass * specify mode 3 (if hardware is not compatible to mode 0). 272e192b24SSimon Glass */ 282e192b24SSimon Glass #ifndef CONFIG_MMC_SPI_MODE 292e192b24SSimon Glass # define CONFIG_MMC_SPI_MODE SPI_MODE_0 302e192b24SSimon Glass #endif 312e192b24SSimon Glass 322e192b24SSimon Glass static int do_mmc_spi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 332e192b24SSimon Glass { 342e192b24SSimon Glass uint bus = CONFIG_MMC_SPI_BUS; 352e192b24SSimon Glass uint cs = CONFIG_MMC_SPI_CS; 362e192b24SSimon Glass uint speed = CONFIG_MMC_SPI_SPEED; 372e192b24SSimon Glass uint mode = CONFIG_MMC_SPI_MODE; 382e192b24SSimon Glass char *endp; 392e192b24SSimon Glass struct mmc *mmc; 402e192b24SSimon Glass 412e192b24SSimon Glass if (argc < 2) 422e192b24SSimon Glass goto usage; 432e192b24SSimon Glass 442e192b24SSimon Glass cs = simple_strtoul(argv[1], &endp, 0); 452e192b24SSimon Glass if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) 462e192b24SSimon Glass goto usage; 472e192b24SSimon Glass if (*endp == ':') { 482e192b24SSimon Glass if (endp[1] == 0) 492e192b24SSimon Glass goto usage; 502e192b24SSimon Glass bus = cs; 512e192b24SSimon Glass cs = simple_strtoul(endp + 1, &endp, 0); 522e192b24SSimon Glass if (*endp != 0) 532e192b24SSimon Glass goto usage; 542e192b24SSimon Glass } 552e192b24SSimon Glass if (argc >= 3) { 562e192b24SSimon Glass speed = simple_strtoul(argv[2], &endp, 0); 572e192b24SSimon Glass if (*argv[2] == 0 || *endp != 0) 582e192b24SSimon Glass goto usage; 592e192b24SSimon Glass } 602e192b24SSimon Glass if (argc >= 4) { 612e192b24SSimon Glass mode = simple_strtoul(argv[3], &endp, 16); 622e192b24SSimon Glass if (*argv[3] == 0 || *endp != 0) 632e192b24SSimon Glass goto usage; 642e192b24SSimon Glass } 652e192b24SSimon Glass if (!spi_cs_is_valid(bus, cs)) { 662e192b24SSimon Glass printf("Invalid SPI bus %u cs %u\n", bus, cs); 672e192b24SSimon Glass return 1; 682e192b24SSimon Glass } 692e192b24SSimon Glass 702e192b24SSimon Glass mmc = mmc_spi_init(bus, cs, speed, mode); 712e192b24SSimon Glass if (!mmc) { 722e192b24SSimon Glass printf("Failed to create MMC Device\n"); 732e192b24SSimon Glass return 1; 742e192b24SSimon Glass } 75*bcce53d0SSimon Glass printf("%s: %d at %u:%u hz %u mode %u\n", mmc->cfg->name, 76*bcce53d0SSimon Glass mmc->block_dev.devnum, bus, cs, speed, mode); 772e192b24SSimon Glass mmc_init(mmc); 782e192b24SSimon Glass return 0; 792e192b24SSimon Glass 802e192b24SSimon Glass usage: 812e192b24SSimon Glass return CMD_RET_USAGE; 822e192b24SSimon Glass } 832e192b24SSimon Glass 842e192b24SSimon Glass U_BOOT_CMD( 852e192b24SSimon Glass mmc_spi, 4, 0, do_mmc_spi, 862e192b24SSimon Glass "mmc_spi setup", 872e192b24SSimon Glass "[bus:]cs [hz] [mode] - setup mmc_spi device" 882e192b24SSimon Glass ); 89