From 3276931a92b67f10d240a937a756751f79486b6f Mon Sep 17 00:00:00 2001 From: visa Date: Wed, 5 Jan 2022 03:32:43 +0000 Subject: [PATCH] Add mpfclock(4), a driver for the PolarFire SoC MSS clock controller. OK kettenis@ --- share/man/man4/man4.riscv64/Makefile | 4 +- share/man/man4/man4.riscv64/mpfclock.4 | 37 ++++ sys/arch/riscv64/conf/GENERIC | 5 +- sys/arch/riscv64/conf/RAMDISK | 5 +- sys/arch/riscv64/conf/files.riscv64 | 7 +- sys/arch/riscv64/dev/mpfclock.c | 235 +++++++++++++++++++++++++ 6 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 share/man/man4/man4.riscv64/mpfclock.4 create mode 100644 sys/arch/riscv64/dev/mpfclock.c diff --git a/share/man/man4/man4.riscv64/Makefile b/share/man/man4/man4.riscv64/Makefile index c31e52f415b..058e3cbe11c 100644 --- a/share/man/man4/man4.riscv64/Makefile +++ b/share/man/man4/man4.riscv64/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.3 2021/08/06 06:35:13 jsg Exp $ +# $OpenBSD: Makefile,v 1.4 2022/01/05 03:32:43 visa Exp $ -MAN= intro.4 plic.4 sfcc.4 sfclock.4 sfuart.4 +MAN= intro.4 mpfclock.4 plic.4 sfcc.4 sfclock.4 sfuart.4 MANSUBDIR=riscv64 diff --git a/share/man/man4/man4.riscv64/mpfclock.4 b/share/man/man4/man4.riscv64/mpfclock.4 new file mode 100644 index 00000000000..d750c940d02 --- /dev/null +++ b/share/man/man4/man4.riscv64/mpfclock.4 @@ -0,0 +1,37 @@ +.\" $OpenBSD: mpfclock.4,v 1.1 2022/01/05 03:32:43 visa Exp $ +.\" +.\" Copyright (c) 2022 Visa Hankala +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: January 5 2022 $ +.Dt MPFCLOCK 4 riscv64 +.Os +.Sh NAME +.Nm mpfclock +.Nd Microchip PolarFire SoC MSS clock controller +.Sh SYNOPSIS +.Cd "mpfclock* at fdt?" +.Sh DESCRIPTION +The +.Nm +driver controls the clock signals for the integrated components +of PolarFire SoCs. +The driver also provides system reset functionality. +.Sh SEE ALSO +.Xr intro 4 +.Sh HISTORY +The +.Nm +driver first appeared in +.Ox 7.1 . diff --git a/sys/arch/riscv64/conf/GENERIC b/sys/arch/riscv64/conf/GENERIC index 4c7e21926e7..3024748578e 100644 --- a/sys/arch/riscv64/conf/GENERIC +++ b/sys/arch/riscv64/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.31 2022/01/03 15:50:16 visa Exp $ +# $OpenBSD: GENERIC,v 1.32 2022/01/05 03:32:44 visa Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -44,6 +44,9 @@ intc0 at cpu0 # NS16550 compatible serial ports com* at fdt? +# PolarFire SoCs +mpfclock* at fdt? early 1 + # SiFive SoCs sfclock* at fdt? early 1 # PRCI sfcc* at fdt? early 1 # L2 Cache Controller diff --git a/sys/arch/riscv64/conf/RAMDISK b/sys/arch/riscv64/conf/RAMDISK index 3c85f6f4a97..74993f13161 100644 --- a/sys/arch/riscv64/conf/RAMDISK +++ b/sys/arch/riscv64/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.27 2022/01/03 15:50:16 visa Exp $ +# $OpenBSD: RAMDISK,v 1.28 2022/01/05 03:32:44 visa Exp $ machine riscv64 maxusers 4 @@ -35,6 +35,9 @@ intc0 at cpu0 # NS16550 compatible serial ports com* at fdt? +# PolarFire SoCs +mpfclock* at fdt? early 1 + # SiFive SoCs sfclock* at fdt? early 1 # PRCI sfcc* at fdt? early 1 # L2 Cache Controller diff --git a/sys/arch/riscv64/conf/files.riscv64 b/sys/arch/riscv64/conf/files.riscv64 index 998c313677a..819892c7100 100644 --- a/sys/arch/riscv64/conf/files.riscv64 +++ b/sys/arch/riscv64/conf/files.riscv64 @@ -1,4 +1,4 @@ -# $OpenBSD: files.riscv64,v 1.17 2021/10/05 18:32:27 deraadt Exp $ +# $OpenBSD: files.riscv64,v 1.18 2022/01/05 03:32:44 visa Exp $ # Standard stanzas config(8) can't run without maxpartitions 16 @@ -84,6 +84,11 @@ device plic attach plic at fdt file arch/riscv64/dev/plic.c plic +# PolarFire SoC MSS clock controller +device mpfclock +attach mpfclock at fdt +file arch/riscv64/dev/mpfclock.c mpfclock + # L2 cache controller device sfcc attach sfcc at fdt diff --git a/sys/arch/riscv64/dev/mpfclock.c b/sys/arch/riscv64/dev/mpfclock.c new file mode 100644 index 00000000000..7b39405941b --- /dev/null +++ b/sys/arch/riscv64/dev/mpfclock.c @@ -0,0 +1,235 @@ +/* $OpenBSD: mpfclock.c,v 1.1 2022/01/05 03:32:44 visa Exp $ */ + +/* + * Copyright (c) 2022 Visa Hankala + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Driver for PolarFire SoC MSS clock controller. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +extern void (*cpuresetfn)(void); + +#define CLOCK_CONFIG_CR 0x0008 +#define CLOCK_CONFIG_CR_AHB_DIV_SHIFT 4 +#define CLOCK_CONFIG_CR_AXI_DIV_SHIFT 2 +#define CLOCK_CONFIG_CR_CPU_DIV_SHIFT 0 +#define CLOCK_CONFIG_CR_DIV_MASK 0x3 +#define MSS_RESET_CR 0x0018 +#define SUBBLK_CLOCK_CR 0x0084 +#define SUBBLK_RESET_CR 0x0088 + +#define CLK_CPU 0 +#define CLK_AXI 1 +#define CLK_AHB 2 +#define CLK_ENVM 3 +#define CLK_MAC0 4 +#define CLK_MAC1 5 +#define CLK_MMC 6 +#define CLK_TIMER 7 +#define CLK_MMUART0 8 +#define CLK_MMUART1 9 +#define CLK_MMUART2 10 +#define CLK_MMUART3 11 +#define CLK_MMUART4 12 +#define CLK_SPI0 13 +#define CLK_SPI1 14 +#define CLK_I2C0 15 +#define CLK_I2C1 16 +#define CLK_CAN0 17 +#define CLK_CAN1 18 +#define CLK_USB 19 +#define CLK_RESERVED 20 /* FPGA in SUBBLK_RESET_CR */ +#define CLK_RTC 21 +#define CLK_QSPI 22 +#define CLK_GPIO0 23 +#define CLK_GPIO1 24 +#define CLK_GPIO2 25 +#define CLK_DDRC 26 +#define CLK_FIC0 27 +#define CLK_FIC1 28 +#define CLK_FIC2 29 +#define CLK_FIC3 30 +#define CLK_ATHENA 31 +#define CLK_CFM 32 + +struct mpfclock_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + uint32_t sc_clkcfg; + uint32_t sc_refclk; + + struct clock_device sc_cd; +}; + +#define HREAD4(sc, reg) \ + (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg))) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val)) + +int mpfclock_match(struct device *, void *, void *); +void mpfclock_attach(struct device *, struct device *, void *); + +void mpfclock_enable(void *, uint32_t *, int); +uint32_t mpfclock_get_frequency(void *, uint32_t *); +int mpfclock_set_frequency(void *, uint32_t *, uint32_t); + +void mpfclock_cpureset(void); + +const struct cfattach mpfclock_ca = { + sizeof(struct mpfclock_softc), mpfclock_match, mpfclock_attach +}; + +struct cfdriver mpfclock_cd = { + NULL, "mpfclock", DV_DULL +}; + +struct mutex mpfclock_mtx = MUTEX_INITIALIZER(IPL_HIGH); +struct mpfclock_softc *mpfclock_sc; + +int +mpfclock_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + if (faa->fa_nreg < 1) + return 0; + return OF_is_compatible(faa->fa_node, "microchip,mpfs-clkcfg"); +} + +void +mpfclock_attach(struct device *parent, struct device *self, void *aux) +{ + struct fdt_attach_args *faa = aux; + struct mpfclock_softc *sc = (struct mpfclock_softc *)self; + + sc->sc_refclk = clock_get_frequency_idx(faa->fa_node, 0); + if (sc->sc_refclk == 0) { + printf(": can't get refclk frequency\n"); + return; + } + + sc->sc_iot = faa->fa_iot; + if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sc->sc_ioh) != 0) { + printf(": can't map registers\n"); + return; + } + + sc->sc_clkcfg = HREAD4(sc, CLOCK_CONFIG_CR); + + printf(": %u MHz ref clock\n", (sc->sc_refclk + 500000) / 1000000); + + sc->sc_cd.cd_node = faa->fa_node; + sc->sc_cd.cd_cookie = sc; + sc->sc_cd.cd_enable = mpfclock_enable; + sc->sc_cd.cd_get_frequency = mpfclock_get_frequency; + sc->sc_cd.cd_set_frequency = mpfclock_set_frequency; + clock_register(&sc->sc_cd); + + mpfclock_sc = sc; + cpuresetfn = mpfclock_cpureset; +} + +uint32_t +mpfclock_get_frequency(void *cookie, uint32_t *cells) +{ + struct mpfclock_softc *sc = cookie; + uint32_t div, shift; + uint32_t idx = cells[0]; + + if (idx == CLK_MMC) + return 200000000; + + if (idx > CLK_AHB) + idx = CLK_AHB; + + switch (idx) { + case CLK_CPU: + shift = CLOCK_CONFIG_CR_CPU_DIV_SHIFT; + break; + case CLK_AXI: + shift = CLOCK_CONFIG_CR_AXI_DIV_SHIFT; + break; + case CLK_AHB: + shift = CLOCK_CONFIG_CR_AHB_DIV_SHIFT; + break; + default: + panic("%s: invalid idx %u\n", __func__, idx); + } + + div = 1U << ((sc->sc_clkcfg >> shift) & CLOCK_CONFIG_CR_DIV_MASK); + + return sc->sc_refclk / div; +} + +int +mpfclock_set_frequency(void *cookie, uint32_t *cells, uint32_t freq) +{ + return -1; +} + +void +mpfclock_enable(void *cookie, uint32_t *cells, int on) +{ + struct mpfclock_softc *sc = cookie; + uint32_t idx = cells[0]; + uint32_t bit, val; + + if (idx < CLK_ENVM || idx - CLK_ENVM > 31) + return; + bit = 1U << (idx - CLK_ENVM); + + mtx_enter(&mpfclock_mtx); + if (on) { + val = HREAD4(sc, SUBBLK_CLOCK_CR); + val |= bit; + HWRITE4(sc, SUBBLK_CLOCK_CR, val); + + val = HREAD4(sc, SUBBLK_RESET_CR); + val &= ~bit; + HWRITE4(sc, SUBBLK_RESET_CR, val); + } else { + val = HREAD4(sc, SUBBLK_RESET_CR); + val |= bit; + HWRITE4(sc, SUBBLK_RESET_CR, val); + + val = HREAD4(sc, SUBBLK_CLOCK_CR); + val &= ~bit; + HWRITE4(sc, SUBBLK_CLOCK_CR, val); + } + mtx_leave(&mpfclock_mtx); +} + +void +mpfclock_cpureset(void) +{ + struct mpfclock_softc *sc = mpfclock_sc; + + HWRITE4(sc, MSS_RESET_CR, 0xdead); +} -- 2.20.1