summaryrefslogtreecommitdiff
path: root/bsp/wch/risc-v/libraries/ch56x_drivers/ch56x_sys.h
blob: 1aa8bb2ac04c5556408aa6efaed44b745586d7ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
/*
 * Copyright (c) 2006-2023, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author            Notes
 * 2022-07-15     Emuzit            first version
 */
#ifndef __CH56X_SYS_H__
#define __CH56X_SYS_H__

#include "soc.h"

#ifdef __cplusplus
extern "C" {
#endif

#define sys_safe_access_enter(sys) \
        do { \
            sys->SAFE_ACCESS_SIG.reg = SAFE_ACCESS_SIG_1; \
            sys->SAFE_ACCESS_SIG.reg = SAFE_ACCESS_SIG_2; \
        } while(0)

#define sys_safe_access_leave(sys) \
        do sys->SAFE_ACCESS_SIG.reg = 0; while(0)

union _sys_safe_access_sig
{
    uint8_t reg;
    struct
    {
        uint8_t safe_acc_mode   : 2;  // RO, current safe access, 11b => RWA ok
        uint8_t resv_2          : 2;
        uint8_t safe_acc_timer  : 3;  // RO, current safe access time count
        uint8_t resv_7          : 1;
    };
};
#define RB_SAFE_ACC_MODE        0x03
#define RB_SAFE_ACC_TIMER       0x70

#define SAFE_ACCESS_SIG_1       0x57
#define SAFE_ACCESS_SIG_2       0xa8

union _sys_glob_rom_cfg
{
    uint8_t reg;
    struct
    {
        uint8_t rom_ext_re      : 1;  // RO, allow programmer to read FlashROM
        uint8_t code_ram_we     : 1;  // RWA, code SRAM writaboe
        uint8_t rom_data_we     : 1;  // RWA, FlashROM data erasable/writable
        uint8_t rom_code_we     : 1;  // RWA, FlashROM code erasable/writable
        uint8_t rom_code_ofs    : 1;  // RWA, FlashROM offset for user code
        uint8_t resv_5          : 3;
    };
};
#define RB_ROM_EXT_RE           0x01
#define RB_CODE_RAM_WE          0x02
#define RB_ROM_DATA_WE          0x04
#define RB_ROM_CODE_WE          0x08
#define RB_ROM_CODE_OFS         0x10

#define ROM_CODE_OFS_0x00000    0
#define ROM_CODE_OFS_0x04000    1

union _sys_rst_boot_stat
{
    uint8_t reg;
    struct
    {
        uint8_t reset_flag      : 2;  // RO, last reset cause
        uint8_t cfg_reset_en    : 1;  // RO, external reset pin (#RST) status
        uint8_t cfg_boot_en     : 1;  // RO, reset as 1
        uint8_t cfg_debug_en    : 1;  // RO
        uint8_t boot_loader     : 1;  // RO
        uint8_t resv_6          : 2;
    };
};
#define RB_RESET_FLAG           0x03
#define RB_CFG_RESET_EN         0x04
#define RB_CFG_BOOT_EN          0x08
#define RB_CFG_DEBUG_EN         0x10
#define RB_BOOT_LOADER          0x20

#define RESET_FLAG_IS_SOFT      0
#define RESET_FLAG_IS_POR       1
#define RESET_FLAG_IS_WDOG      2
#define RESET_FLAG_IS_RSTPIN    3

union _sys_rst_wdog_ctrl
{
    uint8_t reg;
    struct
    {
        uint8_t software_reset  : 1;  // WA/WZ, system software reset, auto clear
#if defined(SOC_SERIES_CH569)
        uint8_t wdog_rst_en     : 1;  // RWA, enable watchdog overflow to reset
        uint8_t wdog_int_en     : 1;  // RWA, enable watchdog overflow interrupt
        uint8_t wdog_int_flag   : 1;  // RW1, watchdog counter overflow
#else
        uint8_t resv_2          : 3;
#endif
        uint8_t resv_4          : 4;  // RO, B.7-6 must write 01b
    };
};
#define RB_SOFTWARE_RESET       0x01
#ifdef SOC_SERIES_CH569
#define RB_WDOG_RST_EN          0x02
#define RB_WDOG_INT_EN          0x04
#define RB_WDOG_INT_FLAG        0x08
#endif
#define wdog_ctrl_wdat(v)       (0x40 | (v))

union _sys_clk_pll_div
{
    uint8_t reg;
    struct
    {
        uint8_t pll_div         : 4;  // RWA, min 2
        uint8_t resv_4          : 4;  // RWA, B.7-6 must write 01b
    };
};
#define clk_pll_div_wdat(div)   (0x40 | (div))

union _sys_clk_cfg_ctrl
{
    uint8_t reg;
    struct
    {
        uint8_t pll_sleep       : 1;  // RWA, PLL sleep control
        uint8_t sel_pll         : 1;  // RWA, clock source select
        uint8_t resv_6          : 6;  // RWA, must write 10b
    };
};
#define RB_CLK_PLL_SLEEP        0x01
#define RB_CLK_SEL_PLL          0x02

#define CLK_PLL_SLEEP_DISABLE   0
#define CLK_PLL_SLEEP_ENABLE    1
#define CLK_SEL_PLL_HSE_30M     0
#define CLK_SEL_PLL_USB_480M    1
#define clk_cfg_ctrl_wdat(v)    (0x80 | (v))

union _sys_clk_mod_aux
{
    uint8_t reg;
    struct
    {
        uint8_t int_125m_en     : 1;  // RWA, USB PHY 125MHz to ETH
        uint8_t ext_125m_en     : 1;  // RWA, external 125MHz to ETH
        uint8_t mco_sel_msk     : 2;  // RWA, MCO output select
        uint8_t mco_en          : 1;  // RWA, MCO output enable
        uint8_t resv_5          : 3;
    };
};
#define RB_INT_125M_EN          0x01
#define RB_EXT_125M_EN          0x02
#define RB_MCO_SEL_MSK          0x0c
#define RB_MCO_EN               0x10

#define MCO_SEL_MSK_125M        0
#define MCO_SEL_MSK_25M         1
#define MCO_SEL_MSK_2_5M        2

/* All bits are RWA (need safe_access_sig), 0/1 : clock on/off
*/
union _sys_slp_clk_off0
{
    uint8_t reg;
    struct
    {
        uint8_t tmr0    : 1;
        uint8_t tmr1    : 1;
        uint8_t tmr2    : 1;
        uint8_t pwmx    : 1;
        uint8_t uart0   : 1;
        uint8_t uart1   : 1;
        uint8_t uart2   : 1;
        uint8_t uart3   : 1;
    };
};
#define RB_SLP_CLK_TMR0         0x01
#define RB_SLP_CLK_TMR1         0x02
#define RB_SLP_CLK_TMR2         0x04
#define RB_SLP_CLK_PWMX         0x08
#define RB_SLP_CLK_UART0        0x10
#define RB_SLP_CLK_UART1        0x20
#define RB_SLP_CLK_UART2        0x40
#define RB_SLP_CLK_UART3        0x80

#define SYS_SLP_CLK_ON          0
#define SYS_SLP_CLK_OFF         1

/* All writable bits are RWA (need safe_access_sig), 0/1 : clock on/off
*/
union _sys_slp_clk_off1
{
    uint8_t reg;
    struct
    {
        uint8_t spi0    : 1;
        uint8_t spi1    : 1;
#if defined(SOC_CH567)
        uint8_t sdc     : 1;
        uint8_t led     : 1;
        uint8_t usb0    : 1;
        uint8_t usb1    : 1;
        uint8_t resv_6  : 1;
#elif defined(SOC_CH568)
        uint8_t sdc     : 1;
        uint8_t led     : 1;
        uint8_t resv_4  : 1;
        uint8_t usb1    : 1;
        uint8_t sata    : 1;
        uint8_t ecdc    : 1;
#else
        uint8_t emmc    : 1;
        uint8_t hspi    : 1;
        uint8_t usbhs   : 1;
        uint8_t usbss   : 1;
        uint8_t serd    : 1;
        uint8_t dvp     : 1;
#endif
    };
};
#define RB_SLP_CLK_SPI0         0x01
#define RB_SLP_CLK_SPI1         0x02
#if defined(SOC_WCH_CH567)
#define RB_SLP_CLK_SDC          0x04
#define RB_SLP_CLK_LED          0x08
#define RB_SLP_CLK_USB0         0x10
#define RB_SLP_CLK_USB1         0x20
#define RB_SLP_CLK_ECDC         0x80
#elif defined(SOC_WCH_CH568)
#define RB_SLP_CLK_SDC          0x04
#define RB_SLP_CLK_LED          0x08
#define RB_SLP_CLK_USB1         0x20
#define RB_SLP_CLK_SATA         0x40
#define RB_SLP_CLK_ECDC         0x80
#else
#define RB_SLP_CLK_EMMC         0x04
#define RB_SLP_CLK_HSPI         0x08
#define RB_SLP_CLK_USBHS        0x10
#define RB_SLP_CLK_USBSS        0x20
#define RB_SLP_CLK_SERD         0x40
#define RB_SLP_CLK_DVP          0x80
#endif

/* All writable bits are RWA (need safe_access_sig)
*/
union _sys_slp_wake_ctrl
{
    uint8_t reg;
    struct
    {
#if defined(SOC_WCH_CH567)
        uint8_t usb0_wake       : 1;
        uint8_t usb1_wake       : 1;
        uint8_t resv_2          : 2;
        uint8_t gpio_wake       : 1;
        uint8_t resv_5          : 3;
#elif defined(SOC_WCH_CH568)
        uint8_t resv_0          : 1;
        uint8_t usb1_wake       : 1;
        uint8_t sata_wake       : 1;
        uint8_t resv_3          : 1;
        uint8_t gpio_wake       : 1;
        uint8_t resv_5          : 3;
#else
        uint8_t usbhs_wake      : 1;
        uint8_t usbss_wake      : 1;
        uint8_t clk_eth         : 1;
        uint8_t clk_ecdc        : 1;
        uint8_t gpio_wake       : 1;
        uint8_t eth_wake        : 1;
        uint8_t resv_6          : 2;
#endif
    };
};
#if defined(SOC_WCH_CH567)
#define RB_SLP_USB0_WAKE        0x01
#define RB_SLP_USB1_WAKE        0x02
#define RB_SLP_GPIO_WAKE        0x10
#elif defined(SOC_WCH_CH568)
#define RB_SLP_USB1_WAKE        0x02
#define RB_SLP_SATA_WAKE        0x04
#define RB_SLP_GPIO_WAKE        0x10
#else
#define RB_SLP_USBHS_WAKE       0x01
#define RB_SLP_USBSS_WAKE       0x02
#define RB_SLP_CLK_ETH          0x04
#define RB_SLP_CLK_ECDC         0x08
#define RB_SLP_GPIO_WAKE        0x10
#define RB_SLP_ETH_WAKE         0x20
#endif

union _sys_slp_power_ctrl
{
    uint8_t reg;
    struct
    {
        uint8_t usbhs_pwrdn     : 1;  // RWA, USBHS power down (0:PWRUP)
        uint8_t resv_2          : 7;
    };
};
#define RB_SLP_USBHS_PWRDN      0x01

union _sys_serd_ana_cfg1
{
    uint16_t reg;
    struct
    {
        uint8_t serd_pll_cfg;         // RWA, reset as 0x5a
        uint8_t serd_30m_sel    : 1;  // RWA
        uint8_t serd_dn_tst     : 1;  // RWA
        uint8_t resv_10         : 6;
    };
};
#define RB_SERD_PLL_CFG         0x0ff
#define RB_SERD_30M_SEL         0x100
#define RB_SERD_DN_TST          0x200

union _sys_serd_ana_cfg2
{
    uint32_t reg;
    struct
    {
        uint32_t serd_trx_cfg   : 25;  // RWA, reset as 423015h
        uint32_t resv_25        : 7;
    };
};
#define RB_SERD_TRX_CFG         0x1000000

/*
 * 0x00  R8_SAFE_ACCESS_SIG: safe access signature register
 * 0x01  R8_CHIP_ID:         RF, chip ID register
 * 0x02  R8_SAFE_ACCESS_ID:  RF, read as 02h
 * 0x03  R8_WDOG_COUNT       RW, watchdog counter
 * 0x04  R8_GLOB_ROM_CFG:    ROM config register
 * 0x05  R8_RST_BOOT_STAT:   RO, boot state register
 * 0x06  R8_RST_WDOG_CTRL:   software reset & watchdog control register
 * 0x07  R8_GLOB_RESET_KEEP: RW, only power-on-reset can clear this register
 * 0x08  R8_CLK_PLL_DIV:     RWA, PLL output divisor register
 * 0x0a  R8_CLK_CFG_CTRL:    RWA, clock config register
 * 0x0b  R8_CLK_MOD_AUX:     RWA, clock auxiliary register
 * 0x0c  R8_SLP_CLK_OFF0:    RWA, sleep control register 0
 * 0x0d  R8_SLP_CLK_OFF1:    RWA, sleep control register 1
 * 0x0e  R8_SLP_WAKE_CTRL:   RWA, wakeup control register
 * 0x0f  R8_SLP_POWER_CTRL:  RWA, low power management register
 * 0x20  R16_SERD_ANA_CFG1:  RWA, SerDes PHY analog param config register 1
 * 0x24  R32_SERD_ANA_CFG2:  RWA, SerDes PHY analog param config register 2
 *
 * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test.
 * Be careful for those with side effect for read.
 */
struct sys_registers
{
    union _sys_safe_access_sig  SAFE_ACCESS_SIG;
    uint8_t                     CHIP_ID;
    uint8_t                     SAFE_ACCESS_ID;
    uint8_t                     WDOG_COUNT;
    union _sys_glob_rom_cfg     GLOB_ROM_CFG;
    union _sys_rst_boot_stat    RST_BOOT_STAT;
    union _sys_rst_wdog_ctrl    RST_WDOG_CTRL;
    uint8_t                     GLOB_RESET_KEEP;
    union _sys_clk_pll_div      CLK_PLL_DIV;
    uint8_t                     resv_9;
    union _sys_clk_cfg_ctrl     CLK_CFG_CTRL;
    union _sys_clk_mod_aux      CLK_MOD_AUX;
    union _sys_slp_clk_off0     SLP_CLK_OFF0;
    union _sys_slp_clk_off1     SLP_CLK_OFF1;
    union _sys_slp_wake_ctrl    SLP_WAKE_CTRL;
    union _sys_slp_power_ctrl   SLP_POWER_CTRL;
#if defined(SOC_SERIES_CH569)
    uint32_t                    resv_10[4];
    union _sys_serd_ana_cfg1    SERD_ANA_CFG1;
    uint16_t                    resv_22;
    union _sys_serd_ana_cfg2    SERD_ANA_CFG2;
#endif
} __packed;

CHECK_STRUCT_SIZE(struct sys_registers, 0x28);

uint32_t sys_hclk_calc(void);
uint32_t sys_hclk_get(void);
int  sys_hclk_set(uint32_t freq);
int  sys_clk_off_by_irqn(uint8_t irqn, int off);
void sys_slp_clk_off0(uint8_t bits, int off);
void sys_slp_clk_off1(uint8_t bits, int off);

#ifdef __cplusplus
}
#endif

#endif