18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014 MediaTek Inc. 48c2ecf20Sopenharmony_ci * Author: James Liao <jamesjj.liao@mediatek.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef __DRV_CLK_MTK_H 88c2ecf20Sopenharmony_ci#define __DRV_CLK_MTK_H 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/regmap.h> 118c2ecf20Sopenharmony_ci#include <linux/bitops.h> 128c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistruct clk; 158c2ecf20Sopenharmony_cistruct clk_onecell_data; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define MAX_MUX_GATE_BIT 31 188c2ecf20Sopenharmony_ci#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define MHZ (1000 * 1000) 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct mtk_fixed_clk { 238c2ecf20Sopenharmony_ci int id; 248c2ecf20Sopenharmony_ci const char *name; 258c2ecf20Sopenharmony_ci const char *parent; 268c2ecf20Sopenharmony_ci unsigned long rate; 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define FIXED_CLK(_id, _name, _parent, _rate) { \ 308c2ecf20Sopenharmony_ci .id = _id, \ 318c2ecf20Sopenharmony_ci .name = _name, \ 328c2ecf20Sopenharmony_ci .parent = _parent, \ 338c2ecf20Sopenharmony_ci .rate = _rate, \ 348c2ecf20Sopenharmony_ci } 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_civoid mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, 378c2ecf20Sopenharmony_ci int num, struct clk_onecell_data *clk_data); 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct mtk_fixed_factor { 408c2ecf20Sopenharmony_ci int id; 418c2ecf20Sopenharmony_ci const char *name; 428c2ecf20Sopenharmony_ci const char *parent_name; 438c2ecf20Sopenharmony_ci int mult; 448c2ecf20Sopenharmony_ci int div; 458c2ecf20Sopenharmony_ci}; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define FACTOR(_id, _name, _parent, _mult, _div) { \ 488c2ecf20Sopenharmony_ci .id = _id, \ 498c2ecf20Sopenharmony_ci .name = _name, \ 508c2ecf20Sopenharmony_ci .parent_name = _parent, \ 518c2ecf20Sopenharmony_ci .mult = _mult, \ 528c2ecf20Sopenharmony_ci .div = _div, \ 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_civoid mtk_clk_register_factors(const struct mtk_fixed_factor *clks, 568c2ecf20Sopenharmony_ci int num, struct clk_onecell_data *clk_data); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct mtk_composite { 598c2ecf20Sopenharmony_ci int id; 608c2ecf20Sopenharmony_ci const char *name; 618c2ecf20Sopenharmony_ci const char * const *parent_names; 628c2ecf20Sopenharmony_ci const char *parent; 638c2ecf20Sopenharmony_ci unsigned flags; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci uint32_t mux_reg; 668c2ecf20Sopenharmony_ci uint32_t divider_reg; 678c2ecf20Sopenharmony_ci uint32_t gate_reg; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci signed char mux_shift; 708c2ecf20Sopenharmony_ci signed char mux_width; 718c2ecf20Sopenharmony_ci signed char gate_shift; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci signed char divider_shift; 748c2ecf20Sopenharmony_ci signed char divider_width; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci u8 mux_flags; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci signed char num_parents; 798c2ecf20Sopenharmony_ci}; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci#define MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, _shift, \ 828c2ecf20Sopenharmony_ci _width, _gate, _flags, _muxflags) { \ 838c2ecf20Sopenharmony_ci .id = _id, \ 848c2ecf20Sopenharmony_ci .name = _name, \ 858c2ecf20Sopenharmony_ci .mux_reg = _reg, \ 868c2ecf20Sopenharmony_ci .mux_shift = _shift, \ 878c2ecf20Sopenharmony_ci .mux_width = _width, \ 888c2ecf20Sopenharmony_ci .gate_reg = _reg, \ 898c2ecf20Sopenharmony_ci .gate_shift = _gate, \ 908c2ecf20Sopenharmony_ci .divider_shift = -1, \ 918c2ecf20Sopenharmony_ci .parent_names = _parents, \ 928c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(_parents), \ 938c2ecf20Sopenharmony_ci .flags = _flags, \ 948c2ecf20Sopenharmony_ci .mux_flags = _muxflags, \ 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* 988c2ecf20Sopenharmony_ci * In case the rate change propagation to parent clocks is undesirable, 998c2ecf20Sopenharmony_ci * this macro allows to specify the clock flags manually. 1008c2ecf20Sopenharmony_ci */ 1018c2ecf20Sopenharmony_ci#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ 1028c2ecf20Sopenharmony_ci _gate, _flags) \ 1038c2ecf20Sopenharmony_ci MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, \ 1048c2ecf20Sopenharmony_ci _shift, _width, _gate, _flags, 0) 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* 1078c2ecf20Sopenharmony_ci * Unless necessary, all MUX_GATE clocks propagate rate changes to their 1088c2ecf20Sopenharmony_ci * parent clock by default. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ci#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) \ 1118c2ecf20Sopenharmony_ci MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ 1128c2ecf20Sopenharmony_ci _gate, CLK_SET_RATE_PARENT) 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#define MUX(_id, _name, _parents, _reg, _shift, _width) \ 1158c2ecf20Sopenharmony_ci MUX_FLAGS(_id, _name, _parents, _reg, \ 1168c2ecf20Sopenharmony_ci _shift, _width, CLK_SET_RATE_PARENT) 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci#define MUX_FLAGS(_id, _name, _parents, _reg, _shift, _width, _flags) { \ 1198c2ecf20Sopenharmony_ci .id = _id, \ 1208c2ecf20Sopenharmony_ci .name = _name, \ 1218c2ecf20Sopenharmony_ci .mux_reg = _reg, \ 1228c2ecf20Sopenharmony_ci .mux_shift = _shift, \ 1238c2ecf20Sopenharmony_ci .mux_width = _width, \ 1248c2ecf20Sopenharmony_ci .gate_shift = -1, \ 1258c2ecf20Sopenharmony_ci .divider_shift = -1, \ 1268c2ecf20Sopenharmony_ci .parent_names = _parents, \ 1278c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(_parents), \ 1288c2ecf20Sopenharmony_ci .flags = _flags, \ 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \ 1328c2ecf20Sopenharmony_ci _div_width, _div_shift) { \ 1338c2ecf20Sopenharmony_ci .id = _id, \ 1348c2ecf20Sopenharmony_ci .parent = _parent, \ 1358c2ecf20Sopenharmony_ci .name = _name, \ 1368c2ecf20Sopenharmony_ci .divider_reg = _div_reg, \ 1378c2ecf20Sopenharmony_ci .divider_shift = _div_shift, \ 1388c2ecf20Sopenharmony_ci .divider_width = _div_width, \ 1398c2ecf20Sopenharmony_ci .gate_reg = _gate_reg, \ 1408c2ecf20Sopenharmony_ci .gate_shift = _gate_shift, \ 1418c2ecf20Sopenharmony_ci .mux_shift = -1, \ 1428c2ecf20Sopenharmony_ci .flags = 0, \ 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistruct clk *mtk_clk_register_composite(const struct mtk_composite *mc, 1468c2ecf20Sopenharmony_ci void __iomem *base, spinlock_t *lock); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_civoid mtk_clk_register_composites(const struct mtk_composite *mcs, 1498c2ecf20Sopenharmony_ci int num, void __iomem *base, spinlock_t *lock, 1508c2ecf20Sopenharmony_ci struct clk_onecell_data *clk_data); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistruct mtk_gate_regs { 1538c2ecf20Sopenharmony_ci u32 sta_ofs; 1548c2ecf20Sopenharmony_ci u32 clr_ofs; 1558c2ecf20Sopenharmony_ci u32 set_ofs; 1568c2ecf20Sopenharmony_ci}; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistruct mtk_gate { 1598c2ecf20Sopenharmony_ci int id; 1608c2ecf20Sopenharmony_ci const char *name; 1618c2ecf20Sopenharmony_ci const char *parent_name; 1628c2ecf20Sopenharmony_ci const struct mtk_gate_regs *regs; 1638c2ecf20Sopenharmony_ci int shift; 1648c2ecf20Sopenharmony_ci const struct clk_ops *ops; 1658c2ecf20Sopenharmony_ci unsigned long flags; 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ciint mtk_clk_register_gates(struct device_node *node, 1698c2ecf20Sopenharmony_ci const struct mtk_gate *clks, int num, 1708c2ecf20Sopenharmony_ci struct clk_onecell_data *clk_data); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ciint mtk_clk_register_gates_with_dev(struct device_node *node, 1738c2ecf20Sopenharmony_ci const struct mtk_gate *clks, 1748c2ecf20Sopenharmony_ci int num, struct clk_onecell_data *clk_data, 1758c2ecf20Sopenharmony_ci struct device *dev); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistruct mtk_clk_divider { 1788c2ecf20Sopenharmony_ci int id; 1798c2ecf20Sopenharmony_ci const char *name; 1808c2ecf20Sopenharmony_ci const char *parent_name; 1818c2ecf20Sopenharmony_ci unsigned long flags; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci u32 div_reg; 1848c2ecf20Sopenharmony_ci unsigned char div_shift; 1858c2ecf20Sopenharmony_ci unsigned char div_width; 1868c2ecf20Sopenharmony_ci unsigned char clk_divider_flags; 1878c2ecf20Sopenharmony_ci const struct clk_div_table *clk_div_table; 1888c2ecf20Sopenharmony_ci}; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ 1918c2ecf20Sopenharmony_ci .id = _id, \ 1928c2ecf20Sopenharmony_ci .name = _name, \ 1938c2ecf20Sopenharmony_ci .parent_name = _parent, \ 1948c2ecf20Sopenharmony_ci .div_reg = _reg, \ 1958c2ecf20Sopenharmony_ci .div_shift = _shift, \ 1968c2ecf20Sopenharmony_ci .div_width = _width, \ 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_civoid mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, 2008c2ecf20Sopenharmony_ci int num, void __iomem *base, spinlock_t *lock, 2018c2ecf20Sopenharmony_ci struct clk_onecell_data *clk_data); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistruct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci#define HAVE_RST_BAR BIT(0) 2068c2ecf20Sopenharmony_ci#define PLL_AO BIT(1) 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistruct mtk_pll_div_table { 2098c2ecf20Sopenharmony_ci u32 div; 2108c2ecf20Sopenharmony_ci unsigned long freq; 2118c2ecf20Sopenharmony_ci}; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistruct mtk_pll_data { 2148c2ecf20Sopenharmony_ci int id; 2158c2ecf20Sopenharmony_ci const char *name; 2168c2ecf20Sopenharmony_ci uint32_t reg; 2178c2ecf20Sopenharmony_ci uint32_t pwr_reg; 2188c2ecf20Sopenharmony_ci uint32_t en_mask; 2198c2ecf20Sopenharmony_ci uint32_t pd_reg; 2208c2ecf20Sopenharmony_ci uint32_t tuner_reg; 2218c2ecf20Sopenharmony_ci uint32_t tuner_en_reg; 2228c2ecf20Sopenharmony_ci uint8_t tuner_en_bit; 2238c2ecf20Sopenharmony_ci int pd_shift; 2248c2ecf20Sopenharmony_ci unsigned int flags; 2258c2ecf20Sopenharmony_ci const struct clk_ops *ops; 2268c2ecf20Sopenharmony_ci u32 rst_bar_mask; 2278c2ecf20Sopenharmony_ci unsigned long fmin; 2288c2ecf20Sopenharmony_ci unsigned long fmax; 2298c2ecf20Sopenharmony_ci int pcwbits; 2308c2ecf20Sopenharmony_ci int pcwibits; 2318c2ecf20Sopenharmony_ci uint32_t pcw_reg; 2328c2ecf20Sopenharmony_ci int pcw_shift; 2338c2ecf20Sopenharmony_ci uint32_t pcw_chg_reg; 2348c2ecf20Sopenharmony_ci const struct mtk_pll_div_table *div_table; 2358c2ecf20Sopenharmony_ci const char *parent_name; 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_civoid mtk_clk_register_plls(struct device_node *node, 2398c2ecf20Sopenharmony_ci const struct mtk_pll_data *plls, int num_plls, 2408c2ecf20Sopenharmony_ci struct clk_onecell_data *clk_data); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistruct clk *mtk_clk_register_ref2usb_tx(const char *name, 2438c2ecf20Sopenharmony_ci const char *parent_name, void __iomem *reg); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_civoid mtk_register_reset_controller(struct device_node *np, 2468c2ecf20Sopenharmony_ci unsigned int num_regs, int regofs); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_civoid mtk_register_reset_controller_set_clr(struct device_node *np, 2498c2ecf20Sopenharmony_ci unsigned int num_regs, int regofs); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci#endif /* __DRV_CLK_MTK_H */ 252