cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

max8925-i2c.c (6019B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * I2C driver for Maxim MAX8925
      4 *
      5 * Copyright (C) 2009 Marvell International Ltd.
      6 *	Haojian Zhuang <haojian.zhuang@marvell.com>
      7 */
      8#include <linux/kernel.h>
      9#include <linux/init.h>
     10#include <linux/platform_device.h>
     11#include <linux/i2c.h>
     12#include <linux/mfd/max8925.h>
     13#include <linux/slab.h>
     14
     15#define RTC_I2C_ADDR		0x68
     16#define ADC_I2C_ADDR		0x47
     17
     18static inline int max8925_read_device(struct i2c_client *i2c,
     19				      int reg, int bytes, void *dest)
     20{
     21	int ret;
     22
     23	if (bytes > 1)
     24		ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
     25	else {
     26		ret = i2c_smbus_read_byte_data(i2c, reg);
     27		if (ret < 0)
     28			return ret;
     29		*(unsigned char *)dest = (unsigned char)ret;
     30	}
     31	return ret;
     32}
     33
     34static inline int max8925_write_device(struct i2c_client *i2c,
     35				       int reg, int bytes, void *src)
     36{
     37	unsigned char buf[9];
     38	int ret;
     39
     40	buf[0] = (unsigned char)reg;
     41	memcpy(&buf[1], src, bytes);
     42
     43	ret = i2c_master_send(i2c, buf, bytes + 1);
     44	if (ret < 0)
     45		return ret;
     46	return 0;
     47}
     48
     49int max8925_reg_read(struct i2c_client *i2c, int reg)
     50{
     51	struct max8925_chip *chip = i2c_get_clientdata(i2c);
     52	unsigned char data = 0;
     53	int ret;
     54
     55	mutex_lock(&chip->io_lock);
     56	ret = max8925_read_device(i2c, reg, 1, &data);
     57	mutex_unlock(&chip->io_lock);
     58
     59	if (ret < 0)
     60		return ret;
     61	else
     62		return (int)data;
     63}
     64EXPORT_SYMBOL(max8925_reg_read);
     65
     66int max8925_reg_write(struct i2c_client *i2c, int reg,
     67		unsigned char data)
     68{
     69	struct max8925_chip *chip = i2c_get_clientdata(i2c);
     70	int ret;
     71
     72	mutex_lock(&chip->io_lock);
     73	ret = max8925_write_device(i2c, reg, 1, &data);
     74	mutex_unlock(&chip->io_lock);
     75
     76	return ret;
     77}
     78EXPORT_SYMBOL(max8925_reg_write);
     79
     80int max8925_bulk_read(struct i2c_client *i2c, int reg,
     81		int count, unsigned char *buf)
     82{
     83	struct max8925_chip *chip = i2c_get_clientdata(i2c);
     84	int ret;
     85
     86	mutex_lock(&chip->io_lock);
     87	ret = max8925_read_device(i2c, reg, count, buf);
     88	mutex_unlock(&chip->io_lock);
     89
     90	return ret;
     91}
     92EXPORT_SYMBOL(max8925_bulk_read);
     93
     94int max8925_bulk_write(struct i2c_client *i2c, int reg,
     95		int count, unsigned char *buf)
     96{
     97	struct max8925_chip *chip = i2c_get_clientdata(i2c);
     98	int ret;
     99
    100	mutex_lock(&chip->io_lock);
    101	ret = max8925_write_device(i2c, reg, count, buf);
    102	mutex_unlock(&chip->io_lock);
    103
    104	return ret;
    105}
    106EXPORT_SYMBOL(max8925_bulk_write);
    107
    108int max8925_set_bits(struct i2c_client *i2c, int reg,
    109		unsigned char mask, unsigned char data)
    110{
    111	struct max8925_chip *chip = i2c_get_clientdata(i2c);
    112	unsigned char value;
    113	int ret;
    114
    115	mutex_lock(&chip->io_lock);
    116	ret = max8925_read_device(i2c, reg, 1, &value);
    117	if (ret < 0)
    118		goto out;
    119	value &= ~mask;
    120	value |= data;
    121	ret = max8925_write_device(i2c, reg, 1, &value);
    122out:
    123	mutex_unlock(&chip->io_lock);
    124	return ret;
    125}
    126EXPORT_SYMBOL(max8925_set_bits);
    127
    128
    129static const struct i2c_device_id max8925_id_table[] = {
    130	{ "max8925", 0 },
    131	{ },
    132};
    133
    134static int max8925_dt_init(struct device_node *np, struct device *dev,
    135			   struct max8925_platform_data *pdata)
    136{
    137	int ret;
    138
    139	ret = of_property_read_u32(np, "maxim,tsc-irq", &pdata->tsc_irq);
    140	if (ret) {
    141		dev_err(dev, "Not found maxim,tsc-irq property\n");
    142		return -EINVAL;
    143	}
    144	return 0;
    145}
    146
    147static int max8925_probe(struct i2c_client *client,
    148				   const struct i2c_device_id *id)
    149{
    150	struct max8925_platform_data *pdata = dev_get_platdata(&client->dev);
    151	struct max8925_chip *chip;
    152	struct device_node *node = client->dev.of_node;
    153
    154	if (node && !pdata) {
    155		/* parse DT to get platform data */
    156		pdata = devm_kzalloc(&client->dev,
    157				     sizeof(struct max8925_platform_data),
    158				     GFP_KERNEL);
    159		if (!pdata)
    160			return -ENOMEM;
    161
    162		if (max8925_dt_init(node, &client->dev, pdata))
    163			return -EINVAL;
    164	} else if (!pdata) {
    165		pr_info("%s: platform data is missing\n", __func__);
    166		return -EINVAL;
    167	}
    168
    169	chip = devm_kzalloc(&client->dev,
    170			    sizeof(struct max8925_chip), GFP_KERNEL);
    171	if (chip == NULL)
    172		return -ENOMEM;
    173	chip->i2c = client;
    174	chip->dev = &client->dev;
    175	i2c_set_clientdata(client, chip);
    176	dev_set_drvdata(chip->dev, chip);
    177	mutex_init(&chip->io_lock);
    178
    179	chip->rtc = i2c_new_dummy_device(chip->i2c->adapter, RTC_I2C_ADDR);
    180	if (IS_ERR(chip->rtc)) {
    181		dev_err(chip->dev, "Failed to allocate I2C device for RTC\n");
    182		return PTR_ERR(chip->rtc);
    183	}
    184	i2c_set_clientdata(chip->rtc, chip);
    185
    186	chip->adc = i2c_new_dummy_device(chip->i2c->adapter, ADC_I2C_ADDR);
    187	if (IS_ERR(chip->adc)) {
    188		dev_err(chip->dev, "Failed to allocate I2C device for ADC\n");
    189		i2c_unregister_device(chip->rtc);
    190		return PTR_ERR(chip->adc);
    191	}
    192	i2c_set_clientdata(chip->adc, chip);
    193
    194	device_init_wakeup(&client->dev, 1);
    195
    196	max8925_device_init(chip, pdata);
    197
    198	return 0;
    199}
    200
    201static int max8925_remove(struct i2c_client *client)
    202{
    203	struct max8925_chip *chip = i2c_get_clientdata(client);
    204
    205	max8925_device_exit(chip);
    206	i2c_unregister_device(chip->adc);
    207	i2c_unregister_device(chip->rtc);
    208	return 0;
    209}
    210
    211#ifdef CONFIG_PM_SLEEP
    212static int max8925_suspend(struct device *dev)
    213{
    214	struct i2c_client *client = to_i2c_client(dev);
    215	struct max8925_chip *chip = i2c_get_clientdata(client);
    216
    217	if (device_may_wakeup(dev) && chip->wakeup_flag)
    218		enable_irq_wake(chip->core_irq);
    219	return 0;
    220}
    221
    222static int max8925_resume(struct device *dev)
    223{
    224	struct i2c_client *client = to_i2c_client(dev);
    225	struct max8925_chip *chip = i2c_get_clientdata(client);
    226
    227	if (device_may_wakeup(dev) && chip->wakeup_flag)
    228		disable_irq_wake(chip->core_irq);
    229	return 0;
    230}
    231#endif
    232
    233static SIMPLE_DEV_PM_OPS(max8925_pm_ops, max8925_suspend, max8925_resume);
    234
    235static const struct of_device_id max8925_dt_ids[] = {
    236	{ .compatible = "maxim,max8925", },
    237	{},
    238};
    239
    240static struct i2c_driver max8925_driver = {
    241	.driver	= {
    242		.name	= "max8925",
    243		.pm     = &max8925_pm_ops,
    244		.of_match_table = max8925_dt_ids,
    245	},
    246	.probe		= max8925_probe,
    247	.remove		= max8925_remove,
    248	.id_table	= max8925_id_table,
    249};
    250
    251static int __init max8925_i2c_init(void)
    252{
    253	int ret;
    254
    255	ret = i2c_add_driver(&max8925_driver);
    256	if (ret != 0)
    257		pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
    258
    259	return ret;
    260}
    261subsys_initcall(max8925_i2c_init);