lib/smbios: Improve Type9
[coreboot2.git] / src / drivers / siemens / nc_fpga / nc_fpga.c
blobe9b39bc925484164b446e36a605574d0f33d3b03
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <types.h>
4 #include <device/pci.h>
5 #include <device/pci_ids.h>
6 #include <device/pci_ops.h>
7 #include <device/mmio.h>
8 #include <hwilib.h>
9 #include <bootstate.h>
11 #include "nc_fpga.h"
13 static void *nc_fpga_bar0;
15 #define FPGA_SET_PARAM(src, dst) \
16 { \
17 uint32_t var; \
18 if (hwilib_get_field(src, (uint8_t *)&var, sizeof(var))) \
19 dst = ((typeof(dst))var); \
22 static void init_temp_mon(void *base_adr)
24 uint32_t cc[5], i = 0;
25 uint8_t num = 0;
26 volatile fan_ctrl_t *ctrl = (fan_ctrl_t *)base_adr;
28 /* Program sensor delay first. */
29 FPGA_SET_PARAM(FANSensorDelay, ctrl->sensordelay);
30 /* Program correction curve for every used sensor. */
31 if ((hwilib_get_field(FANSensorNum, &num, 1) != 1) ||
32 (num == 0) || (num > MAX_NUM_SENSORS))
33 return;
34 for (i = 0; i < num; i++) {
35 if (hwilib_get_field(FANSensorCfg0 + i, (uint8_t *)&cc[0],
36 sizeof(cc)) == sizeof(cc)) {
37 ctrl->sensorcfg[cc[0]].rmin = cc[1] & 0xffff;
38 ctrl->sensorcfg[cc[0]].rmax = cc[2] & 0xffff;
39 ctrl->sensorcfg[cc[0]].nmin = cc[3] & 0xffff;
40 ctrl->sensorcfg[cc[0]].nmax = cc[4] & 0xffff;
43 ctrl->sensornum = num;
45 /* Program sensor selection and temperature thresholds. */
46 FPGA_SET_PARAM(FANSensorSelect, ctrl->sensorselect);
47 FPGA_SET_PARAM(T_Warn, ctrl->t_warn);
48 FPGA_SET_PARAM(T_Crit, ctrl->t_crit);
51 static void init_fan_ctrl(void *base_adr)
53 uint8_t mask = 0, freeze_disable = 0, fan_req = 0;
54 volatile fan_ctrl_t *ctrl = (fan_ctrl_t *)base_adr;
56 /* Program all needed fields of FAN controller. */
57 FPGA_SET_PARAM(FANSamplingTime, ctrl->samplingtime);
58 FPGA_SET_PARAM(FANSetPoint, ctrl->setpoint);
59 FPGA_SET_PARAM(FANHystCtrl, ctrl->hystctrl);
60 FPGA_SET_PARAM(FANHystVal, ctrl->hystval);
61 FPGA_SET_PARAM(FANHystThreshold, ctrl->hystthreshold);
62 FPGA_SET_PARAM(FANKp, ctrl->kp);
63 FPGA_SET_PARAM(FANKi, ctrl->ki);
64 FPGA_SET_PARAM(FANKd, ctrl->kd);
65 FPGA_SET_PARAM(FANMaxSpeed, ctrl->fanmax);
66 FPGA_SET_PARAM(FANStartSpeed, ctrl->fanmin);
67 /* Set freeze and FAN configuration. */
68 if ((hwilib_get_field(FF_FanReq, &fan_req, 1) == 1) &&
69 (hwilib_get_field(FF_FreezeDis, &freeze_disable, 1) == 1)) {
70 if (!fan_req)
71 mask = 1;
72 else if (fan_req && !freeze_disable)
73 mask = 2;
74 else
75 mask = 3;
76 ctrl->fanmon = mask << 10;
80 /** \brief This function is the driver entry point for the init phase
81 * of the PCI bus allocator. It will initialize all the needed parts
82 * of NC_FPGA.
83 * @param *dev Pointer to the used PCI device
84 * @return void Nothing is given back
86 static void nc_fpga_init(struct device *dev)
88 void *bar0_ptr = NULL;
89 uint8_t cmd_reg;
90 uint32_t cap = 0;
92 /* All we need is mapped to BAR 0, get the address. */
93 bar0_ptr = (void *)(pci_read_config32(dev, PCI_BASE_ADDRESS_0) &
94 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK);
95 cmd_reg = pci_read_config8(dev, PCI_COMMAND);
96 /* Ensure BAR0 has a valid value. */
97 if (!bar0_ptr || !(cmd_reg & PCI_COMMAND_MEMORY))
98 return;
99 /* Ensure this is really a NC FPGA by checking magic register. */
100 if (read32(bar0_ptr + NC_MAGIC_OFFSET) != NC_FPGA_MAGIC)
101 return;
102 /* Save BAR0 address so that it can be used on all NC_FPGA devices to
103 set the FW_DONE bit before jumping to payload. */
104 nc_fpga_bar0 = bar0_ptr;
105 /* Open hwinfo block. */
106 if (hwilib_find_blocks("hwinfo.hex") != CB_SUCCESS)
107 return;
108 /* Set up FAN controller and temperature monitor according to */
109 /* capability bits. */
110 cap = read32(bar0_ptr + NC_CAP1_OFFSET);
111 if (cap & (NC_CAP1_TEMP_MON | NC_CAP1_FAN_CTRL))
112 init_temp_mon(bar0_ptr + NC_FANMON_CTRL_OFFSET);
113 if (cap & NC_CAP1_FAN_CTRL)
114 init_fan_ctrl(bar0_ptr + NC_FANMON_CTRL_OFFSET);
115 if (cap & NC_CAP1_DSAVE_NMI_DELAY) {
116 uint16_t *dsave_ptr = (uint16_t *)(bar0_ptr + NC_DSAVE_OFFSET);
117 FPGA_SET_PARAM(NvramVirtTimeDsaveReset, *dsave_ptr);
119 if (cap & NC_CAP1_BL_BRIGHTNESS_CTRL) {
120 uint8_t *bl_bn_ptr =
121 (uint8_t *)(bar0_ptr + NC_BL_BRIGHTNESS_OFFSET);
122 uint8_t *bl_pwm_ptr = (uint8_t *)(bar0_ptr + NC_BL_PWM_OFFSET);
123 FPGA_SET_PARAM(BL_Brightness, *bl_bn_ptr);
124 FPGA_SET_PARAM(PF_PwmFreq, *bl_pwm_ptr);
128 #if CONFIG(NC_FPGA_NOTIFY_CB_READY)
129 /* Set FW_DONE bit in FPGA before jumping to payload. */
130 static void set_fw_done(void *unused)
132 uint32_t reg;
134 if (nc_fpga_bar0) {
135 reg = read32(nc_fpga_bar0 + NC_DIAG_CTRL_OFFSET);
136 reg |= NC_DIAG_FW_DONE;
137 write32(nc_fpga_bar0 + NC_DIAG_CTRL_OFFSET, reg);
141 BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, set_fw_done, NULL);
142 #endif
144 static void nc_fpga_set_resources(struct device *dev)
146 pci_dev_set_resources(dev);
148 if (CONFIG(NC_FPGA_POST_CODE)) {
149 /* Re-initialize base address after set_resources for POST display
150 to work properly.*/
151 nc_fpga_remap(pci_read_config32(dev, PCI_BASE_ADDRESS_0) & ~0xf);
156 static struct device_operations nc_fpga_ops = {
157 .read_resources = pci_dev_read_resources,
158 .set_resources = nc_fpga_set_resources,
159 .enable_resources = pci_dev_enable_resources,
160 .init = nc_fpga_init,
163 static const unsigned short nc_fpga_device_ids[] = { 0x4080, 0x4091, 0 };
165 static const struct pci_driver nc_fpga_driver __pci_driver = {
166 .ops = &nc_fpga_ops,
167 .vendor = PCI_VID_SIEMENS,
168 .devices = nc_fpga_device_ids,