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