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

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
......@@ -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);
......
......@@ -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,
......
......@@ -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)
......
......@@ -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);
......
......@@ -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);
......
......@@ -28,6 +28,9 @@
#define CPUCP_PKT_HBM_ECC_INFO_HBM_CH_SHIFT 6
#define CPUCP_PKT_HBM_ECC_INFO_HBM_CH_MASK 0x000007C0
#define PLL_MAP_MAX_BITS 128
#define PLL_MAP_LEN (PLL_MAP_MAX_BITS / 8)
/*
* info of the pkt queue pointers in the first async occurrence
*/
......@@ -473,6 +476,42 @@ enum cpucp_pll_type_attributes {
cpucp_pll_pci,
};
/*
* PLL enumeration table used for all ASICs and future SW versions.
* For future ASIC-LKD compatibility, we can only add new enumerations.
* at the end of the table.
* Changing the order of entries or removing entries is not allowed.
*/
enum pll_index {
CPU_PLL = 0,
PCI_PLL = 1,
NIC_PLL = 2,
DMA_PLL = 3,
MESH_PLL = 4,
MME_PLL = 5,
TPC_PLL = 6,
IF_PLL = 7,
SRAM_PLL = 8,
NS_DCORE_PLL = 9,
MESH_DCORE_PLL = 10,
HBM_PLL = 11,
TPC_DCORE_PLL = 12,
VIDEO_DCORE_PLL = 13,
SRAM_DCORE_PLL = 14,
NIC_PHY_DCORE_PLL = 15,
MSS_DCORE_PLL = 16,
DMA_DCORE_PLL = 17,
SIF_PLL = 18,
DDR_PLL = 19,
VID_PLL = 20,
BANK_PLL = 21,
MMU_PLL = 22,
IC_PLL = 23,
MC_PLL = 24,
EMMC_PLL = 25,
PLL_MAX
};
/* Event Queue Packets */
struct eq_generic_event {
......@@ -547,6 +586,7 @@ struct cpucp_security_info {
* @dram_size: available DRAM size.
* @card_name: card name that will be displayed in HWMON subsystem on the host
* @sec_info: security information
* @pll_map: Bit map of supported PLLs for current ASIC version.
*/
struct cpucp_info {
struct cpucp_sensor sensors[CPUCP_MAX_SENSORS];
......@@ -568,6 +608,7 @@ struct cpucp_info {
__u8 pad[7];
struct cpucp_security_info sec_info;
__le32 reserved6;
__u8 pll_map[PLL_MAP_LEN];
};
struct cpucp_mac_addr {
......
......@@ -179,6 +179,11 @@
* configured and is ready for use.
* Initialized in: ppboot
*
* CPU_BOOT_DEV_STS0_DYN_PLL_EN Dynamic PLL configuration is enabled.
* FW sends to host a bitmap of supported
* PLLs.
* Initialized in: linux
*
* CPU_BOOT_DEV_STS0_ENABLED Device status register enabled.
* This is a main indication that the
* running FW populates the device status
......@@ -206,6 +211,7 @@
#define CPU_BOOT_DEV_STS0_PKT_PI_ACK_EN (1 << 15)
#define CPU_BOOT_DEV_STS0_FW_LD_COM_EN (1 << 16)
#define CPU_BOOT_DEV_STS0_FW_IATU_CONF_EN (1 << 17)
#define CPU_BOOT_DEV_STS0_DYN_PLL_EN (1 << 19)
#define CPU_BOOT_DEV_STS0_ENABLED (1 << 31)
enum cpu_boot_status {
......
......@@ -20,20 +20,6 @@
#define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */
#define LINUX_FW_OFFSET 0x800000 /* 8MB in HBM */
enum gaudi_pll_index {
CPU_PLL = 0,
PCI_PLL,
SRAM_PLL,
HBM_PLL,
NIC_PLL,
DMA_PLL,
MESH_PLL,
MME_PLL,
TPC_PLL,
IF_PLL,
PLL_MAX
};
enum gaudi_nic_axi_error {
RXB,
RXE,
......
......@@ -15,17 +15,6 @@
#define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */
#define LINUX_FW_OFFSET 0x800000 /* 8MB in DDR */
enum goya_pll_index {
CPU_PLL = 0,
IC_PLL,
MC_PLL,
MME_PLL,
PCI_PLL,
EMMC_PLL,
TPC_PLL,
PLL_MAX
};
#define GOYA_PLL_FREQ_LOW 50000000 /* 50 MHz */
#endif /* GOYA_FW_IF_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment