Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] staging: drm/imx: remove an unnecessary local variable
From: Russell King - ARM Linux @ 2014-02-10 10:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392028185-4528-1-git-send-email-Ying.Liu@freescale.com>

On Mon, Feb 10, 2014 at 06:29:45PM +0800, Liu Ying wrote:
> This patch removes an unnecessary local variable defined
> in the function imx_drm_driver_unload() so as to fix the
> following build warning.
> 
> drivers/staging/imx-drm/imx-drm-core.c: \
> In function ?imx_drm_driver_unload?:
> drivers/staging/imx-drm/imx-drm-core.c:87:25: \
> warning: unused variable ?imxdrm? [-Wunused-variable]

Already-Naked-by: me.  This is required by later patches in the series
posted earlier.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

^ permalink raw reply

* [PATCH v6 1/3] ARM: EXYNOS: Add support for EXYNOS5410 SoC
From: Sachin Kamat @ 2014-02-10 10:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026911-21308-2-git-send-email-t.dakhran@samsung.com>

Hi Tarek,

Nothing in specific about the patch, but to just make you aware that
some clean up
patches haves been proposed which might cause conflicts with this patch. Please
see inline for details.

On 10 February 2014 15:38, Tarek Dakhran <t.dakhran@samsung.com> wrote:
> EXYNOS5410 is SoC in Samsung's Exynos5 SoC series.
> Add initial support for this SoC.
>
> Signed-off-by: Tarek Dakhran <t.dakhran@samsung.com>
> Signed-off-by: Vyacheslav Tyrtov <v.tyrtov@samsung.com>
> Reviewed-by: Tomasz Figa <t.figa@samsung.com>
> ---
>  arch/arm/mach-exynos/Kconfig                 |   10 ++++++++++
>  arch/arm/mach-exynos/common.c                |   18 ++++++++++++++++++
>  arch/arm/mach-exynos/include/mach/map.h      |    1 +
>  arch/arm/mach-exynos/mach-exynos5-dt.c       |    1 +
>  arch/arm/mach-exynos/platsmp.c               |    2 ++
>  arch/arm/plat-samsung/include/plat/cpu.h     |    8 ++++++++
>  arch/arm/plat-samsung/include/plat/map-s5p.h |    3 +++
>  7 files changed, 43 insertions(+)
>
> diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
> index 4c414af..97a06c3 100644
> --- a/arch/arm/mach-exynos/Kconfig
> +++ b/arch/arm/mach-exynos/Kconfig
> @@ -91,6 +91,16 @@ config SOC_EXYNOS5250
>         help
>           Enable EXYNOS5250 SoC support
>
> +config SOC_EXYNOS5410
> +       bool "SAMSUNG EXYNOS5410"
> +       default y
> +       depends on ARCH_EXYNOS5
> +       select PM_GENERIC_DOMAINS if PM
> +       select S5P_PM if PM_SLEEP
> +       select S5P_SLEEP if PM_SLEEP
> +       help
> +         Enable EXYNOS5410 SoC support
> +

Per SoC Kconfig entries are proposed to be removed. Please see [1].

>  config SOC_EXYNOS5420
>         bool "SAMSUNG EXYNOS5420"
>         default y
> diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
> index f18be40..f1483bd 100644
> --- a/arch/arm/mach-exynos/common.c
> +++ b/arch/arm/mach-exynos/common.c
> @@ -52,6 +52,7 @@ static const char name_exynos4210[] = "EXYNOS4210";
>  static const char name_exynos4212[] = "EXYNOS4212";
>  static const char name_exynos4412[] = "EXYNOS4412";
>  static const char name_exynos5250[] = "EXYNOS5250";
> +static const char name_exynos5410[] = "EXYNOS5410";
>  static const char name_exynos5420[] = "EXYNOS5420";
>  static const char name_exynos5440[] = "EXYNOS5440";
>
> @@ -85,6 +86,12 @@ static struct cpu_table cpu_ids[] __initdata = {
>                 .init           = exynos_init,
>                 .name           = name_exynos5250,
>         }, {
> +               .idcode         = EXYNOS5410_SOC_ID,
> +               .idmask         = EXYNOS5_SOC_MASK,
> +               .map_io         = exynos5_map_io,
> +               .init           = exynos_init,
> +               .name           = name_exynos5410,
> +       }, {

This is also proposed to be removed. Please see [2].

[1] http://comments.gmane.org/gmane.linux.kernel.samsung-soc/26800
[2] http://comments.gmane.org/gmane.linux.kernel.samsung-soc/26560

-- 
With warm regards,
Sachin

^ permalink raw reply

* [PATCH 00/17] amba: PM fixups for amba bus and some amba drivers
From: Ulf Hansson @ 2014-02-10 10:25 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140204184909.GT22609@sirena.org.uk>

On 4 February 2014 19:49, Mark Brown <broonie@kernel.org> wrote:
> On Tue, Feb 04, 2014 at 04:58:41PM +0100, Ulf Hansson wrote:
>
>> The fixes for the amba bus needs to be merged prior to the other, thus I think
>> it could make sense to merge this complete patchset through Russell's tree,
>> if he and the other maintainers think this is okay.
>
> What are the actual dependencies for the SPI bit?  AFAICT it's probably
> the first patch needs the bus updating?

Correct!

At this point I thought it made sense to collect all this patches,
since it adopts to use the new SET_PM_RUNTIME_PM_OPS macro from the PM
core.

In principle I wanted to visualize in one go how driver's system
suspend|resume callbacks could be implemented for three similar
scenarios.

Kind regards
Ulf Hansson

^ permalink raw reply

* [PATCH 5/8] tty/serial: at91: add dtr control via gpio
From: Richard Genoud @ 2014-02-10 10:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391786494.259974704@f81.i.mail.ru>

2014-02-07 16:21 GMT+01:00 Alexander Shiyan <shc_work@mail.ru>:
> Hello.
>
> ???????,  7 ??????? 2014, 15:59 +01:00 ?? Richard Genoud <richard.genoud@gmail.com>:
>> On sam9x5, the USART controller doesn't handle DTR/DSR/DCD/RI signals,
>> so we have to control them via GPIO.
>>
>> This patch permits to use a GPIO to control the DTR signal.
>>
>> Signed-off-by: Richard Genoud <richard.genoud@gmail.com>
>> ---
> ...
>> +     if (gpio_is_valid(atmel_port->gpio.dtr)) {
>> +             if (mctrl & TIOCM_DTR)
>> +                     gpio_set_value(atmel_port->gpio.dtr, 0);
>> +             else
>> +                     gpio_set_value(atmel_port->gpio.dtr, 1);
>> +     }
>
> So, if you use GPIO for such purpose (here and in the other patches),
> you should take and use GPIO active level from bindings.
> It will make use of GPIO more flexible and deliver us from further special
> possible bindings to declare the active level.
Yes, I could do that. I'll have to change the alreday merged RTS
binding so that it gets it's active level from DTS, but I don't think
it's a problem, since it's not already in mainline.
Linus, Nicolas, what do you think ?

> Actually, it would be good to have a separate unit for mctrl GPIOs,
> which could be used for other drivers.
good idea, I can add them in serial_core.c

Thanks!

Richard.

^ permalink raw reply

* [PATCH resend] pwm: Remove obsolete HAVE_PWM Kconfig symbol
From: Thierry Reding @ 2014-02-10 10:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390550056-5924-1-git-send-email-s.hauer@pengutronix.de>

On Fri, Jan 24, 2014 at 08:54:16AM +0100, Sascha Hauer wrote:
> Before we had the PWM framework we used to have a barebone PWM api. The
> HAVE_PWM Kconfig symbol used to be selected by the PWM drivers to specify
> the PWM API is present in the kernel. Since the last legacy driver is gone
> the HAVE_PWM symbol can go aswell.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> Cc: Eric Miao <eric.y.miao@gmail.com>
> Cc: Haojian Zhuang <haojian.zhuang@gmail.com>
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-kernel at vger.kernel.org
> Cc: Thierry Reding <thierry.reding@gmail.com>
> Cc: linux-pwm at vger.kernel.orig
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Ralf Baechle <ralf@linux-mips.org>
> ---
> 
> Thierry as PWM maintainer has agreed to take this patch. Would be nice
> to get some Acks from affected architectures. Russell, Ralf?

No replies for over two weeks and this looks simple enough, so I just
went ahead and applied it. Thanks,

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/20140210/f772649b/attachment.sig>

^ permalink raw reply

* [RFC PATCH] i2c: new bus driver for efm32
From: Uwe Kleine-König @ 2014-02-10 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

This was tested on a EFM32GG-DK3750 devboard that has a temperature
sensor and an eeprom on its i2c bus.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
Hello,

there are two places marked with a triple-X where I don't know if I did
it right. The one is "Do I need to protect from .master_xfer being
called again before the previous call returned?" The other is what to
return in the .functionality callback.

Also note there is a matching entry in MAINTAINERS for "ARM/ENERGY MICRO
(SILICON LABS) EFM32 SUPPORT".

Best regards
Uwe

 drivers/i2c/busses/Kconfig              |   7 +
 drivers/i2c/busses/Makefile             |   1 +
 drivers/i2c/busses/i2c-efm32.c          | 527 ++++++++++++++++++++++++++++++++
 include/linux/platform_data/efm32-i2c.h |  15 +
 4 files changed, 550 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-efm32.c
 create mode 100644 include/linux/platform_data/efm32-i2c.h

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index f5ed03164d86..7322ff0c4c60 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -432,6 +432,13 @@ config I2C_DESIGNWARE_PCI
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-designware-pci.
 
+config I2C_EFM32
+	tristate "EFM32 I2C controller"
+	depends on OF && (ARCH_EFM32 || COMPILE_TEST)
+	help
+	  This driver supports the i2c block found in Energy Micro's EFM32
+	  SoCs.
+
 config I2C_EG20T
 	tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
 	depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index a08931fe73e1..2a56ab181851 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)	+= i2c-designware-platform.o
 i2c-designware-platform-objs := i2c-designware-platdrv.o
 obj-$(CONFIG_I2C_DESIGNWARE_PCI)	+= i2c-designware-pci.o
 i2c-designware-pci-objs := i2c-designware-pcidrv.o
+obj-$(CONFIG_I2C_EFM32)		+= i2c-efm32.o
 obj-$(CONFIG_I2C_EG20T)		+= i2c-eg20t.o
 obj-$(CONFIG_I2C_EXYNOS5)	+= i2c-exynos5.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
