linux/drivers/power/supply/smb347-charger.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Summit Microelectronics SMB347 Battery Charger Driver
 *
 * Copyright (C) 2011, Intel Corporation
 *
 * Authors: Bruce E. Robertson <[email protected]>
 *          Mika Westerberg <[email protected]>
 */

#include <linux/delay.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/power_supply.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>

#include <dt-bindings/power/summit,smb347-charger.h>

/* Use the default compensation method */
#define SMB3XX_SOFT_TEMP_COMPENSATE_DEFAULT

/* Use default factory programmed value for hard/soft temperature limit */
#define SMB3XX_TEMP_USE_DEFAULT

/*
 * Configuration registers. These are mirrored to volatile RAM and can be
 * written once %CMD_A_ALLOW_WRITE is set in %CMD_A register. They will be
 * reloaded from non-volatile registers after POR.
 */
#define CFG_CHARGE_CURRENT
#define CFG_CHARGE_CURRENT_FCC_MASK
#define CFG_CHARGE_CURRENT_FCC_SHIFT
#define CFG_CHARGE_CURRENT_PCC_MASK
#define CFG_CHARGE_CURRENT_PCC_SHIFT
#define CFG_CHARGE_CURRENT_TC_MASK
#define CFG_CURRENT_LIMIT
#define CFG_CURRENT_LIMIT_DC_MASK
#define CFG_CURRENT_LIMIT_DC_SHIFT
#define CFG_CURRENT_LIMIT_USB_MASK
#define CFG_FLOAT_VOLTAGE
#define CFG_FLOAT_VOLTAGE_FLOAT_MASK
#define CFG_FLOAT_VOLTAGE_THRESHOLD_MASK
#define CFG_FLOAT_VOLTAGE_THRESHOLD_SHIFT
#define CFG_STAT
#define CFG_STAT_DISABLED
#define CFG_STAT_ACTIVE_HIGH
#define CFG_PIN
#define CFG_PIN_EN_CTRL_MASK
#define CFG_PIN_EN_CTRL_ACTIVE_HIGH
#define CFG_PIN_EN_CTRL_ACTIVE_LOW
#define CFG_PIN_EN_APSD_IRQ
#define CFG_PIN_EN_CHARGER_ERROR
#define CFG_PIN_EN_CTRL
#define CFG_THERM
#define CFG_THERM_SOFT_HOT_COMPENSATION_MASK
#define CFG_THERM_SOFT_HOT_COMPENSATION_SHIFT
#define CFG_THERM_SOFT_COLD_COMPENSATION_MASK
#define CFG_THERM_SOFT_COLD_COMPENSATION_SHIFT
#define CFG_THERM_MONITOR_DISABLED
#define CFG_SYSOK
#define CFG_SYSOK_INOK_ACTIVE_HIGH
#define CFG_SYSOK_SUSPEND_HARD_LIMIT_DISABLED
#define CFG_OTHER
#define CFG_OTHER_RID_MASK
#define CFG_OTHER_RID_ENABLED_AUTO_OTG
#define CFG_OTG
#define CFG_OTG_TEMP_THRESHOLD_MASK
#define CFG_OTG_CURRENT_LIMIT_250mA
#define CFG_OTG_CURRENT_LIMIT_750mA
#define CFG_OTG_TEMP_THRESHOLD_SHIFT
#define CFG_OTG_CC_COMPENSATION_MASK
#define CFG_OTG_CC_COMPENSATION_SHIFT
#define CFG_TEMP_LIMIT
#define CFG_TEMP_LIMIT_SOFT_HOT_MASK
#define CFG_TEMP_LIMIT_SOFT_HOT_SHIFT
#define CFG_TEMP_LIMIT_SOFT_COLD_MASK
#define CFG_TEMP_LIMIT_SOFT_COLD_SHIFT
#define CFG_TEMP_LIMIT_HARD_HOT_MASK
#define CFG_TEMP_LIMIT_HARD_HOT_SHIFT
#define CFG_TEMP_LIMIT_HARD_COLD_MASK
#define CFG_TEMP_LIMIT_HARD_COLD_SHIFT
#define CFG_FAULT_IRQ
#define CFG_FAULT_IRQ_DCIN_UV
#define CFG_STATUS_IRQ
#define CFG_STATUS_IRQ_TERMINATION_OR_TAPER
#define CFG_STATUS_IRQ_CHARGE_TIMEOUT
#define CFG_ADDRESS

/* Command registers */
#define CMD_A
#define CMD_A_CHG_ENABLED
#define CMD_A_SUSPEND_ENABLED
#define CMD_A_OTG_ENABLED
#define CMD_A_ALLOW_WRITE
#define CMD_B
#define CMD_C

