aboutsummaryrefslogtreecommitdiff
path: root/platform/ext/target/musca_s1/Native_Driver/musca_s1_scc_drv.c
blob: 5b8db4f768c9d9a3ee4669bec0827fa8274c291c (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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/*
 * Copyright (c) 2017-2020 Arm Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "musca_s1_scc_drv.h"
/* Use __ISB(), __DSB() */
#include "cmsis.h"

/** Setter bit manipulation macro */
#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1u << (BIT_INDEX)))
/** Clearing bit manipulation macro */
#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1u << (BIT_INDEX)))

struct musca_s1_scc_reg_map_t {
    /* 0x000-0x800 Reserved (offset) */
    const uint32_t reserved0[512];
    /* 0x800 RW Clock Control Selection Register */
    volatile uint32_t clk_ctrl_sel;
    /* 0x804 RW Clock PLL Prediv Control Register */
    volatile uint32_t clk_pll_prediv_ctrl;
    /* 0x808 RW Body Bias Generator CLK Div Register */
    volatile uint32_t clk_bbgen_div_clk;
    /* 0x80C Reserved */
    const uint32_t reserved1;
    /* 0x810 RW QSPI Post PLL CLK divider Register */
    volatile uint32_t clk_postdiv_qspi;
    /* 0x814 RW RTC Post PLL CLK div ctrl Register */
    volatile uint32_t clk_postdiv_ctrl_rtc;
    /* 0x818 Reserved */
    const uint32_t reserved2;
    /* 0x81C RW TEST CLK Post PLL CLK Div Register */
    volatile uint32_t clk_postdiv_ctrl_test;
    /* 0x820 RW Post PLL CLK divider bypass Register */
    volatile uint32_t ctrl_bypass_div;
    /* 0x824 RW PLL0 Control Register */
    volatile uint32_t pll_ctrl_pll0_clk;
    /* 0x828-0x82C Reserved */
    const uint32_t reserved3[2];
    /* 0x830 RW Clock gate enable control Register */
    volatile uint32_t clk_ctrl_enable;
    /* 0x834 RW PLL Status Register */
    volatile uint32_t clk_status;
    /* 0x838-0x83C Reserved */
    const uint32_t reserved4[2];
    /* 0x840 RW Reset Control Register */
    volatile uint32_t reset_ctrl;
    /* 0x844 Reserved */
    const uint32_t reserved5;
    /* 0x848 RW Debug Control Register */
    volatile uint32_t dbg_ctrl;
    /* 0x84C RW SRAM Control Register */
    volatile uint32_t sram_ctrl;
    /* 0x850 RW MPC Interupt Control Register */
    volatile uint32_t intr_ctrl;
    /* 0x854 Reserved */
    const uint32_t reserved6;
    /* 0x858 RW Reset vector for CPU0 SRAM */
    volatile uint32_t cpu0_vtor;
    /* 0x85C RW Reset vector for CPU0 MRAM */
    volatile uint32_t cpu0_vtor_1;
    /* 0x860 RW Reset vector for CPU1 SRAM */
    volatile uint32_t cpu1_vtor;
    /* 0x864 RW Reset vector for CPU1 MRAM */
    volatile uint32_t cpu1_vtor_1;
    /* 0x868 RW Main function in data select */
    volatile uint32_t iomux_main_insel;
    /* 0x874 Reserved */
    const uint32_t reserved7;
    /* 0x870 RW Main function out data select */
    volatile uint32_t iomux_main_outsel;
    /* 0x874 Reserved */
    const uint32_t reserved8;
    /* 0x878 RW Main function out enable select */
    volatile uint32_t iomux_main_oensel;
    /* 0x87C Reserved */
    const uint32_t reserved9;
    /* 0x880 RW Main function default in select */
    volatile uint32_t iomux_main_default_in;
    /* 0x884 Reserved */
    const uint32_t reserved10;
    /* 0x888 RW Alt function 1 in data select */
    volatile uint32_t iomux_altf1_insel;
    /* 0x88C Reserved */
    const uint32_t reserved11;
    /* 0x890 RW Alt function 1 out data select */
    volatile uint32_t iomux_altf1_outsel;
    /* 0x894 Reserved */
    const uint32_t reserved12;
    /* 0x898 RW Alt function 1 out enable select */
    volatile uint32_t iomux_altf1_oensel;
    /* 0x89C Reserved */
    const uint32_t reserved13;
    /* 0x8A0 RW Alt function 1 default in select */
    volatile uint32_t iomux_altf1_default_in;
    /* 0x8A4 Reserved */
    const uint32_t reserved14;
    /* 0x8A8 RW Alt function 2 in data select */
    volatile uint32_t iomux_altf2_insel;
    /* 0x8AC Reserved */
    const uint32_t reserved15;
    /* 0x8B0 RW Alt function 2 out data select */
    volatile uint32_t iomux_altf2_outsel;
    /* 0x8B4 Reserved */
    const uint32_t reserved16;
    /* 0x8B8 RW Alt function 2 out enable select */
    volatile uint32_t iomux_altf2_oensel;
    /* 0x8BC Reserved */
    const uint32_t reserved17;
    /* 0x8C0 RW Alt function 2 default in select */
    volatile uint32_t iomux_altf2_default_in;
    /* 0x8C4-0x8E4 Reserved */
    const uint32_t reserved18[9];
    /* 0x8E8 RW Drive Select 0 */
    volatile uint32_t iopad_ds0;
    /* 0x8EC Reserved */
    const uint32_t reserved19;
    /* 0x8F0 RW Drive Select 1 */
    volatile uint32_t iopad_ds1;
    /* 0x8F4 Reserved */
    const uint32_t reserved20;
    /* 0x8F8 RW Pull Enable */
    volatile uint32_t iopad_pe;
    /* 0x8FC Reserved */
    const uint32_t reserved21;
    /* 0x900 RW Pull Select */
    volatile uint32_t iopad_ps;
    /* 0x904 Reserved */
    const uint32_t reserved22;
    /* 0x908 RW Slew Select */
    volatile uint32_t iopad_sr;
    /* 0x90C Reserved */
    const uint32_t reserved23;
    /* 0x910 RW Input Select */
    volatile uint32_t iopad_is;
    /* 0x914 Reserved */
    const uint32_t reserved24;
    /* 0x918 RW PVT control register */
    volatile uint32_t pvt_ctrl;
    /* 0x91C-0x938 Reserved */
    const uint32_t reserved25[8];
    /* 0x93C RW Static configuration */
    volatile uint32_t static_conf_sig1;
    /* 0x940-0x994 Reserved */
    const uint32_t reserved26[22];
    /* 0x998 RW eMRAM control 0 register */
    volatile uint32_t scc_mram_ctrl0;
    /* 0x99C RW eMRAM control 1 register */
    volatile uint32_t scc_mram_ctrl1;
    /* 0x9A0 RW eMRAM control 2 register */
    volatile uint32_t scc_mram_ctrl2;
    /* 0x9A4-0x9AC Reserved */
    const uint32_t reserved27[3];
    /* 0x9B0 RW eMRAM data input 0 register */
    volatile uint32_t scc_mram_din0;
    /* 0x9B4 RW eMRAM data input 1 register */
    volatile uint32_t scc_mram_din1;
    /* 0x9B8 RW eMRAM data input 2 register */
    volatile uint32_t scc_mram_din2;
    /* 0x9BC Reserved */
    const uint32_t reserved28;
    /* 0x9C0 RW eMRAM data output 0 register */
    volatile uint32_t scc_mram_dout0;
    /* 0x9C4 RW eMRAM data output 1 register */
    volatile uint32_t scc_mram_dout1;
    /* 0x9C8 RW eMRAM data output 2 register */
    volatile uint32_t scc_mram_dout2;
    /* 0x9CC-0x9DC Reserved */
    const uint32_t reserved29[5];
    /* 0x9E0 RW CLK pahes shift control register */
    volatile uint32_t selection_control_reg;
    /* 0x9E4-0xA00 Reserved */
    const uint32_t reserved30[8];
    /* 0xA04 RW SSE-200 OTP control register */
    volatile uint32_t sse_otp_ctrl;
    /* 0xA08-0xA1C Reserved */
    const uint32_t reserved31[6];
    /* 0xA20 RW Body-Biasing control register */
    volatile uint32_t bbgen_ctrl;
    /* 0xA24 RW Spaer control register */
    volatile uint32_t spare_ctrl1;
    /* 0xA28-0xBFC Reserved */
    const uint32_t reserved32[118];
    /* 0xC00 RO Chip ID 0x0797_0477 */
    const uint32_t chip_id;
    /* 0xC04 RO I/O in status */
    const uint32_t io_in_status;
};

/**
 * \brief Musca-S1 SCC eMRAM control 0 register bit fields
 */
#define SCC_MRAM_CTRL0_MRAM_CLK_EN                   0u
    /*!< eMRAM control register 0 Enable eMRAM clock offset */
#define SCC_MRAM_CTRL0_PROC_SPEC_CLK_EN              1u
    /*!< eMRAM control register 0 Enable eMRAM controller clock offset */
#define SCC_MRAM_CTRL0_AUTOSTOP_EN                   2u
    /*!< eMRAM control register 0 Enable autostop offset */
#define SCC_MRAM_CTRL0_MRAM_INV_CLK_SEL              3u
    /*!< eMRAM control register 0 Select clock inversion offset */
#define SCC_MRAM_CTRL0_FAST_READ_EN                  4u
    /*!< eMRAM control register 0 Enable fast read offset */
#define SCC_MRAM_CTRL0_MRAM_DOUT_SEL                 5u
    /*!< eMRAM control register 0 Select eMRAM0 output data offset */
#define SCC_MRAM_CTRL0_PG_VDD_0                      8u
    /*!< eMRAM control register 0 eMRAM0 PG VDD offset */
#define SCC_MRAM_CTRL0_PG_VDD18_0                    9u
    /*!< eMRAM control register 0 eMRAM1 PG VDD18_0 offset */
#define SCC_MRAM_CTRL0_PG_VDD_1                      10u
    /*!< eMRAM control register 0 eMRAM1 PG VDD offset */
#define SCC_MRAM_CTRL0_PG_VDD18_1                    11u
    /*!< eMRAM control register 0 eMRAM1 PG VDD18 offset */
#define SCC_MRAM_CTRL0_WRITE_CSN_CLKS                12u
    /*!< eMRAM control register 0 WRITE_CSN_CLKS offset */
#define SCC_MRAM_CTRL0_CSN_HIGH_CLKS                 16u
    /*!< eMRAM control register 0 CSN_HIGH_CLKS offset */
#define SCC_MRAM_CTRL0_READ_CSN_CLKS                 20u
    /*!< eMRAM control register 0 Number of clocks for single read offset */
#define SCC_MRAM_CTRL0_MRAM_OTP_CLK_EN               29u
    /*!< eMRAM control register 0 Enable eMRAM OTP clock offset */
#define SCC_MRAM_CTRL0_MRAM_CLK_SYNC_BYPASS          30u
    /*!< eMRAM control register 0 Bypass eMRAM clock divider sync offset */
#define SCC_MRAM_CTRL0_MRAM_DA_EN                    31u
    /*!< eMRAM control register 0 Enable eMRAM direct access offset */

/**
 * \brief Clears selected alternate functions for selected pins
 *
 * \param[in] dev        SCC registers base address \ref musca_s1_scc_reg_map_t
 * \param[in] func_mask  Bitmask of alternate functions to clear
 *                       \ref gpio_altfunc_mask_t
 * \param[in] pin_mask   Pin mask for the alternate functions
 */
static void scc_clear_alt_func(struct musca_s1_scc_reg_map_t* scc_regs,
                               enum gpio_altfunc_mask_t func_mask,
                               uint32_t pin_mask)
{
    if (func_mask & GPIO_MAIN_FUNC_MASK) {
        scc_regs->iomux_main_insel &= ~pin_mask;
        scc_regs->iomux_main_outsel &= ~pin_mask;
        scc_regs->iomux_main_oensel &= ~pin_mask;
    }
    if (func_mask & GPIO_ALTFUNC_1_MASK) {
        scc_regs->iomux_altf1_insel &= ~pin_mask;
        scc_regs->iomux_altf1_outsel &= ~pin_mask;
        scc_regs->iomux_altf1_oensel &= ~pin_mask;
    }
    if (func_mask & GPIO_ALTFUNC_2_MASK) {
        scc_regs->iomux_altf2_insel &= ~pin_mask;
        scc_regs->iomux_altf2_outsel &= ~pin_mask;
        scc_regs->iomux_altf2_oensel &= ~pin_mask;
    }
}

void musca_s1_scc_set_alt_func(struct musca_s1_scc_dev_t* dev,
                               enum gpio_altfunc_t altfunc, uint32_t pin_mask)
{
    struct musca_s1_scc_reg_map_t* scc_regs =
                                (struct musca_s1_scc_reg_map_t*) dev->cfg->base;
    enum gpio_altfunc_mask_t altfunc_to_clear = GPIO_ALTFUNC_NONE;
    volatile uint32_t *insel = NULL;
    volatile uint32_t *outsel = NULL;
    volatile uint32_t *oensel = NULL;

    if (altfunc >= GPIO_ALTFUNC_MAX) {
        /* If no altfunction is selected, then nothing to do.
         * This is possible during init and we do not
         * want to change the reset values set by the HW
         */
        return;
    }

    switch (altfunc) {
        case GPIO_MAIN_FUNC:
            insel = &scc_regs->iomux_main_insel;
            outsel = &scc_regs->iomux_main_outsel;
            oensel = &scc_regs->iomux_main_oensel;
            altfunc_to_clear = GPIO_MAIN_FUNC_NEG_MASK;
            break;

        case GPIO_ALTFUNC_1:
            insel = &scc_regs->iomux_altf1_insel;
            outsel = &scc_regs->iomux_altf1_outsel;
            oensel = &scc_regs->iomux_altf1_oensel;
            altfunc_to_clear = GPIO_ALTFUNC_1_NEG_MASK;
            break;

        case GPIO_ALTFUNC_2:
            insel = &scc_regs->iomux_altf2_insel;
            outsel = &scc_regs->iomux_altf2_outsel;
            oensel = &scc_regs->iomux_altf2_oensel;
            altfunc_to_clear = GPIO_ALTFUNC_2_NEG_MASK;
            break;
        default:
        break;
    }

    /* Select the wanted function's output enable bit first.
     * This way the output won't be disabled which is desired
     * if we switch from output to output function
     */
    *oensel |= pin_mask;

    /* Clear all alternate function registers which are not selected */
    scc_clear_alt_func(scc_regs, altfunc_to_clear, pin_mask);

    /* Enable input and output data line */
    *insel |= pin_mask;
    *outsel |= pin_mask;
}

void musca_s1_scc_set_pinmode(struct musca_s1_scc_dev_t* dev, uint32_t pin_mask,
                              enum pinmode_select_t mode)
{
    struct musca_s1_scc_reg_map_t* scc_regs =
                                (struct musca_s1_scc_reg_map_t*) dev->cfg->base;

    switch (mode) {
        case PINMODE_NONE:
            scc_regs->iopad_pe &= ~pin_mask;
            break;
        case PINMODE_PULL_DOWN:
            /* If the pull select bit is set to 0 it means pull down */
            scc_regs->iopad_ps &= ~pin_mask;
            scc_regs->iopad_pe |= pin_mask;
            break;
        case PINMODE_PULL_UP:
            /* If the pull select bit is set to 1 it means pull up */
            scc_regs->iopad_ps |= pin_mask;
            scc_regs->iopad_pe |= pin_mask;
            break;
        default:
            break;
    }
}

void musca_s1_scc_set_default_in(struct musca_s1_scc_dev_t* dev,
                                 enum gpio_altfunc_t altfunc,
                                 uint32_t default_in_mask,
                                 uint32_t default_in_value)
{
    struct musca_s1_scc_reg_map_t* scc_regs =
                                (struct musca_s1_scc_reg_map_t*) dev->cfg->base;
    uint32_t iomux_value = 0;

    if (altfunc >= GPIO_ALTFUNC_MAX) {
        /* If no altfunction is selected, then nothing to do */
        return;
    }

    switch (altfunc) {
        case GPIO_MAIN_FUNC:
            iomux_value = scc_regs->iomux_main_default_in & ~default_in_mask;
            iomux_value |= (default_in_value & default_in_mask);
            scc_regs->iomux_main_default_in = iomux_value;
            scc_regs->iomux_main_insel =
                                (scc_regs->iomux_main_insel & ~default_in_mask);
            break;

        case GPIO_ALTFUNC_1:
            iomux_value = scc_regs->iomux_altf1_default_in & ~default_in_mask;
            iomux_value |= (default_in_value & default_in_mask);
            scc_regs->iomux_altf1_default_in = iomux_value;
            scc_regs->iomux_altf1_insel =
                               (scc_regs->iomux_altf1_insel & ~default_in_mask);
            break;

        case GPIO_ALTFUNC_2:
            iomux_value = scc_regs->iomux_altf2_default_in & ~default_in_mask;
            iomux_value |= (default_in_value & default_in_mask);
            scc_regs->iomux_altf2_default_in = iomux_value;
            scc_regs->iomux_altf2_insel =
                               (scc_regs->iomux_altf2_insel & ~default_in_mask);
            break;
        default:
        break;
    }
}

void musca_s1_scc_mram_fast_read_enable(struct musca_s1_scc_dev_t* dev)
{
    struct musca_s1_scc_reg_map_t* scc_regs =
                                (struct musca_s1_scc_reg_map_t*) dev->cfg->base;
    __DSB();
    SET_BIT(scc_regs->scc_mram_ctrl0, SCC_MRAM_CTRL0_FAST_READ_EN);
    __DSB();
    __ISB();
}

void musca_s1_scc_mram_fast_read_disable(struct musca_s1_scc_dev_t* dev)
{
    struct musca_s1_scc_reg_map_t* scc_regs =
                                (struct musca_s1_scc_reg_map_t*) dev->cfg->base;
    __DSB();
    CLR_BIT(scc_regs->scc_mram_ctrl0, SCC_MRAM_CTRL0_FAST_READ_EN);
    __DSB();
    __ISB();
}

bool musca_s1_scc_mram_is_fast_read_enabled(struct musca_s1_scc_dev_t* dev)
{
    struct musca_s1_scc_reg_map_t* scc_regs =
                                (struct musca_s1_scc_reg_map_t*) dev->cfg->base;
    return (bool)(scc_regs->scc_mram_ctrl0 &
                  (1u << SCC_MRAM_CTRL0_FAST_READ_EN));
}