linux/drivers/mmc/host/sdhci-msm.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * drivers/mmc/host/sdhci-msm.c - Qualcomm SDHCI Platform driver
 *
 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mmc/mmc.h>
#include <linux/pm_runtime.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
#include <linux/iopoll.h>
#include <linux/regulator/consumer.h>
#include <linux/interconnect.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/reset.h>

#include <soc/qcom/ice.h>

#include "sdhci-cqhci.h"
#include "sdhci-pltfm.h"
#include "cqhci.h"

#define CORE_MCI_VERSION
#define CORE_VERSION_MAJOR_SHIFT
#define CORE_VERSION_MAJOR_MASK
#define CORE_VERSION_MINOR_MASK

#define CORE_MCI_GENERICS
#define SWITCHABLE_SIGNALING_VOLTAGE

#define HC_MODE_EN
#define CORE_POWER
#define CORE_SW_RST
#define FF_CLK_SW_RST_DIS

#define CORE_PWRCTL_BUS_OFF
#define CORE_PWRCTL_BUS_ON
#define CORE_PWRCTL_IO_LOW
#define CORE_PWRCTL_IO_HIGH
#define CORE_PWRCTL_BUS_SUCCESS
#define CORE_PWRCTL_BUS_FAIL
#define CORE_PWRCTL_IO_SUCCESS
#define CORE_PWRCTL_IO_FAIL
#define REQ_BUS_OFF
#define REQ_BUS_ON
#define REQ_IO_LOW
#define REQ_IO_HIGH
#define INT_MASK
#define MAX_PHASES
#define CORE_DLL_LOCK
#define CORE_DDR_DLL_LOCK
#define CORE_DLL_EN
#define CORE_CDR_EN
#define CORE_CK_OUT_EN
#define CORE_CDR_EXT_EN
#define CORE_DLL_PDN
#define CORE_DLL_RST
#define CORE_CMD_DAT_TRACK_SEL

#define CORE_DDR_CAL_EN
#define CORE_FLL_CYCLE_CNT
#define CORE_DLL_CLOCK_DISABLE

#define DLL_USR_CTL_POR_VAL
#define ENABLE_DLL_LOCK_STATUS
#define FINE_TUNE_MODE_EN
#define BIAS_OK_SIGNAL

#define DLL_CONFIG_3_LOW_FREQ_VAL
#define DLL_CONFIG_3_HIGH_FREQ_VAL

#define CORE_VENDOR_SPEC_POR_VAL
#define CORE_CLK_PWRSAVE
#define CORE_HC_MCLK_SEL_DFLT
#define CORE_HC_MCLK_SEL_HS400
#define CORE_HC_MCLK_SEL_MASK
#define CORE_IO_PAD_PWR_SWITCH_EN
#define CORE_IO_PAD_PWR_SWITCH
#define CORE_HC_SELECT_IN_EN
#define CORE_HC_SELECT_IN_HS400
#define CORE_HC_SELECT_IN_MASK

#define CORE_3_0V_SUPPORT
#define CORE_1_8V_SUPPORT
#define CORE_VOLT_SUPPORT

#define CORE_CSR_CDC_CTLR_CFG0
#define CORE_SW_TRIG_FULL_CALIB
#define CORE_HW_AUTOCAL_ENA

#define CORE_CSR_CDC_CTLR_CFG1
#define CORE_CSR_CDC_CAL_TIMER_CFG0
#define CORE_TIMER_ENA

#define CORE_CSR_CDC_CAL_TIMER_CFG1
#define CORE_CSR_CDC_REFCOUNT_CFG
#define CORE_CSR_CDC_COARSE_CAL_CFG
#define CORE_CDC_OFFSET_CFG
#define CORE_CSR_CDC_DELAY_CFG
#define CORE_CDC_SLAVE_DDA_CFG
#define CORE_CSR_CDC_STATUS0
#define CORE_CALIBRATION_DONE