/* Interrupt Status registers */
#define IRQSTAT_A
#define IRQSTAT_C
#define IRQSTAT_C_TERMINATION_STAT
#define IRQSTAT_C_TERMINATION_IRQ
#define IRQSTAT_C_TAPER_IRQ
#define IRQSTAT_D
#define IRQSTAT_D_CHARGE_TIMEOUT_STAT
#define IRQSTAT_D_CHARGE_TIMEOUT_IRQ
#define IRQSTAT_E
#define IRQSTAT_E_USBIN_UV_STAT
#define IRQSTAT_E_USBIN_UV_IRQ
#define IRQSTAT_E_DCIN_UV_STAT
#define IRQSTAT_E_DCIN_UV_IRQ
#define IRQSTAT_F

/* Status registers */
#define STAT_A
#define STAT_A_FLOAT_VOLTAGE_MASK
#define STAT_B
#define STAT_C
#define STAT_C_CHG_ENABLED
#define STAT_C_HOLDOFF_STAT
#define STAT_C_CHG_MASK
#define STAT_C_CHG_SHIFT
#define STAT_C_CHG_TERM
#define STAT_C_CHARGER_ERROR
#define STAT_E

#define SMB347_MAX_REGISTER

/**
 * struct smb347_charger - smb347 charger instance
 * @dev: pointer to device
 * @regmap: pointer to driver regmap
 * @mains: power_supply instance for AC/DC power
 * @usb: power_supply instance for USB power
 * @usb_rdev: USB VBUS regulator device
 * @id: SMB charger ID
 * @mains_online: is AC/DC input connected
 * @usb_online: is USB input connected
 * @irq_unsupported: is interrupt unsupported by SMB hardware
 * @usb_vbus_enabled: is USB VBUS powered by SMB charger
 * @max_charge_current: maximum current (in uA) the battery can be charged
 * @max_charge_voltage: maximum voltage (in uV) the battery can be charged
 * @pre_charge_current: current (in uA) to use in pre-charging phase
 * @termination_current: current (in uA) used to determine when the
 *			 charging cycle terminates
 * @pre_to_fast_voltage: voltage (in uV) treshold used for transitioning to
 *			 pre-charge to fast charge mode
 * @mains_current_limit: maximum input current drawn from AC/DC input (in uA)
 * @usb_hc_current_limit: maximum input high current (in uA) drawn from USB
 *			  input
 * @chip_temp_threshold: die temperature where device starts limiting charge
 *			 current [%100 - %130] (in degree C)
 * @soft_cold_temp_limit: soft cold temperature limit [%0 - %15] (in degree C),
 *			  granularity is 5 deg C.
 * @soft_hot_temp_limit: soft hot temperature limit [%40 - %55] (in degree  C),
 *			 granularity is 5 deg C.
 * @hard_cold_temp_limit: hard cold temperature limit [%-5 - %10] (in degree C),
 *			  granularity is 5 deg C.
 * @hard_hot_temp_limit: hard hot temperature limit [%50 - %65] (in degree C),
 *			 granularity is 5 deg C.
 * @suspend_on_hard_temp_limit: suspend charging when hard limit is hit
 * @soft_temp_limit_compensation: compensation method when soft temperature
 *				  limit is hit
 * @charge_current_compensation: current (in uA) for charging compensation
 *				 current when temperature hits soft limits
 * @use_mains: AC/DC input can be used
 * @use_usb: USB input can be used
 * @use_usb_otg: USB OTG output can be used (not implemented yet)
 * @enable_control: how charging enable/disable is controlled
 *		    (driver/pin controls)
 * @inok_polarity: polarity of INOK signal which denotes presence of external
 *		   power supply
 *
 * @use_main, @use_usb, and @use_usb_otg are means to enable/disable
 * hardware support for these. This is useful when we want to have for
 * example OTG charging controlled via OTG transceiver driver and not by
 * the SMB347 hardware.
 *
 * Hard and soft temperature limit values are given as described in the
 * device data sheet and assuming NTC beta value is %3750. Even if this is
 * not the case, these values should be used. They can be mapped to the
 * corresponding NTC beta values with the help of table %2 in the data
 * sheet. So for example if NTC beta is %3375 and we want to program hard
 * hot limit to be %53 deg C, @hard_hot_temp_limit should be set to %50.
 *
 * If zero value is given in any of the current and voltage values, the
 * factory programmed default will be used. For soft/hard temperature
 * values, pass in %SMB3XX_TEMP_USE_DEFAULT instead.
 */
struct smb347_charger {};

enum smb_charger_chipid {};

/* Fast charge current in uA */
static const unsigned int fcc_tbl[NUM_CHIP_TYPES][8] =;
/* Pre-charge current in uA */
static const unsigned int pcc_tbl[NUM_CHIP_TYPES][4] =;

/* Termination current in uA */
static const unsigned int tc_tbl[NUM_CHIP_TYPES][8] =;

/* Input current limit in uA */
static const unsigned int icl_tbl[NUM_CHIP_TYPES][10] =;

/* Charge current compensation in uA */
static const unsigned int ccc_tbl[NUM_CHIP_TYPES][4] =;

/* Convert register value to current using lookup table */
static int hw_to_current(const unsigned int *tbl, size_t size, unsigned int val)
{}

