cregit-Linux how code gets into the kernel

Release 4.11 drivers/clk/mxs/clk-ref.c

Directory: drivers/clk/mxs
/*
 * Copyright 2012 Freescale Semiconductor, Inc.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/slab.h>
#include "clk.h"

/**
 * struct clk_ref - mxs reference clock
 * @hw: clk_hw for the reference clock
 * @reg: register address
 * @idx: the index of the reference clock within the same register
 *
 * The mxs reference clock sources from pll.  Every 4 reference clocks share
 * one register space, and @idx is used to identify them.  Each reference
 * clock has a gate control and a fractional * divider.  The rate is calculated
 * as pll rate  * (18 / FRAC), where FRAC = 18 ~ 35.
 */

struct clk_ref {
	
struct clk_hw hw;
	
void __iomem *reg;
	
u8 idx;
};


#define to_clk_ref(_hw) container_of(_hw, struct clk_ref, hw)


static int clk_ref_enable(struct clk_hw *hw) { struct clk_ref *ref = to_clk_ref(hw); writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + CLR); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo49100.00%1100.00%
Total49100.00%1100.00%


static void clk_ref_disable(struct clk_hw *hw) { struct clk_ref *ref = to_clk_ref(hw); writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + SET); }

Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo46100.00%1100.00%
Total46100.00%1100.00%


static unsigned long clk_ref_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_ref *ref = to_clk_ref(hw); u64 tmp = parent_rate; u8 frac = (readl_relaxed(ref->reg) >> (ref->idx * 8)) & 0x3f; tmp *= 18; do_div(tmp, frac); return tmp; }

Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo67100.00%1100.00%
Total67100.00%1100.00%


static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { unsigned long parent_rate = *prate; u64 tmp = parent_rate; u8 frac; tmp = tmp * 18 + rate / 2; do_div(tmp, rate); frac = tmp; if (frac < 18) frac = 18; else if (frac > 35) frac = 35; tmp = parent_rate; tmp *= 18; do_div(tmp, frac); return tmp; }

Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo95100.00%1100.00%
Total95100.00%1100.00%


static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_ref *ref = to_clk_ref(hw); unsigned long flags; u64 tmp = parent_rate; u32 val; u8 frac, shift = ref->idx * 8; tmp = tmp * 18 + rate / 2; do_div(tmp, rate); frac = tmp; if (frac < 18) frac = 18; else if (frac > 35) frac = 35; spin_lock_irqsave(&mxs_lock, flags); val = readl_relaxed(ref->reg); val &= ~(0x3f << shift); val |= frac << shift; writel_relaxed(val, ref->reg); spin_unlock_irqrestore(&mxs_lock, flags); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo146100.00%1100.00%
Total146100.00%1100.00%

static const struct clk_ops clk_ref_ops = { .enable = clk_ref_enable, .disable = clk_ref_disable, .recalc_rate = clk_ref_recalc_rate, .round_rate = clk_ref_round_rate, .set_rate = clk_ref_set_rate, };
struct clk *mxs_clk_ref(const char *name, const char *parent_name, void __iomem *reg, u8 idx) { struct clk_ref *ref; struct clk *clk; struct clk_init_data init; ref = kzalloc(sizeof(*ref), GFP_KERNEL); if (!ref) return ERR_PTR(-ENOMEM); init.name = name; init.ops = &clk_ref_ops; init.flags = 0; init.parent_names = (parent_name ? &parent_name: NULL); init.num_parents = (parent_name ? 1 : 0); ref->reg = reg; ref->idx = idx; ref->hw.init = &init; clk = clk_register(NULL, &ref->hw); if (IS_ERR(clk)) kfree(ref); return clk; }

Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo156100.00%1100.00%
Total156100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Shawn Guo633100.00%1100.00%
Total633100.00%1100.00%
Directory: drivers/clk/mxs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.