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 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