1*8a27ad81SWachowski, Karol // SPDX-License-Identifier: GPL-2.0-only 2*8a27ad81SWachowski, Karol /* 3*8a27ad81SWachowski, Karol * Copyright (C) 2020 - 2024 Intel Corporation 4*8a27ad81SWachowski, Karol */ 5*8a27ad81SWachowski, Karol 6*8a27ad81SWachowski, Karol #include "ivpu_drv.h" 7*8a27ad81SWachowski, Karol #include "ivpu_hw.h" 8*8a27ad81SWachowski, Karol #include "ivpu_hw_btrs.h" 9*8a27ad81SWachowski, Karol #include "ivpu_hw_ip.h" 10*8a27ad81SWachowski, Karol 11*8a27ad81SWachowski, Karol #include <linux/dmi.h> 12*8a27ad81SWachowski, Karol 13*8a27ad81SWachowski, Karol static char *platform_to_str(u32 platform) 14*8a27ad81SWachowski, Karol { 15*8a27ad81SWachowski, Karol switch (platform) { 16*8a27ad81SWachowski, Karol case IVPU_PLATFORM_SILICON: 17*8a27ad81SWachowski, Karol return "SILICON"; 18*8a27ad81SWachowski, Karol case IVPU_PLATFORM_SIMICS: 19*8a27ad81SWachowski, Karol return "SIMICS"; 20*8a27ad81SWachowski, Karol case IVPU_PLATFORM_FPGA: 21*8a27ad81SWachowski, Karol return "FPGA"; 22*8a27ad81SWachowski, Karol default: 23*8a27ad81SWachowski, Karol return "Invalid platform"; 24*8a27ad81SWachowski, Karol } 25*8a27ad81SWachowski, Karol } 26*8a27ad81SWachowski, Karol 27*8a27ad81SWachowski, Karol static const struct dmi_system_id dmi_platform_simulation[] = { 28*8a27ad81SWachowski, Karol { 29*8a27ad81SWachowski, Karol .ident = "Intel Simics", 30*8a27ad81SWachowski, Karol .matches = { 31*8a27ad81SWachowski, Karol DMI_MATCH(DMI_BOARD_NAME, "lnlrvp"), 32*8a27ad81SWachowski, Karol DMI_MATCH(DMI_BOARD_VERSION, "1.0"), 33*8a27ad81SWachowski, Karol DMI_MATCH(DMI_BOARD_SERIAL, "123456789"), 34*8a27ad81SWachowski, Karol }, 35*8a27ad81SWachowski, Karol }, 36*8a27ad81SWachowski, Karol { 37*8a27ad81SWachowski, Karol .ident = "Intel Simics", 38*8a27ad81SWachowski, Karol .matches = { 39*8a27ad81SWachowski, Karol DMI_MATCH(DMI_BOARD_NAME, "Simics"), 40*8a27ad81SWachowski, Karol }, 41*8a27ad81SWachowski, Karol }, 42*8a27ad81SWachowski, Karol { } 43*8a27ad81SWachowski, Karol }; 44*8a27ad81SWachowski, Karol 45*8a27ad81SWachowski, Karol static void platform_init(struct ivpu_device *vdev) 46*8a27ad81SWachowski, Karol { 47*8a27ad81SWachowski, Karol if (dmi_check_system(dmi_platform_simulation)) 48*8a27ad81SWachowski, Karol vdev->platform = IVPU_PLATFORM_SIMICS; 49*8a27ad81SWachowski, Karol else 50*8a27ad81SWachowski, Karol vdev->platform = IVPU_PLATFORM_SILICON; 51*8a27ad81SWachowski, Karol 52*8a27ad81SWachowski, Karol ivpu_dbg(vdev, MISC, "Platform type: %s (%d)\n", 53*8a27ad81SWachowski, Karol platform_to_str(vdev->platform), vdev->platform); 54*8a27ad81SWachowski, Karol } 55*8a27ad81SWachowski, Karol 56*8a27ad81SWachowski, Karol static void wa_init(struct ivpu_device *vdev) 57*8a27ad81SWachowski, Karol { 58*8a27ad81SWachowski, Karol vdev->wa.punit_disabled = ivpu_is_fpga(vdev); 59*8a27ad81SWachowski, Karol vdev->wa.clear_runtime_mem = false; 60*8a27ad81SWachowski, Karol 61*8a27ad81SWachowski, Karol if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) 62*8a27ad81SWachowski, Karol vdev->wa.interrupt_clear_with_0 = ivpu_hw_btrs_irqs_clear_with_0_mtl(vdev); 63*8a27ad81SWachowski, Karol 64*8a27ad81SWachowski, Karol if (ivpu_device_id(vdev) == PCI_DEVICE_ID_LNL) 65*8a27ad81SWachowski, Karol vdev->wa.disable_clock_relinquish = true; 66*8a27ad81SWachowski, Karol 67*8a27ad81SWachowski, Karol IVPU_PRINT_WA(punit_disabled); 68*8a27ad81SWachowski, Karol IVPU_PRINT_WA(clear_runtime_mem); 69*8a27ad81SWachowski, Karol IVPU_PRINT_WA(interrupt_clear_with_0); 70*8a27ad81SWachowski, Karol IVPU_PRINT_WA(disable_clock_relinquish); 71*8a27ad81SWachowski, Karol } 72*8a27ad81SWachowski, Karol 73*8a27ad81SWachowski, Karol static void timeouts_init(struct ivpu_device *vdev) 74*8a27ad81SWachowski, Karol { 75*8a27ad81SWachowski, Karol if (ivpu_is_fpga(vdev)) { 76*8a27ad81SWachowski, Karol vdev->timeout.boot = 100000; 77*8a27ad81SWachowski, Karol vdev->timeout.jsm = 50000; 78*8a27ad81SWachowski, Karol vdev->timeout.tdr = 2000000; 79*8a27ad81SWachowski, Karol vdev->timeout.reschedule_suspend = 1000; 80*8a27ad81SWachowski, Karol vdev->timeout.autosuspend = -1; 81*8a27ad81SWachowski, Karol vdev->timeout.d0i3_entry_msg = 500; 82*8a27ad81SWachowski, Karol } else if (ivpu_is_simics(vdev)) { 83*8a27ad81SWachowski, Karol vdev->timeout.boot = 50; 84*8a27ad81SWachowski, Karol vdev->timeout.jsm = 500; 85*8a27ad81SWachowski, Karol vdev->timeout.tdr = 10000; 86*8a27ad81SWachowski, Karol vdev->timeout.reschedule_suspend = 10; 87*8a27ad81SWachowski, Karol vdev->timeout.autosuspend = -1; 88*8a27ad81SWachowski, Karol vdev->timeout.d0i3_entry_msg = 100; 89*8a27ad81SWachowski, Karol } else { 90*8a27ad81SWachowski, Karol vdev->timeout.boot = 1000; 91*8a27ad81SWachowski, Karol vdev->timeout.jsm = 500; 92*8a27ad81SWachowski, Karol vdev->timeout.tdr = 2000; 93*8a27ad81SWachowski, Karol vdev->timeout.reschedule_suspend = 10; 94*8a27ad81SWachowski, Karol vdev->timeout.autosuspend = 10; 95*8a27ad81SWachowski, Karol vdev->timeout.d0i3_entry_msg = 5; 96*8a27ad81SWachowski, Karol } 97*8a27ad81SWachowski, Karol } 98*8a27ad81SWachowski, Karol 99*8a27ad81SWachowski, Karol static void memory_ranges_init(struct ivpu_device *vdev) 100*8a27ad81SWachowski, Karol { 101*8a27ad81SWachowski, Karol if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { 102*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000, SZ_512M); 103*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.user, 0xc0000000, 255 * SZ_1M); 104*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.shave, 0x180000000, SZ_2G); 105*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.dma, 0x200000000, SZ_8G); 106*8a27ad81SWachowski, Karol } else { 107*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000, SZ_512M); 108*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.user, 0x80000000, SZ_256M); 109*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.shave, 0x80000000 + SZ_256M, SZ_2G - SZ_256M); 110*8a27ad81SWachowski, Karol ivpu_hw_range_init(&vdev->hw->ranges.dma, 0x200000000, SZ_8G); 111*8a27ad81SWachowski, Karol } 112*8a27ad81SWachowski, Karol } 113*8a27ad81SWachowski, Karol 114*8a27ad81SWachowski, Karol static int wp_enable(struct ivpu_device *vdev) 115*8a27ad81SWachowski, Karol { 116*8a27ad81SWachowski, Karol return ivpu_hw_btrs_wp_drive(vdev, true); 117*8a27ad81SWachowski, Karol } 118*8a27ad81SWachowski, Karol 119*8a27ad81SWachowski, Karol static int wp_disable(struct ivpu_device *vdev) 120*8a27ad81SWachowski, Karol { 121*8a27ad81SWachowski, Karol return ivpu_hw_btrs_wp_drive(vdev, false); 122*8a27ad81SWachowski, Karol } 123*8a27ad81SWachowski, Karol 124*8a27ad81SWachowski, Karol int ivpu_hw_power_up(struct ivpu_device *vdev) 125*8a27ad81SWachowski, Karol { 126*8a27ad81SWachowski, Karol int ret; 127*8a27ad81SWachowski, Karol 128*8a27ad81SWachowski, Karol ret = ivpu_hw_btrs_d0i3_disable(vdev); 129*8a27ad81SWachowski, Karol if (ret) 130*8a27ad81SWachowski, Karol ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret); 131*8a27ad81SWachowski, Karol 132*8a27ad81SWachowski, Karol ret = wp_enable(vdev); 133*8a27ad81SWachowski, Karol if (ret) { 134*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to enable workpoint: %d\n", ret); 135*8a27ad81SWachowski, Karol return ret; 136*8a27ad81SWachowski, Karol } 137*8a27ad81SWachowski, Karol 138*8a27ad81SWachowski, Karol if (ivpu_hw_btrs_gen(vdev) >= IVPU_HW_BTRS_LNL) { 139*8a27ad81SWachowski, Karol if (IVPU_WA(disable_clock_relinquish)) 140*8a27ad81SWachowski, Karol ivpu_hw_btrs_clock_relinquish_disable_lnl(vdev); 141*8a27ad81SWachowski, Karol ivpu_hw_btrs_profiling_freq_reg_set_lnl(vdev); 142*8a27ad81SWachowski, Karol ivpu_hw_btrs_ats_print_lnl(vdev); 143*8a27ad81SWachowski, Karol } 144*8a27ad81SWachowski, Karol 145*8a27ad81SWachowski, Karol ret = ivpu_hw_ip_host_ss_configure(vdev); 146*8a27ad81SWachowski, Karol if (ret) { 147*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to configure host SS: %d\n", ret); 148*8a27ad81SWachowski, Karol return ret; 149*8a27ad81SWachowski, Karol } 150*8a27ad81SWachowski, Karol 151*8a27ad81SWachowski, Karol ivpu_hw_ip_idle_gen_disable(vdev); 152*8a27ad81SWachowski, Karol 153*8a27ad81SWachowski, Karol ret = ivpu_hw_btrs_wait_for_clock_res_own_ack(vdev); 154*8a27ad81SWachowski, Karol if (ret) { 155*8a27ad81SWachowski, Karol ivpu_err(vdev, "Timed out waiting for clock resource own ACK\n"); 156*8a27ad81SWachowski, Karol return ret; 157*8a27ad81SWachowski, Karol } 158*8a27ad81SWachowski, Karol 159*8a27ad81SWachowski, Karol ret = ivpu_hw_ip_pwr_domain_enable(vdev); 160*8a27ad81SWachowski, Karol if (ret) { 161*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to enable power domain: %d\n", ret); 162*8a27ad81SWachowski, Karol return ret; 163*8a27ad81SWachowski, Karol } 164*8a27ad81SWachowski, Karol 165*8a27ad81SWachowski, Karol ret = ivpu_hw_ip_host_ss_axi_enable(vdev); 166*8a27ad81SWachowski, Karol if (ret) { 167*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to enable AXI: %d\n", ret); 168*8a27ad81SWachowski, Karol return ret; 169*8a27ad81SWachowski, Karol } 170*8a27ad81SWachowski, Karol 171*8a27ad81SWachowski, Karol if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_LNL) 172*8a27ad81SWachowski, Karol ivpu_hw_btrs_set_port_arbitration_weights_lnl(vdev); 173*8a27ad81SWachowski, Karol 174*8a27ad81SWachowski, Karol ret = ivpu_hw_ip_top_noc_enable(vdev); 175*8a27ad81SWachowski, Karol if (ret) 176*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to enable TOP NOC: %d\n", ret); 177*8a27ad81SWachowski, Karol 178*8a27ad81SWachowski, Karol return ret; 179*8a27ad81SWachowski, Karol } 180*8a27ad81SWachowski, Karol 181*8a27ad81SWachowski, Karol static void save_d0i3_entry_timestamp(struct ivpu_device *vdev) 182*8a27ad81SWachowski, Karol { 183*8a27ad81SWachowski, Karol vdev->hw->d0i3_entry_host_ts = ktime_get_boottime(); 184*8a27ad81SWachowski, Karol vdev->hw->d0i3_entry_vpu_ts = ivpu_hw_ip_read_perf_timer_counter(vdev); 185*8a27ad81SWachowski, Karol } 186*8a27ad81SWachowski, Karol 187*8a27ad81SWachowski, Karol int ivpu_hw_reset(struct ivpu_device *vdev) 188*8a27ad81SWachowski, Karol { 189*8a27ad81SWachowski, Karol int ret = 0; 190*8a27ad81SWachowski, Karol 191*8a27ad81SWachowski, Karol if (ivpu_hw_btrs_ip_reset(vdev)) { 192*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to reset NPU IP\n"); 193*8a27ad81SWachowski, Karol ret = -EIO; 194*8a27ad81SWachowski, Karol } 195*8a27ad81SWachowski, Karol 196*8a27ad81SWachowski, Karol if (wp_disable(vdev)) { 197*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to disable workpoint\n"); 198*8a27ad81SWachowski, Karol ret = -EIO; 199*8a27ad81SWachowski, Karol } 200*8a27ad81SWachowski, Karol 201*8a27ad81SWachowski, Karol return ret; 202*8a27ad81SWachowski, Karol } 203*8a27ad81SWachowski, Karol 204*8a27ad81SWachowski, Karol int ivpu_hw_power_down(struct ivpu_device *vdev) 205*8a27ad81SWachowski, Karol { 206*8a27ad81SWachowski, Karol int ret = 0; 207*8a27ad81SWachowski, Karol 208*8a27ad81SWachowski, Karol save_d0i3_entry_timestamp(vdev); 209*8a27ad81SWachowski, Karol 210*8a27ad81SWachowski, Karol if (!ivpu_hw_is_idle(vdev)) 211*8a27ad81SWachowski, Karol ivpu_warn(vdev, "NPU not idle during power down\n"); 212*8a27ad81SWachowski, Karol 213*8a27ad81SWachowski, Karol if (ivpu_hw_reset(vdev)) { 214*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to reset NPU\n"); 215*8a27ad81SWachowski, Karol ret = -EIO; 216*8a27ad81SWachowski, Karol } 217*8a27ad81SWachowski, Karol 218*8a27ad81SWachowski, Karol if (ivpu_hw_btrs_d0i3_enable(vdev)) { 219*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to enter D0I3\n"); 220*8a27ad81SWachowski, Karol ret = -EIO; 221*8a27ad81SWachowski, Karol } 222*8a27ad81SWachowski, Karol 223*8a27ad81SWachowski, Karol return ret; 224*8a27ad81SWachowski, Karol } 225*8a27ad81SWachowski, Karol 226*8a27ad81SWachowski, Karol int ivpu_hw_init(struct ivpu_device *vdev) 227*8a27ad81SWachowski, Karol { 228*8a27ad81SWachowski, Karol ivpu_hw_btrs_info_init(vdev); 229*8a27ad81SWachowski, Karol ivpu_hw_btrs_freq_ratios_init(vdev); 230*8a27ad81SWachowski, Karol memory_ranges_init(vdev); 231*8a27ad81SWachowski, Karol platform_init(vdev); 232*8a27ad81SWachowski, Karol wa_init(vdev); 233*8a27ad81SWachowski, Karol timeouts_init(vdev); 234*8a27ad81SWachowski, Karol 235*8a27ad81SWachowski, Karol return 0; 236*8a27ad81SWachowski, Karol } 237*8a27ad81SWachowski, Karol 238*8a27ad81SWachowski, Karol int ivpu_hw_boot_fw(struct ivpu_device *vdev) 239*8a27ad81SWachowski, Karol { 240*8a27ad81SWachowski, Karol int ret; 241*8a27ad81SWachowski, Karol 242*8a27ad81SWachowski, Karol ivpu_hw_ip_snoop_disable(vdev); 243*8a27ad81SWachowski, Karol ivpu_hw_ip_tbu_mmu_enable(vdev); 244*8a27ad81SWachowski, Karol ret = ivpu_hw_ip_soc_cpu_boot(vdev); 245*8a27ad81SWachowski, Karol if (ret) 246*8a27ad81SWachowski, Karol ivpu_err(vdev, "Failed to boot SOC CPU: %d\n", ret); 247*8a27ad81SWachowski, Karol 248*8a27ad81SWachowski, Karol return ret; 249*8a27ad81SWachowski, Karol } 250*8a27ad81SWachowski, Karol 251*8a27ad81SWachowski, Karol void ivpu_hw_profiling_freq_drive(struct ivpu_device *vdev, bool enable) 252*8a27ad81SWachowski, Karol { 253*8a27ad81SWachowski, Karol if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) { 254*8a27ad81SWachowski, Karol vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; 255*8a27ad81SWachowski, Karol return; 256*8a27ad81SWachowski, Karol } 257*8a27ad81SWachowski, Karol 258*8a27ad81SWachowski, Karol if (enable) 259*8a27ad81SWachowski, Karol vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_HIGH; 260*8a27ad81SWachowski, Karol else 261*8a27ad81SWachowski, Karol vdev->hw->pll.profiling_freq = PLL_PROFILING_FREQ_DEFAULT; 262*8a27ad81SWachowski, Karol } 263*8a27ad81SWachowski, Karol 264*8a27ad81SWachowski, Karol void ivpu_irq_handlers_init(struct ivpu_device *vdev) 265*8a27ad81SWachowski, Karol { 266*8a27ad81SWachowski, Karol if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) 267*8a27ad81SWachowski, Karol vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_37xx; 268*8a27ad81SWachowski, Karol else 269*8a27ad81SWachowski, Karol vdev->hw->irq.ip_irq_handler = ivpu_hw_ip_irq_handler_40xx; 270*8a27ad81SWachowski, Karol 271*8a27ad81SWachowski, Karol if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL) 272*8a27ad81SWachowski, Karol vdev->hw->irq.btrs_irq_handler = ivpu_hw_btrs_irq_handler_mtl; 273*8a27ad81SWachowski, Karol else 274*8a27ad81SWachowski, Karol vdev->hw->irq.btrs_irq_handler = ivpu_hw_btrs_irq_handler_lnl; 275*8a27ad81SWachowski, Karol } 276*8a27ad81SWachowski, Karol 277*8a27ad81SWachowski, Karol void ivpu_hw_irq_enable(struct ivpu_device *vdev) 278*8a27ad81SWachowski, Karol { 279*8a27ad81SWachowski, Karol ivpu_hw_ip_irq_enable(vdev); 280*8a27ad81SWachowski, Karol ivpu_hw_btrs_irq_enable(vdev); 281*8a27ad81SWachowski, Karol } 282*8a27ad81SWachowski, Karol 283*8a27ad81SWachowski, Karol void ivpu_hw_irq_disable(struct ivpu_device *vdev) 284*8a27ad81SWachowski, Karol { 285*8a27ad81SWachowski, Karol ivpu_hw_btrs_irq_disable(vdev); 286*8a27ad81SWachowski, Karol ivpu_hw_ip_irq_disable(vdev); 287*8a27ad81SWachowski, Karol } 288*8a27ad81SWachowski, Karol 289*8a27ad81SWachowski, Karol irqreturn_t ivpu_hw_irq_handler(int irq, void *ptr) 290*8a27ad81SWachowski, Karol { 291*8a27ad81SWachowski, Karol bool ip_handled, btrs_handled, wake_thread = false; 292*8a27ad81SWachowski, Karol struct ivpu_device *vdev = ptr; 293*8a27ad81SWachowski, Karol 294*8a27ad81SWachowski, Karol ivpu_hw_btrs_global_int_disable(vdev); 295*8a27ad81SWachowski, Karol 296*8a27ad81SWachowski, Karol btrs_handled = ivpu_hw_btrs_irq_handler(vdev, irq); 297*8a27ad81SWachowski, Karol if (!ivpu_hw_is_idle((vdev)) || !btrs_handled) 298*8a27ad81SWachowski, Karol ip_handled = ivpu_hw_ip_irq_handler(vdev, irq, &wake_thread); 299*8a27ad81SWachowski, Karol else 300*8a27ad81SWachowski, Karol ip_handled = false; 301*8a27ad81SWachowski, Karol 302*8a27ad81SWachowski, Karol /* Re-enable global interrupts to re-trigger MSI for pending interrupts */ 303*8a27ad81SWachowski, Karol ivpu_hw_btrs_global_int_enable(vdev); 304*8a27ad81SWachowski, Karol 305*8a27ad81SWachowski, Karol if (wake_thread) 306*8a27ad81SWachowski, Karol return IRQ_WAKE_THREAD; 307*8a27ad81SWachowski, Karol if (ip_handled || btrs_handled) 308*8a27ad81SWachowski, Karol return IRQ_HANDLED; 309*8a27ad81SWachowski, Karol return IRQ_NONE; 310*8a27ad81SWachowski, Karol } 311