xref: /linux/drivers/mfd/mt6397-core.c (revision 49bda4826843be0ef97a162009a29ea3a63f3935)
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-auxadc",
129 		.of_compatible = "mediatek,mt6323-auxadc",
130 	}, {
131 		.name = "mt6323-efuse",
132 		.of_compatible = "mediatek,mt6323-efuse",
133 	}, {
134 		.name = "mt6323-rtc",
135 		.num_resources = ARRAY_SIZE(mt6323_rtc_resources),
136 		.resources = mt6323_rtc_resources,
137 		.of_compatible = "mediatek,mt6323-rtc",
138 	}, {
139 		.name = "mt6323-regulator",
140 		.of_compatible = "mediatek,mt6323-regulator"
141 	}, {
142 		.name = "mt6323-led",
143 		.of_compatible = "mediatek,mt6323-led"
144 	}, {
145 		.name = "mt6323-keys",
146 		.num_resources = ARRAY_SIZE(mt6323_keys_resources),
147 		.resources = mt6323_keys_resources,
148 		.of_compatible = "mediatek,mt6323-keys"
149 	}, {
150 		.name = "mt6323-pwrc",
151 		.num_resources = ARRAY_SIZE(mt6323_pwrc_resources),
152 		.resources = mt6323_pwrc_resources,
153 		.of_compatible = "mediatek,mt6323-pwrc"
154 	},
155 };
156 
157 static const struct mfd_cell mt6328_devs[] = {
158 	{
159 		.name = "mt6328-regulator",
160 		.of_compatible = "mediatek,mt6328-regulator"
161 	}, {
162 		.name = "mt6328-keys",
163 		.num_resources = ARRAY_SIZE(mt6328_keys_resources),
164 		.resources = mt6328_keys_resources,
165 		.of_compatible = "mediatek,mt6328-keys"
166 	},
167 };
168 
169 static const struct mfd_cell mt6357_devs[] = {
170 	{
171 		.name = "mt6359-auxadc",
172 		.of_compatible = "mediatek,mt6357-auxadc"
173 	}, {
174 		.name = "mt6357-regulator",
175 	}, {
176 		.name = "mt6357-rtc",
177 		.num_resources = ARRAY_SIZE(mt6357_rtc_resources),
178 		.resources = mt6357_rtc_resources,
179 		.of_compatible = "mediatek,mt6357-rtc",
180 	}, {
181 		.name = "mt6357-sound",
182 		.of_compatible = "mediatek,mt6357-sound"
183 	}, {
184 		.name = "mt6357-keys",
185 		.num_resources = ARRAY_SIZE(mt6357_keys_resources),
186 		.resources = mt6357_keys_resources,
187 		.of_compatible = "mediatek,mt6357-keys"
188 	},
189 };
190 
191 /* MT6331 is always used in combination with MT6332 */
192 static const struct mfd_cell mt6331_mt6332_devs[] = {
193 	{
194 		.name = "mt6331-rtc",
195 		.num_resources = ARRAY_SIZE(mt6331_rtc_resources),
196 		.resources = mt6331_rtc_resources,
197 		.of_compatible = "mediatek,mt6331-rtc",
198 	}, {
199 		.name = "mt6331-regulator",
200 		.of_compatible = "mediatek,mt6331-regulator"
201 	}, {
202 		.name = "mt6332-regulator",
203 		.of_compatible = "mediatek,mt6332-regulator"
204 	}, {
205 		.name = "mt6331-keys",
206 		.num_resources = ARRAY_SIZE(mt6331_keys_resources),
207 		.resources = mt6331_keys_resources,
208 		.of_compatible = "mediatek,mt6331-keys"
209 	},
210 };
211 
212 static const struct mfd_cell mt6358_devs[] = {
213 	{
214 		.name = "mt6359-auxadc",
215 		.of_compatible = "mediatek,mt6358-auxadc"
216 	}, {
217 		.name = "mt6358-regulator",
218 		.of_compatible = "mediatek,mt6358-regulator"
219 	}, {
220 		.name = "mt6358-rtc",
221 		.num_resources = ARRAY_SIZE(mt6358_rtc_resources),
222 		.resources = mt6358_rtc_resources,
223 		.of_compatible = "mediatek,mt6358-rtc",
224 	}, {
225 		.name = "mt6358-sound",
226 		.of_compatible = "mediatek,mt6358-sound"
227 	}, {
228 		.name = "mt6358-keys",
229 		.num_resources = ARRAY_SIZE(mt6358_keys_resources),
230 		.resources = mt6358_keys_resources,
231 		.of_compatible = "mediatek,mt6358-keys"
232 	},
233 };
234 
235 static const struct mfd_cell mt6359_devs[] = {
236 	{
237 		.name = "mt6359-auxadc",
238 		.of_compatible = "mediatek,mt6359-auxadc"
239 	},
240 	{ .name = "mt6359-regulator", },
241 	{
242 		.name = "mt6359-rtc",
243 		.num_resources = ARRAY_SIZE(mt6358_rtc_resources),
244 		.resources = mt6358_rtc_resources,
245 		.of_compatible = "mediatek,mt6358-rtc",
246 	},
247 	{ .name = "mt6359-sound", },
248 	{
249 		.name = "mt6359-keys",
250 		.num_resources = ARRAY_SIZE(mt6359_keys_resources),
251 		.resources = mt6359_keys_resources,
252 		.of_compatible = "mediatek,mt6359-keys"
253 	},
254 	{
255 		.name = "mt6359-accdet",
256 		.of_compatible = "mediatek,mt6359-accdet",
257 		.num_resources = ARRAY_SIZE(mt6359_accdet_resources),
258 		.resources = mt6359_accdet_resources,
259 	},
260 };
261 
262 static const struct mfd_cell mt6397_devs[] = {
263 	{
264 		.name = "mt6397-rtc",
265 		.num_resources = ARRAY_SIZE(mt6397_rtc_resources),
266 		.resources = mt6397_rtc_resources,
267 		.of_compatible = "mediatek,mt6397-rtc",
268 	}, {
269 		.name = "mt6397-regulator",
270 		.of_compatible = "mediatek,mt6397-regulator",
271 	}, {
272 		.name = "mt6397-codec",
273 		.of_compatible = "mediatek,mt6397-codec",
274 	}, {
275 		.name = "mt6397-clk",
276 		.of_compatible = "mediatek,mt6397-clk",
277 	}, {
278 		.name = "mt6397-pinctrl",
279 		.of_compatible = "mediatek,mt6397-pinctrl",
280 	}, {
281 		.name = "mt6397-keys",
282 		.num_resources = ARRAY_SIZE(mt6397_keys_resources),
283 		.resources = mt6397_keys_resources,
284 		.of_compatible = "mediatek,mt6397-keys"
285 	}
286 };
287 
288 struct chip_data {
289 	u32 cid_addr;
290 	u32 cid_shift;
291 	const struct mfd_cell *cells;
292 	int cell_size;
293 	int (*irq_init)(struct mt6397_chip *chip);
294 };
295 
296 static const struct chip_data mt6323_core = {
297 	.cid_addr = MT6323_CID,
298 	.cid_shift = 0,
299 	.cells = mt6323_devs,
300 	.cell_size = ARRAY_SIZE(mt6323_devs),
301 	.irq_init = mt6397_irq_init,
302 };
303 
304 static const struct chip_data mt6328_core = {
305 	.cid_addr = MT6328_HWCID,
306 	.cid_shift = 8,
307 	.cells = mt6328_devs,
308 	.cell_size = ARRAY_SIZE(mt6328_devs),
309 	.irq_init = mt6397_irq_init,
310 };
311 
312 static const struct chip_data mt6357_core = {
313 	.cid_addr = MT6357_SWCID,
314 	.cid_shift = 8,
315 	.cells = mt6357_devs,
316 	.cell_size = ARRAY_SIZE(mt6357_devs),
317 	.irq_init = mt6358_irq_init,
318 };
319 
320 static const struct chip_data mt6331_mt6332_core = {
321 	.cid_addr = MT6331_HWCID,
322 	.cid_shift = 8,
323 	.cells = mt6331_mt6332_devs,
324 	.cell_size = ARRAY_SIZE(mt6331_mt6332_devs),
325 	.irq_init = mt6397_irq_init,
326 };
327 
328 static const struct chip_data mt6358_core = {
329 	.cid_addr = MT6358_SWCID,
330 	.cid_shift = 8,
331 	.cells = mt6358_devs,
332 	.cell_size = ARRAY_SIZE(mt6358_devs),
333 	.irq_init = mt6358_irq_init,
334 };
335 
336 static const struct chip_data mt6359_core = {
337 	.cid_addr = MT6359_SWCID,
338 	.cid_shift = 8,
339 	.cells = mt6359_devs,
340 	.cell_size = ARRAY_SIZE(mt6359_devs),
341 	.irq_init = mt6358_irq_init,
342 };
343 
344 static const struct chip_data mt6397_core = {
345 	.cid_addr = MT6397_CID,
346 	.cid_shift = 0,
347 	.cells = mt6397_devs,
348 	.cell_size = ARRAY_SIZE(mt6397_devs),
349 	.irq_init = mt6397_irq_init,
350 };
351 
mt6397_probe(struct platform_device * pdev)352 static int mt6397_probe(struct platform_device *pdev)
353 {
354 	int ret;
355 	unsigned int id = 0;
356 	struct mt6397_chip *pmic;
357 	const struct chip_data *pmic_core;
358 
359 	pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
360 	if (!pmic)
361 		return -ENOMEM;
362 
363 	pmic->dev = &pdev->dev;
364 
365 	/*
366 	 * mt6397 MFD is child device of soc pmic wrapper.
367 	 * Regmap is set from its parent.
368 	 */
369 	pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL);
370 	if (!pmic->regmap)
371 		return -ENODEV;
372 
373 	pmic_core = of_device_get_match_data(&pdev->dev);
374 	if (!pmic_core)
375 		return -ENODEV;
376 
377 	ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id);
378 	if (ret) {
379 		dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret);
380 		return ret;
381 	}
382 
383 	pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff;
384 
385 	platform_set_drvdata(pdev, pmic);
386 
387 	pmic->irq = platform_get_irq(pdev, 0);
388 	if (pmic->irq <= 0)
389 		return pmic->irq;
390 
391 	ret = pmic_core->irq_init(pmic);
392 	if (ret)
393 		return ret;
394 
395 	ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
396 				   pmic_core->cells, pmic_core->cell_size,
397 				   NULL, 0, pmic->irq_domain);
398 	if (ret) {
399 		irq_domain_remove(pmic->irq_domain);
400 		dev_err(&pdev->dev, "failed to add child devices: %d\n", ret);
401 	}
402 
403 	return ret;
404 }
405 
406 static const struct of_device_id mt6397_of_match[] = {
407 	{
408 		.compatible = "mediatek,mt6323",
409 		.data = &mt6323_core,
410 	}, {
411 		.compatible = "mediatek,mt6328",
412 		.data = &mt6328_core,
413 	}, {
414 		.compatible = "mediatek,mt6331",
415 		.data = &mt6331_mt6332_core,
416 	}, {
417 		.compatible = "mediatek,mt6357",
418 		.data = &mt6357_core,
419 	}, {
420 		.compatible = "mediatek,mt6358",
421 		.data = &mt6358_core,
422 	}, {
423 		.compatible = "mediatek,mt6359",
424 		.data = &mt6359_core,
425 	}, {
426 		.compatible = "mediatek,mt6397",
427 		.data = &mt6397_core,
428 	}, {
429 		/* sentinel */
430 	}
431 };
432 MODULE_DEVICE_TABLE(of, mt6397_of_match);
433 
434 static const struct platform_device_id mt6397_id[] = {
435 	{ "mt6397", 0 },
436 	{ },
437 };
438 MODULE_DEVICE_TABLE(platform, mt6397_id);
439 
440 static struct platform_driver mt6397_driver = {
441 	.probe = mt6397_probe,
442 	.driver = {
443 		.name = "mt6397",
444 		.of_match_table = mt6397_of_match,
445 	},
446 	.id_table = mt6397_id,
447 };
448 
449 module_platform_driver(mt6397_driver);
450 
451 MODULE_AUTHOR("Flora Fu, MediaTek");
452 MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
453 MODULE_LICENSE("GPL");
454