From 8dd690482a5c78ac11bb734b8518380b5771b0bb Mon Sep 17 00:00:00 2001 From: pdabade Date: Sat, 21 Dec 2013 22:17:53 +0530 Subject: arch: arm: mach-tegra: Make benign warning as info A request to set brightness to zero is valid irrespective of what previous brightness of backlight was. A request of zero brightness disables PWM; so a re-request can be made to disable a already disabled PWM. bug 1416333 Change-Id: Ia5f29911456eb5d76fa303bb9070a6f04ec97002 Signed-off-by: Pankaj Dabade Reviewed-on: http://git-master/r/348366 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Laxman Dewangan Reviewed-by: Matthew Pedro --- arch/arm/mach-tegra/pwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-tegra/pwm.c b/arch/arm/mach-tegra/pwm.c index d5533c7d3c05..f2c43e994c9f 100644 --- a/arch/arm/mach-tegra/pwm.c +++ b/arch/arm/mach-tegra/pwm.c @@ -3,7 +3,7 @@ * * Tegra pulse-width-modulation controller driver * - * Copyright (c) 2010, NVIDIA Corporation. + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer * * This program is free software; you can redistribute it and/or modify @@ -131,7 +131,7 @@ void pwm_disable(struct pwm_device *pwm) clk_disable(pwm->clk); pwm->clk_enb = 0; } else - dev_warn(&pwm->pdev->dev, "%s called on disabled PWM\n", + dev_info(&pwm->pdev->dev, "%s called on disabled PWM\n", __func__); mutex_unlock(&pwm_lock); } -- cgit v1.2.3 From d633a68ac0c4758927bc436142c196421287d10a Mon Sep 17 00:00:00 2001 From: pdabade Date: Thu, 12 Dec 2013 16:09:30 +0530 Subject: video: tegra: fb: Update and synchronize dc window Update and synchronize DC window after enabling DC while unblanking. bug 1416339 Change-Id: I404004e1cbb3908cceade8aa033a660dc488d400 Signed-off-by: Pankaj Dabade Reviewed-on: http://git-master/r/344778 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Bibek Basu Reviewed-by: Jong Kim Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/video/tegra/fb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index f69048f62cc2..e5ddfd503301 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -6,7 +6,7 @@ * Colin Cross * Travis Geiselbrecht * - * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -284,6 +284,8 @@ static int tegra_fb_blank(int blank, struct fb_info *info) dev_dbg(&tegra_fb->ndev->dev, "unblank\n"); tegra_fb->win->flags = TEGRA_WIN_FLAG_ENABLED; tegra_dc_enable(tegra_fb->win->dc); + tegra_dc_update_windows(&tegra_fb->win, 1); + tegra_dc_sync_windows(&tegra_fb->win, 1); return 0; case FB_BLANK_NORMAL: -- cgit v1.2.3 From 95c7d5a8c9fc4c4d6326d608723237ed197b893a Mon Sep 17 00:00:00 2001 From: pdabade Date: Tue, 10 Dec 2013 10:42:01 +0530 Subject: video: tegra: hdmi: validate variable screeninfo verify variable screeninfo by checking xres and yres before validating aspect ratio. bug 1417318 Change-Id: I473f3e2f30888c053ca53559e33355f216d2a8d3 Signed-off-by: Pankaj Dabade Reviewed-on: http://git-master/r/340236 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Jong Kim Reviewed-by: Jon Mayo Reviewed-by: Matthew Pedro --- drivers/video/tegra/dc/hdmi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/dc/hdmi.c b/drivers/video/tegra/dc/hdmi.c index 55d9163d4faf..f3fcf2e2ee09 100644 --- a/drivers/video/tegra/dc/hdmi.c +++ b/drivers/video/tegra/dc/hdmi.c @@ -4,7 +4,7 @@ * Copyright (C) 2010 Google, Inc. * Author: Erik Gilling * - * Copyright (c) 2010-2012, NVIDIA CORPORATION, All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION, All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -1259,7 +1259,8 @@ static bool tegra_dc_hdmi_valid_asp_ratio(const struct tegra_dc *dc, int s_aspratio = 0; /* To check the aspect upto two decimal digits, calculate in % */ - m_aspratio = (mode->xres*100 / mode->yres); + if (mode->yres) + m_aspratio = (mode->xres*100 / mode->yres); if ((m_aspratio < TEGRA_DC_HDMI_MIN_ASPECT_RATIO_PERCENT) || (m_aspratio > TEGRA_DC_HDMI_MAX_ASPECT_RATIO_PERCENT)) -- cgit v1.2.3 From d283f029d9b971f93f6f4b0e62d3cacb2571a204 Mon Sep 17 00:00:00 2001 From: Rahool Paliwal Date: Mon, 9 Dec 2013 18:07:05 +0530 Subject: media: nvmap: Allow access to videobuf2-dma-nvmap Allow the "user" nvmap client to access the nvmap memory handle of "videobuf2-dma-nvmap" client. Bug 1421388 Change-Id: Id7a28c06214508d807098a6b258345023192a601 Signed-off-by: Rahool Paliwal Reviewed-on: http://git-master/r/344620 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Matthew Pedro --- drivers/video/tegra/nvmap/nvmap_handle.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index 4b7760b22190..1c5e61ccd45d 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -3,7 +3,7 @@ * * Handle allocation and freeing routines for nvmap * - * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -988,6 +988,15 @@ struct nvmap_handle_ref *nvmap_duplicate_handle_id(struct nvmap_client *client, BUG_ON(!client || client->dev != nvmap_dev); /* on success, the reference count for the handle should be * incremented, so the success paths will not call nvmap_handle_put */ + + /* Allow the handle to be accessed by other (non-owner) + clients only if the owner is "videobuf2-dma-nvmap + which is a V4L2 capture kernel module. This handle can + be accessed by the "user" client for rendering/encoding */ + if (!strcmp(((struct nvmap_handle *)id)->owner->name, + "videobuf2-dma-nvmap")) + client = ((struct nvmap_handle *)id)->owner; + h = nvmap_validate_get(client, id); if (!h) { -- cgit v1.2.3 From 3f41b064189a7ee9d2d04b12ad3d15c416366f5d Mon Sep 17 00:00:00 2001 From: Eric Brower Date: Mon, 4 Nov 2013 11:27:55 -0800 Subject: ARM: tegra: pcie: Disable PCIe GEN2 capability Disable PCIe Gen2 capability. This is not supported on Tegra 20/30 SOCs. Bug 1399592 Change-Id: I696a982b93d2e56a3b24379d38e51a5e93e4b7a1 Signed-off-by: Eric Brower Reviewed-on: http://git-master/r/326195 Reviewed-by: Matthew Pedro --- arch/arm/mach-tegra/pcie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index 04d3a5db3f7e..dd6da2a7d965 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -825,7 +825,7 @@ static void tegra_pcie_enable_controller(void) afi_writel(val, AFI_PCIE_CONFIG); /* Disable Gen 2 capability of PCIE */ - val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS; + val = afi_readl(AFI_FUSE) | AFI_FUSE_PCIE_T0_GEN2_DIS; afi_writel(val, AFI_FUSE); /* Initialze internal PHY, enable up to 16 PCIE lanes */ -- cgit v1.2.3 From 8e435e6e4d7155eeffc1fe60ac98b7dab83ed4ec Mon Sep 17 00:00:00 2001 From: Jeetesh Burman Date: Tue, 17 Dec 2013 17:32:59 +0530 Subject: tegra_wdt: support default watchdog api Reworked driver in order to properly support default watchdog api such as triggering by writing a character and disable by sending a magic character. Renamed ENABLE_ON_PROBE to ENABLE_HEARTBEAT which triggers the watchdog using the interrupt service routine. Original patch: http://git.toradex.com/gitweb/linux-toradex.git/commitdiff/5da592b805718b4f33897d642f577b1e6511bc2b Bug 1402031 Change-Id: I33ef556dac6d6717cadc00f8937437b925dc2ca3 Signed-off-by: Stefan Agner Signed-off-by: Jeetesh Burman Reviewed-on: http://git-master/r/346477 Reviewed-by: Varun Wadekar Reviewed-by: Matthew Pedro --- drivers/watchdog/Kconfig | 15 ++-- drivers/watchdog/tegra_wdt.c | 201 ++++++++++++++++++++++++++++++------------- 2 files changed, 150 insertions(+), 66 deletions(-) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9a94f7e093dd..8d41441b05ed 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -217,17 +217,20 @@ config TEGRA_WATCHDOG depends on ARCH_TEGRA help Say Y here to include support for the watchdog timer - embedded in NVIDIA Tegra SoCs. + embedded in NVIDIA Tegra SoCs. The default timeout + is set to 60 seconds. To compile this driver as a module, choose M here: the module will be called tegra_wdt. -config TEGRA_WATCHDOG_ENABLE_ON_PROBE - tristate "Turn on Tegra watchdog at system start up" - depends on ARCH_TEGRA && TEGRA_WATCHDOG +config TEGRA_WATCHDOG_ENABLE_HEARTBEAT + bool "Use the first Tegra watchdog as kernel heartbeats" + depends on TEGRA_WATCHDOG + default n help - Say Y here to enable the tegra watchdog at driver - probe time, rather than when the device is opened. + Say Y here to enable the first tegra watchdog at driver + probe time. The kernel will reload the watchdog by + itself in an interrupt handler. config EP93XX_WATCHDOG tristate "EP93xx Watchdog" diff --git a/drivers/watchdog/tegra_wdt.c b/drivers/watchdog/tegra_wdt.c index 1bcd726ebbd6..3e58a984d9c2 100644 --- a/drivers/watchdog/tegra_wdt.c +++ b/drivers/watchdog/tegra_wdt.c @@ -3,7 +3,8 @@ * * watchdog driver for NVIDIA tegra internal watchdog * - * Copyright (c) 2012, NVIDIA Corporation. + * Copyright (c) 2012-2014, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2013, Toradex AG * * based on drivers/watchdog/softdog.c and drivers/watchdog/omap_wdt.c * @@ -42,13 +43,33 @@ /* minimum and maximum watchdog trigger periods, in seconds */ #define MIN_WDT_PERIOD 5 #define MAX_WDT_PERIOD 1000 + /* Assign Timer 7 to Timer 10 for WDT0 to WDT3, respectively */ #define TMR_SRC_START 7 +/* + * For spinlock lockup detection to work, the heartbeat should be 2*lockup + * for cases where the spinlock disabled irqs. + * Must be between MIN_WDT_PERIOD and MAX_WDT_PERIOD + */ +#define WDT_DEFAULT_TIME 60 + +static int heartbeat = WDT_DEFAULT_TIME; +static bool nowayout = WATCHDOG_NOWAYOUT; + +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat period in seconds (default=" + __MODULE_STRING(WDT_DEFAULT_TIME)); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +#endif enum tegra_wdt_status { WDT_DISABLED = 1 << 0, WDT_ENABLED = 1 << 1, - WDT_ENABLED_AT_PROBE = 1 << 2, + WDT_KERNEL_HEARTBEAT = 1 << 2, }; struct tegra_wdt { @@ -61,18 +82,15 @@ struct tegra_wdt { void __iomem *wdt_source; void __iomem *wdt_timer; void __iomem *int_base; - int irq; int tmrsrc; int timeout; int status; + int way_out_ok; + struct tasklet_struct tasklet; + int irq; + int irq_counter; }; -/* - * For spinlock lockup detection to work, the heartbeat should be 2*lockup - * for cases where the spinlock disabled irqs. - */ -static int heartbeat = 120; /* must be greater than MIN_WDT_PERIOD and lower than MAX_WDT_PERIOD */ - #if defined(CONFIG_ARCH_TEGRA_2x_SOC) #define TIMER_PTV 0x0 @@ -107,6 +125,16 @@ static void tegra_wdt_disable(struct tegra_wdt *wdt) static inline void tegra_wdt_ping(struct tegra_wdt *wdt) { + /* Reset timer */ + tegra_wdt_enable(wdt); + + /* Reenable IRQ in case an interrupt already happend */ + if (wdt->irq_counter) { + writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR); + wdt->irq_counter = 0; + enable_irq(wdt->irq); + } + return; } @@ -114,9 +142,30 @@ static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id) { struct tegra_wdt *wdt = dev_id; - writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR); + wdt->irq_counter++; + + if (wdt->status & WDT_KERNEL_HEARTBEAT) { + tegra_wdt_ping(wdt); + } else { + /* If not in heartbeat mode, disable IRQs to avoid IRQ storm + * We don't acknowledge the interrupt here since the user + * did not reload the timer in time. Upon next interrupt + * the system will reset... + */ + tasklet_schedule(&wdt->tasklet); + disable_irq_nosync(irq); + } + return IRQ_HANDLED; } + +static void tegra_wdt_do_tasklet(unsigned long data) +{ + struct tegra_wdt *wdt = (struct tegra_wdt *)data; + dev_info(wdt->miscdev.parent, "Watchdog interrupt received, system " + "will reset soon if no ping arrives\n"); +} + #elif defined(CONFIG_ARCH_TEGRA_3x_SOC) #define TIMER_PTV 0 @@ -132,6 +181,7 @@ static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id) #define WDT_CFG_PMC2CAR_RST_EN (1 << 15) #define WDT_STATUS (4) #define WDT_INTR_STAT (1 << 1) + #define WDT_STATUS_EXPIR_COUNTER (3 << 12) #define WDT_CMD (8) #define WDT_CMD_START_COUNTER (1 << 0) #define WDT_CMD_DISABLE_COUNTER (1 << 1) @@ -169,19 +219,21 @@ static void tegra_wdt_enable(struct tegra_wdt *wdt) val |= (TIMER_EN | TIMER_PERIODIC); writel(val, wdt->wdt_timer + TIMER_PTV); - /* Interrupt handler is not required for user space - * WDT accesses, since the caller is responsible to ping the - * WDT to reset the counter before expiration, through ioctls. + writel(WDT_CMD_START_COUNTER, wdt->wdt_source + WDT_CMD); + + /* Interrupt handler is not required for user space since + * a warning in a fourth of time don't make sense. Then + * the interrupt line is also shared, so it can't be disabled + * if one watchdog is about to expire... (interrupt storm) * SYS_RST_EN doesnt work as there is no external reset * from Tegra. */ - val = wdt->tmrsrc | WDT_CFG_PERIOD | /*WDT_CFG_INT_EN |*/ + val = wdt->tmrsrc | WDT_CFG_PERIOD | /* WDT_CFG_INT_EN | */ /*WDT_CFG_SYS_RST_EN |*/ WDT_CFG_PMC2CAR_RST_EN; #ifdef CONFIG_TEGRA_FIQ_DEBUGGER val |= WDT_CFG_FIQ_INT_EN; #endif writel(val, wdt->wdt_source + WDT_CFG); - writel(WDT_CMD_START_COUNTER, wdt->wdt_source + WDT_CMD); } static void tegra_wdt_disable(struct tegra_wdt *wdt) @@ -192,17 +244,29 @@ static void tegra_wdt_disable(struct tegra_wdt *wdt) writel(0, wdt->wdt_timer + TIMER_PTV); } +static void tegra_wdt_interrupt_instance(struct tegra_wdt *wdt) +{ + WARN_ON_ONCE(!(wdt->status & WDT_KERNEL_HEARTBEAT)); + + if (wdt->status & WDT_KERNEL_HEARTBEAT) { + tegra_wdt_ping(wdt); + } +} + static irqreturn_t tegra_wdt_interrupt(int irq, void *dev_id) { + struct tegra_wdt *wdt = NULL; unsigned i, status; for (i = 0; i < MAX_NR_CPU_WDT; i++) { - if (tegra_wdt[i] == NULL) + wdt = tegra_wdt[i]; + if (wdt == NULL) continue; - status = readl(tegra_wdt[i]->wdt_source + WDT_STATUS); - if ((tegra_wdt[i]->status & WDT_ENABLED) && - (status & WDT_INTR_STAT)) - tegra_wdt_ping(tegra_wdt[i]); + status = readl(wdt->wdt_source + WDT_STATUS); + if ((wdt->status & WDT_ENABLED) && + (status & WDT_INTR_STAT)) { + tegra_wdt_interrupt_instance(wdt); + } } return IRQ_HANDLED; @@ -228,6 +292,9 @@ static int tegra_wdt_open(struct inode *inode, struct file *file) if (test_and_set_bit(1, &wdt->users)) return -EBUSY; + /* Reset no way out, we need a new magic again */ + wdt->way_out_ok = 0; + wdt->status |= WDT_ENABLED; wdt->timeout = heartbeat; tegra_wdt_enable(wdt); @@ -239,13 +306,19 @@ static int tegra_wdt_release(struct inode *inode, struct file *file) { struct tegra_wdt *wdt = file->private_data; - if (wdt->status == WDT_ENABLED) { -#ifndef CONFIG_WATCHDOG_NOWAYOUT - tegra_wdt_disable(wdt); - wdt->status = WDT_DISABLED; -#endif + if (wdt->status & WDT_ENABLED && !nowayout) { + if (wdt->way_out_ok) { + tegra_wdt_disable(wdt); + wdt->status = WDT_DISABLED; + } else { + dev_info(wdt->miscdev.parent, "No Magic Close " + "received, watchdog not disabled!\n"); + } + } else if (nowayout) { + dev_info(wdt->miscdev.parent, "No way out is " + "enabled, watchdog not disabled!\n"); } - wdt->users = 0; + clear_bit(1, &wdt->users); return 0; } @@ -288,11 +361,10 @@ static long tegra_wdt_ioctl(struct file *file, unsigned int cmd, return put_user(wdt->timeout, (int __user *)arg); case WDIOC_SETOPTIONS: -#ifndef CONFIG_WATCHDOG_NOWAYOUT if (get_user(option, (int __user *)arg)) return -EFAULT; spin_lock(&lock); - if (option & WDIOS_DISABLECARD) { + if (option & WDIOS_DISABLECARD && !nowayout) { wdt->status &= ~WDT_ENABLED; wdt->status |= WDT_DISABLED; tegra_wdt_disable(wdt); @@ -306,9 +378,6 @@ static long tegra_wdt_ioctl(struct file *file, unsigned int cmd, } spin_unlock(&lock); return 0; -#else - return -EINVAL; -#endif } return -ENOTTY; } @@ -316,6 +385,19 @@ static long tegra_wdt_ioctl(struct file *file, unsigned int cmd, static ssize_t tegra_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { + struct tegra_wdt *wdt = file->private_data; + + /* check if way-out char was written as last data */ + char c; + if (len) { + tegra_wdt_ping(wdt); + + if (get_user(c, data + len - 1)) + return -EFAULT; + else + wdt->way_out_ok = (('V' == c) ? 1 : 0); + } + return len; } @@ -333,8 +415,14 @@ static int tegra_wdt_probe(struct platform_device *pdev) struct resource *res_src, *res_wdt, *res_irq; struct resource *res_int_base = NULL; struct tegra_wdt *wdt; - u32 src; int ret = 0; +#ifdef CONFIG_TEGRA_WATCHDOG_ENABLE_HEARTBEAT +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + int is_heartbeat_wdt = 1; +#else + int is_heartbeat_wdt = !(pdev->id); +#endif +#endif if (pdev->id < -1 && pdev->id > 3) { dev_err(&pdev->dev, "only IDs 3:0 supported\n"); @@ -369,7 +457,6 @@ static int tegra_wdt_probe(struct platform_device *pdev) return -ENOMEM; } - wdt->irq = -1; wdt->miscdev.parent = &pdev->dev; if (pdev->id == -1) { wdt->miscdev.minor = WATCHDOG_MINOR; @@ -410,12 +497,17 @@ static int tegra_wdt_probe(struct platform_device *pdev) goto fail; } - src = readl(wdt->wdt_source); - if (src & BIT(12)) +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + /* Watchdog of Tegra 3 are not at the reset controller regs */ + if (readl(wdt->wdt_source) & BIT(12)) dev_info(&pdev->dev, "last reset due to watchdog timeout\n"); +#endif tegra_wdt_disable(wdt); writel(TIMER_PCR_INTR, wdt->wdt_timer + TIMER_PCR); +#ifndef CONFIG_ARCH_TEGRA_2x_SOC + writel(WDT_CMD_START_COUNTER, wdt->wdt_source + WDT_CMD); +#endif if (res_irq != NULL) { #ifdef CONFIG_TEGRA_FIQ_DEBUGGER @@ -436,6 +528,7 @@ static int tegra_wdt_probe(struct platform_device *pdev) goto fail; tegra_wdt_int_priority(wdt); #endif + wdt->irq = -1; ret = request_irq(res_irq->start, tegra_wdt_interrupt, IRQF_DISABLED, dev_name(&pdev->dev), wdt); if (ret) { @@ -464,24 +557,26 @@ static int tegra_wdt_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, wdt); +#ifdef CONFIG_ARCH_TEGRA_2x_SOC + tasklet_init(&wdt->tasklet, tegra_wdt_do_tasklet, (unsigned long)wdt); +#endif -#ifndef CONFIG_ARCH_TEGRA_2x_SOC -#ifdef CONFIG_TEGRA_WATCHDOG_ENABLE_ON_PROBE - /* Init and enable watchdog on WDT0 with timer 8 during probe */ - if (!(pdev->id)) { - u32 val = 0; - wdt->status = WDT_ENABLED | WDT_ENABLED_AT_PROBE; +#ifdef CONFIG_TEGRA_WATCHDOG_ENABLE_HEARTBEAT + /* Enable first watchdog during probe */ + if (is_heartbeat_wdt) { + wdt->status = WDT_ENABLED | WDT_KERNEL_HEARTBEAT; wdt->timeout = heartbeat; + set_bit(1, &wdt->users); tegra_wdt_enable(wdt); - val = readl(wdt->wdt_source + WDT_CFG); - val |= WDT_CFG_INT_EN; - writel(val, wdt->wdt_source + WDT_CFG); - pr_info("WDT heartbeat enabled on probe\n"); + pr_info("WDT kernel heartbeat enabled on probe\n"); } #endif + +#ifndef CONFIG_ARCH_TEGRA_2x_SOC tegra_wdt[pdev->id] = wdt; #endif - pr_info("%s done\n", __func__); + + dev_info(&pdev->dev, "%s done\n", __func__); return 0; fail: if (wdt->irq != -1) @@ -543,16 +638,6 @@ static int tegra_wdt_resume(struct platform_device *pdev) if (wdt->status & WDT_ENABLED) tegra_wdt_enable(wdt); -#ifndef CONFIG_ARCH_TEGRA_2x_SOC - /* Enable interrupt for WDT3 heartbeat watchdog */ - if (wdt->status & WDT_ENABLED_AT_PROBE) { - u32 val = 0; - val = readl(wdt->wdt_source + WDT_CFG); - val |= WDT_CFG_INT_EN; - writel(val, wdt->wdt_source + WDT_CFG); - pr_info("WDT heartbeat enabled on probe\n"); - } -#endif return 0; } #endif @@ -586,10 +671,6 @@ module_exit(tegra_wdt_exit); MODULE_AUTHOR("NVIDIA Corporation"); MODULE_DESCRIPTION("Tegra Watchdog Driver"); -module_param(heartbeat, int, 0); -MODULE_PARM_DESC(heartbeat, - "Watchdog heartbeat period in seconds"); - MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS("platform:tegra_wdt"); -- cgit v1.2.3 From 61a7d245ef0bd5d299de2219361799a824ecc18d Mon Sep 17 00:00:00 2001 From: Jeetesh Burman Date: Mon, 16 Dec 2013 17:47:43 +0530 Subject: mmc: sdhci: add quirk for lack of 1.8v support The OLPC XO-1.75 laptop includes a SDHCI controller which is 1.8v capable, and it truthfully reports so in its capabilities. This alternate voltage is used for driving new "UHS-I" SD cards at their full speed. However, what the controller doesn't know is that the motherboard physically doesn't have a 1.8v supply available. Add a quirk so that systems such as this one can override disable 1.8v support, adding support for UHS-I cards (by running them at 3.3v). This avoids a problem where the system would first try to run the card at 1.8v, fail, and then not be able to fully reset the card to retry at the normal 3.3v voltage. This is more appropriate than using the MISSING_CAPS quirk, which is intended for cases where the SDHCI controller is actually lying about its capabilities, and would force us to somehow override both caps words from another source. Bug 1402031 Change-Id: I7ca070a13241e6403eb2e243ebbc441a311110bc Signed-off-by: Daniel Drake Reviewed-by: Philip Rakity Signed-off-by: Chris Ball Signed-off-by: Jeetesh Burman Reviewed-on: http://git-master/r/346323 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/mmc/host/sdhci.c | 10 +++++++--- include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3a440dcf0f24..a1c7484371b9 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2658,9 +2658,13 @@ int sdhci_add_host(struct sdhci_host *host) mmc_card_is_removable(mmc) && !(host->ops->get_cd)) mmc->caps |= MMC_CAP_NEEDS_POLL; - /* UHS-I mode(s) supported by the host controller. */ - if (host->version >= SDHCI_SPEC_300) - mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; + if (host->quirks & SDHCI_QUIRK2_NO_1_8_V) + caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50); + else + /* UHS-I mode(s) supported by the host controller. */ + if (host->version >= SDHCI_SPEC_300) + mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; /* SDR104 supports also implies SDR50 support */ if (caps[1] & SDHCI_SUPPORT_SDR104) diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 5ee48390decc..db86304e1c28 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h @@ -93,6 +93,8 @@ struct sdhci_host { #define SDHCI_QUIRK_NON_STANDARD_TUNING (1ULL<<33) /* Controller doesn't calculate max_discard_to */ #define SDHCI_QUIRK_NO_CALC_MAX_DISCARD_TO (1ULL<<34) +/* The system physically doesn't support 1.8v, even if the host does */ +#define SDHCI_QUIRK2_NO_1_8_V (1ULL<<35) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ -- cgit v1.2.3 From c682f8ce0abb3fccc8a86f478aeb1479938e91c6 Mon Sep 17 00:00:00 2001 From: Al Cooper Date: Fri, 16 Mar 2012 15:54:17 -0400 Subject: mmc: Prevent 1.8V switch for SD hosts that don't support UHS modes. The driver should not try to switch to 1.8V when the SD 3.0 host controller does not have any UHS capabilities bits set (SDR50, DDR50 or SDR104). See page 72 of "SD Specifications Part A2 SD Host Controller Simplified Specification Version 3.00" under "1.8V Signaling Enable". Instead of setting SDR12 and SDR25 in the host capabilities data structure for all V3.0 host controllers, only set them if SDR104, SDR50 or DDR50 is set in the host capabilities register. This will prevent the switch to 1.8V later. Bug 1402031 Acked-by: Arindam Nath Acked-by: Philip Rakity Acked-by: Girish K S Signed-off-by: Al Cooper Signed-off-by: Jeetesh Burman Signed-off-by: Chris Ball Change-Id: I61d3fdb96fce223649075b6c063a3dd227aef062 Reviewed-on: http://git-master/r/365451 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/mmc/host/sdhci.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a1c7484371b9..ea79a8d62d29 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2661,10 +2661,11 @@ int sdhci_add_host(struct sdhci_host *host) if (host->quirks & SDHCI_QUIRK2_NO_1_8_V) caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); - else - /* UHS-I mode(s) supported by the host controller. */ - if (host->version >= SDHCI_SPEC_300) - mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; + + /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ + if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | + SDHCI_SUPPORT_DDR50)) + mmc->caps |= MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; /* SDR104 supports also implies SDR50 support */ if (caps[1] & SDHCI_SUPPORT_SDR104) -- cgit v1.2.3 From 141076cd925f093adff5971ae8970ae339007ae4 Mon Sep 17 00:00:00 2001 From: Alex Feinman Date: Fri, 16 May 2014 15:55:05 +0100 Subject: Added continuous mode capture support Signed-off-by: Bryan Wu Change-Id: I67c50ff86b53a6c1001d2b688251dc55bd2eff55 Reviewed-on: http://git-master/r/419070 Reviewed-by: Winnie Hsu --- arch/arm/mach-tegra/board-cardhu-sensors.c | 13 ++++-- drivers/media/video/tegra_v4l2_camera.c | 63 ++++++++++++++++++++++++++---- include/media/tegra_v4l2_camera.h | 4 +- 3 files changed, 67 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-tegra/board-cardhu-sensors.c b/arch/arm/mach-tegra/board-cardhu-sensors.c index af66e1f571c6..3c259ebcdba1 100644 --- a/arch/arm/mach-tegra/board-cardhu-sensors.c +++ b/arch/arm/mach-tegra/board-cardhu-sensors.c @@ -115,6 +115,8 @@ static struct tegra_camera_platform_data cardhu_ov5640_camera_platform_data = { .port = TEGRA_CAMERA_PORT_CSI_B, .lanes = 2, .continuous_clk = 0, + .continuous_capture = 1, + .vi_freq = 24000000, }; static struct soc_camera_link ov5640_iclink = { @@ -667,7 +669,7 @@ static const struct i2c_board_info cardhu_i2c3_board_info[] = { }, }; - +#if !defined(CONFIG_SOC_CAMERA) static struct nvc_gpio_pdata sh532u_gpio_pdata[] = { { SH532U_GPIO_RESET, TEGRA_GPIO_PBB0, false, 0, }, }; @@ -862,6 +864,7 @@ static struct i2c_board_info cardhu_i2c8_board_info[] = { }, #endif }; +#endif static int nct_get_temp(void *_data, long *temp) { @@ -1190,14 +1193,15 @@ int __init cardhu_sensors_init(void) cardhu_camera_init(); cam_tca6416_init(); + i2c_register_board_info(2, cardhu_i2c3_board_info, + ARRAY_SIZE(cardhu_i2c3_board_info)); + +#if !defined(CONFIG_SOC_CAMERA) if (board_info.board_id != BOARD_PM315) { - i2c_register_board_info(2, cardhu_i2c3_board_info, - ARRAY_SIZE(cardhu_i2c3_board_info)); i2c_register_board_info(2, cardhu_i2c_board_info_tps61050, ARRAY_SIZE(cardhu_i2c_board_info_tps61050)); } - #ifdef CONFIG_VIDEO_OV14810 /* This is disabled by default; To enable this change Kconfig; * there should be some way to detect dynamically which board @@ -1229,6 +1233,7 @@ int __init cardhu_sensors_init(void) i2c_register_board_info(PCA954x_I2C_BUS2, cardhu_i2c8_board_info, ARRAY_SIZE(cardhu_i2c8_board_info)); +#endif #endif pmu_tca6416_init(); diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index 8f71d1702537..237441f9ee31 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -297,9 +297,12 @@ struct tegra_camera_dev { struct work_struct work; struct mutex work_mutex; + struct soc_camera_device *icd; + u32 syncpt_vi; u32 syncpt_csi_a; u32 syncpt_csi_b; + int capturing; /* Debug */ int num_frames; @@ -724,6 +727,9 @@ static int tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) enum v4l2_mbus_pixelcode input_code = current_fmt->code; u32 hdr, input_control = 0x0; + if ( !pcdev->icd ) + pcdev->icd = icd; + switch (input_code) { case V4L2_MBUS_FMT_UYVY8_2X8: input_control |= 0x2 << 8; @@ -765,8 +771,11 @@ static int tegra_camera_capture_setup(struct tegra_camera_dev *pcdev) /* Set up raise-on-edge, so we get an interrupt on end of frame. */ TC_VI_REG_WT(pcdev, TEGRA_VI_VI_RAISE, 0x00000001); - /* Cleanup registers */ - tegra_camera_capture_clean(pcdev); + if ( !pdata->continuous_capture || !pcdev->capturing ) { + + /* Cleanup registers */ + tegra_camera_capture_clean(pcdev); + } /* Setup registers for CSI-A, CSI-B and VIP inputs */ if (port == TEGRA_CAMERA_PORT_CSI_A) @@ -850,7 +859,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, if (port == TEGRA_CAMERA_PORT_CSI_A) { pcdev->syncpt_csi_a++; TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, - 0x0000f005); + pdata->continuous_capture?0x0000f001 :0x0000f005); + err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, TEGRA_VI_SYNCPT_CSI_A, pcdev->syncpt_csi_a, @@ -859,7 +869,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, } else if (port == TEGRA_CAMERA_PORT_CSI_B) { pcdev->syncpt_csi_b++; TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, - 0x0000f005); + pdata->continuous_capture? 0x0000f001: 0x0000f005); + err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, TEGRA_VI_SYNCPT_CSI_B, pcdev->syncpt_csi_b, @@ -876,6 +887,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, NULL); } + pcdev->capturing = 1; + if (!err) return 0; @@ -1005,6 +1018,20 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev) static void tegra_camera_deactivate(struct tegra_camera_dev *pcdev) { + struct soc_camera_device *icd = pcdev->icd; + if ( icd ) { + struct tegra_camera_platform_data *pdata = icd->link->priv; + + if ( pdata->continuous_capture ) { + pcdev->capturing = 0; + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, + 0x0000f003); + TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, + 0x0000f003); + usleep_range(20000, 21000); + } + } + /* Turn off relevant clocks. */ clk_disable(pcdev->clk_vi); clk_disable(pcdev->clk_vi_sensor); @@ -1192,6 +1219,8 @@ static void tegra_camera_work(struct work_struct *work) struct tegra_camera_dev *pcdev = container_of(work, struct tegra_camera_dev, work); struct tegra_buffer *buf; + struct soc_camera_device *icd; + struct tegra_camera_platform_data *pdata; while (1) { mutex_lock(&pcdev->work_mutex); @@ -1209,10 +1238,15 @@ static void tegra_camera_work(struct work_struct *work) pcdev->active = &buf->vb; spin_unlock_irq(&pcdev->videobuf_queue_lock); - tegra_camera_capture_setup(pcdev); - if (!pcdev->cal_done) { - tegra_camera_csi_pad_calibration(pcdev); - pcdev->cal_done = 1; + icd = buf->icd; + pdata = icd->link->priv; + + if ( !pdata->continuous_capture || !pcdev->capturing ) { + tegra_camera_capture_setup(pcdev); + if (!pcdev->cal_done) { + tegra_camera_csi_pad_calibration(pcdev); + pcdev->cal_done = 1; + } } tegra_camera_capture_frame(pcdev); @@ -1670,6 +1704,18 @@ static int tegra_camera_set_fmt(struct soc_camera_device *icd, return ret; } +static int tegra_camera_enum_fsizes(struct soc_camera_device *icd, struct v4l2_frmsizeenum * fsize) { + struct v4l2_subdev *sd = soc_camera_to_subdev(icd); + int ret; + + //printk("%s (%d)\n", __func__, fsize->index); + ret = v4l2_subdev_call(sd, video, enum_framesizes, fsize); + if (IS_ERR_VALUE(ret)) + return ret; + + return 0; +} + static int tegra_camera_try_fmt(struct soc_camera_device *icd, struct v4l2_format *f) { @@ -1770,6 +1816,7 @@ static struct soc_camera_host_ops tegra_soc_camera_host_ops = { .reqbufs = tegra_camera_reqbufs, .poll = tegra_camera_poll, .querycap = tegra_camera_querycap, + .enum_fsizes = tegra_camera_enum_fsizes, }; static int __devinit tegra_camera_probe(struct nvhost_device *ndev, diff --git a/include/media/tegra_v4l2_camera.h b/include/media/tegra_v4l2_camera.h index f6390b6e5609..aab1cde96d24 100644 --- a/include/media/tegra_v4l2_camera.h +++ b/include/media/tegra_v4l2_camera.h @@ -33,8 +33,10 @@ struct tegra_camera_platform_data { bool flip_h; bool flip_v; enum tegra_camera_port port; - int lanes; /* For CSI port only */ + int lanes; /* For CSI port only */ bool continuous_clk; /* For CSI port only */ + bool continuous_capture; /* CSI only */ + int vi_freq; }; #endif /* _TEGRA_CAMERA_H_ */ -- cgit v1.2.3 From a7feb27765cf32d7da33659771fd0b2571c87b8d Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 4 Jun 2014 11:16:32 -0700 Subject: media: video: fix clock settings for Tegra VI driver - remove reduntant emc clock rate set which is controlled by DVFS - VI's maxim working clock freq is 300MHz - Change VI clock divider from an integer to a decimal, so the maxim VI clock on Cardhu should be 272MHz (PLL_P is 408MHz and divider is 1.5) Bug 1478352 Change-Id: I4028ed8531d92300d131befb53a4c9dc9f90930d Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/419071 Reviewed-by: Winnie Hsu Tested-by: Winnie Hsu --- arch/arm/mach-tegra/tegra3_clocks.c | 2 +- drivers/media/video/tegra_v4l2_camera.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-tegra/tegra3_clocks.c b/arch/arm/mach-tegra/tegra3_clocks.c index 0bc60869a3d0..e9d29d4ce758 100644 --- a/arch/arm/mach-tegra/tegra3_clocks.c +++ b/arch/arm/mach-tegra/tegra3_clocks.c @@ -4369,7 +4369,7 @@ struct clk tegra_list_clks[] = { PERIPH_CLK("uartc_dbg", "serial8250.0", "uartc", 55, 0x1a0, 900000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), PERIPH_CLK("uartd_dbg", "serial8250.0", "uartd", 65, 0x1c0, 900000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), PERIPH_CLK("uarte_dbg", "serial8250.0", "uarte", 66, 0x1c4, 900000000, mux_pllp_clkm, MUX | DIV_U151 | DIV_U151_UART | PERIPH_ON_APB), - PERIPH_CLK_EX("vi", "tegra_camera", "vi", 20, 0x148, 470000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT, &tegra_vi_clk_ops), + PERIPH_CLK_EX("vi", "tegra_camera", "vi", 20, 0x148, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71, &tegra_vi_clk_ops), PERIPH_CLK("vi_sensor", "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 600000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET), PERIPH_CLK("3d2", "3d2", NULL, 98, 0x3b0, 600000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET), diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index 237441f9ee31..8834e27afcee 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -1000,7 +1000,7 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev) tegra_unpowergate_partition(TEGRA_POWERGATE_VENC); /* Turn on relevant clocks. */ - clk_set_rate(pcdev->clk_vi, 150000000); + clk_set_rate(pcdev->clk_vi, 300000000); clk_enable(pcdev->clk_vi); clk_set_rate(pcdev->clk_vi_sensor, 24000000); clk_enable(pcdev->clk_vi_sensor); @@ -1009,7 +1009,6 @@ static void tegra_camera_activate(struct tegra_camera_dev *pcdev) clk_enable(pcdev->clk_csus); clk_set_rate(pcdev->clk_sclk, 80000000); clk_enable(pcdev->clk_sclk); - clk_set_rate(pcdev->clk_sclk, 375000000); clk_enable(pcdev->clk_emc); /* Save current syncpt values. */ @@ -1887,7 +1886,7 @@ static int __devinit tegra_camera_probe(struct nvhost_device *ndev, goto exit_put_clk_sclk; } - clk_set_rate(pcdev->clk_vi, 150000000); + clk_set_rate(pcdev->clk_vi, 300000000); clk_set_rate(pcdev->clk_vi_sensor, 24000000); /* Get regulator pointer */ -- cgit v1.2.3 From 30f8d578556191ac90ca5d1ec4cba5f05cd690ce Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Tue, 8 Jul 2014 14:24:49 +0530 Subject: video: tegra: nvhost: validate nvmap_handle_ref nvhost_job_unpin should always get the nvmap_handle_ref from rb_entry after validating handle and presence in the tree. Bug 1478467 Change-Id: Ibf5f64a1a82fea8adbf7500bdb36b76357776448 Signed-off-by: Bibek Basu Reviewed-on: http://git-master/r/436076 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty Reviewed-by: Matthew Pedro --- drivers/video/tegra/host/nvhost_job.c | 9 ++++++--- drivers/video/tegra/host/nvmap.c | 11 ++++++++++- drivers/video/tegra/host/nvmap.h | 5 +++-- drivers/video/tegra/nvmap/nvmap.c | 16 +++++++++++++--- include/linux/nvmap.h | 5 ++++- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c index f0f7e64d4504..5587f51ea996 100644 --- a/drivers/video/tegra/host/nvhost_job.c +++ b/drivers/video/tegra/host/nvhost_job.c @@ -3,7 +3,7 @@ * * Tegra Graphics Host Job * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -30,6 +30,7 @@ #include "dev.h" #include "nvhost_memmgr.h" #include "chip_support.h" +#include "nvmap.h" /* Magic to use to fill freed handle slots */ #define BAD_MAGIC 0xdeadbeef @@ -327,8 +328,10 @@ void nvhost_job_unpin(struct nvhost_job *job) int i; for (i = 0; i < job->num_unpins; i++) { - mem_op().unpin(job->memmgr, job->unpins[i]); - mem_op().put(job->memmgr, job->unpins[i]); + struct mem_handle *handle; + handle = nvhost_nvmap_validate_ref(job->memmgr, job->unpins[i]); + mem_op().unpin(job->memmgr, handle); + mem_op().put(job->memmgr, handle); } memset(job->unpins, BAD_MAGIC, diff --git a/drivers/video/tegra/host/nvmap.c b/drivers/video/tegra/host/nvmap.c index fd82f40c59ff..b8361c4a1a36 100644 --- a/drivers/video/tegra/host/nvmap.c +++ b/drivers/video/tegra/host/nvmap.c @@ -3,7 +3,7 @@ * * Tegra Graphics Host Nvmap support * - * Copyright (c) 2012, NVIDIA Corporation. + * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -82,6 +82,15 @@ struct mem_handle *nvhost_nvmap_get(struct mem_mgr *mgr, u32 id) nvmap_duplicate_handle_id((struct nvmap_client *)mgr, id); } +struct mem_handle *nvhost_nvmap_validate_ref(struct mem_mgr *mgr, + struct mem_handle *handle) +{ + unsigned long ref; + ref = nvmap_validate_ref((struct nvmap_client *)mgr, + (struct nvmap_handle_ref *)handle); + return (struct mem_handle *)ref; +} + int nvhost_init_nvmap_support(struct nvhost_chip_support *chip) { chip->mem.alloc_mgr = nvhost_nvmap_alloc_mgr; diff --git a/drivers/video/tegra/host/nvmap.h b/drivers/video/tegra/host/nvmap.h index 90f64d44f434..25e3535ce544 100644 --- a/drivers/video/tegra/host/nvmap.h +++ b/drivers/video/tegra/host/nvmap.h @@ -3,7 +3,7 @@ * * Tegra Graphics Host nvmap memory manager * - * Copyright (c) 2010-2012, NVIDIA Corporation. + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -23,5 +23,6 @@ struct nvhost_chip_support; int nvhost_init_nvmap_support(struct nvhost_chip_support *op); - +struct mem_handle *nvhost_nvmap_validate_ref(struct mem_mgr *mgr, + struct mem_handle *handle); #endif diff --git a/drivers/video/tegra/nvmap/nvmap.c b/drivers/video/tegra/nvmap/nvmap.c index 19b821d41284..07463f78d4c0 100644 --- a/drivers/video/tegra/nvmap/nvmap.c +++ b/drivers/video/tegra/nvmap/nvmap.c @@ -3,7 +3,7 @@ * * Memory manager for Tegra GPU * - * Copyright (c) 2009-2012, NVIDIA Corporation. + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -366,7 +366,6 @@ phys_addr_t nvmap_pin(struct nvmap_client *client, h = nvmap_handle_get(ref->handle); if (WARN_ON(!h)) return -EINVAL; - atomic_inc(&ref->pin); if (WARN_ON(mutex_lock_interruptible(&client->share->pin_lock))) { @@ -384,7 +383,6 @@ phys_addr_t nvmap_pin(struct nvmap_client *client, map_iovmm_area(h); phys = handle_phys(h); } - return ret ?: phys; } @@ -618,3 +616,15 @@ int nvmap_mark_global(struct nvmap_client *client, struct nvmap_handle_ref *r) return 0; } + +unsigned long nvmap_validate_ref(struct nvmap_client *client, + struct nvmap_handle_ref *r) +{ + struct nvmap_handle_ref *ref; + unsigned long id = nvmap_ref_to_id(r); + + nvmap_ref_lock(client); + ref = _nvmap_validate_id_locked(client, id); + nvmap_ref_unlock(client); + return (unsigned long)ref; +} diff --git a/include/linux/nvmap.h b/include/linux/nvmap.h index 9cc978ec5a7f..c805f4c1dc07 100644 --- a/include/linux/nvmap.h +++ b/include/linux/nvmap.h @@ -3,7 +3,7 @@ * * structure declarations for nvmem and nvmap user-space ioctls * - * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2009-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -126,6 +126,9 @@ struct nvmap_handle_ref *nvmap_duplicate_handle_id(struct nvmap_client *client, int nvmap_mark_global(struct nvmap_client *client, struct nvmap_handle_ref *r); +unsigned long nvmap_validate_ref(struct nvmap_client *client, + struct nvmap_handle_ref *r); + struct nvmap_platform_carveout { const char *name; unsigned int usage_mask; -- cgit v1.2.3 From 8a370a3b55ee8750167174238ce316900409f558 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Wed, 30 Jul 2014 11:57:09 +0530 Subject: video: tegra: host: power module before access There could be race in refcount update leading to access of module registers without enabling the clock and power.This patch tries to catch such instances and enables power. Bug 1478467 Change-Id: Ia32da44bfcd7838e312815b6261ccadf4470a761 Signed-off-by: Bibek Basu Reviewed-on: http://git-master/r/448701 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Venkat Moganty Reviewed-by: Matthew Pedro --- drivers/video/tegra/host/nvhost_acm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c index 5bde55ad2ff5..fcedb5c1a2c8 100644 --- a/drivers/video/tegra/host/nvhost_acm.c +++ b/drivers/video/tegra/host/nvhost_acm.c @@ -3,7 +3,7 @@ * * Tegra Graphics Host Automatic Clock Management * - * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved. + * Copyright (c) 2010-2014, NVIDIA Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -219,8 +219,11 @@ void nvhost_module_busy(struct nvhost_device *dev) cancel_delayed_work(&dev->powerstate_down); dev->refcount++; - if (dev->refcount > 0 && !nvhost_module_powered(dev)) + if (unlikely(dev->refcount <= 0)) + pr_err("unbalanced refcount %d\n", dev->refcount); + if (!nvhost_module_powered(dev)) to_state_running_locked(dev); + mutex_unlock(&dev->lock); } -- cgit v1.2.3 From ec622e35c3d4862f07e3da676401e3feefa98ecf Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Fri, 20 Jun 2014 09:34:59 -0700 Subject: media: tegra_v4l2_camera: use FRAME_START syncpt Also use nvhost_syncpt_incr_max_ext(). Bug 1478352 Change-Id: Ib868bd2bd7a070e4c410e48bd51977ac45b7d477 Signed-off-by: Bryan Wu Reviewed-on: http://git-master/r/439471 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Bibek Basu Reviewed-by: Matthew Pedro Reviewed-by: Winnie Hsu --- drivers/media/video/tegra_v4l2_camera.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/tegra_v4l2_camera.c b/drivers/media/video/tegra_v4l2_camera.c index 8834e27afcee..c1fc8f8388a6 100644 --- a/drivers/media/video/tegra_v4l2_camera.c +++ b/drivers/media/video/tegra_v4l2_camera.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -487,7 +487,7 @@ static void tegra_camera_capture_setup_csi_a(struct tegra_camera_dev *pcdev, (pdata->continuous_clk << 5) | 0x5); /* Clock settle time */ - TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_END, + TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPA_FRAME_START, (0x1 << 8) | /* Enable continuous syncpt */ TEGRA_VI_SYNCPT_CSI_A); @@ -555,7 +555,7 @@ static void tegra_camera_capture_setup_csi_b(struct tegra_camera_dev *pcdev, (pdata->continuous_clk << 5) | 0x5); /* Clock settle time */ - TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_END, + TC_VI_REG_WT(pcdev, TEGRA_VI_CONT_SYNCPT_CSI_PPB_FRAME_START, (0x1 << 8) | /* Enable continuous syncpt */ TEGRA_VI_SYNCPT_CSI_B); @@ -857,7 +857,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, * wait on VIP VSYNC syncpt. */ if (port == TEGRA_CAMERA_PORT_CSI_A) { - pcdev->syncpt_csi_a++; + pcdev->syncpt_csi_a = nvhost_syncpt_incr_max_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_CSI_A, 1); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPA_COMMAND, pdata->continuous_capture?0x0000f001 :0x0000f005); @@ -867,7 +868,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, NULL); } else if (port == TEGRA_CAMERA_PORT_CSI_B) { - pcdev->syncpt_csi_b++; + pcdev->syncpt_csi_b = nvhost_syncpt_incr_max_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_CSI_B, 1); TC_VI_REG_WT(pcdev, TEGRA_CSI_PIXEL_STREAM_PPB_COMMAND, pdata->continuous_capture? 0x0000f001: 0x0000f005); @@ -877,7 +879,8 @@ static int tegra_camera_capture_start(struct tegra_camera_dev *pcdev, TEGRA_SYNCPT_CSI_WAIT_TIMEOUT, NULL); } else { - pcdev->syncpt_vi++; + pcdev->syncpt_vi = nvhost_syncpt_incr_max_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_VI, 1); TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, 0x00000001); err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, @@ -946,6 +949,8 @@ static int tegra_camera_capture_stop(struct tegra_camera_dev *pcdev, int port) TC_VI_REG_WT(pcdev, TEGRA_VI_CAMERA_CONTROL, 0x00000005); + pcdev->syncpt_vi = nvhost_syncpt_incr_max_ext(pcdev->ndev, + TEGRA_VI_SYNCPT_VI, 1); if (tegra_camera_port_is_csi(port)) err = nvhost_syncpt_wait_timeout_ext(pcdev->ndev, TEGRA_VI_SYNCPT_VI, -- cgit v1.2.3 From bc4bd19dd6e9de8518a784753d7b69224be0b9f6 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Fri, 1 Aug 2014 11:29:19 +0530 Subject: nvmap: fix test condition to avoid infinite loop Make sure that we dont enter infinite loop due to negative value of pins in some cases. Also remove debugging check for refcount. Bug 1478467 Change-Id: I7df8efa5b3cf8927a0c18363add4f031aca48e48 Signed-off-by: Bibek Basu Reviewed-on: http://git-master/r/450209 Reviewed-by: Matthew Pedro Tested-by: Matthew Pedro --- drivers/video/tegra/host/nvhost_acm.c | 4 +--- drivers/video/tegra/nvmap/nvmap_handle.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c index fcedb5c1a2c8..edf9286566b4 100644 --- a/drivers/video/tegra/host/nvhost_acm.c +++ b/drivers/video/tegra/host/nvhost_acm.c @@ -219,9 +219,7 @@ void nvhost_module_busy(struct nvhost_device *dev) cancel_delayed_work(&dev->powerstate_down); dev->refcount++; - if (unlikely(dev->refcount <= 0)) - pr_err("unbalanced refcount %d\n", dev->refcount); - if (!nvhost_module_powered(dev)) + if (dev->refcount > 0 && !nvhost_module_powered(dev)) to_state_running_locked(dev); mutex_unlock(&dev->lock); diff --git a/drivers/video/tegra/nvmap/nvmap_handle.c b/drivers/video/tegra/nvmap/nvmap_handle.c index 1c5e61ccd45d..1a6aec5ae998 100644 --- a/drivers/video/tegra/nvmap/nvmap_handle.c +++ b/drivers/video/tegra/nvmap/nvmap_handle.c @@ -904,7 +904,7 @@ void nvmap_free_handle_id(struct nvmap_client *client, unsigned long id) nvmap_err(client, "%s freeing pinned handle %p\n", current->group_leader->comm, h); - while (pins--) + while (pins-- > 0) nvmap_unpin_handles(client, &ref->handle, 1); if (h->owner == client) -- cgit v1.2.3 From 36a8e8ba4538d17acaac60ffca6835cf21f33709 Mon Sep 17 00:00:00 2001 From: Eric Yuen Date: Tue, 8 Jul 2014 10:34:33 +0000 Subject: arm: tegra3: PCIe Clock and Reset Conform to Specification PCIe Reset line must be asserted for at least 100us after clock is enabled. PEX 2 Controller Register fix, offsets are not at constant intervals. Bug 1521306 Reviewed-on: http://git-master/r/225399 (cherry picked from commit df0760bf515236bed2e87e590509642ab72a01b5) Change-Id: I7b44ea51e7e02f2bca93cfc75ed85e01ab91fe03 Signed-off-by: Shreshtha Sahu Reviewed-on: http://git-master/r/435598 Reviewed-by: Jay Agarwal GVS: Gerrit_Virtual_Submit Reviewed-by: Eric Brower Reviewed-by: Winnie Hsu --- arch/arm/mach-tegra/pcie.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index dd6da2a7d965..c863ca3a062b 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c @@ -342,6 +342,15 @@ static bool is_dock_conn_at_boot = true; void __iomem *tegra_pcie_io_base; EXPORT_SYMBOL(tegra_pcie_io_base); +/* Array of PCIe Controller Register offsets */ +static u32 pex_controller_registers[] = { + AFI_PEX0_CTRL, + AFI_PEX1_CTRL, +#if MAX_PCIE_SUPPORTED_PORTS == 3 + AFI_PEX2_CTRL, +#endif +}; + static inline void afi_writel(u32 value, unsigned long offset) { writel(value, offset + AFI_OFFSET + tegra_pcie.regs); @@ -797,15 +806,13 @@ static void tegra_pcie_enable_controller(void) reg |= 1 << MSELECT_CONFIG_0_ENABLE_PCIE_APERTURE; writel(reg, reg_mselect_base); - /* Enable slot clock and pulse the reset signals */ - for (i = 0, reg = AFI_PEX0_CTRL; i < MAX_PCIE_SUPPORTED_PORTS; - i++, reg += (i*8)) { - val = afi_readl(reg) | AFI_PEX_CTRL_CLKREQ_EN | AFI_PEX_CTRL_REFCLK_EN; - afi_writel(val, reg); + /* Enable slot clock and ensure reset signals is assert */ + for (i = 0; i < ARRAY_SIZE(pex_controller_registers); i++) { + reg = pex_controller_registers[i]; + val = afi_readl(reg) | AFI_PEX_CTRL_REFCLK_EN | + AFI_PEX_CTRL_CLKREQ_EN; val &= ~AFI_PEX_CTRL_RST; - afi_writel(val, reg); - val = afi_readl(reg) | AFI_PEX_CTRL_RST; afi_writel(val, reg); } afi_writel(0, AFI_PEXBIAS_CTRL_0); @@ -865,6 +872,18 @@ static void tegra_pcie_enable_controller(void) val = pads_readl(PADS_PLL_CTL); } while (!(val & PADS_PLL_CTL_LOCKDET)); + /* Wait for clock to latch (min of 100us) */ + udelay(100); + + /* deassert PEX reset signal */ + for (i = 0; i < ARRAY_SIZE(pex_controller_registers); i++) { + reg = pex_controller_registers[i]; + val = afi_readl(reg); + val |= AFI_PEX_CTRL_RST; + afi_writel(val, reg); + } + + /* turn off IDDQ override */ val = pads_readl(PADS_CTL) & ~PADS_CTL_IDDQ_1L; pads_writel(val, PADS_CTL); -- cgit v1.2.3 From c7460e0d6afd754ebf5555477129579bc83c47b9 Mon Sep 17 00:00:00 2001 From: Shreshtha SAHU Date: Wed, 3 Sep 2014 17:45:17 +0530 Subject: arm: tegra30: pcie: do not disable clk after deasserting resets Do not disable and re-enable clocks after deasserting PCIE, AFI and PCIEX resets. Deasserting the resets should be followed by programming the PCIE. Bug 1521306 Change-Id: Idc43bc9b21cac3818852ed059fe512f4cd75b748 Signed-off-by: Shreshtha SAHU Reviewed-on: http://git-master/r/495616 GVS: Gerrit_Virtual_Submit Reviewed-by: Eric Brower Reviewed-by: Prashant Gaikwad Reviewed-by: Winnie Hsu --- arch/arm/mach-tegra/powergate.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c index 4c0d8bec276e..e8f96a4cac0e 100644 --- a/arch/arm/mach-tegra/powergate.c +++ b/arch/arm/mach-tegra/powergate.c @@ -709,7 +709,10 @@ int tegra_unpowergate_partition(int id) mc_flush_done(id); /* Disable all clks enabled earlier. Drivers should enable clks */ - partition_clk_disable(id); +#ifdef CONFIG_ARCH_TEGRA_3x_SOC + if (id != TEGRA_POWERGATE_PCIE) +#endif + partition_clk_disable(id); return 0; @@ -743,9 +746,14 @@ int tegra_unpowergate_partition_with_clk_on(int id) goto err_unpowergating; /* Enable clks for the partition */ - ret = partition_clk_enable(id); - if (ret) - goto err_unpowergate_clk; +#ifdef CONFIG_ARCH_TEGRA_3x_SOC + if (id != TEGRA_POWERGATE_PCIE) +#endif + { + ret = partition_clk_enable(id); + if (ret) + goto err_unpowergate_clk; + } return ret; -- cgit v1.2.3