mlxreg-hotplug.c 21 KB

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