Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
On Tuesday 26 February 2008, Haavard Skinnemoen wrote: > > Another way to address that rm9200 issue would be to just rate > > the TC clockevent source lower than the one based on the system > > timer, so it's set up but never enabled ... and remember "t2_clk", > > calling clk_enable() only when that clockevent device is active. > > > > That would address one half of the suspend/resume equation too, > > ensuring that clock is disabled during suspend... > > Yes, we could probably do that. Which means we can just remove all the > ifdeffery? There'd still be the #ifdef for CONFIG_GENERIC_CLOCKEVENTS, unless all the platforms get updated to support that. Right now it's a "patches available but not merged" situation. > > The other half being: how to clk_disable(t0_clk) during system > > suspend? (And t1_clk on some systems.) There's currently no > > clocksource.set_mode() call; evidently there's an assumption that > > such counters cost no power, so they can always be left running. > > Yes...that would be a clocksource core issue I guess. Better leave that > for later... My thoughts exactly. ;) Plus a bit of puzzlement why that didn't trigger at least a warning during AT91 suspend testing. There used to be warnings there about clocks which were wrongly left enabled... - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
On Mon, 25 Feb 2008 09:51:16 -0800 David Brownell <[EMAIL PROTECTED]> wrote: > > > > > +static cycle_t tc_get_cycles(void) > > > > > +{ > > > > > + unsigned long flags; > > > > > + u32 lower, upper; > > > > > + > > > > > + raw_local_irq_save(flags); > > > > > > > > Why do you need to use the raw version? > > > > > > This is part of the system timer code, and it should never be a > > > preemption point. Plus I didn't want to waste any instruction > > > cycles in code that runs before e.g. the DBGU IRQ handler would > > > get called... observably, such extra cycles *do* hurt. > > > > I don't understand what you mean by preemption point, but I guess the > > non-raw version may consume some extra cycles when lockdep is enabled. > > A preemption point is where CONFIG_PREEMPT kicks in task switching > logic; lockdep is different. I know, but I dont' see how local_irq_save/restore has anything to do with it, raw or not. There would be absolutely no point checking for preemption on local_irq_restore() since no one would have been able to set the TIF_NEED_RESCHED flag while interrupts were disabled... raw_local_irq_save/restore is only different from local_irq_save/restore when lockdep is enabled. That's why I don't understand why you're talking about preemption. > > If we really expect using TC as a clocksource but not as a clockevent > > is going to be a common usage, perhaps we should move the decision into > > Kconfig? > > Maybe, but I already spent lots more time on this than I wanted. :( I'm not asking you to do it. I'm asking if it would be a good thing to do. I said that I can take these patches off your back if you want, but I want to make sure I don't do anything with them that you disagree with. > Another way to address that rm9200 issue would be to just rate > the TC clockevent source lower than the one based on the system > timer, so it's set up but never enabled ... and remember "t2_clk", > calling clk_enable() only when that clockevent device is active. > > That would address one half of the suspend/resume equation too, > ensuring that clock is disabled during suspend... Yes, we could probably do that. Which means we can just remove all the ifdeffery? > The other half being: how to clk_disable(t0_clk) during system > suspend? (And t1_clk on some systems.) There's currently no > clocksource.set_mode() call; evidently there's an assumption that > such counters cost no power, so they can always be left running. Yes...that would be a clocksource core issue I guess. Better leave that for later... > > > > I don't think it is safe to assume that one clock per channel always > > > > means one irq per channel as well... > > > > > > On current chips, that's how it works. > > > > Indeed. I just don't see any fundamental reason why it has to work that > > way, which is why I don't think we should depend on it. > > AT91 chips share identifiers between clocks and interrupts; that's > fundamental, yes? > > If some future chip works differently, that's a good time to change > things. Otherwise I see little point in caring about such issues. Agreed. Haavard -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
On Mon, 25 Feb 2008 09:51:16 -0800 David Brownell [EMAIL PROTECTED] wrote: +static cycle_t tc_get_cycles(void) +{ + unsigned long flags; + u32 lower, upper; + + raw_local_irq_save(flags); Why do you need to use the raw version? This is part of the system timer code, and it should never be a preemption point. Plus I didn't want to waste any instruction cycles in code that runs before e.g. the DBGU IRQ handler would get called... observably, such extra cycles *do* hurt. I don't understand what you mean by preemption point, but I guess the non-raw version may consume some extra cycles when lockdep is enabled. A preemption point is where CONFIG_PREEMPT kicks in task switching logic; lockdep is different. I know, but I dont' see how local_irq_save/restore has anything to do with it, raw or not. There would be absolutely no point checking for preemption on local_irq_restore() since no one would have been able to set the TIF_NEED_RESCHED flag while interrupts were disabled... raw_local_irq_save/restore is only different from local_irq_save/restore when lockdep is enabled. That's why I don't understand why you're talking about preemption. If we really expect using TC as a clocksource but not as a clockevent is going to be a common usage, perhaps we should move the decision into Kconfig? Maybe, but I already spent lots more time on this than I wanted. :( I'm not asking you to do it. I'm asking if it would be a good thing to do. I said that I can take these patches off your back if you want, but I want to make sure I don't do anything with them that you disagree with. Another way to address that rm9200 issue would be to just rate the TC clockevent source lower than the one based on the system timer, so it's set up but never enabled ... and remember t2_clk, calling clk_enable() only when that clockevent device is active. That would address one half of the suspend/resume equation too, ensuring that clock is disabled during suspend... Yes, we could probably do that. Which means we can just remove all the ifdeffery? The other half being: how to clk_disable(t0_clk) during system suspend? (And t1_clk on some systems.) There's currently no clocksource.set_mode() call; evidently there's an assumption that such counters cost no power, so they can always be left running. Yes...that would be a clocksource core issue I guess. Better leave that for later... I don't think it is safe to assume that one clock per channel always means one irq per channel as well... On current chips, that's how it works. Indeed. I just don't see any fundamental reason why it has to work that way, which is why I don't think we should depend on it. AT91 chips share identifiers between clocks and interrupts; that's fundamental, yes? If some future chip works differently, that's a good time to change things. Otherwise I see little point in caring about such issues. Agreed. Haavard -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
On Tuesday 26 February 2008, Haavard Skinnemoen wrote: Another way to address that rm9200 issue would be to just rate the TC clockevent source lower than the one based on the system timer, so it's set up but never enabled ... and remember t2_clk, calling clk_enable() only when that clockevent device is active. That would address one half of the suspend/resume equation too, ensuring that clock is disabled during suspend... Yes, we could probably do that. Which means we can just remove all the ifdeffery? There'd still be the #ifdef for CONFIG_GENERIC_CLOCKEVENTS, unless all the platforms get updated to support that. Right now it's a patches available but not merged situation. The other half being: how to clk_disable(t0_clk) during system suspend? (And t1_clk on some systems.) There's currently no clocksource.set_mode() call; evidently there's an assumption that such counters cost no power, so they can always be left running. Yes...that would be a clocksource core issue I guess. Better leave that for later... My thoughts exactly. ;) Plus a bit of puzzlement why that didn't trigger at least a warning during AT91 suspend testing. There used to be warnings there about clocks which were wrongly left enabled... - Dave -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
> > > > +static cycle_t tc_get_cycles(void) > > > > +{ > > > > + unsigned long flags; > > > > + u32 lower, upper; > > > > + > > > > + raw_local_irq_save(flags); > > > > > > Why do you need to use the raw version? > > > > This is part of the system timer code, and it should never be a > > preemption point. Plus I didn't want to waste any instruction > > cycles in code that runs before e.g. the DBGU IRQ handler would > > get called... observably, such extra cycles *do* hurt. > > I don't understand what you mean by preemption point, but I guess the > non-raw version may consume some extra cycles when lockdep is enabled. A preemption point is where CONFIG_PREEMPT kicks in task switching logic; lockdep is different. > If we really expect using TC as a clocksource but not as a clockevent > is going to be a common usage, perhaps we should move the decision into > Kconfig? Maybe, but I already spent lots more time on this than I wanted. :( Another way to address that rm9200 issue would be to just rate the TC clockevent source lower than the one based on the system timer, so it's set up but never enabled ... and remember "t2_clk", calling clk_enable() only when that clockevent device is active. That would address one half of the suspend/resume equation too, ensuring that clock is disabled during suspend... The other half being: how to clk_disable(t0_clk) during system suspend? (And t1_clk on some systems.) There's currently no clocksource.set_mode() call; evidently there's an assumption that such counters cost no power, so they can always be left running. > > > I don't think it is safe to assume that one clock per channel always > > > means one irq per channel as well... > > > > On current chips, that's how it works. > > Indeed. I just don't see any fundamental reason why it has to work that > way, which is why I don't think we should depend on it. AT91 chips share identifiers between clocks and interrupts; that's fundamental, yes? If some future chip works differently, that's a good time to change things. Otherwise I see little point in caring about such issues. - Dave -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
On Sun, 24 Feb 2008 15:42:51 -0800 David Brownell <[EMAIL PROTECTED]> wrote: > > On Fri, 22 Feb 2008 17:28:37 -0800 > > David Brownell <[EMAIL PROTECTED]> wrote: > > > > > +static cycle_t tc_get_cycles(void) > > > +{ > > > + unsigned long flags; > > > + u32 lower, upper; > > > + > > > + raw_local_irq_save(flags); > > > > Why do you need to use the raw version? > > This is part of the system timer code, and it should never be a > preemption point. Plus I didn't want to waste any instruction > cycles in code that runs before e.g. the DBGU IRQ handler would > get called... observably, such extra cycles *do* hurt. I don't understand what you mean by preemption point, but I guess the non-raw version may consume some extra cycles when lockdep is enabled. > > > +#ifdef CONFIG_GENERIC_CLOCKEVENTS > > > +#define USE_TC_CLKEVT > > > +#endif > > > + > > > +#ifdef CONFIG_ARCH_AT91RM9200 > > > +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's > > > + * always running ... configuring a TC channel to work the same way > > > + * would just waste some power. > > > + */ > > > +#undef USE_TC_CLKEVT > > > +#endif > > > + > > > +#ifdef USE_TC_CLKEVT > > > > Can't you just use #ifndef CONFIG_ARCH_AT91RM9200 and avoid the whole > > ifdef/define/undef dance above? > > I can't know that some other platform won't have a better system > timer solution, and didn't want to assume that only that single > venerable chip had such a solution ... it's kind of puzzling to > me (software guy) that none of the newest Atmel SOCs have better > timer infrastructure than they do. ;) Heh. If we really expect using TC as a clocksource but not as a clockevent is going to be a common usage, perhaps we should move the decision into Kconfig? Besides, I don't really see the difference between having a big #ifdef expression around the whole clockevent block and having a big #ifdef expression around the definition of USE_TC_CLKEVT except that the latter is more code... > > > + case CLOCK_EVT_MODE_ONESHOT: > > > + /* slow clock, count up to RC, then irq and stop */ > > > > Hmm. Do you really want to stop it? Won't you get better accuracy if > > you let it run and program the next event as (prev_event + delta)? > > No, ONESHOT means "stop after the IRQ I asked for". And when > tc_next_event() is asked to trigger that IRQ, it's relative to > the instant it's requested, not relative to the last one that > was requested (which may not have triggered yet, or may have > been quite some time ago). Right. Sounds like it might introduce some inaccuracy, but I guess it's the clocksource's job to keep track of the actual time at the time of the event. > > > +static struct irqaction tc_irqaction = { > > > + .name = "tc_clkevt", > > > + .flags = IRQF_TIMER | IRQF_DISABLED, > > > + .handler= ch2_irq, > > > +}; > > > > I don't think you need to define this statically. You can call > > request_irq() at arch_initcall() time. > > That could be done, yes ... and using request_irq()/free_irq() > would also let this be linked as a module, not just statically. > > On the other hand, doing it this way doesn't hurt either does it? > Unless a modular build is important. No, it doesn't hurt. Maybe we should keep it static so that we have the option of initializing it earlier if we need to. > > I don't think it is safe to assume that one clock per channel always > > means one irq per channel as well... > > On current chips, that's how it works. Indeed. I just don't see any fundamental reason why it has to work that way, which is why I don't think we should depend on it. > > What's wrong with > > > > irq = platform_get_irq(pdev, 2); > > if (irq < 0) > > irq = platform_get_irq(pdev, 0); > > Nothing much, except that I took the more concise path. Got patch? Not until we reach a conclusion about the tclib core. > > How about we make tcb_clksrc_init() global and call it from the > > platform code with whatever TCB the platform thinks is appropriate? > > That could work too, but if it goes that way then there's no > point in changes to support a modular build (e.g. the irqaction > thing you noted above). True. > > Perhaps remove the prompt from ATMEL_TCB_CLKSRC and have the platform > > select it as well? I certainly want to force this stuff on on the > > AP7000...otherwise we'll just get lots of complaints that the thing is > > using 4x more power than it's supposed to... > > Well, "force" seems the wrong approach to me. That should be a > board-specific choice. The ap700x power budget may not be the > most important system design consideration, so making such a > decision at the platform ("ap700x") level seems wrong. > > Suppose someone has to build an AVR32 based system that uses both > TCB modules to hook up to external hardware, so that neither one > is available for use as a "system timer"? Good point. Let's keep it as it is and let the board "select" it
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
On Sun, 24 Feb 2008 15:42:51 -0800 David Brownell [EMAIL PROTECTED] wrote: On Fri, 22 Feb 2008 17:28:37 -0800 David Brownell [EMAIL PROTECTED] wrote: +static cycle_t tc_get_cycles(void) +{ + unsigned long flags; + u32 lower, upper; + + raw_local_irq_save(flags); Why do you need to use the raw version? This is part of the system timer code, and it should never be a preemption point. Plus I didn't want to waste any instruction cycles in code that runs before e.g. the DBGU IRQ handler would get called... observably, such extra cycles *do* hurt. I don't understand what you mean by preemption point, but I guess the non-raw version may consume some extra cycles when lockdep is enabled. +#ifdef CONFIG_GENERIC_CLOCKEVENTS +#define USE_TC_CLKEVT +#endif + +#ifdef CONFIG_ARCH_AT91RM9200 +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's + * always running ... configuring a TC channel to work the same way + * would just waste some power. + */ +#undef USE_TC_CLKEVT +#endif + +#ifdef USE_TC_CLKEVT Can't you just use #ifndef CONFIG_ARCH_AT91RM9200 and avoid the whole ifdef/define/undef dance above? I can't know that some other platform won't have a better system timer solution, and didn't want to assume that only that single venerable chip had such a solution ... it's kind of puzzling to me (software guy) that none of the newest Atmel SOCs have better timer infrastructure than they do. ;) Heh. If we really expect using TC as a clocksource but not as a clockevent is going to be a common usage, perhaps we should move the decision into Kconfig? Besides, I don't really see the difference between having a big #ifdef expression around the whole clockevent block and having a big #ifdef expression around the definition of USE_TC_CLKEVT except that the latter is more code... + case CLOCK_EVT_MODE_ONESHOT: + /* slow clock, count up to RC, then irq and stop */ Hmm. Do you really want to stop it? Won't you get better accuracy if you let it run and program the next event as (prev_event + delta)? No, ONESHOT means stop after the IRQ I asked for. And when tc_next_event() is asked to trigger that IRQ, it's relative to the instant it's requested, not relative to the last one that was requested (which may not have triggered yet, or may have been quite some time ago). Right. Sounds like it might introduce some inaccuracy, but I guess it's the clocksource's job to keep track of the actual time at the time of the event. +static struct irqaction tc_irqaction = { + .name = tc_clkevt, + .flags = IRQF_TIMER | IRQF_DISABLED, + .handler= ch2_irq, +}; I don't think you need to define this statically. You can call request_irq() at arch_initcall() time. That could be done, yes ... and using request_irq()/free_irq() would also let this be linked as a module, not just statically. On the other hand, doing it this way doesn't hurt either does it? Unless a modular build is important. No, it doesn't hurt. Maybe we should keep it static so that we have the option of initializing it earlier if we need to. I don't think it is safe to assume that one clock per channel always means one irq per channel as well... On current chips, that's how it works. Indeed. I just don't see any fundamental reason why it has to work that way, which is why I don't think we should depend on it. What's wrong with irq = platform_get_irq(pdev, 2); if (irq 0) irq = platform_get_irq(pdev, 0); Nothing much, except that I took the more concise path. Got patch? Not until we reach a conclusion about the tclib core. How about we make tcb_clksrc_init() global and call it from the platform code with whatever TCB the platform thinks is appropriate? That could work too, but if it goes that way then there's no point in changes to support a modular build (e.g. the irqaction thing you noted above). True. Perhaps remove the prompt from ATMEL_TCB_CLKSRC and have the platform select it as well? I certainly want to force this stuff on on the AP7000...otherwise we'll just get lots of complaints that the thing is using 4x more power than it's supposed to... Well, force seems the wrong approach to me. That should be a board-specific choice. The ap700x power budget may not be the most important system design consideration, so making such a decision at the platform (ap700x) level seems wrong. Suppose someone has to build an AVR32 based system that uses both TCB modules to hook up to external hardware, so that neither one is available for use as a system timer? Good point. Let's keep it as it is and let the board select it through its defconfig. Haavard -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
+static cycle_t tc_get_cycles(void) +{ + unsigned long flags; + u32 lower, upper; + + raw_local_irq_save(flags); Why do you need to use the raw version? This is part of the system timer code, and it should never be a preemption point. Plus I didn't want to waste any instruction cycles in code that runs before e.g. the DBGU IRQ handler would get called... observably, such extra cycles *do* hurt. I don't understand what you mean by preemption point, but I guess the non-raw version may consume some extra cycles when lockdep is enabled. A preemption point is where CONFIG_PREEMPT kicks in task switching logic; lockdep is different. If we really expect using TC as a clocksource but not as a clockevent is going to be a common usage, perhaps we should move the decision into Kconfig? Maybe, but I already spent lots more time on this than I wanted. :( Another way to address that rm9200 issue would be to just rate the TC clockevent source lower than the one based on the system timer, so it's set up but never enabled ... and remember t2_clk, calling clk_enable() only when that clockevent device is active. That would address one half of the suspend/resume equation too, ensuring that clock is disabled during suspend... The other half being: how to clk_disable(t0_clk) during system suspend? (And t1_clk on some systems.) There's currently no clocksource.set_mode() call; evidently there's an assumption that such counters cost no power, so they can always be left running. I don't think it is safe to assume that one clock per channel always means one irq per channel as well... On current chips, that's how it works. Indeed. I just don't see any fundamental reason why it has to work that way, which is why I don't think we should depend on it. AT91 chips share identifiers between clocks and interrupts; that's fundamental, yes? If some future chip works differently, that's a good time to change things. Otherwise I see little point in caring about such issues. - Dave -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
> Again, sorry for the delay...it really sucks that I haven't been able > to look at this stuff closely until now. Hopefully a late review is > better than no review. Yes. The review I've gotten so far has been of the "it works for me, thanks" variety. (The only issue reported to me is that NO_HZ on AT91 seems to make the DBGU lose characters sometimes ... that one-byte "fifo" makes trouble whenever there's the slightest delay in IRQ handling, and NO_HZ can easily add such delays as part of ensuring that "jiffies" is current before invoking handlers.) > On Fri, 22 Feb 2008 17:28:37 -0800 > David Brownell <[EMAIL PROTECTED]> wrote: > > > +static cycle_t tc_get_cycles(void) > > +{ > > + unsigned long flags; > > + u32 lower, upper; > > + > > + raw_local_irq_save(flags); > > Why do you need to use the raw version? This is part of the system timer code, and it should never be a preemption point. Plus I didn't want to waste any instruction cycles in code that runs before e.g. the DBGU IRQ handler would get called... observably, such extra cycles *do* hurt. > > +retry: > > + upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); > > + lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); > > + if (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))) > > + goto retry; > > Did you just open-code a do/while loop using goto? ;-) I take that back about late review being better than none. ;) > > +#ifdef CONFIG_GENERIC_CLOCKEVENTS > > +#define USE_TC_CLKEVT > > +#endif > > + > > +#ifdef CONFIG_ARCH_AT91RM9200 > > +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's > > + * always running ... configuring a TC channel to work the same way > > + * would just waste some power. > > + */ > > +#undef USE_TC_CLKEVT > > +#endif > > + > > +#ifdef USE_TC_CLKEVT > > Can't you just use #ifndef CONFIG_ARCH_AT91RM9200 and avoid the whole > ifdef/define/undef dance above? I can't know that some other platform won't have a better system timer solution, and didn't want to assume that only that single venerable chip had such a solution ... it's kind of puzzling to me (software guy) that none of the newest Atmel SOCs have better timer infrastructure than they do. ;) > > + case CLOCK_EVT_MODE_ONESHOT: > > + /* slow clock, count up to RC, then irq and stop */ > > Hmm. Do you really want to stop it? Won't you get better accuracy if > you let it run and program the next event as (prev_event + delta)? No, ONESHOT means "stop after the IRQ I asked for". And when tc_next_event() is asked to trigger that IRQ, it's relative to the instant it's requested, not relative to the last one that was requested (which may not have triggered yet, or may have been quite some time ago). > > +static struct irqaction tc_irqaction = { > > + .name = "tc_clkevt", > > + .flags = IRQF_TIMER | IRQF_DISABLED, > > + .handler= ch2_irq, > > +}; > > I don't think you need to define this statically. You can call > request_irq() at arch_initcall() time. That could be done, yes ... and using request_irq()/free_irq() would also let this be linked as a module, not just statically. On the other hand, doing it this way doesn't hurt either does it? Unless a modular build is important. > > +static void __init setup_clkevents(struct platform_device *pdev, > > + struct clk *t0_clk, int clk32k_divisor_idx) > > +{ > > + struct clk *t2_clk = clk_get(>dev, "t2_clk"); > > + int irq; > > + > > + /* SOCs have either one IRQ and one clock for the whole > > +* TC block; or one each per channel. We use channel 2. > > +*/ > > + if (IS_ERR(t2_clk)) { > > + t2_clk = t0_clk; > > + irq = platform_get_irq(pdev, 0); > > + } else { > > + irq = platform_get_irq(pdev, 2); > > + clk_enable(t2_clk); > > + } > > I don't think it is safe to assume that one clock per channel always > means one irq per channel as well... On current chips, that's how it works. > What's wrong with > > irq = platform_get_irq(pdev, 2); > if (irq < 0) > irq = platform_get_irq(pdev, 0); Nothing much, except that I took the more concise path. Got patch? > > +config ATMEL_TCB_CLKSRC > > + bool "TC Block Clocksource" > > + depends on ATMEL_TCLIB && GENERIC_TIME > > + default y > > + help > > + Select this to get a high precision clocksource based on a > > + TC block with a 5+ MHz base clock rate. Two timer channels > > + are combined to make a single 32-bit timer. > > + > > + When GENERIC_CLOCKEVENTS is defined, the third timer channel > > + may be used as a clock event device supporting oneshot mode > > + (delays of up to two seconds) based on the 32 KiHz clock. > > + > > +config ATMEL_TCB_CLKSRC_BLOCK > > + int > > + depends on ATMEL_TCB_CLKSRC > > + prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || > > CPU_AT32AP700X > > + default 0 > > + range 0
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
Again, sorry for the delay...it really sucks that I haven't been able to look at this stuff closely until now. Hopefully a late review is better than no review. On Fri, 22 Feb 2008 17:28:37 -0800 David Brownell <[EMAIL PROTECTED]> wrote: > +static cycle_t tc_get_cycles(void) > +{ > + unsigned long flags; > + u32 lower, upper; > + > + raw_local_irq_save(flags); Why do you need to use the raw version? > +retry: > + upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); > + lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); > + if (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))) > + goto retry; Did you just open-code a do/while loop using goto? ;-) > +#ifdef CONFIG_GENERIC_CLOCKEVENTS > +#define USE_TC_CLKEVT > +#endif > + > +#ifdef CONFIG_ARCH_AT91RM9200 > +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's > + * always running ... configuring a TC channel to work the same way > + * would just waste some power. > + */ > +#undef USE_TC_CLKEVT > +#endif > + > +#ifdef USE_TC_CLKEVT Can't you just use #ifndef CONFIG_ARCH_AT91RM9200 and avoid the whole ifdef/define/undef dance above? > + case CLOCK_EVT_MODE_ONESHOT: > + /* slow clock, count up to RC, then irq and stop */ Hmm. Do you really want to stop it? Won't you get better accuracy if you let it run and program the next event as (prev_event + delta)? > +static struct irqaction tc_irqaction = { > + .name = "tc_clkevt", > + .flags = IRQF_TIMER | IRQF_DISABLED, > + .handler= ch2_irq, > +}; I don't think you need to define this statically. You can call request_irq() at arch_initcall() time. > +static void __init setup_clkevents(struct platform_device *pdev, > + struct clk *t0_clk, int clk32k_divisor_idx) > +{ > + struct clk *t2_clk = clk_get(>dev, "t2_clk"); > + int irq; > + > + /* SOCs have either one IRQ and one clock for the whole > + * TC block; or one each per channel. We use channel 2. > + */ > + if (IS_ERR(t2_clk)) { > + t2_clk = t0_clk; > + irq = platform_get_irq(pdev, 0); > + } else { > + irq = platform_get_irq(pdev, 2); > + clk_enable(t2_clk); > + } I don't think it is safe to assume that one clock per channel always means one irq per channel as well... What's wrong with irq = platform_get_irq(pdev, 2); if (irq < 0) irq = platform_get_irq(pdev, 0); ? > +config ATMEL_TCB_CLKSRC > + bool "TC Block Clocksource" > + depends on ATMEL_TCLIB && GENERIC_TIME > + default y > + help > + Select this to get a high precision clocksource based on a > + TC block with a 5+ MHz base clock rate. Two timer channels > + are combined to make a single 32-bit timer. > + > + When GENERIC_CLOCKEVENTS is defined, the third timer channel > + may be used as a clock event device supporting oneshot mode > + (delays of up to two seconds) based on the 32 KiHz clock. > + > +config ATMEL_TCB_CLKSRC_BLOCK > + int > + depends on ATMEL_TCB_CLKSRC > + prompt "TC Block" if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || > CPU_AT32AP700X > + default 0 > + range 0 1 Hmm...I don't like the direction this is going... How about we make tcb_clksrc_init() global and call it from the platform code with whatever TCB the platform thinks is appropriate? Perhaps remove the prompt from ATMEL_TCB_CLKSRC and have the platform select it as well? I certainly want to force this stuff on on the AP7000...otherwise we'll just get lots of complaints that the thing is using 4x more power than it's supposed to... Haavard -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
Again, sorry for the delay...it really sucks that I haven't been able to look at this stuff closely until now. Hopefully a late review is better than no review. On Fri, 22 Feb 2008 17:28:37 -0800 David Brownell [EMAIL PROTECTED] wrote: +static cycle_t tc_get_cycles(void) +{ + unsigned long flags; + u32 lower, upper; + + raw_local_irq_save(flags); Why do you need to use the raw version? +retry: + upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); + lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); + if (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))) + goto retry; Did you just open-code a do/while loop using goto? ;-) +#ifdef CONFIG_GENERIC_CLOCKEVENTS +#define USE_TC_CLKEVT +#endif + +#ifdef CONFIG_ARCH_AT91RM9200 +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's + * always running ... configuring a TC channel to work the same way + * would just waste some power. + */ +#undef USE_TC_CLKEVT +#endif + +#ifdef USE_TC_CLKEVT Can't you just use #ifndef CONFIG_ARCH_AT91RM9200 and avoid the whole ifdef/define/undef dance above? + case CLOCK_EVT_MODE_ONESHOT: + /* slow clock, count up to RC, then irq and stop */ Hmm. Do you really want to stop it? Won't you get better accuracy if you let it run and program the next event as (prev_event + delta)? +static struct irqaction tc_irqaction = { + .name = tc_clkevt, + .flags = IRQF_TIMER | IRQF_DISABLED, + .handler= ch2_irq, +}; I don't think you need to define this statically. You can call request_irq() at arch_initcall() time. +static void __init setup_clkevents(struct platform_device *pdev, + struct clk *t0_clk, int clk32k_divisor_idx) +{ + struct clk *t2_clk = clk_get(pdev-dev, t2_clk); + int irq; + + /* SOCs have either one IRQ and one clock for the whole + * TC block; or one each per channel. We use channel 2. + */ + if (IS_ERR(t2_clk)) { + t2_clk = t0_clk; + irq = platform_get_irq(pdev, 0); + } else { + irq = platform_get_irq(pdev, 2); + clk_enable(t2_clk); + } I don't think it is safe to assume that one clock per channel always means one irq per channel as well... What's wrong with irq = platform_get_irq(pdev, 2); if (irq 0) irq = platform_get_irq(pdev, 0); ? +config ATMEL_TCB_CLKSRC + bool TC Block Clocksource + depends on ATMEL_TCLIB GENERIC_TIME + default y + help + Select this to get a high precision clocksource based on a + TC block with a 5+ MHz base clock rate. Two timer channels + are combined to make a single 32-bit timer. + + When GENERIC_CLOCKEVENTS is defined, the third timer channel + may be used as a clock event device supporting oneshot mode + (delays of up to two seconds) based on the 32 KiHz clock. + +config ATMEL_TCB_CLKSRC_BLOCK + int + depends on ATMEL_TCB_CLKSRC + prompt TC Block if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X + default 0 + range 0 1 Hmm...I don't like the direction this is going... How about we make tcb_clksrc_init() global and call it from the platform code with whatever TCB the platform thinks is appropriate? Perhaps remove the prompt from ATMEL_TCB_CLKSRC and have the platform select it as well? I certainly want to force this stuff on on the AP7000...otherwise we'll just get lots of complaints that the thing is using 4x more power than it's supposed to... Haavard -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
Again, sorry for the delay...it really sucks that I haven't been able to look at this stuff closely until now. Hopefully a late review is better than no review. Yes. The review I've gotten so far has been of the it works for me, thanks variety. (The only issue reported to me is that NO_HZ on AT91 seems to make the DBGU lose characters sometimes ... that one-byte fifo makes trouble whenever there's the slightest delay in IRQ handling, and NO_HZ can easily add such delays as part of ensuring that jiffies is current before invoking handlers.) On Fri, 22 Feb 2008 17:28:37 -0800 David Brownell [EMAIL PROTECTED] wrote: +static cycle_t tc_get_cycles(void) +{ + unsigned long flags; + u32 lower, upper; + + raw_local_irq_save(flags); Why do you need to use the raw version? This is part of the system timer code, and it should never be a preemption point. Plus I didn't want to waste any instruction cycles in code that runs before e.g. the DBGU IRQ handler would get called... observably, such extra cycles *do* hurt. +retry: + upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); + lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); + if (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))) + goto retry; Did you just open-code a do/while loop using goto? ;-) I take that back about late review being better than none. ;) +#ifdef CONFIG_GENERIC_CLOCKEVENTS +#define USE_TC_CLKEVT +#endif + +#ifdef CONFIG_ARCH_AT91RM9200 +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's + * always running ... configuring a TC channel to work the same way + * would just waste some power. + */ +#undef USE_TC_CLKEVT +#endif + +#ifdef USE_TC_CLKEVT Can't you just use #ifndef CONFIG_ARCH_AT91RM9200 and avoid the whole ifdef/define/undef dance above? I can't know that some other platform won't have a better system timer solution, and didn't want to assume that only that single venerable chip had such a solution ... it's kind of puzzling to me (software guy) that none of the newest Atmel SOCs have better timer infrastructure than they do. ;) + case CLOCK_EVT_MODE_ONESHOT: + /* slow clock, count up to RC, then irq and stop */ Hmm. Do you really want to stop it? Won't you get better accuracy if you let it run and program the next event as (prev_event + delta)? No, ONESHOT means stop after the IRQ I asked for. And when tc_next_event() is asked to trigger that IRQ, it's relative to the instant it's requested, not relative to the last one that was requested (which may not have triggered yet, or may have been quite some time ago). +static struct irqaction tc_irqaction = { + .name = tc_clkevt, + .flags = IRQF_TIMER | IRQF_DISABLED, + .handler= ch2_irq, +}; I don't think you need to define this statically. You can call request_irq() at arch_initcall() time. That could be done, yes ... and using request_irq()/free_irq() would also let this be linked as a module, not just statically. On the other hand, doing it this way doesn't hurt either does it? Unless a modular build is important. +static void __init setup_clkevents(struct platform_device *pdev, + struct clk *t0_clk, int clk32k_divisor_idx) +{ + struct clk *t2_clk = clk_get(pdev-dev, t2_clk); + int irq; + + /* SOCs have either one IRQ and one clock for the whole +* TC block; or one each per channel. We use channel 2. +*/ + if (IS_ERR(t2_clk)) { + t2_clk = t0_clk; + irq = platform_get_irq(pdev, 0); + } else { + irq = platform_get_irq(pdev, 2); + clk_enable(t2_clk); + } I don't think it is safe to assume that one clock per channel always means one irq per channel as well... On current chips, that's how it works. What's wrong with irq = platform_get_irq(pdev, 2); if (irq 0) irq = platform_get_irq(pdev, 0); Nothing much, except that I took the more concise path. Got patch? +config ATMEL_TCB_CLKSRC + bool TC Block Clocksource + depends on ATMEL_TCLIB GENERIC_TIME + default y + help + Select this to get a high precision clocksource based on a + TC block with a 5+ MHz base clock rate. Two timer channels + are combined to make a single 32-bit timer. + + When GENERIC_CLOCKEVENTS is defined, the third timer channel + may be used as a clock event device supporting oneshot mode + (delays of up to two seconds) based on the 32 KiHz clock. + +config ATMEL_TCB_CLKSRC_BLOCK + int + depends on ATMEL_TCB_CLKSRC + prompt TC Block if ARCH_AT91RM9200 || ARCH_AT91SAM9260 || CPU_AT32AP700X + default 0 + range 0 1 Hmm...I don't like the direction this is going... How about we make tcb_clksrc_init() global and call it from the platform code with whatever TCB the platform thinks is
[patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
Clocksource and clockevent device based on the Atmel TC blocks. The clockevent device handles both periodic and oneshot modes, so this enables NO_HZ and high res timers on some platforms that previously couldn't use those mechanisms. This works on both AVR32 and AT91 chips, given relevant patches for tclib support (always) and clockevents (or else this will only look like a higher precision clocksource). It's an updated and modularized version of an AT91-only patch that has circulated for some time now. Signed-off-by: David Brownell <[EMAIL PROTECTED]> --- As with the preceding patch, this depends on platform updates that won't merge before 2.6.26 ... in this case, updates to switch over to clocksources (at91sam9 chips, but not at91rm9200) and clockevents (avr32 and at91sam9), on top of platform_device setup. drivers/clocksource/Makefile |1 drivers/clocksource/tcb_clksrc.c | 303 +++ drivers/misc/Kconfig | 25 +++ 3 files changed, 329 insertions(+) --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o obj-$(CONFIG_X86_CYCLONE_TIMER)+= cyclone.o obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o --- /dev/null +++ b/drivers/clocksource/tcb_clksrc.c @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* + * We're configured to use a specific TC block, one that's not hooked + * up to external hardware, to provide a time solution: + * + * - Two channels combine to create a free-running 32 bit counter + * with a base rate of 5+ MHz, packaged as a clocksource (with + * resolution better than 200 nsec). + * + * - The third channel may be used to provide a 16-bit clockevent + * source, used in either periodic or oneshot mode. This runs + * at 32 KiHZ, and can handle delays of up to two seconds. + * + * A boot clocksource and clockevent source are also currently needed, + * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so + * this code can be used when init_timers() is called, well before most + * devices are set up. (Some low end AT91 parts, which can run uClinux, + * have only the timers in one TC block... they currently don't support + * the tclib code, because of that initialization issue.) + * + * REVISIT behavior during system suspend states... we should disable + * all clocks and save the power. Easily done for clockevent devices, + * but clocksources won't necessarily get the needed notifications. + * For deeper system sleep states, this will be mandatory... + */ + +static void __iomem *tcaddr; + +static cycle_t tc_get_cycles(void) +{ + unsigned long flags; + u32 lower, upper; + + raw_local_irq_save(flags); +retry: + upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); + lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); + if (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))) + goto retry; + + raw_local_irq_restore(flags); + return (upper << 16) | lower; +} + +static struct clocksource clksrc = { + .name = "tcb_clksrc", + .rating = 200, + .read = tc_get_cycles, + .mask = CLOCKSOURCE_MASK(32), + .shift = 18, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +#ifdef CONFIG_GENERIC_CLOCKEVENTS +#define USE_TC_CLKEVT +#endif + +#ifdef CONFIG_ARCH_AT91RM9200 +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's + * always running ... configuring a TC channel to work the same way + * would just waste some power. + */ +#undef USE_TC_CLKEVT +#endif + +#ifdef USE_TC_CLKEVT + +/* For now, we always use the 32K clock ... this optimizes for NO_HZ, + * because using one of the divided clocks would usually mean the + * tick rate can never be less than several dozen Hz (vs 0.5 Hz). + * + * A divided clock could be good for high resolution timers, since + * 30.5 usec resolution can seem "low". + */ +static u32 timer_clock; + +static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) +{ + __raw_writel(0xff, tcaddr + ATMEL_TC_REG(2, IDR)); + __raw_writel(ATMEL_TC_CLKDIS, tcaddr + ATMEL_TC_REG(2, CCR)); + + switch (m) { + + /* By not making the gentime core emulate periodic mode on top +* of oneshot, we get lower overhead and improved accuracy. +*/ + case CLOCK_EVT_MODE_PERIODIC: + /* slow clock, count up to RC, then irq and restart */ + __raw_writel(timer_clock + | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, + tcaddr + ATMEL_TC_REG(2, CMR)); + __raw_writel((32768 + HZ/2) / HZ, tcaddr + ATMEL_TC_REG(2, RC)); + + /* Enable clock and interrupts on RC
[patch 2.6.25-rc2-git 2/2] atmel_tc clocksource/clockevent code
Clocksource and clockevent device based on the Atmel TC blocks. The clockevent device handles both periodic and oneshot modes, so this enables NO_HZ and high res timers on some platforms that previously couldn't use those mechanisms. This works on both AVR32 and AT91 chips, given relevant patches for tclib support (always) and clockevents (or else this will only look like a higher precision clocksource). It's an updated and modularized version of an AT91-only patch that has circulated for some time now. Signed-off-by: David Brownell [EMAIL PROTECTED] --- As with the preceding patch, this depends on platform updates that won't merge before 2.6.26 ... in this case, updates to switch over to clocksources (at91sam9 chips, but not at91rm9200) and clockevents (avr32 and at91sam9), on top of platform_device setup. drivers/clocksource/Makefile |1 drivers/clocksource/tcb_clksrc.c | 303 +++ drivers/misc/Kconfig | 25 +++ 3 files changed, 329 insertions(+) --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o obj-$(CONFIG_X86_CYCLONE_TIMER)+= cyclone.o obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o --- /dev/null +++ b/drivers/clocksource/tcb_clksrc.c @@ -0,0 +1,303 @@ +#include linux/init.h +#include linux/clocksource.h +#include linux/clockchips.h +#include linux/interrupt.h +#include linux/irq.h + +#include linux/clk.h +#include linux/err.h +#include linux/ioport.h +#include linux/io.h +#include linux/platform_device.h +#include linux/atmel_tc.h + + +/* + * We're configured to use a specific TC block, one that's not hooked + * up to external hardware, to provide a time solution: + * + * - Two channels combine to create a free-running 32 bit counter + * with a base rate of 5+ MHz, packaged as a clocksource (with + * resolution better than 200 nsec). + * + * - The third channel may be used to provide a 16-bit clockevent + * source, used in either periodic or oneshot mode. This runs + * at 32 KiHZ, and can handle delays of up to two seconds. + * + * A boot clocksource and clockevent source are also currently needed, + * unless the relevant platforms (ARM/AT91, AVR32/AT32) are changed so + * this code can be used when init_timers() is called, well before most + * devices are set up. (Some low end AT91 parts, which can run uClinux, + * have only the timers in one TC block... they currently don't support + * the tclib code, because of that initialization issue.) + * + * REVISIT behavior during system suspend states... we should disable + * all clocks and save the power. Easily done for clockevent devices, + * but clocksources won't necessarily get the needed notifications. + * For deeper system sleep states, this will be mandatory... + */ + +static void __iomem *tcaddr; + +static cycle_t tc_get_cycles(void) +{ + unsigned long flags; + u32 lower, upper; + + raw_local_irq_save(flags); +retry: + upper = __raw_readl(tcaddr + ATMEL_TC_REG(1, CV)); + lower = __raw_readl(tcaddr + ATMEL_TC_REG(0, CV)); + if (upper != __raw_readl(tcaddr + ATMEL_TC_REG(1, CV))) + goto retry; + + raw_local_irq_restore(flags); + return (upper 16) | lower; +} + +static struct clocksource clksrc = { + .name = tcb_clksrc, + .rating = 200, + .read = tc_get_cycles, + .mask = CLOCKSOURCE_MASK(32), + .shift = 18, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +#ifdef CONFIG_GENERIC_CLOCKEVENTS +#define USE_TC_CLKEVT +#endif + +#ifdef CONFIG_ARCH_AT91RM9200 +/* The AT91rm9200 system timer is a oneshot-capable 32k timer that's + * always running ... configuring a TC channel to work the same way + * would just waste some power. + */ +#undef USE_TC_CLKEVT +#endif + +#ifdef USE_TC_CLKEVT + +/* For now, we always use the 32K clock ... this optimizes for NO_HZ, + * because using one of the divided clocks would usually mean the + * tick rate can never be less than several dozen Hz (vs 0.5 Hz). + * + * A divided clock could be good for high resolution timers, since + * 30.5 usec resolution can seem low. + */ +static u32 timer_clock; + +static void tc_mode(enum clock_event_mode m, struct clock_event_device *d) +{ + __raw_writel(0xff, tcaddr + ATMEL_TC_REG(2, IDR)); + __raw_writel(ATMEL_TC_CLKDIS, tcaddr + ATMEL_TC_REG(2, CCR)); + + switch (m) { + + /* By not making the gentime core emulate periodic mode on top +* of oneshot, we get lower overhead and improved accuracy. +*/ + case CLOCK_EVT_MODE_PERIODIC: + /* slow clock, count up to RC, then irq and restart */ + __raw_writel(timer_clock + | ATMEL_TC_WAVE | ATMEL_TC_WAVESEL_UP_AUTO, + tcaddr +