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 }
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); } }
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; } }