Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/4] watchdog: add support for ux500_wdt watchdog
From: Fabio Baltieri @ 2013-01-18 11:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358509214-22407-1-git-send-email-fabio.baltieri@linaro.org>

This patch adds support for the ux500_wdt watchdog that is found in
ST-Ericsson Ux500 platform.  The driver is based on PRCMU APIs.

Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
 drivers/watchdog/Kconfig                |  12 +++
 drivers/watchdog/Makefile               |   1 +
 drivers/watchdog/ux500_wdt.c            | 171 ++++++++++++++++++++++++++++++++
 include/linux/platform_data/ux500_wdt.h |  19 ++++
 4 files changed, 203 insertions(+)
 create mode 100644 drivers/watchdog/ux500_wdt.c
 create mode 100644 include/linux/platform_data/ux500_wdt.h

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7f809fd..26e1fdb 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -364,6 +364,18 @@ config IMX2_WDT
 	  To compile this driver as a module, choose M here: the
 	  module will be called imx2_wdt.
 
+config UX500_WATCHDOG
+	tristate "ST-Ericsson Ux500 watchdog"
+	depends on MFD_DB8500_PRCMU
+	select WATCHDOG_CORE
+	default y
+	help
+	  Say Y here to include Watchdog timer support for the watchdog
+	  existing in the prcmu of ST-Ericsson Ux500 series platforms.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ux500_wdt.
+
 # AVR32 Architecture
 
 config AT32AP700X_WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 97bbdb3a..bec86ee 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
+obj-$(CONFIG_UX500_WATCHDOG) += ux500_wdt.o
 
 # AVR32 Architecture
 obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/ux500_wdt.c b/drivers/watchdog/ux500_wdt.c
new file mode 100644
index 0000000..dd608db
--- /dev/null
+++ b/drivers/watchdog/ux500_wdt.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011-2013
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org> for ST-Ericsson
+ * Author: Jonas Aaberg <jonas.aberg@stericsson.com> for ST-Ericsson
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/ux500_wdt.h>
+
+#include <linux/mfd/dbx500-prcmu.h>
+
+#define WATCHDOG_TIMEOUT 600 /* 10 minutes */
+
+#define WATCHDOG_MIN	0
+#define WATCHDOG_MAX28	268435  /* 28 bit resolution in ms == 268435.455 s */
+#define WATCHDOG_MAX32	4294967 /* 32 bit resolution in ms == 4294967.295 s */
+
+static int timeout = WATCHDOG_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+	"Watchdog timeout in seconds. default="
+				__MODULE_STRING(WATCHDOG_TIMEOUT) ".");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+	"Watchdog cannot be stopped once started (default="
+				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int ux500_wdt_start(struct watchdog_device *wdd)
+{
+	return prcmu_enable_a9wdog(PRCMU_WDOG_ALL);
+}
+
+static int ux500_wdt_stop(struct watchdog_device *wdd)
+{
+	return prcmu_disable_a9wdog(PRCMU_WDOG_ALL);
+}
+
+static int ux500_wdt_keepalive(struct watchdog_device *wdd)
+{
+	return prcmu_kick_a9wdog(PRCMU_WDOG_ALL);
+}
+
+static int ux500_wdt_set_timeout(struct watchdog_device *wdd,
+				 unsigned int timeout)
+{
+	ux500_wdt_stop(wdd);
+	prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+	ux500_wdt_start(wdd);
+
+	return 0;
+}
+
+static const struct watchdog_info ux500_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+	.identity = "Ux500 WDT",
+	.firmware_version = 1,
+};
+
+static const struct watchdog_ops ux500_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = ux500_wdt_start,
+	.stop  = ux500_wdt_stop,
+	.ping  = ux500_wdt_keepalive,
+	.set_timeout = ux500_wdt_set_timeout,
+};
+
+static struct watchdog_device ux500_wdt = {
+	.info = &ux500_wdt_info,
+	.ops = &ux500_wdt_ops,
+	.min_timeout = WATCHDOG_MIN,
+	.max_timeout = WATCHDOG_MAX32,
+};
+
+static int ux500_wdt_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct ux500_wdt_data *pdata = pdev->dev.platform_data;
+
+	if (pdata) {
+		if (pdata->timeout > 0)
+			timeout = pdata->timeout;
+		if (pdata->has_28_bits_resolution)
+			ux500_wdt.max_timeout = WATCHDOG_MAX28;
+	}
+
+	watchdog_set_nowayout(&ux500_wdt, nowayout);
+
+	/* disable auto off on sleep */
+	prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
+
+	/* set HW initial value */
+	prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+
+	ret = watchdog_register_device(&ux500_wdt);
+	if (ret)
+		return ret;
+
+	dev_info(&pdev->dev, "initialized\n");
+
+	return 0;
+}
+
+static int ux500_wdt_remove(struct platform_device *dev)
+{
+	watchdog_unregister_device(&ux500_wdt);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ux500_wdt_suspend(struct platform_device *pdev,
+			     pm_message_t state)
+{
+	if (watchdog_active(&ux500_wdt)) {
+		ux500_wdt_stop(&ux500_wdt);
+		prcmu_config_a9wdog(PRCMU_WDOG_CPU1, true);
+
+		prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+		ux500_wdt_start(&ux500_wdt);
+	}
+	return 0;
+}
+
+static int ux500_wdt_resume(struct platform_device *pdev)
+{
+	if (watchdog_active(&ux500_wdt)) {
+		ux500_wdt_stop(&ux500_wdt);
+		prcmu_config_a9wdog(PRCMU_WDOG_CPU1, false);
+
+		prcmu_load_a9wdog(PRCMU_WDOG_ALL, timeout * 1000);
+		ux500_wdt_start(&ux500_wdt);
+	}
+	return 0;
+}
+#else
+#define ux500_wdt_suspend NULL
+#define ux500_wdt_resume NULL
+#endif
+
+static struct platform_driver ux500_wdt_driver = {
+	.probe		= ux500_wdt_probe,
+	.remove		= ux500_wdt_remove,
+	.suspend	= ux500_wdt_suspend,
+	.resume		= ux500_wdt_resume,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ux500_wdt",
+	},
+};
+
+module_platform_driver(ux500_wdt_driver);
+
+MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>");
+MODULE_DESCRIPTION("Ux500 Watchdog Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS("platform:ux500_wdt");
diff --git a/include/linux/platform_data/ux500_wdt.h b/include/linux/platform_data/ux500_wdt.h
new file mode 100644
index 0000000..aa2dfe7
--- /dev/null
+++ b/include/linux/platform_data/ux500_wdt.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) ST Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * STE Ux500 Watchdog platform data
+ */
+#ifndef __UX500_WDT_H
+#define __UX500_WDT_H
+
+/**
+ * struct ux500_wdt_data
+ */
+struct ux500_wdt_data {
+	int timeout;
+	bool has_28_bits_resolution;
+};
+
+#endif /* __UX500_WDT_H */
-- 
1.7.12.1

^ permalink raw reply related

* [PATCH 2/4] mfd: dbx500-prcmu: export a9wdog functions
From: Fabio Baltieri @ 2013-01-18 11:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358509214-22407-1-git-send-email-fabio.baltieri@linaro.org>

Add EXPORT_SYMBOL to db500_prcmu_*_a9wdog functions to allow usage from
module.

Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 268f45d..7a63fa8 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2212,21 +2212,25 @@ int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 			    sleep_auto_off ? A9WDOG_AUTO_OFF_EN :
 			    A9WDOG_AUTO_OFF_DIS);
 }
+EXPORT_SYMBOL(db8500_prcmu_config_a9wdog);
 
 int db8500_prcmu_enable_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
 }
+EXPORT_SYMBOL(db8500_prcmu_enable_a9wdog);
 
 int db8500_prcmu_disable_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
 }
+EXPORT_SYMBOL(db8500_prcmu_disable_a9wdog);
 
 int db8500_prcmu_kick_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
 }