new file mode 100644
index 000000000000..9e860abcab63
--- /dev/null
+++ b/drivers/i2c/busses/i2c-efm32.c
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2014 Uwe Kleine-Koenig for Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/platform_data/efm32-i2c.h>
+
+#define DRIVER_NAME "efm32-i2c"
+
+#define MASK_VAL(mask, val)		((val << __ffs(mask)) & mask)
+
+#define REG_CTRL		0x00
+#define REG_CTRL_EN			0x00001
+#define REG_CTRL_SLAVE			0x00002
+#define REG_CTRL_AUTOACK		0x00004
+#define REG_CTRL_AUTOSE			0x00008
+#define REG_CTRL_AUTOSN			0x00010
+#define REG_CTRL_ARBDIS			0x00020
+#define REG_CTRL_GCAMEN			0x00040
+#define REG_CTRL_CLHR__MASK		0x00300
+#define REG_CTRL_BITO__MASK		0x03000
+#define REG_CTRL_BITO_OFF		0x00000
+#define REG_CTRL_BITO_40PCC		0x01000
+#define REG_CTRL_BITO_80PCC		0x02000
+#define REG_CTRL_BITO_160PCC		0x03000
+#define REG_CTRL_GIBITO			0x08000
+#define REG_CTRL_CLTO__MASK		0x70000
+#define REG_CTRL_CLTO_OFF		0x00000
+
+#define REG_CMD			0x04
+#define REG_CMD_START			0x00001
+#define REG_CMD_STOP			0x00002
+#define REG_CMD_ACK			0x00004
+#define REG_CMD_NACK			0x00008
+#define REG_CMD_CONT			0x00010
+#define REG_CMD_ABORT			0x00020
+#define REG_CMD_CLEARTX			0x00040
+#define REG_CMD_CLEARPC			0x00080
+
+#define REG_STATE		0x08
+#define REG_STATE_BUSY			0x00001
+#define REG_STATE_MASTER		0x00002
+#define REG_STATE_TRANSMITTER		0x00004
+#define REG_STATE_NACKED		0x00008
+#define REG_STATE_BUSHOLD		0x00010
+#define REG_STATE_STATE__MASK		0x000e0
+#define REG_STATE_STATE_IDLE		0x00000
+#define REG_STATE_STATE_WAIT		0x00020
+#define REG_STATE_STATE_START		0x00040
+#define REG_STATE_STATE_ADDR		0x00060
+#define REG_STATE_STATE_ADDRACK		0x00080
+#define REG_STATE_STATE_DATA		0x000a0
+#define REG_STATE_STATE_DATAACK		0x000c0
+
+#define REG_STATUS		0x0c
+#define REG_STATUS_PSTART		0x00001
+#define REG_STATUS_PSTOP		0x00002
+#define REG_STATUS_PACK			0x00004
+#define REG_STATUS_PNACK		0x00008
+#define REG_STATUS_PCONT		0x00010
+#define REG_STATUS_PABORT		0x00020
+#define REG_STATUS_TXC			0x00040
+#define REG_STATUS_TXBL			0x00080
+#define REG_STATUS_RXDATAV		0x00100
+
+#define REG_CLKDIV		0x10
+#define REG_CLKDIV_DIV__MASK		0x001ff
+#define REG_CLKDIV_DIV(div)		MASK_VAL(REG_CLKDIV_DIV__MASK, (div))
+
+#define REG_SADDR		0x14
+#define REG_SADDRMASK		0x18
+#define REG_RXDATA		0x1c
+#define REG_RXDATAP		0x20
+#define REG_TXDATA		0x24
+#define REG_IF			0x28
+#define REG_IF_START			0x00001
+#define REG_IF_RSTART			0x00002
+#define REG_IF_ADDR			0x00004
+#define REG_IF_TXC			0x00008
+#define REG_IF_TXBL			0x00010
+#define REG_IF_RXDATAV			0x00020
+#define REG_IF_ACK			0x00040
+#define REG_IF_NACK			0x00080
+#define REG_IF_MSTOP			0x00100
+#define REG_IF_ARBLOST			0x00200
+#define REG_IF_BUSERR			0x00400
+#define REG_IF_BUSHOLD			0x00800
+#define REG_IF_TXOF			0x01000
+#define REG_IF_RXUF			0x02000
+#define REG_IF_BITO			0x04000
+#define REG_IF_CLTO			0x08000
+#define REG_IF_SSTOP			0x10000
+
+#define REG_IFS			0x2c
+#define REG_IFC			0x30
+#define REG_IFC__MASK			0x1ffcf
+
+#define REG_IEN			0x34
+
+#define REG_ROUTE		0x38
+#define REG_ROUTE_SDAPEN		0x00001
+#define REG_ROUTE_SCLPEN		0x00002
+#define REG_ROUTE_LOCATION__MASK	0x00700
+#define REG_ROUTE_LOCATION(n)		MASK_VAL(REG_ROUTE_LOCATION__MASK, (n))
+
+struct efm32_i2c_ddata {
+	struct i2c_adapter adapter;
+	spinlock_t lock;
+
+	struct clk *clk;
+	void __iomem *base;
+	unsigned int irq;
+	struct efm32_i2c_pdata pdata;
+
+	/* transfer data */
+	struct completion done;
+	struct i2c_msg *msgs;
+	size_t num_msgs;
+	size_t current_word, current_msg;
+};
+
+static u32 efm32_i2c_read32(struct efm32_i2c_ddata *ddata, unsigned offset)
+{
+	return readl(ddata->base + offset);
+}
+
+static void efm32_i2c_write32(struct efm32_i2c_ddata *ddata,
+		unsigned offset, u32 value)
+{
+	writel(value, ddata->base + offset);
+}
+
+static void efm32_i2c_send_next_msg(struct efm32_i2c_ddata *ddata)
+{
+	struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
+
+	dev_dbg(&ddata->adapter.dev, "send msg %zu/%zu (addr = %x, flags = %x, if = %08x)\n",
+			ddata->current_msg, ddata->num_msgs, cur_msg->addr,
+			cur_msg->flags, efm32_i2c_read32(ddata, REG_IF));
+	efm32_i2c_write32(ddata, REG_CMD, REG_CMD_START);
+	efm32_i2c_write32(ddata, REG_TXDATA, cur_msg->addr << 1 |
+			(cur_msg->flags & I2C_M_RD ? 1 : 0));
+}
+
+static void efm32_i2c_send_next_byte(struct efm32_i2c_ddata *ddata)
+{
+	struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
+	dev_dbg(&ddata->adapter.dev, "%s, %zu %zu\n",
+			__func__, ddata->current_word, cur_msg->len);
+	if (ddata->current_word >= cur_msg->len) {
+		/* cur_msg completely transferred */
+		ddata->current_word = 0;
+		ddata->current_msg += 1;
+
+		if (ddata->current_msg >= ddata->num_msgs) {
+			dev_dbg(&ddata->adapter.dev, "Stop\n");
+			efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
+			complete(&ddata->done);
+		} else {
+			efm32_i2c_send_next_msg(ddata);
+		}
+	} else {
+		dev_dbg(&ddata->adapter.dev, "send byte %zu/%zu\n",
+				ddata->current_word, cur_msg->len);
+		efm32_i2c_write32(ddata, REG_TXDATA,
+				cur_msg->buf[ddata->current_word++]);
+	}
+}
+
+static void efm32_i2c_recv_next_byte(struct efm32_i2c_ddata *ddata)
+{
+	struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
+
+	cur_msg->buf[ddata->current_word] = efm32_i2c_read32(ddata, REG_RXDATA);
+	dev_dbg(&ddata->adapter.dev, "recv byte %zu/%zu: 0x%02hhx\n",
+			ddata->current_word, cur_msg->len, cur_msg->buf[ddata->current_word]);
+	ddata->current_word += 1;
+	if (ddata->current_word >= cur_msg->len) {
+		/* cur_msg completely transferred */
+		ddata->current_word = 0;
+		ddata->current_msg += 1;
+
+		efm32_i2c_write32(ddata, REG_CMD, REG_CMD_NACK);
+
+		if (ddata->current_msg >= ddata->num_msgs) {
+			efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
+			complete(&ddata->done);
+		} else {
+			efm32_i2c_send_next_msg(ddata);
+		}
+	} else {
+		efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ACK);
+	}
+}
+
+static irqreturn_t efm32_i2c_irq(int irq, void *dev_id)
+{
+	struct efm32_i2c_ddata *ddata = dev_id;
+	struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
+	u32 irqflag = efm32_i2c_read32(ddata, REG_IF);
+	u32 state = efm32_i2c_read32(ddata, REG_STATE);
+
+	dev_dbg(&ddata->adapter.dev, "irq: if: %08x, state: %08x, status: %08x\n",
+			irqflag, state, efm32_i2c_read32(ddata, REG_STATUS));
+	efm32_i2c_write32(ddata, REG_IFC, irqflag & REG_IFC__MASK);
+
+	switch (state & REG_STATE_STATE__MASK) {
+	case REG_STATE_STATE_IDLE:
+		/* arbitration lost? */
+		complete(&ddata->done);
+		break;
+	case REG_STATE_STATE_WAIT:
+		/* huh, this shouldn't happen */
+		BUG();
+		break;
+	case REG_STATE_STATE_START:
+		/* "caller" is expected to send an address */
+		break;
+	case REG_STATE_STATE_ADDR:
+		/* wait for Ack or NAck of slave */
+		break;
+	case REG_STATE_STATE_ADDRACK:
+		if (state & REG_STATE_NACKED) {
+			efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
+			complete(&ddata->done);
+		} else if (cur_msg->flags & I2C_M_RD) {
+			/* wait for slave to send first data byte */
+		} else {
+			efm32_i2c_send_next_byte(ddata);
+		}
+		break;
+	case REG_STATE_STATE_DATA:
+		if (cur_msg->flags & I2C_M_RD) {
+			efm32_i2c_recv_next_byte(ddata);
+		} else {
+			/* wait for Ack or Nack of slave */
+		}
+		break;
+	case REG_STATE_STATE_DATAACK:
+		if (state & REG_STATE_NACKED) {
+			efm32_i2c_write32(ddata, REG_CMD, REG_CMD_STOP);
+			complete(&ddata->done);
+		} else {
+			efm32_i2c_send_next_byte(ddata);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int efm32_i2c_master_xfer(struct i2c_adapter *adap,
+		struct i2c_msg *msgs, int num)
+{
+	struct efm32_i2c_ddata *ddata = i2c_get_adapdata(adap);
+	int ret = -EBUSY;
+
+	spin_lock_irq(&ddata->lock);
+
+	if (ddata->msgs)
+		/*
+		 * XXX: can .master_xfer be called when the previous is still
+		 * running?
+		 */
+		goto out_unlock;
+
+	ddata->msgs = msgs;
+	ddata->num_msgs = num;
+	ddata->current_word = 0;
+	ddata->current_msg = 0;
+
+	init_completion(&ddata->done);
+
+	dev_dbg(&ddata->adapter.dev, "state: %08x, status: %08x\n",
+			efm32_i2c_read32(ddata, REG_STATE),
+			efm32_i2c_read32(ddata, REG_STATUS));
+
+	efm32_i2c_send_next_msg(ddata);
+
+	spin_unlock_irq(&ddata->lock);
+
+	wait_for_completion(&ddata->done);
+
+	spin_lock_irq(&ddata->lock);
+
+	if (ddata->current_msg >= ddata->num_msgs)
+		ret = ddata->num_msgs;
+	else
+		ret = -EIO;
+
+	ddata->msgs = NULL;
+
+out_unlock:
+	spin_unlock_irq(&ddata->lock);
+	return ret;
+}
+
+static u32 efm32_i2c_functionality(struct i2c_adapter *adap)
+{
+	/* XXX: some more? */
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm efm32_i2c_algo = {
+	.master_xfer = efm32_i2c_master_xfer,
+	.functionality = efm32_i2c_functionality,
+};
+
+static u32 efm32_i2c_get_configured_location(struct efm32_i2c_ddata *ddata)
+{
+	u32 reg = efm32_i2c_read32(ddata, REG_ROUTE);
+
+	return (reg & REG_ROUTE_LOCATION__MASK) >>
+		__ffs(REG_ROUTE_LOCATION__MASK);
+}
+
+static int efm32_i2c_probe_dt(struct platform_device *pdev,
+		struct efm32_i2c_ddata *ddata)
+{
+	struct device_node *np = pdev->dev.of_node;
+	u32 location, frequency;
+	int ret;
+
+	if (!np)
+		return 1;
+
+	ret = of_property_read_u32(np, "location", &location);
+	if (!ret) {
+		dev_dbg(&pdev->dev, "using location %u\n", location);
+	} else {
+		/* default to location configured in hardware */
+		location = efm32_i2c_get_configured_location(ddata);
+
+		dev_info(&pdev->dev, "fall back to location %u\n", location);
+	}
+
+	ddata->pdata.location = location;
+
+	ret = of_property_read_u32(np, "clock-frequency", &frequency);
+	if (!ret) {
+		dev_dbg(&pdev->dev, "using frequency %u\n", frequency);
+	} else {
+		frequency = 100000;
+		dev_info(&pdev->dev, "defaulting to 100 kHz\n");
+	}
+	ddata->pdata.frequency = frequency;
+
+	/* i2c core takes care about bus numbering using an alias */
+	ddata->adapter.nr = -1;
+
+	return 0;
+}
+
+static int efm32_i2c_probe(struct platform_device *pdev)
+{
+	struct efm32_i2c_ddata *ddata;
+	struct resource *res;
+	unsigned long rate;
+	int ret;
+	u32 clkdiv;
+
+	ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata) {
+		dev_dbg(&pdev->dev, "failed to allocate private data\n");
+		return -ENOMEM;
+	}
+	platform_set_drvdata(pdev, ddata);
+
+	strlcpy(ddata->adapter.name, pdev->name, sizeof(ddata->adapter.name));
+	ddata->adapter.owner = THIS_MODULE;
+	ddata->adapter.algo = &efm32_i2c_algo;
+	ddata->adapter.dev.parent = &pdev->dev;
+	ddata->adapter.dev.of_node = pdev->dev.of_node;
+	i2c_set_adapdata(&ddata->adapter, ddata);
+
+	spin_lock_init(&ddata->lock);
+
+	ddata->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ddata->clk)) {
+		ret = PTR_ERR(ddata->clk);
+		dev_err(&pdev->dev, "failed to get clock: %d\n", ret);
+		return ret;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "failed to determine base address\n");
+		return -ENODEV;
+	}
+
+	if (resource_size(res) < 0x42) {
+		dev_err(&pdev->dev, "memory resource too small\n");
+		return -EINVAL;
+	}
+
+	ddata->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(ddata->base))
+		return PTR_ERR(ddata->base);
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret <= 0) {
+		dev_err(&pdev->dev, "failed to get irq (%d)\n", ret);
+		if (!ret)
+			ret = -EINVAL;
+		return ret;
+	}
+
+	ddata->irq = ret;
+
+	ret = clk_prepare_enable(ddata->clk);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to enable clock (%d)\n", ret);
+		return ret;
+	}
+
+	ret = efm32_i2c_probe_dt(pdev, ddata);
+	if (ret > 0) {
+		/* not created by device tree */
+		const struct efm32_i2c_pdata *pdata =
+			dev_get_platdata(&pdev->dev);
+
+		if (pdata)
+			ddata->pdata = *pdata;
+		else {
+			ddata->pdata.location =
+				efm32_i2c_get_configured_location(ddata);
+			ddata->pdata.frequency = 100000;
+		}
+
+		ddata->adapter.nr = pdev->id;
+	} else if (ret < 0) {
+		goto err_disable_clk;
+	}
+
+	rate = clk_get_rate(ddata->clk);
+	if (!rate) {
+		dev_err(&pdev->dev, "there is no input clock available\n");
+		ret = -EIO;
+		goto err_disable_clk;
+	}
+	clkdiv = DIV_ROUND_UP(rate, 8 * ddata->pdata.frequency) - 1;
+	if (clkdiv >= 0x200) {
+		dev_err(&pdev->dev,
+				"input clock too fast (%lu) to divide down to bus freq (%lu)",
+				rate, ddata->pdata.frequency);
+		ret = -EIO;
+		goto err_disable_clk;
+	}
+
+	dev_dbg(&pdev->dev, "input clock = %lu, bus freq = %lu, clkdiv = %lu\n",
+			rate, ddata->pdata.frequency, (unsigned long)clkdiv);
+	efm32_i2c_write32(ddata, REG_CLKDIV, REG_CLKDIV_DIV(clkdiv));
+
+	efm32_i2c_write32(ddata, REG_ROUTE, REG_ROUTE_SDAPEN |
+			REG_ROUTE_SCLPEN |
+			REG_ROUTE_LOCATION(ddata->pdata.location));
+
+	efm32_i2c_write32(ddata, REG_CTRL, REG_CTRL_EN |
+			REG_CTRL_BITO_160PCC | 0 * REG_CTRL_GIBITO);
+
+	efm32_i2c_write32(ddata, REG_IFC, REG_IFC__MASK);
+	efm32_i2c_write32(ddata, REG_IEN, REG_IF_TXC | REG_IF_ACK | REG_IF_NACK
+			| REG_IF_ARBLOST | REG_IF_BUSERR | REG_IF_RXDATAV);
+
+	/* to make bus idle */
+	efm32_i2c_write32(ddata, REG_CMD, REG_CMD_ABORT);
+
+	ret = request_irq(ddata->irq, efm32_i2c_irq, 0, DRIVER_NAME, ddata);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to request irq (%d)\n", ret);
+		return ret;
+	}
+
+	ret = i2c_add_numbered_adapter(&ddata->adapter);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add i2c adapter (%d)\n", ret);
+		free_irq(ddata->irq, ddata);
+
+err_disable_clk:
+		clk_disable_unprepare(ddata->clk);
+	}
+	return ret;
+}
+
+static int efm32_i2c_remove(struct platform_device *pdev)
+{
+	struct efm32_i2c_ddata *ddata = platform_get_drvdata(pdev);
+
+	free_irq(ddata->irq, ddata);
+	clk_disable_unprepare(ddata->clk);
+
+	return 0;
+}
+
+static const struct of_device_id efm32_i2c_dt_ids[] = {
+	{
+		.compatible = "efm32,i2c",
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(of, efm32_i2c_dt_ids);
+
+static struct platform_driver efm32_i2c_driver = {
+	.probe = efm32_i2c_probe,
+	.remove = efm32_i2c_remove,
+
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = efm32_i2c_dt_ids,
+	},
+};
+module_platform_driver(efm32_i2c_driver);
+
+MODULE_AUTHOR("Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>");
+MODULE_DESCRIPTION("EFM32 i2c driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/include/linux/platform_data/efm32-i2c.h b/include/linux/platform_data/efm32-i2c.h
new file mode 100644
index 000000000000..5e175db68bb6
--- /dev/null
+++ b/include/linux/platform_data/efm32-i2c.h
@@ -0,0 +1,15 @@
+#ifndef __LINUX_PLATFORM_DATA_EFM32_I2C_H__
+#define __LINUX_PLATFORM_DATA_EFM32_I2C_H__
+
+#include <linux/types.h>
+
+/**
+ * struct efm32_i2c_pdata
+ * @location: pinmux location for the I/O pins (to be written to the ROUTE
+ * 	register)
+ */
+struct efm32_i2c_pdata {
+	u8 location;
+	unsigned long frequency; /* in Hz */
+};
+#endif /* ifndef __LINUX_PLATFORM_DATA_EFM32_I2C_H__ */
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH 14/17] i2c: nomadik: Fixup deployment of runtime PM
From: Ulf Hansson @ 2014-02-10 10:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAOMZO5CzUuQrmbk6FpFGR56jHBtW-1d_AGcdgB2xyMG0Nkf+Fw@mail.gmail.com>

On 5 February 2014 15:45, Fabio Estevam <festevam@gmail.com> wrote:
> On Tue, Feb 4, 2014 at 1:58 PM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
>> +static int nmk_i2c_runtime_resume(struct device *dev)
>> +{
>> +       struct amba_device *adev = to_amba_device(dev);,
>> +       struct nmk_i2c_dev *nmk_i2c = amba_get_drvdata(adev);
>> +
>> +       clk_prepare_enable(nmk_i2c->clk);
>
> Previously the code was checking the return value from
> clk_prepare_enable(). You should keep the check here.

Will fix in v2! Thanks for reviewing!

Kind regards
Ulf Hansson

>
> Regards,
>
> Fabio Estevam

^ permalink raw reply

* [PATCH 14/17] i2c: nomadik: Fixup deployment of runtime PM
From: Ulf Hansson @ 2014-02-10 10:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdZwoXf5ovmQEAN6Ugvz91+_i5uGqStR3MGXQeJGHitj3Q@mail.gmail.com>

On 5 February 2014 15:34, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Tue, Feb 4, 2014 at 4:58 PM, Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
>> Since the device is active while a successful probe has been completed,
>> the reference counting for the clock will be screwed up and never reach
>> zero.
>>
>> The issue is resolved by implementing runtime PM callbacks and let them
>> handle the resources accordingly, including the clock.
>>
>> Cc: Alessandro Rubini <rubini@unipv.it>
>> Cc: Linus Walleij <linus.walleij@linaro.org>
>> Cc: Wolfram Sang <wsa@the-dreams.de>
>> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
>
> Hm do I read it right as patch 13 breaks runtime PM by leaving
> the device active after probe() and this patch
> 14 fixes it again? Maybe these two patches should be squashed
> then.

You are right; but the driver will still be working, you just don't
get the benefit from inactivating the device at request inactivity -
as you pointed out.

The reason for why I wanted to do this as separate steps was to make
it easier for reviewing, otherwise the patch(es) would have been quite
big and messy. I am for sure open to  adopt to your proposal, but just
wanted to give you some more background, before I go ahead and send a
v2.

Kind regards
Ulf Hansson

>
> Yours,
> Linus Walleij

^ permalink raw reply

* [PATCHv2 2/2] arm: Get rid of meminfo
From: Catalin Marinas @ 2014-02-10 10:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52F846AE.3050800@codeaurora.org>

On Mon, Feb 10, 2014 at 03:25:34AM +0000, Laura Abbott wrote:
> On 2/6/2014 6:09 PM, Courtney Cavin wrote:
> > On Wed, Feb 05, 2014 at 01:02:31AM +0100, Laura Abbott wrote:
> >> memblock is now fully integrated into the kernel and is the prefered
> >> method for tracking memory. Rather than reinvent the wheel with
> >> meminfo, migrate to using memblock directly instead of meminfo as
> >> an intermediate.
> >>
> >> Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
> > [...]
> >> diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
> >> index 0b11c1a..51d814e 100644
> >> --- a/arch/arm/mach-pxa/spitz.c
> >> +++ b/arch/arm/mach-pxa/spitz.c
> >> @@ -32,6 +32,7 @@
> >>   #include <linux/io.h>
> >>   #include <linux/module.h>
> >>   #include <linux/reboot.h>
> >> +#include <linux/memblock.h>
> >>
> >>   #include <asm/setup.h>
> >>   #include <asm/mach-types.h>
> >> @@ -971,13 +972,9 @@ static void __init spitz_init(void)
> >>          spitz_i2c_init();
> >>   }
> >>
> >> -static void __init spitz_fixup(struct tag *tags, char **cmdline,
> >> -                              struct meminfo *mi)
> >> +static void __init spitz_fixup(struct tag *tags, char **cmdline)
> >>   {
> >> -       sharpsl_save_param();
> >> -       mi->nr_banks = 1;
> >> -       mi->bank[0].start = 0xa0000000;
> >> -       mi->bank[0].size = (64*1024*1024);
> >> +       memblock_addr(0xa0000000, SZ_64M);
> >
> > memblock_add() ?
> Yes, that was a typo on my part. I'll send out a v3 with collected acks.

And better testing ;)

-- 
Catalin

^ permalink raw reply

* [PATCH v6 3/3] arm: dts: keystone: add keystone timer entry
From: Ivan Khoronzhuk @ 2014-02-10 10:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392027058-11680-1-git-send-email-ivan.khoronzhuk@ti.com>

Add keystone timer entry to keystone device tree.
This 64-bit timer is used as backup clock event device.

Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
---
 arch/arm/boot/dts/keystone-clocks.dtsi | 10 ++++++++++
 arch/arm/boot/dts/keystone.dtsi        |  7 +++++++
 2 files changed, 17 insertions(+)

diff --git a/arch/arm/boot/dts/keystone-clocks.dtsi b/arch/arm/boot/dts/keystone-clocks.dtsi
index 2363593..16d2aba 100644
--- a/arch/arm/boot/dts/keystone-clocks.dtsi
+++ b/arch/arm/boot/dts/keystone-clocks.dtsi
@@ -737,6 +737,16 @@ clocks {
 		domain-id = <0>;
 	};
 
+	clktimer15: clktimer15 {
+		#clock-cells = <0>;
+		compatible = "ti,keystone,psc-clock";
+		clocks = <&clkmodrst0>;
+		clock-output-names = "timer15";
+		reg = <0x02350000 0xb00>, <0x02350000 0x400>;
+		reg-names = "control", "domain";
+		domain-id = <0>;
+	};
+
 	clkuart0: clkuart0 {
 		#clock-cells = <0>;
 		compatible = "ti,keystone,psc-clock";
diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index b420290..cac9841 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -208,5 +208,12 @@
 				usb-phy = <&usb_phy>, <&usb_phy>;
 			};
 		};
+
+		clock_event: timer at 22f0000 {
+			compatible = "ti,keystone-timer";
+			reg = <0x022f0000 0x80>;
+			interrupts = <GIC_SPI 110 IRQ_TYPE_EDGE_RISING>;
+			clocks = <&clktimer15>;
+		};
 	};
 };
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH v6 2/3] clocksource: keystone: add bindings for keystone timer
From: Ivan Khoronzhuk @ 2014-02-10 10:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392027058-11680-1-git-send-email-ivan.khoronzhuk@ti.com>

This patch provides bindings for the 64-bit timer in the KeyStone
architecture devices. The timer can be configured as a general-purpose 64-bit
timer, dual general-purpose 32-bit timers. When configured as dual 32-bit
timers, each half can operate in conjunction (chain mode) or independently
(unchained mode) of each other.

It is global timer is a free running up-counter and can generate interrupt
when the counter reaches preset counter values.

Documentation:
http://www.ti.com/lit/ug/sprugv5a/sprugv5a.pdf

Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
---
 .../bindings/timer/ti,keystone-timer.txt           | 29 ++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/ti,keystone-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/ti,keystone-timer.txt b/Documentation/devicetree/bindings/timer/ti,keystone-timer.txt
new file mode 100644
index 0000000..5fbe361
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/ti,keystone-timer.txt
@@ -0,0 +1,29 @@
+* Device tree bindings for Texas instruments Keystone timer
+
+This document provides bindings for the 64-bit timer in the KeyStone
+architecture devices. The timer can be configured as a general-purpose 64-bit
+timer, dual general-purpose 32-bit timers. When configured as dual 32-bit
+timers, each half can operate in conjunction (chain mode) or independently
+(unchained mode) of each other.
+
+It is global timer is a free running up-counter and can generate interrupt
+when the counter reaches preset counter values.
+
+Documentation:
+http://www.ti.com/lit/ug/sprugv5a/sprugv5a.pdf
+
+Required properties:
+
+- compatible : should be "ti,keystone-timer".
+- reg : specifies base physical address and count of the registers.
+- interrupts : interrupt generated by the timer.
+- clocks : the clock feeding the timer clock.
+
+Example:
+
+timer at 22f0000 {
+	compatible = "ti,keystone-timer";
+	reg = <0x022f0000 0x80>;
+	interrupts = <GIC_SPI 110 IRQ_TYPE_EDGE_RISING>;
+	clocks = <&clktimer15>;
+};
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH v6 1/3] clocksource: timer-keystone: introduce clocksource driver for Keystone
From: Ivan Khoronzhuk @ 2014-02-10 10:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392027058-11680-1-git-send-email-ivan.khoronzhuk@ti.com>

