1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <stdint.h>
8 #include <unistd.h>
9 
10 #include <ddk/mmio-buffer.h>
11 #include <hw/reg.h>
12 #include <zircon/assert.h>
13 
14 // clang-format off
15 #define SDM_FRACTIONALITY         ((uint32_t)16384)
16 #define S905D2_FIXED_PLL_RATE     ((uint32_t)2000000000)
17 
18 /* Initial configuration values for PLLs.  These were taken
19     from the AmLogic SDK.  No documentation available to
20     understand settings at this time beyond the multiply/divide
21     ratios.
22 */
23 #define G12A_MPLL_CNTL0 0x00000543
24 #define G12A_MPLL_CNTL2 0x40000033
25 
26 // TODO(hollande) - the pll design for HIFI and SYS are
27 //  the same.  Find out from Amlogic whey the register
28 //  settings are different.
29 #define G12A_HIFI_PLL_CNTL1 0x00000000
30 #define G12A_HIFI_PLL_CNTL2 0x00000000
31 #define G12A_HIFI_PLL_CNTL3 0x6a285c00
32 #define G12A_HIFI_PLL_CNTL4 0x65771290
33 #define G12A_HIFI_PLL_CNTL5 0x39272000
34 #define G12A_HIFI_PLL_CNTL6 0x56540000
35 
36 #define G12A_SYS_PLL_CNTL1 0x00000000
37 #define G12A_SYS_PLL_CNTL2 0x00000000
38 #define G12A_SYS_PLL_CNTL3 0x48681c00
39 #define G12A_SYS_PLL_CNTL4 0x88770290
40 #define G12A_SYS_PLL_CNTL5 0x39272000
41 #define G12A_SYS_PLL_CNTL6 0x56540000
42 
43 #define G12A_GP0_PLL_CNTL1 0x00000000
44 #define G12A_GP0_PLL_CNTL2 0x00000000
45 #define G12A_GP0_PLL_CNTL3 0x48681c00
46 #define G12A_GP0_PLL_CNTL4 0x33771290
47 #define G12A_GP0_PLL_CNTL5 0x39272000
48 #define G12A_GP0_PLL_CNTL6 0x56540000
49 
50 // HHI register offsets (all are 32-bit registers)
51 #define HHI_GP0_PLL_CNTL0           (0x10 << 2)
52 #define HHI_PCIE_PLL_CNTL0          (0x26 << 2)
53 
54 #define HHI_HIFI_PLL_CNTL0          (0x36 << 2)
55 #define HHI_HIFI_PLL_CNTL1          (0x37 << 2)
56 #define HHI_HIFI_PLL_CNTL2          (0x38 << 2)
57 #define HHI_HIFI_PLL_CNTL3          (0x39 << 2)
58 #define HHI_HIFI_PLL_CNTL4          (0x3a << 2)
59 #define HHI_HIFI_PLL_CNTL5          (0x3b << 2)
60 #define HHI_HIFI_PLL_CNTL6          (0x3c << 2)
61 
62 #define HHI_MPLL_CNTL0              (0x9e << 2)
63 #define HHI_MPLL_CNTL1              (0x9f << 2)
64 #define HHI_MPLL_CNTL2              (0xa0 << 2)
65 #define HHI_MPLL_CNTL3              (0xa1 << 2)
66 #define HHI_MPLL_CNTL4              (0xa2 << 2)
67 #define HHI_MPLL_CNTL5              (0xa3 << 2)
68 #define HHI_MPLL_CNTL6              (0xa4 << 2)
69 #define HHI_MPLL_CNTL7              (0xa5 << 2)
70 #define HHI_MPLL_CNTL8              (0xa6 << 2)
71 
72 #define HHI_FIX_PLL_CNTL0           (0xa8 << 2)
73 #define HHI_FIX_PLL_CNTL1           (0xa9 << 2)
74 #define HHI_FIX_PLL_CNTL2           (0xaa << 2)
75 #define HHI_FIX_PLL_CNTL3           (0xab << 2)
76 #define HHI_FIX_PLL_CNTL4           (0xac << 2)
77 #define HHI_FIX_PLL_CNTL5           (0xad << 2)
78 #define HHI_FIX_PLL_CNTL6           (0xae << 2)
79 
80 #define HHI_SYS_PLL_CNTL0           (0xbd << 2)
81 #define HHI_SYS_PLL_CNTL1           (0xbe << 2)
82 #define HHI_SYS_PLL_CNTL2           (0xbf << 2)
83 #define HHI_SYS_PLL_CNTL3           (0xc0 << 2)
84 #define HHI_SYS_PLL_CNTL4           (0xc1 << 2)
85 #define HHI_SYS_PLL_CNTL5           (0xc2 << 2)
86 #define HHI_SYS_PLL_CNTL6           (0xc3 << 2)
87 
88 #define HHI_GP0_PLL_CNTL0           (0x10 << 2)
89 #define HHI_GP0_PLL_CNTL1           (0x11 << 2)
90 #define HHI_GP0_PLL_CNTL2           (0x12 << 2)
91 #define HHI_GP0_PLL_CNTL3           (0x13 << 2)
92 #define HHI_GP0_PLL_CNTL4           (0x14 << 2)
93 #define HHI_GP0_PLL_CNTL5           (0x15 << 2)
94 #define HHI_GP0_PLL_CNTL6           (0x16 << 2)
95 
96 // HHI PLL register bitfield definitions
97 #define HHI_PLL_LOCK           (1 << 31)
98 #define HHI_PLL_CNTL0_EN       (1 << 28)
99 #define HHI_PLL_CNTL0_RESET    (1 << 29)
100 #define HHI_PLL_CNTL0_M_SHIFT  (0)
101 #define HHI_PLL_CNTL0_M        (0xff << HHI_PLL_CNTL0_M_SHIFT)
102 #define HHI_PLL_CNTL0_N_SHIFT  (10)
103 #define HHI_PLL_CNTL0_N        (0x1f << HHI_PLL_CNTL0_N_SHIFT)
104 #define HHI_PLL_CNTL0_OD_SHIFT (16)
105 #define HHI_PLL_CNTL0_OD       (0x3  << HHI_PLL_CNTL0_OD_SHIFT)
106 
107 // clang-format on
108 
109 typedef enum {
110     GP0_PLL,
111     PCIE_PLL,
112     HIFI_PLL,
113     SYS_PLL,
114 } hhi_plls_t;
115 
116 typedef struct {
117     uint64_t rate;
118     uint32_t n;
119     uint32_t m;
120     uint32_t frac;
121     uint32_t od;
122 } hhi_pll_rate_t;
123 
124 typedef struct aml_hiu_dev {
125     mmio_buffer_t mmio;
126     uint8_t* regs_vaddr;
127 } aml_hiu_dev_t;
128 
129 typedef struct aml_pll_dev {
130     aml_hiu_dev_t* hiu;               // Pointer to the register control block.
131     const hhi_pll_rate_t* rate_table; // Pointer to this PLLs rate table.
132     uint32_t rate_idx;                // Index in rate table of current setting.
133     uint32_t frequency;               // Current operating frequency.
134     hhi_plls_t pll_num;               // Which pll is this
135     size_t rate_count;                // Number of entries in the rate table.
136 } aml_pll_dev_t;
137 
hiu_clk_get_reg(aml_hiu_dev_t * dev,uint32_t offset)138 static inline uint32_t hiu_clk_get_reg(aml_hiu_dev_t* dev, uint32_t offset) {
139     return readl(dev->regs_vaddr + offset);
140 }
141 
hiu_clk_set_reg(aml_hiu_dev_t * dev,uint32_t offset,uint32_t value)142 static inline uint32_t hiu_clk_set_reg(aml_hiu_dev_t* dev, uint32_t offset, uint32_t value) {
143     writel(value, dev->regs_vaddr + offset);
144     return hiu_clk_get_reg(dev, offset);
145 }
146 
hiu_get_pll_offs(aml_pll_dev_t * pll_dev)147 static inline uint32_t hiu_get_pll_offs(aml_pll_dev_t* pll_dev) {
148     switch (pll_dev->pll_num) {
149     case GP0_PLL:
150         return HHI_GP0_PLL_CNTL0;
151     case PCIE_PLL:
152         return HHI_PCIE_PLL_CNTL0;
153     case HIFI_PLL:
154         return HHI_HIFI_PLL_CNTL0;
155     case SYS_PLL:
156         return HHI_SYS_PLL_CNTL0;
157     default:
158         ZX_DEBUG_ASSERT(0);
159     }
160     return 0;
161 }
162 
163 __BEGIN_CDECLS;
164 
165 /*
166     Maps the hiu register block (containing all the pll controls).
167 */
168 zx_status_t s905d2_hiu_init(aml_hiu_dev_t* device);
169 
170 /*
171     Initializes the selected pll. This resetting the pll and writing initial
172     values to control registers.  When exiting init the PLL will be in a
173     halted (de-enabled) state.
174 */
175 zx_status_t s905d2_pll_init(aml_hiu_dev_t* device, aml_pll_dev_t* pll, hhi_plls_t pll_num);
176 /*
177     Sets the rate of the selected pll. If the requested frequency is not found
178     it will return with ZX_ERR_NOT_SUPPORTED.
179 */
180 zx_status_t s905d2_pll_set_rate(aml_pll_dev_t* pll, uint64_t freq);
181 
182 /*
183     Enables the selected pll.  This assumes the pll has been initialized and
184     valid divider values have been written to the control registers.
185 */
186 zx_status_t s905d2_pll_ena(aml_pll_dev_t* pll);
187 
188 /*
189     Disable the selected pll.  Returns if the pll was actually enabled
190     when the call was made.
191 */
192 bool s905d2_pll_disable(aml_pll_dev_t* pll_dev);
193 
194 /*
195     Look for freq in pll rate table.  Returns ZX_ERR_NOT_SUPPORTED if the rate
196     can not be found.
197 */
198 zx_status_t s905d2_pll_fetch_rate(aml_pll_dev_t* pll_dev, uint64_t freq, const hhi_pll_rate_t** pll_rate);
199 
200 /*
201     Returns correct pll rate table for selected pll.
202 */
203 const hhi_pll_rate_t* s905d2_pll_get_rate_table(hhi_plls_t pll_num);
204 
205 /*
206     Returns the count of the rate table for the pll.
207 */
208 size_t s905d2_get_rate_table_count(hhi_plls_t pll_num);
209 
210 __END_CDECLS;
211