0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/err.h>
0011 #include <linux/i2c.h>
0012 #include <linux/init.h>
0013 #include <linux/kernel.h>
0014 #include <linux/mfd/as3711.h>
0015 #include <linux/mfd/core.h>
0016 #include <linux/of.h>
0017 #include <linux/regmap.h>
0018 #include <linux/slab.h>
0019
0020 enum {
0021 AS3711_REGULATOR,
0022 AS3711_BACKLIGHT,
0023 };
0024
0025
0026
0027
0028
0029 static struct mfd_cell as3711_subdevs[] = {
0030 [AS3711_REGULATOR] = {.name = "as3711-regulator",},
0031 [AS3711_BACKLIGHT] = {.name = "as3711-backlight",},
0032 };
0033
0034 static bool as3711_volatile_reg(struct device *dev, unsigned int reg)
0035 {
0036 switch (reg) {
0037 case AS3711_GPIO_SIGNAL_IN:
0038 case AS3711_INTERRUPT_STATUS_1:
0039 case AS3711_INTERRUPT_STATUS_2:
0040 case AS3711_INTERRUPT_STATUS_3:
0041 case AS3711_CHARGER_STATUS_1:
0042 case AS3711_CHARGER_STATUS_2:
0043 case AS3711_REG_STATUS:
0044 return true;
0045 }
0046 return false;
0047 }
0048
0049 static bool as3711_precious_reg(struct device *dev, unsigned int reg)
0050 {
0051 switch (reg) {
0052 case AS3711_INTERRUPT_STATUS_1:
0053 case AS3711_INTERRUPT_STATUS_2:
0054 case AS3711_INTERRUPT_STATUS_3:
0055 return true;
0056 }
0057 return false;
0058 }
0059
0060 static bool as3711_readable_reg(struct device *dev, unsigned int reg)
0061 {
0062 switch (reg) {
0063 case AS3711_SD_1_VOLTAGE:
0064 case AS3711_SD_2_VOLTAGE:
0065 case AS3711_SD_3_VOLTAGE:
0066 case AS3711_SD_4_VOLTAGE:
0067 case AS3711_LDO_1_VOLTAGE:
0068 case AS3711_LDO_2_VOLTAGE:
0069 case AS3711_LDO_3_VOLTAGE:
0070 case AS3711_LDO_4_VOLTAGE:
0071 case AS3711_LDO_5_VOLTAGE:
0072 case AS3711_LDO_6_VOLTAGE:
0073 case AS3711_LDO_7_VOLTAGE:
0074 case AS3711_LDO_8_VOLTAGE:
0075 case AS3711_SD_CONTROL:
0076 case AS3711_GPIO_SIGNAL_OUT:
0077 case AS3711_GPIO_SIGNAL_IN:
0078 case AS3711_SD_CONTROL_1:
0079 case AS3711_SD_CONTROL_2:
0080 case AS3711_CURR_CONTROL:
0081 case AS3711_CURR1_VALUE:
0082 case AS3711_CURR2_VALUE:
0083 case AS3711_CURR3_VALUE:
0084 case AS3711_STEPUP_CONTROL_1:
0085 case AS3711_STEPUP_CONTROL_2:
0086 case AS3711_STEPUP_CONTROL_4:
0087 case AS3711_STEPUP_CONTROL_5:
0088 case AS3711_REG_STATUS:
0089 case AS3711_INTERRUPT_STATUS_1:
0090 case AS3711_INTERRUPT_STATUS_2:
0091 case AS3711_INTERRUPT_STATUS_3:
0092 case AS3711_CHARGER_STATUS_1:
0093 case AS3711_CHARGER_STATUS_2:
0094 case AS3711_ASIC_ID_1:
0095 case AS3711_ASIC_ID_2:
0096 return true;
0097 }
0098 return false;
0099 }
0100
0101 static const struct regmap_config as3711_regmap_config = {
0102 .reg_bits = 8,
0103 .val_bits = 8,
0104 .volatile_reg = as3711_volatile_reg,
0105 .readable_reg = as3711_readable_reg,
0106 .precious_reg = as3711_precious_reg,
0107 .max_register = AS3711_MAX_REG,
0108 .num_reg_defaults_raw = AS3711_NUM_REGS,
0109 .cache_type = REGCACHE_RBTREE,
0110 };
0111
0112 #ifdef CONFIG_OF
0113 static const struct of_device_id as3711_of_match[] = {
0114 {.compatible = "ams,as3711",},
0115 {}
0116 };
0117 #endif
0118
0119 static int as3711_i2c_probe(struct i2c_client *client,
0120 const struct i2c_device_id *id)
0121 {
0122 struct as3711 *as3711;
0123 struct as3711_platform_data *pdata;
0124 unsigned int id1, id2;
0125 int ret;
0126
0127 if (!client->dev.of_node) {
0128 pdata = dev_get_platdata(&client->dev);
0129 if (!pdata)
0130 dev_dbg(&client->dev, "Platform data not found\n");
0131 } else {
0132 pdata = devm_kzalloc(&client->dev,
0133 sizeof(*pdata), GFP_KERNEL);
0134 if (!pdata)
0135 return -ENOMEM;
0136 }
0137
0138 as3711 = devm_kzalloc(&client->dev, sizeof(struct as3711), GFP_KERNEL);
0139 if (!as3711)
0140 return -ENOMEM;
0141
0142 as3711->dev = &client->dev;
0143 i2c_set_clientdata(client, as3711);
0144
0145 if (client->irq)
0146 dev_notice(&client->dev, "IRQ not supported yet\n");
0147
0148 as3711->regmap = devm_regmap_init_i2c(client, &as3711_regmap_config);
0149 if (IS_ERR(as3711->regmap)) {
0150 ret = PTR_ERR(as3711->regmap);
0151 dev_err(&client->dev,
0152 "regmap initialization failed: %d\n", ret);
0153 return ret;
0154 }
0155
0156 ret = regmap_read(as3711->regmap, AS3711_ASIC_ID_1, &id1);
0157 if (!ret)
0158 ret = regmap_read(as3711->regmap, AS3711_ASIC_ID_2, &id2);
0159 if (ret < 0) {
0160 dev_err(&client->dev, "regmap_read() failed: %d\n", ret);
0161 return ret;
0162 }
0163 if (id1 != 0x8b)
0164 return -ENODEV;
0165 dev_info(as3711->dev, "AS3711 detected: %x:%x\n", id1, id2);
0166
0167
0168
0169
0170
0171 if (pdata) {
0172 as3711_subdevs[AS3711_REGULATOR].platform_data =
0173 &pdata->regulator;
0174 as3711_subdevs[AS3711_REGULATOR].pdata_size =
0175 sizeof(pdata->regulator);
0176 as3711_subdevs[AS3711_BACKLIGHT].platform_data =
0177 &pdata->backlight;
0178 as3711_subdevs[AS3711_BACKLIGHT].pdata_size =
0179 sizeof(pdata->backlight);
0180 } else {
0181 as3711_subdevs[AS3711_REGULATOR].platform_data = NULL;
0182 as3711_subdevs[AS3711_REGULATOR].pdata_size = 0;
0183 as3711_subdevs[AS3711_BACKLIGHT].platform_data = NULL;
0184 as3711_subdevs[AS3711_BACKLIGHT].pdata_size = 0;
0185 }
0186
0187 ret = devm_mfd_add_devices(as3711->dev, -1, as3711_subdevs,
0188 ARRAY_SIZE(as3711_subdevs), NULL, 0, NULL);
0189 if (ret < 0)
0190 dev_err(&client->dev, "add mfd devices failed: %d\n", ret);
0191
0192 return ret;
0193 }
0194
0195 static const struct i2c_device_id as3711_i2c_id[] = {
0196 {.name = "as3711", .driver_data = 0},
0197 {}
0198 };
0199
0200 static struct i2c_driver as3711_i2c_driver = {
0201 .driver = {
0202 .name = "as3711",
0203 .of_match_table = of_match_ptr(as3711_of_match),
0204 },
0205 .probe = as3711_i2c_probe,
0206 .id_table = as3711_i2c_id,
0207 };
0208
0209 static int __init as3711_i2c_init(void)
0210 {
0211 return i2c_add_driver(&as3711_i2c_driver);
0212 }
0213
0214 subsys_initcall(as3711_i2c_init);