Add broadcast clock-event device for the Keystone arch.

The timer can be configured as a general-purpose 64-bit timer,
dual general-purpose 32-bit timers. When configured as dual 32-bit
timers, each half can operate in conjunction (chain mode) or
independently (unchained mode) of each other.

Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Acked-by: Santosh shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
---
 drivers/clocksource/Makefile         |   1 +
 drivers/clocksource/timer-keystone.c | 244 +++++++++++++++++++++++++++++++++++
 2 files changed, 245 insertions(+)
 create mode 100644 drivers/clocksource/timer-keystone.c

diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index c7ca50a..4abe5aa 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -37,3 +37,4 @@ obj-$(CONFIG_ARM_ARCH_TIMER)		+= arm_arch_timer.o
 obj-$(CONFIG_ARM_GLOBAL_TIMER)		+= arm_global_timer.o
 obj-$(CONFIG_CLKSRC_METAG_GENERIC)	+= metag_generic.o
 obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST)	+= dummy_timer.o
+obj-$(CONFIG_ARCH_KEYSTONE)		+= timer-keystone.o
diff --git a/drivers/clocksource/timer-keystone.c b/drivers/clocksource/timer-keystone.c
new file mode 100644
index 0000000..86b08cd
--- /dev/null
+++ b/drivers/clocksource/timer-keystone.c
@@ -0,0 +1,244 @@
+/*
+ * Keystone broadcast clock-event
+ *
+ * Copyright 2013 Texas Instruments, Inc.
+ *
+ * Author: Ivan Khoronzhuk <ivan.khoronzhuk@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define TIMER_NAME			"timer-keystone"
+
+/* Timer register offsets */
+#define TIM12				0x10
+#define TIM34				0x14
+#define PRD12				0x18
+#define PRD34				0x1c
+#define TCR				0x20
+#define TGCR				0x24
+#define INTCTLSTAT			0x44
+
+/* Timer register bitfields */
+#define TCR_ENAMODE_MASK		0xC0
+#define TCR_ENAMODE_ONESHOT_MASK	0x40
+#define TCR_ENAMODE_PERIODIC_MASK	0x80
+
+#define TGCR_TIM_UNRESET_MASK		0x03
+#define INTCTLSTAT_ENINT_MASK		0x01
+
+/**
+ * struct keystone_timer: holds timer's data
+ * @base: timer memory base address
+ * @hz_period: cycles per HZ period
+ * @event_dev: event device based on timer
+ */
+static struct keystone_timer {
+	void __iomem *base;
+	unsigned long hz_period;
+	struct clock_event_device event_dev;
+} timer;
+
+static inline u32 keystone_timer_readl(unsigned long rg)
+{
+	return readl_relaxed(timer.base + rg);
+}
+
+static inline void keystone_timer_writel(u32 val, unsigned long rg)
+{
+	writel_relaxed(val, timer.base + rg);
+}
+
+/**
+ * keystone_timer_barrier: write memory barrier
+ * use explicit barrier to avoid using readl/writel non relaxed function
+ * variants, because in our case non relaxed variants hide the true places
+ * where barrier is needed.
+ */
+static inline void keystone_timer_barrier(void)
+{
+	__iowmb();
+}
+
+/**
+ * keystone_timer_config: configures timer to work in oneshot/periodic modes.
+ * @ mode: mode to configure
+ * @ period: cycles number to configure for
+ */
+static int keystone_timer_config(u64 period, enum clock_event_mode mode)
+{
+	u32 tcr;
+	u32 off;
+
+	tcr = keystone_timer_readl(TCR);
+	off = tcr & ~(TCR_ENAMODE_MASK);
+
+	/* set enable mode */
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+		tcr |= TCR_ENAMODE_ONESHOT_MASK;
+		break;
+	case CLOCK_EVT_MODE_PERIODIC:
+		tcr |= TCR_ENAMODE_PERIODIC_MASK;
+		break;
+	default:
+		return -1;
+	}
+
+	/* disable timer */
+	keystone_timer_writel(off, TCR);
+	/* here we have to be sure the timer has been disabled */
+	keystone_timer_barrier();
+
+	/* reset counter to zero, set new period */
+	keystone_timer_writel(0, TIM12);
+	keystone_timer_writel(0, TIM34);
+	keystone_timer_writel(period & 0xffffffff, PRD12);
+	keystone_timer_writel(period >> 32, PRD34);
+
+	/*
+	 * enable timer
+	 * here we have to be sure that CNTLO, CNTHI, PRDLO, PRDHI registers
+	 * have been written.
+	 */
+	keystone_timer_barrier();
+	keystone_timer_writel(tcr, TCR);
+	return 0;
+}
+
+static void keystone_timer_disable(void)
+{
+	u32 tcr;
+
+	tcr = keystone_timer_readl(TCR);
+
+	/* disable timer */
+	tcr &= ~(TCR_ENAMODE_MASK);
+	keystone_timer_writel(tcr, TCR);
+}
+
+static irqreturn_t keystone_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+static int keystone_set_next_event(unsigned long cycles,
+				  struct clock_event_device *evt)
+{
+	return keystone_timer_config(cycles, evt->mode);
+}
+
+static void keystone_set_mode(enum clock_event_mode mode,
+			     struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		keystone_timer_config(timer.hz_period, CLOCK_EVT_MODE_PERIODIC);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_ONESHOT:
+		keystone_timer_disable();
+		break;
+	default:
+		break;
+	}
+}
+
+static void __init keystone_timer_init(struct device_node *np)
+{
+	struct clock_event_device *event_dev = &timer.event_dev;
+	unsigned long rate;
+	struct clk *clk;
+	int irq, error;
+	u32 tgcr;
+
+	irq  = irq_of_parse_and_map(np, 0);
+	if (irq == NO_IRQ) {
+		pr_err("%s: failed to map interrupts\n", __func__);
+		return;
+	}
+
+	timer.base = of_iomap(np, 0);
+	if (!timer.base) {
+		pr_err("%s: failed to map registers\n", __func__);
+		return;
+	}
+
+	clk = of_clk_get(np, 0);
+	if (IS_ERR(clk)) {
+		pr_err("%s: failed to get clock\n", __func__);
+		iounmap(timer.base);
+		return;
+	}
+
+	error = clk_prepare_enable(clk);
+	if (error) {
+		pr_err("%s: failed to enable clock\n", __func__);
+		goto err;
+	}
+
+	rate = clk_get_rate(clk);
+
+	/* disable, use internal clock source */
+	keystone_timer_writel(0, TCR);
+	/* here we have to be sure the timer has been disabled */
+	keystone_timer_barrier();
+
+	/* reset timer as 64-bit, no pre-scaler, plus features are disabled */
+	tgcr = 0;
+	keystone_timer_writel(0, TGCR);
+
+	/* unreset timer */
+	tgcr |= TGCR_TIM_UNRESET_MASK;
+	keystone_timer_writel(tgcr, TGCR);
+
+	/* init counter to zero */
+	keystone_timer_writel(0, TIM12);
+	keystone_timer_writel(0, TIM34);
+
+	timer.hz_period = DIV_ROUND_UP(rate, HZ);
+
+	/* enable timer interrupts */
+	keystone_timer_writel(INTCTLSTAT_ENINT_MASK, INTCTLSTAT);
+
+	error = request_irq(irq, keystone_timer_interrupt, IRQF_TIMER,
+			    TIMER_NAME, event_dev);
+	if (error) {
+		pr_err("%s: failed to setup irq\n", __func__);
+		goto err;
+	}
+
+	/* setup clockevent */
+	event_dev->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	event_dev->set_next_event = keystone_set_next_event;
+	event_dev->set_mode = keystone_set_mode;
+	event_dev->cpumask = cpu_all_mask;
+	event_dev->owner = THIS_MODULE;
+	event_dev->name = TIMER_NAME;
+	event_dev->irq = irq;
+
+	clockevents_config_and_register(event_dev, rate, 1, ULONG_MAX);
+
+	pr_info("keystone timer clock @%lu Hz\n", rate);
+	return;
+err:
+	clk_put(clk);
+	iounmap(timer.base);
+}
+
+CLOCKSOURCE_OF_DECLARE(keystone_timer, "ti,keystone-timer",
+					keystone_timer_init);
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH v6 0/3] Introduce clocksource driver for Keystone platform
From: Ivan Khoronzhuk @ 2014-02-10 10:10 UTC (permalink / raw)
  To: linux-arm-kernel

