Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2014 Google, Inc.
0004  */
0005 
0006 #include <linux/clk.h>
0007 #include <linux/clk-provider.h>
0008 #include <linux/kernel.h>
0009 #include <linux/of.h>
0010 #include <linux/of_address.h>
0011 #include <linux/slab.h>
0012 
0013 #include "clk.h"
0014 
0015 struct pistachio_clk_provider *
0016 pistachio_clk_alloc_provider(struct device_node *node, unsigned int num_clks)
0017 {
0018     struct pistachio_clk_provider *p;
0019 
0020     p = kzalloc(sizeof(*p), GFP_KERNEL);
0021     if (!p)
0022         return p;
0023 
0024     p->clk_data.clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
0025     if (!p->clk_data.clks)
0026         goto free_provider;
0027     p->clk_data.clk_num = num_clks;
0028     p->node = node;
0029     p->base = of_iomap(node, 0);
0030     if (!p->base) {
0031         pr_err("Failed to map clock provider registers\n");
0032         goto free_clks;
0033     }
0034 
0035     return p;
0036 
0037 free_clks:
0038     kfree(p->clk_data.clks);
0039 free_provider:
0040     kfree(p);
0041     return NULL;
0042 }
0043 
0044 void pistachio_clk_register_provider(struct pistachio_clk_provider *p)
0045 {
0046     unsigned int i;
0047 
0048     for (i = 0; i < p->clk_data.clk_num; i++) {
0049         if (IS_ERR(p->clk_data.clks[i]))
0050             pr_warn("Failed to register clock %d: %ld\n", i,
0051                 PTR_ERR(p->clk_data.clks[i]));
0052     }
0053 
0054     of_clk_add_provider(p->node, of_clk_src_onecell_get, &p->clk_data);
0055 }
0056 
0057 void pistachio_clk_register_gate(struct pistachio_clk_provider *p,
0058                  struct pistachio_gate *gate,
0059                  unsigned int num)
0060 {
0061     struct clk *clk;
0062     unsigned int i;
0063 
0064     for (i = 0; i < num; i++) {
0065         clk = clk_register_gate(NULL, gate[i].name, gate[i].parent,
0066                     CLK_SET_RATE_PARENT,
0067                     p->base + gate[i].reg, gate[i].shift,
0068                     0, NULL);
0069         p->clk_data.clks[gate[i].id] = clk;
0070     }
0071 }
0072 
0073 void pistachio_clk_register_mux(struct pistachio_clk_provider *p,
0074                 struct pistachio_mux *mux,
0075                 unsigned int num)
0076 {
0077     struct clk *clk;
0078     unsigned int i;
0079 
0080     for (i = 0; i < num; i++) {
0081         clk = clk_register_mux(NULL, mux[i].name, mux[i].parents,
0082                        mux[i].num_parents,
0083                        CLK_SET_RATE_NO_REPARENT,
0084                        p->base + mux[i].reg, mux[i].shift,
0085                        get_count_order(mux[i].num_parents),
0086                        0, NULL);
0087         p->clk_data.clks[mux[i].id] = clk;
0088     }
0089 }
0090 
0091 void pistachio_clk_register_div(struct pistachio_clk_provider *p,
0092                 struct pistachio_div *div,
0093                 unsigned int num)
0094 {
0095     struct clk *clk;
0096     unsigned int i;
0097 
0098     for (i = 0; i < num; i++) {
0099         clk = clk_register_divider(NULL, div[i].name, div[i].parent,
0100                        0, p->base + div[i].reg, 0,
0101                        div[i].width, div[i].div_flags,
0102                        NULL);
0103         p->clk_data.clks[div[i].id] = clk;
0104     }
0105 }
0106 
0107 void pistachio_clk_register_fixed_factor(struct pistachio_clk_provider *p,
0108                      struct pistachio_fixed_factor *ff,
0109                      unsigned int num)
0110 {
0111     struct clk *clk;
0112     unsigned int i;
0113 
0114     for (i = 0; i < num; i++) {
0115         clk = clk_register_fixed_factor(NULL, ff[i].name, ff[i].parent,
0116                         0, 1, ff[i].div);
0117         p->clk_data.clks[ff[i].id] = clk;
0118     }
0119 }
0120 
0121 void pistachio_clk_force_enable(struct pistachio_clk_provider *p,
0122                 unsigned int *clk_ids, unsigned int num)
0123 {
0124     unsigned int i;
0125     int err;
0126 
0127     for (i = 0; i < num; i++) {
0128         struct clk *clk = p->clk_data.clks[clk_ids[i]];
0129 
0130         if (IS_ERR(clk))
0131             continue;
0132 
0133         err = clk_prepare_enable(clk);
0134         if (err)
0135             pr_err("Failed to enable clock %s: %d\n",
0136                    __clk_get_name(clk), err);
0137     }
0138 }