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