* [PATCH] arm: Add unwinding annotations for 64bit division functions
From: Dave Martin @ 2011-09-21 11:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2285dff3fee56758b6279062a5a30dc7.squirrel@www.codeaurora.org>
On Mon, Sep 19, 2011 at 06:55:39PM -0700, Laura Abbott wrote:
>
> On Mon, September 19, 2011 4:22 pm, Nicolas Pitre wrote:
> > On Mon, 19 Sep 2011, Laura Abbott wrote:
> >
> >> The 64bit division functions never had unwinding annotations
> >> added. This prevents a backtrace from being printed within
> >> the function and if a division by 0 occurs. Add the annotations.
> >>
> >> Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
> >> ---
> >> arch/arm/lib/div64.S | 8 ++++++++
> >> 1 files changed, 8 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
> >> index faa7748..e55c484 100644
> >> --- a/arch/arm/lib/div64.S
> >> +++ b/arch/arm/lib/div64.S
> >> @@ -13,6 +13,7 @@
> >> */
> >>
> >> #include <linux/linkage.h>
> >> +#include <asm/unwind.h>
> >>
> >> #ifdef __ARMEB__
> >> #define xh r0
> >> @@ -44,6 +45,7 @@
> >> */
> >>
> >> ENTRY(__do_div64)
> >> +UNWIND(.fnstart)
> >>
> >> @ Test for easy paths first.
> >> subs ip, r4, #1
> >> @@ -189,7 +191,12 @@ ENTRY(__do_div64)
> >> moveq yh, xh
> >> moveq xh, #0
> >> moveq pc, lr
> >> +UNWIND(.fnend)
> >>
> >> +UNWIND(.fnstart)
> >> +UNWIND(.pad #4)
> >> +UNWIND(.save {lr})
> >> +Ldiv0_64:
> >
> > Why this phony fnend+fnstart here?
> >
> If a division by 0 occurs, we need to be able to access the saved LR on
> the stack which is setup right before calling the __div0 function. This
> can't go at the top of __do_div64 because if we try to do a backtrace from
> within __do_div64 the annotation won't be correct as the LR was never
> saved on the stack. (yes, __do_div64 is all register math but it's still
> possible to take a prefetch abort in the middle of that function. Taking a
> prefetch abort in the middle of __do_div64 is what found this issue in the
> first place.) This setup handles both cases correctly.
Talking to Catalin a bit more, it sounds like prefetch aborts should not
happen in kernel code, and data aborts should not happen when accessing
the kernel stack. If either of these happens, there's no guarantee that
the kernel will be able to recover from the situation fully, so
backtracing may not be the primary concern.
The kinds of situation that the backtracer _can_ cope with are:
a) explicit, synchonous backtrace requests (BUG() etc. within C
functions)
b) aborts when accessing random memory (but not the stack) outside the
function progolgue/epilogue sequences (i.e., so that the state the
unwind info described actually matches reality)
If you get a data abort when accessing the kernel stack, the backtracer
probably won't work at all, because it relies on the same stack. Faults
during prologue/epilogue sequences can't be handled correctly because
the unwind annotations don't descirbe the interim state during these
sequences. There is no general way to use the unwinder annotations to
describe fully how the state evolves during prologue/epilogue sequences.
So, having thought about it, it may be that having the extra .fnstart/
.fnend pair doesn't really help that much after all.
For this code, we do want the unwind state to be properly recorded for
the "bl __div0" call site after Ldiv0_64; but we probably don't need to
worry about backtracing from any other point in this code -- partly
becuase the probably of needing to do it is very low, and partly because
we will likely fail to produce a backtrace in this situation. If this
is a reasonable assumption, then a single unwind annotation block should
be sufficient:
ENTRY(__do_div64)
UNWIND(.fnstart)
subs ip, r4, #1
@ ...
moveq pc, lr
UNWIND(.pad #4)
UNWIND(.save {lr}
stmfd sp!, {r0, lr}
@ ...
bl __div0
@ ...
UNWIND(.fnend)
The location of the .pad and .save is of course not meaningful for the
unwind data: only their respective order, and the fact that they appear
between the .fnstart/.fnend directives. Putting them next to the stmfd
just makes the code easier to read.
The extra annotations in the original patch are harmless, though.
Cheers
---Dave
^ permalink raw reply
* [PATCH v3 0/4] ARM: Samsung: Add board setup for M-5MOLS and NOON010PC30 camera sensors
From: Kukjin Kim @ 2011-09-21 11:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316453441-13525-1-git-send-email-s.nawrocki@samsung.com>
Sylwester Nawrocki wrote:
>
> Hello,
>
> the following change set adds board setup code for NOOON01PC30 sensor on
> GONI
> and M-5MOLS on UNIVERSAL_C210 board.
> Some clocks are modified in line with latest FIMC driver modifications for
v3.2.
>
> Changes since previous version:
> - improved error handling, switched to gpio_request_array()
> - created against git://github.com/kgene/linux-samsung.git for-next
>
Thanks for your re-submitting :)
> Sylwester Nawrocki (4):
> ARM: S5PV210: Rename sclk_cam clocks for FIMC media driver
> ARM: S5PV210: Add support for NOON010PC30 sensor on GONI board
> ARM: EXYNOS4: Rename sclk_cam clocks for FIMC driver
> ARM: S5PV210: UNIVERSAL_C210: Add support for M-5MOLS image sensor
>
> arch/arm/mach-exynos4/Kconfig | 3 +
> arch/arm/mach-exynos4/clock.c | 6 +-
> arch/arm/mach-exynos4/mach-universal_c210.c | 206
> +++++++++++++++++++++++++-
> arch/arm/mach-s5pv210/Kconfig | 1 +
> arch/arm/mach-s5pv210/clock.c | 6 +-
> arch/arm/mach-s5pv210/mach-goni.c | 53 +++++++
> 6 files changed, 259 insertions(+), 16 deletions(-)
> --
> 1.7.6.3
>
> The patches can be pulled from
git://git.infradead.org/users/kmpark/linux-2.6-
> samsung,
> branch samsung-board-camera.
>
Looks ok to me, will apply.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH V2 0/3] ARM: EXYNOS4: Support suspend/resume for EXYNOS4212
From: Kukjin Kim @ 2011-09-21 11:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316395542-27578-1-git-send-email-boyko.lee@samsung.com>
Jongpill Lee wrote:
>
> [PATCH V2 1/3] ARM: EXYNOS4: Modify PMU register setting function
> [PATCH V2 2/3] ARM: EXYNOS4: Add PMU register definition for EXYNOS4212
> [PATCH V2 3/3] ARM: EXYNOS4: Support suspend/resume for EXYNOS4212
Would be helpful if you could add changes since previous submitted patches
next time :)
Looks ok to me, will apply.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH] arm: Add unwinding annotations for 64bit division functions
From: Russell King - ARM Linux @ 2011-09-21 11:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110921113906.GB2872@arm.com>
On Wed, Sep 21, 2011 at 12:39:09PM +0100, Dave Martin wrote:
> Talking to Catalin a bit more, it sounds like prefetch aborts should not
> happen in kernel code, and data aborts should not happen when accessing
> the kernel stack.
No faults should happen in kernel code, except for:
1. instructions specifically marked in the exception table, which are used
to access user memory.
2. instructions causing an 'undefined instruction' exception.
Standard ARM instructions like 'add', 'mov' etc should _never_ fault,
and if they do that means your core isn't executing ARM instructions
correctly (eg, the hardware design is faulty.)
Instructions such as VFP, kprobes tracing, etc are expected fault
locations, and those are fairly well controlled where they can be placed.
With things like ftrace, it certainly is the case that the unwinder can
theoretically be called from almost anywhere in a function.
So I suggest that this does need to be fixed, and you can't rely on
"prefetch aborts should not happen". That's true of prefetch aborts
but not of other aborts.
^ permalink raw reply
* [RESEND PATCH 2/3] ARM: EXYNOS4: Update consistent DMA size to 8MB
From: Kukjin Kim @ 2011-09-21 11:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316583860-32510-3-git-send-email-hatim.rv@samsung.com>
Hatim Ali wrote:
>
> Change the consistent DMA allocation to 8MB to support the
> TVOUT driver.
>
Probably, this conflicts with 'Remove define CONSISTENT_DMA_SIZE'.
As other guy said, we need to check the progress of it before this.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
> NOTE: Once CMA support is merged into mainline, we will use it for memory
> allocation.
>
> Signed-off-by: Hatim Ali <hatim.rv@samsung.com>
> ---
> arch/arm/mach-exynos4/include/mach/memory.h | 2 ++
> 1 files changed, 2 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-exynos4/include/mach/memory.h b/arch/arm/mach-
> exynos4/include/mach/memory.h
> index 374ef2c..7549742 100644
> --- a/arch/arm/mach-exynos4/include/mach/memory.h
> +++ b/arch/arm/mach-exynos4/include/mach/memory.h
> @@ -15,6 +15,8 @@
>
> #define PLAT_PHYS_OFFSET UL(0x40000000)
>
> +#define CONSISTENT_DMA_SIZE SZ_8M
> +
> /* Maximum of 256MiB in one bank */
> #define MAX_PHYSMEM_BITS 32
> #define SECTION_SIZE_BITS 28
> --
> 1.7.2.3
^ permalink raw reply
* [PATCH v2 3/3] net/fec: add imx6q enet support
From: Shawn Guo @ 2011-09-21 11:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110921113239.GF1966@pengutronix.de>
On Wed, Sep 21, 2011 at 01:32:39PM +0200, Wolfram Sang wrote:
>
> > +/* Controller has GBIT support */
> > +#define FEC_QUIRK_HAS_GBIT (1 << 3)
>
> Heh, this is not really a quirk, but a nice feature :) I think we can
> drop QUIRK if we see driver_data more as "flags" instead of "quirks"?
> Minor, though.
>
As you have told, all these FEC_QUIRK_* are just flags actually. The
name was pick to keep the consistency, as they are all used for the
same purpose.
> > MODULE_DEVICE_TABLE(of, fec_dt_ids);
> > @@ -373,6 +383,7 @@ fec_restart(struct net_device *ndev, int duplex)
> > int i;
> > u32 temp_mac[2];
> > u32 rcntl = OPT_FRAME_SIZE | 0x04;
> > + u32 ecntl = 0x2; /* ETHEREN */
>
> Also minor, but the patch looks like a good oportunity to start
> replacing magic values with proper defines?
>
There are already so many magic numbers. It really deserves a separated
patch.
I heard that Uwe had a plan to do that some time ago. He gives up
now? :)
--
Regards,
Shawn
^ permalink raw reply
* [PATCH v2 1/3] net/fec: change phy-reset-gpio request warning to debug message
From: Shawn Guo @ 2011-09-21 12:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110921112555.GE1966@pengutronix.de>
On Wed, Sep 21, 2011 at 01:25:55PM +0200, Wolfram Sang wrote:
> Hi Shawn,
>
> On Wed, Sep 21, 2011 at 07:10:30PM +0800, Shawn Guo wrote:
> > FEC can work without a phy reset on some platforms, which means not
> > very platform necessarily have a phy-reset gpio encoded in device tree.
> > So it makes more sense to have the phy-reset-gpio request failure as
> > a debug message rather than a warning.
>
> Or remove it entirely?
>
I would like to keep it. When people want to debug at this point, they
do not need to type the debug message.
> >
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > ---
> > drivers/net/ethernet/freescale/fec.c | 2 +-
> > 1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c
> > index 158b82e..a057abf 100644
> > --- a/drivers/net/ethernet/freescale/fec.c
> > +++ b/drivers/net/ethernet/freescale/fec.c
> > @@ -1422,7 +1422,7 @@ static int __devinit fec_reset_phy(struct platform_device *pdev)
> > phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
> > err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset");
> > if (err) {
> > - pr_warn("FEC: failed to get gpio phy-reset: %d\n", err);
> > + pr_debug("FEC: failed to get gpio phy-reset: %d\n", err);
> > return err;
>
> I also wanted to suggested to drop returning the error code, since it is
> not an error anymore, strictly speaking. Then I noticed that the caller
> does not check the error code. So, this could be added or turn the
> function to void?
>
To me, keep the return value as integer is more scalable. Someday,
someone need to add more stuff in the function, or want to improve
the caller to check return value, it plays.
Regards,
Shawn
> > }
> > msleep(1);
> > --
^ permalink raw reply
* [PATCH V2 1/3] ARM: EXYNOS4: Add TVOUT support for SMDKV310
From: Kukjin Kim @ 2011-09-21 12:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316583860-32510-2-git-send-email-hatim.rv@samsung.com>
Hatim Ali wrote:
>
> Add support for TVOUT on SMDKV310 board.
>
> Signed-off-by: Hatim Ali <hatim.rv@samsung.com>
> ---
> Changes since V1:
> Incorporated changes as suggested by Tomasz Stanislawski
> - Added GPIO settings for hot-plug detection.
> - Added setting hdmi and mixer's parent for TV power domain.
>
> arch/arm/mach-exynos4/Kconfig | 2 ++
> arch/arm/mach-exynos4/mach-smdkv310.c | 25
> +++++++++++++++++++++++++
> 2 files changed, 27 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
> index 3b594fe..0bf0fe04 100644
> --- a/arch/arm/mach-exynos4/Kconfig
> +++ b/arch/arm/mach-exynos4/Kconfig
> @@ -131,6 +131,7 @@ config MACH_SMDKV310
> select S3C_DEV_RTC
> select S3C_DEV_WDT
> select S3C_DEV_I2C1
> + select S5P_DEV_I2C_HDMIPHY
> select S5P_DEV_MFC
> select S3C_DEV_HSMMC
> select S3C_DEV_HSMMC1
> @@ -140,6 +141,7 @@ config MACH_SMDKV310
> select EXYNOS4_DEV_AHCI
> select SAMSUNG_DEV_KEYPAD
> select EXYNOS4_DEV_PD
> + select S5P_DEV_TV
> select SAMSUNG_DEV_PWM
> select EXYNOS4_DEV_SYSMMU
> select EXYNOS4_SETUP_FIMD0
> diff --git a/arch/arm/mach-exynos4/mach-smdkv310.c b/arch/arm/mach-
> exynos4/mach-smdkv310.c
> index 7ce4d8b..50de270 100644
> --- a/arch/arm/mach-exynos4/mach-smdkv310.c
> +++ b/arch/arm/mach-exynos4/mach-smdkv310.c
> @@ -239,6 +239,7 @@ static struct platform_device *smdkv310_devices[]
> __initdata = {
> &s3c_device_hsmmc2,
> &s3c_device_hsmmc3,
> &s3c_device_i2c1,
> + &s5p_device_i2c_hdmiphy,
> &s3c_device_rtc,
> &s3c_device_wdt,
> &exynos4_device_ac97,
> @@ -262,6 +263,8 @@ static struct platform_device *smdkv310_devices[]
> __initdata = {
> &smdkv310_lcd_lte480wv,
> &smdkv310_smsc911x,
> &exynos4_device_ahci,
> + &s5p_device_hdmi,
> + &s5p_device_mixer,
> };
>
> static void __init smdkv310_smsc911x_init(void)
> @@ -298,6 +301,25 @@ static struct platform_pwm_backlight_data
> smdkv310_bl_data = {
> .pwm_period_ns = 1000,
> };
>
> +static void s5p_tv_setup(void)
> +{
> + int ret;
> +
> + /* direct HPD to HDMI chip */
> + ret = gpio_request(EXYNOS4_GPX3(7), "hpd-plug");
> +
> + if (!ret) {
> + gpio_direction_input(EXYNOS4_GPX3(7));
> + s3c_gpio_cfgpin_range(EXYNOS4_GPX3(7),
> + 1, S3C_GPIO_SFN(3));
Why do you use 's3c_gpio_cfgpin_range()' for just one gpio pin not range...?
> + } else
> + pr_err("Failed to request gpio for hpd: %d\n", ret);
According to coding style, should be added { and } around above.
> +
> + /* setup dependencies between TV devices */
> + s5p_device_hdmi.dev.parent = &exynos4_device_pd[PD_TV].dev;
> + s5p_device_mixer.dev.parent = &exynos4_device_pd[PD_TV].dev;
> +}
> +
> static void __init smdkv310_map_io(void)
> {
> s5p_init_io(NULL, 0, S5P_VA_CHIPID);
> @@ -327,6 +349,9 @@ static void __init smdkv310_machine_init(void)
> samsung_bl_set(&smdkv310_bl_gpio_info, &smdkv310_bl_data);
> s5p_fimd0_set_platdata(&smdkv310_lcd0_pdata);
>
> + s5p_tv_setup();
> + s5p_i2c_hdmiphy_set_platdata(NULL);
> +
> platform_add_devices(smdkv310_devices,
> ARRAY_SIZE(smdkv310_devices));
> s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
> }
> --
> 1.7.2.3
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH 53/57] sound: irq: Remove IRQF_DISABLED
From: Yong Zhang @ 2011-09-21 12:10 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <s5hsjnqxlxb.wl%tiwai@suse.de>
On Wed, Sep 21, 2011 at 11:52:00AM +0200, Takashi Iwai wrote:
> At Wed, 21 Sep 2011 17:28:54 +0800,
> Yong Zhang wrote:
> >
> > Since commit [c58543c8: genirq: Run irq handlers with interrupts disabled],
>
> Hm, this id hits a different commit:
> commit c58543c869606532c2382f027d6466f4672ea756
> Author: David S. Miller <davem@davemloft.net>
> Date: Tue Oct 13 00:49:09 2009 -0700
>
> sparc64: Set IRQF_DISABLED on LDC channel IRQs.
>
> You mean commit e58aa3d2d0cc01ad8d6f7f640a0670433f794922?
Oh, yes. No idea how I made it wrong :(
Thanks,
Yong
>
> > We run all interrupt handlers with interrupts disabled
> > and we even check and yell when an interrupt handler
> > returns with interrupts enabled (see commit [b738a50a:
> > genirq: Warn when handler enables interrupts]).
> >
> > So now this flag is a NOOP and can be removed.
> >
> > Signed-off-by: Yong Zhang <yong.zhang0@gmail.com>
> > Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
>
> Do you want to merge by yourself or shall I take it to sound git tree?
> Since IRQF_DISABLED isn't used, it can be applied safely in 3.1-based
> tree, right?
>
> Anyway, if needed, take my ack:
> Acked-by: Takashi Iwai <tiwai@suse.de>
>
>
> thanks,
>
> Takashi
>
> > ---
> > include/sound/initval.h | 2 +-
> > sound/arm/aaci.c | 2 +-
> > sound/arm/pxa2xx-ac97-lib.c | 2 +-
> > sound/drivers/ml403-ac97cr.c | 4 ++--
> > sound/drivers/mpu401/mpu401_uart.c | 2 +-
> > sound/drivers/mtpav.c | 2 +-
> > sound/drivers/serial-u16550.c | 2 +-
> > sound/isa/ad1816a/ad1816a_lib.c | 2 +-
> > sound/isa/es1688/es1688_lib.c | 2 +-
> > sound/isa/es18xx.c | 2 +-
> > sound/isa/gus/gus_main.c | 2 +-
> > sound/isa/gus/gusmax.c | 2 +-
> > sound/isa/gus/interwave.c | 2 +-
> > sound/isa/opl3sa2.c | 2 +-
> > sound/isa/opti9xx/opti92x-ad1848.c | 2 +-
> > sound/isa/sb/sb_common.c | 2 +-
> > sound/isa/wavefront/wavefront.c | 2 +-
> > sound/isa/wss/wss_lib.c | 2 +-
> > sound/mips/au1x00.c | 4 ++--
> > sound/pci/sis7019.c | 4 ++--
> > sound/ppc/snd_ps3.c | 2 +-
> > sound/soc/au1x/dma.c | 2 +-
> > sound/soc/codecs/tlv320dac33.c | 2 +-
> > sound/soc/nuc900/nuc900-pcm.c | 2 +-
> > sound/soc/samsung/ac97.c | 2 +-
> > sound/soc/sh/fsi.c | 2 +-
> > sound/soc/txx9/txx9aclc-ac97.c | 2 +-
> > sound/sparc/amd7930.c | 2 +-
> > 28 files changed, 31 insertions(+), 31 deletions(-)
> >
> > diff --git a/include/sound/initval.h b/include/sound/initval.h
> > index 1daa6df..f99a0d2 100644
> > --- a/include/sound/initval.h
> > +++ b/include/sound/initval.h
> > @@ -62,7 +62,7 @@ static int snd_legacy_find_free_irq(int *irq_table)
> > {
> > while (*irq_table != -1) {
> > if (!request_irq(*irq_table, snd_legacy_empty_irq_handler,
> > - IRQF_DISABLED | IRQF_PROBE_SHARED, "ALSA Test IRQ",
> > + IRQF_PROBE_SHARED, "ALSA Test IRQ",
> > (void *) irq_table)) {
> > free_irq(*irq_table, (void *) irq_table);
> > return *irq_table;
> > diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
> > index d0cead3..e518d38 100644
> > --- a/sound/arm/aaci.c
> > +++ b/sound/arm/aaci.c
> > @@ -443,7 +443,7 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream)
> > mutex_lock(&aaci->irq_lock);
> > if (!aaci->users++) {
> > ret = request_irq(aaci->dev->irq[0], aaci_irq,
> > - IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci);
> > + IRQF_SHARED, DRIVER_NAME, aaci);
> > if (ret != 0)
> > aaci->users--;
> > }
> > diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
> > index 88eec38..8ad6535 100644
> > --- a/sound/arm/pxa2xx-ac97-lib.c
> > +++ b/sound/arm/pxa2xx-ac97-lib.c
> > @@ -359,7 +359,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
> > if (ret)
> > goto err_clk2;
> >
> > - ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
> > + ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
> > if (ret < 0)
> > goto err_irq;
> >
> > diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
> > index 5cfcb90..2c7a763 100644
> > --- a/sound/drivers/ml403-ac97cr.c
> > +++ b/sound/drivers/ml403-ac97cr.c
> > @@ -1153,7 +1153,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
> > "0x%x done\n", (unsigned int)ml403_ac97cr->port);
> > /* get irq */
> > irq = platform_get_irq(pfdev, 0);
> > - if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
> > + if (request_irq(irq, snd_ml403_ac97cr_irq, 0,
> > dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
> > snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
> > "unable to grab IRQ %d\n",
> > @@ -1166,7 +1166,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
> > "request (playback) irq %d done\n",
> > ml403_ac97cr->irq);
> > irq = platform_get_irq(pfdev, 1);
> > - if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
> > + if (request_irq(irq, snd_ml403_ac97cr_irq, 0,
> > dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
> > snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
> > "unable to grab IRQ %d\n",
> > diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
> > index 34df505..1cff331 100644
> > --- a/sound/drivers/mpu401/mpu401_uart.c
> > +++ b/sound/drivers/mpu401/mpu401_uart.c
> > @@ -578,7 +578,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
> > else
> > mpu->cport = port + 1;
> > if (irq >= 0) {
> > - if (request_irq(irq, snd_mpu401_uart_interrupt, IRQF_DISABLED,
> > + if (request_irq(irq, snd_mpu401_uart_interrupt, 0,
> > "MPU401 UART", (void *) mpu)) {
> > snd_printk(KERN_ERR "mpu401_uart: "
> > "unable to grab IRQ %d\n", irq);
> > diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
> > index f50021c..7693079 100644
> > --- a/sound/drivers/mtpav.c
> > +++ b/sound/drivers/mtpav.c
> > @@ -590,7 +590,7 @@ static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
> > return -EBUSY;
> > }
> > mcard->port = port;
> > - if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) {
> > + if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) {
> > snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
> > return -EBUSY;
> > }
> > diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
> > index 6c5bf58..85aad43 100644
> > --- a/sound/drivers/serial-u16550.c
> > +++ b/sound/drivers/serial-u16550.c
> > @@ -816,7 +816,7 @@ static int __devinit snd_uart16550_create(struct snd_card *card,
> >
> > if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
> > if (request_irq(irq, snd_uart16550_interrupt,
> > - IRQF_DISABLED, "Serial MIDI", uart)) {
> > + 0, "Serial MIDI", uart)) {
> > snd_printk(KERN_WARNING
> > "irq %d busy. Using Polling.\n", irq);
> > } else {
> > diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
> > index 05aef8b..177eed3 100644
> > --- a/sound/isa/ad1816a/ad1816a_lib.c
> > +++ b/sound/isa/ad1816a/ad1816a_lib.c
> > @@ -595,7 +595,7 @@ int __devinit snd_ad1816a_create(struct snd_card *card,
> > snd_ad1816a_free(chip);
> > return -EBUSY;
> > }
> > - if (request_irq(irq, snd_ad1816a_interrupt, IRQF_DISABLED, "AD1816A", (void *) chip)) {
> > + if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) {
> > snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq);
> > snd_ad1816a_free(chip);
> > return -EBUSY;
> > diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
> > index 0767620..d3eab6f 100644
> > --- a/sound/isa/es1688/es1688_lib.c
> > +++ b/sound/isa/es1688/es1688_lib.c
> > @@ -661,7 +661,7 @@ int snd_es1688_create(struct snd_card *card,
> > snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4);
> > return -EBUSY;
> > }
> > - if (request_irq(irq, snd_es1688_interrupt, IRQF_DISABLED, "ES1688", (void *) chip)) {
> > + if (request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip)) {
> > snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq);
> > return -EBUSY;
> > }
> > diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
> > index aeee8f8..bf6ad0b 100644
> > --- a/sound/isa/es18xx.c
> > +++ b/sound/isa/es18xx.c
> > @@ -1805,7 +1805,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
> > return -EBUSY;
> > }
> >
> > - if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx",
> > + if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx",
> > (void *) card)) {
> > snd_es18xx_free(card);
> > snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
> > diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
> > index 12eb98f..3167e5a 100644
> > --- a/sound/isa/gus/gus_main.c
> > +++ b/sound/isa/gus/gus_main.c
> > @@ -180,7 +180,7 @@ int snd_gus_create(struct snd_card *card,
> > snd_gus_free(gus);
> > return -EBUSY;
> > }
> > - if (irq >= 0 && request_irq(irq, snd_gus_interrupt, IRQF_DISABLED, "GUS GF1", (void *) gus)) {
> > + if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) {
> > snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq);
> > snd_gus_free(gus);
> > return -EBUSY;
> > diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
> > index 3e4a58b..c43faa0 100644
> > --- a/sound/isa/gus/gusmax.c
> > +++ b/sound/isa/gus/gusmax.c
> > @@ -291,7 +291,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
> > goto _err;
> > }
> >
> > - if (request_irq(xirq, snd_gusmax_interrupt, IRQF_DISABLED, "GUS MAX", (void *)maxcard)) {
> > + if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) {
> > snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
> > err = -EBUSY;
> > goto _err;
> > diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
> > index c7b80e4..5f869a3 100644
> > --- a/sound/isa/gus/interwave.c
> > +++ b/sound/isa/gus/interwave.c
> > @@ -684,7 +684,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
> > if ((err = snd_gus_initialize(gus)) < 0)
> > return err;
> >
> > - if (request_irq(xirq, snd_interwave_interrupt, IRQF_DISABLED,
> > + if (request_irq(xirq, snd_interwave_interrupt, 0,
> > "InterWave", iwcard)) {
> > snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
> > return -EBUSY;
> > diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
> > index de99f47..bbafb0b 100644
> > --- a/sound/isa/opl3sa2.c
> > +++ b/sound/isa/opl3sa2.c
> > @@ -667,7 +667,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
> > err = snd_opl3sa2_detect(card);
> > if (err < 0)
> > return err;
> > - err = request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED,
> > + err = request_irq(xirq, snd_opl3sa2_interrupt, 0,
> > "OPL3-SA2", card);
> > if (err) {
> > snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
> > diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
> > index 346e12b..6dbbfa7 100644
> > --- a/sound/isa/opti9xx/opti92x-ad1848.c
> > +++ b/sound/isa/opti9xx/opti92x-ad1848.c
> > @@ -892,7 +892,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
> > #endif
> > #ifdef OPTi93X
> > error = request_irq(irq, snd_opti93x_interrupt,
> > - IRQF_DISABLED, DEV_NAME" - WSS", chip);
> > + 0, DEV_NAME" - WSS", chip);
> > if (error < 0) {
> > snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
> > return error;
> > diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
> > index eae6c1c..d2e1921 100644
> > --- a/sound/isa/sb/sb_common.c
> > +++ b/sound/isa/sb/sb_common.c
> > @@ -240,7 +240,7 @@ int snd_sbdsp_create(struct snd_card *card,
> > if (request_irq(irq, irq_handler,
> > (hardware == SB_HW_ALS4000 ||
> > hardware == SB_HW_CS5530) ?
> > - IRQF_SHARED : IRQF_DISABLED,
> > + IRQF_SHARED : 0,
> > "SoundBlaster", (void *) chip)) {
> > snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
> > snd_sbdsp_free(chip);
> > diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
> > index 83f291d..8714297 100644
> > --- a/sound/isa/wavefront/wavefront.c
> > +++ b/sound/isa/wavefront/wavefront.c
> > @@ -418,7 +418,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
> > return -EBUSY;
> > }
> > if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt,
> > - IRQF_DISABLED, "ICS2115", acard)) {
> > + 0, "ICS2115", acard)) {
> > snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
> > return -EBUSY;
> > }
> > diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
> > index 2a42cc3..7277c5b 100644
> > --- a/sound/isa/wss/wss_lib.c
> > +++ b/sound/isa/wss/wss_lib.c
> > @@ -1833,7 +1833,7 @@ int snd_wss_create(struct snd_card *card,
> > }
> > chip->cport = cport;
> > if (!(hwshare & WSS_HWSHARE_IRQ))
> > - if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
> > + if (request_irq(irq, snd_wss_interrupt, 0,
> > "WSS", (void *) chip)) {
> > snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
> > snd_wss_free(chip);
> > diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
> > index 446cf97..7567ebd 100644
> > --- a/sound/mips/au1x00.c
> > +++ b/sound/mips/au1x00.c
> > @@ -465,13 +465,13 @@ snd_au1000_pcm_new(struct snd_au1000 *au1000)
> >
> > flags = claim_dma_lock();
> > if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
> > - "AC97 TX", au1000_dma_interrupt, IRQF_DISABLED,
> > + "AC97 TX", au1000_dma_interrupt, 0,
> > au1000->stream[PLAYBACK])) < 0) {
> > release_dma_lock(flags);
> > return -EBUSY;
> > }
> > if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX,
> > - "AC97 RX", au1000_dma_interrupt, IRQF_DISABLED,
> > + "AC97 RX", au1000_dma_interrupt, 0,
> > au1000->stream[CAPTURE])) < 0){
> > release_dma_lock(flags);
> > return -EBUSY;
> > diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
> > index bcf6152..5ffb20b 100644
> > --- a/sound/pci/sis7019.c
> > +++ b/sound/pci/sis7019.c
> > @@ -1234,7 +1234,7 @@ static int sis_resume(struct pci_dev *pci)
> > goto error;
> > }
> >
> > - if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED,
> > + if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED,
> > KBUILD_MODNAME, sis)) {
> > printk(KERN_ERR "sis7019: unable to regain IRQ %d\n", pci->irq);
> > goto error;
> > @@ -1340,7 +1340,7 @@ static int __devinit sis_chip_create(struct snd_card *card,
> > if (rc)
> > goto error_out_cleanup;
> >
> > - if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED,
> > + if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED,
> > KBUILD_MODNAME, sis)) {
> > printk(KERN_ERR "unable to allocate irq %d\n", sis->irq);
> > goto error_out_cleanup;
> > diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
> > index bc823a5..775bd95 100644
> > --- a/sound/ppc/snd_ps3.c
> > +++ b/sound/ppc/snd_ps3.c
> > @@ -845,7 +845,7 @@ static int __devinit snd_ps3_allocate_irq(void)
> > return ret;
> > }
> >
> > - ret = request_irq(the_card.irq_no, snd_ps3_interrupt, IRQF_DISABLED,
> > + ret = request_irq(the_card.irq_no, snd_ps3_interrupt, 0,
> > SND_PS3_DRIVER_NAME, &the_card);
> > if (ret) {
> > pr_info("%s: request_irq failed (%d)\n", __func__, ret);
> > diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c
> > index 7aa5b76..177f713 100644
> > --- a/sound/soc/au1x/dma.c
> > +++ b/sound/soc/au1x/dma.c
> > @@ -211,7 +211,7 @@ static int alchemy_pcm_open(struct snd_pcm_substream *substream)
> > /* DMA setup */
> > name = (s == SNDRV_PCM_STREAM_PLAYBACK) ? "audio-tx" : "audio-rx";
> > ctx->stream[s].dma = request_au1000_dma(dmaids[s], name,
> > - au1000_dma_interrupt, IRQF_DISABLED,
> > + au1000_dma_interrupt, 0,
> > &ctx->stream[s]);
> > set_dma_mode(ctx->stream[s].dma,
> > get_dma_mode(ctx->stream[s].dma) & ~DMA_NC);
> > diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
> > index faa5e9f..243d177 100644
> > --- a/sound/soc/codecs/tlv320dac33.c
> > +++ b/sound/soc/codecs/tlv320dac33.c
> > @@ -1431,7 +1431,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
> > /* Check if the IRQ number is valid and request it */
> > if (dac33->irq >= 0) {
> > ret = request_irq(dac33->irq, dac33_interrupt_handler,
> > - IRQF_TRIGGER_RISING | IRQF_DISABLED,
> > + IRQF_TRIGGER_RISING,
> > codec->name, codec);
> > if (ret < 0) {
> > dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
> > diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
> > index e46d551..865b288 100644
> > --- a/sound/soc/nuc900/nuc900-pcm.c
> > +++ b/sound/soc/nuc900/nuc900-pcm.c
> > @@ -268,7 +268,7 @@ static int nuc900_dma_open(struct snd_pcm_substream *substream)
> > nuc900_audio = nuc900_ac97_data;
> >
> > if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt,
> > - IRQF_DISABLED, "nuc900-dma", substream))
> > + 0, "nuc900-dma", substream))
> > return -EBUSY;
> >
> > runtime->private_data = nuc900_audio;
> > diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
> > index b4f9b00..41b387b 100644
> > --- a/sound/soc/samsung/ac97.c
> > +++ b/sound/soc/samsung/ac97.c
> > @@ -450,7 +450,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
> > }
> >
> > ret = request_irq(irq_res->start, s3c_ac97_irq,
> > - IRQF_DISABLED, "AC97", NULL);
> > + 0, "AC97", NULL);
> > if (ret < 0) {
> > dev_err(&pdev->dev, "ac97: interrupt request failed.\n");
> > goto err4;
> > diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
> > index 8e112cc..1493ebf 100644
> > --- a/sound/soc/sh/fsi.c
> > +++ b/sound/soc/sh/fsi.c
> > @@ -1285,7 +1285,7 @@ static int fsi_probe(struct platform_device *pdev)
> > pm_runtime_enable(&pdev->dev);
> > dev_set_drvdata(&pdev->dev, master);
> >
> > - ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED,
> > + ret = request_irq(irq, &fsi_interrupt, 0,
> > id_entry->name, master);
> > if (ret) {
> > dev_err(&pdev->dev, "irq request err\n");
> > diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
> > index 743d07b..a4e3f55 100644
> > --- a/sound/soc/txx9/txx9aclc-ac97.c
> > +++ b/sound/soc/txx9/txx9aclc-ac97.c
> > @@ -201,7 +201,7 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
> > if (!drvdata->base)
> > return -EBUSY;
> > err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq,
> > - IRQF_DISABLED, dev_name(&pdev->dev), drvdata);
> > + 0, dev_name(&pdev->dev), drvdata);
> > if (err < 0)
> > return err;
> >
> > diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
> > index ad7d4d7..f036776 100644
> > --- a/sound/sparc/amd7930.c
> > +++ b/sound/sparc/amd7930.c
> > @@ -962,7 +962,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card,
> > amd7930_idle(amd);
> >
> > if (request_irq(irq, snd_amd7930_interrupt,
> > - IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) {
> > + IRQF_SHARED, "amd7930", amd)) {
> > snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n",
> > dev, irq);
> > snd_amd7930_free(amd);
> > --
> > 1.7.4.1
> >
^ permalink raw reply
* [PATCH v5 00/15] OMAP2+: Serial: Runtime adaptation + cleanup
From: Govindraj.R @ 2011-09-21 12:11 UTC (permalink / raw)
To: linux-arm-kernel
Converting uart driver to adapt to pm runtime API's.
Code re-org + cleanup.
Moving some functionality from serial.c to omap-serial.c
Changes involves:
================
1.) Cleaning up certain uart calls from sram_idle func.
2.) Removed all types of uart clock handling code from serial.c
3.) Using hwmod_mux API enable wakeup capability for uart pad during
hwmod_idle state i.e., when uart clocks are disabled we can enable
io-pad wakeup capability for uart if mux_data is available for
given uart. Also during during resume from idle call to uart we need
to enable clocks back conditionally and this can be done only when io-pad
wakeup event bit is set for uart_rx pad. So we need a hwmod API
which can probe the uart pad and let us know whether a uart wakeup
happened. So omap_hmwod_pad_wakeup_status API is added to meet this
requirement.
3.) Adapted omap-serial driver to use runtime API's.
4.) Modify serial_init calls to accept uart parameters from board file.
Like dma_usage, rx_timeout, dma_rx_pollrate, auto_suspend_timeout etc.
5.) Use the omap_prm driver with irq_chaining to wake up uart after clocks are
cut.
Patch series is based on 3.1.0-rc4 + omap_device fixes.
^ permalink raw reply
* [PATCH v2 1/3] net/fec: change phy-reset-gpio request warning to debug message
From: Wolfram Sang @ 2011-09-21 12:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20110921120341.GG28907@S2100-06.ap.freescale.net>
On Wed, Sep 21, 2011 at 08:03:42PM +0800, Shawn Guo wrote:
> On Wed, Sep 21, 2011 at 01:25:55PM +0200, Wolfram Sang wrote:
> > Hi Shawn,
> >
> > On Wed, Sep 21, 2011 at 07:10:30PM +0800, Shawn Guo wrote:
> > > FEC can work without a phy reset on some platforms, which means not
> > > very platform necessarily have a phy-reset gpio encoded in device tree.
> > > So it makes more sense to have the phy-reset-gpio request failure as
> > > a debug message rather than a warning.
> >
> > Or remove it entirely?
> >
> I would like to keep it. When people want to debug at this point, they
> do not need to type the debug message.
I just think the message might be confusing in case you don't need the
gpio, because then failing is expected behaviour. For those platforms,
it is not even an error then, so you must drop returning the error. To
be very precise, you should check of_get_named_gpio() and return if no
gpio is specified. Then, you can distinguish that case from problems
when getting the GPIO.
> > I also wanted to suggested to drop returning the error code, since it is
> > not an error anymore, strictly speaking. Then I noticed that the caller
> > does not check the error code. So, this could be added or turn the
> > function to void?
> >
> To me, keep the return value as integer is more scalable. Someday,
> someone need to add more stuff in the function, or want to improve
> the caller to check return value, it plays.
I agree that keeping it int is way better. But why not add it now to
keep things proper and tested? If this patch gets accepted as it is and
later someone else will add error checking to the caller, your platform
will lose FEC support as a regression.
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110921/8880ce14/attachment.sig>
^ permalink raw reply
* [PATCH v5 01/15] OMAP2+: hwmod: Add API to enable IO ring wakeup.
From: Govindraj.R @ 2011-09-21 12:12 UTC (permalink / raw)
To: linux-arm-kernel
Add API to enable IO pad wakeup capability based on mux dynamic pad and
wake_up enable flag available from hwmod_mux initialization.
Use the wakeup_enable flag and enable wakeup capability
for the given pads. Wakeup capability will be enabled/disabled
during hwmod idle transition based on whether wakeup_flag is
set or cleared.
Call the omap_hwmod_set_ioring_wakeup from hwmod_wakeup_enable/disable.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/omap_hwmod.c | 59 ++++++++++++++++++++++++++++++++++++++
1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 84cc0bd..e751dd9 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2062,6 +2062,34 @@ static int __init omap_hwmod_setup_all(void)
core_initcall(omap_hwmod_setup_all);
/**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+ struct omap_device_pad *pad;
+ int ret = -EINVAL, j;
+
+ if (oh->mux && oh->mux->enabled) {
+ for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+ pad = oh->mux->pads_dynamic[j];
+ if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+ if (set_wake)
+ pad->idle |= OMAP_WAKEUP_EN;
+ else
+ pad->idle &= ~OMAP_WAKEUP_EN;
+ ret = 0;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
* omap_hwmod_enable - enable an omap_hwmod
* @oh: struct omap_hwmod *
*
@@ -2393,6 +2421,35 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
{
return _del_initiator_dep(oh, init_oh);
}
+/**
+ * omap_hwmod_enable_ioring_wakeup - Set wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * set wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh)
+{
+ /* Enable pad wake-up capability */
+ return omap_hwmod_set_ioring_wakeup(oh, true);
+}
+
+/**
+ * omap_hwmod_disable_ioring_wakeup - Clear wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * clear wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh)
+{
+ /* Disable pad wakeup capability */
+ return omap_hwmod_set_ioring_wakeup(oh, false);
+}
/**
* omap_hwmod_enable_wakeup - allow device to wake up the system
@@ -2419,6 +2476,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
v = oh->_sysc_cache;
_enable_wakeup(oh, &v);
_write_sysconfig(v, oh);
+ omap_hwmod_enable_ioring_wakeup(oh);
spin_unlock_irqrestore(&oh->_lock, flags);
return 0;
@@ -2449,6 +2507,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
v = oh->_sysc_cache;
_disable_wakeup(oh, &v);
_write_sysconfig(v, oh);
+ omap_hwmod_disable_ioring_wakeup(oh);
spin_unlock_irqrestore(&oh->_lock, flags);
return 0;
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 02/15] OMAP2+: hwmod: Add API to check IO PAD wakeup status
From: Govindraj.R @ 2011-09-21 12:12 UTC (permalink / raw)
To: linux-arm-kernel
Add API to determine IO-PAD wakeup event status for a given
hwmod dynamic_mux pad.
Wake up event set will be cleared on pad mux_read.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/mux.c | 30 ++++++++++++++++++++++++++
arch/arm/mach-omap2/mux.h | 13 +++++++++++
arch/arm/mach-omap2/omap_hwmod.c | 7 ++++++
arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 +
4 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index 655e948..fb75aae 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -351,6 +351,36 @@ err1:
return NULL;
}
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup capability is set and wakeup event occurred.
+ * Returns false if wakeup event has not occurred or pads are not available.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ int i;
+ unsigned int val;
+ u8 ret = false;
+
+ for (i = 0; i < hmux->nr_pads; i++) {
+ struct omap_device_pad *pad = &hmux->pads[i];
+
+ if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+ val = omap_mux_read(pad->partition,
+ pad->mux->reg_offset);
+ if (val & OMAP_WAKEUP_EVENT) {
+ ret = true;
+ break;
+ }
+ }
+ }
+
+ return ret;
+}
+
/* Assumes the calling function takes care of locking */
void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
{
diff --git a/arch/arm/mach-omap2/mux.h b/arch/arm/mach-omap2/mux.h
index 2132308..8b2150a 100644
--- a/arch/arm/mach-omap2/mux.h
+++ b/arch/arm/mach-omap2/mux.h
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
*/
void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux: Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);
#else
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+ return 0;
+}
+
static inline int omap_mux_init_gpio(int gpio, int val)
{
return 0;
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e751dd9..a8b24d7 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2724,3 +2724,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
return 0;
}
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+ if (oh && oh->mux)
+ return omap_hwmod_mux_get_wake_status(oh->mux);
+ return -EINVAL;
+}
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0e329ca..9a6195c 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -607,6 +607,7 @@ u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
/*
* Chip variant-specific hwmod init routines - XXX should be converted
* to use initcalls once the initial boot ordering is straightened out
--
1.7.4.1
^ permalink raw reply related
* [PATCH 53/57] sound: irq: Remove IRQF_DISABLED
From: Yong Zhang @ 2011-09-21 12:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <alpine.LFD.2.02.1109211154280.2723@ionos>
On Wed, Sep 21, 2011 at 11:55:36AM +0200, Thomas Gleixner wrote:
> On Wed, 21 Sep 2011, Takashi Iwai wrote:
>
> > At Wed, 21 Sep 2011 17:28:54 +0800,
> > Yong Zhang wrote:
> > >
> > > Since commit [c58543c8: genirq: Run irq handlers with interrupts disabled],
> >
> > Hm, this id hits a different commit:
> > commit c58543c869606532c2382f027d6466f4672ea756
> > Author: David S. Miller <davem@davemloft.net>
> > Date: Tue Oct 13 00:49:09 2009 -0700
> >
> > sparc64: Set IRQF_DISABLED on LDC channel IRQs.
> >
> > You mean commit e58aa3d2d0cc01ad8d6f7f640a0670433f794922?
>
> Yeah.
>
> > > We run all interrupt handlers with interrupts disabled
> > > and we even check and yell when an interrupt handler
> > > returns with interrupts enabled (see commit [b738a50a:
> > > genirq: Warn when handler enables interrupts]).
> > >
> > > So now this flag is a NOOP and can be removed.
> > >
> > > Signed-off-by: Yong Zhang <yong.zhang0@gmail.com>
> > > Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
> >
> > Do you want to merge by yourself or shall I take it to sound git tree?
> > Since IRQF_DISABLED isn't used, it can be applied safely in 3.1-based
> > tree, right?
>
> Yes, please go ahead. I'll pick up the leftovers.
Takashi, if you take it, could you please modify that commit id to the
right one?
Otherwise I could change it when I refresh this patchset.
Thanks,
Yong
^ permalink raw reply
* [PATCH V5 0/6] ARM: S5P64X0: Add Framebuffer support
From: Kukjin Kim @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316454841-20869-1-git-send-email-ajaykumar.rs@samsung.com>
Ajay Kumar wrote:
>
> The patches are created against "for-next" branch of Kukjin Kim's tree
at:
> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
>
> Changes since V1:
> - Remove mach/regs-fb.h, instead use plat/regs-fb.h.
> - Add common pdata for FB and LCD in SMDK6440 and SMDK6450.
> - Modify names(s5p-->smdk), max_bpp and refresh rate.
> - Modify variable name(cfg-->chipid).
> - Use __raw_readl, __raw_writel instead of readl and writel.
>
> Changes since V2:
> -Change name of the config-COMMON_FB to SMDK64X0_COMMON_FB.
> -Change filename common-fb.h to smdk64x0-common-fb.h.
> -Change filename common-fb.c to smdk64x0-common-fb.c.
>
> Changes since V3:
> -Add FB and LCD plat-data in corresponding machine files
> instead of creating common file smdk64x0-common-fb.c.
> -Modify name S5P64X0_SETUP_FB to S5P64X0_SETUP_FB_24BPP.
> -Modify file name setup-fb.c to setup-fb-24bpp.c.
> -Move SPCON settings to machine file.
> -Use soc_is_s5p6440()/soc_is_s5p6450() to check CPU ID.
>
> Changes since V4:
> -Removed refresh rate from plat data(s3c_fb_pd_win)
> -Fixed complation warning:"function declaration isn't a prototype"
> for s5p6440_set_lcd_interface() and s5p6450_set_lcd_interface().
>
>
> These patches have dependency on the patch:
> "ARM: S5P64X0: Fix mask value for S5P64X0 CPU IDs",
> at http://www.spinics.net/lists/arm-kernel/msg138990.html
>
> o To Kukjin,
> [PATCH RESEND V5 1/6] video: s3c-fb: Add S5P64X0 specific
> s3c_fb_driverdata
> [PATCH RESEND V5 2/6] ARM: S5P64X0: Add register base and IRQ for
> Framebuffer
> [PATCH RESEND V5 3/6] ARM: S5P64X0: Set s3c_device_fb name
> [PATCH RESEND V5 4/6] ARM: S5P64X0: Add GPIO setup for LCD
> [PATCH V5 5/6]ARM: S5P6440: Add LCD-LTE480 and enable Framebuffer
> support
> [PATCH V5 6/6]ARM: S5P6450: Add LCD-LTE480 and enable Framebuffer
> support
>
> arch/arm/mach-s5p64x0/Kconfig | 10 +++
> arch/arm/mach-s5p64x0/Makefile | 1 +
> arch/arm/mach-s5p64x0/cpu.c | 3 +
> arch/arm/mach-s5p64x0/include/mach/irqs.h | 4 +
> arch/arm/mach-s5p64x0/include/mach/map.h | 3 +
> arch/arm/mach-s5p64x0/include/mach/regs-gpio.h | 4 +
> arch/arm/mach-s5p64x0/mach-smdk6440.c | 74
> +++++++++++++++++++++++
> arch/arm/mach-s5p64x0/mach-smdk6450.c | 75
> ++++++++++++++++++++++++
> arch/arm/mach-s5p64x0/setup-fb-24bpp.c | 29 +++++++++
> arch/arm/plat-samsung/include/plat/fb.h | 7 ++
> drivers/video/s3c-fb.c | 27 +++++++++
> 11 files changed, 237 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-s5p64x0/setup-fb-24bpp.c
Looks ok to me, will apply.
But as I said, the 'video: s3c-fb: Add S5P64X0 specific s3c_fb_driverdata'
should be sent to Florian's tree.
I think, it's enough to re-send it to Florian Tobias Schandina.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply
* [PATCH v5 03/15] OMAP2+: UART: cleanup + remove uart pm specific API
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In preparation to UART runtime conversion remove uart specific calls
from pm24xx/34xx files and their definition from serial.c
These func calls will no more be used with upcoming uart runtime design.
1.) omap_uart_can_sleep :- currently used to set uart->can_sleep flag based
on which uart clocks can be gated, not needed further as driver can
autosuspend based on usage_count and autosuspend delay with runtime API's.
2.) omap_uart_prepare_suspend :- can be taken care with driver suspend hooks.
3.) omap_uart_enable_irqs :- Used to enable/disable uart irq's in suspend
path from PM code, this is removed as same is handled by
uart_suspend_port/uart_resume_port in omap-serial driver which will
do an port_shutdown on suspend freeing irq and port_startup on resume
enabling back irq.
4.) Remove prepare_idle/resume_idle calls used to gate uart clocks.
UART clocks can be gated within driver using runtime funcs
and be woken up using irq_chaining from omap_prm driver.
5.) Remove console_locking from idle path as clock gating is done withing
driver itself with runtime API.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/pm24xx.c | 19 -------
arch/arm/mach-omap2/pm34xx.c | 24 --------
arch/arm/mach-omap2/serial.c | 87 ------------------------------
arch/arm/plat-omap/include/plat/serial.h | 5 --
4 files changed, 0 insertions(+), 135 deletions(-)
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index bf089e7..83a8b96 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -133,27 +133,11 @@ static void omap2_enter_full_retention(void)
if (omap_irq_pending())
goto no_sleep;
- /* Block console output in case it is on one of the OMAP UARTs */
- if (!is_suspending())
- if (!console_trylock())
- goto no_sleep;
-
- omap_uart_prepare_idle(0);
- omap_uart_prepare_idle(1);
- omap_uart_prepare_idle(2);
-
/* Jump to SRAM suspend code */
omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
OMAP_SDRC_REGADDR(SDRC_POWER));
- omap_uart_resume_idle(2);
- omap_uart_resume_idle(1);
- omap_uart_resume_idle(0);
-
- if (!is_suspending())
- console_unlock();
-
no_sleep:
if (omap2_pm_debug) {
unsigned long long tmp;
@@ -265,8 +249,6 @@ static int omap2_can_sleep(void)
{
if (omap2_fclks_active())
return 0;
- if (!omap_uart_can_sleep())
- return 0;
if (osc_ck->usecount > 1)
return 0;
if (omap_dma_running())
@@ -317,7 +299,6 @@ static int omap2_pm_suspend(void)
mir1 = omap_readl(0x480fe0a4);
omap_writel(1 << 5, 0x480fe0ac);
- omap_uart_prepare_suspend();
omap2_enter_full_retention();
omap_writel(mir1, 0x480fe0a4);
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7255d9b..4ea6aa7 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -379,18 +379,9 @@ void omap_sram_idle(void)
omap3_enable_io_chain();
}
- /* Block console output in case it is on one of the OMAP UARTs */
- if (!is_suspending())
- if (per_next_state < PWRDM_POWER_ON ||
- core_next_state < PWRDM_POWER_ON)
- if (!console_trylock())
- goto console_still_active;
-
/* PER */
if (per_next_state < PWRDM_POWER_ON) {
per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
- omap_uart_prepare_idle(2);
- omap_uart_prepare_idle(3);
omap2_gpio_prepare_for_idle(per_going_off);
if (per_next_state == PWRDM_POWER_OFF)
omap3_per_save_context();
@@ -398,8 +389,6 @@ void omap_sram_idle(void)
/* CORE */
if (core_next_state < PWRDM_POWER_ON) {
- omap_uart_prepare_idle(0);
- omap_uart_prepare_idle(1);
if (core_next_state == PWRDM_POWER_OFF) {
omap3_core_save_context();
omap3_cm_save_context();
@@ -446,8 +435,6 @@ void omap_sram_idle(void)
omap3_sram_restore_context();
omap2_sms_restore_context();
}
- omap_uart_resume_idle(0);
- omap_uart_resume_idle(1);
if (core_next_state == PWRDM_POWER_OFF)
omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
OMAP3430_GR_MOD,
@@ -461,14 +448,8 @@ void omap_sram_idle(void)
omap2_gpio_resume_after_idle();
if (per_prev_state == PWRDM_POWER_OFF)
omap3_per_restore_context();
- omap_uart_resume_idle(2);
- omap_uart_resume_idle(3);
}
- if (!is_suspending())
- console_unlock();
-
-console_still_active:
/* Disable IO-PAD and IO-CHAIN wakeup */
if (omap3_has_io_wakeup() &&
(per_next_state < PWRDM_POWER_ON ||
@@ -485,8 +466,6 @@ console_still_active:
int omap3_can_sleep(void)
{
- if (!omap_uart_can_sleep())
- return 0;
return 1;
}
@@ -531,7 +510,6 @@ static int omap3_pm_suspend(void)
goto restore;
}
- omap_uart_prepare_suspend();
omap3_intc_suspend();
omap_sram_idle();
@@ -578,14 +556,12 @@ static int omap3_pm_begin(suspend_state_t state)
{
disable_hlt();
suspend_state = state;
- omap_uart_enable_irqs(0);
return 0;
}
static void omap3_pm_end(void)
{
suspend_state = PM_SUSPEND_ON;
- omap_uart_enable_irqs(1);
enable_hlt();
return;
}
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 3d1c1d3..60108fd 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -26,7 +26,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/serial_8250.h>
-#include <linux/pm_runtime.h>
#include <linux/console.h>
#ifdef CONFIG_SERIAL_OMAP
@@ -389,72 +388,6 @@ static void omap_uart_idle_timer(unsigned long data)
omap_uart_allow_sleep(uart);
}
-void omap_uart_prepare_idle(int num)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (num == uart->num && uart->can_sleep) {
- omap_uart_disable_clocks(uart);
- return;
- }
- }
-}
-
-void omap_uart_resume_idle(int num)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (num == uart->num && uart->can_sleep) {
- omap_uart_enable_clocks(uart);
-
- /* Check for IO pad wakeup */
- if (cpu_is_omap34xx() && uart->padconf) {
- u16 p = omap_ctrl_readw(uart->padconf);
-
- if (p & OMAP3_PADCONF_WAKEUPEVENT0)
- omap_uart_block_sleep(uart);
- }
-
- /* Check for normal UART wakeup */
- if (__raw_readl(uart->wk_st) & uart->wk_mask)
- omap_uart_block_sleep(uart);
- return;
- }
- }
-}
-
-void omap_uart_prepare_suspend(void)
-{
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- omap_uart_allow_sleep(uart);
- }
-}
-
-int omap_uart_can_sleep(void)
-{
- struct omap_uart_state *uart;
- int can_sleep = 1;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (!uart->clocked)
- continue;
-
- if (!uart->can_sleep) {
- can_sleep = 0;
- continue;
- }
-
- /* This UART can now safely sleep. */
- omap_uart_allow_sleep(uart);
- }
-
- return can_sleep;
-}
-
/**
* omap_uart_interrupt()
*
@@ -552,26 +485,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
WARN_ON(ret);
}
-void omap_uart_enable_irqs(int enable)
-{
- int ret;
- struct omap_uart_state *uart;
-
- list_for_each_entry(uart, &uart_list, node) {
- if (enable) {
- pm_runtime_put_sync(&uart->pdev->dev);
- ret = request_threaded_irq(uart->irq, NULL,
- omap_uart_interrupt,
- IRQF_SHARED,
- "serial idle",
- (void *)uart);
- } else {
- pm_runtime_get_noresume(&uart->pdev->dev);
- free_irq(uart->irq, (void *)uart);
- }
- }
-}
-
static ssize_t sleep_timeout_show(struct device *dev,
struct device_attribute *attr,
char *buf)
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index de3b10c..b8d9303 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -109,12 +109,7 @@ struct omap_board_data;
extern void omap_serial_init(void);
extern void omap_serial_init_port(struct omap_board_data *bdata);
-extern int omap_uart_can_sleep(void);
extern void omap_uart_check_wakeup(void);
-extern void omap_uart_prepare_suspend(void);
-extern void omap_uart_prepare_idle(int num);
-extern void omap_uart_resume_idle(int num);
-extern void omap_uart_enable_irqs(int enable);
#endif
#endif
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 04/15] OMAP2+: UART: cleanup 8250 console driver support
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607206-21669-1-git-send-email-govindraj.raja@ti.com>
We had been using traditional 8250 driver as uart console driver
prior to omap-serial driver. Since we have omap-serial driver
in mainline kernel for some time now it has been used as default
uart console driver on omap2+ platforms. Remove 8250 support for
omap-uarts.
Serial_in and serial_out override for 8250 serial driver is also
removed. Empty fifo read fix is already taken care with omap-serial
driver with data ready bit check from LSR reg before reading RX fifo.
Also waiting for THRE(transmit hold reg empty) is done with wait_for_xmitr
in omap-serial driver.
Remove headers that were necessary to support 8250 support
and remove all config bindings done to keep 8250 backward compatibility
while adding omap-serial driver. Remove omap_uart_reset needed for
8250 autoconf.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/serial.c | 111 ------------------------------------------
1 files changed, 0 insertions(+), 111 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 60108fd..784a8f9 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -19,22 +19,16 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/serial_reg.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/serial_8250.h>
#include <linux/console.h>
-#ifdef CONFIG_SERIAL_OMAP
#include <plat/omap-serial.h>
-#endif
-
#include <plat/common.h>
#include <plat/board.h>
-#include <plat/clock.h>
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
@@ -46,10 +40,8 @@
#include "control.h"
#include "mux.h"
-#define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV 0x52
#define UART_OMAP_WER 0x17 /* Wake-up enable register */
-#define UART_ERRATA_FIFO_FULL_ABORT (0x1 << 0)
#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1)
/*
@@ -156,19 +148,6 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
__raw_writeb(value, uart->membase + offset);
}
-/*
- * Internal UARTs need to be initialized for the 8250 autoconfig to work
- * properly. Note that the TX watermark initialization may not be needed
- * once the 8250.c watermark handling code is merged.
- */
-
-static inline void __init omap_uart_reset(struct omap_uart_state *uart)
-{
- serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
- serial_write_reg(uart, UART_OMAP_SCR, 0x08);
- serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
-}
-
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
/*
@@ -533,41 +512,6 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
#define DEV_CREATE_FILE(dev, attr)
#endif /* CONFIG_PM */
-#ifndef CONFIG_SERIAL_OMAP
-/*
- * Override the default 8250 read handler: mem_serial_in()
- * Empty RX fifo read causes an abort on omap3630 and omap4
- * This function makes sure that an empty rx fifo is not read on these silicons
- * (OMAP1/2/3430 are not affected)
- */
-static unsigned int serial_in_override(struct uart_port *up, int offset)
-{
- if (UART_RX == offset) {
- unsigned int lsr;
- lsr = __serial_read_reg(up, UART_LSR);
- if (!(lsr & UART_LSR_DR))
- return -EPERM;
- }
-
- return __serial_read_reg(up, offset);
-}
-
-static void serial_out_override(struct uart_port *up, int offset, int value)
-{
- unsigned int status, tmout = 10000;
-
- status = __serial_read_reg(up, UART_LSR);
- while (!(status & UART_LSR_THRE)) {
- /* Wait up to 10ms for the character(s) to be sent. */
- if (--tmout == 0)
- break;
- udelay(1);
- status = __serial_read_reg(up, UART_LSR);
- }
- __serial_write_reg(up, offset, value);
-}
-#endif
-
static int __init omap_serial_early_init(void)
{
int i = 0;
@@ -628,15 +572,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
void *pdata = NULL;
u32 pdata_size = 0;
char *name;
-#ifndef CONFIG_SERIAL_OMAP
- struct plat_serial8250_port ports[2] = {
- {},
- {.flags = 0},
- };
- struct plat_serial8250_port *p = &ports[0];
-#else
struct omap_uart_port_info omap_up;
-#endif
if (WARN_ON(!bdata))
return;
@@ -651,51 +587,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
oh = uart->oh;
uart->dma_enabled = 0;
-#ifndef CONFIG_SERIAL_OMAP
- name = "serial8250";
-
- /*
- * !! 8250 driver does not use standard IORESOURCE* It
- * has it's own custom pdata that can be taken from
- * the hwmod resource data. But, this needs to be
- * done after the build.
- *
- * ?? does it have to be done before the register ??
- * YES, because platform_device_data_add() copies
- * pdata, it does not use a pointer.
- */
- p->flags = UPF_BOOT_AUTOCONF;
- p->iotype = UPIO_MEM;
- p->regshift = 2;
- p->uartclk = OMAP24XX_BASE_BAUD * 16;
- p->irq = oh->mpu_irqs[0].irq;
- p->mapbase = oh->slaves[0]->addr->pa_start;
- p->membase = omap_hwmod_get_mpu_rt_va(oh);
- p->irqflags = IRQF_SHARED;
- p->private_data = uart;
-
- /*
- * omap44xx, ti816x: Never read empty UART fifo
- * omap3xxx: Never read empty UART fifo on UARTs
- * with IP rev >=0x52
- */
- uart->regshift = p->regshift;
- uart->membase = p->membase;
- if (cpu_is_omap44xx() || cpu_is_ti816x())
- uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
- else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
- >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
- uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-
- if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
- p->serial_in = serial_in_override;
- p->serial_out = serial_out_override;
- }
-
- pdata = &ports[0];
- pdata_size = 2 * sizeof(struct plat_serial8250_port);
-#else
-
name = DRIVER_NAME;
omap_up.dma_enabled = uart->dma_enabled;
@@ -707,7 +598,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
pdata = &omap_up;
pdata_size = sizeof(struct omap_uart_port_info);
-#endif
if (WARN_ON(!oh))
return;
@@ -740,7 +630,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
omap_device_enable(uart->pdev);
omap_uart_idle_init(uart);
- omap_uart_reset(uart);
omap_hwmod_enable_wakeup(uart->oh);
omap_device_idle(uart->pdev);
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 05/15] OMAP2+: UART: Cleanup part of clock gating mechanism for uart
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607206-21669-1-git-send-email-govindraj.raja@ti.com>
Currently we use a shared irq handler to identify uart activity and then
trigger a timer. Based the timeout value set from sysfs the timer used to
expire. If no uart-activity was detected timer-expiry func sets can_sleep
flag. Based on this we will disable the uart clocks in idle path.
Since the clock gating mechanism is outside the uart driver, we currently
use this mechanism. In preparation to runtime implementation for omap-serial
driver we can cleanup this mechanism and use runtime API's to gate uart clocks.
Also remove timer related info from local uart_state struct and remove
the code used to set timeout value from sysfs.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/serial.c | 116 +------------------------
arch/arm/plat-omap/include/plat/omap-serial.h | 1 -
2 files changed, 1 insertions(+), 116 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 784a8f9..3465fd7 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -57,8 +57,6 @@
struct omap_uart_state {
int num;
int can_sleep;
- struct timer_list timer;
- u32 timeout;
void __iomem *wk_st;
void __iomem *wk_en;
@@ -66,13 +64,9 @@ struct omap_uart_state {
u32 padconf;
u32 dma_enabled;
- struct clk *ick;
- struct clk *fck;
int clocked;
- int irq;
int regshift;
- int irqflags;
void __iomem *membase;
resource_size_t mapbase;
@@ -339,51 +333,6 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
omap_uart_smart_idle_enable(uart, 0);
uart->can_sleep = 0;
- if (uart->timeout)
- mod_timer(&uart->timer, jiffies + uart->timeout);
- else
- del_timer(&uart->timer);
-}
-
-static void omap_uart_allow_sleep(struct omap_uart_state *uart)
-{
- if (device_may_wakeup(&uart->pdev->dev))
- omap_uart_enable_wakeup(uart);
- else
- omap_uart_disable_wakeup(uart);
-
- if (!uart->clocked)
- return;
-
- omap_uart_smart_idle_enable(uart, 1);
- uart->can_sleep = 1;
- del_timer(&uart->timer);
-}
-
-static void omap_uart_idle_timer(unsigned long data)
-{
- struct omap_uart_state *uart = (struct omap_uart_state *)data;
-
- omap_uart_allow_sleep(uart);
-}
-
-/**
- * omap_uart_interrupt()
- *
- * This handler is used only to detect that *any* UART interrupt has
- * occurred. It does _nothing_ to handle the interrupt. Rather,
- * any UART interrupt will trigger the inactivity timer so the
- * UART will not idle or sleep for its timeout period.
- *
- **/
-/* static int first_interrupt; */
-static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
-{
- struct omap_uart_state *uart = dev_id;
-
- omap_uart_block_sleep(uart);
-
- return IRQ_NONE;
}
static void omap_uart_idle_init(struct omap_uart_state *uart)
@@ -391,11 +340,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
int ret;
uart->can_sleep = 0;
- uart->timeout = DEFAULT_TIMEOUT;
- setup_timer(&uart->timer, omap_uart_idle_timer,
- (unsigned long) uart);
- if (uart->timeout)
- mod_timer(&uart->timer, jiffies + uart->timeout);
omap_uart_smart_idle_enable(uart, 0);
if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
@@ -457,51 +401,8 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
uart->wk_mask = 0;
uart->padconf = 0;
}
-
- uart->irqflags |= IRQF_SHARED;
- ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
- IRQF_SHARED, "serial idle", (void *)uart);
- WARN_ON(ret);
-}
-
-static ssize_t sleep_timeout_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_device *odev = to_omap_device(pdev);
- struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
-
- return sprintf(buf, "%u\n", uart->timeout / HZ);
}
-static ssize_t sleep_timeout_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t n)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct omap_device *odev = to_omap_device(pdev);
- struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
- unsigned int value;
-
- if (sscanf(buf, "%u", &value) != 1) {
- dev_err(dev, "sleep_timeout_store: Invalid value\n");
- return -EINVAL;
- }
-
- uart->timeout = value * HZ;
- if (uart->timeout)
- mod_timer(&uart->timer, jiffies + uart->timeout);
- else
- /* A zero value means disable timeout feature */
- omap_uart_block_sleep(uart);
-
- return n;
-}
-
-static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show,
- sleep_timeout_store);
-#define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
#else
static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
static void omap_uart_block_sleep(struct omap_uart_state *uart)
@@ -509,7 +410,6 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
/* Needed to enable UART clocks when built without CONFIG_PM */
omap_uart_enable_clocks(uart);
}
-#define DEV_CREATE_FILE(dev, attr)
#endif /* CONFIG_PM */
static int __init omap_serial_early_init(void)
@@ -593,7 +493,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
omap_up.mapbase = oh->slaves[0]->addr->pa_start;
omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
- omap_up.irqflags = IRQF_SHARED;
omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
pdata = &omap_up;
@@ -611,7 +510,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
omap_device_disable_idle_on_suspend(pdev);
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
- uart->irq = oh->mpu_irqs[0].irq;
uart->regshift = 2;
uart->mapbase = oh->slaves[0]->addr->pa_start;
uart->membase = omap_hwmod_get_mpu_rt_va(oh);
@@ -633,24 +531,12 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
omap_hwmod_enable_wakeup(uart->oh);
omap_device_idle(uart->pdev);
- /*
- * Need to block sleep long enough for interrupt driven
- * driver to start. Console driver is in polling mode
- * so device needs to be kept enabled while polling driver
- * is in use.
- */
- if (uart->timeout)
- uart->timeout = (30 * HZ);
omap_uart_block_sleep(uart);
- uart->timeout = DEFAULT_TIMEOUT;
-
console_unlock();
if ((cpu_is_omap34xx() && uart->padconf) ||
- (uart->wk_en && uart->wk_mask)) {
+ (uart->wk_en && uart->wk_mask))
device_init_wakeup(&pdev->dev, true);
- DEV_CREATE_FILE(&pdev->dev, &dev_attr_sleep_timeout);
- }
/* Enable the MDR1 errata for OMAP3 */
if (cpu_is_omap34xx() && !cpu_is_ti816x())
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 2682043..307cd6f 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -61,7 +61,6 @@ struct omap_uart_port_info {
unsigned int uartclk; /* UART clock rate */
void __iomem *membase; /* ioremap cookie or NULL */
resource_size_t mapbase; /* resource base */
- unsigned long irqflags; /* request_irq flags */
upf_t flags; /* UPF_* flags */
};
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 06/15] OMAP2+: UART: Remove certain feilds from omap_uart_state struct
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607206-21669-1-git-send-email-govindraj.raja@ti.com>
Removing some of the uart info that is maintained in omap_uart_state struct
used for UART PM in serial.c.
Remove omap_uart_state struct dependency from omap_serial_init,
omap_serial_init_port, omap_serial_early_init and omap_uart_idle_init functions.
And populate the same info in omap_uart_port_info struct used as pdata struct.
Added omap_uart_hwmod_lookup function to look up oh by name used
in serial_port_init and omap_serial_early_init functions.
A list of omap_uart_state was maintained one for each uart, the same is removed.
Number of uarts available is maintained in num_uarts field, re-use the same in
omap_serial_init func to register each uart.
Remove omap_info which used details from omap_uart_state and use
a pdata pointer to pass platform specific info to driver.
The mapbase (start_address), membase(io_remap cookie) maintained as part of
uart_state struct and pdata struct are removed as this is handled within
driver. Errata field is also moved to pdata. These changes are done
to cleanup serial.c file and prepare for runtime changes.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/serial.c | 132 +++++++++---------------
arch/arm/plat-omap/include/plat/omap-serial.h | 4 +-
drivers/tty/serial/omap-serial.c | 12 ++-
3 files changed, 61 insertions(+), 87 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 3465fd7..fd0c345 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -67,14 +67,6 @@ struct omap_uart_state {
int clocked;
int regshift;
- void __iomem *membase;
- resource_size_t mapbase;
-
- struct list_head node;
- struct omap_hwmod *oh;
- struct platform_device *pdev;
-
- u32 errata;
#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
int context_valid;
@@ -89,7 +81,6 @@ struct omap_uart_state {
#endif
};
-static LIST_HEAD(uart_list);
static u8 num_uarts;
static int uart_idle_hwmod(struct omap_device *od)
@@ -142,7 +133,7 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
__raw_writeb(value, uart->membase + offset);
}
-#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_PM)
/*
* Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
@@ -335,22 +326,17 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
uart->can_sleep = 0;
}
-static void omap_uart_idle_init(struct omap_uart_state *uart)
+static void omap_uart_idle_init(struct omap_uart_port_info *uart,
+ unsigned short num)
{
- int ret;
-
- uart->can_sleep = 0;
- omap_uart_smart_idle_enable(uart, 0);
-
if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
- u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
+ u32 mod = (num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
u32 wk_mask = 0;
u32 padconf = 0;
- /* XXX These PRM accesses do not belong here */
uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
- switch (uart->num) {
+ switch (num) {
case 0:
wk_mask = OMAP3430_ST_UART1_MASK;
padconf = 0x182;
@@ -369,12 +355,11 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
break;
}
uart->wk_mask = wk_mask;
- uart->padconf = padconf;
} else if (cpu_is_omap24xx()) {
u32 wk_mask = 0;
u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
- switch (uart->num) {
+ switch (num) {
case 0:
wk_mask = OMAP24XX_ST_UART1_MASK;
break;
@@ -399,7 +384,6 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
uart->wk_en = NULL;
uart->wk_st = NULL;
uart->wk_mask = 0;
- uart->padconf = 0;
}
}
@@ -412,28 +396,27 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
}
#endif /* CONFIG_PM */
-static int __init omap_serial_early_init(void)
+struct omap_hwmod *omap_uart_hwmod_lookup(int num)
{
- int i = 0;
+ struct omap_hwmod *oh;
+ char oh_name[MAX_UART_HWMOD_NAME_LEN];
+
+ snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN, "uart%d", num + 1);
+ oh = omap_hwmod_lookup(oh_name);
+ WARN(IS_ERR(oh), "Could not lookup hmwod info for %s\n",
+ oh_name);
+ return oh;
+}
+static int __init omap_serial_early_init(void)
+{
do {
- char oh_name[MAX_UART_HWMOD_NAME_LEN];
struct omap_hwmod *oh;
- struct omap_uart_state *uart;
- snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
- "uart%d", i + 1);
- oh = omap_hwmod_lookup(oh_name);
+ oh = omap_uart_hwmod_lookup(num_uarts);
if (!oh)
break;
- uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
- if (WARN_ON(!uart))
- return -ENODEV;
-
- uart->oh = oh;
- uart->num = i++;
- list_add_tail(&uart->node, &uart_list);
num_uarts++;
/*
@@ -446,7 +429,7 @@ static int __init omap_serial_early_init(void)
* to determine SoC specific init before omap_device
* is ready. Therefore, don't allow idle here
*/
- uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+ oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
} while (1);
return 0;
@@ -466,57 +449,47 @@ core_initcall(omap_serial_early_init);
*/
void __init omap_serial_init_port(struct omap_board_data *bdata)
{
- struct omap_uart_state *uart;
struct omap_hwmod *oh;
struct platform_device *pdev;
- void *pdata = NULL;
+ char *name = DRIVER_NAME;
+ struct omap_uart_port_info *pdata;
u32 pdata_size = 0;
- char *name;
- struct omap_uart_port_info omap_up;
if (WARN_ON(!bdata))
return;
if (WARN_ON(bdata->id < 0))
return;
- if (WARN_ON(bdata->id >= num_uarts))
+ if (WARN_ON(bdata->id >= OMAP_MAX_HSUART_PORTS))
return;
- list_for_each_entry(uart, &uart_list, node)
- if (bdata->id == uart->num)
- break;
-
- oh = uart->oh;
- uart->dma_enabled = 0;
- name = DRIVER_NAME;
+ oh = omap_uart_hwmod_lookup(bdata->id);
+ if (!oh)
+ return;
- omap_up.dma_enabled = uart->dma_enabled;
- omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
- omap_up.mapbase = oh->slaves[0]->addr->pa_start;
- omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
- omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ pr_err("Memory allocation for UART pdata failed\n");
+ return;
+ }
- pdata = &omap_up;
pdata_size = sizeof(struct omap_uart_port_info);
+ omap_uart_idle_init(pdata, bdata->id);
- if (WARN_ON(!oh))
- return;
+ pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
+ pdata->flags = UPF_BOOT_AUTOCONF;
- pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
- omap_uart_latency,
- ARRAY_SIZE(omap_uart_latency), false);
+ /* Enable the MDR1 errata for OMAP3 */
+ if (cpu_is_omap34xx() && !cpu_is_ti816x())
+ pdata->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+
+ pdev = omap_device_build(name, bdata->id, oh, pdata,
+ pdata_size, omap_uart_latency,
+ ARRAY_SIZE(omap_uart_latency), false);
WARN(IS_ERR(pdev), "Could not build omap_device for %s: %s.\n",
name, oh->name);
- omap_device_disable_idle_on_suspend(pdev);
oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
- uart->regshift = 2;
- uart->mapbase = oh->slaves[0]->addr->pa_start;
- uart->membase = omap_hwmod_get_mpu_rt_va(oh);
- uart->pdev = pdev;
-
- oh->dev_attr = uart;
-
console_lock(); /* in case the earlycon is on the UART */
/*
@@ -524,23 +497,18 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
* on init. Now that omap_device is ready, ensure full idle
* before doing omap_device_enable().
*/
- omap_hwmod_idle(uart->oh);
+ omap_hwmod_idle(oh);
- omap_device_enable(uart->pdev);
- omap_uart_idle_init(uart);
- omap_hwmod_enable_wakeup(uart->oh);
- omap_device_idle(uart->pdev);
+ omap_device_enable(pdev);
+ omap_hwmod_enable_wakeup(oh);
- omap_uart_block_sleep(uart);
console_unlock();
- if ((cpu_is_omap34xx() && uart->padconf) ||
- (uart->wk_en && uart->wk_mask))
+ if ((cpu_is_omap34xx() && bdata->pads) ||
+ (pdata->wk_en && pdata->wk_mask))
device_init_wakeup(&pdev->dev, true);
- /* Enable the MDR1 errata for OMAP3 */
- if (cpu_is_omap34xx() && !cpu_is_ti816x())
- uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
+ kfree(pdata);
}
/**
@@ -552,11 +520,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
*/
void __init omap_serial_init(void)
{
- struct omap_uart_state *uart;
struct omap_board_data bdata;
+ u8 i;
- list_for_each_entry(uart, &uart_list, node) {
- bdata.id = uart->num;
+ for (i = 0; i < num_uarts; i++) {
+ bdata.id = i;
bdata.flags = 0;
bdata.pads = NULL;
bdata.pads_cnt = 0;
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 307cd6f..0f061b4 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -59,9 +59,9 @@
struct omap_uart_port_info {
bool dma_enabled; /* To specify DMA Mode */
unsigned int uartclk; /* UART clock rate */
- void __iomem *membase; /* ioremap cookie or NULL */
- resource_size_t mapbase; /* resource base */
upf_t flags; /* UPF_* flags */
+
+ u32 errata;
};
struct uart_omap_dma {
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 5e713d3..6c2ea54 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1275,10 +1275,16 @@ static int serial_omap_probe(struct platform_device *pdev)
up->port.ops = &serial_omap_pops;
up->port.line = pdev->id;
- up->port.membase = omap_up_info->membase;
- up->port.mapbase = omap_up_info->mapbase;
+ up->port.mapbase = mem->start;
+ up->port.membase = ioremap(mem->start, resource_size(mem));
+
+ if (!up->port.membase) {
+ dev_err(&pdev->dev, "can't ioremap UART\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
up->port.flags = omap_up_info->flags;
- up->port.irqflags = omap_up_info->irqflags;
up->port.uartclk = omap_up_info->uartclk;
up->uart_dma.uart_base = mem->start;
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 07/15] OMAP2+: UART: Add default mux for all uarts.
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607206-21669-1-git-send-email-govindraj.raja@ti.com>
Prior to this change rx-pad wakeup was done by writing to rx-pad offset value
populated in serial.c idle_init. Now with mux framework support we can use
mux_utilities along with hmwod framework to handle io-pad configuration and
enable rx-pad wake-up mechanism.
Add default mux data for all uart's if mux info is not passed from
board file to avoid breaking any board support.
With the default pads we have populated wakeup capability for rx pads
which can be used to enable uart_rx io-pad wakeup from hwmod framework.
The pad values in 3430 board file are same as the default pad values
populated in serial.c. Remove pad values from 3430 board file and use
the default pads from serial.c file.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/board-3430sdp.c | 100 +------------------
arch/arm/mach-omap2/serial.c | 190 +++++++++++++++++++++++------------
2 files changed, 128 insertions(+), 162 deletions(-)
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index bd600cf..b12b38f 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -482,106 +482,8 @@ static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
static struct omap_board_mux board_mux[] __initdata = {
{ .reg_offset = OMAP_MUX_TERMINATOR },
};
-
-static struct omap_device_pad serial1_pads[] __initdata = {
- /*
- * Note that off output enable is an active low
- * signal. So setting this means pin is a
- * input enabled in off mode
- */
- OMAP_MUX_STATIC("uart1_cts.uart1_cts",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart1_rts.uart1_rts",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart1_rx.uart1_rx",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart1_tx.uart1_tx",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial2_pads[] __initdata = {
- OMAP_MUX_STATIC("uart2_cts.uart2_cts",
- OMAP_PIN_INPUT_PULLUP |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rts.uart2_rts",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_rx.uart2_rx",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart2_tx.uart2_tx",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
-};
-
-static struct omap_device_pad serial3_pads[] __initdata = {
- OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
- OMAP_PIN_INPUT_PULLDOWN |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
- OMAP_PIN_INPUT |
- OMAP_PIN_OFF_INPUT_PULLDOWN |
- OMAP_OFFOUT_EN |
- OMAP_MUX_MODE0),
- OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
- OMAP_PIN_OUTPUT |
- OMAP_OFF_EN |
- OMAP_MUX_MODE0),
-};
-
-static struct omap_board_data serial1_data __initdata = {
- .id = 0,
- .pads = serial1_pads,
- .pads_cnt = ARRAY_SIZE(serial1_pads),
-};
-
-static struct omap_board_data serial2_data __initdata = {
- .id = 1,
- .pads = serial2_pads,
- .pads_cnt = ARRAY_SIZE(serial2_pads),
-};
-
-static struct omap_board_data serial3_data __initdata = {
- .id = 2,
- .pads = serial3_pads,
- .pads_cnt = ARRAY_SIZE(serial3_pads),
-};
-
-static inline void board_serial_init(void)
-{
- omap_serial_init_port(&serial1_data);
- omap_serial_init_port(&serial2_data);
- omap_serial_init_port(&serial3_data);
-}
#else
#define board_mux NULL
-
-static inline void board_serial_init(void)
-{
- omap_serial_init();
-}
#endif
/*
@@ -718,7 +620,7 @@ static void __init omap_3430sdp_init(void)
else
gpio_pendown = SDP3430_TS_GPIO_IRQ_SDPV1;
omap_ads7846_init(1, gpio_pendown, 310, NULL);
- board_serial_init();
+ omap_serial_init();
usb_musb_init(NULL);
board_smc91x_init();
board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index fd0c345..1561140 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -57,11 +57,6 @@
struct omap_uart_state {
int num;
int can_sleep;
-
- void __iomem *wk_st;
- void __iomem *wk_en;
- u32 wk_mask;
- u32 padconf;
u32 dma_enabled;
int clocked;
@@ -326,69 +321,135 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
uart->can_sleep = 0;
}
-static void omap_uart_idle_init(struct omap_uart_port_info *uart,
- unsigned short num)
+#ifdef CONFIG_OMAP_MUX
+static struct omap_device_pad default_uart1_pads[] __initdata = {
+ {
+ .name = "uart1_cts.uart1_cts",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart1_rts.uart1_rts",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart1_tx.uart1_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart1_rx.uart1_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad default_uart2_pads[] __initdata = {
+ {
+ .name = "uart2_cts.uart2_cts",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_rts.uart2_rts",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_tx.uart2_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart2_rx.uart2_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad default_uart3_pads[] __initdata = {
+ {
+ .name = "uart3_cts_rctx.uart3_cts_rctx",
+ .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart3_rts_sd.uart3_rts_sd",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart3_tx_irtx.uart3_tx_irtx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart3_rx_irrx.uart3_rx_irrx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ },
+};
+
+static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {
+ {
+ .name = "gpmc_wait2.uart4_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "gpmc_wait3.uart4_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
+ .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE2,
+ },
+};
+
+static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {
+ {
+ .name = "uart4_tx.uart4_tx",
+ .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0,
+ },
+ {
+ .name = "uart4_rx.uart4_rx",
+ .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP,
+ .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0,
+ },
+};
+#else
+static struct omap_device_pad default_uart1_pads[] __initdata = {};
+static struct omap_device_pad default_uart2_pads[] __initdata = {};
+static struct omap_device_pad default_uart3_pads[] __initdata = {};
+static struct omap_device_pad default_omap36xx_uart4_pads[] __initdata = {};
+static struct omap_device_pad default_omap4_uart4_pads[] __initdata = {};
+#endif
+
+static void omap_serial_fill_default_pads(struct omap_board_data *bdata)
{
- if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
- u32 mod = (num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
- u32 wk_mask = 0;
- u32 padconf = 0;
-
- uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1);
- uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1);
- switch (num) {
- case 0:
- wk_mask = OMAP3430_ST_UART1_MASK;
- padconf = 0x182;
- break;
- case 1:
- wk_mask = OMAP3430_ST_UART2_MASK;
- padconf = 0x17a;
- break;
- case 2:
- wk_mask = OMAP3430_ST_UART3_MASK;
- padconf = 0x19e;
- break;
- case 3:
- wk_mask = OMAP3630_ST_UART4_MASK;
- padconf = 0x0d2;
- break;
- }
- uart->wk_mask = wk_mask;
- } else if (cpu_is_omap24xx()) {
- u32 wk_mask = 0;
- u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
-
- switch (num) {
- case 0:
- wk_mask = OMAP24XX_ST_UART1_MASK;
- break;
- case 1:
- wk_mask = OMAP24XX_ST_UART2_MASK;
- break;
- case 2:
- wk_en = OMAP24XX_PM_WKEN2;
- wk_st = OMAP24XX_PM_WKST2;
- wk_mask = OMAP24XX_ST_UART3_MASK;
- break;
- }
- uart->wk_mask = wk_mask;
- if (cpu_is_omap2430()) {
- uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, wk_en);
- uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, wk_st);
- } else if (cpu_is_omap2420()) {
- uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, wk_en);
- uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, wk_st);
+ switch (bdata->id) {
+ case 0:
+ bdata->pads = default_uart1_pads;
+ bdata->pads_cnt = ARRAY_SIZE(default_uart1_pads);
+ break;
+ case 1:
+ bdata->pads = default_uart2_pads;
+ bdata->pads_cnt = ARRAY_SIZE(default_uart2_pads);
+ break;
+ case 2:
+ bdata->pads = default_uart3_pads;
+ bdata->pads_cnt = ARRAY_SIZE(default_uart3_pads);
+ break;
+ case 3:
+ if (cpu_is_omap44xx()) {
+ bdata->pads = default_omap4_uart4_pads;
+ bdata->pads_cnt =
+ ARRAY_SIZE(default_omap4_uart4_pads);
+ } else {
+ bdata->pads = default_omap36xx_uart4_pads;
+ bdata->pads_cnt =
+ ARRAY_SIZE(default_omap36xx_uart4_pads);
}
- } else {
- uart->wk_en = NULL;
- uart->wk_st = NULL;
- uart->wk_mask = 0;
+ break;
+ default:
+ break;
}
}
#else
-static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
static void omap_uart_block_sleep(struct omap_uart_state *uart)
{
/* Needed to enable UART clocks when built without CONFIG_PM */
@@ -473,7 +534,6 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
}
pdata_size = sizeof(struct omap_uart_port_info);
- omap_uart_idle_init(pdata, bdata->id);
pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
pdata->flags = UPF_BOOT_AUTOCONF;
@@ -528,6 +588,10 @@ void __init omap_serial_init(void)
bdata.flags = 0;
bdata.pads = NULL;
bdata.pads_cnt = 0;
+
+ if (cpu_is_omap44xx() || cpu_is_omap34xx())
+ omap_serial_fill_default_pads(&bdata);
+
omap_serial_init_port(&bdata);
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 08/15] OMAP2+: UART: Store certain reg values to port structure
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607206-21669-1-git-send-email-govindraj.raja@ti.com>
In preparation to runtime conversion add missing uart regs to
port structure which can be used in context restore.
Also ensuring all uart reg info's are part of port structure.
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/plat-omap/include/plat/omap-serial.h | 3 ++
drivers/tty/serial/omap-serial.c | 33 ++++++++++++++----------
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 0f061b4..74822b3 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -99,6 +99,9 @@ struct uart_omap_port {
unsigned char mcr;
unsigned char fcr;
unsigned char efr;
+ unsigned char dll;
+ unsigned char dlh;
+ unsigned char mdr1;
int use_dma;
/*
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 6c2ea54..9a0eac2 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -433,8 +433,9 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
- mcr |= up->mcr;
- serial_out(up, UART_MCR, mcr);
+ up->mcr = serial_in(up, UART_MCR);
+ up->mcr |= mcr;
+ serial_out(up, UART_MCR, up->mcr);
}
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
@@ -573,8 +574,6 @@ static inline void
serial_omap_configure_xonxoff
(struct uart_omap_port *up, struct ktermios *termios)
{
- unsigned char efr = 0;
-
up->lcr = serial_in(up, UART_LCR);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
up->efr = serial_in(up, UART_EFR);
@@ -584,8 +583,7 @@ serial_omap_configure_xonxoff
serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
/* clear SW control mode bits */
- efr = up->efr;
- efr &= OMAP_UART_SW_CLR;
+ up->efr &= OMAP_UART_SW_CLR;
/*
* IXON Flag:
@@ -593,7 +591,7 @@ serial_omap_configure_xonxoff
* Transmit XON1, XOFF1
*/
if (termios->c_iflag & IXON)
- efr |= OMAP_UART_SW_TX;
+ up->efr |= OMAP_UART_SW_TX;
/*
* IXOFF Flag:
@@ -601,7 +599,7 @@ serial_omap_configure_xonxoff
* Receiver compares XON1, XOFF1.
*/
if (termios->c_iflag & IXOFF)
- efr |= OMAP_UART_SW_RX;
+ up->efr |= OMAP_UART_SW_RX;
serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
@@ -624,7 +622,7 @@ serial_omap_configure_xonxoff
* load the new software flow control mode IXON or IXOFF
* and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
*/
- serial_out(up, UART_EFR, efr | UART_EFR_SCD);
+ serial_out(up, UART_EFR, up->efr | UART_EFR_SCD);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
@@ -671,6 +669,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
quot = serial_omap_get_divisor(port, baud);
+ up->dll = quot & 0xff;
+ up->dlh = quot >> 8;
+ up->mdr1 = UART_OMAP_MDR1_DISABLE;
+
up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
UART_FCR_ENABLE_FIFO;
if (up->use_dma)
@@ -723,6 +725,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
up->ier |= UART_IER_MSI;
serial_out(up, UART_IER, up->ier);
serial_out(up, UART_LCR, cval); /* reset DLAB */
+ up->lcr = cval;
/* FIFOs and DMA Settings */
@@ -759,7 +762,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
/* Protocol, Baud Rate, and Interrupt Settings */
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
up->efr = serial_in(up, UART_EFR);
@@ -769,8 +772,8 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_IER, 0);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
- serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
+ serial_out(up, UART_DLL, up->dll); /* LS of divisor */
+ serial_out(up, UART_DLM, up->dlh); /* MS of divisor */
serial_out(up, UART_LCR, 0);
serial_out(up, UART_IER, up->ier);
@@ -780,9 +783,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_LCR, cval);
if (baud > 230400 && baud != 3000000)
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_13X_MODE);
+ up->mdr1 = UART_OMAP_MDR1_13X_MODE;
else
- serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
+ up->mdr1 = UART_OMAP_MDR1_16X_MODE;
+
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
/* Hardware Flow Control Configuration */
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 09/15] OMAP2+: UART: Add runtime pm support for omap-serial driver
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607206-21669-1-git-send-email-govindraj.raja@ti.com>
Adapts omap-serial driver to use pm_runtime API's.
Use runtime runtime API's to handle uart clocks and obtain
device_usage statics. Set runtime API's usage to irq_safe so that
we can use get_sync from irq context. Auto-suspend for port specific
activities and put for reg access. Use device_may_wakeup to check
whether uart has wakeup capabilities and then enable uart runtime
usage for the uart.
Removing save_context/restore_context functions from serial.c
Adding context restore to .runtime_suspend and using reg values from port
structure to restore the uart port context based on context_loss_count.
Maintain internal state machine using wakeups_enabled field for avoiding
repeated enable/disable of uart port wakeup mechanism.
Remove omap_uart_disable_wakeup and modify omap_uart_enable_wakeup
to accept pdev and bool value to enable/disable the uart wakeup mechanism
after uart clock's are cut. omap_hwmod_enable_wakeup is used to set
pad wakeup for the uarts. PM_WKEN reg values are left to default.
Removed omap_uart_enable/disable_clocks in serial.c now clock handling
done with runtime API's.
By default uart autosuspend delay is set to -1 to avoid character loss
if uart's are autoidled and woken up on rx pin.
After boot up UART's can be autoidled by setting autosuspendi delay from sysfs.
echo 3000 > /sys/devices/platform/omap/omap_uart.X/power/autosuspend_delay_ms
X=0,1,2,3 for UART1/2/3/4. Number of uarts available may vary across omap_soc.
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/serial.c | 206 ++----------------------
arch/arm/plat-omap/include/plat/omap-serial.h | 5 +
drivers/tty/serial/omap-serial.c | 169 +++++++++++++++++++--
3 files changed, 179 insertions(+), 201 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 1561140..43d8f0d 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -32,6 +32,7 @@
#include <plat/dma.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
#include "prm2xxx_3xxx.h"
#include "pm.h"
@@ -40,8 +41,6 @@
#include "control.h"
#include "mux.h"
-#define UART_OMAP_WER 0x17 /* Wake-up enable register */
-
#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1)
/*
@@ -56,24 +55,7 @@
struct omap_uart_state {
int num;
- int can_sleep;
u32 dma_enabled;
-
- int clocked;
-
- int regshift;
-#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
- int context_valid;
-
- /* Registers to be saved/restored for OFF-mode */
- u16 dll;
- u16 dlh;
- u16 ier;
- u16 sysc;
- u16 scr;
- u16 wer;
- u16 mcr;
-#endif
};
static u8 num_uarts;
@@ -100,34 +82,6 @@ static struct omap_device_pm_latency omap_uart_latency[] = {
},
};
-static inline unsigned int __serial_read_reg(struct uart_port *up,
- int offset)
-{
- offset <<= up->regshift;
- return (unsigned int)__raw_readb(up->membase + offset);
-}
-
-static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
- int offset)
-{
- offset <<= uart->regshift;
- return (unsigned int)__raw_readb(uart->membase + offset);
-}
-
-static inline void __serial_write_reg(struct uart_port *up, int offset,
- int value)
-{
- offset <<= up->regshift;
- __raw_writeb(value, up->membase + offset);
-}
-
-static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
- int value)
-{
- offset <<= uart->regshift;
- __raw_writeb(value, uart->membase + offset);
-}
-
#if defined(CONFIG_PM)
/*
@@ -164,134 +118,8 @@ static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
udelay(1);
}
}
-
-static void omap_uart_save_context(struct omap_uart_state *uart)
-{
- u16 lcr = 0;
-
- if (!enable_off_mode)
- return;
-
- lcr = serial_read_reg(uart, UART_LCR);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- uart->dll = serial_read_reg(uart, UART_DLL);
- uart->dlh = serial_read_reg(uart, UART_DLM);
- serial_write_reg(uart, UART_LCR, lcr);
- uart->ier = serial_read_reg(uart, UART_IER);
- uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
- uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
- uart->wer = serial_read_reg(uart, UART_OMAP_WER);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
- uart->mcr = serial_read_reg(uart, UART_MCR);
- serial_write_reg(uart, UART_LCR, lcr);
-
- uart->context_valid = 1;
-}
-
-static void omap_uart_restore_context(struct omap_uart_state *uart)
-{
- u16 efr = 0;
-
- if (!enable_off_mode)
- return;
-
- if (!uart->context_valid)
- return;
-
- uart->context_valid = 0;
-
- if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
- omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0);
- else
- serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
-
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- efr = serial_read_reg(uart, UART_EFR);
- serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
- serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
- serial_write_reg(uart, UART_IER, 0x0);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_write_reg(uart, UART_DLL, uart->dll);
- serial_write_reg(uart, UART_DLM, uart->dlh);
- serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
- serial_write_reg(uart, UART_IER, uart->ier);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_write_reg(uart, UART_MCR, uart->mcr);
- serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_write_reg(uart, UART_EFR, efr);
- serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
- serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
- serial_write_reg(uart, UART_OMAP_WER, uart->wer);
- serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
-
- if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
- omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1);
- else
- /* UART 16x mode */
- serial_write_reg(uart, UART_OMAP_MDR1,
- UART_OMAP_MDR1_16X_MODE);
-}
-#else
-static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
-static inline void omap_uart_restore_context(struct omap_uart_state *uart) {}
#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
-static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
-{
- if (uart->clocked)
- return;
-
- omap_device_enable(uart->pdev);
- uart->clocked = 1;
- omap_uart_restore_context(uart);
-}
-
-#ifdef CONFIG_PM
-
-static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
-{
- if (!uart->clocked)
- return;
-
- omap_uart_save_context(uart);
- uart->clocked = 0;
- omap_device_idle(uart->pdev);
-}
-
-static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
-{
- /* Set wake-enable bit */
- if (uart->wk_en && uart->wk_mask) {
- u32 v = __raw_readl(uart->wk_en);
- v |= uart->wk_mask;
- __raw_writel(v, uart->wk_en);
- }
-
- /* Ensure IOPAD wake-enables are set */
- if (cpu_is_omap34xx() && uart->padconf) {
- u16 v = omap_ctrl_readw(uart->padconf);
- v |= OMAP3_PADCONF_WAKEUPENABLE0;
- omap_ctrl_writew(v, uart->padconf);
- }
-}
-
-static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
-{
- /* Clear wake-enable bit */
- if (uart->wk_en && uart->wk_mask) {
- u32 v = __raw_readl(uart->wk_en);
- v &= ~uart->wk_mask;
- __raw_writel(v, uart->wk_en);
- }
-
- /* Ensure IOPAD wake-enables are cleared */
- if (cpu_is_omap34xx() && uart->padconf) {
- u16 v = omap_ctrl_readw(uart->padconf);
- v &= ~OMAP3_PADCONF_WAKEUPENABLE0;
- omap_ctrl_writew(v, uart->padconf);
- }
-}
-
static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
int enable)
{
@@ -313,14 +141,6 @@ static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
}
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
-{
- omap_uart_enable_clocks(uart);
-
- omap_uart_smart_idle_enable(uart, 0);
- uart->can_sleep = 0;
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_device_pad default_uart1_pads[] __initdata = {
{
@@ -449,12 +269,22 @@ static void omap_serial_fill_default_pads(struct omap_board_data *bdata)
}
}
-#else
-static void omap_uart_block_sleep(struct omap_uart_state *uart)
+static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
{
- /* Needed to enable UART clocks when built without CONFIG_PM */
- omap_uart_enable_clocks(uart);
+ struct omap_device *od = to_omap_device(pdev);
+
+ if (!od)
+ return;
+
+ if (enable)
+ omap_hwmod_enable_wakeup(od->hwmods[0]);
+ else
+ omap_hwmod_disable_wakeup(od->hwmods[0]);
}
+
+#else
+static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
+{}
#endif /* CONFIG_PM */
struct omap_hwmod *omap_uart_hwmod_lookup(int num)
@@ -537,6 +367,8 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
pdata->uartclk = OMAP24XX_BASE_BAUD * 16;
pdata->flags = UPF_BOOT_AUTOCONF;
+ pdata->enable_wakeup = omap_uart_enable_wakeup;
+ pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
/* Enable the MDR1 errata for OMAP3 */
if (cpu_is_omap34xx() && !cpu_is_ti816x())
@@ -560,12 +392,10 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
omap_hwmod_idle(oh);
omap_device_enable(pdev);
- omap_hwmod_enable_wakeup(oh);
console_unlock();
- if ((cpu_is_omap34xx() && bdata->pads) ||
- (pdata->wk_en && pdata->wk_mask))
+ if ((cpu_is_omap34xx() && bdata->pads))
device_init_wakeup(&pdev->dev, true);
kfree(pdata);
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 74822b3..8ef81ce 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -62,6 +62,9 @@ struct omap_uart_port_info {
upf_t flags; /* UPF_* flags */
u32 errata;
+
+ void (*enable_wakeup)(struct platform_device *, bool);
+ u32 (*get_context_loss_count)(struct device *);
};
struct uart_omap_dma {
@@ -113,6 +116,8 @@ struct uart_omap_port {
unsigned char msr_saved_flags;
char name[20];
unsigned long port_activity;
+ u32 context_loss_cnt;
+ u8 wakeups_enabled;
};
#endif /* __OMAP_SERIAL_H__ */
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 9a0eac2..43c33da 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -37,11 +37,14 @@
#include <linux/clk.h>
#include <linux/serial_core.h>
#include <linux/irq.h>
+#include <linux/pm_runtime.h>
#include <plat/dma.h>
#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
+#define OMAP_UART_AUTOSUSPEND_DELAY -1
+
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
@@ -102,6 +105,8 @@ static void serial_omap_stop_rxdma(struct uart_omap_port *up)
omap_free_dma(up->uart_dma.rx_dma_channel);
up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
up->uart_dma.rx_dma_used = false;
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
}
}
@@ -110,8 +115,11 @@ static void serial_omap_enable_ms(struct uart_port *port)
struct uart_omap_port *up = (struct uart_omap_port *)port;
dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
+
+ pm_runtime_get_sync(&up->pdev->dev);
up->ier |= UART_IER_MSI;
serial_out(up, UART_IER, up->ier);
+ pm_runtime_put(&up->pdev->dev);
}
static void serial_omap_stop_tx(struct uart_port *port)
@@ -129,23 +137,32 @@ static void serial_omap_stop_tx(struct uart_port *port)
omap_stop_dma(up->uart_dma.tx_dma_channel);
omap_free_dma(up->uart_dma.tx_dma_channel);
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
}
+ pm_runtime_get_sync(&up->pdev->dev);
if (up->ier & UART_IER_THRI) {
up->ier &= ~UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
}
+
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
}
static void serial_omap_stop_rx(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+ pm_runtime_get_sync(&up->pdev->dev);
if (up->use_dma)
serial_omap_stop_rxdma(up);
up->ier &= ~UART_IER_RLSI;
up->port.read_status_mask &= ~UART_LSR_DR;
serial_out(up, UART_IER, up->ier);
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
}
static inline void receive_chars(struct uart_omap_port *up, int *status)
@@ -262,7 +279,10 @@ static void serial_omap_start_tx(struct uart_port *port)
int ret = 0;
if (!up->use_dma) {
+ pm_runtime_get_sync(&up->pdev->dev);
serial_omap_enable_ier_thri(up);
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
return;
}
@@ -272,6 +292,7 @@ static void serial_omap_start_tx(struct uart_port *port)
xmit = &up->port.state->xmit;
if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
+ pm_runtime_get_sync(&up->pdev->dev);
ret = omap_request_dma(up->uart_dma.uart_dma_tx,
"UART Tx DMA",
(void *)uart_tx_dma_callback, up,
@@ -354,9 +375,13 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
unsigned int iir, lsr;
unsigned long flags;
+ pm_runtime_get_sync(&up->pdev->dev);
iir = serial_in(up, UART_IIR);
- if (iir & UART_IIR_NO_INT)
+ if (iir & UART_IIR_NO_INT) {
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
return IRQ_NONE;
+ }
spin_lock_irqsave(&up->port.lock, flags);
lsr = serial_in(up, UART_LSR);
@@ -378,6 +403,9 @@ static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
transmit_chars(up);
spin_unlock_irqrestore(&up->port.lock, flags);
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
+
up->port_activity = jiffies;
return IRQ_HANDLED;
}
@@ -388,11 +416,12 @@ static unsigned int serial_omap_tx_empty(struct uart_port *port)
unsigned long flags = 0;
unsigned int ret = 0;
+ pm_runtime_get_sync(&up->pdev->dev);
dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
spin_lock_irqsave(&up->port.lock, flags);
ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
spin_unlock_irqrestore(&up->port.lock, flags);
-
+ pm_runtime_put(&up->pdev->dev);
return ret;
}
@@ -402,7 +431,10 @@ static unsigned int serial_omap_get_mctrl(struct uart_port *port)
unsigned char status;
unsigned int ret = 0;
+ pm_runtime_get_sync(&up->pdev->dev);
status = check_modem_status(up);
+ pm_runtime_put(&up->pdev->dev);
+
dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
if (status & UART_MSR_DCD)
@@ -433,9 +465,11 @@ static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
if (mctrl & TIOCM_LOOP)
mcr |= UART_MCR_LOOP;
+ pm_runtime_get_sync(&up->pdev->dev);
up->mcr = serial_in(up, UART_MCR);
up->mcr |= mcr;
serial_out(up, UART_MCR, up->mcr);
+ pm_runtime_put(&up->pdev->dev);
}
static void serial_omap_break_ctl(struct uart_port *port, int break_state)
@@ -444,6 +478,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+ pm_runtime_get_sync(&up->pdev->dev);
spin_lock_irqsave(&up->port.lock, flags);
if (break_state == -1)
up->lcr |= UART_LCR_SBC;
@@ -451,6 +486,7 @@ static void serial_omap_break_ctl(struct uart_port *port, int break_state)
up->lcr &= ~UART_LCR_SBC;
serial_out(up, UART_LCR, up->lcr);
spin_unlock_irqrestore(&up->port.lock, flags);
+ pm_runtime_put(&up->pdev->dev);
}
static int serial_omap_startup(struct uart_port *port)
@@ -469,6 +505,7 @@ static int serial_omap_startup(struct uart_port *port)
dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
+ pm_runtime_get_sync(&up->pdev->dev);
/*
* Clear the FIFO buffers and disable them.
* (they will be reenabled in set_termios())
@@ -524,6 +561,8 @@ static int serial_omap_startup(struct uart_port *port)
/* Enable module level wake up */
serial_out(up, UART_OMAP_WER, OMAP_UART_WER_MOD_WKUP);
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
up->port_activity = jiffies;
return 0;
}
@@ -534,6 +573,8 @@ static void serial_omap_shutdown(struct uart_port *port)
unsigned long flags = 0;
dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+
+ pm_runtime_get_sync(&up->pdev->dev);
/*
* Disable interrupts from this port
*/
@@ -567,6 +608,7 @@ static void serial_omap_shutdown(struct uart_port *port)
up->uart_dma.rx_buf_dma_phys);
up->uart_dma.rx_buf = NULL;
}
+ pm_runtime_put(&up->pdev->dev);
free_irq(up->port.irq, up);
}
@@ -682,6 +724,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
+ pm_runtime_get_sync(&up->pdev->dev);
spin_lock_irqsave(&up->port.lock, flags);
/*
@@ -814,6 +857,7 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_omap_configure_xonxoff(up, termios);
spin_unlock_irqrestore(&up->port.lock, flags);
+ pm_runtime_put(&up->pdev->dev);
dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
}
@@ -825,6 +869,8 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
unsigned char efr;
dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+
+ pm_runtime_get_sync(&up->pdev->dev);
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
efr = serial_in(up, UART_EFR);
serial_out(up, UART_EFR, efr | UART_EFR_ECB);
@@ -834,6 +880,7 @@ serial_omap_pm(struct uart_port *port, unsigned int state,
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
serial_out(up, UART_EFR, efr);
serial_out(up, UART_LCR, 0);
+ pm_runtime_put(&up->pdev->dev);
}
static void serial_omap_release_port(struct uart_port *port)
@@ -911,19 +958,26 @@ static inline void wait_for_xmitr(struct uart_omap_port *up)
static void serial_omap_poll_put_char(struct uart_port *port, unsigned char ch)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+ pm_runtime_get_sync(&up->pdev->dev);
wait_for_xmitr(up);
serial_out(up, UART_TX, ch);
+ pm_runtime_put(&up->pdev->dev);
}
static int serial_omap_poll_get_char(struct uart_port *port)
{
struct uart_omap_port *up = (struct uart_omap_port *)port;
- unsigned int status = serial_in(up, UART_LSR);
+ unsigned int status;
+ pm_runtime_get_sync(&up->pdev->dev);
+ status = serial_in(up, UART_LSR);
if (!(status & UART_LSR_DR))
return NO_POLL_CHAR;
- return serial_in(up, UART_RX);
+ status = serial_in(up, UART_RX);
+ pm_runtime_put(&up->pdev->dev);
+ return status;
}
#endif /* CONFIG_CONSOLE_POLL */
@@ -951,6 +1005,8 @@ serial_omap_console_write(struct console *co, const char *s,
unsigned int ier;
int locked = 1;
+ pm_runtime_get_sync(&up->pdev->dev);
+
local_irq_save(flags);
if (up->port.sysrq)
locked = 0;
@@ -983,6 +1039,8 @@ serial_omap_console_write(struct console *co, const char *s,
if (up->msr_saved_flags)
check_modem_status(up);
+ pm_runtime_mark_last_busy(&up->pdev->dev);
+ pm_runtime_put_autosuspend(&up->pdev->dev);
if (locked)
spin_unlock(&up->port.lock);
local_irq_restore(flags);
@@ -1065,19 +1123,18 @@ static struct uart_driver serial_omap_reg = {
.cons = OMAP_CONSOLE,
};
-static int
-serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+static int serial_omap_suspend(struct device *dev)
{
- struct uart_omap_port *up = platform_get_drvdata(pdev);
+ struct uart_omap_port *up = dev_get_drvdata(dev);
if (up)
uart_suspend_port(&serial_omap_reg, &up->port);
return 0;
}
-static int serial_omap_resume(struct platform_device *dev)
+static int serial_omap_resume(struct device *dev)
{
- struct uart_omap_port *up = platform_get_drvdata(dev);
+ struct uart_omap_port *up = dev_get_drvdata(dev);
if (up)
uart_resume_port(&serial_omap_reg, &up->port);
@@ -1140,6 +1197,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up)
int ret = 0;
if (up->uart_dma.rx_dma_channel == -1) {
+ pm_runtime_get_sync(&up->pdev->dev);
ret = omap_request_dma(up->uart_dma.uart_dma_rx,
"UART Rx DMA",
(void *)uart_rx_dma_callback, up,
@@ -1305,6 +1363,16 @@ static int serial_omap_probe(struct platform_device *pdev)
up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
}
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ OMAP_UART_AUTOSUSPEND_DELAY);
+
+ pm_runtime_irq_safe(&pdev->dev);
+ if (device_may_wakeup(&pdev->dev)) {
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
+ }
+
ui[pdev->id] = up;
serial_omap_add_console_port(up);
@@ -1312,6 +1380,7 @@ static int serial_omap_probe(struct platform_device *pdev)
if (ret != 0)
goto do_release_region;
+ pm_runtime_put(&pdev->dev);
platform_set_drvdata(pdev, up);
return 0;
err:
@@ -1326,22 +1395,96 @@ static int serial_omap_remove(struct platform_device *dev)
{
struct uart_omap_port *up = platform_get_drvdata(dev);
- platform_set_drvdata(dev, NULL);
if (up) {
+ pm_runtime_disable(&up->pdev->dev);
uart_remove_one_port(&serial_omap_reg, &up->port);
kfree(up);
}
+
+ platform_set_drvdata(dev, NULL);
+ return 0;
+}
+
+static void serial_omap_restore_context(struct uart_omap_port *up)
+{
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+ serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0x0); /* Operational mode */
+ serial_out(up, UART_IER, 0x0);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+ serial_out(up, UART_DLL, up->dll);
+ serial_out(up, UART_DLM, up->dlh);
+ serial_out(up, UART_LCR, 0x0); /* Operational mode */
+ serial_out(up, UART_IER, up->ier);
+ serial_out(up, UART_FCR, up->fcr);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_out(up, UART_MCR, up->mcr);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
+ serial_out(up, UART_EFR, up->efr);
+ serial_out(up, UART_LCR, up->lcr);
+ /* UART 16x mode */
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
+}
+
+static int serial_omap_runtime_suspend(struct device *dev)
+{
+ struct uart_omap_port *up = dev_get_drvdata(dev);
+ struct omap_uart_port_info *pdata = dev->platform_data;
+
+ if (!up)
+ return -EINVAL;
+
+ if (!pdata->enable_wakeup || !pdata->get_context_loss_count)
+ return 0;
+
+ if (pdata->get_context_loss_count)
+ up->context_loss_cnt = pdata->get_context_loss_count(dev);
+
+ if (device_may_wakeup(dev)) {
+ if (!up->wakeups_enabled) {
+ pdata->enable_wakeup(up->pdev, true);
+ up->wakeups_enabled = true;
+ }
+ } else {
+ if (up->wakeups_enabled) {
+ pdata->enable_wakeup(up->pdev, false);
+ up->wakeups_enabled = false;
+ }
+ }
+
+ return 0;
+}
+
+static int serial_omap_runtime_resume(struct device *dev)
+{
+ struct uart_omap_port *up = dev_get_drvdata(dev);
+ struct omap_uart_port_info *pdata = dev->platform_data;
+
+ if (up) {
+ if (pdata->get_context_loss_count) {
+ u32 loss_cnt = pdata->get_context_loss_count(dev);
+
+ if (up->context_loss_cnt != loss_cnt)
+ serial_omap_restore_context(up);
+ }
+ }
+
return 0;
}
+static const struct dev_pm_ops serial_omap_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(serial_omap_suspend, serial_omap_resume)
+ SET_RUNTIME_PM_OPS(serial_omap_runtime_suspend,
+ serial_omap_runtime_resume, NULL)
+};
+
static struct platform_driver serial_omap_driver = {
.probe = serial_omap_probe,
.remove = serial_omap_remove,
-
- .suspend = serial_omap_suspend,
- .resume = serial_omap_resume,
.driver = {
.name = DRIVER_NAME,
+ .pm = &serial_omap_dev_pm_ops,
},
};
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 10/15] OMAP2+: UART: Move errata handling from serial.c to omap-serial
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
Move the errata handling mechanism from serial.c to omap-serial file
and utilise the same func in driver file.
Errata i202, i291 are moved to be handled with omap-serial
Moving the errata macro from serial.c file to driver header file
as from on errata will be handled in driver file itself.
Corrected errata id from chapter reference 2.15 to errata id i291.
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
arch/arm/mach-omap2/serial.c | 78 +++++--------------------
arch/arm/plat-omap/include/plat/omap-serial.h | 5 ++
drivers/tty/serial/omap-serial.c | 63 ++++++++++++++++++--
3 files changed, 77 insertions(+), 69 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 43d8f0d..9fe248e 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -41,8 +41,6 @@
#include "control.h"
#include "mux.h"
-#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1)
-
/*
* NOTE: By default the serial timeout is disabled as it causes lost characters
* over the serial ports. This means that the UART clocks will stay on until
@@ -53,11 +51,6 @@
#define MAX_UART_HWMOD_NAME_LEN 16
-struct omap_uart_state {
- int num;
- u32 dma_enabled;
-};
-
static u8 num_uarts;
static int uart_idle_hwmod(struct omap_device *od)
@@ -84,63 +77,6 @@ static struct omap_device_pm_latency omap_uart_latency[] = {
#if defined(CONFIG_PM)
-/*
- * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
- * The access to uart register after MDR1 Access
- * causes UART to corrupt data.
- *
- * Need a delay =
- * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
- * give 10 times as much
- */
-static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
- u8 fcr_val)
-{
- u8 timeout = 255;
-
- serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
- udelay(2);
- serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
- UART_FCR_CLEAR_RCVR);
- /*
- * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
- * TX_FIFO_E bit is 1.
- */
- while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
- (UART_LSR_THRE | UART_LSR_DR))) {
- timeout--;
- if (!timeout) {
- /* Should *never* happen. we warn and carry on */
- dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
- serial_read_reg(uart, UART_LSR));
- break;
- }
- udelay(1);
- }
-}
-#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */
-
-static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
- int enable)
-{
- u8 idlemode;
-
- if (enable) {
- /**
- * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
- * in Smartidle Mode When Configured for DMA Operations.
- */
- if (uart->dma_enabled)
- idlemode = HWMOD_IDLEMODE_FORCE;
- else
- idlemode = HWMOD_IDLEMODE_SMART;
- } else {
- idlemode = HWMOD_IDLEMODE_NO;
- }
-
- omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
-}
-
#ifdef CONFIG_OMAP_MUX
static struct omap_device_pad default_uart1_pads[] __initdata = {
{
@@ -282,7 +218,20 @@ static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
omap_hwmod_disable_wakeup(od->hwmods[0]);
}
+/*
+ * Errata i291: [UART]:Cannot Acknowledge Idle Requests
+ * in Smartidle Mode When Configured for DMA Operations.
+ * WA: configure uart in force idle mode.
+ */
+static void omap_uart_set_forceidle(struct platform_device *pdev)
+{
+ struct omap_device *od = to_omap_device(pdev);
+
+ omap_hwmod_set_slave_idlemode(od->hwmods[0], HWMOD_IDLEMODE_FORCE);
+}
+
#else
+static void omap_uart_set_forceidle(struct platform_device *pdev) {}
static void omap_uart_enable_wakeup(struct platform_device *pdev, bool enable)
{}
#endif /* CONFIG_PM */
@@ -369,6 +318,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
pdata->flags = UPF_BOOT_AUTOCONF;
pdata->enable_wakeup = omap_uart_enable_wakeup;
pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
+ pdata->set_force_idle = omap_uart_set_forceidle;
/* Enable the MDR1 errata for OMAP3 */
if (cpu_is_omap34xx() && !cpu_is_ti816x())
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 8ef81ce..12f5262 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -56,6 +56,8 @@
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
+#define UART_ERRATA_i202_MDR1_ACCESS (0x1 << 1)
+
struct omap_uart_port_info {
bool dma_enabled; /* To specify DMA Mode */
unsigned int uartclk; /* UART clock rate */
@@ -65,6 +67,7 @@ struct omap_uart_port_info {
void (*enable_wakeup)(struct platform_device *, bool);
u32 (*get_context_loss_count)(struct device *);
+ void (*set_force_idle)(struct platform_device *);
};
struct uart_omap_dma {
@@ -118,6 +121,8 @@ struct uart_omap_port {
unsigned long port_activity;
u32 context_loss_cnt;
u8 wakeups_enabled;
+ u32 errata;
+
};
#endif /* __OMAP_SERIAL_H__ */
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 43c33da..817443e 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -51,6 +51,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
static void serial_omap_rx_timeout(unsigned long uart_no);
static int serial_omap_start_rxdma(struct uart_omap_port *up);
+static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
{
@@ -805,7 +806,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
/* Protocol, Baud Rate, and Interrupt Settings */
- serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, up->mdr1);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
+
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
up->efr = serial_in(up, UART_EFR);
@@ -830,7 +835,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
else
up->mdr1 = UART_OMAP_MDR1_16X_MODE;
- serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, up->mdr1);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
/* Hardware Flow Control Configuration */
@@ -1350,6 +1358,7 @@ static int serial_omap_probe(struct platform_device *pdev)
up->port.flags = omap_up_info->flags;
up->port.uartclk = omap_up_info->uartclk;
up->uart_dma.uart_base = mem->start;
+ up->errata = omap_up_info->errata;
if (omap_up_info->dma_enabled) {
up->uart_dma.uart_dma_tx = dma_tx->start;
@@ -1405,9 +1414,47 @@ static int serial_omap_remove(struct platform_device *dev)
return 0;
}
+/*
+ * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6)
+ * The access to uart register after MDR1 Access
+ * causes UART to corrupt data.
+ *
+ * Need a delay =
+ * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS)
+ * give 10 times as much
+ */
+static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1)
+{
+ u8 timeout = 255;
+
+ serial_out(up, UART_OMAP_MDR1, mdr1);
+ udelay(2);
+ serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT |
+ UART_FCR_CLEAR_RCVR);
+ /*
+ * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
+ * TX_FIFO_E bit is 1.
+ */
+ while (UART_LSR_THRE != (serial_in(up, UART_LSR) &
+ (UART_LSR_THRE | UART_LSR_DR))) {
+ timeout--;
+ if (!timeout) {
+ /* Should *never* happen. we warn and carry on */
+ dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n",
+ serial_in(up, UART_LSR));
+ break;
+ }
+ udelay(1);
+ }
+}
+
static void serial_omap_restore_context(struct uart_omap_port *up)
{
- serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE);
+ else
+ serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
+
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
serial_out(up, UART_EFR, UART_EFR_ECB);
serial_out(up, UART_LCR, 0x0); /* Operational mode */
@@ -1423,8 +1470,10 @@ static void serial_omap_restore_context(struct uart_omap_port *up)
serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */
serial_out(up, UART_EFR, up->efr);
serial_out(up, UART_LCR, up->lcr);
- /* UART 16x mode */
- serial_out(up, UART_OMAP_MDR1, up->mdr1);
+ if (up->errata & UART_ERRATA_i202_MDR1_ACCESS)
+ serial_omap_mdr1_errataset(up, up->mdr1);
+ else
+ serial_out(up, UART_OMAP_MDR1, up->mdr1);
}
static int serial_omap_runtime_suspend(struct device *dev)
@@ -1453,6 +1502,10 @@ static int serial_omap_runtime_suspend(struct device *dev)
}
}
+ /* Errata i291 */
+ if (up->use_dma && pdata->set_force_idle)
+ pdata->set_force_idle(up->pdev);
+
return 0;
}
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 11/15] OMAP2+: UART: Allow UART parameters to be configured from board file.
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607232-21709-1-git-send-email-govindraj.raja@ti.com>
From: Deepak K <deepak.k@ti.com>
The following UART parameters are defined within the UART driver:
1). Whether the UART uses DMA (dma_enabled), by default set to 0
2). The size of dma buffer (set to 4096 bytes)
3). The time after which the dma should stop if no more data is received.
4). The auto suspend delay that will be passed for pm_runtime_autosuspend
where uart will be disabled after timeout
Different UARTs may be used for different purpose such as the console,
for interfacing bluetooth chip, for interfacing to a modem chip, etc.
Therefore, it is necessary to be able to customize the above settings
for a given board on a per UART basis.
This change allows these parameters to be configured from the board file
and allows the parameters to be configured for each UART independently.
If a board does not define its own custom parameters for the UARTs, then
use the default parameters in the structure "omap_serial_default_info".
The default parameters are defined to be the same as the current settings
in the UART driver to avoid breaking the UART for any cuurnelty supported
boards. By default, make all boards use the default UART parameters.
Signed-off-by: Deepak K <deepak.k@ti.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
This patch is derived and reworked from a custom 2.6.35 kernel
Available here:
http://git.omapzoom.org/?p=kernel/omap.git;
a=commitdiff;h=584ef316542f77312be7ba96a0f3013c8f64852b;
hp=7233a76cb362c0fc603f773274159adff91d3513
arch/arm/mach-omap2/board-4430sdp.c | 8 ++--
arch/arm/mach-omap2/board-n8x0.c | 6 +-
arch/arm/mach-omap2/board-omap4panda.c | 8 ++--
arch/arm/mach-omap2/serial.c | 56 ++++++++++++++++++++----
arch/arm/plat-omap/include/plat/omap-serial.h | 7 ++-
arch/arm/plat-omap/include/plat/serial.h | 6 ++-
drivers/tty/serial/omap-serial.c | 8 +--
7 files changed, 69 insertions(+), 30 deletions(-)
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index c7cef44..41b43cb 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -743,11 +743,11 @@ static inline void board_serial_init(void)
bdata.pads_cnt = 0;
bdata.id = 0;
/* pass dummy data for UART1 */
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
- omap_serial_init_port(&serial2_data);
- omap_serial_init_port(&serial3_data);
- omap_serial_init_port(&serial4_data);
+ omap_serial_init_port(&serial2_data, NULL);
+ omap_serial_init_port(&serial3_data, NULL);
+ omap_serial_init_port(&serial4_data, NULL);
}
#else
#define board_mux NULL
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index e11f0c5..3408726 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -656,15 +656,15 @@ static inline void board_serial_init(void)
bdata.pads_cnt = 0;
bdata.id = 0;
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
bdata.id = 1;
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
bdata.id = 2;
bdata.pads = serial2_pads;
bdata.pads_cnt = ARRAY_SIZE(serial2_pads);
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
}
#else
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 9aaa960..fdfac0c 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -425,11 +425,11 @@ static inline void board_serial_init(void)
bdata.pads_cnt = 0;
bdata.id = 0;
/* pass dummy data for UART1 */
- omap_serial_init_port(&bdata);
+ omap_serial_init_port(&bdata, NULL);
- omap_serial_init_port(&serial2_data);
- omap_serial_init_port(&serial3_data);
- omap_serial_init_port(&serial4_data);
+ omap_serial_init_port(&serial2_data, NULL);
+ omap_serial_init_port(&serial3_data, NULL);
+ omap_serial_init_port(&serial4_data, NULL);
}
#else
#define board_mux NULL
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 9fe248e..0e45d9a 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -42,17 +42,29 @@
#include "mux.h"
/*
- * NOTE: By default the serial timeout is disabled as it causes lost characters
- * over the serial ports. This means that the UART clocks will stay on until
- * disabled via sysfs. This also causes that any deeper omap sleep states are
- * blocked.
+ * NOTE: By default the serial auto_suspend timeout is disabled as it causes
+ * lost characters over the serial ports. This means that the UART clocks will
+ * stay on until power/autosuspend_delay is set for the uart from sysfs.
+ * This also causes that any deeper omap sleep states are blocked.
*/
-#define DEFAULT_TIMEOUT 0
+#define DEFAULT_AUTOSUSPEND_DELAY -1
#define MAX_UART_HWMOD_NAME_LEN 16
static u8 num_uarts;
+#define DEFAULT_RXDMA_TIMEOUT 1 /* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
+
+static struct omap_uart_port_info omap_serial_default_info[] = {
+ {
+ .dma_enabled = 0,
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY,
+ },
+};
+
static int uart_idle_hwmod(struct omap_device *od)
{
omap_hwmod_idle(od->hwmods[0]);
@@ -279,6 +291,7 @@ core_initcall(omap_serial_early_init);
/**
* omap_serial_init_port() - initialize single serial port
* @bdata: port specific board data pointer
+ * @info: platform specific data pointer
*
* This function initialies serial driver for given port only.
* Platforms can call this function instead of omap_serial_init()
@@ -287,7 +300,8 @@ core_initcall(omap_serial_early_init);
* Don't mix calls to omap_serial_init_port() and omap_serial_init(),
* use only one of the two.
*/
-void __init omap_serial_init_port(struct omap_board_data *bdata)
+void __init omap_serial_init_port(struct omap_board_data *bdata,
+ struct omap_uart_port_info *info)
{
struct omap_hwmod *oh;
struct platform_device *pdev;
@@ -306,6 +320,9 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
if (!oh)
return;
+ if (info == NULL)
+ info = omap_serial_default_info;
+
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
pr_err("Memory allocation for UART pdata failed\n");
@@ -319,6 +336,10 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
pdata->enable_wakeup = omap_uart_enable_wakeup;
pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
pdata->set_force_idle = omap_uart_set_forceidle;
+ pdata->dma_enabled = info->dma_enabled;
+ pdata->dma_rx_buf_size = info->dma_rx_buf_size;
+ pdata->dma_rx_timeout = info->dma_rx_timeout;
+ pdata->autosuspend_timeout = info->autosuspend_timeout;
/* Enable the MDR1 errata for OMAP3 */
if (cpu_is_omap34xx() && !cpu_is_ti816x())
@@ -352,13 +373,14 @@ void __init omap_serial_init_port(struct omap_board_data *bdata)
}
/**
- * omap_serial_init() - initialize all supported serial ports
+ * omap_serial_board_init() - initialize all supported serial ports
+ * @info: platform specific data pointer
*
* Initializes all available UARTs as serial ports. Platforms
* can call this function when they want to have default behaviour
* for serial ports (e.g initialize them all as serial ports).
*/
-void __init omap_serial_init(void)
+void __init omap_serial_board_init(struct omap_uart_port_info *info)
{
struct omap_board_data bdata;
u8 i;
@@ -372,7 +394,21 @@ void __init omap_serial_init(void)
if (cpu_is_omap44xx() || cpu_is_omap34xx())
omap_serial_fill_default_pads(&bdata);
- omap_serial_init_port(&bdata);
-
+ if (info == NULL)
+ omap_serial_init_port(&bdata, NULL);
+ else
+ omap_serial_init_port(&bdata, &info[i]);
}
}
+
+/**
+ * omap_serial_init() - initialize all supported serial ports
+ *
+ * Initializes all available UARTs.
+ * Platforms can call this function when they want to have default behaviour
+ * for serial ports (e.g initialize them all as serial ports).
+ */
+void __init omap_serial_init(void)
+{
+ omap_serial_board_init(NULL);
+}
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index 12f5262..a40a41a 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -64,6 +64,9 @@ struct omap_uart_port_info {
upf_t flags; /* UPF_* flags */
u32 errata;
+ unsigned int dma_rx_buf_size;
+ unsigned int dma_rx_timeout;
+ unsigned int autosuspend_timeout;
void (*enable_wakeup)(struct platform_device *, bool);
u32 (*get_context_loss_count)(struct device *);
@@ -91,8 +94,8 @@ struct uart_omap_dma {
spinlock_t rx_lock;
/* timer to poll activity on rx dma */
struct timer_list rx_timer;
- int rx_buf_size;
- int rx_timeout;
+ unsigned int rx_buf_size;
+ unsigned int rx_timeout;
};
struct uart_omap_port {
diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h
index b8d9303..e25534e 100644
--- a/arch/arm/plat-omap/include/plat/serial.h
+++ b/arch/arm/plat-omap/include/plat/serial.h
@@ -106,10 +106,12 @@
#ifndef __ASSEMBLER__
struct omap_board_data;
+struct omap_uart_port_info;
extern void omap_serial_init(void);
-extern void omap_serial_init_port(struct omap_board_data *bdata);
-extern void omap_uart_check_wakeup(void);
+extern void omap_serial_board_init(struct omap_uart_port_info *platform_data);
+extern void omap_serial_init_port(struct omap_board_data *bdata,
+ struct omap_uart_port_info *platform_data);
#endif
#endif
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 817443e..15e0655 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -43,8 +43,6 @@
#include <plat/dmtimer.h>
#include <plat/omap-serial.h>
-#define OMAP_UART_AUTOSUSPEND_DELAY -1
-
static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
@@ -1364,8 +1362,8 @@ static int serial_omap_probe(struct platform_device *pdev)
up->uart_dma.uart_dma_tx = dma_tx->start;
up->uart_dma.uart_dma_rx = dma_rx->start;
up->use_dma = 1;
- up->uart_dma.rx_buf_size = 4096;
- up->uart_dma.rx_timeout = 2;
+ up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
+ up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
spin_lock_init(&(up->uart_dma.tx_lock));
spin_lock_init(&(up->uart_dma.rx_lock));
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
@@ -1374,7 +1372,7 @@ static int serial_omap_probe(struct platform_device *pdev)
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev,
- OMAP_UART_AUTOSUSPEND_DELAY);
+ omap_up_info->autosuspend_timeout);
pm_runtime_irq_safe(&pdev->dev);
if (device_may_wakeup(&pdev->dev)) {
--
1.7.4.1
^ permalink raw reply related
* [PATCH v5 12/15] OMAP2+: UART: Make the RX_TIMEOUT for DMA configurable for each UART
From: Govindraj.R @ 2011-09-21 12:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1316607232-21709-1-git-send-email-govindraj.raja@ti.com>
From: Jon Hunter <jon-hunter@ti.com>
When using DMA there are two timeouts defined. The first timeout,
rx_timeout, is really a polling rate in which software polls the
DMA status to see if the DMA has finished. This is necessary for
the RX side because we do not know how much data we will receive.
The secound timeout, RX_TIMEOUT, is a timeout after which the
DMA will be stopped if no more data is received. To make this
clearer, rename rx_timeout as rx_poll_rate and rename the
function serial_omap_rx_timeout() to serial_omap_rxdma_poll().
The OMAP-Serial driver defines an RX_TIMEOUT of 3 seconds that is
used to indicate when the DMA for UART can be stopped if no more
data is received. The value is a global definition that is applied
to all instances of the UART.
Each UART may be used for a different purpose and so the timeout
required may differ. Make this value configurable for each UART so
that this value can be optimised for power savings.
Acked-by: Kevin Hilman <khilman@ti.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
Signed-off-by: Govindraj.R <govindraj.raja@ti.com>
---
This patch is derived from a custom 2.6.35 kernel
Available here:
http://git.omapzoom.org/?p=kernel/omap.git;a=commitdiff;
h=b47839fb84e68333ea29a327cf5aa694b71be7d6;
hp=f62f570e8580507be48ad004defc2ec714b6e05d
arch/arm/mach-omap2/serial.c | 5 ++++-
arch/arm/plat-omap/include/plat/omap-serial.h | 3 ++-
drivers/tty/serial/omap-serial.c | 15 ++++++++-------
3 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 0e45d9a..57d063a 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -53,13 +53,15 @@
static u8 num_uarts;
-#define DEFAULT_RXDMA_TIMEOUT 1 /* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_POLLRATE 1 /* RX DMA polling rate (us) */
#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
+#define DEFAULT_RXDMA_TIMEOUT (3 * HZ)/* RX DMA timeout (jiffies) */
static struct omap_uart_port_info omap_serial_default_info[] = {
{
.dma_enabled = 0,
.dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
.dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
.autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY,
},
@@ -338,6 +340,7 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
pdata->set_force_idle = omap_uart_set_forceidle;
pdata->dma_enabled = info->dma_enabled;
pdata->dma_rx_buf_size = info->dma_rx_buf_size;
+ pdata->dma_rx_poll_rate = info->dma_rx_poll_rate;
pdata->dma_rx_timeout = info->dma_rx_timeout;
pdata->autosuspend_timeout = info->autosuspend_timeout;
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
index a40a41a..28abc6b 100644
--- a/arch/arm/plat-omap/include/plat/omap-serial.h
+++ b/arch/arm/plat-omap/include/plat/omap-serial.h
@@ -51,7 +51,6 @@
#define OMAP_UART_DMA_CH_FREE -1
-#define RX_TIMEOUT (3 * HZ)
#define OMAP_MAX_HSUART_PORTS 4
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
@@ -67,6 +66,7 @@ struct omap_uart_port_info {
unsigned int dma_rx_buf_size;
unsigned int dma_rx_timeout;
unsigned int autosuspend_timeout;
+ unsigned int dma_rx_poll_rate;
void (*enable_wakeup)(struct platform_device *, bool);
u32 (*get_context_loss_count)(struct device *);
@@ -95,6 +95,7 @@ struct uart_omap_dma {
/* timer to poll activity on rx dma */
struct timer_list rx_timer;
unsigned int rx_buf_size;
+ unsigned int rx_poll_rate;
unsigned int rx_timeout;
};
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 15e0655..64e4ab5 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -47,7 +47,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
/* Forward declaration of functions */
static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
-static void serial_omap_rx_timeout(unsigned long uart_no);
+static void serial_omap_rxdma_poll(unsigned long uart_no);
static int serial_omap_start_rxdma(struct uart_omap_port *up);
static void serial_omap_mdr1_errataset(struct uart_omap_port *up, u8 mdr1);
@@ -542,7 +542,7 @@ static int serial_omap_startup(struct uart_port *port)
(dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
0);
init_timer(&(up->uart_dma.rx_timer));
- up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
+ up->uart_dma.rx_timer.function = serial_omap_rxdma_poll;
up->uart_dma.rx_timer.data = up->pdev->id;
/* Currently the buffer size is 4KB. Can increase it */
up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
@@ -1147,7 +1147,7 @@ static int serial_omap_resume(struct device *dev)
return 0;
}
-static void serial_omap_rx_timeout(unsigned long uart_no)
+static void serial_omap_rxdma_poll(unsigned long uart_no)
{
struct uart_omap_port *up = ui[uart_no];
unsigned int curr_dma_pos, curr_transmitted_size;
@@ -1157,9 +1157,9 @@ static void serial_omap_rx_timeout(unsigned long uart_no)
if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
(curr_dma_pos == 0)) {
if (jiffies_to_msecs(jiffies - up->port_activity) <
- RX_TIMEOUT) {
+ up->uart_dma.rx_timeout) {
mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
+ usecs_to_jiffies(up->uart_dma.rx_poll_rate));
} else {
serial_omap_stop_rxdma(up);
up->ier |= (UART_IER_RDI | UART_IER_RLSI);
@@ -1188,7 +1188,7 @@ static void serial_omap_rx_timeout(unsigned long uart_no)
}
} else {
mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
+ usecs_to_jiffies(up->uart_dma.rx_poll_rate));
}
up->port_activity = jiffies;
}
@@ -1227,7 +1227,7 @@ static int serial_omap_start_rxdma(struct uart_omap_port *up)
/* FIXME: Cache maintenance needed here? */
omap_start_dma(up->uart_dma.rx_dma_channel);
mod_timer(&up->uart_dma.rx_timer, jiffies +
- usecs_to_jiffies(up->uart_dma.rx_timeout));
+ usecs_to_jiffies(up->uart_dma.rx_poll_rate));
up->uart_dma.rx_dma_used = true;
return ret;
}
@@ -1364,6 +1364,7 @@ static int serial_omap_probe(struct platform_device *pdev)
up->use_dma = 1;
up->uart_dma.rx_buf_size = omap_up_info->dma_rx_buf_size;
up->uart_dma.rx_timeout = omap_up_info->dma_rx_timeout;
+ up->uart_dma.rx_poll_rate = omap_up_info->dma_rx_poll_rate;
spin_lock_init(&(up->uart_dma.tx_lock));
spin_lock_init(&(up->uart_dma.rx_lock));
up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
--
1.7.4.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox