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

meson-mx-socinfo.c (4139B)


      1/*
      2 * Copyright (c) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
      3 *
      4 * SPDX-License-Identifier: GPL-2.0+
      5 */
      6
      7#include <linux/io.h>
      8#include <linux/of.h>
      9#include <linux/of_address.h>
     10#include <linux/of_platform.h>
     11#include <linux/platform_device.h>
     12#include <linux/slab.h>
     13#include <linux/sys_soc.h>
     14#include <linux/bitfield.h>
     15#include <linux/regmap.h>
     16#include <linux/mfd/syscon.h>
     17
     18#define MESON_SOCINFO_MAJOR_VER_MESON6		0x16
     19#define MESON_SOCINFO_MAJOR_VER_MESON8		0x19
     20#define MESON_SOCINFO_MAJOR_VER_MESON8B		0x1b
     21
     22#define MESON_MX_ASSIST_HW_REV			0x14c
     23
     24#define MESON_MX_ANALOG_TOP_METAL_REVISION	0x0
     25
     26#define MESON_MX_BOOTROM_MISC_VER		0x4
     27
     28static const char *meson_mx_socinfo_revision(unsigned int major_ver,
     29					     unsigned int misc_ver,
     30					     unsigned int metal_rev)
     31{
     32	unsigned int minor_ver;
     33
     34	switch (major_ver) {
     35	case MESON_SOCINFO_MAJOR_VER_MESON6:
     36		minor_ver = 0xa;
     37		break;
     38
     39	case MESON_SOCINFO_MAJOR_VER_MESON8:
     40		if (metal_rev == 0x11111112)
     41			major_ver = 0x1d;
     42
     43		if (metal_rev == 0x11111111 || metal_rev == 0x11111112)
     44			minor_ver = 0xa;
     45		else if (metal_rev == 0x11111113)
     46			minor_ver = 0xb;
     47		else if (metal_rev == 0x11111133)
     48			minor_ver = 0xc;
     49		else
     50			minor_ver = 0xd;
     51
     52		break;
     53
     54	case MESON_SOCINFO_MAJOR_VER_MESON8B:
     55		if (metal_rev == 0x11111111)
     56			minor_ver = 0xa;
     57		else
     58			minor_ver = 0xb;
     59
     60		break;
     61
     62	default:
     63		minor_ver = 0x0;
     64		break;
     65	}
     66
     67	return kasprintf(GFP_KERNEL, "Rev%X (%x - 0:%X)", minor_ver, major_ver,
     68			 misc_ver);
     69}
     70
     71static const char *meson_mx_socinfo_soc_id(unsigned int major_ver,
     72					   unsigned int metal_rev)
     73{
     74	const char *soc_id;
     75
     76	switch (major_ver) {
     77	case MESON_SOCINFO_MAJOR_VER_MESON6:
     78		soc_id = "Meson6 (AML8726-MX)";
     79		break;
     80
     81	case MESON_SOCINFO_MAJOR_VER_MESON8:
     82		if (metal_rev == 0x11111112)
     83			soc_id = "Meson8m2 (S812)";
     84		else
     85			soc_id = "Meson8 (S802)";
     86
     87		break;
     88
     89	case MESON_SOCINFO_MAJOR_VER_MESON8B:
     90		soc_id = "Meson8b (S805)";
     91		break;
     92
     93	default:
     94		soc_id = "Unknown";
     95		break;
     96	}
     97
     98	return kstrdup_const(soc_id, GFP_KERNEL);
     99}
    100
    101static const struct of_device_id meson_mx_socinfo_analog_top_ids[] = {
    102	{ .compatible = "amlogic,meson8-analog-top", },
    103	{ .compatible = "amlogic,meson8b-analog-top", },
    104	{ /* sentinel */ }
    105};
    106
    107static int __init meson_mx_socinfo_init(void)
    108{
    109	struct soc_device_attribute *soc_dev_attr;
    110	struct soc_device *soc_dev;
    111	struct device_node *np;
    112	struct regmap *assist_regmap, *bootrom_regmap, *analog_top_regmap;
    113	unsigned int major_ver, misc_ver, metal_rev = 0;
    114	int ret;
    115
    116	assist_regmap =
    117		syscon_regmap_lookup_by_compatible("amlogic,meson-mx-assist");
    118	if (IS_ERR(assist_regmap))
    119		return PTR_ERR(assist_regmap);
    120
    121	bootrom_regmap =
    122		syscon_regmap_lookup_by_compatible("amlogic,meson-mx-bootrom");
    123	if (IS_ERR(bootrom_regmap))
    124		return PTR_ERR(bootrom_regmap);
    125
    126	np = of_find_matching_node(NULL, meson_mx_socinfo_analog_top_ids);
    127	if (np) {
    128		analog_top_regmap = syscon_node_to_regmap(np);
    129		if (IS_ERR(analog_top_regmap))
    130			return PTR_ERR(analog_top_regmap);
    131
    132		ret = regmap_read(analog_top_regmap,
    133				  MESON_MX_ANALOG_TOP_METAL_REVISION,
    134				  &metal_rev);
    135		if (ret)
    136			return ret;
    137	}
    138
    139	ret = regmap_read(assist_regmap, MESON_MX_ASSIST_HW_REV, &major_ver);
    140	if (ret < 0)
    141		return ret;
    142
    143	ret = regmap_read(bootrom_regmap, MESON_MX_BOOTROM_MISC_VER,
    144			  &misc_ver);
    145	if (ret < 0)
    146		return ret;
    147
    148	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
    149	if (!soc_dev_attr)
    150		return -ENODEV;
    151
    152	soc_dev_attr->family = "Amlogic Meson";
    153
    154	np = of_find_node_by_path("/");
    155	of_property_read_string(np, "model", &soc_dev_attr->machine);
    156	of_node_put(np);
    157
    158	soc_dev_attr->revision = meson_mx_socinfo_revision(major_ver, misc_ver,
    159							   metal_rev);
    160	soc_dev_attr->soc_id = meson_mx_socinfo_soc_id(major_ver, metal_rev);
    161
    162	soc_dev = soc_device_register(soc_dev_attr);
    163	if (IS_ERR(soc_dev)) {
    164		kfree_const(soc_dev_attr->revision);
    165		kfree_const(soc_dev_attr->soc_id);
    166		kfree(soc_dev_attr);
    167		return PTR_ERR(soc_dev);
    168	}
    169
    170	dev_info(soc_device_to_device(soc_dev), "Amlogic %s %s detected\n",
    171		 soc_dev_attr->soc_id, soc_dev_attr->revision);
    172
    173	return 0;
    174}
    175device_initcall(meson_mx_socinfo_init);