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