Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
0004  */
0005 
0006 #include <linux/clk-provider.h>
0007 #include <linux/slab.h>
0008 #include <linux/io.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011 
0012 #include <soc/tegra/fuse.h>
0013 
0014 #include "clk.h"
0015 
0016 static DEFINE_SPINLOCK(periph_ref_lock);
0017 
0018 /* Macros to assist peripheral gate clock */
0019 #define read_enb(gate) \
0020     readl_relaxed(gate->clk_base + (gate->regs->enb_reg))
0021 #define write_enb_set(val, gate) \
0022     writel_relaxed(val, gate->clk_base + (gate->regs->enb_set_reg))
0023 #define write_enb_clr(val, gate) \
0024     writel_relaxed(val, gate->clk_base + (gate->regs->enb_clr_reg))
0025 
0026 #define read_rst(gate) \
0027     readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
0028 #define write_rst_clr(val, gate) \
0029     writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
0030 
0031 #define periph_clk_to_bit(gate) (1 << (gate->clk_num % 32))
0032 
0033 #define LVL2_CLK_GATE_OVRE 0x554
0034 
0035 /* Peripheral gate clock ops */
0036 static int clk_periph_is_enabled(struct clk_hw *hw)
0037 {
0038     struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0039     int state = 1;
0040 
0041     if (!(read_enb(gate) & periph_clk_to_bit(gate)))
0042         state = 0;
0043 
0044     if (!(gate->flags & TEGRA_PERIPH_NO_RESET))
0045         if (read_rst(gate) & periph_clk_to_bit(gate))
0046             state = 0;
0047 
0048     return state;
0049 }
0050 
0051 static void clk_periph_enable_locked(struct clk_hw *hw)
0052 {
0053     struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0054 
0055     write_enb_set(periph_clk_to_bit(gate), gate);
0056     udelay(2);
0057 
0058     if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
0059         writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
0060         writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
0061         udelay(1);
0062         writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
0063     }
0064 }
0065 
0066 static void clk_periph_disable_locked(struct clk_hw *hw)
0067 {
0068     struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0069 
0070     /*
0071      * If peripheral is in the APB bus then read the APB bus to
0072      * flush the write operation in apb bus. This will avoid the
0073      * peripheral access after disabling clock
0074      */
0075     if (gate->flags & TEGRA_PERIPH_ON_APB)
0076         tegra_read_chipid();
0077 
0078     write_enb_clr(periph_clk_to_bit(gate), gate);
0079 }
0080 
0081 static int clk_periph_enable(struct clk_hw *hw)
0082 {
0083     struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0084     unsigned long flags = 0;
0085 
0086     spin_lock_irqsave(&periph_ref_lock, flags);
0087 
0088     if (!gate->enable_refcnt[gate->clk_num]++)
0089         clk_periph_enable_locked(hw);
0090 
0091     spin_unlock_irqrestore(&periph_ref_lock, flags);
0092 
0093     return 0;
0094 }
0095 
0096 static void clk_periph_disable(struct clk_hw *hw)
0097 {
0098     struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0099     unsigned long flags = 0;
0100 
0101     spin_lock_irqsave(&periph_ref_lock, flags);
0102 
0103     WARN_ON(!gate->enable_refcnt[gate->clk_num]);
0104 
0105     if (--gate->enable_refcnt[gate->clk_num] == 0)
0106         clk_periph_disable_locked(hw);
0107 
0108     spin_unlock_irqrestore(&periph_ref_lock, flags);
0109 }
0110 
0111 static void clk_periph_disable_unused(struct clk_hw *hw)
0112 {
0113     struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
0114     unsigned long flags = 0;
0115 
0116     spin_lock_irqsave(&periph_ref_lock, flags);
0117 
0118     /*
0119      * Some clocks are duplicated and some of them are marked as critical,
0120      * like fuse and fuse_burn for example, thus the enable_refcnt will
0121      * be non-zero here if the "unused" duplicate is disabled by CCF.
0122      */
0123     if (!gate->enable_refcnt[gate->clk_num])
0124         clk_periph_disable_locked(hw);
0125 
0126     spin_unlock_irqrestore(&periph_ref_lock, flags);
0127 }
0128 
0129 const struct clk_ops tegra_clk_periph_gate_ops = {
0130     .is_enabled = clk_periph_is_enabled,
0131     .enable = clk_periph_enable,
0132     .disable = clk_periph_disable,
0133     .disable_unused = clk_periph_disable_unused,
0134 };
0135 
0136 struct clk *tegra_clk_register_periph_gate(const char *name,
0137         const char *parent_name, u8 gate_flags, void __iomem *clk_base,
0138         unsigned long flags, int clk_num, int *enable_refcnt)
0139 {
0140     struct tegra_clk_periph_gate *gate;
0141     struct clk *clk;
0142     struct clk_init_data init;
0143     const struct tegra_clk_periph_regs *pregs;
0144 
0145     pregs = get_reg_bank(clk_num);
0146     if (!pregs)
0147         return ERR_PTR(-EINVAL);
0148 
0149     gate = kzalloc(sizeof(*gate), GFP_KERNEL);
0150     if (!gate) {
0151         pr_err("%s: could not allocate periph gate clk\n", __func__);
0152         return ERR_PTR(-ENOMEM);
0153     }
0154 
0155     init.name = name;
0156     init.flags = flags;
0157     init.parent_names = parent_name ? &parent_name : NULL;
0158     init.num_parents = parent_name ? 1 : 0;
0159     init.ops = &tegra_clk_periph_gate_ops;
0160 
0161     gate->magic = TEGRA_CLK_PERIPH_GATE_MAGIC;
0162     gate->clk_base = clk_base;
0163     gate->clk_num = clk_num;
0164     gate->flags = gate_flags;
0165     gate->enable_refcnt = enable_refcnt;
0166     gate->regs = pregs;
0167 
0168     /* Data in .init is copied by clk_register(), so stack variable OK */
0169     gate->hw.init = &init;
0170 
0171     clk = clk_register(NULL, &gate->hw);
0172     if (IS_ERR(clk))
0173         kfree(gate);
0174 
0175     return clk;
0176 }