From ee0a4e960609867a0db049fee48fa6eec0234bb8 Mon Sep 17 00:00:00 2001 From: lbh Date: Tue, 11 Oct 2022 15:38:43 +0800 Subject: [PATCH] pnangn:2nd main charger add led driver code pnangn: chg led support for 2nd charger 2nd main charger add led kernel driver code Change-Id: I5b23f30662b98d2f112554b68ce90b2d4dbee790 Reviewed-on: https://gerrit.mot.com/2401202 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Jing Hu Reviewed-by: Xiangpo Zhao Submit-Approved: Jira Key --- drivers/power/bq2589x_chg_mmi/Android.mk | 4 + drivers/power/bq2589x_chg_mmi/Kbuild | 4 + .../power/bq2589x_chg_mmi/bq2589x_charger.c | 217 +++++++++++++++++- drivers/power/bq2589x_chg_mmi/bq2589x_reg.h | 13 ++ drivers/power/sgm4154x_chg_mmi/Android.mk | 4 +- drivers/power/sgm4154x_chg_mmi/Kbuild | 4 +- .../power/sgm4154x_chg_mmi/sgm4154x_charger.h | 2 +- 7 files changed, 242 insertions(+), 6 deletions(-) diff --git a/drivers/power/bq2589x_chg_mmi/Android.mk b/drivers/power/bq2589x_chg_mmi/Android.mk index 7173c89798ca..0861a1687f32 100644 --- a/drivers/power/bq2589x_chg_mmi/Android.mk +++ b/drivers/power/bq2589x_chg_mmi/Android.mk @@ -13,6 +13,10 @@ ifeq ($(MMI_QC3P_WT6670_DETECTED),true) KERNEL_CFLAGS += CONFIG_MMI_QC3P_WT6670_DETECTED=y endif +ifeq ($(MMI_EXT_CHG_LED),true) + KERNEL_CFLAGS += CONFIG_MMI_EXT_CHG_LED=y +endif + LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) LOCAL_ADDITIONAL_DEPENDENCIES := $(KERNEL_MODULES_OUT)/mmi_discrete_charger_class.ko diff --git a/drivers/power/bq2589x_chg_mmi/Kbuild b/drivers/power/bq2589x_chg_mmi/Kbuild index a82c06f61d9d..d40823873eee 100644 --- a/drivers/power/bq2589x_chg_mmi/Kbuild +++ b/drivers/power/bq2589x_chg_mmi/Kbuild @@ -13,4 +13,8 @@ ifneq ($(filter m y,$(CONFIG_MMI_QC3P_WT6670_DETECTED)),) EXTRA_CFLAGS += -DCONFIG_MMI_QC3P_WT6670_DETECTED endif +ifneq ($(filter m y,$(CONFIG_MMI_EXT_CHG_LED)),) + EXTRA_CFLAGS += -DCONFIG_MMI_EXT_CHG_LED +endif + KBUILD_EXTRA_SYMBOLS += $(CURDIR)/$(KBUILD_EXTMOD)/../mmi_discrete_charger/$(GKI_OBJ_MODULE_DIR)/Module.symvers diff --git a/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c b/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c index 5fcd37f3492b..9b21905cd06f 100644 --- a/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c +++ b/drivers/power/bq2589x_chg_mmi/bq2589x_charger.c @@ -34,6 +34,52 @@ #include #include "bq2589x_reg.h" +#ifdef __indicator_led_en__ +static struct bq2589x *bq_g; +#define TRILED_NUM_MAX 3 + +struct pwm_setting { + u64 pre_period_ns; + u64 period_ns; + u64 duty_ns; +}; + +struct led_setting { + u64 on_ms; + u64 off_ms; + enum led_brightness brightness; + bool blink; + bool breath; +}; + +struct qpnp_led_dev { + struct led_classdev cdev; + struct pwm_device *pwm_dev; + struct pwm_setting pwm_setting; + struct led_setting led_setting; + struct indicator_led_chip *chip; + struct mutex lock; + const char *label; + const char *default_trigger; + u8 id; + bool blinking; + bool breathing; +}; + +struct indicator_led_chip { + struct device *dev; + struct qpnp_led_dev *leds; + struct nvmem_device *pbs_nvmem; + struct mutex bus_lock; + int num_leds; + u16 reg_base; + u8 subtype; + u8 bitmap; + struct pinctrl *pinctrl; + struct pinctrl_state *pin_sta_default; +}; +#endif + #define BQ2589x_MANUFACTURER "Texas Instruments" #define BQ25890_IRQ_PIN "bq2589x_irq" #define BQ2589X_STATUS_PLUGIN 0x0001 @@ -2948,6 +2994,167 @@ static struct charger_ops bq2589x_chg_ops = { .rerun_aicl = mmi_rerun_aicl, }; +#ifdef __indicator_led_en__ +static int indicator_led_set_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct qpnp_led_dev *led = + container_of(led_cdev, struct qpnp_led_dev, cdev); + int rc = 0; + + mutex_lock(&led->lock); + if (brightness > LED_FULL) + brightness = LED_FULL; + + if (brightness == led->led_setting.brightness && + !led->blinking && !led->breathing) { + mutex_unlock(&led->lock); + return 0; + } + + led->led_setting.brightness = brightness; + if (!!brightness) + bq2589x_update_bits(bq_g, BQ2589X_REG_07, BQ2589X_EN_LED_MASK, BQ2589X_LED_ENABLE<led_setting.blink = false; + led->led_setting.breath = false; + + mutex_unlock(&led->lock); + + return rc; +} + +static enum led_brightness indicator_led_get_brightness( + struct led_classdev *led_cdev) +{ + return led_cdev->brightness; +} + +static int indicator_led_set_blink(struct led_classdev *led_cdev, + unsigned long *on_ms, unsigned long *off_ms) +{ + int rc = 0; + return rc; +} + +static int indicator_led_register(struct indicator_led_chip *chip) +{ + struct qpnp_led_dev *led; + int rc, i, j; + + + for (i = 0; i < chip->num_leds; i++) { + led = &chip->leds[i]; + mutex_init(&led->lock); + led->cdev.name = led->label; + led->cdev.max_brightness = LED_FULL; + led->cdev.brightness_set_blocking = indicator_led_set_brightness; + led->cdev.brightness_get = indicator_led_get_brightness; + led->cdev.blink_set = indicator_led_set_blink; + led->cdev.default_trigger = led->default_trigger; + led->cdev.brightness = LED_OFF; + + rc = devm_led_classdev_register(chip->dev, &led->cdev); + if (rc < 0) { + dev_err(chip->dev, "%s led class device registering failed, rc=%d\n", + led->label, rc); + goto err_out; + } + } + + return 0; + +err_out: + for (j = 0; j <= i; j++) { + mutex_destroy(&chip->leds[j].lock); + } + return rc; +} + +static int indicator_led_parse_dt(struct indicator_led_chip *chip) +{ + struct device_node *node = chip->dev->of_node, *child_node; + struct qpnp_led_dev *led; + int rc = 0, id, i = 0; + + chip->num_leds = of_get_available_child_count(node); + if (chip->num_leds == 0) { + dev_err(chip->dev, "No led child node defined\n"); + return -ENODEV; + } + + if (chip->num_leds > TRILED_NUM_MAX) { + dev_err(chip->dev, "can't support %d leds(max %d)\n", + chip->num_leds, TRILED_NUM_MAX); + return -EINVAL; + } + + chip->leds = devm_kcalloc(chip->dev, chip->num_leds, + sizeof(struct qpnp_led_dev), GFP_KERNEL); + if (!chip->leds) + return -ENOMEM; + + for_each_available_child_of_node(node, child_node) { + rc = of_property_read_u32(child_node, "led-sources", &id); + if (rc) { + dev_err(chip->dev, "Get led-sources failed, rc=%d\n", + rc); + return rc; + } + + if (id >= TRILED_NUM_MAX) { + dev_err(chip->dev, "only support 0~%d current source\n", + TRILED_NUM_MAX - 1); + return -EINVAL; + } + + led = &chip->leds[i++]; + led->chip = chip; + led->id = id; + led->label = + of_get_property(child_node, "label", NULL) ? : + child_node->name; + led->default_trigger = of_get_property(child_node, + "linux,default-trigger", NULL); + } + + return rc; +} + +static int indicator_led_probe(struct i2c_client *client) +{ + struct indicator_led_chip *chip; + int rc = 0; + + chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->dev = &client->dev; + + rc = indicator_led_parse_dt(chip); + if (rc < 0) { + if (rc != -EPROBE_DEFER) + dev_err(chip->dev, "Devicetree properties parsing failed, rc=%d\n", + rc); + return rc; + } + rc = indicator_led_register(chip); + if (rc < 0) { + dev_err(chip->dev, "Registering LED class devices failed, rc=%d\n", + rc); + goto destroy; + } + + dev_err(chip->dev, "%s has been finished\n", __func__); + return 0; +destroy: + return rc; +} +#endif + static int bq2589x_charger_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -2960,7 +3167,9 @@ static int bq2589x_charger_probe(struct i2c_client *client, dev_err(dev, "%s: out of memory\n", __func__); return -ENOMEM; } - +#ifdef __indicator_led_en__ + bq_g = bq; +#endif bq->dev = dev; bq->client = client; i2c_set_clientdata(client, bq); @@ -3077,6 +3286,12 @@ static int bq2589x_charger_probe(struct i2c_client *client, if (bq2589x_is_factory_mode()) bq->factory_mode = true; + +#ifdef __indicator_led_en__ + bq2589x_update_bits(bq, BQ2589X_REG_07, BQ2589X_EN_LED_MASK, BQ2589X_LED_DISABLE< +#include +#endif /* Register 00h */ #define BQ2589X_REG_00 0x00 @@ -146,6 +154,11 @@ #define BQ2589X_TERM_ENABLE 1 #define BQ2589X_TERM_DISABLE 0 +#define BQ2589X_EN_LED_MASK 0x40 +#define BQ2589X_EN_LED_SHIFT 6 +#define BQ2589X_LED_ENABLE 0 +#define BQ2589X_LED_DISABLE 1 + #define BQ2589X_WDT_MASK 0x30 #define BQ2589X_WDT_SHIFT 4 #define BQ2589X_WDT_DISABLE 0 diff --git a/drivers/power/sgm4154x_chg_mmi/Android.mk b/drivers/power/sgm4154x_chg_mmi/Android.mk index 24b762a536e5..86d613c304a4 100644 --- a/drivers/power/sgm4154x_chg_mmi/Android.mk +++ b/drivers/power/sgm4154x_chg_mmi/Android.mk @@ -21,8 +21,8 @@ ifeq ($(MMI_QC3P_Z350_DETECTED),true) KERNEL_CFLAGS += CONFIG_MMI_QC3P_Z350_DETECTED=y endif -ifeq ($(MMI_SGM4154X_CHG_LED),true) - KERNEL_CFLAGS += CONFIG_MMI_SGM4154X_CHG_LED=y +ifeq ($(MMI_EXT_CHG_LED),true) + KERNEL_CFLAGS += CONFIG_MMI_EXT_CHG_LED=y endif LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) diff --git a/drivers/power/sgm4154x_chg_mmi/Kbuild b/drivers/power/sgm4154x_chg_mmi/Kbuild index ef41a4ad2507..b050e07ac04b 100644 --- a/drivers/power/sgm4154x_chg_mmi/Kbuild +++ b/drivers/power/sgm4154x_chg_mmi/Kbuild @@ -19,8 +19,8 @@ ifneq ($(filter m y,$(CONFIG_MMI_QC3P_Z350_DETECTED)),) EXTRA_CFLAGS += -DCONFIG_MMI_QC3P_Z350_DETECTED endif -ifneq ($(filter m y,$(CONFIG_MMI_SGM4154X_CHG_LED)),) - EXTRA_CFLAGS += -DCONFIG_MMI_SGM4154X_CHG_LED +ifneq ($(filter m y,$(CONFIG_MMI_EXT_CHG_LED)),) + EXTRA_CFLAGS += -DCONFIG_MMI_EXT_CHG_LED endif obj-m += sgm4154x_charger.o diff --git a/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h b/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h index 073ff79623ef..996cc845f62e 100644 --- a/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h +++ b/drivers/power/sgm4154x_chg_mmi/sgm4154x_charger.h @@ -8,7 +8,7 @@ #include #include #include -#ifdef CONFIG_MMI_SGM4154X_CHG_LED +#ifdef CONFIG_MMI_EXT_CHG_LED #define __indicator_led_en__ #endif