0001
0002
0003
0004
0005
0006 #include <linux/device.h>
0007 #include <linux/errno.h>
0008 #include <linux/gfp.h>
0009 #include <linux/kernel.h>
0010 #include <linux/module.h>
0011 #include <linux/spmi.h>
0012 #include <linux/types.h>
0013 #include <linux/regmap.h>
0014 #include <linux/of_platform.h>
0015 #include <soc/qcom/qcom-spmi-pmic.h>
0016
0017 #define PMIC_REV2 0x101
0018 #define PMIC_REV3 0x102
0019 #define PMIC_REV4 0x103
0020 #define PMIC_TYPE 0x104
0021 #define PMIC_SUBTYPE 0x105
0022 #define PMIC_FAB_ID 0x1f2
0023
0024 #define PMIC_TYPE_VALUE 0x51
0025
0026 #define PMIC_REV4_V2 0x02
0027
0028 struct qcom_spmi_dev {
0029 int num_usids;
0030 struct qcom_spmi_pmic pmic;
0031 };
0032
0033 #define N_USIDS(n) ((void *)n)
0034
0035 static const struct of_device_id pmic_spmi_id_table[] = {
0036 { .compatible = "qcom,pm660", .data = N_USIDS(2) },
0037 { .compatible = "qcom,pm660l", .data = N_USIDS(2) },
0038 { .compatible = "qcom,pm8004", .data = N_USIDS(2) },
0039 { .compatible = "qcom,pm8005", .data = N_USIDS(2) },
0040 { .compatible = "qcom,pm8019", .data = N_USIDS(2) },
0041 { .compatible = "qcom,pm8028", .data = N_USIDS(2) },
0042 { .compatible = "qcom,pm8110", .data = N_USIDS(2) },
0043 { .compatible = "qcom,pm8150", .data = N_USIDS(2) },
0044 { .compatible = "qcom,pm8150b", .data = N_USIDS(2) },
0045 { .compatible = "qcom,pm8150c", .data = N_USIDS(2) },
0046 { .compatible = "qcom,pm8150l", .data = N_USIDS(2) },
0047 { .compatible = "qcom,pm8226", .data = N_USIDS(2) },
0048 { .compatible = "qcom,pm8841", .data = N_USIDS(2) },
0049 { .compatible = "qcom,pm8901", .data = N_USIDS(2) },
0050 { .compatible = "qcom,pm8909", .data = N_USIDS(2) },
0051 { .compatible = "qcom,pm8916", .data = N_USIDS(2) },
0052 { .compatible = "qcom,pm8941", .data = N_USIDS(2) },
0053 { .compatible = "qcom,pm8950", .data = N_USIDS(2) },
0054 { .compatible = "qcom,pm8994", .data = N_USIDS(2) },
0055 { .compatible = "qcom,pm8998", .data = N_USIDS(2) },
0056 { .compatible = "qcom,pma8084", .data = N_USIDS(2) },
0057 { .compatible = "qcom,pmd9635", .data = N_USIDS(2) },
0058 { .compatible = "qcom,pmi8950", .data = N_USIDS(2) },
0059 { .compatible = "qcom,pmi8962", .data = N_USIDS(2) },
0060 { .compatible = "qcom,pmi8994", .data = N_USIDS(2) },
0061 { .compatible = "qcom,pmi8998", .data = N_USIDS(2) },
0062 { .compatible = "qcom,pmk8002", .data = N_USIDS(2) },
0063 { .compatible = "qcom,smb2351", .data = N_USIDS(2) },
0064 { .compatible = "qcom,spmi-pmic", .data = N_USIDS(1) },
0065 { }
0066 };
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078 static struct spmi_device *qcom_pmic_get_base_usid(struct device *dev)
0079 {
0080 struct spmi_device *sdev;
0081 struct qcom_spmi_dev *ctx;
0082 struct device_node *spmi_bus;
0083 struct device_node *other_usid = NULL;
0084 int function_parent_usid, ret;
0085 u32 pmic_addr;
0086
0087 sdev = to_spmi_device(dev);
0088 ctx = dev_get_drvdata(&sdev->dev);
0089
0090
0091
0092
0093
0094 if (sdev->usid % ctx->num_usids == 0)
0095 return sdev;
0096
0097 function_parent_usid = sdev->usid;
0098
0099
0100
0101
0102
0103
0104
0105
0106 spmi_bus = of_get_parent(sdev->dev.of_node);
0107 do {
0108 other_usid = of_get_next_child(spmi_bus, other_usid);
0109
0110 ret = of_property_read_u32_index(other_usid, "reg", 0, &pmic_addr);
0111 if (ret)
0112 return ERR_PTR(ret);
0113
0114 sdev = spmi_device_from_of(other_usid);
0115 if (pmic_addr == function_parent_usid - (ctx->num_usids - 1)) {
0116 if (!sdev)
0117
0118
0119
0120
0121
0122
0123 return ERR_PTR(-EPROBE_DEFER);
0124 return sdev;
0125 }
0126 } while (other_usid->sibling);
0127
0128 return ERR_PTR(-ENODATA);
0129 }
0130
0131 static int pmic_spmi_load_revid(struct regmap *map, struct device *dev,
0132 struct qcom_spmi_pmic *pmic)
0133 {
0134 int ret;
0135
0136 ret = regmap_read(map, PMIC_TYPE, &pmic->type);
0137 if (ret < 0)
0138 return ret;
0139
0140 if (pmic->type != PMIC_TYPE_VALUE)
0141 return ret;
0142
0143 ret = regmap_read(map, PMIC_SUBTYPE, &pmic->subtype);
0144 if (ret < 0)
0145 return ret;
0146
0147 pmic->name = of_match_device(pmic_spmi_id_table, dev)->compatible;
0148
0149 ret = regmap_read(map, PMIC_REV2, &pmic->rev2);
0150 if (ret < 0)
0151 return ret;
0152
0153 ret = regmap_read(map, PMIC_REV3, &pmic->minor);
0154 if (ret < 0)
0155 return ret;
0156
0157 ret = regmap_read(map, PMIC_REV4, &pmic->major);
0158 if (ret < 0)
0159 return ret;
0160
0161 if (pmic->subtype == PMI8998_SUBTYPE || pmic->subtype == PM660_SUBTYPE) {
0162 ret = regmap_read(map, PMIC_FAB_ID, &pmic->fab_id);
0163 if (ret < 0)
0164 return ret;
0165 }
0166
0167
0168
0169
0170
0171
0172
0173 if ((pmic->subtype == PM8941_SUBTYPE || pmic->subtype == PM8226_SUBTYPE) &&
0174 pmic->major < PMIC_REV4_V2)
0175 pmic->major++;
0176
0177 if (pmic->subtype == PM8110_SUBTYPE)
0178 pmic->minor = pmic->rev2;
0179
0180 dev_dbg(dev, "%x: %s v%d.%d\n",
0181 pmic->subtype, pmic->name, pmic->major, pmic->minor);
0182
0183 return 0;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195 const struct qcom_spmi_pmic *qcom_pmic_get(struct device *dev)
0196 {
0197 struct spmi_device *sdev;
0198 struct qcom_spmi_dev *spmi;
0199
0200
0201
0202
0203 if (!of_match_device(pmic_spmi_id_table, dev->parent))
0204 return ERR_PTR(-EINVAL);
0205
0206 sdev = qcom_pmic_get_base_usid(dev->parent);
0207
0208 if (IS_ERR(sdev))
0209 return ERR_CAST(sdev);
0210
0211 spmi = dev_get_drvdata(&sdev->dev);
0212
0213 return &spmi->pmic;
0214 }
0215 EXPORT_SYMBOL(qcom_pmic_get);
0216
0217 static const struct regmap_config spmi_regmap_config = {
0218 .reg_bits = 16,
0219 .val_bits = 8,
0220 .max_register = 0xffff,
0221 .fast_io = true,
0222 };
0223
0224 static int pmic_spmi_probe(struct spmi_device *sdev)
0225 {
0226 struct regmap *regmap;
0227 struct qcom_spmi_dev *ctx;
0228 int ret;
0229
0230 regmap = devm_regmap_init_spmi_ext(sdev, &spmi_regmap_config);
0231 if (IS_ERR(regmap))
0232 return PTR_ERR(regmap);
0233
0234 ctx = devm_kzalloc(&sdev->dev, sizeof(*ctx), GFP_KERNEL);
0235 if (!ctx)
0236 return -ENOMEM;
0237
0238 ctx->num_usids = (uintptr_t)of_device_get_match_data(&sdev->dev);
0239
0240
0241 if (sdev->usid % ctx->num_usids == 0) {
0242 ret = pmic_spmi_load_revid(regmap, &sdev->dev, &ctx->pmic);
0243 if (ret < 0)
0244 return ret;
0245 }
0246 spmi_device_set_drvdata(sdev, ctx);
0247
0248 return devm_of_platform_populate(&sdev->dev);
0249 }
0250
0251 MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
0252
0253 static struct spmi_driver pmic_spmi_driver = {
0254 .probe = pmic_spmi_probe,
0255 .driver = {
0256 .name = "pmic-spmi",
0257 .of_match_table = pmic_spmi_id_table,
0258 },
0259 };
0260 module_spmi_driver(pmic_spmi_driver);
0261
0262 MODULE_DESCRIPTION("Qualcomm SPMI PMIC driver");
0263 MODULE_ALIAS("spmi:spmi-pmic");
0264 MODULE_LICENSE("GPL v2");
0265 MODULE_AUTHOR("Josh Cartwright <joshc@codeaurora.org>");
0266 MODULE_AUTHOR("Stanimir Varbanov <svarbanov@mm-sol.com>");