From 39a723452f430a7ef89b0ffa934b2d4312890076 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 20 Feb 2015 17:04:11 +0900 Subject: ARM: keystone: move SoC sources to mach-keystone Move arch/arm/cpu/armv7/keystone/* -> arch/arm/mach-keystone/* Signed-off-by: Masahiro Yamada Cc: Tom Rini --- arch/arm/mach-keystone/psc.c | 227 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 arch/arm/mach-keystone/psc.c (limited to 'arch/arm/mach-keystone/psc.c') diff --git a/arch/arm/mach-keystone/psc.c b/arch/arm/mach-keystone/psc.c new file mode 100644 index 0000000000..237e776e87 --- /dev/null +++ b/arch/arm/mach-keystone/psc.c @@ -0,0 +1,227 @@ +/* + * Keystone: PSC configuration module + * + * (C) Copyright 2012-2014 + * Texas Instruments Incorporated, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +int psc_delay(void) +{ + udelay(10); + return 10; +} + +/* + * FUNCTION PURPOSE: Wait for end of transitional state + * + * DESCRIPTION: Polls pstat for the selected domain and waits for transitions + * to be complete. + * + * Since this is boot loader code it is *ASSUMED* that interrupts + * are disabled and no other core is mucking around with the psc + * at the same time. + * + * Returns 0 when the domain is free. Returns -1 if a timeout + * occurred waiting for the completion. + */ +int psc_wait(u32 domain_num) +{ + u32 retry; + u32 ptstat; + + /* + * Do nothing if the power domain is in transition. This should never + * happen since the boot code is the only software accesses psc. + * It's still remotely possible that the hardware state machines + * initiate transitions. + * Don't trap if the domain (or a module in this domain) is + * stuck in transition. + */ + retry = 0; + + do { + ptstat = __raw_readl(KS2_PSC_BASE + PSC_REG_PSTAT); + ptstat = ptstat & (1 << domain_num); + } while ((ptstat != 0) && ((retry += psc_delay()) < + PSC_PTSTAT_TIMEOUT_LIMIT)); + + if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT) + return -1; + + return 0; +} + +u32 psc_get_domain_num(u32 mod_num) +{ + u32 domain_num; + + /* Get the power domain associated with the module number */ + domain_num = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num)); + domain_num = PSC_REG_MDCFG_GET_PD(domain_num); + + return domain_num; +} + +/* + * FUNCTION PURPOSE: Power up/down a module + * + * DESCRIPTION: Powers up/down the requested module and the associated power + * domain if required. No action is taken it the module is + * already powered up/down. + * + * This only controls modules. The domain in which the module + * resides will be left in the power on state. Multiple modules + * can exist in a power domain, so powering down the domain based + * on a single module is not done. + * + * Returns 0 on success, -1 if the module can't be powered up, or + * if there is a timeout waiting for the transition. + */ +int psc_set_state(u32 mod_num, u32 state) +{ + u32 domain_num; + u32 pdctl; + u32 mdctl; + u32 ptcmd; + u32 reset_iso; + u32 v; + + /* + * Get the power domain associated with the module number, and reset + * isolation functionality + */ + v = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCFG(mod_num)); + domain_num = PSC_REG_MDCFG_GET_PD(v); + reset_iso = PSC_REG_MDCFG_GET_RESET_ISO(v); + + /* Wait for the status of the domain/module to be non-transitional */ + if (psc_wait(domain_num) != 0) + return -1; + + /* + * Perform configuration even if the current status matches the + * existing state + * + * Set the next state of the power domain to on. It's OK if the domain + * is always on. This code will not ever power down a domain, so no + * change is made if the new state is power down. + */ + if (state == PSC_REG_VAL_MDCTL_NEXT_ON) { + pdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_PDCTL(domain_num)); + pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, + PSC_REG_VAL_PDCTL_NEXT_ON); + __raw_writel(pdctl, KS2_PSC_BASE + PSC_REG_PDCTL(domain_num)); + } + + /* Set the next state for the module to enabled/disabled */ + mdctl = __raw_readl(KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); + mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, state); + mdctl = PSC_REG_MDCTL_SET_RESET_ISO(mdctl, reset_iso); + __raw_writel(mdctl, KS2_PSC_BASE + PSC_REG_MDCTL(mod_num)); + + /* Trigger the enable */ + ptcmd = __raw_readl(KS2_PSC_BASE + PSC_REG_PTCMD); + ptcmd |= (u32)(1<