linux/drivers/clk/pistachio/clk.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (C) 2014 Google, Inc.
   4 */
   5
   6#include <linux/clk.h>
   7#include <linux/clk-provider.h>
   8#include <linux/kernel.h>
   9#include <linux/of.h>
  10#include <linux/of_address.h>
  11#include <linux/slab.h>
  12
  13#include "clk.h"
  14
  15struct pistachio_clk_provider *
  16pistachio_clk_alloc_provider(struct device_node *node, unsigned int num_clks)
  17{
  18        struct pistachio_clk_provider *p;
  19
  20        p = kzalloc(sizeof(*p), GFP_KERNEL);
  21        if (!p)
  22                return p;
  23
  24        p->clk_data.clks = kcalloc(num_clks, sizeof(struct clk *), GFP_KERNEL);
  25        if (!p->clk_data.clks)
  26                goto free_provider;
  27        p->clk_data.clk_num = num_clks;
  28        p->node = node;
  29        p->base = of_iomap(node, 0);
  30        if (!p->base) {
  31                pr_err("Failed to map clock provider registers\n");
  32                goto free_clks;
  33        }
  34
  35        return p;
  36
  37free_clks:
  38        kfree(p->clk_data.clks);
  39free_provider:
  40        kfree(p);
  41        return NULL;
  42}
  43
  44void pistachio_clk_register_provider(struct pistachio_clk_provider *p)
  45{
  46        unsigned int i;
  47
  48        for (i = 0; i < p->clk_data.clk_num; i++) {
  49                if (IS_ERR(p->clk_data.clks[i]))
  50                        pr_warn("Failed to register clock %d: %ld\n", i,
  51                                PTR_ERR(p->clk_data.clks[i]));
  52        }
  53
  54        of_clk_add_provider(p->node, of_clk_src_onecell_get, &p->clk_data);
  55}
  56
  57void pistachio_clk_register_gate(struct pistachio_clk_provider *p,
  58                                 struct pistachio_gate *gate,
  59                                 unsigned int num)
  60{
  61        struct clk *clk;
  62        unsigned int i;
  63
  64        for (i = 0; i < num; i++) {
  65                clk = clk_register_gate(NULL, gate[i].name, gate[i].parent,
  66                                        CLK_SET_RATE_PARENT,
  67                                        p->base + gate[i].reg, gate[i].shift,
  68                                        0, NULL);
  69                p->clk_data.clks[gate[i].id] = clk;
  70        }
  71}
  72
  73void pistachio_clk_register_mux(struct pistachio_clk_provider *p,
  74                                struct pistachio_mux *mux,
  75                                unsigned int num)
  76{
  77        struct clk *clk;
  78        unsigned int i;
  79
  80        for (i = 0; i < num; i++) {
  81                clk = clk_register_mux(NULL, mux[i].name, mux[i].parents,
  82                                       mux[i].num_parents,
  83                                       CLK_SET_RATE_NO_REPARENT,
  84                                       p->base + mux[i].reg, mux[i].shift,
  85                                       get_count_order(mux[i].num_parents),
  86                                       0, NULL);
  87                p->clk_data.clks[mux[i].id] = clk;
  88        }
  89}
  90
  91void pistachio_clk_register_div(struct pistachio_clk_provider *p,
  92                                struct pistachio_div *div,
  93                                unsigned int num)
  94{
  95        struct clk *clk;
  96        unsigned int i;
  97
  98        for (i = 0; i < num; i++) {
  99                clk = clk_register_divider(NULL, div[i].name, div[i].parent,
 100                                           0, p->base + div[i].reg, 0,
 101                                           div[i].width, div[i].div_flags,
 102                                           NULL);
 103                p->clk_data.clks[div[i].id] = clk;
 104        }
 105}
 106
 107void pistachio_clk_register_fixed_factor(struct pistachio_clk_provider *p,
 108                                         struct pistachio_fixed_factor *ff,
 109                                         unsigned int num)
 110{
 111        struct clk *clk;
 112        unsigned int i;
 113
 114        for (i = 0; i < num; i++) {
 115                clk = clk_register_fixed_factor(NULL, ff[i].name, ff[i].parent,
 116                                                0, 1, ff[i].div);
 117                p->clk_data.clks[ff[i].id] = clk;
 118        }
 119}
 120
 121void pistachio_clk_force_enable(struct pistachio_clk_provider *p,
 122                                unsigned int *clk_ids, unsigned int num)
 123{
 124        unsigned int i;
 125        int err;
 126
 127        for (i = 0; i < num; i++) {
 128                struct clk *clk = p->clk_data.clks[clk_ids[i]];
 129
 130                if (IS_ERR(clk))
 131                        continue;
 132
 133                err = clk_prepare_enable(clk);
 134                if (err)
 135                        pr_err("Failed to enable clock %s: %d\n",
 136                               __clk_get_name(clk), err);
 137        }
 138}
 139