hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/mfd/max77620.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Maxim MAX77620 MFD Driver
34 *
....@@ -7,10 +8,6 @@
78 * Laxman Dewangan <ldewangan@nvidia.com>
89 * Chaitanya Bandi <bandik@nvidia.com>
910 * Mallikarjun Kasoju <mkasoju@nvidia.com>
10
- *
11
- * This program is free software; you can redistribute it and/or modify
12
- * it under the terms of the GNU General Public License version 2 as
13
- * published by the Free Software Foundation.
1411 */
1512
1613 /****************** Teminology used in driver ********************
....@@ -36,6 +33,8 @@
3633 #include <linux/of_device.h>
3734 #include <linux/regmap.h>
3835 #include <linux/slab.h>
36
+
37
+static struct max77620_chip *max77620_scratch;
3938
4039 static const struct resource gpio_resources[] = {
4140 DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
....@@ -111,6 +110,26 @@
111110 },
112111 };
113112
113
+static const struct mfd_cell max77663_children[] = {
114
+ { .name = "max77620-pinctrl", },
115
+ { .name = "max77620-clock", },
116
+ { .name = "max77663-pmic", },
117
+ { .name = "max77620-watchdog", },
118
+ {
119
+ .name = "max77620-gpio",
120
+ .resources = gpio_resources,
121
+ .num_resources = ARRAY_SIZE(gpio_resources),
122
+ }, {
123
+ .name = "max77620-rtc",
124
+ .resources = rtc_resources,
125
+ .num_resources = ARRAY_SIZE(rtc_resources),
126
+ }, {
127
+ .name = "max77663-power",
128
+ .resources = power_resources,
129
+ .num_resources = ARRAY_SIZE(power_resources),
130
+ },
131
+};
132
+
114133 static const struct regmap_range max77620_readable_ranges[] = {
115134 regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
116135 };
....@@ -158,6 +177,7 @@
158177 .rd_table = &max77620_readable_table,
159178 .wr_table = &max77620_writable_table,
160179 .volatile_table = &max77620_volatile_table,
180
+ .use_single_write = true,
161181 };
162182
163183 static const struct regmap_config max20024_regmap_config = {
....@@ -168,6 +188,35 @@
168188 .cache_type = REGCACHE_RBTREE,
169189 .rd_table = &max20024_readable_table,
170190 .wr_table = &max77620_writable_table,
191
+ .volatile_table = &max77620_volatile_table,
192
+};
193
+
194
+static const struct regmap_range max77663_readable_ranges[] = {
195
+ regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
196
+};
197
+
198
+static const struct regmap_access_table max77663_readable_table = {
199
+ .yes_ranges = max77663_readable_ranges,
200
+ .n_yes_ranges = ARRAY_SIZE(max77663_readable_ranges),
201
+};
202
+
203
+static const struct regmap_range max77663_writable_ranges[] = {
204
+ regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
205
+};
206
+
207
+static const struct regmap_access_table max77663_writable_table = {
208
+ .yes_ranges = max77663_writable_ranges,
209
+ .n_yes_ranges = ARRAY_SIZE(max77663_writable_ranges),
210
+};
211
+
212
+static const struct regmap_config max77663_regmap_config = {
213
+ .name = "power-slave",
214
+ .reg_bits = 8,
215
+ .val_bits = 8,
216
+ .max_register = MAX77620_REG_CID5 + 1,
217
+ .cache_type = REGCACHE_RBTREE,
218
+ .rd_table = &max77663_readable_table,
219
+ .wr_table = &max77663_writable_table,
171220 .volatile_table = &max77620_volatile_table,
172221 };
173222
....@@ -240,6 +289,9 @@
240289 case MAX77620:
241290 fps_min_period = MAX77620_FPS_PERIOD_MIN_US;
242291 break;
292
+ case MAX77663:
293
+ fps_min_period = MAX20024_FPS_PERIOD_MIN_US;
294
+ break;
243295 default:
244296 return -EINVAL;
245297 }
....@@ -274,18 +326,21 @@
274326 case MAX77620:
275327 fps_max_period = MAX77620_FPS_PERIOD_MAX_US;
276328 break;
329
+ case MAX77663:
330
+ fps_max_period = MAX20024_FPS_PERIOD_MAX_US;
331
+ break;
277332 default:
278333 return -EINVAL;
279334 }
280335
281336 for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
282337 sprintf(fps_name, "fps%d", fps_id);
283
- if (!strcmp(fps_np->name, fps_name))
338
+ if (of_node_name_eq(fps_np, fps_name))
284339 break;
285340 }
286341
287342 if (fps_id == MAX77620_FPS_COUNT) {
288
- dev_err(dev, "FPS node name %s is not valid\n", fps_np->name);
343
+ dev_err(dev, "FPS node name %pOFn is not valid\n", fps_np);
289344 return -EINVAL;
290345 }
291346
....@@ -362,9 +417,13 @@
362417
363418 for_each_child_of_node(fps_np, fps_child) {
364419 ret = max77620_config_fps(chip, fps_child);
365
- if (ret < 0)
420
+ if (ret < 0) {
421
+ of_node_put(fps_child);
422
+ of_node_put(fps_np);
366423 return ret;
424
+ }
367425 }
426
+ of_node_put(fps_np);
368427
369428 config = chip->enable_global_lpm ? MAX77620_ONOFFCNFG2_SLP_LPM_MSK : 0;
370429 ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
....@@ -375,6 +434,9 @@
375434 }
376435
377436 skip_fps:
437
+ if (chip->chip_id == MAX77663)
438
+ return 0;
439
+
378440 /* Enable wake on EN0 pin */
379441 ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
380442 MAX77620_ONOFFCNFG2_WK_EN0,
....@@ -423,6 +485,15 @@
423485 return ret;
424486 }
425487
488
+static void max77620_pm_power_off(void)
489
+{
490
+ struct max77620_chip *chip = max77620_scratch;
491
+
492
+ regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
493
+ MAX77620_ONOFFCNFG1_SFT_RST,
494
+ MAX77620_ONOFFCNFG1_SFT_RST);
495
+}
496
+
426497 static int max77620_probe(struct i2c_client *client,
427498 const struct i2c_device_id *id)
428499 {
....@@ -430,6 +501,7 @@
430501 struct max77620_chip *chip;
431502 const struct mfd_cell *mfd_cells;
432503 int n_mfd_cells;
504
+ bool pm_off;
433505 int ret;
434506
435507 chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
....@@ -438,7 +510,6 @@
438510
439511 i2c_set_clientdata(client, chip);
440512 chip->dev = &client->dev;
441
- chip->irq_base = -1;
442513 chip->chip_irq = client->irq;
443514 chip->chip_id = (enum max77620_chip_id)id->driver_data;
444515
....@@ -452,6 +523,11 @@
452523 mfd_cells = max20024_children;
453524 n_mfd_cells = ARRAY_SIZE(max20024_children);
454525 rmap_config = &max20024_regmap_config;
526
+ break;
527
+ case MAX77663:
528
+ mfd_cells = max77663_children;
529
+ n_mfd_cells = ARRAY_SIZE(max77663_children);
530
+ rmap_config = &max77663_regmap_config;
455531 break;
456532 default:
457533 dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id);
....@@ -471,8 +547,8 @@
471547
472548 max77620_top_irq_chip.irq_drv_data = chip;
473549 ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
474
- IRQF_ONESHOT | IRQF_SHARED,
475
- chip->irq_base, &max77620_top_irq_chip,
550
+ IRQF_ONESHOT | IRQF_SHARED, 0,
551
+ &max77620_top_irq_chip,
476552 &chip->top_irq_data);
477553 if (ret < 0) {
478554 dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret);
....@@ -489,6 +565,12 @@
489565 if (ret < 0) {
490566 dev_err(chip->dev, "Failed to add MFD children: %d\n", ret);
491567 return ret;
568
+ }
569
+
570
+ pm_off = of_device_is_system_power_controller(client->dev.of_node);
571
+ if (pm_off && !pm_power_off) {
572
+ max77620_scratch = chip;
573
+ pm_power_off = max77620_pm_power_off;
492574 }
493575
494576 return 0;
....@@ -546,6 +628,9 @@
546628 return ret;
547629 }
548630
631
+ if (chip->chip_id == MAX77663)
632
+ goto out;
633
+
549634 /* Disable WK_EN0 */
550635 ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
551636 MAX77620_ONOFFCNFG2_WK_EN0, 0);
....@@ -581,7 +666,7 @@
581666 * For MAX20024: No need to configure WKEN0 on resume as
582667 * it is configured on Init.
583668 */
584
- if (chip->chip_id == MAX20024)
669
+ if (chip->chip_id == MAX20024 || chip->chip_id == MAX77663)
585670 goto out;
586671
587672 /* Enable WK_EN0 */
....@@ -603,6 +688,7 @@
603688 static const struct i2c_device_id max77620_id[] = {
604689 {"max77620", MAX77620},
605690 {"max20024", MAX20024},
691
+ {"max77663", MAX77663},
606692 {},
607693 };
608694