/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2021 MediaTek Inc. */ #include #include #include #include #include #include #include static struct class *charger_class; static ssize_t charger_show_name(struct device *dev, struct device_attribute *attr, char *buf) { struct charger_device *chg_dev = to_charger_device(dev); return snprintf(buf, 20, "%s\n", chg_dev->props.alias_name ? chg_dev->props.alias_name : "anonymous"); } /* static int charger_suspend(struct device *dev, pm_message_t state) { struct charger_device *chg_dev = to_charger_device(dev); if (chg_dev->ops->suspend) return chg_dev->ops->suspend(chg_dev, state); return 0; } static int charger_resume(struct device *dev) { struct charger_device *chg_dev = to_charger_device(dev); if (chg_dev->ops->resume) return chg_dev->ops->resume(chg_dev); return 0; } */ static void charger_device_release(struct device *dev) { struct charger_device *chg_dev = to_charger_device(dev); kfree(chg_dev); } int charger_dev_enable(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable) return chg_dev->ops->enable(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable); int charger_dev_is_enabled(struct charger_device *chg_dev, bool *en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->is_enabled) return chg_dev->ops->is_enabled(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_is_enabled); int charger_dev_plug_in(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->plug_in) return chg_dev->ops->plug_in(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_plug_in); int charger_dev_plug_out(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->plug_out) return chg_dev->ops->plug_out(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_plug_out); int charger_dev_do_event(struct charger_device *chg_dev, u32 event, u32 args) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->event) return chg_dev->ops->event(chg_dev, event, args); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_do_event); int charger_dev_set_charging_current(struct charger_device *chg_dev, u32 uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_charging_current) return chg_dev->ops->set_charging_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_charging_current); int charger_dev_get_charging_current(struct charger_device *chg_dev, u32 *uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_charging_current) return chg_dev->ops->get_charging_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_charging_current); int charger_dev_get_min_charging_current(struct charger_device *chg_dev, u32 *uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_min_charging_current) return chg_dev->ops->get_min_charging_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_min_charging_current); int charger_dev_enable_chip(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_chip) return chg_dev->ops->enable_chip(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_chip); int charger_dev_is_chip_enabled(struct charger_device *chg_dev, bool *en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->is_chip_enabled) return chg_dev->ops->is_chip_enabled(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_is_chip_enabled); int charger_dev_enable_direct_charging(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_direct_charging) return chg_dev->ops->enable_direct_charging(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_direct_charging); int charger_dev_kick_direct_charging_wdt(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->kick_direct_charging_wdt) return chg_dev->ops->kick_direct_charging_wdt(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_kick_direct_charging_wdt); int charger_dev_get_vbus(struct charger_device *chg_dev, u32 *vbus) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_vbus_adc) return chg_dev->ops->get_vbus_adc(chg_dev, vbus); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_vbus); #if defined(CONFIG_USB_FACTORY_MODE) int charger_dev_get_vsys(struct charger_device *chg_dev, u32 *vsys) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_vsys_adc) return chg_dev->ops->get_vsys_adc(chg_dev, vsys); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_vsys); #endif int charger_dev_get_ibus(struct charger_device *chg_dev, u32 *ibus) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_ibus_adc) return chg_dev->ops->get_ibus_adc(chg_dev, ibus); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_ibus); int charger_dev_get_ibat(struct charger_device *chg_dev, u32 *ibat) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_ibat_adc) return chg_dev->ops->get_ibat_adc(chg_dev, ibat); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_ibat); int charger_dev_get_temperature(struct charger_device *chg_dev, int *tchg_min, int *tchg_max) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_tchg_adc) return chg_dev->ops->get_tchg_adc(chg_dev, tchg_min, tchg_max); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_temperature); int charger_dev_set_input_current(struct charger_device *chg_dev, u32 uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_input_current) return chg_dev->ops->set_input_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_input_current); int charger_dev_get_input_current(struct charger_device *chg_dev, u32 *uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_input_current) return chg_dev->ops->get_input_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_input_current); int charger_dev_get_min_input_current(struct charger_device *chg_dev, u32 *uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_min_input_current) return chg_dev->ops->get_min_input_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_min_input_current); int charger_dev_set_eoc_current(struct charger_device *chg_dev, u32 uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_eoc_current) chg_dev->ops->set_eoc_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_eoc_current); int charger_dev_get_eoc_current(struct charger_device *chg_dev, u32 *uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_eoc_current) return chg_dev->ops->get_eoc_current(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_eoc_current); int charger_dev_kick_wdt(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->kick_wdt) return chg_dev->ops->kick_wdt(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_kick_wdt); int charger_dev_set_constant_voltage(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_constant_voltage) return chg_dev->ops->set_constant_voltage(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_constant_voltage); int charger_dev_get_constant_voltage(struct charger_device *chg_dev, u32 *uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_constant_voltage) return chg_dev->ops->get_constant_voltage(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_constant_voltage); int charger_dev_dump_registers(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->dump_registers) return chg_dev->ops->dump_registers(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_dump_registers); int charger_dev_is_charging_done(struct charger_device *chg_dev, bool *done) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->is_charging_done) return chg_dev->ops->is_charging_done(chg_dev, done); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_is_charging_done); int charger_dev_enable_vbus_ovp(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_vbus_ovp) return chg_dev->ops->enable_vbus_ovp(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_vbus_ovp); int charger_dev_set_mivr(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_mivr) return chg_dev->ops->set_mivr(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_mivr); int charger_dev_get_mivr(struct charger_device *chg_dev, u32 *uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_mivr) return chg_dev->ops->get_mivr(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_mivr); int charger_dev_enable_powerpath(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_powerpath) return chg_dev->ops->enable_powerpath(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_powerpath); int charger_dev_is_powerpath_enabled(struct charger_device *chg_dev, bool *en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->is_powerpath_enabled) return chg_dev->ops->is_powerpath_enabled(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_is_powerpath_enabled); int charger_dev_enable_safety_timer(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_safety_timer) return chg_dev->ops->enable_safety_timer(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_safety_timer); int charger_dev_enable_hz(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_hz) return chg_dev->ops->enable_hz(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_hz); #if defined(CONFIG_USB_FACTORY_MODE) int charger_dev_enable_aicc(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_aicc) return chg_dev->ops->enable_aicc(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_aicc); int charger_dev_en_wdt(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->en_wdt) return chg_dev->ops->en_wdt(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_en_wdt); int charger_dev_set_iinlmtsel(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_iinlmtsel) return chg_dev->ops->set_iinlmtsel(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_iinlmtsel); int charger_dev_en_ilim(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->en_ilim) return chg_dev->ops->en_ilim(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_en_ilim); #endif int charger_dev_get_adc(struct charger_device *charger_dev, enum adc_channel chan, int *min, int *max) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->get_adc) return charger_dev->ops->get_adc(charger_dev, chan, min, max); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_adc); int charger_dev_get_adc_accuracy(struct charger_device *charger_dev, enum adc_channel chan, int *min, int *max) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->get_adc_accuracy) return charger_dev->ops->get_adc_accuracy(charger_dev, chan, min, max); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_adc_accuracy); int charger_dev_is_safety_timer_enabled(struct charger_device *chg_dev, bool *en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->is_safety_timer_enabled) return chg_dev->ops->is_safety_timer_enabled(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_is_safety_timer_enabled); int charger_dev_enable_termination(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_termination) return chg_dev->ops->enable_termination(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_termination); int charger_dev_get_mivr_state(struct charger_device *chg_dev, bool *in_loop) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_mivr_state) return chg_dev->ops->get_mivr_state(chg_dev, in_loop); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_mivr_state); int charger_dev_send_ta_current_pattern(struct charger_device *chg_dev, bool is_increase) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->send_ta_current_pattern) return chg_dev->ops->send_ta_current_pattern(chg_dev, is_increase); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_send_ta_current_pattern); int charger_dev_send_ta20_current_pattern(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->send_ta20_current_pattern) return chg_dev->ops->send_ta20_current_pattern(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_send_ta20_current_pattern); int charger_dev_reset_ta(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->reset_ta) return chg_dev->ops->reset_ta(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_reset_ta); int charger_dev_set_pe20_efficiency_table(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_pe20_efficiency_table) return chg_dev->ops->set_pe20_efficiency_table(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_pe20_efficiency_table); int charger_dev_enable_cable_drop_comp(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_cable_drop_comp) return chg_dev->ops->enable_cable_drop_comp(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_cable_drop_comp); int charger_dev_set_direct_charging_ibusoc(struct charger_device *chg_dev, u32 uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_direct_charging_ibusoc) return chg_dev->ops->set_direct_charging_ibusoc(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_direct_charging_ibusoc); int charger_dev_set_direct_charging_vbusov(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_direct_charging_vbusov) return chg_dev->ops->set_direct_charging_vbusov(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_direct_charging_vbusov); int charger_dev_set_ibusocp(struct charger_device *chg_dev, u32 uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_ibusocp) return chg_dev->ops->set_ibusocp(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_ibusocp); int charger_dev_set_vbusovp(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_vbusovp) return chg_dev->ops->set_vbusovp(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_vbusovp); int charger_dev_set_ibatocp(struct charger_device *chg_dev, u32 uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_ibatocp) return chg_dev->ops->set_ibatocp(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_ibatocp); int charger_dev_set_vbatovp(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_vbatovp) return chg_dev->ops->set_vbatovp(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_vbatovp); int charger_dev_set_vbatovp_alarm(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_vbatovp_alarm) return chg_dev->ops->set_vbatovp_alarm(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_vbatovp_alarm); int charger_dev_reset_vbatovp_alarm(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->reset_vbatovp_alarm) return chg_dev->ops->reset_vbatovp_alarm(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_reset_vbatovp_alarm); int charger_dev_set_vbusovp_alarm(struct charger_device *chg_dev, u32 uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_vbusovp_alarm) return chg_dev->ops->set_vbusovp_alarm(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_vbusovp_alarm); int charger_dev_reset_vbusovp_alarm(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->reset_vbusovp_alarm) return chg_dev->ops->reset_vbusovp_alarm(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_reset_vbusovp_alarm); int charger_dev_is_vbuslowerr(struct charger_device *chg_dev, bool *err) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->is_vbuslowerr) return chg_dev->ops->is_vbuslowerr(chg_dev, err); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_is_vbuslowerr); int charger_dev_init_chip(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->init_chip) return chg_dev->ops->init_chip(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_init_chip); int charger_dev_enable_auto_trans(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_auto_trans) return chg_dev->ops->enable_auto_trans(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_auto_trans); int charger_dev_set_auto_trans(struct charger_device *chg_dev, u32 uV, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_auto_trans) return chg_dev->ops->set_auto_trans(chg_dev, uV, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_auto_trans); int charger_dev_enable_chg_type_det(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_chg_type_det) return chg_dev->ops->enable_chg_type_det(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_chg_type_det); int charger_dev_enable_otg(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_otg) return chg_dev->ops->enable_otg(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_otg); int charger_dev_enable_discharge(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_discharge) return chg_dev->ops->enable_discharge(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_discharge); #if defined(CONFIG_USB_FACTORY_MODE) int charger_dev_enable_eoc(struct charger_device *chg_dev, bool en) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_eoc) return chg_dev->ops->enable_eoc(chg_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_eoc); int charger_dev_set_eoc_timer(struct charger_device *chg_dev, unsigned int time) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_eoc_timer) return chg_dev->ops->set_eoc_timer(chg_dev, time); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_eoc_timer); #endif int charger_dev_set_boost_current_limit(struct charger_device *chg_dev, u32 uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->set_boost_current_limit) return chg_dev->ops->set_boost_current_limit(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_boost_current_limit); int charger_dev_get_zcv(struct charger_device *chg_dev, u32 *uV) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_zcv) return chg_dev->ops->get_zcv(chg_dev, uV); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_zcv); int charger_dev_run_aicl(struct charger_device *chg_dev, u32 *uA) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->run_aicl) return chg_dev->ops->run_aicl(chg_dev, uA); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_run_aicl); int charger_dev_reset_eoc_state(struct charger_device *chg_dev) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->reset_eoc_state) return chg_dev->ops->reset_eoc_state(chg_dev); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_reset_eoc_state); #if defined(CONFIG_USB_FACTORY_MODE) int charger_dev_enable_ship_mode(struct charger_device *chg_dev, bool battfet) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->enable_ship_mode) return chg_dev->ops->enable_ship_mode(chg_dev, battfet); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_ship_mode); #endif int charger_dev_safety_check(struct charger_device *chg_dev, u32 polling_ieoc) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->safety_check) return chg_dev->ops->safety_check(chg_dev, polling_ieoc); return -ENOTSUPP; } int charger_dev_notify(struct charger_device *chg_dev, int event) { return srcu_notifier_call_chain( &chg_dev->evt_nh, event, &chg_dev->noti); } int charger_dev_enable_usbid(struct charger_device *charger_dev, bool en) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->enable_usbid) return charger_dev->ops->enable_usbid(charger_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_usbid); int charger_dev_set_usbid_rup(struct charger_device *charger_dev, u32 rup) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->set_usbid_rup) return charger_dev->ops->set_usbid_rup(charger_dev, rup); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_usbid_rup); int charger_dev_set_usbid_src_ton(struct charger_device *charger_dev, u32 src_ton) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->set_usbid_src_ton) return charger_dev->ops->set_usbid_src_ton(charger_dev, src_ton); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_set_usbid_src_ton); int charger_dev_enable_usbid_floating(struct charger_device *charger_dev, bool en) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->enable_usbid_floating) return charger_dev->ops->enable_usbid_floating(charger_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_usbid_floating); int charger_dev_enable_force_typec_otp(struct charger_device *charger_dev, bool en) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->enable_force_typec_otp) return charger_dev->ops->enable_force_typec_otp(charger_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_force_typec_otp); int charger_dev_get_ctd_dischg_status(struct charger_device *charger_dev, u8 *status) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->get_ctd_dischg_status) return charger_dev->ops->get_ctd_dischg_status(charger_dev, status); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_ctd_dischg_status); int charger_dev_enable_hidden_mode(struct charger_device *charger_dev, bool en) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->enable_hidden_mode) return charger_dev->ops->enable_hidden_mode(charger_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_hidden_mode); int charger_dev_enable_bleed_discharge(struct charger_device *charger_dev, bool en) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->enable_bleed_discharge) return charger_dev->ops->enable_bleed_discharge(charger_dev, en); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_enable_bleed_discharge); #if defined(CONFIG_USB_FACTORY_MODE) int charger_dev_get_health(struct charger_device *chg_dev, int *health) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_health) return chg_dev->ops->get_health(chg_dev, health); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_health); int charger_dev_get_charge_type(struct charger_device *chg_dev, int *type) { if (chg_dev != NULL && chg_dev->ops != NULL && chg_dev->ops->get_charge_type) return chg_dev->ops->get_charge_type(chg_dev, type); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_charge_type); int charger_dev_get_charging_status(struct charger_device *charger_dev, u32 *charging_status) { if (charger_dev != NULL && charger_dev->ops != NULL && charger_dev->ops->get_charging_status) return charger_dev->ops->get_charging_status(charger_dev, charging_status); return -ENOTSUPP; } EXPORT_SYMBOL(charger_dev_get_charging_status); #endif static DEVICE_ATTR(name, 0444, charger_show_name, NULL); static struct attribute *charger_class_attrs[] = { &dev_attr_name.attr, NULL, }; static const struct attribute_group charger_group = { .attrs = charger_class_attrs, }; static const struct attribute_group *charger_groups[] = { &charger_group, NULL, }; int register_charger_device_notifier(struct charger_device *chg_dev, struct notifier_block *nb) { int ret; ret = srcu_notifier_chain_register(&chg_dev->evt_nh, nb); return ret; } EXPORT_SYMBOL(register_charger_device_notifier); int unregister_charger_device_notifier(struct charger_device *chg_dev, struct notifier_block *nb) { return srcu_notifier_chain_unregister(&chg_dev->evt_nh, nb); } EXPORT_SYMBOL(unregister_charger_device_notifier); /** * charger_device_register - create and register a new object of * charger_device class. * @name: the name of the new object * @parent: a pointer to the parent device * @devdata: an optional pointer to be stored for private driver use. * The methods may retrieve it by using charger_get_data(charger_dev). * @ops: the charger operations structure. * * Creates and registers new charger device. Returns either an * ERR_PTR() or a pointer to the newly allocated device. */ struct charger_device *charger_device_register(const char *name, struct device *parent, void *devdata, const struct charger_ops *ops, const struct charger_properties *props) { struct charger_device *chg_dev = NULL; static struct lock_class_key key; struct srcu_notifier_head *head = NULL; int rc; char *charger_name = NULL; pr_debug("%s: name=%s\n", __func__, name); chg_dev = kzalloc(sizeof(*chg_dev), GFP_KERNEL); if (!chg_dev) return ERR_PTR(-ENOMEM); head = &chg_dev->evt_nh; srcu_init_notifier_head(head); /* Rename srcu's lock to avoid LockProve warning */ lockdep_init_map(&(&head->srcu)->dep_map, name, &key, 0); mutex_init(&chg_dev->ops_lock); chg_dev->dev.class = charger_class; chg_dev->dev.parent = parent; chg_dev->dev.release = charger_device_release; charger_name = kasprintf(GFP_KERNEL, "%s", name); dev_set_name(&chg_dev->dev, charger_name); dev_set_drvdata(&chg_dev->dev, devdata); kfree(charger_name); /* Copy properties */ if (props) { memcpy(&chg_dev->props, props, sizeof(struct charger_properties)); } rc = device_register(&chg_dev->dev); if (rc) { kfree(chg_dev); return ERR_PTR(rc); } chg_dev->ops = ops; return chg_dev; } EXPORT_SYMBOL(charger_device_register); /** * charger_device_unregister - unregisters a switching charger device * object. * @charger_dev: the switching charger device object to be unregistered * and freed. * * Unregisters a previously registered via charger_device_register object. */ void charger_device_unregister(struct charger_device *chg_dev) { if (!chg_dev) return; mutex_lock(&chg_dev->ops_lock); chg_dev->ops = NULL; mutex_unlock(&chg_dev->ops_lock); device_unregister(&chg_dev->dev); } EXPORT_SYMBOL(charger_device_unregister); static int charger_match_device_by_name(struct device *dev, const void *data) { const char *name = data; return strcmp(dev_name(dev), name) == 0; } struct charger_device *get_charger_by_name(const char *name) { struct device *dev = NULL; if (!name) return (struct charger_device *)NULL; dev = class_find_device(charger_class, NULL, name, charger_match_device_by_name); return dev ? to_charger_device(dev) : NULL; } EXPORT_SYMBOL(get_charger_by_name); static void __exit charger_class_exit(void) { class_destroy(charger_class); } static int __init charger_class_init(void) { charger_class = class_create(THIS_MODULE, "switching_charger"); if (IS_ERR(charger_class)) { pr_notice("Unable to create charger class; errno = %ld\n", PTR_ERR(charger_class)); return PTR_ERR(charger_class); } charger_class->dev_groups = charger_groups; /* charger_class->suspend = charger_suspend; charger_class->resume = charger_resume; */ return 0; } subsys_initcall(charger_class_init); module_exit(charger_class_exit); MODULE_DESCRIPTION("Switching Charger Class Device"); MODULE_AUTHOR("Patrick Chang "); MODULE_VERSION("1.0.0_G"); MODULE_LICENSE("GPL");