/* Convert current to register value using lookup table */
static int current_to_hw(const unsigned int *tbl, size_t size, unsigned int val)
{}

/**
 * smb347_update_ps_status - refreshes the power source status
 * @smb: pointer to smb347 charger instance
 *
 * Function checks whether any power source is connected to the charger and
 * updates internal state accordingly. If there is a change to previous state
 * function returns %1, otherwise %0 and negative errno in case of errror.
 */
static int smb347_update_ps_status(struct smb347_charger *smb)
{}

/*
 * smb347_is_ps_online - returns whether input power source is connected
 * @smb: pointer to smb347 charger instance
 *
 * Returns %true if input power source is connected. Note that this is
 * dependent on what platform has configured for usable power sources. For
 * example if USB is disabled, this will return %false even if the USB cable
 * is connected.
 */
static bool smb347_is_ps_online(struct smb347_charger *smb)
{}

/**
 * smb347_charging_status - returns status of charging
 * @smb: pointer to smb347 charger instance
 *
 * Function returns charging status. %0 means no charging is in progress,
 * %1 means pre-charging, %2 fast-charging and %3 taper-charging.
 */
static int smb347_charging_status(struct smb347_charger *smb)
{}

static int smb347_charging_set(struct smb347_charger *smb, bool enable)
{}

static inline int smb347_charging_enable(struct smb347_charger *smb)
{}

static inline int smb347_charging_disable(struct smb347_charger *smb)
{}

static int smb347_start_stop_charging(struct smb347_charger *smb)
{}

static int smb347_set_charge_current(struct smb347_charger *smb)
{}

static int smb347_set_current_limits(struct smb347_charger *smb)
{}

static int smb347_set_voltage_limits(struct smb347_charger *smb)
{}

static int smb347_set_temp_limits(struct smb347_charger *smb)
{}

/*
 * smb347_set_writable - enables/disables writing to non-volatile registers
 * @smb: pointer to smb347 charger instance
 *
 * You can enable/disable writing to the non-volatile configuration
 * registers by calling this function.
 *
 * Returns %0 on success and negative errno in case of failure.
 */
static int smb347_set_writable(struct smb347_charger *smb, bool writable,
			       bool irq_toggle)
{}

static int smb347_hw_init(struct smb347_charger *smb)
{}

static irqreturn_t smb347_interrupt(int irq, void *data)
{}

static int smb347_irq_set(struct smb347_charger *smb, bool enable)
{}

static inline int smb347_irq_enable(struct smb347_charger *smb)
{}

static inline int smb347_irq_disable(struct smb347_charger *smb)
{}

static int smb347_irq_init(struct smb347_charger *smb,
			   struct i2c_client *client)
{}

/*
 * Returns the constant charge current programmed
 * into the charger in uA.
 */
static int get_const_charge_current(struct smb347_charger *smb)
{}

/*
 * Returns the constant charge voltage programmed
 * into the charger in uV.
 */
static int get_const_charge_voltage(struct smb347_charger *smb)
{}

static int smb347_get_charging_status(struct smb347_charger *smb,
				      struct power_supply *psy)
{}

static int smb347_get_property_locked(struct power_supply *psy,
				      enum power_supply_property prop,
				      union power_supply_propval *val)
{}

static int smb347_get_property(struct power_supply *psy,
			       enum power_supply_property prop,
			       union power_supply_propval *val)
{}

static enum power_supply_property smb347_properties[] =;

static bool smb347_volatile_reg(struct device *dev, unsigned int reg)
{}

static bool smb347_readable_reg(struct device *dev, unsigned int reg)
{}

static void smb347_dt_parse_dev_info(struct smb347_charger *smb)
{}

static int smb347_get_battery_info(struct smb347_charger *smb)
{}

static int smb347_usb_vbus_get_current_limit(struct regulator_dev *rdev)
{}

static int smb347_usb_vbus_set_new_current_limit(struct smb347_charger *smb,
						 int max_uA)
{}

static int smb347_usb_vbus_set_current_limit(struct regulator_dev *rdev,
					     int min_uA, int max_uA)
{}

static int smb347_usb_vbus_regulator_enable(struct regulator_dev *rdev)
{}

static int smb347_usb_vbus_regulator_disable(struct regulator_dev *rdev)
{}

static const struct regmap_config smb347_regmap =;

static const struct regulator_ops smb347_usb_vbus_regulator_ops =;

static const struct power_supply_desc smb347_mains_desc =;

static const struct power_supply_desc smb347_usb_desc =;

static const struct regulator_desc smb347_usb_vbus_regulator_desc =;

static int smb347_probe(struct i2c_client *client)
{}

static void smb347_remove(struct i2c_client *client)
{}

static void smb347_shutdown(struct i2c_client *client)
{}

static const struct i2c_device_id smb347_id[] =;
MODULE_DEVICE_TABLE(i2c, smb347_id);

static const struct of_device_id smb3xx_of_match[] =;
MODULE_DEVICE_TABLE(of, smb3xx_of_match);

static struct i2c_driver smb347_driver =;
module_i2c_driver();

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();