Rtwo/kernel/motorola/sm8550/drivers/mmc/host/sdhci-msm.h
2025-09-30 19:22:48 -05:00

368 lines
9.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2013-2014,2020-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _DRIVERS_MMC_SDHCI_MSM_H
#define _DRIVERS_MMC_SDHCI_MSM_H
#include <linux/of_device.h>
#include <linux/delay.h>
#include <linux/mmc/mmc.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/interconnect.h>
#include <linux/iopoll.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_qos.h>
#include <linux/cpu.h>
#include <linux/cpumask.h>
#include <linux/interrupt.h>
#include <linux/of.h>
#include <linux/reset.h>
#include "sdhci-pltfm.h"
#if IS_ENABLED(CONFIG_MMC_SDHCI_MSM_SCALING)
#include "sdhci-msm-scaling.h"
#endif
#include "cqhci.h"
#define MMC_CAP2_CLK_SCALE (1 << 28) /* Allow dynamic clk scaling */
/* CPU Clusters Info */
enum cpu_cluster_info {
SILVER_CORE,
GOLD_CORE,
GOLD_PRIME_CORE,
MAX_NUM_CLUSTERS,
};
enum dev_state {
DEV_SUSPENDING = 1,
DEV_SUSPENDED,
DEV_RESUMED,
};
enum sdhci_msm_mmc_load {
MMC_LOAD_HIGH,
MMC_LOAD_LOW,
};
/**
* struct mmc_devfeq_clk_scaling - main context for MMC clock scaling logic
*
* @lock: spinlock to protect statistics
* @devfreq: struct that represent mmc-host as a client for devfreq
* @devfreq_profile: MMC device profile, mostly polling interval and callbacks
* @ondemand_gov_data: struct supplied to ondemmand governor (thresholds)
* @state: load state, can be HIGH or LOW. used to notify mmc_host_ops callback
* @start_busy: timestamped armed once a data request is started
* @measure_interval_start: timestamped armed once a measure interval started
* @devfreq_abort: flag to sync between different contexts relevant to devfreq
* @skip_clk_scale_freq_update: flag that enable/disable frequency change
* @freq_table_sz: table size of frequencies supplied to devfreq
* @freq_table: frequencies table supplied to devfreq
* @curr_freq: current frequency
* @polling_delay_ms: polling interval for status collection used by devfreq
* @upthreshold: up-threshold supplied to ondemand governor
* @downthreshold: down-threshold supplied to ondemand governor
* @need_freq_change: flag indicating if a frequency change is required
* @is_busy_started: flag indicating if a request is handled by the HW
* @enable: flag indicating if the clock scaling logic is enabled for this host
* @is_suspended: to make devfreq request queued when mmc is suspened
*/
#if IS_ENABLED(CONFIG_MMC_SDHCI_MSM_SCALING)
struct sdhci_msm_mmc_devfeq_clk_scaling {
spinlock_t lock;
struct devfreq *devfreq;
struct devfreq_dev_profile devfreq_profile;
struct devfreq_simple_ondemand_data ondemand_gov_data;
enum sdhci_msm_mmc_load state;
ktime_t start_busy;
ktime_t measure_interval_start;
atomic_t devfreq_abort;
bool skip_clk_scale_freq_update;
int freq_table_sz;
int pltfm_freq_table_sz;
u32 *freq_table;
u32 *pltfm_freq_table;
unsigned long total_busy_time_us;
unsigned long target_freq;
unsigned long curr_freq;
unsigned long polling_delay_ms;
unsigned int upthreshold;
unsigned int downthreshold;
unsigned int lower_bus_speed_mode;
#define MMC_SCALING_LOWER_DDR52_MODE 1
bool need_freq_change;
bool is_busy_started;
bool enable;
bool is_suspended;
};
#endif
struct sdhci_msm_variant_ops {
u32 (*msm_readl_relaxed)(struct sdhci_host *host, u32 offset);
void (*msm_writel_relaxed)(u32 val, struct sdhci_host *host,
u32 offset);
};
struct sdhci_msm_offset {
u32 core_hc_mode;
u32 core_mci_data_cnt;
u32 core_mci_status;
u32 core_mci_fifo_cnt;
u32 core_mci_version;
u32 core_generics;
u32 core_testbus_config;
u32 core_testbus_sel2_bit;
u32 core_testbus_ena;
u32 core_testbus_sel2;
u32 core_pwrctl_status;
u32 core_pwrctl_mask;
u32 core_pwrctl_clear;
u32 core_pwrctl_ctl;
u32 core_sdcc_debug_reg;
u32 core_dll_config;
u32 core_dll_status;
u32 core_vendor_spec;
u32 core_vendor_spec_adma_err_addr0;
u32 core_vendor_spec_adma_err_addr1;
u32 core_vendor_spec_func2;
u32 core_vendor_spec_capabilities0;
u32 core_vendor_spec_capabilities1;
u32 core_ddr_200_cfg;
u32 core_vendor_spec3;
u32 core_dll_config_2;
u32 core_dll_config_3;
u32 core_ddr_config_old; /* Applicable to sdcc minor ver < 0x49 */
u32 core_ddr_config;
u32 core_dll_usr_ctl; /* Present on SDCC5.1 onwards */
};
/* This structure keeps information per regulator */
struct sdhci_msm_reg_data {
struct sdhci_msm_host *msm_host;
/* voltage regulator handle */
struct regulator *reg;
/* regulator name */
const char *name;
/* voltage level to be set */
u32 low_vol_level;
u32 high_vol_level;
/* Load values for low power and high power mode */
u32 lpm_uA;
u32 hpm_uA;
/* is this regulator enabled? */
bool is_enabled;
/* is this regulator needs to be always on? */
bool is_always_on;
/* is low power mode setting required for this regulator? */
bool lpm_sup;
bool set_voltage_sup;
bool is_voltage_supplied;
};
/*
* This structure keeps information for all the
* regulators required for a SDCC slot.
*/
struct sdhci_msm_vreg_data {
/* keeps VDD/VCC regulator info */
struct sdhci_msm_reg_data *vdd_data;
/* keeps VDD IO regulator info */
struct sdhci_msm_reg_data *vdd_io_data;
};
/* Per cpu cluster qos group */
struct qos_cpu_group {
cpumask_t mask; /* CPU mask of cluster */
unsigned int *votes; /* Different votes for cluster */
struct dev_pm_qos_request *qos_req; /* Pointer to host qos request*/
bool voted;
struct sdhci_msm_host *host;
bool initialized;
bool curr_vote;
};
/* Per host qos request structure */
struct sdhci_msm_qos_req {
struct qos_cpu_group *qcg; /* CPU group per host */
unsigned int num_groups; /* Number of groups */
unsigned int active_mask; /* Active affine irq mask */
};
enum constraint {
QOS_PERF,
QOS_POWER,
QOS_MAX,
};
struct sdhci_msm_bus_vote_data {
const char *name;
unsigned int num_usecase;
struct msm_bus_path *usecase;
unsigned int *bw_vecs;
unsigned int bw_vecs_size;
struct icc_path *sdhc_ddr;
struct icc_path *cpu_sdhc;
u32 curr_vote;
};
/*
* DLL registers which needs be programmed with HSR settings.
* Add any new register only at the end and don't change the
* sequence.
*/
struct sdhci_msm_dll_hsr {
u32 dll_config;
u32 dll_config_2;
u32 dll_config_3;
u32 dll_usr_ctl;
u32 ddr_config;
};
struct cqe_regs_restore {
u32 cqe_vendor_cfg1;
};
struct sdhci_msm_regs_restore {
bool is_supported;
bool is_valid;
u32 vendor_pwrctl_mask;
u32 vendor_pwrctl_ctl;
u32 vendor_caps_0;
u32 vendor_func;
u32 vendor_func2;
u32 vendor_func3;
u32 hc_2c_2e;
u32 hc_28_2a;
u32 hc_34_36;
u32 hc_38_3a;
u32 hc_3c_3e;
u32 hc_caps_1;
u32 testbus_config;
u32 dll_config;
u32 dll_config2;
u32 dll_config3;
u32 dll_usr_ctl;
};
struct sdhci_msm_host {
struct platform_device *pdev;
void __iomem *core_mem; /* MSM SDCC mapped address */
#ifdef CONFIG_MMC_CRYPTO
void __iomem *ice_mem; /* MSM ICE mapped address (if available) */
#endif
#if (IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER) || IS_ENABLED(CONFIG_QTI_HW_KEY_MANAGER_V1))
void __iomem *ice_hwkm_mem;
#endif
int pwr_irq; /* power irq */
struct clk *bus_clk; /* SDHC bus voter clock */
struct clk *xo_clk; /* TCXO clk needed for FLL feature of cm_dll*/
/* core, iface, ice, cal, sleep clocks */
struct clk_bulk_data bulk_clks[5];
unsigned long clk_rate;
struct sdhci_msm_vreg_data *vreg_data;
struct mmc_host *mmc;
struct opp_table *opp_table;
bool has_opp_table;
struct cqhci_host *cq_host;
bool use_14lpp_dll_reset;
bool tuning_done;
bool calibration_done;
u8 saved_tuning_phase;
bool use_cdclp533;
u32 curr_pwr_state;
u32 curr_io_level;
wait_queue_head_t pwr_irq_wait;
bool pwr_irq_flag;
u32 caps_0;
bool mci_removed;
bool restore_dll_config;
const struct sdhci_msm_variant_ops *var_ops;
const struct sdhci_msm_offset *offset;
bool use_cdr;
u32 transfer_mode;
bool updated_ddr_cfg;
bool skip_bus_bw_voting;
struct sdhci_msm_bus_vote_data *bus_vote_data;
struct delayed_work bus_vote_work;
struct delayed_work clk_gating_work;
struct delayed_work pmqos_unvote_work;
struct workqueue_struct *workq; /* QoS work queue */
struct sdhci_msm_qos_req *sdhci_qos;
struct irq_affinity_notify affinity_notify;
struct device_attribute clk_gating;
struct device_attribute pm_qos;
u32 clk_gating_delay;
u32 pm_qos_delay;
bool cqhci_offset_changed;
bool reg_store;
struct reset_control *core_reset;
bool vbias_skip_wa;
bool pltfm_init_done;
bool fake_core_3_0v_support;
bool core_3_0v_support;
bool use_7nm_dll;
struct sdhci_msm_dll_hsr *dll_hsr;
struct sdhci_msm_regs_restore regs_restore;
struct cqe_regs_restore cqe_regs;
u32 *sup_ice_clk_table;
unsigned char sup_ice_clk_cnt;
u32 ice_clk_max;
u32 ice_clk_min;
u32 ice_clk_rate;
bool uses_tassadar_dll;
bool uses_level_shifter;
bool dll_lock_bist_fail_wa;
u32 dll_config;
u32 ddr_config;
u16 last_cmd;
bool vqmmc_enabled;
void *sdhci_msm_ipc_log_ctx;
bool dbg_en;
bool err_occurred;
bool crash_on_err;
#if IS_ENABLED(CONFIG_MMC_SDHCI_MSM_SCALING)
struct sdhci_msm_mmc_devfeq_clk_scaling clk_scaling;
#endif
unsigned long clk_scaling_lowest; /* lowest scaleable
* frequency.
*/
unsigned long clk_scaling_highest; /* highest scaleable
* frequency.
*/
atomic_t active_reqs;
unsigned int part_curr;
int scale_caps;
int clk_scale_init_done;
int defer_clk_scaling_resume;
int scaling_suspended;
u8 raw_ext_csd_cmdq;
u8 raw_ext_csd_cache_ctrl;
u8 raw_ext_csd_bus_width;
u8 raw_ext_csd_hs_timing;
struct mmc_ios cached_ios;
bool rst_n_disable;
};
struct mmc_pwrseq_ops {
void (*pre_power_on)(struct mmc_host *host);
void (*post_power_on)(struct mmc_host *host);
void (*power_off)(struct mmc_host *host);
void (*reset)(struct mmc_host *host);
};
struct mmc_pwrseq {
struct mmc_pwrseq_ops *ops;
struct device *dev;
struct list_head pwrseq_node;
struct module *owner;
};
#endif