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

reset-uniphier-glue.c (4912B)


      1// SPDX-License-Identifier: GPL-2.0
      2//
      3// reset-uniphier-glue.c - Glue layer reset driver for UniPhier
      4// Copyright 2018 Socionext Inc.
      5// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
      6
      7#include <linux/clk.h>
      8#include <linux/module.h>
      9#include <linux/of_device.h>
     10#include <linux/platform_device.h>
     11#include <linux/reset.h>
     12#include <linux/reset/reset-simple.h>
     13
     14#define MAX_CLKS	2
     15#define MAX_RSTS	2
     16
     17struct uniphier_glue_reset_soc_data {
     18	int nclks;
     19	const char * const *clock_names;
     20	int nrsts;
     21	const char * const *reset_names;
     22};
     23
     24struct uniphier_glue_reset_priv {
     25	struct clk_bulk_data clk[MAX_CLKS];
     26	struct reset_control_bulk_data rst[MAX_RSTS];
     27	struct reset_simple_data rdata;
     28	const struct uniphier_glue_reset_soc_data *data;
     29};
     30
     31static void uniphier_clk_disable(void *_priv)
     32{
     33	struct uniphier_glue_reset_priv *priv = _priv;
     34
     35	clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
     36}
     37
     38static void uniphier_rst_assert(void *_priv)
     39{
     40	struct uniphier_glue_reset_priv *priv = _priv;
     41
     42	reset_control_bulk_assert(priv->data->nrsts, priv->rst);
     43}
     44
     45static int uniphier_glue_reset_probe(struct platform_device *pdev)
     46{
     47	struct device *dev = &pdev->dev;
     48	struct uniphier_glue_reset_priv *priv;
     49	struct resource *res;
     50	resource_size_t size;
     51	int i, ret;
     52
     53	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
     54	if (!priv)
     55		return -ENOMEM;
     56
     57	priv->data = of_device_get_match_data(dev);
     58	if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
     59		    priv->data->nrsts > MAX_RSTS))
     60		return -EINVAL;
     61
     62	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     63	size = resource_size(res);
     64	priv->rdata.membase = devm_ioremap_resource(dev, res);
     65	if (IS_ERR(priv->rdata.membase))
     66		return PTR_ERR(priv->rdata.membase);
     67
     68	for (i = 0; i < priv->data->nclks; i++)
     69		priv->clk[i].id = priv->data->clock_names[i];
     70	ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
     71	if (ret)
     72		return ret;
     73
     74	for (i = 0; i < priv->data->nrsts; i++)
     75		priv->rst[i].id = priv->data->reset_names[i];
     76	ret = devm_reset_control_bulk_get_shared(dev, priv->data->nrsts,
     77						 priv->rst);
     78	if (ret)
     79		return ret;
     80
     81	ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
     82	if (ret)
     83		return ret;
     84
     85	ret = devm_add_action_or_reset(dev, uniphier_clk_disable, priv);
     86	if (ret)
     87		return ret;
     88
     89	ret = reset_control_bulk_deassert(priv->data->nrsts, priv->rst);
     90	if (ret)
     91		return ret;
     92
     93	ret = devm_add_action_or_reset(dev, uniphier_rst_assert, priv);
     94	if (ret)
     95		return ret;
     96
     97	spin_lock_init(&priv->rdata.lock);
     98	priv->rdata.rcdev.owner = THIS_MODULE;
     99	priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
    100	priv->rdata.rcdev.ops = &reset_simple_ops;
    101	priv->rdata.rcdev.of_node = dev->of_node;
    102	priv->rdata.active_low = true;
    103
    104	platform_set_drvdata(pdev, priv);
    105
    106	return devm_reset_controller_register(dev, &priv->rdata.rcdev);
    107}
    108
    109static const char * const uniphier_pro4_clock_reset_names[] = {
    110	"gio", "link",
    111};
    112
    113static const struct uniphier_glue_reset_soc_data uniphier_pro4_data = {
    114	.nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
    115	.clock_names = uniphier_pro4_clock_reset_names,
    116	.nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
    117	.reset_names = uniphier_pro4_clock_reset_names,
    118};
    119
    120static const char * const uniphier_pxs2_clock_reset_names[] = {
    121	"link",
    122};
    123
    124static const struct uniphier_glue_reset_soc_data uniphier_pxs2_data = {
    125	.nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
    126	.clock_names = uniphier_pxs2_clock_reset_names,
    127	.nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
    128	.reset_names = uniphier_pxs2_clock_reset_names,
    129};
    130
    131static const struct of_device_id uniphier_glue_reset_match[] = {
    132	{
    133		.compatible = "socionext,uniphier-pro4-usb3-reset",
    134		.data = &uniphier_pro4_data,
    135	},
    136	{
    137		.compatible = "socionext,uniphier-pro5-usb3-reset",
    138		.data = &uniphier_pro4_data,
    139	},
    140	{
    141		.compatible = "socionext,uniphier-pxs2-usb3-reset",
    142		.data = &uniphier_pxs2_data,
    143	},
    144	{
    145		.compatible = "socionext,uniphier-ld20-usb3-reset",
    146		.data = &uniphier_pxs2_data,
    147	},
    148	{
    149		.compatible = "socionext,uniphier-pxs3-usb3-reset",
    150		.data = &uniphier_pxs2_data,
    151	},
    152	{
    153		.compatible = "socionext,uniphier-nx1-usb3-reset",
    154		.data = &uniphier_pxs2_data,
    155	},
    156	{
    157		.compatible = "socionext,uniphier-pro4-ahci-reset",
    158		.data = &uniphier_pro4_data,
    159	},
    160	{
    161		.compatible = "socionext,uniphier-pxs2-ahci-reset",
    162		.data = &uniphier_pxs2_data,
    163	},
    164	{
    165		.compatible = "socionext,uniphier-pxs3-ahci-reset",
    166		.data = &uniphier_pxs2_data,
    167	},
    168	{ /* Sentinel */ }
    169};
    170MODULE_DEVICE_TABLE(of, uniphier_glue_reset_match);
    171
    172static struct platform_driver uniphier_glue_reset_driver = {
    173	.probe = uniphier_glue_reset_probe,
    174	.driver = {
    175		.name = "uniphier-glue-reset",
    176		.of_match_table = uniphier_glue_reset_match,
    177	},
    178};
    179module_platform_driver(uniphier_glue_reset_driver);
    180
    181MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
    182MODULE_DESCRIPTION("UniPhier Glue layer reset driver");
    183MODULE_LICENSE("GPL");