firmware/br-ext-chip-goke/board/gk7205v200/kernel/patches/00_drivers-clk-goke-clk.c.p...

193 lines
4.5 KiB
Diff

--- linux-4.9.37/drivers/clk/goke/clk.c 1970-01-01 03:00:00.000000000 +0300
+++ linux-4.9.y/drivers/clk/goke/clk.c 2021-06-07 13:01:33.000000000 +0300
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+
+#include "clk.h"
+
+static DEFINE_SPINLOCK(gk_clk_lock);
+
+struct gk_clock_data *gk_clk_init(struct device_node *np,
+ int nr_clks)
+{
+ struct gk_clock_data *clk_data;
+ struct clk **clk_table;
+ void __iomem *base;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ pr_err("%s: failed to map clock registers\n", __func__);
+ goto err;
+ }
+
+ clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+ if (!clk_data) {
+ pr_err("%s: could not allocate clock data\n", __func__);
+ goto err;
+ }
+ clk_data->base = base;
+
+ clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
+ if (!clk_table) {
+ pr_err("%s: could not allocate clock lookup table\n", __func__);
+ goto err_data;
+ }
+ clk_data->clk_data.clks = clk_table;
+ clk_data->clk_data.clk_num = nr_clks;
+ of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
+ return clk_data;
+err_data:
+ kfree(clk_data);
+err:
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gk_clk_init);
+
+int gk_clk_register_fixed_rate(const struct gk_fixed_rate_clock *clks,
+ int nums, struct gk_clock_data *data)
+{
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ clk = clk_register_fixed_rate(NULL, clks[i].name,
+ clks[i].parent_name,
+ clks[i].flags,
+ clks[i].fixed_rate);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_fixed_rate);
+
+int gk_clk_register_fixed_factor(const struct gk_fixed_factor_clock *clks,
+ int nums,
+ struct gk_clock_data *data)
+{
+ struct clk *clk;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ clk = clk_register_fixed_factor(NULL, clks[i].name,
+ clks[i].parent_name,
+ clks[i].flags, clks[i].mult,
+ clks[i].div);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_fixed_factor);
+
+int gk_clk_register_mux(const struct gk_mux_clock *clks,
+ int nums, struct gk_clock_data *data)
+{
+ struct clk *clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ u32 mask = BIT(clks[i].width) - 1;
+
+ clk = clk_register_mux_table(NULL, clks[i].name,
+ clks[i].parent_names,
+ clks[i].num_parents, clks[i].flags,
+ base + clks[i].offset, clks[i].shift,
+ mask, clks[i].mux_flags,
+ clks[i].table, &gk_clk_lock);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+
+ if (clks[i].alias)
+ clk_register_clkdev(clk, clks[i].alias, NULL);
+
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_mux(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_mux);
+
+
+int gk_clk_register_gate(const struct gk_gate_clock *clks,
+ int nums, struct gk_clock_data *data)
+{
+ struct clk *clk;
+ void __iomem *base = data->base;
+ int i;
+
+ for (i = 0; i < nums; i++) {
+ clk = clk_register_gate(NULL, clks[i].name,
+ clks[i].parent_name,
+ clks[i].flags,
+ base + clks[i].offset,
+ clks[i].bit_idx,
+ clks[i].gate_flags,
+ &gk_clk_lock);
+ if (IS_ERR(clk)) {
+ pr_err("%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ goto err;
+ }
+
+ if (clks[i].alias)
+ clk_register_clkdev(clk, clks[i].alias, NULL);
+
+ data->clk_data.clks[clks[i].id] = clk;
+ }
+
+ return 0;
+
+err:
+ while (i--)
+ clk_unregister_gate(data->clk_data.clks[clks[i].id]);
+
+ return PTR_ERR(clk);
+}
+EXPORT_SYMBOL_GPL(gk_clk_register_gate);
\ No newline at end of file