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

lima_pmu.c (2656B)


      1// SPDX-License-Identifier: GPL-2.0 OR MIT
      2/* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
      3
      4#include <linux/iopoll.h>
      5#include <linux/device.h>
      6
      7#include "lima_device.h"
      8#include "lima_pmu.h"
      9#include "lima_regs.h"
     10
     11#define pmu_write(reg, data) writel(data, ip->iomem + reg)
     12#define pmu_read(reg) readl(ip->iomem + reg)
     13
     14static int lima_pmu_wait_cmd(struct lima_ip *ip)
     15{
     16	struct lima_device *dev = ip->dev;
     17	int err;
     18	u32 v;
     19
     20	err = readl_poll_timeout(ip->iomem + LIMA_PMU_INT_RAWSTAT,
     21				 v, v & LIMA_PMU_INT_CMD_MASK,
     22				 100, 100000);
     23	if (err) {
     24		dev_err(dev->dev, "timeout wait pmu cmd\n");
     25		return err;
     26	}
     27
     28	pmu_write(LIMA_PMU_INT_CLEAR, LIMA_PMU_INT_CMD_MASK);
     29	return 0;
     30}
     31
     32static u32 lima_pmu_get_ip_mask(struct lima_ip *ip)
     33{
     34	struct lima_device *dev = ip->dev;
     35	u32 ret = 0;
     36	int i;
     37
     38	ret |= LIMA_PMU_POWER_GP0_MASK;
     39
     40	if (dev->id == lima_gpu_mali400) {
     41		ret |= LIMA_PMU_POWER_L2_MASK;
     42		for (i = 0; i < 4; i++) {
     43			if (dev->ip[lima_ip_pp0 + i].present)
     44				ret |= LIMA_PMU_POWER_PP_MASK(i);
     45		}
     46	} else {
     47		if (dev->ip[lima_ip_pp0].present)
     48			ret |= LIMA450_PMU_POWER_PP0_MASK;
     49		for (i = lima_ip_pp1; i <= lima_ip_pp3; i++) {
     50			if (dev->ip[i].present) {
     51				ret |= LIMA450_PMU_POWER_PP13_MASK;
     52				break;
     53			}
     54		}
     55		for (i = lima_ip_pp4; i <= lima_ip_pp7; i++) {
     56			if (dev->ip[i].present) {
     57				ret |= LIMA450_PMU_POWER_PP47_MASK;
     58				break;
     59			}
     60		}
     61	}
     62
     63	return ret;
     64}
     65
     66static int lima_pmu_hw_init(struct lima_ip *ip)
     67{
     68	int err;
     69	u32 stat;
     70
     71	pmu_write(LIMA_PMU_INT_MASK, 0);
     72
     73	/* If this value is too low, when in high GPU clk freq,
     74	 * GPU will be in unstable state.
     75	 */
     76	pmu_write(LIMA_PMU_SW_DELAY, 0xffff);
     77
     78	/* status reg 1=off 0=on */
     79	stat = pmu_read(LIMA_PMU_STATUS);
     80
     81	/* power up all ip */
     82	if (stat) {
     83		pmu_write(LIMA_PMU_POWER_UP, stat);
     84		err = lima_pmu_wait_cmd(ip);
     85		if (err)
     86			return err;
     87	}
     88	return 0;
     89}
     90
     91static void lima_pmu_hw_fini(struct lima_ip *ip)
     92{
     93	u32 stat;
     94
     95	if (!ip->data.mask)
     96		ip->data.mask = lima_pmu_get_ip_mask(ip);
     97
     98	stat = ~pmu_read(LIMA_PMU_STATUS) & ip->data.mask;
     99	if (stat) {
    100		pmu_write(LIMA_PMU_POWER_DOWN, stat);
    101
    102		/* Don't wait for interrupt on Mali400 if all domains are
    103		 * powered off because the HW won't generate an interrupt
    104		 * in this case.
    105		 */
    106		if (ip->dev->id == lima_gpu_mali400)
    107			pmu_write(LIMA_PMU_INT_CLEAR, LIMA_PMU_INT_CMD_MASK);
    108		else
    109			lima_pmu_wait_cmd(ip);
    110	}
    111}
    112
    113int lima_pmu_resume(struct lima_ip *ip)
    114{
    115	return lima_pmu_hw_init(ip);
    116}
    117
    118void lima_pmu_suspend(struct lima_ip *ip)
    119{
    120	lima_pmu_hw_fini(ip);
    121}
    122
    123int lima_pmu_init(struct lima_ip *ip)
    124{
    125	return lima_pmu_hw_init(ip);
    126}
    127
    128void lima_pmu_fini(struct lima_ip *ip)
    129{
    130	lima_pmu_hw_fini(ip);
    131}