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