1 /* SPDX-License-Identifier: GPL-2.0-only */
4 #include <device/pci.h>
5 #include <device/pci_ids.h>
6 #include <device/pci_ops.h>
7 #include <device/mmio.h>
13 static void *nc_fpga_bar0
;
15 #define FPGA_SET_PARAM(src, dst) \
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;
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
))
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)) {
72 else if (fan_req
&& !freeze_disable
)
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
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
;
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
))
99 /* Ensure this is really a NC FPGA by checking magic register. */
100 if (read32(bar0_ptr
+ NC_MAGIC_OFFSET
) != NC_FPGA_MAGIC
)
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
)
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
) {
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
)
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
);
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
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
= {
167 .vendor
= PCI_VID_SIEMENS
,
168 .devices
= nc_fpga_device_ids
,