/*
* Copyright (C) 2007-2010 ST-Ericsson
* License terms: GNU General Public License (GPL) version 2
* Low-level core for exclusive access to the AB3100 IC on the I2C bus
* and some basic chip-configuration.
* Author: Linus Walleij <linus.walleij@stericsson.com>
*/
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/random.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/mfd/core.h>
#include <linux/mfd/abx500.h>
/* These are the only registers inside AB3100 used in this main file */
/* Interrupt event registers */
#define AB3100_EVENTA1 0x21
#define AB3100_EVENTA2 0x22
#define AB3100_EVENTA3 0x23
/* AB3100 DAC converter registers */
#define AB3100_DIS 0x00
#define AB3100_D0C 0x01
#define AB3100_D1C 0x02
#define AB3100_D2C 0x03
#define AB3100_D3C 0x04
/* Chip ID register */
#define AB3100_CID 0x20
/* AB3100 interrupt registers */
#define AB3100_IMRA1 0x24
#define AB3100_IMRA2 0x25
#define AB3100_IMRA3 0x26
#define AB3100_IMRB1 0x2B
#define AB3100_IMRB2 0x2C
#define AB3100_IMRB3 0x2D
/* System Power Monitoring and control registers */
#define AB3100_MCA 0x2E
#define AB3100_MCB 0x2F
/* SIM power up */
#define AB3100_SUP 0x50
/*
* I2C communication
*
* The AB3100 is usually assigned address 0x48 (7-bit)
* The chip is defined in the platform i2c_board_data section.
*/
static int ab3100_get_chip_id(struct device *dev)
{
struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
return (int)ab3100->chip_id;
}
static int ab3100_set_register_interruptible(struct ab3100 *ab3100,
u8 reg, u8 regval)
{
u8 regandval[2] = {reg, regval};
int err;
err = mutex_lock_interruptible(&ab3100->access_mutex);
if (err)
return err;
/*
* A two-byte write message with the first byte containing the register
* number and the second byte containing the value to be written
* effectively sets a register in the AB3100.
*/
err = i2c_master_send(ab3100->i2c_client, regandval, 2);
if (err < 0) {
dev_err(ab3100->dev,
"write error (write register): %d\n",
err);
} else if (err != 2) {
dev_err(ab3100->dev,
"write error (write register) "
"%d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
/* All is well */
err = 0;
}
mutex_unlock(&ab3100->access_mutex);
return err;
}
static int set_register_interruptible(struct device *dev,
u8 bank, u8 reg, u8 value)
{
struct ab3100 *ab3100 = dev_get_drvdata(dev->parent);
return ab3100_set_register_interruptible(ab3100, reg, value);
}
/*
* The test registers exist at an I2C bus address up one
* from the ordinary base. They are not supposed to be used
* in production code, but sometimes you have to do that
* anyway. It's currently only used from this file so declare
* it static and do not export.
*/
static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100,
u8 reg, u8 regval)
{
u8 regandval[2] = {reg, regval};
int err;
err = mutex_lock_interruptible(&ab3100->access_mutex);
if (err)
return err;
err = i2c_master_send(ab3100->testreg_client, regandval, 2);
if (err < 0) {
dev_err(ab3100->dev,
"write error (write test register): %d\n",
err);
} else if (err != 2) {
dev_err(ab3100->dev,
"write error (write test register) "
"%d bytes transferred (expected 2)\n",
err);
err = -EIO;
} else {
/* All is well */
err = 0;
}
mutex_unlock(&ab3100->access_mutex);
return err;
}
static int ab3100_get_register_interruptible(struct ab3100 *ab3100,
u8 reg, u8 *regval)
{
int err;
err = mutex_lock_interruptible(&ab3100->access_mutex);
if (err)
return err;
/*
* AB3100 require an I2C "stop" command between each message, else
* it will not work. The only way of achieveing this with the
* message transport layer is to send the read and write messages
* separately.
*/
err = i2c_master_send(ab3100->i2c_client, ®, 1);
if (err < 0) {
dev_err(ab3100->dev,
"write error (send register address): %d\n",
err);
goto get_reg_out_unlock;
} else if (err != 1) {
dev_err(ab3100->dev,
"write error (send register address) "
"%d bytes transferred (expected 1)\n",
err);
err = -EIO;
goto get_reg_out_unlock;
} else {
/* All is well */
err = 0;
}
err = i2c_master_recv(ab3100->i2c_client, regval, 1);