110 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright 2012 Freescale Semiconductor, Inc.4 */5 6#include <linux/clk-provider.h>7#include <linux/delay.h>8#include <linux/err.h>9#include <linux/io.h>10#include <linux/slab.h>11#include "clk.h"12 13/**14 * struct clk_pll - mxs pll clock15 * @hw: clk_hw for the pll16 * @base: base address of the pll17 * @power: the shift of power bit18 * @rate: the clock rate of the pll19 *20 * The mxs pll is a fixed rate clock with power and gate control,21 * and the shift of gate bit is always 31.22 */23struct clk_pll {24 struct clk_hw hw;25 void __iomem *base;26 u8 power;27 unsigned long rate;28};29 30#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)31 32static int clk_pll_prepare(struct clk_hw *hw)33{34 struct clk_pll *pll = to_clk_pll(hw);35 36 writel_relaxed(1 << pll->power, pll->base + SET);37 38 udelay(10);39 40 return 0;41}42 43static void clk_pll_unprepare(struct clk_hw *hw)44{45 struct clk_pll *pll = to_clk_pll(hw);46 47 writel_relaxed(1 << pll->power, pll->base + CLR);48}49 50static int clk_pll_enable(struct clk_hw *hw)51{52 struct clk_pll *pll = to_clk_pll(hw);53 54 writel_relaxed(1 << 31, pll->base + CLR);55 56 return 0;57}58 59static void clk_pll_disable(struct clk_hw *hw)60{61 struct clk_pll *pll = to_clk_pll(hw);62 63 writel_relaxed(1 << 31, pll->base + SET);64}65 66static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,67 unsigned long parent_rate)68{69 struct clk_pll *pll = to_clk_pll(hw);70 71 return pll->rate;72}73 74static const struct clk_ops clk_pll_ops = {75 .prepare = clk_pll_prepare,76 .unprepare = clk_pll_unprepare,77 .enable = clk_pll_enable,78 .disable = clk_pll_disable,79 .recalc_rate = clk_pll_recalc_rate,80};81 82struct clk *mxs_clk_pll(const char *name, const char *parent_name,83 void __iomem *base, u8 power, unsigned long rate)84{85 struct clk_pll *pll;86 struct clk *clk;87 struct clk_init_data init;88 89 pll = kzalloc(sizeof(*pll), GFP_KERNEL);90 if (!pll)91 return ERR_PTR(-ENOMEM);92 93 init.name = name;94 init.ops = &clk_pll_ops;95 init.flags = 0;96 init.parent_names = (parent_name ? &parent_name: NULL);97 init.num_parents = (parent_name ? 1 : 0);98 99 pll->base = base;100 pll->rate = rate;101 pll->power = power;102 pll->hw.init = &init;103 104 clk = clk_register(NULL, &pll->hw);105 if (IS_ERR(clk))106 kfree(pll);107 108 return clk;109}110