1 /* 2 * Copyright (c) 2014, The Linux Foundation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 and 6 * only version 2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include <linux/kernel.h> 15 #include <linux/module.h> 16 #include <linux/spmi.h> 17 #include <linux/regmap.h> 18 #include <linux/of_platform.h> 19 20 #define PMIC_REV2 0x101 21 #define PMIC_REV3 0x102 22 #define PMIC_REV4 0x103 23 #define PMIC_TYPE 0x104 24 #define PMIC_SUBTYPE 0x105 25 26 #define PMIC_TYPE_VALUE 0x51 27 28 #define COMMON_SUBTYPE 0x00 29 #define PM8941_SUBTYPE 0x01 30 #define PM8841_SUBTYPE 0x02 31 #define PM8019_SUBTYPE 0x03 32 #define PM8226_SUBTYPE 0x04 33 #define PM8110_SUBTYPE 0x05 34 #define PMA8084_SUBTYPE 0x06 35 #define PMI8962_SUBTYPE 0x07 36 #define PMD9635_SUBTYPE 0x08 37 #define PM8994_SUBTYPE 0x09 38 #define PMI8994_SUBTYPE 0x0a 39 #define PM8916_SUBTYPE 0x0b 40 #define PM8004_SUBTYPE 0x0c 41 #define PM8909_SUBTYPE 0x0d 42 43 static const struct of_device_id pmic_spmi_id_table[] = { 44 { .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE }, 45 { .compatible = "qcom,pm8941", .data = (void *)PM8941_SUBTYPE }, 46 { .compatible = "qcom,pm8841", .data = (void *)PM8841_SUBTYPE }, 47 { .compatible = "qcom,pm8019", .data = (void *)PM8019_SUBTYPE }, 48 { .compatible = "qcom,pm8226", .data = (void *)PM8226_SUBTYPE }, 49 { .compatible = "qcom,pm8110", .data = (void *)PM8110_SUBTYPE }, 50 { .compatible = "qcom,pma8084", .data = (void *)PMA8084_SUBTYPE }, 51 { .compatible = "qcom,pmi8962", .data = (void *)PMI8962_SUBTYPE }, 52 { .compatible = "qcom,pmd9635", .data = (void *)PMD9635_SUBTYPE }, 53 { .compatible = "qcom,pm8994", .data = (void *)PM8994_SUBTYPE }, 54 { .compatible = "qcom,pmi8994", .data = (void *)PMI8994_SUBTYPE }, 55 { .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE }, 56 { .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE }, 57 { .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE }, 58 { } 59 }; 60 61 static void pmic_spmi_show_revid(struct regmap *map, struct device *dev) 62 { 63 unsigned int rev2, minor, major, type, subtype; 64 const char *name = "unknown"; 65 int ret, i; 66 67 ret = regmap_read(map, PMIC_TYPE, &type); 68 if (ret < 0) 69 return; 70 71 if (type != PMIC_TYPE_VALUE) 72 return; 73 74 ret = regmap_read(map, PMIC_SUBTYPE, &subtype); 75 if (ret < 0) 76 return; 77 78 for (i = 0; i < ARRAY_SIZE(pmic_spmi_id_table); i++) { 79 if (subtype == (unsigned long)pmic_spmi_id_table[i].data) 80 break; 81 } 82 83 if (i != ARRAY_SIZE(pmic_spmi_id_table)) 84 name = pmic_spmi_id_table[i].compatible; 85 86 ret = regmap_read(map, PMIC_REV2, &rev2); 87 if (ret < 0) 88 return; 89 90 ret = regmap_read(map, PMIC_REV3, &minor); 91 if (ret < 0) 92 return; 93 94 ret = regmap_read(map, PMIC_REV4, &major); 95 if (ret < 0) 96 return; 97 98 /* 99 * In early versions of PM8941 and PM8226, the major revision number 100 * started incrementing from 0 (eg 0 = v1.0, 1 = v2.0). 101 * Increment the major revision number here if the chip is an early 102 * version of PM8941 or PM8226. 103 */ 104 if ((subtype == PM8941_SUBTYPE || subtype == PM8226_SUBTYPE) && 105 major < 0x02) 106 major++; 107 108 if (subtype == PM8110_SUBTYPE) 109 minor = rev2; 110 111 dev_dbg(dev, "%x: %s v%d.%d\n", subtype, name, major, minor); 112 } 113 114 static const struct regmap_config spmi_regmap_config = { 115 .reg_bits = 16, 116 .val_bits = 8, 117 .max_register = 0xffff, 118 .fast_io = true, 119 }; 120 121 static int pmic_spmi_probe(struct spmi_device *sdev) 122 { 123 struct device_node *root = sdev->dev.of_node; 124 struct regmap *regmap; 125 126 regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config); 127 if (IS_ERR(regmap)) 128 return PTR_ERR(regmap); 129 130 pmic_spmi_show_revid(regmap, &sdev->dev); 131 132 return of_platform_populate(root, NULL, NULL, &sdev->dev); 133 } 134 135 static void pmic_spmi_remove(struct spmi_device *sdev) 136 { 137 of_platform_depopulate(&sdev->dev); 138 } 139 140 MODULE_DEVICE_TABLE(of, pmic_spmi_id_table); 141 142 static struct spmi_driver pmic_spmi_driver = { 143 .probe = pmic_spmi_probe, 144 .remove = pmic_spmi_remove, 145 .driver = { 146 .name = "pmic-spmi", 147 .of_match_table = pmic_spmi_id_table, 148 }, 149 }; 150 module_spmi_driver(pmic_spmi_driver); 151 152 MODULE_DESCRIPTION("Qualcomm SPMI PMIC driver"); 153 MODULE_ALIAS("spmi:spmi-pmic"); 154 MODULE_LICENSE("GPL v2"); 155 MODULE_AUTHOR("Josh Cartwright <joshc@codeaurora.org>"); 156 MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>"); 157