#define CORE_CDC_ERROR_CODE_MASK

#define CORE_CSR_CDC_GEN_CFG
#define CORE_CDC_SWITCH_BYPASS_OFF
#define CORE_CDC_SWITCH_RC_EN

#define CORE_CDC_T4_DLY_SEL
#define CORE_CMDIN_RCLK_EN
#define CORE_START_CDC_TRAFFIC

#define CORE_PWRSAVE_DLL

#define DDR_CONFIG_POR_VAL


#define INVALID_TUNING_PHASE
#define SDHCI_MSM_MIN_CLOCK
#define CORE_FREQ_100MHZ

#define CDR_SELEXT_SHIFT
#define CDR_SELEXT_MASK
#define CMUX_SHIFT_PHASE_SHIFT
#define CMUX_SHIFT_PHASE_MASK

#define MSM_MMC_AUTOSUSPEND_DELAY_MS

/* Timeout value to avoid infinite waiting for pwr_irq */
#define MSM_PWR_IRQ_TIMEOUT_MS

/* Max load for eMMC Vdd-io supply */
#define MMC_VQMMC_MAX_LOAD_UA

#define msm_host_readl(msm_host, host, offset)

#define msm_host_writel(msm_host, val, host, offset)

/* CQHCI vendor specific registers */
#define CQHCI_VENDOR_CFG1
#define CQHCI_VENDOR_DIS_RST_ON_CQ_EN

struct sdhci_msm_offset {};

static const struct sdhci_msm_offset sdhci_msm_v5_offset =;

static const struct sdhci_msm_offset sdhci_msm_mci_offset =;

struct sdhci_msm_variant_ops {};

/*
 * From V5, register spaces have changed. Wrap this info in a structure
 * and choose the data_structure based on version info mentioned in DT.
 */
struct sdhci_msm_variant_info {};

struct sdhci_msm_host {};

static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
{}

/*
 * APIs to read/write to vendor specific registers which were there in the
 * core_mem region before MCI was removed.
 */
static u32 sdhci_msm_mci_variant_readl_relaxed(struct sdhci_host *host,
		u32 offset)
{}

static u32 sdhci_msm_v5_variant_readl_relaxed(struct sdhci_host *host,
		u32 offset)
{}

static void sdhci_msm_mci_variant_writel_relaxed(u32 val,
		struct sdhci_host *host, u32 offset)
{}

static void sdhci_msm_v5_variant_writel_relaxed(u32 val,
		struct sdhci_host *host, u32 offset)
{}

static unsigned int msm_get_clock_mult_for_bus_mode(struct sdhci_host *host)
{}

static void msm_set_clock_rate_for_bus_mode(struct sdhci_host *host,
					    unsigned int clock)
{}

/* Platform specific tuning */
static inline int msm_dll_poll_ck_out_en(struct sdhci_host *host, u8 poll)
{}

static int msm_config_cm_dll_phase(struct sdhci_host *host, u8 phase)
{}

/*
 * Find out the greatest range of consecuitive selected
 * DLL clock output phases that can be used as sampling
 * setting for SD3.0 UHS-I card read operation (in SDR104
 * timing mode) or for eMMC4.5 card read operation (in
 * HS400/HS200 timing mode).
 * Select the 3/4 of the range and configure the DLL with the
 * selected DLL clock output phase.
 */

static int msm_find_most_appropriate_phase(struct sdhci_host *host,
					   u8 *phase_table, u8 total_phases)
{}

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

/* Initialize the DLL (Programmable Delay Line) */
static int msm_init_cm_dll(struct sdhci_host *host)
{}

static void msm_hc_select_default(struct sdhci_host *host)
{}

static void msm_hc_select_hs400(struct sdhci_host *host)
{}

