linux/drivers/mmc/host/sdhci.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  linux/drivers/mmc/host/sdhci.c - Secure Digital Host Controller Interface driver
 *
 *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
 *
 * Thanks to the following companies for their support:
 *
 *     - JMicron (hardware and technical support)
 */

#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
#include <linux/ktime.h>
#include <linux/highmem.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/scatterlist.h>
#include <linux/sizes.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>

#include <linux/leds.h>

#include <linux/mmc/mmc.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/slot-gpio.h>

#include "sdhci.h"

#define DRIVER_NAME

#define DBG(f, x...)

#define SDHCI_DUMP(f, x...)

#define MAX_TUNING_LOOP

static unsigned int debug_quirks =;
static unsigned int debug_quirks2;

static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);

static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd);

void sdhci_dumpregs(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

/*****************************************************************************\
 *                                                                           *
 * Low level functions                                                       *
 *                                                                           *
\*****************************************************************************/

static void sdhci_do_enable_v4_mode(struct sdhci_host *host)
{}

/*
 * This can be called before sdhci_add_host() by Vendor's host controller
 * driver to enable v4 mode if supported.
 */
void sdhci_enable_v4_mode(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

static inline bool sdhci_data_line_cmd(struct mmc_command *cmd)
{}

static void sdhci_set_card_detection(struct sdhci_host *host, bool enable)
{}

static void sdhci_enable_card_detection(struct sdhci_host *host)
{}

static void sdhci_disable_card_detection(struct sdhci_host *host)
{}

static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
{}

static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
{}

void sdhci_reset(struct sdhci_host *host, u8 mask)
{}
EXPORT_SYMBOL_GPL();

static bool sdhci_do_reset(struct sdhci_host *host, u8 mask)
{}

static void sdhci_reset_for_all(struct sdhci_host *host)
{}

enum sdhci_reset_reason {};

static void sdhci_reset_for_reason(struct sdhci_host *host, enum sdhci_reset_reason reason)
{}

#define sdhci_reset_for(h, r)

static void sdhci_set_default_irqs(struct sdhci_host *host)
{}

static void sdhci_config_dma(struct sdhci_host *host)
{}

static void sdhci_init(struct sdhci_host *host, int soft)
{}

static void sdhci_reinit(struct sdhci_host *host)
{}

static void __sdhci_led_activate(struct sdhci_host *host)
{}

static void __sdhci_led_deactivate(struct sdhci_host *host)
{}

#if IS_REACHABLE(CONFIG_LEDS_CLASS)
static void sdhci_led_control(struct led_classdev *led,
			      enum led_brightness brightness)
{}

static int sdhci_led_register(struct sdhci_host *host)
{}

static void sdhci_led_unregister(struct sdhci_host *host)
{}

static inline void sdhci_led_activate(struct sdhci_host *host)
{}

static inline void sdhci_led_deactivate(struct sdhci_host *host)
{}

#else

static inline int sdhci_led_register(struct sdhci_host *host)
{
	return 0;
}

static inline void sdhci_led_unregister(struct sdhci_host *host)
{
}

static inline void sdhci_led_activate(struct sdhci_host *host)
{
	__sdhci_led_activate(host);
}

static inline void sdhci_led_deactivate(struct sdhci_host *host)
{
	__sdhci_led_deactivate(host);
}

#endif

static void sdhci_mod_timer(struct sdhci_host *host, struct mmc_request *mrq,
			    unsigned long timeout)
{}

static void sdhci_del_timer(struct sdhci_host *host, struct mmc_request *mrq)
{}

static inline bool sdhci_has_requests(struct sdhci_host *host)
{}

/*****************************************************************************\
 *                                                                           *
 * Core functions                                                            *
 *                                                                           *
\*****************************************************************************/

static void sdhci_read_block_pio(struct sdhci_host *host)
{}

static void sdhci_write_block_pio(struct sdhci_host *host)
{}

static void sdhci_transfer_pio(struct sdhci_host *host)
{}

static int sdhci_pre_dma_transfer(struct sdhci_host *host,
				  struct mmc_data *data, int cookie)
{}

static char *sdhci_kmap_atomic(struct scatterlist *sg)
{}

static void sdhci_kunmap_atomic(void *buffer)
{}

void sdhci_adma_write_desc(struct sdhci_host *host, void **desc,
			   dma_addr_t addr, int len, unsigned int cmd)
{}
EXPORT_SYMBOL_GPL();

static inline void __sdhci_adma_write_desc(struct sdhci_host *host,
					   void **desc, dma_addr_t addr,
					   int len, unsigned int cmd)
{}

static void sdhci_adma_mark_end(void *desc)
{}

static void sdhci_adma_table_pre(struct sdhci_host *host,
	struct mmc_data *data, int sg_count)
{}

static void sdhci_adma_table_post(struct sdhci_host *host,
	struct mmc_data *data)
{}

static void sdhci_set_adma_addr(struct sdhci_host *host, dma_addr_t addr)
{}

static dma_addr_t sdhci_sdma_address(struct sdhci_host *host)
{}

static void sdhci_set_sdma_addr(struct sdhci_host *host, dma_addr_t addr)
{}

static unsigned int sdhci_target_timeout(struct sdhci_host *host,
					 struct mmc_command *cmd,
					 struct mmc_data *data)
{}

static void sdhci_calc_sw_timeout(struct sdhci_host *host,
				  struct mmc_command *cmd)
{}

static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd,
			     bool *too_big)
{}

static void sdhci_set_transfer_irqs(struct sdhci_host *host)
{}

void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable)
{}
EXPORT_SYMBOL_GPL();