Add a broadcast timer64 based clockevent driver for keystone arch.
This driver uses timer in 64-bit general purpose mode as clock event
device.

Documentation:
    http://www.ti.com/lit/ug/sprugv5a/sprugv5a.pdf

Based on
git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone.git
keystone/master

v5..v6:
	added function to encapsulate __iowmb().

v4..v5:
	used __iowmb() insted of wmb()

v3..v4:
	rebased on latest of linux-keystone.git keystone/master

v2..v3:
- clocksource: timer-keystone: introduce clocksource driver for
	changed "u64" type to "unsigned long" for hz_period as more appropriate
	hz_period rounded up by DIV_ROUND_UP(rate, HZ)
	corrected comments

v1..v2:
- clocksource: timer-keystone: introduce clocksource driver for
	renamed timer on "timer-keystone"
	in keystone_timer_interrupt() evet pointer is passed via "dev_id"
	used __relaxed variants of writel/readl and added explicit barriers
	added "keystone_timer_disable()" for using in keystone_set_mode()
	keystone_timer_config() is not used for disabling the timer any more
	in case of an unsupported mode the keystone_timer_config() returns -1.
	used request_irq() instead of setup_irq()
	assigned irq for event_device in event_dev->irq
	calculated timer.hz_period for CLOCK_EVT_MODE_PERIODIC at init
	deleted spare call of keystone_timer_config() in keystone_timer_init()

Ivan Khoronzhuk (3):
  clocksource: timer-keystone: introduce clocksource driver for Keystone
  clocksource: keystone: add bindings for keystone timer
  arm: dts: keystone: add keystone timer entry

 .../bindings/timer/ti,keystone-timer.txt           |  29 +++
 arch/arm/boot/dts/keystone-clocks.dtsi             |  10 +
 arch/arm/boot/dts/keystone.dtsi                    |   7 +
 drivers/clocksource/Makefile                       |   1 +
 drivers/clocksource/timer-keystone.c               | 244 +++++++++++++++++++++
 5 files changed, 291 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/ti,keystone-timer.txt
 create mode 100644 drivers/clocksource/timer-keystone.c

-- 
1.8.3.2

^ permalink raw reply

* [PATCH v6 3/3] ARM: dts: Add initial device tree support for EXYNOS5410
From: Tarek Dakhran @ 2014-02-10 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026911-21308-1-git-send-email-t.dakhran@samsung.com>

Add initial device tree nodes for EXYNOS5410 SoC and SMDK5410 board.

Signed-off-by: Tarek Dakhran <t.dakhran@samsung.com>
Signed-off-by: Vyacheslav Tyrtov <v.tyrtov@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
---
 arch/arm/boot/dts/Makefile                |    1 +
 arch/arm/boot/dts/exynos5410-smdk5410.dts |   72 +++++++++++++++
 arch/arm/boot/dts/exynos5410.dtsi         |  140 +++++++++++++++++++++++++++++
 3 files changed, 213 insertions(+)
 create mode 100644 arch/arm/boot/dts/exynos5410-smdk5410.dts
 create mode 100644 arch/arm/boot/dts/exynos5410.dtsi

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b9d6a8b..693dcdc 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -73,6 +73,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
 	exynos5250-smdk5250.dtb \
 	exynos5250-snow.dtb \
 	exynos5420-arndale-octa.dtb \
+	exynos5410-smdk5410.dtb \
 	exynos5420-smdk5420.dtb \
 	exynos5440-sd5v1.dtb \
 	exynos5440-ssdk5440.dtb
