blob: 4ef182a297f04d83ec238d12c0f3aced53a50ffc [file] [log] [blame]
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef __KGSL_GMU_H
#define __KGSL_GMU_H
#include "kgsl_hfi.h"
#define FW_VER_MAJOR(ver) (((ver)>>28) & 0xFF)
#define FW_VER_MINOR(ver) (((ver)>>16) & 0xFFF)
#define FW_VERSION(major, minor) \
(((major) << 28) | (((minor) & 0xFFF) << 16))
#define GMU_INT_WDOG_BITE BIT(0)
#define GMU_INT_RSCC_COMP BIT(1)
#define GMU_INT_FENCE_ERR BIT(3)
#define GMU_INT_DBD_WAKEUP BIT(4)
#define GMU_INT_HOST_AHB_BUS_ERR BIT(5)
#define GMU_AO_INT_MASK \
(GMU_INT_WDOG_BITE | \
GMU_INT_HOST_AHB_BUS_ERR | \
GMU_INT_FENCE_ERR)
#define MAX_GMUFW_SIZE 0x2000 /* in bytes */
#define FENCE_RANGE_MASK ((0x1 << 31) | ((0xA << 2) << 18) | (0x8A0))
#define FENCE_STATUS_WRITEDROPPED0_MASK 0x1
#define FENCE_STATUS_WRITEDROPPED1_MASK 0x2
/* Bitmask for GPU low power mode enabling and hysterisis*/
#define SPTP_ENABLE_MASK (BIT(2) | BIT(0))
#define IFPC_ENABLE_MASK (BIT(1) | BIT(0))
#define HW_NAP_ENABLE_MASK BIT(0)
#define MIN_BW_ENABLE_MASK BIT(12)
#define MIN_BW_HYST 0xFA0
/* Bitmask for RPMH capability enabling */
#define RPMH_INTERFACE_ENABLE BIT(0)
#define LLC_VOTE_ENABLE BIT(4)
#define DDR_VOTE_ENABLE BIT(8)
#define MX_VOTE_ENABLE BIT(9)
#define CX_VOTE_ENABLE BIT(10)
#define GFX_VOTE_ENABLE BIT(11)
#define RPMH_ENABLE_MASK (RPMH_INTERFACE_ENABLE | \
LLC_VOTE_ENABLE | \
DDR_VOTE_ENABLE | \
MX_VOTE_ENABLE | \
CX_VOTE_ENABLE | \
GFX_VOTE_ENABLE)
/* Bitmask for GPU idle status check */
#define GPUBUSYIGNAHB BIT(23)
#define CXGXCPUBUSYIGNAHB BIT(30)
/* GMU timeouts */
#define GMU_IDLE_TIMEOUT 100 /* ms */
/* Constants for GMU OOBs */
#define OOB_BOOT_OPTION 0
#define OOB_SLUMBER_OPTION 1
/* Bitmasks for GMU OOBs */
#define OOB_BOOT_SLUMBER_SET_MASK BIT(22)
#define OOB_BOOT_SLUMBER_CHECK_MASK BIT(30)
#define OOB_BOOT_SLUMBER_CLEAR_MASK BIT(30)
#define OOB_DCVS_SET_MASK BIT(23)
#define OOB_DCVS_CHECK_MASK BIT(31)
#define OOB_DCVS_CLEAR_MASK BIT(31)
#define OOB_GPU_SET_MASK BIT(16)
#define OOB_GPU_CHECK_MASK BIT(24)
#define OOB_GPU_CLEAR_MASK BIT(24)
#define OOB_PERFCNTR_SET_MASK BIT(17)
#define OOB_PERFCNTR_CHECK_MASK BIT(25)
#define OOB_PERFCNTR_CLEAR_MASK BIT(25)
#define OOB_PREEMPTION_SET_MASK BIT(18)
#define OOB_PREEMPTION_CHECK_MASK BIT(26)
#define OOB_PREEMPTION_CLEAR_MASK BIT(26)
/*
* Wait time before trying to write the register again.
* Hopefully the GMU has finished waking up during this delay.
* This delay must be less than the IFPC main hysteresis or
* the GMU will start shutting down before we try again.
*/
#define GMU_WAKEUP_DELAY_US 10
/* Max amount of tries to wake up the GMU. */
#define GMU_WAKEUP_RETRY_MAX 60
/* Bits for the flags field in the gmu structure */
enum gmu_flags {
GMU_BOOT_INIT_DONE = 0,
GMU_CLK_ON = 1,
GMU_HFI_ON = 2,
GMU_FAULT = 3,
GMU_DCVS_REPLAY = 4,
GMU_RSCC_SLEEP_SEQ_DONE = 5,
};
/**
* struct gmu_memdesc - Gmu shared memory object descriptor
* @hostptr: Kernel virtual address
* @gmuaddr: GPU virtual address
* @physaddr: Physical address of the memory object
* @size: Size of the memory object
* @attr: memory attributes for this memory
*/
struct gmu_memdesc {
void *hostptr;
uint64_t gmuaddr;
phys_addr_t physaddr;
uint64_t size;
uint32_t attr;
};
struct gmu_bw_votes {
uint32_t cmds_wait_bitmask;
uint32_t cmds_per_bw_vote;
uint32_t cmd_addrs[MAX_BW_CMDS];
uint32_t cmd_data[MAX_GX_LEVELS][MAX_BW_CMDS];
};
struct rpmh_votes_t {
struct arc_vote_desc gx_votes[MAX_GX_LEVELS];
struct arc_vote_desc cx_votes[MAX_CX_LEVELS];
struct gmu_bw_votes ddr_votes;
struct gmu_bw_votes cnoc_votes;
};
#define MAX_GMU_CLKS 6
#define DEFAULT_GMU_FREQ_IDX 1
/*
* These are the different ways the GMU can boot. GMU_WARM_BOOT is waking up
* from slumber. GMU_COLD_BOOT is booting for the first time.
*/
enum gmu_boot {
GMU_WARM_BOOT = 0,
GMU_COLD_BOOT = 1,
};
enum gmu_load_mode {
CACHED_LOAD_BOOT,
CACHED_BOOT,
TCM_BOOT,
TCM_LOAD_BOOT,
INVALID_LOAD
};
enum gmu_pwrctrl_mode {
GMU_FW_START,
GMU_FW_STOP,
GMU_SUSPEND,
GMU_DCVS_NOHFI,
GMU_NOTIFY_SLUMBER,
INVALID_POWER_CTRL
};
enum gpu_idle_level {
GPU_HW_ACTIVE = 0x0,
GPU_HW_SPTP_PC = 0x2,
GPU_HW_IFPC = 0x3,
GPU_HW_NAP = 0x4,
GPU_HW_MIN_VOLT = 0x5,
GPU_HW_MIN_DDR = 0x6,
GPU_HW_SLUMBER = 0xF
};
/**
* struct gmu_device - GMU device structure
* @ver: GMU FW version, read from GMU
* @reg_phys: GMU CSR physical address
* @reg_virt: GMU CSR virtual address
* @reg_len: GMU CSR range
* @gmu2gpu_offset: address difference between GMU register set
* and GPU register set, the offset will be used when accessing
* gmu registers using offset defined in GPU register space.
* @pdc_reg_virt: starting kernel virtual address for RPMh PDC registers
* @gmu_interrupt_num: GMU interrupt number
* @fw_image: descriptor of GMU memory that has GMU image in it
* @hfi_mem: pointer to HFI shared memory
* @dump_mem: pointer to GMU debug dump memory
* @hfi: HFI controller
* @lm_config: GPU LM configuration data
* @lm_dcvs_level: Minimal DCVS level that enable LM. LM disable in
* lower levels
* @bcl_config: Battery Current Limit configuration data
* @gmu_freqs: GMU frequency table with lowest freq at index 0
* @gpu_freqs: GPU frequency table with lowest freq at index 0
* @num_gmupwrlevels: number GMU frequencies in GMU freq table
* @num_gpupwrlevels: number GPU frequencies in GPU freq table
* @num_bwlevel: number of GPU BW levels
* @num_cnocbwlevel: number CNOC BW levels
* @rpmh_votes: RPMh TCS command set for GPU, GMU voltage and bw scaling
* @cx_gdsc: CX headswitch that controls power of GMU and
subsystem peripherals
* @gx_gdsc: GX headswitch that controls power of GPU subsystem
* @clks: GPU subsystem clocks required for GMU functionality
* @load_mode: GMU FW load/boot mode
* @flags: GMU power control flags
* @wakeup_pwrlevel: GPU wake up power/DCVS level in case different
* than default power level
* @pcl: GPU BW scaling client
* @ccl: CNOC BW scaling client
* @idle_level: Minimal GPU idle power level
* @fault_count: GMU fault count
*/
struct gmu_device {
unsigned int ver;
struct platform_device *pdev;
unsigned long reg_phys;
void __iomem *reg_virt;
unsigned int reg_len;
unsigned int gmu2gpu_offset;
void __iomem *pdc_reg_virt;
unsigned int gmu_interrupt_num;
struct gmu_memdesc fw_image;
struct gmu_memdesc *hfi_mem;
struct gmu_memdesc *dump_mem;
struct kgsl_hfi hfi;
struct limits_config lm_config;
unsigned int lm_dcvs_level;
unsigned int bcl_config;
unsigned int gmu_freqs[MAX_CX_LEVELS];
unsigned int gpu_freqs[MAX_GX_LEVELS];
unsigned int num_gmupwrlevels;
unsigned int num_gpupwrlevels;
unsigned int num_bwlevels;
unsigned int num_cnocbwlevels;
struct rpmh_votes_t rpmh_votes;
struct regulator *cx_gdsc;
struct regulator *gx_gdsc;
struct clk *clks[MAX_GMU_CLKS];
enum gmu_load_mode load_mode;
unsigned long flags;
unsigned int wakeup_pwrlevel;
unsigned int pcl;
unsigned int ccl;
unsigned int idle_level;
unsigned int fault_count;
};
void gmu_snapshot(struct kgsl_device *device);
bool kgsl_gmu_isenabled(struct kgsl_device *device);
int gmu_probe(struct kgsl_device *device);
void gmu_remove(struct kgsl_device *device);
int allocate_gmu_image(struct gmu_device *gmu, unsigned int size);
int gmu_start(struct kgsl_device *device);
void gmu_stop(struct kgsl_device *device);
int gmu_dcvs_set(struct gmu_device *gmu, unsigned int gpu_pwrlevel,
unsigned int bus_level);
#endif /* __KGSL_GMU_H */