summary refs log tree commit diff stats
path: root/include/hw/misc
diff options
context:
space:
mode:
Diffstat (limited to 'include/hw/misc')
-rw-r--r--include/hw/misc/npcm7xx_clk.h146
-rw-r--r--include/hw/misc/npcm7xx_pwm.h105
2 files changed, 243 insertions, 8 deletions
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
index 2338fbbdb5..d5c8d16ca4 100644
--- a/include/hw/misc/npcm7xx_clk.h
+++ b/include/hw/misc/npcm7xx_clk.h
@@ -17,15 +17,10 @@
 #define NPCM7XX_CLK_H
 
 #include "exec/memory.h"
+#include "hw/clock.h"
 #include "hw/sysbus.h"
 
 /*
- * The reference clock frequency for the timer modules, and the SECCNT and
- * CNTR25M registers in this module, is always 25 MHz.
- */
-#define NPCM7XX_TIMER_REF_HZ            (25000000)
-
-/*
  * Number of registers in our device state structure. Don't change this without
  * incrementing the version_id in the vmstate.
  */
@@ -33,16 +28,151 @@
 
 #define NPCM7XX_WATCHDOG_RESET_GPIO_IN "npcm7xx-clk-watchdog-reset-gpio-in"
 
-typedef struct NPCM7xxCLKState {
+/* Maximum amount of clock inputs in a SEL module. */
+#define NPCM7XX_CLK_SEL_MAX_INPUT 5
+
+/* PLLs in CLK module. */
+typedef enum NPCM7xxClockPLL {
+    NPCM7XX_CLOCK_PLL0,
+    NPCM7XX_CLOCK_PLL1,
+    NPCM7XX_CLOCK_PLL2,
+    NPCM7XX_CLOCK_PLLG,
+    NPCM7XX_CLOCK_NR_PLLS,
+} NPCM7xxClockPLL;
+
+/* SEL/MUX in CLK module. */
+typedef enum NPCM7xxClockSEL {
+    NPCM7XX_CLOCK_PIXCKSEL,
+    NPCM7XX_CLOCK_MCCKSEL,
+    NPCM7XX_CLOCK_CPUCKSEL,
+    NPCM7XX_CLOCK_CLKOUTSEL,
+    NPCM7XX_CLOCK_UARTCKSEL,
+    NPCM7XX_CLOCK_TIMCKSEL,
+    NPCM7XX_CLOCK_SDCKSEL,
+    NPCM7XX_CLOCK_GFXMSEL,
+    NPCM7XX_CLOCK_SUCKSEL,
+    NPCM7XX_CLOCK_NR_SELS,
+} NPCM7xxClockSEL;
+
+/* Dividers in CLK module. */
+typedef enum NPCM7xxClockDivider {
+    NPCM7XX_CLOCK_PLL1D2, /* PLL1/2 */
+    NPCM7XX_CLOCK_PLL2D2, /* PLL2/2 */
+    NPCM7XX_CLOCK_MC_DIVIDER,
+    NPCM7XX_CLOCK_AXI_DIVIDER,
+    NPCM7XX_CLOCK_AHB_DIVIDER,
+    NPCM7XX_CLOCK_AHB3_DIVIDER,
+    NPCM7XX_CLOCK_SPI0_DIVIDER,
+    NPCM7XX_CLOCK_SPIX_DIVIDER,
+    NPCM7XX_CLOCK_APB1_DIVIDER,
+    NPCM7XX_CLOCK_APB2_DIVIDER,
+    NPCM7XX_CLOCK_APB3_DIVIDER,
+    NPCM7XX_CLOCK_APB4_DIVIDER,
+    NPCM7XX_CLOCK_APB5_DIVIDER,
+    NPCM7XX_CLOCK_CLKOUT_DIVIDER,
+    NPCM7XX_CLOCK_UART_DIVIDER,
+    NPCM7XX_CLOCK_TIMER_DIVIDER,
+    NPCM7XX_CLOCK_ADC_DIVIDER,
+    NPCM7XX_CLOCK_MMC_DIVIDER,
+    NPCM7XX_CLOCK_SDHC_DIVIDER,
+    NPCM7XX_CLOCK_GFXM_DIVIDER, /* divide by 3 */
+    NPCM7XX_CLOCK_UTMI_DIVIDER,
+    NPCM7XX_CLOCK_NR_DIVIDERS,
+} NPCM7xxClockConverter;
+
+typedef struct NPCM7xxCLKState NPCM7xxCLKState;
+
+/**
+ * struct NPCM7xxClockPLLState - A PLL module in CLK module.
+ * @name: The name of the module.
+ * @clk: The CLK module that owns this module.
+ * @clock_in: The input clock of this module.
+ * @clock_out: The output clock of this module.
+ * @reg: The control registers for this PLL module.
+ */
+typedef struct NPCM7xxClockPLLState {
+    DeviceState parent;
+
+    const char *name;
+    NPCM7xxCLKState *clk;
+    Clock *clock_in;
+    Clock *clock_out;
+
+    int reg;
+} NPCM7xxClockPLLState;
+
+/**
+ * struct NPCM7xxClockSELState - A SEL module in CLK module.
+ * @name: The name of the module.
+ * @clk: The CLK module that owns this module.
+ * @input_size: The size of inputs of this module.
+ * @clock_in: The input clocks of this module.
+ * @clock_out: The output clocks of this module.
+ * @offset: The offset of this module in the control register.
+ * @len: The length of this module in the control register.
+ */
+typedef struct NPCM7xxClockSELState {
+    DeviceState parent;
+
+    const char *name;
+    NPCM7xxCLKState *clk;
+    uint8_t input_size;
+    Clock *clock_in[NPCM7XX_CLK_SEL_MAX_INPUT];
+    Clock *clock_out;
+
+    int offset;
+    int len;
+} NPCM7xxClockSELState;
+
+/**
+ * struct NPCM7xxClockDividerState - A Divider module in CLK module.
+ * @name: The name of the module.
+ * @clk: The CLK module that owns this module.
+ * @clock_in: The input clock of this module.
+ * @clock_out: The output clock of this module.
+ * @divide: The function the divider uses to divide the input.
+ * @reg: The index of the control register that contains the divisor.
+ * @offset: The offset of the divisor in the control register.
+ * @len: The length of the divisor in the control register.
+ * @divisor: The divisor for a constant divisor
+ */
+typedef struct NPCM7xxClockDividerState {
+    DeviceState parent;
+
+    const char *name;
+    NPCM7xxCLKState *clk;
+    Clock *clock_in;
+    Clock *clock_out;
+
+    uint32_t (*divide)(struct NPCM7xxClockDividerState *s);
+    union {
+        struct {
+            int reg;
+            int offset;
+            int len;
+        };
+        int divisor;
+    };
+} NPCM7xxClockDividerState;
+
+struct NPCM7xxCLKState {
     SysBusDevice parent;
 
     MemoryRegion iomem;
 
+    /* Clock converters */
+    NPCM7xxClockPLLState plls[NPCM7XX_CLOCK_NR_PLLS];
+    NPCM7xxClockSELState sels[NPCM7XX_CLOCK_NR_SELS];
+    NPCM7xxClockDividerState dividers[NPCM7XX_CLOCK_NR_DIVIDERS];
+
     uint32_t regs[NPCM7XX_CLK_NR_REGS];
 
     /* Time reference for SECCNT and CNTR25M, initialized by power on reset */
     int64_t ref_ns;
-} NPCM7xxCLKState;
+
+    /* The incoming reference clock. */
+    Clock *clkref;
+};
 
 #define TYPE_NPCM7XX_CLK "npcm7xx-clk"
 #define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
