linux/drivers/clk/sprd/mux.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2//
   3// Spreadtrum multiplexer clock driver
   4//
   5// Copyright (C) 2017 Spreadtrum, Inc.
   6// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
   7
   8#include <linux/clk.h>
   9#include <linux/clk-provider.h>
  10#include <linux/regmap.h>
  11
  12#include "mux.h"
  13
  14u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
  15                              const struct sprd_mux_ssel *mux)
  16{
  17        unsigned int reg;
  18        u8 parent;
  19        int num_parents;
  20        int i;
  21
  22        regmap_read(common->regmap, common->reg, &reg);
  23        parent = reg >> mux->shift;
  24        parent &= (1 << mux->width) - 1;
  25
  26        if (!mux->table)
  27                return parent;
  28
  29        num_parents = clk_hw_get_num_parents(&common->hw);
  30
  31        for (i = 0; i < num_parents - 1; i++)
  32                if (parent >= mux->table[i] && parent < mux->table[i + 1])
  33                        return i;
  34
  35        return num_parents - 1;
  36}
  37EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent);
  38
  39static u8 sprd_mux_get_parent(struct clk_hw *hw)
  40{
  41        struct sprd_mux *cm = hw_to_sprd_mux(hw);
  42
  43        return sprd_mux_helper_get_parent(&cm->common, &cm->mux);
  44}
  45
  46int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
  47                               const struct sprd_mux_ssel *mux,
  48                               u8 index)
  49{
  50        unsigned int reg;
  51
  52        if (mux->table)
  53                index = mux->table[index];
  54
  55        regmap_read(common->regmap, common->reg, &reg);
  56        reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift);
  57        regmap_write(common->regmap, common->reg,
  58                          reg | (index << mux->shift));
  59
  60        return 0;
  61}
  62EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent);
  63
  64static int sprd_mux_set_parent(struct clk_hw *hw, u8 index)
  65{
  66        struct sprd_mux *cm = hw_to_sprd_mux(hw);
  67
  68        return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index);
  69}
  70
  71const struct clk_ops sprd_mux_ops = {
  72        .get_parent = sprd_mux_get_parent,
  73        .set_parent = sprd_mux_set_parent,
  74        .determine_rate = __clk_mux_determine_rate,
  75};
  76EXPORT_SYMBOL_GPL(sprd_mux_ops);
  77