Thomas Gleixner | 1802d0b | 2019-05-27 08:55:21 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 2 | /* |
| 3 | * Copyright (c) 2014 MediaTek Inc. |
| 4 | * Author: Flora Fu, MediaTek |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 5 | */ |
| 6 | |
| 7 | #include <linux/interrupt.h> |
Josef Friedl | 7c3f7cd | 2019-08-18 15:56:06 +0200 | [diff] [blame] | 8 | #include <linux/ioport.h> |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 9 | #include <linux/module.h> |
| 10 | #include <linux/of_device.h> |
| 11 | #include <linux/of_irq.h> |
| 12 | #include <linux/regmap.h> |
| 13 | #include <linux/mfd/core.h> |
John Crispin | 44760cf | 2016-01-27 12:47:38 +0100 | [diff] [blame] | 14 | #include <linux/mfd/mt6323/core.h> |
Hsin-Hsiung Wang | 2b91c28 | 2020-04-21 11:00:10 +0800 | [diff] [blame] | 15 | #include <linux/mfd/mt6358/core.h> |
Hsin-Hsiung Wang | 708cb5c | 2019-08-05 13:21:49 +0800 | [diff] [blame] | 16 | #include <linux/mfd/mt6397/core.h> |
John Crispin | 44760cf | 2016-01-27 12:47:38 +0100 | [diff] [blame] | 17 | #include <linux/mfd/mt6323/registers.h> |
Hsin-Hsiung Wang | 2b91c28 | 2020-04-21 11:00:10 +0800 | [diff] [blame] | 18 | #include <linux/mfd/mt6358/registers.h> |
Hsin-Hsiung Wang | 708cb5c | 2019-08-05 13:21:49 +0800 | [diff] [blame] | 19 | #include <linux/mfd/mt6397/registers.h> |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 20 | |
Josef Friedl | 8391c6c | 2019-08-18 15:56:08 +0200 | [diff] [blame] | 21 | #define MT6323_RTC_BASE 0x8000 |
| 22 | #define MT6323_RTC_SIZE 0x40 |
| 23 | |
Hsin-Hsiung Wang | 2b91c28 | 2020-04-21 11:00:10 +0800 | [diff] [blame] | 24 | #define MT6358_RTC_BASE 0x0588 |
| 25 | #define MT6358_RTC_SIZE 0x3c |
| 26 | |
Eddie Huang | a5d7ea0 | 2015-05-06 15:23:40 +0800 | [diff] [blame] | 27 | #define MT6397_RTC_BASE 0xe000 |
| 28 | #define MT6397_RTC_SIZE 0x3e |
| 29 | |
Josef Friedl | 8391c6c | 2019-08-18 15:56:08 +0200 | [diff] [blame] | 30 | #define MT6323_PWRC_BASE 0x8000 |
| 31 | #define MT6323_PWRC_SIZE 0x40 |
| 32 | |
| 33 | static const struct resource mt6323_rtc_resources[] = { |
| 34 | DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE), |
| 35 | DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC), |
| 36 | }; |
| 37 | |
Hsin-Hsiung Wang | 2b91c28 | 2020-04-21 11:00:10 +0800 | [diff] [blame] | 38 | static const struct resource mt6358_rtc_resources[] = { |
| 39 | DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE), |
| 40 | DEFINE_RES_IRQ(MT6358_IRQ_RTC), |
| 41 | }; |
| 42 | |
Eddie Huang | a5d7ea0 | 2015-05-06 15:23:40 +0800 | [diff] [blame] | 43 | static const struct resource mt6397_rtc_resources[] = { |
Josef Friedl | 7c3f7cd | 2019-08-18 15:56:06 +0200 | [diff] [blame] | 44 | DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE), |
| 45 | DEFINE_RES_IRQ(MT6397_IRQ_RTC), |
Eddie Huang | a5d7ea0 | 2015-05-06 15:23:40 +0800 | [diff] [blame] | 46 | }; |
| 47 | |
Chen Zhong | 55d1d15 | 2017-10-25 21:16:04 +0800 | [diff] [blame] | 48 | static const struct resource mt6323_keys_resources[] = { |
| 49 | DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY), |
| 50 | DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY), |
| 51 | }; |
| 52 | |
| 53 | static const struct resource mt6397_keys_resources[] = { |
| 54 | DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY), |
| 55 | DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY), |
| 56 | }; |
| 57 | |
Josef Friedl | 8391c6c | 2019-08-18 15:56:08 +0200 | [diff] [blame] | 58 | static const struct resource mt6323_pwrc_resources[] = { |
| 59 | DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE), |
| 60 | }; |
| 61 | |
John Crispin | 44760cf | 2016-01-27 12:47:38 +0100 | [diff] [blame] | 62 | static const struct mfd_cell mt6323_devs[] = { |
| 63 | { |
Josef Friedl | 8391c6c | 2019-08-18 15:56:08 +0200 | [diff] [blame] | 64 | .name = "mt6323-rtc", |
| 65 | .num_resources = ARRAY_SIZE(mt6323_rtc_resources), |
| 66 | .resources = mt6323_rtc_resources, |
| 67 | .of_compatible = "mediatek,mt6323-rtc", |
| 68 | }, { |
John Crispin | 44760cf | 2016-01-27 12:47:38 +0100 | [diff] [blame] | 69 | .name = "mt6323-regulator", |
| 70 | .of_compatible = "mediatek,mt6323-regulator" |
Sean Wang | 040fc9b | 2017-03-20 14:47:27 +0800 | [diff] [blame] | 71 | }, { |
Sean Wang | 1cb8af8 | 2017-01-23 11:54:45 +0800 | [diff] [blame] | 72 | .name = "mt6323-led", |
| 73 | .of_compatible = "mediatek,mt6323-led" |
Chen Zhong | 55d1d15 | 2017-10-25 21:16:04 +0800 | [diff] [blame] | 74 | }, { |
| 75 | .name = "mtk-pmic-keys", |
| 76 | .num_resources = ARRAY_SIZE(mt6323_keys_resources), |
| 77 | .resources = mt6323_keys_resources, |
| 78 | .of_compatible = "mediatek,mt6323-keys" |
Josef Friedl | 8391c6c | 2019-08-18 15:56:08 +0200 | [diff] [blame] | 79 | }, { |
| 80 | .name = "mt6323-pwrc", |
| 81 | .num_resources = ARRAY_SIZE(mt6323_pwrc_resources), |
| 82 | .resources = mt6323_pwrc_resources, |
| 83 | .of_compatible = "mediatek,mt6323-pwrc" |
Sean Wang | 1cb8af8 | 2017-01-23 11:54:45 +0800 | [diff] [blame] | 84 | }, |
John Crispin | 44760cf | 2016-01-27 12:47:38 +0100 | [diff] [blame] | 85 | }; |
| 86 | |
Hsin-Hsiung Wang | 2b91c28 | 2020-04-21 11:00:10 +0800 | [diff] [blame] | 87 | static const struct mfd_cell mt6358_devs[] = { |
| 88 | { |
| 89 | .name = "mt6358-regulator", |
| 90 | .of_compatible = "mediatek,mt6358-regulator" |
| 91 | }, { |
| 92 | .name = "mt6358-rtc", |
| 93 | .num_resources = ARRAY_SIZE(mt6358_rtc_resources), |
| 94 | .resources = mt6358_rtc_resources, |
| 95 | .of_compatible = "mediatek,mt6358-rtc", |
| 96 | }, { |
| 97 | .name = "mt6358-sound", |
| 98 | .of_compatible = "mediatek,mt6358-sound" |
| 99 | }, |
| 100 | }; |
| 101 | |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 102 | static const struct mfd_cell mt6397_devs[] = { |
| 103 | { |
| 104 | .name = "mt6397-rtc", |
Eddie Huang | a5d7ea0 | 2015-05-06 15:23:40 +0800 | [diff] [blame] | 105 | .num_resources = ARRAY_SIZE(mt6397_rtc_resources), |
| 106 | .resources = mt6397_rtc_resources, |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 107 | .of_compatible = "mediatek,mt6397-rtc", |
| 108 | }, { |
| 109 | .name = "mt6397-regulator", |
| 110 | .of_compatible = "mediatek,mt6397-regulator", |
| 111 | }, { |
| 112 | .name = "mt6397-codec", |
| 113 | .of_compatible = "mediatek,mt6397-codec", |
| 114 | }, { |
| 115 | .name = "mt6397-clk", |
| 116 | .of_compatible = "mediatek,mt6397-clk", |
Hongzhou Yang | cf55078 | 2015-05-27 02:10:35 -0700 | [diff] [blame] | 117 | }, { |
| 118 | .name = "mt6397-pinctrl", |
| 119 | .of_compatible = "mediatek,mt6397-pinctrl", |
Chen Zhong | 55d1d15 | 2017-10-25 21:16:04 +0800 | [diff] [blame] | 120 | }, { |
| 121 | .name = "mtk-pmic-keys", |
| 122 | .num_resources = ARRAY_SIZE(mt6397_keys_resources), |
| 123 | .resources = mt6397_keys_resources, |
| 124 | .of_compatible = "mediatek,mt6397-keys" |
| 125 | } |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 126 | }; |
| 127 | |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 128 | struct chip_data { |
| 129 | u32 cid_addr; |
| 130 | u32 cid_shift; |
Hsin-Hsiung Wang | d0c7347 | 2020-04-21 11:00:08 +0800 | [diff] [blame] | 131 | const struct mfd_cell *cells; |
| 132 | int cell_size; |
| 133 | int (*irq_init)(struct mt6397_chip *chip); |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 134 | }; |
| 135 | |
| 136 | static const struct chip_data mt6323_core = { |
| 137 | .cid_addr = MT6323_CID, |
| 138 | .cid_shift = 0, |
Hsin-Hsiung Wang | d0c7347 | 2020-04-21 11:00:08 +0800 | [diff] [blame] | 139 | .cells = mt6323_devs, |
| 140 | .cell_size = ARRAY_SIZE(mt6323_devs), |
| 141 | .irq_init = mt6397_irq_init, |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 142 | }; |
| 143 | |
Hsin-Hsiung Wang | 2b91c28 | 2020-04-21 11:00:10 +0800 | [diff] [blame] | 144 | static const struct chip_data mt6358_core = { |
| 145 | .cid_addr = MT6358_SWCID, |
| 146 | .cid_shift = 8, |
| 147 | .cells = mt6358_devs, |
| 148 | .cell_size = ARRAY_SIZE(mt6358_devs), |
| 149 | .irq_init = mt6358_irq_init, |
| 150 | }; |
| 151 | |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 152 | static const struct chip_data mt6397_core = { |
| 153 | .cid_addr = MT6397_CID, |
| 154 | .cid_shift = 0, |
Hsin-Hsiung Wang | d0c7347 | 2020-04-21 11:00:08 +0800 | [diff] [blame] | 155 | .cells = mt6397_devs, |
| 156 | .cell_size = ARRAY_SIZE(mt6397_devs), |
| 157 | .irq_init = mt6397_irq_init, |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 158 | }; |
| 159 | |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 160 | static int mt6397_probe(struct platform_device *pdev) |
| 161 | { |
| 162 | int ret; |
Hsin-Hsiung Wang | d0c7347 | 2020-04-21 11:00:08 +0800 | [diff] [blame] | 163 | unsigned int id = 0; |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 164 | struct mt6397_chip *pmic; |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 165 | const struct chip_data *pmic_core; |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 166 | |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 167 | pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); |
| 168 | if (!pmic) |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 169 | return -ENOMEM; |
| 170 | |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 171 | pmic->dev = &pdev->dev; |
John Crispin | feec479 | 2016-01-27 12:47:36 +0100 | [diff] [blame] | 172 | |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 173 | /* |
| 174 | * mt6397 MFD is child device of soc pmic wrapper. |
| 175 | * Regmap is set from its parent. |
| 176 | */ |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 177 | pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL); |
| 178 | if (!pmic->regmap) |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 179 | return -ENODEV; |
| 180 | |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 181 | pmic_core = of_device_get_match_data(&pdev->dev); |
| 182 | if (!pmic_core) |
| 183 | return -ENODEV; |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 184 | |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 185 | ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id); |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 186 | if (ret) { |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 187 | dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret); |
Henry Chen | 1387ff5 | 2016-04-15 16:30:29 +0800 | [diff] [blame] | 188 | return ret; |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 189 | } |
| 190 | |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 191 | pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff; |
| 192 | |
| 193 | platform_set_drvdata(pdev, pmic); |
| 194 | |
Henry Chen | 1387ff5 | 2016-04-15 16:30:29 +0800 | [diff] [blame] | 195 | pmic->irq = platform_get_irq(pdev, 0); |
| 196 | if (pmic->irq <= 0) |
| 197 | return pmic->irq; |
| 198 | |
Hsin-Hsiung Wang | d0c7347 | 2020-04-21 11:00:08 +0800 | [diff] [blame] | 199 | ret = pmic_core->irq_init(pmic); |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 200 | if (ret) |
| 201 | return ret; |
Henry Chen | 1387ff5 | 2016-04-15 16:30:29 +0800 | [diff] [blame] | 202 | |
Hsin-Hsiung Wang | d0c7347 | 2020-04-21 11:00:08 +0800 | [diff] [blame] | 203 | ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, |
| 204 | pmic_core->cells, pmic_core->cell_size, |
| 205 | NULL, 0, pmic->irq_domain); |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 206 | if (ret) { |
| 207 | irq_domain_remove(pmic->irq_domain); |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 208 | dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); |
John Crispin | 1d2c25e | 2016-01-27 12:47:37 +0100 | [diff] [blame] | 209 | } |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 210 | |
| 211 | return ret; |
| 212 | } |
| 213 | |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 214 | static const struct of_device_id mt6397_of_match[] = { |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 215 | { |
| 216 | .compatible = "mediatek,mt6323", |
| 217 | .data = &mt6323_core, |
| 218 | }, { |
Hsin-Hsiung Wang | 2b91c28 | 2020-04-21 11:00:10 +0800 | [diff] [blame] | 219 | .compatible = "mediatek,mt6358", |
| 220 | .data = &mt6358_core, |
| 221 | }, { |
Frank Wunderlich | 11c4f2b | 2019-10-03 20:53:23 +0200 | [diff] [blame] | 222 | .compatible = "mediatek,mt6397", |
| 223 | .data = &mt6397_core, |
| 224 | }, { |
| 225 | /* sentinel */ |
| 226 | } |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 227 | }; |
| 228 | MODULE_DEVICE_TABLE(of, mt6397_of_match); |
| 229 | |
Javier Martinez Canillas | e1d9a10 | 2016-02-10 13:50:18 -0300 | [diff] [blame] | 230 | static const struct platform_device_id mt6397_id[] = { |
| 231 | { "mt6397", 0 }, |
| 232 | { }, |
| 233 | }; |
| 234 | MODULE_DEVICE_TABLE(platform, mt6397_id); |
| 235 | |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 236 | static struct platform_driver mt6397_driver = { |
| 237 | .probe = mt6397_probe, |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 238 | .driver = { |
| 239 | .name = "mt6397", |
| 240 | .of_match_table = of_match_ptr(mt6397_of_match), |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 241 | }, |
Javier Martinez Canillas | e1d9a10 | 2016-02-10 13:50:18 -0300 | [diff] [blame] | 242 | .id_table = mt6397_id, |
Flora Fu | 6df8dd5 | 2015-02-22 13:15:29 +0100 | [diff] [blame] | 243 | }; |
| 244 | |
| 245 | module_platform_driver(mt6397_driver); |
| 246 | |
| 247 | MODULE_AUTHOR("Flora Fu, MediaTek"); |
| 248 | MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC"); |
| 249 | MODULE_LICENSE("GPL"); |