root/drivers/platform/x86/amd/pmc/pmc.h
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * AMD SoC Power Management Controller Driver
 *
 * Copyright (c) 2023, Advanced Micro Devices, Inc.
 * All Rights Reserved.
 *
 * Author: Mario Limonciello <mario.limonciello@amd.com>
 */

#ifndef PMC_H
#define PMC_H

#include <linux/types.h>
#include <linux/mutex.h>

/* SMU communication registers */
#define AMD_PMC_REGISTER_RESPONSE       0x980
#define AMD_PMC_REGISTER_ARGUMENT       0x9BC
#define AMD_PMC_REGISTER_MESSAGE        0x538

/* SMU communication registers for 1Ah 20h SoC */
#define AMD_PMC_REGISTER_MSG_1AH_20H    0x938

/* SMU communication registers for 1Ah 80h SoC */
#define AMD_PMC_REGISTER_MSG_1AH_80H    0xA10
#define AMD_PMC_REGISTER_ARG_1AH_80H    0xA18
#define AMD_PMC_REGISTER_RSP_1AH_80H    0xA14

/* PMC Scratch Registers */
#define AMD_PMC_SCRATCH_REG_CZN         0x94
#define AMD_PMC_SCRATCH_REG_YC          0xD14
#define AMD_PMC_SCRATCH_REG_1AH         0xF14

/* STB Registers */
#define AMD_PMC_STB_S2IDLE_PREPARE      0xC6000001
#define AMD_PMC_STB_S2IDLE_RESTORE      0xC6000002
#define AMD_PMC_STB_S2IDLE_CHECK        0xC6000003

/* Base address of SMU for mapping physical address to virtual address */
#define AMD_PMC_MAPPING_SIZE            0x01000
#define AMD_PMC_BASE_ADDR_OFFSET        0x10000
#define AMD_PMC_BASE_ADDR_LO            0x13B102E8
#define AMD_PMC_BASE_ADDR_HI            0x13B102EC
#define AMD_PMC_BASE_ADDR_LO_MASK       GENMASK(15, 0)
#define AMD_PMC_BASE_ADDR_HI_MASK       GENMASK(31, 20)

/* SMU Response Codes */
#define AMD_PMC_RESULT_OK                    0x01
#define AMD_PMC_RESULT_CMD_REJECT_BUSY       0xFC
#define AMD_PMC_RESULT_CMD_REJECT_PREREQ     0xFD
#define AMD_PMC_RESULT_CMD_UNKNOWN           0xFE
#define AMD_PMC_RESULT_FAILED                0xFF

/* FCH SSC Registers */
#define FCH_S0I3_ENTRY_TIME_L_OFFSET    0x30
#define FCH_S0I3_ENTRY_TIME_H_OFFSET    0x34
#define FCH_S0I3_EXIT_TIME_L_OFFSET     0x38
#define FCH_S0I3_EXIT_TIME_H_OFFSET     0x3C
#define FCH_SSC_MAPPING_SIZE            0x800
#define FCH_BASE_PHY_ADDR_LOW           0xFED81100
#define FCH_BASE_PHY_ADDR_HIGH          0x00000000

/* SMU Message Definations */
#define SMU_MSG_GETSMUVERSION           0x02
#define SMU_MSG_LOG_GETDRAM_ADDR_HI     0x04
#define SMU_MSG_LOG_GETDRAM_ADDR_LO     0x05
#define SMU_MSG_LOG_START               0x06
#define SMU_MSG_LOG_RESET               0x07
#define SMU_MSG_LOG_DUMP_DATA           0x08
#define SMU_MSG_GET_SUP_CONSTRAINTS     0x09

#define PMC_MSG_DELAY_MIN_US            50
#define RESPONSE_REGISTER_LOOP_MAX      20000

#define DELAY_MIN_US            2000
#define DELAY_MAX_US            3000

enum s2d_msg_port {
        MSG_PORT_PMC,
        MSG_PORT_S2D,
};

struct amd_mp2_dev {
        void __iomem *mmio;
        void __iomem *vslbase;
        void *stbdata;
        void *devres_gid;
        struct pci_dev *pdev;
        dma_addr_t dma_addr;
        int stb_len;
        bool is_stb_data;
};

struct stb_arg {
        u32 s2d_msg_id;
        u32 msg;
        u32 arg;
        u32 resp;
};

struct amd_pmc_bit_map {
        const char *name;
        u32 bit_mask;
};

