blob: f230205c31126ab85b64d2980c64f3b41c6befb6 [file] [log] [blame]
Tom Rinidec7ea02024-05-20 13:35:03 -06001/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * (C) Copyright 2022 - Analog Devices, Inc.
4 *
5 * Written and/or maintained by Timesys Corporation
6 *
7 * Author: Greg Malysa <greg.malysa@timesys.com>
8 *
9 * Ported from Linux: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
10 */
11
12#ifndef CLK_ADI_CLK_H
13#define CLK_ADI_CLK_H
14
15#include <linux/compiler_types.h>
16#include <linux/types.h>
17#include <linux/clk-provider.h>
18
19#define CGU_CTL 0x00
20#define CGU_PLLCTL 0x04
21#define CGU_STAT 0x08
22#define CGU_DIV 0x0C
23#define CGU_CLKOUTSEL 0x10
24#define CGU_OSCWDCTL 0x14
25#define CGU_TSCTL 0x18
26#define CGU_TSVALUE0 0x1C
27#define CGU_TSVALUE1 0x20
28#define CGU_TSCOUNT0 0x24
29#define CGU_TSCOUNT1 0x28
30#define CGU_CCBF_DIS 0x2C
31#define CGU_CCBF_STAT 0x30
32#define CGU_SCBF_DIS 0x38
33#define CGU_SCBF_STAT 0x3C
34#define CGU_DIVEX 0x40
35#define CGU_REVID 0x48
36
37#define CDU_CFG0 0x00
38#define CDU_CFG1 0x04
39#define CDU_CFG2 0x08
40#define CDU_CFG3 0x0C
41#define CDU_CFG4 0x10
42#define CDU_CFG5 0x14
43#define CDU_CFG6 0x18
44#define CDU_CFG7 0x1C
45#define CDU_CFG8 0x20
46#define CDU_CFG9 0x24
47#define CDU_CFG10 0x28
48#define CDU_CFG11 0x2C
49#define CDU_CFG12 0x30
50#define CDU_CFG13 0x34
51#define CDU_CFG14 0x38
52
53#define PLL3_OFFSET 0x2c
54
55#define CDU_CLKINSEL 0x44
56
57#define CGU_MSEL_SHIFT 8
58#define CGU_MSEL_WIDTH 7
59
60#define PLL3_MSEL_SHIFT 4
61#define PLL3_MSEL_WIDTH 7
62
63#define CDU_MUX_SIZE 4
64#define CDU_MUX_SHIFT 1
65#define CDU_MUX_WIDTH 2
66#define CDU_EN_BIT 0
67
68extern const struct clk_ops adi_clk_ops;
69
70struct clk *sc5xx_cgu_pll(const char *name, const char *parent_name,
71 void __iomem *base, u8 shift, u8 width, u32 m_offset, bool half_m);
72
73/**
74 * All CDU clock muxes are the same size
75 */
76static inline struct clk *cdu_mux(const char *name, void __iomem *reg,
77 const char * const *parents)
78{
79 return clk_register_mux(NULL, name, parents, CDU_MUX_SIZE,
80 CLK_SET_RATE_PARENT, reg, CDU_MUX_SHIFT, CDU_MUX_WIDTH, 0);
81}
82
83static inline struct clk *cgu_divider(const char *name, const char *parent,
84 void __iomem *reg, u8 shift, u8 width, u8 extra_flags)
85{
86 return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT,
87 reg, shift, width, CLK_DIVIDER_MAX_AT_ZERO | extra_flags);
88}
89
90static inline struct clk *cdu_gate(const char *name, const char *parent,
91 void __iomem *reg, u32 flags)
92{
93 return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT | flags,
94 reg, CDU_EN_BIT, 0, NULL);
95}
96
97static inline struct clk *cgu_gate(const char *name, const char *parent,
98 void __iomem *reg, u8 bit)
99{
100 return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg, bit,
101 CLK_GATE_SET_TO_DISABLE, NULL);
102}
103
104static inline int cdu_check_clocks(struct clk *clks[], size_t count)
105{
106 size_t i;
107
108 for (i = 0; i < count; ++i) {
109 if (clks[i]) {
110 if (IS_ERR(clks[i])) {
111 pr_err("Clock %zu failed to register: %ld\n", i, PTR_ERR(clks[i]));
112 return PTR_ERR(clks[i]);
113 }
114 clks[i]->id = i;
115 } else {
116 pr_err("ADI Clock framework: Null pointer detected on clock %zu\n", i);
117 }
118 }
119
120 return 0;
121}
122
123#endif