Commit e8f9392a authored by Ohad Sharabi's avatar Ohad Sharabi Committed by Oded Gabbay
Browse files

habanalabs: support legacy and new pll indexes



In order to use minimum of hard coded values common to LKD and F/W
a dynamic method to work with PLLs is introduced in this patch.
Formerly asic specific PLL numbering is now common for all asics.
To be backward compatible a bit in dev status is defined, if the bit is
not set LKD will keep working with old PLL numbering.

Signed-off-by: default avatarOhad Sharabi <osharabi@habana.ai>
Reviewed-by: default avatarOded Gabbay <ogabbay@kernel.org>
Signed-off-by: default avatarOded Gabbay <ogabbay@kernel.org>
parent 8445dde1
Loading
Loading
Loading
Loading
+47 −2
Original line number Diff line number Diff line
@@ -539,18 +539,63 @@ int hl_fw_cpucp_total_energy_get(struct hl_device *hdev, u64 *total_energy)
	return rc;
}

int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, u16 pll_index,
int get_used_pll_index(struct hl_device *hdev, enum pll_index input_pll_index,
						enum pll_index *pll_index)
{
	struct asic_fixed_properties *prop = &hdev->asic_prop;
	u8 pll_byte, pll_bit_off;
	bool dynamic_pll;

	if (input_pll_index >= PLL_MAX) {
		dev_err(hdev->dev, "PLL index %d is out of range\n",
							input_pll_index);
		return -EINVAL;
	}

	dynamic_pll = prop->fw_security_status_valid &&
		(prop->fw_app_security_map & CPU_BOOT_DEV_STS0_DYN_PLL_EN);

	if (!dynamic_pll) {
		/*
		 * in case we are working with legacy FW (each asic has unique
		 * PLL numbering) extract the legacy numbering
		 */
		*pll_index = hdev->legacy_pll_map[input_pll_index];
		return 0;
	}

	/* PLL map is a u8 array */
	pll_byte = prop->cpucp_info.pll_map[input_pll_index >> 3];
	pll_bit_off = input_pll_index & 0x7;

	if (!(pll_byte & BIT(pll_bit_off))) {
		dev_err(hdev->dev, "PLL index %d is not supported\n",
							input_pll_index);
		return -EINVAL;
	}

	*pll_index = input_pll_index;

	return 0;
}

int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, enum pll_index pll_index,
		u16 *pll_freq_arr)
{
	struct cpucp_packet pkt;
	enum pll_index used_pll_idx;
	u64 result;
	int rc;

	rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
	if (rc)
		return rc;

	memset(&pkt, 0, sizeof(pkt));

	pkt.ctl = cpu_to_le32(CPUCP_PACKET_PLL_INFO_GET <<
				CPUCP_PKT_CTL_OPCODE_SHIFT);
	pkt.pll_type = __cpu_to_le16(pll_index);
	pkt.pll_type = __cpu_to_le16((u16)used_pll_idx);

	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
			HL_CPUCP_INFO_TIMEOUT_USEC, &result);
+11 −3
Original line number Diff line number Diff line
@@ -1946,6 +1946,8 @@ struct hl_mmu_funcs {
 * @aggregated_cs_counters: aggregated cs counters among all contexts
 * @mmu_priv: device-specific MMU data.
 * @mmu_func: device-related MMU functions.
 * @legacy_pll_map: map holding map between dynamic (common) PLL indexes and
 *                  static (asic specific) PLL indexes.
 * @dram_used_mem: current DRAM memory consumption.
 * @timeout_jiffies: device CS timeout value.
 * @max_power: the max power of the device, as configured by the sysadmin. This
@@ -2070,6 +2072,8 @@ struct hl_device {
	struct hl_mmu_priv		mmu_priv;
	struct hl_mmu_funcs		mmu_func[MMU_NUM_PGT_LOCATIONS];

	enum pll_index			*legacy_pll_map;

	atomic64_t			dram_used_mem;
	u64				timeout_jiffies;
	u64				max_power;
@@ -2383,7 +2387,9 @@ int hl_fw_cpucp_pci_counters_get(struct hl_device *hdev,
		struct hl_info_pci_counters *counters);
int hl_fw_cpucp_total_energy_get(struct hl_device *hdev,
			u64 *total_energy);
int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, u16 pll_index,
int get_used_pll_index(struct hl_device *hdev, enum pll_index input_pll_index,
						enum pll_index *pll_index);
int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, enum pll_index pll_index,
		u16 *pll_freq_arr);
int hl_fw_cpucp_power_get(struct hl_device *hdev, u64 *power);
int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg,
@@ -2404,8 +2410,10 @@ int hl_pci_set_outbound_region(struct hl_device *hdev,
int hl_pci_init(struct hl_device *hdev);
void hl_pci_fini(struct hl_device *hdev);

long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr);
void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq);
long hl_get_frequency(struct hl_device *hdev, enum pll_index pll_index,
								bool curr);
void hl_set_frequency(struct hl_device *hdev, enum pll_index pll_index,
								u64 freq);
int hl_get_temperature(struct hl_device *hdev,
		       int sensor_index, u32 attr, long *value);
int hl_set_temperature(struct hl_device *hdev,
+18 −6
Original line number Diff line number Diff line
@@ -9,12 +9,18 @@

#include <linux/pci.h>

long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
long hl_get_frequency(struct hl_device *hdev, enum pll_index pll_index,
								bool curr)
{
	struct cpucp_packet pkt;
	u32 used_pll_idx;
	u64 result;
	int rc;

	rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
	if (rc)
		return rc;

	memset(&pkt, 0, sizeof(pkt));

	if (curr)
@@ -23,7 +29,7 @@ long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
	else
		pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_GET <<
						CPUCP_PKT_CTL_OPCODE_SHIFT);
	pkt.pll_index = cpu_to_le32(pll_index);
	pkt.pll_index = cpu_to_le32((u32)used_pll_idx);

	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
						0, &result);