+EXPORT_SYMBOL(db8500_prcmu_kick_a9wdog);
 
 /*
  * timeout is 28 bit, in ms.
@@ -2244,6 +2248,7 @@ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
 			    (u8)((timeout >> 12) & 0xff),
 			    (u8)((timeout >> 20) & 0xff));
 }
+EXPORT_SYMBOL(db8500_prcmu_load_a9wdog);
 
 /**
  * prcmu_abb_read() - Read register value(s) from the ABB.
-- 
1.7.12.1

^ permalink raw reply related

* [PATCH 1/4] mfd: dbx500-prcmu: add watchdog ID definitions
From: Fabio Baltieri @ 2013-01-18 11:40 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358509214-22407-1-git-send-email-fabio.baltieri@linaro.org>

Add definition of watchdog IDs to be used by ux500_wdt driver.

Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Fabio Baltieri <fabio.baltieri@linaro.org>
---
 include/linux/mfd/dbx500-prcmu.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index c202d6c..c6e0608 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -147,6 +147,18 @@ enum prcmu_clock {
 };
 
 /**
+ * enum prcmu_wdog_id - PRCMU watchdog IDs
+ * @PRCMU_WDOG_ALL: use all timers
+ * @PRCMU_WDOG_CPU1: use first CPU timer only
+ * @PRCMU_WDOG_CPU2: use second CPU timer conly
+ */
+enum prcmu_wdog_id {
+	PRCMU_WDOG_ALL = 0x00,
+	PRCMU_WDOG_CPU1 = 0x01,
+	PRCMU_WDOG_CPU2 = 0x02,
+};
+
+/**
  * enum ape_opp - APE OPP states definition
  * @APE_OPP_INIT:
  * @APE_NO_CHANGE: The APE operating point is unchanged
-- 
1.7.12.1

^ permalink raw reply related

* [PATCH 0/4] add ux500_wdt support
From: Fabio Baltieri @ 2013-01-18 11:40 UTC (permalink / raw)
  To: linux-arm-kernel

Hi all,

this set adds support for the ux500_wdt timer, implemented in the PRCMU
unit of ST-Ericsson ux500 architecture.

The first two patches add the necessary definitions and function export
to the PRCMU driver currently in mainline, while the third an fourth
patches add the actual watchdog driver and mfd_cell definition to make
it probe when PRCMU is compiled in.

As the patches touches files in both mfd and watchdog subsystems, what do
you think is the best way to handle this set?

Thanks,
Fabio


Fabio Baltieri (4):
  mfd: dbx500-prcmu: add watchdog ID definitions
  mfd: dbx500-prcmu: export a9wdog functions
  watchdog: add support for ux500_wdt watchdog
  mfd: db8500-prcmu: add ux500_wdt mfd_cell

 drivers/mfd/db8500-prcmu.c              |  17 ++++
 drivers/watchdog/Kconfig                |  12 +++
 drivers/watchdog/Makefile               |   1 +
 drivers/watchdog/ux500_wdt.c            | 171 ++++++++++++++++++++++++++++++++
 include/linux/mfd/dbx500-prcmu.h        |  12 +++
 include/linux/platform_data/ux500_wdt.h |  19 ++++
 6 files changed, 232 insertions(+)
 create mode 100644 drivers/watchdog/ux500_wdt.c
 create mode 100644 include/linux/platform_data/ux500_wdt.h

-- 
1.7.12.1

^ permalink raw reply

* [PATCH RFC 1/2] Implementation of pci_fixup_irqs for descendants of a specified bus
From: Andrew Murray @ 2013-01-18 11:37 UTC (permalink / raw)
  To: linux-arm-kernel

Continuing from discussion with Thierry (lkml.org/lkml/2013/1/18/107) perhaps
this will be useful to fold into your patchset. 
---
This patch provides pci_bus_fixup_irqs which performs the same
function as pci_fixup_irqs but only to descendants of the specified
bus.

This can reduce unnecessary fixing up of device irqs when new buses
are added.

Signed-off-by: Andrew Murray <Andrew.Murray@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
---
 drivers/pci/setup-irq.c |   15 +++++++++++++++
 include/linux/pci.h     |    3 +++
 2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
index eb219a1..ea91874 100644
--- a/drivers/pci/setup-irq.c
+++ b/drivers/pci/setup-irq.c
@@ -62,3 +62,18 @@ pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
 	for_each_pci_dev(dev)
 		pdev_fixup_irq(dev, swizzle, map_irq);
 }
+
+void __init
+pci_bus_fixup_irqs(struct pci_bus *bus,
+		u8 (*swizzle)(struct pci_dev *, u8 *),
+		int (*map_irq)(const struct pci_dev *, u8, u8))
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pdev_fixup_irq(dev, swizzle, map_irq);
+
+		if (dev->subordinate)
+			pci_bus_fixup_irqs(dev->subordinate, swizzle, map_irq);
+	}
+}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 5faa831..1b3c2eb 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -953,6 +953,9 @@ void pdev_enable_device(struct pci_dev *);
 int pci_enable_resources(struct pci_dev *, int mask);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
 		    int (*)(const struct pci_dev *, u8, u8));
+void pci_bus_fixup_irqs(struct pci_bus *bus,
+		u8 (*swizzle)(struct pci_dev *, u8 *),
+		int (*map_irq)(const struct pci_dev *, u8, u8));
 #define HAVE_PCI_REQ_REGIONS	2
 int __must_check pci_request_regions(struct pci_dev *, const char *);
 int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *);
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH v4] ARM: OMAP2+: AM33XX: omap2plus_defconfig: Add support for few drivers
From: AnilKumar, Chimata @ 2013-01-18 11:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357202279-6094-1-git-send-email-anilkumar@ti.com>

On Thu, Jan 03, 2013 at 14:07:59, AnilKumar, Chimata wrote:
> Adds tps65910 PMIC, lis3lv02d accelerometer, tsl2550 ambient light sensor,
> tmp275 temperature sensor, matrix keypad, gbio based leds and D_CAN drivers
> support. These peripherals are present on AM33XX family of devices (EVM,
> BeagleBone and EVMSK). One has to manually enable these support to use the
> drivers, so this patch enables all the drivers in omap2plus_defconfig

Hi Tony,

Could you please pull this patch, if there are no further comments?

Thanks
AnilKumar
 
> Signed-off-by: AnilKumar Ch <anilkumar@ti.com>
> ---
> Changes from v3:
> 	- Incorporated Olof Johansson's comments on v3
> 	  * Combined all the patches into a single patch
> 
> Changes from v2:
> 	- Incorporated Tony's comments on v2
> 	  * Enabled as modules instead of kernel built-in drivers.
> 	- Dropped 1st patch because it was accepted.
> 
> Changes from v1:
> 	- Incorporated martinez javier's comments on v1
> 	  * Enabled few more triggers in omap2plus_defconfig
> 	- Included Igor's patch, which modifies the omap2plus
> 	  defconfig for AM33XX devices.
> 
>  arch/arm/configs/omap2plus_defconfig |   22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
> index 19b7311..9fb2373 100644
> --- a/arch/arm/configs/omap2plus_defconfig
> +++ b/arch/arm/configs/omap2plus_defconfig
> @@ -52,6 +52,11 @@ CONFIG_IP_PNP_RARP=y
>  # CONFIG_INET_LRO is not set
>  # CONFIG_IPV6 is not set
>  CONFIG_NETFILTER=y
> +CONFIG_CAN=m
> +CONFIG_CAN_RAW=m
> +CONFIG_CAN_BCM=m
> +CONFIG_CAN_C_CAN=m
> +CONFIG_CAN_C_CAN_PLATFORM=m
>  CONFIG_BT=m
>  CONFIG_BT_HCIUART=m
>  CONFIG_BT_HCIUART_H4=y
> @@ -81,6 +86,9 @@ CONFIG_MTD_UBI=y
>  CONFIG_BLK_DEV_LOOP=y
>  CONFIG_BLK_DEV_RAM=y
>  CONFIG_BLK_DEV_RAM_SIZE=16384
> +CONFIG_SENSORS_LIS3LV02D=m
> +CONFIG_SENSORS_TSL2550=m
> +CONFIG_SENSORS_LIS3_I2C=m
>  CONFIG_SCSI=y
>  CONFIG_BLK_DEV_SD=y
>  CONFIG_SCSI_MULTI_LUN=y
> @@ -106,6 +114,7 @@ CONFIG_USB_KC2190=y
>  CONFIG_INPUT_JOYDEV=y
>  CONFIG_INPUT_EVDEV=y
>  CONFIG_KEYBOARD_GPIO=y
> +CONFIG_KEYBOARD_MATRIX=m
>  CONFIG_KEYBOARD_TWL4030=y
>  CONFIG_INPUT_TOUCHSCREEN=y
>  CONFIG_TOUCHSCREEN_ADS7846=y
> @@ -129,14 +138,17 @@ CONFIG_GPIO_SYSFS=y
>  CONFIG_GPIO_TWL4030=y
>  CONFIG_W1=y
>  CONFIG_POWER_SUPPLY=y
> +CONFIG_SENSORS_LM75=m
>  CONFIG_WATCHDOG=y
>  CONFIG_OMAP_WATCHDOG=y
>  CONFIG_TWL4030_WATCHDOG=y
>  CONFIG_MFD_TPS65217=y
> +CONFIG_MFD_TPS65910=y
>  CONFIG_REGULATOR_TWL4030=y
>  CONFIG_REGULATOR_TPS65023=y
>  CONFIG_REGULATOR_TPS6507X=y
>  CONFIG_REGULATOR_TPS65217=y
> +CONFIG_REGULATOR_TPS65910=y
>  CONFIG_FB=y
>  CONFIG_FIRMWARE_EDID=y
>  CONFIG_FB_MODE_HELPERS=y
> @@ -193,6 +205,16 @@ CONFIG_MMC_UNSAFE_RESUME=y
>  CONFIG_SDIO_UART=y
>  CONFIG_MMC_OMAP=y
>  CONFIG_MMC_OMAP_HS=y
> +CONFIG_NEW_LEDS=y
> +CONFIG_LEDS_GPIO=y
> +CONFIG_LEDS_TRIGGERS=y
> +CONFIG_LEDS_TRIGGER_TIMER=y
> +CONFIG_LEDS_TRIGGER_ONESHOT=y
> +CONFIG_LEDS_TRIGGER_HEARTBEAT=y
> +CONFIG_LEDS_TRIGGER_BACKLIGHT=y
> +CONFIG_LEDS_TRIGGER_CPU=y
> +CONFIG_LEDS_TRIGGER_GPIO=y
> +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
>  CONFIG_RTC_CLASS=y
>  CONFIG_RTC_DRV_TWL92330=y
>  CONFIG_RTC_DRV_TWL4030=y
> -- 
> 1.7.9.5
> 
> 

^ permalink raw reply

* [PATCH v2 2/2] ARM: uncompress debug support for multiplatform build
From: Shawn Guo @ 2013-01-18 11:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201301180847.50913.arnd@arndb.de>

On Fri, Jan 18, 2013 at 08:47:50AM +0000, Arnd Bergmann wrote:
> On Friday 18 January 2013, Shawn Guo wrote:
> > +ENTRY(putc)
> > +       addruart r1, r2, r3
> > +       waituart r3, r1
> > +       senduart r0, r1
> > +       busyuart r3, r1
> > +       mov      pc, lr
> > +ENDPROC(putc)
> 
> Ah, so it actually worked? I was expecting at least some part of
> my code to be wrong ;-) My assembler skills are very much
> lacking and I had not tried it.
> 
Yes, it worked.  Actually, I wrote it myself after reading your comment
saying take your code as approximation.  And then I compared my code
with yours and found the only difference is the indent of the last
statement :)

> Upon closer inspection, it seems that the CR/LF logic from
> the printascii function is not here, and it probably should be.
> 
No.  As Russell already pointed out, the current implementation of
putc() is exactly what putstr() expect, with no CR/LF logic.

Shawn

^ permalink raw reply

* [PATCH 1/1] ARM: Add API to detect SCU base address from CP15
From: Hiroshi Doyu @ 2013-01-18 10:59 UTC (permalink / raw)
  To: linux-arm-kernel

Add API to detect SCU base address from CP15.

Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
NOTE:
This wasn't delivered to linux-arm-kernel at lists.infradead.org, resending....

For usage: http://patchwork.ozlabs.org/patch/212013/
---
 arch/arm/include/asm/smp_scu.h |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h
index 4eb6d00..f619eef 100644
--- a/arch/arm/include/asm/smp_scu.h
+++ b/arch/arm/include/asm/smp_scu.h
@@ -6,6 +6,23 @@
 #define SCU_PM_POWEROFF	3
 
 #ifndef __ASSEMBLER__
+
+#include <asm/cputype.h>
+
+static inline phys_addr_t scu_get_base(void)
+{
+	phys_addr_t pa;
+	unsigned long part_number = read_cpuid_part_number();
+
+	switch (part_number) {
+	case ARM_CPU_PART_CORTEX_A9:
+		/* Get SCU physical base */
+		asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa));
+		return pa;
+	default:
+		return 0;
+	}
+}
 unsigned int scu_get_core_count(void __iomem *);
 void scu_enable(void __iomem *);
 int scu_power_mode(void __iomem *, unsigned int);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 2/2] usb: chipidea: imx: Add system suspend/resume API
