cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vss.c (2245B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Au1300 media block power gating (VSS)
      4 *
      5 * This is a stop-gap solution until I have the clock framework integration
      6 * ready. This stuff here really must be handled transparently when clocks
      7 * for various media blocks are enabled/disabled.
      8 */
      9
     10#include <linux/export.h>
     11#include <linux/spinlock.h>
     12#include <asm/mach-au1x00/au1000.h>
     13
     14#define VSS_GATE	0x00	/* gate wait timers */
     15#define VSS_CLKRST	0x04	/* clock/block control */
     16#define VSS_FTR		0x08	/* footers */
     17
     18#define VSS_ADDR(blk)	(KSEG1ADDR(AU1300_VSS_PHYS_ADDR) + (blk * 0x0c))
     19
     20static DEFINE_SPINLOCK(au1300_vss_lock);
     21
     22/* enable a block as outlined in the databook */
     23static inline void __enable_block(int block)
     24{
     25	void __iomem *base = (void __iomem *)VSS_ADDR(block);
     26
     27	__raw_writel(3, base + VSS_CLKRST);	/* enable clock, assert reset */
     28	wmb();
     29
     30	__raw_writel(0x01fffffe, base + VSS_GATE); /* maximum setup time */
     31	wmb();
     32
     33	/* enable footers in sequence */
     34	__raw_writel(0x01, base + VSS_FTR);
     35	wmb();
     36	__raw_writel(0x03, base + VSS_FTR);
     37	wmb();
     38	__raw_writel(0x07, base + VSS_FTR);
     39	wmb();
     40	__raw_writel(0x0f, base + VSS_FTR);
     41	wmb();
     42
     43	__raw_writel(0x01ffffff, base + VSS_GATE); /* start FSM too */
     44	wmb();
     45
     46	__raw_writel(2, base + VSS_CLKRST);	/* deassert reset */
     47	wmb();
     48
     49	__raw_writel(0x1f, base + VSS_FTR);	/* enable isolation cells */
     50	wmb();
     51}
     52
     53/* disable a block as outlined in the databook */
     54static inline void __disable_block(int block)
     55{
     56	void __iomem *base = (void __iomem *)VSS_ADDR(block);
     57
     58	__raw_writel(0x0f, base + VSS_FTR);	/* disable isolation cells */
     59	wmb();
     60	__raw_writel(0, base + VSS_GATE);	/* disable FSM */
     61	wmb();
     62	__raw_writel(3, base + VSS_CLKRST);	/* assert reset */
     63	wmb();
     64	__raw_writel(1, base + VSS_CLKRST);	/* disable clock */
     65	wmb();
     66	__raw_writel(0, base + VSS_FTR);	/* disable all footers */
     67	wmb();
     68}
     69
     70void au1300_vss_block_control(int block, int enable)
     71{
     72	unsigned long flags;
     73
     74	if (alchemy_get_cputype() != ALCHEMY_CPU_AU1300)
     75		return;
     76
     77	/* only one block at a time */
     78	spin_lock_irqsave(&au1300_vss_lock, flags);
     79	if (enable)
     80		__enable_block(block);
     81	else
     82		__disable_block(block);
     83	spin_unlock_irqrestore(&au1300_vss_lock, flags);
     84}
     85EXPORT_SYMBOL_GPL(au1300_vss_block_control);