^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2018, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * In Certain QCOM SoCs like apq8096 and msm8996 that have KRYO processors,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * the CPU frequency subset and voltage value of each OPP varies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * based on the silicon variant in use. Qualcomm Process Voltage Scaling Tables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * defines the voltage and frequency value based on the msm-id in SMEM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * and speedbin blown in the efuse combination.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * The qcom-cpufreq-nvmem driver reads the msm-id and efuse value from the SoC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * to provide the OPP framework with required information.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * This is used to determine the voltage and frequency value for each OPP of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * operating-points-v2 table when it is parsed by the OPP framework.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/nvmem-consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/pm_domain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/pm_opp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/soc/qcom/smem.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define MSM_ID_SMEM 137
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) enum _msm_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MSM8996V3 = 0xF6ul,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) APQ8096V3 = 0x123ul,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MSM8996SG = 0x131ul,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) APQ8096SG = 0x138ul,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) enum _msm8996_version {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MSM8996_V3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MSM8996_SG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) NUM_OF_MSM8996_VERSIONS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct qcom_cpufreq_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct qcom_cpufreq_match_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) int (*get_version)(struct device *cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct nvmem_cell *speedbin_nvmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) char **pvs_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct qcom_cpufreq_drv *drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) const char **genpd_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct qcom_cpufreq_drv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct opp_table **names_opp_tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct opp_table **hw_opp_tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct opp_table **genpd_opp_tables;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 versions;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) const struct qcom_cpufreq_match_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static void get_krait_bin_format_a(struct device *cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int *speed, int *pvs, int *pvs_ver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct nvmem_cell *pvs_nvmem, u8 *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u32 pte_efuse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) pte_efuse = *((u32 *)buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *speed = pte_efuse & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (*speed == 0xf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *speed = (pte_efuse >> 4) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (*speed == 0xf) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) *speed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) dev_warn(cpu_dev, "Speed bin: Defaulting to %d\n", *speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dev_dbg(cpu_dev, "Speed bin: %d\n", *speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *pvs = (pte_efuse >> 10) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (*pvs == 0x7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *pvs = (pte_efuse >> 13) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (*pvs == 0x7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *pvs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dev_warn(cpu_dev, "PVS bin: Defaulting to %d\n", *pvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dev_dbg(cpu_dev, "PVS bin: %d\n", *pvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void get_krait_bin_format_b(struct device *cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int *speed, int *pvs, int *pvs_ver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct nvmem_cell *pvs_nvmem, u8 *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u32 pte_efuse, redundant_sel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) pte_efuse = *((u32 *)buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) redundant_sel = (pte_efuse >> 24) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *pvs_ver = (pte_efuse >> 4) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) switch (redundant_sel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) *speed = (pte_efuse >> 27) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) *pvs = (pte_efuse >> 27) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *speed = pte_efuse & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* 4 bits of PVS are in efuse register bits 31, 8-6. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *speed = pte_efuse & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* Check SPEED_BIN_BLOW_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (pte_efuse & BIT(3)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) dev_dbg(cpu_dev, "Speed bin: %d\n", *speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dev_warn(cpu_dev, "Speed bin not set. Defaulting to 0!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *speed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Check PVS_BLOW_STATUS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) pte_efuse = *(((u32 *)buf) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) pte_efuse &= BIT(21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (pte_efuse) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) dev_dbg(cpu_dev, "PVS bin: %d\n", *pvs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dev_warn(cpu_dev, "PVS bin not set. Defaulting to 0!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *pvs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) u32 *msm_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) enum _msm8996_version version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (IS_ERR(msm_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return NUM_OF_MSM8996_VERSIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* The first 4 bytes are format, next to them is the actual msm-id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) msm_id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) switch ((enum _msm_id)*msm_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case MSM8996V3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case APQ8096V3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) version = MSM8996_V3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case MSM8996SG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) case APQ8096SG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) version = MSM8996_SG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) version = NUM_OF_MSM8996_VERSIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct nvmem_cell *speedbin_nvmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) char **pvs_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct qcom_cpufreq_drv *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u8 *speedbin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) enum _msm8996_version msm8996_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) *pvs_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) msm8996_version = qcom_cpufreq_get_msm_id();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) dev_err(cpu_dev, "Not Snapdragon 820/821!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) speedbin = nvmem_cell_read(speedbin_nvmem, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (IS_ERR(speedbin))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return PTR_ERR(speedbin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) switch (msm8996_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) case MSM8996_V3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) drv->versions = 1 << (unsigned int)(*speedbin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) case MSM8996_SG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) drv->versions = 1 << ((unsigned int)(*speedbin) + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) BUG();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) kfree(speedbin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int qcom_cpufreq_krait_name_version(struct device *cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct nvmem_cell *speedbin_nvmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) char **pvs_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct qcom_cpufreq_drv *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) int speed = 0, pvs = 0, pvs_ver = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u8 *speedbin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) size_t len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) speedbin = nvmem_cell_read(speedbin_nvmem, &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) if (IS_ERR(speedbin))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return PTR_ERR(speedbin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) switch (len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) get_krait_bin_format_a(cpu_dev, &speed, &pvs, &pvs_ver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) speedbin_nvmem, speedbin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) get_krait_bin_format_b(cpu_dev, &speed, &pvs, &pvs_ver,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) speedbin_nvmem, speedbin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dev_err(cpu_dev, "Unable to read nvmem data. Defaulting to 0!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) snprintf(*pvs_name, sizeof("speedXX-pvsXX-vXX"), "speed%d-pvs%d-v%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) speed, pvs, pvs_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) drv->versions = (1 << speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) kfree(speedbin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static const struct qcom_cpufreq_match_data match_data_kryo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) .get_version = qcom_cpufreq_kryo_name_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) static const struct qcom_cpufreq_match_data match_data_krait = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) .get_version = qcom_cpufreq_krait_name_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static const char *qcs404_genpd_names[] = { "cpr", NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static const struct qcom_cpufreq_match_data match_data_qcs404 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .genpd_names = qcs404_genpd_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static int qcom_cpufreq_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct qcom_cpufreq_drv *drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) struct nvmem_cell *speedbin_nvmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct device *cpu_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) char *pvs_name = "speedXX-pvsXX-vXX";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) unsigned cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) cpu_dev = get_cpu_device(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (!cpu_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) np = dev_pm_opp_of_get_opp_desc_node(cpu_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) drv = kzalloc(sizeof(*drv), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) match = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) drv->data = match->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (!drv->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto free_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (drv->data->get_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) speedbin_nvmem = of_nvmem_cell_get(np, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (IS_ERR(speedbin_nvmem)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) dev_err(cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) "Could not get nvmem cell: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) PTR_ERR(speedbin_nvmem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ret = PTR_ERR(speedbin_nvmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) goto free_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ret = drv->data->get_version(cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) speedbin_nvmem, &pvs_name, drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) nvmem_cell_put(speedbin_nvmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) goto free_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) nvmem_cell_put(speedbin_nvmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) drv->names_opp_tables = kcalloc(num_possible_cpus(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) sizeof(*drv->names_opp_tables),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!drv->names_opp_tables) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) goto free_drv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) drv->hw_opp_tables = kcalloc(num_possible_cpus(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) sizeof(*drv->hw_opp_tables),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (!drv->hw_opp_tables) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) goto free_opp_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) drv->genpd_opp_tables = kcalloc(num_possible_cpus(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) sizeof(*drv->genpd_opp_tables),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (!drv->genpd_opp_tables) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) goto free_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) cpu_dev = get_cpu_device(cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (NULL == cpu_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) goto free_genpd_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (drv->data->get_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (pvs_name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) drv->names_opp_tables[cpu] = dev_pm_opp_set_prop_name(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) pvs_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (IS_ERR(drv->names_opp_tables[cpu])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) ret = PTR_ERR(drv->names_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_err(cpu_dev, "Failed to add OPP name %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) pvs_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) goto free_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) drv->hw_opp_tables[cpu] = dev_pm_opp_set_supported_hw(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) cpu_dev, &drv->versions, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) if (IS_ERR(drv->hw_opp_tables[cpu])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ret = PTR_ERR(drv->hw_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev_err(cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) "Failed to set supported hardware\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) goto free_genpd_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (drv->data->genpd_names) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) drv->genpd_opp_tables[cpu] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) dev_pm_opp_attach_genpd(cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) drv->data->genpd_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (IS_ERR(drv->genpd_opp_tables[cpu])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) ret = PTR_ERR(drv->genpd_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) dev_err(cpu_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) "Could not attach to pm_domain: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) goto free_genpd_opp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) cpufreq_dt_pdev = platform_device_register_simple("cpufreq-dt", -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!IS_ERR(cpufreq_dt_pdev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) platform_set_drvdata(pdev, drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) ret = PTR_ERR(cpufreq_dt_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) dev_err(cpu_dev, "Failed to register platform device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) free_genpd_opp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (IS_ERR_OR_NULL(drv->genpd_opp_tables[cpu]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) kfree(drv->genpd_opp_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) free_opp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (IS_ERR_OR_NULL(drv->names_opp_tables[cpu]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dev_pm_opp_put_prop_name(drv->names_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) if (IS_ERR_OR_NULL(drv->hw_opp_tables[cpu]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) kfree(drv->hw_opp_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) free_opp_names:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) kfree(drv->names_opp_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) free_drv:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) kfree(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static int qcom_cpufreq_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) struct qcom_cpufreq_drv *drv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) platform_device_unregister(cpufreq_dt_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) for_each_possible_cpu(cpu) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (drv->names_opp_tables[cpu])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) dev_pm_opp_put_supported_hw(drv->names_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (drv->hw_opp_tables[cpu])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) dev_pm_opp_put_supported_hw(drv->hw_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (drv->genpd_opp_tables[cpu])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dev_pm_opp_detach_genpd(drv->genpd_opp_tables[cpu]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) kfree(drv->names_opp_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) kfree(drv->hw_opp_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) kfree(drv->genpd_opp_tables);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) kfree(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) static struct platform_driver qcom_cpufreq_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) .probe = qcom_cpufreq_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) .remove = qcom_cpufreq_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) .name = "qcom-cpufreq-nvmem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) static const struct of_device_id qcom_cpufreq_match_list[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) { .compatible = "qcom,apq8096", .data = &match_data_kryo },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) { .compatible = "qcom,msm8996", .data = &match_data_kryo },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) { .compatible = "qcom,qcs404", .data = &match_data_qcs404 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) { .compatible = "qcom,ipq8064", .data = &match_data_krait },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) { .compatible = "qcom,apq8064", .data = &match_data_krait },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) { .compatible = "qcom,msm8974", .data = &match_data_krait },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) { .compatible = "qcom,msm8960", .data = &match_data_krait },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) MODULE_DEVICE_TABLE(of, qcom_cpufreq_match_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * Since the driver depends on smem and nvmem drivers, which may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * return EPROBE_DEFER, all the real activity is done in the probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * which may be defered as well. The init here is only registering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * the driver and the platform device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) static int __init qcom_cpufreq_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct device_node *np = of_find_node_by_path("/");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (!np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) match = of_match_node(qcom_cpufreq_match_list, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) of_node_put(np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (!match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ret = platform_driver_register(&qcom_cpufreq_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (unlikely(ret < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) cpufreq_pdev = platform_device_register_data(NULL, "qcom-cpufreq-nvmem",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) -1, match, sizeof(*match));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = PTR_ERR_OR_ZERO(cpufreq_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (0 == ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) platform_driver_unregister(&qcom_cpufreq_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) module_init(qcom_cpufreq_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static void __exit qcom_cpufreq_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) platform_device_unregister(cpufreq_pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) platform_driver_unregister(&qcom_cpufreq_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) module_exit(qcom_cpufreq_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) MODULE_DESCRIPTION("Qualcomm Technologies, Inc. CPUfreq driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) MODULE_LICENSE("GPL v2");