cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

imx-scu-soc.c (2965B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright 2019 NXP.
      4 */
      5
      6#include <dt-bindings/firmware/imx/rsrc.h>
      7#include <linux/firmware/imx/sci.h>
      8#include <linux/slab.h>
      9#include <linux/sys_soc.h>
     10#include <linux/platform_device.h>
     11#include <linux/of.h>
     12
     13static struct imx_sc_ipc *imx_sc_soc_ipc_handle;
     14
     15struct imx_sc_msg_misc_get_soc_id {
     16	struct imx_sc_rpc_msg hdr;
     17	union {
     18		struct {
     19			u32 control;
     20			u16 resource;
     21		} __packed req;
     22		struct {
     23			u32 id;
     24		} resp;
     25	} data;
     26} __packed __aligned(4);
     27
     28struct imx_sc_msg_misc_get_soc_uid {
     29	struct imx_sc_rpc_msg hdr;
     30	u32 uid_low;
     31	u32 uid_high;
     32} __packed;
     33
     34static int imx_scu_soc_uid(u64 *soc_uid)
     35{
     36	struct imx_sc_msg_misc_get_soc_uid msg;
     37	struct imx_sc_rpc_msg *hdr = &msg.hdr;
     38	int ret;
     39
     40	hdr->ver = IMX_SC_RPC_VERSION;
     41	hdr->svc = IMX_SC_RPC_SVC_MISC;
     42	hdr->func = IMX_SC_MISC_FUNC_UNIQUE_ID;
     43	hdr->size = 1;
     44
     45	ret = imx_scu_call_rpc(imx_sc_soc_ipc_handle, &msg, true);
     46	if (ret) {
     47		pr_err("%s: get soc uid failed, ret %d\n", __func__, ret);
     48		return ret;
     49	}
     50
     51	*soc_uid = msg.uid_high;
     52	*soc_uid <<= 32;
     53	*soc_uid |= msg.uid_low;
     54
     55	return 0;
     56}
     57
     58static int imx_scu_soc_id(void)
     59{
     60	struct imx_sc_msg_misc_get_soc_id msg;
     61	struct imx_sc_rpc_msg *hdr = &msg.hdr;
     62	int ret;
     63
     64	hdr->ver = IMX_SC_RPC_VERSION;
     65	hdr->svc = IMX_SC_RPC_SVC_MISC;
     66	hdr->func = IMX_SC_MISC_FUNC_GET_CONTROL;
     67	hdr->size = 3;
     68
     69	msg.data.req.control = IMX_SC_C_ID;
     70	msg.data.req.resource = IMX_SC_R_SYSTEM;
     71
     72	ret = imx_scu_call_rpc(imx_sc_soc_ipc_handle, &msg, true);
     73	if (ret) {
     74		pr_err("%s: get soc info failed, ret %d\n", __func__, ret);
     75		return ret;
     76	}
     77
     78	return msg.data.resp.id;
     79}
     80
     81int imx_scu_soc_init(struct device *dev)
     82{
     83	struct soc_device_attribute *soc_dev_attr;
     84	struct soc_device *soc_dev;
     85	int id, ret;
     86	u64 uid = 0;
     87	u32 val;
     88
     89	ret = imx_scu_get_handle(&imx_sc_soc_ipc_handle);
     90	if (ret)
     91		return ret;
     92
     93	soc_dev_attr = devm_kzalloc(dev, sizeof(*soc_dev_attr),
     94				    GFP_KERNEL);
     95	if (!soc_dev_attr)
     96		return -ENOMEM;
     97
     98	soc_dev_attr->family = "Freescale i.MX";
     99
    100	ret = of_property_read_string(of_root,
    101				      "model",
    102				      &soc_dev_attr->machine);
    103	if (ret)
    104		return ret;
    105
    106	id = imx_scu_soc_id();
    107	if (id < 0)
    108		return -EINVAL;
    109
    110	ret = imx_scu_soc_uid(&uid);
    111	if (ret < 0)
    112		return -EINVAL;
    113
    114	/* format soc_id value passed from SCU firmware */
    115	val = id & 0x1f;
    116	soc_dev_attr->soc_id = devm_kasprintf(dev, GFP_KERNEL, "0x%x", val);
    117	if (!soc_dev_attr->soc_id)
    118		return -ENOMEM;
    119
    120	/* format revision value passed from SCU firmware */
    121	val = (id >> 5) & 0xf;
    122	val = (((val >> 2) + 1) << 4) | (val & 0x3);
    123	soc_dev_attr->revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d",
    124						(val >> 4) & 0xf, val & 0xf);
    125	if (!soc_dev_attr->revision)
    126		return -ENOMEM;
    127
    128	soc_dev_attr->serial_number = devm_kasprintf(dev, GFP_KERNEL,
    129						     "%016llX", uid);
    130	if (!soc_dev_attr->serial_number)
    131		return -ENOMEM;
    132
    133	soc_dev = soc_device_register(soc_dev_attr);
    134	if (IS_ERR(soc_dev))
    135		return PTR_ERR(soc_dev);
    136
    137	return 0;
    138}