mirror of
https://github.com/apache/nuttx.git
synced 2026-08-23 06:28:45 +00:00
The SD path never performs the CMD6 switch its eMMC counterpart has performed for years, so an SD card is left in default speed and every host clocked accordingly, at 25MHz rather than the 50MHz the card supports. A TODO in this file has asked for it since 2010; this removes it. A host asks for the switch by reporting SDIO_CAPS_SD_HS_MODE, which mirrors the eMMC capability beside it. The switch is attempted once the bus is at the default transfer rate and the wide bus is selected, and the card's own answer decides the outcome: the 64 byte status block reports the function actually selected, and a card that cannot do what was asked says so there rather than failing the command. Cards below version 1.10 of the physical layer specification are not asked, since CMD6 postdates them. Only a confirmed switch reaches the host, as the new CLOCK_SD_TRANSFER_4BIT_HS rate. That is a rate rather than a flag on an existing one because the host is clocked twice during initialization, once before the switch can have happened, and a host that cannot tell the two apart would run a card in default speed past its rated 25MHz. The enumerator is added last, so no existing driver's switch statement changes meaning, and the rate reaches only a host that reported the new capability, which none in tree does. Every failure path is survivable: a card that declines, a card too old to ask, and a host that never asks all stay at the default rate. Documents the two capabilities and the clock rates a lower half has to handle. The MMC/SD documentation was three sentences and a pointer to the SDIO page, so it said nothing about how a card is registered, how the bus width and clock are negotiated, or what any of the configuration options do. It now covers those, the ioctl interface and /proc/mmcsd, and the high speed switch this commit adds is described where somebody looking for it would look rather than only in the SDIO lower half page. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond <justin@dynam.ac>
151 lines
5.7 KiB
C
151 lines
5.7 KiB
C
/****************************************************************************
|
|
* drivers/mmcsd/mmcsd.h
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifndef __DRIVERS_MMCSD_MMCSD_H
|
|
#define __DRIVERS_MMCSD_MMCSD_H
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
#include <nuttx/sdio.h>
|
|
#include <stdint.h>
|
|
#include <nuttx/debug.h>
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* Enable excessive debug options */
|
|
|
|
#undef CONFIG_MMCSD_DUMPALL /* MUST BE DEFINED MANUALLY */
|
|
|
|
#if !defined(CONFIG_DEBUG_INFO) || !defined(CONFIG_DEBUG_FS)
|
|
# undef CONFIG_MMCSD_DUMPALL
|
|
#endif
|
|
|
|
#ifdef CONFIG_MMCSD_MMCSUPPORT
|
|
# define MMCSD_PART_COUNT 8
|
|
#else
|
|
# define MMCSD_PART_COUNT 1
|
|
#endif
|
|
|
|
/* Card type */
|
|
|
|
#define MMCSD_CARDTYPE_UNKNOWN 0 /* Unknown card type */
|
|
#define MMCSD_CARDTYPE_MMC 1 /* Bit 0: MMC card */
|
|
#define MMCSD_CARDTYPE_SDV1 2 /* Bit 1: SD version 1.x */
|
|
#define MMCSD_CARDTYPE_SDV2 4 /* Bit 2: SD version 2.x with byte addressing */
|
|
#define MMCSD_CARDTYPE_BLOCK 8 /* Bit 3: SD version 2.x or MMC with block addressing */
|
|
|
|
#define IS_MMC(t) (((t) & MMCSD_CARDTYPE_MMC) != 0)
|
|
#define IS_SD(t) (((t) & (MMCSD_CARDTYPE_SDV1|MMCSD_CARDTYPE_SDV2)) != 0)
|
|
#define IS_SDV1(t) (((t) & MMCSD_CARDTYPE_SDV1) != 0)
|
|
#define IS_SDV2(t) (((t) & MMCSD_CARDTYPE_SDV2) != 0)
|
|
#define IS_BLOCK(t) (((t) & MMCSD_CARDTYPE_BLOCK) != 0)
|
|
|
|
/****************************************************************************
|
|
* Public Types
|
|
****************************************************************************/
|
|
|
|
struct mmcsd_part_s
|
|
{
|
|
FAR struct mmcsd_state_s *priv;
|
|
blkcnt_t nblocks; /* Number of blocks */
|
|
};
|
|
|
|
/* This structure is contains the unique state of the MMC/SD block driver */
|
|
|
|
struct mmcsd_state_s
|
|
{
|
|
FAR struct sdio_dev_s *dev; /* The SDIO device bound to this instance */
|
|
uint8_t crefs; /* Open references on the driver */
|
|
mutex_t lock; /* Assures mutually exclusive access to the slot */
|
|
int minor; /* Device number */
|
|
struct mmcsd_part_s part[MMCSD_PART_COUNT]; /* Partition data */
|
|
uint32_t partnum; /* Partition number */
|
|
|
|
/* Status flags */
|
|
|
|
uint8_t probed:1; /* true: mmcsd_probe() discovered a card */
|
|
uint8_t widebus:1; /* true: Wide 4-bit bus selected */
|
|
uint8_t mediachanged:1; /* true: Media changed since last check */
|
|
uint8_t wrbusy:1; /* true: Last transfer was a write, card may be busy */
|
|
uint8_t wrprotect:1; /* true: Card is write protected (from CSD) */
|
|
uint8_t locked:1; /* true: Media is locked (from R1) */
|
|
uint8_t dsrimp:1; /* true: card supports CMD4/DSR setting (from CSD) */
|
|
#ifdef CONFIG_SDIO_DMA
|
|
uint8_t dma:1; /* true: hardware supports DMA */
|
|
#endif
|
|
|
|
uint8_t mode:4; /* (See MMCSDMODE_* definitions) */
|
|
uint8_t type:4; /* Card type (See MMCSD_CARDTYPE_* definitions) */
|
|
uint8_t buswidth:4; /* Bus widths supported (SD only) */
|
|
uint8_t cmd23support:1; /* CMD23 supported (SD only) */
|
|
uint8_t sdversion:4; /* SD physical layer version (SD only) */
|
|
sdio_capset_t caps; /* SDIO driver capabilities/limitations */
|
|
uint32_t cid[4]; /* CID register */
|
|
uint32_t csd[4]; /* CSD register */
|
|
uint16_t selblocklen; /* The currently selected block length */
|
|
uint16_t rca; /* Relative Card Address (RCS) register */
|
|
|
|
/* Memory card geometry (extracted from the CSD) */
|
|
|
|
uint8_t blockshift; /* Log2 of blocksize */
|
|
uint16_t blocksize; /* Read block length (== block size) */
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Public Functions Definitions
|
|
****************************************************************************/
|
|
|
|
#undef EXTERN
|
|
#if defined(__cplusplus)
|
|
#define EXTERN extern "C"
|
|
extern "C"
|
|
{
|
|
#else
|
|
#define EXTERN extern
|
|
#endif
|
|
|
|
#ifdef CONFIG_MMCSD_PROCFS
|
|
void mmcsd_initialize_procfs(void);
|
|
#endif
|
|
|
|
#ifdef CONFIG_MMCSD_DUMPALL
|
|
# define mmcsd_dumpbuffer(m,b,l) finfodumpbuffer(m,b,l)
|
|
#else
|
|
# define mmcsd_dumpbuffer(m,b,l)
|
|
#endif
|
|
|
|
#if defined(CONFIG_DEBUG_INFO) && defined(CONFIG_DEBUG_FS)
|
|
EXTERN void mmcsd_dmpcsd(FAR const uint8_t *csd, uint8_t cardtype);
|
|
#else
|
|
# define mmcsd_dmpcsd(csd,cadtype)
|
|
#endif
|
|
|
|
#undef EXTERN
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif
|
|
#endif /* __DRIVERS_MMCSD_MMCSD_H */
|