Esempio n. 1
0
void init_protection(struct mxs_info *info)
{
	enum ddi_power_5v_status pmu_5v_status;
	uint16_t battery_voltage;

	pmu_5v_status = ddi_power_GetPmu5vStatus();
	battery_voltage = ddi_power_GetBattery();

	/* InitializeFiqSystem(); */
	ddi_power_InitOutputBrownouts();

	if (info->powersource == NO_VDD5V_SOURCE) {
		ddi_power_EnableBatteryBoInterrupt(true);
		return;
	}

	/* if we start the kernel with 4p2 already started
	 * by the bootlets, we need to hand off from this
	 * state to the kernel 4p2 enabled state.
	 */
	if ((pmu_5v_status == existing_5v_connection) &&
		 ddi_power_check_4p2_bits()) {
		ddi_power_enable_5v_disconnect_detection();

		/* includes VBUS DROOP workaround for errata */
		ddi_power_init_4p2_protection();

		/* if we still have our 5V connection, we can disable
		 * battery brownout interrupt.  This is because the
		 * VDD5V DROOP IRQ handler will also shutdown if battery
		 * is browned out and it will enable the battery brownout
		 * and bring VBUSVALID_TRSH level back to a normal level
		 * which caused the hardware battery brownout shutdown
		 * to be enabled.  The benefit of this is that device
		 * that have detachable batteries (or devices going through
		 * the assembly line and running this firmware to test
		 *  with) can avoid shutting down if 5V is present and
		 *  battery voltage goes away.
		 */
		ddi_power_EnableBatteryBoInterrupt(false);

		info->sm_5v_connection_status = _5v_connected_verified;
	} else {
#ifdef DEBUG_IRQS
		if (battery_voltage <
			OS_SHUTDOWN_BATTERY_VOLTAGE_THRESHOLD_MV) {
			printk(KERN_CRIT "Polled battery voltage measurement is\
				less than %dmV.  Kernel should be halted/\
				shutdown\n",
				OS_SHUTDOWN_BATTERY_VOLTAGE_THRESHOLD_MV);

			return;
		}
#endif
		info->sm_5v_connection_status = _5v_disconnected_verified;
		ddi_power_EnableBatteryBoInterrupt(true);

	}


	/* all brownouts are now handled software fiqs.  We
	 * can now disable the hardware protection mechanisms
	 *  because leaving them on yields ~2kV ESD level
	 *  versus ~4kV ESD levels when they are off.  This
	 *  difference is suspected to be cause by the fast
	 *  falling edge pswitch functionality being tripped
	 *  by ESD events.  This functionality is disabled
	 *  when PWD_OFF is disabled.
	 */
#ifdef DISABLE_HARDWARE_PROTECTION_MECHANISMS
	__raw_writel(BM_POWER_RESET_PWD_OFF,
		HW_POWER_RESET_SET_ADDR);
#endif




}
Esempio n. 2
0
static void check_and_handle_5v_connection(struct mxs_info *info)
{

	switch (ddi_power_GetPmu5vStatus()) {

	case new_5v_connection:

		if (info->is_5v_irq_detected == 0) {
			/* we must wait for irq_vdd5v handler run first to
				reset info->sm_new_5v_connection_jiffies.
				Otherwise the debounce checking is wrong.
       */;
			break;
		}
		info->is_5v_irq_detected = 0;
		ddi_power_enable_5v_disconnect_detection();
		info->sm_5v_connection_status = _5v_connected_unverified;

	case existing_5v_connection:
		if (info->sm_5v_connection_status != _5v_connected_verified) {
			/* we allow some time to pass before considering
			 * the 5v connection to be ready to use.  This
			 * will give the USB system time to enumerate
			 * (coordination with USB driver to be added
			 * in the future).
			 */

			/* handle jiffies rollover case */
			if ((jiffies - info->sm_new_5v_connection_jiffies)
				< 0) {
				info->sm_new_5v_connection_jiffies = jiffies;
				break;
			}

			if ((jiffies_to_msecs(jiffies -
				info->sm_new_5v_connection_jiffies)) >
				_5V_DEBOUNCE_TIME_MS) {
				info->sm_5v_connection_status =
					_5v_connected_verified;
				dev_dbg(info->dev,
					"5v connection verified\n");
			if (info->onboard_vbus5v) {
				if (regulator_is_enabled(
					info->onboard_vbus5v) > 0) {
					info->onboard_vbus5v_online = 1;
					pr_debug("When supply from \
					onboard vbus 5v ,\
					DO NOT switch to 4p2 \n");
					break;
			}
		}
#ifdef CONFIG_MXS_VBUS_CURRENT_DRAW
	#ifdef CONFIG_USB_GADGET
		/* if there is USB 2.0 current limitation requirement,
		* waiting for USB enum done.
		*/
		if ((__raw_readl(REGS_POWER_BASE + HW_POWER_5VCTRL)
			& BM_POWER_5VCTRL_CHARGE_4P2_ILIMIT) ==
			(0x20 << BP_POWER_5VCTRL_CHARGE_4P2_ILIMIT)) {
			dev_info(info->dev, "waiting USB enum done...\r\n");
		}
		while ((__raw_readl(REGS_POWER_BASE + HW_POWER_5VCTRL)
			& BM_POWER_5VCTRL_CHARGE_4P2_ILIMIT)
			== (0x20 << BP_POWER_5VCTRL_CHARGE_4P2_ILIMIT)) {
			msleep(50);
		}
	#endif
#endif
				ddi_power_Enable4p2(450);

				/* part of handling for errata.  It is
				 *  now "somewhat" safe to
				 * turn on vddio interrupts again
				 */
				ddi_power_enable_vddio_interrupt(true);
			}
		}
Esempio n. 3
0
static void check_and_handle_5v_connection(struct stmp3xxx_info *info)
{

	switch (ddi_power_GetPmu5vStatus()) {

	case new_5v_connection:
		ddi_power_enable_5v_disconnect_detection();
		info->sm_5v_connection_status = _5v_connected_unverified;

	case existing_5v_connection:
		if (info->sm_5v_connection_status != _5v_connected_verified) {
			/* we allow some time to pass before considering
			 * the 5v connection to be ready to use.  This
			 * will give the USB system time to enumerate
			 * (coordination with USB driver to be added
			 * in the future).
			 */

			/* handle jiffies rollover case */
			if ((jiffies - info->sm_new_5v_connection_jiffies)
				< 0) {
				info->sm_new_5v_connection_jiffies = jiffies;
				break;
			}

			if ((jiffies_to_msecs(jiffies -
				info->sm_new_5v_connection_jiffies)) >
				_5V_DEBOUNCE_TIME_MS) {
				info->sm_5v_connection_status =
					_5v_connected_verified;
				dev_info(info->dev,
					"5v connection verified\n");
				ddi_power_Enable4p2(450);


				/* part of handling for errata.  It is
				 *  now "somewhat" safe to
				 * turn on vddio interrupts again
				 */
				ddi_power_enable_vddio_interrupt(true);
			}
		}
		break;

	case new_5v_disconnection:

		ddi_bc_SetDisable();
		ddi_bc_SetCurrentLimit(0);
		if (info->regulator)
			regulator_set_current_limit(info->regulator, 0, 0);
		info->is_usb_online = 0;
		info->is_ac_online = 0;

		info->sm_5v_connection_status = _5v_disconnected_unverified;

	case existing_5v_disconnection:

		if (info->sm_5v_connection_status !=
			_5v_disconnected_verified) {
			if ((jiffies - info->sm_new_5v_disconnection_jiffies)
				< 0) {
				info->sm_new_5v_connection_jiffies = jiffies;
				break;
			}

			if ((jiffies_to_msecs(jiffies -
				info->sm_new_5v_disconnection_jiffies)) >
				_5V_DEBOUNCE_TIME_MS) {
				info->sm_5v_connection_status =
					_5v_disconnected_verified;
				ddi_power_execute_5v_to_battery_handoff();
				ddi_power_enable_5v_connect_detection();

				/* part of handling for errata.
				 * It is now safe to
				 * turn on vddio interrupts again
				 */
				ddi_power_enable_vddio_interrupt(true);
				dev_info(info->dev,
					"5v disconnection handled\n");

			}
		}

		break;
	}
}