1
0
Fork 0
alistair23-linux/include/linux/power/max77818_battery_utils.h

169 lines
5.3 KiB
C

/*
* Maxim MAX77818 Battery Utils
*
* Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
*
* Author: Steinar Bakkemo <steinar.bakkemo@remarkable.com>
* Author: Shawn Guo <shawn.guo@linaro.org>
* Author: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
*
* 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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
* kind, whether express or implied; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __MAX17818_BATTERY_UTILS_H_
#define __MAX17818_BATTERY_UTILS_H_
#include <linux/mfd/max77818/max77818.h>
/* Exported function required for modules external to the max77818_battery
* module to be able to use the MAX77818_DO_NON_FGCC_OP macrov*/
int max77818_utils_set_fgcc_mode(struct max77818_dev *max77818_dev,
bool enabled,
bool *cur_mode);
/* Magic to enable optional macro param */
#define VARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define VARGS(...) VARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)
/* Common macro to be user from any context having access to the common
* max77818 struct defined in the max77818 MDF driver */
#define MAX77818_START_NON_FGCC_OP_3(max77818_dev, fgcc_restore_state, op_description) ( \
{ \
int ret = 0; \
bool restore_state = 0; \
\
if (!max77818_dev) { \
printk("%s: max77818_dev is NULL in MAX77818_DO_NON_FGCC_OP\n", __func__); \
ret = -EINVAL; \
} \
else { \
dev_dbg(max77818_dev->dev, op_description); \
\
dev_dbg(max77818_dev->dev, "Applying lock\n"); \
mutex_lock(&max77818_dev->lock); \
\
dev_dbg(max77818_dev->dev, "Clearing FGCC mode\n"); \
ret = max77818_utils_set_fgcc_mode(max77818_dev, \
false, \
&restore_state); \
if (ret) { \
dev_err(max77818_dev->dev, \
"Failed to clear FGCC bit in CONFIG register\n"); \
} \
else { \
fgcc_restore_state = restore_state; \
} \
\
/* UNLOCKING IS DONE IN MAX77818_FINISH_NON_FGCC_OP */ \
} \
ret; \
})
#define MAX77818_START_NON_FGCC_OP_2(max77818_dev, fgcc_restore_state) MAX77818_START_NON_FGCC_OP_3(max77818_dev, fgcc_restore_state, "")
#define MAX77818_START_NON_FGCC_OP(...) ( CONCAT(MAX77818_START_NON_FGCC_OP_, VARGS(__VA_ARGS__))(__VA_ARGS__) )
/* Common macro to be user from any context having access to the common
* max77818 struct defined in the max77818 MDF driver */
#define MAX77818_FINISH_NON_FGCC_OP_3(max77818_dev, fgcc_restore_state, op_description) ( \
{ \
int ret = 0; \
\
if (!max77818_dev) { \
printk("%s: max77818_dev is NULL in MAX77818_DO_NON_FGCC_OP\n", __func__); \
ret = -EINVAL; \
} \
else { \
dev_dbg(max77818_dev->dev, op_description); \
\
if (fgcc_restore_state) { \
dev_dbg(max77818_dev->dev, "Restoring FGCC mode\n"); \
\
ret = max77818_utils_set_fgcc_mode(max77818_dev, \
true, \
NULL); \
if (ret) { \
dev_err(max77818_dev->dev, \
"Failed to set FGCC bit in CONFIG register\n"); \
} \
} \
else { \
dev_dbg(max77818_dev->dev, \
"Leaving FGCC bit as it were (OFF)\n"); \
} \
dev_dbg(max77818_dev->dev, "Releasing lock\n"); \
mutex_unlock(&max77818_dev->lock); \
} \
ret; \
})
#define MAX77818_FINISH_NON_FGCC_OP_2(max77818_dev, fgcc_restore_state) MAX77818_FINISH_NON_FGCC_OP_3(max77818_dev, fgcc_restore_state, "")
#define MAX77818_FINISH_NON_FGCC_OP(...) ( CONCAT(MAX77818_FINISH_NON_FGCC_OP_, VARGS(__VA_ARGS__))(__VA_ARGS__) )
/* Common macro to be used from any context having access to the common
* max77818 struct defined in the max77818 MFD driver */
#define MAX77818_DO_NON_FGCC_OP_3(max77818_dev, op, op_description) ( \
{ \
int ret = 0; \
bool restore_state = 0; \
\
if (!max77818_dev) { \
printk("%s: max77818_dev is NULL in MAX77818_DO_NON_FGCC_OP\n", __func__); \
ret = -EINVAL; \
} \
else { \
dev_dbg(max77818_dev->dev, "Applying lock\n"); \
mutex_lock(&max77818_dev->lock); \
\
dev_dbg(max77818_dev->dev, "Clearing FGCC mode\n"); \
\
ret = max77818_utils_set_fgcc_mode(max77818_dev, \
false, \
&restore_state); \
if (ret) { \
dev_err(max77818_dev->dev, \
"Failed to clear FGCC bit in CONFIG register\n"); \
} \
else { \
dev_dbg(max77818_dev->dev, op_description); \
ret = op; \
\
if (ret) { \
dev_err(max77818_dev->dev, \
"Failed to read charger mode from charger driver\n"); \
} \
else { \
if (restore_state) { \
dev_dbg(max77818_dev->dev, "Restoring FGCC mode\n"); \
\
ret = max77818_utils_set_fgcc_mode( \
max77818_dev, true, NULL); \
if (ret) { \
dev_err(max77818_dev->dev, \
"Failed to set FGCC bit in CONFIG register\n"); \
} \
} \
else { \
dev_dbg(max77818_dev->dev, \
"Leaving FGCC bit as it were (OFF)\n"); \
} \
} \
} \
dev_dbg(max77818_dev->dev, "Releasing lock\n"); \
mutex_unlock(&max77818_dev->lock); \
} \
ret; \
})
#define MAX77818_DO_NON_FGCC_OP_2(max77818_dev, op) MAX77818_DO_NON_FGCC_OP_3(max77818_dev, op, "")
#define MAX77818_DO_NON_FGCC_OP(...) ( CONCAT(MAX77818_DO_NON_FGCC_OP_, VARGS(__VA_ARGS__))(__VA_ARGS__) )
#endif /* __MAX17818_BATTERY_UTILS_H_ */