250 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright (c) 2014 MediaTek Inc.4 * Author: James Liao <jamesjj.liao@mediatek.com>5 */6 7#ifndef __DRV_CLK_MTK_H8#define __DRV_CLK_MTK_H9 10#include <linux/clk-provider.h>11#include <linux/io.h>12#include <linux/kernel.h>13#include <linux/spinlock.h>14#include <linux/types.h>15 16#include "reset.h"17 18#define MAX_MUX_GATE_BIT 3119#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1)20 21#define MHZ (1000 * 1000)22 23struct platform_device;24 25/*26 * We need the clock IDs to start from zero but to maintain devicetree27 * backwards compatibility we can't change bindings to start from zero.28 * Only a few platforms are affected, so we solve issues given by the29 * commonized MTK clocks probe function(s) by adding a dummy clock at30 * the beginning where needed.31 */32#define CLK_DUMMY 033 34extern const struct clk_ops mtk_clk_dummy_ops;35extern const struct mtk_gate_regs cg_regs_dummy;36 37#define GATE_DUMMY(_id, _name) { \38 .id = _id, \39 .name = _name, \40 .regs = &cg_regs_dummy, \41 .ops = &mtk_clk_dummy_ops, \42 }43 44struct mtk_fixed_clk {45 int id;46 const char *name;47 const char *parent;48 unsigned long rate;49};50 51#define FIXED_CLK(_id, _name, _parent, _rate) { \52 .id = _id, \53 .name = _name, \54 .parent = _parent, \55 .rate = _rate, \56 }57 58int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num,59 struct clk_hw_onecell_data *clk_data);60void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num,61 struct clk_hw_onecell_data *clk_data);62 63struct mtk_fixed_factor {64 int id;65 const char *name;66 const char *parent_name;67 int mult;68 int div;69 unsigned long flags;70};71 72#define FACTOR_FLAGS(_id, _name, _parent, _mult, _div, _fl) { \73 .id = _id, \74 .name = _name, \75 .parent_name = _parent, \76 .mult = _mult, \77 .div = _div, \78 .flags = _fl, \79 }80 81#define FACTOR(_id, _name, _parent, _mult, _div) \82 FACTOR_FLAGS(_id, _name, _parent, _mult, _div, CLK_SET_RATE_PARENT)83 84int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,85 struct clk_hw_onecell_data *clk_data);86void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num,87 struct clk_hw_onecell_data *clk_data);88 89struct mtk_composite {90 int id;91 const char *name;92 const char * const *parent_names;93 const char *parent;94 unsigned flags;95 96 uint32_t mux_reg;97 uint32_t divider_reg;98 uint32_t gate_reg;99 100 signed char mux_shift;101 signed char mux_width;102 signed char gate_shift;103 104 signed char divider_shift;105 signed char divider_width;106 107 u8 mux_flags;108 109 signed char num_parents;110};111 112#define MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, _shift, \113 _width, _gate, _flags, _muxflags) { \114 .id = _id, \115 .name = _name, \116 .mux_reg = _reg, \117 .mux_shift = _shift, \118 .mux_width = _width, \119 .gate_reg = _reg, \120 .gate_shift = _gate, \121 .divider_shift = -1, \122 .parent_names = _parents, \123 .num_parents = ARRAY_SIZE(_parents), \124 .flags = _flags, \125 .mux_flags = _muxflags, \126 }127 128/*129 * In case the rate change propagation to parent clocks is undesirable,130 * this macro allows to specify the clock flags manually.131 */132#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \133 _gate, _flags) \134 MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, \135 _shift, _width, _gate, _flags, 0)136 137/*138 * Unless necessary, all MUX_GATE clocks propagate rate changes to their139 * parent clock by default.140 */141#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) \142 MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \143 _gate, CLK_SET_RATE_PARENT)144 145#define MUX(_id, _name, _parents, _reg, _shift, _width) \146 MUX_FLAGS(_id, _name, _parents, _reg, \147 _shift, _width, CLK_SET_RATE_PARENT)148 149#define MUX_FLAGS(_id, _name, _parents, _reg, _shift, _width, _flags) { \150 .id = _id, \151 .name = _name, \152 .mux_reg = _reg, \153 .mux_shift = _shift, \154 .mux_width = _width, \155 .gate_shift = -1, \156 .divider_shift = -1, \157 .parent_names = _parents, \158 .num_parents = ARRAY_SIZE(_parents), \159 .flags = _flags, \160 }161 162#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \163 _div_width, _div_shift) { \164 .id = _id, \165 .parent = _parent, \166 .name = _name, \167 .divider_reg = _div_reg, \168 .divider_shift = _div_shift, \169 .divider_width = _div_width, \170 .gate_reg = _gate_reg, \171 .gate_shift = _gate_shift, \172 .mux_shift = -1, \173 .flags = 0, \174 }175 176int mtk_clk_register_composites(struct device *dev,177 const struct mtk_composite *mcs, int num,178 void __iomem *base, spinlock_t *lock,179 struct clk_hw_onecell_data *clk_data);180void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num,181 struct clk_hw_onecell_data *clk_data);182 183struct mtk_clk_divider {184 int id;185 const char *name;186 const char *parent_name;187 unsigned long flags;188 189 u32 div_reg;190 unsigned char div_shift;191 unsigned char div_width;192 unsigned char clk_divider_flags;193 const struct clk_div_table *clk_div_table;194};195 196#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \197 .id = _id, \198 .name = _name, \199 .parent_name = _parent, \200 .div_reg = _reg, \201 .div_shift = _shift, \202 .div_width = _width, \203}204 205int mtk_clk_register_dividers(struct device *dev,206 const struct mtk_clk_divider *mcds, int num,207 void __iomem *base, spinlock_t *lock,208 struct clk_hw_onecell_data *clk_data);209void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num,210 struct clk_hw_onecell_data *clk_data);211 212struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);213struct clk_hw_onecell_data *mtk_devm_alloc_clk_data(struct device *dev,214 unsigned int clk_num);215void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data);216 217struct clk_hw *mtk_clk_register_ref2usb_tx(const char *name,218 const char *parent_name, void __iomem *reg);219void mtk_clk_unregister_ref2usb_tx(struct clk_hw *hw);220 221struct mtk_clk_desc {222 const struct mtk_gate *clks;223 size_t num_clks;224 const struct mtk_composite *composite_clks;225 size_t num_composite_clks;226 const struct mtk_clk_divider *divider_clks;227 size_t num_divider_clks;228 const struct mtk_fixed_clk *fixed_clks;229 size_t num_fixed_clks;230 const struct mtk_fixed_factor *factor_clks;231 size_t num_factor_clks;232 const struct mtk_mux *mux_clks;233 size_t num_mux_clks;234 const struct mtk_clk_rst_desc *rst_desc;235 spinlock_t *clk_lock;236 bool shared_io;237 238 int (*clk_notifier_func)(struct device *dev, struct clk *clk);239 unsigned int mfg_clk_idx;240 241 bool need_runtime_pm;242};243 244int mtk_clk_pdev_probe(struct platform_device *pdev);245void mtk_clk_pdev_remove(struct platform_device *pdev);246int mtk_clk_simple_probe(struct platform_device *pdev);247void mtk_clk_simple_remove(struct platform_device *pdev);248 249#endif /* __DRV_CLK_MTK_H */250