Commit 566a9b05 authored by Tony Lindgren's avatar Tony Lindgren

bus: ti-sysc: Handle module quirks based dts configuration

Let's configure few module quirks via device tree using the
properties for "ti,no-idle-on-init", "ti,no-reset-on-init"
and "ti,sysc-delay-us".

Let's also reorder the probe a bit so we have pdata available
earlier, and move the PM runtime calls to sysc_init_module()
from sysc_read_revision().
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent a7199e2b
...@@ -50,6 +50,8 @@ static const char * const clock_names[] = { "fck", "ick", }; ...@@ -50,6 +50,8 @@ static const char * const clock_names[] = { "fck", "ick", };
* @legacy_mode: configured for legacy mode if set * @legacy_mode: configured for legacy mode if set
* @cap: interconnect target module capabilities * @cap: interconnect target module capabilities
* @cfg: interconnect target module configuration * @cfg: interconnect target module configuration
* @name: name if available
* @revision: interconnect target module revision
*/ */
struct sysc { struct sysc {
struct device *dev; struct device *dev;
...@@ -61,12 +63,32 @@ struct sysc { ...@@ -61,12 +63,32 @@ struct sysc {
const char *legacy_mode; const char *legacy_mode;
const struct sysc_capabilities *cap; const struct sysc_capabilities *cap;
struct sysc_config cfg; struct sysc_config cfg;
const char *name;
u32 revision;
}; };
static u32 sysc_read(struct sysc *ddata, int offset)
{
if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
u32 val;
val = readw_relaxed(ddata->module_va + offset);
val |= (readw_relaxed(ddata->module_va + offset + 4) << 16);
return val;
}
return readl_relaxed(ddata->module_va + offset);
}
static u32 sysc_read_revision(struct sysc *ddata) static u32 sysc_read_revision(struct sysc *ddata)
{ {
return readl_relaxed(ddata->module_va + int offset = ddata->offsets[SYSC_REVISION];
ddata->offsets[SYSC_REVISION]);
if (offset < 0)
return 0;
return sysc_read(ddata, offset);
} }
static int sysc_get_one_clock(struct sysc *ddata, static int sysc_get_one_clock(struct sysc *ddata,
...@@ -393,22 +415,12 @@ static int sysc_map_and_check_registers(struct sysc *ddata) ...@@ -393,22 +415,12 @@ static int sysc_map_and_check_registers(struct sysc *ddata)
*/ */
static int sysc_show_rev(char *bufp, struct sysc *ddata) static int sysc_show_rev(char *bufp, struct sysc *ddata)
{ {
int error, len; int len;
if (ddata->offsets[SYSC_REVISION] < 0) if (ddata->offsets[SYSC_REVISION] < 0)
return sprintf(bufp, ":NA"); return sprintf(bufp, ":NA");
error = pm_runtime_get_sync(ddata->dev); len = sprintf(bufp, ":%08x", ddata->revision);
if (error < 0) {
pm_runtime_put_noidle(ddata->dev);
return 0;
}
len = sprintf(bufp, ":%08x", sysc_read_revision(ddata));
pm_runtime_mark_last_busy(ddata->dev);
pm_runtime_put_autosuspend(ddata->dev);
return len; return len;
} }
...@@ -488,6 +500,66 @@ static const struct dev_pm_ops sysc_pm_ops = { ...@@ -488,6 +500,66 @@ static const struct dev_pm_ops sysc_pm_ops = {
NULL) NULL)
}; };
/* At this point the module is configured enough to read the revision */
static int sysc_init_module(struct sysc *ddata)
{
int error;
error = pm_runtime_get_sync(ddata->dev);
if (error < 0) {
pm_runtime_put_noidle(ddata->dev);
return 0;
}
ddata->revision = sysc_read_revision(ddata);
pm_runtime_put_sync(ddata->dev);
return 0;
}
/* Device tree configured quirks */
struct sysc_dts_quirk {
const char *name;
u32 mask;
};
static const struct sysc_dts_quirk sysc_dts_quirks[] = {
{ .name = "ti,no-idle-on-init",
.mask = SYSC_QUIRK_NO_IDLE_ON_INIT, },
{ .name = "ti,no-reset-on-init",
.mask = SYSC_QUIRK_NO_RESET_ON_INIT, },
};
static int sysc_init_dts_quirks(struct sysc *ddata)
{
struct device_node *np = ddata->dev->of_node;
const struct property *prop;
int i, len, error;
u32 val;
ddata->legacy_mode = of_get_property(np, "ti,hwmods", NULL);
for (i = 0; i < ARRAY_SIZE(sysc_dts_quirks); i++) {
prop = of_get_property(np, sysc_dts_quirks[i].name, &len);
if (!prop)
break;
ddata->cfg.quirks |= sysc_dts_quirks[i].mask;
}
error = of_property_read_u32(np, "ti,sysc-delay-us", &val);
if (!error) {
if (val > 255) {
dev_warn(ddata->dev, "bad ti,sysc-delay-us: %i\n",
val);
}
ddata->cfg.srst_udelay = (u8)val;
}
return 0;
}
static void sysc_unprepare(struct sysc *ddata) static void sysc_unprepare(struct sysc *ddata)
{ {
int i; int i;
...@@ -722,7 +794,6 @@ static int sysc_init_match(struct sysc *ddata) ...@@ -722,7 +794,6 @@ static int sysc_init_match(struct sysc *ddata)
static int sysc_probe(struct platform_device *pdev) static int sysc_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node;
struct sysc *ddata; struct sysc *ddata;
int error; int error;
...@@ -731,12 +802,16 @@ static int sysc_probe(struct platform_device *pdev) ...@@ -731,12 +802,16 @@ static int sysc_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
ddata->dev = &pdev->dev; ddata->dev = &pdev->dev;
ddata->legacy_mode = of_get_property(np, "ti,hwmods", NULL); platform_set_drvdata(pdev, ddata);
error = sysc_init_match(ddata); error = sysc_init_match(ddata);
if (error) if (error)
return error; return error;
error = sysc_init_dts_quirks(ddata);
if (error)
goto unprepare;
error = sysc_get_clocks(ddata); error = sysc_get_clocks(ddata);
if (error) if (error)
return error; return error;
...@@ -745,9 +820,12 @@ static int sysc_probe(struct platform_device *pdev) ...@@ -745,9 +820,12 @@ static int sysc_probe(struct platform_device *pdev)
if (error) if (error)
goto unprepare; goto unprepare;
platform_set_drvdata(pdev, ddata);
pm_runtime_enable(ddata->dev); pm_runtime_enable(ddata->dev);
error = sysc_init_module(ddata);
if (error)
goto unprepare;
error = pm_runtime_get_sync(ddata->dev); error = pm_runtime_get_sync(ddata->dev);
if (error < 0) { if (error < 0) {
pm_runtime_put_noidle(ddata->dev); pm_runtime_put_noidle(ddata->dev);
......
...@@ -41,6 +41,10 @@ struct sysc_regbits { ...@@ -41,6 +41,10 @@ struct sysc_regbits {
s8 emufree_shift; s8 emufree_shift;
}; };
#define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6)
#define SYSC_QUIRK_NO_RESET_ON_INIT BIT(5)
#define SYSC_QUIRK_OPT_CLKS_NEEDED BIT(4)
#define SYSC_QUIRK_OPT_CLKS_IN_RESET BIT(3)
#define SYSC_QUIRK_16BIT BIT(2) #define SYSC_QUIRK_16BIT BIT(2)
#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)
...@@ -61,9 +65,11 @@ struct sysc_capabilities { ...@@ -61,9 +65,11 @@ struct sysc_capabilities {
/** /**
* struct sysc_config - configuration for an interconnect target module * struct sysc_config - configuration for an interconnect target module
* @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 {
u8 srst_udelay;
u32 quirks; u32 quirks;
}; };
......
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