From 40d9f9124822013331367fb4ab59936c3ac944d6 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Sep 2018 12:16:54 -0700 Subject: [PATCH 1/8] bus: ti-sysc: Defer suspend as needed We don't care when we suspend but some our children do. In order to avoid tagging various modules with SYSC_QUIRK_RESOURCE_PROVIDER, let's do it automatically by tagging modules that are busy on suspend for noirq suspend. This way we can just do module detection on define DEBUG. Note that we still need to keep SYSC_QUIRK_LEGACY_IDLE flag around so the our legacy single-child devices that set pm_runtime_irq_safe() can manage the interconnect target module themselves. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 120 +++++++++++++------------- include/linux/platform_data/ti-sysc.h | 1 - 2 files changed, 62 insertions(+), 59 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index c9bac9dc4637..087a67617eef 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -87,6 +87,7 @@ struct sysc { u32 revision; bool enabled; bool needs_resume; + unsigned int noirq_suspend:1; bool child_needs_resume; struct delayed_work idle_work; }; @@ -712,19 +713,25 @@ static int sysc_suspend(struct device *dev) ddata = dev_get_drvdata(dev); - if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER | - SYSC_QUIRK_LEGACY_IDLE)) + if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) return 0; - if (!ddata->enabled) + if (!ddata->enabled || ddata->noirq_suspend) 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", + if (error == -EBUSY) { + dev_dbg(ddata->dev, "%s busy, tagging for noirq suspend %s\n", + __func__, ddata->name ? ddata->name : ""); + + ddata->noirq_suspend = true; + + return 0; + } else if (error < 0) { + dev_warn(ddata->dev, "%s cannot suspend %i %s\n", __func__, error, ddata->name ? ddata->name : ""); @@ -743,73 +750,86 @@ static int sysc_resume(struct device *dev) ddata = dev_get_drvdata(dev); - if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER | - SYSC_QUIRK_LEGACY_IDLE)) + if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) return 0; - if (ddata->needs_resume) { - dev_dbg(ddata->dev, "%s %s\n", __func__, + if (!ddata->needs_resume || ddata->noirq_suspend) + return 0; + + 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 : ""); - 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 error; } + ddata->needs_resume = false; + return 0; } static int sysc_noirq_suspend(struct device *dev) { struct sysc *ddata; + int error; 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) + if (!ddata->enabled || !ddata->noirq_suspend) return 0; dev_dbg(ddata->dev, "%s %s\n", __func__, ddata->name ? ddata->name : ""); + error = sysc_runtime_suspend(dev); + if (error) { + dev_warn(ddata->dev, "%s busy %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_noirq_resume(struct device *dev) { struct sysc *ddata; + int error; ddata = dev_get_drvdata(dev); if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) return 0; - if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER)) + if (!ddata->needs_resume || !ddata->noirq_suspend) return 0; - if (ddata->needs_resume) { - dev_dbg(ddata->dev, "%s %s\n", __func__, - ddata->name ? ddata->name : ""); + dev_dbg(ddata->dev, "%s %s\n", __func__, + ddata->name ? ddata->name : ""); - ddata->needs_resume = false; + error = sysc_runtime_resume(dev); + if (error) { + dev_warn(ddata->dev, "%s cannot resume %i %s\n", + __func__, error, + ddata->name ? ddata->name : ""); - return sysc_runtime_resume(dev); + return error; } + /* Maybe also reconsider clearing noirq_suspend at some point */ + ddata->needs_resume = false; + return 0; } #endif @@ -848,26 +868,6 @@ 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_OPT_CLKS_IN_RESET), @@ -892,23 +892,25 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { 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("control", 0, 0, 0x10, -1, 0x40000900, 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("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0), + SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffffffff, 0), SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0), + SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xffffffff, 0), + SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0), + SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), + SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0), + SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffffffff, 0), + SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 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), @@ -916,6 +918,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 0xffffffff, 0), + SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xffffffff, 0), + SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0d00, 0xffffffff, 0), #endif }; diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 2efa3470a451..1ea3aab972b4 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -46,7 +46,6 @@ struct sysc_regbits { s8 emufree_shift; }; -#define SYSC_QUIRK_RESOURCE_PROVIDER BIT(9) #define SYSC_QUIRK_LEGACY_IDLE BIT(8) #define SYSC_QUIRK_RESET_STATUS BIT(7) #define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6) From b82beef51817953eef1ad47e2e5e983e167a8863 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Sep 2018 12:16:59 -0700 Subject: [PATCH 2/8] bus: ti-sysc: Update revision masks to support am437x We need to detect few new devices to tag for noirq_suspend and pm_runtime_irq_safe to avoid causing regressions compared to legacy platform data booting. Let's update i2c, gpio, uart and wdt revision masks to detect them on am437x. Note that we can remove the second wdt entry with the updated mask. Note that we also have some uarts with a different revision register. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 087a67617eef..f7c9c1e3673a 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -869,7 +869,7 @@ struct sysc_revision_quirk { static const struct sysc_revision_quirk sysc_revision_quirks[] = { /* These drivers need to be fixed to not use pm_runtime_irq_safe() */ - SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffffffff, + SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffff0fff, SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET), SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000020, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), @@ -889,7 +889,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { 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("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff, + SYSC_QUIRK_LEGACY_IDLE), + SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), #ifdef DEBUG From 1ba3069314cacee710cd113c43c6c122e259e45e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Sep 2018 12:17:05 -0700 Subject: [PATCH 3/8] bus: ti-sysc: Detect more devices on am473x for debugging When debug is enabled, we want to see what devices we're detecting to make things a bit easier for us. Many of these devices will also be available on am335x and dra7, and some just need updating the revision register mask. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index f7c9c1e3673a..9cda6994920a 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -895,33 +895,50 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK_LEGACY_IDLE), #ifdef DEBUG + SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, 0), SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), + SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902, + 0xffffffff, 0), + SYSC_QUIRK("dcan", 0, 0, -1, -1, 0x00001401, 0xffffffff, 0), + SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0), + SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0), SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0), SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, 0), + SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, 0), SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), - SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xffffffff, 0), + SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffffff0, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), + SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0), SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffffffff, 0), + SYSC_QUIRK("mcspi", 0, 0, 0x110, 0x114, 0x40300a0b, 0xffffffff, 0), SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0), + SYSC_QUIRK("m3", 0, 0, -1, -1, 0x5f580105, 0x0fff0f00, 0), SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xffffffff, 0), + SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0), SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0), + SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4f000100, 0xffffffff, 0), SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffffffff, 0), + SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0), SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 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("rng", 0, 0x1fe0, 0x1fe4, -1, 0x00000020, 0xffffffff, 0), + SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffffffff, 0), + SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 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), - SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xffffffff, 0), - SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0d00, 0xffffffff, 0), + SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0), + SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0), #endif }; From 23731eac984834e9dec240d5e836b4cea0d53d30 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 24 Sep 2018 12:17:09 -0700 Subject: [PATCH 4/8] bus: ti-sysc: Detect devices on am335x when DEBUG is enabled When debug is enabled, we want to see what devices we're detecting to make things a bit easier for us. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 9cda6994920a..71e91306cef4 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -899,7 +899,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, 0), SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902, - 0xffffffff, 0), + 0xffff00f0, 0), + SYSC_QUIRK("dcan", 0, 0, -1, -1, 0xffffffff, 0xffffffff, 0), SYSC_QUIRK("dcan", 0, 0, -1, -1, 0x00001401, 0xffffffff, 0), SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0), SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0), @@ -909,6 +910,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffffff0, 0), + SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0), @@ -920,8 +922,10 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0), SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0), + SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x00004102, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4e8b0100, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4f000100, 0xffffffff, 0), SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffffffff, 0), @@ -931,7 +935,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40002903, 0xffffffff, 0), SYSC_QUIRK("spinlock", 0, 0, 0x10, -1, 0x50020000, 0xffffffff, 0), SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -1, 0x00000020, 0xffffffff, 0), - SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffffffff, 0), + SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xfffff0f0, 0), SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0), SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), From 3a3d802b025fc2f6d8079d77026e64c6f760ab31 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 27 Sep 2018 13:33:58 -0700 Subject: [PATCH 5/8] bus: ti-sysc: Detect timer and gpio on dra7 We need to detect timer and gpio on dra7 because of the SYSC_QUIRK_LEGACY_IDLE flag for suspend and resume. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 799d69f646fc..a645c6bc0c42 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -866,7 +866,7 @@ struct sysc_revision_quirk { static const struct sysc_revision_quirk sysc_revision_quirks[] = { /* These drivers need to be fixed to not use pm_runtime_irq_safe() */ - SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffff0fff, + SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffff00ff, SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET), SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000020, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), @@ -881,7 +881,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { 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("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff, + SYSC_QUIRK_LEGACY_IDLE), + SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff, SYSC_QUIRK_LEGACY_IDLE), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), From c6eb4af39fcfd8adbe3ed9d7ee39be17a4b9a611 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 27 Sep 2018 13:34:27 -0700 Subject: [PATCH 6/8] bus: ti-sysc: Detect devices for debug on dra7 We want to see the names of detected devices when DEBUG is enabled. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index a645c6bc0c42..d8ddf36eb096 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -895,7 +895,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { #ifdef DEBUG SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), + SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0), SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, 0), + SYSC_QUIRK("cm", 0, 0, -1, -1, 0x40000301, 0xffffffff, 0), SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902, 0xffff00f0, 0), @@ -908,16 +910,16 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, 0), SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), - SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffffff0, 0), + SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, 0), SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0), - SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffffffff, 0), + SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffff00ff, 0), SYSC_QUIRK("mcspi", 0, 0, 0x110, 0x114, 0x40300a0b, 0xffffffff, 0), SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0), SYSC_QUIRK("m3", 0, 0, -1, -1, 0x5f580105, 0x0fff0f00, 0), - SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xffffffff, 0), + SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0), SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0), SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0), @@ -926,15 +928,16 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4e8b0100, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4f000100, 0xffffffff, 0), + SYSC_QUIRK("scm", 0, 0, -1, -1, 0x40000900, 0xffffffff, 0), SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0), - SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffffffff, 0), + SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffff0ff0, 0), SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0), SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 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("rng", 0, 0x1fe0, 0x1fe4, -1, 0x00000020, 0xffffffff, 0), - SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xfffff0f0, 0), + SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffff00f0, 0), SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0), SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0), SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), From f949078302594b2f68aa8b4f94dae540d9b66d2c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 28 Sep 2018 15:21:50 -0700 Subject: [PATCH 7/8] bus: ti-sysc: Make some warnings debug only We're currently warning about busy children on suspend in sysc_child_suspend_noirq() but the legacy code omap_device does not do that. Let's just make it dev_dbg() instead of dev_warn(). Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index d8ddf36eb096..59df869109a3 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1253,8 +1253,8 @@ static int sysc_child_suspend_noirq(struct device *dev) if (!pm_runtime_status_suspended(dev)) { error = pm_generic_runtime_suspend(dev); if (error) { - dev_warn(dev, "%s busy at %i: %i\n", - __func__, __LINE__, error); + dev_dbg(dev, "%s busy at %i: %i\n", + __func__, __LINE__, error); return 0; } From f5e80203dadc28176f7b5ad2ec00652dd524fb9a Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 1 Oct 2018 09:33:28 -0700 Subject: [PATCH 8/8] bus: ti-sysc: Just use SET_NOIRQ_SYSTEM_SLEEP_PM_OPS As Grygorii Strashko pointed out, the runtime PM use count of the children can be whatever at suspend and we should not use it. So let's just suspend ti-sysc at noirq level and get rid of some code. Let's also remove the PM_SLEEP ifdef and use __maybe_unused as the PM code already deals with the ifdefs. Suggested-by: Grygorii Strashko Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 115 ++---------------------------------------- 1 file changed, 4 insertions(+), 111 deletions(-) diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 59df869109a3..a3a2d39280d9 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -87,7 +87,6 @@ struct sysc { u32 revision; bool enabled; bool needs_resume; - unsigned int noirq_suspend:1; bool child_needs_resume; struct delayed_work idle_work; }; @@ -702,137 +701,31 @@ awake: return error; } -#ifdef CONFIG_PM_SLEEP -static int sysc_suspend(struct device *dev) +static int __maybe_unused sysc_noirq_suspend(struct device *dev) { struct sysc *ddata; - int error; ddata = dev_get_drvdata(dev); if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) return 0; - if (!ddata->enabled || ddata->noirq_suspend) - return 0; - - dev_dbg(ddata->dev, "%s %s\n", __func__, - ddata->name ? ddata->name : ""); - - error = pm_runtime_put_sync_suspend(dev); - if (error == -EBUSY) { - dev_dbg(ddata->dev, "%s busy, tagging for noirq suspend %s\n", - __func__, ddata->name ? ddata->name : ""); - - ddata->noirq_suspend = true; - - return 0; - } else if (error < 0) { - dev_warn(ddata->dev, "%s cannot suspend %i %s\n", - __func__, error, - ddata->name ? ddata->name : ""); - - return 0; - } - - ddata->needs_resume = true; - - return 0; + return pm_runtime_force_suspend(dev); } -static int sysc_resume(struct device *dev) +static int __maybe_unused sysc_noirq_resume(struct device *dev) { struct sysc *ddata; - int error; ddata = dev_get_drvdata(dev); if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) return 0; - if (!ddata->needs_resume || ddata->noirq_suspend) - return 0; - - 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; + return pm_runtime_force_resume(dev); } -static int sysc_noirq_suspend(struct device *dev) -{ - struct sysc *ddata; - int error; - - ddata = dev_get_drvdata(dev); - - if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) - return 0; - - if (!ddata->enabled || !ddata->noirq_suspend) - return 0; - - dev_dbg(ddata->dev, "%s %s\n", __func__, - ddata->name ? ddata->name : ""); - - error = sysc_runtime_suspend(dev); - if (error) { - dev_warn(ddata->dev, "%s busy %i %s\n", - __func__, error, ddata->name ? ddata->name : ""); - - return 0; - } - - ddata->needs_resume = true; - - return 0; -} - -static int sysc_noirq_resume(struct device *dev) -{ - struct sysc *ddata; - int error; - - ddata = dev_get_drvdata(dev); - - if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) - return 0; - - if (!ddata->needs_resume || !ddata->noirq_suspend) - return 0; - - dev_dbg(ddata->dev, "%s %s\n", __func__, - ddata->name ? ddata->name : ""); - - error = sysc_runtime_resume(dev); - if (error) { - dev_warn(ddata->dev, "%s cannot resume %i %s\n", - __func__, error, - ddata->name ? ddata->name : ""); - - return error; - } - - /* Maybe also reconsider clearing noirq_suspend at some point */ - ddata->needs_resume = false; - - return 0; -} -#endif - 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,