Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * linux/drivers/mfd/aat2870-core.c
0004  *
0005  * Copyright (c) 2011, NVIDIA Corporation.
0006  * Author: Jin Park <jinyoungp@nvidia.com>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/init.h>
0011 #include <linux/debugfs.h>
0012 #include <linux/slab.h>
0013 #include <linux/uaccess.h>
0014 #include <linux/i2c.h>
0015 #include <linux/delay.h>
0016 #include <linux/gpio.h>
0017 #include <linux/mfd/core.h>
0018 #include <linux/mfd/aat2870.h>
0019 #include <linux/regulator/machine.h>
0020 
0021 static struct aat2870_register aat2870_regs[AAT2870_REG_NUM] = {
0022     /* readable, writeable, value */
0023     { 0, 1, 0x00 }, /* 0x00 AAT2870_BL_CH_EN */
0024     { 0, 1, 0x16 }, /* 0x01 AAT2870_BLM */
0025     { 0, 1, 0x16 }, /* 0x02 AAT2870_BLS */
0026     { 0, 1, 0x56 }, /* 0x03 AAT2870_BL1 */
0027     { 0, 1, 0x56 }, /* 0x04 AAT2870_BL2 */
0028     { 0, 1, 0x56 }, /* 0x05 AAT2870_BL3 */
0029     { 0, 1, 0x56 }, /* 0x06 AAT2870_BL4 */
0030     { 0, 1, 0x56 }, /* 0x07 AAT2870_BL5 */
0031     { 0, 1, 0x56 }, /* 0x08 AAT2870_BL6 */
0032     { 0, 1, 0x56 }, /* 0x09 AAT2870_BL7 */
0033     { 0, 1, 0x56 }, /* 0x0A AAT2870_BL8 */
0034     { 0, 1, 0x00 }, /* 0x0B AAT2870_FLR */
0035     { 0, 1, 0x03 }, /* 0x0C AAT2870_FM */
0036     { 0, 1, 0x03 }, /* 0x0D AAT2870_FS */
0037     { 0, 1, 0x10 }, /* 0x0E AAT2870_ALS_CFG0 */
0038     { 0, 1, 0x06 }, /* 0x0F AAT2870_ALS_CFG1 */
0039     { 0, 1, 0x00 }, /* 0x10 AAT2870_ALS_CFG2 */
0040     { 1, 0, 0x00 }, /* 0x11 AAT2870_AMB */
0041     { 0, 1, 0x00 }, /* 0x12 AAT2870_ALS0 */
0042     { 0, 1, 0x00 }, /* 0x13 AAT2870_ALS1 */
0043     { 0, 1, 0x00 }, /* 0x14 AAT2870_ALS2 */
0044     { 0, 1, 0x00 }, /* 0x15 AAT2870_ALS3 */
0045     { 0, 1, 0x00 }, /* 0x16 AAT2870_ALS4 */
0046     { 0, 1, 0x00 }, /* 0x17 AAT2870_ALS5 */
0047     { 0, 1, 0x00 }, /* 0x18 AAT2870_ALS6 */
0048     { 0, 1, 0x00 }, /* 0x19 AAT2870_ALS7 */
0049     { 0, 1, 0x00 }, /* 0x1A AAT2870_ALS8 */
0050     { 0, 1, 0x00 }, /* 0x1B AAT2870_ALS9 */
0051     { 0, 1, 0x00 }, /* 0x1C AAT2870_ALSA */
0052     { 0, 1, 0x00 }, /* 0x1D AAT2870_ALSB */
0053     { 0, 1, 0x00 }, /* 0x1E AAT2870_ALSC */
0054     { 0, 1, 0x00 }, /* 0x1F AAT2870_ALSD */
0055     { 0, 1, 0x00 }, /* 0x20 AAT2870_ALSE */
0056     { 0, 1, 0x00 }, /* 0x21 AAT2870_ALSF */
0057     { 0, 1, 0x00 }, /* 0x22 AAT2870_SUB_SET */
0058     { 0, 1, 0x00 }, /* 0x23 AAT2870_SUB_CTRL */
0059     { 0, 1, 0x00 }, /* 0x24 AAT2870_LDO_AB */
0060     { 0, 1, 0x00 }, /* 0x25 AAT2870_LDO_CD */
0061     { 0, 1, 0x00 }, /* 0x26 AAT2870_LDO_EN */
0062 };
0063 
0064 static struct mfd_cell aat2870_devs[] = {
0065     {
0066         .name = "aat2870-backlight",
0067         .id = AAT2870_ID_BL,
0068         .pdata_size = sizeof(struct aat2870_bl_platform_data),
0069     },
0070     {
0071         .name = "aat2870-regulator",
0072         .id = AAT2870_ID_LDOA,
0073         .pdata_size = sizeof(struct regulator_init_data),
0074     },
0075     {
0076         .name = "aat2870-regulator",
0077         .id = AAT2870_ID_LDOB,
0078         .pdata_size = sizeof(struct regulator_init_data),
0079     },
0080     {
0081         .name = "aat2870-regulator",
0082         .id = AAT2870_ID_LDOC,
0083         .pdata_size = sizeof(struct regulator_init_data),
0084     },
0085     {
0086         .name = "aat2870-regulator",
0087         .id = AAT2870_ID_LDOD,
0088         .pdata_size = sizeof(struct regulator_init_data),
0089     },
0090 };
0091 
0092 static int __aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
0093 {
0094     int ret;
0095 
0096     if (addr >= AAT2870_REG_NUM) {
0097         dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
0098         return -EINVAL;
0099     }
0100 
0101     if (!aat2870->reg_cache[addr].readable) {
0102         *val = aat2870->reg_cache[addr].value;
0103         goto out;
0104     }
0105 
0106     ret = i2c_master_send(aat2870->client, &addr, 1);
0107     if (ret < 0)
0108         return ret;
0109     if (ret != 1)
0110         return -EIO;
0111 
0112     ret = i2c_master_recv(aat2870->client, val, 1);
0113     if (ret < 0)
0114         return ret;
0115     if (ret != 1)
0116         return -EIO;
0117 
0118 out:
0119     dev_dbg(aat2870->dev, "read: addr=0x%02x, val=0x%02x\n", addr, *val);
0120     return 0;
0121 }
0122 
0123 static int __aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
0124 {
0125     u8 msg[2];
0126     int ret;
0127 
0128     if (addr >= AAT2870_REG_NUM) {
0129         dev_err(aat2870->dev, "Invalid address, 0x%02x\n", addr);
0130         return -EINVAL;
0131     }
0132 
0133     if (!aat2870->reg_cache[addr].writeable) {
0134         dev_err(aat2870->dev, "Address 0x%02x is not writeable\n",
0135             addr);
0136         return -EINVAL;
0137     }
0138 
0139     msg[0] = addr;
0140     msg[1] = val;
0141     ret = i2c_master_send(aat2870->client, msg, 2);
0142     if (ret < 0)
0143         return ret;
0144     if (ret != 2)
0145         return -EIO;
0146 
0147     aat2870->reg_cache[addr].value = val;
0148 
0149     dev_dbg(aat2870->dev, "write: addr=0x%02x, val=0x%02x\n", addr, val);
0150     return 0;
0151 }
0152 
0153 static int aat2870_read(struct aat2870_data *aat2870, u8 addr, u8 *val)
0154 {
0155     int ret;
0156 
0157     mutex_lock(&aat2870->io_lock);
0158     ret = __aat2870_read(aat2870, addr, val);
0159     mutex_unlock(&aat2870->io_lock);
0160 
0161     return ret;
0162 }
0163 
0164 static int aat2870_write(struct aat2870_data *aat2870, u8 addr, u8 val)
0165 {
0166     int ret;
0167 
0168     mutex_lock(&aat2870->io_lock);
0169     ret = __aat2870_write(aat2870, addr, val);
0170     mutex_unlock(&aat2870->io_lock);
0171 
0172     return ret;
0173 }
0174 
0175 static int aat2870_update(struct aat2870_data *aat2870, u8 addr, u8 mask,
0176               u8 val)
0177 {
0178     int change;
0179     u8 old_val, new_val;
0180     int ret;
0181 
0182     mutex_lock(&aat2870->io_lock);
0183 
0184     ret = __aat2870_read(aat2870, addr, &old_val);
0185     if (ret)
0186         goto out_unlock;
0187 
0188     new_val = (old_val & ~mask) | (val & mask);
0189     change = old_val != new_val;
0190     if (change)
0191         ret = __aat2870_write(aat2870, addr, new_val);
0192 
0193 out_unlock:
0194     mutex_unlock(&aat2870->io_lock);
0195 
0196     return ret;
0197 }
0198 
0199 static inline void aat2870_enable(struct aat2870_data *aat2870)
0200 {
0201     if (aat2870->en_pin >= 0)
0202         gpio_set_value(aat2870->en_pin, 1);
0203 
0204     aat2870->is_enable = 1;
0205 }
0206 
0207 static inline void aat2870_disable(struct aat2870_data *aat2870)
0208 {
0209     if (aat2870->en_pin >= 0)
0210         gpio_set_value(aat2870->en_pin, 0);
0211 
0212     aat2870->is_enable = 0;
0213 }
0214 
0215 #ifdef CONFIG_DEBUG_FS
0216 static ssize_t aat2870_dump_reg(struct aat2870_data *aat2870, char *buf)
0217 {
0218     u8 addr, val;
0219     ssize_t count = 0;
0220     int ret;
0221 
0222     count += sprintf(buf, "aat2870 registers\n");
0223     for (addr = 0; addr < AAT2870_REG_NUM; addr++) {
0224         count += snprintf(buf + count, PAGE_SIZE - count, "0x%02x: ", addr);
0225         if (count >= PAGE_SIZE - 1)
0226             break;
0227 
0228         ret = aat2870->read(aat2870, addr, &val);
0229         if (ret == 0)
0230             count += snprintf(buf + count, PAGE_SIZE - count,
0231                       "0x%02x", val);
0232         else
0233             count += snprintf(buf + count, PAGE_SIZE - count,
0234                       "<read fail: %d>", ret);
0235 
0236         if (count >= PAGE_SIZE - 1)
0237             break;
0238 
0239         count += snprintf(buf + count, PAGE_SIZE - count, "\n");
0240         if (count >= PAGE_SIZE - 1)
0241             break;
0242     }
0243 
0244     /* Truncate count; min() would cause a warning */
0245     if (count >= PAGE_SIZE)
0246         count = PAGE_SIZE - 1;
0247 
0248     return count;
0249 }
0250 
0251 static ssize_t aat2870_reg_read_file(struct file *file, char __user *user_buf,
0252                      size_t count, loff_t *ppos)
0253 {
0254     struct aat2870_data *aat2870 = file->private_data;
0255     char *buf;
0256     ssize_t ret;
0257 
0258     buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
0259     if (!buf)
0260         return -ENOMEM;
0261 
0262     ret = aat2870_dump_reg(aat2870, buf);
0263     if (ret >= 0)
0264         ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
0265 
0266     kfree(buf);
0267 
0268     return ret;
0269 }
0270 
0271 static ssize_t aat2870_reg_write_file(struct file *file,
0272                       const char __user *user_buf, size_t count,
0273                       loff_t *ppos)
0274 {
0275     struct aat2870_data *aat2870 = file->private_data;
0276     char buf[32];
0277     ssize_t buf_size;
0278     char *start = buf;
0279     unsigned long addr, val;
0280     int ret;
0281 
0282     buf_size = min(count, (size_t)(sizeof(buf)-1));
0283     if (copy_from_user(buf, user_buf, buf_size)) {
0284         dev_err(aat2870->dev, "Failed to copy from user\n");
0285         return -EFAULT;
0286     }
0287     buf[buf_size] = 0;
0288 
0289     while (*start == ' ')
0290         start++;
0291 
0292     ret = kstrtoul(start, 16, &addr);
0293     if (ret)
0294         return ret;
0295 
0296     if (addr >= AAT2870_REG_NUM) {
0297         dev_err(aat2870->dev, "Invalid address, 0x%lx\n", addr);
0298         return -EINVAL;
0299     }
0300 
0301     while (*start == ' ')
0302         start++;
0303 
0304     ret = kstrtoul(start, 16, &val);
0305     if (ret)
0306         return ret;
0307 
0308     ret = aat2870->write(aat2870, (u8)addr, (u8)val);
0309     if (ret)
0310         return ret;
0311 
0312     return buf_size;
0313 }
0314 
0315 static const struct file_operations aat2870_reg_fops = {
0316     .open = simple_open,
0317     .read = aat2870_reg_read_file,
0318     .write = aat2870_reg_write_file,
0319 };
0320 
0321 static void aat2870_init_debugfs(struct aat2870_data *aat2870)
0322 {
0323     aat2870->dentry_root = debugfs_create_dir("aat2870", NULL);
0324 
0325     debugfs_create_file("regs", 0644, aat2870->dentry_root, aat2870,
0326                 &aat2870_reg_fops);
0327 }
0328 
0329 #else
0330 static inline void aat2870_init_debugfs(struct aat2870_data *aat2870)
0331 {
0332 }
0333 #endif /* CONFIG_DEBUG_FS */
0334 
0335 static int aat2870_i2c_probe(struct i2c_client *client,
0336                  const struct i2c_device_id *id)
0337 {
0338     struct aat2870_platform_data *pdata = dev_get_platdata(&client->dev);
0339     struct aat2870_data *aat2870;
0340     int i, j;
0341     int ret = 0;
0342 
0343     aat2870 = devm_kzalloc(&client->dev, sizeof(struct aat2870_data),
0344                 GFP_KERNEL);
0345     if (!aat2870)
0346         return -ENOMEM;
0347 
0348     aat2870->dev = &client->dev;
0349     dev_set_drvdata(aat2870->dev, aat2870);
0350 
0351     aat2870->client = client;
0352     i2c_set_clientdata(client, aat2870);
0353 
0354     aat2870->reg_cache = aat2870_regs;
0355 
0356     if (pdata->en_pin < 0)
0357         aat2870->en_pin = -1;
0358     else
0359         aat2870->en_pin = pdata->en_pin;
0360 
0361     aat2870->init = pdata->init;
0362     aat2870->uninit = pdata->uninit;
0363     aat2870->read = aat2870_read;
0364     aat2870->write = aat2870_write;
0365     aat2870->update = aat2870_update;
0366 
0367     mutex_init(&aat2870->io_lock);
0368 
0369     if (aat2870->init)
0370         aat2870->init(aat2870);
0371 
0372     if (aat2870->en_pin >= 0) {
0373         ret = devm_gpio_request_one(&client->dev, aat2870->en_pin,
0374                     GPIOF_OUT_INIT_HIGH, "aat2870-en");
0375         if (ret < 0) {
0376             dev_err(&client->dev,
0377                 "Failed to request GPIO %d\n", aat2870->en_pin);
0378             return ret;
0379         }
0380     }
0381 
0382     aat2870_enable(aat2870);
0383 
0384     for (i = 0; i < pdata->num_subdevs; i++) {
0385         for (j = 0; j < ARRAY_SIZE(aat2870_devs); j++) {
0386             if ((pdata->subdevs[i].id == aat2870_devs[j].id) &&
0387                     !strcmp(pdata->subdevs[i].name,
0388                         aat2870_devs[j].name)) {
0389                 aat2870_devs[j].platform_data =
0390                     pdata->subdevs[i].platform_data;
0391                 break;
0392             }
0393         }
0394     }
0395 
0396     ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs,
0397                   ARRAY_SIZE(aat2870_devs), NULL, 0, NULL);
0398     if (ret != 0) {
0399         dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret);
0400         goto out_disable;
0401     }
0402 
0403     aat2870_init_debugfs(aat2870);
0404 
0405     return 0;
0406 
0407 out_disable:
0408     aat2870_disable(aat2870);
0409     return ret;
0410 }
0411 
0412 #ifdef CONFIG_PM_SLEEP
0413 static int aat2870_i2c_suspend(struct device *dev)
0414 {
0415     struct i2c_client *client = to_i2c_client(dev);
0416     struct aat2870_data *aat2870 = i2c_get_clientdata(client);
0417 
0418     aat2870_disable(aat2870);
0419 
0420     return 0;
0421 }
0422 
0423 static int aat2870_i2c_resume(struct device *dev)
0424 {
0425     struct i2c_client *client = to_i2c_client(dev);
0426     struct aat2870_data *aat2870 = i2c_get_clientdata(client);
0427     struct aat2870_register *reg = NULL;
0428     int i;
0429 
0430     aat2870_enable(aat2870);
0431 
0432     /* restore registers */
0433     for (i = 0; i < AAT2870_REG_NUM; i++) {
0434         reg = &aat2870->reg_cache[i];
0435         if (reg->writeable)
0436             aat2870->write(aat2870, i, reg->value);
0437     }
0438 
0439     return 0;
0440 }
0441 #endif /* CONFIG_PM_SLEEP */
0442 
0443 static SIMPLE_DEV_PM_OPS(aat2870_pm_ops, aat2870_i2c_suspend,
0444              aat2870_i2c_resume);
0445 
0446 static const struct i2c_device_id aat2870_i2c_id_table[] = {
0447     { "aat2870", 0 },
0448     { }
0449 };
0450 
0451 static struct i2c_driver aat2870_i2c_driver = {
0452     .driver = {
0453         .name           = "aat2870",
0454         .pm         = &aat2870_pm_ops,
0455         .suppress_bind_attrs    = true,
0456     },
0457     .probe      = aat2870_i2c_probe,
0458     .id_table   = aat2870_i2c_id_table,
0459 };
0460 
0461 static int __init aat2870_init(void)
0462 {
0463     return i2c_add_driver(&aat2870_i2c_driver);
0464 }
0465 subsys_initcall(aat2870_init);