linux/arch/arm/mach-davinci/psc.c
<<
>>
Prefs
   1/*
   2 * TI DaVinci Power and Sleep Controller (PSC)
   3 *
   4 * Copyright (C) 2006 Texas Instruments.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 *  You should have received a copy of the GNU General Public License
  17 *  along with this program; if not, write to the Free Software
  18 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 *
  20 */
  21#include <linux/kernel.h>
  22#include <linux/module.h>
  23#include <linux/init.h>
  24#include <linux/io.h>
  25
  26#include <mach/cputype.h>
  27#include <mach/hardware.h>
  28#include <mach/psc.h>
  29#include <mach/mux.h>
  30
  31/* PSC register offsets */
  32#define EPCPR           0x070
  33#define PTCMD           0x120
  34#define PTSTAT          0x128
  35#define PDSTAT          0x200
  36#define PDCTL1          0x304
  37#define MDSTAT          0x800
  38#define MDCTL           0xA00
  39
  40#define MDSTAT_STATE_MASK 0x1f
  41
  42/* Return nonzero iff the domain's clock is active */
  43int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
  44{
  45        void __iomem *psc_base;
  46        u32 mdstat;
  47        struct davinci_soc_info *soc_info = &davinci_soc_info;
  48
  49        if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
  50                pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
  51                                (int)soc_info->psc_bases, ctlr);
  52                return 0;
  53        }
  54
  55        psc_base = soc_info->psc_bases[ctlr];
  56        mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
  57
  58        /* if clocked, state can be "Enable" or "SyncReset" */
  59        return mdstat & BIT(12);
  60}
  61
  62/* Enable or disable a PSC domain */
  63void davinci_psc_config(unsigned int domain, unsigned int ctlr,
  64                unsigned int id, char enable)
  65{
  66        u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
  67        void __iomem *psc_base;
  68        struct davinci_soc_info *soc_info = &davinci_soc_info;
  69        u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */
  70
  71        if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
  72                pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
  73                                (int)soc_info->psc_bases, ctlr);
  74                return;
  75        }
  76
  77        psc_base = soc_info->psc_bases[ctlr];
  78
  79        mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
  80        mdctl &= ~MDSTAT_STATE_MASK;
  81        mdctl |= next_state;
  82        __raw_writel(mdctl, psc_base + MDCTL + 4 * id);
  83
  84        pdstat = __raw_readl(psc_base + PDSTAT);
  85        if ((pdstat & 0x00000001) == 0) {
  86                pdctl1 = __raw_readl(psc_base + PDCTL1);
  87                pdctl1 |= 0x1;
  88                __raw_writel(pdctl1, psc_base + PDCTL1);
  89
  90                ptcmd = 1 << domain;
  91                __raw_writel(ptcmd, psc_base + PTCMD);
  92
  93                do {
  94                        epcpr = __raw_readl(psc_base + EPCPR);
  95                } while ((((epcpr >> domain) & 1) == 0));
  96
  97                pdctl1 = __raw_readl(psc_base + PDCTL1);
  98                pdctl1 |= 0x100;
  99                __raw_writel(pdctl1, psc_base + PDCTL1);
 100
 101                do {
 102                        ptstat = __raw_readl(psc_base +
 103                                               PTSTAT);
 104                } while (!(((ptstat >> domain) & 1) == 0));
 105        } else {
 106                ptcmd = 1 << domain;
 107                __raw_writel(ptcmd, psc_base + PTCMD);
 108
 109                do {
 110                        ptstat = __raw_readl(psc_base + PTSTAT);
 111                } while (!(((ptstat >> domain) & 1) == 0));
 112        }
 113
 114        do {
 115                mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
 116        } while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
 117}
 118