siemens/nc_fpga: Add driver for Siemens NC FPGA
Add driver code to initialize Siemens NC FPGA as PCI device. Beside some glue logic it contains a FAN controller and temperature monitor. Change-Id: I2cb722a60081028ee5a8251f51125f12ed38d824 Signed-off-by: Werner Zeh <werner.zeh@siemens.com> Reviewed-on: https://review.coreboot.org/15543 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
This commit is contained in:
parent
9007ffd3d1
commit
6c571462e5
|
@ -0,0 +1,3 @@
|
||||||
|
config DRIVER_SIEMENS_NC_FPGA
|
||||||
|
bool
|
||||||
|
default n
|
|
@ -0,0 +1,16 @@
|
||||||
|
##
|
||||||
|
## This file is part of the coreboot project.
|
||||||
|
##
|
||||||
|
## Copyright 2016 Siemens AG
|
||||||
|
##
|
||||||
|
## 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; version 2 of the License.
|
||||||
|
##
|
||||||
|
## 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
ramstage-$(CONFIG_DRIVER_SIEMENS_NC_FPGA) += nc_fpga.c
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Siemens AG.
|
||||||
|
*
|
||||||
|
* 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; version 2 of the License.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <device/pci.h>
|
||||||
|
#include <device/pci_ids.h>
|
||||||
|
#include <device/pci_ops.h>
|
||||||
|
#include <device/pci_def.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <delay.h>
|
||||||
|
#include <hwilib.h>
|
||||||
|
#include "nc_fpga.h"
|
||||||
|
|
||||||
|
#define FPGA_SET_PARAM(src, dst) \
|
||||||
|
{ \
|
||||||
|
typeof(dst) var; \
|
||||||
|
size_t len = sizeof(var); \
|
||||||
|
if (hwilib_get_field(src, (uint8_t *)&var, len) == len) \
|
||||||
|
dst = (typeof(dst))(var); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_temp_mon (void *base_adr)
|
||||||
|
{
|
||||||
|
uint32_t cc[5], i = 0;
|
||||||
|
uint8_t num = 0;
|
||||||
|
volatile fan_ctrl_t *ctrl = (fan_ctrl_t *)base_adr;
|
||||||
|
|
||||||
|
/* Program sensor delay first. */
|
||||||
|
FPGA_SET_PARAM(FANSensorDelay, ctrl->sensordelay);
|
||||||
|
/* Program correction curve for every used sensor. */
|
||||||
|
if (hwilib_get_field(FANSensorNum, &num, sizeof(num) != sizeof(num)) ||
|
||||||
|
(num == 0) || (num > MAX_NUM_SENSORS))
|
||||||
|
return;
|
||||||
|
for (i = 0; i < num; i ++) {
|
||||||
|
if (hwilib_get_field(FANSensorCfg0 + i, (uint8_t *)&cc[0],
|
||||||
|
sizeof(cc)) == sizeof(cc)) {
|
||||||
|
ctrl->sensorcfg[cc[0]].rmin = cc[1] & 0xffff;
|
||||||
|
ctrl->sensorcfg[cc[0]].rmax = cc[2] & 0xffff;
|
||||||
|
ctrl->sensorcfg[cc[0]].nmin = cc[3] & 0xffff;
|
||||||
|
ctrl->sensorcfg[cc[0]].nmax = cc[4] & 0xffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctrl->sensornum = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_fan_ctrl (void *base_adr)
|
||||||
|
{
|
||||||
|
uint8_t mask = 0, freeze_mode = 0, fan_req = 0;
|
||||||
|
volatile fan_ctrl_t *ctrl = (fan_ctrl_t *)base_adr;
|
||||||
|
|
||||||
|
/* Program all needed fields of FAN controller. */
|
||||||
|
FPGA_SET_PARAM(FANSensorSelect, ctrl->sensorselect);
|
||||||
|
FPGA_SET_PARAM(T_Warn, ctrl->t_warn);
|
||||||
|
FPGA_SET_PARAM(T_Crit, ctrl->t_crit);
|
||||||
|
FPGA_SET_PARAM(FANSamplingTime, ctrl->samplingtime);
|
||||||
|
FPGA_SET_PARAM(FANSetPoint, ctrl->setpoint);
|
||||||
|
FPGA_SET_PARAM(FANHystCtrl, ctrl->hystctrl);
|
||||||
|
FPGA_SET_PARAM(FANHystVal, ctrl->hystval);
|
||||||
|
FPGA_SET_PARAM(FANHystThreshold, ctrl->hystthreshold);
|
||||||
|
FPGA_SET_PARAM(FANKp, ctrl->kp);
|
||||||
|
FPGA_SET_PARAM(FANKi, ctrl->ki);
|
||||||
|
FPGA_SET_PARAM(FANKd, ctrl->kd);
|
||||||
|
FPGA_SET_PARAM(FANMaxSpeed, ctrl->fanmax);
|
||||||
|
/* Set freeze and FAN configuration. */
|
||||||
|
if ((hwilib_get_field(FF_FanReq, &fan_req, 1) == 1) &&
|
||||||
|
(hwilib_get_field(FF_FreezeDis, &freeze_mode, 1) == 1)) {
|
||||||
|
if (!fan_req)
|
||||||
|
mask = 1;
|
||||||
|
else if (fan_req && freeze_mode)
|
||||||
|
mask = 2;
|
||||||
|
else
|
||||||
|
mask = 3;
|
||||||
|
ctrl->fanmon = mask << 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief This function is the driver entry point for the init phase
|
||||||
|
* of the PCI bus allocator. It will initialize all the needed parts
|
||||||
|
* of NC_FPGA.
|
||||||
|
* @param *dev Pointer to the used PCI device
|
||||||
|
* @return void Nothing is given back
|
||||||
|
*/
|
||||||
|
static void nc_fpga_init(struct device *dev)
|
||||||
|
{
|
||||||
|
void *bar0_ptr = NULL;
|
||||||
|
uint8_t cmd_reg;
|
||||||
|
uint32_t cap = 0;
|
||||||
|
|
||||||
|
/* All we need is mapped to BAR 0, get the address. */
|
||||||
|
bar0_ptr = (void *)(pci_read_config32(dev, PCI_BASE_ADDRESS_0) &
|
||||||
|
~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
|
||||||
|
cmd_reg = pci_read_config8(dev, PCI_COMMAND);
|
||||||
|
/* Ensure BAR0 has a valid value. */
|
||||||
|
if (!bar0_ptr || !(cmd_reg & PCI_COMMAND_MEMORY))
|
||||||
|
return;
|
||||||
|
/* Ensure this is really a NC FPGA by checking magic register. */
|
||||||
|
if (read32(bar0_ptr + NC_MAGIC_OFFSET) != NC_FPGA_MAGIC)
|
||||||
|
return;
|
||||||
|
/* Open hwinfo block. */
|
||||||
|
if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
|
||||||
|
return;
|
||||||
|
/* Set up FAN controller and temperature monitor according to */
|
||||||
|
/* capability bits. */
|
||||||
|
cap = read32(bar0_ptr + NC_CAP1_OFFSET);
|
||||||
|
if (cap & (NC_CAP1_TEMP_MON | NC_CAP1_FAN_CTRL))
|
||||||
|
init_temp_mon(bar0_ptr + NC_FANMON_CTRL_OFFSET);
|
||||||
|
if (cap & NC_CAP1_FAN_CTRL)
|
||||||
|
init_fan_ctrl(bar0_ptr + NC_FANMON_CTRL_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct device_operations nc_fpga_ops = {
|
||||||
|
.read_resources = pci_dev_read_resources,
|
||||||
|
.set_resources = pci_dev_set_resources,
|
||||||
|
.enable_resources = pci_dev_enable_resources,
|
||||||
|
.init = nc_fpga_init,
|
||||||
|
.scan_bus = 0,
|
||||||
|
.ops_pci = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned short nc_fpga_device_ids[] = { 0x4091, 0 };
|
||||||
|
|
||||||
|
static const struct pci_driver nc_fpga_driver __pci_driver = {
|
||||||
|
.ops = &nc_fpga_ops,
|
||||||
|
.vendor = 0x110A,
|
||||||
|
.devices = nc_fpga_device_ids,
|
||||||
|
};
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Siemens AG.
|
||||||
|
*
|
||||||
|
* 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; version 2 of the License.
|
||||||
|
*
|
||||||
|
* 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 _SIEMENS_NC_FPGA_H_
|
||||||
|
#define _SIEMENS_NC_FPGA_H_
|
||||||
|
|
||||||
|
#define NC_MAGIC_OFFSET 0x020
|
||||||
|
#define NC_FPGA_MAGIC 0x4E433746
|
||||||
|
#define NC_CAP1_OFFSET 0x080
|
||||||
|
#define NC_CAP1_FAN_CTRL 0x080
|
||||||
|
#define NC_CAP1_TEMP_MON 0x100
|
||||||
|
#define NC_FANMON_CTRL_OFFSET 0x400
|
||||||
|
|
||||||
|
#define MAX_NUM_SENSORS 4
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t rmin;
|
||||||
|
uint16_t rmax;
|
||||||
|
uint16_t nmin;
|
||||||
|
uint16_t nmax;
|
||||||
|
} temp_cc_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t res0;
|
||||||
|
uint8_t sensornum;
|
||||||
|
uint8_t res1;
|
||||||
|
uint32_t sensordelay;
|
||||||
|
uint32_t res2[4];
|
||||||
|
temp_cc_t sensorcfg[8];
|
||||||
|
uint32_t res3[4];
|
||||||
|
uint8_t sensorselect;
|
||||||
|
uint8_t res4[3];
|
||||||
|
uint16_t t_warn;
|
||||||
|
uint16_t t_crit;
|
||||||
|
uint16_t res5;
|
||||||
|
uint8_t res6[2];
|
||||||
|
uint32_t samplingtime;
|
||||||
|
uint16_t setpoint;
|
||||||
|
uint8_t hystctrl;
|
||||||
|
uint8_t res7;
|
||||||
|
uint16_t kp;
|
||||||
|
uint16_t ki;
|
||||||
|
uint16_t kd;
|
||||||
|
uint16_t res8[2];
|
||||||
|
uint16_t fanmax;
|
||||||
|
uint16_t hystval;
|
||||||
|
uint16_t hystthreshold;
|
||||||
|
uint16_t res9[4];
|
||||||
|
uint32_t fanmon;
|
||||||
|
} __attribute__ ((packed)) fan_ctrl_t;
|
||||||
|
|
||||||
|
#endif /* _SIEMENS_NC_FPGA_H_ */
|
Loading…
Reference in New Issue