Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144460242
D43034.id131454.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
87 KB
Referenced Files
None
Subscribers
None
D43034.id131454.diff
View Options
diff --git a/sys/contrib/device-tree/include/dt-bindings/clock/starfive-jh7110-clkgen.h b/sys/contrib/device-tree/include/dt-bindings/clock/starfive-jh7110-clkgen.h
new file mode 100644
--- /dev/null
+++ b/sys/contrib/device-tree/include/dt-bindings/clock/starfive-jh7110-clkgen.h
@@ -0,0 +1,374 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright 2022 StarFive, Inc <xingyu.wu@starfivetech.com>
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CLKGEN_H__
+#define __DT_BINDINGS_CLOCK_STARFIVE_JH7110_CLKGEN_H__
+
+/* sys register */
+#define JH7110_CPU_ROOT 0
+#define JH7110_CPU_CORE 1
+#define JH7110_CPU_BUS 2
+#define JH7110_GPU_ROOT 3
+#define JH7110_PERH_ROOT 4
+#define JH7110_BUS_ROOT 5
+#define JH7110_NOCSTG_BUS 6
+#define JH7110_AXI_CFG0 7
+#define JH7110_STG_AXIAHB 8
+#define JH7110_AHB0 9
+#define JH7110_AHB1 10
+#define JH7110_APB_BUS_FUNC 11
+#define JH7110_APB0 12
+#define JH7110_PLL0_DIV2 13
+#define JH7110_PLL1_DIV2 14
+#define JH7110_PLL2_DIV2 15
+#define JH7110_AUDIO_ROOT 16
+#define JH7110_MCLK_INNER 17
+#define JH7110_MCLK 18
+#define JH7110_MCLK_OUT 19
+#define JH7110_ISP_2X 20
+#define JH7110_ISP_AXI 21
+#define JH7110_GCLK0 22
+#define JH7110_GCLK1 23
+#define JH7110_GCLK2 24
+#define JH7110_U7_CORE_CLK 25
+#define JH7110_U7_CORE_CLK1 26
+#define JH7110_U7_CORE_CLK2 27
+#define JH7110_U7_CORE_CLK3 28
+#define JH7110_U7_CORE_CLK4 29
+#define JH7110_U7_DEBUG_CLK 30
+#define JH7110_U7_RTC_TOGGLE 31
+#define JH7110_U7_TRACE_CLK0 32
+#define JH7110_U7_TRACE_CLK1 33
+#define JH7110_U7_TRACE_CLK2 34
+#define JH7110_U7_TRACE_CLK3 35
+#define JH7110_U7_TRACE_CLK4 36
+#define JH7110_U7_TRACE_COM_CLK 37
+#define JH7110_NOC_BUS_CLK_CPU_AXI 38
+#define JH7110_NOC_BUS_CLK_AXICFG0_AXI 39
+#define JH7110_OSC_DIV2 40
+#define JH7110_PLL1_DIV4 41
+#define JH7110_PLL1_DIV8 42
+#define JH7110_DDR_BUS 43
+#define JH7110_DDR_CLK_AXI 44
+#define JH7110_GPU_CORE 45
+#define JH7110_GPU_CORE_CLK 46
+#define JH7110_GPU_SYS_CLK 47
+#define JH7110_GPU_CLK_APB 48
+#define JH7110_GPU_RTC_TOGGLE 49
+#define JH7110_NOC_BUS_CLK_GPU_AXI 50
+#define JH7110_ISP_TOP_CLK_ISPCORE_2X 51
+#define JH7110_ISP_TOP_CLK_ISP_AXI 52
+#define JH7110_NOC_BUS_CLK_ISP_AXI 53
+#define JH7110_HIFI4_CORE 54
+#define JH7110_HIFI4_AXI 55
+#define JH7110_AXI_CFG1_DEC_CLK_MAIN 56
+#define JH7110_AXI_CFG1_DEC_CLK_AHB 57
+#define JH7110_VOUT_SRC 58
+#define JH7110_VOUT_AXI 59
+#define JH7110_NOC_BUS_CLK_DISP_AXI 60
+#define JH7110_VOUT_TOP_CLK_VOUT_AHB 61
+#define JH7110_VOUT_TOP_CLK_VOUT_AXI 62
+#define JH7110_VOUT_TOP_CLK_HDMITX0_MCLK 63
+#define JH7110_VOUT_TOP_CLK_MIPIPHY_REF 64
+#define JH7110_JPEGC_AXI 65
+#define JH7110_CODAJ12_CLK_AXI 66
+#define JH7110_CODAJ12_CLK_CORE 67
+#define JH7110_CODAJ12_CLK_APB 68
+#define JH7110_VDEC_AXI 69
+#define JH7110_WAVE511_CLK_AXI 70
+#define JH7110_WAVE511_CLK_BPU 71
+#define JH7110_WAVE511_CLK_VCE 72
+#define JH7110_WAVE511_CLK_APB 73
+#define JH7110_VDEC_JPG_ARB_JPGCLK 74
+#define JH7110_VDEC_JPG_ARB_MAINCLK 75
+#define JH7110_NOC_BUS_CLK_VDEC_AXI 76
+#define JH7110_VENC_AXI 77
+#define JH7110_WAVE420L_CLK_AXI 78
+#define JH7110_WAVE420L_CLK_BPU 79
+#define JH7110_WAVE420L_CLK_VCE 80
+#define JH7110_WAVE420L_CLK_APB 81
+#define JH7110_NOC_BUS_CLK_VENC_AXI 82
+#define JH7110_AXI_CFG0_DEC_CLK_MAIN_DIV 83
+#define JH7110_AXI_CFG0_DEC_CLK_MAIN 84
+#define JH7110_AXI_CFG0_DEC_CLK_HIFI4 85
+#define JH7110_AXIMEM2_128B_CLK_AXI 86
+#define JH7110_QSPI_CLK_AHB 87
+#define JH7110_QSPI_CLK_APB 88
+#define JH7110_QSPI_REF_SRC 89
+#define JH7110_QSPI_CLK_REF 90
+#define JH7110_SDIO0_CLK_AHB 91
+#define JH7110_SDIO1_CLK_AHB 92
+#define JH7110_SDIO0_CLK_SDCARD 93
+#define JH7110_SDIO1_CLK_SDCARD 94
+#define JH7110_USB_125M 95
+#define JH7110_NOC_BUS_CLK_STG_AXI 96
+#define JH7110_GMAC5_CLK_AHB 97
+#define JH7110_GMAC5_CLK_AXI 98
+#define JH7110_GMAC_SRC 99
+#define JH7110_GMAC1_GTXCLK 100
+#define JH7110_GMAC1_RMII_RTX 101
+#define JH7110_GMAC5_CLK_PTP 102
+#define JH7110_GMAC5_CLK_RX 103
+#define JH7110_GMAC5_CLK_RX_INV 104
+#define JH7110_GMAC5_CLK_TX 105
+#define JH7110_GMAC5_CLK_TX_INV 106
+#define JH7110_GMAC1_GTXC 107
+#define JH7110_GMAC0_GTXCLK 108
+#define JH7110_GMAC0_PTP 109
+#define JH7110_GMAC_PHY 110
+#define JH7110_GMAC0_GTXC 111
+#define JH7110_SYS_IOMUX_PCLK 112
+#define JH7110_MAILBOX_CLK_APB 113
+#define JH7110_INT_CTRL_CLK_APB 114
+#define JH7110_CAN0_CTRL_CLK_APB 115
+#define JH7110_CAN0_CTRL_CLK_TIMER 116
+#define JH7110_CAN0_CTRL_CLK_CAN 117
+#define JH7110_CAN1_CTRL_CLK_APB 118
+#define JH7110_CAN1_CTRL_CLK_TIMER 119
+#define JH7110_CAN1_CTRL_CLK_CAN 120
+#define JH7110_PWM_CLK_APB 121
+#define JH7110_DSKIT_WDT_CLK_APB 122
+#define JH7110_DSKIT_WDT_CLK_WDT 123
+#define JH7110_TIMER_CLK_APB 124
+#define JH7110_TIMER_CLK_TIMER0 125
+#define JH7110_TIMER_CLK_TIMER1 126
+#define JH7110_TIMER_CLK_TIMER2 127
+#define JH7110_TIMER_CLK_TIMER3 128
+#define JH7110_TEMP_SENSOR_CLK_APB 129
+#define JH7110_TEMP_SENSOR_CLK_TEMP 130
+#define JH7110_SPI0_CLK_APB 131
+#define JH7110_SPI1_CLK_APB 132
+#define JH7110_SPI2_CLK_APB 133
+#define JH7110_SPI3_CLK_APB 134
+#define JH7110_SPI4_CLK_APB 135
+#define JH7110_SPI5_CLK_APB 136
+#define JH7110_SPI6_CLK_APB 137
+#define JH7110_I2C0_CLK_APB 138
+#define JH7110_I2C1_CLK_APB 139
+#define JH7110_I2C2_CLK_APB 140
+#define JH7110_I2C3_CLK_APB 141
+#define JH7110_I2C4_CLK_APB 142
+#define JH7110_I2C5_CLK_APB 143
+#define JH7110_I2C6_CLK_APB 144
+#define JH7110_UART0_CLK_APB 145
+#define JH7110_UART0_CLK_CORE 146
+#define JH7110_UART1_CLK_APB 147
+#define JH7110_UART1_CLK_CORE 148
+#define JH7110_UART2_CLK_APB 149
+#define JH7110_UART2_CLK_CORE 150
+#define JH7110_UART3_CLK_APB 151
+#define JH7110_UART3_CLK_CORE 152
+#define JH7110_UART4_CLK_APB 153
+#define JH7110_UART4_CLK_CORE 154
+#define JH7110_UART5_CLK_APB 155
+#define JH7110_UART5_CLK_CORE 156
+#define JH7110_PWMDAC_CLK_APB 157
+#define JH7110_PWMDAC_CLK_CORE 158
+#define JH7110_SPDIF_CLK_APB 159
+#define JH7110_SPDIF_CLK_CORE 160
+#define JH7110_I2STX0_4CHCLK_APB 161
+#define JH7110_I2STX_4CH0_BCLK_MST 162
+#define JH7110_I2STX_4CH0_BCLK_MST_INV 163
+#define JH7110_I2STX_4CH0_LRCK_MST 164
+#define JH7110_I2STX0_4CHBCLK 165
+#define JH7110_I2STX0_4CHBCLK_N 166
+#define JH7110_I2STX0_4CHLRCK 167
+#define JH7110_I2STX1_4CHCLK_APB 168
+#define JH7110_I2STX_4CH1_BCLK_MST 169
+#define JH7110_I2STX_4CH1_BCLK_MST_INV 170
+#define JH7110_I2STX_4CH1_LRCK_MST 171
+#define JH7110_I2STX1_4CHBCLK 172
+#define JH7110_I2STX1_4CHBCLK_N 173
+#define JH7110_I2STX1_4CHLRCK 174
+#define JH7110_I2SRX0_3CH_CLK_APB 175
+#define JH7110_I2SRX_3CH_BCLK_MST 176
+#define JH7110_I2SRX_3CH_BCLK_MST_INV 177
+#define JH7110_I2SRX_3CH_LRCK_MST 178
+#define JH7110_I2SRX0_3CH_BCLK 179
+#define JH7110_I2SRX0_3CH_BCLK_N 180
+#define JH7110_I2SRX0_3CH_LRCK 181
+#define JH7110_PDM_CLK_DMIC 182
+#define JH7110_PDM_CLK_APB 183
+#define JH7110_TDM_CLK_AHB 184
+#define JH7110_TDM_CLK_APB 185
+#define JH7110_TDM_INTERNAL 186
+#define JH7110_TDM_CLK_TDM 187
+#define JH7110_TDM_CLK_TDM_N 188
+#define JH7110_JTAG_CERTIFICATION_TRNG_CLK 189
+
+#define JH7110_CLK_SYS_REG_END 190
+
+/* stg register */
+#define JH7110_HIFI4_CLK_CORE 190
+#define JH7110_USB0_CLK_USB_APB 191
+#define JH7110_USB0_CLK_UTMI_APB 192
+#define JH7110_USB0_CLK_AXI 193
+#define JH7110_USB0_CLK_LPM 194
+#define JH7110_USB0_CLK_STB 195
+#define JH7110_USB0_CLK_APP_125 196
+#define JH7110_USB0_REFCLK 197
+#define JH7110_PCIE0_CLK_AXI_MST0 198
+#define JH7110_PCIE0_CLK_APB 199
+#define JH7110_PCIE0_CLK_TL 200
+#define JH7110_PCIE1_CLK_AXI_MST0 201
+#define JH7110_PCIE1_CLK_APB 202
+#define JH7110_PCIE1_CLK_TL 203
+#define JH7110_PCIE01_SLV_DEC_MAINCLK 204
+#define JH7110_SEC_HCLK 205
+#define JH7110_SEC_MISCAHB_CLK 206
+#define JH7110_STG_MTRX_GRP0_CLK_MAIN 207
+#define JH7110_STG_MTRX_GRP0_CLK_BUS 208
+#define JH7110_STG_MTRX_GRP0_CLK_STG 209
+#define JH7110_STG_MTRX_GRP1_CLK_MAIN 210
+#define JH7110_STG_MTRX_GRP1_CLK_BUS 211
+#define JH7110_STG_MTRX_GRP1_CLK_STG 212
+#define JH7110_STG_MTRX_GRP1_CLK_HIFI 213
+#define JH7110_E2_RTC_CLK 214
+#define JH7110_E2_CLK_CORE 215
+#define JH7110_E2_CLK_DBG 216
+#define JH7110_DMA1P_CLK_AXI 217
+#define JH7110_DMA1P_CLK_AHB 218
+
+#define JH7110_CLK_STG_REG_END 219
+
+/* aon register */
+#define JH7110_OSC_DIV4 219
+#define JH7110_AON_APB_FUNC 220
+#define JH7110_U0_GMAC5_CLK_AHB 221
+#define JH7110_U0_GMAC5_CLK_AXI 222
+#define JH7110_GMAC0_RMII_RTX 223
+#define JH7110_U0_GMAC5_CLK_TX 224
+#define JH7110_U0_GMAC5_CLK_TX_INV 225
+#define JH7110_U0_GMAC5_CLK_RX 226
+#define JH7110_U0_GMAC5_CLK_RX_INV 227
+#define JH7110_OTPC_CLK_APB 228
+#define JH7110_RTC_HMS_CLK_APB 229
+#define JH7110_RTC_INTERNAL 230
+#define JH7110_RTC_HMS_CLK_OSC32K 231
+#define JH7110_RTC_HMS_CLK_CAL 232
+
+#define JH7110_CLK_REG_END 233
+
+/* sys other */
+#define JH7110_PLL0_OUT 233
+#define JH7110_PLL1_OUT 234
+#define JH7110_PLL2_OUT 235
+#define JH7110_AON_APB 236
+#define JH7110_RESET1_CTRL_CLK_SRC 237
+#define JH7110_DDR_ROOT 238
+#define JH7110_VDEC_ROOT 239
+#define JH7110_VENC_ROOT 240
+#define JH7110_VOUT_ROOT 241
+#define JH7110_GMACUSB_ROOT 242
+#define JH7110_PCLK2_MUX_FUNC_PCLK 243
+#define JH7110_PCLK2_MUX_BIST_PCLK 244
+#define JH7110_APB_BUS 245
+#define JH7110_APB12 246
+#define JH7110_AXI_CFG1 247
+#define JH7110_PLL_WRAP_CRG_GCLK0 248
+#define JH7110_PLL_WRAP_CRG_GCLK1 249
+#define JH7110_PLL_WRAP_CRG_GCLK2 250
+#define JH7110_JTAG2APB_PCLK 251
+#define JH7110_U7_BUS_CLK 252
+#define JH7110_U7_IRQ_SYNC_BUS_CLK 253
+#define JH7110_NOC_BUS_CLK2_CPU_AXI 254
+#define JH7110_NOC_BUS_CLK_APB_BUS 255
+#define JH7110_NOC_BUS_CLK2_APB_BUS 256
+#define JH7110_NOC_BUS_CLK2_AXICFG0_AXI 257
+#define JH7110_DDR_CLK_DDRPHY_PLL_BYPASS 258
+#define JH7110_DDR_CLK_OSC 259
+#define JH7110_DDR_CLK_APB 260
+#define JH7110_NOC_BUS_CLK_DDRC 261
+#define JH7110_NOC_BUS_CLK2_DDRC 262
+#define JH7110_SYS_AHB_DEC_CLK_AHB 263
+#define JH7110_STG_AHB_DEC_CLK_AHB 264
+#define JH7110_NOC_BUS_CLK2_GPU_AXI 265
+#define JH7110_ISP_TOP_CLK_DVP 266
+#define JH7110_NOC_BUS_CLK2_ISP_AXI 267
+#define JH7110_ISP_TOP_CLK_BIST_APB 268
+#define JH7110_NOC_BUS_CLK2_DISP_AXI 269
+#define JH7110_VOUT_TOP_CLK_HDMITX0_BCLK 270
+#define JH7110_VOUT_TOP_U0_HDMI_TX_PIN_WS 271
+#define JH7110_VOUT_TOP_CLK_HDMIPHY_REF 272
+#define JH7110_VOUT_TOP_BIST_PCLK 273
+#define JH7110_AXIMEM0_128B_CLK_AXI 274
+#define JH7110_VDEC_INTSRAM_CLK_VDEC_AXI 275
+#define JH7110_NOC_BUS_CLK2_VDEC_AXI 276
+#define JH7110_AXIMEM1_128B_CLK_AXI 277
+#define JH7110_VENC_INTSRAM_CLK_VENC_AXI 278
+#define JH7110_NOC_BUS_CLK2_VENC_AXI 279
+#define JH7110_SRAM_CLK_ROM 280
+#define JH7110_NOC_BUS_CLK2_STG_AXI 281
+#define JH7110_GMAC5_CLK_RMII 282
+#define JH7110_AON_AHB 283
+#define JH7110_SYS_CRG_PCLK 284
+#define JH7110_SYS_SYSCON_PCLK 285
+#define JH7110_SPI0_CLK_CORE 286
+#define JH7110_SPI1_CLK_CORE 287
+#define JH7110_SPI2_CLK_CORE 288
+#define JH7110_SPI3_CLK_CORE 289
+#define JH7110_SPI4_CLK_CORE 290
+#define JH7110_SPI5_CLK_CORE 291
+#define JH7110_SPI6_CLK_CORE 292
+#define JH7110_I2C0_CLK_CORE 293
+#define JH7110_I2C1_CLK_CORE 294
+#define JH7110_I2C2_CLK_CORE 295
+#define JH7110_I2C3_CLK_CORE 296
+#define JH7110_I2C4_CLK_CORE 297
+#define JH7110_I2C5_CLK_CORE 298
+#define JH7110_I2C6_CLK_CORE 299
+#define JH7110_I2STX_BCLK_MST 300
+#define JH7110_I2STX_LRCK_MST 301
+#define JH7110_I2SRX_BCLK_MST 302
+#define JH7110_I2SRX_LRCK_MST 303
+#define JH7110_PDM_CLK_DMIC0_BCLK_SLV 304
+#define JH7110_PDM_CLK_DMIC0_LRCK_SLV 305
+#define JH7110_PDM_CLK_DMIC1_BCLK_SLV 306
+#define JH7110_PDM_CLK_DMIC1_LRCK_SLV 307
+#define JH7110_TDM_CLK_MST 308
+#define JH7110_AHB2APB_CLK_AHB 309
+#define JH7110_P2P_ASYNC_CLK_APBS 310
+#define JH7110_P2P_ASYNC_CLK_APBM 311
+#define JH7110_JTAG_DAISY_CHAIN_JTAG_TCK 312
+#define JH7110_U7_DEBUG_SYSTEMJTAG_JTAG_TCK 313
+#define JH7110_E2_DEBUG_SYSTEMJTAG_TCK 314
+#define JH7110_JTAG_CERTIFICATION_TCK 315
+#define JH7110_SEC_SKP_CLK 316
+#define JH7110_U2_PCLK_MUX_PCLK 317
+
+#define JH7110_CLK_SYS_END 318
+
+/* stg other */
+#define JH7110_PCIE0_CLK_AXI_SLV0 318
+#define JH7110_PCIE0_CLK_AXI_SLV 319
+#define JH7110_PCIE0_CLK_OSC 320
+#define JH7110_PCIE1_CLK_AXI_SLV0 321
+#define JH7110_PCIE1_CLK_AXI_SLV 322
+#define JH7110_PCIE1_CLK_OSC 323
+#define JH7110_E2_IRQ_SYNC_CLK_CORE 324
+#define JH7110_STG_CRG_PCLK 325
+#define JH7110_STG_SYSCON_PCLK 326
+#define JH7110_STG_APB 327
+
+#define JH7110_CLK_STG_END 328
+
+/* aon other */
+#define JH7110_U0_GMAC5_CLK_PTP 328
+#define JH7110_U0_GMAC5_CLK_RMII 329
+#define JH7110_AON_SYSCON_PCLK 330
+#define JH7110_AON_IOMUX_PCLK 331
+#define JH7110_AON_CRG_PCLK 332
+#define JH7110_PMU_CLK_APB 333
+#define JH7110_PMU_CLK_WKUP 334
+#define JH7110_RTC_HMS_CLK_OSC32K_G 335
+#define JH7110_32K_OUT 336
+#define JH7110_RESET0_CTRL_CLK_SRC 337
+/* aon other and source */
+#define JH7110_PCLK_MUX_FUNC_PCLK 338
+#define JH7110_PCLK_MUX_BIST_PCLK 339
+
+#define JH7110_CLK_END 340
+
+#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7110_H__ */
diff --git a/sys/contrib/device-tree/include/dt-bindings/reset/starfive-jh7110.h b/sys/contrib/device-tree/include/dt-bindings/reset/starfive-jh7110.h
new file mode 100644
--- /dev/null
+++ b/sys/contrib/device-tree/include/dt-bindings/reset/starfive-jh7110.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2021 samin <samin.guo@starfivetech.com>
+ */
+
+#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7110_H__
+#define __DT_BINDINGS_RESET_STARFIVE_JH7110_H__
+
+/*
+ * group[0]: syscrg: assert0
+ */
+#define RSTN_U0_JTAG2APB_PRESETN 0
+#define RSTN_U0_SYS_SYSCON_PRESETN 1
+#define RSTN_U0_SYS_IOMUX_PRESETN 2
+#define RSTN_U0_U7MC_RST_BUS 3
+#define RSTN_U0_U7MC_DEBUG 4
+#define RSTN_U0_U7MC_CORE0 5
+#define RSTN_U0_U7MC_CORE1 6
+#define RSTN_U0_U7MC_CORE2 7
+#define RSTN_U0_U7MC_CORE3 8
+#define RSTN_U0_U7MC_CORE4 9
+#define RSTN_U0_U7MC_CORE0_ST 10
+#define RSTN_U0_U7MC_CORE1_ST 11
+#define RSTN_U0_U7MC_CORE2_ST 12
+#define RSTN_U0_U7MC_CORE3_ST 13
+#define RSTN_U0_U7MC_CORE4_ST 14
+#define RSTN_U0_U7MC_TRACE_RST0 15
+#define RSTN_U0_U7MC_TRACE_RST1 16
+#define RSTN_U0_U7MC_TRACE_RST2 17
+#define RSTN_U0_U7MC_TRACE_RST3 18
+#define RSTN_U0_U7MC_TRACE_RST4 19
+#define RSTN_U0_U7MC_TRACE_COM 20
+#define RSTN_U0_IMG_GPU_APB 21
+#define RSTN_U0_IMG_GPU_DOMA 22
+#define RSTN_U0_NOC_BUS_APB_BUS_N 23
+#define RSTN_U0_NOC_BUS_AXICFG0_AXI_N 24
+#define RSTN_U0_NOC_BUS_CPU_AXI_N 25
+#define RSTN_U0_NOC_BUS_DISP_AXI_N 26
+#define RSTN_U0_NOC_BUS_GPU_AXI_N 27
+#define RSTN_U0_NOC_BUS_ISP_AXI_N 28
+#define RSTN_U0_NOC_BUS_DDRC_N 29
+#define RSTN_U0_NOC_BUS_STG_AXI_N 30
+#define RSTN_U0_NOC_BUS_VDEC_AXI_N 31
+/*
+ * group[1]: syscrg: assert1
+ */
+#define RSTN_U0_NOC_BUS_VENC_AXI_N 32
+#define RSTN_U0_AXI_CFG1_DEC_AHB 33
+#define RSTN_U0_AXI_CFG1_DEC_MAIN 34
+#define RSTN_U0_AXI_CFG0_DEC_MAIN 35
+#define RSTN_U0_AXI_CFG0_DEC_MAIN_DIV 36
+#define RSTN_U0_AXI_CFG0_DEC_HIFI4 37
+#define RSTN_U0_DDR_AXI 38
+#define RSTN_U0_DDR_OSC 39
+#define RSTN_U0_DDR_APB 40
+#define RSTN_U0_DOM_ISP_TOP_N 41
+#define RSTN_U0_DOM_ISP_TOP_AXI 42
+#define RSTN_U0_DOM_VOUT_TOP_SRC 43
+#define RSTN_U0_CODAJ12_AXI 44
+#define RSTN_U0_CODAJ12_CORE 45
+#define RSTN_U0_CODAJ12_APB 46
+#define RSTN_U0_WAVE511_AXI 47
+#define RSTN_U0_WAVE511_BPU 48
+#define RSTN_U0_WAVE511_VCE 49
+#define RSTN_U0_WAVE511_APB 50
+#define RSTN_U0_VDEC_JPG_ARB_JPG 51
+#define RSTN_U0_VDEC_JPG_ARB_MAIN 52
+#define RSTN_U0_AXIMEM_128B_AXI 53
+#define RSTN_U0_WAVE420L_AXI 54
+#define RSTN_U0_WAVE420L_BPU 55
+#define RSTN_U0_WAVE420L_VCE 56
+#define RSTN_U0_WAVE420L_APB 57
+#define RSTN_U1_AXIMEM_128B_AXI 58
+#define RSTN_U2_AXIMEM_128B_AXI 59
+#define RSTN_U0_INTMEM_ROM_SRAM_ROM 60
+#define RSTN_U0_CDNS_QSPI_AHB 61
+#define RSTN_U0_CDNS_QSPI_APB 62
+#define RSTN_U0_CDNS_QSPI_REF 63
+/*
+ * group[2]: syscrg: assert2
+ */
+#define RSTN_U0_DW_SDIO_AHB 64
+#define RSTN_U1_DW_SDIO_AHB 65
+#define RSTN_U1_DW_GMAC5_AXI64_A_I 66
+#define RSTN_U1_DW_GMAC5_AXI64_H_N 67
+#define RSTN_U0_MAILBOX_RRESETN 68
+#define RSTN_U0_SSP_SPI_APB 69
+#define RSTN_U1_SSP_SPI_APB 70
+#define RSTN_U2_SSP_SPI_APB 71
+#define RSTN_U3_SSP_SPI_APB 72
+#define RSTN_U4_SSP_SPI_APB 73
+#define RSTN_U5_SSP_SPI_APB 74
+#define RSTN_U6_SSP_SPI_APB 75
+#define RSTN_U0_DW_I2C_APB 76
+#define RSTN_U1_DW_I2C_APB 77
+#define RSTN_U2_DW_I2C_APB 78
+#define RSTN_U3_DW_I2C_APB 79
+#define RSTN_U4_DW_I2C_APB 80
+#define RSTN_U5_DW_I2C_APB 81
+#define RSTN_U6_DW_I2C_APB 82
+#define RSTN_U0_DW_UART_APB 83
+#define RSTN_U0_DW_UART_CORE 84
+#define RSTN_U1_DW_UART_APB 85
+#define RSTN_U1_DW_UART_CORE 86
+#define RSTN_U2_DW_UART_APB 87
+#define RSTN_U2_DW_UART_CORE 88
+#define RSTN_U3_DW_UART_APB 89
+#define RSTN_U3_DW_UART_CORE 90
+#define RSTN_U4_DW_UART_APB 91
+#define RSTN_U4_DW_UART_CORE 92
+#define RSTN_U5_DW_UART_APB 93
+#define RSTN_U5_DW_UART_CORE 94
+#define RSTN_U0_CDNS_SPDIF_APB 95
+/*
+ * group[3]: syscrg: assert3
+ */
+#define RSTN_U0_PWMDAC_APB 96
+#define RSTN_U0_PDM_4MIC_DMIC 97
+#define RSTN_U0_PDM_4MIC_APB 98
+#define RSTN_U0_I2SRX_3CH_APB 99
+#define RSTN_U0_I2SRX_3CH_BCLK 100
+#define RSTN_U0_I2STX_4CH_APB 101
+#define RSTN_U0_I2STX_4CH_BCLK 102
+#define RSTN_U1_I2STX_4CH_APB 103
+#define RSTN_U1_I2STX_4CH_BCLK 104
+#define RSTN_U0_TDM16SLOT_AHB 105
+#define RSTN_U0_TDM16SLOT_TDM 106
+#define RSTN_U0_TDM16SLOT_APB 107
+#define RSTN_U0_PWM_8CH_APB 108
+#define RSTN_U0_DSKIT_WDT_APB 109
+#define RSTN_U0_DSKIT_WDT_CORE 110
+#define RSTN_U0_CAN_CTRL_APB 111
+#define RSTN_U0_CAN_CTRL_CORE 112
+#define RSTN_U0_CAN_CTRL_TIMER 113
+#define RSTN_U1_CAN_CTRL_APB 114
+#define RSTN_U1_CAN_CTRL_CORE 115
+#define RSTN_U1_CAN_CTRL_TIMER 116
+#define RSTN_U0_TIMER_APB 117
+#define RSTN_U0_TIMER_TIMER0 118
+#define RSTN_U0_TIMER_TIMER1 119
+#define RSTN_U0_TIMER_TIMER2 120
+#define RSTN_U0_TIMER_TIMER3 121
+#define RSTN_U0_INT_CTRL_APB 122
+#define RSTN_U0_TEMP_SENSOR_APB 123
+#define RSTN_U0_TEMP_SENSOR_TEMP 124
+#define RSTN_U0_JTAG_CERTIFICATION_N 125
+/*
+ * group[4]: stgcrg
+ */
+#define RSTN_U0_STG_SYSCON_PRESETN 128
+#define RSTN_U0_HIFI4_CORE 129
+#define RSTN_U0_HIFI4_AXI 130
+#define RSTN_U0_SEC_TOP_HRESETN 131
+#define RSTN_U0_E24_CORE 132
+#define RSTN_U0_DW_DMA1P_AXI 133
+#define RSTN_U0_DW_DMA1P_AHB 134
+#define RSTN_U0_CDN_USB_AXI 135
+#define RSTN_U0_CDN_USB_APB 136
+#define RSTN_U0_CDN_USB_UTMI_APB 137
+#define RSTN_U0_CDN_USB_PWRUP 138
+#define RSTN_U0_PLDA_PCIE_AXI_MST0 139
+#define RSTN_U0_PLDA_PCIE_AXI_SLV0 140
+#define RSTN_U0_PLDA_PCIE_AXI_SLV 141
+#define RSTN_U0_PLDA_PCIE_BRG 142
+#define RSTN_U0_PLDA_PCIE_CORE 143
+#define RSTN_U0_PLDA_PCIE_APB 144
+#define RSTN_U1_PLDA_PCIE_AXI_MST0 145
+#define RSTN_U1_PLDA_PCIE_AXI_SLV0 146
+#define RSTN_U1_PLDA_PCIE_AXI_SLV 147
+#define RSTN_U1_PLDA_PCIE_BRG 148
+#define RSTN_U1_PLDA_PCIE_CORE 149
+#define RSTN_U1_PLDA_PCIE_APB 150
+/*
+ * group[5]: aoncrg
+ */
+#define RSTN_U0_DW_GMAC5_AXI64_AXI 160
+#define RSTN_U0_DW_GMAC5_AXI64_AHB 161
+#define RSTN_U0_AON_IOMUX_PRESETN 162
+#define RSTN_U0_PMU_APB 163
+#define RSTN_U0_PMU_WKUP 164
+#define RSTN_U0_RTC_HMS_APB 165
+#define RSTN_U0_RTC_HMS_CAL 166
+#define RSTN_U0_RTC_HMS_OSC32K 167
+/*
+ * group[6]: ispcrg
+ */
+#define RSTN_U0_ISPV2_TOP_WRAPPER_P 192
+#define RSTN_U0_ISPV2_TOP_WRAPPER_C 193
+#define RSTN_U0_M31DPHY_HW 194
+#define RSTN_U0_M31DPHY_B09_ALWAYS_ON 195
+#define RSTN_U0_VIN_N_PCLK 196
+#define RSTN_U0_VIN_N_PIXEL_CLK_IF0 197
+#define RSTN_U0_VIN_N_PIXEL_CLK_IF1 198
+#define RSTN_U0_VIN_N_PIXEL_CLK_IF2 199
+#define RSTN_U0_VIN_N_PIXEL_CLK_IF3 200
+#define RSTN_U0_VIN_N_SYS_CLK 201
+#define RSTN_U0_VIN_P_AXIRD 202
+#define RSTN_U0_VIN_P_AXIWR 203
+/*
+ * group[7]: voutcrg
+ */
+#define RSTN_U0_DC8200_AXI 224
+#define RSTN_U0_DC8200_AHB 225
+#define RSTN_U0_DC8200_CORE 226
+#define RSTN_U0_CDNS_DSITX_DPI 227
+#define RSTN_U0_CDNS_DSITX_APB 228
+#define RSTN_U0_CDNS_DSITX_RXESC 229
+#define RSTN_U0_CDNS_DSITX_SYS 230
+#define RSTN_U0_CDNS_DSITX_TXBYTEHS 231
+#define RSTN_U0_CDNS_DSITX_TXESC 232
+#define RSTN_U0_HDMI_TX_HDMI 233
+#define RSTN_U0_MIPITX_DPHY_SYS 234
+#define RSTN_U0_MIPITX_DPHY_TXBYTEHS 235
+
+#define RSTN_JH7110_RESET_END 236
+
+#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7110_H__ */
diff --git a/sys/riscv/starfive/clk/jh7110_clk.h b/sys/riscv/starfive/clk/jh7110_clk.h
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/clk/jh7110_clk.h
@@ -0,0 +1,108 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright 2023 Jari Sihvola <jsihv@gmx.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <dev/extres/clk/clk.h>
+
+#ifndef _CLK_JH7110_CLK_H_
+#define _CLK_JH7110_CLK_H_
+
+#define JH7110_CLK_HAS_GATE 0x01
+#define JH7110_CLK_HAS_MUX 0x02
+#define JH7110_CLK_HAS_DIV 0x04
+#define JH7110_CLK_HAS_INV 0x08
+
+#define JH7110_CLK_AON 0x10
+#define JH7110_CLK_ISP 0x20
+#define JH7110_CLK_STG 0x40
+#define JH7110_CLK_SYS 0x80
+#define JH7110_CLK_VOUT 0x100
+
+#define PLL0_DEFAULT_FREQ 1500000000
+
+
+struct jh7110_clk_def {
+ struct clknode_init_def clkdef;
+ uint32_t offset;
+ uint32_t flags;
+ uint64_t d_max;
+};
+
+struct jh7110_pll_def {
+ struct clknode_init_def clkdef;
+ struct mtx *mtx;
+ struct syscon *sysregs;
+ struct resource *syscon_mem_res;
+ uint32_t *pll_offsets;
+
+};
+
+#define JH7110_PLL(_idx, _name, _pn) \
+{ \
+ .clkdef.id = _idx, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = _pn, \
+ .clkdef.parent_cnt = nitems(_pn), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .fixed_flags = 0, \
+ .mult = 1, \
+ .div = 1, \
+}
+
+#define JH7110_CLK(_idx, _name, _pn, _d_max, _flags) \
+{ \
+ .clkdef.id = _idx, \
+ .clkdef.name = _name, \
+ .clkdef.parent_names = _pn, \
+ .clkdef.parent_cnt = nitems(_pn), \
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS, \
+ .flags = _flags, \
+ .d_max = _d_max, \
+}
+
+#define JH7110_GATE(_idx, _name, _pn) \
+ JH7110_CLK(_idx, _name, _pn, 0, JH7110_CLK_HAS_GATE)
+#define JH7110_MUX(_idx, _name, _pn) \
+ JH7110_CLK(_idx, _name, _pn, 0, JH7110_CLK_HAS_MUX)
+#define JH7110_DIV(_idx, _name, _pn, _d_max) \
+ JH7110_CLK(_idx, _name, _pn, _d_max, JH7110_CLK_HAS_DIV)
+#define JH7110_GATEMUX(_idx, _name, _pn) \
+ JH7110_CLK(_idx, _name, _pn, 0, JH7110_CLK_HAS_GATE | JH7110_CLK_HAS_MUX)
+#define JH7110_GATEDIV(_idx, _name, _pn, _d_max) \
+ JH7110_CLK(_idx, _name, _pn, _d_max, JH7110_CLK_HAS_GATE \
+ | JH7110_CLK_HAS_DIV)
+#define JH7110_INV(_idx, _name, _pn) \
+ JH7110_CLK(_idx, _name, _pn, 0, JH7110_CLK_HAS_INV)
+
+struct resource *jh7110_clk_get_memres(struct clknode *clk, uint32_t flags);
+
+int jh7110_clk_register(struct clkdom *clkdom,
+ const struct jh7110_clk_def *clkdef, int mem_group);
+
+int jh7110_clk_pll_register(struct clkdom *clkdom,
+ struct jh7110_pll_def *clkdef);
+
+#endif /* _CLK_JH7110_CLK_H_ */
diff --git a/sys/riscv/starfive/clk/jh7110_clk.c b/sys/riscv/starfive/clk/jh7110_clk.c
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/clk/jh7110_clk.c
@@ -0,0 +1,251 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 Emmanuel Vadot <manu@freebsd.org>
+ * Copyright (c) 2022 Mitchell Horne <mhorne@FreeBSD.org>
+ * Copyright (c) 2023 Jari Sihvola <jsihv@gmx.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <riscv/starfive/clk/jh7110_clk.h>
+
+#include <dt-bindings/clock/starfive-jh7110-clkgen.h>
+
+#include "clkdev_if.h"
+
+#define JH7110_DIV_MASK 0xffffff
+#define JH7110_MUX_SHIFT 24
+#define JH7110_MUX_MASK 0x3f000000
+#define JH7110_ENABLE_SHIFT 31
+#define REG_SIZE 4
+
+struct jh7110_clk_sc {
+ uint32_t offset;
+ uint32_t flags;
+ uint64_t d_max;
+ int id;
+};
+
+#define DIV_ROUND_CLOSEST(n, d) (((n) + (d) / 2) / (d))
+
+#define READ4_MEMRES(_clk, off) \
+ bus_read_4(jh7110_clk_get_memres(_clk, sc->flags), off)
+#define WRITE4_MEMRES(_clk, off, _val) \
+ bus_write_4(jh7110_clk_get_memres(_clk, sc->flags), off, _val)
+#define DEVICE_LOCK(_clk) \
+ CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
+#define DEVICE_UNLOCK(_clk) \
+ CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
+
+static int
+jh7110_clk_init(struct clknode *clk, device_t dev)
+{
+ struct jh7110_clk_sc *sc;
+ uint32_t reg;
+ int idx = 0;
+
+ sc = clknode_get_softc(clk);
+
+ if (sc->flags & JH7110_CLK_HAS_MUX) {
+ DEVICE_LOCK(clk);
+ reg = READ4_MEMRES(clk, sc->offset);
+ DEVICE_UNLOCK(clk);
+ idx = (reg & JH7110_MUX_MASK) >> JH7110_MUX_SHIFT;
+ }
+
+ clknode_init_parent_idx(clk, idx);
+
+ return (0);
+}
+
+static int
+jh7110_clk_set_gate(struct clknode *clk, bool enable)
+{
+ struct jh7110_clk_sc *sc;
+ uint32_t reg;
+
+ sc = clknode_get_softc(clk);
+
+ if ((sc->flags & JH7110_CLK_HAS_GATE) == 0)
+ return (0);
+
+ DEVICE_LOCK(clk);
+ reg = READ4_MEMRES(clk, sc->offset);
+ if (enable)
+ reg |= (1 << JH7110_ENABLE_SHIFT);
+ else
+ reg &= ~(1 << JH7110_ENABLE_SHIFT);
+ WRITE4_MEMRES(clk, sc->offset, reg);
+ DEVICE_UNLOCK(clk);
+
+ return (0);
+}
+
+static int
+jh7110_clk_set_mux(struct clknode *clk, int idx)
+{
+ struct jh7110_clk_sc *sc;
+ uint32_t reg;
+
+ sc = clknode_get_softc(clk);
+
+ if ((sc->flags & JH7110_CLK_HAS_MUX) == 0)
+ return (ENXIO);
+
+ /* Checking index size */
+ if ((idx & (JH7110_MUX_MASK >> JH7110_MUX_SHIFT)) != idx)
+ return (EINVAL);
+
+ DEVICE_LOCK(clk);
+
+ reg = READ4_MEMRES(clk, sc->offset) & ~JH7110_MUX_MASK;
+ reg |= idx << JH7110_MUX_SHIFT;
+ WRITE4_MEMRES(clk, sc->offset, reg);
+
+ DEVICE_UNLOCK(clk);
+
+ return (0);
+}
+
+static int
+jh7110_clk_recalc_freq(struct clknode *clk, uint64_t *freq)
+{
+ struct jh7110_clk_sc *sc;
+ uint32_t divisor;
+
+ sc = clknode_get_softc(clk);
+
+ /* Returning error here causes panic */
+ if ((sc->flags & JH7110_CLK_HAS_DIV) == 0)
+ return (0);
+
+ DEVICE_LOCK(clk);
+ divisor = READ4_MEMRES(clk, sc->offset) & JH7110_DIV_MASK;
+ DEVICE_UNLOCK(clk);
+
+ if (sc->id >= JH7110_UART3_CLK_CORE &&
+ sc->id <= JH7110_UART5_CLK_CORE &&
+ sc->id % 2 == 0)
+ divisor >>= 8;
+
+ if (divisor)
+ *freq = *freq / divisor;
+ else
+ *freq = 0;
+
+ return (0);
+}
+
+static int
+jh7110_clk_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
+ int flags, int *done)
+{
+
+ struct jh7110_clk_sc *sc;
+ uint32_t divisor;
+
+ sc = clknode_get_softc(clk);
+
+ if ((sc->flags & JH7110_CLK_HAS_DIV) == 0)
+ return (0);
+
+ divisor = MIN(MAX(DIV_ROUND_CLOSEST(fin, *fout), 1UL), sc->d_max);
+
+ if (sc->id >= JH7110_UART3_CLK_CORE &&
+ sc->id <= JH7110_UART5_CLK_CORE &&
+ sc->id % 2 == 0)
+ divisor <<= 8;
+
+ if (flags & CLK_SET_DRYRUN) {
+ *done = 1;
+ *fout = divisor;
+ return (0);
+ }
+
+ DEVICE_LOCK(clk);
+ divisor |= READ4_MEMRES(clk, sc->offset) & ~JH7110_DIV_MASK;
+ WRITE4_MEMRES(clk, sc->offset, divisor);
+ DEVICE_UNLOCK(clk);
+
+ *fout = divisor;
+ *done = 1;
+
+ return (0);
+}
+
+static clknode_method_t jh7110_clknode_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, jh7110_clk_init),
+ CLKNODEMETHOD(clknode_set_gate, jh7110_clk_set_gate),
+ CLKNODEMETHOD(clknode_set_mux, jh7110_clk_set_mux),
+ CLKNODEMETHOD(clknode_recalc_freq, jh7110_clk_recalc_freq),
+ CLKNODEMETHOD(clknode_set_freq, jh7110_clk_set_freq),
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(jh7110_clknode, jh7110_clknode_class, jh7110_clknode_methods,
+ sizeof(struct jh7110_clk_sc), clknode_class);
+
+int
+jh7110_clk_register(struct clkdom *clkdom,
+ const struct jh7110_clk_def *clkdef, int mem_group)
+{
+ struct clknode *clk;
+ struct jh7110_clk_sc *sc;
+
+ clk = clknode_create(clkdom, &jh7110_clknode_class, &clkdef->clkdef);
+ if (clk == NULL) {
+ return (-1);
+ }
+
+ sc = clknode_get_softc(clk);
+
+ if (mem_group == JH7110_CLK_AON) {
+ sc->offset = (clkdef->clkdef.id - JH7110_CLK_STG_REG_END)
+ * REG_SIZE;
+ } else if (mem_group == JH7110_CLK_STG) {
+ sc->offset = (clkdef->clkdef.id - JH7110_CLK_SYS_REG_END)
+ * REG_SIZE;
+ } else {
+ sc->offset = clkdef->clkdef.id * REG_SIZE;
+ }
+
+ sc->flags = clkdef->flags | mem_group;
+ sc->id = clkdef->clkdef.id;
+ sc->d_max = clkdef->d_max;
+
+ clknode_register(clkdom, clk);
+
+ return (0);
+}
diff --git a/sys/riscv/starfive/clk/jh7110_clk_pll.h b/sys/riscv/starfive/clk/jh7110_clk_pll.h
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/clk/jh7110_clk_pll.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * StarFive JH7110 PLL Clock Generator Driver
+ *
+ * Copyright (C) 2022 Xingyu Wu <xingyu.wu@starfivetech.com>
+ */
+
+#define PLL0_DACPD_SHIFT 24
+#define PLL0_DACPD_MASK 0x1000000
+#define PLL0_DSMPD_SHIFT 25
+#define PLL0_DSMPD_MASK 0x2000000
+#define PLL0_FBDIV_SHIFT 0
+#define PLL0_FBDIV_MASK 0xFFF
+#define PLL0_FRAC_SHIFT 0
+#define PLL0_FRAC_MASK 0xFFFFFF
+#define PLL0_POSTDIV1_SHIFT 28
+#define PLL0_POSTDIV1_MASK 0x30000000
+#define PLL0_PREDIV_SHIFT 0
+#define PLL0_PREDIV_MASK 0x3F
+
+#define PLL1_DACPD_SHIFT 15
+#define PLL1_DACPD_MASK 0x8000
+#define PLL1_DSMPD_SHIFT 16
+#define PLL1_DSMPD_MASK 0x10000
+#define PLL1_FBDIV_SHIFT 17
+#define PLL1_FBDIV_MASK 0x1FFE0000
+#define PLL1_FRAC_SHIFT 0
+#define PLL1_FRAC_MASK 0xFFFFFF
+#define PLL1_POSTDIV1_SHIFT 28
+#define PLL1_POSTDIV1_MASK 0x30000000
+#define PLL1_PREDIV_SHIFT 0
+#define PLL1_PREDIV_MASK 0x3F
+
+#define PLL2_DACPD_SHIFT 15
+#define PLL2_DACPD_MASK 0x8000
+#define PLL2_DSMPD_SHIFT 16
+#define PLL2_DSMPD_MASK 0x10000
+#define PLL2_FBDIV_SHIFT 17
+#define PLL2_FBDIV_MASK 0x1FFE0000
+#define PLL2_FRAC_SHIFT 0
+#define PLL2_FRAC_MASK 0xFFFFFF
+#define PLL2_POSTDIV1_SHIFT 28
+#define PLL2_POSTDIV1_MASK 0x30000000
+#define PLL2_PREDIV_SHIFT 0
+#define PLL2_PREDIV_MASK 0x3F
+
+#define FRAC_PATR_SIZE 1000
+
+struct starfive_pll_syscon_value {
+ uint64_t freq;
+ uint32_t prediv;
+ uint32_t fbdiv;
+ uint32_t postdiv1;
+ uint32_t dacpd;
+ uint32_t dsmpd;
+ uint32_t frac;
+};
+
+enum starfive_pll0_freq_value {
+ PLL0_FREQ_375_VALUE = 375000000,
+ PLL0_FREQ_500_VALUE = 500000000,
+ PLL0_FREQ_625_VALUE = 625000000,
+ PLL0_FREQ_750_VALUE = 750000000,
+ PLL0_FREQ_875_VALUE = 875000000,
+ PLL0_FREQ_1000_VALUE = 1000000000,
+ PLL0_FREQ_1250_VALUE = 1250000000,
+ PLL0_FREQ_1375_VALUE = 1375000000,
+ PLL0_FREQ_1500_VALUE = 1500000000
+};
+
+enum starfive_pll0_freq {
+ PLL0_FREQ_375 = 0,
+ PLL0_FREQ_500,
+ PLL0_FREQ_625,
+ PLL0_FREQ_750,
+ PLL0_FREQ_875,
+ PLL0_FREQ_1000,
+ PLL0_FREQ_1250,
+ PLL0_FREQ_1375,
+ PLL0_FREQ_1500,
+ PLL0_FREQ_MAX = PLL0_FREQ_1500
+};
+
+enum starfive_pll1_freq_value {
+ PLL1_FREQ_1066_VALUE = 1066000000,
+};
+
+enum starfive_pll1_freq {
+ PLL1_FREQ_1066 = 0,
+};
+
+enum starfive_pll2_freq_value {
+ PLL2_FREQ_1188_VALUE = 1188000000,
+ PLL2_FREQ_12288_VALUE = 1228800000,
+};
+
+enum starfive_pll2_freq {
+ PLL2_FREQ_1188 = 0,
+ PLL2_FREQ_12288,
+};
+
+static const struct starfive_pll_syscon_value
+ jh7110_pll0_syscon_freq[] = {
+ [PLL0_FREQ_375] = {
+ .freq = PLL0_FREQ_375_VALUE,
+ .prediv = 8,
+ .fbdiv = 125,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_500] = {
+ .freq = PLL0_FREQ_500_VALUE,
+ .prediv = 6,
+ .fbdiv = 125,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_625] = {
+ .freq = PLL0_FREQ_625_VALUE,
+ .prediv = 24,
+ .fbdiv = 625,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_750] = {
+ .freq = PLL0_FREQ_750_VALUE,
+ .prediv = 4,
+ .fbdiv = 125,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_875] = {
+ .freq = PLL0_FREQ_875_VALUE,
+ .prediv = 24,
+ .fbdiv = 875,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_1000] = {
+ .freq = PLL0_FREQ_1000_VALUE,
+ .prediv = 3,
+ .fbdiv = 125,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_1250] = {
+ .freq = PLL0_FREQ_1250_VALUE,
+ .prediv = 12,
+ .fbdiv = 625,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_1375] = {
+ .freq = PLL0_FREQ_1375_VALUE,
+ .prediv = 24,
+ .fbdiv = 1375,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL0_FREQ_1500] = {
+ .freq = PLL0_FREQ_1500_VALUE,
+ .prediv = 2,
+ .fbdiv = 125,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+};
+
+static const struct starfive_pll_syscon_value
+ jh7110_pll1_syscon_freq[] = {
+ [PLL1_FREQ_1066] = {
+ .freq = PLL1_FREQ_1066_VALUE,
+ .prediv = 12,
+ .fbdiv = 533,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+};
+
+static const struct starfive_pll_syscon_value
+ jh7110_pll2_syscon_freq[] = {
+ [PLL2_FREQ_1188] = {
+ .freq = PLL2_FREQ_1188_VALUE,
+ .prediv = 2,
+ .fbdiv = 99,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+ [PLL2_FREQ_12288] = {
+ .freq = PLL2_FREQ_12288_VALUE,
+ .prediv = 5,
+ .fbdiv = 256,
+ .postdiv1 = 1,
+ .dacpd = 1,
+ .dsmpd = 1,
+ },
+};
diff --git a/sys/riscv/starfive/clk/jh7110_clk_pll.c b/sys/riscv/starfive/clk/jh7110_clk_pll.c
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/clk/jh7110_clk_pll.c
@@ -0,0 +1,313 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2023 Jari Sihvola <jsihv@gmx.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/fbio.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/fpe.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include <riscv/starfive/clk/jh7110_clk.h>
+#include <riscv/starfive/clk/jh7110_clk_pll.h>
+
+#include "clkdev_if.h"
+
+#define SYSCON_READ_4(reg) bus_read_4(sc->syscon_mem_res, (reg))
+#define SYSCON_MODIFY_4(reg, cbits, sbits) \
+ jh7110_syscon_modify_4(sc->syscon_mem_res, (reg), (cbits), (sbits))
+
+struct jh7110_clk_pll_sc {
+ struct mtx *mtx;
+ struct syscon *sysregs;
+ struct resource *syscon_mem_res;
+ const struct
+ starfive_pll_syscon_value * syscon_arr;
+ int syscon_arr_nitems;
+
+ uint32_t flags;
+
+ uint32_t dacpd_offset;
+ uint32_t dsmpd_offset;
+ uint32_t fbdiv_offset;
+ uint32_t frac_offset;
+ uint32_t prediv_offset;
+ uint32_t postdiv1_offset;
+
+ uint32_t dacpd_mask;
+ uint32_t dsmpd_mask;
+ uint32_t fbdiv_mask;
+ uint32_t frac_mask;
+ uint32_t prediv_mask;
+ uint32_t postdiv1_mask;
+
+ uint32_t dacpd_shift;
+ uint32_t dsmpd_shift;
+ uint32_t fbdiv_shift;
+ uint32_t frac_shift;
+ uint32_t prediv_shift;
+ uint32_t postdiv1_shift;
+};
+
+/*
+ * Since syscon pseudo device does not currently support more than
+ * one syscon memory region, we use this temporary function instead
+ */
+
+static int
+jh7110_syscon_modify_4(struct resource *res, bus_size_t offset,
+ uint32_t clear_bits, uint32_t set_bits)
+{
+ uint32_t val;
+ uint32_t new_val;
+
+ val = bus_read_4(res, offset);
+
+ new_val = val & ~clear_bits;
+ new_val = set_bits | new_val;
+
+ if (new_val != val)
+ bus_write_4(res, offset, new_val);
+
+ return (0);
+}
+
+static int
+jh7110_clk_pll_init(struct clknode *clk, device_t dev)
+{
+ clknode_init_parent_idx(clk, 0);
+
+ return (0);
+}
+
+static int
+jh7110_clk_pll_recalc_freq(struct clknode *clk, uint64_t *freq)
+{
+ struct jh7110_clk_pll_sc *sc;
+
+ uint32_t dacpd, dsmpd, fbdiv, prediv, postdiv1;
+ uint64_t frac;
+
+ sc = clknode_get_softc(clk);
+
+ mtx_lock(sc->mtx);
+ dacpd = (SYSCON_READ_4(sc->dacpd_offset)
+ & sc->dacpd_mask) >> sc->dacpd_shift;
+ dsmpd = (SYSCON_READ_4(sc->dsmpd_offset)
+ & sc->dsmpd_mask) >> sc->dsmpd_shift;
+ fbdiv = (SYSCON_READ_4(sc->fbdiv_offset)
+ & sc->fbdiv_mask) >> sc->fbdiv_shift;
+ prediv = (SYSCON_READ_4(sc->prediv_offset)
+ & sc->prediv_mask) >> sc->prediv_shift;
+ postdiv1 = (SYSCON_READ_4(sc->postdiv1_offset)
+ & sc->postdiv1_mask) >> sc->postdiv1_shift;
+ frac = (SYSCON_READ_4(sc->frac_offset)
+ & sc->frac_mask) >> sc->frac_shift;
+ mtx_unlock(sc->mtx);
+
+ /* dacpd and dsmpd both being 0 entails Fraction Multiple Mode */
+ if ((dacpd == 0) && (dsmpd == 0)) {
+ *freq = *freq / FRAC_PATR_SIZE * (fbdiv * FRAC_PATR_SIZE +
+ (frac * FRAC_PATR_SIZE / (1 << 24))) / prediv / (1 << postdiv1);
+ } else {
+ *freq = *freq / FRAC_PATR_SIZE * (fbdiv * FRAC_PATR_SIZE)
+ / prediv / (1 << postdiv1);
+ }
+
+ return (0);
+}
+
+static int
+jh7110_clk_pll_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout,
+ int flags, int *done)
+{
+
+ struct jh7110_clk_pll_sc *sc;
+ const struct starfive_pll_syscon_value *syscon_val = NULL;
+
+ sc = clknode_get_softc(clk);
+
+ for (int i = 0; i != sc->syscon_arr_nitems; i++) {
+ if (*fout == sc->syscon_arr[i].freq) {
+ syscon_val = &sc->syscon_arr[i];
+ }
+ }
+
+ if (syscon_val == NULL) {
+ printf("%s: tried to set an unknown frequency %ju for %s\n",
+ __func__, *fout, clknode_get_name(clk));
+ return (EINVAL);
+ }
+
+ if (flags & CLK_SET_DRYRUN) {
+ *done = 1;
+ return (0);
+ }
+
+ mtx_lock(sc->mtx);
+ SYSCON_MODIFY_4(sc->dacpd_offset, sc->dacpd_mask,
+ syscon_val->dacpd << sc->dacpd_shift & sc->dacpd_mask);
+ SYSCON_MODIFY_4(sc->dsmpd_offset, sc->dsmpd_mask,
+ syscon_val->dsmpd << sc->dsmpd_shift & sc->dsmpd_mask);
+ SYSCON_MODIFY_4(sc->prediv_offset, sc->prediv_mask,
+ syscon_val->prediv << sc->prediv_shift & sc->prediv_mask);
+ SYSCON_MODIFY_4(sc->fbdiv_offset, sc->fbdiv_mask,
+ syscon_val->fbdiv << sc->fbdiv_shift & sc->fbdiv_mask);
+ SYSCON_MODIFY_4(sc->postdiv1_offset,
+ sc->postdiv1_mask, (syscon_val->postdiv1 >> 1)
+ << sc->postdiv1_shift & sc->postdiv1_mask);
+
+ if (!syscon_val->dacpd && !syscon_val->dsmpd) {
+ SYSCON_MODIFY_4(sc->frac_offset, sc->frac_mask,
+ syscon_val->frac << sc->frac_shift & sc->frac_mask);
+ }
+
+ mtx_unlock(sc->mtx);
+ *done = 1;
+
+ return (0);
+}
+
+static clknode_method_t jh7110_clk_pll_clknode_methods[] = {
+ /* Device interface */
+ CLKNODEMETHOD(clknode_init, jh7110_clk_pll_init),
+ CLKNODEMETHOD(clknode_recalc_freq, jh7110_clk_pll_recalc_freq),
+ CLKNODEMETHOD(clknode_set_freq, jh7110_clk_pll_set_freq),
+ CLKNODEMETHOD_END
+};
+
+DEFINE_CLASS_1(jh7110_clk_pll_clknode, jh7110_clk_pll_clknode_class,
+ jh7110_clk_pll_clknode_methods,
+ sizeof(struct jh7110_clk_pll_sc), clknode_class);
+
+int
+jh7110_clk_pll_register(struct clkdom *clkdom, struct jh7110_pll_def *clkdef)
+{
+ struct clknode *clk;
+ struct jh7110_clk_pll_sc *sc;
+
+ clk = clknode_create(clkdom, &jh7110_clk_pll_clknode_class,
+ &clkdef->clkdef);
+ if (clk == NULL)
+ return (1);
+
+ sc = clknode_get_softc(clk);
+ sc->sysregs = clkdef->sysregs;
+ sc->syscon_mem_res = clkdef->syscon_mem_res;
+ sc->mtx = clkdef->mtx;
+
+ if (!strncmp(clknode_get_name(clk), "pll0_out", 8)) {
+ sc->syscon_arr = jh7110_pll0_syscon_freq;
+ sc->syscon_arr_nitems = nitems(jh7110_pll0_syscon_freq);
+
+ sc->dacpd_offset = clkdef->pll_offsets[0];
+ sc->dsmpd_offset = clkdef->pll_offsets[0];
+ sc->fbdiv_offset = clkdef->pll_offsets[1];
+ sc->frac_offset = clkdef->pll_offsets[2];
+ sc->prediv_offset = clkdef->pll_offsets[3];
+ sc->postdiv1_offset = clkdef->pll_offsets[2];
+
+ sc->dacpd_mask = PLL0_DACPD_MASK;
+ sc->dsmpd_mask = PLL0_DSMPD_MASK;
+ sc->fbdiv_mask = PLL0_FBDIV_MASK;
+ sc->frac_mask = PLL0_FRAC_MASK;
+ sc->prediv_mask = PLL0_PREDIV_MASK;
+ sc->postdiv1_mask = PLL0_POSTDIV1_MASK;
+
+ sc->dacpd_shift = PLL0_DACPD_SHIFT;
+ sc->dsmpd_shift = PLL0_DSMPD_SHIFT;
+ sc->fbdiv_shift = PLL0_FBDIV_SHIFT;
+ sc->frac_shift = PLL0_FRAC_SHIFT;
+ sc->prediv_shift = PLL0_PREDIV_SHIFT;
+ sc->postdiv1_shift = PLL0_POSTDIV1_SHIFT;
+ }
+
+ else if (!strncmp(clknode_get_name(clk), "pll1_out", 8)) {
+ sc->syscon_arr = jh7110_pll1_syscon_freq;
+ sc->syscon_arr_nitems = nitems(jh7110_pll1_syscon_freq);
+
+ sc->dacpd_offset = clkdef->pll_offsets[3];
+ sc->dsmpd_offset = clkdef->pll_offsets[3];
+ sc->fbdiv_offset = clkdef->pll_offsets[3];
+ sc->frac_offset = clkdef->pll_offsets[4];
+ sc->prediv_offset = clkdef->pll_offsets[5];
+ sc->postdiv1_offset = clkdef->pll_offsets[4];
+
+ sc->dacpd_mask = PLL1_DACPD_MASK;
+ sc->dsmpd_mask = PLL1_DSMPD_MASK;
+ sc->fbdiv_mask = PLL1_FBDIV_MASK;
+ sc->frac_mask = PLL1_FRAC_MASK;
+ sc->prediv_mask = PLL1_PREDIV_MASK;
+ sc->postdiv1_mask = PLL1_POSTDIV1_MASK;
+
+ sc->dacpd_shift = PLL1_DACPD_SHIFT;
+ sc->dsmpd_shift = PLL1_DSMPD_SHIFT;
+ sc->fbdiv_shift = PLL1_FBDIV_SHIFT;
+ sc->frac_shift = PLL1_FRAC_SHIFT;
+ sc->prediv_shift = PLL1_PREDIV_SHIFT;
+ sc->postdiv1_shift = PLL1_POSTDIV1_SHIFT;
+ }
+
+ else if (!strncmp(clknode_get_name(clk), "pll2_out", 8)) {
+ sc->syscon_arr = jh7110_pll2_syscon_freq;
+ sc->syscon_arr_nitems = nitems(jh7110_pll2_syscon_freq);
+
+ sc->dacpd_offset = clkdef->pll_offsets[5];
+ sc->dsmpd_offset = clkdef->pll_offsets[5];
+ sc->fbdiv_offset = clkdef->pll_offsets[5];
+ sc->frac_offset = clkdef->pll_offsets[6];
+ sc->prediv_offset = clkdef->pll_offsets[7];
+ sc->postdiv1_offset = clkdef->pll_offsets[6];
+
+ sc->dacpd_mask = PLL2_DACPD_MASK;
+ sc->dsmpd_mask = PLL2_DSMPD_MASK;
+ sc->fbdiv_mask = PLL2_FBDIV_MASK;
+ sc->frac_mask = PLL2_FRAC_MASK;
+ sc->prediv_mask = PLL2_PREDIV_MASK;
+ sc->postdiv1_mask = PLL2_POSTDIV1_MASK;
+
+ sc->dacpd_shift = PLL2_DACPD_SHIFT;
+ sc->dsmpd_shift = PLL2_DSMPD_SHIFT;
+ sc->fbdiv_shift = PLL2_FBDIV_SHIFT;
+ sc->frac_shift = PLL2_FRAC_SHIFT;
+ sc->prediv_shift = PLL2_PREDIV_SHIFT;
+ sc->postdiv1_shift = PLL2_POSTDIV1_SHIFT;
+ }
+
+ clknode_register(clkdom, clk);
+
+ return (0);
+}
diff --git a/sys/riscv/starfive/clk/jh7110_clkgen.c b/sys/riscv/starfive/clk/jh7110_clkgen.c
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/clk/jh7110_clkgen.c
@@ -0,0 +1,689 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2016 Michal Meloun <mmel@FreeBSD.org>
+ * Copyright (c) 2020 Oskar Holmlund <oskar.holmlund@ohdata.se>
+ * Copyright (c) 2022 Mitchell Horne <mhorne@FreeBSD.org>
+ * Copyright (c) 2023 Jari Sihvola <jsihv@gmx.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/fbio.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/clk/clk_div.h>
+#include <dev/extres/clk/clk_fixed.h>
+#include <dev/extres/clk/clk_gate.h>
+#include <dev/extres/clk/clk_link.h>
+#include <dev/extres/clk/clk_mux.h>
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <vm/pmap.h>
+#include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
+
+#include <riscv/starfive/clk/jh7110_clk.h>
+
+#include <dt-bindings/clock/starfive-jh7110-clkgen.h>
+
+#include "clkdev_if.h"
+
+static struct ofw_compat_data compat_data[] = {
+ { "starfive,jh7110-clkgen", 1 },
+ { NULL, 0 }
+};
+
+struct jh7110_clkgen_softc {
+ struct mtx mtx;
+ struct clkdom *clkdom;
+ int *rid;
+
+ struct resource *sys_mem_res;
+ struct resource *stg_mem_res;
+ struct resource *aon_mem_res;
+ struct resource *isp_mem_res;
+ struct resource *vout_mem_res;
+ struct resource *syscon_mem_res;
+};
+
+static struct resource_spec res_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE },
+ RESOURCE_SPEC_END
+};
+
+#define RD4(sc, reg) bus_read_4(&(sc)->sys_mem_res[0], (reg))
+#define WR4(sc, reg, val) bus_write_4(&(sc)->sys_mem_res[0], (reg), (val))
+
+struct resource *
+jh7110_clk_get_memres(struct clknode *clk, uint32_t flags)
+{
+ struct jh7110_clkgen_softc *sc;
+
+ sc = device_get_softc(clknode_get_device(clk));
+
+ if (flags & JH7110_CLK_SYS)
+ return (sc->sys_mem_res);
+ else if (flags & JH7110_CLK_AON)
+ return (sc->aon_mem_res);
+ else if (flags & JH7110_CLK_ISP)
+ return (sc->isp_mem_res);
+ else if (flags & JH7110_CLK_STG)
+ return (sc->stg_mem_res);
+ else if (flags & JH7110_CLK_VOUT)
+ return (sc->vout_mem_res);
+
+ device_printf(clknode_get_device(clk),
+ "Error: clknode %s without a mem resource flag\n",
+ clknode_get_name(clk));
+
+ return (NULL);
+}
+
+/* parents for non-pll SYS clocks */
+static const char *cpu_root_p[] = { "osc", "pll0_out" };
+static const char *cpu_core_p[] = { "cpu_root" };
+static const char *cpu_bus_p[] = { "cpu_core" };
+static const char *perh_root_p[] = { "pll0_out", "pll2_out" };
+static const char *bus_root_p[] = { "osc", "pll2_out" };
+
+static const char *apb0_p[] = { "apb_bus" };
+
+static const char *u0_sys_iomux_pclk_p[] = { "apb12" };
+
+static const char *u0_dw_uart_clk_apb_p[] = { "apb0" };
+static const char *u0_dw_uart_clk_core_p[] = { "osc" };
+static const char *u1_dw_uart_clk_apb_p[] = { "apb0" };
+static const char *u1_dw_uart_clk_core_p[] = { "osc" };
+static const char *u2_dw_uart_clk_apb_p[] = { "apb0" };
+static const char *u2_dw_uart_clk_core_p[] = { "osc" };
+static const char *u3_dw_uart_clk_apb_p[] = { "apb0" };
+static const char *u3_dw_uart_clk_core_p[] = { "perh_root" };
+
+static const char *apb_bus_func_p[] = { "stg_axiahb" };
+static const char *stg_axiahb_p[] = { "axi_cfg0" };
+static const char *ahb0_p[] = { "stg_axiahb" };
+static const char *axi_cfg0_p[] = { "bus_root" };
+
+static const char *u0_dw_sdio_clk_ahb_p[] = { "ahb0" };
+static const char *u1_dw_sdio_clk_ahb_p[] = { "ahb0" };
+static const char *u0_dw_sdio_clk_sdcard_p[] = { "axi_cfg0" };
+static const char *u1_dw_sdio_clk_sdcard_p[] = { "axi_cfg0" };
+
+static const char *gmac_src_p[] = { "gmacusb_root" };
+
+static const char *u1_dw_gmac5_axi64_clk_rx_p[] = { "gmac1_rgmii_rxin",
+ "gmac1_rmii_rtx" };
+static const char *u1_dw_gmac5_axi64_clk_rx_inv_p[] = {
+ "u1_dw_gmac5_axi64_clk_rx" };
+
+static const char *gmac0_gtxclk_p[] = { "gmacusb_root" };
+static const char *gmac0_ptp_p[] = { "gmac_src" };
+static const char *gmac_phy_p[] = { "gmac_src" };
+static const char *gmac0_gtxc_p[] = { "gmac0_gtxclk" };
+
+static const char *gmac1_gtxclk_p[] = { "gmacusb_root" };
+
+static const char *u1_dw_gmac5_axi64_clk_tx_p[] = { "gmac1_gtxclk",
+ "gmac1_rmii_rtx" };
+static const char *u1_dw_gmac5_axi64_clk_tx_inv_p[] = {
+ "u1_dw_gmac5_axi64_clk_tx" };
+static const char *u1_dw_gmac5_axi64_clk_ptp_p[] = { "gmac_src" };
+static const char *u1_dw_gmac5_axi64_clk_ahb_p[] = { "ahb0" };
+static const char *u1_dw_gmac5_axi64_clk_axi_p[] = { "stg_axiahb" };
+static const char *gmac1_gtxc_p[] = { "gmac1_gtxclk" };
+static const char *gmac1_rmii_rtx_p[] = { "gmac1_rmii_refin" };
+
+static const char *nocstg_bus_p[] = { "bus_root" };
+static const char *noc_bus_clk_stg_axi_p[] = { "nocstg_bus" };
+
+/* parents for pll fixed clocks and pll_out clocks */
+static const char *gmacusb_root_p[] = { "pll0_out" };
+static const char *apb12_p[] = { "apb_bus" };
+static const char *apb_bus_p[] = { "u2_pclk_mux_pclk" };
+static const char *u2_pclk_mux_pclk_p[] = { "u2_pclk_mux_func_pclk" };
+static const char *u2_pclk_mux_func_pclk_p[] = { "apb_bus_func" };
+static const char *aon_ahb_p[] = { "stg_axiahb" };
+static const char *u0_dw_gmac5_axi64_clk_rmii_p[] = { "gmac0_rmii_refin" };
+static const char *u1_dw_gmac5_axi64_clk_rmii_p[] = { "gmac0_rmii_refin" };
+static const char *pll_parents[] = { "osc" };
+static const char *stg_apb_p[] = { "apb_bus" };
+static const char *u0_plda_pcie_clk_axi_slv0_p[] = {
+ "u0_plda_pcie_clk_axi_mst0" };
+static const char *u1_plda_pcie_clk_axi_slv0_p[] = {
+ "u1_plda_pcie_clk_axi_mst0" };
+static const char *u0_plda_pcie_clk_axi_slv_p[] = {
+ "u0_plda_pcie_clk_axi_mst0" };
+static const char *u1_plda_pcie_clk_axi_slv_p[] = {
+ "u1_plda_pcie_clk_axi_mst0" };
+static const char *u0_plda_pcie_clk_osc_p[] = { "osc" };
+static const char *u1_plda_pcie_clk_osc_p[] = { "osc" };
+static const char *u0_e2_sft7110_irq_sync_clk_core_p[] = { "stg_axiahb" };
+static const char *u0_u7mc_sft7110_irq_sync_bux_clk_p[] = { "cpu_bus" };
+
+/* non-pll SYS clocks */
+static const struct jh7110_clk_def sys_clks[] = {
+ JH7110_MUX(JH7110_CPU_ROOT, "cpu_root", cpu_root_p),
+ JH7110_DIV(JH7110_CPU_CORE, "cpu_core", cpu_core_p, 7),
+ JH7110_DIV(JH7110_CPU_BUS, "cpu_bus", cpu_bus_p, 2),
+ JH7110_GATEDIV(JH7110_PERH_ROOT, "perh_root", perh_root_p, 2),
+ JH7110_MUX(JH7110_BUS_ROOT, "bus_root", bus_root_p),
+
+ JH7110_MUX(JH7110_GMAC5_CLK_RX, "u1_dw_gmac5_axi64_clk_rx",
+ u1_dw_gmac5_axi64_clk_rx_p),
+ JH7110_INV(JH7110_GMAC5_CLK_RX_INV, "u1_dw_gmac5_axi64_clk_rx_inv",
+ u1_dw_gmac5_axi64_clk_rx_inv_p),
+
+ JH7110_GATE(JH7110_GMAC5_CLK_AHB, "u1_dw_gmac5_axi64_clk_ahb",
+ u1_dw_gmac5_axi64_clk_ahb_p),
+
+ JH7110_GATE(JH7110_APB0, "apb0", apb0_p),
+ JH7110_GATE(JH7110_SYS_IOMUX_PCLK, "u0_sys_iomux_pclk",
+ u0_sys_iomux_pclk_p),
+ JH7110_GATE(JH7110_UART0_CLK_APB, "u0_dw_uart_clk_apb",
+ u0_dw_uart_clk_apb_p),
+ JH7110_GATE(JH7110_UART0_CLK_CORE, "u0_dw_uart_clk_core",
+ u0_dw_uart_clk_core_p),
+ JH7110_GATE(JH7110_UART1_CLK_APB, "u1_dw_uart_clk_apb",
+ u1_dw_uart_clk_apb_p),
+ JH7110_GATE(JH7110_UART1_CLK_CORE, "u1_dw_uart_clk_core",
+ u1_dw_uart_clk_core_p),
+ JH7110_GATE(JH7110_UART2_CLK_APB, "u2_dw_uart_clk_apb",
+ u2_dw_uart_clk_apb_p),
+ JH7110_GATE(JH7110_UART2_CLK_CORE, "u2_dw_uart_clk_core",
+ u2_dw_uart_clk_core_p),
+ JH7110_GATE(JH7110_UART3_CLK_APB, "u3_dw_uart_clk_apb",
+ u3_dw_uart_clk_apb_p),
+ JH7110_GATE(JH7110_UART3_CLK_CORE, "u3_dw_uart_clk_core",
+ u3_dw_uart_clk_core_p),
+
+ JH7110_DIV(JH7110_AXI_CFG0, "axi_cfg0", axi_cfg0_p, 3),
+ JH7110_DIV(JH7110_STG_AXIAHB, "stg_axiahb", stg_axiahb_p, 2),
+ JH7110_GATE(JH7110_AHB0, "ahb0", ahb0_p),
+ JH7110_DIV(JH7110_APB_BUS_FUNC, "apb_bus_func", apb_bus_func_p, 8),
+
+ JH7110_GATE(JH7110_SDIO0_CLK_AHB, "u0_dw_sdio_clk_ahb",
+ u0_dw_sdio_clk_ahb_p),
+ JH7110_GATE(JH7110_SDIO1_CLK_AHB, "u1_dw_sdio_clk_ahb",
+ u1_dw_sdio_clk_ahb_p),
+ JH7110_GATEDIV(JH7110_SDIO0_CLK_SDCARD, "u0_dw_sdio_clk_sdcard",
+ u0_dw_sdio_clk_sdcard_p, 15),
+ JH7110_GATEDIV(JH7110_SDIO1_CLK_SDCARD, "u1_dw_sdio_clk_sdcard",
+ u1_dw_sdio_clk_sdcard_p, 15),
+
+ JH7110_DIV(JH7110_GMAC_SRC, "gmac_src", gmac_src_p, 7),
+
+ JH7110_GATEDIV(JH7110_GMAC0_GTXCLK, "gmac0_gtxclk", gmac0_gtxclk_p, 15),
+ JH7110_GATEDIV(JH7110_GMAC0_PTP, "gmac0_ptp", gmac0_ptp_p, 31),
+ JH7110_GATEDIV(JH7110_GMAC_PHY, "gmac_phy", gmac_phy_p, 31),
+ JH7110_GATE(JH7110_GMAC0_GTXC, "gmac0_gtxc", gmac0_gtxc_p),
+
+ JH7110_DIV(JH7110_GMAC1_GTXCLK, "gmac1_gtxclk", gmac1_gtxclk_p, 15),
+ JH7110_GATEMUX(JH7110_GMAC5_CLK_TX, "u1_dw_gmac5_axi64_clk_tx",
+ u1_dw_gmac5_axi64_clk_tx_p),
+ JH7110_INV(JH7110_GMAC5_CLK_TX_INV, "u1_dw_gmac5_axi64_clk_tx_inv",
+ u1_dw_gmac5_axi64_clk_tx_inv_p),
+ JH7110_GATEDIV(JH7110_GMAC5_CLK_PTP, "u1_dw_gmac5_axi64_clk_ptp",
+ u1_dw_gmac5_axi64_clk_ptp_p, 31),
+ JH7110_GATE(JH7110_GMAC5_CLK_AXI, "u1_dw_gmac5_axi64_clk_axi",
+ u1_dw_gmac5_axi64_clk_axi_p),
+ JH7110_GATE(JH7110_GMAC1_GTXC, "gmac1_gtxc", gmac1_gtxc_p),
+ JH7110_DIV(JH7110_GMAC1_RMII_RTX, "gmac1_rmii_rtx",
+ gmac1_rmii_rtx_p, 30),
+
+ JH7110_DIV(JH7110_NOCSTG_BUS, "nocstg_bus", nocstg_bus_p, 3),
+
+ JH7110_GATE(JH7110_NOC_BUS_CLK_STG_AXI,
+ "u0_sft_7110_noc_bus_clk_stg_axi", noc_bus_clk_stg_axi_p),
+};
+
+/* pll_out clks (SYS) */
+static struct jh7110_pll_def pll_out_clks[] = {
+ {
+ .clkdef.id = JH7110_PLL0_OUT,
+ .clkdef.name = "pll0_out",
+ .clkdef.parent_names = pll_parents,
+ .clkdef.parent_cnt = nitems(pll_parents),
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS,
+ },
+ {
+ .clkdef.id = JH7110_PLL1_OUT,
+ .clkdef.name = "pll1_out",
+ .clkdef.parent_names = pll_parents,
+ .clkdef.parent_cnt = nitems(pll_parents),
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS,
+ },
+ {
+ .clkdef.id = JH7110_PLL2_OUT,
+ .clkdef.name = "pll2_out",
+ .clkdef.parent_names = pll_parents,
+ .clkdef.parent_cnt = nitems(pll_parents),
+ .clkdef.flags = CLK_NODE_STATIC_STRINGS,
+ },
+};
+
+/* fixed pll clocks */
+static struct clk_fixed_def fixed_pll_clks[] = {
+
+ /* SYS */
+ JH7110_PLL(JH7110_GMACUSB_ROOT, "gmacusb_root", gmacusb_root_p),
+ JH7110_PLL(JH7110_PCLK2_MUX_FUNC_PCLK, "u2_pclk_mux_func_pclk",
+ u2_pclk_mux_func_pclk_p),
+ JH7110_PLL(JH7110_U2_PCLK_MUX_PCLK, "u2_pclk_mux_pclk",
+ u2_pclk_mux_pclk_p),
+ JH7110_PLL(JH7110_APB_BUS, "apb_bus", apb_bus_p),
+ JH7110_PLL(JH7110_APB12, "apb12", apb12_p),
+
+ JH7110_PLL(JH7110_AON_AHB, "aon_ahb", aon_ahb_p),
+ JH7110_PLL(JH7110_GMAC5_CLK_RMII, "u1_dw_gmac5_axi64_clk_rmii",
+ u1_dw_gmac5_axi64_clk_rmii_p),
+ JH7110_PLL(JH7110_U7_IRQ_SYNC_BUS_CLK,
+ "u0_u7mc_sft7110_irq_sync_bux_clk",
+ u0_u7mc_sft7110_irq_sync_bux_clk_p),
+
+ /* AON */
+ JH7110_PLL(JH7110_U0_GMAC5_CLK_RMII, "u0_dw_gmac5_axi64_clk_rmii",
+ u0_dw_gmac5_axi64_clk_rmii_p),
+
+ /* STG */
+ JH7110_PLL(JH7110_STG_APB, "stg_apb", stg_apb_p),
+ JH7110_PLL(JH7110_PCIE0_CLK_AXI_SLV0, "u0_plda_pcie_clk_axi_slv0",
+ u0_plda_pcie_clk_axi_slv0_p),
+
+ JH7110_PLL(JH7110_PCIE0_CLK_AXI_SLV, "u0_plda_pcie_clk_axi_slv",
+ u0_plda_pcie_clk_axi_slv_p),
+
+ JH7110_PLL(JH7110_PCIE1_CLK_AXI_SLV0, "u1_plda_pcie_clk_axi_slv0",
+ u1_plda_pcie_clk_axi_slv0_p),
+ JH7110_PLL(JH7110_PCIE1_CLK_AXI_SLV, "u1_plda_pcie_clk_axi_slv",
+ u1_plda_pcie_clk_axi_slv_p),
+ JH7110_PLL(JH7110_PCIE0_CLK_OSC, "u0_plda_pcie_clk_osc",
+ u0_plda_pcie_clk_osc_p),
+ JH7110_PLL(JH7110_PCIE1_CLK_OSC, "u1_plda_pcie_clk_osc",
+ u1_plda_pcie_clk_osc_p),
+ JH7110_PLL(JH7110_E2_IRQ_SYNC_CLK_CORE,
+ "u0_e2_sft7110_irq_sync_clk_core",
+ u0_e2_sft7110_irq_sync_clk_core_p),
+};
+
+/* non-pll AON clocks & parents */
+static const char *u0_dw_gmac5_axi64_clk_ahb_p[] = { "aon_ahb" };
+static const char *u0_dw_gmac5_axi64_clk_axi_p[] = { "aon_ahb" };
+static const char *gmac0_rmii_rtx_p[] = { "gmac0_rmii_refin" };
+static const char *u0_dw_gmac5_axi64_clk_tx_p[] = { "gmac0_gtxclk",
+ "gmac0_rmii_rtx" };
+static const char *u0_dw_gmac5_axi64_clk_tx_inv_p[] = {
+ "u0_dw_gmac5_axi64_clk_tx" };
+static const char *u0_dw_gmac5_axi64_clk_rx_p[] = { "gmac0_rgmii_rxin",
+ "gmac0_rmii_rtx" };
+static const char *u0_dw_gmac5_axi64_clk_rx_inv_p[] = {
+ "u0_dw_gmac5_axi64_clk_rx" };
+
+static const struct jh7110_clk_def aon_clks[] = {
+ JH7110_GATE(JH7110_U0_GMAC5_CLK_AHB, "u0_dw_gmac5_axi64_clk_ahb",
+ u0_dw_gmac5_axi64_clk_ahb_p),
+ JH7110_GATE(JH7110_U0_GMAC5_CLK_AXI, "u0_dw_gmac5_axi64_clk_axi",
+ u0_dw_gmac5_axi64_clk_axi_p),
+ JH7110_DIV(JH7110_GMAC0_RMII_RTX, "gmac0_rmii_rtx",
+ gmac0_rmii_rtx_p, 30),
+ JH7110_GATEMUX(JH7110_U0_GMAC5_CLK_TX, "u0_dw_gmac5_axi64_clk_tx",
+ u0_dw_gmac5_axi64_clk_tx_p),
+ JH7110_INV(JH7110_U0_GMAC5_CLK_TX_INV, "u0_dw_gmac5_axi64_clk_tx_inv",
+ u0_dw_gmac5_axi64_clk_tx_inv_p),
+ JH7110_MUX(JH7110_U0_GMAC5_CLK_RX, "u0_dw_gmac5_axi64_clk_rx",
+ u0_dw_gmac5_axi64_clk_rx_p),
+ JH7110_INV(JH7110_U0_GMAC5_CLK_RX_INV, "u0_dw_gmac5_axi64_clk_rx_inv",
+ u0_dw_gmac5_axi64_clk_rx_inv_p),
+};
+
+/* STG clocks & parents */
+static const char *u0_plda_pcie_clk_apb_p[] = { "stg_apb" };
+static const char *u0_plda_pcie_clk_axi_mst0_p[] = { "stg_axiahb" };
+static const char *u0_plda_pcie_clk_tl_p[] = { "stg_axiahb" };
+static const char *u1_plda_pcie_clk_apb_p[] = { "stg_apb" };
+static const char *u1_plda_pcie_clk_axi_mst0_p[] = { "stg_axiahb" };
+static const char *u1_plda_pcie_clk_tl_p[] = { "stg_axiahb" };
+static const char *u0_pcie01_slv_dec_mainclk_p[] = { "stg_axiahb" };
+
+static const struct jh7110_clk_def stg_clks[] = {
+ JH7110_GATE(JH7110_PCIE0_CLK_APB, "u0_plda_pcie_clk_apb",
+ u0_plda_pcie_clk_apb_p),
+ JH7110_GATE(JH7110_PCIE0_CLK_AXI_MST0, "u0_plda_pcie_clk_axi_mst0",
+ u0_plda_pcie_clk_axi_mst0_p),
+ JH7110_GATE(JH7110_PCIE0_CLK_TL, "u0_plda_pcie_clk_tl",
+ u0_plda_pcie_clk_tl_p),
+ JH7110_GATE(JH7110_PCIE1_CLK_APB, "u1_plda_pcie_clk_apb",
+ u1_plda_pcie_clk_apb_p),
+ JH7110_GATE(JH7110_PCIE1_CLK_AXI_MST0, "u1_plda_pcie_clk_axi_mst0",
+ u1_plda_pcie_clk_axi_mst0_p),
+ JH7110_GATE(JH7110_PCIE1_CLK_TL, "u1_plda_pcie_clk_tl",
+ u1_plda_pcie_clk_tl_p),
+ JH7110_GATE(JH7110_PCIE01_SLV_DEC_MAINCLK, "u0_pcie01_slv_dec_mainclk",
+ u0_pcie01_slv_dec_mainclk_p),
+};
+
+/* Default DT mapper. */
+static int
+jh7110_ofw_map(struct clkdom *clkdom, uint32_t ncells,
+ phandle_t *cells, struct clknode **clk)
+{
+ int id = cells[0];
+
+ if (ncells == 1) {
+ *clk = clknode_find_by_id(clkdom, id);
+ } else {
+ return (ERANGE);
+ }
+ if (*clk == NULL) {
+ return (ENXIO);
+ }
+ return (0);
+}
+
+static int
+jh7110_clkgen_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "StarFive JH7110 clock generator controller");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+jh7110_clkgen_attach(device_t dev)
+{
+ struct jh7110_clkgen_softc *sc;
+ cell_t reg;
+ int i, rid, error;
+ pcell_t *sysprop;
+ pcell_t pll_offsets[8];
+ struct syscon *sysregs = NULL;
+ phandle_t node;
+ clk_t osc, cpu_core, cpu_root, pll0_out;
+ uint64_t cpu_core_freq;
+
+ sc = device_get_softc(dev);
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ node = ofw_bus_get_node(dev);
+
+ /* Allocate memory groups */
+
+ error = bus_alloc_resources(dev, res_spec, &sc->sys_mem_res);
+ if (error) {
+ device_printf(dev, "Couldn't allocate sys group resources\n");
+ return (ENXIO);
+ }
+
+ error = ofw_bus_find_string_index(node, "reg-names", "stg", &rid);
+ if (error != 0) {
+ device_printf(dev, "Cannot get 'stg' memory\n");
+ return (ENXIO);
+ }
+ sc->stg_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->stg_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate 'stg' (rid: %d)\n",
+ rid);
+ return (ENXIO);
+ }
+ error = ofw_bus_find_string_index(node, "reg-names", "aon", &rid);
+ if (error != 0) {
+ device_printf(dev, "Cannot get 'aon' memory\n");
+ return (ENXIO);
+ }
+ sc->aon_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->aon_mem_res == NULL) {
+ device_printf(dev, "Cannot allocate 'aon' (rid: %d)\n",
+ rid);
+ return (ENXIO);
+ }
+
+ /* Sanity check */
+ error = OF_searchencprop(node, "#clock-cells", ®, sizeof(reg));
+ if (error == -1) {
+ device_printf(dev, "Failed to get #clock-cells\n");
+ return (ENXIO);
+ }
+ if (reg != 1) {
+ device_printf(dev, "clock cells(%d) != 1\n", reg);
+ return (ENXIO);
+ }
+
+ /* Create clock domain */
+ sc->clkdom = clkdom_create(dev);
+ if (sc->clkdom == NULL) {
+ device_printf(dev, "Failed to create clkdom\n");
+ return (ENXIO);
+ }
+ clkdom_set_ofw_mapper(sc->clkdom, jh7110_ofw_map);
+
+ /* Temporary solution for syscon registers */
+ sc->syscon_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
+ 0x13030000, 0x1303FFFF, 0x1000, RF_ACTIVE);
+
+ /* Get syscon property for pll_out clocks */
+ error = OF_getencprop_alloc_multi(node, "starfive,sys-syscon",
+ sizeof(pcell_t), (void **)&sysprop);
+
+ /* Element 0 is a phandle, 1-8 are offset values */
+ for (int i = 0; i != 8; i++)
+ pll_offsets[i] = sysprop[i + 1];
+
+ /* Registering clocks */
+
+ for (i = 0; i < nitems(pll_out_clks); i++) {
+ pll_out_clks[i].pll_offsets = pll_offsets;
+ pll_out_clks[i].sysregs = sysregs;
+ pll_out_clks[i].syscon_mem_res = sc->syscon_mem_res;
+ pll_out_clks[i].mtx = &sc->mtx;
+ error = jh7110_clk_pll_register(sc->clkdom, &pll_out_clks[i]);
+ if (error != 0)
+ device_printf(dev, "Failed to register clock %s: %d\n",
+ pll_out_clks[i].clkdef.name, error);
+ }
+
+ for (i = 0; i < nitems(sys_clks); i++) {
+ error = jh7110_clk_register(sc->clkdom, &sys_clks[i],
+ JH7110_CLK_SYS);
+ if (error != 0)
+ device_printf(dev, "Failed to register clock %s: %d\n",
+ sys_clks[i].clkdef.name, error);
+ }
+
+ for (i = 0; i < nitems(fixed_pll_clks); i++) {
+
+ error = clknode_fixed_register(sc->clkdom, &fixed_pll_clks[i]);
+ if (error != 0)
+ device_printf(dev, "Failed to register clock %s: %d\n",
+ fixed_pll_clks[i].clkdef.name, error);
+ }
+
+ for (int i = 0; i < nitems(aon_clks); i++) {
+ error = jh7110_clk_register(sc->clkdom, &aon_clks[i],
+ JH7110_CLK_AON);
+ if (error != 0)
+ device_printf(dev, "Failed to register clock %s: %d\n",
+ aon_clks[i].clkdef.name, error);
+ }
+
+ for (i = 0; i < nitems(stg_clks); i++) {
+ error = jh7110_clk_register(sc->clkdom, &stg_clks[i],
+ JH7110_CLK_STG);
+ if (error != 0)
+ device_printf(dev, "Failed to register clock %s: %d\n",
+ stg_clks[i].clkdef.name, error);
+ }
+
+ error = clkdom_finit(sc->clkdom);
+ if (error) {
+ device_printf(dev, "Clkdom_finit returns error %d.\n", error);
+ }
+
+ /* Adjusting clocks */
+
+ error = clk_get_by_name(dev, "osc", &osc);
+ if (error != 0)
+ device_printf(dev, "Failed to get osc by name\n");
+
+ error = clk_get_by_id(dev, sc->clkdom, JH7110_CPU_CORE, &cpu_core);
+ if (error != 0)
+ device_printf(dev, "Failed to get cpu_core\n");
+
+ error = clk_get_by_id(dev, sc->clkdom, JH7110_CPU_ROOT, &cpu_root);
+ if (error != 0)
+ device_printf(dev, "Failed to get cpu_root\n");
+
+ error = clk_get_by_id(dev, sc->clkdom, JH7110_PLL0_OUT, &pll0_out);
+ if (error != 0)
+ device_printf(dev, "Failed to get pll0_out\n");
+
+ error = clk_get_freq(pll0_out, &cpu_core_freq);
+ if (error != 0)
+ device_printf(dev, "Failed to set cpu_root freq\n");
+
+ error = clk_set_freq(cpu_core, cpu_core_freq / 2, 0);
+ if (error != 0)
+ device_printf(dev, "Failed to set cpu_core freq\n");
+
+ error = clk_set_parent_by_clk(cpu_root, osc);
+ if (error != 0)
+ device_printf(dev, "Failed to set cpu_root parent (2)\n");
+
+ error = clk_set_freq(pll0_out, PLL0_DEFAULT_FREQ, 0);
+ if (error != 0)
+ device_printf(dev, "Failed to set freq for pll0_out\n");
+
+ error = clk_set_parent_by_clk(cpu_root, pll0_out);
+ if (error != 0)
+ device_printf(dev, "Failed to set pll0_out parent\n");
+
+ if (bootverbose)
+ clkdom_dump(sc->clkdom);
+
+ return (0);
+}
+
+static int
+jh7110_clkgen_detach(device_t dev)
+{
+ /* Detach not supported */
+ return (EACCES);
+}
+
+
+static int
+jh7110_clkgen_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+{
+ struct jh7110_clkgen_softc *sc;
+ sc = device_get_softc(dev);
+
+ *val = RD4(sc, addr);
+
+ return (0);
+}
+
+static int
+jh7110_clkgen_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+ struct jh7110_clkgen_softc *sc;
+ sc = device_get_softc(dev);
+
+ WR4(sc, addr, val);
+
+ return (0);
+}
+
+static int
+jh7110_clkgen_modify_4(device_t dev, bus_addr_t addr,
+ uint32_t clr, uint32_t set)
+{
+ struct jh7110_clkgen_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ reg = RD4(sc, addr);
+ reg &= ~clr;
+ reg |= set;
+ WR4(sc, addr, reg);
+
+ return (0);
+}
+
+
+static void
+jh7110_clkgen_device_lock(device_t dev)
+{
+ struct jh7110_clkgen_softc *sc;
+ sc = device_get_softc(dev);
+ mtx_lock(&sc->mtx);
+}
+
+static void
+jh7110_clkgen_device_unlock(device_t dev)
+{
+ struct jh7110_clkgen_softc *sc;
+ sc = device_get_softc(dev);
+ mtx_unlock(&sc->mtx);
+}
+
+static device_method_t jh7110_clkgen_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, jh7110_clkgen_probe),
+ DEVMETHOD(device_attach, jh7110_clkgen_attach),
+ DEVMETHOD(device_detach, jh7110_clkgen_detach),
+
+ /* clkdev interface */
+ DEVMETHOD(clkdev_read_4, jh7110_clkgen_read_4),
+ DEVMETHOD(clkdev_write_4, jh7110_clkgen_write_4),
+ DEVMETHOD(clkdev_modify_4, jh7110_clkgen_modify_4),
+ DEVMETHOD(clkdev_device_lock, jh7110_clkgen_device_lock),
+ DEVMETHOD(clkdev_device_unlock, jh7110_clkgen_device_unlock),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(jh7110_clkgen, jh7110_clkgen_driver, jh7110_clkgen_methods,
+ sizeof(struct jh7110_clkgen_softc));
+EARLY_DRIVER_MODULE(jh7110_clkgen, simplebus, jh7110_clkgen_driver, 0, 0,
+ BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(jh7110_clkgen, 1);
diff --git a/sys/riscv/starfive/jh7110_gpio.c b/sys/riscv/starfive/jh7110_gpio.c
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/jh7110_gpio.c
@@ -0,0 +1,315 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2023 Jari Sihvola <jsihv@gmx.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include <dev/extres/clk/clk.h>
+#include <dev/gpio/gpiobusvar.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "gpio_if.h"
+
+#define JH7110_GPIO_PINS 64
+
+#define GPIOEN 0xdc
+#define GPIOE_0 0x100
+#define GPIOE_1 0x104
+#define GPIO_DIN_LOW 0x118
+#define GPIO_DIN_HIGH 0x11c
+#define GP0_DOUT_CFG 0x0
+#define GP0_DOEN_CFG 0x40
+
+#define ENABLE_MASK 0x3f
+#define DATA_OUT_MASK 0x7f
+
+#define ALIGN_4(_val) (_val & ~3)
+#define MOD_4(_val) (_val & 3)
+
+
+struct jh7110_gpio_softc {
+ device_t dev;
+ device_t busdev;
+ struct mtx mtx;
+ struct resource *res;
+ clk_t clk;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"starfive,jh7110-sys-pinctrl", 1},
+ {NULL, 0}
+};
+
+static struct resource_spec jh7110_gpio_spec[] = {
+ { SYS_RES_MEMORY, 0, RF_ACTIVE },
+ { -1, 0 }
+};
+
+#define JH7110_GPIO_LOCK(_sc) mtx_lock(&(_sc)->mtx)
+#define JH7110_GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
+
+#define JH7110_GPIO_READ(sc, reg) bus_read_4((sc)->res, (reg))
+#define JH7110_GPIO_WRITE(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
+
+static device_t
+jh7110_gpio_get_bus(device_t dev)
+{
+ struct jh7110_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ return (sc->busdev);
+}
+
+static int
+jh7110_gpio_pin_max(device_t dev, int *maxpin)
+{
+ *maxpin = JH7110_GPIO_PINS - 1;
+
+ return (0);
+}
+
+static int
+jh7110_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
+{
+ struct jh7110_gpio_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ if (pin >= JH7110_GPIO_PINS)
+ return (EINVAL);
+
+ JH7110_GPIO_LOCK(sc);
+ if (pin < 32) {
+ reg = JH7110_GPIO_READ(sc, GPIO_DIN_LOW);
+ *val = (reg >> pin) & 0x1;
+ } else {
+ reg = JH7110_GPIO_READ(sc, GPIO_DIN_HIGH);
+ *val = (reg >> (pin - 32)) & 0x1;
+ }
+ JH7110_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+jh7110_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+ struct jh7110_gpio_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ if (pin >= JH7110_GPIO_PINS)
+ return (EINVAL);
+
+ JH7110_GPIO_LOCK(sc);
+ reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + ALIGN_4(pin));
+ reg &= ~(DATA_OUT_MASK << MOD_4(pin) * 8);
+ reg |= reg << MOD_4(pin) * 8;
+ JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + ALIGN_4(pin), value);
+ JH7110_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+jh7110_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+ struct jh7110_gpio_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ if (pin >= JH7110_GPIO_PINS)
+ return (EINVAL);
+
+ /* Reading the direction */
+ JH7110_GPIO_LOCK(sc);
+ reg = JH7110_GPIO_READ(sc, GP0_DOEN_CFG + ALIGN_4(pin));
+ if ((reg & ENABLE_MASK << MOD_4(pin) * 8) == 0)
+ *flags |= GPIO_PIN_OUTPUT;
+ else
+ *flags |= GPIO_PIN_INPUT;
+ JH7110_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+
+static int
+jh7110_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+ struct jh7110_gpio_softc *sc;
+ uint32_t reg;
+
+ sc = device_get_softc(dev);
+
+ if (pin >= JH7110_GPIO_PINS)
+ return (EINVAL);
+
+ /* Setting the direction, enable or disable output */
+ JH7110_GPIO_LOCK(sc);
+ if (flags & GPIO_PIN_INPUT) {
+ reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + ALIGN_4(pin));
+ reg &= ~(ENABLE_MASK << MOD_4(pin) * 8);
+ reg |= 1 << MOD_4(pin) * 8;
+ JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + ALIGN_4(pin), reg);
+ } else if (flags & GPIO_PIN_OUTPUT) {
+ reg = JH7110_GPIO_READ(sc, GP0_DOUT_CFG + ALIGN_4(pin));
+ reg &= ~(ENABLE_MASK << MOD_4(pin) * 8);
+ reg |= 0 << MOD_4(pin) * 8;
+ JH7110_GPIO_WRITE(sc, GP0_DOUT_CFG + ALIGN_4(pin), reg);
+ }
+ JH7110_GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+jh7110_gpio_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev)) {
+ return (ENXIO);
+ }
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) {
+ return (ENXIO);
+ }
+
+ device_set_desc(dev, "StarFive JH7110 GPIO generator driver");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+jh7110_gpio_detach(device_t dev)
+{
+ struct jh7110_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
+ gpiobus_detach_bus(dev);
+ mtx_destroy(&sc->mtx);
+
+ return (0);
+}
+
+static int
+jh7110_gpio_attach(device_t dev)
+{
+ struct jh7110_gpio_softc *sc;
+ int err;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF);
+
+ if (bus_alloc_resources(dev, jh7110_gpio_spec, &sc->res)) {
+ device_printf(dev, "Could not allocate resources\n");
+ bus_release_resources(dev, jh7110_gpio_spec, &sc->res);
+ mtx_destroy(&sc->mtx);
+ return (ENXIO);
+ }
+
+ if (clk_get_by_ofw_index(dev, 0, 0, &sc->clk) != 0) {
+ device_printf(dev, "Cannot get clock\n");
+ jh7110_gpio_detach(dev);
+ return (ENXIO);
+ }
+
+ err = clk_enable(sc->clk);
+ if (err != 0) {
+ device_printf(dev, "Could not enable clock %s\n",
+ clk_get_name(sc->clk));
+ jh7110_gpio_detach(dev);
+ return (ENXIO);
+ }
+
+ sc->busdev = gpiobus_attach_bus(dev);
+ if (sc->busdev == NULL) {
+ device_printf(dev, "Cannot attach gpiobus\n");
+ jh7110_gpio_detach(dev);
+ return (ENXIO);
+ }
+
+ /* Reseting GPIO interrupts */
+ JH7110_GPIO_WRITE(sc, GPIOE_0, 0);
+ JH7110_GPIO_WRITE(sc, GPIOE_1, 0);
+ JH7110_GPIO_WRITE(sc, GPIOEN, 1);
+
+ return (0);
+}
+
+static phandle_t
+jh7110_gpio_get_node(device_t bus, device_t dev)
+{
+ return (ofw_bus_get_node(bus));
+}
+
+static device_method_t jh7110_gpio_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, jh7110_gpio_probe),
+ DEVMETHOD(device_attach, jh7110_gpio_attach),
+ DEVMETHOD(device_detach, jh7110_gpio_detach),
+
+ /* GPIO protocol */
+ DEVMETHOD(gpio_get_bus, jh7110_gpio_get_bus),
+ DEVMETHOD(gpio_pin_max, jh7110_gpio_pin_max),
+ DEVMETHOD(gpio_pin_getflags, jh7110_gpio_pin_getflags),
+ DEVMETHOD(gpio_pin_setflags, jh7110_gpio_pin_setflags),
+ DEVMETHOD(gpio_pin_get, jh7110_gpio_pin_get),
+ DEVMETHOD(gpio_pin_set, jh7110_gpio_pin_set),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, jh7110_gpio_get_node),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(gpio, jh7110_gpio_driver, jh7110_gpio_methods,
+ sizeof(struct jh7110_gpio_softc));
+EARLY_DRIVER_MODULE(jh7110_gpio, simplebus, jh7110_gpio_driver, 0, 0,
+ BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
+MODULE_DEPEND(jh7110_gpio, gpiobus, 1, 1, 1);
diff --git a/sys/riscv/starfive/jh7110_reset.c b/sys/riscv/starfive/jh7110_reset.c
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/jh7110_reset.c
@@ -0,0 +1,342 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2023 Jari Sihvola <jsihv@gmx.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/time.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/extres/hwreset/hwreset.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dt-bindings/reset/starfive-jh7110.h>
+
+#include "hwreset_if.h"
+
+/* offsets for reset registers */
+#define AONCRG_RESET_SELECTOR 0x38
+#define ISPCRG_RESET_SELECTOR 0x38
+#define VOUTCRG_RESET_SELECTOR 0x48
+#define STGCRG_RESET_SELECTOR 0x74
+#define AONCRG_RESET_STATUS 0x3c
+#define ISPCRG_RESET_STATUS 0x3c
+#define VOUTCRG_RESET_STATUS 0x4c
+#define STGCRG_RESET_STATUS 0x78
+#define SYSCRG_RESET_SELECTOR0 0x2f8
+#define SYSCRG_RESET_SELECTOR1 0x2fc
+#define SYSCRG_RESET_SELECTOR2 0x300
+#define SYSCRG_RESET_SELECTOR3 0x304
+#define SYSCRG_RESET_STATUS0 0x308
+#define SYSCRG_RESET_STATUS1 0x30c
+#define SYSCRG_RESET_STATUS2 0x310
+#define SYSCRG_RESET_STATUS3 0x314
+
+static struct ofw_compat_data compat_data[] = {
+ { "starfive,jh7110-reset", 1 },
+ { NULL, 0 }
+};
+
+struct jh7110_reset_softc {
+ struct mtx mtx;
+ struct resource *sys_mem;
+ struct resource *stg_mem;
+ struct resource *aon_mem;
+ struct resource *isp_mem;
+ struct resource *vout_mem;
+};
+
+struct jh7110_reset_carrier {
+ struct resource *res;
+ uint64_t status_offset;
+ uint64_t selector_offset;
+};
+
+enum JH7110_CRG {
+ SYS0,
+ SYS1,
+ SYS2,
+ SYS3,
+ STG,
+ AON,
+ ISP,
+ VOUT,
+};
+
+#define RESET_READ(iodata, ss) \
+ bus_read_4((iodata).res, (iodata).ss##_offset)
+#define RESET_WRITE(iodata, ss, val) \
+ bus_write_4((iodata).res, (iodata).ss##_offset, val)
+
+static int
+jh7110_io_assign(struct jh7110_reset_softc *sc,
+ intptr_t id, struct jh7110_reset_carrier *iodata)
+{
+
+ uint32_t crg = id / 32;
+
+ if (crg == SYS0) {
+ iodata->res = sc->sys_mem;
+ iodata->status_offset = SYSCRG_RESET_STATUS0;
+ iodata->selector_offset = SYSCRG_RESET_SELECTOR0;
+ } else if (crg == SYS1) {
+ iodata->res = sc->sys_mem;
+ iodata->status_offset = SYSCRG_RESET_STATUS1;
+ iodata->selector_offset = SYSCRG_RESET_SELECTOR1;
+ } else if (crg == SYS2) {
+ iodata->res = sc->sys_mem;
+ iodata->status_offset = SYSCRG_RESET_STATUS2;
+ iodata->selector_offset = SYSCRG_RESET_SELECTOR2;
+ } else if (crg == SYS3) {
+ iodata->res = sc->sys_mem;
+ iodata->status_offset = SYSCRG_RESET_STATUS3;
+ iodata->selector_offset = SYSCRG_RESET_SELECTOR3;
+ } else if (crg == STG) {
+ iodata->res = sc->stg_mem;
+ iodata->status_offset = STGCRG_RESET_STATUS;
+ iodata->selector_offset = STGCRG_RESET_SELECTOR;
+ } else if (crg == AON) {
+ iodata->res = sc->aon_mem;
+ iodata->status_offset = AONCRG_RESET_STATUS;
+ iodata->selector_offset = AONCRG_RESET_SELECTOR;
+ } else if (crg == ISP) {
+ iodata->res = sc->isp_mem;
+ iodata->status_offset = ISPCRG_RESET_STATUS;
+ iodata->selector_offset = ISPCRG_RESET_SELECTOR;
+ } else if (crg == VOUT) {
+ iodata->res = sc->vout_mem;
+ iodata->status_offset = VOUTCRG_RESET_STATUS;
+ iodata->selector_offset = VOUTCRG_RESET_SELECTOR;
+ }
+
+ return (0);
+}
+
+static int
+jh7110_reset_assert(device_t dev, intptr_t id, bool assert)
+{
+
+ struct jh7110_reset_softc *sc;
+ struct jh7110_reset_carrier iodata;
+ struct timeval time_end, time_comp;
+ uint32_t regvalue, ready = 0;
+ uint32_t bitmask = 1UL << id % 32;
+ int ret;
+
+ sc = device_get_softc(dev);
+ jh7110_io_assign(sc, id, &iodata);
+
+ mtx_lock(&sc->mtx);
+
+ regvalue = RESET_READ(iodata, selector);
+
+ if (assert)
+ regvalue |= bitmask;
+ else
+ regvalue &= ~bitmask;
+ RESET_WRITE(iodata, selector, regvalue);
+
+ /*
+ * Timeout to prevent perpetual hanging when deasserting with
+ * gated clocks
+ */
+
+ getmicrotime(&time_end);
+ time_end.tv_usec += 1000;
+
+ if (!assert)
+ ready = bitmask;
+
+ for (;;) {
+ regvalue = RESET_READ(iodata, status);
+
+ if ((regvalue & bitmask) == ready)
+ break;
+
+ getmicrotime(&time_comp);
+ if (time_end.tv_usec <= time_comp.tv_usec) {
+ regvalue = RESET_READ(iodata, status);
+ break;
+ }
+ }
+
+ ret = ((regvalue & bitmask) == ready) ? 0 : -ETIMEDOUT;
+
+ mtx_unlock(&sc->mtx);
+
+ return (ret);
+}
+
+static int
+jh7110_reset_is_asserted(device_t dev, intptr_t id, bool *reset)
+{
+ struct jh7110_reset_softc *sc;
+ struct jh7110_reset_carrier iodata;
+ uint32_t reg_value;
+ uint32_t bitmask;
+
+ sc = device_get_softc(dev);
+
+ jh7110_io_assign(sc, id, &iodata);
+
+ mtx_lock(&sc->mtx);
+ reg_value = RESET_READ(iodata, status);
+ bitmask = (1UL << id % 32);
+ mtx_unlock(&sc->mtx);
+
+ *reset = (reg_value & bitmask) == 0;
+
+ return (0);
+}
+
+static int
+jh7110_reset_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "StarFive JH7110 reset driver");
+
+ return (0);
+}
+
+static int
+jh7110_reset_attach(device_t dev)
+{
+ struct jh7110_reset_softc *sc;
+ phandle_t node;
+ int rid, err;
+
+ sc = device_get_softc(dev);
+ node = ofw_bus_get_node(dev);
+
+ rid = 0;
+ err = ofw_bus_find_string_index(node, "reg-names", "syscrg", &rid);
+
+ if (err != 0) {
+ device_printf(dev, "Cannot get 'syscrg' index\n");
+ return (ENXIO);
+ }
+ sc->sys_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->sys_mem == NULL) {
+ device_printf(dev, "Cannot allocate 'syscrg'\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ err = ofw_bus_find_string_index(node, "reg-names", "stgcrg", &rid);
+ if (err != 0) {
+ device_printf(dev, "Cannot get 'stg' index\n");
+ return (ENXIO);
+ }
+ sc->stg_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->stg_mem == NULL) {
+ device_printf(dev, "Cannot allocate 'stgcrg'\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ err = ofw_bus_find_string_index(node, "reg-names", "aoncrg", &rid);
+ if (err != 0) {
+ device_printf(dev, "Cannot get 'aon' index\n");
+ return (ENXIO);
+ }
+ sc->aon_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->aon_mem == NULL) {
+ device_printf(dev, "Cannot allocate 'aoncrg'\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ err = ofw_bus_find_string_index(node, "reg-names", "ispcrg", &rid);
+ if (err != 0) {
+ device_printf(dev, "Cannot get 'isp' index\n");
+ return (ENXIO);
+ }
+ sc->isp_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->isp_mem == NULL) {
+ device_printf(dev, "Cannot allocate 'isp'\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ err = ofw_bus_find_string_index(node, "reg-names", "voutcrg", &rid);
+ if (err != 0) {
+ device_printf(dev, "Cannot get 'vout' index\n");
+ return (ENXIO);
+ }
+ sc->vout_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->vout_mem == NULL) {
+ device_printf(dev, "Cannot allocate 'vout'\n");
+ return (ENXIO);
+ }
+
+ mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
+
+ hwreset_register_ofw_provider(dev);
+
+ return (0);
+}
+
+static device_method_t jh7110_reset_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, jh7110_reset_probe),
+ DEVMETHOD(device_attach, jh7110_reset_attach),
+
+ /* Reset interface */
+ DEVMETHOD(hwreset_assert, jh7110_reset_assert),
+ DEVMETHOD(hwreset_is_asserted, jh7110_reset_is_asserted),
+
+ DEVMETHOD_END
+};
+
+static driver_t jh7110_reset_driver = {
+ "jh7110_reset",
+ jh7110_reset_methods,
+ sizeof(struct jh7110_reset_softc),
+};
+
+EARLY_DRIVER_MODULE(jh7110_reset, simplebus, jh7110_reset_driver, 0, 0,
+ BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
+MODULE_VERSION(jh7110_reset, 1);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 1:37 PM (10 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28584929
Default Alt Text
D43034.id131454.diff (87 KB)
Attached To
Mode
D43034: jh7110_gpio: Add StarFive JH7110 GPIO controller driver
Attached
Detach File
Event Timeline
Log In to Comment