From: Russell King - ARM Linux @ 2013-01-18 10:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358477428-2605-2-git-send-email-peter.chen@freescale.com>

On Fri, Jan 18, 2013 at 10:50:28AM +0800, Peter Chen wrote:
> +#ifdef CONFIG_PM
> +static int ci13xxx_imx_suspend(struct device *dev)
> +{
> +	struct ci13xxx_imx_data *data =
> +		platform_get_drvdata(to_platform_device(dev));

Is there a reason not to use dev_get_drvdata() here?  Hint:

#define to_platform_device(x) container_of((x), struct platform_device, dev)

static inline void *platform_get_drvdata(const struct platform_device *pdev)
{
        return dev_get_drvdata(&pdev->dev);
}

So, you're going from a dev => platform device => the same dev again.

It's perfectly valid to use dev_get_drvdata() here because we're not going
to separate these two (it makes absolutely no sense to.)

^ permalink raw reply

* [RESEND][v3 4/9] ARM: Add API to detect SCU base address from CP15
From: Hiroshi Doyu @ 2013-01-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1358237598-32413-1-git-send-email-hdoyu@nvidia.com>

Add API to detect SCU base address from CP15.

Signed-off-by: Hiroshi Doyu <hdoyu@nvidia.com>
---
NOTE:
This wasn't delivered to linux-arm-kernel at lists.infradead.org, resending....

For usage: http://patchwork.ozlabs.org/patch/212013/
---
 arch/arm/include/asm/smp_scu.h |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h
index 4eb6d00..f619eef 100644
--- a/arch/arm/include/asm/smp_scu.h
+++ b/arch/arm/include/asm/smp_scu.h
@@ -6,6 +6,23 @@
 #define SCU_PM_POWEROFF	3
 
 #ifndef __ASSEMBLER__
+
+#include <asm/cputype.h>
+
+static inline phys_addr_t scu_get_base(void)
+{
+	phys_addr_t pa;
+	unsigned long part_number = read_cpuid_part_number();
+
+	switch (part_number) {
+	case ARM_CPU_PART_CORTEX_A9:
+		/* Get SCU physical base */
+		asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa));
+		return pa;
+	default:
+		return 0;
+	}
+}
 unsigned int scu_get_core_count(void __iomem *);
 void scu_enable(void __iomem *);
 int scu_power_mode(void __iomem *, unsigned int);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] ARM: remove unnecessary 'select GENERIC_GPIO'
From: Grant Likely @ 2013-01-18 10:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdYw6V_GGjBsj_bzzkmFVTamuMq2oMwYDKhjMrXeS5j+fQ@mail.gmail.com>

On Thu, 17 Jan 2013 14:36:00 +0100, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Tue, Jan 15, 2013 at 2:13 PM, Shawn Guo <shawn.guo@linaro.org> wrote:
> 
> > The only use of GENERIC_GPIO (defined by architecture) in GPIO subsystem
> > is being selected by GPIOLIB.  Also there are no any use of the option
> > at architecture level. Only two sub-architectures shmobile and orion
> > really use the option as below.
> >
> >   arch/arm/mach-shmobile/Makefile:obj-$(CONFIG_GENERIC_GPIO)      += $(pfc-y)
> >   arch/arm/plat-orion/Makefile:orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o
> >
> > Remove all those unnecessary sub-architecture level selection of
> > GENERIC_GPIO, which are there only for confusing people.
> >
> > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> 
> Acked-by: Linus Walleij <linus.walleij@linaro.org>

Looks good to me also.

Acked-by: Grant Likely <grant.likely@secretlab.ca>

^ permalink raw reply

* [PATCH v3 8/8] arm/dts: AM335x-evm: Add TSC/ADC MFD device support
From: Patil, Rachna @ 2013-01-18 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

Add support for core multifunctional device along
with its clients touchscreen and ADC.

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 arch/arm/boot/dts/am335x-evm.dts |   13 +++++++++++++
 arch/arm/boot/dts/am33xx.dtsi    |    8 ++++++++
 2 files changed, 21 insertions(+)

diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index d649644..ea28476 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -244,3 +244,16 @@
 &cpsw_emac1 {
 	phy_id = <&davinci_mdio>, <1>;
 };
+
+&tscadc {
+	tsc {
+		wires = <4>;
+		x-plate-resistance = <200>;
+		steps-to-configure = <5>;
+		wire-config = <0x00 0x11 0x22 0x33>;
+	};
+
+	adc {
+		adc-channels = <4>;
+	};
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index c2f14e8..211ec42 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -385,5 +385,13 @@
 				mac-address = [ 00 00 00 00 00 00 ];
 			};
 		};
