19741b1a6SJames Liao /* 29741b1a6SJames Liao * Copyright (c) 2014 MediaTek Inc. 39741b1a6SJames Liao * Author: James Liao <jamesjj.liao@mediatek.com> 49741b1a6SJames Liao * 59741b1a6SJames Liao * This program is free software; you can redistribute it and/or modify 69741b1a6SJames Liao * it under the terms of the GNU General Public License version 2 as 79741b1a6SJames Liao * published by the Free Software Foundation. 89741b1a6SJames Liao * 99741b1a6SJames Liao * This program is distributed in the hope that it will be useful, 109741b1a6SJames Liao * but WITHOUT ANY WARRANTY; without even the implied warranty of 119741b1a6SJames Liao * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 129741b1a6SJames Liao * GNU General Public License for more details. 139741b1a6SJames Liao */ 149741b1a6SJames Liao 159741b1a6SJames Liao #ifndef __DRV_CLK_MTK_H 169741b1a6SJames Liao #define __DRV_CLK_MTK_H 179741b1a6SJames Liao 189741b1a6SJames Liao #include <linux/regmap.h> 199741b1a6SJames Liao #include <linux/bitops.h> 209741b1a6SJames Liao #include <linux/clk-provider.h> 219741b1a6SJames Liao 22c726639bSStephen Boyd struct clk; 23c726639bSStephen Boyd 249741b1a6SJames Liao #define MAX_MUX_GATE_BIT 31 259741b1a6SJames Liao #define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) 269741b1a6SJames Liao 279741b1a6SJames Liao #define MHZ (1000 * 1000) 289741b1a6SJames Liao 294fa04380SJames Liao struct mtk_fixed_clk { 304fa04380SJames Liao int id; 314fa04380SJames Liao const char *name; 324fa04380SJames Liao const char *parent; 334fa04380SJames Liao unsigned long rate; 344fa04380SJames Liao }; 354fa04380SJames Liao 364fa04380SJames Liao #define FIXED_CLK(_id, _name, _parent, _rate) { \ 374fa04380SJames Liao .id = _id, \ 384fa04380SJames Liao .name = _name, \ 394fa04380SJames Liao .parent = _parent, \ 404fa04380SJames Liao .rate = _rate, \ 414fa04380SJames Liao } 424fa04380SJames Liao 434fa04380SJames Liao void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, 444fa04380SJames Liao int num, struct clk_onecell_data *clk_data); 454fa04380SJames Liao 469741b1a6SJames Liao struct mtk_fixed_factor { 479741b1a6SJames Liao int id; 489741b1a6SJames Liao const char *name; 499741b1a6SJames Liao const char *parent_name; 509741b1a6SJames Liao int mult; 519741b1a6SJames Liao int div; 529741b1a6SJames Liao }; 539741b1a6SJames Liao 549741b1a6SJames Liao #define FACTOR(_id, _name, _parent, _mult, _div) { \ 559741b1a6SJames Liao .id = _id, \ 569741b1a6SJames Liao .name = _name, \ 579741b1a6SJames Liao .parent_name = _parent, \ 589741b1a6SJames Liao .mult = _mult, \ 599741b1a6SJames Liao .div = _div, \ 609741b1a6SJames Liao } 619741b1a6SJames Liao 6207d13069SJames Liao void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, 639741b1a6SJames Liao int num, struct clk_onecell_data *clk_data); 649741b1a6SJames Liao 659741b1a6SJames Liao struct mtk_composite { 669741b1a6SJames Liao int id; 679741b1a6SJames Liao const char *name; 689741b1a6SJames Liao const char * const *parent_names; 699741b1a6SJames Liao const char *parent; 709741b1a6SJames Liao unsigned flags; 719741b1a6SJames Liao 729741b1a6SJames Liao uint32_t mux_reg; 739741b1a6SJames Liao uint32_t divider_reg; 749741b1a6SJames Liao uint32_t gate_reg; 759741b1a6SJames Liao 769741b1a6SJames Liao signed char mux_shift; 779741b1a6SJames Liao signed char mux_width; 789741b1a6SJames Liao signed char gate_shift; 799741b1a6SJames Liao 809741b1a6SJames Liao signed char divider_shift; 819741b1a6SJames Liao signed char divider_width; 829741b1a6SJames Liao 839741b1a6SJames Liao signed char num_parents; 849741b1a6SJames Liao }; 859741b1a6SJames Liao 8606445994SPhilipp Zabel /* 8706445994SPhilipp Zabel * In case the rate change propagation to parent clocks is undesirable, 8806445994SPhilipp Zabel * this macro allows to specify the clock flags manually. 8906445994SPhilipp Zabel */ 90*e9862118SShunli Wang #define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ 91*e9862118SShunli Wang _gate, _flags) { \ 929741b1a6SJames Liao .id = _id, \ 939741b1a6SJames Liao .name = _name, \ 949741b1a6SJames Liao .mux_reg = _reg, \ 959741b1a6SJames Liao .mux_shift = _shift, \ 969741b1a6SJames Liao .mux_width = _width, \ 979741b1a6SJames Liao .gate_reg = _reg, \ 989741b1a6SJames Liao .gate_shift = _gate, \ 999741b1a6SJames Liao .divider_shift = -1, \ 1009741b1a6SJames Liao .parent_names = _parents, \ 1019741b1a6SJames Liao .num_parents = ARRAY_SIZE(_parents), \ 10206445994SPhilipp Zabel .flags = _flags, \ 1039741b1a6SJames Liao } 1049741b1a6SJames Liao 10506445994SPhilipp Zabel /* 10606445994SPhilipp Zabel * Unless necessary, all MUX_GATE clocks propagate rate changes to their 10706445994SPhilipp Zabel * parent clock by default. 10806445994SPhilipp Zabel */ 10906445994SPhilipp Zabel #define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) \ 110*e9862118SShunli Wang MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ 111*e9862118SShunli Wang _gate, CLK_SET_RATE_PARENT) 11206445994SPhilipp Zabel 1139741b1a6SJames Liao #define MUX(_id, _name, _parents, _reg, _shift, _width) { \ 1149741b1a6SJames Liao .id = _id, \ 1159741b1a6SJames Liao .name = _name, \ 1169741b1a6SJames Liao .mux_reg = _reg, \ 1179741b1a6SJames Liao .mux_shift = _shift, \ 1189741b1a6SJames Liao .mux_width = _width, \ 1199741b1a6SJames Liao .gate_shift = -1, \ 1209741b1a6SJames Liao .divider_shift = -1, \ 1219741b1a6SJames Liao .parent_names = _parents, \ 1229741b1a6SJames Liao .num_parents = ARRAY_SIZE(_parents), \ 1239741b1a6SJames Liao .flags = CLK_SET_RATE_PARENT, \ 1249741b1a6SJames Liao } 1259741b1a6SJames Liao 126*e9862118SShunli Wang #define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \ 127*e9862118SShunli Wang _div_width, _div_shift) { \ 1289741b1a6SJames Liao .id = _id, \ 1299741b1a6SJames Liao .parent = _parent, \ 1309741b1a6SJames Liao .name = _name, \ 1319741b1a6SJames Liao .divider_reg = _div_reg, \ 1329741b1a6SJames Liao .divider_shift = _div_shift, \ 1339741b1a6SJames Liao .divider_width = _div_width, \ 1349741b1a6SJames Liao .gate_reg = _gate_reg, \ 1359741b1a6SJames Liao .gate_shift = _gate_shift, \ 1369741b1a6SJames Liao .mux_shift = -1, \ 1379741b1a6SJames Liao .flags = 0, \ 1389741b1a6SJames Liao } 1399741b1a6SJames Liao 1409741b1a6SJames Liao struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, 1419741b1a6SJames Liao void __iomem *base, spinlock_t *lock); 1429741b1a6SJames Liao 1439741b1a6SJames Liao void mtk_clk_register_composites(const struct mtk_composite *mcs, 1449741b1a6SJames Liao int num, void __iomem *base, spinlock_t *lock, 1459741b1a6SJames Liao struct clk_onecell_data *clk_data); 1469741b1a6SJames Liao 1479741b1a6SJames Liao struct mtk_gate_regs { 1489741b1a6SJames Liao u32 sta_ofs; 1499741b1a6SJames Liao u32 clr_ofs; 1509741b1a6SJames Liao u32 set_ofs; 1519741b1a6SJames Liao }; 1529741b1a6SJames Liao 1539741b1a6SJames Liao struct mtk_gate { 1549741b1a6SJames Liao int id; 1559741b1a6SJames Liao const char *name; 1569741b1a6SJames Liao const char *parent_name; 1579741b1a6SJames Liao const struct mtk_gate_regs *regs; 1589741b1a6SJames Liao int shift; 1599741b1a6SJames Liao const struct clk_ops *ops; 1609741b1a6SJames Liao }; 1619741b1a6SJames Liao 162*e9862118SShunli Wang int mtk_clk_register_gates(struct device_node *node, 163*e9862118SShunli Wang const struct mtk_gate *clks, int num, 164*e9862118SShunli Wang struct clk_onecell_data *clk_data); 165*e9862118SShunli Wang 166*e9862118SShunli Wang struct mtk_clk_divider { 167*e9862118SShunli Wang int id; 168*e9862118SShunli Wang const char *name; 169*e9862118SShunli Wang const char *parent_name; 170*e9862118SShunli Wang unsigned long flags; 171*e9862118SShunli Wang 172*e9862118SShunli Wang u32 div_reg; 173*e9862118SShunli Wang unsigned char div_shift; 174*e9862118SShunli Wang unsigned char div_width; 175*e9862118SShunli Wang unsigned char clk_divider_flags; 176*e9862118SShunli Wang const struct clk_div_table *clk_div_table; 177*e9862118SShunli Wang }; 178*e9862118SShunli Wang 179*e9862118SShunli Wang #define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ 180*e9862118SShunli Wang .id = _id, \ 181*e9862118SShunli Wang .name = _name, \ 182*e9862118SShunli Wang .parent_name = _parent, \ 183*e9862118SShunli Wang .div_reg = _reg, \ 184*e9862118SShunli Wang .div_shift = _shift, \ 185*e9862118SShunli Wang .div_width = _width, \ 186*e9862118SShunli Wang } 187*e9862118SShunli Wang 188*e9862118SShunli Wang void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, 189*e9862118SShunli Wang int num, void __iomem *base, spinlock_t *lock, 190*e9862118SShunli Wang struct clk_onecell_data *clk_data); 1919741b1a6SJames Liao 1929741b1a6SJames Liao struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); 1939741b1a6SJames Liao 1949741b1a6SJames Liao #define HAVE_RST_BAR BIT(0) 195*e9862118SShunli Wang #define PLL_AO BIT(1) 1969741b1a6SJames Liao 19775ce0cdbSJames Liao struct mtk_pll_div_table { 19875ce0cdbSJames Liao u32 div; 19975ce0cdbSJames Liao unsigned long freq; 20075ce0cdbSJames Liao }; 20175ce0cdbSJames Liao 2029741b1a6SJames Liao struct mtk_pll_data { 2039741b1a6SJames Liao int id; 2049741b1a6SJames Liao const char *name; 2059741b1a6SJames Liao uint32_t reg; 2069741b1a6SJames Liao uint32_t pwr_reg; 2079741b1a6SJames Liao uint32_t en_mask; 2089741b1a6SJames Liao uint32_t pd_reg; 2099741b1a6SJames Liao uint32_t tuner_reg; 2109741b1a6SJames Liao int pd_shift; 2119741b1a6SJames Liao unsigned int flags; 2129741b1a6SJames Liao const struct clk_ops *ops; 2139741b1a6SJames Liao u32 rst_bar_mask; 2149741b1a6SJames Liao unsigned long fmax; 2159741b1a6SJames Liao int pcwbits; 2169741b1a6SJames Liao uint32_t pcw_reg; 2179741b1a6SJames Liao int pcw_shift; 21875ce0cdbSJames Liao const struct mtk_pll_div_table *div_table; 2199741b1a6SJames Liao }; 2209741b1a6SJames Liao 22107d13069SJames Liao void mtk_clk_register_plls(struct device_node *node, 2229741b1a6SJames Liao const struct mtk_pll_data *plls, int num_plls, 2239741b1a6SJames Liao struct clk_onecell_data *clk_data); 2249741b1a6SJames Liao 225cdb2bab7SJames Liao struct clk *mtk_clk_register_ref2usb_tx(const char *name, 226cdb2bab7SJames Liao const char *parent_name, void __iomem *reg); 227cdb2bab7SJames Liao 228d633fb7aSSascha Hauer #ifdef CONFIG_RESET_CONTROLLER 229d633fb7aSSascha Hauer void mtk_register_reset_controller(struct device_node *np, 230d633fb7aSSascha Hauer unsigned int num_regs, int regofs); 231d633fb7aSSascha Hauer #else 232d633fb7aSSascha Hauer static inline void mtk_register_reset_controller(struct device_node *np, 233d633fb7aSSascha Hauer unsigned int num_regs, int regofs) 234d633fb7aSSascha Hauer { 235d633fb7aSSascha Hauer } 236d633fb7aSSascha Hauer #endif 237d633fb7aSSascha Hauer 2389741b1a6SJames Liao #endif /* __DRV_CLK_MTK_H */ 239