| /* SPDX-License-Identifier: GPL-2.0 */ |
| /* |
| * AMD Versal SysMon driver |
| * |
| * Copyright (C) 2019 - 2022, Xilinx, Inc. |
| * Copyright (C) 2022 - 2026, Advanced Micro Devices, Inc. |
| */ |
| |
| #ifndef _VERSAL_SYSMON_H_ |
| #define _VERSAL_SYSMON_H_ |
| |
| #include <linux/bits.h> |
| #include <linux/mutex.h> |
| #include <linux/spinlock_types.h> |
| #include <linux/workqueue.h> |
| |
| struct device; |
| struct regmap; |
| |
| /* Register offsets (sorted by address) */ |
| #define SYSMON_NPI_LOCK 0x000C |
| #define SYSMON_ISR 0x0044 |
| #define SYSMON_IMR 0x0048 |
| #define SYSMON_IER 0x004C |
| #define SYSMON_IDR 0x0050 |
| #define SYSMON_CONFIG 0x0100 |
| #define SYSMON_TEMP_MAX 0x1030 |
| #define SYSMON_TEMP_MIN 0x1034 |
| #define SYSMON_SUPPLY_BASE 0x1040 |
| #define SYSMON_ALARM_FLAG 0x1018 |
| #define SYSMON_ALARM_REG 0x1940 |
| #define SYSMON_SUPPLY_EN_AVG_BASE 0x1958 |
| #define SYSMON_TEMP_TH_LOW 0x1970 |
| #define SYSMON_TEMP_TH_UP 0x1974 |
| #define SYSMON_SUPPLY_TH_LOW 0x1980 |
| #define SYSMON_SUPPLY_TH_UP 0x1C80 |
| #define SYSMON_TEMP_EV_CFG 0x1F84 |
| #define SYSMON_TEMP_MIN_MIN 0x1F8C |
| #define SYSMON_TEMP_MAX_MAX 0x1F90 |
| #define SYSMON_STATUS_RESET 0x1F94 |
| #define SYSMON_TEMP_SAT_BASE 0x1FAC |
| #define SYSMON_TEMP_EN_AVG_BASE 0x24B4 |
| #define SYSMON_MAX_REG 0x24C0 |
| |
| /* NPI unlock value written to SYSMON_NPI_LOCK */ |
| #define SYSMON_NPI_UNLOCK_CODE 0xF9E8D7C6 |
| |
| /* Register stride: 4 bytes per 32-bit register */ |
| #define SYSMON_REG_STRIDE 4 |
| |
| #define SYSMON_SUPPLY_IDX_MAX 159 |
| #define SYSMON_TEMP_SAT_MAX 64 |
| #define SYSMON_NO_OF_EVENTS 32 |
| #define SYSMON_INTR_ALL_MASK GENMASK(31, 0) |
| |
| /* ISR/IMR temperature alarm mask (bit 9) */ |
| #define SYSMON_TEMP_INTR_MASK BIT(9) |
| |
| /* SYSMON_CONFIG: supply oversampling ratio */ |
| #define SYSMON_CONFIG_SUPPLY_OSR GENMASK(17, 14) |
| |
| /* SYSMON_CONFIG: temperature satellite oversampling ratio */ |
| #define SYSMON_CONFIG_TEMP_SAT_OSR GENMASK(27, 24) |
| |
| /* Per-channel averaging enable register counts */ |
| #define SYSMON_SUPPLY_EN_AVG_COUNT 5 |
| #define SYSMON_TEMP_EN_AVG_COUNT 2 |
| |
| /* Supply voltage conversion register fields */ |
| #define SYSMON_MANTISSA_MASK GENMASK(15, 0) |
| #define SYSMON_FMT_MASK BIT(16) |
| #define SYSMON_MODE_MASK GENMASK(18, 17) |
| |
| /* Q8.7 fractional shift */ |
| #define SYSMON_FRACTIONAL_SHIFT 7U |
| #define SYSMON_SUPPLY_MANTISSA_BITS 16 |
| |
| /* Bits per alarm register */ |
| #define SYSMON_ALARM_BITS_PER_REG 32 |
| |
| #define SYSMON_UNMASK_WORK_DELAY_MS 500 |
| |
| /** |
| * struct sysmon - Driver data for Versal SysMon |
| * @regmap: register map for hardware access |
| * @lock: protects read-modify-write sequences on threshold registers |
| * and cached state that spans multiple regmap calls |
| * @irq_lock: protects interrupt mask register updates (MMIO path only) |
| * @masked_temp: currently masked temperature alarm bits |
| * @temp_mask: temperature interrupt configuration mask |
| * @temp_hysteresis: cached DEVICE_TEMP hysteresis in millicelsius |
| * @sysmon_unmask_work: re-enables events after alarm condition clears |
| * @temp_oversampling: current temp oversampling ratio |
| * @supply_oversampling: current supply oversampling ratio |
| */ |
| struct sysmon { |
| struct regmap *regmap; |
| /* |
| * Protects read-modify-write sequences on threshold registers |
| * and cached state (oversampling ratios, hysteresis values) |
| * that spans multiple regmap calls. |
| */ |
| struct mutex lock; |
| /* |
| * Protects interrupt mask register updates. Only used on the |
| * MMIO path (fast_io regmap); I2C has no IRQ and never reaches |
| * the event code that takes this lock. |
| */ |
| spinlock_t irq_lock; |
| unsigned int masked_temp; |
| unsigned int temp_mask; |
| int temp_hysteresis; |
| struct delayed_work sysmon_unmask_work; |
| unsigned int temp_oversampling; |
| unsigned int supply_oversampling; |
| }; |
| |
| int devm_versal_sysmon_core_probe(struct device *dev, struct regmap *regmap); |
| |
| #endif /* _VERSAL_SYSMON_H_ */ |