+
+		tscadc: tscadc at 44e0d000 {
+			compatible = "ti,ti-tscadc";
+			reg = <0x44e0d000 0x1000>;
+			interrupt-parent = <&intc>;
+			interrupts = <16>;
+			ti,hwmods = "adc_tsc";
+		};
 	};
 };
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 7/8] IIO: ti_am335x_adc: Add DT support
From: Patil, Rachna @ 2013-01-18 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

Add DT support for client ADC driver.

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 drivers/iio/adc/ti_am335x_adc.c |   26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index cd030e1..81ca8e5 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -22,6 +22,8 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/iio/iio.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
 #include <linux/platform_data/ti_am335x_adc.h>
@@ -141,11 +143,12 @@ static int tiadc_probe(struct platform_device *pdev)
 	struct iio_dev		*indio_dev;
 	struct tiadc_device	*adc_dev;
 	struct ti_tscadc_dev	*tscadc_dev = pdev->dev.platform_data;
-	struct mfd_tscadc_board	*pdata;
+	struct mfd_tscadc_board	*pdata = tscadc_dev->dev->platform_data;
+	struct device_node	*node = tscadc_dev->dev->of_node;
 	int			err;
+	u32			val32;
 
-	pdata = tscadc_dev->dev->platform_data;
-	if (!pdata || !pdata->adc_init) {
+	if (!pdata && !node) {
 		dev_err(&pdev->dev, "Could not find platform data\n");
 		return -EINVAL;
 	}
@@ -159,7 +162,22 @@ static int tiadc_probe(struct platform_device *pdev)
 	adc_dev = iio_priv(indio_dev);
 
 	adc_dev->mfd_tscadc = tscadc_dev;
-	adc_dev->channels = pdata->adc_init->adc_channels;
+
+	if (pdata)
+		adc_dev->channels = pdata->adc_init->adc_channels;
+	else {
+		node = of_find_node_by_name(node, "adc");
+		if (!node)
+			return  -EINVAL;
+		else {
+			err = of_property_read_u32(node,
+					"adc-channels", &val32);
+			if (err < 0)
+				goto err_free_device;
+			else
+				adc_dev->channels = val32;
+		}
+	}
 
 	indio_dev->dev.parent = &pdev->dev;
 	indio_dev->name = dev_name(&pdev->dev);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 6/8] input: ti_am335x_tsc: Add DT support
From: Patil, Rachna @ 2013-01-18 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

Add DT support for client touchscreen driver

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 drivers/input/touchscreen/ti_am335x_tsc.c |   94 +++++++++++++++++++++++++----
 1 file changed, 81 insertions(+), 13 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 064d2b2..249dac5 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -26,6 +26,8 @@
 #include <linux/io.h>
 #include <linux/input/ti_am335x_tsc.h>
 #include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
 
@@ -366,6 +368,74 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 	return IRQ_HANDLED;
 }
 
+static int titsc_parse_dt(struct ti_tscadc_dev *tscadc_dev,
+					struct titsc *ts_dev)
+{
+	struct device_node *node = tscadc_dev->dev->of_node;
+	int err, i;
+	u32 val32, wires_conf[4];
+
+	if (!node)
+		return -EINVAL;
+	else {
+		node = of_find_node_by_name(node, "tsc");
+		if (!node)
+			return -EINVAL;
+		else {
+			err = of_property_read_u32(node, "wires", &val32);
+			if (err < 0)
+				goto error_ret;
+			else
+				ts_dev->wires = val32;
+
+			err = of_property_read_u32(node,
+					"x-plate-resistance", &val32);
+			if (err < 0)
+				goto error_ret;
+			else
+				ts_dev->x_plate_resistance = val32;
+
+			err = of_property_read_u32(node,
+					"steps-to-configure", &val32);
+			if (err < 0)
+				goto error_ret;
+			else
+				ts_dev->steps_to_configure = val32;
+
+			err = of_property_read_u32_array(node, "wire-config",
+					wires_conf, ARRAY_SIZE(wires_conf));
+			if (err < 0)
+				goto error_ret;
+			else {
+				for (i = 0; i < ARRAY_SIZE(wires_conf); i++)
+					ts_dev->config_inp[i] = wires_conf[i];
+			}
+		}
+	}
+	return 0;
+
+error_ret:
+	return err;
+}
+
+static int titsc_parse_pdata(struct ti_tscadc_dev *tscadc_dev,
+					struct titsc *ts_dev)
+{
+	struct mfd_tscadc_board	*pdata = tscadc_dev->dev->platform_data;
+
+	if (!pdata)
+		return -EINVAL;
+
+	ts_dev->wires = pdata->tsc_init->wires;
+	ts_dev->x_plate_resistance =
+		pdata->tsc_init->x_plate_resistance;
+	ts_dev->steps_to_configure =
+		pdata->tsc_init->steps_to_configure;
+	memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
+		sizeof(pdata->tsc_init->wire_config));
+	return 0;
+}
+
 /*
  * The functions for inserting/removing driver as a module.
  */
@@ -375,16 +445,8 @@ static int titsc_probe(struct platform_device *pdev)
 	struct titsc *ts_dev;
 	struct input_dev *input_dev;
 	struct ti_tscadc_dev *tscadc_dev = pdev->dev.platform_data;
-	struct mfd_tscadc_board	*pdata;
 	int err;
 
-	pdata = tscadc_dev->dev->platform_data;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "Could not find platform data\n");
-		return -EINVAL;
-	}
-
 	/* Allocate memory for device */
 	ts_dev = kzalloc(sizeof(struct titsc), GFP_KERNEL);
 	input_dev = input_allocate_device();
@@ -398,11 +460,17 @@ static int titsc_probe(struct platform_device *pdev)
 	ts_dev->mfd_tscadc = tscadc_dev;
 	ts_dev->input = input_dev;
 	ts_dev->irq = tscadc_dev->irq;
-	ts_dev->wires = pdata->tsc_init->wires;
-	ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
-	ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
-	memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
-			sizeof(pdata->tsc_init->wire_config));
+
+	if (tscadc_dev->dev->platform_data)
+		err = titsc_parse_pdata(tscadc_dev, ts_dev);
+	else
+		err = titsc_parse_dt(tscadc_dev, ts_dev);
+
+	if (err) {
+		dev_err(&pdev->dev, "Could not find platform data\n");
+		err = -EINVAL;
+		goto err_free_mem;
+	}
 
 	err = request_irq(ts_dev->irq, titsc_irq,
 			  0, pdev->dev.driver->name, ts_dev);
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 5/8] MFD: ti_am335x_tscadc: Add DT support
From: Patil, Rachna @ 2013-01-18 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

Make changes to add DT support in the MFD core driver.

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 drivers/mfd/ti_am335x_tscadc.c |   28 +++++++++++++++++++++++-----
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index e9f3fb5..4c01056 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -22,6 +22,8 @@
 #include <linux/regmap.h>
 #include <linux/mfd/core.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/ti_am335x_tscadc.h>
 #include <linux/input/ti_am335x_tsc.h>
@@ -64,20 +66,31 @@ static	int ti_tscadc_probe(struct platform_device *pdev)
 	struct resource		*res;
 	struct clk		*clk;
 	struct mfd_tscadc_board	*pdata = pdev->dev.platform_data;
+	struct device_node	*node = pdev->dev.of_node;
 	struct mfd_cell		*cell;
 	int			err, ctrl;
 	int			clk_value, clock_rate;
-	int			tsc_wires, adc_channels = 0, total_channels;
+	int			tsc_wires = 0, adc_channels = 0, total_channels;
 
