bus: ti-sysc: Make OCP reset work for sysstatus and sysconfig reset bits
We've had minimal OCP softreset support in ti-sysc interconnect target module driver only used for MCAN driver so far. But it turns out that MCAN has the sysstatus register resetdone bit inverted compared to most other modules. Let's make OCP softreset work for other typical cases with reset status in sysstatus or sysconfig register so we can use the new functions for sysc_enable_module() and sysc_disable_module() without "ti,hwmods" property in the following patches. Tested-by: Keerthy <j-keerthy@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
parent
5aa9129536
commit
e0db94fe87
|
@ -153,6 +153,26 @@ static u32 sysc_read_revision(struct sysc *ddata)
|
||||||
return sysc_read(ddata, offset);
|
return sysc_read(ddata, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 sysc_read_sysconfig(struct sysc *ddata)
|
||||||
|
{
|
||||||
|
int offset = ddata->offsets[SYSC_SYSCONFIG];
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sysc_read(ddata, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 sysc_read_sysstatus(struct sysc *ddata)
|
||||||
|
{
|
||||||
|
int offset = ddata->offsets[SYSC_SYSSTATUS];
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sysc_read(ddata, offset);
|
||||||
|
}
|
||||||
|
|
||||||
static int sysc_add_named_clock_from_child(struct sysc *ddata,
|
static int sysc_add_named_clock_from_child(struct sysc *ddata,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *optfck_name)
|
const char *optfck_name)
|
||||||
|
@ -1369,34 +1389,49 @@ static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset)
|
||||||
return reset_control_deassert(ddata->rsts);
|
return reset_control_deassert(ddata->rsts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the caller must ensure the interconnect target module is enabled
|
||||||
|
* before calling reset. Otherwise reset will not complete.
|
||||||
|
*/
|
||||||
static int sysc_reset(struct sysc *ddata)
|
static int sysc_reset(struct sysc *ddata)
|
||||||
{
|
{
|
||||||
int offset = ddata->offsets[SYSC_SYSCONFIG];
|
int sysc_offset, syss_offset, sysc_val, rstval, quirks, error = 0;
|
||||||
int val;
|
u32 sysc_mask, syss_done;
|
||||||
|
|
||||||
if (ddata->legacy_mode || offset < 0 ||
|
sysc_offset = ddata->offsets[SYSC_SYSCONFIG];
|
||||||
|
syss_offset = ddata->offsets[SYSC_SYSSTATUS];
|
||||||
|
quirks = ddata->cfg.quirks;
|
||||||
|
|
||||||
|
if (ddata->legacy_mode || sysc_offset < 0 ||
|
||||||
|
ddata->cap->regbits->srst_shift < 0 ||
|
||||||
ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
|
ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
sysc_mask = BIT(ddata->cap->regbits->srst_shift);
|
||||||
* Currently only support reset status in sysstatus.
|
|
||||||
* Warn and return error in all other cases
|
|
||||||
*/
|
|
||||||
if (!ddata->cfg.syss_mask) {
|
|
||||||
dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = sysc_read(ddata, offset);
|
if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED)
|
||||||
val |= (0x1 << ddata->cap->regbits->srst_shift);
|
syss_done = 0;
|
||||||
sysc_write(ddata, offset, val);
|
else
|
||||||
|
syss_done = ddata->cfg.syss_mask;
|
||||||
|
|
||||||
|
sysc_val = sysc_read_sysconfig(ddata);
|
||||||
|
sysc_val |= sysc_mask;
|
||||||
|
sysc_write(ddata, sysc_offset, sysc_val);
|
||||||
|
|
||||||
/* Poll on reset status */
|
/* Poll on reset status */
|
||||||
offset = ddata->offsets[SYSC_SYSSTATUS];
|
if (syss_offset >= 0) {
|
||||||
|
error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval,
|
||||||
|
(rstval & ddata->cfg.syss_mask) ==
|
||||||
|
syss_done,
|
||||||
|
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||||
|
|
||||||
return readl_poll_timeout(ddata->module_va + offset, val,
|
} else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) {
|
||||||
(val & ddata->cfg.syss_mask) == 0x0,
|
error = readx_poll_timeout(sysc_read_sysconfig, ddata, rstval,
|
||||||
100, MAX_MODULE_SOFTRESET_WAIT);
|
!(rstval & sysc_mask),
|
||||||
|
100, MAX_MODULE_SOFTRESET_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2099,6 +2134,7 @@ static const struct sysc_capabilities sysc_dra7_mcan = {
|
||||||
.type = TI_SYSC_DRA7_MCAN,
|
.type = TI_SYSC_DRA7_MCAN,
|
||||||
.sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
|
.sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
|
||||||
.regbits = &sysc_regbits_dra7_mcan,
|
.regbits = &sysc_regbits_dra7_mcan,
|
||||||
|
.mod_quirks = SYSS_QUIRK_RESETDONE_INVERTED,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int sysc_init_pdata(struct sysc *ddata)
|
static int sysc_init_pdata(struct sysc *ddata)
|
||||||
|
|
|
@ -47,6 +47,7 @@ struct sysc_regbits {
|
||||||
s8 emufree_shift;
|
s8 emufree_shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SYSS_QUIRK_RESETDONE_INVERTED BIT(14)
|
||||||
#define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13)
|
#define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13)
|
||||||
#define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12)
|
#define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12)
|
||||||
#define SYSC_QUIRK_SWSUP_SIDLE BIT(11)
|
#define SYSC_QUIRK_SWSUP_SIDLE BIT(11)
|
||||||
|
|
Loading…
Reference in New Issue