1/* 2 * Copyright 2008 Cavium Networks 3 * 4 * This file is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License, Version 2, as 6 * published by the Free Software Foundation. 7 */ 8 9#include <linux/init.h> 10#include <linux/module.h> 11#include <linux/io.h> 12#include <linux/delay.h> 13#include <linux/atomic.h> 14#include "cns3xxx.h" 15#include "pm.h" 16#include "core.h" 17 18void cns3xxx_pwr_clk_en(unsigned int block) 19{ 20 u32 reg = __raw_readl(PM_CLK_GATE_REG); 21 22 reg |= (block & PM_CLK_GATE_REG_MASK); 23 __raw_writel(reg, PM_CLK_GATE_REG); 24} 25EXPORT_SYMBOL(cns3xxx_pwr_clk_en); 26 27void cns3xxx_pwr_clk_dis(unsigned int block) 28{ 29 u32 reg = __raw_readl(PM_CLK_GATE_REG); 30 31 reg &= ~(block & PM_CLK_GATE_REG_MASK); 32 __raw_writel(reg, PM_CLK_GATE_REG); 33} 34EXPORT_SYMBOL(cns3xxx_pwr_clk_dis); 35 36void cns3xxx_pwr_power_up(unsigned int block) 37{ 38 u32 reg = __raw_readl(PM_PLL_HM_PD_CTRL_REG); 39 40 reg &= ~(block & CNS3XXX_PWR_PLL_ALL); 41 __raw_writel(reg, PM_PLL_HM_PD_CTRL_REG); 42 43 /* Wait for 300us for the PLL output clock locked. */ 44 udelay(300); 45}; 46EXPORT_SYMBOL(cns3xxx_pwr_power_up); 47 48void cns3xxx_pwr_power_down(unsigned int block) 49{ 50 u32 reg = __raw_readl(PM_PLL_HM_PD_CTRL_REG); 51 52 /* write '1' to power down */ 53 reg |= (block & CNS3XXX_PWR_PLL_ALL); 54 __raw_writel(reg, PM_PLL_HM_PD_CTRL_REG); 55}; 56EXPORT_SYMBOL(cns3xxx_pwr_power_down); 57 58static void cns3xxx_pwr_soft_rst_force(unsigned int block) 59{ 60 u32 reg = __raw_readl(PM_SOFT_RST_REG); 61 62 /* 63 * bit 0, 28, 29 => program low to reset, 64 * the other else program low and then high 65 */ 66 if (block & 0x30000001) { 67 reg &= ~(block & PM_SOFT_RST_REG_MASK); 68 } else { 69 reg &= ~(block & PM_SOFT_RST_REG_MASK); 70 __raw_writel(reg, PM_SOFT_RST_REG); 71 reg |= (block & PM_SOFT_RST_REG_MASK); 72 } 73 74 __raw_writel(reg, PM_SOFT_RST_REG); 75} 76 77void cns3xxx_pwr_soft_rst(unsigned int block) 78{ 79 static unsigned int soft_reset; 80 81 if (soft_reset & block) { 82 /* SPI/I2C/GPIO use the same block, reset once. */ 83 return; 84 } else { 85 soft_reset |= block; 86 } 87 cns3xxx_pwr_soft_rst_force(block); 88} 89EXPORT_SYMBOL(cns3xxx_pwr_soft_rst); 90 91void cns3xxx_restart(enum reboot_mode mode, const char *cmd) 92{ 93 /* 94 * To reset, we hit the on-board reset register 95 * in the system FPGA. 96 */ 97 cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(GLOBAL)); 98} 99 100/* 101 * cns3xxx_cpu_clock - return CPU/L2 clock 102 * aclk: cpu clock/2 103 * hclk: cpu clock/4 104 * pclk: cpu clock/8 105 */ 106int cns3xxx_cpu_clock(void) 107{ 108 u32 reg = __raw_readl(PM_CLK_CTRL_REG); 109 int cpu; 110 int cpu_sel; 111 int div_sel; 112 113 cpu_sel = (reg >> PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL) & 0xf; 114 div_sel = (reg >> PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV) & 0x3; 115 116 cpu = (300 + ((cpu_sel / 3) * 100) + ((cpu_sel % 3) * 33)) >> div_sel; 117 118 return cpu; 119} 120EXPORT_SYMBOL(cns3xxx_cpu_clock); 121 122atomic_t usb_pwr_ref = ATOMIC_INIT(0); 123EXPORT_SYMBOL(usb_pwr_ref); 124