On Mon, Jan 03, 2022 at 08:44:22PM +0100, Mark Kettenis wrote:
> > Date: Mon, 3 Jan 2022 16:31:29 +0000
> > From: Visa Hankala <v...@hankala.org>
> > 
> > This adds an initial driver for the PolarFire SoC MSS clock controller.
> > 
> > The driver also provides a reset function for the SoC. The soft reset
> > register is in the same region that covers the clock control registers.
> > 
> > OK?
> 
> None of the other clock drivers use a mutex to protect themselves from
> multiple clients simultanously enabling/disabling clocks.  And I don't
> really see the need for that in the foreseeable future.

I think it is wiser to keep the mutex in case some driver will toggle
clocks at runtime. Handling the serialization within the driver is less
prone to errors. Only the clock driver knows that the state updates
have to go through common registers.

> Other than that:
> 
> ok kettenis@
> 
> > Index: share/man/man4/man4.riscv64/Makefile
> > ===================================================================
> > RCS file: src/share/man/man4/man4.riscv64/Makefile,v
> > retrieving revision 1.3
> > diff -u -p -r1.3 Makefile
> > --- share/man/man4/man4.riscv64/Makefile    6 Aug 2021 06:35:13 -0000       
> > 1.3
> > +++ share/man/man4/man4.riscv64/Makefile    3 Jan 2022 16:26:48 -0000
> > @@ -1,6 +1,6 @@
> >  #  $OpenBSD: Makefile,v 1.3 2021/08/06 06:35:13 jsg 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
> >  
> > Index: share/man/man4/man4.riscv64/mpfclock.4
> > ===================================================================
> > RCS file: share/man/man4/man4.riscv64/mpfclock.4
> > diff -N share/man/man4/man4.riscv64/mpfclock.4
> > --- /dev/null       1 Jan 1970 00:00:00 -0000
> > +++ share/man/man4/man4.riscv64/mpfclock.4  3 Jan 2022 16:26:48 -0000
> > @@ -0,0 +1,37 @@
> > +.\"        $OpenBSD$
> > +.\"
> > +.\" 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$
> > +.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 .
> > Index: sys/arch/riscv64/conf/GENERIC
> > ===================================================================
> > RCS file: src/sys/arch/riscv64/conf/GENERIC,v
> > retrieving revision 1.31
> > diff -u -p -r1.31 GENERIC
> > --- sys/arch/riscv64/conf/GENERIC   3 Jan 2022 15:50:16 -0000       1.31
> > +++ sys/arch/riscv64/conf/GENERIC   3 Jan 2022 16:26:48 -0000
> > @@ -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
> > Index: sys/arch/riscv64/conf/RAMDISK
> > ===================================================================
> > RCS file: src/sys/arch/riscv64/conf/RAMDISK,v
> > retrieving revision 1.27
> > diff -u -p -r1.27 RAMDISK
> > --- sys/arch/riscv64/conf/RAMDISK   3 Jan 2022 15:50:16 -0000       1.27
> > +++ sys/arch/riscv64/conf/RAMDISK   3 Jan 2022 16:26:48 -0000
> > @@ -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
> > Index: sys/arch/riscv64/conf/files.riscv64
> > ===================================================================
> > RCS file: src/sys/arch/riscv64/conf/files.riscv64,v
> > retrieving revision 1.17
> > diff -u -p -r1.17 files.riscv64
> > --- sys/arch/riscv64/conf/files.riscv64     5 Oct 2021 18:32:27 -0000       
> > 1.17
> > +++ sys/arch/riscv64/conf/files.riscv64     3 Jan 2022 16:26:48 -0000
> > @@ -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
> > Index: sys/arch/riscv64/dev/mpfclock.c
> > ===================================================================
> > RCS file: sys/arch/riscv64/dev/mpfclock.c
> > diff -N sys/arch/riscv64/dev/mpfclock.c
> > --- /dev/null       1 Jan 1970 00:00:00 -0000
> > +++ sys/arch/riscv64/dev/mpfclock.c 3 Jan 2022 16:26:48 -0000
> > @@ -0,0 +1,235 @@
> > +/* $OpenBSD$       */
> > +
> > +/*
> > + * 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 <sys/param.h>
> > +#include <sys/systm.h>
> > +#include <sys/device.h>
> > +#include <sys/mutex.h>
> > +
> > +#include <machine/bus.h>
> > +#include <machine/fdt.h>
> > +
> > +#include <dev/ofw/fdt.h>
> > +#include <dev/ofw/openfirm.h>
> > +#include <dev/ofw/ofw_clock.h>
> > +
> > +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);
> > +}
> > 
> > 
> 

Reply via email to