87 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2016 Socionext Inc.4 * Author: Masahiro Yamada <yamada.masahiro@socionext.com>5 */6 7#include <linux/clk-provider.h>8#include <linux/device.h>9#include <linux/regmap.h>10 11#include "clk-uniphier.h"12 13struct uniphier_clk_mux {14 struct clk_hw hw;15 struct regmap *regmap;16 unsigned int reg;17 const unsigned int *masks;18 const unsigned int *vals;19};20 21#define to_uniphier_clk_mux(_hw) container_of(_hw, struct uniphier_clk_mux, hw)22 23static int uniphier_clk_mux_set_parent(struct clk_hw *hw, u8 index)24{25 struct uniphier_clk_mux *mux = to_uniphier_clk_mux(hw);26 27 return regmap_write_bits(mux->regmap, mux->reg, mux->masks[index],28 mux->vals[index]);29}30 31static u8 uniphier_clk_mux_get_parent(struct clk_hw *hw)32{33 struct uniphier_clk_mux *mux = to_uniphier_clk_mux(hw);34 unsigned int num_parents = clk_hw_get_num_parents(hw);35 int ret;36 unsigned int val;37 unsigned int i;38 39 ret = regmap_read(mux->regmap, mux->reg, &val);40 if (ret)41 return ret;42 43 for (i = 0; i < num_parents; i++)44 if ((mux->masks[i] & val) == mux->vals[i])45 return i;46 47 return -EINVAL;48}49 50static const struct clk_ops uniphier_clk_mux_ops = {51 .determine_rate = __clk_mux_determine_rate,52 .set_parent = uniphier_clk_mux_set_parent,53 .get_parent = uniphier_clk_mux_get_parent,54};55 56struct clk_hw *uniphier_clk_register_mux(struct device *dev,57 struct regmap *regmap,58 const char *name,59 const struct uniphier_clk_mux_data *data)60{61 struct uniphier_clk_mux *mux;62 struct clk_init_data init;63 int ret;64 65 mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);66 if (!mux)67 return ERR_PTR(-ENOMEM);68 69 init.name = name;70 init.ops = &uniphier_clk_mux_ops;71 init.flags = CLK_SET_RATE_PARENT;72 init.parent_names = data->parent_names;73 init.num_parents = data->num_parents;74 75 mux->regmap = regmap;76 mux->reg = data->reg;77 mux->masks = data->masks;78 mux->vals = data->vals;79 mux->hw.init = &init;80 81 ret = devm_clk_hw_register(dev, &mux->hw);82 if (ret)83 return ERR_PTR(ret);84 85 return &mux->hw;86}87