drivers/power/supply/rt9455_charger.c

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

File Facts

System
Linux kernel
Corpus path
drivers/power/supply/rt9455_charger.c
Extension
.c
Size
49239 bytes
Lines
1756
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 rt9455_info {
	struct i2c_client		*client;
	struct regmap			*regmap;
	struct regmap_field		*regmap_fields[F_MAX_FIELDS];
	struct power_supply		*charger;
#if IS_ENABLED(CONFIG_USB_PHY)
	struct usb_phy			*usb_phy;
	struct notifier_block		nb;
#endif
	struct delayed_work		pwr_rdy_work;
	struct delayed_work		max_charging_time_work;
	struct delayed_work		batt_presence_work;
	u32				voreg;
	u32				boost_voltage;
};

/*
 * Iterate through each element of the 'tbl' array until an element whose value
 * is greater than v is found. Return the index of the respective element,
 * or the index of the last element in the array, if no such element is found.
 */
static unsigned int rt9455_find_idx(const int tbl[], int tbl_size, int v)
{
	int i;

	/*
	 * No need to iterate until the last index in the table because
	 * if no element greater than v is found in the table,
	 * or if only the last element is greater than v,
	 * function returns the index of the last element.
	 */
	for (i = 0; i < tbl_size - 1; i++)
		if (v <= tbl[i])
			return i;

	return (tbl_size - 1);
}

static int rt9455_get_field_val(struct rt9455_info *info,
				enum rt9455_fields field,
				const int tbl[], int tbl_size, int *val)
{
	unsigned int v;
	int ret;

	ret = regmap_field_read(info->regmap_fields[field], &v);
	if (ret)
		return ret;

	v = (v >= tbl_size) ? (tbl_size - 1) : v;
	*val = tbl[v];

	return 0;
}

static int rt9455_set_field_val(struct rt9455_info *info,
				enum rt9455_fields field,
				const int tbl[], int tbl_size, int val)
{
	unsigned int idx = rt9455_find_idx(tbl, tbl_size, val);

	return regmap_field_write(info->regmap_fields[field], idx);
}

static int rt9455_register_reset(struct rt9455_info *info)
{
	struct device *dev = &info->client->dev;
	unsigned int v;
	int ret, limit = 100;

	ret = regmap_field_write(info->regmap_fields[F_RST], 0x01);
	if (ret) {
		dev_err(dev, "Failed to set RST bit\n");
		return ret;
	}

	/*
	 * To make sure that reset operation has finished, loop until RST bit
	 * is set to 0.
	 */
	do {
		ret = regmap_field_read(info->regmap_fields[F_RST], &v);
		if (ret) {
			dev_err(dev, "Failed to read RST bit\n");
			return ret;
		}

		if (!v)
			break;

Annotation

Implementation Notes