drivers/ufs/core/ufs-txeq.c

Source file repositories/reference/linux-study-clean/drivers/ufs/core/ufs-txeq.c

File Facts

System
Linux kernel
Corpus path
drivers/ufs/core/ufs-txeq.c
Extension
.c
Size
50480 bytes
Lines
1585
Domain
Driver Families
Bucket
drivers/ufs
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (params->host[lane].precode_en) {
			local_precode_en |= PRECODEEN_TX_BIT(lane);
			peer_precode_en |= PRECODEEN_RX_BIT(lane);
		}
	}

	/* Enable Pre-Coding for Device's TX & Host's RX pair */
	for (lane = 0; lane < pwr_info->lane_rx; lane++) {
		if (params->device[lane].precode_en) {
			peer_precode_en |= PRECODEEN_TX_BIT(lane);
			local_precode_en |= PRECODEEN_RX_BIT(lane);
		}
	}

	if (!local_precode_en && !peer_precode_en) {
		dev_dbg(hba->dev, "Pre-Coding is not required for Host and Device\n");
		return 0;
	}

	/* Set local PA_PreCodeEn */
	ret = ufshcd_dme_set(hba, UIC_ARG_MIB(PA_PRECODEEN), local_precode_en);
	if (ret) {
		dev_err(hba->dev, "Failed to set local PA_PreCodeEn: %d\n", ret);
		return ret;
	}

	/* Set peer PA_PreCodeEn */
	ret = ufshcd_dme_peer_set(hba, UIC_ARG_MIB(PA_PRECODEEN), peer_precode_en);
	if (ret) {
		dev_err(hba->dev, "Failed to set peer PA_PreCodeEn: %d\n", ret);
		return ret;
	}

	dev_dbg(hba->dev, "Local PA_PreCodeEn: 0x%02x, Peer PA_PreCodeEn: 0x%02x\n",
		local_precode_en, peer_precode_en);

	return 0;
}

void ufshcd_print_tx_eq_params(struct ufs_hba *hba)
{
	struct ufs_pa_layer_attr *pwr_info = &hba->max_pwr_info.info;
	struct ufshcd_tx_eq_params *params;
	u32 gear = hba->pwr_info.gear_tx;
	int lane;

	if (!ufshcd_is_tx_eq_supported(hba))
		return;

	if (gear < UFS_HS_G1 || gear > UFS_HS_GEAR_MAX)
		return;

	params = &hba->tx_eq_params[gear - 1];
	if (!params->is_valid || !params->is_applied)
		return;

	for (lane = 0; lane < pwr_info->lane_tx; lane++)
		dev_dbg(hba->dev, "Host TX Lane %d: PreShoot %u, DeEmphasis %u, FOM %u, PreCodeEn %d\n",
			lane, params->host[lane].preshoot,
			params->host[lane].deemphasis,
			params->host[lane].fom_val,
			params->host[lane].precode_en);

	for (lane = 0; lane < pwr_info->lane_rx; lane++)
		dev_dbg(hba->dev, "Device TX Lane %d: PreShoot %u, DeEmphasis %u, FOM %u, PreCodeEn %d\n",
			lane, params->device[lane].preshoot,
			params->device[lane].deemphasis,
			params->device[lane].fom_val,
			params->device[lane].precode_en);
}

static inline u32
ufshcd_compose_tx_eq_setting(struct ufshcd_tx_eq_settings *settings,
			     int num_lanes)
{
	u32 setting = 0;
	int lane;

	for (lane = 0; lane < num_lanes; lane++, settings++) {
		setting |= TX_HS_PRESHOOT_BITS(lane, settings->preshoot);
		setting |= TX_HS_DEEMPHASIS_BITS(lane, settings->deemphasis);
	}

	return setting;
}

/**
 * ufshcd_apply_tx_eq_settings - Apply TX Equalization settings for target gear
 * @hba: per adapter instance
 * @params: TX EQ parameters data structure

Annotation

Implementation Notes