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

clk-a10-ve.c (3647B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright 2015 Chen-Yu Tsai
      4 *
      5 * Chen-Yu Tsai <wens@csie.org>
      6 */
      7
      8#include <linux/clk-provider.h>
      9#include <linux/io.h>
     10#include <linux/of.h>
     11#include <linux/of_address.h>
     12#include <linux/reset-controller.h>
     13#include <linux/slab.h>
     14#include <linux/spinlock.h>
     15
     16static DEFINE_SPINLOCK(ve_lock);
     17
     18#define SUN4I_VE_ENABLE		31
     19#define SUN4I_VE_DIVIDER_SHIFT	16
     20#define SUN4I_VE_DIVIDER_WIDTH	3
     21#define SUN4I_VE_RESET		0
     22
     23/*
     24 * sunxi_ve_reset... - reset bit in ve clk registers handling
     25 */
     26
     27struct ve_reset_data {
     28	void __iomem			*reg;
     29	spinlock_t			*lock;
     30	struct reset_controller_dev	rcdev;
     31};
     32
     33static int sunxi_ve_reset_assert(struct reset_controller_dev *rcdev,
     34				 unsigned long id)
     35{
     36	struct ve_reset_data *data = container_of(rcdev,
     37						  struct ve_reset_data,
     38						  rcdev);
     39	unsigned long flags;
     40	u32 reg;
     41
     42	spin_lock_irqsave(data->lock, flags);
     43
     44	reg = readl(data->reg);
     45	writel(reg & ~BIT(SUN4I_VE_RESET), data->reg);
     46
     47	spin_unlock_irqrestore(data->lock, flags);
     48
     49	return 0;
     50}
     51
     52static int sunxi_ve_reset_deassert(struct reset_controller_dev *rcdev,
     53				   unsigned long id)
     54{
     55	struct ve_reset_data *data = container_of(rcdev,
     56						  struct ve_reset_data,
     57						  rcdev);
     58	unsigned long flags;
     59	u32 reg;
     60
     61	spin_lock_irqsave(data->lock, flags);
     62
     63	reg = readl(data->reg);
     64	writel(reg | BIT(SUN4I_VE_RESET), data->reg);
     65
     66	spin_unlock_irqrestore(data->lock, flags);
     67
     68	return 0;
     69}
     70
     71static int sunxi_ve_of_xlate(struct reset_controller_dev *rcdev,
     72			     const struct of_phandle_args *reset_spec)
     73{
     74	if (WARN_ON(reset_spec->args_count != 0))
     75		return -EINVAL;
     76
     77	return 0;
     78}
     79
     80static const struct reset_control_ops sunxi_ve_reset_ops = {
     81	.assert		= sunxi_ve_reset_assert,
     82	.deassert	= sunxi_ve_reset_deassert,
     83};
     84
     85static void __init sun4i_ve_clk_setup(struct device_node *node)
     86{
     87	struct clk *clk;
     88	struct clk_divider *div;
     89	struct clk_gate *gate;
     90	struct ve_reset_data *reset_data;
     91	const char *parent;
     92	const char *clk_name = node->name;
     93	void __iomem *reg;
     94	int err;
     95
     96	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
     97	if (IS_ERR(reg))
     98		return;
     99
    100	div = kzalloc(sizeof(*div), GFP_KERNEL);
    101	if (!div)
    102		goto err_unmap;
    103
    104	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
    105	if (!gate)
    106		goto err_free_div;
    107
    108	of_property_read_string(node, "clock-output-names", &clk_name);
    109	parent = of_clk_get_parent_name(node, 0);
    110
    111	gate->reg = reg;
    112	gate->bit_idx = SUN4I_VE_ENABLE;
    113	gate->lock = &ve_lock;
    114
    115	div->reg = reg;
    116	div->shift = SUN4I_VE_DIVIDER_SHIFT;
    117	div->width = SUN4I_VE_DIVIDER_WIDTH;
    118	div->lock = &ve_lock;
    119
    120	clk = clk_register_composite(NULL, clk_name, &parent, 1,
    121				     NULL, NULL,
    122				     &div->hw, &clk_divider_ops,
    123				     &gate->hw, &clk_gate_ops,
    124				     CLK_SET_RATE_PARENT);
    125	if (IS_ERR(clk))
    126		goto err_free_gate;
    127
    128	err = of_clk_add_provider(node, of_clk_src_simple_get, clk);
    129	if (err)
    130		goto err_unregister_clk;
    131
    132	reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
    133	if (!reset_data)
    134		goto err_del_provider;
    135
    136	reset_data->reg = reg;
    137	reset_data->lock = &ve_lock;
    138	reset_data->rcdev.nr_resets = 1;
    139	reset_data->rcdev.ops = &sunxi_ve_reset_ops;
    140	reset_data->rcdev.of_node = node;
    141	reset_data->rcdev.of_xlate = sunxi_ve_of_xlate;
    142	reset_data->rcdev.of_reset_n_cells = 0;
    143	err = reset_controller_register(&reset_data->rcdev);
    144	if (err)
    145		goto err_free_reset;
    146
    147	return;
    148
    149err_free_reset:
    150	kfree(reset_data);
    151err_del_provider:
    152	of_clk_del_provider(node);
    153err_unregister_clk:
    154	clk_unregister(clk);
    155err_free_gate:
    156	kfree(gate);
    157err_free_div:
    158	kfree(div);
    159err_unmap:
    160	iounmap(reg);
    161}
    162CLK_OF_DECLARE(sun4i_ve, "allwinner,sun4i-a10-ve-clk",
    163	       sun4i_ve_clk_setup);