-	if (!pdata) {
+	if (!pdata && !pdev->dev.of_node) {
 		dev_err(&pdev->dev, "Could not find platform data\n");
 		return -EINVAL;
 	}
 
-	if (pdata->adc_init)
-		adc_channels = pdata->adc_init->adc_channels;
+	if (pdev->dev.platform_data) {
+		if (pdata->tsc_init)
+			tsc_wires = pdata->tsc_init->wires;
+
+		if (pdata->adc_init)
+			adc_channels = pdata->adc_init->adc_channels;
+	} else {
+		node = of_find_node_by_name(pdev->dev.of_node, "tsc");
+		of_property_read_u32(node, "wires", &tsc_wires);
+
+		node = of_find_node_by_name(pdev->dev.of_node, "adc");
+		of_property_read_u32(node, "adc-channels", &adc_channels);
+	}
 
-	tsc_wires = pdata->tsc_init->wires;
 	total_channels = tsc_wires + adc_channels;
 
 	if (total_channels > 8) {
@@ -256,11 +269,16 @@ static const struct dev_pm_ops tscadc_pm_ops = {
 #define TSCADC_PM_OPS NULL
 #endif
 
+static const struct of_device_id ti_tscadc_dt_ids[] = {
+	{ .compatible = "ti,ti-tscadc", },
+};
+
 static struct platform_driver ti_tscadc_driver = {
 	.driver = {
 		.name   = "ti_tscadc",
 		.owner	= THIS_MODULE,
 		.pm	= TSCADC_PM_OPS,
+		.of_match_table = of_match_ptr(ti_tscadc_dt_ids),
 	},
 	.probe	= ti_tscadc_probe,
 	.remove	= ti_tscadc_remove,
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 4/8] MFD: ti_am335x_tscadc: add device tree binding information
From: Patil, Rachna @ 2013-01-18 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 .../devicetree/bindings/mfd/ti_am335x_tscadc.txt   |   35 ++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/ti_am335x_tscadc.txt

diff --git a/Documentation/devicetree/bindings/mfd/ti_am335x_tscadc.txt b/Documentation/devicetree/bindings/mfd/ti_am335x_tscadc.txt
new file mode 100644
index 0000000..c13c492
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/ti_am335x_tscadc.txt
@@ -0,0 +1,35 @@
+Texas Instruments - TSC / ADC multi-functional device
+
+ti_tscadc is a multi-function device with touchscreen and ADC on chip.
+This document describes the binding for mfd device.
+
+Required properties:
+- compatible: "ti,ti-tscadc"
+- reg: Specifies the address of MFD block
+- interrupts: IRQ line connected to the main SoC
+- interrupt-parent: The parent interrupt controller
+
+Optional properties:
+- ti,hwmods: Hardware information related to TSC/ADC MFD device
+
+Example:
+
+	tscadc: tscadc at 44e0d000 {
+		compatible = "ti,ti-tscadc";
+		reg = <0x44e0d000 0x1000>;
+
+		interrupt-parent = <&intc>;
+		interrupts = <16>;
+		ti,hwmods = "adc_tsc";
+
+		tsc {
+			wires = <4>;
+			x-plate-resistance = <200>;
+			steps-to-configure = <5>;
+			wire-config = <0x00 0x11 0x22 0x33>;
+		};
+
+		adc {
+			adc-channels = <4>;
+		};
+	};
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 3/8] input: touchscreen: ti_tsc: remove unwanted fifo flush
From: Patil, Rachna @ 2013-01-18 10:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

When touchscreen and ADC are used together, this
unwanted fifo flush leads to loss of ADC data.

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 drivers/input/touchscreen/ti_am335x_tsc.c |   10 ----------
 1 file changed, 10 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 0c460f9..064d2b2 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -308,8 +308,6 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 	unsigned int x = 0, y = 0;
 	unsigned int z1, z2, z;
 	unsigned int fsm;
-	unsigned int fifo1count, fifo0count;
-	int i;
 
 	status = titsc_readl(ts_dev, REG_IRQSTATUS);
 	if (status & IRQENB_FIFO0THRES) {
@@ -318,14 +316,6 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 		z1 = titsc_readl(ts_dev, REG_FIFO0) & 0xfff;
 		z2 = titsc_readl(ts_dev, REG_FIFO1) & 0xfff;
 
-		fifo1count = titsc_readl(ts_dev, REG_FIFO1CNT);
-		for (i = 0; i < fifo1count; i++)
-			titsc_readl(ts_dev, REG_FIFO1);
-
-		fifo0count = titsc_readl(ts_dev, REG_FIFO0CNT);
-		for (i = 0; i < fifo0count; i++)
-			titsc_readl(ts_dev, REG_FIFO0);
-
 		if (ts_dev->pen_down && z1 != 0 && z2 != 0) {
 			/*
 			 * Calculate pressure using formula
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 2/8] input: ti_am335x_tsc: Order of TSC wires, made configurable
From: Patil, Rachna @ 2013-01-18 10:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

The current driver expected touchscreen input
wires(XP,XN,YP,YN) to be connected in a particular order.
Making changes to accept this as platform data.

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 drivers/input/touchscreen/ti_am335x_tsc.c |  156 ++++++++++++++++++++++++++---
 include/linux/input/ti_am335x_tsc.h       |   12 +++
 include/linux/mfd/ti_am335x_tscadc.h      |   10 +-
 3 files changed, 159 insertions(+), 19 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index da652e0..0c460f9 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -33,6 +33,17 @@
 #define SEQ_SETTLE		275
 #define MAX_12BIT		((1 << 12) - 1)
 
+/*
+ * Refer to function regbit_map() to
+ * map the values in the matrix.
+ */
+static int config[4][4] = {
+		{1,	0,	1,	0},
+		{2,	3,	2,	3},
+		{4,	5,	4,	5},
+		{0,	6,	0,	6}
+};
+
 struct titsc {
 	struct input_dev	*input;
 	struct ti_tscadc_dev	*mfd_tscadc;
@@ -42,6 +53,9 @@ struct titsc {
 	unsigned int		enable_bits;
 	bool			pen_down;
 	int			steps_to_configure;
+	int			config_inp[20];
+	int			bit_xp, bit_xn, bit_yp, bit_yn;
+	int			inp_xp, inp_xn, inp_yp, inp_yn;
 };
 
 static unsigned int titsc_readl(struct titsc *ts, unsigned int reg)
@@ -55,6 +69,107 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
 	writel(val, tsc->mfd_tscadc->tscadc_base + reg);
 }
 
+/*
+ * Each of the analog lines are mapped
+ * with one or two register bits,
+ * which can be either pulled high/low
+ * depending on the value to be read.
+ */
+static int regbit_map(int val)
+{
+	int map_bits = 0;
+
+	switch (val) {
+	case 1:
+		map_bits = XPP;
+		break;
+	case 2:
+		map_bits = XNP;
+		break;
+	case 3:
+		map_bits = XNN;
+		break;
+	case 4:
+		map_bits = YPP;
+		break;
+	case 5:
+		map_bits = YPN;
+		break;
+	case 6:
+		map_bits = YNN;
+		break;
+	}
+
+	return map_bits;
+}
+
+static int titsc_config_wires(struct titsc *ts_dev)
+{
+	int		analog_line[10], wire_order[10];
+	int		i, temp_bits, err;
+
+	for (i = 0; i < 4; i++) {
+		/*
+		 * Get the order in which TSC wires are attached
+		 * w.r.t. each of the analog input lines on the EVM.
+		 */
+		analog_line[i] = ts_dev->config_inp[i] & 0xF0;
+		analog_line[i] = analog_line[i] >> 4;
+
+		wire_order[i] = ts_dev->config_inp[i] & 0x0F;
+	}
+
+	for (i = 0; i < 4; i++) {
+		switch (wire_order[i]) {
+		case 0:
+			temp_bits = config[analog_line[i]][0];
+			if (temp_bits == 0) {
+				err = -EINVAL;
+				goto ret;
+			} else {
+				ts_dev->bit_xp = regbit_map(temp_bits);
+				ts_dev->inp_xp = analog_line[i];
+				break;
+			}
+		case 1:
+			temp_bits = config[analog_line[i]][1];
+			if (temp_bits == 0) {
+				err = -EINVAL;
+				goto ret;
+			} else {
+				ts_dev->bit_xn = regbit_map(temp_bits);
+				ts_dev->inp_xn = analog_line[i];
+				break;
+			}
+		case 2:
+			temp_bits = config[analog_line[i]][2];
+			if (temp_bits == 0) {
+				err = -EINVAL;
+				goto ret;
+			} else {
+				ts_dev->bit_yp = regbit_map(temp_bits);
+				ts_dev->inp_yp = analog_line[i];
+				break;
+			}
+		case 3:
+			temp_bits = config[analog_line[i]][3];
+			if (temp_bits == 0) {
+				err = -EINVAL;
+				goto ret;
+			} else {
+				ts_dev->bit_yn = regbit_map(temp_bits);
+				ts_dev->inp_yn = analog_line[i];
+				break;
+			}
+		}
+	}
+
+	return 0;
+
+ret:
+	return err;
+}
+
 static void titsc_step_config(struct titsc *ts_dev)
 {
 	unsigned int	config;
@@ -65,18 +180,18 @@ static void titsc_step_config(struct titsc *ts_dev)
 	total_steps = 2 * ts_dev->steps_to_configure;
 
 	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_AVG_16 | STEPCONFIG_XPP;
+			STEPCONFIG_AVG_16 | ts_dev->bit_xp;
 	switch (ts_dev->wires) {
 	case 4:
-		config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+		config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 		break;
 	case 5:
-		config |= STEPCONFIG_YNN |
-				STEPCONFIG_INP_AN4 | STEPCONFIG_XNN |
-				STEPCONFIG_YPP;
+		config |= ts_dev->bit_yn |
+				STEPCONFIG_INP_AN4 | ts_dev->bit_xn |
+				ts_dev->bit_yp;
 		break;
 	case 8:
-		config |= STEPCONFIG_INP_AN2 | STEPCONFIG_XNN;
+		config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
 		break;
 	}
 
@@ -87,18 +202,18 @@ static void titsc_step_config(struct titsc *ts_dev)
 
 	config = 0;
 	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_AVG_16 | STEPCONFIG_YNN |
+			STEPCONFIG_AVG_16 | ts_dev->bit_yn |
 			STEPCONFIG_INM_ADCREFM | STEPCONFIG_FIFO1;
 	switch (ts_dev->wires) {
 	case 4:
-		config |= STEPCONFIG_YPP;
+		config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 		break;
 	case 5:
-		config |= STEPCONFIG_XPP | STEPCONFIG_INP_AN4 |
-				STEPCONFIG_XNP | STEPCONFIG_YPN;
+		config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 |
+				ts_dev->bit_xn | ts_dev->bit_yp;
 		break;
 	case 8:
-		config |= STEPCONFIG_YPP;
+		config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp);
 		break;
 	}
 
@@ -109,9 +224,9 @@ static void titsc_step_config(struct titsc *ts_dev)
 
 	config = 0;
 	/* Charge step configuration */
-	config = STEPCONFIG_XPP | STEPCONFIG_YNN |
+	config = ts_dev->bit_xp | ts_dev->bit_yn |
 			STEPCHARGE_RFP_XPUL | STEPCHARGE_RFM_XNUR |
-			STEPCHARGE_INM_AN1 | STEPCHARGE_INP_AN1;
+			STEPCHARGE_INM_AN1 | STEPCHARGE_INP(ts_dev->inp_yp);
 
 	titsc_writel(ts_dev, REG_CHARGECONFIG, config);
 	titsc_writel(ts_dev, REG_CHARGEDELAY, CHARGEDLY_OPENDLY);
@@ -119,13 +234,14 @@ static void titsc_step_config(struct titsc *ts_dev)
 	config = 0;
 	/* Configure to calculate pressure */
 	config = STEPCONFIG_MODE_HWSYNC |
-			STEPCONFIG_AVG_16 | STEPCONFIG_YPP |
-			STEPCONFIG_XNN | STEPCONFIG_INM_ADCREFM;
+			STEPCONFIG_AVG_16 | ts_dev->bit_yp |
+			ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
+			STEPCONFIG_INP(ts_dev->inp_xp);
 	titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 1), config);
 	titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 1),
 			STEPCONFIG_OPENDLY);
 
