staging: hikey9xx: hi6421-spmi-pmic: rename some vars
[linux-block.git] / drivers / staging / hikey9xx / hi6421-spmi-pmic.c
CommitLineData
4b5e9b39 1// SPDX-License-Identifier: GPL-2.0
64542b9f
MCC
2//
3// Device driver for regulators in HISI PMIC IC
4//
5// Copyright (c) 2013 Linaro Ltd.
6// Copyright (c) 2011 Hisilicon.
7//
8// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
4524ac56 9
4524ac56 10#include <linux/interrupt.h>
6b946699 11#include <linux/irq.h>
cf0f27b7 12#include <linux/mfd/core.h>
6b946699
MCC
13#include <linux/mfd/hi6421-spmi-pmic.h>
14#include <linux/module.h>
4524ac56 15#include <linux/of_gpio.h>
6b946699
MCC
16#include <linux/platform_device.h>
17#include <linux/slab.h>
4524ac56 18#include <linux/spmi.h>
4524ac56
M
19
20/* 8-bit register offset in PMIC */
21#define HISI_MASK_STATE 0xff
22
b240d014
MCC
23#define HISI_IRQ_ARRAY 2
24#define HISI_IRQ_NUM (HISI_IRQ_ARRAY * 8)
25
26#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202
27#define SOC_PMIC_IRQ0_ADDR 0x0212
28
4524ac56
M
29#define HISI_IRQ_KEY_NUM 0
30#define HISI_IRQ_KEY_VALUE 0xc0
31#define HISI_IRQ_KEY_DOWN 7
32#define HISI_IRQ_KEY_UP 6
33
6b946699 34#define HISI_MASK_FIELD 0xFF
4524ac56 35#define HISI_BITS 8
4524ac56
M
36
37/*define the first group interrupt register number*/
6b946699 38#define HISI_PMIC_FIRST_GROUP_INT_NUM 2
4524ac56 39
cf0f27b7
MCC
40static const struct mfd_cell hi6421v600_devs[] = {
41 { .name = "hi6421v600-regulator", },
4524ac56
M
42};
43
fb02e3eb 44static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
4524ac56 45{
fcd73240 46 struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
4524ac56 47 unsigned long pending;
fb02e3eb 48 unsigned int data;
4524ac56
M
49 int i, offset;
50
b240d014 51 for (i = 0; i < HISI_IRQ_ARRAY; i++) {
fcd73240 52 regmap_read(ddata->regmap, offset, &data);
fb02e3eb
MCC
53 data &= HISI_MASK_FIELD;
54 if (data != 0)
55 pr_debug("data[%d]=0x%d\n\r", i, data);
fcd73240 56 regmap_write(ddata->regmap, i + SOC_PMIC_IRQ0_ADDR, data);
4524ac56 57
fb02e3eb
MCC
58 /* for_each_set_bit() macro requires unsigned long */
59 pending = data;
4524ac56 60
4b5e9b39 61 /* solve powerkey order */
6b946699
MCC
62 if ((i == HISI_IRQ_KEY_NUM) &&
63 ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) {
fcd73240
MCC
64 generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_DOWN]);
65 generic_handle_irq(ddata->irqs[HISI_IRQ_KEY_UP]);
4524ac56
M
66 pending &= (~HISI_IRQ_KEY_VALUE);
67 }
68
69 if (pending) {
70 for_each_set_bit(offset, &pending, HISI_BITS)
fcd73240 71 generic_handle_irq(ddata->irqs[offset + i * HISI_BITS]);
4524ac56
M
72 }
73 }
74
4524ac56
M
75 return IRQ_HANDLED;
76}
77
1eb2784a 78static void hi6421_spmi_irq_mask(struct irq_data *d)
4524ac56 79{
fcd73240 80 struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
4524ac56 81 unsigned long flags;
fb02e3eb
MCC
82 unsigned int data;
83 u32 offset;
4524ac56 84
4524ac56 85 offset = (irqd_to_hwirq(d) >> 3);
b240d014 86 offset += SOC_PMIC_IRQ_MASK_0_ADDR;
bd07d62a 87
fcd73240 88 spin_lock_irqsave(&ddata->lock, flags);
fb02e3eb 89
fcd73240 90 regmap_read(ddata->regmap, offset, &data);
4524ac56 91 data |= (1 << (irqd_to_hwirq(d) & 0x07));
fcd73240
MCC
92 regmap_write(ddata->regmap, offset, data);
93 spin_unlock_irqrestore(&ddata->lock, flags);
4524ac56
M
94}
95
1eb2784a 96static void hi6421_spmi_irq_unmask(struct irq_data *d)
4524ac56 97{
fcd73240 98 struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
4524ac56
M
99 u32 data, offset;
100 unsigned long flags;
101
4524ac56 102 offset = (irqd_to_hwirq(d) >> 3);
b240d014 103 offset += SOC_PMIC_IRQ_MASK_0_ADDR;
bd07d62a 104
fcd73240
MCC
105 spin_lock_irqsave(&ddata->lock, flags);
106 regmap_read(ddata->regmap, offset, &data);
02a9bd4f 107 data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
fcd73240
MCC
108 regmap_write(ddata->regmap, offset, data);
109 spin_unlock_irqrestore(&ddata->lock, flags);
4524ac56
M
110}
111
1eb2784a 112static struct irq_chip hi6421_spmi_pmu_irqchip = {
4524ac56 113 .name = "hisi-irq",
1eb2784a
MCC
114 .irq_mask = hi6421_spmi_irq_mask,
115 .irq_unmask = hi6421_spmi_irq_unmask,
116 .irq_disable = hi6421_spmi_irq_mask,
117 .irq_enable = hi6421_spmi_irq_unmask,
4524ac56
M
118};
119
1eb2784a 120static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
4d70881a 121 irq_hw_number_t hw)
4524ac56 122{
fcd73240 123 struct hi6421_spmi_pmic *ddata = d->host_data;
4524ac56 124
1eb2784a 125 irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
4524ac56 126 handle_simple_irq, "hisi");
fcd73240 127 irq_set_chip_data(virq, ddata);
4524ac56
M
128 irq_set_irq_type(virq, IRQ_TYPE_NONE);
129
130 return 0;
131}
132
1eb2784a
MCC
133static const struct irq_domain_ops hi6421_spmi_domain_ops = {
134 .map = hi6421_spmi_irq_map,
4524ac56
M
135 .xlate = irq_domain_xlate_twocell,
136};
137
fcd73240 138static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *ddata)
4524ac56 139{
fb02e3eb
MCC
140 int i;
141 unsigned int pending;
4b5e9b39 142
b240d014 143 for (i = 0 ; i < HISI_IRQ_ARRAY; i++)
fcd73240 144 regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
1eb2784a 145 HISI_MASK_STATE);
4524ac56 146
b240d014 147 for (i = 0 ; i < HISI_IRQ_ARRAY; i++) {
fcd73240 148 regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
4b5e9b39
MCC
149
150 pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n",
b240d014 151 SOC_PMIC_IRQ0_ADDR + i, pending);
fcd73240 152 regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
fb02e3eb 153 HISI_MASK_STATE);
4524ac56 154 }
4524ac56
M
155}
156
fb02e3eb
MCC
157static const struct regmap_config spmi_regmap_config = {
158 .reg_bits = 16,
159 .val_bits = 8,
160 .max_register = 0xffff,
161 .fast_io = true
162};
163
1eb2784a 164static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
4524ac56
M
165{
166 struct device *dev = &pdev->dev;
167 struct device_node *np = dev->of_node;
fcd73240 168 struct hi6421_spmi_pmic *ddata;
fb02e3eb 169 struct regmap *map;
4524ac56 170 unsigned int virq;
6b946699 171 int ret, i;
4524ac56 172
fcd73240
MCC
173 ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
174 if (!ddata)
4524ac56 175 return -ENOMEM;
4524ac56 176
fb02e3eb
MCC
177 map = devm_regmap_init_spmi_ext(pdev, &spmi_regmap_config);
178 if (IS_ERR(map))
179 return PTR_ERR(map);
180
fcd73240 181 spin_lock_init(&ddata->lock);
4524ac56 182
fcd73240
MCC
183 ddata->dev = dev;
184 ddata->regmap = map;
4524ac56 185
fcd73240
MCC
186 ddata->gpio = of_get_gpio(np, 0);
187 if (ddata->gpio < 0)
188 return ddata->gpio;
4524ac56 189
fcd73240 190 if (!gpio_is_valid(ddata->gpio))
4524ac56
M
191 return -EINVAL;
192
fcd73240 193 ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
4524ac56 194 if (ret < 0) {
fcd73240 195 dev_err(dev, "failed to request gpio%d\n", ddata->gpio);
4524ac56
M
196 return ret;
197 }
198
fcd73240 199 ddata->irq = gpio_to_irq(ddata->gpio);
4524ac56 200
fcd73240 201 hi6421_spmi_pmic_irq_prc(ddata);
4524ac56 202
fcd73240
MCC
203 ddata->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL);
204 if (!ddata->irqs) {
ba3e4a2a 205 ret = -ENOMEM;
4524ac56 206 goto irq_malloc;
ba3e4a2a 207 }
4524ac56 208
fcd73240
MCC
209 ddata->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0,
210 &hi6421_spmi_domain_ops, ddata);
211 if (!ddata->domain) {
4524ac56
M
212 dev_err(dev, "failed irq domain add simple!\n");
213 ret = -ENODEV;
6b946699 214 goto irq_malloc;
4524ac56
M
215 }
216
b240d014 217 for (i = 0; i < HISI_IRQ_NUM; i++) {
fcd73240 218 virq = irq_create_mapping(ddata->domain, i);
6b946699
MCC
219 if (!virq) {
220 dev_err(dev, "Failed mapping hwirq\n");
4524ac56 221 ret = -ENOSPC;
6b946699 222 goto irq_malloc;
4524ac56 223 }
fcd73240
MCC
224 ddata->irqs[i] = virq;
225 dev_dbg(dev, "%s: ddata->irqs[%d] = %d\n",
226 __func__, i, ddata->irqs[i]);
4524ac56
M
227 }
228
fcd73240 229 ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL,
4b5e9b39 230 IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
fcd73240 231 "pmic", ddata);
4524ac56 232 if (ret < 0) {
6b946699
MCC
233 dev_err(dev, "could not claim pmic IRQ: error %d\n", ret);
234 goto irq_malloc;
4524ac56
M
235 }
236
fcd73240 237 dev_set_drvdata(&pdev->dev, ddata);
cf0f27b7
MCC
238
239 /*
fcd73240 240 * The logic below will rely that the ddata is already stored at
cf0f27b7
MCC
241 * drvdata.
242 */
4d70881a 243 dev_dbg(&pdev->dev, "SPMI-PMIC: adding children for %pOF\n",
cf0f27b7
MCC
244 pdev->dev.of_node);
245 ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
246 hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
247 NULL, 0, NULL);
6b946699
MCC
248 if (!ret)
249 return 0;
cf0f27b7 250
6b946699 251 dev_err(dev, "Failed to add child devices: %d\n", ret);
4524ac56 252
4524ac56 253irq_malloc:
fcd73240 254 free_irq(ddata->irq, ddata);
6b946699 255
4524ac56
M
256 return ret;
257}
258
1eb2784a 259static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
4524ac56 260{
fcd73240 261 struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
4524ac56 262
fcd73240 263 free_irq(ddata->irq, ddata);
4524ac56 264}
4b5e9b39 265
cf0f27b7 266static const struct of_device_id pmic_spmi_id_table[] = {
9f46c343 267 { .compatible = "hisilicon,hi6421-spmi" },
cf0f27b7
MCC
268 { }
269};
270MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
4524ac56 271
1eb2784a 272static struct spmi_driver hi6421_spmi_pmic_driver = {
4524ac56 273 .driver = {
cf0f27b7
MCC
274 .name = "hi6421-spmi-pmic",
275 .of_match_table = pmic_spmi_id_table,
4524ac56 276 },
1eb2784a
MCC
277 .probe = hi6421_spmi_pmic_probe,
278 .remove = hi6421_spmi_pmic_remove,
4524ac56 279};
1eb2784a 280module_spmi_driver(hi6421_spmi_pmic_driver);
4524ac56 281
cf0f27b7 282MODULE_DESCRIPTION("HiSilicon Hi6421v600 SPMI PMIC driver");
4524ac56 283MODULE_LICENSE("GPL v2");