text: /* Copyright 2017 The Chromium OS Authors. All rights reserved.
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  
  /*
   * MAX14637 USB BC 1.2 Charger Detector driver.
   *
   * NOTE: The driver assumes that CHG_AL_N and SW_OPEN are not connected,
   * therefore the value of CHG_DET indicates whether the source is NOT a
   * low-power standard downstream port (SDP).  In order to use higher currents,
   * the system will have to charge ramp.
   */
  
  #include "max14637.h"
  #include "charge_manager.h"
  #include "chipset.h"
  #include "common.h"
  #include "console.h"
  #include "gpio.h"
  #include "hooks.h"
  #include "power.h"
  #include "power/cannonlake.h"
  #include "task.h"
  #include "tcpm.h"
  #include "timer.h"
  #include "usb_charge.h"
  #include "usb_pd.h"
  #include "util.h"
  
  #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args)
  
  #if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW)
  /**
   * Returns true if the charger detect pin is activated.
   *
   * @parm cfg driver for chip to read the charger detect pin for.
   * @return 1 if charger detect is activated (high when active high or
   *	low with active low), otherwise 0.
   */
  static int is_chg_det_activated(const struct max14637_config_t * const cfg)
  {
  	return !!gpio_get_level(cfg->chg_det_pin) ^
  		!!(cfg->flags & MAX14637_FLAGS_CHG_DET_ACTIVE_LOW);
  }
  #endif
  
  /**
   * Activates the Chip Enable GPIO based on the enabled value.
   *
   * @param cfg driver for chip that will set chip enable gpio.
   * @param enable 1 to activate gpio (high for active high and low for active
   *	low).
   */
  static void activate_chip_enable(
  	const struct max14637_config_t * const cfg, const int enable)
  {
  	gpio_set_level(
  		cfg->chip_enable_pin,
  		!!enable ^ !!(cfg->flags & MAX14637_FLAGS_ENABLE_ACTIVE_LOW));
  }
  
  /**
   * Perform BC1.2 detection and update charge manager.
   *
   * @param port: The Type-C port where VBUS is present.
   */
  static void bc12_detect(const int port)
  {
  	const struct max14637_config_t * const cfg = &max14637_config[port];
  	struct charge_port_info new_chg;
  
  	/*
  	 * Enable the IC to begin detection and connect switches if
  	 * necessary. This is only necessary if the port power role is a
  	 * sink. If the power role is a source then just keep the max14637
  	 * powered on so that data switches are close. Note that the gpio enable
  	 * for this chip is active by default. In order to trigger bc1.2
  	 * detection, the chip enable must be driven low, then high again so the
  	 * chip will start bc1.2 client side detection. Add a 100 msec delay to
  	 * avoid collision with a device that might be doing bc1.2 client side
  	 * detection.
  	 */
  	msleep(100);
  	activate_chip_enable(cfg, 0);
  	msleep(1);
  	activate_chip_enable(cfg, 1);
  
  	new_chg.voltage = USB_CHARGER_VOLTAGE_MV;
  #if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW)
  	/*
  	 * Apple or TomTom charger detection can take as long as 600ms.  Wait a
  	 * little bit longer for margin.
  	 */
  	msleep(630);
  
  	/*
  	 * The driver assumes that CHG_AL_N and SW_OPEN are not connected,
  	 * therefore an activated CHG_DET indicates whether the source is NOT a
  	 * low-power standard downstream port (SDP). The system will have to
  	 * ramp the current to determine the limit.  The Type-C spec prohibits
  	 * proprietary methods now, therefore 1500mA is the max.
  	 */
  	new_chg.current = is_chg_det_activated(cfg) ? USB_CHARGER_MAX_CURR_MA :
  						      500;
  #else
  	/*
  	 * If the board doesn't support charge ramping, then assume the lowest
  	 * denominator; that is assume the charger detected is a weak dedicated
  	 * charging port (DCP) which can only supply 500mA.
  	 */
  	new_chg.current = 500;
  #endif /* !defined(CONFIG_CHARGE_RAMP_SW && CONFIG_CHARGE_RAMP_HW) */
  
  	charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, port, &new_chg);
  }
  
  /**
   * If VBUS is present and port power role is sink, then trigger bc1.2 client
   * detection. If VBUS is not present then update charge manager. Note that both
   * chip_enable and VBUS must be active for the IC to be powered up. Chip enable
   * is kept enabled by default so that bc1.2 client detection is not triggered
   * when the port power role is source.
   *
   * @param port: Which USB Type-C port to examine.
   */
  static void detect_or_power_down_ic(const int port)
  {
  	int vbus_present;
  
  #ifdef CONFIG_USB_PD_VBUS_DETECT_TCPC
  	vbus_present = tcpm_check_vbus_level(port, VBUS_PRESENT);
  #else
  	vbus_present = pd_snk_is_vbus_provided(port);
  #endif /* !defined(CONFIG_USB_PD_VBUS_DETECT_TCPC) */
  
  	if (vbus_present) {
  #if defined(CONFIG_POWER_PP5000_CONTROL) && defined(HAS_TASK_CHIPSET)
  		/* Turn on the 5V rail to allow the chip to be powered. */
  		power_5v_enable(task_get_current(), 1);
  #endif
  		if (pd_get_power_role(port) == PD_ROLE_SINK)
  			bc12_detect(port);
  	} else {
  		/* Let charge manager know there's no more charge available. */
  		charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, port, NULL);
  #if defined(CONFIG_POWER_PP5000_CONTROL) && defined(HAS_TASK_CHIPSET)
  		/* Issue a request to turn off the rail. */
  		power_5v_enable(task_get_current(), 0);
  #endif
  	}
  }
  
  static void max14637_usb_charger_task(const int port)
  {
  	uint32_t evt;
  	const struct max14637_config_t * const cfg = &max14637_config[port];
  
  	ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_MAX_COUNT);
  	/*
  	 * Have chip enable active as default state so data switches are closed
  	 * and bc1.2 client side detection is not activated when the port power
  	 * role is a source.
  	 */
  	activate_chip_enable(cfg, 1);
  	/* Check whether bc1.2 client mode detection needs to be triggered */
  	detect_or_power_down_ic(port);
  
  	while (1) {
  		evt = task_wait_event(-1);
  
  		if (evt & USB_CHG_EVENT_VBUS)
  			detect_or_power_down_ic(port);
  	}
  }
  
  #if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW)
  static int max14637_ramp_allowed(int supplier)
  {
  	/*
  	 * Due to the limitations in the application of the MAX14637, we
  	 * don't quite know exactly what we're plugged into.  Therefore,
  	 * the supplier type will be CHARGE_SUPPLIER_OTHER.
  	 */
  	return supplier == CHARGE_SUPPLIER_OTHER;
  }
  
  static int max14637_ramp_max(int supplier, int sup_curr)
  {
  	/* Use the current limit that was decided by the MAX14637. */
  	if (supplier == CHARGE_SUPPLIER_OTHER)
  		return sup_curr;
  	else
  		return 500;
  }
  #endif /* CONFIG_CHARGE_RAMP_SW || CONFIG_CHARGE_RAMP_HW */
  
  /* Called on AP S5 -> S3  and S3/S0iX -> S0 transition */
  static void bc12_chipset_startup(void)
  {
  	int port;
  
  	/*
  	 * For each port, trigger a new USB_CHG_EVENT_VBUS event to handle cases
  	 * where there was no change in VBUS following an AP resume/startup
  	 * event. If a legacy charger is connected to the port, then VBUS will
  	 * not drop even during the USB PD hard reset.
  	 */
  	for (port = 0; port < CONFIG_USB_PD_PORT_MAX_COUNT; port++)
  		task_set_event(USB_CHG_PORT_TO_TASK_ID(port),
  			       USB_CHG_EVENT_VBUS, 0);
  }
  DECLARE_HOOK(HOOK_CHIPSET_STARTUP, bc12_chipset_startup, HOOK_PRIO_DEFAULT);
  DECLARE_HOOK(HOOK_CHIPSET_RESUME, bc12_chipset_startup, HOOK_PRIO_DEFAULT);
  
  const struct bc12_drv max14637_drv = {
  	.usb_charger_task = max14637_usb_charger_task,
  #if defined(CONFIG_CHARGE_RAMP_SW) || defined(CONFIG_CHARGE_RAMP_HW)
  	.ramp_allowed = max14637_ramp_allowed,
  	.ramp_max = max14637_ramp_max,
  #endif /* CONFIG_CHARGE_RAMP_SW || CONFIG_CHARGE_RAMP_HW */
  };
  
  #ifdef CONFIG_BC12_SINGLE_DRIVER
  /* provide a default bc12_ports[] for backward compatibility */
  struct bc12_config bc12_ports[CHARGE_PORT_COUNT] = {
  	[0 ... (CHARGE_PORT_COUNT - 1)] = {
  		.drv = &max14637_drv,
  	},
  };
  #endif /* CONFIG_BC12_SINGLE_DRIVER */
  