aboutsummaryrefslogtreecommitdiff
path: root/include/hw/misc/npcm7xx_clk.h
blob: d5c8d16ca42ef3f4f3b863aec64379bf5e01d9d9 (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
/*
 * Nuvoton NPCM7xx Clock Control Registers.
 *
 * Copyright 2020 Google LLC
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 * for more details.
 */
#ifndef NPCM7XX_CLK_H
#define NPCM7XX_CLK_H

#include "exec/memory.h"
#include "hw/clock.h"
#include "hw/sysbus.h"

/*
 * Number of registers in our device state structure. Don't change this without
 * incrementing the version_id in the vmstate.
 */
#define NPCM7XX_CLK_NR_REGS             (0x70 / sizeof(uint32_t))

#define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"

/* Maximum amount of clock inputs in a SEL module. */
#define NPCM7XX_CLK_SEL_MAX_INPUT 5

/* PLLs in CLK module. */
typedef enum NPCM7xxClockPLL {
    NPCM7XX_CLOCK_PLL0,
    NPCM7XX_CLOCK_PLL1,
    NPCM7XX_CLOCK_PLL2,
    NPCM7XX_CLOCK_PLLG,
    NPCM7XX_CLOCK_NR_PLLS,
} NPCM7xxClockPLL;

/* SEL/MUX in CLK module. */
typedef enum NPCM7xxClockSEL {
    NPCM7XX_CLOCK_PIXCKSEL,
    NPCM7XX_CLOCK_MCCKSEL,
    NPCM7XX_CLOCK_CPUCKSEL,
    NPCM7XX_CLOCK_CLKOUTSEL,
    NPCM7XX_CLOCK_UARTCKSEL,
    NPCM7XX_CLOCK_TIMCKSEL,
    NPCM7XX_CLOCK_SDCKSEL,
    NPCM7XX_CLOCK_GFXMSEL,
    NPCM7XX_CLOCK_SUCKSEL,
    NPCM7XX_CLOCK_NR_SELS,
} NPCM7xxClockSEL;

/* Dividers in CLK module. */
typedef enum NPCM7xxClockDivider {
    NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
    NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
    NPCM7XX_CLOCK_MC_DIVIDER,
    NPCM7XX_CLOCK_AXI_DIVIDER,
    NPCM7XX_CLOCK_AHB_DIVIDER,
    NPCM7XX_CLOCK_AHB3_DIVIDER,
    NPCM7XX_CLOCK_SPI0_DIVIDER,
    NPCM7XX_CLOCK_SPIX_DIVIDER,
    NPCM7XX_CLOCK_APB1_DIVIDER,
    NPCM7XX_CLOCK_APB2_DIVIDER,
    NPCM7XX_CLOCK_APB3_DIVIDER,
    NPCM7XX_CLOCK_APB4_DIVIDER,
    NPCM7XX_CLOCK_APB5_DIVIDER,
    NPCM7XX_CLOCK_CLKOUT_DIVIDER,
    NPCM7XX_CLOCK_UART_DIVIDER,
    NPCM7XX_CLOCK_TIMER_DIVIDER,
    NPCM7XX_CLOCK_ADC_DIVIDER,
    NPCM7XX_CLOCK_MMC_DIVIDER,
    NPCM7XX_CLOCK_SDHC_DIVIDER,
    NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
    NPCM7XX_CLOCK_UTMI_DIVIDER,
    NPCM7XX_CLOCK_NR_DIVIDERS,
} NPCM7xxClockConverter;

typedef struct NPCM7xxCLKState NPCM7xxCLKState;

/**
 * struct NPCM7xxClockPLLState - A PLL module in CLK module.
 * @name: The name of the module.
 * @clk: The CLK module that owns this module.
 * @clock_in: The input clock of this module.
 * @clock_out: The output clock of this module.
 * @reg: The control registers for this PLL module.
 */
typedef struct NPCM7xxClockPLLState {
    DeviceState parent;

    const char *name;
    NPCM7xxCLKState *clk;
    Clock *clock_in;
    Clock *clock_out;

    int reg;
} NPCM7xxClockPLLState;

/**
 * struct NPCM7xxClockSELState - A SEL module in CLK module.
 * @name: The name of the module.
 * @clk: The CLK module that owns this module.
 * @input_size: The size of inputs of this module.
 * @clock_in: The input clocks of this module.
 * @clock_out: The output clocks of this module.
 * @offset: The offset of this module in the control register.
 * @len: The length of this module in the control register.
 */
typedef struct NPCM7xxClockSELState {
    DeviceState parent;

    const char *name;
    NPCM7xxCLKState *clk;
    uint8_t input_size;
    Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
    Clock *clock_out;

    int offset;
    int len;
} NPCM7xxClockSELState;

/**
 * struct NPCM7xxClockDividerState - A Divider module in CLK module.
 * @name: The name of the module.
 * @clk: The CLK module that owns this module.
 * @clock_in: The input clock of this module.
 * @clock_out: The output clock of this module.
 * @divide: The function the divider uses to divide the input.
 * @reg: The index of the control register that contains the divisor.
 * @offset: The offset of the divisor in the control register.
 * @len: The length of the divisor in the control register.
 * @divisor: The divisor for a constant divisor
 */
typedef struct NPCM7xxClockDividerState {
    DeviceState parent;

    const char *name;
    NPCM7xxCLKState *clk;
    Clock *clock_in;
    Clock *clock_out;

    uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
    union {
        struct {
            int reg;
            int offset;
            int len;
        };
        int divisor;
    };
} NPCM7xxClockDividerState;

struct NPCM7xxCLKState {
    SysBusDevice parent;

    MemoryRegion iomem;

    /* Clock converters */
    NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
    NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
    NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];

    uint32_t regs[NPCM7XX_CLK_NR_REGS];

    /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
    int64_t ref_ns;

    /* The incoming reference clock. */
    Clock *clkref;
};

#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)

#endif /* NPCM7XX_CLK_H */