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.c (7794B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Hisilicon clock driver
      4 *
      5 * Copyright (c) 2012-2013 Hisilicon Limited.
      6 * Copyright (c) 2012-2013 Linaro Limited.
      7 *
      8 * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
      9 *	   Xin Li <li.xin@linaro.org>
     10 */
     11
     12#include <linux/kernel.h>
     13#include <linux/clkdev.h>
     14#include <linux/clk-provider.h>
     15#include <linux/delay.h>
     16#include <linux/io.h>
     17#include <linux/of.h>
     18#include <linux/of_address.h>
     19#include <linux/of_device.h>
     20#include <linux/slab.h>
     21
     22#include "clk.h"
     23
     24static DEFINE_SPINLOCK(hisi_clk_lock);
     25
     26struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
     27						int nr_clks)
     28{
     29	struct hisi_clock_data *clk_data;
     30	struct resource *res;
     31	struct clk **clk_table;
     32
     33	clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
     34	if (!clk_data)
     35		return NULL;
     36
     37	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
     38	if (!res)
     39		return NULL;
     40	clk_data->base = devm_ioremap(&pdev->dev,
     41				res->start, resource_size(res));
     42	if (!clk_data->base)
     43		return NULL;
     44
     45	clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
     46				       sizeof(*clk_table),
     47				       GFP_KERNEL);
     48	if (!clk_table)
     49		return NULL;
     50
     51	clk_data->clk_data.clks = clk_table;
     52	clk_data->clk_data.clk_num = nr_clks;
     53
     54	return clk_data;
     55}
     56EXPORT_SYMBOL_GPL(hisi_clk_alloc);
     57
     58struct hisi_clock_data *hisi_clk_init(struct device_node *np,
     59					     int nr_clks)
     60{
     61	struct hisi_clock_data *clk_data;
     62	struct clk **clk_table;
     63	void __iomem *base;
     64
     65	base = of_iomap(np, 0);
     66	if (!base) {
     67		pr_err("%s: failed to map clock registers\n", __func__);
     68		goto err;
     69	}
     70
     71	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
     72	if (!clk_data)
     73		goto err;
     74
     75	clk_data->base = base;
     76	clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
     77	if (!clk_table)
     78		goto err_data;
     79
     80	clk_data->clk_data.clks = clk_table;
     81	clk_data->clk_data.clk_num = nr_clks;
     82	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
     83	return clk_data;
     84err_data:
     85	kfree(clk_data);
     86err:
     87	return NULL;
     88}
     89EXPORT_SYMBOL_GPL(hisi_clk_init);
     90
     91int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
     92					 int nums, struct hisi_clock_data *data)
     93{
     94	struct clk *clk;
     95	int i;
     96
     97	for (i = 0; i < nums; i++) {
     98		clk = clk_register_fixed_rate(NULL, clks[i].name,
     99					      clks[i].parent_name,
    100					      clks[i].flags,
    101					      clks[i].fixed_rate);
    102		if (IS_ERR(clk)) {
    103			pr_err("%s: failed to register clock %s\n",
    104			       __func__, clks[i].name);
    105			goto err;
    106		}
    107		data->clk_data.clks[clks[i].id] = clk;
    108	}
    109
    110	return 0;
    111
    112err:
    113	while (i--)
    114		clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
    115
    116	return PTR_ERR(clk);
    117}
    118EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);
    119
    120int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
    121					   int nums,
    122					   struct hisi_clock_data *data)
    123{
    124	struct clk *clk;
    125	int i;
    126
    127	for (i = 0; i < nums; i++) {
    128		clk = clk_register_fixed_factor(NULL, clks[i].name,
    129						clks[i].parent_name,
    130						clks[i].flags, clks[i].mult,
    131						clks[i].div);
    132		if (IS_ERR(clk)) {
    133			pr_err("%s: failed to register clock %s\n",
    134			       __func__, clks[i].name);
    135			goto err;
    136		}
    137		data->clk_data.clks[clks[i].id] = clk;
    138	}
    139
    140	return 0;
    141
    142err:
    143	while (i--)
    144		clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
    145
    146	return PTR_ERR(clk);
    147}
    148EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);
    149
    150int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
    151				  int nums, struct hisi_clock_data *data)
    152{
    153	struct clk *clk;
    154	void __iomem *base = data->base;
    155	int i;
    156
    157	for (i = 0; i < nums; i++) {
    158		u32 mask = BIT(clks[i].width) - 1;
    159
    160		clk = clk_register_mux_table(NULL, clks[i].name,
    161					clks[i].parent_names,
    162					clks[i].num_parents, clks[i].flags,
    163					base + clks[i].offset, clks[i].shift,
    164					mask, clks[i].mux_flags,
    165					clks[i].table, &hisi_clk_lock);
    166		if (IS_ERR(clk)) {
    167			pr_err("%s: failed to register clock %s\n",
    168			       __func__, clks[i].name);
    169			goto err;
    170		}
    171
    172		if (clks[i].alias)
    173			clk_register_clkdev(clk, clks[i].alias, NULL);
    174
    175		data->clk_data.clks[clks[i].id] = clk;
    176	}
    177
    178	return 0;
    179
    180err:
    181	while (i--)
    182		clk_unregister_mux(data->clk_data.clks[clks[i].id]);
    183
    184	return PTR_ERR(clk);
    185}
    186EXPORT_SYMBOL_GPL(hisi_clk_register_mux);
    187
    188int hisi_clk_register_phase(struct device *dev,
    189			    const struct hisi_phase_clock *clks,
    190			    int nums, struct hisi_clock_data *data)
    191{
    192	void __iomem *base = data->base;
    193	struct clk *clk;
    194	int i;
    195
    196	for (i = 0; i < nums; i++) {
    197		clk = clk_register_hisi_phase(dev, &clks[i], base,
    198					      &hisi_clk_lock);
    199		if (IS_ERR(clk)) {
    200			pr_err("%s: failed to register clock %s\n", __func__,
    201			       clks[i].name);
    202			return PTR_ERR(clk);
    203		}
    204
    205		data->clk_data.clks[clks[i].id] = clk;
    206	}
    207
    208	return 0;
    209}
    210EXPORT_SYMBOL_GPL(hisi_clk_register_phase);
    211
    212int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
    213				      int nums, struct hisi_clock_data *data)
    214{
    215	struct clk *clk;
    216	void __iomem *base = data->base;
    217	int i;
    218
    219	for (i = 0; i < nums; i++) {
    220		clk = clk_register_divider_table(NULL, clks[i].name,
    221						 clks[i].parent_name,
    222						 clks[i].flags,
    223						 base + clks[i].offset,
    224						 clks[i].shift, clks[i].width,
    225						 clks[i].div_flags,
    226						 clks[i].table,
    227						 &hisi_clk_lock);
    228		if (IS_ERR(clk)) {
    229			pr_err("%s: failed to register clock %s\n",
    230			       __func__, clks[i].name);
    231			goto err;
    232		}
    233
    234		if (clks[i].alias)
    235			clk_register_clkdev(clk, clks[i].alias, NULL);
    236
    237		data->clk_data.clks[clks[i].id] = clk;
    238	}
    239
    240	return 0;
    241
    242err:
    243	while (i--)
    244		clk_unregister_divider(data->clk_data.clks[clks[i].id]);
    245
    246	return PTR_ERR(clk);
    247}
    248EXPORT_SYMBOL_GPL(hisi_clk_register_divider);
    249
    250int hisi_clk_register_gate(const struct hisi_gate_clock *clks,
    251				       int nums, struct hisi_clock_data *data)
    252{
    253	struct clk *clk;
    254	void __iomem *base = data->base;
    255	int i;
    256
    257	for (i = 0; i < nums; i++) {
    258		clk = clk_register_gate(NULL, clks[i].name,
    259						clks[i].parent_name,
    260						clks[i].flags,
    261						base + clks[i].offset,
    262						clks[i].bit_idx,
    263						clks[i].gate_flags,
    264						&hisi_clk_lock);
    265		if (IS_ERR(clk)) {
    266			pr_err("%s: failed to register clock %s\n",
    267			       __func__, clks[i].name);
    268			goto err;
    269		}
    270
    271		if (clks[i].alias)
    272			clk_register_clkdev(clk, clks[i].alias, NULL);
    273
    274		data->clk_data.clks[clks[i].id] = clk;
    275	}
    276
    277	return 0;
    278
    279err:
    280	while (i--)
    281		clk_unregister_gate(data->clk_data.clks[clks[i].id]);
    282
    283	return PTR_ERR(clk);
    284}
    285EXPORT_SYMBOL_GPL(hisi_clk_register_gate);
    286
    287void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks,
    288				       int nums, struct hisi_clock_data *data)
    289{
    290	struct clk *clk;
    291	void __iomem *base = data->base;
    292	int i;
    293
    294	for (i = 0; i < nums; i++) {
    295		clk = hisi_register_clkgate_sep(NULL, clks[i].name,
    296						clks[i].parent_name,
    297						clks[i].flags,
    298						base + clks[i].offset,
    299						clks[i].bit_idx,
    300						clks[i].gate_flags,
    301						&hisi_clk_lock);
    302		if (IS_ERR(clk)) {
    303			pr_err("%s: failed to register clock %s\n",
    304			       __func__, clks[i].name);
    305			continue;
    306		}
    307
    308		if (clks[i].alias)
    309			clk_register_clkdev(clk, clks[i].alias, NULL);
    310
    311		data->clk_data.clks[clks[i].id] = clk;
    312	}
    313}
    314EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep);
    315
    316void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
    317					int nums, struct hisi_clock_data *data)
    318{
    319	struct clk *clk;
    320	void __iomem *base = data->base;
    321	int i;
    322
    323	for (i = 0; i < nums; i++) {
    324		clk = hi6220_register_clkdiv(NULL, clks[i].name,
    325						clks[i].parent_name,
    326						clks[i].flags,
    327						base + clks[i].offset,
    328						clks[i].shift,
    329						clks[i].width,
    330						clks[i].mask_bit,
    331						&hisi_clk_lock);
    332		if (IS_ERR(clk)) {
    333			pr_err("%s: failed to register clock %s\n",
    334			       __func__, clks[i].name);
    335			continue;
    336		}
    337
    338		if (clks[i].alias)
    339			clk_register_clkdev(clk, clks[i].alias, NULL);
    340
    341		data->clk_data.clks[clks[i].id] = clk;
    342	}
    343}