1 // SPDX-License-Identifier: GPL-2.0-only
3 * Device driver for MFD hi655x PMIC
5 * Copyright (c) 2016 HiSilicon Ltd.
8 * Chen Feng <puck.chen@hisilicon.com>
9 * Fei Wang <w.f@huawei.com>
13 #include <linux/interrupt.h>
14 #include <linux/init.h>
15 #include <linux/mfd/core.h>
16 #include <linux/mfd/hi655x-pmic.h>
17 #include <linux/module.h>
18 #include <linux/gpio/consumer.h>
19 #include <linux/mod_devicetable.h>
20 #include <linux/platform_device.h>
21 #include <linux/regmap.h>
23 static const struct regmap_irq hi655x_irqs
[] = {
24 { .reg_offset
= 0, .mask
= OTMP_D1R_INT_MASK
},
25 { .reg_offset
= 0, .mask
= VSYS_2P5_R_INT_MASK
},
26 { .reg_offset
= 0, .mask
= VSYS_UV_D3R_INT_MASK
},
27 { .reg_offset
= 0, .mask
= VSYS_6P0_D200UR_INT_MASK
},
28 { .reg_offset
= 0, .mask
= PWRON_D4SR_INT_MASK
},
29 { .reg_offset
= 0, .mask
= PWRON_D20F_INT_MASK
},
30 { .reg_offset
= 0, .mask
= PWRON_D20R_INT_MASK
},
31 { .reg_offset
= 0, .mask
= RESERVE_INT_MASK
},
34 static const struct regmap_irq_chip hi655x_irq_chip
= {
35 .name
= "hi655x-pmic",
38 .num_irqs
= ARRAY_SIZE(hi655x_irqs
),
39 .status_base
= HI655X_IRQ_STAT_BASE
,
40 .ack_base
= HI655X_IRQ_STAT_BASE
,
41 .mask_base
= HI655X_IRQ_MASK_BASE
,
44 static const struct regmap_config hi655x_regmap_config
= {
46 .reg_stride
= HI655X_STRIDE
,
48 .max_register
= HI655X_BUS_ADDR(0x400) - HI655X_STRIDE
,
51 static const struct resource pwrkey_resources
[] = {
54 .start
= PWRON_D20R_INT
,
55 .end
= PWRON_D20R_INT
,
56 .flags
= IORESOURCE_IRQ
,
59 .start
= PWRON_D20F_INT
,
60 .end
= PWRON_D20F_INT
,
61 .flags
= IORESOURCE_IRQ
,
64 .start
= PWRON_D4SR_INT
,
65 .end
= PWRON_D4SR_INT
,
66 .flags
= IORESOURCE_IRQ
,
70 static const struct mfd_cell hi655x_pmic_devs
[] = {
72 .name
= "hi65xx-powerkey",
73 .num_resources
= ARRAY_SIZE(pwrkey_resources
),
74 .resources
= &pwrkey_resources
[0],
76 { .name
= "hi655x-regulator", },
77 { .name
= "hi655x-clk", },
80 static void hi655x_local_irq_clear(struct regmap
*map
)
84 regmap_write(map
, HI655X_ANA_IRQM_BASE
, HI655X_IRQ_CLR
);
85 for (i
= 0; i
< HI655X_IRQ_ARRAY
; i
++) {
86 regmap_write(map
, HI655X_IRQ_STAT_BASE
+ i
* HI655X_STRIDE
,
91 static int hi655x_pmic_probe(struct platform_device
*pdev
)
94 struct hi655x_pmic
*pmic
;
95 struct device
*dev
= &pdev
->dev
;
98 pmic
= devm_kzalloc(dev
, sizeof(*pmic
), GFP_KERNEL
);
103 base
= devm_platform_ioremap_resource(pdev
, 0);
105 return PTR_ERR(base
);
107 pmic
->regmap
= devm_regmap_init_mmio_clk(dev
, NULL
, base
,
108 &hi655x_regmap_config
);
109 if (IS_ERR(pmic
->regmap
))
110 return PTR_ERR(pmic
->regmap
);
112 regmap_read(pmic
->regmap
, HI655X_BUS_ADDR(HI655X_VER_REG
), &pmic
->ver
);
113 if ((pmic
->ver
< PMU_VER_START
) || (pmic
->ver
> PMU_VER_END
)) {
114 dev_warn(dev
, "PMU version %d unsupported\n", pmic
->ver
);
118 hi655x_local_irq_clear(pmic
->regmap
);
120 pmic
->gpio
= devm_gpiod_get_optional(dev
, "pmic", GPIOD_IN
);
121 if (IS_ERR(pmic
->gpio
))
122 return dev_err_probe(dev
, PTR_ERR(pmic
->gpio
),
123 "Failed to request hi655x pmic-gpio");
125 ret
= regmap_add_irq_chip(pmic
->regmap
, gpiod_to_irq(pmic
->gpio
),
126 IRQF_TRIGGER_LOW
| IRQF_NO_SUSPEND
, 0,
127 &hi655x_irq_chip
, &pmic
->irq_data
);
129 dev_err(dev
, "Failed to obtain 'hi655x_pmic_irq' %d\n", ret
);
133 platform_set_drvdata(pdev
, pmic
);
135 ret
= mfd_add_devices(dev
, PLATFORM_DEVID_AUTO
, hi655x_pmic_devs
,
136 ARRAY_SIZE(hi655x_pmic_devs
), NULL
, 0,
137 regmap_irq_get_domain(pmic
->irq_data
));
139 dev_err(dev
, "Failed to register device %d\n", ret
);
140 regmap_del_irq_chip(gpiod_to_irq(pmic
->gpio
), pmic
->irq_data
);
147 static void hi655x_pmic_remove(struct platform_device
*pdev
)
149 struct hi655x_pmic
*pmic
= platform_get_drvdata(pdev
);
151 regmap_del_irq_chip(gpiod_to_irq(pmic
->gpio
), pmic
->irq_data
);
152 mfd_remove_devices(&pdev
->dev
);
155 static const struct of_device_id hi655x_pmic_match
[] = {
156 { .compatible
= "hisilicon,hi655x-pmic", },
159 MODULE_DEVICE_TABLE(of
, hi655x_pmic_match
);
161 static struct platform_driver hi655x_pmic_driver
= {
163 .name
= "hi655x-pmic",
164 .of_match_table
= hi655x_pmic_match
,
166 .probe
= hi655x_pmic_probe
,
167 .remove
= hi655x_pmic_remove
,
169 module_platform_driver(hi655x_pmic_driver
);
171 MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
172 MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver");
173 MODULE_LICENSE("GPL v2");