linux/drivers/mmc/host/sdhci-of-arasan.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Arasan Secure Digital Host Controller Interface.
 * Copyright (C) 2011 - 2012 Michal Simek <[email protected]>
 * Copyright (c) 2012 Wind River Systems, Inc.
 * Copyright (C) 2013 Pengutronix e.K.
 * Copyright (C) 2013 Xilinx Inc.
 *
 * Based on sdhci-of-esdhc.c
 *
 * Copyright (c) 2007 Freescale Semiconductor, Inc.
 * Copyright (c) 2009 MontaVista Software, Inc.
 *
 * Authors: Xiaobo Xie <[email protected]>
 *	    Anton Vorontsov <[email protected]>
 */

#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/firmware/xlnx-zynqmp.h>

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

#define SDHCI_ARASAN_VENDOR_REGISTER

#define SDHCI_ARASAN_ITAPDLY_REGISTER
#define SDHCI_ARASAN_ITAPDLY_SEL_MASK

#define SDHCI_ARASAN_OTAPDLY_REGISTER
#define SDHCI_ARASAN_OTAPDLY_SEL_MASK

#define SDHCI_ARASAN_CQE_BASE_ADDR
#define VENDOR_ENHANCED_STROBE

#define PHY_CLK_TOO_SLOW_HZ
#define MIN_PHY_CLK_HZ

#define SDHCI_ITAPDLY_CHGWIN
#define SDHCI_ITAPDLY_ENABLE
#define SDHCI_OTAPDLY_ENABLE

#define PHY_CTRL_REG1
#define PHY_CTRL_ITAPDLY_ENA_MASK
#define PHY_CTRL_ITAPDLY_SEL_MASK
#define PHY_CTRL_ITAPDLY_SEL_SHIFT
#define PHY_CTRL_ITAP_CHG_WIN_MASK
#define PHY_CTRL_OTAPDLY_ENA_MASK
#define PHY_CTRL_OTAPDLY_SEL_MASK
#define PHY_CTRL_OTAPDLY_SEL_SHIFT
#define PHY_CTRL_STRB_SEL_MASK
#define PHY_CTRL_STRB_SEL_SHIFT
#define PHY_CTRL_TEST_CTRL_MASK

#define PHY_CTRL_REG2
#define PHY_CTRL_EN_DLL_MASK
#define PHY_CTRL_DLL_RDY_MASK
#define PHY_CTRL_FREQ_SEL_MASK
#define PHY_CTRL_FREQ_SEL_SHIFT
#define PHY_CTRL_SEL_DLY_TX_MASK
#define PHY_CTRL_SEL_DLY_RX_MASK
#define FREQSEL_200M_170M
#define FREQSEL_170M_140M
#define FREQSEL_140M_110M
#define FREQSEL_110M_80M
#define FREQSEL_80M_50M
#define FREQSEL_275M_250M
#define FREQSEL_250M_225M
#define FREQSEL_225M_200M
#define PHY_DLL_TIMEOUT_MS

/* Default settings for ZynqMP Clock Phases */
#define ZYNQMP_ICLK_PHASE
#define ZYNQMP_OCLK_PHASE

#define VERSAL_ICLK_PHASE
#define VERSAL_OCLK_PHASE

#define VERSAL_NET_EMMC_ICLK_PHASE
#define VERSAL_NET_EMMC_OCLK_PHASE

#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL

/*
 * On some SoCs the syscon area has a feature where the upper 16-bits of
 * each 32-bit register act as a write mask for the lower 16-bits.  This allows
 * atomic updates of the register without locking.  This macro is used on SoCs
 * that have that feature.
 */
#define HIWORD_UPDATE(val, mask, shift)

/**
 * struct sdhci_arasan_soc_ctl_field - Field used in sdhci_arasan_soc_ctl_map
 *
 * @reg:	Offset within the syscon of the register containing this field
 * @width:	Number of bits for this field
 * @shift:	Bit offset within @reg of this field (or -1 if not avail)
 */
struct sdhci_arasan_soc_ctl_field {};

