1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Maxim MAX77620 MFD Driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author:
8*4882a593Smuzhiyun * Laxman Dewangan <ldewangan@nvidia.com>
9*4882a593Smuzhiyun * Chaitanya Bandi <bandik@nvidia.com>
10*4882a593Smuzhiyun * Mallikarjun Kasoju <mkasoju@nvidia.com>
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun /****************** Teminology used in driver ********************
14*4882a593Smuzhiyun * Here are some terminology used from datasheet for quick reference:
15*4882a593Smuzhiyun * Flexible Power Sequence (FPS):
16*4882a593Smuzhiyun * The Flexible Power Sequencer (FPS) allows each regulator to power up under
17*4882a593Smuzhiyun * hardware or software control. Additionally, each regulator can power on
18*4882a593Smuzhiyun * independently or among a group of other regulators with an adjustable
19*4882a593Smuzhiyun * power-up and power-down delays (sequencing). GPIO1, GPIO2, and GPIO3 can
20*4882a593Smuzhiyun * be programmed to be part of a sequence allowing external regulators to be
21*4882a593Smuzhiyun * sequenced along with internal regulators. 32KHz clock can be programmed to
22*4882a593Smuzhiyun * be part of a sequence.
23*4882a593Smuzhiyun * There is 3 FPS confguration registers and all resources are configured to
24*4882a593Smuzhiyun * any of these FPS or no FPS.
25*4882a593Smuzhiyun */
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <linux/i2c.h>
28*4882a593Smuzhiyun #include <linux/interrupt.h>
29*4882a593Smuzhiyun #include <linux/mfd/core.h>
30*4882a593Smuzhiyun #include <linux/mfd/max77620.h>
31*4882a593Smuzhiyun #include <linux/init.h>
32*4882a593Smuzhiyun #include <linux/of.h>
33*4882a593Smuzhiyun #include <linux/of_device.h>
34*4882a593Smuzhiyun #include <linux/regmap.h>
35*4882a593Smuzhiyun #include <linux/slab.h>
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static struct max77620_chip *max77620_scratch;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun static const struct resource gpio_resources[] = {
40*4882a593Smuzhiyun DEFINE_RES_IRQ(MAX77620_IRQ_TOP_GPIO),
41*4882a593Smuzhiyun };
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun static const struct resource power_resources[] = {
44*4882a593Smuzhiyun DEFINE_RES_IRQ(MAX77620_IRQ_LBT_MBATLOW),
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static const struct resource rtc_resources[] = {
48*4882a593Smuzhiyun DEFINE_RES_IRQ(MAX77620_IRQ_TOP_RTC),
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun static const struct resource thermal_resources[] = {
52*4882a593Smuzhiyun DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM1),
53*4882a593Smuzhiyun DEFINE_RES_IRQ(MAX77620_IRQ_LBT_TJALRM2),
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun static const struct regmap_irq max77620_top_irqs[] = {
57*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_TOP_GLBL, 0, MAX77620_IRQ_TOP_GLBL_MASK),
58*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_TOP_SD, 0, MAX77620_IRQ_TOP_SD_MASK),
59*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_TOP_LDO, 0, MAX77620_IRQ_TOP_LDO_MASK),
60*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_TOP_GPIO, 0, MAX77620_IRQ_TOP_GPIO_MASK),
61*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_TOP_RTC, 0, MAX77620_IRQ_TOP_RTC_MASK),
62*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_TOP_32K, 0, MAX77620_IRQ_TOP_32K_MASK),
63*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_TOP_ONOFF, 0, MAX77620_IRQ_TOP_ONOFF_MASK),
64*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_LBT_MBATLOW, 1, MAX77620_IRQ_LBM_MASK),
65*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM1, 1, MAX77620_IRQ_TJALRM1_MASK),
66*4882a593Smuzhiyun REGMAP_IRQ_REG(MAX77620_IRQ_LBT_TJALRM2, 1, MAX77620_IRQ_TJALRM2_MASK),
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun static const struct mfd_cell max77620_children[] = {
70*4882a593Smuzhiyun { .name = "max77620-pinctrl", },
71*4882a593Smuzhiyun { .name = "max77620-clock", },
72*4882a593Smuzhiyun { .name = "max77620-pmic", },
73*4882a593Smuzhiyun { .name = "max77620-watchdog", },
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun .name = "max77620-gpio",
76*4882a593Smuzhiyun .resources = gpio_resources,
77*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(gpio_resources),
78*4882a593Smuzhiyun }, {
79*4882a593Smuzhiyun .name = "max77620-rtc",
80*4882a593Smuzhiyun .resources = rtc_resources,
81*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(rtc_resources),
82*4882a593Smuzhiyun }, {
83*4882a593Smuzhiyun .name = "max77620-power",
84*4882a593Smuzhiyun .resources = power_resources,
85*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(power_resources),
86*4882a593Smuzhiyun }, {
87*4882a593Smuzhiyun .name = "max77620-thermal",
88*4882a593Smuzhiyun .resources = thermal_resources,
89*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(thermal_resources),
90*4882a593Smuzhiyun },
91*4882a593Smuzhiyun };
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun static const struct mfd_cell max20024_children[] = {
94*4882a593Smuzhiyun { .name = "max20024-pinctrl", },
95*4882a593Smuzhiyun { .name = "max77620-clock", },
96*4882a593Smuzhiyun { .name = "max20024-pmic", },
97*4882a593Smuzhiyun { .name = "max77620-watchdog", },
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun .name = "max77620-gpio",
100*4882a593Smuzhiyun .resources = gpio_resources,
101*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(gpio_resources),
102*4882a593Smuzhiyun }, {
103*4882a593Smuzhiyun .name = "max77620-rtc",
104*4882a593Smuzhiyun .resources = rtc_resources,
105*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(rtc_resources),
106*4882a593Smuzhiyun }, {
107*4882a593Smuzhiyun .name = "max20024-power",
108*4882a593Smuzhiyun .resources = power_resources,
109*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(power_resources),
110*4882a593Smuzhiyun },
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun static const struct mfd_cell max77663_children[] = {
114*4882a593Smuzhiyun { .name = "max77620-pinctrl", },
115*4882a593Smuzhiyun { .name = "max77620-clock", },
116*4882a593Smuzhiyun { .name = "max77663-pmic", },
117*4882a593Smuzhiyun { .name = "max77620-watchdog", },
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun .name = "max77620-gpio",
120*4882a593Smuzhiyun .resources = gpio_resources,
121*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(gpio_resources),
122*4882a593Smuzhiyun }, {
123*4882a593Smuzhiyun .name = "max77620-rtc",
124*4882a593Smuzhiyun .resources = rtc_resources,
125*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(rtc_resources),
126*4882a593Smuzhiyun }, {
127*4882a593Smuzhiyun .name = "max77663-power",
128*4882a593Smuzhiyun .resources = power_resources,
129*4882a593Smuzhiyun .num_resources = ARRAY_SIZE(power_resources),
130*4882a593Smuzhiyun },
131*4882a593Smuzhiyun };
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun static const struct regmap_range max77620_readable_ranges[] = {
134*4882a593Smuzhiyun regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun static const struct regmap_access_table max77620_readable_table = {
138*4882a593Smuzhiyun .yes_ranges = max77620_readable_ranges,
139*4882a593Smuzhiyun .n_yes_ranges = ARRAY_SIZE(max77620_readable_ranges),
140*4882a593Smuzhiyun };
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun static const struct regmap_range max20024_readable_ranges[] = {
143*4882a593Smuzhiyun regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
144*4882a593Smuzhiyun regmap_reg_range(MAX20024_REG_MAX_ADD, MAX20024_REG_MAX_ADD),
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun static const struct regmap_access_table max20024_readable_table = {
148*4882a593Smuzhiyun .yes_ranges = max20024_readable_ranges,
149*4882a593Smuzhiyun .n_yes_ranges = ARRAY_SIZE(max20024_readable_ranges),
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun static const struct regmap_range max77620_writable_ranges[] = {
153*4882a593Smuzhiyun regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_DVSSD4),
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun static const struct regmap_access_table max77620_writable_table = {
157*4882a593Smuzhiyun .yes_ranges = max77620_writable_ranges,
158*4882a593Smuzhiyun .n_yes_ranges = ARRAY_SIZE(max77620_writable_ranges),
159*4882a593Smuzhiyun };
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun static const struct regmap_range max77620_cacheable_ranges[] = {
162*4882a593Smuzhiyun regmap_reg_range(MAX77620_REG_SD0_CFG, MAX77620_REG_LDO_CFG3),
163*4882a593Smuzhiyun regmap_reg_range(MAX77620_REG_FPS_CFG0, MAX77620_REG_FPS_SD3),
164*4882a593Smuzhiyun };
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun static const struct regmap_access_table max77620_volatile_table = {
167*4882a593Smuzhiyun .no_ranges = max77620_cacheable_ranges,
168*4882a593Smuzhiyun .n_no_ranges = ARRAY_SIZE(max77620_cacheable_ranges),
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun static const struct regmap_config max77620_regmap_config = {
172*4882a593Smuzhiyun .name = "power-slave",
173*4882a593Smuzhiyun .reg_bits = 8,
174*4882a593Smuzhiyun .val_bits = 8,
175*4882a593Smuzhiyun .max_register = MAX77620_REG_DVSSD4 + 1,
176*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
177*4882a593Smuzhiyun .rd_table = &max77620_readable_table,
178*4882a593Smuzhiyun .wr_table = &max77620_writable_table,
179*4882a593Smuzhiyun .volatile_table = &max77620_volatile_table,
180*4882a593Smuzhiyun .use_single_write = true,
181*4882a593Smuzhiyun };
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun static const struct regmap_config max20024_regmap_config = {
184*4882a593Smuzhiyun .name = "power-slave",
185*4882a593Smuzhiyun .reg_bits = 8,
186*4882a593Smuzhiyun .val_bits = 8,
187*4882a593Smuzhiyun .max_register = MAX20024_REG_MAX_ADD + 1,
188*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
189*4882a593Smuzhiyun .rd_table = &max20024_readable_table,
190*4882a593Smuzhiyun .wr_table = &max77620_writable_table,
191*4882a593Smuzhiyun .volatile_table = &max77620_volatile_table,
192*4882a593Smuzhiyun };
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun static const struct regmap_range max77663_readable_ranges[] = {
195*4882a593Smuzhiyun regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun static const struct regmap_access_table max77663_readable_table = {
199*4882a593Smuzhiyun .yes_ranges = max77663_readable_ranges,
200*4882a593Smuzhiyun .n_yes_ranges = ARRAY_SIZE(max77663_readable_ranges),
201*4882a593Smuzhiyun };
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun static const struct regmap_range max77663_writable_ranges[] = {
204*4882a593Smuzhiyun regmap_reg_range(MAX77620_REG_CNFGGLBL1, MAX77620_REG_CID5),
205*4882a593Smuzhiyun };
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun static const struct regmap_access_table max77663_writable_table = {
208*4882a593Smuzhiyun .yes_ranges = max77663_writable_ranges,
209*4882a593Smuzhiyun .n_yes_ranges = ARRAY_SIZE(max77663_writable_ranges),
210*4882a593Smuzhiyun };
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun static const struct regmap_config max77663_regmap_config = {
213*4882a593Smuzhiyun .name = "power-slave",
214*4882a593Smuzhiyun .reg_bits = 8,
215*4882a593Smuzhiyun .val_bits = 8,
216*4882a593Smuzhiyun .max_register = MAX77620_REG_CID5 + 1,
217*4882a593Smuzhiyun .cache_type = REGCACHE_RBTREE,
218*4882a593Smuzhiyun .rd_table = &max77663_readable_table,
219*4882a593Smuzhiyun .wr_table = &max77663_writable_table,
220*4882a593Smuzhiyun .volatile_table = &max77620_volatile_table,
221*4882a593Smuzhiyun };
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /*
224*4882a593Smuzhiyun * MAX77620 and MAX20024 has the following steps of the interrupt handling
225*4882a593Smuzhiyun * for TOP interrupts:
226*4882a593Smuzhiyun * 1. When interrupt occurs from PMIC, mask the PMIC interrupt by setting GLBLM.
227*4882a593Smuzhiyun * 2. Read IRQTOP and service the interrupt.
228*4882a593Smuzhiyun * 3. Once all interrupts has been checked and serviced, the interrupt service
229*4882a593Smuzhiyun * routine un-masks the hardware interrupt line by clearing GLBLM.
230*4882a593Smuzhiyun */
max77620_irq_global_mask(void * irq_drv_data)231*4882a593Smuzhiyun static int max77620_irq_global_mask(void *irq_drv_data)
232*4882a593Smuzhiyun {
233*4882a593Smuzhiyun struct max77620_chip *chip = irq_drv_data;
234*4882a593Smuzhiyun int ret;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT,
237*4882a593Smuzhiyun MAX77620_GLBLM_MASK, MAX77620_GLBLM_MASK);
238*4882a593Smuzhiyun if (ret < 0)
239*4882a593Smuzhiyun dev_err(chip->dev, "Failed to set GLBLM: %d\n", ret);
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun return ret;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
max77620_irq_global_unmask(void * irq_drv_data)244*4882a593Smuzhiyun static int max77620_irq_global_unmask(void *irq_drv_data)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct max77620_chip *chip = irq_drv_data;
247*4882a593Smuzhiyun int ret;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_INTENLBT,
250*4882a593Smuzhiyun MAX77620_GLBLM_MASK, 0);
251*4882a593Smuzhiyun if (ret < 0)
252*4882a593Smuzhiyun dev_err(chip->dev, "Failed to reset GLBLM: %d\n", ret);
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return ret;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun static struct regmap_irq_chip max77620_top_irq_chip = {
258*4882a593Smuzhiyun .name = "max77620-top",
259*4882a593Smuzhiyun .irqs = max77620_top_irqs,
260*4882a593Smuzhiyun .num_irqs = ARRAY_SIZE(max77620_top_irqs),
261*4882a593Smuzhiyun .num_regs = 2,
262*4882a593Smuzhiyun .status_base = MAX77620_REG_IRQTOP,
263*4882a593Smuzhiyun .mask_base = MAX77620_REG_IRQTOPM,
264*4882a593Smuzhiyun .handle_pre_irq = max77620_irq_global_mask,
265*4882a593Smuzhiyun .handle_post_irq = max77620_irq_global_unmask,
266*4882a593Smuzhiyun };
267*4882a593Smuzhiyun
268*4882a593Smuzhiyun /* max77620_get_fps_period_reg_value: Get FPS bit field value from
269*4882a593Smuzhiyun * requested periods.
270*4882a593Smuzhiyun * MAX77620 supports the FPS period of 40, 80, 160, 320, 540, 1280, 2560
271*4882a593Smuzhiyun * and 5120 microseconds. MAX20024 supports the FPS period of 20, 40, 80,
272*4882a593Smuzhiyun * 160, 320, 540, 1280 and 2560 microseconds.
273*4882a593Smuzhiyun * The FPS register has 3 bits field to set the FPS period as
274*4882a593Smuzhiyun * bits max77620 max20024
275*4882a593Smuzhiyun * 000 40 20
276*4882a593Smuzhiyun * 001 80 40
277*4882a593Smuzhiyun * :::
278*4882a593Smuzhiyun */
max77620_get_fps_period_reg_value(struct max77620_chip * chip,int tperiod)279*4882a593Smuzhiyun static int max77620_get_fps_period_reg_value(struct max77620_chip *chip,
280*4882a593Smuzhiyun int tperiod)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun int fps_min_period;
283*4882a593Smuzhiyun int i;
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun switch (chip->chip_id) {
286*4882a593Smuzhiyun case MAX20024:
287*4882a593Smuzhiyun fps_min_period = MAX20024_FPS_PERIOD_MIN_US;
288*4882a593Smuzhiyun break;
289*4882a593Smuzhiyun case MAX77620:
290*4882a593Smuzhiyun fps_min_period = MAX77620_FPS_PERIOD_MIN_US;
291*4882a593Smuzhiyun break;
292*4882a593Smuzhiyun case MAX77663:
293*4882a593Smuzhiyun fps_min_period = MAX20024_FPS_PERIOD_MIN_US;
294*4882a593Smuzhiyun break;
295*4882a593Smuzhiyun default:
296*4882a593Smuzhiyun return -EINVAL;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun for (i = 0; i < 7; i++) {
300*4882a593Smuzhiyun if (fps_min_period >= tperiod)
301*4882a593Smuzhiyun return i;
302*4882a593Smuzhiyun fps_min_period *= 2;
303*4882a593Smuzhiyun }
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun return i;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun /* max77620_config_fps: Configure FPS configuration registers
309*4882a593Smuzhiyun * based on platform specific information.
310*4882a593Smuzhiyun */
max77620_config_fps(struct max77620_chip * chip,struct device_node * fps_np)311*4882a593Smuzhiyun static int max77620_config_fps(struct max77620_chip *chip,
312*4882a593Smuzhiyun struct device_node *fps_np)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun struct device *dev = chip->dev;
315*4882a593Smuzhiyun unsigned int mask = 0, config = 0;
316*4882a593Smuzhiyun u32 fps_max_period;
317*4882a593Smuzhiyun u32 param_val;
318*4882a593Smuzhiyun int tperiod, fps_id;
319*4882a593Smuzhiyun int ret;
320*4882a593Smuzhiyun char fps_name[10];
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun switch (chip->chip_id) {
323*4882a593Smuzhiyun case MAX20024:
324*4882a593Smuzhiyun fps_max_period = MAX20024_FPS_PERIOD_MAX_US;
325*4882a593Smuzhiyun break;
326*4882a593Smuzhiyun case MAX77620:
327*4882a593Smuzhiyun fps_max_period = MAX77620_FPS_PERIOD_MAX_US;
328*4882a593Smuzhiyun break;
329*4882a593Smuzhiyun case MAX77663:
330*4882a593Smuzhiyun fps_max_period = MAX20024_FPS_PERIOD_MAX_US;
331*4882a593Smuzhiyun break;
332*4882a593Smuzhiyun default:
333*4882a593Smuzhiyun return -EINVAL;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
337*4882a593Smuzhiyun sprintf(fps_name, "fps%d", fps_id);
338*4882a593Smuzhiyun if (of_node_name_eq(fps_np, fps_name))
339*4882a593Smuzhiyun break;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun if (fps_id == MAX77620_FPS_COUNT) {
343*4882a593Smuzhiyun dev_err(dev, "FPS node name %pOFn is not valid\n", fps_np);
344*4882a593Smuzhiyun return -EINVAL;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun ret = of_property_read_u32(fps_np, "maxim,shutdown-fps-time-period-us",
348*4882a593Smuzhiyun ¶m_val);
349*4882a593Smuzhiyun if (!ret) {
350*4882a593Smuzhiyun mask |= MAX77620_FPS_TIME_PERIOD_MASK;
351*4882a593Smuzhiyun chip->shutdown_fps_period[fps_id] = min(param_val,
352*4882a593Smuzhiyun fps_max_period);
353*4882a593Smuzhiyun tperiod = max77620_get_fps_period_reg_value(chip,
354*4882a593Smuzhiyun chip->shutdown_fps_period[fps_id]);
355*4882a593Smuzhiyun config |= tperiod << MAX77620_FPS_TIME_PERIOD_SHIFT;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun ret = of_property_read_u32(fps_np, "maxim,suspend-fps-time-period-us",
359*4882a593Smuzhiyun ¶m_val);
360*4882a593Smuzhiyun if (!ret)
361*4882a593Smuzhiyun chip->suspend_fps_period[fps_id] = min(param_val,
362*4882a593Smuzhiyun fps_max_period);
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun ret = of_property_read_u32(fps_np, "maxim,fps-event-source",
365*4882a593Smuzhiyun ¶m_val);
366*4882a593Smuzhiyun if (!ret) {
367*4882a593Smuzhiyun if (param_val > 2) {
368*4882a593Smuzhiyun dev_err(dev, "FPS%d event-source invalid\n", fps_id);
369*4882a593Smuzhiyun return -EINVAL;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun mask |= MAX77620_FPS_EN_SRC_MASK;
372*4882a593Smuzhiyun config |= param_val << MAX77620_FPS_EN_SRC_SHIFT;
373*4882a593Smuzhiyun if (param_val == 2) {
374*4882a593Smuzhiyun mask |= MAX77620_FPS_ENFPS_SW_MASK;
375*4882a593Smuzhiyun config |= MAX77620_FPS_ENFPS_SW;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun if (!chip->sleep_enable && !chip->enable_global_lpm) {
380*4882a593Smuzhiyun ret = of_property_read_u32(fps_np,
381*4882a593Smuzhiyun "maxim,device-state-on-disabled-event",
382*4882a593Smuzhiyun ¶m_val);
383*4882a593Smuzhiyun if (!ret) {
384*4882a593Smuzhiyun if (param_val == 0)
385*4882a593Smuzhiyun chip->sleep_enable = true;
386*4882a593Smuzhiyun else if (param_val == 1)
387*4882a593Smuzhiyun chip->enable_global_lpm = true;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_FPS_CFG0 + fps_id,
392*4882a593Smuzhiyun mask, config);
393*4882a593Smuzhiyun if (ret < 0) {
394*4882a593Smuzhiyun dev_err(dev, "Failed to update FPS CFG: %d\n", ret);
395*4882a593Smuzhiyun return ret;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun return 0;
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun
max77620_initialise_fps(struct max77620_chip * chip)401*4882a593Smuzhiyun static int max77620_initialise_fps(struct max77620_chip *chip)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun struct device *dev = chip->dev;
404*4882a593Smuzhiyun struct device_node *fps_np, *fps_child;
405*4882a593Smuzhiyun u8 config;
406*4882a593Smuzhiyun int fps_id;
407*4882a593Smuzhiyun int ret;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
410*4882a593Smuzhiyun chip->shutdown_fps_period[fps_id] = -1;
411*4882a593Smuzhiyun chip->suspend_fps_period[fps_id] = -1;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun fps_np = of_get_child_by_name(dev->of_node, "fps");
415*4882a593Smuzhiyun if (!fps_np)
416*4882a593Smuzhiyun goto skip_fps;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun for_each_child_of_node(fps_np, fps_child) {
419*4882a593Smuzhiyun ret = max77620_config_fps(chip, fps_child);
420*4882a593Smuzhiyun if (ret < 0) {
421*4882a593Smuzhiyun of_node_put(fps_child);
422*4882a593Smuzhiyun of_node_put(fps_np);
423*4882a593Smuzhiyun return ret;
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun of_node_put(fps_np);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun config = chip->enable_global_lpm ? MAX77620_ONOFFCNFG2_SLP_LPM_MSK : 0;
429*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
430*4882a593Smuzhiyun MAX77620_ONOFFCNFG2_SLP_LPM_MSK, config);
431*4882a593Smuzhiyun if (ret < 0) {
432*4882a593Smuzhiyun dev_err(dev, "Failed to update SLP_LPM: %d\n", ret);
433*4882a593Smuzhiyun return ret;
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun skip_fps:
437*4882a593Smuzhiyun if (chip->chip_id == MAX77663)
438*4882a593Smuzhiyun return 0;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun /* Enable wake on EN0 pin */
441*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
442*4882a593Smuzhiyun MAX77620_ONOFFCNFG2_WK_EN0,
443*4882a593Smuzhiyun MAX77620_ONOFFCNFG2_WK_EN0);
444*4882a593Smuzhiyun if (ret < 0) {
445*4882a593Smuzhiyun dev_err(dev, "Failed to update WK_EN0: %d\n", ret);
446*4882a593Smuzhiyun return ret;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun /* For MAX20024, SLPEN will be POR reset if CLRSE is b11 */
450*4882a593Smuzhiyun if ((chip->chip_id == MAX20024) && chip->sleep_enable) {
451*4882a593Smuzhiyun config = MAX77620_ONOFFCNFG1_SLPEN | MAX20024_ONOFFCNFG1_CLRSE;
452*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
453*4882a593Smuzhiyun config, config);
454*4882a593Smuzhiyun if (ret < 0) {
455*4882a593Smuzhiyun dev_err(dev, "Failed to update SLPEN: %d\n", ret);
456*4882a593Smuzhiyun return ret;
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun return 0;
461*4882a593Smuzhiyun }
462*4882a593Smuzhiyun
max77620_read_es_version(struct max77620_chip * chip)463*4882a593Smuzhiyun static int max77620_read_es_version(struct max77620_chip *chip)
464*4882a593Smuzhiyun {
465*4882a593Smuzhiyun unsigned int val;
466*4882a593Smuzhiyun u8 cid_val[6];
467*4882a593Smuzhiyun int i;
468*4882a593Smuzhiyun int ret;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun for (i = MAX77620_REG_CID0; i <= MAX77620_REG_CID5; i++) {
471*4882a593Smuzhiyun ret = regmap_read(chip->rmap, i, &val);
472*4882a593Smuzhiyun if (ret < 0) {
473*4882a593Smuzhiyun dev_err(chip->dev, "Failed to read CID: %d\n", ret);
474*4882a593Smuzhiyun return ret;
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun dev_dbg(chip->dev, "CID%d: 0x%02x\n",
477*4882a593Smuzhiyun i - MAX77620_REG_CID0, val);
478*4882a593Smuzhiyun cid_val[i - MAX77620_REG_CID0] = val;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun
481*4882a593Smuzhiyun /* CID4 is OTP Version and CID5 is ES version */
482*4882a593Smuzhiyun dev_info(chip->dev, "PMIC Version OTP:0x%02X and ES:0x%X\n",
483*4882a593Smuzhiyun cid_val[4], MAX77620_CID5_DIDM(cid_val[5]));
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun return ret;
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun
max77620_pm_power_off(void)488*4882a593Smuzhiyun static void max77620_pm_power_off(void)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun struct max77620_chip *chip = max77620_scratch;
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
493*4882a593Smuzhiyun MAX77620_ONOFFCNFG1_SFT_RST,
494*4882a593Smuzhiyun MAX77620_ONOFFCNFG1_SFT_RST);
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
max77620_probe(struct i2c_client * client,const struct i2c_device_id * id)497*4882a593Smuzhiyun static int max77620_probe(struct i2c_client *client,
498*4882a593Smuzhiyun const struct i2c_device_id *id)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun const struct regmap_config *rmap_config;
501*4882a593Smuzhiyun struct max77620_chip *chip;
502*4882a593Smuzhiyun const struct mfd_cell *mfd_cells;
503*4882a593Smuzhiyun int n_mfd_cells;
504*4882a593Smuzhiyun bool pm_off;
505*4882a593Smuzhiyun int ret;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
508*4882a593Smuzhiyun if (!chip)
509*4882a593Smuzhiyun return -ENOMEM;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun i2c_set_clientdata(client, chip);
512*4882a593Smuzhiyun chip->dev = &client->dev;
513*4882a593Smuzhiyun chip->chip_irq = client->irq;
514*4882a593Smuzhiyun chip->chip_id = (enum max77620_chip_id)id->driver_data;
515*4882a593Smuzhiyun
516*4882a593Smuzhiyun switch (chip->chip_id) {
517*4882a593Smuzhiyun case MAX77620:
518*4882a593Smuzhiyun mfd_cells = max77620_children;
519*4882a593Smuzhiyun n_mfd_cells = ARRAY_SIZE(max77620_children);
520*4882a593Smuzhiyun rmap_config = &max77620_regmap_config;
521*4882a593Smuzhiyun break;
522*4882a593Smuzhiyun case MAX20024:
523*4882a593Smuzhiyun mfd_cells = max20024_children;
524*4882a593Smuzhiyun n_mfd_cells = ARRAY_SIZE(max20024_children);
525*4882a593Smuzhiyun rmap_config = &max20024_regmap_config;
526*4882a593Smuzhiyun break;
527*4882a593Smuzhiyun case MAX77663:
528*4882a593Smuzhiyun mfd_cells = max77663_children;
529*4882a593Smuzhiyun n_mfd_cells = ARRAY_SIZE(max77663_children);
530*4882a593Smuzhiyun rmap_config = &max77663_regmap_config;
531*4882a593Smuzhiyun break;
532*4882a593Smuzhiyun default:
533*4882a593Smuzhiyun dev_err(chip->dev, "ChipID is invalid %d\n", chip->chip_id);
534*4882a593Smuzhiyun return -EINVAL;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun chip->rmap = devm_regmap_init_i2c(client, rmap_config);
538*4882a593Smuzhiyun if (IS_ERR(chip->rmap)) {
539*4882a593Smuzhiyun ret = PTR_ERR(chip->rmap);
540*4882a593Smuzhiyun dev_err(chip->dev, "Failed to initialise regmap: %d\n", ret);
541*4882a593Smuzhiyun return ret;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
544*4882a593Smuzhiyun ret = max77620_read_es_version(chip);
545*4882a593Smuzhiyun if (ret < 0)
546*4882a593Smuzhiyun return ret;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun max77620_top_irq_chip.irq_drv_data = chip;
549*4882a593Smuzhiyun ret = devm_regmap_add_irq_chip(chip->dev, chip->rmap, client->irq,
550*4882a593Smuzhiyun IRQF_ONESHOT | IRQF_SHARED, 0,
551*4882a593Smuzhiyun &max77620_top_irq_chip,
552*4882a593Smuzhiyun &chip->top_irq_data);
553*4882a593Smuzhiyun if (ret < 0) {
554*4882a593Smuzhiyun dev_err(chip->dev, "Failed to add regmap irq: %d\n", ret);
555*4882a593Smuzhiyun return ret;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun ret = max77620_initialise_fps(chip);
559*4882a593Smuzhiyun if (ret < 0)
560*4882a593Smuzhiyun return ret;
561*4882a593Smuzhiyun
562*4882a593Smuzhiyun ret = devm_mfd_add_devices(chip->dev, PLATFORM_DEVID_NONE,
563*4882a593Smuzhiyun mfd_cells, n_mfd_cells, NULL, 0,
564*4882a593Smuzhiyun regmap_irq_get_domain(chip->top_irq_data));
565*4882a593Smuzhiyun if (ret < 0) {
566*4882a593Smuzhiyun dev_err(chip->dev, "Failed to add MFD children: %d\n", ret);
567*4882a593Smuzhiyun return ret;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun pm_off = of_device_is_system_power_controller(client->dev.of_node);
571*4882a593Smuzhiyun if (pm_off && !pm_power_off) {
572*4882a593Smuzhiyun max77620_scratch = chip;
573*4882a593Smuzhiyun pm_power_off = max77620_pm_power_off;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun return 0;
577*4882a593Smuzhiyun }
578*4882a593Smuzhiyun
579*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
max77620_set_fps_period(struct max77620_chip * chip,int fps_id,int time_period)580*4882a593Smuzhiyun static int max77620_set_fps_period(struct max77620_chip *chip,
581*4882a593Smuzhiyun int fps_id, int time_period)
582*4882a593Smuzhiyun {
583*4882a593Smuzhiyun int period = max77620_get_fps_period_reg_value(chip, time_period);
584*4882a593Smuzhiyun int ret;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_FPS_CFG0 + fps_id,
587*4882a593Smuzhiyun MAX77620_FPS_TIME_PERIOD_MASK,
588*4882a593Smuzhiyun period << MAX77620_FPS_TIME_PERIOD_SHIFT);
589*4882a593Smuzhiyun if (ret < 0) {
590*4882a593Smuzhiyun dev_err(chip->dev, "Failed to update FPS period: %d\n", ret);
591*4882a593Smuzhiyun return ret;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun return 0;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun
max77620_i2c_suspend(struct device * dev)597*4882a593Smuzhiyun static int max77620_i2c_suspend(struct device *dev)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun struct max77620_chip *chip = dev_get_drvdata(dev);
600*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
601*4882a593Smuzhiyun unsigned int config;
602*4882a593Smuzhiyun int fps;
603*4882a593Smuzhiyun int ret;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) {
606*4882a593Smuzhiyun if (chip->suspend_fps_period[fps] < 0)
607*4882a593Smuzhiyun continue;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun ret = max77620_set_fps_period(chip, fps,
610*4882a593Smuzhiyun chip->suspend_fps_period[fps]);
611*4882a593Smuzhiyun if (ret < 0)
612*4882a593Smuzhiyun return ret;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun /*
616*4882a593Smuzhiyun * For MAX20024: No need to configure SLPEN on suspend as
617*4882a593Smuzhiyun * it will be configured on Init.
618*4882a593Smuzhiyun */
619*4882a593Smuzhiyun if (chip->chip_id == MAX20024)
620*4882a593Smuzhiyun goto out;
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun config = (chip->sleep_enable) ? MAX77620_ONOFFCNFG1_SLPEN : 0;
623*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG1,
624*4882a593Smuzhiyun MAX77620_ONOFFCNFG1_SLPEN,
625*4882a593Smuzhiyun config);
626*4882a593Smuzhiyun if (ret < 0) {
627*4882a593Smuzhiyun dev_err(dev, "Failed to configure sleep in suspend: %d\n", ret);
628*4882a593Smuzhiyun return ret;
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyun if (chip->chip_id == MAX77663)
632*4882a593Smuzhiyun goto out;
633*4882a593Smuzhiyun
634*4882a593Smuzhiyun /* Disable WK_EN0 */
635*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
636*4882a593Smuzhiyun MAX77620_ONOFFCNFG2_WK_EN0, 0);
637*4882a593Smuzhiyun if (ret < 0) {
638*4882a593Smuzhiyun dev_err(dev, "Failed to configure WK_EN in suspend: %d\n", ret);
639*4882a593Smuzhiyun return ret;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun out:
643*4882a593Smuzhiyun disable_irq(client->irq);
644*4882a593Smuzhiyun
645*4882a593Smuzhiyun return 0;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun
max77620_i2c_resume(struct device * dev)648*4882a593Smuzhiyun static int max77620_i2c_resume(struct device *dev)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun struct max77620_chip *chip = dev_get_drvdata(dev);
651*4882a593Smuzhiyun struct i2c_client *client = to_i2c_client(dev);
652*4882a593Smuzhiyun int ret;
653*4882a593Smuzhiyun int fps;
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun for (fps = 0; fps < MAX77620_FPS_COUNT; fps++) {
656*4882a593Smuzhiyun if (chip->shutdown_fps_period[fps] < 0)
657*4882a593Smuzhiyun continue;
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun ret = max77620_set_fps_period(chip, fps,
660*4882a593Smuzhiyun chip->shutdown_fps_period[fps]);
661*4882a593Smuzhiyun if (ret < 0)
662*4882a593Smuzhiyun return ret;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun
665*4882a593Smuzhiyun /*
666*4882a593Smuzhiyun * For MAX20024: No need to configure WKEN0 on resume as
667*4882a593Smuzhiyun * it is configured on Init.
668*4882a593Smuzhiyun */
669*4882a593Smuzhiyun if (chip->chip_id == MAX20024 || chip->chip_id == MAX77663)
670*4882a593Smuzhiyun goto out;
671*4882a593Smuzhiyun
672*4882a593Smuzhiyun /* Enable WK_EN0 */
673*4882a593Smuzhiyun ret = regmap_update_bits(chip->rmap, MAX77620_REG_ONOFFCNFG2,
674*4882a593Smuzhiyun MAX77620_ONOFFCNFG2_WK_EN0,
675*4882a593Smuzhiyun MAX77620_ONOFFCNFG2_WK_EN0);
676*4882a593Smuzhiyun if (ret < 0) {
677*4882a593Smuzhiyun dev_err(dev, "Failed to configure WK_EN0 n resume: %d\n", ret);
678*4882a593Smuzhiyun return ret;
679*4882a593Smuzhiyun }
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun out:
682*4882a593Smuzhiyun enable_irq(client->irq);
683*4882a593Smuzhiyun
684*4882a593Smuzhiyun return 0;
685*4882a593Smuzhiyun }
686*4882a593Smuzhiyun #endif
687*4882a593Smuzhiyun
688*4882a593Smuzhiyun static const struct i2c_device_id max77620_id[] = {
689*4882a593Smuzhiyun {"max77620", MAX77620},
690*4882a593Smuzhiyun {"max20024", MAX20024},
691*4882a593Smuzhiyun {"max77663", MAX77663},
692*4882a593Smuzhiyun {},
693*4882a593Smuzhiyun };
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun static const struct dev_pm_ops max77620_pm_ops = {
696*4882a593Smuzhiyun SET_SYSTEM_SLEEP_PM_OPS(max77620_i2c_suspend, max77620_i2c_resume)
697*4882a593Smuzhiyun };
698*4882a593Smuzhiyun
699*4882a593Smuzhiyun static struct i2c_driver max77620_driver = {
700*4882a593Smuzhiyun .driver = {
701*4882a593Smuzhiyun .name = "max77620",
702*4882a593Smuzhiyun .pm = &max77620_pm_ops,
703*4882a593Smuzhiyun },
704*4882a593Smuzhiyun .probe = max77620_probe,
705*4882a593Smuzhiyun .id_table = max77620_id,
706*4882a593Smuzhiyun };
707*4882a593Smuzhiyun builtin_i2c_driver(max77620_driver);
708