1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014 MediaTek Inc.
4  * Author: Flora Fu, MediaTek
5  */
6 
7 #include <linux/interrupt.h>
8 #include <linux/ioport.h>
9 #include <linux/irqdomain.h>
10 #include <linux/module.h>
11 #include <linux/of.h>
12 #include <linux/platform_device.h>
13 #include <linux/regmap.h>
14 #include <linux/mfd/core.h>
15 #include <linux/mfd/mt6323/core.h>
16 #include <linux/mfd/mt6328/core.h>
17 #include <linux/mfd/mt6331/core.h>
18 #include <linux/mfd/mt6357/core.h>
19 #include <linux/mfd/mt6358/core.h>
20 #include <linux/mfd/mt6359/core.h>
21 #include <linux/mfd/mt6397/core.h>
22 #include <linux/mfd/mt6323/registers.h>
23 #include <linux/mfd/mt6328/registers.h>
24 #include <linux/mfd/mt6331/registers.h>
25 #include <linux/mfd/mt6357/registers.h>
26 #include <linux/mfd/mt6358/registers.h>
27 #include <linux/mfd/mt6359/registers.h>
28 #include <linux/mfd/mt6397/registers.h>
29 
30 #define MT6323_RTC_BASE		0x8000
31 #define MT6323_RTC_SIZE		0x40
32 
33 #define MT6357_RTC_BASE		0x0588
34 #define MT6357_RTC_SIZE		0x3c
35 
36 #define MT6331_RTC_BASE		0x4000
37 #define MT6331_RTC_SIZE		0x40
38 
39 #define MT6358_RTC_BASE		0x0588
40 #define MT6358_RTC_SIZE		0x3c
41 
42 #define MT6397_RTC_BASE		0xe000
43 #define MT6397_RTC_SIZE		0x3e
44 
45 #define MT6323_PWRC_BASE	0x8000
46 #define MT6323_PWRC_SIZE	0x40
47 
48 static const struct resource mt6323_rtc_resources[] = {
49 	DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE),
50 	DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC),
51 };
52 
53 static const struct resource mt6357_rtc_resources[] = {
54 	DEFINE_RES_MEM(MT6357_RTC_BASE, MT6357_RTC_SIZE),
55 	DEFINE_RES_IRQ(MT6357_IRQ_RTC),
56 };
57 
58 static const struct resource mt6331_rtc_resources[] = {
59 	DEFINE_RES_MEM(MT6331_RTC_BASE, MT6331_RTC_SIZE),
60 	DEFINE_RES_IRQ(MT6331_IRQ_STATUS_RTC),
61 };
62 
63 static const struct resource mt6358_rtc_resources[] = {
64 	DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE),
65 	DEFINE_RES_IRQ(MT6358_IRQ_RTC),
66 };
67 
68 static const struct resource mt6397_rtc_resources[] = {
69 	DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE),
70 	DEFINE_RES_IRQ(MT6397_IRQ_RTC),
71 };
72 
73 static const struct resource mt6358_keys_resources[] = {
74 	DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY, "powerkey"),
75 	DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY, "homekey"),
76 	DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY_R, "powerkey_r"),
77 	DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY_R, "homekey_r"),
78 };
79 
80 static const struct resource mt6359_keys_resources[] = {
81 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY, "powerkey"),
82 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY, "homekey"),
83 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY_R, "powerkey_r"),
84 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"),
85 };
86 
87 static const struct resource mt6359_accdet_resources[] = {
88 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET, "accdet_irq"),
89 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT0, "accdet_eint0"),
90 	DEFINE_RES_IRQ_NAMED(MT6359_IRQ_ACCDET_EINT1, "accdet_eint1"),
91 };
92 
93 static const struct resource mt6323_keys_resources[] = {
94 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"),
95 	DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"),
96 };
97 
98 static const struct resource mt6328_keys_resources[] = {
99 	DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_PWRKEY, "powerkey"),
100 	DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_HOMEKEY, "homekey"),
101 	DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_PWRKEY_R, "powerkey_r"),
102 	DEFINE_RES_IRQ_NAMED(MT6328_IRQ_STATUS_HOMEKEY_R, "homekey_r"),
103 };
104 
105 static const struct resource mt6357_keys_resources[] = {
106 	DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY, "powerkey"),
107 	DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY, "homekey"),
108 	DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY_R, "powerkey_r"),
109 	DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY_R, "homekey_r"),
110 };
111 
112 static const struct resource mt6331_keys_resources[] = {
113 	DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_PWRKEY, "powerkey"),
114 	DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"),
115 };
116 
117 static const struct resource mt6397_keys_resources[] = {
118 	DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"),
119 	DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"),
120 };
121 
122 static const struct resource mt6323_pwrc_resources[] = {
123 	DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE),
124 };
125 
126 static const struct mfd_cell mt6323_devs[] = {
127 	{
128 		.name = "mt6323-rtc",
129 		.num_resources = ARRAY_SIZE(mt6323_rtc_resources),
130 		.resources = mt6323_rtc_resources,
131 		.of_compatible = "mediatek,mt6323-rtc",
132 	}, {
133 		.name = "mt6323-regulator",
134 		.of_compatible = "mediatek,mt6323-regulator"
135 	}, {
136 		.name = "mt6323-led",
137 		.of_compatible = "mediatek,mt6323-led"
138 	}, {
139 		.name = "mtk-pmic-keys",
140 		.num_resources = ARRAY_SIZE(mt6323_keys_resources),
141 		.resources = mt6323_keys_resources,
142 		.of_compatible = "mediatek,mt6323-keys"
143 	}, {
144 		.name = "mt6323-pwrc",
145 		.num_resources = ARRAY_SIZE(mt6323_pwrc_resources),
146 		.resources = mt6323_pwrc_resources,
147 		.of_compatible = "mediatek,mt6323-pwrc"
148 	},
149 };
150 
151 static const struct mfd_cell mt6328_devs[] = {
152 	{
153 		.name = "mt6328-regulator",
154 		.of_compatible = "mediatek,mt6328-regulator"
155 	}, {
156 		.name = "mtk-pmic-keys",
157 		.num_resources = ARRAY_SIZE(mt6328_keys_resources),
158 		.resources = mt6328_keys_resources,
159 		.of_compatible = "mediatek,mt6328-keys"
160 	},
161 };
162 
163 static const struct mfd_cell mt6357_devs[] = {
164 	{
165 		.name = "mt6359-auxadc",
166 		.of_compatible = "mediatek,mt6357-auxadc"
167 	}, {
168 		.name = "mt6357-regulator",
169 	}, {
170 		.name = "mt6357-rtc",
171 		.num_resources = ARRAY_SIZE(mt6357_rtc_resources),
172 		.resources = mt6357_rtc_resources,
173 		.of_compatible = "mediatek,mt6357-rtc",
174 	}, {
175 		.name = "mt6357-sound",
176 		.of_compatible = "mediatek,mt6357-sound"
177 	}, {
178 		.name = "mtk-pmic-keys",
179 		.num_resources = ARRAY_SIZE(mt6357_keys_resources),
180 		.resources = mt6357_keys_resources,
181 		.of_compatible = "mediatek,mt6357-keys"
182 	},
183 };
184 
185 /* MT6331 is always used in combination with MT6332 */
186 static const struct mfd_cell mt6331_mt6332_devs[] = {
187 	{
188 		.name = "mt6331-rtc",
189 		.num_resources = ARRAY_SIZE(mt6331_rtc_resources),
190 		.resources = mt6331_rtc_resources,
191 		.of_compatible = "mediatek,mt6331-rtc",
192 	}, {
193 		.name = "mt6331-regulator",
194 		.of_compatible = "mediatek,mt6331-regulator"
195 	}, {
196 		.name = "mt6332-regulator",
197 		.of_compatible = "mediatek,mt6332-regulator"
198 	}, {
199 		.name = "mtk-pmic-keys",
200 		.num_resources = ARRAY_SIZE(mt6331_keys_resources),
201 		.resources = mt6331_keys_resources,
202 		.of_compatible = "mediatek,mt6331-keys"
203 	},
204 };
205 
206 static const struct mfd_cell mt6358_devs[] = {
207 	{
208 		.name = "mt6359-auxadc",
209 		.of_compatible = "mediatek,mt6358-auxadc"
210 	}, {
211 		.name = "mt6358-regulator",
212 		.of_compatible = "mediatek,mt6358-regulator"
213 	}, {
214 		.name = "mt6358-rtc",
215 		.num_resources = ARRAY_SIZE(mt6358_rtc_resources),
216 		.resources = mt6358_rtc_resources,
217 		.of_compatible = "mediatek,mt6358-rtc",
218 	}, {
219 		.name = "mt6358-sound",
220 		.of_compatible = "mediatek,mt6358-sound"
221 	}, {
222 		.name = "mt6358-keys",
223 		.num_resources = ARRAY_SIZE(mt6358_keys_resources),
224 		.resources = mt6358_keys_resources,
225 		.of_compatible = "mediatek,mt6358-keys"
226 	},
227 };
228 
229 static const struct mfd_cell mt6359_devs[] = {
230 	{
231 		.name = "mt6359-auxadc",
232 		.of_compatible = "mediatek,mt6359-auxadc"
233 	},
234 	{ .name = "mt6359-regulator", },
235 	{
236 		.name = "mt6359-rtc",
237 		.num_resources = ARRAY_SIZE(mt6358_rtc_resources),
238 		.resources = mt6358_rtc_resources,
239 		.of_compatible = "mediatek,mt6358-rtc",
240 	},
241 	{ .name = "mt6359-sound", },
242 	{
243 		.name = "mtk-pmic-keys",
244 		.num_resources = ARRAY_SIZE(mt6359_keys_resources),
245 		.resources = mt6359_keys_resources,
246 		.of_compatible = "mediatek,mt6359-keys"
247 	},
248 	{
249 		.name = "mt6359-accdet",
250 		.of_compatible = "mediatek,mt6359-accdet",
251 		.num_resources = ARRAY_SIZE(mt6359_accdet_resources),
252 		.resources = mt6359_accdet_resources,
253 	},
254 };
255 
256 static const struct mfd_cell mt6397_devs[] = {
257 	{
258 		.name = "mt6397-rtc",
259 		.num_resources = ARRAY_SIZE(mt6397_rtc_resources),
260 		.resources = mt6397_rtc_resources,
261 		.of_compatible = "mediatek,mt6397-rtc",
262 	}, {
263 		.name = "mt6397-regulator",
264 		.of_compatible = "mediatek,mt6397-regulator",
265 	}, {
266 		.name = "mt6397-codec",
267 		.of_compatible = "mediatek,mt6397-codec",
268 	}, {
269 		.name = "mt6397-clk",
270 		.of_compatible = "mediatek,mt6397-clk",
271 	}, {
272 		.name = "mt6397-pinctrl",
273 		.of_compatible = "mediatek,mt6397-pinctrl",
274 	}, {
275 		.name = "mtk-pmic-keys",
276 		.num_resources = ARRAY_SIZE(mt6397_keys_resources),
277 		.resources = mt6397_keys_resources,
278 		.of_compatible = "mediatek,mt6397-keys"
279 	}
280 };
281 
282 struct chip_data {
283 	u32 cid_addr;
284 	u32 cid_shift;
285 	const struct mfd_cell *cells;
286 	int cell_size;
287 	int (*irq_init)(struct mt6397_chip *chip);
288 };
289 
290 static const struct chip_data mt6323_core = {
291 	.cid_addr = MT6323_CID,
292 	.cid_shift = 0,
293 	.cells = mt6323_devs,
294 	.cell_size = ARRAY_SIZE(mt6323_devs),
295 	.irq_init = mt6397_irq_init,
296 };
297 
298 static const struct chip_data mt6328_core = {
299 	.cid_addr = MT6328_HWCID,
300 	.cid_shift = 0,
301 	.cells = mt6328_devs,
302 	.cell_size = ARRAY_SIZE(mt6328_devs),
303 	.irq_init = mt6397_irq_init,
304 };
305 
306 static const struct chip_data mt6357_core = {
307 	.cid_addr = MT6357_SWCID,
308 	.cid_shift = 8,
309 	.cells = mt6357_devs,
310 	.cell_size = ARRAY_SIZE(mt6357_devs),
311 	.irq_init = mt6358_irq_init,
312 };
313 
314 static const struct chip_data mt6331_mt6332_core = {
315 	.cid_addr = MT6331_HWCID,
316 	.cid_shift = 0,
317 	.cells = mt6331_mt6332_devs,
318 	.cell_size = ARRAY_SIZE(mt6331_mt6332_devs),
319 	.irq_init = mt6397_irq_init,
320 };
321 
322 static const struct chip_data mt6358_core = {
323 	.cid_addr = MT6358_SWCID,
324 	.cid_shift = 8,
325 	.cells = mt6358_devs,
326 	.cell_size = ARRAY_SIZE(mt6358_devs),
327 	.irq_init = mt6358_irq_init,
328 };
329 
330 static const struct chip_data mt6359_core = {
331 	.cid_addr = MT6359_SWCID,
332 	.cid_shift = 8,
333 	.cells = mt6359_devs,
334 	.cell_size = ARRAY_SIZE(mt6359_devs),
335 	.irq_init = mt6358_irq_init,
336 };
337 
338 static const struct chip_data mt6397_core = {
339 	.cid_addr = MT6397_CID,
340 	.cid_shift = 0,
341 	.cells = mt6397_devs,
342 	.cell_size = ARRAY_SIZE(mt6397_devs),
343 	.irq_init = mt6397_irq_init,
344 };
345 
mt6397_probe(struct platform_device * pdev)346 static int mt6397_probe(struct platform_device *pdev)
347 {
348 	int ret;
349 	unsigned int id = 0;
350 	struct mt6397_chip *pmic;
351 	const struct chip_data *pmic_core;
352 
353 	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
354 	if (!pmic)
355 		return -ENOMEM;
356 
357 	pmic->dev = &pdev->dev;
358 
359 	/*
360 	 * mt6397 MFD is child device of soc pmic wrapper.
361 	 * Regmap is set from its parent.
362 	 */
363 	pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);
364 	if (!pmic->regmap)
365 		return -ENODEV;
366 
367 	pmic_core = of_device_get_match_data(&pdev->dev);
368 	if (!pmic_core)
369 		return -ENODEV;
370 
371 	ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
372 	if (ret) {
373 		dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret);
374 		return ret;
375 	}
376 
377 	pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff;
378 
379 	platform_set_drvdata(pdev, pmic);
380 
381 	pmic->irq = platform_get_irq(pdev, 0);
382 	if (pmic->irq <= 0)
383 		return pmic->irq;
384 
385 	ret = pmic_core->irq_init(pmic);
386 	if (ret)
387 		return ret;
388 
389 	ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
390 				   pmic_core->cells, pmic_core->cell_size,
391 				   NULL, 0, pmic->irq_domain);
392 	if (ret) {
393 		irq_domain_remove(pmic->irq_domain);
394 		dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
395 	}
396 
397 	return ret;
398 }
399 
400 static const struct of_device_id mt6397_of_match[] = {
401 	{
402 		.compatible = "mediatek,mt6323",
403 		.data = &mt6323_core,
404 	}, {
405 		.compatible = "mediatek,mt6328",
406 		.data = &mt6328_core,
407 	}, {
408 		.compatible = "mediatek,mt6331",
409 		.data = &mt6331_mt6332_core,
410 	}, {
411 		.compatible = "mediatek,mt6357",
412 		.data = &mt6357_core,
413 	}, {
414 		.compatible = "mediatek,mt6358",
415 		.data = &mt6358_core,
416 	}, {
417 		.compatible = "mediatek,mt6359",
418 		.data = &mt6359_core,
419 	}, {
420 		.compatible = "mediatek,mt6397",
421 		.data = &mt6397_core,
422 	}, {
423 		/* sentinel */
424 	}
425 };
426 MODULE_DEVICE_TABLE(of, mt6397_of_match);
427 
428 static const struct platform_device_id mt6397_id[] = {
429 	{ "mt6397", 0 },
430 	{ },
431 };
432 MODULE_DEVICE_TABLE(platform, mt6397_id);
433 
434 static struct platform_driver mt6397_driver = {
435 	.probe = mt6397_probe,
436 	.driver = {
437 		.name = "mt6397",
438 		.of_match_table = mt6397_of_match,
439 	},
440 	.id_table = mt6397_id,
441 };
442 
443 module_platform_driver(mt6397_driver);
444 
445 MODULE_AUTHOR("Flora Fu, MediaTek");
446 MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
447 MODULE_LICENSE("GPL");
448