xref: /linux/drivers/platform/mellanox/mlxreg-dpu.c (revision 1193e205dbb6feca917dc8e1862ffcdf2194234b)
1d00f779eSVadim Pasternak // SPDX-License-Identifier: GPL-2.0+
2d00f779eSVadim Pasternak /*
3d00f779eSVadim Pasternak  * Nvidia Data Processor Unit platform driver
4d00f779eSVadim Pasternak  *
5d00f779eSVadim Pasternak  * Copyright (C) 2025 Nvidia Technologies Ltd.
6d00f779eSVadim Pasternak  */
7d00f779eSVadim Pasternak 
8d00f779eSVadim Pasternak #include <linux/device.h>
9d00f779eSVadim Pasternak #include <linux/dev_printk.h>
10d00f779eSVadim Pasternak #include <linux/i2c.h>
11d00f779eSVadim Pasternak #include <linux/module.h>
12d00f779eSVadim Pasternak #include <linux/platform_data/mlxcpld.h>
13d00f779eSVadim Pasternak #include <linux/platform_data/mlxreg.h>
14d00f779eSVadim Pasternak #include <linux/platform_device.h>
15d00f779eSVadim Pasternak #include <linux/regmap.h>
16d00f779eSVadim Pasternak 
17d00f779eSVadim Pasternak /* I2C bus IO offsets */
18d00f779eSVadim Pasternak #define MLXREG_DPU_REG_FPGA1_VER_OFFSET			0x2400
19d00f779eSVadim Pasternak #define MLXREG_DPU_REG_FPGA1_PN_OFFSET			0x2404
20d00f779eSVadim Pasternak #define MLXREG_DPU_REG_FPGA1_PN1_OFFSET			0x2405
21d00f779eSVadim Pasternak #define MLXREG_DPU_REG_PG_OFFSET			0x2414
22d00f779eSVadim Pasternak #define MLXREG_DPU_REG_PG_EVENT_OFFSET			0x2415
23d00f779eSVadim Pasternak #define MLXREG_DPU_REG_PG_MASK_OFFSET			0x2416
24d00f779eSVadim Pasternak #define MLXREG_DPU_REG_RESET_GP1_OFFSET			0x2417
25d00f779eSVadim Pasternak #define MLXREG_DPU_REG_RST_CAUSE1_OFFSET		0x241e
26d00f779eSVadim Pasternak #define MLXREG_DPU_REG_GP0_RO_OFFSET			0x242b
27d00f779eSVadim Pasternak #define MLXREG_DPU_REG_GP0_OFFSET			0x242e
28d00f779eSVadim Pasternak #define MLXREG_DPU_REG_GP1_OFFSET			0x242c
29d00f779eSVadim Pasternak #define MLXREG_DPU_REG_GP4_OFFSET			0x2438
30d00f779eSVadim Pasternak #define MLXREG_DPU_REG_AGGRCO_OFFSET			0x2442
31d00f779eSVadim Pasternak #define MLXREG_DPU_REG_AGGRCO_MASK_OFFSET		0x2443
32d00f779eSVadim Pasternak #define MLXREG_DPU_REG_HEALTH_OFFSET			0x244d
33d00f779eSVadim Pasternak #define MLXREG_DPU_REG_HEALTH_EVENT_OFFSET		0x244e
34d00f779eSVadim Pasternak #define MLXREG_DPU_REG_HEALTH_MASK_OFFSET		0x244f
35d00f779eSVadim Pasternak #define MLXREG_DPU_REG_FPGA1_MVER_OFFSET		0x24de
36d00f779eSVadim Pasternak #define MLXREG_DPU_REG_CONFIG3_OFFSET			0x24fd
37d00f779eSVadim Pasternak #define MLXREG_DPU_REG_MAX				0x3fff
38d00f779eSVadim Pasternak 
39d00f779eSVadim Pasternak /* Power Good event masks. */
40d00f779eSVadim Pasternak #define MLXREG_DPU_PG_VDDIO_MASK			BIT(0)
41d00f779eSVadim Pasternak #define MLXREG_DPU_PG_VDD_CPU_MASK			BIT(1)
42d00f779eSVadim Pasternak #define MLXREG_DPU_PG_VDD_MASK				BIT(2)
43d00f779eSVadim Pasternak #define MLXREG_DPU_PG_1V8_MASK				BIT(3)
44d00f779eSVadim Pasternak #define MLXREG_DPU_PG_COMPARATOR_MASK			BIT(4)
45d00f779eSVadim Pasternak #define MLXREG_DPU_PG_VDDQ_MASK				BIT(5)
46d00f779eSVadim Pasternak #define MLXREG_DPU_PG_HVDD_MASK				BIT(6)
47d00f779eSVadim Pasternak #define MLXREG_DPU_PG_DVDD_MASK				BIT(7)
48d00f779eSVadim Pasternak #define MLXREG_DPU_PG_MASK				(MLXREG_DPU_PG_DVDD_MASK | \
49d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_HVDD_MASK | \
50d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_VDDQ_MASK | \
51d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_COMPARATOR_MASK | \
52d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_1V8_MASK | \
53d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_VDD_CPU_MASK | \
54d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_VDD_MASK | \
55d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_VDDIO_MASK)
56d00f779eSVadim Pasternak 
57d00f779eSVadim Pasternak /* Health event masks. */
58d00f779eSVadim Pasternak #define MLXREG_DPU_HLTH_THERMAL_TRIP_MASK		BIT(0)
59d00f779eSVadim Pasternak #define MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK		BIT(1)
60d00f779eSVadim Pasternak #define MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK		BIT(2)
61d00f779eSVadim Pasternak #define MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK		BIT(3)
62d00f779eSVadim Pasternak #define MLXREG_DPU_HLTH_VDDQ_ALERT_MASK			BIT(4)
63d00f779eSVadim Pasternak #define MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK		BIT(5)
64d00f779eSVadim Pasternak #define MLXREG_DPU_HEALTH_MASK				(MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK | \
65d00f779eSVadim Pasternak 							 MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK | \
66d00f779eSVadim Pasternak 							 MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK | \
67d00f779eSVadim Pasternak 							 MLXREG_DPU_HLTH_VDDQ_ALERT_MASK | \
68d00f779eSVadim Pasternak 							 MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK | \
69d00f779eSVadim Pasternak 							 MLXREG_DPU_HLTH_THERMAL_TRIP_MASK)
70d00f779eSVadim Pasternak 
71d00f779eSVadim Pasternak /* Hotplug aggregation masks. */
72d00f779eSVadim Pasternak #define MLXREG_DPU_HEALTH_AGGR_MASK			BIT(0)
73d00f779eSVadim Pasternak #define MLXREG_DPU_PG_AGGR_MASK				BIT(1)
74d00f779eSVadim Pasternak #define MLXREG_DPU_AGGR_MASK				(MLXREG_DPU_HEALTH_AGGR_MASK | \
75d00f779eSVadim Pasternak 							 MLXREG_DPU_PG_AGGR_MASK)
76d00f779eSVadim Pasternak 
77d00f779eSVadim Pasternak /* Voltage regulator firmware update status mask. */
78d00f779eSVadim Pasternak #define MLXREG_DPU_VOLTREG_UPD_MASK			GENMASK(5, 4)
79d00f779eSVadim Pasternak 
80d00f779eSVadim Pasternak #define MLXREG_DPU_NR_NONE				(-1)
81d00f779eSVadim Pasternak 
82d00f779eSVadim Pasternak /*
83d00f779eSVadim Pasternak  * enum mlxreg_dpu_type - Data Processor Unit types
84d00f779eSVadim Pasternak  *
85d00f779eSVadim Pasternak  * @MLXREG_DPU_BF3: DPU equipped with BF3 SoC;
86d00f779eSVadim Pasternak  */
87d00f779eSVadim Pasternak enum mlxreg_dpu_type {
88d00f779eSVadim Pasternak 	MLXREG_DPU_BF3 = 0x0050,
89d00f779eSVadim Pasternak };
90d00f779eSVadim Pasternak 
91d00f779eSVadim Pasternak /* Default register access data. */
92d00f779eSVadim Pasternak static struct mlxreg_core_data mlxreg_dpu_io_data[] = {
93d00f779eSVadim Pasternak 	{
94d00f779eSVadim Pasternak 		.label = "fpga1_version",
95d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_FPGA1_VER_OFFSET,
96d00f779eSVadim Pasternak 		.bit = GENMASK(7, 0),
97d00f779eSVadim Pasternak 		.mode = 0444,
98d00f779eSVadim Pasternak 	},
99d00f779eSVadim Pasternak 	{
100d00f779eSVadim Pasternak 		.label = "fpga1_pn",
101d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_FPGA1_PN_OFFSET,
102d00f779eSVadim Pasternak 		.bit = GENMASK(15, 0),
103d00f779eSVadim Pasternak 		.mode = 0444,
104d00f779eSVadim Pasternak 		.regnum = 2,
105d00f779eSVadim Pasternak 	},
106d00f779eSVadim Pasternak 	{
107d00f779eSVadim Pasternak 		.label = "fpga1_version_min",
108d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_FPGA1_MVER_OFFSET,
109d00f779eSVadim Pasternak 		.bit = GENMASK(7, 0),
110d00f779eSVadim Pasternak 		.mode = 0444,
111d00f779eSVadim Pasternak 	},
112d00f779eSVadim Pasternak 	{
113d00f779eSVadim Pasternak 		.label = "perst_rst",
114d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
115d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(0),
116d00f779eSVadim Pasternak 		.mode = 0644,
117d00f779eSVadim Pasternak 	},
118d00f779eSVadim Pasternak 	{
119d00f779eSVadim Pasternak 		.label = "usbphy_rst",
120d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
121d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(1),
122d00f779eSVadim Pasternak 		.mode = 0644,
123d00f779eSVadim Pasternak 	},
124d00f779eSVadim Pasternak 	{
125d00f779eSVadim Pasternak 		.label = "phy_rst",
126d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
127d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(2),
128d00f779eSVadim Pasternak 		.mode = 0644,
129d00f779eSVadim Pasternak 	},
130d00f779eSVadim Pasternak 	{
131d00f779eSVadim Pasternak 		.label = "tpm_rst",
132d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RESET_GP1_OFFSET,
133d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(6),
134d00f779eSVadim Pasternak 		.mode = 0644,
135d00f779eSVadim Pasternak 	},
136d00f779eSVadim Pasternak 	{
137d00f779eSVadim Pasternak 		.label = "reset_from_main_board",
138d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
139d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(1),
140d00f779eSVadim Pasternak 		.mode = 0444,
141d00f779eSVadim Pasternak 	},
142d00f779eSVadim Pasternak 	{
143d00f779eSVadim Pasternak 		.label = "reset_aux_pwr_or_reload",
144d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
145d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(2),
146d00f779eSVadim Pasternak 		.mode = 0444,
147d00f779eSVadim Pasternak 	},
148d00f779eSVadim Pasternak 	{
149d00f779eSVadim Pasternak 		.label = "reset_comex_pwr_fail",
150d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
151d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(3),
152d00f779eSVadim Pasternak 		.mode = 0444,
153d00f779eSVadim Pasternak 	},
154d00f779eSVadim Pasternak 	{
155d00f779eSVadim Pasternak 		.label = "reset_dpu_thermal",
156d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
157d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(6),
158d00f779eSVadim Pasternak 		.mode = 0444,
159d00f779eSVadim Pasternak 	},
160d00f779eSVadim Pasternak 	{
161d00f779eSVadim Pasternak 		.label = "reset_pwr_off",
162d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_RST_CAUSE1_OFFSET,
163d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(7),
164d00f779eSVadim Pasternak 		.mode = 0444,
165d00f779eSVadim Pasternak 	},
166d00f779eSVadim Pasternak 	{
167d00f779eSVadim Pasternak 		.label = "dpu_id",
168d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_GP0_RO_OFFSET,
169d00f779eSVadim Pasternak 		.bit = GENMASK(3, 0),
170d00f779eSVadim Pasternak 		.mode = 0444,
171d00f779eSVadim Pasternak 	},
172d00f779eSVadim Pasternak 	{
173d00f779eSVadim Pasternak 		.label = "voltreg_update_status",
174d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_GP0_RO_OFFSET,
175d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_VOLTREG_UPD_MASK,
176d00f779eSVadim Pasternak 		.bit = 5,
177d00f779eSVadim Pasternak 		.mode = 0444,
178d00f779eSVadim Pasternak 	},
179d00f779eSVadim Pasternak 	{
180d00f779eSVadim Pasternak 		.label = "boot_progress",
181d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_GP1_OFFSET,
182d00f779eSVadim Pasternak 		.mask = GENMASK(3, 0),
183d00f779eSVadim Pasternak 		.mode = 0444,
184d00f779eSVadim Pasternak 	},
185d00f779eSVadim Pasternak 	{
186d00f779eSVadim Pasternak 		.label = "ufm_upgrade",
187d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_GP4_OFFSET,
188d00f779eSVadim Pasternak 		.mask = GENMASK(7, 0) & ~BIT(1),
189d00f779eSVadim Pasternak 		.mode = 0644,
190d00f779eSVadim Pasternak 	},
191d00f779eSVadim Pasternak };
192d00f779eSVadim Pasternak 
193d00f779eSVadim Pasternak static struct mlxreg_core_platform_data mlxreg_dpu_default_regs_io_data = {
194d00f779eSVadim Pasternak 		.data = mlxreg_dpu_io_data,
195d00f779eSVadim Pasternak 		.counter = ARRAY_SIZE(mlxreg_dpu_io_data),
196d00f779eSVadim Pasternak };
197d00f779eSVadim Pasternak 
198d00f779eSVadim Pasternak /* Default hotplug data. */
199d00f779eSVadim Pasternak static struct mlxreg_core_data mlxreg_dpu_power_events_items_data[] = {
200d00f779eSVadim Pasternak 	{
201d00f779eSVadim Pasternak 		.label = "pg_vddio",
202d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
203d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_VDDIO_MASK,
204d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
205d00f779eSVadim Pasternak 	},
206d00f779eSVadim Pasternak 	{
207d00f779eSVadim Pasternak 		.label = "pg_vdd_cpu",
208d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
209d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_VDD_CPU_MASK,
210d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
211d00f779eSVadim Pasternak 	},
212d00f779eSVadim Pasternak 	{
213d00f779eSVadim Pasternak 		.label = "pg_vdd",
214d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
215d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_VDD_MASK,
216d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
217d00f779eSVadim Pasternak 	},
218d00f779eSVadim Pasternak 	{
219d00f779eSVadim Pasternak 		.label = "pg_1v8",
220d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
221d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_1V8_MASK,
222d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
223d00f779eSVadim Pasternak 	},
224d00f779eSVadim Pasternak 	{
225d00f779eSVadim Pasternak 		.label = "pg_comparator",
226d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
227d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_COMPARATOR_MASK,
228d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
229d00f779eSVadim Pasternak 	},
230d00f779eSVadim Pasternak 	{
231d00f779eSVadim Pasternak 		.label = "pg_vddq",
232d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
233d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_VDDQ_MASK,
234d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
235d00f779eSVadim Pasternak 	},
236d00f779eSVadim Pasternak 	{
237d00f779eSVadim Pasternak 		.label = "pg_hvdd",
238d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
239d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_HVDD_MASK,
240d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
241d00f779eSVadim Pasternak 	},
242d00f779eSVadim Pasternak 	{
243d00f779eSVadim Pasternak 		.label = "pg_dvdd",
244d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
245d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_DVDD_MASK,
246d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
247d00f779eSVadim Pasternak 	},
248d00f779eSVadim Pasternak };
249d00f779eSVadim Pasternak 
250d00f779eSVadim Pasternak static struct mlxreg_core_data mlxreg_dpu_health_events_items_data[] = {
251d00f779eSVadim Pasternak 	{
252d00f779eSVadim Pasternak 		.label = "thermal_trip",
253d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_HEALTH_OFFSET,
254d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_HLTH_THERMAL_TRIP_MASK,
255d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
256d00f779eSVadim Pasternak 	},
257d00f779eSVadim Pasternak 	{
258d00f779eSVadim Pasternak 		.label = "ufm_upgrade_done",
259d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_HEALTH_OFFSET,
260d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_HLTH_UFM_UPGRADE_DONE_MASK,
261d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
262d00f779eSVadim Pasternak 	},
263d00f779eSVadim Pasternak 	{
264d00f779eSVadim Pasternak 		.label = "vddq_hot_alert",
265d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_HEALTH_OFFSET,
266d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_HLTH_VDDQ_HOT_ALERT_MASK,
267d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
268d00f779eSVadim Pasternak 	},
269d00f779eSVadim Pasternak 	{
270d00f779eSVadim Pasternak 		.label = "vdd_cpu_hot_alert",
271d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_HEALTH_OFFSET,
272d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_HLTH_VDD_CPU_HOT_ALERT_MASK,
273d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
274d00f779eSVadim Pasternak 	},
275d00f779eSVadim Pasternak 	{
276d00f779eSVadim Pasternak 		.label = "vddq_alert",
277d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_HEALTH_OFFSET,
278d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_HLTH_VDDQ_ALERT_MASK,
279d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
280d00f779eSVadim Pasternak 	},
281d00f779eSVadim Pasternak 	{
282d00f779eSVadim Pasternak 		.label = "vdd_cpu_alert",
283d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_HEALTH_OFFSET,
284d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_HLTH_VDD_CPU_ALERT_MASK,
285d00f779eSVadim Pasternak 		.hpdev.nr = MLXREG_DPU_NR_NONE,
286d00f779eSVadim Pasternak 	},
287d00f779eSVadim Pasternak };
288d00f779eSVadim Pasternak 
289d00f779eSVadim Pasternak static struct mlxreg_core_item mlxreg_dpu_hotplug_items[] = {
290d00f779eSVadim Pasternak 	{
291d00f779eSVadim Pasternak 		.data = mlxreg_dpu_power_events_items_data,
292d00f779eSVadim Pasternak 		.aggr_mask = MLXREG_DPU_PG_AGGR_MASK,
293d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_PG_OFFSET,
294d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_PG_MASK,
295d00f779eSVadim Pasternak 		.count = ARRAY_SIZE(mlxreg_dpu_power_events_items_data),
296d00f779eSVadim Pasternak 		.health = false,
297d00f779eSVadim Pasternak 		.inversed = 0,
298d00f779eSVadim Pasternak 	},
299d00f779eSVadim Pasternak 	{
300d00f779eSVadim Pasternak 		.data = mlxreg_dpu_health_events_items_data,
301d00f779eSVadim Pasternak 		.aggr_mask = MLXREG_DPU_HEALTH_AGGR_MASK,
302d00f779eSVadim Pasternak 		.reg = MLXREG_DPU_REG_HEALTH_OFFSET,
303d00f779eSVadim Pasternak 		.mask = MLXREG_DPU_HEALTH_MASK,
304d00f779eSVadim Pasternak 		.count = ARRAY_SIZE(mlxreg_dpu_health_events_items_data),
305d00f779eSVadim Pasternak 		.health = false,
306d00f779eSVadim Pasternak 		.inversed = 0,
307d00f779eSVadim Pasternak 	},
308d00f779eSVadim Pasternak };
309d00f779eSVadim Pasternak 
310d00f779eSVadim Pasternak static
311d00f779eSVadim Pasternak struct mlxreg_core_hotplug_platform_data mlxreg_dpu_default_hotplug_data = {
312d00f779eSVadim Pasternak 	.items = mlxreg_dpu_hotplug_items,
313d00f779eSVadim Pasternak 	.count = ARRAY_SIZE(mlxreg_dpu_hotplug_items),
314d00f779eSVadim Pasternak 	.cell = MLXREG_DPU_REG_AGGRCO_OFFSET,
315d00f779eSVadim Pasternak 	.mask = MLXREG_DPU_AGGR_MASK,
316d00f779eSVadim Pasternak };
317d00f779eSVadim Pasternak 
318d00f779eSVadim Pasternak /**
319d00f779eSVadim Pasternak  * struct mlxreg_dpu - device private data
320d00f779eSVadim Pasternak  * @dev: platform device
321d00f779eSVadim Pasternak  * @data: platform core data
322d00f779eSVadim Pasternak  * @io_data: register access platform data
323d00f779eSVadim Pasternak  * @io_regs: register access device
324d00f779eSVadim Pasternak  * @hotplug_data: hotplug platform data
325d00f779eSVadim Pasternak  * @hotplug: hotplug device
326d00f779eSVadim Pasternak  */
327d00f779eSVadim Pasternak struct mlxreg_dpu {
328d00f779eSVadim Pasternak 	struct device *dev;
329d00f779eSVadim Pasternak 	struct mlxreg_core_data *data;
330d00f779eSVadim Pasternak 	struct mlxreg_core_platform_data *io_data;
331d00f779eSVadim Pasternak 	struct platform_device *io_regs;
332d00f779eSVadim Pasternak 	struct mlxreg_core_hotplug_platform_data *hotplug_data;
333d00f779eSVadim Pasternak 	struct platform_device *hotplug;
334d00f779eSVadim Pasternak };
335d00f779eSVadim Pasternak 
mlxreg_dpu_writeable_reg(struct device * dev,unsigned int reg)336d00f779eSVadim Pasternak static bool mlxreg_dpu_writeable_reg(struct device *dev, unsigned int reg)
337d00f779eSVadim Pasternak {
338d00f779eSVadim Pasternak 	switch (reg) {
339d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_EVENT_OFFSET:
340d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_MASK_OFFSET:
341d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_RESET_GP1_OFFSET:
342d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP0_OFFSET:
343d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP1_OFFSET:
344d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP4_OFFSET:
345d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_AGGRCO_OFFSET:
346d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET:
347d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET:
348d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_MASK_OFFSET:
349d00f779eSVadim Pasternak 		return true;
350d00f779eSVadim Pasternak 	}
351d00f779eSVadim Pasternak 	return false;
352d00f779eSVadim Pasternak }
353d00f779eSVadim Pasternak 
mlxreg_dpu_readable_reg(struct device * dev,unsigned int reg)354d00f779eSVadim Pasternak static bool mlxreg_dpu_readable_reg(struct device *dev, unsigned int reg)
355d00f779eSVadim Pasternak {
356d00f779eSVadim Pasternak 	switch (reg) {
357d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_VER_OFFSET:
358d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_PN_OFFSET:
359d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_PN1_OFFSET:
360d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_OFFSET:
361d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_EVENT_OFFSET:
362d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_MASK_OFFSET:
363d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_RESET_GP1_OFFSET:
364d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_RST_CAUSE1_OFFSET:
365d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP0_RO_OFFSET:
366d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP0_OFFSET:
367d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP1_OFFSET:
368d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP4_OFFSET:
369d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_AGGRCO_OFFSET:
370d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET:
371d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_OFFSET:
372d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET:
373d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_MASK_OFFSET:
374d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_MVER_OFFSET:
375d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_CONFIG3_OFFSET:
376d00f779eSVadim Pasternak 		return true;
377d00f779eSVadim Pasternak 	}
378d00f779eSVadim Pasternak 	return false;
379d00f779eSVadim Pasternak }
380d00f779eSVadim Pasternak 
mlxreg_dpu_volatile_reg(struct device * dev,unsigned int reg)381d00f779eSVadim Pasternak static bool mlxreg_dpu_volatile_reg(struct device *dev, unsigned int reg)
382d00f779eSVadim Pasternak {
383d00f779eSVadim Pasternak 	switch (reg) {
384d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_VER_OFFSET:
385d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_PN_OFFSET:
386d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_PN1_OFFSET:
387d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_OFFSET:
388d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_EVENT_OFFSET:
389d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_PG_MASK_OFFSET:
390d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_RESET_GP1_OFFSET:
391d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_RST_CAUSE1_OFFSET:
392d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP0_RO_OFFSET:
393d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP0_OFFSET:
394d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP1_OFFSET:
395d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_GP4_OFFSET:
396d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_AGGRCO_OFFSET:
397d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_AGGRCO_MASK_OFFSET:
398d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_OFFSET:
399d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_EVENT_OFFSET:
400d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_HEALTH_MASK_OFFSET:
401d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_FPGA1_MVER_OFFSET:
402d00f779eSVadim Pasternak 	case MLXREG_DPU_REG_CONFIG3_OFFSET:
403d00f779eSVadim Pasternak 		return true;
404d00f779eSVadim Pasternak 	}
405d00f779eSVadim Pasternak 	return false;
406d00f779eSVadim Pasternak }
407d00f779eSVadim Pasternak 
408d00f779eSVadim Pasternak /* Configuration for the register map of a device with 2 bytes address space. */
409d00f779eSVadim Pasternak static const struct regmap_config mlxreg_dpu_regmap_conf = {
410d00f779eSVadim Pasternak 	.reg_bits = 16,
411d00f779eSVadim Pasternak 	.val_bits = 8,
412d00f779eSVadim Pasternak 	.max_register = MLXREG_DPU_REG_MAX,
413d00f779eSVadim Pasternak 	.cache_type = REGCACHE_FLAT,
414d00f779eSVadim Pasternak 	.writeable_reg = mlxreg_dpu_writeable_reg,
415d00f779eSVadim Pasternak 	.readable_reg = mlxreg_dpu_readable_reg,
416d00f779eSVadim Pasternak 	.volatile_reg = mlxreg_dpu_volatile_reg,
417d00f779eSVadim Pasternak };
418d00f779eSVadim Pasternak 
419d00f779eSVadim Pasternak static int
mlxreg_dpu_copy_hotplug_data(struct device * dev,struct mlxreg_dpu * mlxreg_dpu,const struct mlxreg_core_hotplug_platform_data * hotplug_data)420d00f779eSVadim Pasternak mlxreg_dpu_copy_hotplug_data(struct device *dev, struct mlxreg_dpu *mlxreg_dpu,
421d00f779eSVadim Pasternak 			     const struct mlxreg_core_hotplug_platform_data *hotplug_data)
422d00f779eSVadim Pasternak {
423d00f779eSVadim Pasternak 	struct mlxreg_core_item *item;
424d00f779eSVadim Pasternak 	int i;
425d00f779eSVadim Pasternak 
426d00f779eSVadim Pasternak 	mlxreg_dpu->hotplug_data = devm_kmemdup(dev, hotplug_data,
427d00f779eSVadim Pasternak 						sizeof(*mlxreg_dpu->hotplug_data), GFP_KERNEL);
428d00f779eSVadim Pasternak 	if (!mlxreg_dpu->hotplug_data)
429d00f779eSVadim Pasternak 		return -ENOMEM;
430d00f779eSVadim Pasternak 
431d00f779eSVadim Pasternak 	mlxreg_dpu->hotplug_data->items = devm_kmemdup(dev, hotplug_data->items,
432d00f779eSVadim Pasternak 						       mlxreg_dpu->hotplug_data->count *
433d00f779eSVadim Pasternak 						       sizeof(*mlxreg_dpu->hotplug_data->items),
434d00f779eSVadim Pasternak 						       GFP_KERNEL);
435d00f779eSVadim Pasternak 	if (!mlxreg_dpu->hotplug_data->items)
436d00f779eSVadim Pasternak 		return -ENOMEM;
437d00f779eSVadim Pasternak 
438d00f779eSVadim Pasternak 	item = mlxreg_dpu->hotplug_data->items;
439d00f779eSVadim Pasternak 	for (i = 0; i < hotplug_data->count; i++, item++) {
440d00f779eSVadim Pasternak 		item->data = devm_kmemdup(dev, hotplug_data->items[i].data,
441d00f779eSVadim Pasternak 					  hotplug_data->items[i].count * sizeof(*item->data),
442d00f779eSVadim Pasternak 					  GFP_KERNEL);
443d00f779eSVadim Pasternak 		if (!item->data)
444d00f779eSVadim Pasternak 			return -ENOMEM;
445d00f779eSVadim Pasternak 	}
446d00f779eSVadim Pasternak 
447d00f779eSVadim Pasternak 	return 0;
448d00f779eSVadim Pasternak }
449d00f779eSVadim Pasternak 
mlxreg_dpu_config_init(struct mlxreg_dpu * mlxreg_dpu,void * regmap,struct mlxreg_core_data * data,int irq)450d00f779eSVadim Pasternak static int mlxreg_dpu_config_init(struct mlxreg_dpu *mlxreg_dpu, void *regmap,
451d00f779eSVadim Pasternak 				  struct mlxreg_core_data *data, int irq)
452d00f779eSVadim Pasternak {
453d00f779eSVadim Pasternak 	struct device *dev = &data->hpdev.client->dev;
454d00f779eSVadim Pasternak 	u32 regval;
455d00f779eSVadim Pasternak 	int err;
456d00f779eSVadim Pasternak 
457d00f779eSVadim Pasternak 	/* Validate DPU type. */
458d00f779eSVadim Pasternak 	err = regmap_read(regmap, MLXREG_DPU_REG_CONFIG3_OFFSET, &regval);
459d00f779eSVadim Pasternak 	if (err)
460d00f779eSVadim Pasternak 		return err;
461d00f779eSVadim Pasternak 
462d00f779eSVadim Pasternak 	switch (regval) {
463d00f779eSVadim Pasternak 	case MLXREG_DPU_BF3:
464d00f779eSVadim Pasternak 		/* Copy platform specific hotplug data. */
465d00f779eSVadim Pasternak 		err = mlxreg_dpu_copy_hotplug_data(dev, mlxreg_dpu,
466d00f779eSVadim Pasternak 						   &mlxreg_dpu_default_hotplug_data);
467d00f779eSVadim Pasternak 		if (err)
468d00f779eSVadim Pasternak 			return err;
469d00f779eSVadim Pasternak 
470d00f779eSVadim Pasternak 		mlxreg_dpu->io_data = &mlxreg_dpu_default_regs_io_data;
471d00f779eSVadim Pasternak 
472d00f779eSVadim Pasternak 		break;
473d00f779eSVadim Pasternak 	default:
474d00f779eSVadim Pasternak 		return -ENODEV;
475d00f779eSVadim Pasternak 	}
476d00f779eSVadim Pasternak 
477d00f779eSVadim Pasternak 	/* Register IO access driver. */
478d00f779eSVadim Pasternak 	if (mlxreg_dpu->io_data) {
479d00f779eSVadim Pasternak 		mlxreg_dpu->io_data->regmap = regmap;
480d00f779eSVadim Pasternak 		mlxreg_dpu->io_regs =
481d00f779eSVadim Pasternak 			platform_device_register_resndata(dev, "mlxreg-io",
482d00f779eSVadim Pasternak 							  data->slot, NULL, 0,
483d00f779eSVadim Pasternak 							  mlxreg_dpu->io_data,
484d00f779eSVadim Pasternak 							  sizeof(*mlxreg_dpu->io_data));
485d00f779eSVadim Pasternak 		if (IS_ERR(mlxreg_dpu->io_regs)) {
486d00f779eSVadim Pasternak 			dev_err(dev, "Failed to create regio for client %s at bus %d at addr 0x%02x\n",
487d00f779eSVadim Pasternak 				data->hpdev.brdinfo->type, data->hpdev.nr,
488d00f779eSVadim Pasternak 				data->hpdev.brdinfo->addr);
489d00f779eSVadim Pasternak 			return PTR_ERR(mlxreg_dpu->io_regs);
490d00f779eSVadim Pasternak 		}
491d00f779eSVadim Pasternak 	}
492d00f779eSVadim Pasternak 
493d00f779eSVadim Pasternak 	/* Register hotplug driver. */
494d00f779eSVadim Pasternak 	if (mlxreg_dpu->hotplug_data && irq) {
495d00f779eSVadim Pasternak 		mlxreg_dpu->hotplug_data->regmap = regmap;
496d00f779eSVadim Pasternak 		mlxreg_dpu->hotplug_data->irq = irq;
497d00f779eSVadim Pasternak 		mlxreg_dpu->hotplug =
498d00f779eSVadim Pasternak 			platform_device_register_resndata(dev, "mlxreg-hotplug",
499d00f779eSVadim Pasternak 							  data->slot, NULL, 0,
500d00f779eSVadim Pasternak 							  mlxreg_dpu->hotplug_data,
501d00f779eSVadim Pasternak 							  sizeof(*mlxreg_dpu->hotplug_data));
502d00f779eSVadim Pasternak 		if (IS_ERR(mlxreg_dpu->hotplug)) {
503d00f779eSVadim Pasternak 			err = PTR_ERR(mlxreg_dpu->hotplug);
504d00f779eSVadim Pasternak 			goto fail_register_hotplug;
505d00f779eSVadim Pasternak 		}
506d00f779eSVadim Pasternak 	}
507d00f779eSVadim Pasternak 
508d00f779eSVadim Pasternak 	return 0;
509d00f779eSVadim Pasternak 
510d00f779eSVadim Pasternak fail_register_hotplug:
511d00f779eSVadim Pasternak 	platform_device_unregister(mlxreg_dpu->io_regs);
512d00f779eSVadim Pasternak 
513d00f779eSVadim Pasternak 	return err;
514d00f779eSVadim Pasternak }
515d00f779eSVadim Pasternak 
mlxreg_dpu_config_exit(struct mlxreg_dpu * mlxreg_dpu)516d00f779eSVadim Pasternak static void mlxreg_dpu_config_exit(struct mlxreg_dpu *mlxreg_dpu)
517d00f779eSVadim Pasternak {
518d00f779eSVadim Pasternak 	platform_device_unregister(mlxreg_dpu->hotplug);
519d00f779eSVadim Pasternak 	platform_device_unregister(mlxreg_dpu->io_regs);
520d00f779eSVadim Pasternak }
521d00f779eSVadim Pasternak 
mlxreg_dpu_probe(struct platform_device * pdev)522d00f779eSVadim Pasternak static int mlxreg_dpu_probe(struct platform_device *pdev)
523d00f779eSVadim Pasternak {
524d00f779eSVadim Pasternak 	struct mlxreg_core_data *data;
525d00f779eSVadim Pasternak 	struct mlxreg_dpu *mlxreg_dpu;
526d00f779eSVadim Pasternak 	void *regmap;
527d00f779eSVadim Pasternak 	int err;
528d00f779eSVadim Pasternak 
529d00f779eSVadim Pasternak 	data = dev_get_platdata(&pdev->dev);
530d00f779eSVadim Pasternak 	if (!data || !data->hpdev.brdinfo)
531d00f779eSVadim Pasternak 		return -EINVAL;
532d00f779eSVadim Pasternak 
533d00f779eSVadim Pasternak 	data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr);
534d00f779eSVadim Pasternak 	if (!data->hpdev.adapter)
535d00f779eSVadim Pasternak 		return -EPROBE_DEFER;
536d00f779eSVadim Pasternak 
537d00f779eSVadim Pasternak 	mlxreg_dpu = devm_kzalloc(&pdev->dev, sizeof(*mlxreg_dpu), GFP_KERNEL);
538*f94ffc3fSVadim Pasternak 	if (!mlxreg_dpu) {
539*f94ffc3fSVadim Pasternak 		err = -ENOMEM;
540*f94ffc3fSVadim Pasternak 		goto alloc_fail;
541*f94ffc3fSVadim Pasternak 	}
542d00f779eSVadim Pasternak 
543d00f779eSVadim Pasternak 	/* Create device at the top of DPU I2C tree. */
544d00f779eSVadim Pasternak 	data->hpdev.client = i2c_new_client_device(data->hpdev.adapter,
545d00f779eSVadim Pasternak 						   data->hpdev.brdinfo);
546d00f779eSVadim Pasternak 	if (IS_ERR(data->hpdev.client)) {
547d00f779eSVadim Pasternak 		dev_err(&pdev->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
548d00f779eSVadim Pasternak 			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
549d00f779eSVadim Pasternak 		err = PTR_ERR(data->hpdev.client);
550d00f779eSVadim Pasternak 		goto i2c_new_device_fail;
551d00f779eSVadim Pasternak 	}
552d00f779eSVadim Pasternak 
553d00f779eSVadim Pasternak 	regmap = devm_regmap_init_i2c(data->hpdev.client, &mlxreg_dpu_regmap_conf);
554d00f779eSVadim Pasternak 	if (IS_ERR(regmap)) {
555d00f779eSVadim Pasternak 		dev_err(&pdev->dev, "Failed to create regmap for client %s at bus %d at addr 0x%02x\n",
556d00f779eSVadim Pasternak 			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
557d00f779eSVadim Pasternak 		err = PTR_ERR(regmap);
558d00f779eSVadim Pasternak 		goto devm_regmap_init_i2c_fail;
559d00f779eSVadim Pasternak 	}
560d00f779eSVadim Pasternak 
561d00f779eSVadim Pasternak 	/* Sync registers with hardware. */
562d00f779eSVadim Pasternak 	regcache_mark_dirty(regmap);
563d00f779eSVadim Pasternak 	err = regcache_sync(regmap);
564d00f779eSVadim Pasternak 	if (err) {
565d00f779eSVadim Pasternak 		dev_err(&pdev->dev, "Failed to sync regmap for client %s at bus %d at addr 0x%02x\n",
566d00f779eSVadim Pasternak 			data->hpdev.brdinfo->type, data->hpdev.nr, data->hpdev.brdinfo->addr);
567d00f779eSVadim Pasternak 		goto regcache_sync_fail;
568d00f779eSVadim Pasternak 	}
569d00f779eSVadim Pasternak 
570d00f779eSVadim Pasternak 	mlxreg_dpu->data = data;
571d00f779eSVadim Pasternak 	mlxreg_dpu->dev = &pdev->dev;
572d00f779eSVadim Pasternak 	platform_set_drvdata(pdev, mlxreg_dpu);
573d00f779eSVadim Pasternak 
574d00f779eSVadim Pasternak 	err = mlxreg_dpu_config_init(mlxreg_dpu, regmap, data, data->hpdev.brdinfo->irq);
575d00f779eSVadim Pasternak 	if (err)
576d00f779eSVadim Pasternak 		goto mlxreg_dpu_config_init_fail;
577d00f779eSVadim Pasternak 
578d00f779eSVadim Pasternak 	return err;
579d00f779eSVadim Pasternak 
580d00f779eSVadim Pasternak mlxreg_dpu_config_init_fail:
581d00f779eSVadim Pasternak regcache_sync_fail:
582d00f779eSVadim Pasternak devm_regmap_init_i2c_fail:
583d00f779eSVadim Pasternak 	i2c_unregister_device(data->hpdev.client);
584d00f779eSVadim Pasternak i2c_new_device_fail:
585*f94ffc3fSVadim Pasternak alloc_fail:
586d00f779eSVadim Pasternak 	i2c_put_adapter(data->hpdev.adapter);
587d00f779eSVadim Pasternak 	return err;
588d00f779eSVadim Pasternak }
589d00f779eSVadim Pasternak 
mlxreg_dpu_remove(struct platform_device * pdev)590d00f779eSVadim Pasternak static void mlxreg_dpu_remove(struct platform_device *pdev)
591d00f779eSVadim Pasternak {
592d00f779eSVadim Pasternak 	struct mlxreg_core_data *data = dev_get_platdata(&pdev->dev);
593d00f779eSVadim Pasternak 	struct mlxreg_dpu *mlxreg_dpu = platform_get_drvdata(pdev);
594d00f779eSVadim Pasternak 
595d00f779eSVadim Pasternak 	mlxreg_dpu_config_exit(mlxreg_dpu);
596d00f779eSVadim Pasternak 	i2c_unregister_device(data->hpdev.client);
597d00f779eSVadim Pasternak 	i2c_put_adapter(data->hpdev.adapter);
598d00f779eSVadim Pasternak }
599d00f779eSVadim Pasternak 
600d00f779eSVadim Pasternak static struct platform_driver mlxreg_dpu_driver = {
601d00f779eSVadim Pasternak 	.probe = mlxreg_dpu_probe,
602d00f779eSVadim Pasternak 	.remove = mlxreg_dpu_remove,
603d00f779eSVadim Pasternak 	.driver = {
604d00f779eSVadim Pasternak 		.name = "mlxreg-dpu",
605d00f779eSVadim Pasternak 	},
606d00f779eSVadim Pasternak };
607d00f779eSVadim Pasternak 
608d00f779eSVadim Pasternak module_platform_driver(mlxreg_dpu_driver);
609d00f779eSVadim Pasternak 
610d00f779eSVadim Pasternak MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>");
611d00f779eSVadim Pasternak MODULE_DESCRIPTION("Nvidia Data Processor Unit platform driver");
612d00f779eSVadim Pasternak MODULE_LICENSE("Dual BSD/GPL");
613d00f779eSVadim Pasternak MODULE_ALIAS("platform:mlxreg-dpu");
614