diff --git a/arch/arm/boot/dts/exynos5410-smdk5410.dts b/arch/arm/boot/dts/exynos5410-smdk5410.dts
new file mode 100644
index 0000000..7ffd351
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410-smdk5410.dts
@@ -0,0 +1,72 @@
+/*
+ * SAMSUNG SMDK5410 board device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+/dts-v1/;
+#include "exynos5410.dtsi"
+/ {
+	model = "Samsung SMDK5410 board based on EXYNOS5410";
+	compatible = "samsung,smdk5410", "samsung,exynos5410";
+
+	memory {
+		reg = <0x40000000 0x80000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttySAC2,115200";
+	};
+
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		fin_pll: clock-fin-pll {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <24000000>;
+			clock-output-names = "fin_pll";
+		};
+	};
+
+	mmc at 12200000 {
+		status = "okay";
+		num-slots = <1>;
+		supports-highspeed;
+		broken-cd;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
+
+		slot at 0 {
+			reg = <0>;
+			bus-width = <8>;
+		};
+	};
+
+	mmc at 12220000 {
+		status = "okay";
+		num-slots = <1>;
+		supports-highspeed;
+		card-detect-delay = <200>;
+		samsung,dw-mshc-ciu-div = <3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
+
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+		};
+	};
+
+};
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
new file mode 100644
index 0000000..56b44d1
--- /dev/null
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -0,0 +1,140 @@
+/*
+ * SAMSUNG EXYNOS5410 SoC device tree source
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * SAMSUNG EXYNOS5410 SoC device nodes are listed in this file.
+ * EXYNOS5410 based board files can include this file and provide
+ * values for board specfic bindings.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <dt-bindings/clock/exynos5410.h>
+#include "exynos5.dtsi"
+/ {
+	compatible = "samsung,exynos5410";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		CPU0: cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+			clock-frequency = <1600000000>;
+		};
+
+		CPU1: cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+			clock-frequency = <1600000000>;
+		};
+
+		CPU2: cpu at 2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+			clock-frequency = <1600000000>;
+		};
+
+		CPU3: cpu at 3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+			clock-frequency = <1600000000>;
+		};
+	};
+
+	clock: clock-controller at 10010000 {
+		compatible = "samsung,exynos5410-clock";
+		reg = <0x10010000 0x30000>;
+		#clock-cells = <1>;
+	};
+
+	timer at 101C0000 {
+		compatible = "samsung,exynos4210-mct";
+		reg = <0x101C0000 0xB00>;
+		interrupt-parent = <&interrupt_map>;
+		interrupts = <0>, <1>, <2>, <3>,
+			<4>, <5>, <6>, <7>,
+			<8>, <9>, <10>, <11>;
+		clocks = <&fin_pll>, <&clock CLK_MCT>;
+		clock-names = "fin_pll", "mct";
+
+		interrupt_map: interrupt-map {
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupt-map = <0 &combiner 23 3>,
+					<1 &combiner 23 4>,
+					<2 &combiner 25 2>,
+					<3 &combiner 25 3>,
+					<4 &gic 0 120 0>,
+					<5 &gic 0 121 0>,
+					<6 &gic 0 122 0>,
+					<7 &gic 0 123 0>,
+					<8 &gic 0 128 0>,
+					<9 &gic 0 129 0>,
+					<10 &gic 0 130 0>,
+					<11 &gic 0 131 0>;
+		};
+	};
+
+	mmc_0: mmc at 12200000 {
+		compatible = "samsung,exynos5250-dw-mshc";
+		interrupts = <0 75 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x12200000 0x1000>;
+		clocks = <&clock CLK_MMC0>, <&clock CLK_SCLK_MMC0>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x80>;
+		status = "disabled";
+	};
+
+	mmc_1: mmc at 12210000 {
+		compatible = "samsung,exynos5250-dw-mshc";
+		interrupts = <0 76 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x12210000 0x1000>;
+		clocks = <&clock CLK_MMC1>, <&clock CLK_SCLK_MMC1>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x80>;
+		status = "disabled";
+	};
+
+	mmc_2: mmc at 12220000 {
+		compatible = "samsung,exynos5250-dw-mshc";
+		interrupts = <0 77 0>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x12220000 0x1000>;
+		clocks = <&clock CLK_MMC2>, <&clock CLK_SCLK_MMC2>;
+		clock-names = "biu", "ciu";
+		fifo-depth = <0x80>;
+		status = "disabled";
+	};
+
+	serial at 12C00000 {
+		clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+		clock-names = "uart", "clk_uart_baud0";
+	};
+
+	serial at 12C10000 {
+		clocks = <&clock CLK_UART1>, <&clock CLK_SCLK_UART1>;
+		clock-names = "uart", "clk_uart_baud0";
+	};
+
+	serial at 12C20000 {
+		clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
+		clock-names = "uart", "clk_uart_baud0";
+	};
+
+};
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v6 2/3] clk: exynos5410: register clocks using common clock framework
From: Tarek Dakhran @ 2014-02-10 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026911-21308-1-git-send-email-t.dakhran@samsung.com>

The EXYNOS5410 clocks are statically listed and registered
using the Samsung specific common clock helper functions.

Signed-off-by: Tarek Dakhran <t.dakhran@samsung.com>
Signed-off-by: Vyacheslav Tyrtov <v.tyrtov@samsung.com>
Acked-by: Tomasz Figa <t.figa@samsung.com>
---
 .../devicetree/bindings/clock/exynos5410-clock.txt |   54 +++++
 drivers/clk/samsung/Makefile                       |    1 +
 drivers/clk/samsung/clk-exynos5410.c               |  239 ++++++++++++++++++++
 include/dt-bindings/clock/exynos5410.h             |   32 +++
 4 files changed, 326 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/exynos5410-clock.txt
 create mode 100644 drivers/clk/samsung/clk-exynos5410.c
 create mode 100644 include/dt-bindings/clock/exynos5410.h

diff --git a/Documentation/devicetree/bindings/clock/exynos5410-clock.txt b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt
new file mode 100644
index 0000000..604a75c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/exynos5410-clock.txt
@@ -0,0 +1,54 @@
+* Samsung Exynos5410 Clock Controller
+
+The Exynos5410 clock controller generates and supplies clock to various
+controllers within the Exynos5410 SoC.
+
+Required Properties:
+
+- compatible: should be "samsung,exynos5410-clock"
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+All available clocks are defined as preprocessor macros in
+dt-bindings/clock/exynos5410.h header and can be used in device
+tree sources.
+
+External clock:
+
+There is clock that is generated outside the SoC. It is expected
+that it is defined using standard clock bindings with following
+clock-output-name:
+ - "fin_pll" - PLL input clock - required.
+
+Example 1: An example of a clock controller node is listed below.
+
+	clock: clock-controller at 0x10010000 {
+		compatible = "samsung,exynos5410-clock";
+		reg = <0x10010000 0x30000>;
+		#clock-cells = <1>;
+	};
+
+Example 2: Required external clock.
+
+	fin_pll: clock-fin-pll {
+		compatible = "fixed-clock";
+		reg = <0>;
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "fin_pll";
+	};
+
+Example 3: UART controller node that consumes the clock generated by the clock
+	   controller. Refer to the standard clock bindings for information
+	   about 'clocks' and 'clock-names' property.
+
+	serial at 12C20000 {
+		compatible = "samsung,exynos4210-uart";
+		reg = <0x12C00000 0x100>;
+		interrupts = <0 51 0>;
+		clocks = <&clock CLK_UART0>, <&clock CLK_SCLK_UART0>;
+		clock-names = "uart", "clk_uart_baud0";
+	};
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 8eb4799..b572dd7 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-pll.o
 obj-$(CONFIG_ARCH_EXYNOS4)	+= clk-exynos4.o
 obj-$(CONFIG_SOC_EXYNOS5250)	+= clk-exynos5250.o
+obj-$(CONFIG_SOC_EXYNOS5410)	+= clk-exynos5410.o
 obj-$(CONFIG_SOC_EXYNOS5420)	+= clk-exynos5420.o
 obj-$(CONFIG_SOC_EXYNOS5440)	+= clk-exynos5440.o
 obj-$(CONFIG_ARCH_EXYNOS)	+= clk-exynos-audss.o
diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c
new file mode 100644
index 0000000..33d8c8c
--- /dev/null
+++ b/drivers/clk/samsung/clk-exynos5410.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Tarek Dakhran <t.dakhran@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Common Clock Framework support for Exynos5410 SoC.
+*/
+
+#include <dt-bindings/clock/exynos5410.h>
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+
+#define APLL_LOCK               0x0
+#define APLL_CON0               0x100
+#define CPLL_LOCK               0x10020
+#define CPLL_CON0               0x10120
+#define MPLL_LOCK               0x4000
+#define MPLL_CON0               0x4100
+#define BPLL_LOCK               0x20010
+#define BPLL_CON0               0x20110
+#define KPLL_LOCK               0x28000
+#define KPLL_CON0               0x28100
+
+#define SRC_CPU			0x200
+#define DIV_CPU0		0x500
+#define SRC_CPERI1		0x4204
+#define DIV_TOP0		0x10510
+#define DIV_TOP1		0x10514
+#define DIV_FSYS1		0x1054c
+#define DIV_FSYS2		0x10550
+#define DIV_PERIC0		0x10558
+#define SRC_TOP0		0x10210
+#define SRC_TOP1		0x10214
+#define SRC_TOP2		0x10218
+#define SRC_FSYS		0x10244
+#define SRC_PERIC0		0x10250
+#define SRC_MASK_FSYS		0x10340
+#define SRC_MASK_PERIC0		0x10350
+#define GATE_BUS_FSYS0		0x10740
+#define GATE_IP_FSYS		0x10944
+#define GATE_IP_PERIC		0x10950
+#define GATE_IP_PERIS		0x10960
+#define SRC_CDREX		0x20200
+#define SRC_KFC			0x28200
+#define DIV_KFC0		0x28500
+
+/* list of PLLs */
+enum exynos5410_plls {
+	apll, cpll, mpll,
+	bpll, kpll,
+	nr_plls                 /* number of PLLs */
+};
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static unsigned long exynos5410_clk_regs[] __initdata = {
+	SRC_CPU,
+	DIV_CPU0,
+	SRC_CPERI1,
+	DIV_TOP0,
+	DIV_TOP1,
+	DIV_FSYS1,
+	DIV_FSYS2,
+	DIV_PERIC0,
+	SRC_TOP0,
+	SRC_TOP1,
+	SRC_TOP2,
+	SRC_FSYS,
+	SRC_PERIC0,
+	SRC_MASK_FSYS,
+	SRC_MASK_PERIC0,
+	GATE_BUS_FSYS0,
+	GATE_IP_FSYS,
+	GATE_IP_PERIC,
+	GATE_IP_PERIS,
+	SRC_CDREX,
+	SRC_KFC,
+	DIV_KFC0,
+};
+
+/* list of all parent clocks */
+PNAME(apll_p)		= { "fin_pll", "fout_apll", };
+PNAME(bpll_p)		= { "fin_pll", "fout_bpll", };
+PNAME(cpll_p)		= { "fin_pll", "fout_cpll" };
+PNAME(mpll_p)		= { "fin_pll", "fout_mpll", };
+PNAME(kpll_p)		= { "fin_pll", "fout_kpll", };
+
+PNAME(mout_cpu_p)	= { "mout_apll", "sclk_mpll", };
+PNAME(mout_kfc_p)	= { "mout_kpll", "sclk_mpll", };
+
+PNAME(mpll_user_p)	= { "fin_pll", "sclk_mpll", };
+PNAME(bpll_user_p)	= { "fin_pll", "sclk_bpll", };
+PNAME(mpll_bpll_p)	= { "sclk_mpll_muxed", "sclk_bpll_muxed", };
+
+PNAME(group2_p)		= { "fin_pll", "fin_pll", "none", "none",
+			"none", "none", "sclk_mpll_bpll",
+			 "none", "none", "sclk_cpll" };
+
+static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = {
+	MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1),
+	MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
+
+	MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1),
+	MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
+
+	MUX(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1),
+	MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1),
+
+	MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1),
+	MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1),
+
+	MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1),
+
+	MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1),
+
+	MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4),
+	MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4),
+	MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4),
+
+	MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4),
+	MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4),
+	MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4),
+
+	MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1),
+	MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1),
+};
+
+static struct samsung_div_clock exynos5410_div_clks[] __initdata = {
+	DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
+	DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3),
+
+	DIV(0, "div_acp", "div_arm2", DIV_CPU0, 8, 3),
+	DIV(0, "div_cpud", "div_arm2", DIV_CPU0, 4, 3),
+	DIV(0, "div_atb", "div_arm2", DIV_CPU0, 16, 3),
+	DIV(0, "pclk_dbg", "div_arm2", DIV_CPU0, 20, 3),
+
+	DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3),
+	DIV(0, "div_aclk", "div_kfc", DIV_KFC0, 4, 3),
+	DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3),
+
+	DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3),
+	DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
+
+	DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+	DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+	DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+
+	DIV_F(0, "div_mmc_pre0", "div_mmc0",
+			DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(0, "div_mmc_pre1", "div_mmc1",
+			DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
+	DIV_F(0, "div_mmc_pre2", "div_mmc2",
+			DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
+
+	DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
+	DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
+	DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
+	DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
+
+	DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
+	DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3),
+};
+
+static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = {
+	GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+
+	GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0",
+			SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1",
+			SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2",
+			SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+
+	GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0),
+	GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0),
+	GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0),
+
+	GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
+	GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
+	GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+
+	GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0",
+			SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1",
+			SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
+	GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2",
+			SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+};
+
+static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = {
+	[apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK,
+		APLL_CON0, NULL),
+	[cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK,
+		CPLL_CON0, NULL),
+	[mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK,
+		MPLL_CON0, NULL),
+	[bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK,
+		BPLL_CON0, NULL),
+	[kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK,
+		KPLL_CON0, NULL),
+};
+
+/* register exynos5410 clocks */
+static void __init exynos5410_clk_init(struct device_node *np)
+{
+	void __iomem *reg_base;
+
+	reg_base = of_iomap(np, 0);
+	if (!reg_base)
+		panic("%s: failed to map registers\n", __func__);
+
+	samsung_clk_init(np, reg_base, CLK_NR_CLKS,
+			exynos5410_clk_regs, ARRAY_SIZE(exynos5410_clk_regs),
+			NULL, 0);
+
+	samsung_clk_register_pll(exynos5410_plls, ARRAY_SIZE(exynos5410_plls),
+					reg_base);
+
+	samsung_clk_register_mux(exynos5410_mux_clks,
+			ARRAY_SIZE(exynos5410_mux_clks));
+	samsung_clk_register_div(exynos5410_div_clks,
+			ARRAY_SIZE(exynos5410_div_clks));
+	samsung_clk_register_gate(exynos5410_gate_clks,
+			ARRAY_SIZE(exynos5410_gate_clks));
+
+	pr_debug("Exynos5410: clock setup completed.\n");
+}
+CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init);
diff --git a/include/dt-bindings/clock/exynos5410.h b/include/dt-bindings/clock/exynos5410.h
new file mode 100644
index 0000000..3df181f
--- /dev/null
+++ b/include/dt-bindings/clock/exynos5410.h
@@ -0,0 +1,32 @@
+#ifndef _DT_BINDINGS_CLOCK_EXYNOS_5410_H
+#define _DT_BINDINGS_CLOCK_EXYNOS_5410_H
+
+/* core clocks */
+#define CLK_FOUT_APLL 1
+#define CLK_FOUT_CPLL 2
+#define CLK_FOUT_MPLL 3
+#define CLK_FOUT_BPLL 4
+#define CLK_FOUT_KPLL 5
+
+/* gate for special clocks (sclk) */
+#define CLK_SCLK_UART0 128
+#define CLK_SCLK_UART1 129
+#define CLK_SCLK_UART2 130
+#define CLK_SCLK_UART3 131
+#define CLK_SCLK_MMC0 132
+#define CLK_SCLK_MMC1 133
+#define CLK_SCLK_MMC2 134
+
+/* gate clocks */
+#define CLK_UART0 257
+#define CLK_UART1 258
+#define CLK_UART2 259
+#define CLK_UART3 260
+#define CLK_MCT 315
+#define CLK_MMC0 351
+#define CLK_MMC1 352
+#define CLK_MMC2 353
+
+#define CLK_NR_CLKS 512
+
+#endif /* _DT_BINDINGS_CLOCK_EXYNOS_5410_H */
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v6 1/3] ARM: EXYNOS: Add support for EXYNOS5410 SoC
From: Tarek Dakhran @ 2014-02-10 10:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026911-21308-1-git-send-email-t.dakhran@samsung.com>

EXYNOS5410 is SoC in Samsung's Exynos5 SoC series.
Add initial support for this SoC.

Signed-off-by: Tarek Dakhran <t.dakhran@samsung.com>
Signed-off-by: Vyacheslav Tyrtov <v.tyrtov@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
---
 arch/arm/mach-exynos/Kconfig                 |   10 ++++++++++
 arch/arm/mach-exynos/common.c                |   18 ++++++++++++++++++
 arch/arm/mach-exynos/include/mach/map.h      |    1 +
 arch/arm/mach-exynos/mach-exynos5-dt.c       |    1 +
 arch/arm/mach-exynos/platsmp.c               |    2 ++
 arch/arm/plat-samsung/include/plat/cpu.h     |    8 ++++++++
 arch/arm/plat-samsung/include/plat/map-s5p.h |    3 +++
 7 files changed, 43 insertions(+)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 4c414af..97a06c3 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -91,6 +91,16 @@ config SOC_EXYNOS5250
 	help
 	  Enable EXYNOS5250 SoC support
 
+config SOC_EXYNOS5410
+	bool "SAMSUNG EXYNOS5410"
+	default y
+	depends on ARCH_EXYNOS5
+	select PM_GENERIC_DOMAINS if PM
+	select S5P_PM if PM_SLEEP
+	select S5P_SLEEP if PM_SLEEP
+	help
+	  Enable EXYNOS5410 SoC support
+
 config SOC_EXYNOS5420
 	bool "SAMSUNG EXYNOS5420"
 	default y
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index f18be40..f1483bd 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -52,6 +52,7 @@ static const char name_exynos4210[] = "EXYNOS4210";
 static const char name_exynos4212[] = "EXYNOS4212";
 static const char name_exynos4412[] = "EXYNOS4412";
 static const char name_exynos5250[] = "EXYNOS5250";
+static const char name_exynos5410[] = "EXYNOS5410";
 static const char name_exynos5420[] = "EXYNOS5420";
 static const char name_exynos5440[] = "EXYNOS5440";
 
@@ -85,6 +86,12 @@ static struct cpu_table cpu_ids[] __initdata = {
 		.init		= exynos_init,
 		.name		= name_exynos5250,
 	}, {
+		.idcode		= EXYNOS5410_SOC_ID,
+		.idmask		= EXYNOS5_SOC_MASK,
+		.map_io		= exynos5_map_io,
+		.init		= exynos_init,
+		.name		= name_exynos5410,
+	}, {
 		.idcode		= EXYNOS5420_SOC_ID,
 		.idmask		= EXYNOS5_SOC_MASK,
 		.map_io		= exynos5_map_io,
@@ -215,6 +222,15 @@ static struct map_desc exynos4x12_iodesc[] __initdata = {
 	},
 };
 