/**
 * struct sdhci_arasan_soc_ctl_map - Map in syscon to corecfg registers
 *
 * @baseclkfreq:	Where to find corecfg_baseclkfreq
 * @clockmultiplier:	Where to find corecfg_clockmultiplier
 * @support64b:		Where to find SUPPORT64B bit
 * @hiword_update:	If true, use HIWORD_UPDATE to access the syscon
 *
 * It's up to the licensee of the Arsan IP block to make these available
 * somewhere if needed.  Presumably these will be scattered somewhere that's
 * accessible via the syscon API.
 */
struct sdhci_arasan_soc_ctl_map {};

/**
 * struct sdhci_arasan_clk_ops - Clock Operations for Arasan SD controller
 *
 * @sdcardclk_ops:	The output clock related operations
 * @sampleclk_ops:	The sample clock related operations
 */
struct sdhci_arasan_clk_ops {};

/**
 * struct sdhci_arasan_clk_data - Arasan Controller Clock Data.
 *
 * @sdcardclk_hw:	Struct for the clock we might provide to a PHY.
 * @sdcardclk:		Pointer to normal 'struct clock' for sdcardclk_hw.
 * @sampleclk_hw:	Struct for the clock we might provide to a PHY.
 * @sampleclk:		Pointer to normal 'struct clock' for sampleclk_hw.
 * @clk_phase_in:	Array of Input Clock Phase Delays for all speed modes
 * @clk_phase_out:	Array of Output Clock Phase Delays for all speed modes
 * @set_clk_delays:	Function pointer for setting Clock Delays
 * @clk_of_data:	Platform specific runtime clock data storage pointer
 */
struct sdhci_arasan_clk_data {};

/**
 * struct sdhci_arasan_data - Arasan Controller Data
 *
 * @host:		Pointer to the main SDHCI host structure.
 * @clk_ahb:		Pointer to the AHB clock
 * @phy:		Pointer to the generic phy
 * @is_phy_on:		True if the PHY is on; false if not.
 * @internal_phy_reg:	True if the PHY is within the Host controller.
 * @has_cqe:		True if controller has command queuing engine.
 * @clk_data:		Struct for the Arasan Controller Clock Data.
 * @clk_ops:		Struct for the Arasan Controller Clock Operations.
 * @soc_ctl_base:	Pointer to regmap for syscon for soc_ctl registers.
 * @soc_ctl_map:	Map to get offsets into soc_ctl registers.
 * @quirks:		Arasan deviations from spec.
 */
struct sdhci_arasan_data {};

struct sdhci_arasan_of_data {};

static const struct sdhci_arasan_soc_ctl_map rk3399_soc_ctl_map =;

static const struct sdhci_arasan_soc_ctl_map intel_lgm_emmc_soc_ctl_map =;

static const struct sdhci_arasan_soc_ctl_map intel_lgm_sdxc_soc_ctl_map =;

static const struct sdhci_arasan_soc_ctl_map intel_keembay_soc_ctl_map =;

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

static int sdhci_arasan_phy_set_dll(struct sdhci_host *host, bool enable)
{}

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

/**
 * sdhci_arasan_syscon_write - Write to a field in soc_ctl registers
 *
 * @host:	The sdhci_host
 * @fld:	The field to write to
 * @val:	The value to write
 *
 * This function allows writing to fields in sdhci_arasan_soc_ctl_map.
 * Note that if a field is specified as not available (shift < 0) then
 * this function will silently return an error code.  It will be noisy
 * and print errors for any other (unexpected) errors.
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_arasan_syscon_write(struct sdhci_host *host,
				   const struct sdhci_arasan_soc_ctl_field *fld,
				   u32 val)
{}

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

static void sdhci_arasan_hs400_enhanced_strobe(struct mmc_host *mmc,
					struct mmc_ios *ios)
{}

static void sdhci_arasan_reset(struct sdhci_host *host, u8 mask)
{}

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

static const struct sdhci_ops sdhci_arasan_ops =;

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

static void sdhci_arasan_dumpregs(struct mmc_host *mmc)
{}

static void sdhci_arasan_cqe_enable(struct mmc_host *mmc)
{}

static const struct cqhci_host_ops sdhci_arasan_cqhci_ops =;

static const struct sdhci_ops sdhci_arasan_cqe_ops =;

static const struct sdhci_pltfm_data sdhci_arasan_cqe_pdata =;

#ifdef CONFIG_PM_SLEEP
/**
 * sdhci_arasan_suspend - Suspend method for the driver
 * @dev:	Address of the device structure
 *
 * Put the device in a low power state.
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_arasan_suspend(struct device *dev)
{}

/**
 * sdhci_arasan_resume - Resume method for the driver
 * @dev:	Address of the device structure
 *
 * Resume operation after suspend
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_arasan_resume(struct device *dev)
{}
#endif /* ! CONFIG_PM_SLEEP */

