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", },
83 static void hi655x_local_irq_clear(struct regmap
*map
)
87 regmap_write(map
, HI655X_ANA_IRQM_BASE
, HI655X_IRQ_CLR
);
88 for (i
= 0; i
< HI655X_IRQ_ARRAY
; i
++) {
89 regmap_write(map
, HI655X_IRQ_STAT_BASE
+ i
* HI655X_STRIDE
,
94 static int hi655x_pmic_probe(struct platform_device
*pdev
)
97 struct hi655x_pmic
*pmic
;
98 struct device
*dev
= &pdev
->dev
;
99 struct device_node
*np
= dev
->of_node
;
102 pmic
= devm_kzalloc(dev
, sizeof(*pmic
), GFP_KERNEL
);
107 pmic
->res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
108 base
= devm_ioremap_resource(dev
, pmic
->res
);
110 return PTR_ERR(base
);
112 pmic
->regmap
= devm_regmap_init_mmio_clk(dev
, NULL
, base
,
113 &hi655x_regmap_config
);
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");