drivers/power/supply/rt9471.c

Source file repositories/reference/linux-study-clean/drivers/power/supply/rt9471.c

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/rt9471.c
Extension
.c
Size
25849 bytes
Lines
940
Domain
Driver Families
Bucket
drivers/power
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rt9471_chip {
	struct device *dev;
	struct regmap *regmap;
	struct regmap_field *rm_fields[F_MAX_FIELDS];
	struct regmap_irq_chip_data *irq_chip_data;
	struct regulator_dev *otg_rdev;
	struct power_supply *psy;
	struct power_supply_desc psy_desc;
	struct mutex var_lock;
	enum power_supply_usb_type psy_usb_type;
	int psy_usb_curr;
};

static const struct reg_field rt9471_reg_fields[F_MAX_FIELDS] = {
	[F_WDT]		= REG_FIELD(RT9471_REG_TOP, 0, 1),
	[F_WDT_RST]	= REG_FIELD(RT9471_REG_TOP, 2, 2),
	[F_CHG_EN]	= REG_FIELD(RT9471_REG_FUNC, 0, 0),
	[F_HZ]		= REG_FIELD(RT9471_REG_FUNC, 5, 5),
	[F_BATFET_DIS]	= REG_FIELD(RT9471_REG_FUNC, 7, 7),
	[F_AICR]	= REG_FIELD(RT9471_REG_IBUS, 0, 5),
	[F_AICC_EN]	= REG_FIELD(RT9471_REG_IBUS, 7, 7),
	[F_MIVR]	= REG_FIELD(RT9471_REG_VBUS, 0, 3),
	[F_IPRE_CHG]	= REG_FIELD(RT9471_REG_PRECHG, 0, 3),
	[F_VPRE_CHG]	= REG_FIELD(RT9471_REG_PRECHG, 4, 6),
	[F_VBAT_REG]	= REG_FIELD(RT9471_REG_VCHG, 0, 6),
	[F_ICHG_REG]	= REG_FIELD(RT9471_REG_ICHG, 0, 5),
	[F_EOC_RST]	= REG_FIELD(RT9471_REG_EOC, 0, 0),
	[F_TE]		= REG_FIELD(RT9471_REG_EOC, 1, 1),
	[F_IEOC_CHG]	= REG_FIELD(RT9471_REG_EOC, 4, 7),
	[F_DEVICE_ID]	= REG_FIELD(RT9471_REG_INFO, 3, 6),
	[F_REG_RST]	= REG_FIELD(RT9471_REG_INFO, 7, 7),
	[F_BC12_EN]	= REG_FIELD(RT9471_REG_DPDMDET, 7, 7),
	[F_IC_STAT]	= REG_FIELD(RT9471_REG_ICSTAT, 0, 3),
	[F_PORT_STAT]	= REG_FIELD(RT9471_REG_ICSTAT, 4, 7),
	[F_ST_CHG_DONE]	= REG_FIELD(RT9471_REG_STAT0, 3, 3),
	[F_ST_CHG_RDY]	= REG_FIELD(RT9471_REG_STAT0, 6, 6),
	[F_ST_VBUS_GD]	= REG_FIELD(RT9471_REG_STAT0, 7, 7),
};

static const struct linear_range rt9471_chg_ranges[RT9471_MAX_RANGES] = {
	[RT9471_RANGE_AICR] = LINEAR_RANGE(50000,	1, 63, 50000),
	[RT9471_RANGE_MIVR] = LINEAR_RANGE(3900000,	0, 15, 100000),
	[RT9471_RANGE_IPRE] = LINEAR_RANGE(50000,	0, 15, 50000),
	[RT9471_RANGE_VCHG] = LINEAR_RANGE(3900000,	0, 80, 10000),
	[RT9471_RANGE_ICHG] = LINEAR_RANGE(0,		0, 63, 50000),
	[RT9471_RANGE_IEOC] = LINEAR_RANGE(50000,	0, 15, 50000),
};

static int rt9471_set_value_by_field_range(struct rt9471_chip *chip,
					   enum rt9471_fields field,
					   enum rt9471_ranges range, int val)
{
	unsigned int sel;

	if (val < 0)
		return -EINVAL;

	linear_range_get_selector_within(rt9471_chg_ranges + range, val, &sel);

	return regmap_field_write(chip->rm_fields[field], sel);
}


static int rt9471_get_value_by_field_range(struct rt9471_chip *chip,
					   enum rt9471_fields field,
					   enum rt9471_ranges range, int *val)
{
	unsigned int sel, rvalue;
	int ret;

	ret = regmap_field_read(chip->rm_fields[field], &sel);
	if (ret)
		return ret;

	ret = linear_range_get_value(rt9471_chg_ranges + range, sel, &rvalue);
	if (ret)
		return ret;

	*val = rvalue;
	return 0;
}

static int rt9471_set_ieoc(struct rt9471_chip *chip, int microamp)
{
	int ret;

	if (microamp == 0)
		return regmap_field_write(chip->rm_fields[F_TE], 0);

	ret = rt9471_set_value_by_field_range(chip, F_IEOC_CHG, RT9471_RANGE_IEOC, microamp);

Annotation

Implementation Notes