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-sun8i-apb0.c (2720B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2014 Chen-Yu Tsai
      4 * Author: Chen-Yu Tsai <wens@csie.org>
      5 *
      6 * Allwinner A23 APB0 clock driver
      7 *
      8 * Based on clk-sun6i-apb0.c
      9 * Allwinner A31 APB0 clock driver
     10 *
     11 * Copyright (C) 2014 Free Electrons
     12 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
     13 */
     14
     15#include <linux/clk-provider.h>
     16#include <linux/init.h>
     17#include <linux/io.h>
     18#include <linux/of.h>
     19#include <linux/of_address.h>
     20#include <linux/platform_device.h>
     21
     22static struct clk *sun8i_a23_apb0_register(struct device_node *node,
     23					   void __iomem *reg)
     24{
     25	const char *clk_name = node->name;
     26	const char *clk_parent;
     27	struct clk *clk;
     28	int ret;
     29
     30	clk_parent = of_clk_get_parent_name(node, 0);
     31	if (!clk_parent)
     32		return ERR_PTR(-EINVAL);
     33
     34	of_property_read_string(node, "clock-output-names", &clk_name);
     35
     36	/* The A23 APB0 clock is a standard 2 bit wide divider clock */
     37	clk = clk_register_divider(NULL, clk_name, clk_parent, 0, reg,
     38				   0, 2, 0, NULL);
     39	if (IS_ERR(clk))
     40		return clk;
     41
     42	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
     43	if (ret)
     44		goto err_unregister;
     45
     46	return clk;
     47
     48err_unregister:
     49	clk_unregister_divider(clk);
     50
     51	return ERR_PTR(ret);
     52}
     53
     54static void sun8i_a23_apb0_setup(struct device_node *node)
     55{
     56	void __iomem *reg;
     57	struct resource res;
     58	struct clk *clk;
     59
     60	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
     61	if (IS_ERR(reg)) {
     62		/*
     63		 * This happens with clk nodes instantiated through mfd,
     64		 * as those do not have their resources assigned in the
     65		 * device tree. Do not print an error in this case.
     66		 */
     67		if (PTR_ERR(reg) != -EINVAL)
     68			pr_err("Could not get registers for a23-apb0-clk\n");
     69
     70		return;
     71	}
     72
     73	clk = sun8i_a23_apb0_register(node, reg);
     74	if (IS_ERR(clk))
     75		goto err_unmap;
     76
     77	return;
     78
     79err_unmap:
     80	iounmap(reg);
     81	of_address_to_resource(node, 0, &res);
     82	release_mem_region(res.start, resource_size(&res));
     83}
     84CLK_OF_DECLARE_DRIVER(sun8i_a23_apb0, "allwinner,sun8i-a23-apb0-clk",
     85		      sun8i_a23_apb0_setup);
     86
     87static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
     88{
     89	struct device_node *np = pdev->dev.of_node;
     90	void __iomem *reg;
     91	struct clk *clk;
     92
     93	reg = devm_platform_ioremap_resource(pdev, 0);
     94	if (IS_ERR(reg))
     95		return PTR_ERR(reg);
     96
     97	clk = sun8i_a23_apb0_register(np, reg);
     98	return PTR_ERR_OR_ZERO(clk);
     99}
    100
    101static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
    102	{ .compatible = "allwinner,sun8i-a23-apb0-clk" },
    103	{ /* sentinel */ }
    104};
    105
    106static struct platform_driver sun8i_a23_apb0_clk_driver = {
    107	.driver = {
    108		.name = "sun8i-a23-apb0-clk",
    109		.of_match_table = sun8i_a23_apb0_clk_dt_ids,
    110	},
    111	.probe = sun8i_a23_apb0_clk_probe,
    112};
    113builtin_platform_driver(sun8i_a23_apb0_clk_driver);