summaryrefslogtreecommitdiff
path: root/drivers/iio/adc/versal-sysmon.h
blob: bb9a75bf71c0d7469f29616d049ee942d3c3558c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* 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_ */