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, ®val);
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