Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2008 Cavium Networks
0004  */
0005 
0006 #include <linux/init.h>
0007 #include <linux/module.h>
0008 #include <linux/io.h>
0009 #include <linux/delay.h>
0010 #include <linux/atomic.h>
0011 #include "cns3xxx.h"
0012 #include "pm.h"
0013 #include "core.h"
0014 
0015 void cns3xxx_pwr_clk_en(unsigned int block)
0016 {
0017     u32 reg = __raw_readl(PM_CLK_GATE_REG);
0018 
0019     reg |= (block & PM_CLK_GATE_REG_MASK);
0020     __raw_writel(reg, PM_CLK_GATE_REG);
0021 }
0022 EXPORT_SYMBOL(cns3xxx_pwr_clk_en);
0023 
0024 void cns3xxx_pwr_clk_dis(unsigned int block)
0025 {
0026     u32 reg = __raw_readl(PM_CLK_GATE_REG);
0027 
0028     reg &= ~(block & PM_CLK_GATE_REG_MASK);
0029     __raw_writel(reg, PM_CLK_GATE_REG);
0030 }
0031 EXPORT_SYMBOL(cns3xxx_pwr_clk_dis);
0032 
0033 void cns3xxx_pwr_power_up(unsigned int block)
0034 {
0035     u32 reg = __raw_readl(PM_PLL_HM_PD_CTRL_REG);
0036 
0037     reg &= ~(block & CNS3XXX_PWR_PLL_ALL);
0038     __raw_writel(reg, PM_PLL_HM_PD_CTRL_REG);
0039 
0040     /* Wait for 300us for the PLL output clock locked. */
0041     udelay(300);
0042 };
0043 EXPORT_SYMBOL(cns3xxx_pwr_power_up);
0044 
0045 void cns3xxx_pwr_power_down(unsigned int block)
0046 {
0047     u32 reg = __raw_readl(PM_PLL_HM_PD_CTRL_REG);
0048 
0049     /* write '1' to power down */
0050     reg |= (block & CNS3XXX_PWR_PLL_ALL);
0051     __raw_writel(reg, PM_PLL_HM_PD_CTRL_REG);
0052 };
0053 EXPORT_SYMBOL(cns3xxx_pwr_power_down);
0054 
0055 static void cns3xxx_pwr_soft_rst_force(unsigned int block)
0056 {
0057     u32 reg = __raw_readl(PM_SOFT_RST_REG);
0058 
0059     /*
0060      * bit 0, 28, 29 => program low to reset,
0061      * the other else program low and then high
0062      */
0063     if (block & 0x30000001) {
0064         reg &= ~(block & PM_SOFT_RST_REG_MASK);
0065     } else {
0066         reg &= ~(block & PM_SOFT_RST_REG_MASK);
0067         __raw_writel(reg, PM_SOFT_RST_REG);
0068         reg |= (block & PM_SOFT_RST_REG_MASK);
0069     }
0070 
0071     __raw_writel(reg, PM_SOFT_RST_REG);
0072 }
0073 
0074 void cns3xxx_pwr_soft_rst(unsigned int block)
0075 {
0076     static unsigned int soft_reset;
0077 
0078     if (soft_reset & block) {
0079         /* SPI/I2C/GPIO use the same block, reset once. */
0080         return;
0081     } else {
0082         soft_reset |= block;
0083     }
0084     cns3xxx_pwr_soft_rst_force(block);
0085 }
0086 EXPORT_SYMBOL(cns3xxx_pwr_soft_rst);
0087 
0088 void cns3xxx_restart(enum reboot_mode mode, const char *cmd)
0089 {
0090     /*
0091      * To reset, we hit the on-board reset register
0092      * in the system FPGA.
0093      */
0094     cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(GLOBAL));
0095 }
0096 
0097 /*
0098  * cns3xxx_cpu_clock - return CPU/L2 clock
0099  *  aclk: cpu clock/2
0100  *  hclk: cpu clock/4
0101  *  pclk: cpu clock/8
0102  */
0103 int cns3xxx_cpu_clock(void)
0104 {
0105     u32 reg = __raw_readl(PM_CLK_CTRL_REG);
0106     int cpu;
0107     int cpu_sel;
0108     int div_sel;
0109 
0110     cpu_sel = (reg >> PM_CLK_CTRL_REG_OFFSET_PLL_CPU_SEL) & 0xf;
0111     div_sel = (reg >> PM_CLK_CTRL_REG_OFFSET_CPU_CLK_DIV) & 0x3;
0112 
0113     cpu = (300 + ((cpu_sel / 3) * 100) + ((cpu_sel % 3) * 33)) >> div_sel;
0114 
0115     return cpu;
0116 }
0117 EXPORT_SYMBOL(cns3xxx_cpu_clock);
0118 
0119 atomic_t usb_pwr_ref = ATOMIC_INIT(0);
0120 EXPORT_SYMBOL(usb_pwr_ref);