summaryrefslogtreecommitdiff
path: root/bsp/spacemit/dm/soc/spacemit-socinfo.c
blob: df4fdc9bbce9f7550e7f7cee9713d699ff0bc6b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (c) 2006-2024, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-5-1       GuEe-GUI     first version
 */

#include <rtthread.h>
#include <rtdevice.h>

#define DBG_TAG "soc.info"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>

struct spacemit_soc_info
{
    rt_uint32_t die_id;     /* Die/wafer id */
    rt_uint32_t ver_id;     /* Die/wafer version */
    rt_uint32_t pack_id;    /* Package id */
    rt_uint32_t svtdro;     /* Dro vaule */
    rt_uint64_t chipid;     /* Chip serial number */
    rt_uint32_t soc_id;     /* SoC id */
    char *name;             /* Chip name */
};

struct spacemit_soc_id
{
    const char *name;
    rt_uint32_t id;
};

static const struct spacemit_soc_id soc_ids[] =
{
    { "unknown", 0x00000000 },
    /* k1 serial soc */
    { "M1-8571", 0x36070000 },
    { "K1-6370", 0x36070009 },
    { "K1-6350", 0x36070012 },
    { "K1-6371", 0x36070040 },
    { "M103-6370", 0x36070109 },
    { "M103-6371", 0x36070140 },
};

static const char *soc_id_to_chip_name(rt_uint32_t die_id, rt_uint32_t ver_id, rt_uint32_t pack_id)
{
    rt_uint32_t soc_id = (die_id << 16) | (pack_id);

    for (int i = 0; i < RT_ARRAY_SIZE(soc_ids); ++i)
    {
        if (soc_id == soc_ids[i].id)
        {
            return soc_ids[i].name;
        }
    }

    /* The soc id is unknown */
    return soc_ids[0].name;
}

static rt_ssize_t socinfo_get_nvparam(struct rt_device *dev, char *cell_name, void *val, rt_size_t size)
{
    rt_ssize_t res;
    struct rt_nvmem_cell *cell;

    cell = rt_nvmem_get_cell_by_name(dev, cell_name);
    if (rt_is_err(cell))
    {
        LOG_E("NVMEM cell get %s failed", cell_name);
        return rt_ptr_err(cell);
    }

    res = rt_nvmem_cell_read(cell, val, rt_min_t(rt_size_t, cell->bytes, size));
    if (res < 0)
    {
        LOG_E("NVMEM cell read %s failed", cell_name);
        goto _end;
    }

_end:
    rt_nvmem_put_cell(cell);

    return res;
}

static rt_err_t spacemit_socinfo_probe(struct rt_platform_device *pdev)
{
    rt_ssize_t res;
    struct rt_device *dev = &pdev->parent;
    struct spacemit_soc_info socinfo;

    rt_memset(&socinfo, 0, sizeof(socinfo));

    if ((res = socinfo_get_nvparam(dev, "soc_die_id",
        &socinfo.die_id, sizeof(socinfo.die_id))) <= 0)
    {
        LOG_E("Try to get soc_%s from efuse failed", "die_id");
    }

    if ((res = socinfo_get_nvparam(dev, "soc_ver_id",
        &socinfo.ver_id, sizeof(socinfo.ver_id))) <= 0)
    {
        LOG_E("Try to get soc_%s from efuse failed", "ver_id");
    }

    if ((res = socinfo_get_nvparam(dev, "soc_pack_id",
        &socinfo.pack_id, sizeof(socinfo.pack_id))) <= 0)
    {
        LOG_E("Try to get soc_%s from efuse failed", "pack_id");
    }

    if ((res = socinfo_get_nvparam(dev, "soc_svt_dro",
        &socinfo.svtdro, sizeof(socinfo.svtdro))) <= 0)
    {
        LOG_E("Try to get soc_%s from efuse failed", "svt_dro");
    }

    if ((res = socinfo_get_nvparam(dev, "soc_chip_id",
        &socinfo.chipid, sizeof(socinfo.chipid))) <= 0)
    {
        LOG_E("Try to get soc_%s from efuse failed", "chip_id");
    }

    socinfo.soc_id = (socinfo.die_id << 16) | socinfo.pack_id;

    LOG_I("Revision : %c", (socinfo.ver_id + 'A') & 0xff);
    LOG_I("ID       : %s", soc_id_to_chip_name(socinfo.die_id, socinfo.ver_id, socinfo.pack_id));
    LOG_I("Serial No: %016lx", socinfo.chipid);

    return RT_EOK;
}

static const struct rt_ofw_node_id spacemit_socinfo_ofw_ids[] =
{
    { .compatible = "spacemit,socinfo-k1x" },
    { /* sentinel */ }
};

static struct rt_platform_driver spacemit_socinfo_driver =
{
    .name = "spacemit-socinfo",
    .ids = spacemit_socinfo_ofw_ids,

    .probe = spacemit_socinfo_probe,
};
RT_PLATFORM_DRIVER_EXPORT(spacemit_socinfo_driver);