/*
 * sdhci_msm_hc_select_mode :- In general all timing modes are
 * controlled via UHS mode select in Host Control2 register.
 * eMMC specific HS200/HS400 doesn't have their respective modes
 * defined here, hence we use these values.
 *
 * HS200 - SDR104 (Since they both are equivalent in functionality)
 * HS400 - This involves multiple configurations
 *		Initially SDR104 - when tuning is required as HS200
 *		Then when switching to DDR @ 400MHz (HS400) we use
 *		the vendor specific HC_SELECT_IN to control the mode.
 *
 * In addition to controlling the modes we also need to select the
 * correct input clock for DLL depending on the mode.
 *
 * HS400 - divided clock (free running MCLK/2)
 * All other modes - default (free running MCLK)
 */
static void sdhci_msm_hc_select_mode(struct sdhci_host *host)
{}

static int sdhci_msm_cdclp533_calibration(struct sdhci_host *host)
{}

static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
{}

static int sdhci_msm_hs400_dll_calibration(struct sdhci_host *host)
{}

static bool sdhci_msm_is_tuning_needed(struct sdhci_host *host)
{}

static int sdhci_msm_restore_sdr_dll_config(struct sdhci_host *host)
{}

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

static int sdhci_msm_execute_tuning(struct mmc_host *mmc, u32 opcode)
{}

/*
 * sdhci_msm_hs400 - Calibrate the DLL for HS400 bus speed mode operation.
 * This needs to be done for both tuning and enhanced_strobe mode.
 * DLL operation is only needed for clock > 100MHz. For clock <= 100MHz
 * fixed feedback clock is used.
 */
static void sdhci_msm_hs400(struct sdhci_host *host, struct mmc_ios *ios)
{}

static void sdhci_msm_set_uhs_signaling(struct sdhci_host *host,
					unsigned int uhs)
{}

static int sdhci_msm_set_pincfg(struct sdhci_msm_host *msm_host, bool level)
{}

static int sdhci_msm_set_vmmc(struct mmc_host *mmc)
{}

static int msm_toggle_vqmmc(struct sdhci_msm_host *msm_host,
			      struct mmc_host *mmc, bool level)
{}

static int msm_config_vqmmc_mode(struct sdhci_msm_host *msm_host,
			      struct mmc_host *mmc, bool hpm)
{}

static int sdhci_msm_set_vqmmc(struct sdhci_msm_host *msm_host,
			      struct mmc_host *mmc, bool level)
{}

static inline void sdhci_msm_init_pwr_irq_wait(struct sdhci_msm_host *msm_host)
{}

static inline void sdhci_msm_complete_pwr_irq_wait(
		struct sdhci_msm_host *msm_host)
{}

/*
 * sdhci_msm_check_power_status API should be called when registers writes
 * which can toggle sdhci IO bus ON/OFF or change IO lines HIGH/LOW happens.
 * To what state the register writes will change the IO lines should be passed
 * as the argument req_type. This API will check whether the IO line's state
 * is already the expected state and will wait for power irq only if
 * power irq is expected to be triggered based on the current IO line state
 * and expected IO line state.
 */
static void sdhci_msm_check_power_status(struct sdhci_host *host, u32 req_type)
{}

static void sdhci_msm_dump_pwr_ctrl_regs(struct sdhci_host *host)
{}

static void sdhci_msm_handle_pwr_irq(struct sdhci_host *host, int irq)
{}

static irqreturn_t sdhci_msm_pwr_irq(int irq, void *data)
{}

static unsigned int sdhci_msm_get_max_clock(struct sdhci_host *host)
{}

static unsigned int sdhci_msm_get_min_clock(struct sdhci_host *host)
{}

/*
 * __sdhci_msm_set_clock - sdhci_msm clock control.
 *
 * Description:
 * MSM controller does not use internal divider and
 * instead directly control the GCC clock as per
 * HW recommendation.
 **/
static void __sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
{}

