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>
This commit is contained in:
Hao Wu 2021-03-11 10:08:54 -08:00 committed by Peter Maydell
parent fc11115f74
commit a9d3d7b17e
2 changed files with 109 additions and 1 deletions

View File

@ -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);
}

View File

@ -18,6 +18,7 @@
#include "hw/boards.h"
#include "hw/adc/npcm7xx_adc.h"
#include "hw/core/split-irq.h"
#include "hw/cpu/a9mpcore.h"
#include "hw/gpio/npcm7xx_gpio.h"
#include "hw/i2c/npcm7xx_smbus.h"
@ -48,8 +49,16 @@
#define NPCM7XX_GIC_CPU_IF_ADDR (0xf03fe100) /* GIC within A9 */
#define NPCM7XX_BOARD_SETUP_ADDR (0xffff1000) /* Boot ROM */
#define NPCM7XX_NR_PWM_MODULES 2
typedef struct NPCM7xxMachine {
MachineState parent;
/*
* PWM fan splitter. each splitter connects to one PWM output and
* multiple MFT inputs.
*/
SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
NPCM7XX_PWM_PER_MODULE];
} NPCM7xxMachine;
#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
@ -82,7 +91,7 @@ typedef struct NPCM7xxState {
NPCM7xxCLKState clk;
NPCM7xxTimerCtrlState tim[3];
NPCM7xxADCState adc;
NPCM7xxPWMState pwm[2];
NPCM7xxPWMState pwm[NPCM7XX_NR_PWM_MODULES];
NPCM7xxMFTState mft[8];
NPCM7xxOTPState key_storage;
NPCM7xxOTPState fuse_array;