Skip to content
67 changes: 38 additions & 29 deletions drivers/clk/bcm/clk-raspberrypi.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ const struct raspberrypi_clk_data *clk_hw_to_data(const struct clk_hw *hw)
struct raspberrypi_clk_variant {
bool export;
char *clkdev;
unsigned long min_rate;
u32 min_rate;
u32 max_rate;
bool minimize;
bool maximize;
u32 flags;
Expand Down Expand Up @@ -141,17 +142,17 @@ raspberrypi_clk_variants[RPI_FIRMWARE_NUM_CLK_ID] = {
[RPI_FIRMWARE_PIXEL_CLK_ID] = {
.export = true,
.minimize = true,
.flags = CLK_IS_CRITICAL,
.flags = CLK_IGNORE_UNUSED,
},
[RPI_FIRMWARE_HEVC_CLK_ID] = {
.export = true,
.minimize = true,
.flags = CLK_IS_CRITICAL,
.flags = CLK_IGNORE_UNUSED,
},
[RPI_FIRMWARE_ISP_CLK_ID] = {
.export = true,
.minimize = true,
.flags = CLK_IS_CRITICAL,
.flags = CLK_IGNORE_UNUSED,
},
[RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = {
.export = true,
Expand Down Expand Up @@ -290,27 +291,42 @@ static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
static int raspberrypi_fw_prepare(struct clk_hw *hw)
{
const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk_variant *variant = data->variant;
struct raspberrypi_clk *rpi = data->rpi;
u32 state = RPI_FIRMWARE_STATE_ENABLE_BIT;
int ret;

ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_SET_CLOCK_STATE, &state);
if (ret)
if (ret) {
dev_err_ratelimited(rpi->dev,
"Failed to set clock %s state to on: %d\n",
clk_hw_get_name(hw), ret);
return ret;
}

if (variant->maximize)
ret = raspberrypi_fw_set_rate(hw, variant->max_rate, 0);

return ret;
}

static void raspberrypi_fw_unprepare(struct clk_hw *hw)
{
const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
struct raspberrypi_clk_variant *variant = data->variant;
struct raspberrypi_clk *rpi = data->rpi;
u32 state = 0;
int ret;

/*
* On current firmware versions, RPI_FIRMWARE_SET_CLOCK_STATE doesn't
* actually power off the clock. To achieve meaningful power consumption
* reduction, the driver needs to set the clock rate to minimum before
* disabling it.
*/
raspberrypi_fw_set_rate(hw, variant->min_rate, 0);

ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_SET_CLOCK_STATE, &state);
if (ret)
Expand All @@ -335,7 +351,7 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
{
struct raspberrypi_clk_data *data;
struct clk_init_data init = {};
u32 min_rate, max_rate;
unsigned long rate;
int ret;

data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL);
Expand All @@ -355,18 +371,20 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,

data->hw.init = &init;

ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
&min_rate);
if (ret) {
dev_err(rpi->dev, "Failed to get clock %d min freq: %d\n",
id, ret);
return ERR_PTR(ret);
if (!variant->min_rate) {
ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_MIN_CLOCK_RATE,
&variant->min_rate);
if (ret) {
dev_err(rpi->dev, "Failed to get clock %d min freq: %d\n",
id, ret);
return ERR_PTR(ret);
}
}

ret = raspberrypi_clock_property(rpi->firmware, data,
RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
&max_rate);
&variant->max_rate);
if (ret) {
dev_err(rpi->dev, "Failed to get clock %d max freq: %d\n",
id, ret);
Expand All @@ -377,7 +395,7 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
if (ret)
return ERR_PTR(ret);

clk_hw_set_rate_range(&data->hw, min_rate, max_rate);
clk_hw_set_rate_range(&data->hw, variant->min_rate, variant->max_rate);

if (variant->clkdev) {
ret = devm_clk_hw_register_clkdev(rpi->dev, &data->hw,
Expand All @@ -388,20 +406,11 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
}
}

if (variant->maximize)
variant->min_rate = max_rate;

if (variant->min_rate) {
unsigned long rate;

clk_hw_set_rate_range(&data->hw, variant->min_rate, max_rate);

rate = raspberrypi_fw_get_rate(&data->hw, 0);
if (rate < variant->min_rate) {
ret = raspberrypi_fw_set_rate(&data->hw, variant->min_rate, 0);
if (ret)
return ERR_PTR(ret);
}
rate = raspberrypi_fw_get_rate(&data->hw, 0);
if (rate < variant->min_rate) {
ret = raspberrypi_fw_set_rate(&data->hw, variant->min_rate, 0);
if (ret)
return ERR_PTR(ret);
}

return &data->hw;
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/v3d/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ v3d-y := \
v3d_sched.o \
v3d_sysfs.o \
v3d_submit.o \
v3d_gemfs.o
v3d_gemfs.o \
v3d_power.o

v3d-$(CONFIG_DEBUG_FS) += v3d_debugfs.o

Expand Down
23 changes: 21 additions & 2 deletions drivers/gpu/drm/v3d/v3d_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@ static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
struct drm_debugfs_entry *entry = m->private;
struct drm_device *dev = entry->dev;
struct v3d_dev *v3d = to_v3d_dev(dev);
int i, core;
int i, core, ret;

ret = v3d_pm_runtime_get(v3d);
if (ret)
return ret;

for (i = 0; i < ARRAY_SIZE(v3d_hub_reg_defs); i++) {
const struct v3d_reg_def *def = &v3d_hub_reg_defs[i];
Expand Down Expand Up @@ -138,6 +142,8 @@ static int v3d_v3d_debugfs_regs(struct seq_file *m, void *unused)
}
}

v3d_pm_runtime_put(v3d);

return 0;
}

Expand All @@ -147,7 +153,11 @@ static int v3d_v3d_debugfs_ident(struct seq_file *m, void *unused)
struct drm_device *dev = entry->dev;
struct v3d_dev *v3d = to_v3d_dev(dev);
u32 ident0, ident1, ident2, ident3, cores;
int core;
int core, ret;

ret = v3d_pm_runtime_get(v3d);
if (ret)
return ret;

ident0 = V3D_READ(V3D_HUB_IDENT0);
ident1 = V3D_READ(V3D_HUB_IDENT1);
Expand Down Expand Up @@ -206,6 +216,8 @@ static int v3d_v3d_debugfs_ident(struct seq_file *m, void *unused)
}
}

v3d_pm_runtime_put(v3d);

return 0;
}

Expand Down Expand Up @@ -233,6 +245,11 @@ static int v3d_measure_clock(struct seq_file *m, void *unused)
uint32_t cycles;
int core = 0;
int measure_ms = 1000;
int ret;

ret = v3d_pm_runtime_get(v3d);
if (ret)
return ret;

if (v3d->ver >= V3D_GEN_41) {
int cycle_count_reg = V3D_PCTR_CYCLE_COUNT(v3d->ver);
Expand All @@ -252,6 +269,8 @@ static int v3d_measure_clock(struct seq_file *m, void *unused)
msleep(measure_ms);
cycles = V3D_CORE_READ(core, V3D_PCTR_0_PCTR0);

v3d_pm_runtime_put(v3d);

seq_printf(m, "cycles: %d (%d.%d Mhz)\n",
cycles,
cycles / (measure_ms * 1000),
Expand Down
Loading
Loading