static SIMPLE_DEV_PM_OPS(sdhci_arasan_dev_pm_ops, sdhci_arasan_suspend,
			 sdhci_arasan_resume);

/**
 * sdhci_arasan_sdcardclk_recalc_rate - Return the card clock rate
 *
 * @hw:			Pointer to the hardware clock structure.
 * @parent_rate:		The parent rate (should be rate of clk_xin).
 *
 * Return the current actual rate of the SD card clock.  This can be used
 * to communicate with out PHY.
 *
 * Return: The card clock rate.
 */
static unsigned long sdhci_arasan_sdcardclk_recalc_rate(struct clk_hw *hw,
						      unsigned long parent_rate)
{}

static const struct clk_ops arasan_sdcardclk_ops =;

/**
 * sdhci_arasan_sampleclk_recalc_rate - Return the sampling clock rate
 *
 * @hw:			Pointer to the hardware clock structure.
 * @parent_rate:		The parent rate (should be rate of clk_xin).
 *
 * Return the current actual rate of the sampling clock.  This can be used
 * to communicate with out PHY.
 *
 * Return: The sample clock rate.
 */
static unsigned long sdhci_arasan_sampleclk_recalc_rate(struct clk_hw *hw,
						      unsigned long parent_rate)
{}

static const struct clk_ops arasan_sampleclk_ops =;

/**
 * sdhci_zynqmp_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
 *
 * @hw:			Pointer to the hardware clock structure.
 * @degrees:		The clock phase shift between 0 - 359.
 *
 * Set the SD Output Clock Tap Delays for Output path
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_zynqmp_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
{}

static const struct clk_ops zynqmp_sdcardclk_ops =;

/**
 * sdhci_zynqmp_sampleclk_set_phase - Set the SD Input Clock Tap Delays
 *
 * @hw:			Pointer to the hardware clock structure.
 * @degrees:		The clock phase shift between 0 - 359.
 *
 * Set the SD Input Clock Tap Delays for Input path
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_zynqmp_sampleclk_set_phase(struct clk_hw *hw, int degrees)
{}

static const struct clk_ops zynqmp_sampleclk_ops =;

/**
 * sdhci_versal_sdcardclk_set_phase - Set the SD Output Clock Tap Delays
 *
 * @hw:			Pointer to the hardware clock structure.
 * @degrees:		The clock phase shift between 0 - 359.
 *
 * Set the SD Output Clock Tap Delays for Output path
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_versal_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
{}

static const struct clk_ops versal_sdcardclk_ops =;

/**
 * sdhci_versal_sampleclk_set_phase - Set the SD Input Clock Tap Delays
 *
 * @hw:			Pointer to the hardware clock structure.
 * @degrees:		The clock phase shift between 0 - 359.
 *
 * Set the SD Input Clock Tap Delays for Input path
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_versal_sampleclk_set_phase(struct clk_hw *hw, int degrees)
{}

static const struct clk_ops versal_sampleclk_ops =;

static int sdhci_versal_net_emmc_sdcardclk_set_phase(struct clk_hw *hw, int degrees)
{}

static const struct clk_ops versal_net_sdcardclk_ops =;

static int sdhci_versal_net_emmc_sampleclk_set_phase(struct clk_hw *hw, int degrees)
{}

static const struct clk_ops versal_net_sampleclk_ops =;

static void arasan_zynqmp_dll_reset(struct sdhci_host *host, u32 deviceid)
{}

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

/**
 * sdhci_arasan_update_clockmultiplier - Set corecfg_clockmultiplier
 *
 * @host:		The sdhci_host
 * @value:		The value to write
 *
 * The corecfg_clockmultiplier is supposed to contain clock multiplier
 * value of programmable clock generator.
 *
 * NOTES:
 * - Many existing devices don't seem to do this and work fine.  To keep
 *   compatibility for old hardware where the device tree doesn't provide a
 *   register map, this function is a noop if a soc_ctl_map hasn't been provided
 *   for this platform.
 * - The value of corecfg_clockmultiplier should sync with that of corresponding
 *   value reading from sdhci_capability_register. So this function is called
 *   once at probe time and never called again.
 */
static void sdhci_arasan_update_clockmultiplier(struct sdhci_host *host,
						u32 value)
{}

/**
 * sdhci_arasan_update_baseclkfreq - Set corecfg_baseclkfreq
 *
 * @host:		The sdhci_host
 *
 * The corecfg_baseclkfreq is supposed to contain the MHz of clk_xin.  This
 * function can be used to make that happen.
 *
 * NOTES:
 * - Many existing devices don't seem to do this and work fine.  To keep
 *   compatibility for old hardware where the device tree doesn't provide a
 *   register map, this function is a noop if a soc_ctl_map hasn't been provided
 *   for this platform.
 * - It's assumed that clk_xin is not dynamic and that we use the SDHCI divider
 *   to achieve lower clock rates.  That means that this function is called once
 *   at probe time and never called again.
 */
static void sdhci_arasan_update_baseclkfreq(struct sdhci_host *host)
{}

static void sdhci_arasan_set_clk_delays(struct sdhci_host *host)
{}

static void arasan_dt_read_clk_phase(struct device *dev,
				     struct sdhci_arasan_clk_data *clk_data,
				     unsigned int timing, const char *prop)
{}

/**
 * arasan_dt_parse_clk_phases - Read Clock Delay values from DT
 *
 * @dev:		Pointer to our struct device.
 * @clk_data:		Pointer to the Clock Data structure
 *
 * Called at initialization to parse the values of Clock Delays.
 */
static void arasan_dt_parse_clk_phases(struct device *dev,
				       struct sdhci_arasan_clk_data *clk_data)
{}

static const struct sdhci_pltfm_data sdhci_arasan_pdata =;

static const struct sdhci_arasan_clk_ops arasan_clk_ops =;

static struct sdhci_arasan_of_data sdhci_arasan_generic_data =;

static const struct sdhci_pltfm_data sdhci_keembay_emmc_pdata =;

static const struct sdhci_pltfm_data sdhci_keembay_sd_pdata =;

static const struct sdhci_pltfm_data sdhci_keembay_sdio_pdata =;

static struct sdhci_arasan_of_data sdhci_arasan_rk3399_data =;

static struct sdhci_arasan_of_data intel_lgm_emmc_data =;

static struct sdhci_arasan_of_data intel_lgm_sdxc_data =;

static const struct sdhci_pltfm_data sdhci_arasan_zynqmp_pdata =;

static const struct sdhci_pltfm_data sdhci_arasan_versal_net_pdata =;

static const struct sdhci_arasan_clk_ops zynqmp_clk_ops =;

static struct sdhci_arasan_of_data sdhci_arasan_zynqmp_data =;

static const struct sdhci_arasan_clk_ops versal_clk_ops =;

static struct sdhci_arasan_of_data sdhci_arasan_versal_data =;

static const struct sdhci_arasan_clk_ops versal_net_clk_ops =;

static struct sdhci_arasan_of_data sdhci_arasan_versal_net_data =;

static struct sdhci_arasan_of_data intel_keembay_emmc_data =;

static struct sdhci_arasan_of_data intel_keembay_sd_data =;

static struct sdhci_arasan_of_data intel_keembay_sdio_data =;

static const struct of_device_id sdhci_arasan_of_match[] =;
MODULE_DEVICE_TABLE(of, sdhci_arasan_of_match);

/**
 * sdhci_arasan_register_sdcardclk - Register the sdcardclk for a PHY to use
 *
 * @sdhci_arasan:	Our private data structure.
 * @clk_xin:		Pointer to the functional clock
 * @dev:		Pointer to our struct device.
 *
 * Some PHY devices need to know what the actual card clock is.  In order for
 * them to find out, we'll provide a clock through the common clock framework
 * for them to query.
 *
 * Return: 0 on success and error value on error
 */
static int
sdhci_arasan_register_sdcardclk(struct sdhci_arasan_data *sdhci_arasan,
				struct clk *clk_xin,
				struct device *dev)
{}

/**
 * sdhci_arasan_register_sampleclk - Register the sampleclk for a PHY to use
 *
 * @sdhci_arasan:	Our private data structure.
 * @clk_xin:		Pointer to the functional clock
 * @dev:		Pointer to our struct device.
 *
 * Some PHY devices need to know what the actual card clock is.  In order for
 * them to find out, we'll provide a clock through the common clock framework
 * for them to query.
 *
 * Return: 0 on success and error value on error
 */
static int
sdhci_arasan_register_sampleclk(struct sdhci_arasan_data *sdhci_arasan,
				struct clk *clk_xin,
				struct device *dev)
{}

/**
 * sdhci_arasan_unregister_sdclk - Undoes sdhci_arasan_register_sdclk()
 *
 * @dev:		Pointer to our struct device.
 *
 * Should be called any time we're exiting and sdhci_arasan_register_sdclk()
 * returned success.
 */
static void sdhci_arasan_unregister_sdclk(struct device *dev)
{}

/**
 * sdhci_arasan_update_support64b - Set SUPPORT_64B (64-bit System Bus Support)
 * @host:		The sdhci_host
 * @value:		The value to write
 *
 * This should be set based on the System Address Bus.
 * 0: the Core supports only 32-bit System Address Bus.
 * 1: the Core supports 64-bit System Address Bus.
 *
 * NOTE:
 * For Keem Bay, it is required to clear this bit. Its default value is 1'b1.
 * Keem Bay does not support 64-bit access.
 */
static void sdhci_arasan_update_support64b(struct sdhci_host *host, u32 value)
{}

/**
 * sdhci_arasan_register_sdclk - Register the sdcardclk for a PHY to use
 *
 * @sdhci_arasan:	Our private data structure.
 * @clk_xin:		Pointer to the functional clock
 * @dev:		Pointer to our struct device.
 *
 * Some PHY devices need to know what the actual card clock is.  In order for
 * them to find out, we'll provide a clock through the common clock framework
 * for them to query.
 *
 * Note: without seriously re-architecting SDHCI's clock code and testing on
 * all platforms, there's no way to create a totally beautiful clock here
 * with all clock ops implemented.  Instead, we'll just create a clock that can
 * be queried and set the CLK_GET_RATE_NOCACHE attribute to tell common clock
 * framework that we're doing things behind its back.  This should be sufficient
 * to create nice clean device tree bindings and later (if needed) we can try
 * re-architecting SDHCI if we see some benefit to it.
 *
 * Return: 0 on success and error value on error
 */
static int sdhci_arasan_register_sdclk(struct sdhci_arasan_data *sdhci_arasan,
				       struct clk *clk_xin,
				       struct device *dev)
{}

static int sdhci_zynqmp_set_dynamic_config(struct device *dev,
					   struct sdhci_arasan_data *sdhci_arasan)
{}

static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan)
{}

static int sdhci_arasan_probe(struct platform_device *pdev)
{}

static void sdhci_arasan_remove(struct platform_device *pdev)
{}

static struct platform_driver sdhci_arasan_driver =;

module_platform_driver();

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