brintos

brintos / linux-shallow public Read only

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