blob: 69a26abc6237162678f0091586848f29b140eb0e [file] [log] [blame]
/*
* drivers/mfd/max77663-core.c
* Max77663 mfd driver (I2C bus access)
*
* Copyright 2011 Maxim Integrated Products, Inc.
* Copyright (C) 2011-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
*/
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <linux/kthread.h>
#include <linux/mfd/core.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/seq_file.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/mfd/max77663-core.h>
/* RTC i2c slave address */
#define MAX77663_RTC_I2C_ADDR 0x48
/* Registers */
#define MAX77663_REG_IRQ_TOP 0x05
#define MAX77663_REG_LBT_IRQ 0x06
#define MAX77663_REG_SD_IRQ 0x07
#define MAX77663_REG_LDOX_IRQ 0x08
#define MAX77663_REG_LDO8_IRQ 0x09
#define MAX77663_REG_GPIO_IRQ 0x0A
#define MAX77663_REG_ONOFF_IRQ 0x0B
#define MAX77663_REG_NVER 0x0C
#define MAX77663_REG_IRQ_TOP_MASK 0x0D
#define MAX77663_REG_LBT_IRQ_MASK 0x0E
#define MAX77663_REG_SD_IRQ_MASK 0x0F
#define MAX77663_REG_LDOX_IRQ_MASK 0x10
#define MAX77663_REG_LDO8_IRQ_MASK 0x11
#define MAX77663_REG_ONOFF_IRQ_MASK 0x12
#define MAX77663_REG_GPIO_CTRL0 0x36
#define MAX77663_REG_GPIO_CTRL1 0x37
#define MAX77663_REG_GPIO_CTRL2 0x38
#define MAX77663_REG_GPIO_CTRL3 0x39
#define MAX77663_REG_GPIO_CTRL4 0x3A
#define MAX77663_REG_GPIO_CTRL5 0x3B
#define MAX77663_REG_GPIO_CTRL6 0x3C
#define MAX77663_REG_GPIO_CTRL7 0x3D
#define MAX77663_REG_GPIO_PU 0x3E
#define MAX77663_REG_GPIO_PD 0x3F
#define MAX77663_REG_GPIO_ALT 0x40
#define MAX77663_REG_ONOFF_CFG1 0x41
#define MAX77663_REG_ONOFF_CFG2 0x42
#define MAX77663_REG_CID4 0x5C
#define MAX77663_REG_CID5 0x5D
#define IRQ_TOP_GLBL_MASK (1 << 7)
#define IRQ_TOP_GLBL_SHIFT 7
#define IRQ_TOP_SD_MASK (1 << 6)
#define IRQ_TOP_SD_SHIFT 6
#define IRQ_TOP_LDO_MASK (1 << 5)
#define IRQ_TOP_LDO_SHIFT 5
#define IRQ_TOP_GPIO_MASK (1 << 4)
#define IRQ_TOP_GPIO_SHIFT 4
#define IRQ_TOP_RTC_MASK (1 << 3)
#define IRQ_TOP_RTC_SHIFT 3
#define IRQ_TOP_32K_MASK (1 << 2)
#define IRQ_TOP_32K_SHIFT 2
#define IRQ_TOP_ONOFF_MASK (1 << 1)
#define IRQ_TOP_ONOFF_SHIFT 1
#define IRQ_TOP_NVER_MASK (1 << 0)
#define IRQ_TOP_NVER_SHIFT 0
#define IRQ_GLBL_MASK (1 << 0)
#define IRQ_LBT_BASE MAX77663_IRQ_LBT_LB
#define IRQ_LBT_END MAX77663_IRQ_LBT_THERM_ALRM2
#define IRQ_GPIO_BASE MAX77663_IRQ_GPIO0
#define IRQ_GPIO_END MAX77663_IRQ_GPIO7
#define IRQ_ONOFF_BASE MAX77663_IRQ_ONOFF_HRDPOWRN
#define IRQ_ONOFF_END MAX77663_IRQ_ONOFF_ACOK_RISING
#define GPIO_REG_ADDR(offset) (MAX77663_REG_GPIO_CTRL0 + offset)
#define GPIO_CTRL_DBNC_MASK (3 << 6)
#define GPIO_CTRL_DBNC_SHIFT 6
#define GPIO_CTRL_REFE_IRQ_MASK (3 << 4)
#define GPIO_CTRL_REFE_IRQ_SHIFT 4
#define GPIO_CTRL_DOUT_MASK (1 << 3)
#define GPIO_CTRL_DOUT_SHIFT 3
#define GPIO_CTRL_DIN_MASK (1 << 2)
#define GPIO_CTRL_DIN_SHIFT 2
#define GPIO_CTRL_DIR_MASK (1 << 1)
#define GPIO_CTRL_DIR_SHIFT 1
#define GPIO_CTRL_OUT_DRV_MASK (1 << 0)
#define GPIO_CTRL_OUT_DRV_SHIFT 0
#define GPIO_REFE_IRQ_NONE 0
#define GPIO_REFE_IRQ_EDGE_FALLING 1
#define GPIO_REFE_IRQ_EDGE_RISING 2
#define GPIO_REFE_IRQ_EDGE_BOTH 3
#define GPIO_DBNC_NONE 0
#define GPIO_DBNC_8MS 1
#define GPIO_DBNC_16MS 2
#define GPIO_DBNC_32MS 3
#define ONOFF_SFT_RST_MASK (1 << 7)
#define ONOFF_SLPEN_MASK (1 << 2)
#define ONOFF_PWR_OFF_MASK (1 << 1)
#define ONOFF_SLP_LPM_MASK (1 << 5)
#define ONOFF_IRQ_EN0_RISING (1 << 3)
enum {
CACHE_IRQ_LBT,
CACHE_IRQ_SD,
CACHE_IRQ_LDO,
CACHE_IRQ_ONOFF,
CACHE_IRQ_NR,
};
struct max77663_irq_data {
int mask_reg;
u16 mask;
u8 top_mask;
u8 top_shift;
int cache_idx;
bool is_rtc;
bool is_unmask;
u8 trigger_type;
};
struct max77663_chip {
struct device *dev;
struct i2c_client *i2c_power;
struct i2c_client *i2c_rtc;
struct regmap *regmap_power;
struct regmap *regmap_rtc;
struct max77663_platform_data *pdata;
struct mutex io_lock;
struct irq_chip irq;
struct mutex irq_lock;
int irq_base;
int irq_top_count[8];
u8 cache_irq_top_mask;
u16 cache_irq_mask[CACHE_IRQ_NR];
u8 rtc_i2c_addr;
};
struct max77663_chip *max77663_chip;
static struct resource gpio_resources[] = {
{
.start = MAX77663_IRQ_INT_TOP_GPIO,
.end = MAX77663_IRQ_INT_TOP_GPIO,
.flags = IORESOURCE_IRQ,
}
};
static struct resource rtc_resources[] = {
{
.start = MAX77663_IRQ_RTC,
.end = MAX77663_IRQ_RTC,
.flags = IORESOURCE_IRQ,
}
};
static struct mfd_cell max77663_cells[] = {
{
.name = "max77663-gpio",
.num_resources = ARRAY_SIZE(gpio_resources),
.resources = &gpio_resources[0],
}, {
.name = "max77663-pmic",
}, {
.name = "max77663-rtc",
.num_resources = ARRAY_SIZE(rtc_resources),
.resources = &rtc_resources[0],
},
};
#define IRQ_DATA_LBT(_name, _shift) \
[MAX77663_IRQ_LBT_##_name] = { \
.mask_reg = MAX77663_REG_LBT_IRQ_MASK, \
.mask = (1 << _shift), \
.top_mask = IRQ_TOP_GLBL_MASK, \
.top_shift = IRQ_TOP_GLBL_SHIFT, \
.cache_idx = CACHE_IRQ_LBT, \
}
#define IRQ_DATA_GPIO_TOP() \
[MAX77663_IRQ_INT_TOP_GPIO] = { \
.top_mask = IRQ_TOP_GPIO_MASK, \
.top_shift = IRQ_TOP_GPIO_SHIFT, \
.cache_idx = -1, \
}
#define IRQ_DATA_ONOFF(_name, _shift) \
[MAX77663_IRQ_ONOFF_##_name] = { \
.mask_reg = MAX77663_REG_ONOFF_IRQ_MASK,\
.mask = (1 << _shift), \
.top_mask = IRQ_TOP_ONOFF_MASK, \
.top_shift = IRQ_TOP_ONOFF_SHIFT, \
.cache_idx = CACHE_IRQ_ONOFF, \
}
static struct max77663_irq_data max77663_irqs[MAX77663_IRQ_NR] = {
IRQ_DATA_GPIO_TOP(),
IRQ_DATA_LBT(LB, 3),
IRQ_DATA_LBT(THERM_ALRM1, 2),
IRQ_DATA_LBT(THERM_ALRM2, 1),
IRQ_DATA_ONOFF(HRDPOWRN, 0),
IRQ_DATA_ONOFF(EN0_1SEC, 1),
IRQ_DATA_ONOFF(EN0_FALLING, 2),
IRQ_DATA_ONOFF(EN0_RISING, 3),
IRQ_DATA_ONOFF(LID_FALLING, 4),
IRQ_DATA_ONOFF(LID_RISING, 5),
IRQ_DATA_ONOFF(ACOK_FALLING, 6),
IRQ_DATA_ONOFF(ACOK_RISING, 7),
[MAX77663_IRQ_RTC] = {
.top_mask = IRQ_TOP_RTC_MASK,
.top_shift = IRQ_TOP_RTC_SHIFT,
.cache_idx = -1,
.is_rtc = 1,
},
[MAX77663_IRQ_SD_PF] = {
.mask_reg = MAX77663_REG_SD_IRQ_MASK,
.mask = 0xF8,
.top_mask = IRQ_TOP_SD_MASK,
.top_shift = IRQ_TOP_SD_SHIFT,
.cache_idx = CACHE_IRQ_SD,
},
[MAX77663_IRQ_LDO_PF] = {
.mask_reg = MAX77663_REG_LDOX_IRQ_MASK,
.mask = 0x1FF,
.top_mask = IRQ_TOP_LDO_MASK,
.top_shift = IRQ_TOP_LDO_SHIFT,
.cache_idx = CACHE_IRQ_LDO,
},
[MAX77663_IRQ_32K] = {
.top_mask = IRQ_TOP_32K_MASK,
.top_shift = IRQ_TOP_32K_SHIFT,
.cache_idx = -1,
},
[MAX77663_IRQ_NVER] = {
.top_mask = IRQ_TOP_NVER_MASK,
.top_shift = IRQ_TOP_NVER_SHIFT,
.cache_idx = -1,
},
};
/* MAX77663 PMU doesn't allow PWR_OFF and SFT_RST setting in ONOFF_CFG1
* at the same time. So if it try to set PWR_OFF and SFT_RST to ONOFF_CFG1
* simultaneously, handle only SFT_RST and ignore PWR_OFF.
*/
#define CHECK_ONOFF_CFG1_MASK (ONOFF_SFT_RST_MASK | ONOFF_PWR_OFF_MASK)
#define CHECK_ONOFF_CFG1(_addr, _val) \
unlikely((_addr == MAX77663_REG_ONOFF_CFG1) && \
((_val & CHECK_ONOFF_CFG1_MASK) == CHECK_ONOFF_CFG1_MASK))
static inline int max77663_i2c_write(struct max77663_chip *chip, u8 addr,
void *src, u32 bytes, bool is_rtc)
{
int ret = 0;
dev_dbg(chip->dev, "i2c_write: addr=0x%02x, src=0x%02x, bytes=%u\n",
addr, *((u8 *)src), bytes);
if (is_rtc) {
/* RTC registers support sequential writing */
ret = regmap_bulk_write(chip->regmap_rtc, addr, src, bytes);
} else {
/* Power registers support register-data pair writing */
u8 *src8 = (u8 *)src;
unsigned int val;
int i;
for (i = 0; i < bytes; i++) {
if (CHECK_ONOFF_CFG1(addr, *src8))
val = *src8++ & ~ONOFF_PWR_OFF_MASK;
else
val = *src8++;
ret = regmap_write(chip->regmap_power, addr, val);
if (ret < 0)
break;
addr++;
}
}
if (ret < 0)
dev_err(chip->dev, "%s() failed, e %d\n", __func__, ret);
return ret;
}
static inline int max77663_i2c_read(struct max77663_chip *chip, u8 addr,
void *dest, u32 bytes, bool is_rtc)
{
int ret = 0;
struct regmap *regmap = chip->regmap_power;
if (is_rtc)
regmap = chip->regmap_rtc;
ret = regmap_bulk_read(regmap, addr, dest, bytes);
if (ret < 0) {
dev_err(chip->dev, "%s() failed, e %d\n", __func__, ret);
return ret;
}
dev_dbg(chip->dev, "i2c_read: addr=0x%02x, dest=0x%02x, bytes=%u\n",
addr, *((u8 *)dest), bytes);
return ret;
}
int max77663_read(struct device *dev, u8 addr, void *values, u32 len,
bool is_rtc)
{
struct max77663_chip *chip = dev_get_drvdata(dev);
int ret;
mutex_lock(&chip->io_lock);
ret = max77663_i2c_read(chip, addr, values, len, is_rtc);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(max77663_read);
int max77663_write(struct device *dev, u8 addr, void *values, u32 len,
bool is_rtc)
{
struct max77663_chip *chip = dev_get_drvdata(dev);
int ret;
mutex_lock(&chip->io_lock);
ret = max77663_i2c_write(chip, addr, values, len, is_rtc);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(max77663_write);
int max77663_set_bits(struct device *dev, u8 addr, u8 mask, u8 value,
bool is_rtc)
{
struct max77663_chip *chip = dev_get_drvdata(dev);
int ret;
struct regmap *regmap = chip->regmap_power;
if (is_rtc)
regmap = chip->regmap_rtc;
mutex_lock(&chip->io_lock);
ret = regmap_update_bits(regmap, addr, mask, value);
mutex_unlock(&chip->io_lock);
return ret;
}
EXPORT_SYMBOL(max77663_set_bits);
static void max77663_power_off(void)
{
struct max77663_chip *chip = max77663_chip;
if (!chip)
return;
dev_info(chip->dev, "%s: Global shutdown\n", __func__);
max77663_set_bits(chip->dev, MAX77663_REG_ONOFF_CFG1,
ONOFF_SFT_RST_MASK, ONOFF_SFT_RST_MASK, 0);
}
static int max77663_sleep(struct max77663_chip *chip, bool on)
{
int ret = 0;
if (chip->pdata->flags & SLP_LPM_ENABLE) {
/* Put the power rails into Low-Power mode during sleep mode,
* if the power rail's power mode is GLPM. */
ret = max77663_set_bits(chip->dev, MAX77663_REG_ONOFF_CFG2,
ONOFF_SLP_LPM_MASK,
on ? ONOFF_SLP_LPM_MASK : 0, 0);
if (ret < 0)
return ret;
}
/* Enable sleep that AP can be placed into sleep mode
* by pulling EN1 low */
return max77663_set_bits(chip->dev, MAX77663_REG_ONOFF_CFG1,
ONOFF_SLPEN_MASK,
on ? ONOFF_SLPEN_MASK : 0, 0);
}
static inline int max77663_cache_write(struct device *dev, u8 addr, u8 mask,
u8 val, u8 *cache)
{
u8 new_val;
int ret;
new_val = (*cache & ~mask) | (val & mask);
if (*cache != new_val) {
ret = max77663_write(dev, addr, &new_val, 1, 0);
if (ret < 0)
return ret;
*cache = new_val;
}
return 0;
}
static void max77663_irq_mask(struct irq_data *data)
{
struct max77663_chip *chip = irq_data_get_irq_chip_data(data);
max77663_irqs[data->irq - chip->irq_base].is_unmask = 0;
}
static void max77663_irq_unmask(struct irq_data *data)
{
struct max77663_chip *chip = irq_data_get_irq_chip_data(data);
max77663_irqs[data->irq - chip->irq_base].is_unmask = 1;
}
static void max77663_irq_lock(struct irq_data *data)
{
struct max77663_chip *chip = irq_data_get_irq_chip_data(data);
mutex_lock(&chip->irq_lock);
}
static void max77663_irq_sync_unlock(struct irq_data *data)
{
struct max77663_chip *chip = irq_data_get_irq_chip_data(data);
struct max77663_irq_data *irq_data =
&max77663_irqs[data->irq - chip->irq_base];
int idx = irq_data->cache_idx;
u8 irq_top_mask = chip->cache_irq_top_mask;
u16 irq_mask = chip->cache_irq_mask[idx];
int update_irq_top = 0;
u32 len = 1;
int ret;
if (irq_data->is_unmask) {
if (chip->irq_top_count[irq_data->top_shift] == 0)
update_irq_top = 1;
chip->irq_top_count[irq_data->top_shift]++;
if (irq_data->top_mask != IRQ_TOP_GLBL_MASK)
irq_top_mask &= ~irq_data->top_mask;
if (idx != -1)
irq_mask &= ~irq_data->mask;
} else {
if (chip->irq_top_count[irq_data->top_shift] == 1)
update_irq_top = 1;
if (--chip->irq_top_count[irq_data->top_shift] < 0)
chip->irq_top_count[irq_data->top_shift] = 0;
if (irq_data->top_mask != IRQ_TOP_GLBL_MASK)
irq_top_mask |= irq_data->top_mask;
if (idx != -1)
irq_mask |= irq_data->mask;
}
if ((idx != -1) && (irq_mask != chip->cache_irq_mask[idx])) {
if (irq_data->top_mask == IRQ_TOP_LDO_MASK)
len = 2;
ret = max77663_write(chip->dev, irq_data->mask_reg,
&irq_mask, len, irq_data->is_rtc);
if (ret < 0)
goto out;
chip->cache_irq_mask[idx] = irq_mask;
}
if (update_irq_top && (irq_top_mask != chip->cache_irq_top_mask)) {
ret = max77663_cache_write(chip->dev, MAX77663_REG_IRQ_TOP_MASK,
irq_data->top_mask, irq_top_mask,
&chip->cache_irq_top_mask);
if (ret < 0)
goto out;
}
out:
mutex_unlock(&chip->irq_lock);
}
static inline int max77663_do_irq(struct max77663_chip *chip, u8 addr,
int irq_base, int irq_end)
{
struct max77663_irq_data *irq_data = NULL;
int irqs_to_handle[irq_end - irq_base + 1];
int handled = 0;
u16 val;
u32 len = 1;
int i;
int ret;
ret = max77663_read(chip->dev, addr, &val, len, 0);
if (ret < 0)
return ret;
for (i = irq_base; i <= irq_end; i++) {
irq_data = &max77663_irqs[i];
if (val & irq_data->mask) {
irqs_to_handle[handled] = i + chip->irq_base;
handled++;
}
}
for (i = 0; i < handled; i++)
handle_nested_irq(irqs_to_handle[i]);
return 0;
}
static irqreturn_t max77663_irq(int irq, void *data)
{
struct max77663_chip *chip = data;
u8 irq_top;
int ret;
ret = max77663_read(chip->dev, MAX77663_REG_IRQ_TOP, &irq_top, 1, 0);
if (ret < 0) {
dev_err(chip->dev, "irq: Failed to get irq top status\n");
return IRQ_NONE;
}
if (irq_top & IRQ_TOP_GLBL_MASK) {
ret = max77663_do_irq(chip, MAX77663_REG_LBT_IRQ, IRQ_LBT_BASE,
IRQ_LBT_END);
if (ret < 0)
return IRQ_NONE;
}
if (irq_top & IRQ_TOP_GPIO_MASK)
handle_nested_irq(MAX77663_IRQ_INT_TOP_GPIO + chip->irq_base);
if (irq_top & IRQ_TOP_ONOFF_MASK) {
ret = max77663_do_irq(chip, MAX77663_REG_ONOFF_IRQ,
IRQ_ONOFF_BASE, IRQ_ONOFF_END);
if (ret < 0)
return IRQ_NONE;
}
if (irq_top & IRQ_TOP_RTC_MASK)
handle_nested_irq(MAX77663_IRQ_RTC + chip->irq_base);
if (irq_top & IRQ_TOP_SD_MASK)
handle_nested_irq(MAX77663_IRQ_SD_PF + chip->irq_base);
if (irq_top & IRQ_TOP_LDO_MASK)
handle_nested_irq(MAX77663_IRQ_LDO_PF + chip->irq_base);
if (irq_top & IRQ_TOP_32K_MASK)
handle_nested_irq(MAX77663_IRQ_32K + chip->irq_base);
if (irq_top & IRQ_TOP_NVER_MASK)
handle_nested_irq(MAX77663_IRQ_NVER + chip->irq_base);
return IRQ_HANDLED;
}
static struct irq_chip max77663_irq_chip = {
.name = "max77663-irq",
.irq_mask = max77663_irq_mask,
.irq_unmask = max77663_irq_unmask,
.irq_bus_lock = max77663_irq_lock,
.irq_bus_sync_unlock = max77663_irq_sync_unlock,
};
static int max77663_irq_init(struct max77663_chip *chip)
{
u32 temp;
int i, ret = 0;
mutex_init(&chip->irq_lock);
/* Mask all interrupts */
chip->cache_irq_top_mask = 0xFF;
chip->cache_irq_mask[CACHE_IRQ_LBT] = 0x0F;
chip->cache_irq_mask[CACHE_IRQ_SD] = 0xFF;
chip->cache_irq_mask[CACHE_IRQ_LDO] = 0xFFFF;
chip->cache_irq_mask[CACHE_IRQ_ONOFF] = 0xFF;
max77663_write(chip->dev, MAX77663_REG_IRQ_TOP_MASK,
&chip->cache_irq_top_mask, 1, 0);
max77663_write(chip->dev, MAX77663_REG_LBT_IRQ_MASK,
&chip->cache_irq_mask[CACHE_IRQ_LBT], 1, 0);
max77663_write(chip->dev, MAX77663_REG_SD_IRQ_MASK,
&chip->cache_irq_mask[CACHE_IRQ_SD], 1, 0);
max77663_write(chip->dev, MAX77663_REG_LDOX_IRQ_MASK,
&chip->cache_irq_mask[CACHE_IRQ_LDO], 2, 0);
max77663_write(chip->dev, MAX77663_REG_ONOFF_IRQ_MASK,
&chip->cache_irq_mask[CACHE_IRQ_ONOFF], 1, 0);
/* Clear all interrups */
max77663_read(chip->dev, MAX77663_REG_LBT_IRQ, &temp, 1, 0);
max77663_read(chip->dev, MAX77663_REG_SD_IRQ, &temp, 1, 0);
max77663_read(chip->dev, MAX77663_REG_LDOX_IRQ, &temp, 2, 0);
//max77663_read(chip->dev, MAX77663_REG_GPIO_IRQ, &temp, 1, 0);
max77663_read(chip->dev, MAX77663_REG_ONOFF_IRQ, &temp, 1, 0);
for (i = chip->irq_base; i < (MAX77663_IRQ_NR + chip->irq_base); i++) {
int irq = i - chip->irq_base;
if (i >= NR_IRQS) {
dev_err(chip->dev,
"irq_init: Can't set irq chip for irq %d\n", i);
continue;
}
if ((irq >= MAX77663_IRQ_GPIO0) && (irq <= MAX77663_IRQ_GPIO7))
continue;
irq_set_chip_data(i, chip);
irq_set_chip_and_handler(i, &max77663_irq_chip, handle_edge_irq);
#ifdef CONFIG_ARM
set_irq_flags(i, IRQF_VALID);
#else
irq_set_noprobe(i);
#endif
irq_set_nested_thread(i, 1);
}
ret = request_threaded_irq(chip->i2c_power->irq, NULL, max77663_irq,
IRQF_ONESHOT, "max77663", chip);
if (ret) {
dev_err(chip->dev, "irq_init: Failed to request irq %d\n",
chip->i2c_power->irq);
return ret;
}
device_init_wakeup(chip->dev, 1);
enable_irq_wake(chip->i2c_power->irq);
chip->cache_irq_top_mask &= ~IRQ_TOP_GLBL_MASK;
max77663_write(chip->dev, MAX77663_REG_IRQ_TOP_MASK,
&chip->cache_irq_top_mask, 1, 0);
chip->cache_irq_mask[CACHE_IRQ_LBT] &= ~IRQ_GLBL_MASK;
max77663_write(chip->dev, MAX77663_REG_LBT_IRQ_MASK,
&chip->cache_irq_mask[CACHE_IRQ_LBT], 1, 0);
chip->cache_irq_mask[CACHE_IRQ_ONOFF] &= ~ONOFF_IRQ_EN0_RISING;
max77663_write(chip->dev, MAX77663_REG_ONOFF_IRQ_MASK,
&chip->cache_irq_mask[CACHE_IRQ_ONOFF], 1, 0);
return 0;
}
static void max77663_irq_exit(struct max77663_chip *chip)
{
if (chip->i2c_power->irq)
free_irq(chip->i2c_power->irq, chip);
}
#ifdef CONFIG_DEBUG_FS
static struct dentry *max77663_dentry_regs;
static int max77663_debugfs_dump_regs(struct max77663_chip *chip, char *label,
u8 *addrs, int num_addrs, char *buf,
ssize_t *len, int is_rtc)
{
ssize_t count = *len;
u8 val;
int ret = 0;
int i;
count += sprintf(buf + count, "%s\n", label);
if (count >= PAGE_SIZE - 1)
return -ERANGE;
for (i = 0; i < num_addrs; i++) {
count += sprintf(buf + count, "0x%02x: ", addrs[i]);
if (count >= PAGE_SIZE - 1)
return -ERANGE;
ret = max77663_read(chip->dev, addrs[i], &val, 1, is_rtc);
if (ret == 0)
count += sprintf(buf + count, "0x%02x\n", val);
else
count += sprintf(buf + count, "<read fail: %d>\n", ret);
if (count >= PAGE_SIZE - 1)
return -ERANGE;
}
*len = count;
return 0;
}
static int max77663_debugfs_regs_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
return 0;
}
static ssize_t max77663_debugfs_regs_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct max77663_chip *chip = file->private_data;
char *buf;
size_t len = 0;
ssize_t ret;
/* Excluded interrupt status register to prevent register clear */
u8 global_regs[] = { 0x00, 0x01, 0x02, 0x05, 0x0D, 0x0E, 0x13 };
u8 sd_regs[] = {
0x07, 0x0F, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
0x1E, 0x1F, 0x20, 0x21, 0x22
};
u8 ldo_regs[] = {
0x10, 0x11, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34,
0x35
};
u8 gpio_regs[] = {
0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40
};
u8 rtc_regs[] = {
0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B
};
u8 osc_32k_regs[] = { 0x03 };
u8 bbc_regs[] = { 0x04 };
u8 onoff_regs[] = { 0x12, 0x15, 0x41, 0x42 };
u8 fps_regs[] = {
0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C,
0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56,
0x57
};
u8 cid_regs[] = { 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D };
buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
len += sprintf(buf + len, "MAX77663 Registers\n");
max77663_debugfs_dump_regs(chip, "[Global]", global_regs,
ARRAY_SIZE(global_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[Step-Down]", sd_regs,
ARRAY_SIZE(sd_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[LDO]", ldo_regs,
ARRAY_SIZE(ldo_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[GPIO]", gpio_regs,
ARRAY_SIZE(gpio_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[RTC]", rtc_regs,
ARRAY_SIZE(rtc_regs), buf, &len, 1);
max77663_debugfs_dump_regs(chip, "[32kHz Oscillator]", osc_32k_regs,
ARRAY_SIZE(osc_32k_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[Backup Battery Charger]", bbc_regs,
ARRAY_SIZE(bbc_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[On/OFF Controller]", onoff_regs,
ARRAY_SIZE(onoff_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[Flexible Power Sequencer]", fps_regs,
ARRAY_SIZE(fps_regs), buf, &len, 0);
max77663_debugfs_dump_regs(chip, "[Chip Identification]", cid_regs,
ARRAY_SIZE(cid_regs), buf, &len, 0);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return ret;
}
static const struct file_operations max77663_debugfs_regs_fops = {
.open = max77663_debugfs_regs_open,
.read = max77663_debugfs_regs_read,
};
static void max77663_debugfs_init(struct max77663_chip *chip)
{
max77663_dentry_regs = debugfs_create_file(chip->i2c_power->name,
0444, 0, chip,
&max77663_debugfs_regs_fops);
if (!max77663_dentry_regs)
dev_warn(chip->dev,
"debugfs_init: Failed to create debugfs file\n");
}
static void max77663_debugfs_exit(struct max77663_chip *chip)
{
debugfs_remove(max77663_dentry_regs);
}
#else
static inline void max77663_debugfs_init(struct max77663_chip *chip)
{
}
static inline void max77663_debugfs_exit(struct max77663_chip *chip)
{
}
#endif /* CONFIG_DEBUG_FS */
static bool rd_wr_reg_power(struct device *dev, unsigned int reg)
{
if (reg < 0x60)
return true;
dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg);
BUG();
return false;
}
static bool rd_wr_reg_rtc(struct device *dev, unsigned int reg)
{
if (reg < 0x1C)
return true;
dev_err(dev, "non-existing reg %s() reg 0x%x\n", __func__, reg);
BUG();
return false;
}
int max77663_read_chip_version(struct device *dev, u8 *val)
{
int ret, version;
version = MAX77663_DRV_NOT_DEFINED;
ret = max77663_read(dev, MAX77663_REG_CID4, val, 1, 0);
if (!ret) {
if (*val == 0x24)
version = MAX77663_DRV_24;
return version;
}
return ret;
}
static const struct regmap_config max77663_regmap_config_power = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x60,
.writeable_reg = rd_wr_reg_power,
.readable_reg = rd_wr_reg_power,
.cache_type = REGCACHE_RBTREE,
};
static const struct regmap_config max77663_regmap_config_rtc = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0x1C,
.writeable_reg = rd_wr_reg_rtc,
.readable_reg = rd_wr_reg_rtc,
.cache_type = REGCACHE_RBTREE,
};
static int max77663_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct max77663_platform_data *pdata = client->dev.platform_data;
struct max77663_chip *chip;
int ret = 0;
u8 val;
if (pdata == NULL) {
dev_err(&client->dev, "probe: Invalid platform_data\n");
return -ENODEV;
}
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (chip == NULL) {
dev_err(&client->dev, "probe: kzalloc() failed\n");
return -ENOMEM;
}
max77663_chip = chip;
chip->i2c_power = client;
i2c_set_clientdata(client, chip);
chip->regmap_power = devm_regmap_init_i2c(client,
&max77663_regmap_config_power);
if (IS_ERR(chip->regmap_power)) {
ret = PTR_ERR(chip->regmap_power);
dev_err(&client->dev, "power regmap init failed: %d\n", ret);
return ret;
}
if (pdata->rtc_i2c_addr)
chip->rtc_i2c_addr = pdata->rtc_i2c_addr;
else
chip->rtc_i2c_addr = MAX77663_RTC_I2C_ADDR;
chip->i2c_rtc = i2c_new_dummy(client->adapter, chip->rtc_i2c_addr);
if (!chip->i2c_rtc) {
dev_err(&client->dev, "can't attach client at addr 0x%x\n",
chip->rtc_i2c_addr);
return -ENOMEM;
}
i2c_set_clientdata(chip->i2c_rtc, chip);
chip->regmap_rtc = devm_regmap_init_i2c(chip->i2c_rtc,
&max77663_regmap_config_rtc);
if (IS_ERR(chip->regmap_rtc)) {
ret = PTR_ERR(chip->regmap_rtc);
dev_err(&client->dev, "rtc tegmap init failed: %d\n", ret);
goto out_rtc_regmap_fail;
}
chip->dev = &client->dev;
chip->pdata = pdata;
chip->irq_base = pdata->irq_base;
mutex_init(&chip->io_lock);
/* Dummy read to see if chip is present or not*/
ret = max77663_read(chip->dev, MAX77663_REG_CID5, &val, 1, 0);
if (ret < 0) {
dev_err(chip->dev, "preinit: Failed to get register 0x%x\n",
MAX77663_REG_CID5);
return ret;
}
/* Reading chip version */
ret = max77663_read_chip_version(chip->dev, &val);
if (ret < 0)
dev_err(chip->dev, "Failed to read chip version\n");
else
dev_dbg(chip->dev, "Chip version - 0x%x\n", val);
max77663_irq_init(chip);
max77663_debugfs_init(chip);
ret = max77663_sleep(chip, false);
if (ret < 0) {
dev_err(&client->dev, "probe: Failed to disable sleep\n");
goto out_exit;
}
if (pdata->use_power_off && !pm_power_off)
pm_power_off = max77663_power_off;
ret = mfd_add_devices(&client->dev, -1, max77663_cells,
ARRAY_SIZE(max77663_cells), NULL, chip->irq_base,
NULL);
if (ret < 0) {
dev_err(&client->dev, "mfd add dev failed, e = %d\n", ret);
goto out_exit;
}
ret = mfd_add_devices(&client->dev, 0, pdata->sub_devices,
pdata->num_subdevs, NULL, 0, NULL);
if (ret != 0) {
dev_err(&client->dev, "probe: Failed to add subdev: %d\n", ret);
goto out_mfd_clean;
}
return 0;
out_mfd_clean:
mfd_remove_devices(chip->dev);
out_exit:
max77663_debugfs_exit(chip);
max77663_irq_exit(chip);
mutex_destroy(&chip->io_lock);
out_rtc_regmap_fail:
i2c_unregister_device(chip->i2c_rtc);
max77663_chip = NULL;
return ret;
}
static int max77663_remove(struct i2c_client *client)
{
struct max77663_chip *chip = i2c_get_clientdata(client);
mfd_remove_devices(chip->dev);
max77663_debugfs_exit(chip);
max77663_irq_exit(chip);
mutex_destroy(&chip->io_lock);
i2c_unregister_device(chip->i2c_rtc);
max77663_chip = NULL;
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int max77663_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct max77663_chip *chip = i2c_get_clientdata(client);
int ret;
if (client->irq)
disable_irq(client->irq);
ret = max77663_sleep(chip, true);
if (ret < 0)
dev_err(dev, "suspend: Failed to enable sleep\n");
return ret;
}
static int max77663_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct max77663_chip *chip = i2c_get_clientdata(client);
int ret;
ret = max77663_sleep(chip, false);
if (ret < 0) {
dev_err(dev, "resume: Failed to disable sleep\n");
return ret;
}
if (client->irq)
enable_irq(client->irq);
return 0;
}
#else
#define max77663_suspend NULL
#define max77663_resume NULL
#endif /* CONFIG_PM_SLEEP */
static const struct i2c_device_id max77663_id[] = {
{"max77663", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, max77663_id);
static const struct dev_pm_ops max77663_pm = {
.suspend = max77663_suspend,
.resume = max77663_resume,
};
static struct i2c_driver max77663_driver = {
.driver = {
.name = "max77663",
.owner = THIS_MODULE,
.pm = &max77663_pm,
},
.probe = max77663_probe,
.remove = max77663_remove,
.id_table = max77663_id,
};
static int __init max77663_init(void)
{
return i2c_add_driver(&max77663_driver);
}
subsys_initcall(max77663_init);
static void __exit max77663_exit(void)
{
i2c_del_driver(&max77663_driver);
}
module_exit(max77663_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MAX77663 Multi Function Device Core Driver");
MODULE_VERSION("1.0");