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/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> 14 #include <linux/mfd/mt6323/core.h> 15 #include <linux/mfd/mt6331/core.h> 16 #include <linux/mfd/mt6357/core.h> 17 #include <linux/mfd/mt6358/core.h> 18 #include <linux/mfd/mt6359/core.h> 19 #include <linux/mfd/mt6397/core.h> 20 #include <linux/mfd/mt6323/registers.h> 21 #include <linux/mfd/mt6331/registers.h> 22 #include <linux/mfd/mt6357/registers.h> 23 #include <linux/mfd/mt6358/registers.h> 24 #include <linux/mfd/mt6359/registers.h> 25 #include <linux/mfd/mt6397/registers.h> 26 27 #define MT6323_RTC_BASE 0x8000 28 #define MT6323_RTC_SIZE 0x40 29 30 #define MT6357_RTC_BASE 0x0588 31 #define MT6357_RTC_SIZE 0x3c 32 33 #define MT6331_RTC_BASE 0x4000 34 #define MT6331_RTC_SIZE 0x40 35 36 #define MT6358_RTC_BASE 0x0588 37 #define MT6358_RTC_SIZE 0x3c 38 39 #define MT6397_RTC_BASE 0xe000 40 #define MT6397_RTC_SIZE 0x3e 41 42 #define MT6323_PWRC_BASE 0x8000 43 #define MT6323_PWRC_SIZE 0x40 44 45 static const struct resource mt6323_rtc_resources[] = { 46 DEFINE_RES_MEM(MT6323_RTC_BASE, MT6323_RTC_SIZE), 47 DEFINE_RES_IRQ(MT6323_IRQ_STATUS_RTC), 48 }; 49 50 static const struct resource mt6357_rtc_resources[] = { 51 DEFINE_RES_MEM(MT6357_RTC_BASE, MT6357_RTC_SIZE), 52 DEFINE_RES_IRQ(MT6357_IRQ_RTC), 53 }; 54 55 static const struct resource mt6331_rtc_resources[] = { 56 DEFINE_RES_MEM(MT6331_RTC_BASE, MT6331_RTC_SIZE), 57 DEFINE_RES_IRQ(MT6331_IRQ_STATUS_RTC), 58 }; 59 60 static const struct resource mt6358_rtc_resources[] = { 61 DEFINE_RES_MEM(MT6358_RTC_BASE, MT6358_RTC_SIZE), 62 DEFINE_RES_IRQ(MT6358_IRQ_RTC), 63 }; 64 65 static const struct resource mt6397_rtc_resources[] = { 66 DEFINE_RES_MEM(MT6397_RTC_BASE, MT6397_RTC_SIZE), 67 DEFINE_RES_IRQ(MT6397_IRQ_RTC), 68 }; 69 70 static const struct resource mt6358_keys_resources[] = { 71 DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY, "powerkey"), 72 DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY, "homekey"), 73 DEFINE_RES_IRQ_NAMED(MT6358_IRQ_PWRKEY_R, "powerkey_r"), 74 DEFINE_RES_IRQ_NAMED(MT6358_IRQ_HOMEKEY_R, "homekey_r"), 75 }; 76 77 static const struct resource mt6359_keys_resources[] = { 78 DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY, "powerkey"), 79 DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY, "homekey"), 80 DEFINE_RES_IRQ_NAMED(MT6359_IRQ_PWRKEY_R, "powerkey_r"), 81 DEFINE_RES_IRQ_NAMED(MT6359_IRQ_HOMEKEY_R, "homekey_r"), 82 }; 83 84 static const struct resource mt6323_keys_resources[] = { 85 DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_PWRKEY, "powerkey"), 86 DEFINE_RES_IRQ_NAMED(MT6323_IRQ_STATUS_FCHRKEY, "homekey"), 87 }; 88 89 static const struct resource mt6357_keys_resources[] = { 90 DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY, "powerkey"), 91 DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY, "homekey"), 92 DEFINE_RES_IRQ_NAMED(MT6357_IRQ_PWRKEY_R, "powerkey_r"), 93 DEFINE_RES_IRQ_NAMED(MT6357_IRQ_HOMEKEY_R, "homekey_r"), 94 }; 95 96 static const struct resource mt6331_keys_resources[] = { 97 DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_PWRKEY, "powerkey"), 98 DEFINE_RES_IRQ_NAMED(MT6331_IRQ_STATUS_HOMEKEY, "homekey"), 99 }; 100 101 static const struct resource mt6397_keys_resources[] = { 102 DEFINE_RES_IRQ_NAMED(MT6397_IRQ_PWRKEY, "powerkey"), 103 DEFINE_RES_IRQ_NAMED(MT6397_IRQ_HOMEKEY, "homekey"), 104 }; 105 106 static const struct resource mt6323_pwrc_resources[] = { 107 DEFINE_RES_MEM(MT6323_PWRC_BASE, MT6323_PWRC_SIZE), 108 }; 109 110 static const struct mfd_cell mt6323_devs[] = { 111 { 112 .name = "mt6323-rtc", 113 .num_resources = ARRAY_SIZE(mt6323_rtc_resources), 114 .resources = mt6323_rtc_resources, 115 .of_compatible = "mediatek,mt6323-rtc", 116 }, { 117 .name = "mt6323-regulator", 118 .of_compatible = "mediatek,mt6323-regulator" 119 }, { 120 .name = "mt6323-led", 121 .of_compatible = "mediatek,mt6323-led" 122 }, { 123 .name = "mtk-pmic-keys", 124 .num_resources = ARRAY_SIZE(mt6323_keys_resources), 125 .resources = mt6323_keys_resources, 126 .of_compatible = "mediatek,mt6323-keys" 127 }, { 128 .name = "mt6323-pwrc", 129 .num_resources = ARRAY_SIZE(mt6323_pwrc_resources), 130 .resources = mt6323_pwrc_resources, 131 .of_compatible = "mediatek,mt6323-pwrc" 132 }, 133 }; 134 135 static const struct mfd_cell mt6357_devs[] = { 136 { 137 .name = "mt6357-regulator", 138 }, { 139 .name = "mt6357-rtc", 140 .num_resources = ARRAY_SIZE(mt6357_rtc_resources), 141 .resources = mt6357_rtc_resources, 142 .of_compatible = "mediatek,mt6357-rtc", 143 }, { 144 .name = "mtk-pmic-keys", 145 .num_resources = ARRAY_SIZE(mt6357_keys_resources), 146 .resources = mt6357_keys_resources, 147 .of_compatible = "mediatek,mt6357-keys" 148 }, 149 }; 150 151 /* MT6331 is always used in combination with MT6332 */ 152 static const struct mfd_cell mt6331_mt6332_devs[] = { 153 { 154 .name = "mt6331-rtc", 155 .num_resources = ARRAY_SIZE(mt6331_rtc_resources), 156 .resources = mt6331_rtc_resources, 157 .of_compatible = "mediatek,mt6331-rtc", 158 }, { 159 .name = "mt6331-regulator", 160 .of_compatible = "mediatek,mt6331-regulator" 161 }, { 162 .name = "mt6332-regulator", 163 .of_compatible = "mediatek,mt6332-regulator" 164 }, { 165 .name = "mtk-pmic-keys", 166 .num_resources = ARRAY_SIZE(mt6331_keys_resources), 167 .resources = mt6331_keys_resources, 168 .of_compatible = "mediatek,mt6331-keys" 169 }, 170 }; 171 172 static const struct mfd_cell mt6358_devs[] = { 173 { 174 .name = "mt6358-regulator", 175 .of_compatible = "mediatek,mt6358-regulator" 176 }, { 177 .name = "mt6358-rtc", 178 .num_resources = ARRAY_SIZE(mt6358_rtc_resources), 179 .resources = mt6358_rtc_resources, 180 .of_compatible = "mediatek,mt6358-rtc", 181 }, { 182 .name = "mt6358-sound", 183 .of_compatible = "mediatek,mt6358-sound" 184 }, { 185 .name = "mt6358-keys", 186 .num_resources = ARRAY_SIZE(mt6358_keys_resources), 187 .resources = mt6358_keys_resources, 188 .of_compatible = "mediatek,mt6358-keys" 189 }, 190 }; 191 192 static const struct mfd_cell mt6359_devs[] = { 193 { .name = "mt6359-regulator", }, 194 { 195 .name = "mt6359-rtc", 196 .num_resources = ARRAY_SIZE(mt6358_rtc_resources), 197 .resources = mt6358_rtc_resources, 198 .of_compatible = "mediatek,mt6358-rtc", 199 }, 200 { .name = "mt6359-sound", }, 201 { 202 .name = "mtk-pmic-keys", 203 .num_resources = ARRAY_SIZE(mt6359_keys_resources), 204 .resources = mt6359_keys_resources, 205 .of_compatible = "mediatek,mt6359-keys" 206 }, 207 }; 208 209 static const struct mfd_cell mt6397_devs[] = { 210 { 211 .name = "mt6397-rtc", 212 .num_resources = ARRAY_SIZE(mt6397_rtc_resources), 213 .resources = mt6397_rtc_resources, 214 .of_compatible = "mediatek,mt6397-rtc", 215 }, { 216 .name = "mt6397-regulator", 217 .of_compatible = "mediatek,mt6397-regulator", 218 }, { 219 .name = "mt6397-codec", 220 .of_compatible = "mediatek,mt6397-codec", 221 }, { 222 .name = "mt6397-clk", 223 .of_compatible = "mediatek,mt6397-clk", 224 }, { 225 .name = "mt6397-pinctrl", 226 .of_compatible = "mediatek,mt6397-pinctrl", 227 }, { 228 .name = "mtk-pmic-keys", 229 .num_resources = ARRAY_SIZE(mt6397_keys_resources), 230 .resources = mt6397_keys_resources, 231 .of_compatible = "mediatek,mt6397-keys" 232 } 233 }; 234 235 struct chip_data { 236 u32 cid_addr; 237 u32 cid_shift; 238 const struct mfd_cell *cells; 239 int cell_size; 240 int (*irq_init)(struct mt6397_chip *chip); 241 }; 242 243 static const struct chip_data mt6323_core = { 244 .cid_addr = MT6323_CID, 245 .cid_shift = 0, 246 .cells = mt6323_devs, 247 .cell_size = ARRAY_SIZE(mt6323_devs), 248 .irq_init = mt6397_irq_init, 249 }; 250 251 static const struct chip_data mt6357_core = { 252 .cid_addr = MT6357_SWCID, 253 .cid_shift = 8, 254 .cells = mt6357_devs, 255 .cell_size = ARRAY_SIZE(mt6357_devs), 256 .irq_init = mt6358_irq_init, 257 }; 258 259 static const struct chip_data mt6331_mt6332_core = { 260 .cid_addr = MT6331_HWCID, 261 .cid_shift = 0, 262 .cells = mt6331_mt6332_devs, 263 .cell_size = ARRAY_SIZE(mt6331_mt6332_devs), 264 .irq_init = mt6397_irq_init, 265 }; 266 267 static const struct chip_data mt6358_core = { 268 .cid_addr = MT6358_SWCID, 269 .cid_shift = 8, 270 .cells = mt6358_devs, 271 .cell_size = ARRAY_SIZE(mt6358_devs), 272 .irq_init = mt6358_irq_init, 273 }; 274 275 static const struct chip_data mt6359_core = { 276 .cid_addr = MT6359_SWCID, 277 .cid_shift = 8, 278 .cells = mt6359_devs, 279 .cell_size = ARRAY_SIZE(mt6359_devs), 280 .irq_init = mt6358_irq_init, 281 }; 282 283 static const struct chip_data mt6397_core = { 284 .cid_addr = MT6397_CID, 285 .cid_shift = 0, 286 .cells = mt6397_devs, 287 .cell_size = ARRAY_SIZE(mt6397_devs), 288 .irq_init = mt6397_irq_init, 289 }; 290 291 static int mt6397_probe(struct platform_device *pdev) 292 { 293 int ret; 294 unsigned int id = 0; 295 struct mt6397_chip *pmic; 296 const struct chip_data *pmic_core; 297 298 pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); 299 if (!pmic) 300 return -ENOMEM; 301 302 pmic->dev = &pdev->dev; 303 304 /* 305 * mt6397 MFD is child device of soc pmic wrapper. 306 * Regmap is set from its parent. 307 */ 308 pmic->regmap = dev_get_regmap(pdev->dev.parent, NULL); 309 if (!pmic->regmap) 310 return -ENODEV; 311 312 pmic_core = of_device_get_match_data(&pdev->dev); 313 if (!pmic_core) 314 return -ENODEV; 315 316 ret = regmap_read(pmic->regmap, pmic_core->cid_addr, &id); 317 if (ret) { 318 dev_err(&pdev->dev, "Failed to read chip id: %d\n", ret); 319 return ret; 320 } 321 322 pmic->chip_id = (id >> pmic_core->cid_shift) & 0xff; 323 324 platform_set_drvdata(pdev, pmic); 325 326 pmic->irq = platform_get_irq(pdev, 0); 327 if (pmic->irq <= 0) 328 return pmic->irq; 329 330 ret = pmic_core->irq_init(pmic); 331 if (ret) 332 return ret; 333 334 ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, 335 pmic_core->cells, pmic_core->cell_size, 336 NULL, 0, pmic->irq_domain); 337 if (ret) { 338 irq_domain_remove(pmic->irq_domain); 339 dev_err(&pdev->dev, "failed to add child devices: %d\n", ret); 340 } 341 342 return ret; 343 } 344 345 static const struct of_device_id mt6397_of_match[] = { 346 { 347 .compatible = "mediatek,mt6323", 348 .data = &mt6323_core, 349 }, { 350 .compatible = "mediatek,mt6331", 351 .data = &mt6331_mt6332_core, 352 }, { 353 .compatible = "mediatek,mt6357", 354 .data = &mt6357_core, 355 }, { 356 .compatible = "mediatek,mt6358", 357 .data = &mt6358_core, 358 }, { 359 .compatible = "mediatek,mt6359", 360 .data = &mt6359_core, 361 }, { 362 .compatible = "mediatek,mt6397", 363 .data = &mt6397_core, 364 }, { 365 /* sentinel */ 366 } 367 }; 368 MODULE_DEVICE_TABLE(of, mt6397_of_match); 369 370 static const struct platform_device_id mt6397_id[] = { 371 { "mt6397", 0 }, 372 { }, 373 }; 374 MODULE_DEVICE_TABLE(platform, mt6397_id); 375 376 static struct platform_driver mt6397_driver = { 377 .probe = mt6397_probe, 378 .driver = { 379 .name = "mt6397", 380 .of_match_table = mt6397_of_match, 381 }, 382 .id_table = mt6397_id, 383 }; 384 385 module_platform_driver(mt6397_driver); 386 387 MODULE_AUTHOR("Flora Fu, MediaTek"); 388 MODULE_DESCRIPTION("Driver for MediaTek MT6397 PMIC"); 389 MODULE_LICENSE("GPL"); 390