#include <linux/list.h>
#include <linux/compiler.h>
+#include <part.h>
#define SD_VERSION_SD 0x20000
#define SD_VERSION_3 (SD_VERSION_SD | 0x300)
#define MMC_VERSION_4_41 (MMC_VERSION_MMC | 0x429)
#define MMC_VERSION_4_5 (MMC_VERSION_MMC | 0x405)
-#define MMC_MODE_HS 0x001
-#define MMC_MODE_HS_52MHz 0x010
-#define MMC_MODE_4BIT 0x100
-#define MMC_MODE_8BIT 0x200
-#define MMC_MODE_SPI 0x400
-#define MMC_MODE_HC 0x800
-
-#define MMC_MODE_MASK_WIDTH_BITS (MMC_MODE_4BIT | MMC_MODE_8BIT)
-#define MMC_MODE_WIDTH_BITS_SHIFT 8
+#define MMC_MODE_HS (1 << 0)
+#define MMC_MODE_HS_52MHz (1 << 1)
+#define MMC_MODE_4BIT (1 << 2)
+#define MMC_MODE_8BIT (1 << 3)
+#define MMC_MODE_SPI (1 << 4)
+#define MMC_MODE_HC (1 << 5)
+#define MMC_MODE_DDR_52MHz (1 << 6)
#define SD_DATA_4BIT 0x00040000
#define COMM_ERR -18 /* Communications Error */
#define TIMEOUT -19
#define IN_PROGRESS -20 /* operation is in progress */
+#define SWITCH_ERR -21 /* Card reports failure to switch mode */
#define MMC_CMD_GO_IDLE_STATE 0
#define MMC_CMD_SEND_OP_COND 1
#define MMC_CMD_SET_BLOCKLEN 16
#define MMC_CMD_READ_SINGLE_BLOCK 17
#define MMC_CMD_READ_MULTIPLE_BLOCK 18
+#define MMC_CMD_SET_BLOCK_COUNT 23
#define MMC_CMD_WRITE_SINGLE_BLOCK 24
#define MMC_CMD_WRITE_MULTIPLE_BLOCK 25
#define MMC_CMD_ERASE_GROUP_START 35
#define SD_HIGHSPEED_BUSY 0x00020000
#define SD_HIGHSPEED_SUPPORTED 0x00020000
-#define MMC_HS_TIMING 0x00000100
-#define MMC_HS_52MHZ 0x2
-
#define OCR_BUSY 0x80000000
#define OCR_HCS 0x40000000
#define OCR_VOLTAGE_MASK 0x007FFF80
#define SECURE_ERASE 0x80000000
#define MMC_STATUS_MASK (~0x0206BF7F)
+#define MMC_STATUS_SWITCH_ERROR (1 << 7)
#define MMC_STATUS_RDY_FOR_DATA (1 << 8)
#define MMC_STATUS_CURR_STATE (0xf << 9)
#define MMC_STATUS_ERROR (1 << 19)
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
#define EXT_CSD_PARTITIONS_ATTRIBUTE 156 /* R/W */
#define EXT_CSD_PARTITIONING_SUPPORT 160 /* RO */
+#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
#define EXT_CSD_RPMB_MULT 168 /* RO */
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
#define EXT_CSD_BOOT_BUS_WIDTH 177
#define EXT_CSD_CARD_TYPE_26 (1 << 0) /* Card can run at 26MHz */
#define EXT_CSD_CARD_TYPE_52 (1 << 1) /* Card can run at 52MHz */
+#define EXT_CSD_CARD_TYPE_DDR_1_8V (1 << 2)
+#define EXT_CSD_CARD_TYPE_DDR_1_2V (1 << 3)
+#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
+ | EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
+#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
+#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_BOOT_ACK_ENABLE (1 << 6)
#define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3)
#define EXT_CSD_BOOT_PART_NUM(x) (x << 3)
#define EXT_CSD_PARTITION_ACCESS(x) (x << 0)
+#define EXT_CSD_BOOT_BUS_WIDTH_MODE(x) (x << 3)
+#define EXT_CSD_BOOT_BUS_WIDTH_RESET(x) (x << 2)
+#define EXT_CSD_BOOT_BUS_WIDTH_WIDTH(x) (x)
#define R1_ILLEGAL_COMMAND (1 << 22)
#define R1_APP_CMD (1 << 5)
* boot partitions (2), general purpose partitions (4) in MMC v4.4.
*/
#define MMC_NUM_BOOT_PARTITION 2
+#define MMC_PART_RPMB 3 /* RPMB partition number */
struct mmc_cid {
unsigned long psn;
uint blocksize;
};
+/* forward decl. */
+struct mmc;
+
+struct mmc_ops {
+ int (*send_cmd)(struct mmc *mmc,
+ struct mmc_cmd *cmd, struct mmc_data *data);
+ void (*set_ios)(struct mmc *mmc);
+ int (*init)(struct mmc *mmc);
+ int (*getcd)(struct mmc *mmc);
+ int (*getwp)(struct mmc *mmc);
+};
+
+struct mmc_config {
+ const char *name;
+ const struct mmc_ops *ops;
+ uint host_caps;
+ uint voltages;
+ uint f_min;
+ uint f_max;
+ uint b_max;
+ unsigned char part_type;
+};
+
+/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
struct mmc {
struct list_head link;
- char name[32];
- void *priv;
- uint voltages;
+ const struct mmc_config *cfg; /* provided configuration */
uint version;
+ void *priv;
uint has_init;
- uint f_min;
- uint f_max;
int high_capacity;
uint bus_width;
uint clock;
uint card_caps;
- uint host_caps;
uint ocr;
+ uint dsr;
+ uint dsr_imp;
uint scr[2];
uint csd[4];
uint cid[4];
u64 capacity_rpmb;
u64 capacity_gp[4];
block_dev_desc_t block_dev;
- int (*send_cmd)(struct mmc *mmc,
- struct mmc_cmd *cmd, struct mmc_data *data);
- void (*set_ios)(struct mmc *mmc);
- int (*init)(struct mmc *mmc);
- int (*getcd)(struct mmc *mmc);
- int (*getwp)(struct mmc *mmc);
- uint b_max;
char op_cond_pending; /* 1 if we are waiting on an op_cond command */
char init_in_progress; /* 1 if we have done mmc_start_init() */
char preinit; /* start init as early as possible */
};
int mmc_register(struct mmc *mmc);
+struct mmc *mmc_create(const struct mmc_config *cfg, void *priv);
+void mmc_destroy(struct mmc *mmc);
int mmc_initialize(bd_t *bis);
int mmc_init(struct mmc *mmc);
int mmc_read(struct mmc *mmc, u64 src, uchar *dst, int size);
int mmc_set_dev(int dev_num);
void print_mmc_devices(char separator);
int get_mmc_num(void);
-int board_mmc_getcd(struct mmc *mmc);
int mmc_switch_part(int dev_num, unsigned int part_num);
int mmc_getcd(struct mmc *mmc);
+int board_mmc_getcd(struct mmc *mmc);
int mmc_getwp(struct mmc *mmc);
-void spl_mmc_load(void) __noreturn;
+int board_mmc_getwp(struct mmc *mmc);
+int mmc_set_dsr(struct mmc *mmc, u16 val);
/* Function to change the size of boot partition and rpmb partitions */
int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
unsigned long rpmbsize);
-/* Function to send commands to open/close the specified boot partition */
-int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
-
+/* Function to modify the PARTITION_CONFIG field of EXT_CSD */
+int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access);
+/* Function to modify the BOOT_BUS_WIDTH field of EXT_CSD */
+int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode);
+/* Function to modify the RST_n_FUNCTION field of EXT_CSD */
+int mmc_set_rst_n_function(struct mmc *mmc, u8 enable);
+/* Functions to read / write the RPMB partition */
+int mmc_rpmb_set_key(struct mmc *mmc, void *key);
+int mmc_rpmb_get_counter(struct mmc *mmc, unsigned long *counter);
+int mmc_rpmb_read(struct mmc *mmc, void *addr, unsigned short blk,
+ unsigned short cnt, unsigned char *key);
+int mmc_rpmb_write(struct mmc *mmc, void *addr, unsigned short blk,
+ unsigned short cnt, unsigned char *key);
/**
* Start device initialization and return immediately; it does not block on
* polling OCR (operation condition register) status. Then you should call
#ifdef CONFIG_GENERIC_MMC
#ifdef CONFIG_MMC_SPI
-#define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)
+#define mmc_host_is_spi(mmc) ((mmc)->cfg->host_caps & MMC_MODE_SPI)
#else
#define mmc_host_is_spi(mmc) 0
#endif
int mmc_legacy_init(int verbose);
#endif
+void board_mmc_power_init(void);
+int board_mmc_init(bd_t *bis);
+int cpu_mmc_init(bd_t *bis);
+int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr);
+
+/* Set block count limit because of 16 bit register limit on some hardware*/
+#ifndef CONFIG_SYS_MMC_MAX_BLK_COUNT
+#define CONFIG_SYS_MMC_MAX_BLK_COUNT 65535
+#endif
+
#endif /* _MMC_H_ */