^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2012-2014, NVIDIA CORPORATION. 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) #include <linux/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <soc/tegra/fuse.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "fuse.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #define CPU_SPEEDO_LSBIT 20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #define CPU_SPEEDO_MSBIT 29
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define CPU_SPEEDO_REDUND_LSBIT 30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define CPU_SPEEDO_REDUND_MSBIT 39
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define SOC_SPEEDO_LSBIT 40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define SOC_SPEEDO_MSBIT 47
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SOC_SPEEDO_REDUND_LSBIT 48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SOC_SPEEDO_REDUND_MSBIT 55
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SOC_SPEEDO_REDUND_OFFS (SOC_SPEEDO_REDUND_MSBIT - SOC_SPEEDO_MSBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SPEEDO_MULT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PROCESS_CORNERS_NUM 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SPEEDO_ID_SELECT_0(rev) ((rev) <= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SPEEDO_ID_SELECT_1(sku) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) (((sku) != 20) && ((sku) != 23) && ((sku) != 24) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ((sku) != 27) && ((sku) != 28))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) SPEEDO_ID_0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) SPEEDO_ID_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) SPEEDO_ID_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) SPEEDO_ID_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {315, 366, 420, UINT_MAX},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {303, 368, 419, UINT_MAX},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {316, 331, 383, UINT_MAX},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static const u32 __initconst soc_process_speedos[][PROCESS_CORNERS_NUM] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {165, 195, 224, UINT_MAX},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {165, 195, 224, UINT_MAX},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {165, 195, 224, UINT_MAX},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) != SPEEDO_ID_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (SPEEDO_ID_SELECT_0(sku_info->revision))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) sku_info->soc_speedo_id = SPEEDO_ID_0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) else if (SPEEDO_ID_SELECT_1(sku_info->sku_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) sku_info->soc_speedo_id = SPEEDO_ID_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) sku_info->soc_speedo_id = SPEEDO_ID_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) reg = tegra_fuse_read_spare(i) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) tegra_fuse_read_spare(i + CPU_SPEEDO_REDUND_OFFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) val = (val << 1) | (reg & 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) val = val * SPEEDO_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pr_debug("Tegra CPU speedo value %u\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (val <= cpu_process_speedos[sku_info->soc_speedo_id][i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) sku_info->cpu_process_id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) for (i = SOC_SPEEDO_MSBIT; i >= SOC_SPEEDO_LSBIT; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) reg = tegra_fuse_read_spare(i) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) tegra_fuse_read_spare(i + SOC_SPEEDO_REDUND_OFFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) val = (val << 1) | (reg & 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) val = val * SPEEDO_MULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) pr_debug("Core speedo value %u\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if (val <= soc_process_speedos[sku_info->soc_speedo_id][i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) sku_info->soc_process_id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }