Apex performance ioctl

Change-Id: Id3ae759f748b3f8c6f6a5320a5088c43fad0e812
This commit is contained in:
Alex Van Damme
2018-07-23 16:06:02 -07:00
parent d737e80b17
commit 237454b288
2 changed files with 85 additions and 0 deletions

15
apex.h
View File

@@ -77,6 +77,19 @@ struct apex_gate_clock_ioctl {
u64 force_idle;
};
/* Performance expectation ioctl. */
enum apex_performance_expectation {
APEX_PERFORMANCE_LOW = 0,
APEX_PERFORMANCE_MED = 1,
APEX_PERFORMANCE_HIGH = 2,
APEX_PERFORMANCE_MAX = 3,
};
struct apex_performance_expectation_ioctl {
/* Expected performance from apex. */
uint32_t performance;
};
/* Base number for all Apex-common IOCTLs */
#define APEX_IOCTL_BASE 0x7F
@@ -84,4 +97,6 @@ struct apex_gate_clock_ioctl {
#define APEX_IOCTL_GATE_CLOCK \
_IOW(APEX_IOCTL_BASE, 0, struct apex_gate_clock_ioctl)
#define APEX_IOCTL_PERFORMANCE_EXPECTATION _IOW(APEX_IOCTL_BASE, 1, struct apex_performance_expectation_ioctl)
#endif /* __APEX_H__ */

View File

@@ -146,6 +146,8 @@ static long apex_ioctl(struct file *file, uint cmd, ulong arg);
static long apex_clock_gating(struct gasket_dev *gasket_dev, ulong arg);
static long apex_set_performance_expectation(struct gasket_dev *gasket_dev, ulong arg);
static int apex_enter_reset(struct gasket_dev *gasket_dev, uint type);
static int apex_quit_reset(struct gasket_dev *gasket_dev, uint type);
@@ -652,6 +654,8 @@ static long apex_ioctl(struct file *filp, uint cmd, ulong arg)
switch (cmd) {
case APEX_IOCTL_GATE_CLOCK:
return apex_clock_gating(gasket_dev, arg);
case APEX_IOCTL_PERFORMANCE_EXPECTATION:
return apex_set_performance_expectation(gasket_dev, arg);
default:
return -ENOTTY; /* unknown command */
}
@@ -697,6 +701,72 @@ static long apex_clock_gating(struct gasket_dev *gasket_dev, ulong arg)
return 0;
}
/*
* apex_set_performance_expectation: Adjust clock rates for Apex.
* @gasket_dev: device pointer.
* @arg: User ioctl arg, in this case to an apex_performance_expectation_ioctl struct.
*/
static long apex_set_performance_expectation(struct gasket_dev *gasket_dev, ulong arg)
{
struct apex_performance_expectation_ioctl ibuf;
uint32_t rg_gcb_clk_div = 0;
uint32_t rg_axi_clk_125m = 0;
const int AXI_CLK_125M_SHIFT = 2;
const int MCU_CLK_250M_SHIFT = 3;
// 8051 clock is always 250 MHz for PCIe, as it's not used at all.
const uint32_t rg_8051_clk_250m = 1;
if (bypass_top_level)
return 0;
if (copy_from_user(&ibuf, (void __user *)arg, sizeof(ibuf)))
return -EFAULT;
switch (ibuf.performance) {
case APEX_PERFORMANCE_LOW:
// - GCB clock: 62.5 MHz
// - AXI clock: 125 MHz
rg_gcb_clk_div = 3;
rg_axi_clk_125m = 0;
break;
case APEX_PERFORMANCE_MED:
// - GCB clock: 125 MHz
// - AXI clock: 125 MHz
rg_gcb_clk_div = 2;
rg_axi_clk_125m = 0;
break;
case APEX_PERFORMANCE_HIGH:
// - GCB clock: 250 MHz
// - AXI clock: 125 MHz
rg_gcb_clk_div = 1;
rg_axi_clk_125m = 0;
break;
case APEX_PERFORMANCE_MAX:
// - GCB clock: 500 MHz
// - AXI clock: 125 MHz
rg_gcb_clk_div = 0;
rg_axi_clk_125m = 0;
break;
default:
return -EINVAL;
}
/*
* Set clock rates for GCB, AXI, and 8051:
*/
gasket_read_modify_write_32(
gasket_dev, APEX_BAR_INDEX, APEX_BAR2_REG_SCU_3,
(rg_gcb_clk_div | (rg_axi_clk_125m << AXI_CLK_125M_SHIFT) | (rg_8051_clk_250m << MCU_CLK_250M_SHIFT)),
/*mask_width=*/4, /*mask_shift=*/28);
return 0;
}
/*
* Display driver sysfs entries.
* @device: Kernel device structure.