/* * AM33XX-CM3 firmware * * Cortex-M3 (CM3) firmware for power management on Texas Instruments' AM33XX series of SoCs * * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ * * This software is licensed under the standard terms and conditions in the Texas Instruments Incorporated * Technology and Software Publicly Available Software License Agreement , a copy of which is included in the * software download. */ #include #include #include #include #include #define HWMOD_DISABLE 0x0 #define HWMOD_ENABLE 0x2 #define HWMOD_MASK 0x3 static const unsigned int *hwmods; static const enum hwmod_id *essential_hwmods; static const enum hwmod_id *interconnect_hwmods; void hwmod_init(void) { if (soc_id == AM335X_SOC_ID) { hwmods = am335x_hwmods; essential_hwmods = am335x_essential_hwmods; interconnect_hwmods = am335x_interconnect_hwmods; } else if (soc_id == AM43XX_SOC_ID) { hwmods = am43xx_hwmods; essential_hwmods = am43xx_essential_hwmods; interconnect_hwmods = am43xx_interconnect_hwmods; } } #define DEFAULT_IDLEST_SHIFT 16 #define DEFAULT_IDLEST_MASK (3 << DEFAULT_IDLEST_SHIFT) #define DEFAULT_IDLEST_IDLE_VAL 3 #define DEFAULT_IDLEST_ACTIVE_VAL 0 #define HWMOD_IDLE_TIMEOUT 0xFFFF /* TODO: Add a timeout and bail out */ static void _hwmod_enable(int reg) { int i = 0; __raw_writel(HWMOD_ENABLE, reg); while ((i++ < HWMOD_IDLE_TIMEOUT) && (__raw_readl(reg) & DEFAULT_IDLEST_MASK)>>DEFAULT_IDLEST_SHIFT != DEFAULT_IDLEST_ACTIVE_VAL); } static void _hwmod_disable(int reg) { int i = 0; __raw_writel(HWMOD_DISABLE, reg); while ((i++ < HWMOD_IDLE_TIMEOUT) && (__raw_readl(reg) & DEFAULT_IDLEST_MASK)>>DEFAULT_IDLEST_SHIFT != DEFAULT_IDLEST_IDLE_VAL); } static bool _hwmod_is_enabled(int reg) { return (__raw_readl(reg) & HWMOD_MASK) == HWMOD_ENABLE; } static int hwmods_state_change(int state, const enum hwmod_id *ids) { int i; for (i = 0; ids[i] != HWMOD_END; i++) if (state == HWMOD_DISABLE) _hwmod_disable(hwmods[ids[i]]); for (i--; i >= 0; i--) if (state == HWMOD_ENABLE) _hwmod_enable(hwmods[ids[i]]); return 0; } void hwmod_enable(enum hwmod_id id) { _hwmod_enable(hwmods[id]); } void hwmod_disable(enum hwmod_id id) { _hwmod_disable(hwmods[id]); } bool hwmod_is_enabled(enum hwmod_id id) { return _hwmod_is_enabled(hwmods[id]); } /* * Looks like we'll have to ensure that we disable some hwmods when going down * ideally this list should have 0 entries but we need to check * what are the things that are really really necessary here */ int essential_hwmods_disable(void) { /* Disable only the bare essential hwmods */ hwmods_state_change(HWMOD_DISABLE, essential_hwmods); return 0; } int essential_hwmods_enable(void) { /* Enable only the bare essential hwmods */ hwmods_state_change(HWMOD_ENABLE, essential_hwmods); return 0; } int interconnect_hwmods_disable(void) { hwmods_state_change(HWMOD_DISABLE, interconnect_hwmods); return 0; } int interconnect_hwmods_enable(void) { hwmods_state_change(HWMOD_ENABLE, interconnect_hwmods); return 0; }