mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	extcon: intel-cht-wc: Add support for registering a power_supply class-device
The bq25890 used on the Yogabook YB1-X90 / -X91 models relies on the extcon-driver's BC-1.2 charger detection, and the bq25890 driver expect this info to be available through a parent power_supply class-device which models the detected charger (idem to how the Type-C TCPM code registers a power_supply classdev for the connected charger). Add support for registering the power_supply class-device expected by this setup. Acked-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
This commit is contained in:
		
							parent
							
								
									73b5ae3415
								
							
						
					
					
						commit
						66e31186cd
					
				
					 1 changed files with 81 additions and 0 deletions
				
			
		| 
						 | 
					@ -14,6 +14,7 @@
 | 
				
			||||||
#include <linux/module.h>
 | 
					#include <linux/module.h>
 | 
				
			||||||
#include <linux/mod_devicetable.h>
 | 
					#include <linux/mod_devicetable.h>
 | 
				
			||||||
#include <linux/platform_device.h>
 | 
					#include <linux/platform_device.h>
 | 
				
			||||||
 | 
					#include <linux/power_supply.h>
 | 
				
			||||||
#include <linux/property.h>
 | 
					#include <linux/property.h>
 | 
				
			||||||
#include <linux/regmap.h>
 | 
					#include <linux/regmap.h>
 | 
				
			||||||
#include <linux/regulator/consumer.h>
 | 
					#include <linux/regulator/consumer.h>
 | 
				
			||||||
