File Index
Files and directories
Sign in
FILE

mt6397-core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/mfd/mt6397-core.c C
  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
 48static 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
 53static 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
 58static 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
 63static 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
 68static 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
 73static 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
 80static 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
 87static 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
 93static 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
 98static 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
105static 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
112static 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
117static 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
122static const struct resource mt6323_pwrc_resources[] = {
123	DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE),
124};
125
126static 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 = "mt6323-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
151static const struct mfd_cell mt6328_devs[] = {
152	{
153		.name = "mt6328-regulator",
154		.of_compatible = "mediatek,mt6328-regulator"
155	}, {
156		.name = "mt6328-keys",
157		.num_resources = ARRAY_SIZE(mt6328_keys_resources),
158		.resources = mt6328_keys_resources,
159		.of_compatible = "mediatek,mt6328-keys"
160	},
161};
162
163static 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 = "mt6357-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 */
186static 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 = "mt6331-keys",
200		.num_resources = ARRAY_SIZE(mt6331_keys_resources),
201		.resources = mt6331_keys_resources,
202		.of_compatible = "mediatek,mt6331-keys"
203	},
204};
205
206static 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
229static 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 = "mt6359-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
256static 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 = "mt6397-keys",
276		.num_resources = ARRAY_SIZE(mt6397_keys_resources),
277		.resources = mt6397_keys_resources,
278		.of_compatible = "mediatek,mt6397-keys"
279	}
280};
281
282struct 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
290static 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
298static 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
306static 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
314static 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
322static 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
330static 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
338static 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
346static 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
400static 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};
426MODULE_DEVICE_TABLE(of, mt6397_of_match);
427
428static const struct platform_device_id mt6397_id[] = {
429	{ "mt6397", 0 },
430	{ },
431};
432MODULE_DEVICE_TABLE(platform, mt6397_id);
433
434static 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
443module_platform_driver(mt6397_driver);
444
445MODULE_AUTHOR("Flora Fu, MediaTek");
446MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC");
447MODULE_LICENSE("GPL");
~/ Read-only file preview.