/* sdhci_msm_set_clock - Called with (host->lock) spinlock held. */
static void sdhci_msm_set_clock(struct sdhci_host *host, unsigned int clock)
{}

/*****************************************************************************\
 *                                                                           *
 * Inline Crypto Engine (ICE) support                                        *
 *                                                                           *
\*****************************************************************************/

#ifdef CONFIG_MMC_CRYPTO

static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
			      struct cqhci_host *cq_host)
{}

static void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host)
{}

static __maybe_unused int sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host)
{}

static __maybe_unused int sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
{}

/*
 * Program a key into a QC ICE keyslot, or evict a keyslot.  QC ICE requires
 * vendor-specific SCM calls for this; it doesn't support the standard way.
 */
static int sdhci_msm_program_key(struct cqhci_host *cq_host,
				 const union cqhci_crypto_cfg_entry *cfg,
				 int slot)
{}

#else /* CONFIG_MMC_CRYPTO */

static inline int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
				     struct cqhci_host *cq_host)
{
	return 0;
}

static inline void sdhci_msm_ice_enable(struct sdhci_msm_host *msm_host)
{
}

static inline __maybe_unused int
sdhci_msm_ice_resume(struct sdhci_msm_host *msm_host)
{
	return 0;
}

static inline __maybe_unused int
sdhci_msm_ice_suspend(struct sdhci_msm_host *msm_host)
{
	return 0;
}
#endif /* !CONFIG_MMC_CRYPTO */

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

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

static void sdhci_msm_cqe_enable(struct mmc_host *mmc)
{}

static void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery)
{}

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

static const struct cqhci_host_ops sdhci_msm_cqhci_ops =;

static int sdhci_msm_cqe_add_host(struct sdhci_host *host,
				struct platform_device *pdev)
{}

/*
 * Platform specific register write functions. This is so that, if any
 * register write needs to be followed up by platform specific actions,
 * they can be added here. These functions can go to sleep when writes
 * to certain registers are done.
 * These functions are relying on sdhci_set_ios not using spinlock.
 */
static int __sdhci_msm_check_write(struct sdhci_host *host, u16 val, int reg)
{}

/* This function may sleep*/
static void sdhci_msm_writew(struct sdhci_host *host, u16 val, int reg)
{}

/* This function may sleep*/
static void sdhci_msm_writeb(struct sdhci_host *host, u8 val, int reg)
{}

static void sdhci_msm_set_regulator_caps(struct sdhci_msm_host *msm_host)
{}

static int sdhci_msm_register_vreg(struct sdhci_msm_host *msm_host)
{}

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

#define DRIVER_NAME
#define SDHCI_MSM_DUMP(f, x...)

static void sdhci_msm_dump_vendor_regs(struct sdhci_host *host)
{}

static const struct sdhci_msm_variant_ops mci_var_ops =;

static const struct sdhci_msm_variant_ops v5_var_ops =;

static const struct sdhci_msm_variant_info sdhci_msm_mci_var =;

static const struct sdhci_msm_variant_info sdhci_msm_v5_var =;

static const struct sdhci_msm_variant_info sdm845_sdhci_var =;

static const struct of_device_id sdhci_msm_dt_match[] =;

MODULE_DEVICE_TABLE(of, sdhci_msm_dt_match);

static const struct sdhci_ops sdhci_msm_ops =;

static const struct sdhci_pltfm_data sdhci_msm_pdata =;

static inline void sdhci_msm_get_of_property(struct platform_device *pdev,
		struct sdhci_host *host)
{}

static int sdhci_msm_gcc_reset(struct device *dev, struct sdhci_host *host)
{}

static int sdhci_msm_probe(struct platform_device *pdev)
{}

static void sdhci_msm_remove(struct platform_device *pdev)
{}

static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev)
{}

static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
{}

static const struct dev_pm_ops sdhci_msm_pm_ops =;

static struct platform_driver sdhci_msm_driver =;

module_platform_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();