Blame view
drivers/clk/clk-composite.c
4.12 KB
000976358 clk: add composit... |
1 2 3 4 5 6 7 8 9 10 11 |
// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. * Copyright 2019 NXP */ #include <common.h> #include <asm/io.h> #include <malloc.h> #include <clk-uclass.h> #include <dm/device.h> |
61b29b826 dm: core: Require... |
12 |
#include <dm/devres.h> |
000976358 clk: add composit... |
13 14 |
#include <linux/clk-provider.h> #include <clk.h> |
61b29b826 dm: core: Require... |
15 |
#include <linux/err.h> |
000976358 clk: add composit... |
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
#include "clk.h" #define UBOOT_DM_CLK_COMPOSITE "clk_composite" static u8 clk_composite_get_parent(struct clk *clk) { struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? (struct clk *)dev_get_clk_ptr(clk->dev) : clk); struct clk *mux = composite->mux; return clk_mux_get_parent(mux); } static int clk_composite_set_parent(struct clk *clk, struct clk *parent) { struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? (struct clk *)dev_get_clk_ptr(clk->dev) : clk); const struct clk_ops *mux_ops = composite->mux_ops; struct clk *mux = composite->mux; return mux_ops->set_parent(mux, parent); } static unsigned long clk_composite_recalc_rate(struct clk *clk) { struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? (struct clk *)dev_get_clk_ptr(clk->dev) : clk); const struct clk_ops *rate_ops = composite->rate_ops; struct clk *rate = composite->rate; return rate_ops->get_rate(rate); } static ulong clk_composite_set_rate(struct clk *clk, unsigned long rate) { struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? (struct clk *)dev_get_clk_ptr(clk->dev) : clk); const struct clk_ops *rate_ops = composite->rate_ops; struct clk *clk_rate = composite->rate; return rate_ops->set_rate(clk_rate, rate); } static int clk_composite_enable(struct clk *clk) { struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? (struct clk *)dev_get_clk_ptr(clk->dev) : clk); const struct clk_ops *gate_ops = composite->gate_ops; struct clk *gate = composite->gate; return gate_ops->enable(gate); } static int clk_composite_disable(struct clk *clk) { struct clk_composite *composite = to_clk_composite(clk_dev_binded(clk) ? (struct clk *)dev_get_clk_ptr(clk->dev) : clk); const struct clk_ops *gate_ops = composite->gate_ops; struct clk *gate = composite->gate; gate_ops->disable(gate); return 0; } struct clk_ops clk_composite_ops = { /* This will be set according to clk_register_composite */ }; struct clk *clk_register_composite(struct device *dev, const char *name, const char * const *parent_names, int num_parents, struct clk *mux, const struct clk_ops *mux_ops, struct clk *rate, const struct clk_ops *rate_ops, struct clk *gate, const struct clk_ops *gate_ops, unsigned long flags) { struct clk *clk; struct clk_composite *composite; int ret; struct clk_ops *composite_ops = &clk_composite_ops; composite = kzalloc(sizeof(*composite), GFP_KERNEL); if (!composite) return ERR_PTR(-ENOMEM); if (mux && mux_ops) { composite->mux = mux; composite->mux_ops = mux_ops; if (mux_ops->set_parent) composite_ops->set_parent = clk_composite_set_parent; mux->data = (ulong)composite; } if (rate && rate_ops) { if (!rate_ops->get_rate) { clk = ERR_PTR(-EINVAL); goto err; } composite_ops->get_rate = clk_composite_recalc_rate; /* .set_rate requires either .round_rate or .determine_rate */ if (rate_ops->set_rate) composite_ops->set_rate = clk_composite_set_rate; composite->rate = rate; composite->rate_ops = rate_ops; rate->data = (ulong)composite; } if (gate && gate_ops) { if (!gate_ops->enable || !gate_ops->disable) { clk = ERR_PTR(-EINVAL); goto err; } composite->gate = gate; composite->gate_ops = gate_ops; composite_ops->enable = clk_composite_enable; composite_ops->disable = clk_composite_disable; gate->data = (ulong)composite; } clk = &composite->clk; ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name, parent_names[clk_composite_get_parent(clk)]); if (ret) { clk = ERR_PTR(ret); goto err; } return clk; err: kfree(composite); return clk; } U_BOOT_DRIVER(clk_composite) = { .name = UBOOT_DM_CLK_COMPOSITE, .id = UCLASS_CLK, .ops = &clk_composite_ops, .flags = DM_FLAG_PRE_RELOC, }; |