haiku/headers/private/drivers/mmc.h
Adrien Destugues 5ec64c5cdd sd/mmc: Cleanup and improve reliability
Store the bus cookie in the mmc_disk driver and pass it to the bus
manager when executing commands. This avoids calling into the device
manager at each read and write operation. The code to get the cookie
from mmc_disk isn't so nice since it needs to access the grandparent
device (the mmc bus root), it would be simpler if this cookie would be
available directly from mmc bus devices.

We can get card removal and card insertion interrupt at the same time
due to insufficient hardware debouncing (the SDHCI spec says we
shouldn't, but it happens on Ricoh controllers. Can't blame them, they
don't advertise themselves as compliant with the spec). So, check the
card status from the interrupt handler and ignore the incorrect
interrupts.

Fix unreliable card initialization: power must be turned on before
starting up the SD clock. Remove a now unneeded delay that was added in
an attempt to avoid initial instability.

Change-Id: Ibd8d051da1a1d859f3924ee535f4a05d9b6398d4
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3639
Reviewed-by: Jérôme Duval <jerome.duval@gmail.com>
2021-01-20 19:02:38 +00:00

113 lines
3.3 KiB
C

/*
* Copyright 2019-2020, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Adrien Destugues, pulkomandy@pulkomandy.tk
*/
#ifndef _MMC_H
#define _MMC_H
#include <device_manager.h>
#define MMC_BUS_MODULE_NAME "bus_managers/mmc/driver_v1"
struct IOOperation;
enum {
CARD_TYPE_MMC,
CARD_TYPE_SD,
CARD_TYPE_SDHC,
CARD_TYPE_UHS1,
CARD_TYPE_UHS2,
CARD_TYPE_SDIO
};
// Commands for SD cards defined in SD Specifications Part 1:
// Physical Layer Simplified Specification Version 8.00
// They are in the common .h file for the mmc stack because the SDHCI driver
// currently needs to map them to the corresponding expected response types.
enum SD_COMMANDS {
// Basic commands, class 0
SD_GO_IDLE_STATE = 0,
SD_ALL_SEND_CID = 2,
SD_SEND_RELATIVE_ADDR = 3,
SD_SELECT_DESELECT_CARD = 7,
SD_SEND_IF_COND = 8,
SD_SEND_CSD = 9,
SD_STOP_TRANSMISSION = 12,
// Block oriented read and write commands, class 2
SD_READ_SINGLE_BLOCK = 17,
SD_READ_MULTIPLE_BLOCKS = 18,
SD_WRITE_SINGLE_BLOCK = 24,
SD_WRITE_MULTIPLE_BLOCKS = 25,
// Application specific commands, class 8
SD_APP_CMD = 55,
// I/O mode commands, class 9
SD_IO_ABORT = 52,
};
enum SDHCI_APPLICATION_COMMANDS {
SD_SET_BUS_WIDTH = 6,
SD_SEND_OP_COND = 41,
};
// Interface between mmc_bus and underlying implementation (sdhci_pci or any
// other thing that can execute mmc commands)
typedef struct mmc_bus_interface {
driver_module_info info;
status_t (*set_clock)(void* controller, uint32_t kilohertz);
// Configure the bus clock. The bus is initialized with a slow clock
// that allows device enumeration in all cases, but after enumeration
// the mmc_bus knows how fast each card can go, and configures the bus
// accordingly.
status_t (*execute_command)(void* controller, uint8_t command,
uint32_t argument, uint32_t* result);
// Execute a command with no I/O phase
status_t (*do_io)(void* controller, uint8_t command,
IOOperation* operation, bool offsetAsSectors);
// Execute a command that involves a data transfer.
void (*set_scan_semaphore)(void* controller, sem_id sem);
// Pass the semaphore used for device rescan to the bus controller
void (*set_bus_width)(void* controller, int width);
// Set the data bus width to 1, 4 or 8 bit mode.
} mmc_bus_interface;
// Interface between mmc device driver (mmc_disk, sdio drivers, ...) and mmc_bus
// This interface is rather generic as it allows implementation of drivers for
// different type of cards, which will use different commands. The bus
// provides a generic interface for all of them, and is not specific to any
// type of card.
typedef struct mmc_device_interface {
driver_module_info info;
status_t (*execute_command)(device_node* node, void* cookie, uint16_t rca,
uint8_t command, uint32_t argument, uint32_t* result);
// Execute a command with no I/O phase
status_t (*do_io)(device_node* controller, void* cookie, uint16_t rca,
uint8_t command, IOOperation* operation, bool offsetAsSectors);
// Execute a command that involves a data transfer.
void (*set_bus_width)(device_node* controller, void* cookie, int width);
// Set the data bus width to 1, 4 or 8 bit mode.
} mmc_device_interface;
// Device attribute paths for the MMC device
static const char* kMmcRcaAttribute = "mmc/rca";
static const char* kMmcTypeAttribute = "mmc/type";
#endif /* _MMC_H */