bus: ti-sysc: Add parsing of module capabilities
We need to configure the interconnect target module based on the device three configuration. Let's also add a new quirk for SYSC_QUIRK_RESET_STATUS to indicate that the SYSCONFIG reset bit changes after the reset is done. Signed-off-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
Родитель
566a9b05e1
Коммит
c5a2de97fb
|
@ -39,6 +39,9 @@ enum sysc_clocks {
|
||||||
|
|
||||||
static const char * const clock_names[] = { "fck", "ick", };
|
static const char * const clock_names[] = { "fck", "ick", };
|
||||||
|
|
||||||
|
#define SYSC_IDLEMODE_MASK 3
|
||||||
|
#define SYSC_CLOCKACTIVITY_MASK 3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sysc - TI sysc interconnect target module registers and capabilities
|
* struct sysc - TI sysc interconnect target module registers and capabilities
|
||||||
* @dev: struct device pointer
|
* @dev: struct device pointer
|
||||||
|
@ -517,6 +520,91 @@ static int sysc_init_module(struct sysc *ddata)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sysc_init_sysc_mask(struct sysc *ddata)
|
||||||
|
{
|
||||||
|
struct device_node *np = ddata->dev->of_node;
|
||||||
|
int error;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
error = of_property_read_u32(np, "ti,sysc-mask", &val);
|
||||||
|
if (error)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (val)
|
||||||
|
ddata->cfg.sysc_val = val & ddata->cap->sysc_mask;
|
||||||
|
else
|
||||||
|
ddata->cfg.sysc_val = ddata->cap->sysc_mask;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sysc_init_idlemode(struct sysc *ddata, u8 *idlemodes,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
struct device_node *np = ddata->dev->of_node;
|
||||||
|
struct property *prop;
|
||||||
|
const __be32 *p;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
of_property_for_each_u32(np, name, prop, p, val) {
|
||||||
|
if (val >= SYSC_NR_IDLEMODES) {
|
||||||
|
dev_err(ddata->dev, "invalid idlemode: %i\n", val);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
*idlemodes |= (1 << val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sysc_init_idlemodes(struct sysc *ddata)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = sysc_init_idlemode(ddata, &ddata->cfg.midlemodes,
|
||||||
|
"ti,sysc-midle");
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = sysc_init_idlemode(ddata, &ddata->cfg.sidlemodes,
|
||||||
|
"ti,sysc-sidle");
|
||||||
|
if (error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only some devices on omap4 and later have SYSCONFIG reset done
|
||||||
|
* bit. We can detect this if there is no SYSSTATUS at all, or the
|
||||||
|
* SYSTATUS bit 0 is not used. Note that some SYSSTATUS registers
|
||||||
|
* have multiple bits for the child devices like OHCI and EHCI.
|
||||||
|
* Depends on SYSC being parsed first.
|
||||||
|
*/
|
||||||
|
static int sysc_init_syss_mask(struct sysc *ddata)
|
||||||
|
{
|
||||||
|
struct device_node *np = ddata->dev->of_node;
|
||||||
|
int error;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
error = of_property_read_u32(np, "ti,syss-mask", &val);
|
||||||
|
if (error) {
|
||||||
|
if ((ddata->cap->type == TI_SYSC_OMAP4 ||
|
||||||
|
ddata->cap->type == TI_SYSC_OMAP4_TIMER) &&
|
||||||
|
(ddata->cfg.sysc_val & SYSC_OMAP4_SOFTRESET))
|
||||||
|
ddata->cfg.quirks |= SYSC_QUIRK_RESET_STATUS;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(val & 1) && (ddata->cfg.sysc_val & SYSC_OMAP4_SOFTRESET))
|
||||||
|
ddata->cfg.quirks |= SYSC_QUIRK_RESET_STATUS;
|
||||||
|
|
||||||
|
ddata->cfg.syss_mask = val;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Device tree configured quirks */
|
/* Device tree configured quirks */
|
||||||
struct sysc_dts_quirk {
|
struct sysc_dts_quirk {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -820,6 +908,18 @@ static int sysc_probe(struct platform_device *pdev)
|
||||||
if (error)
|
if (error)
|
||||||
goto unprepare;
|
goto unprepare;
|
||||||
|
|
||||||
|
error = sysc_init_sysc_mask(ddata);
|
||||||
|
if (error)
|
||||||
|
goto unprepare;
|
||||||
|
|
||||||
|
error = sysc_init_idlemodes(ddata);
|
||||||
|
if (error)
|
||||||
|
goto unprepare;
|
||||||
|
|
||||||
|
error = sysc_init_syss_mask(ddata);
|
||||||
|
if (error)
|
||||||
|
goto unprepare;
|
||||||
|
|
||||||
pm_runtime_enable(ddata->dev);
|
pm_runtime_enable(ddata->dev);
|
||||||
|
|
||||||
error = sysc_init_module(ddata);
|
error = sysc_init_module(ddata);
|
||||||
|
|
|
@ -41,6 +41,7 @@ struct sysc_regbits {
|
||||||
s8 emufree_shift;
|
s8 emufree_shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SYSC_QUIRK_RESET_STATUS BIT(7)
|
||||||
#define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6)
|
#define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6)
|
||||||
#define SYSC_QUIRK_NO_RESET_ON_INIT BIT(5)
|
#define SYSC_QUIRK_NO_RESET_ON_INIT BIT(5)
|
||||||
#define SYSC_QUIRK_OPT_CLKS_NEEDED BIT(4)
|
#define SYSC_QUIRK_OPT_CLKS_NEEDED BIT(4)
|
||||||
|
@ -49,6 +50,8 @@ struct sysc_regbits {
|
||||||
#define SYSC_QUIRK_UNCACHED BIT(1)
|
#define SYSC_QUIRK_UNCACHED BIT(1)
|
||||||
#define SYSC_QUIRK_USE_CLOCKACT BIT(0)
|
#define SYSC_QUIRK_USE_CLOCKACT BIT(0)
|
||||||
|
|
||||||
|
#define SYSC_NR_IDLEMODES 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sysc_capabilities - capabilities for an interconnect target module
|
* struct sysc_capabilities - capabilities for an interconnect target module
|
||||||
*
|
*
|
||||||
|
@ -65,10 +68,17 @@ struct sysc_capabilities {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sysc_config - configuration for an interconnect target module
|
* struct sysc_config - configuration for an interconnect target module
|
||||||
|
* @sysc_val: configured value for sysc register
|
||||||
|
* @midlemodes: bitmask of supported master idle modes
|
||||||
|
* @sidlemodes: bitmask of supported master idle modes
|
||||||
* @srst_udelay: optional delay needed after OCP soft reset
|
* @srst_udelay: optional delay needed after OCP soft reset
|
||||||
* @quirks: bitmask of enabled quirks
|
* @quirks: bitmask of enabled quirks
|
||||||
*/
|
*/
|
||||||
struct sysc_config {
|
struct sysc_config {
|
||||||
|
u32 sysc_val;
|
||||||
|
u32 syss_mask;
|
||||||
|
u8 midlemodes;
|
||||||
|
u8 sidlemodes;
|
||||||
u8 srst_udelay;
|
u8 srst_udelay;
|
||||||
u32 quirks;
|
u32 quirks;
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче