xref: /linux/drivers/platform/mellanox/mlxreg-hotplug.c (revision e70140ba0d2b1a30467d4af6bcfe761327b9ec95)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Mellanox hotplug driver
4  *
5  * Copyright (C) 2016-2020 Mellanox Technologies
6  */
7 
8 #include <linux/bitops.h>
9 #include <linux/device.h>
10 #include <linux/hwmon.h>
11 #include <linux/hwmon-sysfs.h>
12 #include <linux/i2c.h>
13 #include <linux/interrupt.h>
14 #include <linux/module.h>
15 #include <linux/platform_data/mlxreg.h>
16 #include <linux/platform_device.h>
17 #include <linux/spinlock.h>
18 #include <linux/string_helpers.h>
19 #include <linux/regmap.h>
20 #include <linux/workqueue.h>
21 
22 /* Offset of event and mask registers from status register. */
23 #define MLXREG_HOTPLUG_EVENT_OFF	1
24 #define MLXREG_HOTPLUG_MASK_OFF		2
25 #define MLXREG_HOTPLUG_AGGR_MASK_OFF	1
26 
27 /* ASIC good health mask. */
28 #define MLXREG_HOTPLUG_GOOD_HEALTH_MASK	0x02
29 
30 #define MLXREG_HOTPLUG_ATTRS_MAX	128
31 #define MLXREG_HOTPLUG_NOT_ASSERT	3
32 
33 /**
34  * struct mlxreg_hotplug_priv_data - platform private data:
35  * @irq: platform device interrupt number;
36  * @dev: basic device;
37  * @pdev: platform device;
38  * @plat: platform data;
39  * @regmap: register map handle;
40  * @dwork_irq: delayed work template;
41  * @lock: spin lock;
42  * @hwmon: hwmon device;
43  * @mlxreg_hotplug_attr: sysfs attributes array;
44  * @mlxreg_hotplug_dev_attr: sysfs sensor device attribute array;
45  * @group: sysfs attribute group;
46  * @groups: list of sysfs attribute group for hwmon registration;
47  * @cell: location of top aggregation interrupt register;
48  * @mask: top aggregation interrupt common mask;
49  * @aggr_cache: last value of aggregation register status;
50  * @after_probe: flag indication probing completion;
51  * @not_asserted: number of entries in workqueue with no signal assertion;
52  */
53 struct mlxreg_hotplug_priv_data {
54 	int irq;
55 	struct device *dev;
56 	struct platform_device *pdev;
57 	struct mlxreg_hotplug_platform_data *plat;
58 	struct regmap *regmap;
59 	struct delayed_work dwork_irq;
60 	spinlock_t lock; /* sync with interrupt */
61 	struct device *hwmon;
62 	struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
63 	struct sensor_device_attribute_2
64 			mlxreg_hotplug_dev_attr[MLXREG_HOTPLUG_ATTRS_MAX];
65 	struct attribute_group group;
66 	const struct attribute_group *groups[2];
67 	u32 cell;
68 	u32 mask;
69 	u32 aggr_cache;
70 	bool after_probe;
71 	u8 not_asserted;
72 };
73 
74 /* Environment variables array for udev. */
75 static char *mlxreg_hotplug_udev_envp[] = { NULL, NULL };
76 
77 static int
mlxreg_hotplug_udev_event_send(struct kobject * kobj,struct mlxreg_core_data * data,bool action)78 mlxreg_hotplug_udev_event_send(struct kobject *kobj,
79 			       struct mlxreg_core_data *data, bool action)
80 {
81 	char event_str[MLXREG_CORE_LABEL_MAX_SIZE + 2];
82 	char label[MLXREG_CORE_LABEL_MAX_SIZE] = { 0 };
83 
84 	mlxreg_hotplug_udev_envp[0] = event_str;
85 	string_upper(label, data->label);
86 	snprintf(event_str, MLXREG_CORE_LABEL_MAX_SIZE, "%s=%d", label, !!action);
87 
88 	return kobject_uevent_env(kobj, KOBJ_CHANGE, mlxreg_hotplug_udev_envp);
89 }
90 
91 static void
mlxreg_hotplug_pdata_export(void * pdata,void * regmap)92 mlxreg_hotplug_pdata_export(void *pdata, void *regmap)
93 {
94 	struct mlxreg_core_hotplug_platform_data *dev_pdata = pdata;
95 
96 	/* Export regmap to underlying device. */
97 	dev_pdata->regmap = regmap;
98 }
99 
mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data * priv,struct mlxreg_core_data * data,enum mlxreg_hotplug_kind kind)100 static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
101 					struct mlxreg_core_data *data,
102 					enum mlxreg_hotplug_kind kind)
103 {
104 	struct i2c_board_info *brdinfo = data->hpdev.brdinfo;
105 	struct mlxreg_core_hotplug_platform_data *pdata;
106 	struct i2c_client *client;
107 
108 	/* Notify user by sending hwmon uevent. */
109 	mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, true);
110 
111 	/*
112 	 * Return if adapter number is negative. It could be in case hotplug
113 	 * event is not associated with hotplug device.
114 	 */
115 	if (data->hpdev.nr < 0 && data->hpdev.action != MLXREG_HOTPLUG_DEVICE_NO_ACTION)
116 		return 0;
117 
118 	pdata = dev_get_platdata(&priv->pdev->dev);
119 	switch (data->hpdev.action) {
120 	case MLXREG_HOTPLUG_DEVICE_DEFAULT_ACTION:
121 		data->hpdev.adapter = i2c_get_adapter(data->hpdev.nr +
122 						      pdata->shift_nr);
123 		if (!data->hpdev.adapter) {
124 			dev_err(priv->dev, "Failed to get adapter for bus %d\n",
125 				data->hpdev.nr + pdata->shift_nr);
126 			return -EFAULT;
127 		}
128 
129 		/* Export platform data to underlying device. */
130 		if (brdinfo->platform_data)
131 			mlxreg_hotplug_pdata_export(brdinfo->platform_data, pdata->regmap);
132 
133 		client = i2c_new_client_device(data->hpdev.adapter,
134 					       brdinfo);
135 		if (IS_ERR(client)) {
136 			dev_err(priv->dev, "Failed to create client %s at bus %d at addr 0x%02x\n",
137 				brdinfo->type, data->hpdev.nr +
138 				pdata->shift_nr, brdinfo->addr);
139 
140 			i2c_put_adapter(data->hpdev.adapter);
141 			data->hpdev.adapter = NULL;
142 			return PTR_ERR(client);
143 		}
144 
145 		data->hpdev.client = client;
146 		break;
147 	case MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION:
148 		/* Export platform data to underlying device. */
149 		if (data->hpdev.brdinfo && data->hpdev.brdinfo->platform_data)
150 			mlxreg_hotplug_pdata_export(data->hpdev.brdinfo->platform_data,
151 						    pdata->regmap);
152 		/* Pass parent hotplug device handle to underlying device. */
153 		data->notifier = data->hpdev.notifier;
154 		data->hpdev.pdev = platform_device_register_resndata(&priv->pdev->dev,
155 								     brdinfo->type,
156 								     data->hpdev.nr,
157 								     NULL, 0, data,
158 								     sizeof(*data));
159 		if (IS_ERR(data->hpdev.pdev))
160 			return PTR_ERR(data->hpdev.pdev);
161 
162 		break;
163 	default:
164 		break;
165 	}
166 
167 	if (data->hpdev.notifier && data->hpdev.notifier->user_handler)
168 		return data->hpdev.notifier->user_handler(data->hpdev.notifier->handle, kind, 1);
169 
170 	return 0;
171 }
172 
173 static void
mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data * priv,struct mlxreg_core_data * data,enum mlxreg_hotplug_kind kind)174 mlxreg_hotplug_device_destroy(struct mlxreg_hotplug_priv_data *priv,
175 			      struct mlxreg_core_data *data,
176 			      enum mlxreg_hotplug_kind kind)
177 {
178 	/* Notify user by sending hwmon uevent. */
179 	mlxreg_hotplug_udev_event_send(&priv->hwmon->kobj, data, false);
180 	if (data->hpdev.notifier && data->hpdev.notifier->user_handler)
181 		data->hpdev.notifier->user_handler(data->hpdev.notifier->handle, kind, 0);
182 
183 	switch (data->hpdev.action) {
184 	case MLXREG_HOTPLUG_DEVICE_DEFAULT_ACTION:
185 		if (data->hpdev.client) {
186 			i2c_unregister_device(data->hpdev.client);
187 			data->hpdev.client = NULL;
188 		}
189 
190 		if (data->hpdev.adapter) {
191 			i2c_put_adapter(data->hpdev.adapter);
192 			data->hpdev.adapter = NULL;
193 		}
194 		break;
195 	case MLXREG_HOTPLUG_DEVICE_PLATFORM_ACTION:
196 		if (data->hpdev.pdev)
197 			platform_device_unregister(data->hpdev.pdev);
198 		break;
199 	default:
200 		break;
201 	}
202 }
203 
mlxreg_hotplug_attr_show(struct device * dev,struct device_attribute * attr,char * buf)204 static ssize_t mlxreg_hotplug_attr_show(struct device *dev,
205 					struct device_attribute *attr,
206 					char *buf)
207 {
208 	struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(dev);
209 	struct mlxreg_core_hotplug_platform_data *pdata;
210 	int index = to_sensor_dev_attr_2(attr)->index;
211 	int nr = to_sensor_dev_attr_2(attr)->nr;
212 	struct mlxreg_core_item *item;
213 	struct mlxreg_core_data *data;
214 	u32 regval;
215 	int ret;
216 
217 	pdata = dev_get_platdata(&priv->pdev->dev);
218 	item = pdata->items + nr;
219 	data = item->data + index;
220 
221 	ret = regmap_read(priv->regmap, data->reg, &regval);
222 	if (ret)
223 		return ret;
224 
225 	if (item->health) {
226 		regval &= data->mask;
227 	} else {
228 		/* Bit = 0 : functional if item->inversed is true. */
229 		if (item->inversed)
230 			regval = !(regval & data->mask);
231 		else
232 			regval = !!(regval & data->mask);
233 	}
234 
235 	return sprintf(buf, "%u\n", regval);
236 }
237 
238 #define PRIV_ATTR(i) priv->mlxreg_hotplug_attr[i]
239 #define PRIV_DEV_ATTR(i) priv->mlxreg_hotplug_dev_attr[i]
240 
mlxreg_hotplug_item_label_index_get(u32 mask,u32 bit)241 static int mlxreg_hotplug_item_label_index_get(u32 mask, u32 bit)
242 {
243 	int i, j;
244 
245 	for (i = 0, j = -1; i <= bit; i++) {
246 		if (mask & BIT(i))
247 			j++;
248 	}
249 	return j;
250 }
251 
mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data * priv)252 static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
253 {
254 	struct mlxreg_core_hotplug_platform_data *pdata;
255 	struct mlxreg_core_item *item;
256 	struct mlxreg_core_data *data;
257 	unsigned long mask;
258 	u32 regval;
259 	int num_attrs = 0, id = 0, i, j, k, count, ret;
260 
261 	pdata = dev_get_platdata(&priv->pdev->dev);
262 	item = pdata->items;
263 
264 	/* Go over all kinds of items - psu, pwr, fan. */
265 	for (i = 0; i < pdata->counter; i++, item++) {
266 		if (item->capability) {
267 			/*
268 			 * Read group capability register to get actual number
269 			 * of interrupt capable components and set group mask
270 			 * accordingly.
271 			 */
272 			ret = regmap_read(priv->regmap, item->capability,
273 					  &regval);
274 			if (ret)
275 				return ret;
276 
277 			item->mask = GENMASK((regval & item->mask) - 1, 0);
278 		}
279 
280 		data = item->data;
281 
282 		/* Go over all unmasked units within item. */
283 		mask = item->mask;
284 		k = 0;
285 		count = item->ind ? item->ind : item->count;
286 		for_each_set_bit(j, &mask, count) {
287 			if (data->capability) {
288 				/*
289 				 * Read capability register and skip non
290 				 * relevant attributes.
291 				 */
292 				ret = regmap_read(priv->regmap,
293 						  data->capability, &regval);
294 				if (ret)
295 					return ret;
296 
297 				if (!(regval & data->bit)) {
298 					data++;
299 					continue;
300 				}
301 			}
302 
303 			PRIV_ATTR(id) = &PRIV_DEV_ATTR(id).dev_attr.attr;
304 			PRIV_ATTR(id)->name = devm_kasprintf(&priv->pdev->dev,
305 							     GFP_KERNEL,
306 							     data->label);
307 			if (!PRIV_ATTR(id)->name) {
308 				dev_err(priv->dev, "Memory allocation failed for attr %d.\n",
309 					id);
310 				return -ENOMEM;
311 			}
312 
313 			PRIV_DEV_ATTR(id).dev_attr.attr.name =
314 							PRIV_ATTR(id)->name;
315 			PRIV_DEV_ATTR(id).dev_attr.attr.mode = 0444;
316 			PRIV_DEV_ATTR(id).dev_attr.show =
317 						mlxreg_hotplug_attr_show;
318 			PRIV_DEV_ATTR(id).nr = i;
319 			PRIV_DEV_ATTR(id).index = k;
320 			sysfs_attr_init(&PRIV_DEV_ATTR(id).dev_attr.attr);
321 			data++;
322 			id++;
323 			k++;
324 		}
325 		num_attrs += k;
326 	}
327 
328 	priv->group.attrs = devm_kcalloc(&priv->pdev->dev,
329 					 num_attrs,
330 					 sizeof(struct attribute *),
331 					 GFP_KERNEL);
332 	if (!priv->group.attrs)
333 		return -ENOMEM;
334 
335 	priv->group.attrs = priv->mlxreg_hotplug_attr;
336 	priv->groups[0] = &priv->group;
337 	priv->groups[1] = NULL;
338 
339 	return 0;
340 }
341 
342 static void
mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data * priv,struct mlxreg_core_item * item)343 mlxreg_hotplug_work_helper(struct mlxreg_hotplug_priv_data *priv,
344 			   struct mlxreg_core_item *item)
345 {
346 	struct mlxreg_core_data *data;
347 	unsigned long asserted;
348 	u32 regval, bit;
349 	int ret;
350 
351 	/* Mask event. */
352 	ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
353 			   0);
354 	if (ret)
355 		goto out;
356 
357 	/* Read status. */
358 	ret = regmap_read(priv->regmap, item->reg, &regval);
359 	if (ret)
360 		goto out;
361 
362 	/* Set asserted bits and save last status. */
363 	regval &= item->mask;
364 	asserted = item->cache ^ regval;
365 	item->cache = regval;
366 	for_each_set_bit(bit, &asserted, 8) {
367 		int pos;
368 
369 		pos = mlxreg_hotplug_item_label_index_get(item->mask, bit);
370 		if (pos < 0)
371 			goto out;
372 
373 		data = item->data + pos;
374 		if (regval & BIT(bit)) {
375 			if (item->inversed)
376 				mlxreg_hotplug_device_destroy(priv, data, item->kind);
377 			else
378 				mlxreg_hotplug_device_create(priv, data, item->kind);
379 		} else {
380 			if (item->inversed)
381 				mlxreg_hotplug_device_create(priv, data, item->kind);
382 			else
383 				mlxreg_hotplug_device_destroy(priv, data, item->kind);
384 		}
385 	}
386 
387 	/* Acknowledge event. */
388 	ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF,
389 			   0);
390 	if (ret)
391 		goto out;
392 
393 	/* Unmask event. */
394 	ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
395 			   item->mask);
396 
397  out:
398 	if (ret)
399 		dev_err(priv->dev, "Failed to complete workqueue.\n");
400 }
401 
402 static void
mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data * priv,struct mlxreg_core_item * item)403 mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
404 				  struct mlxreg_core_item *item)
405 {
406 	struct mlxreg_core_data *data = item->data;
407 	u32 regval;
408 	int i, ret = 0;
409 
410 	for (i = 0; i < item->count; i++, data++) {
411 		/* Mask event. */
412 		ret = regmap_write(priv->regmap, data->reg +
413 				   MLXREG_HOTPLUG_MASK_OFF, 0);
414 		if (ret)
415 			goto out;
416 
417 		/* Read status. */
418 		ret = regmap_read(priv->regmap, data->reg, &regval);
419 		if (ret)
420 			goto out;
421 
422 		regval &= data->mask;
423 
424 		if (item->cache == regval)
425 			goto ack_event;
426 
427 		/*
428 		 * ASIC health indication is provided through two bits. Bits
429 		 * value 0x2 indicates that ASIC reached the good health, value
430 		 * 0x0 indicates ASIC the bad health or dormant state and value
431 		 * 0x3 indicates the booting state. During ASIC reset it should
432 		 * pass the following states: dormant -> booting -> good.
433 		 */
434 		if (regval == MLXREG_HOTPLUG_GOOD_HEALTH_MASK) {
435 			if (!data->attached) {
436 				/*
437 				 * ASIC is in steady state. Connect associated
438 				 * device, if configured.
439 				 */
440 				mlxreg_hotplug_device_create(priv, data, item->kind);
441 				data->attached = true;
442 			}
443 		} else {
444 			if (data->attached) {
445 				/*
446 				 * ASIC health is failed after ASIC has been
447 				 * in steady state. Disconnect associated
448 				 * device, if it has been connected.
449 				 */
450 				mlxreg_hotplug_device_destroy(priv, data, item->kind);
451 				data->attached = false;
452 				data->health_cntr = 0;
453 			}
454 		}
455 		item->cache = regval;
456 ack_event:
457 		/* Acknowledge event. */
458 		ret = regmap_write(priv->regmap, data->reg +
459 				   MLXREG_HOTPLUG_EVENT_OFF, 0);
460 		if (ret)
461 			goto out;
462 
463 		/* Unmask event. */
464 		ret = regmap_write(priv->regmap, data->reg +
465 				   MLXREG_HOTPLUG_MASK_OFF, data->mask);
466 		if (ret)
467 			goto out;
468 	}
469 
470  out:
471 	if (ret)
472 		dev_err(priv->dev, "Failed to complete workqueue.\n");
473 }
474 
475 /*
476  * mlxreg_hotplug_work_handler - performs traversing of device interrupt
477  * registers according to the below hierarchy schema:
478  *
479  *				Aggregation registers (status/mask)
480  * PSU registers:		*---*
481  * *-----------------*		|   |
482  * |status/event/mask|----->    | * |
483  * *-----------------*		|   |
484  * Power registers:		|   |
485  * *-----------------*		|   |
486  * |status/event/mask|----->    | * |
487  * *-----------------*		|   |
488  * FAN registers:		|   |--> CPU
489  * *-----------------*		|   |
490  * |status/event/mask|----->    | * |
491  * *-----------------*		|   |
492  * ASIC registers:		|   |
493  * *-----------------*		|   |
494  * |status/event/mask|----->    | * |
495  * *-----------------*		|   |
496  *				*---*
497  *
498  * In case some system changed are detected: FAN in/out, PSU in/out, power
499  * cable attached/detached, ASIC health good/bad, relevant device is created
500  * or destroyed.
501  */
mlxreg_hotplug_work_handler(struct work_struct * work)502 static void mlxreg_hotplug_work_handler(struct work_struct *work)
503 {
504 	struct mlxreg_core_hotplug_platform_data *pdata;
505 	struct mlxreg_hotplug_priv_data *priv;
506 	struct mlxreg_core_item *item;
507 	u32 regval, aggr_asserted;
508 	unsigned long flags;
509 	int i, ret;
510 
511 	priv = container_of(work, struct mlxreg_hotplug_priv_data,
512 			    dwork_irq.work);
513 	pdata = dev_get_platdata(&priv->pdev->dev);
514 	item = pdata->items;
515 
516 	/* Mask aggregation event. */
517 	ret = regmap_write(priv->regmap, pdata->cell +
518 			   MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
519 	if (ret < 0)
520 		goto out;
521 
522 	/* Read aggregation status. */
523 	ret = regmap_read(priv->regmap, pdata->cell, &regval);
524 	if (ret)
525 		goto out;
526 
527 	regval &= pdata->mask;
528 	aggr_asserted = priv->aggr_cache ^ regval;
529 	priv->aggr_cache = regval;
530 
531 	/*
532 	 * Handler is invoked, but no assertion is detected at top aggregation
533 	 * status level. Set aggr_asserted to mask value to allow handler extra
534 	 * run over all relevant signals to recover any missed signal.
535 	 */
536 	if (priv->not_asserted == MLXREG_HOTPLUG_NOT_ASSERT) {
537 		priv->not_asserted = 0;
538 		aggr_asserted = pdata->mask;
539 	}
540 	if (!aggr_asserted)
541 		goto unmask_event;
542 
543 	/* Handle topology and health configuration changes. */
544 	for (i = 0; i < pdata->counter; i++, item++) {
545 		if (aggr_asserted & item->aggr_mask) {
546 			if (item->health)
547 				mlxreg_hotplug_health_work_helper(priv, item);
548 			else
549 				mlxreg_hotplug_work_helper(priv, item);
550 		}
551 	}
552 
553 	spin_lock_irqsave(&priv->lock, flags);
554 
555 	/*
556 	 * It is possible, that some signals have been inserted, while
557 	 * interrupt has been masked by mlxreg_hotplug_work_handler. In this
558 	 * case such signals will be missed. In order to handle these signals
559 	 * delayed work is canceled and work task re-scheduled for immediate
560 	 * execution. It allows to handle missed signals, if any. In other case
561 	 * work handler just validates that no new signals have been received
562 	 * during masking.
563 	 */
564 	cancel_delayed_work(&priv->dwork_irq);
565 	schedule_delayed_work(&priv->dwork_irq, 0);
566 
567 	spin_unlock_irqrestore(&priv->lock, flags);
568 
569 	return;
570 
571 unmask_event:
572 	priv->not_asserted++;
573 	/* Unmask aggregation event (no need acknowledge). */
574 	ret = regmap_write(priv->regmap, pdata->cell +
575 			   MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
576 
577  out:
578 	if (ret)
579 		dev_err(priv->dev, "Failed to complete workqueue.\n");
580 }
581 
mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data * priv)582 static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
583 {
584 	struct mlxreg_core_hotplug_platform_data *pdata;
585 	struct mlxreg_core_item *item;
586 	struct mlxreg_core_data *data;
587 	u32 regval;
588 	int i, j, ret;
589 
590 	pdata = dev_get_platdata(&priv->pdev->dev);
591 	item = pdata->items;
592 
593 	for (i = 0; i < pdata->counter; i++, item++) {
594 		/* Clear group presense event. */
595 		ret = regmap_write(priv->regmap, item->reg +
596 				   MLXREG_HOTPLUG_EVENT_OFF, 0);
597 		if (ret)
598 			goto out;
599 
600 		/*
601 		 * Verify if hardware configuration requires to disable
602 		 * interrupt capability for some of components.
603 		 */
604 		data = item->data;
605 		for (j = 0; j < item->count; j++, data++) {
606 			/* Verify if the attribute has capability register. */
607 			if (data->capability) {
608 				/* Read capability register. */
609 				ret = regmap_read(priv->regmap,
610 						  data->capability, &regval);
611 				if (ret)
612 					goto out;
613 
614 				if (!(regval & data->bit))
615 					item->mask &= ~BIT(j);
616 			}
617 		}
618 
619 		/* Set group initial status as mask and unmask group event. */
620 		if (item->inversed) {
621 			item->cache = item->mask;
622 			ret = regmap_write(priv->regmap, item->reg +
623 					   MLXREG_HOTPLUG_MASK_OFF,
624 					   item->mask);
625 			if (ret)
626 				goto out;
627 		}
628 	}
629 
630 	/* Keep aggregation initial status as zero and unmask events. */
631 	ret = regmap_write(priv->regmap, pdata->cell +
632 			   MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
633 	if (ret)
634 		goto out;
635 
636 	/* Keep low aggregation initial status as zero and unmask events. */
637 	if (pdata->cell_low) {
638 		ret = regmap_write(priv->regmap, pdata->cell_low +
639 				   MLXREG_HOTPLUG_AGGR_MASK_OFF,
640 				   pdata->mask_low);
641 		if (ret)
642 			goto out;
643 	}
644 
645 	/* Invoke work handler for initializing hot plug devices setting. */
646 	mlxreg_hotplug_work_handler(&priv->dwork_irq.work);
647 
648  out:
649 	if (ret)
650 		dev_err(priv->dev, "Failed to set interrupts.\n");
651 	enable_irq(priv->irq);
652 	return ret;
653 }
654 
mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data * priv)655 static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
656 {
657 	struct mlxreg_core_hotplug_platform_data *pdata;
658 	struct mlxreg_core_item *item;
659 	struct mlxreg_core_data *data;
660 	int count, i, j;
661 
662 	pdata = dev_get_platdata(&priv->pdev->dev);
663 	item = pdata->items;
664 	disable_irq(priv->irq);
665 	cancel_delayed_work_sync(&priv->dwork_irq);
666 
667 	/* Mask low aggregation event, if defined. */
668 	if (pdata->cell_low)
669 		regmap_write(priv->regmap, pdata->cell_low +
670 			     MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
671 
672 	/* Mask aggregation event. */
673 	regmap_write(priv->regmap, pdata->cell + MLXREG_HOTPLUG_AGGR_MASK_OFF,
674 		     0);
675 
676 	/* Clear topology configurations. */
677 	for (i = 0; i < pdata->counter; i++, item++) {
678 		data = item->data;
679 		/* Mask group presense event. */
680 		regmap_write(priv->regmap, data->reg + MLXREG_HOTPLUG_MASK_OFF,
681 			     0);
682 		/* Clear group presense event. */
683 		regmap_write(priv->regmap, data->reg +
684 			     MLXREG_HOTPLUG_EVENT_OFF, 0);
685 
686 		/* Remove all the attached devices in group. */
687 		count = item->count;
688 		for (j = 0; j < count; j++, data++)
689 			mlxreg_hotplug_device_destroy(priv, data, item->kind);
690 	}
691 }
692 
mlxreg_hotplug_irq_handler(int irq,void * dev)693 static irqreturn_t mlxreg_hotplug_irq_handler(int irq, void *dev)
694 {
695 	struct mlxreg_hotplug_priv_data *priv;
696 
697 	priv = (struct mlxreg_hotplug_priv_data *)dev;
698 
699 	/* Schedule work task for immediate execution.*/
700 	schedule_delayed_work(&priv->dwork_irq, 0);
701 
702 	return IRQ_HANDLED;
703 }
704 
mlxreg_hotplug_probe(struct platform_device * pdev)705 static int mlxreg_hotplug_probe(struct platform_device *pdev)
706 {
707 	struct mlxreg_core_hotplug_platform_data *pdata;
708 	struct mlxreg_hotplug_priv_data *priv;
709 	struct i2c_adapter *deferred_adap;
710 	int err;
711 
712 	pdata = dev_get_platdata(&pdev->dev);
713 	if (!pdata) {
714 		dev_err(&pdev->dev, "Failed to get platform data.\n");
715 		return -EINVAL;
716 	}
717 
718 	/* Defer probing if the necessary adapter is not configured yet. */
719 	deferred_adap = i2c_get_adapter(pdata->deferred_nr);
720 	if (!deferred_adap)
721 		return -EPROBE_DEFER;
722 	i2c_put_adapter(deferred_adap);
723 
724 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
725 	if (!priv)
726 		return -ENOMEM;
727 
728 	if (pdata->irq) {
729 		priv->irq = pdata->irq;
730 	} else {
731 		priv->irq = platform_get_irq(pdev, 0);
732 		if (priv->irq < 0)
733 			return priv->irq;
734 	}
735 
736 	priv->regmap = pdata->regmap;
737 	priv->dev = pdev->dev.parent;
738 	priv->pdev = pdev;
739 
740 	err = devm_request_irq(&pdev->dev, priv->irq,
741 			       mlxreg_hotplug_irq_handler, IRQF_TRIGGER_FALLING
742 			       | IRQF_SHARED, "mlxreg-hotplug", priv);
743 	if (err) {
744 		dev_err(&pdev->dev, "Failed to request irq: %d\n", err);
745 		return err;
746 	}
747 
748 	disable_irq(priv->irq);
749 	spin_lock_init(&priv->lock);
750 	INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler);
751 	dev_set_drvdata(&pdev->dev, priv);
752 
753 	err = mlxreg_hotplug_attr_init(priv);
754 	if (err) {
755 		dev_err(&pdev->dev, "Failed to allocate attributes: %d\n",
756 			err);
757 		return err;
758 	}
759 
760 	priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
761 					"mlxreg_hotplug", priv, priv->groups);
762 	if (IS_ERR(priv->hwmon)) {
763 		dev_err(&pdev->dev, "Failed to register hwmon device %ld\n",
764 			PTR_ERR(priv->hwmon));
765 		return PTR_ERR(priv->hwmon);
766 	}
767 
768 	/* Perform initial interrupts setup. */
769 	mlxreg_hotplug_set_irq(priv);
770 	priv->after_probe = true;
771 
772 	return 0;
773 }
774 
mlxreg_hotplug_remove(struct platform_device * pdev)775 static void mlxreg_hotplug_remove(struct platform_device *pdev)
776 {
777 	struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(&pdev->dev);
778 
779 	/* Clean interrupts setup. */
780 	mlxreg_hotplug_unset_irq(priv);
781 	devm_free_irq(&pdev->dev, priv->irq, priv);
782 }
783 
784 static struct platform_driver mlxreg_hotplug_driver = {
785 	.driver = {
786 		.name = "mlxreg-hotplug",
787 	},
788 	.probe = mlxreg_hotplug_probe,
789 	.remove = mlxreg_hotplug_remove,
790 };
791 
792 module_platform_driver(mlxreg_hotplug_driver);
793 
794 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
795 MODULE_DESCRIPTION("Mellanox regmap hotplug platform driver");
796 MODULE_LICENSE("Dual BSD/GPL");
797 MODULE_ALIAS("platform:mlxreg-hotplug");
798