-	config |= STEPCONFIG_INP_AN3 | STEPCONFIG_FIFO1;
+	config |= STEPCONFIG_INP(ts_dev->inp_yn) | STEPCONFIG_FIFO1;
 	titsc_writel(ts_dev, REG_STEPCONFIG(total_steps + 2), config);
 	titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
 			STEPCONFIG_OPENDLY);
@@ -295,6 +411,8 @@ static int titsc_probe(struct platform_device *pdev)
 	ts_dev->wires = pdata->tsc_init->wires;
 	ts_dev->x_plate_resistance = pdata->tsc_init->x_plate_resistance;
 	ts_dev->steps_to_configure = pdata->tsc_init->steps_to_configure;
+	memcpy(ts_dev->config_inp, pdata->tsc_init->wire_config,
+			sizeof(pdata->tsc_init->wire_config));
 
 	err = request_irq(ts_dev->irq, titsc_irq,
 			  0, pdev->dev.driver->name, ts_dev);
@@ -304,6 +422,11 @@ static int titsc_probe(struct platform_device *pdev)
 	}
 
 	titsc_writel(ts_dev, REG_IRQENABLE, IRQENB_FIFO0THRES);
+	err = titsc_config_wires(ts_dev);
+	if (err) {
+		dev_err(&pdev->dev, "wrong i/p wire configuration\n");
+		goto err_free_irq;
+	}
 	titsc_step_config(ts_dev);
 	titsc_writel(ts_dev, REG_FIFO0THR, ts_dev->steps_to_configure);
 
@@ -373,6 +496,7 @@ static int titsc_resume(struct device *dev)
 				0x00);
 		titsc_writel(ts_dev, REG_IRQCLR, IRQENB_HW_PEN);
 	}
+	titsc_config_wires(ts_dev);
 	titsc_step_config(ts_dev);
 	titsc_writel(ts_dev, REG_FIFO0THR,
 			ts_dev->steps_to_configure);
diff --git a/include/linux/input/ti_am335x_tsc.h b/include/linux/input/ti_am335x_tsc.h
index 49269a2..6a66b4d 100644
--- a/include/linux/input/ti_am335x_tsc.h
+++ b/include/linux/input/ti_am335x_tsc.h
@@ -12,12 +12,24 @@
  *			A step configured to read a single
  *			co-ordinate value, can be applied
  *			more number of times for better results.
+ * @wire_config:	Different EVM's could have a different order
+ *			for connecting wires on touchscreen.
+ *			We need to provide an 8 bit number where in
+ *			the 1st four bits represent the analog lines
+ *			and the next 4 bits represent positive/
+ *			negative terminal on that input line.
+ *			Notations to represent the input lines and
+ *			terminals resoectively is as follows:
+ *			AIN0 = 0, AIN1 = 1 and so on till AIN7 = 7.
+ *			XP  = 0, XN = 1, YP = 2, YN = 3.
+ *
  */
 
 struct tsc_data {
 	int wires;
 	int x_plate_resistance;
 	int steps_to_configure;
+	int wire_config[10];
 };
 
 #endif
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index 23e4f33..9624fea 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -72,8 +72,6 @@
 #define STEPCONFIG_INM_ADCREFM	STEPCONFIG_INM(8)
 #define STEPCONFIG_INP_MASK	(0xF << 19)
 #define STEPCONFIG_INP(val)	((val) << 19)
-#define STEPCONFIG_INP_AN2	STEPCONFIG_INP(2)
-#define STEPCONFIG_INP_AN3	STEPCONFIG_INP(3)
 #define STEPCONFIG_INP_AN4	STEPCONFIG_INP(4)
 #define STEPCONFIG_INP_ADCREFM	STEPCONFIG_INP(8)
 #define STEPCONFIG_FIFO1	BIT(26)
@@ -95,7 +93,6 @@
 #define STEPCHARGE_INM_AN1	STEPCHARGE_INM(1)
 #define STEPCHARGE_INP_MASK	(0xF << 19)
 #define STEPCHARGE_INP(val)	((val) << 19)
-#define STEPCHARGE_INP_AN1	STEPCHARGE_INP(1)
 #define STEPCHARGE_RFM_MASK	(3 << 23)
 #define STEPCHARGE_RFM(val)	((val) << 23)
 #define STEPCHARGE_RFM_XNUR	STEPCHARGE_RFM(1)
@@ -117,6 +114,13 @@
 #define CNTRLREG_8WIRE		CNTRLREG_AFE_CTRL(3)
 #define CNTRLREG_TSCENB		BIT(7)
 
+#define XPP			STEPCONFIG_XPP
+#define XNP			STEPCONFIG_XNP
+#define XNN			STEPCONFIG_XNN
+#define YPP			STEPCONFIG_YPP
+#define YPN			STEPCONFIG_YPN
+#define YNN			STEPCONFIG_YNN
+
 #define ADC_CLK			3000000
 #define	MAX_CLK_DIV		7
 #define TOTAL_STEPS		16
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH v3 1/8] input: ti_am335x_tsc: Step enable bits made configurable
From: Patil, Rachna @ 2013-01-18 10:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1358502134.git.rachna@ti.com>

From: "Patil, Rachna" <rachna@ti.com>

Current code has hard coded value written to
step enable bits. Now the bits are updated based
on how many steps are needed to be configured got
from platform data.

The user needs to take care not to exceed
the count more than 16. While using ADC and TSC
one should take care to set this parameter correctly.

