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

mcb-lpc.c (3546B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * MEN Chameleon Bus.
      4 *
      5 * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de)
      6 * Author: Andreas Werner <andreas.werner@men.de>
      7 */
      8
      9#include <linux/platform_device.h>
     10#include <linux/module.h>
     11#include <linux/dmi.h>
     12#include <linux/mcb.h>
     13#include <linux/io.h>
     14#include "mcb-internal.h"
     15
     16struct priv {
     17	struct mcb_bus *bus;
     18	struct resource *mem;
     19	void __iomem *base;
     20};
     21
     22static int mcb_lpc_probe(struct platform_device *pdev)
     23{
     24	struct resource *res;
     25	struct priv *priv;
     26	int ret = 0;
     27
     28	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
     29	if (!priv)
     30		return -ENOMEM;
     31
     32	priv->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     33	if (!priv->mem) {
     34		dev_err(&pdev->dev, "No Memory resource\n");
     35		return -ENODEV;
     36	}
     37
     38	res = devm_request_mem_region(&pdev->dev, priv->mem->start,
     39				      resource_size(priv->mem),
     40				      KBUILD_MODNAME);
     41	if (!res) {
     42		dev_err(&pdev->dev, "Failed to request IO memory\n");
     43		return -EBUSY;
     44	}
     45
     46	priv->base = devm_ioremap(&pdev->dev, priv->mem->start,
     47				  resource_size(priv->mem));
     48	if (!priv->base) {
     49		dev_err(&pdev->dev, "Cannot ioremap\n");
     50		return -ENOMEM;
     51	}
     52
     53	platform_set_drvdata(pdev, priv);
     54
     55	priv->bus = mcb_alloc_bus(&pdev->dev);
     56	if (IS_ERR(priv->bus))
     57		return PTR_ERR(priv->bus);
     58
     59	ret = chameleon_parse_cells(priv->bus, priv->mem->start, priv->base);
     60	if (ret < 0) {
     61		mcb_release_bus(priv->bus);
     62		return ret;
     63	}
     64
     65	dev_dbg(&pdev->dev, "Found %d cells\n", ret);
     66
     67	mcb_bus_add_devices(priv->bus);
     68
     69	return 0;
     70
     71}
     72
     73static int mcb_lpc_remove(struct platform_device *pdev)
     74{
     75	struct priv *priv = platform_get_drvdata(pdev);
     76
     77	mcb_release_bus(priv->bus);
     78
     79	return 0;
     80}
     81
     82static struct platform_device *mcb_lpc_pdev;
     83
     84static int mcb_lpc_create_platform_device(const struct dmi_system_id *id)
     85{
     86	struct resource *res = id->driver_data;
     87	int ret;
     88
     89	mcb_lpc_pdev = platform_device_alloc("mcb-lpc", -1);
     90	if (!mcb_lpc_pdev)
     91		return -ENOMEM;
     92
     93	ret = platform_device_add_resources(mcb_lpc_pdev, res, 1);
     94	if (ret)
     95		goto out_put;
     96
     97	ret = platform_device_add(mcb_lpc_pdev);
     98	if (ret)
     99		goto out_put;
    100
    101	return 0;
    102
    103out_put:
    104	platform_device_put(mcb_lpc_pdev);
    105	return ret;
    106}
    107
    108static struct resource sc24_fpga_resource = DEFINE_RES_MEM(0xe000e000, CHAM_HEADER_SIZE);
    109static struct resource sc31_fpga_resource = DEFINE_RES_MEM(0xf000e000, CHAM_HEADER_SIZE);
    110
    111static struct platform_driver mcb_lpc_driver = {
    112	.driver		= {
    113		.name = "mcb-lpc",
    114	},
    115	.probe		= mcb_lpc_probe,
    116	.remove		= mcb_lpc_remove,
    117};
    118
    119static const struct dmi_system_id mcb_lpc_dmi_table[] = {
    120	{
    121		.ident = "SC24",
    122		.matches = {
    123			DMI_MATCH(DMI_SYS_VENDOR, "MEN"),
    124			DMI_MATCH(DMI_PRODUCT_VERSION, "14SC24"),
    125		},
    126		.driver_data = (void *)&sc24_fpga_resource,
    127		.callback = mcb_lpc_create_platform_device,
    128	},
    129	{
    130		.ident = "SC31",
    131		.matches = {
    132			DMI_MATCH(DMI_SYS_VENDOR, "MEN"),
    133			DMI_MATCH(DMI_PRODUCT_VERSION, "14SC31"),
    134		},
    135		.driver_data = (void *)&sc31_fpga_resource,
    136		.callback = mcb_lpc_create_platform_device,
    137	},
    138	{}
    139};
    140MODULE_DEVICE_TABLE(dmi, mcb_lpc_dmi_table);
    141
    142static int __init mcb_lpc_init(void)
    143{
    144	if (!dmi_check_system(mcb_lpc_dmi_table))
    145		return -ENODEV;
    146
    147	return platform_driver_register(&mcb_lpc_driver);
    148}
    149
    150static void __exit mcb_lpc_exit(void)
    151{
    152	platform_device_unregister(mcb_lpc_pdev);
    153	platform_driver_unregister(&mcb_lpc_driver);
    154}
    155
    156module_init(mcb_lpc_init);
    157module_exit(mcb_lpc_exit);
    158
    159MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
    160MODULE_LICENSE("GPL");
    161MODULE_DESCRIPTION("MCB over LPC support");
    162MODULE_IMPORT_NS(MCB);