PSC driver for Curiew
authorSandeep Paulraj <s-paulraj@ti.com>
Thu, 16 Dec 2010 19:44:50 +0000 (14:44 -0500)
committerSandeep Nair <a0875039@gt48xvq51.gt.design.ti.com>
Mon, 7 Mar 2011 20:33:50 +0000 (15:33 -0500)
Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
src/hw/pscs/psccur/psc.c [new file with mode: 0755]
src/hw/pscs/psccur/pscloc.h [new file with mode: 0755]

diff --git a/src/hw/pscs/psccur/psc.c b/src/hw/pscs/psccur/psc.c
new file mode 100755 (executable)
index 0000000..f55395a
--- /dev/null
@@ -0,0 +1,346 @@
+/***********************************************************************************
+ * FILE PURPOSE: Driver for the PSC module
+ ***********************************************************************************
+ * FILE NAME: psc.c
+ *
+ * DESCRIPTION: The boot loader PSC driver
+ *
+ * Copyright (C) 2006, Texas Instruments, Inc.
+ * @file psc.c
+ * 
+ * @brief
+ *   The PSC 2.0.x driver
+ *
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+#include "types.h"
+#include "pscapi.h"
+#include "pscloc.h"
+#include "target.h"
+
+
+#define DEVICE_REG32_W(x,y)   *(volatile unsigned int *)(x)=(y)
+#define DEVICE_REG32_R(x)    (*(volatile unsigned int *)(x))
+
+/***********************************************************************************
+ * FUNCTION PURPOSE: Wait!
+ ***********************************************************************************
+ * DESCRIPTION: This function doesn't do didly. It loops around for a bit
+ *              to give transitions some time to occur.
+ *              This function always returns 1.
+ ***********************************************************************************/
+int16 pscDelay (void)
+{
+  volatile uint32 i;
+  for (i = 0; i < 10000; i++);
+
+  return (0);
+
+} /* pscDelay */
+
+
+/***********************************************************************************
+ * 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.
+ ***********************************************************************************/
+int16 pscWait (uint32 domainNum)
+{
+  uint32 retry;
+  uint32 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 = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PSTAT);
+    ptstat = ptstat & (1 << domainNum);
+
+  } while ((ptstat != 0) &&  ((retry += pscDelay ()) < PSC_PTSTAT_TIMEOUT_LIMIT));
+
+  if (retry >= PSC_PTSTAT_TIMEOUT_LIMIT)
+    return (-1);
+
+  return (0);
+
+} /* pscWait */
+
+
+/***********************************************************************************
+ * FUNCTION PURPOSE: Return the PSC state
+ ***********************************************************************************
+ * DESCRIPTION: Checks the power state of the module
+ ***********************************************************************************/
+BOOL pscModuleIsEnabled (uint32 modNum)
+{
+#if 0
+       uint32 domainNum;
+  uint32 mdstat;
+
+  /* Get the power domain associated with the module number */
+  domainNum = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCFG(modNum));
+  domainNum = PSC_REG_MDCFG_GET_PD (domainNum);
+
+  /* Wait for the status of the domain/module to be non-transitional,
+   * but don't trap if stuck in a transitional state. */ 
+  pscWait (domainNum);
+
+  mdstat = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDSTAT(modNum));
+  mdstat = PSC_REG_MDSTAT_GET_STATUS (mdstat);
+
+  if ((mdstat == PSC_REG_VAL_MDSTAT_STATE_ON) || 
+      (mdstat == PSC_REG_VAL_MDSTAT_STATE_ENABLE_IN_PROG))
+      return (TRUE);
+
+  else  
+
+    return (FALSE);
+#endif
+
+  return (TRUE);
+} /* pscModuleIsEnabled */
+
+
+
+
+/***********************************************************************************
+ * 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.
+ ***********************************************************************************/
+int16 pscSetState (uint32 modNum, uint32 state)
+{
+#if 0
+  uint32 domainNum;
+  uint32 pdctl;
+  uint32 mdctl;
+  uint32 ptcmd;
+  uint32 resetIso;
+  uint32 v;
+
+  /* Get the power domain associated with the module number, and reset
+   * isolation functionality */
+  v         = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCFG(modNum));
+  domainNum = PSC_REG_MDCFG_GET_PD (v);
+  resetIso  = PSC_REG_MDCFG_GET_RESET_ISO(v);
+
+
+  /* Wait for the status of the domain/module to be non-transitional */ 
+  if (pscWait (domainNum) != 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 = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum));
+      pdctl = PSC_REG_PDCTL_SET_NEXT(pdctl, PSC_REG_VAL_PDCTL_NEXT_ON);
+      DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum), pdctl);
+  }
+
+
+  /* Set the next state for the module to enabled/disabled */
+  mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
+  mdctl = PSC_REG_MDCTL_SET_NEXT (mdctl, state);
+  mdctl = PSC_REG_MDCTL_SET_RESET_ISO (mdctl, resetIso);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
+
+  /* Trigger the enable */
+  ptcmd = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PTCMD);
+  ptcmd |= (uint32)(1<<domainNum);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd);
+
+
+  /* Wait on the complete */
+  return (pscWait (domainNum));
+#endif
+return 0;
+} /* pscSetState*/
+
+
+/***********************************************************************************
+ * FUNCTION PURPOSE: Power up a module
+ ***********************************************************************************
+ * DESCRIPTION: Powers up the requested module and the associated power domain
+ *              if required. No action is taken it the module is already 
+ *              powered up.
+ *
+ *              Returns 0 on success, -1 if the module can't be powered up, or
+ *              if there is a timeout waiting for the transition.
+ ***********************************************************************************/
+int16 pscEnableModule (uint32 modNum)
+{
+
+//  return (pscSetState (modNum, PSC_REG_VAL_MDCTL_NEXT_ON));
+ return 0;
+} /* pscEnableModule */
+
+/************************************************************************************
+ * FUNCTION PURPOSE: Power down a module
+ ************************************************************************************
+ * DESCRIPTION: Powers down the requested module.
+ *  
+ *              Returns 0 on success, -1 on failure or timeout.
+ ************************************************************************************/
+int16 pscDisableModule (uint32 modNum)
+{
+#if 0
+       uint32 mdctl;
+
+  /* Set the bit to apply reset */
+  mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
+  mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl,0);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
+
+  return (pscSetState (modNum, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE));
+#endif
+  return 0;
+} /* pscDisableModule */
+
+
+/************************************************************************************
+ * FUNCTION PURPOSE: Set the reset isolation bit in mdctl
+ ************************************************************************************
+ * DESCRIPTION: The reset isolation enable bit is set. The state of the module
+ *              is not changed. Returns 0 if the module config showed that
+ *              reset isolation is supported. Returns 1 otherwise. This is not
+ *              an error, but setting the bit in mdctl has no effect.
+ ************************************************************************************/
+int16 pscSetResetIso (uint32 modNum)
+{
+#if 0
+       uint32 v;
+  uint32 mdctl;
+
+  /* Set the reset isolation bit */
+  mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
+  mdctl = PSC_REG_MDCTL_SET_RESET_ISO (mdctl, 1);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
+  
+  v = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCFG(modNum));
+  if (PSC_REG_MDCFG_GET_RESET_ISO(v) == 1)
+    return (0);
+
+  return (1);
+#endif
+
+  return (0);
+} /* pscSetResetIso */
+
+/*************************************************************************************
+ * FUNCTION PURPOSE: Disable a power domain
+ *************************************************************************************
+ * DESCRIPTION: The power domain is disabled
+ *************************************************************************************/
+int16 pscDisableDomain (uint32 domainNum)
+{
+#if 0  
+  uint32 pdctl;
+  uint32 ptcmd;
+
+  pdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum));
+  pdctl = PSC_REG_PDCTL_SET_NEXT (pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF);
+  pdctl = PSC_REG_PDCTL_SET_PDMODE (pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum), pdctl);
+
+  ptcmd = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PTCMD);
+  ptcmd |= (uint32)(1<<domainNum);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd);
+#endif
+  return (0);
+
+} /* pscDisableDomain */
+
+
+/*************************************************************************************
+ * FUNCTION PURPOSE: Power down a domain
+ *************************************************************************************
+ * DESCRIPTION: The specified power domain is set to the disabled state
+ *************************************************************************************/
+void pscDisableModAndDomain (uint32 modNum, uint32 domainNum)
+{
+#if 0
+   uint32 pdctl;
+  uint32 ptcmd;
+  uint32 mdctl;
+
+
+  mdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum));
+  mdctl = PSC_REG_MDCTL_SET_NEXT(mdctl, PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE);
+  mdctl = PSC_REG_MDCTL_SET_LRSTZ(mdctl,0);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_MDCTL(modNum), mdctl);
+
+
+  pdctl = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum));
+  pdctl = PSC_REG_PDCTL_SET_NEXT (pdctl, PSC_REG_VAL_PDCTL_NEXT_OFF);
+  pdctl = PSC_REG_PDCTL_SET_PDMODE (pdctl, PSC_REG_VAL_PDCTL_PDMODE_SLEEP);
+
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PDCTL(domainNum), pdctl);
+
+  ptcmd = DEVICE_REG32_R (DEVICE_PSC_BASE + PSC_REG_PTCMD);
+  ptcmd |= (uint32)(1<<domainNum);
+  DEVICE_REG32_W (DEVICE_PSC_BASE + PSC_REG_PTCMD, ptcmd);
+
+
+  /* Wait on the complete */
+  pscWait (domainNum);
+#endif
+
+//  return (0);
+}
+
+
diff --git a/src/hw/pscs/psccur/pscloc.h b/src/hw/pscs/psccur/pscloc.h
new file mode 100755 (executable)
index 0000000..3570635
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
+ * 
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+
+
+
+#ifndef _PSCLOC_H
+#define _PSCLOC_H
+/*************************************************************************************
+ * FILE PURPOSE: Local Power Saver Controller definitions
+ *************************************************************************************
+ * FILE NAME: pscloc.h
+ *
+ * DESCRIPTION: Provides local definitions for the power saver controller
+ *
+ *************************************************************************************/
+#define BOOTBITMASK(x,y)      (   (   (  ((uint32)1 << (((uint32)x)-((uint32)y)+(uint32)1) ) - (uint32)1 )   )   <<  ((uint32)y)   )
+#define BOOT_READ_BITFIELD(z,x,y)   (((uint32)z) & BOOTBITMASK(x,y)) >> (y)
+#define BOOT_SET_BITFIELD(z,f,x,y)  (((uint32)z) & ~BOOTBITMASK(x,y)) | ( (((uint32)f) << (y)) & BOOTBITMASK(x,y) )
+
+/* Register offsets */
+#define PSC_REG_PTCMD           0x120
+#define PSC_REG_PSTAT          0x128
+#define PSC_REG_PDSTAT(x)       (0x200 + (4*(x)))
+#define PSC_REG_PDCTL(x)        (0x300 + (4*(x)))
+#define PSC_REG_MDCFG(x)        (0x600 + (4*(x)))
+#define PSC_REG_MDSTAT(x)       (0x800 + (4*(x)))
+#define PSC_REG_MDCTL(x)        (0xa00 + (4*(x)))
+
+
+/* Macros to access register fields */
+/* PDCTL */
+#define PSC_REG_PDCTL_SET_NEXT(x,y)    BOOT_SET_BITFIELD((x),(y),0,0)
+#define PSC_REG_PDCTL_SET_PDMODE(x,y)  BOOT_SET_BITFIELD((x),(y),15,12)
+
+/* PDSTAT */
+#define PSC_REG_PDSTAT_GET_STATE(x)  BOOT_READ_BITFIELD((x),4,0))
+
+/* MDCFG */
+#define PSC_REG_MDCFG_GET_PD(x)         BOOT_READ_BITFIELD((x),20,16)
+#define PSC_REG_MDCFG_GET_RESET_ISO(x)  BOOT_READ_BITFIELD((x),14,14)
+
+/* MDCTL */
+#define PSC_REG_MDCTL_SET_NEXT(x,y)       BOOT_SET_BITFIELD((x),(y),4,0)
+#define PSC_REG_MDCTL_SET_LRSTZ(x,y)      BOOT_SET_BITFIELD((x),(y),8,8)
+#define PSC_REG_MDCTL_GET_LRSTZ(x)        BOOT_READ_BITFIELD((x),8,8)
+#define PSC_REG_MDCTL_SET_RESET_ISO(x,y)  BOOT_SET_BITFIELD((x),(y),12,12)
+
+
+/* MDSTAT */
+#define PSC_REG_MDSTAT_GET_STATUS(x)   BOOT_READ_BITFIELD((x),5,0)
+#define PSC_REG_MDSTAT_GET_LRSTZ(x)    BOOT_READ_BITFIELD((x),8,8)
+#define PSC_REG_MDSTAT_GET_LRSTDONE(x) BOOT_READ_BITFIELD((x),9,9)
+
+/* PDCTL states */
+#define PSC_REG_VAL_PDCTL_NEXT_ON   1
+#define PSC_REG_VAL_PDCTL_NEXT_OFF  0
+
+#define PSC_REG_VAL_PDCTL_PDMODE_SLEEP  0
+
+/* MDCTL states */
+#define PSC_REG_VAL_MDCTL_NEXT_SWRSTDISABLE     0
+#define PSC_REG_VAL_MDCTL_NEXT_OFF              2
+#define PSC_REG_VAL_MDCTL_NEXT_ON               3  /* Yes, 3 is the on state command */
+
+
+/* MDSTAT states */
+#define PSC_REG_VAL_MDSTAT_STATE_ON                 3
+#define PSC_REG_VAL_MDSTAT_STATE_ENABLE_IN_PROG     0x24
+#define PSC_REG_VAL_MDSTAT_STATE_OFF                2
+#define PSC_REG_VAL_MDSTAT_STATE_DISABLE_IN_PROG1   0x20
+#define PSC_REG_VAL_MDSTAT_STATE_DISABLE_IN_PROG2   0x21
+#define PSC_REG_VAL_MDSTAT_STATE_DISABLE_IN_PROG3   0x22
+
+
+/* Timeout limit on checking PTSTAT. This is the number of times the
+ * wait function will be called before giving up. */
+#define PSC_PTSTAT_TIMEOUT_LIMIT    100
+
+
+
+
+
+#endif /* _PSCLOC_H */