hw: misc: Implement Microchip mpfs ioscb PLLs and sysreg clock dividers
Minimal clock register configuration required to boot Linux without backtraces in the clock code. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260514-reference-overhand-749149e36a88@spud> [ Changes by AF: - Fixup checkpatch errors ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Guenter Roeck committed
May 14, 2026 at 16:23 UTC
7623bf5664ef433097f090aa5080ce2ddb838a05
3 files changed
+61
-1
hw/misc/mchp_pfsoc_ioscb.c
+46
-1
@@ -53,6 +53,8 @@
53
#define IOSCB_MAILBOX_BASE 0x07020800
54
#define IOSCB_CFG_BASE 0x07080000
55
#define IOSCB_CCC_BASE 0x08000000
56
+#define IOSCB_PLL_NW0_BASE 0x08100000
57
+#define IOSCB_PLL_NW1_BASE 0x08200000
58
#define IOSCB_PLL_MSS_BASE 0x0E001000
59
#define IOSCB_CFM_MSS_BASE 0x0E002000
60
#define IOSCB_PLL_DDR_BASE 0x0E010000
@@ -92,6 +94,16 @@ static const MemoryRegionOps mchp_pfsoc_dummy_ops = {
94
/* All PLL modules in IOSCB have the same register layout */
95
96
#define PLL_CTRL 0x04
97
+#define PLL_REF_FB 0x08
98
+#define PLL_DIV_0_1 0x10
99
+#define PLL_DIV_2_3 0x14
100
+#define PLL_CTRL2 0x18
101
+#define PLL_CAL 0x1c
102
+#define PLL_PHADJ 0x20
103
+#define SSCG_REG_0 0x24
104
+#define SSCG_REG_1 0x28
105
+#define SSCG_REG_2 0x2c
106
+#define SSCG_REG_3 0x30
107
108
static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset,
109
unsigned size)
@@ -103,6 +115,22 @@ static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset,
115
/* PLL is locked */
116
val = BIT(25);
117
break;
118
+ case PLL_DIV_0_1:
119
+ case PLL_DIV_2_3:
120
+ val = 0x01000100; /* return valid post divider values */
121
+ break;
122
+ case PLL_CTRL2:
123
+ val = 0x00001110;
124
+ break;
125
+ case PLL_REF_FB:
126
+ val = 0x00000100; /* RFDIV := 1 */
127
+ break;
128
+ case SSCG_REG_2:
129
+ val = 0x00000001; /* INTIN := 1 */
130
+ break;
131
+ case PLL_PHADJ:
132
+ val = 0x00000401;
133
+ break;
134
default:
135
qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read "
136
"(size %d, offset 0x%" HWADDR_PRIx ")\n",
@@ -113,9 +141,18 @@ static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset,
141
return val;
142
}
143
144
+static void mchp_pfsoc_pll_write(void *opaque, hwaddr offset,
145
+ uint64_t value, unsigned size)
146
+{
147
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write "
148
+ "(size %d, value 0x%" PRIx64
149
+ ", offset 0x%" HWADDR_PRIx ")\n",
150
+ __func__, size, value, offset);
151
+}
152
+
153
static const MemoryRegionOps mchp_pfsoc_pll_ops = {
154
.read = mchp_pfsoc_pll_read,
118
- .write = mchp_pfsoc_dummy_write,
155
+ .write = mchp_pfsoc_pll_write,
156
.endianness = DEVICE_LITTLE_ENDIAN,
157
};
158
@@ -240,6 +277,14 @@ static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp)
277
"mchp.pfsoc.ioscb.ccc", IOSCB_CCC_REG_SIZE);
278
memory_region_add_subregion(&s->container, IOSCB_CCC_BASE, &s->ccc);
279
280
+ memory_region_init_io(&s->pll_nw_0, OBJECT(s), &mchp_pfsoc_pll_ops, s,
281
+ "mchp.pfsoc.ioscb.pll_nw_0", IOSCB_SUBMOD_REG_SIZE);
282
+ memory_region_add_subregion(&s->container, IOSCB_PLL_NW0_BASE, &s->pll_nw_0);
283
+
284
+ memory_region_init_io(&s->pll_nw_1, OBJECT(s), &mchp_pfsoc_pll_ops, s,
285
+ "mchp.pfsoc.ioscb.pll_nw_1", IOSCB_SUBMOD_REG_SIZE);
286
+ memory_region_add_subregion(&s->container, IOSCB_PLL_NW1_BASE, &s->pll_nw_1);
287
+
288
memory_region_init_io(&s->pll_mss, OBJECT(s), &mchp_pfsoc_pll_ops, s,
289
"mchp.pfsoc.ioscb.pll_mss", IOSCB_SUBMOD_REG_SIZE);
290
memory_region_add_subregion(&s->container, IOSCB_PLL_MSS_BASE, &s->pll_mss);
hw/misc/mchp_pfsoc_sysreg.c
+13
@@ -29,6 +29,8 @@
29
#include "hw/misc/mchp_pfsoc_sysreg.h"
30
#include "system/runstate.h"
31
32
+#define CLOCK_CONFIG_CR 0x8
33
+#define RTC_CLOCK_CR 0xc
34
#define MSS_RESET_CR 0x18
35
#define ENVM_CR 0xb8
36
#define MESSAGE_INT 0x118c
@@ -39,6 +41,17 @@ static uint64_t mchp_pfsoc_sysreg_read(void *opaque, hwaddr offset,
41
uint32_t val = 0;
42
43
switch (offset) {
44
+ case CLOCK_CONFIG_CR:
45
+ /* Icicle kit reference design cpu/axi/ahb divider setting */
46
+ val = 0x24;
47
+ break;
48
+ case RTC_CLOCK_CR:
49
+ /*
50
+ * Bit 16 enables the RTC clock, 0x7d is the required divider
51
+ * setting for a 125 MHz reference.
52
+ */
53
+ val = BIT(16) | 0x7d;
54
+ break;
55
case ENVM_CR:
56
/* Indicate the eNVM is running at the configured divider rate */
57
val = BIT(6);
include/hw/misc/mchp_pfsoc_ioscb.h
+2
@@ -35,6 +35,8 @@ typedef struct MchpPfSoCIoscbState {
35
MemoryRegion mailbox;
36
MemoryRegion cfg;
37
MemoryRegion ccc;
38
+ MemoryRegion pll_nw_0;
39
+ MemoryRegion pll_nw_1;
40
MemoryRegion pll_mss;
41
MemoryRegion cfm_mss;
42
MemoryRegion pll_ddr;