442 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright (c) 2013 Samsung Electronics Co., Ltd.4 * Copyright (c) 2013 Linaro Ltd.5 * Author: Thomas Abraham <thomas.ab@samsung.com>6 *7 * Common Clock Framework support for all Samsung platforms8*/9 10#ifndef __SAMSUNG_CLK_H11#define __SAMSUNG_CLK_H12 13#include <linux/clk-provider.h>14#include "clk-pll.h"15#include "clk-cpu.h"16 17/**18 * struct samsung_clk_provider - information about clock provider19 * @reg_base: virtual address for the register base20 * @dev: clock provider device needed for runtime PM21 * @lock: maintains exclusion between callbacks for a given clock-provider22 * @clk_data: holds clock related data like clk_hw* and number of clocks23 */24struct samsung_clk_provider {25 void __iomem *reg_base;26 struct device *dev;27 spinlock_t lock;28 /* clk_data must be the last entry due to variable length 'hws' array */29 struct clk_hw_onecell_data clk_data;30};31 32/**33 * struct samsung_clock_alias - information about mux clock34 * @id: platform specific id of the clock35 * @dev_name: name of the device to which this clock belongs36 * @alias: optional clock alias name to be assigned to this clock37 */38struct samsung_clock_alias {39 unsigned int id;40 const char *dev_name;41 const char *alias;42};43 44#define ALIAS(_id, dname, a) \45 { \46 .id = _id, \47 .dev_name = dname, \48 .alias = a, \49 }50 51#define MHZ (1000 * 1000)52 53/**54 * struct samsung_fixed_rate_clock - information about fixed-rate clock55 * @id: platform specific id of the clock56 * @name: name of this fixed-rate clock57 * @parent_name: optional parent clock name58 * @flags: optional fixed-rate clock flags59 * @fixed_rate: fixed clock rate of this clock60 */61struct samsung_fixed_rate_clock {62 unsigned int id;63 char *name;64 const char *parent_name;65 unsigned long flags;66 unsigned long fixed_rate;67};68 69#define FRATE(_id, cname, pname, f, frate) \70 { \71 .id = _id, \72 .name = cname, \73 .parent_name = pname, \74 .flags = f, \75 .fixed_rate = frate, \76 }77 78/**79 * struct samsung_fixed_factor_clock - information about fixed-factor clock80 * @id: platform specific id of the clock81 * @name: name of this fixed-factor clock82 * @parent_name: parent clock name83 * @mult: fixed multiplication factor84 * @div: fixed division factor85 * @flags: optional fixed-factor clock flags86 */87struct samsung_fixed_factor_clock {88 unsigned int id;89 char *name;90 const char *parent_name;91 unsigned long mult;92 unsigned long div;93 unsigned long flags;94};95 96#define FFACTOR(_id, cname, pname, m, d, f) \97 { \98 .id = _id, \99 .name = cname, \100 .parent_name = pname, \101 .mult = m, \102 .div = d, \103 .flags = f, \104 }105 106/**107 * struct samsung_mux_clock - information about mux clock108 * @id: platform specific id of the clock109 * @name: name of this mux clock110 * @parent_names: array of pointer to parent clock names111 * @num_parents: number of parents listed in @parent_names112 * @flags: optional flags for basic clock113 * @offset: offset of the register for configuring the mux114 * @shift: starting bit location of the mux control bit-field in @reg115 * @width: width of the mux control bit-field in @reg116 * @mux_flags: flags for mux-type clock117 */118struct samsung_mux_clock {119 unsigned int id;120 const char *name;121 const char *const *parent_names;122 u8 num_parents;123 unsigned long flags;124 unsigned long offset;125 u8 shift;126 u8 width;127 u8 mux_flags;128};129 130#define __MUX(_id, cname, pnames, o, s, w, f, mf) \131 { \132 .id = _id, \133 .name = cname, \134 .parent_names = pnames, \135 .num_parents = ARRAY_SIZE(pnames), \136 .flags = f, \137 .offset = o, \138 .shift = s, \139 .width = w, \140 .mux_flags = mf, \141 }142 143#define MUX(_id, cname, pnames, o, s, w) \144 __MUX(_id, cname, pnames, o, s, w, CLK_SET_RATE_NO_REPARENT, 0)145 146#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \147 __MUX(_id, cname, pnames, o, s, w, (f) | CLK_SET_RATE_NO_REPARENT, mf)148 149/* Used by MUX clocks where reparenting on clock rate change is allowed. */150#define nMUX(_id, cname, pnames, o, s, w) \151 __MUX(_id, cname, pnames, o, s, w, 0, 0)152 153#define nMUX_F(_id, cname, pnames, o, s, w, f, mf) \154 __MUX(_id, cname, pnames, o, s, w, f, mf)155 156/**157 * struct samsung_div_clock - information about div clock158 * @id: platform specific id of the clock159 * @name: name of this div clock160 * @parent_name: name of the parent clock161 * @flags: optional flags for basic clock162 * @offset: offset of the register for configuring the div163 * @shift: starting bit location of the div control bit-field in @reg164 * @width: width of the bitfield165 * @div_flags: flags for div-type clock166 * @table: array of divider/value pairs ending with a div set to 0167 */168struct samsung_div_clock {169 unsigned int id;170 const char *name;171 const char *parent_name;172 unsigned long flags;173 unsigned long offset;174 u8 shift;175 u8 width;176 u8 div_flags;177 struct clk_div_table *table;178};179 180#define __DIV(_id, cname, pname, o, s, w, f, df, t) \181 { \182 .id = _id, \183 .name = cname, \184 .parent_name = pname, \185 .flags = f, \186 .offset = o, \187 .shift = s, \188 .width = w, \189 .div_flags = df, \190 .table = t, \191 }192 193#define DIV(_id, cname, pname, o, s, w) \194 __DIV(_id, cname, pname, o, s, w, 0, 0, NULL)195 196#define DIV_F(_id, cname, pname, o, s, w, f, df) \197 __DIV(_id, cname, pname, o, s, w, f, df, NULL)198 199#define DIV_T(_id, cname, pname, o, s, w, t) \200 __DIV(_id, cname, pname, o, s, w, 0, 0, t)201 202/**203 * struct samsung_gate_clock - information about gate clock204 * @id: platform specific id of the clock205 * @name: name of this gate clock206 * @parent_name: name of the parent clock207 * @flags: optional flags for basic clock208 * @offset: offset of the register for configuring the gate209 * @bit_idx: bit index of the gate control bit-field in @reg210 * @gate_flags: flags for gate-type clock211 */212struct samsung_gate_clock {213 unsigned int id;214 const char *name;215 const char *parent_name;216 unsigned long flags;217 unsigned long offset;218 u8 bit_idx;219 u8 gate_flags;220};221 222#define __GATE(_id, cname, pname, o, b, f, gf) \223 { \224 .id = _id, \225 .name = cname, \226 .parent_name = pname, \227 .flags = f, \228 .offset = o, \229 .bit_idx = b, \230 .gate_flags = gf, \231 }232 233#define GATE(_id, cname, pname, o, b, f, gf) \234 __GATE(_id, cname, pname, o, b, f, gf)235 236#define PNAME(x) static const char * const x[] __initconst237 238/**239 * struct samsung_clk_reg_dump - register dump of clock controller registers240 * @offset: clock register offset from the controller base address241 * @value: the value to be register at offset242 */243struct samsung_clk_reg_dump {244 u32 offset;245 u32 value;246};247 248/**249 * struct samsung_pll_clock - information about pll clock250 * @id: platform specific id of the clock251 * @name: name of this pll clock252 * @parent_name: name of the parent clock253 * @flags: optional flags for basic clock254 * @con_offset: offset of the register for configuring the PLL255 * @lock_offset: offset of the register for locking the PLL256 * @type: type of PLL to be registered257 * @rate_table: array of PLL settings for possible PLL rates258 */259struct samsung_pll_clock {260 unsigned int id;261 const char *name;262 const char *parent_name;263 unsigned long flags;264 int con_offset;265 int lock_offset;266 enum samsung_pll_type type;267 const struct samsung_pll_rate_table *rate_table;268};269 270#define __PLL(_typ, _id, _name, _pname, _flags, _lock, _con, _rtable) \271 { \272 .id = _id, \273 .type = _typ, \274 .name = _name, \275 .parent_name = _pname, \276 .flags = _flags, \277 .con_offset = _con, \278 .lock_offset = _lock, \279 .rate_table = _rtable, \280 }281 282#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable) \283 __PLL(_typ, _id, _name, _pname, CLK_GET_RATE_NOCACHE, _lock, \284 _con, _rtable)285 286struct samsung_cpu_clock {287 unsigned int id;288 const char *name;289 unsigned int parent_id;290 unsigned int alt_parent_id;291 unsigned long flags;292 int offset;293 enum exynos_cpuclk_layout reg_layout;294 const struct exynos_cpuclk_cfg_data *cfg;295};296 297#define CPU_CLK(_id, _name, _pid, _apid, _flags, _offset, _layout, _cfg) \298 { \299 .id = _id, \300 .name = _name, \301 .parent_id = _pid, \302 .alt_parent_id = _apid, \303 .flags = _flags, \304 .offset = _offset, \305 .reg_layout = _layout, \306 .cfg = _cfg, \307 }308 309struct samsung_clock_reg_cache {310 struct list_head node;311 void __iomem *reg_base;312 struct samsung_clk_reg_dump *rdump;313 unsigned int rd_num;314 const struct samsung_clk_reg_dump *rsuspend;315 unsigned int rsuspend_num;316};317 318/**319 * struct samsung_cmu_info - all clocks information needed for CMU registration320 * @pll_clks: list of PLL clocks321 * @nr_pll_clks: count of clocks in @pll_clks322 * @mux_clks: list of mux clocks323 * @nr_mux_clks: count of clocks in @mux_clks324 * @div_clks: list of div clocks325 * @nr_div_clks: count of clocks in @div_clks326 * @gate_clks: list of gate clocks327 * @nr_gate_clks: count of clocks in @gate_clks328 * @fixed_clks: list of fixed clocks329 * @nr_fixed_clks: count clocks in @fixed_clks330 * @fixed_factor_clks: list of fixed factor clocks331 * @nr_fixed_factor_clks: count of clocks in @fixed_factor_clks332 * @nr_clk_ids: total number of clocks with IDs assigned333 * @cpu_clks: list of CPU clocks334 * @nr_cpu_clks: count of clocks in @cpu_clks335 * @clk_regs: list of clock registers336 * @nr_clk_regs: count of clock registers in @clk_regs337 * @suspend_regs: list of clock registers to set before suspend338 * @nr_suspend_regs: count of clock registers in @suspend_regs339 * @clk_name: name of the parent clock needed for CMU register access340 * @manual_plls: Enable manual control for PLL clocks341 */342struct samsung_cmu_info {343 const struct samsung_pll_clock *pll_clks;344 unsigned int nr_pll_clks;345 const struct samsung_mux_clock *mux_clks;346 unsigned int nr_mux_clks;347 const struct samsung_div_clock *div_clks;348 unsigned int nr_div_clks;349 const struct samsung_gate_clock *gate_clks;350 unsigned int nr_gate_clks;351 const struct samsung_fixed_rate_clock *fixed_clks;352 unsigned int nr_fixed_clks;353 const struct samsung_fixed_factor_clock *fixed_factor_clks;354 unsigned int nr_fixed_factor_clks;355 unsigned int nr_clk_ids;356 const struct samsung_cpu_clock *cpu_clks;357 unsigned int nr_cpu_clks;358 359 const unsigned long *clk_regs;360 unsigned int nr_clk_regs;361 362 const struct samsung_clk_reg_dump *suspend_regs;363 unsigned int nr_suspend_regs;364 const char *clk_name;365 366 /* ARM64 Exynos CMUs */367 bool manual_plls;368};369 370struct samsung_clk_provider *samsung_clk_init(struct device *dev,371 void __iomem *base, unsigned long nr_clks);372void samsung_clk_of_add_provider(struct device_node *np,373 struct samsung_clk_provider *ctx);374void samsung_clk_of_register_fixed_ext(375 struct samsung_clk_provider *ctx,376 struct samsung_fixed_rate_clock *fixed_rate_clk,377 unsigned int nr_fixed_rate_clk,378 const struct of_device_id *clk_matches);379 380void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,381 struct clk_hw *clk_hw, unsigned int id);382 383void samsung_clk_register_alias(struct samsung_clk_provider *ctx,384 const struct samsung_clock_alias *list,385 unsigned int nr_clk);386void samsung_clk_register_fixed_rate(387 struct samsung_clk_provider *ctx,388 const struct samsung_fixed_rate_clock *clk_list,389 unsigned int nr_clk);390void samsung_clk_register_fixed_factor(391 struct samsung_clk_provider *ctx,392 const struct samsung_fixed_factor_clock *list,393 unsigned int nr_clk);394void samsung_clk_register_mux(struct samsung_clk_provider *ctx,395 const struct samsung_mux_clock *clk_list,396 unsigned int nr_clk);397void samsung_clk_register_div(struct samsung_clk_provider *ctx,398 const struct samsung_div_clock *clk_list,399 unsigned int nr_clk);400void samsung_clk_register_gate(struct samsung_clk_provider *ctx,401 const struct samsung_gate_clock *clk_list,402 unsigned int nr_clk);403void samsung_clk_register_pll(struct samsung_clk_provider *ctx,404 const struct samsung_pll_clock *pll_list,405 unsigned int nr_clk);406void samsung_clk_register_cpu(struct samsung_clk_provider *ctx,407 const struct samsung_cpu_clock *list, unsigned int nr_clk);408 409void samsung_cmu_register_clocks(struct samsung_clk_provider *ctx,410 const struct samsung_cmu_info *cmu);411struct samsung_clk_provider *samsung_cmu_register_one(412 struct device_node *,413 const struct samsung_cmu_info *);414 415#ifdef CONFIG_PM_SLEEP416void samsung_clk_extended_sleep_init(void __iomem *reg_base,417 const unsigned long *rdump,418 unsigned long nr_rdump,419 const struct samsung_clk_reg_dump *rsuspend,420 unsigned long nr_rsuspend);421#else422static inline void samsung_clk_extended_sleep_init(void __iomem *reg_base,423 const unsigned long *rdump,424 unsigned long nr_rdump,425 const struct samsung_clk_reg_dump *rsuspend,426 unsigned long nr_rsuspend) {}427#endif428#define samsung_clk_sleep_init(reg_base, rdump, nr_rdump) \429 samsung_clk_extended_sleep_init(reg_base, rdump, nr_rdump, NULL, 0)430 431void samsung_clk_save(void __iomem *base,432 struct samsung_clk_reg_dump *rd,433 unsigned int num_regs);434void samsung_clk_restore(void __iomem *base,435 const struct samsung_clk_reg_dump *rd,436 unsigned int num_regs);437struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(438 const unsigned long *rdump,439 unsigned long nr_rdump);440 441#endif /* __SAMSUNG_CLK_H */442