mmcsd_core.h 6.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
/*
 * File      : mmcsd_core.h
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006, RT-Thread Development Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date           Author		Notes
 * 2011-07-25     weety		first version
 */

#ifndef __CORE_H__
#define __CORE_H__

#include <rtthread.h>
#include "mmcsd_host.h"
#include "mmcsd_card.h"
#include "mmcsd_cmd.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef RT_MMCSD_DBG
#define mmcsd_dbg(fmt, ...)  rt_kprintf(fmt, ##__VA_ARGS__)
#else
#define mmcsd_dbg(fmt, ...)
#endif

struct rt_mmcsd_data {
	rt_uint32_t  blksize;
	rt_uint32_t  blks;
	rt_uint32_t  *buf;
	rt_int32_t  err;
	rt_uint32_t  flags;
#define DATA_DIR_WRITE	(1 << 0)
#define DATA_DIR_READ	(1 << 1)
#define DATA_STREAM	(1 << 2)
	rt_uint32_t  timeout_ns;
	rt_uint32_t  timeout_clks;
};

struct rt_mmcsd_cmd {
	rt_uint32_t  cmd_code;
	rt_uint32_t  arg;
	rt_uint32_t  resp[4];
	rt_uint32_t  flags;
/*rsponse types 
 *bits:0~3
 */
#define RESP_MASK	(0xF)
#define RESP_NONE	(0)
#define RESP_R1		(1 << 0)
#define RESP_R1B	(2 << 0)
#define RESP_R2		(3 << 0)
#define RESP_R3		(4 << 0)
#define RESP_R4		(5 << 0)
#define RESP_R6		(6 << 0)
#define RESP_R7		(7 << 0)
/*command types 
 *bits:4~5
 */
#define CMD_MASK	(3 << 4)		/* command type */
#define CMD_AC		(0 << 4)
#define CMD_ADTC	(1 << 4)
#define CMD_BC		(2 << 4)
#define CMD_BCR		(3 << 4)

#define resp_type(cmd)	((cmd)->flags & RESP_MASK)

/*spi rsponse types 
 *bits:6~8
 */
#define RESP_SPI_MASK	(0x7 << 6)
#define RESP_SPI_R1	(1 << 6)
#define RESP_SPI_R1B	(2 << 6)
#define RESP_SPI_R2	(3 << 6)
#define RESP_SPI_R3	(4 << 6)
#define RESP_SPI_R4	(5 << 6)
#define RESP_SPI_R5	(6 << 6)
#define RESP_SPI_R7	(7 << 6)

#define spi_resp_type(cmd)	((cmd)->flags & RESP_SPI_MASK)
/*
 * These are the command types.
 */
#define cmd_type(cmd)	((cmd)->flags & CMD_MASK)
	
	rt_int32_t  err;

	struct rt_mmcsd_data *data;
};

struct rt_mmcsd_req {
	struct rt_mmcsd_data  *data;
	struct rt_mmcsd_cmd   *cmd;
	struct rt_mmcsd_cmd   *stop;
};

/*the following is response bit*/
#define R1_OUT_OF_RANGE		(1 << 31)	/* er, c */
#define R1_ADDRESS_ERROR	(1 << 30)	/* erx, c */
#define R1_BLOCK_LEN_ERROR	(1 << 29)	/* er, c */
#define R1_ERASE_SEQ_ERROR      (1 << 28)	/* er, c */
#define R1_ERASE_PARAM		(1 << 27)	/* ex, c */
#define R1_WP_VIOLATION		(1 << 26)	/* erx, c */
#define R1_CARD_IS_LOCKED	(1 << 25)	/* sx, a */
#define R1_LOCK_UNLOCK_FAILED	(1 << 24)	/* erx, c */
#define R1_COM_CRC_ERROR	(1 << 23)	/* er, b */
#define R1_ILLEGAL_COMMAND	(1 << 22)	/* er, b */
#define R1_CARD_ECC_FAILED	(1 << 21)	/* ex, c */
#define R1_CC_ERROR		(1 << 20)	/* erx, c */
#define R1_ERROR		(1 << 19)	/* erx, c */
#define R1_UNDERRUN		(1 << 18)	/* ex, c */
#define R1_OVERRUN		(1 << 17)	/* ex, c */
#define R1_CID_CSD_OVERWRITE	(1 << 16)	/* erx, c, CID/CSD overwrite */
#define R1_WP_ERASE_SKIP	(1 << 15)	/* sx, c */
#define R1_CARD_ECC_DISABLED	(1 << 14)	/* sx, a */
#define R1_ERASE_RESET		(1 << 13)	/* sr, c */
#define R1_STATUS(x)            (x & 0xFFFFE000)
#define R1_CURRENT_STATE(x)	((x & 0x00001E00) >> 9)	/* sx, b (4 bits) */
#define R1_READY_FOR_DATA	(1 << 8)	/* sx, a */
#define R1_APP_CMD		(1 << 5)	/* sr, c */


