Message ID | 20140828164645.GG16006@atomide.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 08/28/2014 06:46 PM, Tony Lindgren wrote: >> To use DMA you don't have to enable it in SCR register you can also use >> the FCR register. The manual says that you can only write this DMA >> enable bit in the FCR register if the baud clock is not running. And >> guess what: same thing: I only *toggle* the DMA enable bit here (it >> remains 0 later) and the core won't hit idle. >> Same effect if I toggle this bit while the baud clock is running (the >> manual says that this bit can only be written if the baud clock is not >> running). Seems like the UART is following its own specification and it >> remains blocking once the DMA was enabled. >> It would be nice if someone from the UART-IP team could ACK this. > > Sounds like there should be some way to clear that state.. I wonder > if omap-serial.c had something before it's DMA support was removed? Its DMA was removed? Like there was DMA support? > I'd assume when the UART is powered down by runtime PM it's state > is completetely reset and we could restore the non-DMA state? I tried that by canceling the RX-DMA request and removing the DMA-enable bits from UART but it didn't help. Then I noticed that once that DMA en bit is set, the UART won't do any idle. > Maybe post your current patches and a test patch to try to toggle > the DMA on and off? Oh. I pushed my dirty tree to git://git.breakpoint.cc/bigeasy/linux.git uart_v8_wip The top most commit does not setup dma at all and adds commented out code how to enable DMA via SCR or FCR register. With this I hit core-off. Once _one_ of the modes are enabled, it doesn't work anymore. I will try to address review comments tomorrow and hopefully post a v8 based on -rc2. The same goes for your patch (which I will try tomorrow). >> Bah. Does it make sense to use runtime-PM if we can't hit core-off? I'm >> thinking to add a printk once dma is enabled says that runtime-pm is >> switched off. > > Well if we can't find a way to unset the DMA registers in the UART, > how about only enable it if a kernel cmdline option is specified? Hmmm. So removing DMA properties from DT is not an option? Currently I added a message that DMA might forbid low power mode so people might remove "dma-names" from DT (or assign "") and DMA is off. However if this is no good, then I guess I could add kernel module which enables DMA. > > We do have runtime PM working without it, and the serial console > super important for any kind of debugging no matter what idle > mode the SoC hits.. So let's not break that. Yeah, I know. I've been debugging while I broke something which means uart wasn't working :) > > Regards, > > Tony Sebastian -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
--- a/arch/arm/mach-omap2/pm-debug.c +++ b/arch/arm/mach-omap2/pm-debug.c @@ -142,10 +142,76 @@ static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user) return 0; } +#include "iomap.h" + +struct dregs { + const char *desc; + u32 phys; + void __iomem *virt; + u32 mask; +}; + +#define PER_CM_BASE 0x48005000 +#define PER_CM_REG(name, offset, mask) \ + { name, PER_CM_BASE + offset, \ + OMAP2_L4_IO_ADDRESS(PER_CM_BASE + offset), mask, } + +static struct dregs cm_per[] = { + PER_CM_REG("cm_idlest_per", 0x20, 0xfff80000), /* p 513 */ + { NULL, }, +}; + +#define CORE_CM_BASE 0x48004a00 +#define CORE_CM_REG(name, offset, mask) \ + { name, CORE_CM_BASE + offset, \ + OMAP2_L4_IO_ADDRESS(CORE_CM_BASE + offset), mask, } + +static struct dregs cm_core[] = { + CORE_CM_REG("cm_idlest1_core", 0x20, 0x9c800109), /* p 467 */ + CORE_CM_REG("cm_idlest3_core", 0x28, 0xfffffffb), + { NULL, }, +}; + +void __dregs_dump(struct dregs *dregs, struct seq_file *s) +{ + for (; dregs->desc; dregs++) { + u32 val, blockers; + + val = __raw_readl(dregs->virt); + + seq_printf(s, "%08x %08x (%p) %s", + val, dregs->phys, dregs->virt, + dregs->desc); + + if (dregs->mask) { + blockers = ~val; + blockers &= ~dregs->mask; + + if (blockers) + seq_printf(s, " blocking bits: %08x", + blockers); + } + + seq_printf(s, "\n"); + } +} + +void cm_per_dump(struct seq_file *s) +{ + __dregs_dump(cm_per, s); +} + +void cm_core_dump(struct seq_file *s) +{ + __dregs_dump(cm_core, s); +} + static int pm_dbg_show_counters(struct seq_file *s, void *unused) { pwrdm_for_each(pwrdm_dbg_show_counter, s); clkdm_for_each(clkdm_dbg_show_counter, s); + cm_per_dump(s); + cm_core_dump(s); return 0; }