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/init.h> 23#include <linux/io.h> 24 25#include <mach/cputype.h> 26#include <mach/psc.h> 27 28#include "clock.h" 29 30/* Return nonzero iff the domain's clock is active */ 31int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) 32{ 33 void __iomem *psc_base; 34 u32 mdstat; 35 struct davinci_soc_info *soc_info = &davinci_soc_info; 36 37 if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { 38 pr_warn("PSC: Bad psc data: 0x%x[%d]\n", 39 (int)soc_info->psc_bases, ctlr); 40 return 0; 41 } 42 43 psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); 44 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); 45 iounmap(psc_base); 46 47 /* if clocked, state can be "Enable" or "SyncReset" */ 48 return mdstat & BIT(12); 49} 50 51/* Control "reset" line associated with PSC domain */ 52void davinci_psc_reset(unsigned int ctlr, unsigned int id, bool reset) 53{ 54 u32 mdctl; 55 void __iomem *psc_base; 56 struct davinci_soc_info *soc_info = &davinci_soc_info; 57 58 if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { 59 pr_warn("PSC: Bad psc data: 0x%x[%d]\n", 60 (int)soc_info->psc_bases, ctlr); 61 return; 62 } 63 64 psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); 65 66 mdctl = readl(psc_base + MDCTL + 4 * id); 67 if (reset) 68 mdctl &= ~MDCTL_LRST; 69 else 70 mdctl |= MDCTL_LRST; 71 writel(mdctl, psc_base + MDCTL + 4 * id); 72 73 iounmap(psc_base); 74} 75 76/* Enable or disable a PSC domain */ 77void davinci_psc_config(unsigned int domain, unsigned int ctlr, 78 unsigned int id, bool enable, u32 flags) 79{ 80 u32 epcpr, ptcmd, ptstat, pdstat, pdctl, mdstat, mdctl; 81 void __iomem *psc_base; 82 struct davinci_soc_info *soc_info = &davinci_soc_info; 83 u32 next_state = PSC_STATE_ENABLE; 84 85 if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { 86 pr_warn("PSC: Bad psc data: 0x%x[%d]\n", 87 (int)soc_info->psc_bases, ctlr); 88 return; 89 } 90 91 psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); 92 93 if (!enable) { 94 if (flags & PSC_SWRSTDISABLE) 95 next_state = PSC_STATE_SWRSTDISABLE; 96 else 97 next_state = PSC_STATE_DISABLE; 98 } 99 100 mdctl = __raw_readl(psc_base + MDCTL + 4 * id); 101 mdctl &= ~MDSTAT_STATE_MASK; 102 mdctl |= next_state; 103 if (flags & PSC_FORCE) 104 mdctl |= MDCTL_FORCE; 105 __raw_writel(mdctl, psc_base + MDCTL + 4 * id); 106 107 pdstat = __raw_readl(psc_base + PDSTAT + 4 * domain); 108 if ((pdstat & PDSTAT_STATE_MASK) == 0) { 109 pdctl = __raw_readl(psc_base + PDCTL + 4 * domain); 110 pdctl |= PDCTL_NEXT; 111 __raw_writel(pdctl, psc_base + PDCTL + 4 * domain); 112 113 ptcmd = 1 << domain; 114 __raw_writel(ptcmd, psc_base + PTCMD); 115 116 do { 117 epcpr = __raw_readl(psc_base + EPCPR); 118 } while ((((epcpr >> domain) & 1) == 0)); 119 120 pdctl = __raw_readl(psc_base + PDCTL + 4 * domain); 121 pdctl |= PDCTL_EPCGOOD; 122 __raw_writel(pdctl, psc_base + PDCTL + 4 * domain); 123 } else { 124 ptcmd = 1 << domain; 125 __raw_writel(ptcmd, psc_base + PTCMD); 126 } 127 128 do { 129 ptstat = __raw_readl(psc_base + PTSTAT); 130 } while (!(((ptstat >> domain) & 1) == 0)); 131 132 do { 133 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); 134 } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); 135 136 iounmap(psc_base); 137} 138