blob: 02009597782212340b691695ade8df78b8d8923c [file] [edit]
// SPDX-License-Identifier: GPL-2.0-only
/*
* google_bcl_votable.c Google bcl votable driver
*
* Copyright (c) 2023, Google LLC. All rights reserved.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <misc/gvotable.h>
#include "bcl.h"
#define BCL_WLC "BCL_WLC"
#define BCL_USB "BCL_USB"
enum {
WLC_ENABLED_TX,
WLC_DISABLED_TX,
};
enum {
USB_PLUGGED,
USB_UNPLUGGED,
};
static int google_bcl_wlc_votable_callback(struct gvotable_election *el,
const char *reason, void *value)
{
struct bcl_device *bcl_dev = gvotable_get_data(el);
int ret;
u8 wlc_tx_enable = (long)value ? WLC_ENABLED_TX : WLC_DISABLED_TX;
if (!smp_load_acquire(&bcl_dev->enabled))
return -EINVAL;
if (bcl_dev->ifpmic == MAX77779) {
ret = max77779_adjust_batoilo_lvl(bcl_dev, wlc_tx_enable,
bcl_dev->batt_irq_conf1.batoilo_wlc_trig_lvl,
bcl_dev->batt_irq_conf2.batoilo_wlc_trig_lvl);
if (ret < 0) {
dev_err(bcl_dev->device, "BATOILO cannot be adjusted\n");
return ret;
}
}
/* b/335695535 outlines max77759 configuration */
return 0;
}
static int google_bcl_usb_votable_callback(struct gvotable_election *el,
const char *reason, void *value)
{
int ret = 0;
struct bcl_device *bcl_dev = gvotable_get_data(el);
u8 usb_enable = (long)value ? USB_PLUGGED: USB_UNPLUGGED;
if (!smp_load_acquire(&bcl_dev->enabled))
return -EINVAL;
if (bcl_dev->ifpmic == MAX77779) {
ret = max77779_adjust_batoilo_lvl(bcl_dev, usb_enable,
bcl_dev->batt_irq_conf1.batoilo_usb_trig_lvl,
bcl_dev->batt_irq_conf2.batoilo_usb_trig_lvl);
if (ret < 0)
dev_err(bcl_dev->device, "USB: BATOILO cannot be adjusted\n");
}
/* b/335695535 outlines max77759 configuration */
return ret;
}
int google_bcl_setup_votable(struct bcl_device *bcl_dev)
{
int ret;
bcl_dev->toggle_wlc = gvotable_create_bool_election(NULL, google_bcl_wlc_votable_callback,
bcl_dev);
if (IS_ERR_OR_NULL(bcl_dev->toggle_wlc)) {
ret = PTR_ERR(bcl_dev->toggle_wlc);
dev_err(bcl_dev->device, "no toggle_wlc votable (%d)\n", ret);
return ret;
}
gvotable_set_vote2str(bcl_dev->toggle_wlc, gvotable_v2s_int);
gvotable_election_set_name(bcl_dev->toggle_wlc, BCL_WLC);
bcl_dev->toggle_usb = gvotable_create_bool_election(NULL, google_bcl_usb_votable_callback,
bcl_dev);
if (IS_ERR_OR_NULL(bcl_dev->toggle_usb)) {
ret = PTR_ERR(bcl_dev->toggle_usb);
gvotable_destroy_election(bcl_dev->toggle_wlc);
dev_err(bcl_dev->device, "no toggle_usb votable (%d)\n", ret);
return ret;
}
gvotable_set_vote2str(bcl_dev->toggle_usb, gvotable_v2s_int);
gvotable_election_set_name(bcl_dev->toggle_usb, BCL_USB);
return 0;
}
void google_bcl_remove_votable(struct bcl_device *bcl_dev)
{
if (!IS_ERR_OR_NULL(bcl_dev->toggle_wlc))
gvotable_destroy_election(bcl_dev->toggle_wlc);
if (!IS_ERR_OR_NULL(bcl_dev->toggle_usb))
gvotable_destroy_election(bcl_dev->toggle_usb);
}