root/drivers/clk/sunxi/clk-sun8i-mbus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sun8i_a23_mbus_setup

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2014 Chen-Yu Tsai
   4  *
   5  * Chen-Yu Tsai <wens@csie.org>
   6  */
   7 
   8 #include <linux/clk.h>
   9 #include <linux/clk-provider.h>
  10 #include <linux/io.h>
  11 #include <linux/slab.h>
  12 #include <linux/spinlock.h>
  13 #include <linux/of_address.h>
  14 
  15 #define SUN8I_MBUS_ENABLE       31
  16 #define SUN8I_MBUS_MUX_SHIFT    24
  17 #define SUN8I_MBUS_MUX_MASK     0x3
  18 #define SUN8I_MBUS_DIV_SHIFT    0
  19 #define SUN8I_MBUS_DIV_WIDTH    3
  20 #define SUN8I_MBUS_MAX_PARENTS  4
  21 
  22 static DEFINE_SPINLOCK(sun8i_a23_mbus_lock);
  23 
  24 static void __init sun8i_a23_mbus_setup(struct device_node *node)
  25 {
  26         int num_parents = of_clk_get_parent_count(node);
  27         const char **parents;
  28         const char *clk_name = node->name;
  29         struct resource res;
  30         struct clk_divider *div;
  31         struct clk_gate *gate;
  32         struct clk_mux *mux;
  33         struct clk *clk;
  34         void __iomem *reg;
  35         int err;
  36 
  37         parents = kcalloc(num_parents, sizeof(*parents), GFP_KERNEL);
  38         if (!parents)
  39                 return;
  40 
  41         reg = of_io_request_and_map(node, 0, of_node_full_name(node));
  42         if (IS_ERR(reg)) {
  43                 pr_err("Could not get registers for sun8i-mbus-clk\n");
  44                 goto err_free_parents;
  45         }
  46 
  47         div = kzalloc(sizeof(*div), GFP_KERNEL);
  48         if (!div)
  49                 goto err_unmap;
  50 
  51         mux = kzalloc(sizeof(*mux), GFP_KERNEL);
  52         if (!mux)
  53                 goto err_free_div;
  54 
  55         gate = kzalloc(sizeof(*gate), GFP_KERNEL);
  56         if (!gate)
  57                 goto err_free_mux;
  58 
  59         of_property_read_string(node, "clock-output-names", &clk_name);
  60         of_clk_parent_fill(node, parents, num_parents);
  61 
  62         gate->reg = reg;
  63         gate->bit_idx = SUN8I_MBUS_ENABLE;
  64         gate->lock = &sun8i_a23_mbus_lock;
  65 
  66         div->reg = reg;
  67         div->shift = SUN8I_MBUS_DIV_SHIFT;
  68         div->width = SUN8I_MBUS_DIV_WIDTH;
  69         div->lock = &sun8i_a23_mbus_lock;
  70 
  71         mux->reg = reg;
  72         mux->shift = SUN8I_MBUS_MUX_SHIFT;
  73         mux->mask = SUN8I_MBUS_MUX_MASK;
  74         mux->lock = &sun8i_a23_mbus_lock;
  75 
  76         /* The MBUS clocks needs to be always enabled */
  77         clk = clk_register_composite(NULL, clk_name, parents, num_parents,
  78                                      &mux->hw, &clk_mux_ops,
  79                                      &div->hw, &clk_divider_ops,
  80                                      &gate->hw, &clk_gate_ops,
  81                                      CLK_IS_CRITICAL);
  82         if (IS_ERR(clk))
  83                 goto err_free_gate;
  84 
  85         err = of_clk_add_provider(node, of_clk_src_simple_get, clk);
  86         if (err)
  87                 goto err_unregister_clk;
  88 
  89         kfree(parents); /* parents is deep copied */
  90 
  91         return;
  92 
  93 err_unregister_clk:
  94         /* TODO: The composite clock stuff will leak a bit here. */
  95         clk_unregister(clk);
  96 err_free_gate:
  97         kfree(gate);
  98 err_free_mux:
  99         kfree(mux);
 100 err_free_div:
 101         kfree(div);
 102 err_unmap:
 103         iounmap(reg);
 104         of_address_to_resource(node, 0, &res);
 105         release_mem_region(res.start, resource_size(&res));
 106 err_free_parents:
 107         kfree(parents);
 108 }
 109 CLK_OF_DECLARE(sun8i_a23_mbus, "allwinner,sun8i-a23-mbus-clk", sun8i_a23_mbus_setup);

/* [<][>][^][v][top][bottom][index][help] */