From 6c571462e54f702b17737a344dcd3af0be21a294 Mon Sep 17 00:00:00 2001 From: Werner Zeh Date: Tue, 5 Jul 2016 07:16:34 +0200 Subject: [PATCH] siemens/nc_fpga: Add driver for Siemens NC FPGA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-on: https://review.coreboot.org/15543 Tested-by: build bot (Jenkins) Reviewed-by: Kyösti Mälkki --- src/drivers/siemens/nc_fpga/Kconfig | 3 + src/drivers/siemens/nc_fpga/Makefile.inc | 16 +++ src/drivers/siemens/nc_fpga/nc_fpga.c | 139 +++++++++++++++++++++++ src/drivers/siemens/nc_fpga/nc_fpga.h | 64 +++++++++++ 4 files changed, 222 insertions(+) create mode 100644 src/drivers/siemens/nc_fpga/Kconfig create mode 100644 src/drivers/siemens/nc_fpga/Makefile.inc create mode 100644 src/drivers/siemens/nc_fpga/nc_fpga.c create mode 100644 src/drivers/siemens/nc_fpga/nc_fpga.h diff --git a/src/drivers/siemens/nc_fpga/Kconfig b/src/drivers/siemens/nc_fpga/Kconfig new file mode 100644 index 0000000000..832446fcc2 --- /dev/null +++ b/src/drivers/siemens/nc_fpga/Kconfig @@ -0,0 +1,3 @@ +config DRIVER_SIEMENS_NC_FPGA + bool + default n diff --git a/src/drivers/siemens/nc_fpga/Makefile.inc b/src/drivers/siemens/nc_fpga/Makefile.inc new file mode 100644 index 0000000000..724ed6fdd1 --- /dev/null +++ b/src/drivers/siemens/nc_fpga/Makefile.inc @@ -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 diff --git a/src/drivers/siemens/nc_fpga/nc_fpga.c b/src/drivers/siemens/nc_fpga/nc_fpga.c new file mode 100644 index 0000000000..def456bbb6 --- /dev/null +++ b/src/drivers/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 +#include +#include +#include +#include +#include +#include +#include +#include +#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, +}; diff --git a/src/drivers/siemens/nc_fpga/nc_fpga.h b/src/drivers/siemens/nc_fpga/nc_fpga.h new file mode 100644 index 0000000000..886f3dda05 --- /dev/null +++ b/src/drivers/siemens/nc_fpga/nc_fpga.h @@ -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_ */