2 * Device driver for MFD hi655x PMIC
4 * Copyright (c) 2016 Hisilicon.
7 * Chen Feng <puck.chen@hisilicon.com>
8 * Fei Wang <w.f@huawei.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
15 #include <linux/gpio.h>
17 #include <linux/interrupt.h>
18 #include <linux/init.h>
19 #include <linux/mfd/core.h>
20 #include <linux/mfd/hi655x-pmic.h>
21 #include <linux/module.h>
22 #include <linux/of_gpio.h>
23 #include <linux/of_platform.h>
24 #include <linux/platform_device.h>
25 #include <linux/regmap.h>
27 static const struct regmap_irq hi655x_irqs
[] = {
28 { .reg_offset
= 0, .mask
= OTMP_D1R_INT_MASK
},
29 { .reg_offset
= 0, .mask
= VSYS_2P5_R_INT_MASK
},
30 { .reg_offset
= 0, .mask
= VSYS_UV_D3R_INT_MASK
},
31 { .reg_offset
= 0, .mask
= VSYS_6P0_D200UR_INT_MASK
},
32 { .reg_offset
= 0, .mask
= PWRON_D4SR_INT_MASK
},
33 { .reg_offset
= 0, .mask
= PWRON_D20F_INT_MASK
},
34 { .reg_offset
= 0, .mask
= PWRON_D20R_INT_MASK
},
35 { .reg_offset
= 0, .mask
= RESERVE_INT_MASK
},
38 static const struct regmap_irq_chip hi655x_irq_chip
= {
39 .name
= "hi655x-pmic",
42 .num_irqs
= ARRAY_SIZE(hi655x_irqs
),
43 .status_base
= HI655X_IRQ_STAT_BASE
,
44 .ack_base
= HI655X_IRQ_STAT_BASE
,
45 .mask_base
= HI655X_IRQ_MASK_BASE
,
48 static struct regmap_config hi655x_regmap_config
= {
50 .reg_stride
= HI655X_STRIDE
,
52 .max_register
= HI655X_BUS_ADDR(0xFFF),
55 static struct resource pwrkey_resources
[] = {
58 .start
= PWRON_D20R_INT
,
59 .end
= PWRON_D20R_INT
,
60 .flags
= IORESOURCE_IRQ
,
63 .start
= PWRON_D20F_INT
,
64 .end
= PWRON_D20F_INT
,
65 .flags
= IORESOURCE_IRQ
,
68 .start
= PWRON_D4SR_INT
,
69 .end
= PWRON_D4SR_INT
,
70 .flags
= IORESOURCE_IRQ
,
74 static const struct mfd_cell hi655x_pmic_devs
[] = {
76 .name
= "hi65xx-powerkey",
77 .num_resources
= ARRAY_SIZE(pwrkey_resources
),
78 .resources
= &pwrkey_resources
[0],
80 { .name
= "hi655x-regulator", },
81 { .name
= "hi655x-clk", },
84 static void hi655x_local_irq_clear(struct regmap
*map
)
88 regmap_write(map
, HI655X_ANA_IRQM_BASE
, HI655X_IRQ_CLR
);
89 for (i
= 0; i
< HI655X_IRQ_ARRAY
; i
++) {
90 regmap_write(map
, HI655X_IRQ_STAT_BASE
+ i
* HI655X_STRIDE
,
95 static int hi655x_pmic_probe(struct platform_device
*pdev
)
98 struct hi655x_pmic
*pmic
;
99 struct device
*dev
= &pdev
->dev
;
100 struct device_node
*np
= dev
->of_node
;
103 pmic
= devm_kzalloc(dev
, sizeof(*pmic
), GFP_KERNEL
);
108 pmic
->res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
109 base
= devm_ioremap_resource(dev
, pmic
->res
);
111 return PTR_ERR(base
);
113 pmic
->regmap
= devm_regmap_init_mmio_clk(dev
, NULL
, base
,
114 &hi655x_regmap_config
);
116 regmap_read(pmic
->regmap
, HI655X_BUS_ADDR(HI655X_VER_REG
), &pmic
->ver
);
117 if ((pmic
->ver
< PMU_VER_START
) || (pmic
->ver
> PMU_VER_END
)) {
118 dev_warn(dev
, "PMU version %d unsupported\n", pmic
->ver
);
122 hi655x_local_irq_clear(pmic
->regmap
);
124 pmic
->gpio
= of_get_named_gpio(np
, "pmic-gpios", 0);
125 if (!gpio_is_valid(pmic
->gpio
)) {
126 dev_err(dev
, "Failed to get the pmic-gpios\n");
130 ret
= devm_gpio_request_one(dev
, pmic
->gpio
, GPIOF_IN
,
133 dev_err(dev
, "Failed to request gpio %d ret = %d\n",
138 ret
= regmap_add_irq_chip(pmic
->regmap
, gpio_to_irq(pmic
->gpio
),
139 IRQF_TRIGGER_LOW
| IRQF_NO_SUSPEND
, 0,
140 &hi655x_irq_chip
, &pmic
->irq_data
);
142 dev_err(dev
, "Failed to obtain 'hi655x_pmic_irq' %d\n", ret
);
146 platform_set_drvdata(pdev
, pmic
);
148 ret
= mfd_add_devices(dev
, PLATFORM_DEVID_AUTO
, hi655x_pmic_devs
,
149 ARRAY_SIZE(hi655x_pmic_devs
), NULL
, 0,
150 regmap_irq_get_domain(pmic
->irq_data
));
152 dev_err(dev
, "Failed to register device %d\n", ret
);
153 regmap_del_irq_chip(gpio_to_irq(pmic
->gpio
), pmic
->irq_data
);
160 static int hi655x_pmic_remove(struct platform_device
*pdev
)
162 struct hi655x_pmic
*pmic
= platform_get_drvdata(pdev
);
164 regmap_del_irq_chip(gpio_to_irq(pmic
->gpio
), pmic
->irq_data
);
165 mfd_remove_devices(&pdev
->dev
);
169 static const struct of_device_id hi655x_pmic_match
[] = {
170 { .compatible
= "hisilicon,hi655x-pmic", },
173 MODULE_DEVICE_TABLE(of
, hi655x_pmic_match
);
175 static struct platform_driver hi655x_pmic_driver
= {
177 .name
= "hi655x-pmic",
178 .of_match_table
= of_match_ptr(hi655x_pmic_match
),
180 .probe
= hi655x_pmic_probe
,
181 .remove
= hi655x_pmic_remove
,
183 module_platform_driver(hi655x_pmic_driver
);
185 MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
186 MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver");
187 MODULE_LICENSE("GPL v2");