/* SoC-specific information */
struct amd_pmc_cpu_info {
        u32 smu_msg;
        u32 smu_arg;
        u32 smu_rsp;
        u32 num_ips;
        u32 scratch_reg;
        const struct amd_pmc_bit_map *ips_ptr;
        u8 os_hint;
};

struct amd_pmc_dev {
        void __iomem *regbase;
        void __iomem *smu_virt_addr;
        void __iomem *stb_virt_addr;
        void __iomem *fch_virt_addr;
        u32 base_addr;
        u32 cpu_id;
        u32 dram_size;
        u32 active_ips;
/* SMU version information */
        u8 smu_program;
        u8 major;
        u8 minor;
        u8 rev;
        u8 msg_port;
        struct device *dev;
        struct pci_dev *rdev;
        struct mutex lock; /* generic mutex lock */
        struct dentry *dbgfs_dir;
        struct quirk_entry *quirks;
        bool disable_8042_wakeup;
        bool is_first_check_after_suspend;
        struct amd_mp2_dev *mp2;
        struct stb_arg stb_arg;
        const struct amd_pmc_cpu_info *cpu_info;
};

struct smu_metrics {
        u32 table_version;
        u32 hint_count;
        u32 s0i3_last_entry_status;
        u32 timein_s0i2;
        u64 timeentering_s0i3_lastcapture;
        u64 timeentering_s0i3_totaltime;
        u64 timeto_resume_to_os_lastcapture;
        u64 timeto_resume_to_os_totaltime;
        u64 timein_s0i3_lastcapture;
        u64 timein_s0i3_totaltime;
        u64 timein_swdrips_lastcapture;
        u64 timein_swdrips_totaltime;
        u64 timecondition_notmet_lastcapture[32];
        u64 timecondition_notmet_totaltime[32];
} __packed;

enum amd_pmc_def {
        MSG_TEST = 0x01,
        MSG_OS_HINT_PCO,
        MSG_OS_HINT_RN,
};

void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
bool amd_pmc_quirk_need_suspend_delay(struct amd_pmc_dev *dev);
void amd_pmc_quirks_init(struct amd_pmc_dev *dev);
void amd_mp2_stb_init(struct amd_pmc_dev *dev);
void amd_mp2_stb_deinit(struct amd_pmc_dev *dev);

/* List of supported CPU/device IDs */
#define PCI_DEVICE_ID_AMD_CPU_ID_PCO    0x15D0
#define PCI_DEVICE_ID_AMD_CPU_ID_CZN    0x1630
#define PCI_DEVICE_ID_AMD_CPU_ID_VG     0x1645
#define PCI_DEVICE_ID_AMD_CPU_ID_YC     0x14B5
#define PCI_DEVICE_ID_AMD_CPU_ID_CB     0x14D8
#define PCI_DEVICE_ID_AMD_CPU_ID_PS     0x14E8
#define PCI_DEVICE_ID_AMD_CPU_ID_SP     0x14A4
#define PCI_DEVICE_ID_AMD_CPU_ID_SHP    0x153A

/* Backward compatibility aliases */
#define AMD_CPU_ID_PCO          PCI_DEVICE_ID_AMD_CPU_ID_PCO
#define AMD_CPU_ID_CZN          PCI_DEVICE_ID_AMD_CPU_ID_CZN
#define AMD_CPU_ID_VG           PCI_DEVICE_ID_AMD_CPU_ID_VG
#define AMD_CPU_ID_YC           PCI_DEVICE_ID_AMD_CPU_ID_YC
#define AMD_CPU_ID_CB           PCI_DEVICE_ID_AMD_CPU_ID_CB
#define AMD_CPU_ID_PS           PCI_DEVICE_ID_AMD_CPU_ID_PS
#define AMD_CPU_ID_SP           PCI_DEVICE_ID_AMD_CPU_ID_SP
#define AMD_CPU_ID_SHP          PCI_DEVICE_ID_AMD_CPU_ID_SHP

#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT         0x1507
#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT         0x1122
#define PCI_DEVICE_ID_AMD_1AH_M80H_ROOT         0x115b
#define PCI_DEVICE_ID_AMD_MP2_STB               0x172c

int amd_stb_s2d_init(struct amd_pmc_dev *dev);
int amd_stb_read(struct amd_pmc_dev *dev, u32 *buf);
int amd_stb_write(struct amd_pmc_dev *dev, u32 data);
int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret);

#endif /* PMC_H */