1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d50f8f33SHaojian Zhuang /* 3d50f8f33SHaojian Zhuang * I2C driver for Maxim MAX8925 4d50f8f33SHaojian Zhuang * 5d50f8f33SHaojian Zhuang * Copyright (C) 2009 Marvell International Ltd. 6d50f8f33SHaojian Zhuang * Haojian Zhuang <haojian.zhuang@marvell.com> 7d50f8f33SHaojian Zhuang */ 8d50f8f33SHaojian Zhuang #include <linux/kernel.h> 99eb5f9baSPaul Gortmaker #include <linux/init.h> 10d50f8f33SHaojian Zhuang #include <linux/platform_device.h> 11d50f8f33SHaojian Zhuang #include <linux/i2c.h> 12d50f8f33SHaojian Zhuang #include <linux/mfd/max8925.h> 135a0e3ad6STejun Heo #include <linux/slab.h> 14d50f8f33SHaojian Zhuang 15b13c0df5SHaojian Zhuang #define RTC_I2C_ADDR 0x68 16b13c0df5SHaojian Zhuang #define ADC_I2C_ADDR 0x47 17b13c0df5SHaojian Zhuang 18d50f8f33SHaojian Zhuang static inline int max8925_read_device(struct i2c_client *i2c, 19d50f8f33SHaojian Zhuang int reg, int bytes, void *dest) 20d50f8f33SHaojian Zhuang { 21d50f8f33SHaojian Zhuang int ret; 22d50f8f33SHaojian Zhuang 23b13c0df5SHaojian Zhuang if (bytes > 1) 24b13c0df5SHaojian Zhuang ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest); 25b13c0df5SHaojian Zhuang else { 26b13c0df5SHaojian Zhuang ret = i2c_smbus_read_byte_data(i2c, reg); 27d50f8f33SHaojian Zhuang if (ret < 0) 28d50f8f33SHaojian Zhuang return ret; 29b13c0df5SHaojian Zhuang *(unsigned char *)dest = (unsigned char)ret; 30b13c0df5SHaojian Zhuang } 31d50f8f33SHaojian Zhuang return ret; 32d50f8f33SHaojian Zhuang } 33d50f8f33SHaojian Zhuang 34d50f8f33SHaojian Zhuang static inline int max8925_write_device(struct i2c_client *i2c, 35d50f8f33SHaojian Zhuang int reg, int bytes, void *src) 36d50f8f33SHaojian Zhuang { 3787bd1c92SLee Jones unsigned char buf[9]; 38d50f8f33SHaojian Zhuang int ret; 39d50f8f33SHaojian Zhuang 40d50f8f33SHaojian Zhuang buf[0] = (unsigned char)reg; 41d50f8f33SHaojian Zhuang memcpy(&buf[1], src, bytes); 42d50f8f33SHaojian Zhuang 43d50f8f33SHaojian Zhuang ret = i2c_master_send(i2c, buf, bytes + 1); 44d50f8f33SHaojian Zhuang if (ret < 0) 45d50f8f33SHaojian Zhuang return ret; 46d50f8f33SHaojian Zhuang return 0; 47d50f8f33SHaojian Zhuang } 48d50f8f33SHaojian Zhuang 49d50f8f33SHaojian Zhuang int max8925_reg_read(struct i2c_client *i2c, int reg) 50d50f8f33SHaojian Zhuang { 51d50f8f33SHaojian Zhuang struct max8925_chip *chip = i2c_get_clientdata(i2c); 52b13c0df5SHaojian Zhuang unsigned char data = 0; 53d50f8f33SHaojian Zhuang int ret; 54d50f8f33SHaojian Zhuang 55d50f8f33SHaojian Zhuang mutex_lock(&chip->io_lock); 56d50f8f33SHaojian Zhuang ret = max8925_read_device(i2c, reg, 1, &data); 57d50f8f33SHaojian Zhuang mutex_unlock(&chip->io_lock); 58d50f8f33SHaojian Zhuang 59d50f8f33SHaojian Zhuang if (ret < 0) 60d50f8f33SHaojian Zhuang return ret; 61d50f8f33SHaojian Zhuang else 62d50f8f33SHaojian Zhuang return (int)data; 63d50f8f33SHaojian Zhuang } 64d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_reg_read); 65d50f8f33SHaojian Zhuang 66d50f8f33SHaojian Zhuang int max8925_reg_write(struct i2c_client *i2c, int reg, 67d50f8f33SHaojian Zhuang unsigned char data) 68d50f8f33SHaojian Zhuang { 69d50f8f33SHaojian Zhuang struct max8925_chip *chip = i2c_get_clientdata(i2c); 70d50f8f33SHaojian Zhuang int ret; 71d50f8f33SHaojian Zhuang 72d50f8f33SHaojian Zhuang mutex_lock(&chip->io_lock); 73d50f8f33SHaojian Zhuang ret = max8925_write_device(i2c, reg, 1, &data); 74d50f8f33SHaojian Zhuang mutex_unlock(&chip->io_lock); 75d50f8f33SHaojian Zhuang 76d50f8f33SHaojian Zhuang return ret; 77d50f8f33SHaojian Zhuang } 78d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_reg_write); 79d50f8f33SHaojian Zhuang 80d50f8f33SHaojian Zhuang int max8925_bulk_read(struct i2c_client *i2c, int reg, 81d50f8f33SHaojian Zhuang int count, unsigned char *buf) 82d50f8f33SHaojian Zhuang { 83d50f8f33SHaojian Zhuang struct max8925_chip *chip = i2c_get_clientdata(i2c); 84d50f8f33SHaojian Zhuang int ret; 85d50f8f33SHaojian Zhuang 86d50f8f33SHaojian Zhuang mutex_lock(&chip->io_lock); 87d50f8f33SHaojian Zhuang ret = max8925_read_device(i2c, reg, count, buf); 88d50f8f33SHaojian Zhuang mutex_unlock(&chip->io_lock); 89d50f8f33SHaojian Zhuang 90d50f8f33SHaojian Zhuang return ret; 91d50f8f33SHaojian Zhuang } 92d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_bulk_read); 93d50f8f33SHaojian Zhuang 94d50f8f33SHaojian Zhuang int max8925_bulk_write(struct i2c_client *i2c, int reg, 95d50f8f33SHaojian Zhuang int count, unsigned char *buf) 96d50f8f33SHaojian Zhuang { 97d50f8f33SHaojian Zhuang struct max8925_chip *chip = i2c_get_clientdata(i2c); 98d50f8f33SHaojian Zhuang int ret; 99d50f8f33SHaojian Zhuang 100d50f8f33SHaojian Zhuang mutex_lock(&chip->io_lock); 101d50f8f33SHaojian Zhuang ret = max8925_write_device(i2c, reg, count, buf); 102d50f8f33SHaojian Zhuang mutex_unlock(&chip->io_lock); 103d50f8f33SHaojian Zhuang 104d50f8f33SHaojian Zhuang return ret; 105d50f8f33SHaojian Zhuang } 106d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_bulk_write); 107d50f8f33SHaojian Zhuang 108d50f8f33SHaojian Zhuang int max8925_set_bits(struct i2c_client *i2c, int reg, 109d50f8f33SHaojian Zhuang unsigned char mask, unsigned char data) 110d50f8f33SHaojian Zhuang { 111d50f8f33SHaojian Zhuang struct max8925_chip *chip = i2c_get_clientdata(i2c); 112d50f8f33SHaojian Zhuang unsigned char value; 113d50f8f33SHaojian Zhuang int ret; 114d50f8f33SHaojian Zhuang 115d50f8f33SHaojian Zhuang mutex_lock(&chip->io_lock); 116d50f8f33SHaojian Zhuang ret = max8925_read_device(i2c, reg, 1, &value); 117d50f8f33SHaojian Zhuang if (ret < 0) 118d50f8f33SHaojian Zhuang goto out; 119d50f8f33SHaojian Zhuang value &= ~mask; 120d50f8f33SHaojian Zhuang value |= data; 121d50f8f33SHaojian Zhuang ret = max8925_write_device(i2c, reg, 1, &value); 122d50f8f33SHaojian Zhuang out: 123d50f8f33SHaojian Zhuang mutex_unlock(&chip->io_lock); 124d50f8f33SHaojian Zhuang return ret; 125d50f8f33SHaojian Zhuang } 126d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_set_bits); 127d50f8f33SHaojian Zhuang 128d50f8f33SHaojian Zhuang 129d50f8f33SHaojian Zhuang static const struct i2c_device_id max8925_id_table[] = { 130d50f8f33SHaojian Zhuang { "max8925", 0 }, 131b13c0df5SHaojian Zhuang { }, 132d50f8f33SHaojian Zhuang }; 133d50f8f33SHaojian Zhuang 1344e405ae2SQing Xu static int max8925_dt_init(struct device_node *np, struct device *dev, 1354e405ae2SQing Xu struct max8925_platform_data *pdata) 1364e405ae2SQing Xu { 1374e405ae2SQing Xu int ret; 1384e405ae2SQing Xu 1394e405ae2SQing Xu ret = of_property_read_u32(np, "maxim,tsc-irq", &pdata->tsc_irq); 1404e405ae2SQing Xu if (ret) { 1414e405ae2SQing Xu dev_err(dev, "Not found maxim,tsc-irq property\n"); 1424e405ae2SQing Xu return -EINVAL; 1434e405ae2SQing Xu } 1444e405ae2SQing Xu return 0; 1454e405ae2SQing Xu } 1464e405ae2SQing Xu 147f791be49SBill Pemberton static int max8925_probe(struct i2c_client *client, 148d50f8f33SHaojian Zhuang const struct i2c_device_id *id) 149d50f8f33SHaojian Zhuang { 150334a41ceSJingoo Han struct max8925_platform_data *pdata = dev_get_platdata(&client->dev); 15109530751SJulia Lawall struct max8925_chip *chip; 1524e405ae2SQing Xu struct device_node *node = client->dev.of_node; 153d50f8f33SHaojian Zhuang 1544e405ae2SQing Xu if (node && !pdata) { 1554e405ae2SQing Xu /* parse DT to get platform data */ 1564e405ae2SQing Xu pdata = devm_kzalloc(&client->dev, 1574e405ae2SQing Xu sizeof(struct max8925_platform_data), 1584e405ae2SQing Xu GFP_KERNEL); 1594e405ae2SQing Xu if (!pdata) 1604e405ae2SQing Xu return -ENOMEM; 1614e405ae2SQing Xu 1624e405ae2SQing Xu if (max8925_dt_init(node, &client->dev, pdata)) 1634e405ae2SQing Xu return -EINVAL; 1644e405ae2SQing Xu } else if (!pdata) { 165d50f8f33SHaojian Zhuang pr_info("%s: platform data is missing\n", __func__); 166d50f8f33SHaojian Zhuang return -EINVAL; 167d50f8f33SHaojian Zhuang } 168d50f8f33SHaojian Zhuang 16902c7d848SLee Jones chip = devm_kzalloc(&client->dev, 17002c7d848SLee Jones sizeof(struct max8925_chip), GFP_KERNEL); 171d50f8f33SHaojian Zhuang if (chip == NULL) 172d50f8f33SHaojian Zhuang return -ENOMEM; 173d50f8f33SHaojian Zhuang chip->i2c = client; 174d50f8f33SHaojian Zhuang chip->dev = &client->dev; 175b13c0df5SHaojian Zhuang i2c_set_clientdata(client, chip); 176d50f8f33SHaojian Zhuang dev_set_drvdata(chip->dev, chip); 177b13c0df5SHaojian Zhuang mutex_init(&chip->io_lock); 178b13c0df5SHaojian Zhuang 179*ddbf6ffeSWolfram Sang chip->rtc = i2c_new_dummy_device(chip->i2c->adapter, RTC_I2C_ADDR); 180*ddbf6ffeSWolfram Sang if (IS_ERR(chip->rtc)) { 18196cf3dedSKrzysztof Kozlowski dev_err(chip->dev, "Failed to allocate I2C device for RTC\n"); 182*ddbf6ffeSWolfram Sang return PTR_ERR(chip->rtc); 18396cf3dedSKrzysztof Kozlowski } 184b13c0df5SHaojian Zhuang i2c_set_clientdata(chip->rtc, chip); 185b13c0df5SHaojian Zhuang 186*ddbf6ffeSWolfram Sang chip->adc = i2c_new_dummy_device(chip->i2c->adapter, ADC_I2C_ADDR); 187*ddbf6ffeSWolfram Sang if (IS_ERR(chip->adc)) { 18896cf3dedSKrzysztof Kozlowski dev_err(chip->dev, "Failed to allocate I2C device for ADC\n"); 18996cf3dedSKrzysztof Kozlowski i2c_unregister_device(chip->rtc); 190*ddbf6ffeSWolfram Sang return PTR_ERR(chip->adc); 19196cf3dedSKrzysztof Kozlowski } 192b13c0df5SHaojian Zhuang i2c_set_clientdata(chip->adc, chip); 193b13c0df5SHaojian Zhuang 194ba74e80eSKevin Liu device_init_wakeup(&client->dev, 1); 195ba74e80eSKevin Liu 196d50f8f33SHaojian Zhuang max8925_device_init(chip, pdata); 197d50f8f33SHaojian Zhuang 198d50f8f33SHaojian Zhuang return 0; 199d50f8f33SHaojian Zhuang } 200d50f8f33SHaojian Zhuang 2014740f73fSBill Pemberton static int max8925_remove(struct i2c_client *client) 202d50f8f33SHaojian Zhuang { 203d50f8f33SHaojian Zhuang struct max8925_chip *chip = i2c_get_clientdata(client); 204d50f8f33SHaojian Zhuang 205d50f8f33SHaojian Zhuang max8925_device_exit(chip); 206b13c0df5SHaojian Zhuang i2c_unregister_device(chip->adc); 207b13c0df5SHaojian Zhuang i2c_unregister_device(chip->rtc); 208d50f8f33SHaojian Zhuang return 0; 209d50f8f33SHaojian Zhuang } 210d50f8f33SHaojian Zhuang 211ba74e80eSKevin Liu #ifdef CONFIG_PM_SLEEP 212ba74e80eSKevin Liu static int max8925_suspend(struct device *dev) 213ba74e80eSKevin Liu { 2141b5420e1SGeliang Tang struct i2c_client *client = to_i2c_client(dev); 215ba74e80eSKevin Liu struct max8925_chip *chip = i2c_get_clientdata(client); 216ba74e80eSKevin Liu 217ba74e80eSKevin Liu if (device_may_wakeup(dev) && chip->wakeup_flag) 218ba74e80eSKevin Liu enable_irq_wake(chip->core_irq); 219ba74e80eSKevin Liu return 0; 220ba74e80eSKevin Liu } 221ba74e80eSKevin Liu 222ba74e80eSKevin Liu static int max8925_resume(struct device *dev) 223ba74e80eSKevin Liu { 2241b5420e1SGeliang Tang struct i2c_client *client = to_i2c_client(dev); 225ba74e80eSKevin Liu struct max8925_chip *chip = i2c_get_clientdata(client); 226ba74e80eSKevin Liu 227ba74e80eSKevin Liu if (device_may_wakeup(dev) && chip->wakeup_flag) 228ba74e80eSKevin Liu disable_irq_wake(chip->core_irq); 229ba74e80eSKevin Liu return 0; 230ba74e80eSKevin Liu } 231ba74e80eSKevin Liu #endif 232ba74e80eSKevin Liu 233ba74e80eSKevin Liu static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume); 234ba74e80eSKevin Liu 2354e405ae2SQing Xu static const struct of_device_id max8925_dt_ids[] = { 2364e405ae2SQing Xu { .compatible = "maxim,max8925", }, 2374e405ae2SQing Xu {}, 2384e405ae2SQing Xu }; 2394e405ae2SQing Xu 240d50f8f33SHaojian Zhuang static struct i2c_driver max8925_driver = { 241d50f8f33SHaojian Zhuang .driver = { 242d50f8f33SHaojian Zhuang .name = "max8925", 243ba74e80eSKevin Liu .pm = &max8925_pm_ops, 24452c2c6ebSSachin Kamat .of_match_table = max8925_dt_ids, 245d50f8f33SHaojian Zhuang }, 246d50f8f33SHaojian Zhuang .probe = max8925_probe, 24784449216SBill Pemberton .remove = max8925_remove, 248d50f8f33SHaojian Zhuang .id_table = max8925_id_table, 249d50f8f33SHaojian Zhuang }; 250d50f8f33SHaojian Zhuang 251d50f8f33SHaojian Zhuang static int __init max8925_i2c_init(void) 252d50f8f33SHaojian Zhuang { 253d50f8f33SHaojian Zhuang int ret; 2544ed8f718SLee Jones 255d50f8f33SHaojian Zhuang ret = i2c_add_driver(&max8925_driver); 256d50f8f33SHaojian Zhuang if (ret != 0) 257d50f8f33SHaojian Zhuang pr_err("Failed to register MAX8925 I2C driver: %d\n", ret); 2584ed8f718SLee Jones 259d50f8f33SHaojian Zhuang return ret; 260d50f8f33SHaojian Zhuang } 261d50f8f33SHaojian Zhuang subsys_initcall(max8925_i2c_init); 262