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

pl353-smc.c (3819B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * ARM PL353 SMC driver
      4 *
      5 * Copyright (C) 2012 - 2018 Xilinx, Inc
      6 * Author: Punnaiah Choudary Kalluri <punnaiah@xilinx.com>
      7 * Author: Naga Sureshkumar Relli <nagasure@xilinx.com>
      8 */
      9
     10#include <linux/clk.h>
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/of_platform.h>
     14#include <linux/platform_device.h>
     15#include <linux/amba/bus.h>
     16
     17/**
     18 * struct pl353_smc_data - Private smc driver structure
     19 * @memclk:		Pointer to the peripheral clock
     20 * @aclk:		Pointer to the AXI peripheral clock
     21 */
     22struct pl353_smc_data {
     23	struct clk		*memclk;
     24	struct clk		*aclk;
     25};
     26
     27static int __maybe_unused pl353_smc_suspend(struct device *dev)
     28{
     29	struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
     30
     31	clk_disable(pl353_smc->memclk);
     32	clk_disable(pl353_smc->aclk);
     33
     34	return 0;
     35}
     36
     37static int __maybe_unused pl353_smc_resume(struct device *dev)
     38{
     39	struct pl353_smc_data *pl353_smc = dev_get_drvdata(dev);
     40	int ret;
     41
     42	ret = clk_enable(pl353_smc->aclk);
     43	if (ret) {
     44		dev_err(dev, "Cannot enable axi domain clock.\n");
     45		return ret;
     46	}
     47
     48	ret = clk_enable(pl353_smc->memclk);
     49	if (ret) {
     50		dev_err(dev, "Cannot enable memory clock.\n");
     51		clk_disable(pl353_smc->aclk);
     52		return ret;
     53	}
     54
     55	return ret;
     56}
     57
     58static SIMPLE_DEV_PM_OPS(pl353_smc_dev_pm_ops, pl353_smc_suspend,
     59			 pl353_smc_resume);
     60
     61static const struct of_device_id pl353_smc_supported_children[] = {
     62	{
     63		.compatible = "cfi-flash"
     64	},
     65	{
     66		.compatible = "arm,pl353-nand-r2p1",
     67	},
     68	{}
     69};
     70
     71static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id)
     72{
     73	struct device_node *of_node = adev->dev.of_node;
     74	const struct of_device_id *match = NULL;
     75	struct pl353_smc_data *pl353_smc;
     76	struct device_node *child;
     77	int err;
     78
     79	pl353_smc = devm_kzalloc(&adev->dev, sizeof(*pl353_smc), GFP_KERNEL);
     80	if (!pl353_smc)
     81		return -ENOMEM;
     82
     83	pl353_smc->aclk = devm_clk_get(&adev->dev, "apb_pclk");
     84	if (IS_ERR(pl353_smc->aclk)) {
     85		dev_err(&adev->dev, "aclk clock not found.\n");
     86		return PTR_ERR(pl353_smc->aclk);
     87	}
     88
     89	pl353_smc->memclk = devm_clk_get(&adev->dev, "memclk");
     90	if (IS_ERR(pl353_smc->memclk)) {
     91		dev_err(&adev->dev, "memclk clock not found.\n");
     92		return PTR_ERR(pl353_smc->memclk);
     93	}
     94
     95	err = clk_prepare_enable(pl353_smc->aclk);
     96	if (err) {
     97		dev_err(&adev->dev, "Unable to enable AXI clock.\n");
     98		return err;
     99	}
    100
    101	err = clk_prepare_enable(pl353_smc->memclk);
    102	if (err) {
    103		dev_err(&adev->dev, "Unable to enable memory clock.\n");
    104		goto disable_axi_clk;
    105	}
    106
    107	amba_set_drvdata(adev, pl353_smc);
    108
    109	/* Find compatible children. Only a single child is supported */
    110	for_each_available_child_of_node(of_node, child) {
    111		match = of_match_node(pl353_smc_supported_children, child);
    112		if (!match) {
    113			dev_warn(&adev->dev, "unsupported child node\n");
    114			continue;
    115		}
    116		break;
    117	}
    118	if (!match) {
    119		err = -ENODEV;
    120		dev_err(&adev->dev, "no matching children\n");
    121		goto disable_mem_clk;
    122	}
    123
    124	of_platform_device_create(child, NULL, &adev->dev);
    125
    126	return 0;
    127
    128disable_mem_clk:
    129	clk_disable_unprepare(pl353_smc->memclk);
    130disable_axi_clk:
    131	clk_disable_unprepare(pl353_smc->aclk);
    132
    133	return err;
    134}
    135
    136static void pl353_smc_remove(struct amba_device *adev)
    137{
    138	struct pl353_smc_data *pl353_smc = amba_get_drvdata(adev);
    139
    140	clk_disable_unprepare(pl353_smc->memclk);
    141	clk_disable_unprepare(pl353_smc->aclk);
    142}
    143
    144static const struct amba_id pl353_ids[] = {
    145	{
    146		.id = 0x00041353,
    147		.mask = 0x000fffff,
    148	},
    149	{ 0, 0 },
    150};
    151MODULE_DEVICE_TABLE(amba, pl353_ids);
    152
    153static struct amba_driver pl353_smc_driver = {
    154	.drv = {
    155		.owner = THIS_MODULE,
    156		.name = "pl353-smc",
    157		.pm = &pl353_smc_dev_pm_ops,
    158	},
    159	.id_table = pl353_ids,
    160	.probe = pl353_smc_probe,
    161	.remove = pl353_smc_remove,
    162};
    163
    164module_amba_driver(pl353_smc_driver);
    165
    166MODULE_AUTHOR("Xilinx, Inc.");
    167MODULE_DESCRIPTION("ARM PL353 SMC Driver");
    168MODULE_LICENSE("GPL");