From 237454b288960eb5120ca26529084a59a6b96b9a Mon Sep 17 00:00:00 2001 From: Alex Van Damme Date: Mon, 23 Jul 2018 16:06:02 -0700 Subject: [PATCH] Apex performance ioctl Change-Id: Id3ae759f748b3f8c6f6a5320a5088c43fad0e812 --- apex.h | 15 +++++++++++ apex_driver.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/apex.h b/apex.h index 4ef2641..7279589 100644 --- a/apex.h +++ b/apex.h @@ -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__ */ diff --git a/apex_driver.c b/apex_driver.c index 3a83c3d..b25f763 100644 --- a/apex_driver.c +++ b/apex_driver.c @@ -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.