aboutsummaryrefslogtreecommitdiff
path: root/hw/arm
diff options
context:
space:
mode:
authorHao Wu <wuhaotsh@google.com>2021-03-11 10:08:54 -0800
committerPeter Maydell <peter.maydell@linaro.org>2021-03-12 12:50:36 +0000
commita9d3d7b17e5a3c246ecf4e420d2d4bb089a8d7c3 (patch)
tree381f44068835ea6639de67c10124e7f8316979a7 /hw/arm
parentfc11115f74b4355b38eeebc118e347cd74f35845 (diff)
hw/arm: Connect PWM fans in NPCM7XX boards
This patch adds fan_splitters (split IRQs) in NPCM7XX boards. Each fan splitter corresponds to 1 PWM output and can connect to multiple fan inputs (MFT devices). In NPCM7XX boards(NPCM750 EVB and Quanta GSJ boards), we initializes these splitters and connect them to their corresponding modules according their specific device trees. Reviewed-by: Doug Evans <dje@google.com> Reviewed-by: Tyrone Ting <kfting@nuvoton.com> Signed-off-by: Hao Wu <wuhaotsh@google.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 20210311180855.149764-5-wuhaotsh@google.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm')
-rw-r--r--hw/arm/npcm7xx_boards.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
index fbf6ce8e02..e22fe4bf8f 100644
--- a/hw/arm/npcm7xx_boards.c
+++ b/hw/arm/npcm7xx_boards.c
@@ -21,6 +21,7 @@
#include "hw/core/cpu.h"
#include "hw/i2c/smbus_eeprom.h"
#include "hw/loader.h"
+#include "hw/qdev-core.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu-common.h"
@@ -116,6 +117,64 @@ static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
}
+static void npcm7xx_init_pwm_splitter(NPCM7xxMachine *machine,
+ NPCM7xxState *soc, const int *fan_counts)
+{
+ SplitIRQ *splitters = machine->fan_splitter;
+
+ /*
+ * PWM 0~3 belong to module 0 output 0~3.
+ * PWM 4~7 belong to module 1 output 0~3.
+ */
+ for (int i = 0; i < NPCM7XX_NR_PWM_MODULES; ++i) {
+ for (int j = 0; j < NPCM7XX_PWM_PER_MODULE; ++j) {
+ int splitter_no = i * NPCM7XX_PWM_PER_MODULE + j;
+ DeviceState *splitter;
+
+ if (fan_counts[splitter_no] < 1) {
+ continue;
+ }
+ object_initialize_child(OBJECT(machine), "fan-splitter[*]",
+ &splitters[splitter_no], TYPE_SPLIT_IRQ);
+ splitter = DEVICE(&splitters[splitter_no]);
+ qdev_prop_set_uint16(splitter, "num-lines",
+ fan_counts[splitter_no]);
+ qdev_realize(splitter, NULL, &error_abort);
+ qdev_connect_gpio_out_named(DEVICE(&soc->pwm[i]), "duty-gpio-out",
+ j, qdev_get_gpio_in(splitter, 0));
+ }
+ }
+}
+
+static void npcm7xx_connect_pwm_fan(NPCM7xxState *soc, SplitIRQ *splitter,
+ int fan_no, int output_no)
+{
+ DeviceState *fan;
+ int fan_input;
+ qemu_irq fan_duty_gpio;
+
+ g_assert(fan_no >= 0 && fan_no <= NPCM7XX_MFT_MAX_FAN_INPUT);
+ /*
+ * Fan 0~1 belong to module 0 input 0~1.
+ * Fan 2~3 belong to module 1 input 0~1.
+ * ...
+ * Fan 14~15 belong to module 7 input 0~1.
+ * Fan 16~17 belong to module 0 input 2~3.
+ * Fan 18~19 belong to module 1 input 2~3.
+ */
+ if (fan_no < 16) {
+ fan = DEVICE(&soc->mft[fan_no / 2]);
+ fan_input = fan_no % 2;
+ } else {
+ fan = DEVICE(&soc->mft[(fan_no - 16) / 2]);
+ fan_input = fan_no % 2 + 2;
+ }
+
+ /* Connect the Fan to PWM module */
+ fan_duty_gpio = qdev_get_gpio_in_named(fan, "duty", fan_input);
+ qdev_connect_gpio_out(DEVICE(splitter), output_no, fan_duty_gpio);
+}
+
static void npcm750_evb_i2c_init(NPCM7xxState *soc)
{
/* lm75 temperature sensor on SVB, tmp105 is compatible */
@@ -128,6 +187,30 @@ static void npcm750_evb_i2c_init(NPCM7xxState *soc)
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
}
+static void npcm750_evb_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
+{
+ SplitIRQ *splitter = machine->fan_splitter;
+ static const int fan_counts[] = {2, 2, 2, 2, 2, 2, 2, 2};
+
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x06, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[3], 0x07, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x08, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[4], 0x09, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0a, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[5], 0x0b, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0c, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[6], 0x0d, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0e, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[7], 0x0f, 1);
+}
+
static void quanta_gsj_i2c_init(NPCM7xxState *soc)
{
/* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. */
@@ -142,6 +225,20 @@ static void quanta_gsj_i2c_init(NPCM7xxState *soc)
/* TODO: Add additional i2c devices. */
}
+static void quanta_gsj_fan_init(NPCM7xxMachine *machine, NPCM7xxState *soc)
+{
+ SplitIRQ *splitter = machine->fan_splitter;
+ static const int fan_counts[] = {2, 2, 2, 0, 0, 0, 0, 0};
+
+ npcm7xx_init_pwm_splitter(machine, soc, fan_counts);
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x00, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[0], 0x01, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x02, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[1], 0x03, 1);
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x04, 0);
+ npcm7xx_connect_pwm_fan(soc, &splitter[2], 0x05, 1);
+}
+
static void npcm750_evb_init(MachineState *machine)
{
NPCM7xxState *soc;
@@ -153,6 +250,7 @@ static void npcm750_evb_init(MachineState *machine)
npcm7xx_load_bootrom(machine, soc);
npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
npcm750_evb_i2c_init(soc);
+ npcm750_evb_fan_init(NPCM7XX_MACHINE(machine), soc);
npcm7xx_load_kernel(machine, soc);
}
@@ -168,6 +266,7 @@ static void quanta_gsj_init(MachineState *machine)
npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
drive_get(IF_MTD, 0, 0));
quanta_gsj_i2c_init(soc);
+ quanta_gsj_fan_init(NPCM7XX_MACHINE(machine), soc);
npcm7xx_load_kernel(machine, soc);
}