qemu

Форк
0
/
sifive_u_prci.c 
169 строк · 5.4 Кб
1
/*
2
 * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt)
3
 *
4
 * Copyright (c) 2019 Bin Meng <bmeng.cn@gmail.com>
5
 *
6
 * Simple model of the PRCI to emulate register reads made by the SDK BSP
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms and conditions of the GNU General Public License,
10
 * version 2 or later, as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope it will be useful, but WITHOUT
13
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15
 * more details.
16
 *
17
 * You should have received a copy of the GNU General Public License along with
18
 * this program.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20

21
#include "qemu/osdep.h"
22
#include "hw/sysbus.h"
23
#include "qemu/log.h"
24
#include "qemu/module.h"
25
#include "hw/misc/sifive_u_prci.h"
26

27
static uint64_t sifive_u_prci_read(void *opaque, hwaddr addr, unsigned int size)
28
{
29
    SiFiveUPRCIState *s = opaque;
30

31
    switch (addr) {
32
    case SIFIVE_U_PRCI_HFXOSCCFG:
33
        return s->hfxosccfg;
34
    case SIFIVE_U_PRCI_COREPLLCFG0:
35
        return s->corepllcfg0;
36
    case SIFIVE_U_PRCI_DDRPLLCFG0:
37
        return s->ddrpllcfg0;
38
    case SIFIVE_U_PRCI_DDRPLLCFG1:
39
        return s->ddrpllcfg1;
40
    case SIFIVE_U_PRCI_GEMGXLPLLCFG0:
41
        return s->gemgxlpllcfg0;
42
    case SIFIVE_U_PRCI_GEMGXLPLLCFG1:
43
        return s->gemgxlpllcfg1;
44
    case SIFIVE_U_PRCI_CORECLKSEL:
45
        return s->coreclksel;
46
    case SIFIVE_U_PRCI_DEVICESRESET:
47
        return s->devicesreset;
48
    case SIFIVE_U_PRCI_CLKMUXSTATUS:
49
        return s->clkmuxstatus;
50
    }
51

52
    qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n",
53
                  __func__, addr);
54

55
    return 0;
56
}
57

58
static void sifive_u_prci_write(void *opaque, hwaddr addr,
59
                                uint64_t val64, unsigned int size)
60
{
61
    SiFiveUPRCIState *s = opaque;
62
    uint32_t val32 = (uint32_t)val64;
63

64
    switch (addr) {
65
    case SIFIVE_U_PRCI_HFXOSCCFG:
66
        s->hfxosccfg = val32;
67
        /* OSC stays ready */
68
        s->hfxosccfg |= SIFIVE_U_PRCI_HFXOSCCFG_RDY;
69
        break;
70
    case SIFIVE_U_PRCI_COREPLLCFG0:
71
        s->corepllcfg0 = val32;
72
        /* internal feedback */
73
        s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE;
74
        /* PLL stays locked */
75
        s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK;
76
        break;
77
    case SIFIVE_U_PRCI_DDRPLLCFG0:
78
        s->ddrpllcfg0 = val32;
79
        /* internal feedback */
80
        s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE;
81
        /* PLL stays locked */
82
        s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK;
83
        break;
84
    case SIFIVE_U_PRCI_DDRPLLCFG1:
85
        s->ddrpllcfg1 = val32;
86
        break;
87
    case SIFIVE_U_PRCI_GEMGXLPLLCFG0:
88
        s->gemgxlpllcfg0 = val32;
89
        /* internal feedback */
90
        s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE;
91
        /* PLL stays locked */
92
        s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK;
93
        break;
94
    case SIFIVE_U_PRCI_GEMGXLPLLCFG1:
95
        s->gemgxlpllcfg1 = val32;
96
        break;
97
    case SIFIVE_U_PRCI_CORECLKSEL:
98
        s->coreclksel = val32;
99
        break;
100
    case SIFIVE_U_PRCI_DEVICESRESET:
101
        s->devicesreset = val32;
102
        break;
103
    case SIFIVE_U_PRCI_CLKMUXSTATUS:
104
        s->clkmuxstatus = val32;
105
        break;
106
    default:
107
        qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
108
                      " v=0x%x\n", __func__, addr, val32);
109
    }
110
}
111

112
static const MemoryRegionOps sifive_u_prci_ops = {
113
    .read = sifive_u_prci_read,
114
    .write = sifive_u_prci_write,
115
    .endianness = DEVICE_NATIVE_ENDIAN,
116
    .valid = {
117
        .min_access_size = 4,
118
        .max_access_size = 4
119
    }
120
};
121

122
static void sifive_u_prci_realize(DeviceState *dev, Error **errp)
123
{
124
    SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev);
125

126
    memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_prci_ops, s,
127
                          TYPE_SIFIVE_U_PRCI, SIFIVE_U_PRCI_REG_SIZE);
128
    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
129
}
130

131
static void sifive_u_prci_reset(DeviceState *dev)
132
{
133
    SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev);
134

135
    /* Initialize register to power-on-reset values */
136
    s->hfxosccfg = SIFIVE_U_PRCI_HFXOSCCFG_RDY | SIFIVE_U_PRCI_HFXOSCCFG_EN;
137
    s->corepllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF |
138
                     SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE |
139
                     SIFIVE_U_PRCI_PLLCFG0_LOCK;
140
    s->ddrpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF |
141
                    SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE |
142
                    SIFIVE_U_PRCI_PLLCFG0_LOCK;
143
    s->gemgxlpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF |
144
                       SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE |
145
                       SIFIVE_U_PRCI_PLLCFG0_LOCK;
146
    s->coreclksel = SIFIVE_U_PRCI_CORECLKSEL_HFCLK;
147
}
148

149
static void sifive_u_prci_class_init(ObjectClass *klass, void *data)
150
{
151
    DeviceClass *dc = DEVICE_CLASS(klass);
152

153
    dc->realize = sifive_u_prci_realize;
154
    dc->reset = sifive_u_prci_reset;
155
}
156

157
static const TypeInfo sifive_u_prci_info = {
158
    .name          = TYPE_SIFIVE_U_PRCI,
159
    .parent        = TYPE_SYS_BUS_DEVICE,
160
    .instance_size = sizeof(SiFiveUPRCIState),
161
    .class_init    = sifive_u_prci_class_init,
162
};
163

164
static void sifive_u_prci_register_types(void)
165
{
166
    type_register_static(&sifive_u_prci_info);
167
}
168

169
type_init(sifive_u_prci_register_types)
170

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.