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-periph-a10.c (3193B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2015 Altera Corporation. All rights reserved
      4 */
      5#include <linux/slab.h>
      6#include <linux/clk-provider.h>
      7#include <linux/io.h>
      8#include <linux/of.h>
      9
     10#include "clk.h"
     11
     12#define CLK_MGR_FREE_SHIFT		16
     13#define CLK_MGR_FREE_MASK		0x7
     14
     15#define SOCFPGA_MPU_FREE_CLK		"mpu_free_clk"
     16#define SOCFPGA_NOC_FREE_CLK		"noc_free_clk"
     17#define SOCFPGA_SDMMC_FREE_CLK		"sdmmc_free_clk"
     18#define to_socfpga_periph_clk(p) container_of(p, struct socfpga_periph_clk, hw.hw)
     19
     20static unsigned long clk_periclk_recalc_rate(struct clk_hw *hwclk,
     21					     unsigned long parent_rate)
     22{
     23	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
     24	u32 div;
     25
     26	if (socfpgaclk->fixed_div) {
     27		div = socfpgaclk->fixed_div;
     28	} else if (socfpgaclk->div_reg) {
     29		div = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
     30		div &= GENMASK(socfpgaclk->width - 1, 0);
     31		div += 1;
     32	} else {
     33		div = ((readl(socfpgaclk->hw.reg) & 0x7ff) + 1);
     34	}
     35
     36	return parent_rate / div;
     37}
     38
     39static u8 clk_periclk_get_parent(struct clk_hw *hwclk)
     40{
     41	struct socfpga_periph_clk *socfpgaclk = to_socfpga_periph_clk(hwclk);
     42	u32 clk_src;
     43	const char *name = clk_hw_get_name(hwclk);
     44
     45	clk_src = readl(socfpgaclk->hw.reg);
     46	if (streq(name, SOCFPGA_MPU_FREE_CLK) ||
     47	    streq(name, SOCFPGA_NOC_FREE_CLK) ||
     48	    streq(name, SOCFPGA_SDMMC_FREE_CLK))
     49		return (clk_src >> CLK_MGR_FREE_SHIFT) &
     50			CLK_MGR_FREE_MASK;
     51	else
     52		return 0;
     53}
     54
     55static const struct clk_ops periclk_ops = {
     56	.recalc_rate = clk_periclk_recalc_rate,
     57	.get_parent = clk_periclk_get_parent,
     58};
     59
     60static __init void __socfpga_periph_init(struct device_node *node,
     61	const struct clk_ops *ops)
     62{
     63	u32 reg;
     64	struct clk_hw *hw_clk;
     65	struct socfpga_periph_clk *periph_clk;
     66	const char *clk_name = node->name;
     67	const char *parent_name[SOCFPGA_MAX_PARENTS];
     68	struct clk_init_data init;
     69	int rc;
     70	u32 fixed_div;
     71	u32 div_reg[3];
     72
     73	of_property_read_u32(node, "reg", &reg);
     74
     75	periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL);
     76	if (WARN_ON(!periph_clk))
     77		return;
     78
     79	periph_clk->hw.reg = clk_mgr_a10_base_addr + reg;
     80
     81	rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
     82	if (!rc) {
     83		periph_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
     84		periph_clk->shift = div_reg[1];
     85		periph_clk->width = div_reg[2];
     86	} else {
     87		periph_clk->div_reg = NULL;
     88	}
     89
     90	rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
     91	if (rc)
     92		periph_clk->fixed_div = 0;
     93	else
     94		periph_clk->fixed_div = fixed_div;
     95
     96	of_property_read_string(node, "clock-output-names", &clk_name);
     97
     98	init.name = clk_name;
     99	init.ops = ops;
    100	init.flags = 0;
    101
    102	init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
    103	init.parent_names = parent_name;
    104
    105	periph_clk->hw.hw.init = &init;
    106
    107	hw_clk = &periph_clk->hw.hw;
    108
    109	if (clk_hw_register(NULL, hw_clk)) {
    110		kfree(periph_clk);
    111		return;
    112	}
    113	rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk);
    114	if (rc < 0) {
    115		pr_err("Could not register clock provider for node:%s\n",
    116		       clk_name);
    117		goto err_clk;
    118	}
    119
    120	return;
    121
    122err_clk:
    123	clk_hw_unregister(hw_clk);
    124}
    125
    126void __init socfpga_a10_periph_init(struct device_node *node)
    127{
    128	__socfpga_periph_init(node, &periclk_ops);
    129}