#define R1_SPI_IDLE		(1 << 0)
#define R1_SPI_ERASE_RESET	(1 << 1)
#define R1_SPI_ILLEGAL_COMMAND	(1 << 2)
#define R1_SPI_COM_CRC		(1 << 3)
#define R1_SPI_ERASE_SEQ	(1 << 4)
#define R1_SPI_ADDRESS		(1 << 5)
#define R1_SPI_PARAMETER	(1 << 6)
/* R1 bit 7 is always zero */
#define R2_SPI_CARD_LOCKED	(1 << 8)
#define R2_SPI_WP_ERASE_SKIP	(1 << 9)	/* or lock/unlock fail */
#define R2_SPI_LOCK_UNLOCK_FAIL	R2_SPI_WP_ERASE_SKIP
#define R2_SPI_ERROR		(1 << 10)
#define R2_SPI_CC_ERROR		(1 << 11)
#define R2_SPI_CARD_ECC_ERROR	(1 << 12)
#define R2_SPI_WP_VIOLATION	(1 << 13)
#define R2_SPI_ERASE_PARAM	(1 << 14)
#define R2_SPI_OUT_OF_RANGE	(1 << 15)	/* or CSD overwrite */
#define R2_SPI_CSD_OVERWRITE	R2_SPI_OUT_OF_RANGE

#define CARD_BUSY	0x80000000	/* Card Power up status bit */

/**
 * fls - find last (most-significant) bit set
 * @x: the word to search
 *
 * This is defined the same way as ffs.
 * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
 */

rt_inline rt_uint32_t fls(rt_uint32_t val)
{
	rt_uint32_t  bit = 32;

	if (!val)
		return 0;
	if (!(val & 0xffff0000u)) 
	{
		val <<= 16;
		bit -= 16;
	}
	if (!(val & 0xff000000u)) 
	{
		val <<= 8;
		bit -= 8;
	}
	if (!(val & 0xf0000000u)) 
	{
		val <<= 4;
		bit -= 4;
	}
	if (!(val & 0xc0000000u)) 
	{
		val <<= 2;
		bit -= 2;
	}
	if (!(val & 0x80000000u)) 
	{
		val <<= 1;
		bit -= 1;
	}

	return bit;
}

#if !defined(__GNUC__)
rt_inline rt_uint32_t ffs(rt_uint32_t x)
{
        int r = 1;

        if (!x)
                return 0;
        if (!(x & 0xffff)) {
                x >>= 16;
                r += 16;
        }
        if (!(x & 0xff)) {
                x >>= 8;
                r += 8;
        }
        if (!(x & 0xf)) {
                x >>= 4;
                r += 4;
        }
        if (!(x & 3)) {
                x >>= 2;
                r += 2;
        }
        if (!(x & 1)) {
                x >>= 1;
                r += 1;
        }
        return r;
}
#endif

void mmcsd_host_lock(struct rt_mmcsd_host *host);
void mmcsd_host_unlock(struct rt_mmcsd_host *host);
void mmcsd_req_complete(struct rt_mmcsd_host *host);
void mmcsd_send_request(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req);
rt_int32_t mmcsd_send_cmd(struct rt_mmcsd_host *host, struct rt_mmcsd_cmd *cmd, int retries);
rt_int32_t mmcsd_go_idle(struct rt_mmcsd_host *host);
rt_int32_t mmcsd_spi_read_ocr(struct rt_mmcsd_host *host, rt_int32_t high_capacity, rt_uint32_t *ocr);
rt_int32_t mmcsd_all_get_cid(struct rt_mmcsd_host *host, rt_uint32_t *cid);
rt_int32_t mmcsd_get_cid(struct rt_mmcsd_host *host, rt_uint32_t *cid);
rt_int32_t mmcsd_get_csd(struct rt_mmcsd_card *card, rt_uint32_t *csd);
rt_int32_t mmcsd_select_card(struct rt_mmcsd_card *card);
rt_int32_t mmcsd_deselect_cards(struct rt_mmcsd_card *host);
rt_int32_t mmcsd_spi_use_crc(struct rt_mmcsd_host *host, rt_int32_t use_crc);
void mmcsd_set_chip_select(struct rt_mmcsd_host *host, rt_int32_t mode);
void mmcsd_set_clock(struct rt_mmcsd_host *host, rt_uint32_t clk);
void mmcsd_set_bus_mode(struct rt_mmcsd_host *host, rt_uint32_t mode);
void mmcsd_set_bus_width(struct rt_mmcsd_host *host, rt_uint32_t width);
void mmcsd_set_data_timeout(struct rt_mmcsd_data *data, const struct rt_mmcsd_card *card);
rt_uint32_t mmcsd_select_voltage(struct rt_mmcsd_host *host, rt_uint32_t ocr);
void mmcsd_change(struct rt_mmcsd_host *host);
void mmcsd_detect(void *param);
struct rt_mmcsd_host *mmcsd_alloc_host(void);
void mmcsd_free_host(struct rt_mmcsd_host *host);
void rt_mmcsd_core_init(void);

void rt_mmcsd_blk_init(void);
rt_int32_t rt_mmcsd_blk_probe(struct rt_mmcsd_card *card);
void rt_mmcsd_blk_remove(struct rt_mmcsd_card *card);


#ifdef __cplusplus
}
#endif

#endif