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) ...@@ -539,18 +539,63 @@ int hl_fw_cpucp_total_energy_get(struct hl_device *hdev, u64 *total_energy)
return rc; 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) u16 *pll_freq_arr)
{ {
struct cpucp_packet pkt; struct cpucp_packet pkt;
enum pll_index used_pll_idx;
u64 result; u64 result;
int rc; int rc;
rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
if (rc)
return rc;
memset(&pkt, 0, sizeof(pkt)); memset(&pkt, 0, sizeof(pkt));
pkt.ctl = cpu_to_le32(CPUCP_PACKET_PLL_INFO_GET << pkt.ctl = cpu_to_le32(CPUCP_PACKET_PLL_INFO_GET <<
CPUCP_PKT_CTL_OPCODE_SHIFT); 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), rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
HL_CPUCP_INFO_TIMEOUT_USEC, &result); HL_CPUCP_INFO_TIMEOUT_USEC, &result);
......
...@@ -1946,6 +1946,8 @@ struct hl_mmu_funcs { ...@@ -1946,6 +1946,8 @@ struct hl_mmu_funcs {
* @aggregated_cs_counters: aggregated cs counters among all contexts * @aggregated_cs_counters: aggregated cs counters among all contexts
* @mmu_priv: device-specific MMU data. * @mmu_priv: device-specific MMU data.
* @mmu_func: device-related MMU functions. * @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. * @dram_used_mem: current DRAM memory consumption.
* @timeout_jiffies: device CS timeout value. * @timeout_jiffies: device CS timeout value.
* @max_power: the max power of the device, as configured by the sysadmin. This * @max_power: the max power of the device, as configured by the sysadmin. This
...@@ -2070,6 +2072,8 @@ struct hl_device { ...@@ -2070,6 +2072,8 @@ struct hl_device {
struct hl_mmu_priv mmu_priv; struct hl_mmu_priv mmu_priv;
struct hl_mmu_funcs mmu_func[MMU_NUM_PGT_LOCATIONS]; struct hl_mmu_funcs mmu_func[MMU_NUM_PGT_LOCATIONS];
enum pll_index *legacy_pll_map;
atomic64_t dram_used_mem; atomic64_t dram_used_mem;
u64 timeout_jiffies; u64 timeout_jiffies;
u64 max_power; u64 max_power;
...@@ -2383,7 +2387,9 @@ int hl_fw_cpucp_pci_counters_get(struct hl_device *hdev, ...@@ -2383,7 +2387,9 @@ int hl_fw_cpucp_pci_counters_get(struct hl_device *hdev,
struct hl_info_pci_counters *counters); struct hl_info_pci_counters *counters);
int hl_fw_cpucp_total_energy_get(struct hl_device *hdev, int hl_fw_cpucp_total_energy_get(struct hl_device *hdev,
u64 *total_energy); 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); u16 *pll_freq_arr);
int hl_fw_cpucp_power_get(struct hl_device *hdev, u64 *power); 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, 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, ...@@ -2404,8 +2410,10 @@ int hl_pci_set_outbound_region(struct hl_device *hdev,
int hl_pci_init(struct hl_device *hdev); int hl_pci_init(struct hl_device *hdev);
void hl_pci_fini(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); long hl_get_frequency(struct hl_device *hdev, enum pll_index pll_index,
void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq); 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 hl_get_temperature(struct hl_device *hdev,
int sensor_index, u32 attr, long *value); int sensor_index, u32 attr, long *value);
int hl_set_temperature(struct hl_device *hdev, int hl_set_temperature(struct hl_device *hdev,
......
...@@ -9,12 +9,18 @@ ...@@ -9,12 +9,18 @@
#include <linux/pci.h> #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; struct cpucp_packet pkt;
u32 used_pll_idx;
u64 result; u64 result;
int rc; int rc;
rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
if (rc)
return rc;
memset(&pkt, 0, sizeof(pkt)); memset(&pkt, 0, sizeof(pkt));
if (curr) if (curr)
...@@ -23,7 +29,7 @@ long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr) ...@@ -23,7 +29,7 @@ long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
else else
pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_GET << pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_GET <<
CPUCP_PKT_CTL_OPCODE_SHIFT); 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), rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt),
0, &result); 0, &result);
...@@ -31,23 +37,29 @@ long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr) ...@@ -31,23 +37,29 @@ long hl_get_frequency(struct hl_device *hdev, u32 pll_index, bool curr)
if (rc) { if (rc) {
dev_err(hdev->dev, dev_err(hdev->dev,
"Failed to get frequency of PLL %d, error %d\n", "Failed to get frequency of PLL %d, error %d\n",
pll_index, rc); used_pll_idx, rc);
return rc; return rc;
} }
return (long) result; 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; struct cpucp_packet pkt;
u32 used_pll_idx;
int rc; int rc;
rc = get_used_pll_index(hdev, pll_index, &used_pll_idx);
if (rc)
return;
memset(&pkt, 0, sizeof(pkt)); memset(&pkt, 0, sizeof(pkt));
pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_SET << pkt.ctl = cpu_to_le32(CPUCP_PACKET_FREQUENCY_SET <<
CPUCP_PKT_CTL_OPCODE_SHIFT); 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); pkt.value = cpu_to_le64(freq);
rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), 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) ...@@ -56,7 +68,7 @@ void hl_set_frequency(struct hl_device *hdev, u32 pll_index, u64 freq)
if (rc) if (rc)
dev_err(hdev->dev, dev_err(hdev->dev,
"Failed to set frequency to PLL %d, error %d\n", "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) u64 hl_get_max_power(struct hl_device *hdev)
......
...@@ -105,6 +105,36 @@ ...@@ -105,6 +105,36 @@
#define GAUDI_PLL_MAX 10 #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] = { 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 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", "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) ...@@ -1588,6 +1618,9 @@ static int gaudi_sw_init(struct hl_device *hdev)
hdev->asic_specific = gaudi; hdev->asic_specific = gaudi;
/* store legacy PLL map */
hdev->legacy_pll_map = gaudi_pll_map;
/* Create DMA pool for small allocations */ /* Create DMA pool for small allocations */
hdev->dma_pool = dma_pool_create(dev_name(hdev->dev), hdev->dma_pool = dma_pool_create(dev_name(hdev->dev),
&hdev->pdev->dev, GAUDI_DMA_POOL_BLK_SIZE, 8, 0); &hdev->pdev->dev, GAUDI_DMA_POOL_BLK_SIZE, 8, 0);
......
...@@ -118,6 +118,29 @@ ...@@ -118,6 +118,29 @@
#define IS_MME_IDLE(mme_arch_sts) \ #define IS_MME_IDLE(mme_arch_sts) \
(((mme_arch_sts) & MME_ARCH_IDLE_MASK) == MME_ARCH_IDLE_MASK) (((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] = { 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", "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) ...@@ -853,6 +876,9 @@ static int goya_sw_init(struct hl_device *hdev)
hdev->asic_specific = goya; hdev->asic_specific = goya;
/* store legacy PLL map */
hdev->legacy_pll_map = goya_pll_map;
/* Create DMA pool for small allocations */ /* Create DMA pool for small allocations */
hdev->dma_pool = dma_pool_create(dev_name(hdev->dev), hdev->dma_pool = dma_pool_create(dev_name(hdev->dev),
&hdev->pdev->dev, GOYA_DMA_POOL_BLK_SIZE, 8, 0); &hdev->pdev->dev, GOYA_DMA_POOL_BLK_SIZE, 8, 0);
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#define CPUCP_PKT_HBM_ECC_INFO_HBM_CH_SHIFT 6 #define CPUCP_PKT_HBM_ECC_INFO_HBM_CH_SHIFT 6
#define CPUCP_PKT_HBM_ECC_INFO_HBM_CH_MASK 0x000007C0 #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 * info of the pkt queue pointers in the first async occurrence
*/ */
...@@ -473,6 +476,42 @@ enum cpucp_pll_type_attributes { ...@@ -473,6 +476,42 @@ enum cpucp_pll_type_attributes {
cpucp_pll_pci, 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 */ /* Event Queue Packets */
struct eq_generic_event { struct eq_generic_event {
...@@ -547,6 +586,7 @@ struct cpucp_security_info { ...@@ -547,6 +586,7 @@ struct cpucp_security_info {
* @dram_size: available DRAM size. * @dram_size: available DRAM size.
* @card_name: card name that will be displayed in HWMON subsystem on the host * @card_name: card name that will be displayed in HWMON subsystem on the host
* @sec_info: security information * @sec_info: security information
* @pll_map: Bit map of supported PLLs for current ASIC version.
*/ */
struct cpucp_info { struct cpucp_info {
struct cpucp_sensor sensors[CPUCP_MAX_SENSORS]; struct cpucp_sensor sensors[CPUCP_MAX_SENSORS];
...@@ -568,6 +608,7 @@ struct cpucp_info { ...@@ -568,6 +608,7 @@ struct cpucp_info {
__u8 pad[7]; __u8 pad[7];
struct cpucp_security_info sec_info; struct cpucp_security_info sec_info;
__le32 reserved6; __le32 reserved6;
__u8 pll_map[PLL_MAP_LEN];
}; };
struct cpucp_mac_addr { struct cpucp_mac_addr {
......
...@@ -179,6 +179,11 @@ ...@@ -179,6 +179,11 @@
* configured and is ready for use. * configured and is ready for use.
* Initialized in: ppboot * 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. * CPU_BOOT_DEV_STS0_ENABLED Device status register enabled.
* This is a main indication that the * This is a main indication that the
* running FW populates the device status * running FW populates the device status
...@@ -206,6 +211,7 @@ ...@@ -206,6 +211,7 @@
#define CPU_BOOT_DEV_STS0_PKT_PI_ACK_EN (1 << 15) #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_LD_COM_EN (1 << 16)
#define CPU_BOOT_DEV_STS0_FW_IATU_CONF_EN (1 << 17) #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) #define CPU_BOOT_DEV_STS0_ENABLED (1 << 31)
enum cpu_boot_status { enum cpu_boot_status {
......
...@@ -20,20 +20,6 @@ ...@@ -20,20 +20,6 @@
#define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */ #define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */
#define LINUX_FW_OFFSET 0x800000 /* 8MB in HBM */ #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 { enum gaudi_nic_axi_error {
RXB, RXB,
RXE, RXE,
......
...@@ -15,17 +15,6 @@ ...@@ -15,17 +15,6 @@
#define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */ #define UBOOT_FW_OFFSET 0x100000 /* 1MB in SRAM */
#define LINUX_FW_OFFSET 0x800000 /* 8MB in DDR */ #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 */ #define GOYA_PLL_FREQ_LOW 50000000 /* 50 MHz */
#endif /* GOYA_FW_IF_H */ #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