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