linux/arch/arm/mach-cns3xxx/pm.c
<<
>>
Prefs
   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);
 121