Signed-off-by: Patil, Rachna <rachna@ti.com>
---
 drivers/input/touchscreen/ti_am335x_tsc.c |   10 ++++++++--
 include/linux/mfd/ti_am335x_tscadc.h      |    1 -
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
index 51e7b87..da652e0 100644
--- a/drivers/input/touchscreen/ti_am335x_tsc.c
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c
@@ -39,6 +39,7 @@ struct titsc {
 	unsigned int		irq;
 	unsigned int		wires;
 	unsigned int		x_plate_resistance;
+	unsigned int		enable_bits;
 	bool			pen_down;
 	int			steps_to_configure;
 };
@@ -57,6 +58,7 @@ static void titsc_writel(struct titsc *tsc, unsigned int reg,
 static void titsc_step_config(struct titsc *ts_dev)
 {
 	unsigned int	config;
+	unsigned int	stepenable = 0;
 	int i, total_steps;
 
 	/* Configure the Step registers */
@@ -128,7 +130,11 @@ static void titsc_step_config(struct titsc *ts_dev)
 	titsc_writel(ts_dev, REG_STEPDELAY(total_steps + 2),
 			STEPCONFIG_OPENDLY);
 
-	titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+	for (i = 0; i <= (total_steps + 2); i++)
+		stepenable |= 1 << i;
+	ts_dev->enable_bits = stepenable;
+
+	titsc_writel(ts_dev, REG_SE, ts_dev->enable_bits);
 }
 
 static void titsc_read_coordinates(struct titsc *ts_dev,
@@ -250,7 +256,7 @@ static irqreturn_t titsc_irq(int irq, void *dev)
 
 	titsc_writel(ts_dev, REG_IRQSTATUS, irqclr);
 
-	titsc_writel(ts_dev, REG_SE, STPENB_STEPENB_TC);
+	titsc_writel(ts_dev, REG_SE, ts_dev->enable_bits);
 	return IRQ_HANDLED;
 }
 
diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
index c79ad5d..23e4f33 100644
--- a/include/linux/mfd/ti_am335x_tscadc.h
+++ b/include/linux/mfd/ti_am335x_tscadc.h
@@ -47,7 +47,6 @@
 #define STEPENB_MASK		(0x1FFFF << 0)
 #define STEPENB(val)		((val) << 0)
 #define STPENB_STEPENB		STEPENB(0x1FFFF)
-#define STPENB_STEPENB_TC	STEPENB(0x1FFF)
 
 /* IRQ enable */
 #define IRQENB_HW_PEN		BIT(0)
-- 
1.7.9.5

^ permalink raw reply related

* OMAP baseline test results for v3.8-rc3
From: Peter Ujfalusi @ 2013-01-18 10:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1301171841350.14118@utopia.booyaka.com>

Hi Paul,

On 01/17/2013 07:43 PM, Paul Walmsley wrote:
>> The following patch fixes these:
>> https://lkml.org/lkml/2012/12/24/3
> 
> Thanks, I've added that info in the v3.8-rc3 test summary, and moved the
> paragraph to the 'resolved by posted patches' section.

FYI: the patch is now in mainline (3.8-rc4)

-- 
P?ter

^ permalink raw reply

* [PATCH v3 0/8] MFD: ti_am335x_tscadc: DT support and TSC features addition
From: Patil, Rachna @ 2013-01-18 10:44 UTC (permalink / raw)
  To: linux-arm-kernel

From: "Patil, Rachna" <rachna@ti.com>

This patch set is a cumulative set of [1] and [2] sent earlier.

Note that there are no code changes in either of the patch set,
only rebased on top of Linus's v3.8-rc3 tag to make sure that
all the patches apply without any conflicts.

This patch set has been tested on AM335x EVM.

[1] http://www.spinics.net/lists/linux-input/msg23060.html
[2] http://www.spinics.net/lists/linux-input/msg23090.html

Changes in v3:
	No code change.

Changes in v2:
	Patch "input: ti_am335x_tsc: Add variance filter"
	from v1 has been dropped.
	Add MFD device DT node in AM335x EVM.

Patil, Rachna (8):
  input: ti_am335x_tsc: Step enable bits made configurable
  input: ti_am335x_tsc: Order of TSC wires, made configurable
  input: touchscreen: ti_tsc: remove unwanted fifo flush
  MFD: ti_am335x_tscadc: add device tree binding information
  MFD: ti_am335x_tscadc: Add DT support
  input: ti_am335x_tsc: Add DT support
  IIO: ti_am335x_adc: Add DT support
  arm/dts: AM335x-evm: Add TSC/ADC MFD device support

 .../devicetree/bindings/mfd/ti_am335x_tscadc.txt   |   35 +++
 arch/arm/boot/dts/am335x-evm.dts                   |   13 +
 arch/arm/boot/dts/am33xx.dtsi                      |    8 +
 drivers/iio/adc/ti_am335x_adc.c                    |   26 +-
 drivers/input/touchscreen/ti_am335x_tsc.c          |  266 +++++++++++++++++---
 drivers/mfd/ti_am335x_tscadc.c                     |   28 ++-
 include/linux/input/ti_am335x_tsc.h                |   12 +
 include/linux/mfd/ti_am335x_tscadc.h               |   11 +-
 8 files changed, 347 insertions(+), 52 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/ti_am335x_tscadc.txt

-- 
1.7.9.5

^ permalink raw reply

* [PATCH v2 2/2] ARM: uncompress debug support for multiplatform build
From: Russell King - ARM Linux @ 2013-01-18 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201301180847.50913.arnd@arndb.de>

On Fri, Jan 18, 2013 at 08:47:50AM +0000, Arnd Bergmann wrote:
> On Friday 18 January 2013, Shawn Guo wrote:
> > +ENTRY(putc)
> > +       addruart r1, r2, r3
> > +       waituart r3, r1
> > +       senduart r0, r1
> > +       busyuart r3, r1
> > +       mov      pc, lr
> > +ENDPROC(putc)
> 
> Ah, so it actually worked? I was expecting at least some part of
> my code to be wrong ;-) My assembler skills are very much
> lacking and I had not tried it.
> 
> Upon closer inspection, it seems that the CR/LF logic from
> the printascii function is not here, and it probably should be.

No it shouldn't.  The CR/LF handling is already done (so actually
aliasing it to printch in arch/arm/kernel/debug.S will result in
two CRs per LF.

^ permalink raw reply

* [[PATCH v2]] OMAP: omap4-panda: add WiLink shared transport power functions
From: Peter Ujfalusi @ 2013-01-18 10:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130117231608.GP14149@atomide.com>

Hi Tony,

On 01/18/2013 12:16 AM, Tony Lindgren wrote:
> Well we are planning to drop the non-DT support for omap4 as soon as it's
> usable with DT.

Exactly, but right now we do have legacy and legacy should work in order to
help for example Luca to make the final push which allows us to move to DT
only for OMAP4.

> For omap4 we are only carrying SDP and panda support to
> make this transition easier. The only bindings missing AFAIK are wl12xx and
> USB.
>
> If we add this, then it implies we're somehow supporting it, which is not
> the way to go IMHO as we need to get rid of these platform callbacks instead.

IMHO we should keep these boards working as long as we have the legacy board
support for them.

So what is the policy now regarding to 'old' legacy but still used OMAP4 board
files? I think we should still maintain them, but the effort to get rid of
them should be the highest priority.

-- 
P?ter

^ permalink raw reply

* [PATCH 10/14] PCI: tegra: Move PCIe driver to drivers/pci/host
From: Thierry Reding @ 2013-01-18 10:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20130118095620.GA7552@arm.com>

