Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f24711c authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

power: supply: qti_battery_charger: add SSR support



Add subsystem restart (SSR) support to battery charger driver so
that it can stop read/write properties when subsystem goes down.
Also, send message to enable notification again once subsystem
comes up.

Change-Id: I64f3abfa1d12c4e6a65fd01d7f66155c8741e68a
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 29651506
Loading
Loading
Loading
Loading
+50 −9
Original line number Diff line number Diff line
@@ -148,6 +148,8 @@ struct battery_chg_dev {
	u32				*thermal_levels;
	int				curr_thermal_level;
	int				num_thermal_levels;
	atomic_t			state;
	struct work_struct		subsys_up_work;
};

static const int battery_prop_map[BATT_PROP_MAX] = {
@@ -198,6 +200,16 @@ static int battery_chg_write(struct battery_chg_dev *bcdev, void *data,
{
	int rc;

	/*
	 * When the subsystem goes down, it's better to return the last
	 * known values until it comes back up. Hence, return 0 so that
	 * pmic_glink_write() is not attempted until pmic glink is up.
	 */
	if (atomic_read(&bcdev->state) == PMIC_GLINK_STATE_DOWN) {
		pr_debug("glink state is down\n");
		return 0;
	}

	mutex_lock(&bcdev->rw_lock);
	reinit_completion(&bcdev->ack);
	rc = pmic_glink_write(bcdev->client, data, len);
@@ -268,6 +280,40 @@ static int get_property_id(struct psy_state *pst,
	return -ENOENT;
}

static void battery_chg_notify_enable(struct battery_chg_dev *bcdev)
{
	struct battery_charger_set_notify_msg req_msg = { { 0 } };
	int rc;

	/* Send request to enable notification */
	req_msg.hdr.owner = MSG_OWNER_BC;
	req_msg.hdr.type = MSG_TYPE_NOTIFY;
	req_msg.hdr.opcode = BC_SET_NOTIFY_REQ;

	rc = battery_chg_write(bcdev, &req_msg, sizeof(req_msg));
	if (rc < 0)
		pr_err("Failed to enable notification rc=%d\n", rc);
}

static void battery_chg_subsys_up_work(struct work_struct *work)
{
	struct battery_chg_dev *bcdev = container_of(work,
					struct battery_chg_dev, subsys_up_work);

	battery_chg_notify_enable(bcdev);
}

static void battery_chg_state_cb(void *priv, enum pmic_glink_state state)
{
	struct battery_chg_dev *bcdev = priv;

	pr_debug("state: %d\n", state);

	atomic_set(&bcdev->state, state);
	if (state == PMIC_GLINK_STATE_UP)
		schedule_work(&bcdev->subsys_up_work);
}

/**
 * qti_battery_charger_get_prop() - Gets the property being requested
 *
@@ -977,7 +1023,6 @@ static int battery_chg_probe(struct platform_device *pdev)
	struct battery_chg_dev *bcdev;
	struct device *dev = &pdev->dev;
	struct pmic_glink_client_data client_data = { };
	struct battery_charger_set_notify_msg req_msg = { { 0 } };
	int rc, i;

	bcdev = devm_kzalloc(&pdev->dev, sizeof(*bcdev), GFP_KERNEL);
@@ -1012,12 +1057,15 @@ static int battery_chg_probe(struct platform_device *pdev)

	mutex_init(&bcdev->rw_lock);
	init_completion(&bcdev->ack);
	INIT_WORK(&bcdev->subsys_up_work, battery_chg_subsys_up_work);
	atomic_set(&bcdev->state, PMIC_GLINK_STATE_UP);
	bcdev->dev = dev;

	client_data.id = MSG_OWNER_BC;
	client_data.name = "battery_charger";
	client_data.msg_cb = battery_chg_callback;
	client_data.priv = bcdev;
	client_data.state_cb = battery_chg_state_cb;

	bcdev->client = pmic_glink_register_client(dev, &client_data);
	if (IS_ERR(bcdev->client)) {
@@ -1045,14 +1093,7 @@ static int battery_chg_probe(struct platform_device *pdev)
		goto error;
	}

	/* Send request to enable notification */
	req_msg.hdr.owner = MSG_OWNER_BC;
	req_msg.hdr.type = MSG_TYPE_NOTIFY;
	req_msg.hdr.opcode = BC_SET_NOTIFY_REQ;

	rc = battery_chg_write(bcdev, &req_msg, sizeof(req_msg));
	if (rc < 0)
		pr_err("Failed to enable notification rc=%d\n", rc);
	battery_chg_notify_enable(bcdev);

	return 0;
error: