GNU Linux-libre 6.7.9-gnu
[releases.git] / drivers / platform / mellanox / mlxreg-hotplug.c
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
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
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
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
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
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
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
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
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         /*
352          * Validate if item related to received signal type is valid.
353          * It should never happen, excepted the situation when some
354          * piece of hardware is broken. In such situation just produce
355          * error message and return. Caller must continue to handle the
356          * signals from other devices if any.
357          */
358         if (unlikely(!item)) {
359                 dev_err(priv->dev, "False signal: at offset:mask 0x%02x:0x%02x.\n",
360                         item->reg, item->mask);
361
362                 return;
363         }
364
365         /* Mask event. */
366         ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
367                            0);
368         if (ret)
369                 goto out;
370
371         /* Read status. */
372         ret = regmap_read(priv->regmap, item->reg, &regval);
373         if (ret)
374                 goto out;
375
376         /* Set asserted bits and save last status. */
377         regval &= item->mask;
378         asserted = item->cache ^ regval;
379         item->cache = regval;
380         for_each_set_bit(bit, &asserted, 8) {
381                 int pos;
382
383                 pos = mlxreg_hotplug_item_label_index_get(item->mask, bit);
384                 if (pos < 0)
385                         goto out;
386
387                 data = item->data + pos;
388                 if (regval & BIT(bit)) {
389                         if (item->inversed)
390                                 mlxreg_hotplug_device_destroy(priv, data, item->kind);
391                         else
392                                 mlxreg_hotplug_device_create(priv, data, item->kind);
393                 } else {
394                         if (item->inversed)
395                                 mlxreg_hotplug_device_create(priv, data, item->kind);
396                         else
397                                 mlxreg_hotplug_device_destroy(priv, data, item->kind);
398                 }
399         }
400
401         /* Acknowledge event. */
402         ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_EVENT_OFF,
403                            0);
404         if (ret)
405                 goto out;
406
407         /* Unmask event. */
408         ret = regmap_write(priv->regmap, item->reg + MLXREG_HOTPLUG_MASK_OFF,
409                            item->mask);
410
411  out:
412         if (ret)
413                 dev_err(priv->dev, "Failed to complete workqueue.\n");
414 }
415
416 static void
417 mlxreg_hotplug_health_work_helper(struct mlxreg_hotplug_priv_data *priv,
418                                   struct mlxreg_core_item *item)
419 {
420         struct mlxreg_core_data *data = item->data;
421         u32 regval;
422         int i, ret = 0;
423
424         for (i = 0; i < item->count; i++, data++) {
425                 /* Mask event. */
426                 ret = regmap_write(priv->regmap, data->reg +
427                                    MLXREG_HOTPLUG_MASK_OFF, 0);
428                 if (ret)
429                         goto out;
430
431                 /* Read status. */
432                 ret = regmap_read(priv->regmap, data->reg, &regval);
433                 if (ret)
434                         goto out;
435
436                 regval &= data->mask;
437
438                 if (item->cache == regval)
439                         goto ack_event;
440
441                 /*
442                  * ASIC health indication is provided through two bits. Bits
443                  * value 0x2 indicates that ASIC reached the good health, value
444                  * 0x0 indicates ASIC the bad health or dormant state and value
445                  * 0x3 indicates the booting state. During ASIC reset it should
446                  * pass the following states: dormant -> booting -> good.
447                  */
448                 if (regval == MLXREG_HOTPLUG_GOOD_HEALTH_MASK) {
449                         if (!data->attached) {
450                                 /*
451                                  * ASIC is in steady state. Connect associated
452                                  * device, if configured.
453                                  */
454                                 mlxreg_hotplug_device_create(priv, data, item->kind);
455                                 data->attached = true;
456                         }
457                 } else {
458                         if (data->attached) {
459                                 /*
460                                  * ASIC health is failed after ASIC has been
461                                  * in steady state. Disconnect associated
462                                  * device, if it has been connected.
463                                  */
464                                 mlxreg_hotplug_device_destroy(priv, data, item->kind);
465                                 data->attached = false;
466                                 data->health_cntr = 0;
467                         }
468                 }
469                 item->cache = regval;
470 ack_event:
471                 /* Acknowledge event. */
472                 ret = regmap_write(priv->regmap, data->reg +
473                                    MLXREG_HOTPLUG_EVENT_OFF, 0);
474                 if (ret)
475                         goto out;
476
477                 /* Unmask event. */
478                 ret = regmap_write(priv->regmap, data->reg +
479                                    MLXREG_HOTPLUG_MASK_OFF, data->mask);
480                 if (ret)
481                         goto out;
482         }
483
484  out:
485         if (ret)
486                 dev_err(priv->dev, "Failed to complete workqueue.\n");
487 }
488
489 /*
490  * mlxreg_hotplug_work_handler - performs traversing of device interrupt
491  * registers according to the below hierarchy schema:
492  *
493  *                              Aggregation registers (status/mask)
494  * PSU registers:               *---*
495  * *-----------------*          |   |
496  * |status/event/mask|----->    | * |
497  * *-----------------*          |   |
498  * Power registers:             |   |
499  * *-----------------*          |   |
500  * |status/event/mask|----->    | * |
501  * *-----------------*          |   |
502  * FAN registers:               |   |--> CPU
503  * *-----------------*          |   |
504  * |status/event/mask|----->    | * |
505  * *-----------------*          |   |
506  * ASIC registers:              |   |
507  * *-----------------*          |   |
508  * |status/event/mask|----->    | * |
509  * *-----------------*          |   |
510  *                              *---*
511  *
512  * In case some system changed are detected: FAN in/out, PSU in/out, power
513  * cable attached/detached, ASIC health good/bad, relevant device is created
514  * or destroyed.
515  */
516 static void mlxreg_hotplug_work_handler(struct work_struct *work)
517 {
518         struct mlxreg_core_hotplug_platform_data *pdata;
519         struct mlxreg_hotplug_priv_data *priv;
520         struct mlxreg_core_item *item;
521         u32 regval, aggr_asserted;
522         unsigned long flags;
523         int i, ret;
524
525         priv = container_of(work, struct mlxreg_hotplug_priv_data,
526                             dwork_irq.work);
527         pdata = dev_get_platdata(&priv->pdev->dev);
528         item = pdata->items;
529
530         /* Mask aggregation event. */
531         ret = regmap_write(priv->regmap, pdata->cell +
532                            MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
533         if (ret < 0)
534                 goto out;
535
536         /* Read aggregation status. */
537         ret = regmap_read(priv->regmap, pdata->cell, &regval);
538         if (ret)
539                 goto out;
540
541         regval &= pdata->mask;
542         aggr_asserted = priv->aggr_cache ^ regval;
543         priv->aggr_cache = regval;
544
545         /*
546          * Handler is invoked, but no assertion is detected at top aggregation
547          * status level. Set aggr_asserted to mask value to allow handler extra
548          * run over all relevant signals to recover any missed signal.
549          */
550         if (priv->not_asserted == MLXREG_HOTPLUG_NOT_ASSERT) {
551                 priv->not_asserted = 0;
552                 aggr_asserted = pdata->mask;
553         }
554         if (!aggr_asserted)
555                 goto unmask_event;
556
557         /* Handle topology and health configuration changes. */
558         for (i = 0; i < pdata->counter; i++, item++) {
559                 if (aggr_asserted & item->aggr_mask) {
560                         if (item->health)
561                                 mlxreg_hotplug_health_work_helper(priv, item);
562                         else
563                                 mlxreg_hotplug_work_helper(priv, item);
564                 }
565         }
566
567         spin_lock_irqsave(&priv->lock, flags);
568
569         /*
570          * It is possible, that some signals have been inserted, while
571          * interrupt has been masked by mlxreg_hotplug_work_handler. In this
572          * case such signals will be missed. In order to handle these signals
573          * delayed work is canceled and work task re-scheduled for immediate
574          * execution. It allows to handle missed signals, if any. In other case
575          * work handler just validates that no new signals have been received
576          * during masking.
577          */
578         cancel_delayed_work(&priv->dwork_irq);
579         schedule_delayed_work(&priv->dwork_irq, 0);
580
581         spin_unlock_irqrestore(&priv->lock, flags);
582
583         return;
584
585 unmask_event:
586         priv->not_asserted++;
587         /* Unmask aggregation event (no need acknowledge). */
588         ret = regmap_write(priv->regmap, pdata->cell +
589                            MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
590
591  out:
592         if (ret)
593                 dev_err(priv->dev, "Failed to complete workqueue.\n");
594 }
595
596 static int mlxreg_hotplug_set_irq(struct mlxreg_hotplug_priv_data *priv)
597 {
598         struct mlxreg_core_hotplug_platform_data *pdata;
599         struct mlxreg_core_item *item;
600         struct mlxreg_core_data *data;
601         u32 regval;
602         int i, j, ret;
603
604         pdata = dev_get_platdata(&priv->pdev->dev);
605         item = pdata->items;
606
607         for (i = 0; i < pdata->counter; i++, item++) {
608                 /* Clear group presense event. */
609                 ret = regmap_write(priv->regmap, item->reg +
610                                    MLXREG_HOTPLUG_EVENT_OFF, 0);
611                 if (ret)
612                         goto out;
613
614                 /*
615                  * Verify if hardware configuration requires to disable
616                  * interrupt capability for some of components.
617                  */
618                 data = item->data;
619                 for (j = 0; j < item->count; j++, data++) {
620                         /* Verify if the attribute has capability register. */
621                         if (data->capability) {
622                                 /* Read capability register. */
623                                 ret = regmap_read(priv->regmap,
624                                                   data->capability, &regval);
625                                 if (ret)
626                                         goto out;
627
628                                 if (!(regval & data->bit))
629                                         item->mask &= ~BIT(j);
630                         }
631                 }
632
633                 /* Set group initial status as mask and unmask group event. */
634                 if (item->inversed) {
635                         item->cache = item->mask;
636                         ret = regmap_write(priv->regmap, item->reg +
637                                            MLXREG_HOTPLUG_MASK_OFF,
638                                            item->mask);
639                         if (ret)
640                                 goto out;
641                 }
642         }
643
644         /* Keep aggregation initial status as zero and unmask events. */
645         ret = regmap_write(priv->regmap, pdata->cell +
646                            MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
647         if (ret)
648                 goto out;
649
650         /* Keep low aggregation initial status as zero and unmask events. */
651         if (pdata->cell_low) {
652                 ret = regmap_write(priv->regmap, pdata->cell_low +
653                                    MLXREG_HOTPLUG_AGGR_MASK_OFF,
654                                    pdata->mask_low);
655                 if (ret)
656                         goto out;
657         }
658
659         /* Invoke work handler for initializing hot plug devices setting. */
660         mlxreg_hotplug_work_handler(&priv->dwork_irq.work);
661
662  out:
663         if (ret)
664                 dev_err(priv->dev, "Failed to set interrupts.\n");
665         enable_irq(priv->irq);
666         return ret;
667 }
668
669 static void mlxreg_hotplug_unset_irq(struct mlxreg_hotplug_priv_data *priv)
670 {
671         struct mlxreg_core_hotplug_platform_data *pdata;
672         struct mlxreg_core_item *item;
673         struct mlxreg_core_data *data;
674         int count, i, j;
675
676         pdata = dev_get_platdata(&priv->pdev->dev);
677         item = pdata->items;
678         disable_irq(priv->irq);
679         cancel_delayed_work_sync(&priv->dwork_irq);
680
681         /* Mask low aggregation event, if defined. */
682         if (pdata->cell_low)
683                 regmap_write(priv->regmap, pdata->cell_low +
684                              MLXREG_HOTPLUG_AGGR_MASK_OFF, 0);
685
686         /* Mask aggregation event. */
687         regmap_write(priv->regmap, pdata->cell + MLXREG_HOTPLUG_AGGR_MASK_OFF,
688                      0);
689
690         /* Clear topology configurations. */
691         for (i = 0; i < pdata->counter; i++, item++) {
692                 data = item->data;
693                 /* Mask group presense event. */
694                 regmap_write(priv->regmap, data->reg + MLXREG_HOTPLUG_MASK_OFF,
695                              0);
696                 /* Clear group presense event. */
697                 regmap_write(priv->regmap, data->reg +
698                              MLXREG_HOTPLUG_EVENT_OFF, 0);
699
700                 /* Remove all the attached devices in group. */
701                 count = item->count;
702                 for (j = 0; j < count; j++, data++)
703                         mlxreg_hotplug_device_destroy(priv, data, item->kind);
704         }
705 }
706
707 static irqreturn_t mlxreg_hotplug_irq_handler(int irq, void *dev)
708 {
709         struct mlxreg_hotplug_priv_data *priv;
710
711         priv = (struct mlxreg_hotplug_priv_data *)dev;
712
713         /* Schedule work task for immediate execution.*/
714         schedule_delayed_work(&priv->dwork_irq, 0);
715
716         return IRQ_HANDLED;
717 }
718
719 static int mlxreg_hotplug_probe(struct platform_device *pdev)
720 {
721         struct mlxreg_core_hotplug_platform_data *pdata;
722         struct mlxreg_hotplug_priv_data *priv;
723         struct i2c_adapter *deferred_adap;
724         int err;
725
726         pdata = dev_get_platdata(&pdev->dev);
727         if (!pdata) {
728                 dev_err(&pdev->dev, "Failed to get platform data.\n");
729                 return -EINVAL;
730         }
731
732         /* Defer probing if the necessary adapter is not configured yet. */
733         deferred_adap = i2c_get_adapter(pdata->deferred_nr);
734         if (!deferred_adap)
735                 return -EPROBE_DEFER;
736         i2c_put_adapter(deferred_adap);
737
738         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
739         if (!priv)
740                 return -ENOMEM;
741
742         if (pdata->irq) {
743                 priv->irq = pdata->irq;
744         } else {
745                 priv->irq = platform_get_irq(pdev, 0);
746                 if (priv->irq < 0)
747                         return priv->irq;
748         }
749
750         priv->regmap = pdata->regmap;
751         priv->dev = pdev->dev.parent;
752         priv->pdev = pdev;
753
754         err = devm_request_irq(&pdev->dev, priv->irq,
755                                mlxreg_hotplug_irq_handler, IRQF_TRIGGER_FALLING
756                                | IRQF_SHARED, "mlxreg-hotplug", priv);
757         if (err) {
758                 dev_err(&pdev->dev, "Failed to request irq: %d\n", err);
759                 return err;
760         }
761
762         disable_irq(priv->irq);
763         spin_lock_init(&priv->lock);
764         INIT_DELAYED_WORK(&priv->dwork_irq, mlxreg_hotplug_work_handler);
765         dev_set_drvdata(&pdev->dev, priv);
766
767         err = mlxreg_hotplug_attr_init(priv);
768         if (err) {
769                 dev_err(&pdev->dev, "Failed to allocate attributes: %d\n",
770                         err);
771                 return err;
772         }
773
774         priv->hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
775                                         "mlxreg_hotplug", priv, priv->groups);
776         if (IS_ERR(priv->hwmon)) {
777                 dev_err(&pdev->dev, "Failed to register hwmon device %ld\n",
778                         PTR_ERR(priv->hwmon));
779                 return PTR_ERR(priv->hwmon);
780         }
781
782         /* Perform initial interrupts setup. */
783         mlxreg_hotplug_set_irq(priv);
784         priv->after_probe = true;
785
786         return 0;
787 }
788
789 static void mlxreg_hotplug_remove(struct platform_device *pdev)
790 {
791         struct mlxreg_hotplug_priv_data *priv = dev_get_drvdata(&pdev->dev);
792
793         /* Clean interrupts setup. */
794         mlxreg_hotplug_unset_irq(priv);
795         devm_free_irq(&pdev->dev, priv->irq, priv);
796 }
797
798 static struct platform_driver mlxreg_hotplug_driver = {
799         .driver = {
800                 .name = "mlxreg-hotplug",
801         },
802         .probe = mlxreg_hotplug_probe,
803         .remove_new = mlxreg_hotplug_remove,
804 };
805
806 module_platform_driver(mlxreg_hotplug_driver);
807
808 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
809 MODULE_DESCRIPTION("Mellanox regmap hotplug platform driver");
810 MODULE_LICENSE("Dual BSD/GPL");
811 MODULE_ALIAS("platform:mlxreg-hotplug");