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/* Return nonzero iff the domain's clock is active */ 29int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id) 30{ 31 void __iomem *psc_base; 32 u32 mdstat; 33 struct davinci_soc_info *soc_info = &davinci_soc_info; 34 35 if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { 36 pr_warning("PSC: Bad psc data: 0x%x[%d]\n", 37 (int)soc_info->psc_bases, ctlr); 38 return 0; 39 } 40 41 psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); 42 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); 43 iounmap(psc_base); 44 45 /* if clocked, state can be "Enable" or "SyncReset" */ 46 return mdstat & BIT(12); 47} 48 49/* Enable or disable a PSC domain */ 50void davinci_psc_config(unsigned int domain, unsigned int ctlr, 51 unsigned int id, u32 next_state) 52{ 53 u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl; 54 void __iomem *psc_base; 55 struct davinci_soc_info *soc_info = &davinci_soc_info; 56 57 if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) { 58 pr_warning("PSC: Bad psc data: 0x%x[%d]\n", 59 (int)soc_info->psc_bases, ctlr); 60 return; 61 } 62 63 psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K); 64 65 mdctl = __raw_readl(psc_base + MDCTL + 4 * id); 66 mdctl &= ~MDSTAT_STATE_MASK; 67 mdctl |= next_state; 68 __raw_writel(mdctl, psc_base + MDCTL + 4 * id); 69 70 pdstat = __raw_readl(psc_base + PDSTAT); 71 if ((pdstat & 0x00000001) == 0) { 72 pdctl1 = __raw_readl(psc_base + PDCTL1); 73 pdctl1 |= 0x1; 74 __raw_writel(pdctl1, psc_base + PDCTL1); 75 76 ptcmd = 1 << domain; 77 __raw_writel(ptcmd, psc_base + PTCMD); 78 79 do { 80 epcpr = __raw_readl(psc_base + EPCPR); 81 } while ((((epcpr >> domain) & 1) == 0)); 82 83 pdctl1 = __raw_readl(psc_base + PDCTL1); 84 pdctl1 |= 0x100; 85 __raw_writel(pdctl1, psc_base + PDCTL1); 86 87 do { 88 ptstat = __raw_readl(psc_base + 89 PTSTAT); 90 } while (!(((ptstat >> domain) & 1) == 0)); 91 } else { 92 ptcmd = 1 << domain; 93 __raw_writel(ptcmd, psc_base + PTCMD); 94 95 do { 96 ptstat = __raw_readl(psc_base + PTSTAT); 97 } while (!(((ptstat >> domain) & 1) == 0)); 98 } 99 100 do { 101 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id); 102 } while (!((mdstat & MDSTAT_STATE_MASK) == next_state)); 103 104 iounmap(psc_base); 105} 106