+static struct map_desc exynos5410_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSRAM_NS,
+		.pfn		= __phys_to_pfn(EXYNOS5410_PA_SYSRAM_NS),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
 static struct map_desc exynos5250_iodesc[] __initdata = {
 	{
 		.virtual	= (unsigned long)S5P_VA_SYSRAM_NS,
@@ -379,6 +395,8 @@ static void __init exynos5_map_io(void)
 
 	if (soc_is_exynos5250())
 		iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
+	if (soc_is_exynos5410())
+		iotable_init(exynos5410_iodesc, ARRAY_SIZE(exynos5410_iodesc));
 }
 
 struct bus_type exynos_subsys = {
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 7b046b5..894f431 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -29,6 +29,7 @@
 #define EXYNOS4210_PA_SYSRAM_NS		0x0203F000
 #define EXYNOS4x12_PA_SYSRAM_NS		0x0204F000
 #define EXYNOS5250_PA_SYSRAM_NS		0x0204F000
+#define EXYNOS5410_PA_SYSRAM_NS		0x02073000
 
 #define EXYNOS_PA_CHIPID		0x10000000
 
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index 37ea261..22245b2 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -51,6 +51,7 @@ static void __init exynos5_dt_machine_init(void)
 
 static char const *exynos5_dt_compat[] __initdata = {
 	"samsung,exynos5250",
+	"samsung,exynos5410",
 	"samsung,exynos5420",
 	"samsung,exynos5440",
 	NULL
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 8ea02f6..b681f89 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -39,6 +39,8 @@ static inline void __iomem *cpu_boot_reg_base(void)
 {
 	if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
 		return S5P_INFORM5;
+	if (soc_is_exynos5410())
+		return EXYNOS5410_BOOT_REG;
 	return S5P_VA_SYSRAM;
 }
 
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index 335beb3..8f09488 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -46,6 +46,7 @@ extern unsigned long samsung_cpu_id;
 #define EXYNOS4_CPU_MASK	0xFFFE0000
 
 #define EXYNOS5250_SOC_ID	0x43520000
+#define EXYNOS5410_SOC_ID	0xE5410000
 #define EXYNOS5420_SOC_ID	0xE5420000
 #define EXYNOS5440_SOC_ID	0xE5440000
 #define EXYNOS5_SOC_MASK	0xFFFFF000
@@ -68,6 +69,7 @@ IS_SAMSUNG_CPU(exynos4210, EXYNOS4210_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4212, EXYNOS4212_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
 IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
+IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS5_SOC_MASK)
 IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK)
 IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
 
@@ -148,6 +150,12 @@ IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
 # define soc_is_exynos5250()	0
 #endif
 
+#if defined(CONFIG_SOC_EXYNOS5410)
+# define soc_is_exynos5410()	is_samsung_exynos5410()
+#else
+# define soc_is_exynos5410()	0
+#endif
+
 #if defined(CONFIG_SOC_EXYNOS5420)
 # define soc_is_exynos5420()	is_samsung_exynos5420()
 #else
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index c186786..6310928 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -57,6 +57,9 @@
 #define S3C_UART_OFFSET		(0x400)
 #endif
 
+#define S5P_VA_SYSRAM_NS_X(x)	(S5P_VA_SYSRAM_NS + x)
+#define EXYNOS5410_BOOT_REG	S5P_VA_SYSRAM_NS_X(0x1c)
+
 #include <plat/map-s3c.h>
 
 #endif /* __ASM_PLAT_MAP_S5P_H */
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v6 0/3] Exynos 5410 support
From: Tarek Dakhran @ 2014-02-10 10:08 UTC (permalink / raw)
  To: linux-arm-kernel

The series of patches represent support of Exynos 5410 SoC

The Exynos 5410 is the first Samsung SoC based on bigLITTLE architecture

Patches add new platform description, support of clock controller and device 
tree for Exynos 5410.

Dual cluster support for Exynos 5410 (EDCS) has been removed from this series 
This patches is activating only the big cluster (2xA15 cores)

EDCS patch, which allows all 8 CPU cores (4 x A7 and 4 x A15) 
to run at the same time, will be released separately

Has been build on v3.14-rc1
Has been tested on Exynos 5410 reference board (exynos_defconfig)

Thanks for all your comments to Tomasz Figa, Dave Martin and Nicolas Pitre.
I hope, this is enough clean and hasn't any dependencies to go through 
Samsung tree.

Tarek.


Changelog:

v6:
	small changes in Makefiles for resolving conflicts related to changes in 
	Samsung tree.

Tarek Dakhran (3):
  ARM: EXYNOS: Add support for EXYNOS5410 SoC
  clk: exynos5410: register clocks using common clock framework
  ARM: dts: Add initial device tree support for EXYNOS5410

 .../devicetree/bindings/clock/exynos5410-clock.txt |   54 +++++
 arch/arm/boot/dts/Makefile                         |    1 +
 arch/arm/boot/dts/exynos5410-smdk5410.dts          |   72 ++++++
 arch/arm/boot/dts/exynos5410.dtsi                  |  140 ++++++++++++
 arch/arm/mach-exynos/Kconfig                       |   10 +
 arch/arm/mach-exynos/common.c                      |   18 ++
 arch/arm/mach-exynos/include/mach/map.h            |    1 +
 arch/arm/mach-exynos/mach-exynos5-dt.c             |    1 +
 arch/arm/mach-exynos/platsmp.c                     |    2 +
 arch/arm/plat-samsung/include/plat/cpu.h           |    8 +
 arch/arm/plat-samsung/include/plat/map-s5p.h       |    3 +
 drivers/clk/samsung/Makefile                       |    1 +
 drivers/clk/samsung/clk-exynos5410.c               |  239 ++++++++++++++++++++
 include/dt-bindings/clock/exynos5410.h             |   32 +++
 14 files changed, 582 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/exynos5410-clock.txt
 create mode 100644 arch/arm/boot/dts/exynos5410-smdk5410.dts
 create mode 100644 arch/arm/boot/dts/exynos5410.dtsi
 create mode 100644 drivers/clk/samsung/clk-exynos5410.c
 create mode 100644 include/dt-bindings/clock/exynos5410.h

-- 
1.7.10.4

^ permalink raw reply

* [PATCH] input: sirfsoc-onkey - report onkey untouch event by detecting pin status
From: Barry Song @ 2014-02-10 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

From: Xianglong Du <Xianglong.Du@csr.com>

this patch adds a delayed_work to detect the untouch of onkey since HW will
not generate interrupt for it.

at the same time, we move the KEY event to POWER instead of SUSPEND, which
will be suitable for both Android and Linux. Userspace PowerManager Daemon
will decide to suspend or shutdown based on how long we have touched onkey

Signed-off-by: Xianglong Du <Xianglong.Du@csr.com>
Signed-off-by: Rongjun Ying <Rongjun.Ying@csr.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
---
 drivers/input/misc/sirfsoc-onkey.c |   48 ++++++++++++++++++++++++++++-------
 1 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/drivers/input/misc/sirfsoc-onkey.c b/drivers/input/misc/sirfsoc-onkey.c
index e8897c3..9cd810b 100644
--- a/drivers/input/misc/sirfsoc-onkey.c
+++ b/drivers/input/misc/sirfsoc-onkey.c
@@ -13,16 +13,44 @@
 #include <linux/input.h>
 #include <linux/rtc/sirfsoc_rtciobrg.h>
 #include <linux/of.h>
+#include <linux/workqueue.h>
 
 struct sirfsoc_pwrc_drvdata {
 	u32			pwrc_base;
 	struct input_dev	*input;
+	struct delayed_work	work;
 };
 
 #define PWRC_ON_KEY_BIT			(1 << 0)
 
 #define PWRC_INT_STATUS			0xc
 #define PWRC_INT_MASK			0x10
+#define PWRC_PIN_STATUS			0x14
+#define PWRC_KEY_DETECT_UP_TIME		20	/* ms*/
+
+static inline int sirfsoc_pwrc_is_on_key_down(
+		struct sirfsoc_pwrc_drvdata *pwrcdrv)
+{
+	int state = sirfsoc_rtc_iobrg_readl(
+				pwrcdrv->pwrc_base + PWRC_PIN_STATUS)
+				& PWRC_ON_KEY_BIT;
+	return !state; /* ON_KEY is active low */
+}
+
+static void sirfsoc_pwrc_report_event(struct work_struct *work)
+{
+	struct sirfsoc_pwrc_drvdata *pwrcdrv =
+				container_of((struct delayed_work *)work,
+				struct sirfsoc_pwrc_drvdata, work);
+
+	if (!sirfsoc_pwrc_is_on_key_down(pwrcdrv)) {
+		input_event(pwrcdrv->input, EV_PWR, KEY_POWER, 0);
+		input_sync(pwrcdrv->input);
+	} else {
+		schedule_delayed_work(&pwrcdrv->work,
+			msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME));
+	}
+}
 
 static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
 {
@@ -34,17 +62,11 @@ static irqreturn_t sirfsoc_pwrc_isr(int irq, void *dev_id)
 	sirfsoc_rtc_iobrg_writel(int_status & ~PWRC_ON_KEY_BIT,
 				 pwrcdrv->pwrc_base + PWRC_INT_STATUS);
 
-	/*
-	 * For a typical Linux system, we report KEY_SUSPEND to trigger apm-power.c
-	 * to queue a SUSPEND APM event
-	 */
-	input_event(pwrcdrv->input, EV_PWR, KEY_SUSPEND, 1);
-	input_sync(pwrcdrv->input);
 
-	/*
-	 * Todo: report KEY_POWER event for Android platforms, Android PowerManager
-	 * will handle the suspend and powerdown/hibernation
-	 */
+	input_event(pwrcdrv->input, EV_PWR, KEY_POWER, 1);
+	input_sync(pwrcdrv->input);
+	schedule_delayed_work(&pwrcdrv->work,
+		msecs_to_jiffies(PWRC_KEY_DETECT_UP_TIME));
 
 	return IRQ_HANDLED;
 }
@@ -88,6 +110,8 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 	pwrcdrv->input->phys = "pwrc/input0";
 	pwrcdrv->input->evbit[0] = BIT_MASK(EV_PWR);
 
+	INIT_DELAYED_WORK(&pwrcdrv->work, sirfsoc_pwrc_report_event);
+
 	irq = platform_get_irq(pdev, 0);
 	error = devm_request_irq(&pdev->dev, irq,
 				 sirfsoc_pwrc_isr, IRQF_SHARED,
@@ -119,8 +143,12 @@ static int sirfsoc_pwrc_probe(struct platform_device *pdev)
 
 static int sirfsoc_pwrc_remove(struct platform_device *pdev)
 {
+	struct sirfsoc_pwrc_drvdata *pwrcdrv = dev_get_drvdata(&pdev->dev);
+
 	device_init_wakeup(&pdev->dev, 0);
 
+	cancel_delayed_work_sync(&pwrcdrv->work);
+
 	return 0;
 }
 
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 15/17] i2c: i2c-stu300: deprecate class based instantiation
From: Wolfram Sang @ 2014-02-10 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026654-5343-1-git-send-email-wsa@the-dreams.de>

Warn users that class based instantiation is going away soon in favour
of more robust probing and faster bootup times.

Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: Linus Walleij <linus.walleij@linaro.org>
---