new file mode 100644
index 0000000000..5a689d3f66
--- /dev/null
+++ b/include/hw/misc/npcm7xx_pwm.h
@@ -0,0 +1,105 @@
+/*
+ * Nuvoton NPCM7xx PWM Module
+ *
+ * Copyright 2020 Google LLC
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef NPCM7XX_PWM_H
+#define NPCM7XX_PWM_H
+
+#include "hw/clock.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+
+/* Each PWM module holds 4 PWM channels. */
+#define NPCM7XX_PWM_PER_MODULE 4
+
+/*
+ * Number of registers in one pwm module. Don't change this without increasing
+ * the version_id in vmstate.
+ */
+#define NPCM7XX_PWM_NR_REGS (0x54 / sizeof(uint32_t))
+
+/*
+ * The maximum duty values. Each duty unit represents 1/NPCM7XX_PWM_MAX_DUTY
+ * cycles. For example, if NPCM7XX_PWM_MAX_DUTY=1,000,000 and a PWM has a duty
+ * value of 100,000 the duty cycle for that PWM is 10%.
+ */
+#define NPCM7XX_PWM_MAX_DUTY 1000000
+
+typedef struct NPCM7xxPWMState NPCM7xxPWMState;
+
+/**
+ * struct NPCM7xxPWM - The state of a single PWM channel.
+ * @module: The PWM module that contains this channel.
+ * @irq: GIC interrupt line to fire on expiration if enabled.
+ * @running: Whether this PWM channel is generating output.
+ * @inverted: Whether this PWM channel is inverted.
+ * @index: The index of this PWM channel.
+ * @cnr: The counter register.
+ * @cmr: The comparator register.
+ * @pdr: The data register.
+ * @pwdr: The watchdog register.
+ * @freq: The frequency of this PWM channel.
+ * @duty: The duty cycle of this PWM channel. One unit represents
+ *   1/NPCM7XX_MAX_DUTY cycles.
+ */
+typedef struct NPCM7xxPWM {
+    NPCM7xxPWMState         *module;
+
+    qemu_irq                irq;
+
+    bool                    running;
+    bool                    inverted;
+
+    uint8_t                 index;
+    uint32_t                cnr;
+    uint32_t                cmr;
+    uint32_t                pdr;
+    uint32_t                pwdr;
+
+    uint32_t                freq;
+    uint32_t                duty;
+} NPCM7xxPWM;
+
+/**
+ * struct NPCM7xxPWMState - Pulse Width Modulation device state.
+ * @parent: System bus device.
+ * @iomem: Memory region through which registers are accessed.
+ * @clock: The PWM clock.
+ * @pwm: The PWM channels owned by this module.
+ * @ppr: The prescaler register.
+ * @csr: The clock selector register.
+ * @pcr: The control register.
+ * @pier: The interrupt enable register.
+ * @piir: The interrupt indication register.
+ */
+struct NPCM7xxPWMState {
+    SysBusDevice parent;
+
+    MemoryRegion iomem;
+
+    Clock       *clock;
+    NPCM7xxPWM pwm[NPCM7XX_PWM_PER_MODULE];
+
+    uint32_t    ppr;
+    uint32_t    csr;
+    uint32_t    pcr;
+    uint32_t    pier;
+    uint32_t    piir;
+};
+
+#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
+#define NPCM7XX_PWM(obj) \
+    OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
+
+#endif /* NPCM7XX_PWM_H */