diff options
author | Hao Wu | 2021-03-11 19:08:54 +0100 |
---|---|---|
committer | Peter Maydell | 2021-03-12 13:50:36 +0100 |
commit | a9d3d7b17e5a3c246ecf4e420d2d4bb089a8d7c3 (patch) | |
tree | 381f44068835ea6639de67c10124e7f8316979a7 /hw/arm/npcm7xx_boards.c | |
parent | hw/arm: Add MFT device to NPCM7xx Soc (diff) | |
download | qemu-a9d3d7b17e5a3c246ecf4e420d2d4bb089a8d7c3.tar.gz qemu-a9d3d7b17e5a3c246ecf4e420d2d4bb089a8d7c3.tar.xz qemu-a9d3d7b17e5a3c246ecf4e420d2d4bb089a8d7c3.zip |
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/npcm7xx_boards.c')
-rw-r--r-- | hw/arm/npcm7xx_boards.c | 99 |
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); } |