@@ -31,23 +37,29 @@ long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
	if (rc) {
		dev_err(hdev->dev,
			"Failed to get frequency of PLL %d, error %d\n",
			pll_index, rc);
			used_pll_idx, rc);
		return rc;
	}

	return (long) result;
}

void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
void hl_set_frequency(struct hl_device *hdev, enum pll_index pll_index,
								u64 freq)
{
	struct cpucp_packet pkt;
	u32 used_pll_idx;
	int rc;

	rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
	if (rc)
		return;

	memset(&pkt, 0, sizeof(pkt));

	pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_SET <<
					CPUCP_PKT_CTL_OPCODE_SHIFT);
	pkt.pll_index = cpu_to_le32(pll_index);
	pkt.pll_index = cpu_to_le32((u32)used_pll_idx);
	pkt.value = cpu_to_le64(freq);

	rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
@@ -56,7 +68,7 @@ void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
	if (rc)
		dev_err(hdev->dev,
			"Failed to set frequency to PLL %d, error %d\n",
			pll_index, rc);
			used_pll_idx, rc);
}

u64 hl_get_max_power(struct hl_device *hdev)
+33 −0
Original line number Diff line number Diff line
@@ -105,6 +105,36 @@

#define GAUDI_PLL_MAX 10

/*
 * this enum kept here for compatibility with old FW (in which each asic has
 * unique PLL numbering
 */
enum gaudi_pll_index {
	GAUDI_CPU_PLL = 0,
	GAUDI_PCI_PLL,
	GAUDI_SRAM_PLL,
	GAUDI_HBM_PLL,
	GAUDI_NIC_PLL,
	GAUDI_DMA_PLL,
	GAUDI_MESH_PLL,
	GAUDI_MME_PLL,
	GAUDI_TPC_PLL,
	GAUDI_IF_PLL,
};

static enum pll_index gaudi_pll_map[PLL_MAX] = {
	[CPU_PLL] = GAUDI_CPU_PLL,
	[PCI_PLL] = GAUDI_PCI_PLL,
	[SRAM_PLL] = GAUDI_SRAM_PLL,
	[HBM_PLL] = GAUDI_HBM_PLL,
	[NIC_PLL] = GAUDI_NIC_PLL,
	[DMA_PLL] = GAUDI_DMA_PLL,
	[MESH_PLL] = GAUDI_MESH_PLL,
	[MME_PLL] = GAUDI_MME_PLL,
	[TPC_PLL] = GAUDI_TPC_PLL,
	[IF_PLL] = GAUDI_IF_PLL,
};

static const char gaudi_irq_name[GAUDI_MSI_ENTRIES][GAUDI_MAX_STRING_LEN] = {
		"gaudi cq 0_0", "gaudi cq 0_1", "gaudi cq 0_2", "gaudi cq 0_3",
		"gaudi cq 1_0", "gaudi cq 1_1", "gaudi cq 1_2", "gaudi cq 1_3",
@@ -1588,6 +1618,9 @@ static int gaudi_sw_init(struct hl_device *hdev)

	hdev->asic_specific = gaudi;

	/* store legacy PLL map */
	hdev->legacy_pll_map = gaudi_pll_map;

	/* Create DMA pool for small allocations */
	hdev->dma_pool = dma_pool_create(dev_name(hdev->dev),
			&hdev->pdev->dev, GAUDI_DMA_POOL_BLK_SIZE, 8, 0);
+26 −0
Original line number Diff line number Diff line
@@ -118,6 +118,29 @@
#define IS_MME_IDLE(mme_arch_sts) \
	(((mme_arch_sts) & MME_ARCH_IDLE_MASK) == MME_ARCH_IDLE_MASK)

/*
 * this enum kept here for compatibility with old FW (in which each asic has
 * unique PLL numbering
 */
enum goya_pll_index {
	GOYA_CPU_PLL = 0,
	GOYA_IC_PLL,
	GOYA_MC_PLL,
	GOYA_MME_PLL,
	GOYA_PCI_PLL,
	GOYA_EMMC_PLL,
	GOYA_TPC_PLL,
};

static enum pll_index goya_pll_map[PLL_MAX] = {
	[CPU_PLL] = GOYA_CPU_PLL,
	[IC_PLL] = GOYA_IC_PLL,
	[MC_PLL] = GOYA_MC_PLL,
	[MME_PLL] = GOYA_MME_PLL,
	[PCI_PLL] = GOYA_PCI_PLL,
	[EMMC_PLL] = GOYA_EMMC_PLL,
	[TPC_PLL] = GOYA_TPC_PLL,
};

static const char goya_irq_name[GOYA_MSIX_ENTRIES][GOYA_MAX_STRING_LEN] = {
		"goya cq 0", "goya cq 1", "goya cq 2", "goya cq 3",
@@ -853,6 +876,9 @@ static int goya_sw_init(struct hl_device *hdev)

	hdev->asic_specific = goya;

	/* store legacy PLL map */
	hdev->legacy_pll_map = goya_pll_map;

	/* Create DMA pool for small allocations */
	hdev->dma_pool = dma_pool_create(dev_name(hdev->dev),
			&hdev->pdev->dev, GOYA_DMA_POOL_BLK_SIZE, 8, 0);
Loading