0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/err.h>
0012 #include <linux/i2c.h>
0013 #include <linux/init.h>
0014 #include <linux/mfd/core.h>
0015 #include <linux/mfd/stw481x.h>
0016 #include <linux/module.h>
0017 #include <linux/regmap.h>
0018 #include <linux/spinlock.h>
0019 #include <linux/slab.h>
0020
0021
0022
0023
0024
0025
0026
0027
0028 #define STW_PC_VCORE_SEL 0x05U
0029 #define STW_PC_VAUX_SEL 0x06U
0030 #define STW_PC_VPLL_SEL 0x07U
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 static int stw481x_get_pctl_reg(struct stw481x *stw481x, u8 reg)
0045 {
0046 u8 msb = (reg >> 3) & 0x03;
0047 u8 lsb = (reg << 5) & 0xe0;
0048 unsigned int val;
0049 u8 vrfy;
0050 int ret;
0051
0052 ret = regmap_write(stw481x->map, STW_PCTL_REG_HI, msb);
0053 if (ret)
0054 return ret;
0055 ret = regmap_write(stw481x->map, STW_PCTL_REG_LO, lsb);
0056 if (ret)
0057 return ret;
0058 ret = regmap_read(stw481x->map, STW_PCTL_REG_HI, &val);
0059 if (ret)
0060 return ret;
0061 vrfy = (val & 0x03) << 3;
0062 ret = regmap_read(stw481x->map, STW_PCTL_REG_LO, &val);
0063 if (ret)
0064 return ret;
0065 vrfy |= ((val >> 5) & 0x07);
0066 if (vrfy != reg)
0067 return -EIO;
0068 return (val >> 1) & 0x0f;
0069 }
0070
0071 static int stw481x_startup(struct stw481x *stw481x)
0072 {
0073
0074 static const u8 vcore_val[] = {
0075 100, 105, 110, 115, 120, 122, 124, 126, 128,
0076 130, 132, 134, 136, 138, 140, 145
0077 };
0078 static const u8 vpll_val[] = { 105, 120, 130, 180 };
0079 static const u8 vaux_val[] = { 15, 18, 25, 28 };
0080 u8 vcore;
0081 u8 vcore_slp;
0082 u8 vpll;
0083 u8 vaux;
0084 bool vaux_en;
0085 bool it_warn;
0086 int ret;
0087 unsigned int val;
0088
0089 ret = regmap_read(stw481x->map, STW_CONF1, &val);
0090 if (ret)
0091 return ret;
0092 vaux_en = !!(val & STW_CONF1_PDN_VAUX);
0093 it_warn = !!(val & STW_CONF1_IT_WARN);
0094
0095 dev_info(&stw481x->client->dev, "voltages %s\n",
0096 (val & STW_CONF1_V_MONITORING) ? "OK" : "LOW");
0097 dev_info(&stw481x->client->dev, "MMC level shifter %s\n",
0098 (val & STW_CONF1_MMC_LS_STATUS) ? "high impedance" : "ON");
0099 dev_info(&stw481x->client->dev, "VMMC: %s\n",
0100 (val & STW_CONF1_PDN_VMMC) ? "ON" : "disabled");
0101
0102 dev_info(&stw481x->client->dev, "STw481x power control registers:\n");
0103
0104 ret = stw481x_get_pctl_reg(stw481x, STW_PC_VCORE_SEL);
0105 if (ret < 0)
0106 return ret;
0107 vcore = ret & 0x0f;
0108
0109 ret = stw481x_get_pctl_reg(stw481x, STW_PC_VAUX_SEL);
0110 if (ret < 0)
0111 return ret;
0112 vaux = (ret >> 2) & 3;
0113 vpll = (ret >> 4) & 1;
0114
0115 ret = stw481x_get_pctl_reg(stw481x, STW_PC_VPLL_SEL);
0116 if (ret < 0)
0117 return ret;
0118 vpll |= (ret >> 1) & 2;
0119
0120 dev_info(&stw481x->client->dev, "VCORE: %u.%uV %s\n",
0121 vcore_val[vcore] / 100, vcore_val[vcore] % 100,
0122 (ret & 4) ? "ON" : "OFF");
0123
0124 dev_info(&stw481x->client->dev, "VPLL: %u.%uV %s\n",
0125 vpll_val[vpll] / 100, vpll_val[vpll] % 100,
0126 (ret & 0x10) ? "ON" : "OFF");
0127
0128 dev_info(&stw481x->client->dev, "VAUX: %u.%uV %s\n",
0129 vaux_val[vaux] / 10, vaux_val[vaux] % 10,
0130 vaux_en ? "ON" : "OFF");
0131
0132 ret = regmap_read(stw481x->map, STW_CONF2, &val);
0133 if (ret)
0134 return ret;
0135
0136 dev_info(&stw481x->client->dev, "TWARN: %s threshold, %s\n",
0137 it_warn ? "below" : "above",
0138 (val & STW_CONF2_MASK_TWARN) ?
0139 "enabled" : "mask through VDDOK");
0140 dev_info(&stw481x->client->dev, "VMMC: %s\n",
0141 (val & STW_CONF2_VMMC_EXT) ? "internal" : "external");
0142 dev_info(&stw481x->client->dev, "IT WAKE UP: %s\n",
0143 (val & STW_CONF2_MASK_IT_WAKE_UP) ? "enabled" : "masked");
0144 dev_info(&stw481x->client->dev, "GPO1: %s\n",
0145 (val & STW_CONF2_GPO1) ? "low" : "high impedance");
0146 dev_info(&stw481x->client->dev, "GPO2: %s\n",
0147 (val & STW_CONF2_GPO2) ? "low" : "high impedance");
0148
0149 ret = regmap_read(stw481x->map, STW_VCORE_SLEEP, &val);
0150 if (ret)
0151 return ret;
0152 vcore_slp = val & 0x0f;
0153 dev_info(&stw481x->client->dev, "VCORE SLEEP: %u.%uV\n",
0154 vcore_val[vcore_slp] / 100, vcore_val[vcore_slp] % 100);
0155
0156 return 0;
0157 }
0158
0159
0160
0161
0162
0163 static struct mfd_cell stw481x_cells[] = {
0164 {
0165 .of_compatible = "st,stw481x-vmmc",
0166 .name = "stw481x-vmmc-regulator",
0167 .id = -1,
0168 },
0169 };
0170
0171 static const struct regmap_config stw481x_regmap_config = {
0172 .reg_bits = 8,
0173 .val_bits = 8,
0174 };
0175
0176 static int stw481x_probe(struct i2c_client *client,
0177 const struct i2c_device_id *id)
0178 {
0179 struct stw481x *stw481x;
0180 int ret;
0181 int i;
0182
0183 stw481x = devm_kzalloc(&client->dev, sizeof(*stw481x), GFP_KERNEL);
0184 if (!stw481x)
0185 return -ENOMEM;
0186
0187 i2c_set_clientdata(client, stw481x);
0188 stw481x->client = client;
0189 stw481x->map = devm_regmap_init_i2c(client, &stw481x_regmap_config);
0190 if (IS_ERR(stw481x->map)) {
0191 ret = PTR_ERR(stw481x->map);
0192 dev_err(&client->dev, "Failed to allocate register map: %d\n",
0193 ret);
0194 return ret;
0195 }
0196
0197 ret = stw481x_startup(stw481x);
0198 if (ret) {
0199 dev_err(&client->dev, "chip initialization failed\n");
0200 return ret;
0201 }
0202
0203
0204 for (i = 0; i < ARRAY_SIZE(stw481x_cells); i++) {
0205
0206 stw481x_cells[i].platform_data = stw481x;
0207 stw481x_cells[i].pdata_size = sizeof(*stw481x);
0208 }
0209
0210 ret = devm_mfd_add_devices(&client->dev, 0, stw481x_cells,
0211 ARRAY_SIZE(stw481x_cells), NULL, 0, NULL);
0212 if (ret)
0213 return ret;
0214
0215 dev_info(&client->dev, "initialized STw481x device\n");
0216
0217 return ret;
0218 }
0219
0220
0221
0222
0223
0224
0225 static const struct i2c_device_id stw481x_id[] = {
0226 { "stw481x", 0 },
0227 { },
0228 };
0229 MODULE_DEVICE_TABLE(i2c, stw481x_id);
0230
0231 static const struct of_device_id stw481x_match[] = {
0232 { .compatible = "st,stw4810", },
0233 { .compatible = "st,stw4811", },
0234 { },
0235 };
0236 MODULE_DEVICE_TABLE(of, stw481x_match);
0237
0238 static struct i2c_driver stw481x_driver = {
0239 .driver = {
0240 .name = "stw481x",
0241 .of_match_table = stw481x_match,
0242 },
0243 .probe = stw481x_probe,
0244 .id_table = stw481x_id,
0245 };
0246
0247 module_i2c_driver(stw481x_driver);
0248
0249 MODULE_AUTHOR("Linus Walleij");
0250 MODULE_DESCRIPTION("STw481x PMIC driver");
0251 MODULE_LICENSE("GPL v2");