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 mfd_cell hi655x_pmic_devs
[] = {
28 { .name
= "hi655x-regulator", },
31 static const struct regmap_irq hi655x_irqs
[] = {
32 { .reg_offset
= 0, .mask
= OTMP_D1R_INT
},
33 { .reg_offset
= 0, .mask
= VSYS_2P5_R_INT
},
34 { .reg_offset
= 0, .mask
= VSYS_UV_D3R_INT
},
35 { .reg_offset
= 0, .mask
= VSYS_6P0_D200UR_INT
},
36 { .reg_offset
= 0, .mask
= PWRON_D4SR_INT
},
37 { .reg_offset
= 0, .mask
= PWRON_D20F_INT
},
38 { .reg_offset
= 0, .mask
= PWRON_D20R_INT
},
39 { .reg_offset
= 0, .mask
= RESERVE_INT
},
42 static const struct regmap_irq_chip hi655x_irq_chip
= {
43 .name
= "hi655x-pmic",
46 .num_irqs
= ARRAY_SIZE(hi655x_irqs
),
47 .status_base
= HI655X_IRQ_STAT_BASE
,
48 .mask_base
= HI655X_IRQ_MASK_BASE
,
51 static struct regmap_config hi655x_regmap_config
= {
53 .reg_stride
= HI655X_STRIDE
,
55 .max_register
= HI655X_BUS_ADDR(0xFFF),
58 static void hi655x_local_irq_clear(struct regmap
*map
)
62 regmap_write(map
, HI655X_ANA_IRQM_BASE
, HI655X_IRQ_CLR
);
63 for (i
= 0; i
< HI655X_IRQ_ARRAY
; i
++) {
64 regmap_write(map
, HI655X_IRQ_STAT_BASE
+ i
* HI655X_STRIDE
,
69 static int hi655x_pmic_probe(struct platform_device
*pdev
)
72 struct hi655x_pmic
*pmic
;
73 struct device
*dev
= &pdev
->dev
;
74 struct device_node
*np
= dev
->of_node
;
77 pmic
= devm_kzalloc(dev
, sizeof(*pmic
), GFP_KERNEL
);
82 pmic
->res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
86 base
= devm_ioremap_resource(dev
, pmic
->res
);
90 pmic
->regmap
= devm_regmap_init_mmio_clk(dev
, NULL
, base
,
91 &hi655x_regmap_config
);
93 regmap_read(pmic
->regmap
, HI655X_BUS_ADDR(HI655X_VER_REG
), &pmic
->ver
);
94 if ((pmic
->ver
< PMU_VER_START
) || (pmic
->ver
> PMU_VER_END
)) {
95 dev_warn(dev
, "PMU version %d unsupported\n", pmic
->ver
);
99 hi655x_local_irq_clear(pmic
->regmap
);
101 pmic
->gpio
= of_get_named_gpio(np
, "pmic-gpios", 0);
102 if (!gpio_is_valid(pmic
->gpio
)) {
103 dev_err(dev
, "Failed to get the pmic-gpios\n");
107 ret
= devm_gpio_request_one(dev
, pmic
->gpio
, GPIOF_IN
,
110 dev_err(dev
, "Failed to request gpio %d ret = %d\n",
115 ret
= regmap_add_irq_chip(pmic
->regmap
, gpio_to_irq(pmic
->gpio
),
116 IRQF_TRIGGER_LOW
| IRQF_NO_SUSPEND
, 0,
117 &hi655x_irq_chip
, &pmic
->irq_data
);
119 dev_err(dev
, "Failed to obtain 'hi655x_pmic_irq' %d\n", ret
);
123 platform_set_drvdata(pdev
, pmic
);
125 ret
= mfd_add_devices(dev
, PLATFORM_DEVID_AUTO
, hi655x_pmic_devs
,
126 ARRAY_SIZE(hi655x_pmic_devs
), NULL
, 0, NULL
);
128 dev_err(dev
, "Failed to register device %d\n", ret
);
129 regmap_del_irq_chip(gpio_to_irq(pmic
->gpio
), pmic
->irq_data
);
136 static int hi655x_pmic_remove(struct platform_device
*pdev
)
138 struct hi655x_pmic
*pmic
= platform_get_drvdata(pdev
);
140 regmap_del_irq_chip(gpio_to_irq(pmic
->gpio
), pmic
->irq_data
);
141 mfd_remove_devices(&pdev
->dev
);
145 static const struct of_device_id hi655x_pmic_match
[] = {
146 { .compatible
= "hisilicon,hi655x-pmic", },
150 static struct platform_driver hi655x_pmic_driver
= {
152 .name
= "hi655x-pmic",
153 .of_match_table
= of_match_ptr(hi655x_pmic_match
),
155 .probe
= hi655x_pmic_probe
,
156 .remove
= hi655x_pmic_remove
,
158 module_platform_driver(hi655x_pmic_driver
);
160 MODULE_AUTHOR("Chen Feng <puck.chen@hisilicon.com>");
161 MODULE_DESCRIPTION("Hisilicon hi655x PMIC driver");
162 MODULE_LICENSE("GPL v2");