2007-09-17 01:08:06 +04:00
|
|
|
/*
|
2007-04-06 20:49:48 +04:00
|
|
|
* SD Memory Card emulation. Mostly correct for MMC too.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
|
|
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
|
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
|
|
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
2016-06-29 14:47:03 +03:00
|
|
|
|
|
|
|
#ifndef HW_SD_H
|
|
|
|
#define HW_SD_H
|
2007-04-06 20:49:48 +04:00
|
|
|
|
2019-08-12 08:23:51 +03:00
|
|
|
#include "hw/qdev-core.h"
|
2020-09-03 23:43:22 +03:00
|
|
|
#include "qom/object.h"
|
2016-03-15 18:58:45 +03:00
|
|
|
|
2007-04-06 20:49:48 +04:00
|
|
|
#define OUT_OF_RANGE (1 << 31)
|
|
|
|
#define ADDRESS_ERROR (1 << 30)
|
|
|
|
#define BLOCK_LEN_ERROR (1 << 29)
|
|
|
|
#define ERASE_SEQ_ERROR (1 << 28)
|
|
|
|
#define ERASE_PARAM (1 << 27)
|
|
|
|
#define WP_VIOLATION (1 << 26)
|
|
|
|
#define CARD_IS_LOCKED (1 << 25)
|
|
|
|
#define LOCK_UNLOCK_FAILED (1 << 24)
|
|
|
|
#define COM_CRC_ERROR (1 << 23)
|
|
|
|
#define ILLEGAL_COMMAND (1 << 22)
|
|
|
|
#define CARD_ECC_FAILED (1 << 21)
|
|
|
|
#define CC_ERROR (1 << 20)
|
|
|
|
#define SD_ERROR (1 << 19)
|
|
|
|
#define CID_CSD_OVERWRITE (1 << 16)
|
|
|
|
#define WP_ERASE_SKIP (1 << 15)
|
|
|
|
#define CARD_ECC_DISABLED (1 << 14)
|
|
|
|
#define ERASE_RESET (1 << 13)
|
|
|
|
#define CURRENT_STATE (7 << 9)
|
|
|
|
#define READY_FOR_DATA (1 << 8)
|
|
|
|
#define APP_CMD (1 << 5)
|
|
|
|
#define AKE_SEQ_ERROR (1 << 3)
|
|
|
|
|
2018-06-08 15:15:33 +03:00
|
|
|
enum SDPhySpecificationVersion {
|
|
|
|
SD_PHY_SPECv1_10_VERS = 1,
|
|
|
|
SD_PHY_SPECv2_00_VERS = 2,
|
2018-06-08 15:15:34 +03:00
|
|
|
SD_PHY_SPECv3_01_VERS = 3,
|
2018-06-08 15:15:33 +03:00
|
|
|
};
|
|
|
|
|
2018-02-08 19:48:09 +03:00
|
|
|
typedef enum {
|
|
|
|
SD_VOLTAGE_0_4V = 400, /* currently not supported */
|
|
|
|
SD_VOLTAGE_1_8V = 1800,
|
|
|
|
SD_VOLTAGE_3_0V = 3000,
|
|
|
|
SD_VOLTAGE_3_3V = 3300,
|
|
|
|
} sd_voltage_mv_t;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
UHS_NOT_SUPPORTED = 0,
|
|
|
|
UHS_I = 1,
|
|
|
|
UHS_II = 2, /* currently not supported */
|
|
|
|
UHS_III = 3, /* currently not supported */
|
|
|
|
} sd_uhs_mode_t;
|
|
|
|
|
2007-04-06 20:49:48 +04:00
|
|
|
typedef enum {
|
|
|
|
sd_none = -1,
|
|
|
|
sd_bc = 0, /* broadcast -- no response */
|
2007-07-31 03:54:51 +04:00
|
|
|
sd_bcr, /* broadcast with response */
|
|
|
|
sd_ac, /* addressed -- no data transfer */
|
2007-04-06 20:49:48 +04:00
|
|
|
sd_adtc, /* addressed with data transfer */
|
2009-10-02 01:12:16 +04:00
|
|
|
} sd_cmd_type_t;
|
2007-04-06 20:49:48 +04:00
|
|
|
|
2009-05-10 04:44:56 +04:00
|
|
|
typedef struct {
|
2007-04-06 20:49:48 +04:00
|
|
|
uint8_t cmd;
|
|
|
|
uint32_t arg;
|
|
|
|
uint8_t crc;
|
2009-05-10 04:44:56 +04:00
|
|
|
} SDRequest;
|
2007-04-06 20:49:48 +04:00
|
|
|
|
|
|
|
typedef struct SDState SDState;
|
|
|
|
|
2016-02-18 17:16:18 +03:00
|
|
|
#define TYPE_SD_CARD "sd-card"
|
2020-09-03 23:43:22 +03:00
|
|
|
typedef struct SDCardClass SDCardClass;
|
2020-09-01 00:07:33 +03:00
|
|
|
DECLARE_OBJ_CHECKERS(SDState, SDCardClass,
|
|
|
|
SD_CARD, TYPE_SD_CARD)
|
2016-02-18 17:16:18 +03:00
|
|
|
|
2020-09-03 23:43:22 +03:00
|
|
|
struct SDCardClass {
|
2016-02-18 17:16:18 +03:00
|
|
|
/*< private >*/
|
|
|
|
DeviceClass parent_class;
|
|
|
|
/*< public >*/
|
|
|
|
|
|
|
|
int (*do_command)(SDState *sd, SDRequest *req, uint8_t *response);
|
2020-08-14 12:23:40 +03:00
|
|
|
/**
|
|
|
|
* Write a byte to a SD card.
|
|
|
|
* @sd: card
|
|
|
|
* @value: byte to write
|
|
|
|
*
|
|
|
|
* Write a byte on the data lines of a SD card.
|
|
|
|
*/
|
|
|
|
void (*write_byte)(SDState *sd, uint8_t value);
|
|
|
|
/**
|
|
|
|
* Read a byte from a SD card.
|
|
|
|
* @sd: card
|
|
|
|
*
|
|
|
|
* Read a byte from the data lines of a SD card.
|
|
|
|
*
|
|
|
|
* Return: byte value read
|
|
|
|
*/
|
|
|
|
uint8_t (*read_byte)(SDState *sd);
|
2016-02-18 17:16:18 +03:00
|
|
|
bool (*data_ready)(SDState *sd);
|
2018-02-08 19:48:09 +03:00
|
|
|
void (*set_voltage)(SDState *sd, uint16_t millivolts);
|
2018-02-08 19:48:10 +03:00
|
|
|
uint8_t (*get_dat_lines)(SDState *sd);
|
|
|
|
bool (*get_cmd_line)(SDState *sd);
|
2016-02-18 17:16:18 +03:00
|
|
|
void (*enable)(SDState *sd, bool enable);
|
|
|
|
bool (*get_inserted)(SDState *sd);
|
|
|
|
bool (*get_readonly)(SDState *sd);
|
2020-09-03 23:43:22 +03:00
|
|
|
};
|
2016-02-18 17:16:18 +03:00
|
|
|
|
|
|
|
#define TYPE_SD_BUS "sd-bus"
|
2020-09-01 00:07:37 +03:00
|
|
|
OBJECT_DECLARE_TYPE(SDBus, SDBusClass,
|
qom: Remove module_obj_name parameter from OBJECT_DECLARE* macros
One of the goals of having less boilerplate on QOM declarations
is to avoid human error. Requiring an extra argument that is
never used is an opportunity for mistakes.
Remove the unused argument from OBJECT_DECLARE_TYPE and
OBJECT_DECLARE_SIMPLE_TYPE.
Coccinelle patch used to convert all users of the macros:
@@
declarer name OBJECT_DECLARE_TYPE;
identifier InstanceType, ClassType, lowercase, UPPERCASE;
@@
OBJECT_DECLARE_TYPE(InstanceType, ClassType,
- lowercase,
UPPERCASE);
@@
declarer name OBJECT_DECLARE_SIMPLE_TYPE;
identifier InstanceType, lowercase, UPPERCASE;
@@
OBJECT_DECLARE_SIMPLE_TYPE(InstanceType,
- lowercase,
UPPERCASE);
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Reviewed-by: Cédric Le Goater <clg@kaod.org>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Acked-by: Igor Mammedov <imammedo@redhat.com>
Acked-by: Paul Durrant <paul@xen.org>
Acked-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20200916182519.415636-4-ehabkost@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
2020-09-16 21:25:17 +03:00
|
|
|
SD_BUS)
|
2016-02-18 17:16:18 +03:00
|
|
|
|
|
|
|
struct SDBus {
|
|
|
|
BusState qbus;
|
|
|
|
};
|
|
|
|
|
2020-09-03 23:43:22 +03:00
|
|
|
struct SDBusClass {
|
2016-02-18 17:16:18 +03:00
|
|
|
/*< private >*/
|
|
|
|
BusClass parent_class;
|
|
|
|
/*< public >*/
|
|
|
|
|
|
|
|
/* These methods are called by the SD device to notify the controller
|
|
|
|
* when the card insertion or readonly status changes
|
|
|
|
*/
|
|
|
|
void (*set_inserted)(DeviceState *dev, bool inserted);
|
|
|
|
void (*set_readonly)(DeviceState *dev, bool readonly);
|
2020-09-03 23:43:22 +03:00
|
|
|
};
|
2016-02-18 17:16:18 +03:00
|
|
|
|
|
|
|
/* Functions to be used by qdevified callers (working via
|
|
|
|
* an SDBus rather than directly with SDState)
|
|
|
|
*/
|
2018-02-08 19:48:09 +03:00
|
|
|
void sdbus_set_voltage(SDBus *sdbus, uint16_t millivolts);
|
2018-02-08 19:48:10 +03:00
|
|
|
uint8_t sdbus_get_dat_lines(SDBus *sdbus);
|
|
|
|
bool sdbus_get_cmd_line(SDBus *sdbus);
|
2016-02-18 17:16:18 +03:00
|
|
|
int sdbus_do_command(SDBus *sd, SDRequest *req, uint8_t *response);
|
2020-08-14 12:23:41 +03:00
|
|
|
/**
|
|
|
|
* Write a byte to a SD bus.
|
|
|
|
* @sd: bus
|
|
|
|
* @value: byte to write
|
|
|
|
*
|
|
|
|
* Write a byte on the data lines of a SD bus.
|
|
|
|
*/
|
|
|
|
void sdbus_write_byte(SDBus *sd, uint8_t value);
|
2020-08-14 12:23:42 +03:00
|
|
|
/**
|
|
|
|
* Read a byte from a SD bus.
|
|
|
|
* @sd: bus
|
|
|
|
*
|
|
|
|
* Read a byte from the data lines of a SD bus.
|
|
|
|
*
|
|
|
|
* Return: byte value read
|
|
|
|
*/
|
|
|
|
uint8_t sdbus_read_byte(SDBus *sd);
|
2020-08-14 12:23:43 +03:00
|
|
|
/**
|
|
|
|
* Write data to a SD bus.
|
|
|
|
* @sdbus: bus
|
|
|
|
* @buf: data to write
|
|
|
|
* @length: number of bytes to write
|
|
|
|
*
|
|
|
|
* Write multiple bytes of data on the data lines of a SD bus.
|
|
|
|
*/
|
|
|
|
void sdbus_write_data(SDBus *sdbus, const void *buf, size_t length);
|
2020-08-14 12:23:45 +03:00
|
|
|
/**
|
|
|
|
* Read data from a SD bus.
|
|
|
|
* @sdbus: bus
|
|
|
|
* @buf: buffer to read data into
|
|
|
|
* @length: number of bytes to read
|
|
|
|
*
|
|
|
|
* Read multiple bytes of data on the data lines of a SD bus.
|
|
|
|
*/
|
|
|
|
void sdbus_read_data(SDBus *sdbus, void *buf, size_t length);
|
2016-02-18 17:16:18 +03:00
|
|
|
bool sdbus_data_ready(SDBus *sd);
|
|
|
|
bool sdbus_get_inserted(SDBus *sd);
|
|
|
|
bool sdbus_get_readonly(SDBus *sd);
|
2017-02-28 17:55:09 +03:00
|
|
|
/**
|
|
|
|
* sdbus_reparent_card: Reparent an SD card from one controller to another
|
|
|
|
* @from: controller bus to remove card from
|
|
|
|
* @to: controller bus to move card to
|
|
|
|
*
|
|
|
|
* Reparent an SD card, effectively unplugging it from one controller
|
|
|
|
* and inserting it into another. This is useful for SoCs like the
|
|
|
|
* bcm2835 which have two SD controllers and connect a single SD card
|
|
|
|
* to them, selected by the guest reprogramming GPIO line routing.
|
|
|
|
*/
|
|
|
|
void sdbus_reparent_card(SDBus *from, SDBus *to);
|
2016-02-18 17:16:18 +03:00
|
|
|
|
|
|
|
/* Functions to be used by SD devices to report back to qdevified controllers */
|
|
|
|
void sdbus_set_inserted(SDBus *sd, bool inserted);
|
|
|
|
void sdbus_set_readonly(SDBus *sd, bool inserted);
|
|
|
|
|
2016-06-29 14:47:03 +03:00
|
|
|
#endif /* HW_SD_H */
|