On Fri, Jan 18, 2013 at 09:56:20AM +0000, Andrew Murray wrote:
> On Wed, Jan 09, 2013 at 08:43:10PM +0000, Thierry Reding wrote:
> > Move the PCIe driver from arch/arm/mach-tegra into the drivers/pci/host
> > directory. The motivation is to collect various host controller drivers
> > in the same location in order to facilitate refactoring.
> > 
> > The Tegra PCIe driver has been largely rewritten, both in order to turn
> > it into a proper platform driver and to add MSI (based on code by
> > Krishna Kishore <kthota@nvidia.com>) as well as device tree support.
> > 
> > Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
> 
> [snip]
> 
> > +static int tegra_pcie_enable(struct tegra_pcie *pcie)
> > +{
> > +       struct hw_pci hw;
> > +
> > +       memset(&hw, 0, sizeof(hw));
> > +
> > +       hw.nr_controllers = 1;
> > +       hw.private_data = (void **)&pcie;
> > +       hw.setup = tegra_pcie_setup;
> > +       hw.scan = tegra_pcie_scan_bus;
> > +       hw.map_irq = tegra_pcie_map_irq;
> > +
> > +       pci_common_init(&hw);
> > +
> > +       return 0;
> > +}
> 
> [snip]
> 
> > +static int tegra_pcie_probe(struct platform_device *pdev)
> > +{
> > +       struct device_node *port;
> > +       struct tegra_pcie *pcie;
> > +       int err;
> > +
> > +       pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
> > +       if (!pcie)
> > +               return -ENOMEM;
> > +
> > +       INIT_LIST_HEAD(&pcie->ports);
> > +       pcie->dev = &pdev->dev;
> > +
> > +       err = tegra_pcie_parse_dt(pcie);
> > +       if (err < 0)
> > +               return err;
> > +
> > +       pcibios_min_mem = 0;
> > +
> > +       err = tegra_pcie_get_resources(pcie);
> > +       if (err < 0) {
> > +               dev_err(&pdev->dev, "failed to request resources: %d\n", err);
> > +               return err;
> > +       }
> > +
> > +       err = tegra_pcie_enable_controller(pcie);
> > +       if (err)
> > +               goto put_resources;
> > +
> > +       /* probe root ports */
> > +       for_each_child_of_node(pdev->dev.of_node, port) {
> > +               if (!of_device_is_available(port))
> > +                       continue;
> > +
> > +               err = tegra_pcie_add_port(pcie, port);
> > +               if (err < 0) {
> > +                       dev_err(&pdev->dev, "failed to add port %s: %d\n",
> > +                               port->name, err);
> > +               }
> > +       }
> > +
> > +       /* setup the AFI address translations */
> > +       tegra_pcie_setup_translations(pcie);
> > +
> > +       if (IS_ENABLED(CONFIG_PCI_MSI)) {
> > +               err = tegra_pcie_enable_msi(pcie);
> > +               if (err < 0) {
> > +                       dev_err(&pdev->dev,
> > +                               "failed to enable MSI support: %d\n",
> > +                               err);
> > +                       goto put_resources;
> > +               }
> > +       }
> > +
> > +       err = tegra_pcie_enable(pcie);
> > +       if (err < 0) {
> > +               dev_err(&pdev->dev, "failed to enable PCIe ports: %d\n", err);
> > +               goto disable_msi;
> > +       }
> > +
> > +       platform_set_drvdata(pdev, pcie);
> > +       return 0;
> > +
> > +disable_msi:
> > +       if (IS_ENABLED(CONFIG_PCI_MSI))
> > +               tegra_pcie_disable_msi(pcie);
> > +put_resources:
> > +       tegra_pcie_put_resources(pcie);
> > +       return err;
> > +}
> > +
> 
> [snip]
> 
> > +
> > +static const struct of_device_id tegra_pcie_of_match[] = {
> > +       { .compatible = "nvidia,tegra20-pcie", },
> > +       { },
> > +};
> > +
> > +static struct platform_driver tegra_pcie_driver = {
> > +       .driver = {
> > +               .name = "tegra-pcie",
> > +               .owner = THIS_MODULE,
> > +               .of_match_table = tegra_pcie_of_match,
> > +       },
> > +       .probe = tegra_pcie_probe,
> > +       .remove = tegra_pcie_remove,
> > +};
> > +module_platform_driver(tegra_pcie_driver);
> 
> If you have multiple 'nvidia,tegra20-pcie's in your DT then you will end up
> with multiple calls to tegra_pcie_probe/tegra_pcie_enable/pci_common_init.
> 
> However pci_common_init/pcibios_init_hw assumes it will only ever be called
> once, and will thus result in trying to create multiple busses with the same
> bus number. (The first root bus it creates is always zero provided you haven't
> implemented hw->scan).

Right, I hadn't noticed. There's currently no hardware that actually has
two PCIe host bridges but I wanted to keep the driver properly prepared
in case this ever happened.

Actually I've reimplemented hw->scan, but it still forwards the bus
number setup by pcibios_init_hw() (sys->busnr) to pci_create_root_bus()
so it will still break. I wonder, though, if a better approach would be
to take this number from the bus-range property in DT instead.

> I have a patch for this if you want to fold it into your series? (I see you've
> made changes to bios32 for per-controller data).

I would certainly like to take a look at it.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130118/041e6779/attachment.sig>

^ permalink raw reply

* [PATCH 10/14] PCI: tegra: Move PCIe driver to drivers/pci/host
From: Andrew Murray @ 2013-01-18  9:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1357764194-12677-11-git-send-email-thierry.reding@avionic-design.de>

On Wed, Jan 09, 2013 at 08:43:10PM +0000, Thierry Reding wrote:
> Move the PCIe driver from arch/arm/mach-tegra into the drivers/pci/host
> directory. The motivation is to collect various host controller drivers
> in the same location in order to facilitate refactoring.
> 
> The Tegra PCIe driver has been largely rewritten, both in order to turn
> it into a proper platform driver and to add MSI (based on code by
> Krishna Kishore <kthota@nvidia.com>) as well as device tree support.
> 
> Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>

[snip]

> +static int tegra_pcie_enable(struct tegra_pcie *pcie)
> +{
> +       struct hw_pci hw;
> +
> +       memset(&hw, 0, sizeof(hw));
> +
> +       hw.nr_controllers = 1;
> +       hw.private_data = (void **)&pcie;
> +       hw.setup = tegra_pcie_setup;
> +       hw.scan = tegra_pcie_scan_bus;
> +       hw.map_irq = tegra_pcie_map_irq;
> +
> +       pci_common_init(&hw);
> +
> +       return 0;
> +}

[snip]

> +static int tegra_pcie_probe(struct platform_device *pdev)
> +{
> +       struct device_node *port;
> +       struct tegra_pcie *pcie;
> +       int err;
> +
> +       pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
> +       if (!pcie)
> +               return -ENOMEM;
> +
> +       INIT_LIST_HEAD(&pcie->ports);
> +       pcie->dev = &pdev->dev;
> +
> +       err = tegra_pcie_parse_dt(pcie);
> +       if (err < 0)
> +               return err;
> +
> +       pcibios_min_mem = 0;
> +
> +       err = tegra_pcie_get_resources(pcie);
> +       if (err < 0) {
> +               dev_err(&pdev->dev, "failed to request resources: %d\n", err);
> +               return err;
> +       }
> +
> +       err = tegra_pcie_enable_controller(pcie);
> +       if (err)
> +               goto put_resources;
> +
> +       /* probe root ports */
> +       for_each_child_of_node(pdev->dev.of_node, port) {
> +               if (!of_device_is_available(port))
> +                       continue;
> +
> +               err = tegra_pcie_add_port(pcie, port);
> +               if (err < 0) {
> +                       dev_err(&pdev->dev, "failed to add port %s: %d\n",
> +                               port->name, err);
> +               }
> +       }
> +
> +       /* setup the AFI address translations */
> +       tegra_pcie_setup_translations(pcie);
> +
> +       if (IS_ENABLED(CONFIG_PCI_MSI)) {
> +               err = tegra_pcie_enable_msi(pcie);
> +               if (err < 0) {
> +                       dev_err(&pdev->dev,
> +                               "failed to enable MSI support: %d\n",
> +                               err);
> +                       goto put_resources;
> +               }
> +       }
> +
> +       err = tegra_pcie_enable(pcie);
> +       if (err < 0) {
> +               dev_err(&pdev->dev, "failed to enable PCIe ports: %d\n", err);
> +               goto disable_msi;
> +       }
> +
> +       platform_set_drvdata(pdev, pcie);
> +       return 0;
> +
> +disable_msi:
> +       if (IS_ENABLED(CONFIG_PCI_MSI))
> +               tegra_pcie_disable_msi(pcie);
> +put_resources:
> +       tegra_pcie_put_resources(pcie);
> +       return err;
> +}
> +

[snip]

> +
> +static const struct of_device_id tegra_pcie_of_match[] = {
> +       { .compatible = "nvidia,tegra20-pcie", },
> +       { },
> +};
> +
> +static struct platform_driver tegra_pcie_driver = {
> +       .driver = {
> +               .name = "tegra-pcie",
> +               .owner = THIS_MODULE,
> +               .of_match_table = tegra_pcie_of_match,
> +       },
> +       .probe = tegra_pcie_probe,
> +       .remove = tegra_pcie_remove,
> +};
> +module_platform_driver(tegra_pcie_driver);

If you have multiple 'nvidia,tegra20-pcie's in your DT then you will end up
with multiple calls to tegra_pcie_probe/tegra_pcie_enable/pci_common_init.

However pci_common_init/pcibios_init_hw assumes it will only ever be called
once, and will thus result in trying to create multiple busses with the same
bus number. (The first root bus it creates is always zero provided you haven't
implemented hw->scan).

I have a patch for this if you want to fold it into your series? (I see you've
made changes to bios32 for per-controller data).

Andrew Murray

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox