summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/ti-sysc.c388
-rw-r--r--drivers/media/rc/ir-rx51.c17
-rw-r--r--drivers/mtd/nand/raw/davinci_nand.c6
-rw-r--r--drivers/soc/renesas/Kconfig13
-rw-r--r--drivers/soc/renesas/Makefile2
-rw-r--r--drivers/soc/renesas/r8a77470-sysc.c29
-rw-r--r--drivers/soc/renesas/r8a77990-sysc.c68
-rw-r--r--drivers/soc/renesas/r8a77995-sysc.c3
-rw-r--r--drivers/soc/renesas/rcar-rst.c2
-rw-r--r--drivers/soc/renesas/rcar-sysc.c6
-rw-r--r--drivers/soc/renesas/rcar-sysc.h2
-rw-r--r--drivers/soc/renesas/renesas-soc.c16
12 files changed, 489 insertions, 63 deletions
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 7cd2fd04b212..1cc29629d238 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
@@ -32,10 +33,18 @@ static const char * const reg_names[] = { "rev", "sysc", "syss", };
enum sysc_clocks {
SYSC_FCK,
SYSC_ICK,
+ SYSC_OPTFCK0,
+ SYSC_OPTFCK1,
+ SYSC_OPTFCK2,
+ SYSC_OPTFCK3,
+ SYSC_OPTFCK4,
+ SYSC_OPTFCK5,
+ SYSC_OPTFCK6,
+ SYSC_OPTFCK7,
SYSC_MAX_CLOCKS,
};
-static const char * const clock_names[] = { "fck", "ick", };
+static const char * const clock_names[SYSC_ICK + 1] = { "fck", "ick", };
#define SYSC_IDLEMODE_MASK 3
#define SYSC_CLOCKACTIVITY_MASK 3
@@ -48,6 +57,8 @@ static const char * const clock_names[] = { "fck", "ick", };
* @module_va: virtual address of the interconnect target module
* @offsets: register offsets from module base
* @clocks: clocks used by the interconnect target module
+ * @clock_roles: clock role names for the found clocks
+ * @nr_clocks: number of clocks used by the interconnect target module
* @legacy_mode: configured for legacy mode if set
* @cap: interconnect target module capabilities
* @cfg: interconnect target module configuration
@@ -61,7 +72,10 @@ struct sysc {
u32 module_size;
void __iomem *module_va;
int offsets[SYSC_MAX_REGS];
- struct clk *clocks[SYSC_MAX_CLOCKS];
+ struct clk **clocks;
+ const char **clock_roles;
+ int nr_clocks;
+ struct reset_control *rsts;
const char *legacy_mode;
const struct sysc_capabilities *cap;
struct sysc_config cfg;
@@ -88,6 +102,11 @@ static u32 sysc_read(struct sysc *ddata, int offset)
return readl_relaxed(ddata->module_va + offset);
}
+static bool sysc_opt_clks_needed(struct sysc *ddata)
+{
+ return !!(ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_NEEDED);
+}
+
static u32 sysc_read_revision(struct sysc *ddata)
{
int offset = ddata->offsets[SYSC_REVISION];
@@ -98,21 +117,28 @@ static u32 sysc_read_revision(struct sysc *ddata)
return sysc_read(ddata, offset);
}
-static int sysc_get_one_clock(struct sysc *ddata,
- enum sysc_clocks index)
+static int sysc_get_one_clock(struct sysc *ddata, const char *name)
{
- const char *name;
- int error;
+ int error, i, index = -ENODEV;
+
+ if (!strncmp(clock_names[SYSC_FCK], name, 3))
+ index = SYSC_FCK;
+ else if (!strncmp(clock_names[SYSC_ICK], name, 3))
+ index = SYSC_ICK;
+
+ if (index < 0) {
+ for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+ if (!ddata->clocks[i]) {
+ index = i;
+ break;
+ }
+ }
+ }
- switch (index) {
- case SYSC_FCK:
- break;
- case SYSC_ICK:
- break;
- default:
- return -EINVAL;
+ if (index < 0) {
+ dev_err(ddata->dev, "clock %s not added\n", name);
+ return index;
}
- name = clock_names[index];
ddata->clocks[index] = devm_clk_get(ddata->dev, name);
if (IS_ERR(ddata->clocks[index])) {
@@ -138,10 +164,50 @@ static int sysc_get_one_clock(struct sysc *ddata,
static int sysc_get_clocks(struct sysc *ddata)
{
- int i, error;
+ struct device_node *np = ddata->dev->of_node;
+ struct property *prop;
+ const char *name;
+ int nr_fck = 0, nr_ick = 0, i, error = 0;
- for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
- error = sysc_get_one_clock(ddata, i);
+ ddata->clock_roles = devm_kzalloc(ddata->dev,
+ sizeof(*ddata->clock_roles) *
+ SYSC_MAX_CLOCKS,
+ GFP_KERNEL);
+ if (!ddata->clock_roles)
+ return -ENOMEM;
+
+ of_property_for_each_string(np, "clock-names", prop, name) {
+ if (!strncmp(clock_names[SYSC_FCK], name, 3))
+ nr_fck++;
+ if (!strncmp(clock_names[SYSC_ICK], name, 3))
+ nr_ick++;
+ ddata->clock_roles[ddata->nr_clocks] = name;
+ ddata->nr_clocks++;
+ }
+
+ if (ddata->nr_clocks < 1)
+ return 0;
+
+ if (ddata->nr_clocks > SYSC_MAX_CLOCKS) {
+ dev_err(ddata->dev, "too many clocks for %pOF\n", np);
+
+ return -EINVAL;
+ }
+
+ if (nr_fck > 1 || nr_ick > 1) {
+ dev_err(ddata->dev, "max one fck and ick for %pOF\n", np);
+
+ return -EINVAL;
+ }
+
+ ddata->clocks = devm_kzalloc(ddata->dev,
+ sizeof(*ddata->clocks) * ddata->nr_clocks,
+ GFP_KERNEL);
+ if (!ddata->clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < ddata->nr_clocks; i++) {
+ error = sysc_get_one_clock(ddata, ddata->clock_roles[i]);
if (error && error != -ENOENT)
return error;
}
@@ -150,6 +216,42 @@ static int sysc_get_clocks(struct sysc *ddata)
}
/**
+ * sysc_init_resets - reset module on init
+ * @ddata: device driver data
+ *
+ * A module can have both OCP softreset control and external rstctrl.
+ * If more complicated rstctrl resets are needed, please handle these
+ * directly from the child device driver and map only the module reset
+ * for the parent interconnect target module device.
+ *
+ * Automatic reset of the module on init can be skipped with the
+ * "ti,no-reset-on-init" device tree property.
+ */
+static int sysc_init_resets(struct sysc *ddata)
+{
+ int error;
+
+ ddata->rsts =
+ devm_reset_control_array_get_optional_exclusive(ddata->dev);
+ if (IS_ERR(ddata->rsts))
+ return PTR_ERR(ddata->rsts);
+
+ if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+ goto deassert;
+
+ error = reset_control_assert(ddata->rsts);
+ if (error)
+ return error;
+
+deassert:
+ error = reset_control_deassert(ddata->rsts);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+/**
* sysc_parse_and_check_child_range - parses module IO region from ranges
* @ddata: device driver data
*
@@ -533,9 +635,13 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
goto idled;
}
- for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ for (i = 0; i < ddata->nr_clocks; i++) {
if (IS_ERR_OR_NULL(ddata->clocks[i]))
continue;
+
+ if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
+ break;
+
clk_disable(ddata->clocks[i]);
}
@@ -572,9 +678,13 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
goto awake;
}
- for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ for (i = 0; i < ddata->nr_clocks; i++) {
if (IS_ERR_OR_NULL(ddata->clocks[i]))
continue;
+
+ if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
+ break;
+
error = clk_enable(ddata->clocks[i]);
if (error)
return error;
@@ -590,23 +700,103 @@ awake:
static int sysc_suspend(struct device *dev)
{
struct sysc *ddata;
+ int error;
ddata = dev_get_drvdata(dev);
+ if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER |
+ SYSC_QUIRK_LEGACY_IDLE))
+ return 0;
+
if (!ddata->enabled)
return 0;
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
+ error = pm_runtime_put_sync_suspend(dev);
+ if (error < 0) {
+ dev_warn(ddata->dev, "%s not idle %i %s\n",
+ __func__, error,
+ ddata->name ? ddata->name : "");
+
+ return 0;
+ }
+
ddata->needs_resume = true;
- return sysc_runtime_suspend(dev);
+ return 0;
}
static int sysc_resume(struct device *dev)
{
struct sysc *ddata;
+ int error;
+
+ ddata = dev_get_drvdata(dev);
+
+ if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER |
+ SYSC_QUIRK_LEGACY_IDLE))
+ return 0;
+
+ if (ddata->needs_resume) {
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
+ error = pm_runtime_get_sync(dev);
+ if (error < 0) {
+ dev_err(ddata->dev, "%s error %i %s\n",
+ __func__, error,
+ ddata->name ? ddata->name : "");
+
+ return error;
+ }
+
+ ddata->needs_resume = false;
+ }
+
+ return 0;
+}
+
+static int sysc_noirq_suspend(struct device *dev)
+{
+ struct sysc *ddata;
ddata = dev_get_drvdata(dev);
+
+ if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+ return 0;
+
+ if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER))
+ return 0;
+
+ if (!ddata->enabled)
+ return 0;
+
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
+ ddata->needs_resume = true;
+
+ return sysc_runtime_suspend(dev);
+}
+
+static int sysc_noirq_resume(struct device *dev)
+{
+ struct sysc *ddata;
+
+ ddata = dev_get_drvdata(dev);
+
+ if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+ return 0;
+
+ if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER))
+ return 0;
+
if (ddata->needs_resume) {
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
ddata->needs_resume = false;
return sysc_runtime_resume(dev);
@@ -618,6 +808,7 @@ static int sysc_resume(struct device *dev)
static const struct dev_pm_ops sysc_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(sysc_suspend, sysc_resume)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sysc_noirq_suspend, sysc_noirq_resume)
SET_RUNTIME_PM_OPS(sysc_runtime_suspend,
sysc_runtime_resume,
NULL)
@@ -649,9 +840,29 @@ struct sysc_revision_quirk {
}
static const struct sysc_revision_quirk sysc_revision_quirks[] = {
+ /* These need to use noirq_suspend */
+ SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+
/* These drivers need to be fixed to not use pm_runtime_irq_safe() */
SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffffffff,
- SYSC_QUIRK_LEGACY_IDLE),
+ SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET),
SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000020, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000030, 0xffffffff,
@@ -664,8 +875,40 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
+ /* Some timers on omap4 and later */
+ SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
+ /* Uarts on omap4 and later */
+ SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+
+ /* These devices don't yet suspend properly without legacy setting */
+ SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+ SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+ SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0d00, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+
+#ifdef DEBUG
+ SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, 0),
+ SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),
+ SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, 0),
+ SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),
+ SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0),
+ SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0),
+ SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0),
+ SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0),
+ SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40000902, 0xffffffff, 0),
+ SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40002903, 0xffffffff, 0),
+ SYSC_QUIRK("spinlock", 0, 0, 0x10, -1, 0x50020000, 0xffffffff, 0),
+ SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0),
+ SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0),
+ SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
+ 0xffffffff, 0),
+#endif
};
static void sysc_init_revision_quirks(struct sysc *ddata)
@@ -716,6 +959,7 @@ static int sysc_init_module(struct sysc *ddata)
return 0;
}
+
ddata->revision = sysc_read_revision(ddata);
pm_runtime_put_sync(ddata->dev);
@@ -811,29 +1055,58 @@ static int sysc_init_syss_mask(struct sysc *ddata)
}
/*
- * Many child device drivers need to have fck available to get the clock
- * rate for device internal configuration.
+ * Many child device drivers need to have fck and opt clocks available
+ * to get the clock rate for device internal configuration etc.
*/
-static int sysc_child_add_fck(struct sysc *ddata,
- struct device *child)
+static int sysc_child_add_named_clock(struct sysc *ddata,
+ struct device *child,
+ const char *name)
{
- struct clk *fck;
+ struct clk *clk;
struct clk_lookup *l;
- const char *name = clock_names[SYSC_FCK];
+ int error = 0;
- if (IS_ERR_OR_NULL(ddata->clocks[SYSC_FCK]))
+ if (!name)
return 0;
- fck = clk_get(child, name);
- if (!IS_ERR(fck)) {
- clk_put(fck);
+ clk = clk_get(child, name);
+ if (!IS_ERR(clk)) {
+ clk_put(clk);
return -EEXIST;
}
- l = clkdev_create(ddata->clocks[SYSC_FCK], name, dev_name(child));
+ clk = clk_get(ddata->dev, name);
+ if (IS_ERR(clk))
+ return -ENODEV;
+
+ l = clkdev_create(clk, name, dev_name(child));
+ if (!l)
+ error = -ENOMEM;
+
+ clk_put(clk);
+
+ return error;
+}
+
+static int sysc_child_add_clocks(struct sysc *ddata,
+ struct device *child)
+{
+ int i, error;
+
+ for (i = 0; i < ddata->nr_clocks; i++) {
+ error = sysc_child_add_named_clock(ddata,
+ child,
+ ddata->clock_roles[i]);
+ if (error && error != -EEXIST) {
+ dev_err(ddata->dev, "could not add child clock %s: %i\n",
+ ddata->clock_roles[i], error);
+
+ return error;
+ }
+ }
- return l ? 0 : -ENODEV;
+ return 0;
}
static struct device_type sysc_device_type = {
@@ -891,18 +1164,33 @@ static int sysc_child_suspend_noirq(struct device *dev)
ddata = sysc_child_to_parent(dev);
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
error = pm_generic_suspend_noirq(dev);
- if (error)
+ if (error) {
+ dev_err(dev, "%s error at %i: %i\n",
+ __func__, __LINE__, error);
+
return error;
+ }
if (!pm_runtime_status_suspended(dev)) {
error = pm_generic_runtime_suspend(dev);
- if (error)
+ if (error) {
+ dev_err(dev, "%s error at %i: %i\n",
+ __func__, __LINE__, error);
+
return error;
+ }
error = sysc_runtime_suspend(ddata->dev);
- if (error)
+ if (error) {
+ dev_err(dev, "%s error at %i: %i\n",
+ __func__, __LINE__, error);
+
return error;
+ }
ddata->child_needs_resume = true;
}
@@ -917,6 +1205,9 @@ static int sysc_child_resume_noirq(struct device *dev)
ddata = sysc_child_to_parent(dev);
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
if (ddata->child_needs_resume) {
ddata->child_needs_resume = false;
@@ -983,10 +1274,9 @@ static int sysc_notifier_call(struct notifier_block *nb,
switch (event) {
case BUS_NOTIFY_ADD_DEVICE:
- error = sysc_child_add_fck(ddata, dev);
- if (error && error != -EEXIST)
- dev_warn(ddata->dev, "could not add %s fck: %i\n",
- dev_name(dev), error);
+ error = sysc_child_add_clocks(ddata, dev);
+ if (error)
+ return error;
sysc_legacy_idle_quirk(ddata, dev);
break;
default:
@@ -1314,6 +1604,11 @@ static void ti_sysc_idle(struct work_struct *work)
pm_runtime_put_sync(ddata->dev);
}
+static const struct of_device_id sysc_match_table[] = {
+ { .compatible = "simple-bus", },
+ { /* sentinel */ },
+};
+
static int sysc_probe(struct platform_device *pdev)
{
struct ti_sysc_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -1359,8 +1654,11 @@ static int sysc_probe(struct platform_device *pdev)
if (error)
goto unprepare;
- pm_runtime_enable(ddata->dev);
+ error = sysc_init_resets(ddata);
+ if (error)
+ return error;
+ pm_runtime_enable(ddata->dev);
error = sysc_init_module(ddata);
if (error)
goto unprepare;
@@ -1375,8 +1673,8 @@ static int sysc_probe(struct platform_device *pdev)
sysc_show_registers(ddata);
ddata->dev->type = &sysc_device_type;
- error = of_platform_populate(ddata->dev->of_node,
- NULL, pdata ? pdata->auxdata : NULL,
+ error = of_platform_populate(ddata->dev->of_node, sysc_match_table,
+ pdata ? pdata->auxdata : NULL,
ddata->dev);
if (error)
goto err;
@@ -1391,6 +1689,9 @@ static int sysc_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
}
+ if (!of_get_available_child_count(ddata->dev->of_node))
+ reset_control_assert(ddata->rsts);
+
return 0;
err:
@@ -1420,6 +1721,7 @@ static int sysc_remove(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ reset_control_assert(ddata->rsts);
unprepare:
sysc_unprepare(ddata);
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 49265f02e772..8a93f7468622 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -22,7 +22,6 @@
#include <linux/hrtimer.h>
#include <media/rc-core.h>
-#include <linux/platform_data/media/ir-rx51.h>
#define WBUF_LEN 256
@@ -31,7 +30,6 @@ struct ir_rx51 {
struct pwm_device *pwm;
struct hrtimer timer;
struct device *dev;
- struct ir_rx51_platform_data *pdata;
wait_queue_head_t wqueue;
unsigned int freq; /* carrier frequency */
@@ -130,10 +128,9 @@ static int ir_rx51_tx(struct rc_dev *dev, unsigned int *buffer,
ir_rx51->wbuf[count] = -1; /* Insert termination mark */
/*
- * Adjust latency requirements so the device doesn't go in too
- * deep sleep states
+ * REVISIT: Adjust latency requirements so the device doesn't go in too
+ * deep sleep states with pm_qos_add_request().
*/
- ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, 50);
ir_rx51_on(ir_rx51);
ir_rx51->wbuf_index = 1;
@@ -146,8 +143,7 @@ static int ir_rx51_tx(struct rc_dev *dev, unsigned int *buffer,
*/
wait_event_interruptible(ir_rx51->wqueue, ir_rx51->wbuf_index < 0);
- /* We can sleep again */
- ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, -1);
+ /* REVISIT: Remove pm_qos constraint, we can sleep again */
return count;
}
@@ -244,13 +240,6 @@ static int ir_rx51_probe(struct platform_device *dev)
struct pwm_device *pwm;
struct rc_dev *rcdev;
- ir_rx51.pdata = dev->dev.platform_data;
-
- if (!ir_rx51.pdata) {
- dev_err(&dev->dev, "Platform Data is missing\n");
- return -ENXIO;
- }
-
pwm = pwm_get(&dev->dev, NULL);
if (IS_ERR(pwm)) {
int err = PTR_ERR(pwm);
diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 7255a0d94374..cd12e5abafde 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -545,7 +545,7 @@ static struct davinci_nand_pdata
return ERR_PTR(-ENOMEM);
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-chipselect", &prop))
- pdev->id = prop;
+ pdata->core_chipsel = prop;
else
return ERR_PTR(-EINVAL);
@@ -627,7 +627,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
return -ENODEV;
/* which external chipselect will we be managing? */
- if (pdev->id < 0 || pdev->id > 3)
+ if (pdata->core_chipsel < 0 || pdata->core_chipsel > 3)
return -ENODEV;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
@@ -683,7 +683,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
info->ioaddr = (uint32_t __force) vaddr;
info->current_cs = info->ioaddr;
- info->core_chipsel = pdev->id;
+ info->core_chipsel = pdata->core_chipsel;
info->mask_chipsel = pdata->mask_chipsel;
/* use nandboot-capable ALE/CLE masks by default */
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 3bbe6114a420..1d824cbd462d 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -4,9 +4,11 @@ config SOC_RENESAS
select SOC_BUS
select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \
ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || \
- ARCH_R8A77970 || ARCH_R8A77980 || ARCH_R8A77995
+ ARCH_R8A77970 || ARCH_R8A77980 || ARCH_R8A77990 || \
+ ARCH_R8A77995
select SYSC_R8A7743 if ARCH_R8A7743
select SYSC_R8A7745 if ARCH_R8A7745
+ select SYSC_R8A77470 if ARCH_R8A77470
select SYSC_R8A7779 if ARCH_R8A7779
select SYSC_R8A7790 if ARCH_R8A7790
select SYSC_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793
@@ -17,6 +19,7 @@ config SOC_RENESAS
select SYSC_R8A77965 if ARCH_R8A77965
select SYSC_R8A77970 if ARCH_R8A77970
select SYSC_R8A77980 if ARCH_R8A77980
+ select SYSC_R8A77990 if ARCH_R8A77990
select SYSC_R8A77995 if ARCH_R8A77995
if SOC_RENESAS
@@ -30,6 +33,10 @@ config SYSC_R8A7745
bool "RZ/G1E System Controller support" if COMPILE_TEST
select SYSC_RCAR
+config SYSC_R8A77470
+ bool "RZ/G1C System Controller support" if COMPILE_TEST
+ select SYSC_RCAR
+
config SYSC_R8A7779
bool "R-Car H1 System Controller support" if COMPILE_TEST
select SYSC_RCAR
@@ -70,6 +77,10 @@ config SYSC_R8A77980
bool "R-Car V3H System Controller support" if COMPILE_TEST
select SYSC_RCAR
+config SYSC_R8A77990
+ bool "R-Car E3 System Controller support" if COMPILE_TEST
+ select SYSC_RCAR
+
config SYSC_R8A77995
bool "R-Car D3 System Controller support" if COMPILE_TEST
select SYSC_RCAR
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index ccb5ec57a262..7dc0f20d7907 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_SOC_RENESAS) += renesas-soc.o
# SoC
obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o
obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o
+obj-$(CONFIG_SYSC_R8A77470) += r8a77470-sysc.o
obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o
obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o
obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_SYSC_R8A7796) += r8a7796-sysc.o
obj-$(CONFIG_SYSC_R8A77965) += r8a77965-sysc.o
obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o
obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o
+obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
# Family
diff --git a/drivers/soc/renesas/r8a77470-sysc.c b/drivers/soc/renesas/r8a77470-sysc.c
new file mode 100644
index 000000000000..cfa015e208ef
--- /dev/null
+++ b/drivers/soc/renesas/r8a77470-sysc.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G1C System Controller
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a77470-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a77470_areas[] __initconst = {
+ { "always-on", 0, 0, R8A77470_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+ { "ca7-scu", 0x100, 0, R8A77470_PD_CA7_SCU, R8A77470_PD_ALWAYS_ON,
+ PD_SCU },
+ { "ca7-cpu0", 0x1c0, 0, R8A77470_PD_CA7_CPU0, R8A77470_PD_CA7_SCU,
+ PD_CPU_NOCR },
+ { "ca7-cpu1", 0x1c0, 1, R8A77470_PD_CA7_CPU1, R8A77470_PD_CA7_SCU,
+ PD_CPU_NOCR },
+ { "sgx", 0xc0, 0, R8A77470_PD_SGX, R8A77470_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a77470_sysc_info __initconst = {
+ .areas = r8a77470_areas,
+ .num_areas = ARRAY_SIZE(r8a77470_areas),
+};
diff --git a/drivers/soc/renesas/r8a77990-sysc.c b/drivers/soc/renesas/r8a77990-sysc.c
new file mode 100644
index 000000000000..15579ebc5ed2
--- /dev/null
+++ b/drivers/soc/renesas/r8a77990-sysc.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car E3 System Controller
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/power/r8a77990-sysc.h>
+
+#include "rcar-sysc.h"
+
+static struct rcar_sysc_area r8a77990_areas[] __initdata = {
+ { "always-on", 0, 0, R8A77990_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+ { "ca53-scu", 0x140, 0, R8A77990_PD_CA53_SCU, R8A77990_PD_ALWAYS_ON,
+ PD_SCU },
+ { "ca53-cpu0", 0x200, 0, R8A77990_PD_CA53_CPU0, R8A77990_PD_CA53_SCU,
+ PD_CPU_NOCR },
+ { "ca53-cpu1", 0x200, 1, R8A77990_PD_CA53_CPU1, R8A77990_PD_CA53_SCU,
+ PD_CPU_NOCR },
+ { "cr7", 0x240, 0, R8A77990_PD_CR7, R8A77990_PD_ALWAYS_ON },
+ { "a3vc", 0x380, 0, R8A77990_PD_A3VC, R8A77990_PD_ALWAYS_ON },
+ { "a2vc1", 0x3c0, 1, R8A77990_PD_A2VC1, R8A77990_PD_A3VC },
+ { "3dg-a", 0x100, 0, R8A77990_PD_3DG_A, R8A77990_PD_ALWAYS_ON },
+ { "3dg-b", 0x100, 1, R8A77990_PD_3DG_B, R8A77990_PD_3DG_A },
+};
+
+static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas,
+ unsigned int num_areas, u8 id,
+ int new_parent)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_areas; i++)
+ if (areas[i].isr_bit == id) {
+ areas[i].parent = new_parent;
+ return;
+ }
+}
+
+/* Fixups for R-Car E3 ES1.0 revision */
+static const struct soc_device_attribute r8a77990[] __initconst = {
+ { .soc_id = "r8a77990", .revision = "ES1.0" },
+ { /* sentinel */ }
+};
+
+static int __init r8a77990_sysc_init(void)
+{
+ if (soc_device_match(r8a77990)) {
+ rcar_sysc_fix_parent(r8a77990_areas,
+ ARRAY_SIZE(r8a77990_areas),
+ R8A77990_PD_3DG_A, R8A77990_PD_3DG_B);
+ rcar_sysc_fix_parent(r8a77990_areas,
+ ARRAY_SIZE(r8a77990_areas),
+ R8A77990_PD_3DG_B, R8A77990_PD_ALWAYS_ON);
+ }
+
+ return 0;
+}
+
+const struct rcar_sysc_info r8a77990_sysc_info __initconst = {
+ .init = r8a77990_sysc_init,
+ .areas = r8a77990_areas,
+ .num_areas = ARRAY_SIZE(r8a77990_areas),
+};
diff --git a/drivers/soc/renesas/r8a77995-sysc.c b/drivers/soc/renesas/r8a77995-sysc.c
index f718429cab02..1b2ef415bbe1 100644
--- a/drivers/soc/renesas/r8a77995-sysc.c
+++ b/drivers/soc/renesas/r8a77995-sysc.c
@@ -10,13 +10,12 @@
#include <linux/bug.h>
#include <linux/kernel.h>
-#include <linux/sys_soc.h>
#include <dt-bindings/power/r8a77995-sysc.h>
#include "rcar-sysc.h"
-static struct rcar_sysc_area r8a77995_areas[] __initdata = {
+static const struct rcar_sysc_area r8a77995_areas[] __initconst = {
{ "always-on", 0, 0, R8A77995_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca53-scu", 0x140, 0, R8A77995_PD_CA53_SCU, R8A77995_PD_ALWAYS_ON,
PD_SCU },
diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c
index 8e9cb7996ab0..d9c1034e70e9 100644
--- a/drivers/soc/renesas/rcar-rst.c
+++ b/drivers/soc/renesas/rcar-rst.c
@@ -44,6 +44,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
/* RZ/G is handled like R-Car Gen2 */
{ .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 },
{ .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a77470-rst", .data = &rcar_rst_gen2 },
/* R-Car Gen1 */
{ .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
{ .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
@@ -59,6 +60,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
{ .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77970-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen3 },
+ { .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 },
{ /* sentinel */ }
};
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index faf20e719361..95120acc4d80 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -261,6 +261,9 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A7745
{ .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info },
#endif
+#ifdef CONFIG_SYSC_R8A77470
+ { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info },
+#endif
#ifdef CONFIG_SYSC_R8A7779
{ .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
#endif
@@ -293,6 +296,9 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A77980
{ .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info },
#endif
+#ifdef CONFIG_SYSC_R8A77990
+ { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info },
+#endif
#ifdef CONFIG_SYSC_R8A77995
{ .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info },
#endif
diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h
index dcdc9ec8eba7..a22e7cf25e30 100644
--- a/drivers/soc/renesas/rcar-sysc.h
+++ b/drivers/soc/renesas/rcar-sysc.h
@@ -51,6 +51,7 @@ struct rcar_sysc_info {
extern const struct rcar_sysc_info r8a7743_sysc_info;
extern const struct rcar_sysc_info r8a7745_sysc_info;
+extern const struct rcar_sysc_info r8a77470_sysc_info;
extern const struct rcar_sysc_info r8a7779_sysc_info;
extern const struct rcar_sysc_info r8a7790_sysc_info;
extern const struct rcar_sysc_info r8a7791_sysc_info;
@@ -61,6 +62,7 @@ extern const struct rcar_sysc_info r8a7796_sysc_info;
extern const struct rcar_sysc_info r8a77965_sysc_info;
extern const struct rcar_sysc_info r8a77970_sysc_info;
extern const struct rcar_sysc_info r8a77980_sysc_info;
+extern const struct rcar_sysc_info r8a77990_sysc_info;
extern const struct rcar_sysc_info r8a77995_sysc_info;
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index ea71c413c926..d44d0e687ab8 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -100,6 +100,11 @@ static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
.id = 0x4c,
};
+static const struct renesas_soc soc_rz_g1c __initconst __maybe_unused = {
+ .family = &fam_rzg,
+ .id = 0x53,
+};
+
static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = {
.family = &fam_rcar_gen1,
};
@@ -159,6 +164,11 @@ static const struct renesas_soc soc_rcar_v3h __initconst __maybe_unused = {
.id = 0x56,
};
+static const struct renesas_soc soc_rcar_e3 __initconst __maybe_unused = {
+ .family = &fam_rcar_gen3,
+ .id = 0x57,
+};
+
static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = {
.family = &fam_rcar_gen3,
.id = 0x58,
@@ -192,6 +202,9 @@ static const struct of_device_id renesas_socs[] __initconst = {
#ifdef CONFIG_ARCH_R8A7745
{ .compatible = "renesas,r8a7745", .data = &soc_rz_g1e },
#endif
+#ifdef CONFIG_ARCH_R8A77470
+ { .compatible = "renesas,r8a77470", .data = &soc_rz_g1c },
+#endif
#ifdef CONFIG_ARCH_R8A7778
{ .compatible = "renesas,r8a7778", .data = &soc_rcar_m1a },
#endif
@@ -228,6 +241,9 @@ static const struct of_device_id renesas_socs[] __initconst = {
#ifdef CONFIG_ARCH_R8A77980
{ .compatible = "renesas,r8a77980", .data = &soc_rcar_v3h },
#endif
+#ifdef CONFIG_ARCH_R8A77990
+ { .compatible = "renesas,r8a77990", .data = &soc_rcar_e3 },
+#endif
#ifdef CONFIG_ARCH_R8A77995
{ .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 },
#endif