void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
{}
EXPORT_SYMBOL_GPL();

static void sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
{}

static void sdhci_initialize_data(struct sdhci_host *host,
				  struct mmc_data *data)
{}

static inline void sdhci_set_block_info(struct sdhci_host *host,
					struct mmc_data *data)
{}

static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
{}

#if IS_ENABLED(CONFIG_MMC_SDHCI_EXTERNAL_DMA)

static int sdhci_external_dma_init(struct sdhci_host *host)
{}

static struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host,
						   struct mmc_data *data)
{}

static int sdhci_external_dma_setup(struct sdhci_host *host,
				    struct mmc_command *cmd)
{}

static void sdhci_external_dma_release(struct sdhci_host *host)
{}

static void __sdhci_external_dma_prepare_data(struct sdhci_host *host,
					      struct mmc_command *cmd)
{}

static void sdhci_external_dma_prepare_data(struct sdhci_host *host,
					    struct mmc_command *cmd)
{}

static void sdhci_external_dma_pre_transfer(struct sdhci_host *host,
					    struct mmc_command *cmd)
{}

#else

static inline int sdhci_external_dma_init(struct sdhci_host *host)
{
	return -EOPNOTSUPP;
}

static inline void sdhci_external_dma_release(struct sdhci_host *host)
{
}

static inline void sdhci_external_dma_prepare_data(struct sdhci_host *host,
						   struct mmc_command *cmd)
{
	/* This should never happen */
	WARN_ON_ONCE(1);
}

static inline void sdhci_external_dma_pre_transfer(struct sdhci_host *host,
						   struct mmc_command *cmd)
{
}

static inline struct dma_chan *sdhci_external_dma_channel(struct sdhci_host *host,
							  struct mmc_data *data)
{
	return NULL;
}

#endif

void sdhci_switch_external_dma(struct sdhci_host *host, bool en)
{}
EXPORT_SYMBOL_GPL();

static inline bool sdhci_auto_cmd12(struct sdhci_host *host,
				    struct mmc_request *mrq)
{}

static inline bool sdhci_auto_cmd23(struct sdhci_host *host,
				    struct mmc_request *mrq)
{}

static inline bool sdhci_manual_cmd23(struct sdhci_host *host,
				      struct mmc_request *mrq)
{}

static inline void sdhci_auto_cmd_select(struct sdhci_host *host,
					 struct mmc_command *cmd,
					 u16 *mode)
{}

static void sdhci_set_transfer_mode(struct sdhci_host *host,
	struct mmc_command *cmd)
{}

static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)
{}

static void sdhci_set_mrq_done(struct sdhci_host *host, struct mmc_request *mrq)
{}

static void __sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
{}

static void sdhci_finish_mrq(struct sdhci_host *host, struct mmc_request *mrq)
{}

static void __sdhci_finish_data(struct sdhci_host *host, bool sw_data_timeout)
{}

static void sdhci_finish_data(struct sdhci_host *host)
{}

static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
{}

static bool sdhci_present_error(struct sdhci_host *host,
				struct mmc_command *cmd, bool present)
{}

static bool sdhci_send_command_retry(struct sdhci_host *host,
				     struct mmc_command *cmd,
				     unsigned long flags)
	__releases(host->lock)
	__acquires(host->lock)
{}

static void sdhci_read_rsp_136(struct sdhci_host *host, struct mmc_command *cmd)
{}

static void sdhci_finish_command(struct sdhci_host *host)
{}

static u16 sdhci_get_preset_value(struct sdhci_host *host)
{}

u16 sdhci_calc_clk(struct sdhci_host *host, unsigned int clock,
		   unsigned int *actual_clock)
{}
EXPORT_SYMBOL_GPL();

void sdhci_enable_clk(struct sdhci_host *host, u16 clk)
{}
EXPORT_SYMBOL_GPL();

void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
{}
EXPORT_SYMBOL_GPL();

static void sdhci_set_power_reg(struct sdhci_host *host, unsigned char mode,
				unsigned short vdd)
{}

void sdhci_set_power_noreg(struct sdhci_host *host, unsigned char mode,
			   unsigned short vdd)
{}
EXPORT_SYMBOL_GPL();

void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
		     unsigned short vdd)
{}
EXPORT_SYMBOL_GPL();

/*
 * Some controllers need to configure a valid bus voltage on their power
 * register regardless of whether an external regulator is taking care of power
 * supply. This helper function takes care of it if set as the controller's
 * sdhci_ops.set_power callback.
 */
void sdhci_set_power_and_bus_voltage(struct sdhci_host *host,
				     unsigned char mode,
				     unsigned short vdd)
{}
EXPORT_SYMBOL_GPL();

/*****************************************************************************\
 *                                                                           *
 * MMC callbacks                                                             *
 *                                                                           *
\*****************************************************************************/

void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{}
EXPORT_SYMBOL_GPL();

int sdhci_request_atomic(struct mmc_host *mmc, struct mmc_request *mrq)
{}
EXPORT_SYMBOL_GPL();

void sdhci_set_bus_width(struct sdhci_host *host, int width)
{}
EXPORT_SYMBOL_GPL();

void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
{}
EXPORT_SYMBOL_GPL();

static bool sdhci_timing_has_preset(unsigned char timing)
{}

static bool sdhci_preset_needed(struct sdhci_host *host, unsigned char timing)
{}

static bool sdhci_presetable_values_change(struct sdhci_host *host, struct mmc_ios *ios)
{}

void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{}
EXPORT_SYMBOL_GPL();

static int sdhci_get_cd(struct mmc_host *mmc)
{}

int sdhci_get_cd_nogpio(struct mmc_host *mmc)
{}
EXPORT_SYMBOL_GPL();

int sdhci_get_ro(struct mmc_host *mmc)
{}
EXPORT_SYMBOL_GPL();

static void sdhci_hw_reset(struct mmc_host *mmc)
{}

static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable)
{}

void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
{}
EXPORT_SYMBOL_GPL();

static void sdhci_ack_sdio_irq(struct mmc_host *mmc)
{}

int sdhci_start_signal_voltage_switch(struct mmc_host *mmc,
				      struct mmc_ios *ios)
{}
EXPORT_SYMBOL_GPL();

static int sdhci_card_busy(struct mmc_host *mmc)
{}

static int sdhci_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios)
{}

void sdhci_start_tuning(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

void sdhci_end_tuning(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

void sdhci_reset_tuning(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode)
{}
EXPORT_SYMBOL_GPL();

/*
 * We use sdhci_send_tuning() because mmc_send_tuning() is not a good fit. SDHCI
 * tuning command does not have a data payload (or rather the hardware does it
 * automatically) so mmc_send_tuning() will return -EIO. Also the tuning command
 * interrupt setup is different to other commands and there is no timeout
 * interrupt so special handling is needed.
 */
void sdhci_send_tuning(struct sdhci_host *host, u32 opcode)
{}
EXPORT_SYMBOL_GPL();

int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
{}
EXPORT_SYMBOL_GPL();

int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
{}
EXPORT_SYMBOL_GPL();

static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable)
{}

static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
				int err)
{}

static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq)
{}

static void sdhci_error_out_mrqs(struct sdhci_host *host, int err)
{}

static void sdhci_card_event(struct mmc_host *mmc)
{}

static const struct mmc_host_ops sdhci_ops =;

/*****************************************************************************\
 *                                                                           *
 * Request done                                                              *
 *                                                                           *
\*****************************************************************************/

static bool sdhci_request_done(struct sdhci_host *host)
{}

static void sdhci_complete_work(struct work_struct *work)
{}

static void sdhci_timeout_timer(struct timer_list *t)
{}

static void sdhci_timeout_data_timer(struct timer_list *t)
{}

/*****************************************************************************\
 *                                                                           *
 * Interrupt handling                                                        *
 *                                                                           *
\*****************************************************************************/

static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p)
{}

static void sdhci_adma_show_error(struct sdhci_host *host)
{}

static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{}

static inline bool sdhci_defer_done(struct sdhci_host *host,
				    struct mmc_request *mrq)
{}

static irqreturn_t sdhci_irq(int irq, void *dev_id)
{}

static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
{}

/*****************************************************************************\
 *                                                                           *
 * Suspend/resume                                                            *
 *                                                                           *
\*****************************************************************************/

#ifdef CONFIG_PM

static bool sdhci_cd_irq_can_wakeup(struct sdhci_host *host)
{}

/*
 * To enable wakeup events, the corresponding events have to be enabled in
 * the Interrupt Status Enable register too. See 'Table 1-6: Wakeup Signal
 * Table' in the SD Host Controller Standard Specification.
 * It is useless to restore SDHCI_INT_ENABLE state in
 * sdhci_disable_irq_wakeups() since it will be set by
 * sdhci_enable_card_detection() or sdhci_init().
 */
static bool sdhci_enable_irq_wakeups(struct sdhci_host *host)
{}

static void sdhci_disable_irq_wakeups(struct sdhci_host *host)
{}

int sdhci_suspend_host(struct sdhci_host *host)
{}

EXPORT_SYMBOL_GPL();

int sdhci_resume_host(struct sdhci_host *host)
{}

EXPORT_SYMBOL_GPL();

int sdhci_runtime_suspend_host(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

int sdhci_runtime_resume_host(struct sdhci_host *host, int soft_reset)
{}
EXPORT_SYMBOL_GPL();

#endif /* CONFIG_PM */

/*****************************************************************************\
 *                                                                           *
 * Command Queue Engine (CQE) helpers                                        *
 *                                                                           *
\*****************************************************************************/

void sdhci_cqe_enable(struct mmc_host *mmc)
{}
EXPORT_SYMBOL_GPL();

void sdhci_cqe_disable(struct mmc_host *mmc, bool recovery)
{}
EXPORT_SYMBOL_GPL();

bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error,
		   int *data_error)
{}
EXPORT_SYMBOL_GPL();

/*****************************************************************************\
 *                                                                           *
 * Device allocation/registration                                            *
 *                                                                           *
\*****************************************************************************/

struct sdhci_host *sdhci_alloc_host(struct device *dev,
	size_t priv_size)
{}

EXPORT_SYMBOL_GPL();

static int sdhci_set_dma_mask(struct sdhci_host *host)
{}

void __sdhci_read_caps(struct sdhci_host *host, const u16 *ver,
		       const u32 *caps, const u32 *caps1)
{}
EXPORT_SYMBOL_GPL();

static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
{}

static inline bool sdhci_can_64bit_dma(struct sdhci_host *host)
{}

int sdhci_setup_host(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

void sdhci_cleanup_host(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

int __sdhci_add_host(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

int sdhci_add_host(struct sdhci_host *host)
{}
EXPORT_SYMBOL_GPL();

void sdhci_remove_host(struct sdhci_host *host, int dead)
{}

EXPORT_SYMBOL_GPL();

void sdhci_free_host(struct sdhci_host *host)
{}

EXPORT_SYMBOL_GPL();

/*****************************************************************************\
 *                                                                           *
 * Driver init/exit                                                          *
 *                                                                           *
\*****************************************************************************/

static int __init sdhci_drv_init(void)
{}

static void __exit sdhci_drv_exit(void)
{}

module_init();
module_exit(sdhci_drv_exit);

module_param(debug_quirks, uint, 0444);
module_param(debug_quirks2, uint, 0444);

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

MODULE_PARM_DESC();
MODULE_PARM_DESC();