Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * PRCC clock implementation for ux500 platform.
0004  *
0005  * Copyright (C) 2012 ST-Ericsson SA
0006  * Author: Ulf Hansson <ulf.hansson@linaro.org>
0007  */
0008 
0009 #include <linux/clk-provider.h>
0010 #include <linux/slab.h>
0011 #include <linux/io.h>
0012 #include <linux/err.h>
0013 #include <linux/types.h>
0014 
0015 #include "clk.h"
0016 
0017 #define PRCC_PCKEN          0x000
0018 #define PRCC_PCKDIS         0x004
0019 #define PRCC_KCKEN          0x008
0020 #define PRCC_KCKDIS         0x00C
0021 #define PRCC_PCKSR          0x010
0022 #define PRCC_KCKSR          0x014
0023 
0024 #define to_clk_prcc(_hw) container_of(_hw, struct clk_prcc, hw)
0025 
0026 struct clk_prcc {
0027     struct clk_hw hw;
0028     void __iomem *base;
0029     u32 cg_sel;
0030     int is_enabled;
0031 };
0032 
0033 /* PRCC clock operations. */
0034 
0035 static int clk_prcc_pclk_enable(struct clk_hw *hw)
0036 {
0037     struct clk_prcc *clk = to_clk_prcc(hw);
0038 
0039     writel(clk->cg_sel, (clk->base + PRCC_PCKEN));
0040     while (!(readl(clk->base + PRCC_PCKSR) & clk->cg_sel))
0041         cpu_relax();
0042 
0043     clk->is_enabled = 1;
0044     return 0;
0045 }
0046 
0047 static void clk_prcc_pclk_disable(struct clk_hw *hw)
0048 {
0049     struct clk_prcc *clk = to_clk_prcc(hw);
0050 
0051     writel(clk->cg_sel, (clk->base + PRCC_PCKDIS));
0052     clk->is_enabled = 0;
0053 }
0054 
0055 static int clk_prcc_kclk_enable(struct clk_hw *hw)
0056 {
0057     struct clk_prcc *clk = to_clk_prcc(hw);
0058 
0059     writel(clk->cg_sel, (clk->base + PRCC_KCKEN));
0060     while (!(readl(clk->base + PRCC_KCKSR) & clk->cg_sel))
0061         cpu_relax();
0062 
0063     clk->is_enabled = 1;
0064     return 0;
0065 }
0066 
0067 static void clk_prcc_kclk_disable(struct clk_hw *hw)
0068 {
0069     struct clk_prcc *clk = to_clk_prcc(hw);
0070 
0071     writel(clk->cg_sel, (clk->base + PRCC_KCKDIS));
0072     clk->is_enabled = 0;
0073 }
0074 
0075 static int clk_prcc_is_enabled(struct clk_hw *hw)
0076 {
0077     struct clk_prcc *clk = to_clk_prcc(hw);
0078     return clk->is_enabled;
0079 }
0080 
0081 static const struct clk_ops clk_prcc_pclk_ops = {
0082     .enable = clk_prcc_pclk_enable,
0083     .disable = clk_prcc_pclk_disable,
0084     .is_enabled = clk_prcc_is_enabled,
0085 };
0086 
0087 static const struct clk_ops clk_prcc_kclk_ops = {
0088     .enable = clk_prcc_kclk_enable,
0089     .disable = clk_prcc_kclk_disable,
0090     .is_enabled = clk_prcc_is_enabled,
0091 };
0092 
0093 static struct clk *clk_reg_prcc(const char *name,
0094                 const char *parent_name,
0095                 resource_size_t phy_base,
0096                 u32 cg_sel,
0097                 unsigned long flags,
0098                 const struct clk_ops *clk_prcc_ops)
0099 {
0100     struct clk_prcc *clk;
0101     struct clk_init_data clk_prcc_init;
0102     struct clk *clk_reg;
0103 
0104     if (!name) {
0105         pr_err("clk_prcc: %s invalid arguments passed\n", __func__);
0106         return ERR_PTR(-EINVAL);
0107     }
0108 
0109     clk = kzalloc(sizeof(*clk), GFP_KERNEL);
0110     if (!clk)
0111         return ERR_PTR(-ENOMEM);
0112 
0113     clk->base = ioremap(phy_base, SZ_4K);
0114     if (!clk->base)
0115         goto free_clk;
0116 
0117     clk->cg_sel = cg_sel;
0118     clk->is_enabled = 1;
0119 
0120     clk_prcc_init.name = name;
0121     clk_prcc_init.ops = clk_prcc_ops;
0122     clk_prcc_init.flags = flags;
0123     clk_prcc_init.parent_names = (parent_name ? &parent_name : NULL);
0124     clk_prcc_init.num_parents = (parent_name ? 1 : 0);
0125     clk->hw.init = &clk_prcc_init;
0126 
0127     clk_reg = clk_register(NULL, &clk->hw);
0128     if (IS_ERR_OR_NULL(clk_reg))
0129         goto unmap_clk;
0130 
0131     return clk_reg;
0132 
0133 unmap_clk:
0134     iounmap(clk->base);
0135 free_clk:
0136     kfree(clk);
0137     pr_err("clk_prcc: %s failed to register clk\n", __func__);
0138     return ERR_PTR(-ENOMEM);
0139 }
0140 
0141 struct clk *clk_reg_prcc_pclk(const char *name,
0142                   const char *parent_name,
0143                   resource_size_t phy_base,
0144                   u32 cg_sel,
0145                   unsigned long flags)
0146 {
0147     return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
0148             &clk_prcc_pclk_ops);
0149 }
0150 
0151 struct clk *clk_reg_prcc_kclk(const char *name,
0152                   const char *parent_name,
0153                   resource_size_t phy_base,
0154                   u32 cg_sel,
0155                   unsigned long flags)
0156 {
0157     return clk_reg_prcc(name, parent_name, phy_base, cg_sel, flags,
0158             &clk_prcc_kclk_ops);
0159 }