1 // SPDX-License-Identifier: GPL-2.0-only
3 * Device driver for MFD hi655x PMIC
5 * Copyright (c) 2016 Hisilicon.
8 * Chen Feng <puck.chen@hisilicon.com>
9 * Fei Wang <w.f@huawei.com>
12 #include <linux/gpio.h>
14 #include <linux/interrupt.h>
15 #include <linux/init.h>
16 #include <linux/mfd/core.h>
17 #include <linux/mfd/hi655x-pmic.h>
18 #include <linux/module.h>
19 #include <linux/of_gpio.h>
20 #include <linux/of_platform.h>
21 #include <linux/platform_device.h>
22 #include <linux/regmap.h>
24 static const struct regmap_irq hi655x_irqs
[] = {
25 { .reg_offset
= 0, .mask
= OTMP_D1R_INT_MASK
},
26 { .reg_offset
= 0, .mask
= VSYS_2P5_R_INT_MASK
},
27 { .reg_offset
= 0, .mask
= VSYS_UV_D3R_INT_MASK
},
28 { .reg_offset
= 0, .mask
= VSYS_6P0_D200UR_INT_MASK
},
29 { .reg_offset
= 0, .mask
= PWRON_D4SR_INT_MASK
},
30 { .reg_offset
= 0, .mask
= PWRON_D20F_INT_MASK
},
31 { .reg_offset
= 0, .mask
= PWRON_D20R_INT_MASK
},
32 { .reg_offset
= 0, .mask
= RESERVE_INT_MASK
},
35 static const struct regmap_irq_chip hi655x_irq_chip
= {
36 .name
= "hi655x-pmic",
39 .num_irqs
= ARRAY_SIZE(hi655x_irqs
),
40 .status_base
= HI655X_IRQ_STAT_BASE
,
41 .ack_base
= HI655X_IRQ_STAT_BASE
,
42 .mask_base
= HI655X_IRQ_MASK_BASE
,
45 static struct regmap_config hi655x_regmap_config
= {
47 .reg_stride
= HI655X_STRIDE
,
49 .max_register
= HI655X_BUS_ADDR(0x400) - HI655X_STRIDE
,
52 static const struct resource pwrkey_resources
[] = {
55 .start
= PWRON_D20R_INT
,
56 .end
= PWRON_D20R_INT
,
57 .flags
= IORESOURCE_IRQ
,
60 .start
= PWRON_D20F_INT
,
61 .end
= PWRON_D20F_INT
,
62 .flags
= IORESOURCE_IRQ
,
65 .start
= PWRON_D4SR_INT
,
66 .end
= PWRON_D4SR_INT
,
67 .flags
= IORESOURCE_IRQ
,
71 static const struct mfd_cell hi655x_pmic_devs
[] = {
73 .name
= "hi65xx-powerkey",
74 .num_resources
= ARRAY_SIZE(pwrkey_resources
),
75 .resources
= &pwrkey_resources
[0],
77 { .name
= "hi655x-regulator", },
78 { .name
= "hi655x-clk", },
81 static void hi655x_local_irq_clear(struct regmap
*map
)
85 regmap_write(map
, HI655X_ANA_IRQM_BASE
, HI655X_IRQ_CLR
);
86 for (i
= 0; i
< HI655X_IRQ_ARRAY
; i
++) {
87 regmap_write(map
, HI655X_IRQ_STAT_BASE
+ i
* HI655X_STRIDE
,
92 static int hi655x_pmic_probe(struct platform_device
*pdev
)
95 struct hi655x_pmic
*pmic
;
96 struct device
*dev
= &pdev
->dev
;
97 struct device_node
*np
= dev
->of_node
;
100 pmic
= devm_kzalloc(dev
, sizeof(*pmic
), GFP_KERNEL
);
105 pmic
->res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
106 base
= devm_ioremap_resource(dev
, pmic
->res
);
108 return PTR_ERR(base
);
110 pmic
->regmap
= devm_regmap_init_mmio_clk(dev
, NULL
, base
,
111 &hi655x_regmap_config
);
112 if (IS_ERR(pmic
->regmap
))
113 return PTR_ERR(pmic
->regmap
);
115 regmap_read(pmic
->regmap
, HI655X_BUS_ADDR(HI655X_VER_REG
), &pmic
->ver
);
116 if ((pmic
->ver
< PMU_VER_START
) || (pmic
->ver
> PMU_VER_END
)) {
117 dev_warn(dev
, "PMU version %d unsupported\n", pmic
->ver
);
121 hi655x_local_irq_clear(pmic
->regmap
);
123 pmic
->gpio
= of_get_named_gpio(np
, "pmic-gpios", 0);
124 if (!gpio_is_valid(pmic
->gpio
)) {
125 dev_err(dev
, "Failed to get the pmic-gpios\n");
129 ret
= devm_gpio_request_one(dev
, pmic
->gpio
, GPIOF_IN
,
132 dev_err(dev
, "Failed to request gpio %d ret = %d\n",
137 ret
= regmap_add_irq_chip(pmic
->regmap
, gpio_to_irq(pmic
->gpio
),
138 IRQF_TRIGGER_LOW
| IRQF_NO_SUSPEND
, 0,
139 &hi655x_irq_chip
, &pmic
->irq_data
);
141 dev_err(dev
, "Failed to obtain 'hi655x_pmic_irq' %d\n", ret
);
145 platform_set_drvdata(pdev
, pmic
);
147 ret
= mfd_add_devices(dev
, PLATFORM_DEVID_AUTO
, hi655x_pmic_devs
,
148 ARRAY_SIZE(hi655x_pmic_devs
), NULL
, 0,
149 regmap_irq_get_domain(pmic
->irq_data
));
151 dev_err(dev
, "Failed to register device %d\n", ret
);
152 regmap_del_irq_chip(gpio_to_irq(pmic
->gpio
), pmic
->irq_data
);
159 static int hi655x_pmic_remove(struct platform_device
*pdev
)
161 struct hi655x_pmic
*pmic
= platform_get_drvdata(pdev
);
163 regmap_del_irq_chip(gpio_to_irq(pmic
->gpio
), pmic
->irq_data
);
164 mfd_remove_devices(&pdev
->dev
);
168 static const struct of_device_id hi655x_pmic_match
[] = {
169 { .compatible
= "hisilicon,hi655x-pmic", },
172 MODULE_DEVICE_TABLE(of
, hi655x_pmic_match
);
174 static struct platform_driver hi655x_pmic_driver
= {
176 .name
= "hi655x-pmic",
177 .of_match_table
= of_match_ptr(hi655x_pmic_match
),
179 .probe
= hi655x_pmic_probe
,
180 .remove
= hi655x_pmic_remove
,
182 module_platform_driver(hi655x_pmic_driver
);
184 MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
185 MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver");
186 MODULE_LICENSE("GPL v2");