| 
						 | 
					@ -106,6 +107,8 @@ struct cht_wc_extcon_data {
 | 
				
			||||||
	struct extcon_dev *edev;
 | 
						struct extcon_dev *edev;
 | 
				
			||||||
	struct usb_role_switch *role_sw;
 | 
						struct usb_role_switch *role_sw;
 | 
				
			||||||
	struct regulator *vbus_boost;
 | 
						struct regulator *vbus_boost;
 | 
				
			||||||
 | 
						struct power_supply *psy;
 | 
				
			||||||
 | 
						enum power_supply_usb_type usb_type;
 | 
				
			||||||
	unsigned int previous_cable;
 | 
						unsigned int previous_cable;
 | 
				
			||||||
	bool usb_host;
 | 
						bool usb_host;
 | 
				
			||||||
	bool vbus_boost_enabled;
 | 
						bool vbus_boost_enabled;
 | 
				
			||||||
| 
						 | 
					@ -170,18 +173,23 @@ static int cht_wc_extcon_get_charger(struct cht_wc_extcon_data *ext,
 | 
				
			||||||
		dev_warn(ext->dev,
 | 
							dev_warn(ext->dev,
 | 
				
			||||||
			"Unhandled charger type %d, defaulting to SDP\n",
 | 
								"Unhandled charger type %d, defaulting to SDP\n",
 | 
				
			||||||
			 ret);
 | 
								 ret);
 | 
				
			||||||
 | 
							ext->usb_type = POWER_SUPPLY_USB_TYPE_SDP;
 | 
				
			||||||
		return EXTCON_CHG_USB_SDP;
 | 
							return EXTCON_CHG_USB_SDP;
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_SDP:
 | 
						case CHT_WC_USBSRC_TYPE_SDP:
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_FLOATING:
 | 
						case CHT_WC_USBSRC_TYPE_FLOATING:
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_OTHER:
 | 
						case CHT_WC_USBSRC_TYPE_OTHER:
 | 
				
			||||||
 | 
							ext->usb_type = POWER_SUPPLY_USB_TYPE_SDP;
 | 
				
			||||||
		return EXTCON_CHG_USB_SDP;
 | 
							return EXTCON_CHG_USB_SDP;
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_CDP:
 | 
						case CHT_WC_USBSRC_TYPE_CDP:
 | 
				
			||||||
 | 
							ext->usb_type = POWER_SUPPLY_USB_TYPE_CDP;
 | 
				
			||||||
		return EXTCON_CHG_USB_CDP;
 | 
							return EXTCON_CHG_USB_CDP;
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_DCP:
 | 
						case CHT_WC_USBSRC_TYPE_DCP:
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_DCP_EXTPHY:
 | 
						case CHT_WC_USBSRC_TYPE_DCP_EXTPHY:
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */
 | 
						case CHT_WC_USBSRC_TYPE_MHL: /* MHL2+ delivers upto 2A, treat as DCP */
 | 
				
			||||||
 | 
							ext->usb_type = POWER_SUPPLY_USB_TYPE_DCP;
 | 
				
			||||||
		return EXTCON_CHG_USB_DCP;
 | 
							return EXTCON_CHG_USB_DCP;
 | 
				
			||||||
	case CHT_WC_USBSRC_TYPE_ACA:
 | 
						case CHT_WC_USBSRC_TYPE_ACA:
 | 
				
			||||||
 | 
							ext->usb_type = POWER_SUPPLY_USB_TYPE_ACA;
 | 
				
			||||||
		return EXTCON_CHG_USB_ACA;
 | 
							return EXTCON_CHG_USB_ACA;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -266,6 +274,8 @@ static void cht_wc_extcon_pwrsrc_event(struct cht_wc_extcon_data *ext)
 | 
				
			||||||
	bool ignore_get_charger_errors = ext->usb_host;
 | 
						bool ignore_get_charger_errors = ext->usb_host;
 | 
				
			||||||
	enum usb_role role;
 | 
						enum usb_role role;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ext->usb_type = POWER_SUPPLY_USB_TYPE_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
 | 
						ret = regmap_read(ext->regmap, CHT_WC_PWRSRC_STS, &pwrsrc_sts);
 | 
				
			||||||
	if (ret) {
 | 
						if (ret) {
 | 
				
			||||||
		dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
 | 
							dev_err(ext->dev, "Error reading pwrsrc status: %d\n", ret);
 | 
				
			||||||
| 
						 | 
					@ -320,6 +330,9 @@ static void cht_wc_extcon_pwrsrc_event(struct cht_wc_extcon_data *ext)
 | 
				
			||||||
	ret = usb_role_switch_set_role(ext->role_sw, role);
 | 
						ret = usb_role_switch_set_role(ext->role_sw, role);
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		dev_err(ext->dev, "Error setting USB-role: %d\n", ret);
 | 
							dev_err(ext->dev, "Error setting USB-role: %d\n", ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ext->psy)
 | 
				
			||||||
 | 
							power_supply_changed(ext->psy);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
 | 
					static irqreturn_t cht_wc_extcon_isr(int irq, void *data)
 | 
				
			||||||
| 
						 | 
					@ -420,6 +433,59 @@ static int cht_wc_extcon_get_role_sw_and_regulator(struct cht_wc_extcon_data *ex
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int cht_wc_extcon_psy_get_prop(struct power_supply *psy,
 | 
				
			||||||
 | 
									      enum power_supply_property psp,
 | 
				
			||||||
 | 
									      union power_supply_propval *val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct cht_wc_extcon_data *ext = power_supply_get_drvdata(psy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (psp) {
 | 
				
			||||||
 | 
						case POWER_SUPPLY_PROP_USB_TYPE:
 | 
				
			||||||
 | 
							val->intval = ext->usb_type;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case POWER_SUPPLY_PROP_ONLINE:
 | 
				
			||||||
 | 
							val->intval = ext->usb_type ? 1 : 0;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const enum power_supply_usb_type cht_wc_extcon_psy_usb_types[] = {
 | 
				
			||||||
 | 
						POWER_SUPPLY_USB_TYPE_SDP,
 | 
				
			||||||
 | 
						POWER_SUPPLY_USB_TYPE_CDP,
 | 
				
			||||||
 | 
						POWER_SUPPLY_USB_TYPE_DCP,
 | 
				
			||||||
 | 
						POWER_SUPPLY_USB_TYPE_ACA,
 | 
				
			||||||
 | 
						POWER_SUPPLY_USB_TYPE_UNKNOWN,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const enum power_supply_property cht_wc_extcon_psy_props[] = {
 | 
				
			||||||
 | 
						POWER_SUPPLY_PROP_USB_TYPE,
 | 
				
			||||||
 | 
						POWER_SUPPLY_PROP_ONLINE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct power_supply_desc cht_wc_extcon_psy_desc = {
 | 
				
			||||||
 | 
						.name = "cht_wcove_pwrsrc",
 | 
				
			||||||
 | 
						.type = POWER_SUPPLY_TYPE_USB,
 | 
				
			||||||
 | 
						.usb_types = cht_wc_extcon_psy_usb_types,
 | 
				
			||||||
 | 
						.num_usb_types = ARRAY_SIZE(cht_wc_extcon_psy_usb_types),
 | 
				
			||||||
 | 
						.properties = cht_wc_extcon_psy_props,
 | 
				
			||||||
 | 
						.num_properties = ARRAY_SIZE(cht_wc_extcon_psy_props),
 | 
				
			||||||
 | 
						.get_property = cht_wc_extcon_psy_get_prop,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int cht_wc_extcon_register_psy(struct cht_wc_extcon_data *ext)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct power_supply_config psy_cfg = { .drv_data = ext };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ext->psy = devm_power_supply_register(ext->dev,
 | 
				
			||||||
 | 
										      &cht_wc_extcon_psy_desc,
 | 
				
			||||||
 | 
										      &psy_cfg);
 | 
				
			||||||
 | 
						return PTR_ERR_OR_ZERO(ext->psy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int cht_wc_extcon_probe(struct platform_device *pdev)
 | 
					static int cht_wc_extcon_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
 | 
						struct intel_soc_pmic *pmic = dev_get_drvdata(pdev->dev.parent);
 | 
				
			||||||
| 
						 | 
					@ -463,6 +529,21 @@ static int cht_wc_extcon_probe(struct platform_device *pdev)
 | 
				
			||||||
		cht_wc_extcon_set_5v_boost(ext, false);
 | 
							cht_wc_extcon_set_5v_boost(ext, false);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case INTEL_CHT_WC_LENOVO_YOGABOOK1:
 | 
						case INTEL_CHT_WC_LENOVO_YOGABOOK1:
 | 
				
			||||||
 | 
							/* Do this first, as it may very well return -EPROBE_DEFER. */
 | 
				
			||||||
 | 
							ret = cht_wc_extcon_get_role_sw_and_regulator(ext);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * The bq25890 used here relies on this driver's BC-1.2 charger
 | 
				
			||||||
 | 
							 * detection, and the bq25890 driver expect this info to be
 | 
				
			||||||
 | 
							 * available through a parent power_supply class device which
 | 
				
			||||||
 | 
							 * models the detected charger (idem to how the Type-C TCPM code
 | 
				
			||||||
 | 
							 * registers a power_supply classdev for the connected charger).
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							ret = cht_wc_extcon_register_psy(ext);
 | 
				
			||||||
 | 
							if (ret)
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	case INTEL_CHT_WC_XIAOMI_MIPAD2:
 | 
						case INTEL_CHT_WC_XIAOMI_MIPAD2:
 | 
				
			||||||
		ret = cht_wc_extcon_get_role_sw_and_regulator(ext);
 | 
							ret = cht_wc_extcon_get_role_sw_and_regulator(ext);
 | 
				
			||||||
		if (ret)
 | 
							if (ret)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue