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 = "mt6357-regulator", 139 }, { 140 .name = "mt6357-rtc", 141 .num_resources = ARRAY_SIZE(mt6357_rtc_resources), 142 .resources = mt6357_rtc_resources, 143 .of_compatible = "mediatek,mt6357-rtc", 144 }, { 145 .name = "mt6357-sound", 146 .of_compatible = "mediatek,mt6357-sound" 147 }, { 148 .name = "mtk-pmic-keys", 149 .num_resources = ARRAY_SIZE(mt6357_keys_resources), 150 .resources = mt6357_keys_resources, 151 .of_compatible = "mediatek,mt6357-keys" 152 }, 153 }; 154 155 /* MT6331 is always used in combination with MT6332 */ 156 static const struct mfd_cell mt6331_mt6332_devs[] = { 157 { 158 .name = "mt6331-rtc", 159 .num_resources = ARRAY_SIZE(mt6331_rtc_resources), 160 .resources = mt6331_rtc_resources, 161 .of_compatible = "mediatek,mt6331-rtc", 162 }, { 163 .name = "mt6331-regulator", 164 .of_compatible = "mediatek,mt6331-regulator" 165 }, { 166 .name = "mt6332-regulator", 167 .of_compatible = "mediatek,mt6332-regulator" 168 }, { 169 .name = "mtk-pmic-keys", 170 .num_resources = ARRAY_SIZE(mt6331_keys_resources), 171 .resources = mt6331_keys_resources, 172 .of_compatible = "mediatek,mt6331-keys" 173 }, 174 }; 175 176 static const struct mfd_cell mt6358_devs[] = { 177 { 178 .name = "mt6358-regulator", 179 .of_compatible = "mediatek,mt6358-regulator" 180 }, { 181 .name = "mt6358-rtc", 182 .num_resources = ARRAY_SIZE(mt6358_rtc_resources), 183 .resources = mt6358_rtc_resources, 184 .of_compatible = "mediatek,mt6358-rtc", 185 }, { 186 .name = "mt6358-sound", 187 .of_compatible = "mediatek,mt6358-sound" 188 }, { 189 .name = "mt6358-keys", 190 .num_resources = ARRAY_SIZE(mt6358_keys_resources), 191 .resources = mt6358_keys_resources, 192 .of_compatible = "mediatek,mt6358-keys" 193 }, 194 }; 195 196 static const struct mfd_cell mt6359_devs[] = { 197 { .name = "mt6359-regulator", }, 198 { 199 .name = "mt6359-rtc", 200 .num_resources = ARRAY_SIZE(mt6358_rtc_resources), 201 .resources = mt6358_rtc_resources, 202 .of_compatible = "mediatek,mt6358-rtc", 203 }, 204 { .name = "mt6359-sound", }, 205 { 206 .name = "mtk-pmic-keys", 207 .num_resources = ARRAY_SIZE(mt6359_keys_resources), 208 .resources = mt6359_keys_resources, 209 .of_compatible = "mediatek,mt6359-keys" 210 }, 211 }; 212 213 static const struct mfd_cell mt6397_devs[] = { 214 { 215 .name = "mt6397-rtc", 216 .num_resources = ARRAY_SIZE(mt6397_rtc_resources), 217 .resources = mt6397_rtc_resources, 218 .of_compatible = "mediatek,mt6397-rtc", 219 }, { 220 .name = "mt6397-regulator", 221 .of_compatible = "mediatek,mt6397-regulator", 222 }, { 223 .name = "mt6397-codec", 224 .of_compatible = "mediatek,mt6397-codec", 225 }, { 226 .name = "mt6397-clk", 227 .of_compatible = "mediatek,mt6397-clk", 228 }, { 229 .name = "mt6397-pinctrl", 230 .of_compatible = "mediatek,mt6397-pinctrl", 231 }, { 232 .name = "mtk-pmic-keys", 233 .num_resources = ARRAY_SIZE(mt6397_keys_resources), 234 .resources = mt6397_keys_resources, 235 .of_compatible = "mediatek,mt6397-keys" 236 } 237 }; 238 239 struct chip_data { 240 u32 cid_addr; 241 u32 cid_shift; 242 const struct mfd_cell *cells; 243 int cell_size; 244 int (*irq_init)(struct mt6397_chip *chip); 245 }; 246 247 static const struct chip_data mt6323_core = { 248 .cid_addr = MT6323_CID, 249 .cid_shift = 0, 250 .cells = mt6323_devs, 251 .cell_size = ARRAY_SIZE(mt6323_devs), 252 .irq_init = mt6397_irq_init, 253 }; 254 255 static const struct chip_data mt6357_core = { 256 .cid_addr = MT6357_SWCID, 257 .cid_shift = 8, 258 .cells = mt6357_devs, 259 .cell_size = ARRAY_SIZE(mt6357_devs), 260 .irq_init = mt6358_irq_init, 261 }; 262 263 static const struct chip_data mt6331_mt6332_core = { 264 .cid_addr = MT6331_HWCID, 265 .cid_shift = 0, 266 .cells = mt6331_mt6332_devs, 267 .cell_size = ARRAY_SIZE(mt6331_mt6332_devs), 268 .irq_init = mt6397_irq_init, 269 }; 270 271 static const struct chip_data mt6358_core = { 272 .cid_addr = MT6358_SWCID, 273 .cid_shift = 8, 274 .cells = mt6358_devs, 275 .cell_size = ARRAY_SIZE(mt6358_devs), 276 .irq_init = mt6358_irq_init, 277 }; 278 279 static const struct chip_data mt6359_core = { 280 .cid_addr = MT6359_SWCID, 281 .cid_shift = 8, 282 .cells = mt6359_devs, 283 .cell_size = ARRAY_SIZE(mt6359_devs), 284 .irq_init = mt6358_irq_init, 285 }; 286 287 static const struct chip_data mt6397_core = { 288 .cid_addr = MT6397_CID, 289 .cid_shift = 0, 290 .cells = mt6397_devs, 291 .cell_size = ARRAY_SIZE(mt6397_devs), 292 .irq_init = mt6397_irq_init, 293 }; 294 295 static int mt6397_probe(struct platform_device *pdev) 296 { 297 int ret; 298 unsigned int id = 0; 299 struct mt6397_chip *pmic; 300 const struct chip_data *pmic_core; 301 302 pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 303 if (!pmic) 304 return -ENOMEM; 305 306 pmic->dev = &pdev->dev; 307 308 /* 309 * mt6397 MFD is child device of soc pmic wrapper. 310 * Regmap is set from its parent. 311 */ 312 pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL); 313 if (!pmic->regmap) 314 return -ENODEV; 315 316 pmic_core = of_device_get_match_data(&pdev->dev); 317 if (!pmic_core) 318 return -ENODEV; 319 320 ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id); 321 if (ret) { 322 dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret); 323 return ret; 324 } 325 326 pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff; 327 328 platform_set_drvdata(pdev, pmic); 329 330 pmic->irq = platform_get_irq(pdev, 0); 331 if (pmic->irq <= 0) 332 return pmic->irq; 333 334 ret = pmic_core->irq_init(pmic); 335 if (ret) 336 return ret; 337 338 ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, 339 pmic_core->cells, pmic_core->cell_size, 340 NULL, 0, pmic->irq_domain); 341 if (ret) { 342 irq_domain_remove(pmic->irq_domain); 343 dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); 344 } 345 346 return ret; 347 } 348 349 static const struct of_device_id mt6397_of_match[] = { 350 { 351 .compatible = "mediatek,mt6323", 352 .data = &mt6323_core, 353 }, { 354 .compatible = "mediatek,mt6331", 355 .data = &mt6331_mt6332_core, 356 }, { 357 .compatible = "mediatek,mt6357", 358 .data = &mt6357_core, 359 }, { 360 .compatible = "mediatek,mt6358", 361 .data = &mt6358_core, 362 }, { 363 .compatible = "mediatek,mt6359", 364 .data = &mt6359_core, 365 }, { 366 .compatible = "mediatek,mt6397", 367 .data = &mt6397_core, 368 }, { 369 /* sentinel */ 370 } 371 }; 372 MODULE_DEVICE_TABLE(of, mt6397_of_match); 373 374 static const struct platform_device_id mt6397_id[] = { 375 { "mt6397", 0 }, 376 { }, 377 }; 378 MODULE_DEVICE_TABLE(platform, mt6397_id); 379 380 static struct platform_driver mt6397_driver = { 381 .probe = mt6397_probe, 382 .driver = { 383 .name = "mt6397", 384 .of_match_table = mt6397_of_match, 385 }, 386 .id_table = mt6397_id, 387 }; 388 389 module_platform_driver(mt6397_driver); 390 391 MODULE_AUTHOR("Flora Fu, MediaTek"); 392 MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC"); 393 MODULE_LICENSE("GPL"); 394