This patch is a suggestion. Looking for an ack by someone who actually uses
the driver.

 drivers/i2c/busses/i2c-stu300.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index 04a17b9..d381af9 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -911,7 +911,7 @@ static int stu300_probe(struct platform_device *pdev)
 	adap = &dev->adapter;
 	adap->owner = THIS_MODULE;
 	/* DDC class but actually often used for more generic I2C */
-	adap->class = I2C_CLASS_DDC;
+	adap->class = I2C_CLASS_DDC | I2C_CLASS_DEPRECATED;
 	strlcpy(adap->name, "ST Microelectronics DDC I2C adapter",
 		sizeof(adap->name));
 	adap->nr = bus_nr;
-- 
1.8.5.1

^ permalink raw reply related

* [PATCH 14/17] i2c: i2c-sirf: deprecate class based instantiation
From: Wolfram Sang @ 2014-02-10 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026654-5343-1-git-send-email-wsa@the-dreams.de>

Warn users that class based instantiation is going away soon in favour
of more robust probing and faster bootup times.

Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: Barry Song <baohua@kernel.org>
---

This patch is a suggestion. Looking for an ack by someone who actually uses
the driver.

 drivers/i2c/busses/i2c-sirf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
index 6784f7f..8e3be7e 100644
--- a/drivers/i2c/busses/i2c-sirf.c
+++ b/drivers/i2c/busses/i2c-sirf.c
@@ -312,7 +312,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev)
 		goto out;
 	}
 	adap = &siic->adapter;
-	adap->class = I2C_CLASS_HWMON;
+	adap->class = I2C_CLASS_HWMON | I2C_CLASS_DEPRECATED;
 
 	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	siic->base = devm_ioremap_resource(&pdev->dev, mem_res);
-- 
1.8.5.1

^ permalink raw reply related

* [PATCH 13/17] i2c: i2c-s3c2410: deprecate class based instantiation
From: Wolfram Sang @ 2014-02-10 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026654-5343-1-git-send-email-wsa@the-dreams.de>

Warn users that class based instantiation is going away soon in favour
of more robust probing and faster bootup times.

Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
---

This patch is a suggestion. Looking for an ack by someone who actually uses
the driver.

 drivers/i2c/busses/i2c-s3c2410.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index bf8fb94..4a623e0 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -1062,7 +1062,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
 	i2c->adap.owner   = THIS_MODULE;
 	i2c->adap.algo    = &s3c24xx_i2c_algorithm;
 	i2c->adap.retries = 2;
-	i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	i2c->adap.class   = I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
 	i2c->tx_setup     = 50;
 
 	init_waitqueue_head(&i2c->wait);
-- 
1.8.5.1

^ permalink raw reply related

* [PATCH 10/17] i2c: i2c-nomadik: deprecate class based instantiation
From: Wolfram Sang @ 2014-02-10 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026654-5343-1-git-send-email-wsa@the-dreams.de>

Warn users that class based instantiation is going away soon in favour
of more robust probing and faster bootup times.

Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: Alessandro Rubini <rubini@unipv.it>
Cc: Linus Walleij <linus.walleij@linaro.org>
---

This patch is a suggestion. Looking for an ack by someone who actually uses
the driver.

 drivers/i2c/busses/i2c-nomadik.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 8bf9ac0..e3777ac 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -1019,7 +1019,7 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
 	adap->dev.of_node = np;
 	adap->dev.parent = &adev->dev;
 	adap->owner	= THIS_MODULE;
-	adap->class	= I2C_CLASS_HWMON | I2C_CLASS_SPD;
+	adap->class	= I2C_CLASS_HWMON | I2C_CLASS_SPD | I2C_CLASS_DEPRECATED;
 	adap->algo	= &nmk_i2c_algo;
 	adap->timeout	= msecs_to_jiffies(pdata->timeout);
 	snprintf(adap->name, sizeof(adap->name),
-- 
1.8.5.1

^ permalink raw reply related

* [PATCH 02/17] i2c: add deprecation warning for class based instantiation
From: Wolfram Sang @ 2014-02-10 10:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026654-5343-1-git-send-email-wsa@the-dreams.de>

Class based instantiation can cause noticeable delays when booting. This
mechanism is used when it is not possible to describe slaves on I2C
busses. As we do have other mechanisms, most embedded I2C will not need
classes and for embedded it is explicitly not recommended to use them. Add
a deprecation warning for drivers which want to disable class based
instantiation in the near future to gain boot-up time, so users relying
on this technique can switch to something better. They really should.

Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: linux-arm-kernel at lists.infradead.org
---

 drivers/i2c/i2c-core.c | 7 +++++++
 include/linux/i2c.h    | 1 +
 2 files changed, 8 insertions(+)

diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index d74c0b3..42fcc59 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1935,6 +1935,13 @@ static int i2c_detect_address(struct i2c_client *temp_client,
 		struct i2c_client *client;
 
 		/* Detection succeeded, instantiate the device */
+		if (adapter->class & I2C_CLASS_DEPRECATED)
+			dev_warn(&adapter->dev,
+				"This adapter will soon drop class based instantiation of devices. "
+				"Please make sure client 0x%02x gets instantiated by other means. "
+				"Check 'Documentation/i2c/instantiating-devices' for details.\n",
+				info.addr);
+
 		dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
 			info.type, info.addr);
 		client = i2c_new_device(adapter, &info);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index d9c8dbd3..b9e1707 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -473,6 +473,7 @@ void i2c_unlock_adapter(struct i2c_adapter *);
 #define I2C_CLASS_HWMON		(1<<0)	/* lm_sensors, ... */
 #define I2C_CLASS_DDC		(1<<3)	/* DDC bus on graphics adapters */
 #define I2C_CLASS_SPD		(1<<7)	/* Memory modules */
+#define I2C_CLASS_DEPRECATED	(1<<8)	/* Warn users that adapter will stop using classes */
 
 /* Internal numbers to terminate lists */
 #define I2C_CLIENT_END		0xfffeU
-- 
1.8.5.1

^ permalink raw reply related

* [PATCH 01/17] Documentation: i2c: describe devicetree method for instantiating devices
From: Wolfram Sang @ 2014-02-10 10:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1392026654-5343-1-git-send-email-wsa@the-dreams.de>

Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Cc: devicetree at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
---

 Documentation/i2c/instantiating-devices | 34 +++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices
index c70e7a7..6df095a 100644
--- a/Documentation/i2c/instantiating-devices
+++ b/Documentation/i2c/instantiating-devices
@@ -8,8 +8,8 @@ reason, the kernel code must instantiate I2C devices explicitly. There are
 several ways to achieve this, depending on the context and requirements.
 
 
-Method 1: Declare the I2C devices by bus number
------------------------------------------------
+Method 1a: Declare the I2C devices by bus number
+------------------------------------------------
 
 This method is appropriate when the I2C bus is a system bus as is the case
 for many embedded systems. On such systems, each I2C bus has a number
@@ -51,6 +51,36 @@ The devices will be automatically unbound and destroyed when the I2C bus
 they sit on goes away (if ever.)
 
 
+Method 1b: Declare the I2C devices via devicetree
+-------------------------------------------------
+
+This method has the same implications as method 1a. The declaration of I2C
+devices is here done via devicetree as subnodes of the master controller.
+
+Example:
+
+	i2c1: i2c at 400a0000 {
+		/* ... master properties skipped ... */
+		clock-frequency = <100000>;
+
+		flash at 50 {
+			compatible = "atmel,24c256";
+			reg = <0x50>;
+		};
+
+		pca9532: gpio at 60 {
+			compatible = "nxp,pca9532";
+			gpio-controller;
+			#gpio-cells = <2>;
+			reg = <0x60>;
+		};
+	};
+
+Here, two devices are attached to the bus using a speed of 100kHz. For
+additional properties which might be needed to set up the device, please refer
+to its devicetree documentation in Documentation/devicetree/bindings/.
+
+
 Method 2: Instantiate the devices explicitly
 --------------------------------------------
 
-- 
1.8.5.1

^ permalink raw reply related

* [PATCH 00/17] i2c: deprecate class based instantiation for embedded I2C drivers
From: Wolfram Sang @ 2014-02-10 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

With I2C, class based instantiation means if a master driver has e.g.
I2C_CLASS_HWMON set, all slave drivers with this class will try to probe a
device using an array of possible addresses and some heuristics. That creates
traffic and needs time, even when nothing is connected. This mechanism is
needed when you do not have another method to describe the slaves. Embedded I2C
drivers do not need class based instantiation, since there is i2c_board_info or
devicetree description. Some drivers have the class flags set, though, and it
has spread further over the years. We can't remove the flags directly, because
there might be users out there relying on this feature. So, we add a
deprecation warning if a device is instantiated via class attributes. After
giving some time to switch over, we can then finally remove the class flags and
gain boot time.

Patch 1 adds some missing documentation. Patch 2 adds the deprecation feature.
Patches 3+4 are tested on hardware I need. Patches 5-17 are suggestions for
drivers I think could benefit from that. For those, acks are needed before I
will apply them to my tree. If you use a different driver which can also
benefit from this, just send a patch adding the new DEPRECATED flag.

The series can also be found here:

git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/deprecated_class

Thanks,

   Wolfram


Wolfram Sang (17):
  Documentation: i2c: describe devicetree method for instantiating
    devices
  i2c: add deprecation warning for class based instantiation
  i2c: i2c-omap: deprecate class based instantiation
  i2c: i2c-at91: deprecate class based instantiation
  i2c: i2c-bcm2835: deprecate class based instantiation
  i2c: i2c-bfin-twi: deprecate class based instantiation
  i2c: i2c-davinci: deprecate class based instantiation
  i2c: i2c-designware-platdrv: deprecate class based instantiation
  i2c: i2c-mv64xxx: deprecate class based instantiation
  i2c: i2c-nomadik: deprecate class based instantiation
  i2c: i2c-ocores: deprecate class based instantiation
  i2c: i2c-rcar: deprecate class based instantiation
  i2c: i2c-s3c2410: deprecate class based instantiation
  i2c: i2c-sirf: deprecate class based instantiation
  i2c: i2c-stu300: deprecate class based instantiation
  i2c: i2c-tegra: deprecate class based instantiation
  i2c: i2c-xiic: deprecate class based instantiation

 Documentation/i2c/instantiating-devices     | 34 +++++++++++++++++++++++++++--
 drivers/i2c/busses/i2c-at91.c               |  2 +-
 drivers/i2c/busses/i2c-bcm2835.c            |  2 +-
 drivers/i2c/busses/i2c-bfin-twi.c           |  2 +-
 drivers/i2c/busses/i2c-davinci.c            |  2 +-
 drivers/i2c/busses/i2c-designware-platdrv.c |  2 +-
 drivers/i2c/busses/i2c-mv64xxx.c            |  2 +-
 drivers/i2c/busses/i2c-nomadik.c            |  2 +-
 drivers/i2c/busses/i2c-ocores.c             |  2 +-
 drivers/i2c/busses/i2c-omap.c               |  2 +-
 drivers/i2c/busses/i2c-rcar.c               |  2 +-
 drivers/i2c/busses/i2c-s3c2410.c            |  2 +-
 drivers/i2c/busses/i2c-sirf.c               |  2 +-
 drivers/i2c/busses/i2c-stu300.c             |  2 +-
 drivers/i2c/busses/i2c-tegra.c              |  2 +-
 drivers/i2c/busses/i2c-xiic.c               |  2 +-
 drivers/i2c/i2c-core.c                      |  7 ++++++
 include/linux/i2c.h                         |  1 +
 18 files changed, 55 insertions(+), 17 deletions(-)

-- 
1.8.5.1

^ 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