Commit 27f88d60 authored by Federico Vaga's avatar Federico Vaga Committed by Federico Vaga

sw:cpu: wait reset to happen before returning

The CPU needs time to change state (both direction). This patch adds a
timeout logic for that change to happen. If the change does not happen
within the timeout, then the driver returns a warning on the dmesg.

At this moment in time I'm not sure if it is worthy to actually return
an error. For now, to avoid API changes, we just print a warning.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 0ede1350
......@@ -17,6 +17,16 @@
#include <mockturtle/hw/mockturtle_cpu_csr.h>
#include "mockturtle-drv.h"
static const unsigned int trtl_cpu_reset_timeout_us = 1000000;
/**
* Get the reset bit of the CPUs according to the mask
*/
static uint32_t trtl_cpu_reset_get(struct trtl_dev *trtl)
{
return trtl_ioread(trtl, trtl->base_csr + MT_CPU_CSR_REG_RESET);
}
/**
* Set the reset bit of the CPUs according to the mask
......@@ -43,13 +53,37 @@ static void trtl_cpu_reset_clr(struct trtl_dev *trtl, uint8_t mask)
}
static int trtl_cpu_reset_wait(struct trtl_cpu *cpu, uint32_t state,
unsigned int timeout_us)
{
struct trtl_dev *trtl = to_trtl_dev(cpu->dev.parent);
unsigned long timeout;
timeout = jiffies + usecs_to_jiffies(timeout_us);
while ((trtl_cpu_reset_get(trtl) >> cpu->index) && 0x1 == state) {
cpu_relax();
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
}
return 0;
}
static void trtl_cpu_off(struct trtl_cpu *cpu)
{
struct trtl_dev *trtl = to_trtl_dev(cpu->dev.parent);
int i;
int err, i;
trtl_cpu_reset_set(trtl, (1 << cpu->index));
err = trtl_cpu_reset_wait(cpu, 0, trtl_cpu_reset_timeout_us);
if (err == -ETIMEDOUT)
dev_warn(&cpu->dev,
"The user asked to turn off CPU %d, but after %u us the CPU was still on\n",
cpu->index, trtl_cpu_reset_timeout_us);
/* Clean up all the HMQ */
for (i = 0; i < trtl->cfgrom.n_hmq[cpu->index]; ++i)
trtl_hmq_purge(&cpu->hmq[i]);
......@@ -59,9 +93,16 @@ static void trtl_cpu_off(struct trtl_cpu *cpu)
static void trtl_cpu_on(struct trtl_cpu *cpu)
{
struct trtl_dev *trtl = to_trtl_dev(cpu->dev.parent);
int err;
/* now the CPU can run */
trtl_cpu_reset_clr(trtl, (1 << cpu->index));
err = trtl_cpu_reset_wait(cpu, 1, trtl_cpu_reset_timeout_us);
if (err == -ETIMEDOUT)
dev_warn(&cpu->dev,
"The user asked to turn on CPU %d, but after %u us the CPU was still off\n",
cpu->index, trtl_cpu_reset_timeout_us);
}
......@@ -113,7 +154,7 @@ static ssize_t reset_show(struct device *dev,
struct trtl_dev *trtl = to_trtl_dev(dev->parent);
uint32_t reg_val;
reg_val = trtl_ioread(trtl, trtl->base_csr + MT_CPU_CSR_REG_RESET);
reg_val = trtl_cpu_reset_get(trtl);
return sprintf(buf, "%d\n", !!(reg_val & (1 << cpu->index)));
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment