diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-12-05 13:27:17 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-12-05 13:27:17 -0800 |
commit | c48dcb2fc9ea301e7ee0e67048d4195eb3897ec6 (patch) | |
tree | de75f5b27a76e9f0bca8fbf5a8a54aa325694df6 | |
parent | 05c35b6543cd64cb71ecac7ce4231645b6cd40b2 (diff) | |
download | ltsi-kernel-c48dcb2fc9ea301e7ee0e67048d4195eb3897ec6.tar.gz |
kzm9d board support added
25 files changed, 4607 insertions, 0 deletions
diff --git a/patches.kzm9d/arm-mach-shmobile-fix-build-when-smp-is-enabled-and-emev2-is-not-enabled.patch b/patches.kzm9d/arm-mach-shmobile-fix-build-when-smp-is-enabled-and-emev2-is-not-enabled.patch new file mode 100644 index 0000000000000..5c4105ed426e1 --- /dev/null +++ b/patches.kzm9d/arm-mach-shmobile-fix-build-when-smp-is-enabled-and-emev2-is-not-enabled.patch @@ -0,0 +1,60 @@ +From koba@kmckk.co.jp Wed Oct 3 04:30:37 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:18 +0900 +Subject: [PATCH 26/26] ARM: mach-shmobile: Fix build when SMP is enabled and EMEV2 is not enabled +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-27-git-send-email-koba@kmckk.co.jp> + + +From: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + +Build failed, when SMP is enabled and EMEV2 is not enabled. + +arch/arm/mach-shmobile/built-in.o: In function `shmobile_platform_cpu_kill': +/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:62: undefined reference to `emev2_platform_cpu_kill' +arch/arm/mach-shmobile/built-in.o: In function `shmobile_smp_get_core_count': +/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:39: undefined reference to `emev2_get_core_count' +arch/arm/mach-shmobile/built-in.o: In function `shmobile_smp_prepare_cpus': +/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:53: undefined reference to `emev2_smp_prepare_cpus' +arch/arm/mach-shmobile/built-in.o: In function `platform_secondary_init': +/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:78: undefined reference to `emev2_secondary_init' +arch/arm/mach-shmobile/built-in.o: In function `boot_secondary': +/home/iwamatsu/work/kernel/sh-2.6-devel/arch/arm/mach-shmobile/platsmp.c:90: undefined reference to `emev2_boot_secondary + +This is the cause by when EMEV2 is disabled, that the check by OF of EMEV2 is +performed in platsmp.c. +This patch revise what the function about EMEV2 may not be used in this file, +when EMEV2 is not enabled. + +Signed-off-by: Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> +Acked-by: Simon Horman <horms@verge.net.au> +Acked-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 6ae42bb22b40254e6488bbfe47f970620ab6d433) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-shmobile/platsmp.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c +index 5f1a59b..fde0d23 100644 +--- a/arch/arm/mach-shmobile/platsmp.c ++++ b/arch/arm/mach-shmobile/platsmp.c +@@ -30,7 +30,12 @@ + #endif + + #define is_r8a7779() machine_is_marzen() ++ ++#ifdef CONFIG_ARCH_EMEV2 + #define is_emev2() of_machine_is_compatible("renesas,emev2") ++#else ++#define is_emev2() (0) ++#endif + + static unsigned int __init shmobile_smp_get_core_count(void) + { +-- +1.7.9.5 + diff --git a/patches.kzm9d/arm-mach-shmobile-kzm9d-add-defconfig.patch b/patches.kzm9d/arm-mach-shmobile-kzm9d-add-defconfig.patch new file mode 100644 index 0000000000000..fa9f6e4312723 --- /dev/null +++ b/patches.kzm9d/arm-mach-shmobile-kzm9d-add-defconfig.patch @@ -0,0 +1,122 @@ +From koba@kmckk.co.jp Wed Oct 3 04:30:14 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:15 +0900 +Subject: [PATCH 23/26] ARM: mach-shmobile: kzm9d: Add defconfig +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-24-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Original work by Magnus Damm, tested and tweaked by Simon Horman + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit d252f644789188743b55339f5756a8bcc86fbaa5) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/configs/kzm9d_defconfig | 89 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 89 insertions(+) + create mode 100644 arch/arm/configs/kzm9d_defconfig + +diff --git a/arch/arm/configs/kzm9d_defconfig b/arch/arm/configs/kzm9d_defconfig +new file mode 100644 +index 0000000..26146ff +--- /dev/null ++++ b/arch/arm/configs/kzm9d_defconfig +@@ -0,0 +1,89 @@ ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set ++CONFIG_EXPERIMENTAL=y ++CONFIG_SYSVIPC=y ++CONFIG_NO_HZ=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_LOG_BUF_SHIFT=16 ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SYSCTL_SYSCALL=y ++CONFIG_EMBEDDED=y ++CONFIG_SLAB=y ++# CONFIG_BLK_DEV_BSG is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_ARCH_SHMOBILE=y ++CONFIG_ARCH_EMEV2=y ++CONFIG_MACH_KZM9D=y ++CONFIG_MEMORY_START=0x40000000 ++CONFIG_MEMORY_SIZE=0x10000000 ++# CONFIG_SH_TIMER_TMU is not set ++# CONFIG_SWP_EMULATE is not set ++# CONFIG_CACHE_L2X0 is not set ++CONFIG_SMP=y ++CONFIG_NR_CPUS=2 ++CONFIG_HOTPLUG_CPU=y ++# CONFIG_LOCAL_TIMERS is not set ++CONFIG_AEABI=y ++# CONFIG_OABI_COMPAT is not set ++# CONFIG_CROSS_MEMORY_ATTACH is not set ++CONFIG_FORCE_MAX_ZONEORDER=13 ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_ARM_APPENDED_DTB=y ++CONFIG_CMDLINE="console=tty0 console=ttyS1,115200n81 earlyprintk=serial8250-em.1,115200n81 mem=128M@0x40000000 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096" ++CONFIG_CMDLINE_FORCE=y ++CONFIG_VFP=y ++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set ++# CONFIG_SUSPEND is not set ++CONFIG_NET=y ++CONFIG_PACKET=y ++CONFIG_UNIX=y ++CONFIG_INET=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set ++# CONFIG_INET_XFRM_MODE_TUNNEL is not set ++# CONFIG_INET_XFRM_MODE_BEET is not set ++# CONFIG_INET_LRO is not set ++# CONFIG_INET_DIAG is not set ++# CONFIG_IPV6 is not set ++# CONFIG_WIRELESS is not set ++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++# CONFIG_BLK_DEV is not set ++CONFIG_NETDEVICES=y ++# CONFIG_NET_VENDOR_BROADCOM is not set ++# CONFIG_NET_VENDOR_CHELSIO is not set ++# CONFIG_NET_VENDOR_CIRRUS is not set ++# CONFIG_NET_VENDOR_FARADAY is not set ++# CONFIG_NET_VENDOR_INTEL is not set ++# CONFIG_NET_VENDOR_MARVELL is not set ++# CONFIG_NET_VENDOR_MICREL is not set ++# CONFIG_NET_VENDOR_NATSEMI is not set ++# CONFIG_NET_VENDOR_SEEQ is not set ++CONFIG_SMSC911X=y ++# CONFIG_NET_VENDOR_STMICRO is not set ++# CONFIG_NET_VENDOR_WIZNET is not set ++# CONFIG_WLAN is not set ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_KEYBOARD is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_SERIO is not set ++# CONFIG_LEGACY_PTYS is not set ++# CONFIG_DEVKMEM is not set ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_EM=y ++# CONFIG_HW_RANDOM is not set ++CONFIG_GPIOLIB=y ++CONFIG_GPIO_EM=y ++# CONFIG_HWMON is not set ++# CONFIG_HID_SUPPORT is not set ++# CONFIG_USB_SUPPORT is not set ++# CONFIG_IOMMU_SUPPORT is not set ++# CONFIG_DNOTIFY is not set ++CONFIG_TMPFS=y ++# CONFIG_MISC_FILESYSTEMS is not set ++CONFIG_NFS_FS=y ++CONFIG_ROOT_NFS=y ++# CONFIG_FTRACE is not set +-- +1.7.9.5 + diff --git a/patches.kzm9d/clockevents-make-clockevents_config-a-global-symbol.patch b/patches.kzm9d/clockevents-make-clockevents_config-a-global-symbol.patch new file mode 100644 index 0000000000000..6d696a43c1a41 --- /dev/null +++ b/patches.kzm9d/clockevents-make-clockevents_config-a-global-symbol.patch @@ -0,0 +1,63 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:56 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:04 +0900 +Subject: [PATCH 12/26] clockevents: Make clockevents_config() a global symbol +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Magnus Damm <magnus.damm@gmail.com>, arnd@arndb.de, johnstul@us.ibm.com, rjw@sisk.pl, lethal@linux-sh.org, gregkh@linuxfoundation.org, olof@lixom.net, Thomas Gleixner <tglx@linutronix.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-13-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <magnus.damm@gmail.com> + +Make clockevents_config() into a global symbol to allow it to be used +by compiled-in clockevent drivers. This is needed by drivers that want +to update the timer frequency after registration time. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Tested-by: Simon Horman <horms@verge.net.au> +Cc: arnd@arndb.de +Cc: johnstul@us.ibm.com +Cc: rjw@sisk.pl +Cc: lethal@linux-sh.org +Cc: gregkh@linuxfoundation.org +Cc: olof@lixom.net +Cc: Magnus Damm <magnus.damm@gmail.com> +Link: http://lkml.kernel.org/r/20120509143934.27521.46553.sendpatchset@w520 +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit e5400321a6f15ce0fe77c8455954f213ef7dcc54) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + include/linux/clockchips.h | 1 + + kernel/time/clockevents.c | 3 +-- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h +index 81e803e..acba8943 100644 +--- a/include/linux/clockchips.h ++++ b/include/linux/clockchips.h +@@ -132,6 +132,7 @@ extern u64 clockevent_delta2ns(unsigned long latch, + struct clock_event_device *evt); + extern void clockevents_register_device(struct clock_event_device *dev); + ++extern void clockevents_config(struct clock_event_device *dev, u32 freq); + extern void clockevents_config_and_register(struct clock_event_device *dev, + u32 freq, unsigned long min_delta, + unsigned long max_delta); +diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c +index 9cd928f..7e1ce01 100644 +--- a/kernel/time/clockevents.c ++++ b/kernel/time/clockevents.c +@@ -297,8 +297,7 @@ void clockevents_register_device(struct clock_event_device *dev) + } + EXPORT_SYMBOL_GPL(clockevents_register_device); + +-static void clockevents_config(struct clock_event_device *dev, +- u32 freq) ++void clockevents_config(struct clock_event_device *dev, u32 freq) + { + u64 sec; + +-- +1.7.9.5 + diff --git a/patches.kzm9d/clocksource-em_sti-add-dt-support.patch b/patches.kzm9d/clocksource-em_sti-add-dt-support.patch new file mode 100644 index 0000000000000..cc718d26d94d1 --- /dev/null +++ b/patches.kzm9d/clocksource-em_sti-add-dt-support.patch @@ -0,0 +1,56 @@ +From koba@kmckk.co.jp Wed Oct 3 04:28:36 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:06 +0900 +Subject: [PATCH 14/26] clocksource: em_sti: Add DT support +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Magnus Damm <magnus.damm@gmail.com>, arnd@arndb.de, johnstul@us.ibm.com, rjw@sisk.pl, lethal@linux-sh.org, gregkh@linuxfoundation.org, olof@lixom.net, Thomas Gleixner <tglx@linutronix.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-15-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <magnus.damm@gmail.com> + +Update the em-sti driver to support DT. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Cc: arnd@arndb.de +Cc: horms@verge.net.au +Cc: johnstul@us.ibm.com +Cc: rjw@sisk.pl +Cc: lethal@linux-sh.org +Cc: gregkh@linuxfoundation.org +Cc: olof@lixom.net +Link: http://lkml.kernel.org/r/20120509143950.27521.7949.sendpatchset@w520 +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit fc0830fe017d02b7b4995b5c402b484b65d9dfc6) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/clocksource/em_sti.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c +index 719584a..372051d 100644 +--- a/drivers/clocksource/em_sti.c ++++ b/drivers/clocksource/em_sti.c +@@ -384,11 +384,18 @@ static int __devexit em_sti_remove(struct platform_device *pdev) + return -EBUSY; /* cannot unregister clockevent and clocksource */ + } + ++static const struct of_device_id em_sti_dt_ids[] __devinitconst = { ++ { .compatible = "renesas,em-sti", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, em_sti_dt_ids); ++ + static struct platform_driver em_sti_device_driver = { + .probe = em_sti_probe, + .remove = __devexit_p(em_sti_remove), + .driver = { + .name = "em_sti", ++ .of_match_table = em_sti_dt_ids, + } + }; + +-- +1.7.9.5 + diff --git a/patches.kzm9d/clocksource-em_sti-emma-mobile-sti-driver.patch b/patches.kzm9d/clocksource-em_sti-emma-mobile-sti-driver.patch new file mode 100644 index 0000000000000..cb2092803c489 --- /dev/null +++ b/patches.kzm9d/clocksource-em_sti-emma-mobile-sti-driver.patch @@ -0,0 +1,468 @@ +From koba@kmckk.co.jp Wed Oct 3 04:28:15 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:05 +0900 +Subject: [PATCH 13/26] clocksource: em_sti: Emma Mobile STI driver +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Magnus Damm <magnus.damm@gmail.com>, arnd@arndb.de, johnstul@us.ibm.com, rjw@sisk.pl, lethal@linux-sh.org, gregkh@linuxfoundation.org, olof@lixom.net, Thomas Gleixner <tglx@linutronix.de>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-14-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <magnus.damm@gmail.com> + +The STI hardware is based on a single 48-bit 32kHz +counter that together with two individual compare +registers can generate interrupts. There are no +timer operating modes selectable which means that +the timer can not clear on match. + +This driver is providing clocksource support for the +48-bit counter. Clockevents are also supported using +the same timer in oneshot mode. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Cc: horms@verge.net.au +Cc: arnd@arndb.de +Cc: johnstul@us.ibm.com +Cc: rjw@sisk.pl +Cc: lethal@linux-sh.org +Cc: gregkh@linuxfoundation.org +Cc: olof@lixom.net +Link: http://lkml.kernel.org/r/20120525070344.23443.69756.sendpatchset@w520 +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +(cherry picked from commit b9dbf9517784084ee9496f9f17f9754c1d021a9e) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-shmobile/Kconfig | 6 + drivers/clocksource/Makefile | 1 + drivers/clocksource/em_sti.c | 399 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 406 insertions(+) + create mode 100644 drivers/clocksource/em_sti.c + +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -177,6 +177,12 @@ config SH_TIMER_TMU + help + This enables build of the TMU timer driver. + ++config EM_TIMER_STI ++ bool "STI timer driver" ++ default y ++ help ++ This enables build of the STI timer driver. ++ + endmenu + + config SH_CLK_CPG +--- a/drivers/clocksource/Makefile ++++ b/drivers/clocksource/Makefile +@@ -6,6 +6,7 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC) += + obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o + obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o + obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o ++obj-$(CONFIG_EM_TIMER_STI) += em_sti.o + obj-$(CONFIG_CLKBLD_I8253) += i8253.o + obj-$(CONFIG_CLKSRC_MMIO) += mmio.o + obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o +--- /dev/null ++++ b/drivers/clocksource/em_sti.c +@@ -0,0 +1,399 @@ ++/* ++ * Emma Mobile Timer Support - STI ++ * ++ * Copyright (C) 2012 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/interrupt.h> ++#include <linux/ioport.h> ++#include <linux/io.h> ++#include <linux/clk.h> ++#include <linux/irq.h> ++#include <linux/err.h> ++#include <linux/delay.h> ++#include <linux/clocksource.h> ++#include <linux/clockchips.h> ++#include <linux/slab.h> ++#include <linux/module.h> ++ ++enum { USER_CLOCKSOURCE, USER_CLOCKEVENT, USER_NR }; ++ ++struct em_sti_priv { ++ void __iomem *base; ++ struct clk *clk; ++ struct platform_device *pdev; ++ unsigned int active[USER_NR]; ++ unsigned long rate; ++ raw_spinlock_t lock; ++ struct clock_event_device ced; ++ struct clocksource cs; ++}; ++ ++#define STI_CONTROL 0x00 ++#define STI_COMPA_H 0x10 ++#define STI_COMPA_L 0x14 ++#define STI_COMPB_H 0x18 ++#define STI_COMPB_L 0x1c ++#define STI_COUNT_H 0x20 ++#define STI_COUNT_L 0x24 ++#define STI_COUNT_RAW_H 0x28 ++#define STI_COUNT_RAW_L 0x2c ++#define STI_SET_H 0x30 ++#define STI_SET_L 0x34 ++#define STI_INTSTATUS 0x40 ++#define STI_INTRAWSTATUS 0x44 ++#define STI_INTENSET 0x48 ++#define STI_INTENCLR 0x4c ++#define STI_INTFFCLR 0x50 ++ ++static inline unsigned long em_sti_read(struct em_sti_priv *p, int offs) ++{ ++ return ioread32(p->base + offs); ++} ++ ++static inline void em_sti_write(struct em_sti_priv *p, int offs, ++ unsigned long value) ++{ ++ iowrite32(value, p->base + offs); ++} ++ ++static int em_sti_enable(struct em_sti_priv *p) ++{ ++ int ret; ++ ++ /* enable clock */ ++ ret = clk_enable(p->clk); ++ if (ret) { ++ dev_err(&p->pdev->dev, "cannot enable clock\n"); ++ return ret; ++ } ++ ++ /* configure channel, periodic mode and maximum timeout */ ++ p->rate = clk_get_rate(p->clk); ++ ++ /* reset the counter */ ++ em_sti_write(p, STI_SET_H, 0x40000000); ++ em_sti_write(p, STI_SET_L, 0x00000000); ++ ++ /* mask and clear pending interrupts */ ++ em_sti_write(p, STI_INTENCLR, 3); ++ em_sti_write(p, STI_INTFFCLR, 3); ++ ++ /* enable updates of counter registers */ ++ em_sti_write(p, STI_CONTROL, 1); ++ ++ return 0; ++} ++ ++static void em_sti_disable(struct em_sti_priv *p) ++{ ++ /* mask interrupts */ ++ em_sti_write(p, STI_INTENCLR, 3); ++ ++ /* stop clock */ ++ clk_disable(p->clk); ++} ++ ++static cycle_t em_sti_count(struct em_sti_priv *p) ++{ ++ cycle_t ticks; ++ unsigned long flags; ++ ++ /* the STI hardware buffers the 48-bit count, but to ++ * break it out into two 32-bit access the registers ++ * must be accessed in a certain order. ++ * Always read STI_COUNT_H before STI_COUNT_L. ++ */ ++ raw_spin_lock_irqsave(&p->lock, flags); ++ ticks = (cycle_t)(em_sti_read(p, STI_COUNT_H) & 0xffff) << 32; ++ ticks |= em_sti_read(p, STI_COUNT_L); ++ raw_spin_unlock_irqrestore(&p->lock, flags); ++ ++ return ticks; ++} ++ ++static cycle_t em_sti_set_next(struct em_sti_priv *p, cycle_t next) ++{ ++ unsigned long flags; ++ ++ raw_spin_lock_irqsave(&p->lock, flags); ++ ++ /* mask compare A interrupt */ ++ em_sti_write(p, STI_INTENCLR, 1); ++ ++ /* update compare A value */ ++ em_sti_write(p, STI_COMPA_H, next >> 32); ++ em_sti_write(p, STI_COMPA_L, next & 0xffffffff); ++ ++ /* clear compare A interrupt source */ ++ em_sti_write(p, STI_INTFFCLR, 1); ++ ++ /* unmask compare A interrupt */ ++ em_sti_write(p, STI_INTENSET, 1); ++ ++ raw_spin_unlock_irqrestore(&p->lock, flags); ++ ++ return next; ++} ++ ++static irqreturn_t em_sti_interrupt(int irq, void *dev_id) ++{ ++ struct em_sti_priv *p = dev_id; ++ ++ p->ced.event_handler(&p->ced); ++ return IRQ_HANDLED; ++} ++ ++static int em_sti_start(struct em_sti_priv *p, unsigned int user) ++{ ++ unsigned long flags; ++ int used_before; ++ int ret = 0; ++ ++ raw_spin_lock_irqsave(&p->lock, flags); ++ used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; ++ if (!used_before) ++ ret = em_sti_enable(p); ++ ++ if (!ret) ++ p->active[user] = 1; ++ raw_spin_unlock_irqrestore(&p->lock, flags); ++ ++ return ret; ++} ++ ++static void em_sti_stop(struct em_sti_priv *p, unsigned int user) ++{ ++ unsigned long flags; ++ int used_before, used_after; ++ ++ raw_spin_lock_irqsave(&p->lock, flags); ++ used_before = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; ++ p->active[user] = 0; ++ used_after = p->active[USER_CLOCKSOURCE] | p->active[USER_CLOCKEVENT]; ++ ++ if (used_before && !used_after) ++ em_sti_disable(p); ++ raw_spin_unlock_irqrestore(&p->lock, flags); ++} ++ ++static struct em_sti_priv *cs_to_em_sti(struct clocksource *cs) ++{ ++ return container_of(cs, struct em_sti_priv, cs); ++} ++ ++static cycle_t em_sti_clocksource_read(struct clocksource *cs) ++{ ++ return em_sti_count(cs_to_em_sti(cs)); ++} ++ ++static int em_sti_clocksource_enable(struct clocksource *cs) ++{ ++ int ret; ++ struct em_sti_priv *p = cs_to_em_sti(cs); ++ ++ ret = em_sti_start(p, USER_CLOCKSOURCE); ++ if (!ret) ++ __clocksource_updatefreq_hz(cs, p->rate); ++ return ret; ++} ++ ++static void em_sti_clocksource_disable(struct clocksource *cs) ++{ ++ em_sti_stop(cs_to_em_sti(cs), USER_CLOCKSOURCE); ++} ++ ++static void em_sti_clocksource_resume(struct clocksource *cs) ++{ ++ em_sti_clocksource_enable(cs); ++} ++ ++static int em_sti_register_clocksource(struct em_sti_priv *p) ++{ ++ struct clocksource *cs = &p->cs; ++ ++ memset(cs, 0, sizeof(*cs)); ++ cs->name = dev_name(&p->pdev->dev); ++ cs->rating = 200; ++ cs->read = em_sti_clocksource_read; ++ cs->enable = em_sti_clocksource_enable; ++ cs->disable = em_sti_clocksource_disable; ++ cs->suspend = em_sti_clocksource_disable; ++ cs->resume = em_sti_clocksource_resume; ++ cs->mask = CLOCKSOURCE_MASK(48); ++ cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; ++ ++ dev_info(&p->pdev->dev, "used as clock source\n"); ++ ++ /* Register with dummy 1 Hz value, gets updated in ->enable() */ ++ clocksource_register_hz(cs, 1); ++ return 0; ++} ++ ++static struct em_sti_priv *ced_to_em_sti(struct clock_event_device *ced) ++{ ++ return container_of(ced, struct em_sti_priv, ced); ++} ++ ++static void em_sti_clock_event_mode(enum clock_event_mode mode, ++ struct clock_event_device *ced) ++{ ++ struct em_sti_priv *p = ced_to_em_sti(ced); ++ ++ /* deal with old setting first */ ++ switch (ced->mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ em_sti_stop(p, USER_CLOCKEVENT); ++ break; ++ default: ++ break; ++ } ++ ++ switch (mode) { ++ case CLOCK_EVT_MODE_ONESHOT: ++ dev_info(&p->pdev->dev, "used for oneshot clock events\n"); ++ em_sti_start(p, USER_CLOCKEVENT); ++ clockevents_config(&p->ced, p->rate); ++ break; ++ case CLOCK_EVT_MODE_SHUTDOWN: ++ case CLOCK_EVT_MODE_UNUSED: ++ em_sti_stop(p, USER_CLOCKEVENT); ++ break; ++ default: ++ break; ++ } ++} ++ ++static int em_sti_clock_event_next(unsigned long delta, ++ struct clock_event_device *ced) ++{ ++ struct em_sti_priv *p = ced_to_em_sti(ced); ++ cycle_t next; ++ int safe; ++ ++ next = em_sti_set_next(p, em_sti_count(p) + delta); ++ safe = em_sti_count(p) < (next - 1); ++ ++ return !safe; ++} ++ ++static void em_sti_register_clockevent(struct em_sti_priv *p) ++{ ++ struct clock_event_device *ced = &p->ced; ++ ++ memset(ced, 0, sizeof(*ced)); ++ ced->name = dev_name(&p->pdev->dev); ++ ced->features = CLOCK_EVT_FEAT_ONESHOT; ++ ced->rating = 200; ++ ced->cpumask = cpumask_of(0); ++ ced->set_next_event = em_sti_clock_event_next; ++ ced->set_mode = em_sti_clock_event_mode; ++ ++ dev_info(&p->pdev->dev, "used for clock events\n"); ++ ++ /* Register with dummy 1 Hz value, gets updated in ->set_mode() */ ++ clockevents_config_and_register(ced, 1, 2, 0xffffffff); ++} ++ ++static int __devinit em_sti_probe(struct platform_device *pdev) ++{ ++ struct em_sti_priv *p; ++ struct resource *res; ++ int irq, ret; ++ ++ p = kzalloc(sizeof(*p), GFP_KERNEL); ++ if (p == NULL) { ++ dev_err(&pdev->dev, "failed to allocate driver data\n"); ++ ret = -ENOMEM; ++ goto err0; ++ } ++ ++ p->pdev = pdev; ++ platform_set_drvdata(pdev, p); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "failed to get I/O memory\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ irq = platform_get_irq(pdev, 0); ++ if (irq < 0) { ++ dev_err(&pdev->dev, "failed to get irq\n"); ++ ret = -EINVAL; ++ goto err0; ++ } ++ ++ /* map memory, let base point to the STI instance */ ++ p->base = ioremap_nocache(res->start, resource_size(res)); ++ if (p->base == NULL) { ++ dev_err(&pdev->dev, "failed to remap I/O memory\n"); ++ ret = -ENXIO; ++ goto err0; ++ } ++ ++ /* get hold of clock */ ++ p->clk = clk_get(&pdev->dev, "sclk"); ++ if (IS_ERR(p->clk)) { ++ dev_err(&pdev->dev, "cannot get clock\n"); ++ ret = PTR_ERR(p->clk); ++ goto err1; ++ } ++ ++ if (request_irq(irq, em_sti_interrupt, ++ IRQF_TIMER | IRQF_IRQPOLL | IRQF_NOBALANCING, ++ dev_name(&pdev->dev), p)) { ++ dev_err(&pdev->dev, "failed to request low IRQ\n"); ++ ret = -ENOENT; ++ goto err2; ++ } ++ ++ raw_spin_lock_init(&p->lock); ++ em_sti_register_clockevent(p); ++ em_sti_register_clocksource(p); ++ return 0; ++ ++err2: ++ clk_put(p->clk); ++err1: ++ iounmap(p->base); ++err0: ++ kfree(p); ++ return ret; ++} ++ ++static int __devexit em_sti_remove(struct platform_device *pdev) ++{ ++ return -EBUSY; /* cannot unregister clockevent and clocksource */ ++} ++ ++static struct platform_driver em_sti_device_driver = { ++ .probe = em_sti_probe, ++ .remove = __devexit_p(em_sti_remove), ++ .driver = { ++ .name = "em_sti", ++ } ++}; ++ ++module_platform_driver(em_sti_device_driver); ++ ++MODULE_AUTHOR("Magnus Damm"); ++MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); ++MODULE_LICENSE("GPL v2"); diff --git a/patches.kzm9d/gpio-emma-mobile-gpio-driver-v2.patch b/patches.kzm9d/gpio-emma-mobile-gpio-driver-v2.patch new file mode 100644 index 0000000000000..fa0b501fd36e9 --- /dev/null +++ b/patches.kzm9d/gpio-emma-mobile-gpio-driver-v2.patch @@ -0,0 +1,499 @@ +From koba@kmckk.co.jp Wed Oct 3 04:29:20 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:09 +0900 +Subject: [PATCH 17/26] gpio: Emma Mobile GPIO driver V2 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-18-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +This patch is V2 of the Emma Mobile GPIO driver. This +driver is designed to be reusable between multiple SoCs +that share the same basic building block, but so far it +has only been used on Emma Mobile EV2. + +Each driver instance handles 32 GPIOs with individually +maskable IRQs. The driver operates on two I/O memory +ranges and the 32 GPIOs are hooked up to two interrupts. + +In the case of Emma Mobile EV2 this GPIO building block +is used as main external interrupt controller hooking up +159 GPIOS as 159 interrupts via 5 driver instances and +10 interrupts to the GIC and the Cortex-A9 Dual. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit a07e103ef08c6907d695a06467d7ee950796fccf) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-em.c | 418 ++++++++++++++++++++++++++++++++++ + include/linux/platform_data/gpio-em.h | 10 + 4 files changed, 435 insertions(+) + create mode 100644 drivers/gpio/gpio-em.c + create mode 100644 include/linux/platform_data/gpio-em.h + +--- a/drivers/gpio/Kconfig ++++ b/drivers/gpio/Kconfig +@@ -91,6 +91,12 @@ config GPIO_IT8761E + help + Say yes here to support GPIO functionality of IT8761E super I/O chip. + ++config GPIO_EM ++ tristate "Emma Mobile GPIO" ++ depends on ARM ++ help ++ Say yes here to support GPIO on Renesas Emma Mobile SoCs. ++ + config GPIO_EP93XX + def_bool y + depends on ARCH_EP93XX +--- a/drivers/gpio/Makefile ++++ b/drivers/gpio/Makefile +@@ -15,6 +15,7 @@ obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o + obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o + obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o + obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o ++obj-$(CONFIG_GPIO_EM) += gpio-em.o + obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o + obj-$(CONFIG_GPIO_GE_FPGA) += gpio-ge.o + obj-$(CONFIG_GPIO_IT8761E) += gpio-it8761e.o +--- /dev/null ++++ b/drivers/gpio/gpio-em.c +@@ -0,0 +1,418 @@ ++/* ++ * Emma Mobile GPIO Support - GIO ++ * ++ * Copyright (C) 2012 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/spinlock.h> ++#include <linux/interrupt.h> ++#include <linux/ioport.h> ++#include <linux/io.h> ++#include <linux/irq.h> ++#include <linux/irqdomain.h> ++#include <linux/bitops.h> ++#include <linux/err.h> ++#include <linux/gpio.h> ++#include <linux/slab.h> ++#include <linux/module.h> ++#include <linux/platform_data/gpio-em.h> ++ ++struct em_gio_priv { ++ void __iomem *base0; ++ void __iomem *base1; ++ unsigned int irq_base; ++ spinlock_t sense_lock; ++ struct platform_device *pdev; ++ struct gpio_chip gpio_chip; ++ struct irq_chip irq_chip; ++ struct irq_domain *irq_domain; ++}; ++ ++#define GIO_E1 0x00 ++#define GIO_E0 0x04 ++#define GIO_EM 0x04 ++#define GIO_OL 0x08 ++#define GIO_OH 0x0c ++#define GIO_I 0x10 ++#define GIO_IIA 0x14 ++#define GIO_IEN 0x18 ++#define GIO_IDS 0x1c ++#define GIO_IIM 0x1c ++#define GIO_RAW 0x20 ++#define GIO_MST 0x24 ++#define GIO_IIR 0x28 ++ ++#define GIO_IDT0 0x40 ++#define GIO_IDT1 0x44 ++#define GIO_IDT2 0x48 ++#define GIO_IDT3 0x4c ++#define GIO_RAWBL 0x50 ++#define GIO_RAWBH 0x54 ++#define GIO_IRBL 0x58 ++#define GIO_IRBH 0x5c ++ ++#define GIO_IDT(n) (GIO_IDT0 + ((n) * 4)) ++ ++static inline unsigned long em_gio_read(struct em_gio_priv *p, int offs) ++{ ++ if (offs < GIO_IDT0) ++ return ioread32(p->base0 + offs); ++ else ++ return ioread32(p->base1 + (offs - GIO_IDT0)); ++} ++ ++static inline void em_gio_write(struct em_gio_priv *p, int offs, ++ unsigned long value) ++{ ++ if (offs < GIO_IDT0) ++ iowrite32(value, p->base0 + offs); ++ else ++ iowrite32(value, p->base1 + (offs - GIO_IDT0)); ++} ++ ++static inline struct em_gio_priv *irq_to_priv(struct irq_data *d) ++{ ++ struct irq_chip *chip = irq_data_get_irq_chip(d); ++ return container_of(chip, struct em_gio_priv, irq_chip); ++} ++ ++static void em_gio_irq_disable(struct irq_data *d) ++{ ++ struct em_gio_priv *p = irq_to_priv(d); ++ ++ em_gio_write(p, GIO_IDS, BIT(irqd_to_hwirq(d))); ++} ++ ++static void em_gio_irq_enable(struct irq_data *d) ++{ ++ struct em_gio_priv *p = irq_to_priv(d); ++ ++ em_gio_write(p, GIO_IEN, BIT(irqd_to_hwirq(d))); ++} ++ ++#define GIO_ASYNC(x) (x + 8) ++ ++static unsigned char em_gio_sense_table[IRQ_TYPE_SENSE_MASK + 1] = { ++ [IRQ_TYPE_EDGE_RISING] = GIO_ASYNC(0x00), ++ [IRQ_TYPE_EDGE_FALLING] = GIO_ASYNC(0x01), ++ [IRQ_TYPE_LEVEL_HIGH] = GIO_ASYNC(0x02), ++ [IRQ_TYPE_LEVEL_LOW] = GIO_ASYNC(0x03), ++ [IRQ_TYPE_EDGE_BOTH] = GIO_ASYNC(0x04), ++}; ++ ++static int em_gio_irq_set_type(struct irq_data *d, unsigned int type) ++{ ++ unsigned char value = em_gio_sense_table[type & IRQ_TYPE_SENSE_MASK]; ++ struct em_gio_priv *p = irq_to_priv(d); ++ unsigned int reg, offset, shift; ++ unsigned long flags; ++ unsigned long tmp; ++ ++ if (!value) ++ return -EINVAL; ++ ++ offset = irqd_to_hwirq(d); ++ ++ pr_debug("gio: sense irq = %d, mode = %d\n", offset, value); ++ ++ /* 8 x 4 bit fields in 4 IDT registers */ ++ reg = GIO_IDT(offset >> 3); ++ shift = (offset & 0x07) << 4; ++ ++ spin_lock_irqsave(&p->sense_lock, flags); ++ ++ /* disable the interrupt in IIA */ ++ tmp = em_gio_read(p, GIO_IIA); ++ tmp &= ~BIT(offset); ++ em_gio_write(p, GIO_IIA, tmp); ++ ++ /* change the sense setting in IDT */ ++ tmp = em_gio_read(p, reg); ++ tmp &= ~(0xf << shift); ++ tmp |= value << shift; ++ em_gio_write(p, reg, tmp); ++ ++ /* clear pending interrupts */ ++ em_gio_write(p, GIO_IIR, BIT(offset)); ++ ++ /* enable the interrupt in IIA */ ++ tmp = em_gio_read(p, GIO_IIA); ++ tmp |= BIT(offset); ++ em_gio_write(p, GIO_IIA, tmp); ++ ++ spin_unlock_irqrestore(&p->sense_lock, flags); ++ ++ return 0; ++} ++ ++static irqreturn_t em_gio_irq_handler(int irq, void *dev_id) ++{ ++ struct em_gio_priv *p = dev_id; ++ unsigned long pending; ++ unsigned int offset, irqs_handled = 0; ++ ++ while ((pending = em_gio_read(p, GIO_MST))) { ++ offset = __ffs(pending); ++ em_gio_write(p, GIO_IIR, BIT(offset)); ++ generic_handle_irq(irq_find_mapping(p->irq_domain, offset)); ++ irqs_handled++; ++ } ++ ++ return irqs_handled ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++static inline struct em_gio_priv *gpio_to_priv(struct gpio_chip *chip) ++{ ++ return container_of(chip, struct em_gio_priv, gpio_chip); ++} ++ ++static int em_gio_direction_input(struct gpio_chip *chip, unsigned offset) ++{ ++ em_gio_write(gpio_to_priv(chip), GIO_E0, BIT(offset)); ++ return 0; ++} ++ ++static int em_gio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & BIT(offset)); ++} ++ ++static void __em_gio_set(struct gpio_chip *chip, unsigned int reg, ++ unsigned shift, int value) ++{ ++ /* upper 16 bits contains mask and lower 16 actual value */ ++ em_gio_write(gpio_to_priv(chip), reg, ++ (1 << (shift + 16)) | (value << shift)); ++} ++ ++static void em_gio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ /* output is split into two registers */ ++ if (offset < 16) ++ __em_gio_set(chip, GIO_OL, offset, value); ++ else ++ __em_gio_set(chip, GIO_OH, offset - 16, value); ++} ++ ++static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, ++ int value) ++{ ++ /* write GPIO value to output before selecting output mode of pin */ ++ em_gio_set(chip, offset, value); ++ em_gio_write(gpio_to_priv(chip), GIO_E1, BIT(offset)); ++ return 0; ++} ++ ++static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset) ++{ ++ return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset); ++} ++ ++static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq, ++ irq_hw_number_t hw) ++{ ++ struct em_gio_priv *p = h->host_data; ++ ++ pr_debug("gio: map hw irq = %d, virq = %d\n", (int)hw, virq); ++ ++ irq_set_chip_data(virq, h->host_data); ++ irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); ++ set_irq_flags(virq, IRQF_VALID); /* kill me now */ ++ return 0; ++} ++ ++static struct irq_domain_ops em_gio_irq_domain_ops = { ++ .map = em_gio_irq_domain_map, ++}; ++ ++static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p) ++{ ++ struct platform_device *pdev = p->pdev; ++ struct gpio_em_config *pdata = pdev->dev.platform_data; ++ ++ p->irq_base = irq_alloc_descs(pdata->irq_base, 0, ++ pdata->number_of_pins, numa_node_id()); ++ if (IS_ERR_VALUE(p->irq_base)) { ++ dev_err(&pdev->dev, "cannot get irq_desc\n"); ++ return -ENXIO; ++ } ++ pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n", ++ pdata->gpio_base, pdata->number_of_pins, p->irq_base); ++ ++ p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node, ++ pdata->number_of_pins, ++ p->irq_base, 0, ++ &em_gio_irq_domain_ops, p); ++ if (!p->irq_domain) { ++ irq_free_descs(p->irq_base, pdata->number_of_pins); ++ return -ENXIO; ++ } ++ ++ return 0; ++} ++ ++static void __devexit em_gio_irq_domain_cleanup(struct em_gio_priv *p) ++{ ++ struct gpio_em_config *pdata = p->pdev->dev.platform_data; ++ ++ irq_free_descs(p->irq_base, pdata->number_of_pins); ++ /* FIXME: irq domain wants to be freed! */ ++} ++ ++static int __devinit em_gio_probe(struct platform_device *pdev) ++{ ++ struct gpio_em_config *pdata = pdev->dev.platform_data; ++ struct em_gio_priv *p; ++ struct resource *io[2], *irq[2]; ++ struct gpio_chip *gpio_chip; ++ struct irq_chip *irq_chip; ++ const char *name = dev_name(&pdev->dev); ++ int ret; ++ ++ p = kzalloc(sizeof(*p), GFP_KERNEL); ++ if (!p) { ++ dev_err(&pdev->dev, "failed to allocate driver data\n"); ++ ret = -ENOMEM; ++ goto err0; ++ } ++ ++ p->pdev = pdev; ++ platform_set_drvdata(pdev, p); ++ spin_lock_init(&p->sense_lock); ++ ++ io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1); ++ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); ++ ++ if (!io[0] || !io[1] || !irq[0] || !irq[1] || !pdata) { ++ dev_err(&pdev->dev, "missing IRQ, IOMEM or configuration\n"); ++ ret = -EINVAL; ++ goto err1; ++ } ++ ++ p->base0 = ioremap_nocache(io[0]->start, resource_size(io[0])); ++ if (!p->base0) { ++ dev_err(&pdev->dev, "failed to remap low I/O memory\n"); ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ p->base1 = ioremap_nocache(io[1]->start, resource_size(io[1])); ++ if (!p->base1) { ++ dev_err(&pdev->dev, "failed to remap high I/O memory\n"); ++ ret = -ENXIO; ++ goto err2; ++ } ++ ++ gpio_chip = &p->gpio_chip; ++ gpio_chip->direction_input = em_gio_direction_input; ++ gpio_chip->get = em_gio_get; ++ gpio_chip->direction_output = em_gio_direction_output; ++ gpio_chip->set = em_gio_set; ++ gpio_chip->to_irq = em_gio_to_irq; ++ gpio_chip->label = name; ++ gpio_chip->owner = THIS_MODULE; ++ gpio_chip->base = pdata->gpio_base; ++ gpio_chip->ngpio = pdata->number_of_pins; ++ ++ irq_chip = &p->irq_chip; ++ irq_chip->name = name; ++ irq_chip->irq_mask = em_gio_irq_disable; ++ irq_chip->irq_unmask = em_gio_irq_enable; ++ irq_chip->irq_enable = em_gio_irq_enable; ++ irq_chip->irq_disable = em_gio_irq_disable; ++ irq_chip->irq_set_type = em_gio_irq_set_type; ++ irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; ++ ++ ret = em_gio_irq_domain_init(p); ++ if (ret) { ++ dev_err(&pdev->dev, "cannot initialize irq domain\n"); ++ goto err3; ++ } ++ ++ if (request_irq(irq[0]->start, em_gio_irq_handler, 0, name, p)) { ++ dev_err(&pdev->dev, "failed to request low IRQ\n"); ++ ret = -ENOENT; ++ goto err4; ++ } ++ ++ if (request_irq(irq[1]->start, em_gio_irq_handler, 0, name, p)) { ++ dev_err(&pdev->dev, "failed to request high IRQ\n"); ++ ret = -ENOENT; ++ goto err5; ++ } ++ ++ ret = gpiochip_add(gpio_chip); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to add GPIO controller\n"); ++ goto err6; ++ } ++ return 0; ++ ++err6: ++ free_irq(irq[1]->start, pdev); ++err5: ++ free_irq(irq[0]->start, pdev); ++err4: ++ em_gio_irq_domain_cleanup(p); ++err3: ++ iounmap(p->base1); ++err2: ++ iounmap(p->base0); ++err1: ++ kfree(p); ++err0: ++ return ret; ++} ++ ++static int __devexit em_gio_remove(struct platform_device *pdev) ++{ ++ struct em_gio_priv *p = platform_get_drvdata(pdev); ++ struct resource *irq[2]; ++ int ret; ++ ++ ret = gpiochip_remove(&p->gpio_chip); ++ if (ret) ++ return ret; ++ ++ irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); ++ ++ free_irq(irq[1]->start, pdev); ++ free_irq(irq[0]->start, pdev); ++ em_gio_irq_domain_cleanup(p); ++ iounmap(p->base1); ++ iounmap(p->base0); ++ kfree(p); ++ return 0; ++} ++ ++static struct platform_driver em_gio_device_driver = { ++ .probe = em_gio_probe, ++ .remove = __devexit_p(em_gio_remove), ++ .driver = { ++ .name = "em_gio", ++ } ++}; ++ ++module_platform_driver(em_gio_device_driver); ++ ++MODULE_AUTHOR("Magnus Damm"); ++MODULE_DESCRIPTION("Renesas Emma Mobile GIO Driver"); ++MODULE_LICENSE("GPL v2"); +--- /dev/null ++++ b/include/linux/platform_data/gpio-em.h +@@ -0,0 +1,10 @@ ++#ifndef __GPIO_EM_H__ ++#define __GPIO_EM_H__ ++ ++struct gpio_em_config { ++ unsigned int gpio_base; ++ unsigned int irq_base; ++ unsigned int number_of_pins; ++}; ++ ++#endif /* __GPIO_EM_H__ */ diff --git a/patches.kzm9d/mach-shmobile-emma-mobile-ev2-dt-support-v3.patch b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-dt-support-v3.patch new file mode 100644 index 0000000000000..42e526f1e98c2 --- /dev/null +++ b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-dt-support-v3.patch @@ -0,0 +1,194 @@ +From koba@kmckk.co.jp Wed Oct 3 04:30:22 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:16 +0900 +Subject: [PATCH 24/26] mach-shmobile: Emma Mobile EV2 DT support V3 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-25-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +This is EMEV2 DT support V3. The support is limited to +whatever devices that are complied in the kernel. At this +point we have UARTs handled by "em-uart" and a timer +handled by "em-sti". Clocks and SMP are not supported. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 3d5de27174955702bc874302ba9e72d71d5acd58) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/boot/dts/emev2.dtsi | 63 ++++++++++++++++++++++++++++++++++ + arch/arm/mach-shmobile/clock-emev2.c | 5 +++ + arch/arm/mach-shmobile/setup-emev2.c | 47 ++++++++++++++++++++++++- + 3 files changed, 114 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/emev2.dtsi + +diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi +new file mode 100644 +index 0000000..eb504a6 +--- /dev/null ++++ b/arch/arm/boot/dts/emev2.dtsi +@@ -0,0 +1,63 @@ ++/* ++ * Device Tree Source for the EMEV2 SoC ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++ ++/include/ "skeleton.dtsi" ++ ++/ { ++ compatible = "renesas,emev2"; ++ interrupt-parent = <&gic>; ++ ++ cpus { ++ cpu@0 { ++ compatible = "arm,cortex-a9"; ++ }; ++ cpu@1 { ++ compatible = "arm,cortex-a9"; ++ }; ++ }; ++ ++ gic: interrupt-controller@e0020000 { ++ compatible = "arm,cortex-a9-gic"; ++ interrupt-controller; ++ #interrupt-cells = <3>; ++ reg = <0xe0028000 0x1000>, ++ <0xe0020000 0x0100>; ++ }; ++ ++ sti@e0180000 { ++ compatible = "renesas,em-sti"; ++ reg = <0xe0180000 0x54>; ++ interrupts = <0 125 0>; ++ }; ++ ++ uart@e1020000 { ++ compatible = "renesas,em-uart"; ++ reg = <0xe1020000 0x38>; ++ interrupts = <0 8 0>; ++ }; ++ ++ uart@e1030000 { ++ compatible = "renesas,em-uart"; ++ reg = <0xe1030000 0x38>; ++ interrupts = <0 9 0>; ++ }; ++ ++ uart@e1040000 { ++ compatible = "renesas,em-uart"; ++ reg = <0xe1040000 0x38>; ++ interrupts = <0 10 0>; ++ }; ++ ++ uart@e1050000 { ++ compatible = "renesas,em-uart"; ++ reg = <0xe1050000 0x38>; ++ interrupts = <0 11 0>; ++ }; ++}; +diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c +index 5bc97de..4710f18 100644 +--- a/arch/arm/mach-shmobile/clock-emev2.c ++++ b/arch/arm/mach-shmobile/clock-emev2.c +@@ -191,10 +191,15 @@ static int __init emev2_sclkdiv_register(struct clk *clks, int nr) + + static struct clk_lookup lookups[] = { + CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]), ++ CLKDEV_DEV_ID("e1020000.uart", &gclk_clks[GCLK_USIAU0_SCLK]), + CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]), ++ CLKDEV_DEV_ID("e1030000.uart", &gclk_clks[GCLK_USIBU1_SCLK]), + CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]), ++ CLKDEV_DEV_ID("e1040000.uart", &gclk_clks[GCLK_USIBU2_SCLK]), + CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]), ++ CLKDEV_DEV_ID("e1050000.uart", &gclk_clks[GCLK_USIBU3_SCLK]), + CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]), ++ CLKDEV_DEV_ID("e0180000.sti", &gclk_clks[GCLK_STI_SCLK]), + }; + + void __init emev2_clock_init(void) +diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c +index d40fede..dae9aa6 100644 +--- a/arch/arm/mach-shmobile/setup-emev2.c ++++ b/arch/arm/mach-shmobile/setup-emev2.c +@@ -22,9 +22,11 @@ + #include <linux/irq.h> + #include <linux/platform_device.h> + #include <linux/platform_data/gpio-em.h> ++#include <linux/of_platform.h> + #include <linux/delay.h> + #include <linux/input.h> + #include <linux/io.h> ++#include <linux/of_irq.h> + #include <mach/hardware.h> + #include <mach/common.h> + #include <mach/emev2.h> +@@ -381,9 +383,14 @@ void __init emev2_add_standard_devices(void) + ARRAY_SIZE(emev2_late_devices)); + } + +-void __init emev2_add_early_devices(void) ++void __init emev2_init_delay(void) + { + shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */ ++} ++ ++void __init emev2_add_early_devices(void) ++{ ++ emev2_init_delay(); + + early_platform_add_devices(emev2_early_devices, + ARRAY_SIZE(emev2_early_devices)); +@@ -405,3 +412,41 @@ void __init emev2_init_irq(void) + /* Use GIC to handle interrupts */ + gic_init(0, 29, gic_dist_base, gic_cpu_base); + } ++ ++#ifdef CONFIG_USE_OF ++static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = { ++ { } ++}; ++ ++void __init emev2_add_standard_devices_dt(void) ++{ ++ of_platform_populate(NULL, of_default_bus_match_table, ++ emev2_auxdata_lookup, NULL); ++} ++ ++static const struct of_device_id emev2_dt_irq_match[] = { ++ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, ++ {}, ++}; ++ ++static const char *emev2_boards_compat_dt[] __initdata = { ++ "renesas,emev2", ++ NULL, ++}; ++ ++void __init emev2_init_irq_dt(void) ++{ ++ of_irq_init(emev2_dt_irq_match); ++} ++ ++DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)") ++ .init_early = emev2_init_delay, ++ .nr_irqs = NR_IRQS_LEGACY, ++ .init_irq = emev2_init_irq_dt, ++ .handle_irq = gic_handle_irq, ++ .init_machine = emev2_add_standard_devices_dt, ++ .timer = &shmobile_timer, ++ .dt_compat = emev2_boards_compat_dt, ++MACHINE_END ++ ++#endif /* CONFIG_USE_OF */ +-- +1.7.9.5 + diff --git a/patches.kzm9d/mach-shmobile-emma-mobile-ev2-gpio-support-v3.patch b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-gpio-support-v3.patch new file mode 100644 index 0000000000000..5e9e9227636e0 --- /dev/null +++ b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-gpio-support-v3.patch @@ -0,0 +1,286 @@ +From koba@kmckk.co.jp Wed Oct 3 04:30:00 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:13 +0900 +Subject: [PATCH 21/26] mach-shmobile: Emma Mobile EV2 GPIO support V3 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-22-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Tie in the Emma Mobile GPIO driver "em-gio" to +support the GPIOs on Emma Mobile EV2. + +A static IRQ range is used to allow boards to +hook up their platform devices to the GPIOs. + +DT support is still on the TODO for the GPIO driver, +so only platform device support is included here. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 088efd9273b5076a0aead479aa31f1066d182b3e) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-shmobile/Kconfig | 1 + + arch/arm/mach-shmobile/include/mach/emev2.h | 3 + + arch/arm/mach-shmobile/setup-emev2.c | 203 +++++++++++++++++++++++++++ + 3 files changed, 207 insertions(+) + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 577fbad..95ecfad 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -45,6 +45,7 @@ config ARCH_EMEV2 + bool "Emma Mobile EV2" + select CPU_V7 + select ARM_GIC ++ select ARCH_WANT_OPTIONAL_GPIOLIB + + comment "SH-Mobile Board Type" + +diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h +index 3fc7184..e6b0c1b 100644 +--- a/arch/arm/mach-shmobile/include/mach/emev2.h ++++ b/arch/arm/mach-shmobile/include/mach/emev2.h +@@ -13,4 +13,7 @@ extern void emev2_secondary_init(unsigned int cpu); + extern int emev2_boot_secondary(unsigned int cpu); + extern void emev2_smp_prepare_cpus(void); + ++#define EMEV2_GPIO_BASE 200 ++#define EMEV2_GPIO_IRQ(n) (EMEV2_GPIO_BASE + (n)) ++ + #endif /* __ASM_EMEV2_H__ */ +diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c +index 2a03a78..d40fede 100644 +--- a/arch/arm/mach-shmobile/setup-emev2.c ++++ b/arch/arm/mach-shmobile/setup-emev2.c +@@ -21,6 +21,7 @@ + #include <linux/interrupt.h> + #include <linux/irq.h> + #include <linux/platform_device.h> ++#include <linux/platform_data/gpio-em.h> + #include <linux/delay.h> + #include <linux/input.h> + #include <linux/io.h> +@@ -156,6 +157,203 @@ static struct platform_device sti_device = { + .num_resources = ARRAY_SIZE(sti_resources), + }; + ++ ++/* GIO */ ++static struct gpio_em_config gio0_config = { ++ .gpio_base = 0, ++ .irq_base = EMEV2_GPIO_IRQ(0), ++ .number_of_pins = 32, ++}; ++ ++static struct resource gio0_resources[] = { ++ [0] = { ++ .name = "GIO_000", ++ .start = 0xe0050000, ++ .end = 0xe005002b, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .name = "GIO_000", ++ .start = 0xe0050040, ++ .end = 0xe005005f, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = 99, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .start = 100, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device gio0_device = { ++ .name = "em_gio", ++ .id = 0, ++ .resource = gio0_resources, ++ .num_resources = ARRAY_SIZE(gio0_resources), ++ .dev = { ++ .platform_data = &gio0_config, ++ }, ++}; ++ ++static struct gpio_em_config gio1_config = { ++ .gpio_base = 32, ++ .irq_base = EMEV2_GPIO_IRQ(32), ++ .number_of_pins = 32, ++}; ++ ++static struct resource gio1_resources[] = { ++ [0] = { ++ .name = "GIO_032", ++ .start = 0xe0050080, ++ .end = 0xe00500ab, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .name = "GIO_032", ++ .start = 0xe00500c0, ++ .end = 0xe00500df, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = 101, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .start = 102, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device gio1_device = { ++ .name = "em_gio", ++ .id = 1, ++ .resource = gio1_resources, ++ .num_resources = ARRAY_SIZE(gio1_resources), ++ .dev = { ++ .platform_data = &gio1_config, ++ }, ++}; ++ ++static struct gpio_em_config gio2_config = { ++ .gpio_base = 64, ++ .irq_base = EMEV2_GPIO_IRQ(64), ++ .number_of_pins = 32, ++}; ++ ++static struct resource gio2_resources[] = { ++ [0] = { ++ .name = "GIO_064", ++ .start = 0xe0050100, ++ .end = 0xe005012b, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .name = "GIO_064", ++ .start = 0xe0050140, ++ .end = 0xe005015f, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = 103, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .start = 104, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device gio2_device = { ++ .name = "em_gio", ++ .id = 2, ++ .resource = gio2_resources, ++ .num_resources = ARRAY_SIZE(gio2_resources), ++ .dev = { ++ .platform_data = &gio2_config, ++ }, ++}; ++ ++static struct gpio_em_config gio3_config = { ++ .gpio_base = 96, ++ .irq_base = EMEV2_GPIO_IRQ(96), ++ .number_of_pins = 32, ++}; ++ ++static struct resource gio3_resources[] = { ++ [0] = { ++ .name = "GIO_096", ++ .start = 0xe0050100, ++ .end = 0xe005012b, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .name = "GIO_096", ++ .start = 0xe0050140, ++ .end = 0xe005015f, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = 105, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .start = 106, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device gio3_device = { ++ .name = "em_gio", ++ .id = 3, ++ .resource = gio3_resources, ++ .num_resources = ARRAY_SIZE(gio3_resources), ++ .dev = { ++ .platform_data = &gio3_config, ++ }, ++}; ++ ++static struct gpio_em_config gio4_config = { ++ .gpio_base = 128, ++ .irq_base = EMEV2_GPIO_IRQ(128), ++ .number_of_pins = 31, ++}; ++ ++static struct resource gio4_resources[] = { ++ [0] = { ++ .name = "GIO_128", ++ .start = 0xe0050200, ++ .end = 0xe005022b, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .name = "GIO_128", ++ .start = 0xe0050240, ++ .end = 0xe005025f, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = 107, ++ .flags = IORESOURCE_IRQ, ++ }, ++ [3] = { ++ .start = 108, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device gio4_device = { ++ .name = "em_gio", ++ .id = 4, ++ .resource = gio4_resources, ++ .num_resources = ARRAY_SIZE(gio4_resources), ++ .dev = { ++ .platform_data = &gio4_config, ++ }, ++}; ++ + static struct platform_device *emev2_early_devices[] __initdata = { + &uart0_device, + &uart1_device, +@@ -165,6 +363,11 @@ static struct platform_device *emev2_early_devices[] __initdata = { + + static struct platform_device *emev2_late_devices[] __initdata = { + &sti_device, ++ &gio0_device, ++ &gio1_device, ++ &gio2_device, ++ &gio3_device, ++ &gio4_device, + }; + + void __init emev2_add_standard_devices(void) +-- +1.7.9.5 + diff --git a/patches.kzm9d/mach-shmobile-emma-mobile-ev2-smp-support-v3.patch b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-smp-support-v3.patch new file mode 100644 index 0000000000000..edaa931cc8ed4 --- /dev/null +++ b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-smp-support-v3.patch @@ -0,0 +1,340 @@ +From koba@kmckk.co.jp Wed Oct 3 04:29:51 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:12 +0900 +Subject: [PATCH 20/26] mach-shmobile: Emma Mobile EV2 SMP support V3 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-21-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +This is V3 of Emma Mobile EV2 SMP support. + +At this point only the most basic form of SMP operation +is supported. TWD and CPU Hotplug support is excluded. + +Tied to both the Emma Mobile EV2 and the KZM9D board +due to the need to switch on board in platsmp.c and +the newly introduced need for static mappings. + +The static mappings are needed to allow hardware +acces early during boot when SMP is initialized. +This early requirement forces us to also map in +the SMU registers. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit bd5a875d90c878be4d23f54ea565253734ae2377) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-shmobile/Makefile | 1 + + arch/arm/mach-shmobile/board-kzm9d.c | 1 + + arch/arm/mach-shmobile/clock-emev2.c | 18 +++++ + arch/arm/mach-shmobile/include/mach/emev2.h | 7 ++ + arch/arm/mach-shmobile/platsmp.c | 17 +++++ + arch/arm/mach-shmobile/setup-emev2.c | 24 +++++++ + arch/arm/mach-shmobile/smp-emev2.c | 97 +++++++++++++++++++++++++++ + 7 files changed, 165 insertions(+) + create mode 100644 arch/arm/mach-shmobile/smp-emev2.c + +diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile +index 2e6ff96..a93bcf0 100644 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -19,6 +19,7 @@ smp-y := platsmp.o headsmp.o + smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o + smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o + smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o ++smp-$(CONFIG_ARCH_EMEV2) += smp-emev2.o + + # Pinmux setup + pfc-y := +diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c +index e743f90..42fc479 100644 +--- a/arch/arm/mach-shmobile/board-kzm9d.c ++++ b/arch/arm/mach-shmobile/board-kzm9d.c +@@ -27,6 +27,7 @@ + #include <asm/hardware/gic.h> + + MACHINE_START(KZM9D, "kzm9d") ++ .map_io = emev2_map_io, + .init_early = emev2_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, + .init_irq = emev2_init_irq, +diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c +index 73a1216..5bc97de 100644 +--- a/arch/arm/mach-shmobile/clock-emev2.c ++++ b/arch/arm/mach-shmobile/clock-emev2.c +@@ -40,6 +40,7 @@ + #define USIB2SCLKDIV 0x65c + #define USIB3SCLKDIV 0x660 + #define STI_CLKSEL 0x688 ++#define SMU_GENERAL_REG0 0x7c0 + + /* not pretty, but hey */ + static void __iomem *smu_base; +@@ -50,6 +51,11 @@ static void emev2_smu_write(unsigned long value, int offs) + iowrite32(value, smu_base + offs); + } + ++void emev2_set_boot_vector(unsigned long value) ++{ ++ emev2_smu_write(value, SMU_GENERAL_REG0); ++} ++ + static struct clk_mapping smu_mapping = { + .phys = EMEV2_SMU_BASE, + .len = PAGE_SIZE, +@@ -194,6 +200,18 @@ static struct clk_lookup lookups[] = { + void __init emev2_clock_init(void) + { + int k, ret = 0; ++ static int is_setup; ++ ++ /* yuck, this is ugly as hell, but the non-smp case of clocks ++ * code is now designed to rely on ioremap() instead of static ++ * entity maps. in the case of smp we need access to the SMU ++ * register earlier than ioremap() is actually working without ++ * any static maps. to enable SMP in ugly but with dynamic ++ * mappings we have to call emev2_clock_init() from different ++ * places depending on UP and SMP... ++ */ ++ if (is_setup++) ++ return; + + smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE); + BUG_ON(!smu_base); +diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h +index 92646c1..3fc7184 100644 +--- a/arch/arm/mach-shmobile/include/mach/emev2.h ++++ b/arch/arm/mach-shmobile/include/mach/emev2.h +@@ -1,9 +1,16 @@ + #ifndef __ASM_EMEV2_H__ + #define __ASM_EMEV2_H__ + ++extern void emev2_map_io(void); + extern void emev2_init_irq(void); + extern void emev2_add_early_devices(void); + extern void emev2_add_standard_devices(void); + extern void emev2_clock_init(void); ++extern void emev2_set_boot_vector(unsigned long value); ++extern unsigned int emev2_get_core_count(void); ++extern int emev2_platform_cpu_kill(unsigned int cpu); ++extern void emev2_secondary_init(unsigned int cpu); ++extern int emev2_boot_secondary(unsigned int cpu); ++extern void emev2_smp_prepare_cpus(void); + + #endif /* __ASM_EMEV2_H__ */ +diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c +index 932ac8f..af24bbd 100644 +--- a/arch/arm/mach-shmobile/platsmp.c ++++ b/arch/arm/mach-shmobile/platsmp.c +@@ -20,6 +20,7 @@ + #include <asm/hardware/gic.h> + #include <asm/mach-types.h> + #include <mach/common.h> ++#include <mach/emev2.h> + + #ifdef CONFIG_ARCH_SH73A0 + #define is_sh73a0() (machine_is_ag5evm() || machine_is_kota2() || \ +@@ -29,6 +30,7 @@ + #endif + + #define is_r8a7779() machine_is_marzen() ++#define is_emev2() machine_is_kzm9d() + + static unsigned int __init shmobile_smp_get_core_count(void) + { +@@ -38,6 +40,9 @@ static unsigned int __init shmobile_smp_get_core_count(void) + if (is_r8a7779()) + return r8a7779_get_core_count(); + ++ if (is_emev2()) ++ return emev2_get_core_count(); ++ + return 1; + } + +@@ -48,6 +53,9 @@ static void __init shmobile_smp_prepare_cpus(void) + + if (is_r8a7779()) + r8a7779_smp_prepare_cpus(); ++ ++ if (is_emev2()) ++ emev2_smp_prepare_cpus(); + } + + int shmobile_platform_cpu_kill(unsigned int cpu) +@@ -55,6 +63,9 @@ int shmobile_platform_cpu_kill(unsigned int cpu) + if (is_r8a7779()) + return r8a7779_platform_cpu_kill(cpu); + ++ if (is_emev2()) ++ return emev2_platform_cpu_kill(cpu); ++ + return 1; + } + +@@ -67,6 +78,9 @@ void __cpuinit platform_secondary_init(unsigned int cpu) + + if (is_r8a7779()) + r8a7779_secondary_init(cpu); ++ ++ if (is_emev2()) ++ emev2_secondary_init(cpu); + } + + int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +@@ -77,6 +91,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) + if (is_r8a7779()) + return r8a7779_boot_secondary(cpu); + ++ if (is_emev2()) ++ return emev2_boot_secondary(cpu); ++ + return -ENOSYS; + } + +diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c +index 9fff623..2a03a78 100644 +--- a/arch/arm/mach-shmobile/setup-emev2.c ++++ b/arch/arm/mach-shmobile/setup-emev2.c +@@ -34,6 +34,30 @@ + #include <asm/mach/time.h> + #include <asm/hardware/gic.h> + ++static struct map_desc emev2_io_desc[] __initdata = { ++#ifdef CONFIG_SMP ++ /* 128K entity map for 0xe0100000 (SMU) */ ++ { ++ .virtual = 0xe0100000, ++ .pfn = __phys_to_pfn(0xe0100000), ++ .length = SZ_128K, ++ .type = MT_DEVICE ++ }, ++ /* 2M mapping for SCU + L2 controller */ ++ { ++ .virtual = 0xf0000000, ++ .pfn = __phys_to_pfn(0x1e000000), ++ .length = SZ_2M, ++ .type = MT_DEVICE ++ }, ++#endif ++}; ++ ++void __init emev2_map_io(void) ++{ ++ iotable_init(emev2_io_desc, ARRAY_SIZE(emev2_io_desc)); ++} ++ + /* UART */ + static struct resource uart0_resources[] = { + [0] = { +diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c +new file mode 100644 +index 0000000..6a35c4a +--- /dev/null ++++ b/arch/arm/mach-shmobile/smp-emev2.c +@@ -0,0 +1,97 @@ ++/* ++ * SMP support for Emma Mobile EV2 ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * Copyright (C) 2012 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/smp.h> ++#include <linux/spinlock.h> ++#include <linux/io.h> ++#include <linux/delay.h> ++#include <mach/common.h> ++#include <mach/emev2.h> ++#include <asm/smp_plat.h> ++#include <asm/smp_scu.h> ++#include <asm/hardware/gic.h> ++#include <asm/cacheflush.h> ++ ++#define EMEV2_SCU_BASE 0x1e000000 ++ ++static DEFINE_SPINLOCK(scu_lock); ++static void __iomem *scu_base; ++ ++static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) ++{ ++ unsigned long tmp; ++ ++ /* we assume this code is running on a different cpu ++ * than the one that is changing coherency setting */ ++ spin_lock(&scu_lock); ++ tmp = readl(scu_base + 8); ++ tmp &= ~clr; ++ tmp |= set; ++ writel(tmp, scu_base + 8); ++ spin_unlock(&scu_lock); ++ ++} ++ ++unsigned int __init emev2_get_core_count(void) ++{ ++ if (!scu_base) { ++ scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE); ++ emev2_clock_init(); /* need ioremapped SMU */ ++ } ++ ++ WARN_ON_ONCE(!scu_base); ++ ++ return scu_base ? scu_get_core_count(scu_base) : 1; ++} ++ ++int emev2_platform_cpu_kill(unsigned int cpu) ++{ ++ return 0; /* not supported yet */ ++} ++ ++void __cpuinit emev2_secondary_init(unsigned int cpu) ++{ ++ gic_secondary_init(0); ++} ++ ++int __cpuinit emev2_boot_secondary(unsigned int cpu) ++{ ++ cpu = cpu_logical_map(cpu); ++ ++ /* enable cache coherency */ ++ modify_scu_cpu_psr(0, 3 << (cpu * 8)); ++ ++ /* Tell ROM loader about our vector (in headsmp.S) */ ++ emev2_set_boot_vector(__pa(shmobile_secondary_vector)); ++ ++ gic_raise_softirq(cpumask_of(cpu), 1); ++ return 0; ++} ++ ++void __init emev2_smp_prepare_cpus(void) ++{ ++ int cpu = cpu_logical_map(0); ++ ++ scu_enable(scu_base); ++ ++ /* enable cache coherency on CPU0 */ ++ modify_scu_cpu_psr(0, 3 << (cpu * 8)); ++} +-- +1.7.9.5 + diff --git a/patches.kzm9d/mach-shmobile-emma-mobile-ev2-soc-base-support-v3.patch b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-soc-base-support-v3.patch new file mode 100644 index 0000000000000..5e5996ce333fd --- /dev/null +++ b/patches.kzm9d/mach-shmobile-emma-mobile-ev2-soc-base-support-v3.patch @@ -0,0 +1,495 @@ +From koba@kmckk.co.jp Wed Oct 3 04:29:27 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:10 +0900 +Subject: [PATCH 18/26] mach-shmobile: Emma Mobile EV2 SoC base support V3 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-19-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +This is V3 of the Emma Mobile EV2 SoC support. +Included here is support for serial and timer +devices which is just about enough to boot a kernel. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 7f627f0380cb5ba3e05bcaac31ecf40c1f508ec1) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-shmobile/Kconfig | 5 + + arch/arm/mach-shmobile/Makefile | 1 + + arch/arm/mach-shmobile/clock-emev2.c | 226 +++++++++++++++++++++++++++ + arch/arm/mach-shmobile/include/mach/emev2.h | 9 ++ + arch/arm/mach-shmobile/setup-emev2.c | 180 +++++++++++++++++++++ + 5 files changed, 421 insertions(+) + create mode 100644 arch/arm/mach-shmobile/clock-emev2.c + create mode 100644 arch/arm/mach-shmobile/include/mach/emev2.h + create mode 100644 arch/arm/mach-shmobile/setup-emev2.c + +diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig +index 80b64c5..3031ff8 100644 +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -41,6 +41,11 @@ config ARCH_R8A7779 + select ARM_GIC + select ARCH_WANT_OPTIONAL_GPIOLIB + ++config ARCH_EMEV2 ++ bool "Emma Mobile EV2" ++ select CPU_V7 ++ select ARM_GIC ++ + comment "SH-Mobile Board Type" + + config MACH_G3EVM +diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile +index 015c2d4..91f4470 100644 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_ARCH_SH7372) += setup-sh7372.o clock-sh7372.o intc-sh7372.o + obj-$(CONFIG_ARCH_SH73A0) += setup-sh73a0.o clock-sh73a0.o intc-sh73a0.o + obj-$(CONFIG_ARCH_R8A7740) += setup-r8a7740.o clock-r8a7740.o intc-r8a7740.o + obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o ++obj-$(CONFIG_ARCH_EMEV2) += setup-emev2.o clock-emev2.o + + # SMP objects + smp-y := platsmp.o headsmp.o +diff --git a/arch/arm/mach-shmobile/clock-emev2.c b/arch/arm/mach-shmobile/clock-emev2.c +new file mode 100644 +index 0000000..73a1216 +--- /dev/null ++++ b/arch/arm/mach-shmobile/clock-emev2.c +@@ -0,0 +1,226 @@ ++/* ++ * Emma Mobile EV2 clock framework support ++ * ++ * Copyright (C) 2012 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/io.h> ++#include <linux/sh_clk.h> ++#include <linux/clkdev.h> ++#include <mach/common.h> ++ ++#define EMEV2_SMU_BASE 0xe0110000 ++ ++/* EMEV2 SMU registers */ ++#define USIAU0_RSTCTRL 0x094 ++#define USIBU1_RSTCTRL 0x0ac ++#define USIBU2_RSTCTRL 0x0b0 ++#define USIBU3_RSTCTRL 0x0b4 ++#define STI_RSTCTRL 0x124 ++#define USIAU0GCLKCTRL 0x4a0 ++#define USIBU1GCLKCTRL 0x4b8 ++#define USIBU2GCLKCTRL 0x4bc ++#define USIBU3GCLKCTRL 0x04c0 ++#define STIGCLKCTRL 0x528 ++#define USIAU0SCLKDIV 0x61c ++#define USIB2SCLKDIV 0x65c ++#define USIB3SCLKDIV 0x660 ++#define STI_CLKSEL 0x688 ++ ++/* not pretty, but hey */ ++static void __iomem *smu_base; ++ ++static void emev2_smu_write(unsigned long value, int offs) ++{ ++ BUG_ON(!smu_base || (offs >= PAGE_SIZE)); ++ iowrite32(value, smu_base + offs); ++} ++ ++static struct clk_mapping smu_mapping = { ++ .phys = EMEV2_SMU_BASE, ++ .len = PAGE_SIZE, ++}; ++ ++/* Fixed 32 KHz root clock from C32K pin */ ++static struct clk c32k_clk = { ++ .rate = 32768, ++ .mapping = &smu_mapping, ++}; ++ ++/* PLL3 multiplies C32K with 7000 */ ++static unsigned long pll3_recalc(struct clk *clk) ++{ ++ return clk->parent->rate * 7000; ++} ++ ++static struct sh_clk_ops pll3_clk_ops = { ++ .recalc = pll3_recalc, ++}; ++ ++static struct clk pll3_clk = { ++ .ops = &pll3_clk_ops, ++ .parent = &c32k_clk, ++}; ++ ++static struct clk *main_clks[] = { ++ &c32k_clk, ++ &pll3_clk, ++}; ++ ++enum { SCLKDIV_USIAU0, SCLKDIV_USIBU2, SCLKDIV_USIBU1, SCLKDIV_USIBU3, ++ SCLKDIV_NR }; ++ ++#define SCLKDIV(_reg, _shift) \ ++{ \ ++ .parent = &pll3_clk, \ ++ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \ ++ .enable_bit = _shift, \ ++} ++ ++static struct clk sclkdiv_clks[SCLKDIV_NR] = { ++ [SCLKDIV_USIAU0] = SCLKDIV(USIAU0SCLKDIV, 0), ++ [SCLKDIV_USIBU2] = SCLKDIV(USIB2SCLKDIV, 16), ++ [SCLKDIV_USIBU1] = SCLKDIV(USIB2SCLKDIV, 0), ++ [SCLKDIV_USIBU3] = SCLKDIV(USIB3SCLKDIV, 0), ++}; ++ ++enum { GCLK_USIAU0_SCLK, GCLK_USIBU1_SCLK, GCLK_USIBU2_SCLK, GCLK_USIBU3_SCLK, ++ GCLK_STI_SCLK, ++ GCLK_NR }; ++ ++#define GCLK_SCLK(_parent, _reg) \ ++{ \ ++ .parent = _parent, \ ++ .enable_reg = IOMEM(EMEV2_SMU_BASE + (_reg)), \ ++ .enable_bit = 1, /* SCLK_GCC */ \ ++} ++ ++static struct clk gclk_clks[GCLK_NR] = { ++ [GCLK_USIAU0_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIAU0], ++ USIAU0GCLKCTRL), ++ [GCLK_USIBU1_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU1], ++ USIBU1GCLKCTRL), ++ [GCLK_USIBU2_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU2], ++ USIBU2GCLKCTRL), ++ [GCLK_USIBU3_SCLK] = GCLK_SCLK(&sclkdiv_clks[SCLKDIV_USIBU3], ++ USIBU3GCLKCTRL), ++ [GCLK_STI_SCLK] = GCLK_SCLK(&c32k_clk, STIGCLKCTRL), ++}; ++ ++static int emev2_gclk_enable(struct clk *clk) ++{ ++ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit), ++ clk->mapped_reg); ++ return 0; ++} ++ ++static void emev2_gclk_disable(struct clk *clk) ++{ ++ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit), ++ clk->mapped_reg); ++} ++ ++static struct sh_clk_ops emev2_gclk_clk_ops = { ++ .enable = emev2_gclk_enable, ++ .disable = emev2_gclk_disable, ++ .recalc = followparent_recalc, ++}; ++ ++static int __init emev2_gclk_register(struct clk *clks, int nr) ++{ ++ struct clk *clkp; ++ int ret = 0; ++ int k; ++ ++ for (k = 0; !ret && (k < nr); k++) { ++ clkp = clks + k; ++ clkp->ops = &emev2_gclk_clk_ops; ++ ret |= clk_register(clkp); ++ } ++ ++ return ret; ++} ++ ++static unsigned long emev2_sclkdiv_recalc(struct clk *clk) ++{ ++ unsigned int sclk_div; ++ ++ sclk_div = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0xff; ++ ++ return clk->parent->rate / (sclk_div + 1); ++} ++ ++static struct sh_clk_ops emev2_sclkdiv_clk_ops = { ++ .recalc = emev2_sclkdiv_recalc, ++}; ++ ++static int __init emev2_sclkdiv_register(struct clk *clks, int nr) ++{ ++ struct clk *clkp; ++ int ret = 0; ++ int k; ++ ++ for (k = 0; !ret && (k < nr); k++) { ++ clkp = clks + k; ++ clkp->ops = &emev2_sclkdiv_clk_ops; ++ ret |= clk_register(clkp); ++ } ++ ++ return ret; ++} ++ ++static struct clk_lookup lookups[] = { ++ CLKDEV_DEV_ID("serial8250-em.0", &gclk_clks[GCLK_USIAU0_SCLK]), ++ CLKDEV_DEV_ID("serial8250-em.1", &gclk_clks[GCLK_USIBU1_SCLK]), ++ CLKDEV_DEV_ID("serial8250-em.2", &gclk_clks[GCLK_USIBU2_SCLK]), ++ CLKDEV_DEV_ID("serial8250-em.3", &gclk_clks[GCLK_USIBU3_SCLK]), ++ CLKDEV_DEV_ID("em_sti.0", &gclk_clks[GCLK_STI_SCLK]), ++}; ++ ++void __init emev2_clock_init(void) ++{ ++ int k, ret = 0; ++ ++ smu_base = ioremap(EMEV2_SMU_BASE, PAGE_SIZE); ++ BUG_ON(!smu_base); ++ ++ /* setup STI timer to run on 37.768 kHz and deassert reset */ ++ emev2_smu_write(0, STI_CLKSEL); ++ emev2_smu_write(1, STI_RSTCTRL); ++ ++ /* deassert reset for UART0->UART3 */ ++ emev2_smu_write(2, USIAU0_RSTCTRL); ++ emev2_smu_write(2, USIBU1_RSTCTRL); ++ emev2_smu_write(2, USIBU2_RSTCTRL); ++ emev2_smu_write(2, USIBU3_RSTCTRL); ++ ++ for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) ++ ret = clk_register(main_clks[k]); ++ ++ if (!ret) ++ ret = emev2_sclkdiv_register(sclkdiv_clks, SCLKDIV_NR); ++ ++ if (!ret) ++ ret = emev2_gclk_register(gclk_clks, GCLK_NR); ++ ++ clkdev_add_table(lookups, ARRAY_SIZE(lookups)); ++ ++ if (!ret) ++ shmobile_clk_init(); ++ else ++ panic("failed to setup emev2 clocks\n"); ++} +diff --git a/arch/arm/mach-shmobile/include/mach/emev2.h b/arch/arm/mach-shmobile/include/mach/emev2.h +new file mode 100644 +index 0000000..92646c1 +--- /dev/null ++++ b/arch/arm/mach-shmobile/include/mach/emev2.h +@@ -0,0 +1,9 @@ ++#ifndef __ASM_EMEV2_H__ ++#define __ASM_EMEV2_H__ ++ ++extern void emev2_init_irq(void); ++extern void emev2_add_early_devices(void); ++extern void emev2_add_standard_devices(void); ++extern void emev2_clock_init(void); ++ ++#endif /* __ASM_EMEV2_H__ */ +diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c +new file mode 100644 +index 0000000..9fff623 +--- /dev/null ++++ b/arch/arm/mach-shmobile/setup-emev2.c +@@ -0,0 +1,180 @@ ++/* ++ * Emma Mobile EV2 processor support ++ * ++ * Copyright (C) 2012 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/irq.h> ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++#include <linux/input.h> ++#include <linux/io.h> ++#include <mach/hardware.h> ++#include <mach/common.h> ++#include <mach/emev2.h> ++#include <mach/irqs.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/mach/map.h> ++#include <asm/mach/time.h> ++#include <asm/hardware/gic.h> ++ ++/* UART */ ++static struct resource uart0_resources[] = { ++ [0] = { ++ .start = 0xe1020000, ++ .end = 0xe1020037, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 40, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device uart0_device = { ++ .name = "serial8250-em", ++ .id = 0, ++ .num_resources = ARRAY_SIZE(uart0_resources), ++ .resource = uart0_resources, ++}; ++ ++static struct resource uart1_resources[] = { ++ [0] = { ++ .start = 0xe1030000, ++ .end = 0xe1030037, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 41, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device uart1_device = { ++ .name = "serial8250-em", ++ .id = 1, ++ .num_resources = ARRAY_SIZE(uart1_resources), ++ .resource = uart1_resources, ++}; ++ ++static struct resource uart2_resources[] = { ++ [0] = { ++ .start = 0xe1040000, ++ .end = 0xe1040037, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 42, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device uart2_device = { ++ .name = "serial8250-em", ++ .id = 2, ++ .num_resources = ARRAY_SIZE(uart2_resources), ++ .resource = uart2_resources, ++}; ++ ++static struct resource uart3_resources[] = { ++ [0] = { ++ .start = 0xe1050000, ++ .end = 0xe1050037, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 43, ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device uart3_device = { ++ .name = "serial8250-em", ++ .id = 3, ++ .num_resources = ARRAY_SIZE(uart3_resources), ++ .resource = uart3_resources, ++}; ++ ++/* STI */ ++static struct resource sti_resources[] = { ++ [0] = { ++ .name = "STI", ++ .start = 0xe0180000, ++ .end = 0xe0180053, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = 157, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device sti_device = { ++ .name = "em_sti", ++ .id = 0, ++ .resource = sti_resources, ++ .num_resources = ARRAY_SIZE(sti_resources), ++}; ++ ++static struct platform_device *emev2_early_devices[] __initdata = { ++ &uart0_device, ++ &uart1_device, ++ &uart2_device, ++ &uart3_device, ++}; ++ ++static struct platform_device *emev2_late_devices[] __initdata = { ++ &sti_device, ++}; ++ ++void __init emev2_add_standard_devices(void) ++{ ++ emev2_clock_init(); ++ ++ platform_add_devices(emev2_early_devices, ++ ARRAY_SIZE(emev2_early_devices)); ++ ++ platform_add_devices(emev2_late_devices, ++ ARRAY_SIZE(emev2_late_devices)); ++} ++ ++void __init emev2_add_early_devices(void) ++{ ++ shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */ ++ ++ early_platform_add_devices(emev2_early_devices, ++ ARRAY_SIZE(emev2_early_devices)); ++ ++ /* setup early console here as well */ ++ shmobile_setup_console(); ++} ++ ++void __init emev2_init_irq(void) ++{ ++ void __iomem *gic_dist_base; ++ void __iomem *gic_cpu_base; ++ ++ /* Static mappings, never released */ ++ gic_dist_base = ioremap(0xe0028000, PAGE_SIZE); ++ gic_cpu_base = ioremap(0xe0020000, PAGE_SIZE); ++ BUG_ON(!gic_dist_base || !gic_cpu_base); ++ ++ /* Use GIC to handle interrupts */ ++ gic_init(0, 29, gic_dist_base, gic_cpu_base); ++} +-- +1.7.9.5 + diff --git a/patches.kzm9d/mach-shmobile-kzm9d-board-ethernet-support-v3.patch b/patches.kzm9d/mach-shmobile-kzm9d-board-ethernet-support-v3.patch new file mode 100644 index 0000000000000..848f59f860aac --- /dev/null +++ b/patches.kzm9d/mach-shmobile-kzm9d-board-ethernet-support-v3.patch @@ -0,0 +1,93 @@ +From koba@kmckk.co.jp Wed Oct 3 04:30:07 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:14 +0900 +Subject: [PATCH 22/26] mach-shmobile: KZM9D board Ethernet support V3 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-23-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Tie in the on-board Ethernet controller on KZM9D +and make use of the GPIO controller for external +IRQ pin support. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 0c73f7bc124e1657a583d9dfb0d168a69005e2d3) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-shmobile/board-kzm9d.c | 44 +++++++++++++++++++++++++++++++++- + 1 file changed, 43 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c +index 42fc479..be81f0f 100644 +--- a/arch/arm/mach-shmobile/board-kzm9d.c ++++ b/arch/arm/mach-shmobile/board-kzm9d.c +@@ -20,18 +20,60 @@ + + #include <linux/kernel.h> + #include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/smsc911x.h> + #include <mach/common.h> + #include <mach/emev2.h> + #include <asm/mach-types.h> + #include <asm/mach/arch.h> + #include <asm/hardware/gic.h> + ++/* Ether */ ++static struct resource smsc911x_resources[] = { ++ [0] = { ++ .start = 0x20000000, ++ .end = 0x2000ffff, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = EMEV2_GPIO_IRQ(1), ++ .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, ++ }, ++}; ++ ++static struct smsc911x_platform_config smsc911x_platdata = { ++ .flags = SMSC911X_USE_32BIT, ++ .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, ++ .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, ++}; ++ ++static struct platform_device smsc91x_device = { ++ .name = "smsc911x", ++ .id = 0, ++ .dev = { ++ .platform_data = &smsc911x_platdata, ++ }, ++ .num_resources = ARRAY_SIZE(smsc911x_resources), ++ .resource = smsc911x_resources, ++}; ++ ++static struct platform_device *kzm9d_devices[] __initdata = { ++ &smsc91x_device, ++}; ++ ++void __init kzm9d_add_standard_devices(void) ++{ ++ emev2_add_standard_devices(); ++ ++ platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices)); ++} ++ + MACHINE_START(KZM9D, "kzm9d") + .map_io = emev2_map_io, + .init_early = emev2_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, + .init_irq = emev2_init_irq, + .handle_irq = gic_handle_irq, +- .init_machine = emev2_add_standard_devices, ++ .init_machine = kzm9d_add_standard_devices, + .timer = &shmobile_timer, + MACHINE_END +-- +1.7.9.5 + diff --git a/patches.kzm9d/mach-shmobile-kzm9d-board-support-v3.patch b/patches.kzm9d/mach-shmobile-kzm9d-board-support-v3.patch new file mode 100644 index 0000000000000..74dd54724f6aa --- /dev/null +++ b/patches.kzm9d/mach-shmobile-kzm9d-board-support-v3.patch @@ -0,0 +1,92 @@ +From koba@kmckk.co.jp Wed Oct 3 04:29:37 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:11 +0900 +Subject: [PATCH 19/26] mach-shmobile: KZM9D board support V3 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-20-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +V3 of basic KZM9D board support. At this point a quite +thin layer that makes use of the Emma Mobile EV2 SoC code. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit c050fb10c425cf189da5ca9b84e948ec2fc99049) + +Conflicts: + + arch/arm/mach-shmobile/Kconfig + arch/arm/mach-shmobile/Makefile +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-shmobile/Kconfig | 4 +++ + arch/arm/mach-shmobile/Makefile | 1 + arch/arm/mach-shmobile/board-kzm9d.c | 36 +++++++++++++++++++++++++++++++++++ + 3 files changed, 41 insertions(+) + create mode 100644 arch/arm/mach-shmobile/board-kzm9d.c + +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -112,6 +112,10 @@ config MACH_MARZEN + depends on ARCH_R8A7779 + select ARCH_REQUIRE_GPIOLIB + ++config MACH_KZM9D ++ bool "KZM9D board" ++ depends on ARCH_EMEV2 ++ + config MACH_KZM9G + bool "KZM-A9-GT board" + depends on ARCH_SH73A0 +--- a/arch/arm/mach-shmobile/Makefile ++++ b/arch/arm/mach-shmobile/Makefile +@@ -53,6 +53,7 @@ obj-$(CONFIG_MACH_KOTA2) += board-kota2. + obj-$(CONFIG_MACH_BONITO) += board-bonito.o + obj-$(CONFIG_MACH_MARZEN) += board-marzen.o + obj-$(CONFIG_MACH_ARMADILLO800EVA) += board-armadillo800eva.o ++obj-$(CONFIG_MACH_KZM9D) += board-kzm9d.o + obj-$(CONFIG_MACH_KZM9G) += board-kzm9g.o + + # Framework support +--- /dev/null ++++ b/arch/arm/mach-shmobile/board-kzm9d.c +@@ -0,0 +1,36 @@ ++/* ++ * kzm9d board support ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * Copyright (C) 2012 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; version 2 of the License. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/interrupt.h> ++#include <mach/common.h> ++#include <mach/emev2.h> ++#include <asm/mach-types.h> ++#include <asm/mach/arch.h> ++#include <asm/hardware/gic.h> ++ ++MACHINE_START(KZM9D, "kzm9d") ++ .init_early = emev2_add_early_devices, ++ .nr_irqs = NR_IRQS_LEGACY, ++ .init_irq = emev2_init_irq, ++ .handle_irq = gic_handle_irq, ++ .init_machine = emev2_add_standard_devices, ++ .timer = &shmobile_timer, ++MACHINE_END diff --git a/patches.kzm9d/mach-shmobile-use-dt_machine-for-kzm9d-v3.patch b/patches.kzm9d/mach-shmobile-use-dt_machine-for-kzm9d-v3.patch new file mode 100644 index 0000000000000..b126c0364650d --- /dev/null +++ b/patches.kzm9d/mach-shmobile-use-dt_machine-for-kzm9d-v3.patch @@ -0,0 +1,103 @@ +From koba@kmckk.co.jp Wed Oct 3 04:30:29 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:17 +0900 +Subject: [PATCH 25/26] mach-shmobile: Use DT_MACHINE for KZM9D V3 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, "Rafael J. Wysocki" <rjw@sisk.pl>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-26-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Use DT_MACHINE_START() on the emev2 based KZM9D board. + +Also include a tiny DTS file to describe the board and +update the Kconfig dependencies to select CONFIG_USE_OF. + +Update the SMP glue code to use OF for matching. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> +(cherry picked from commit 450cca47d65b7500ba05d56770adbf8c758dc87d) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/boot/dts/emev2-kzm9d.dts | 26 ++++++++++++++++++++++++++ + arch/arm/mach-shmobile/Kconfig | 1 + + arch/arm/mach-shmobile/board-kzm9d.c | 8 +++++++- + arch/arm/mach-shmobile/platsmp.c | 2 +- + 4 files changed, 35 insertions(+), 2 deletions(-) + create mode 100644 arch/arm/boot/dts/emev2-kzm9d.dts + +--- /dev/null ++++ b/arch/arm/boot/dts/emev2-kzm9d.dts +@@ -0,0 +1,26 @@ ++/* ++ * Device Tree Source for the KZM9D board ++ * ++ * Copyright (C) 2012 Renesas Solutions Corp. ++ * ++ * This file is licensed under the terms of the GNU General Public License ++ * version 2. This program is licensed "as is" without any warranty of any ++ * kind, whether express or implied. ++ */ ++/dts-v1/; ++ ++/include/ "emev2.dtsi" ++ ++/ { ++ model = "EMEV2 KZM9D Board"; ++ compatible = "renesas,kzm9d", "renesas,emev2"; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x40000000 0x8000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS1,115200n81"; ++ }; ++}; +--- a/arch/arm/mach-shmobile/Kconfig ++++ b/arch/arm/mach-shmobile/Kconfig +@@ -116,6 +116,7 @@ config MACH_MARZEN + config MACH_KZM9D + bool "KZM9D board" + depends on ARCH_EMEV2 ++ select USE_OF + + config MACH_KZM9G + bool "KZM-A9-GT board" +--- a/arch/arm/mach-shmobile/board-kzm9d.c ++++ b/arch/arm/mach-shmobile/board-kzm9d.c +@@ -68,7 +68,12 @@ void __init kzm9d_add_standard_devices(v + platform_add_devices(kzm9d_devices, ARRAY_SIZE(kzm9d_devices)); + } + +-MACHINE_START(KZM9D, "kzm9d") ++static const char *kzm9d_boards_compat_dt[] __initdata = { ++ "renesas,kzm9d", ++ NULL, ++}; ++ ++DT_MACHINE_START(KZM9D_DT, "kzm9d") + .map_io = emev2_map_io, + .init_early = emev2_add_early_devices, + .nr_irqs = NR_IRQS_LEGACY, +@@ -76,4 +81,5 @@ MACHINE_START(KZM9D, "kzm9d") + .handle_irq = gic_handle_irq, + .init_machine = kzm9d_add_standard_devices, + .timer = &shmobile_timer, ++ .dt_compat = kzm9d_boards_compat_dt, + MACHINE_END +--- a/arch/arm/mach-shmobile/platsmp.c ++++ b/arch/arm/mach-shmobile/platsmp.c +@@ -30,7 +30,7 @@ + #endif + + #define is_r8a7779() machine_is_marzen() +-#define is_emev2() machine_is_kzm9d() ++#define is_emev2() of_machine_is_compatible("renesas,emev2") + + static unsigned int __init shmobile_smp_get_core_count(void) + { diff --git a/patches.kzm9d/serial-8250_pci-clear-fifos-for-intel-me-serial-over-lan-device-on-bi.patch b/patches.kzm9d/serial-8250_pci-clear-fifos-for-intel-me-serial-over-lan-device-on-bi.patch new file mode 100644 index 0000000000000..60bbd30b0225b --- /dev/null +++ b/patches.kzm9d/serial-8250_pci-clear-fifos-for-intel-me-serial-over-lan-device-on-bi.patch @@ -0,0 +1,136 @@ +From koba@kmckk.co.jp Wed Oct 3 04:26:23 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:22:54 +0900 +Subject: [PATCH 02/26] serial/8250_pci: Clear FIFOs for Intel ME Serial Over Lan device on BI +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Sudhakar Mamillapalli <sudhakar@fb.com>, Nhan H Mai <nhan.h.mai@intel.com>, Dan Williams <dan.j.williams@intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-3-git-send-email-koba@kmckk.co.jp> + + +From: Sudhakar Mamillapalli <sudhakar@fb.com> + +When using Serial Over Lan (SOL) over the virtual serial port in a Intel +management engine (ME) device, on device reset the serial FIFOs need to +be cleared to keep the FIFO indexes in-sync between the host and the +engine. + +On a reset the serial device assertes BI, so using that as a cue FIFOs +are cleared. So for this purpose a new handle_break callback has been +added. One other problem is that the serial registers might temporarily +go to 0 on reset of this device. So instead of using the IER register +read, if 0 returned use the ier value in uart_8250_port. This is hidden +under a custom serial_in. + +Cc: Nhan H Mai <nhan.h.mai@intel.com> +Signed-off-by: Sudhakar Mamillapalli <sudhakar@fb.com> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Dan Williams <dan.j.williams@intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit 0ad372b962d109323d18ac2aa118b2ad100eb8dd) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250.c | 10 +++++++++ + drivers/tty/serial/8250/8250.h | 2 ++ + drivers/tty/serial/8250/8250_pci.c | 39 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 51 insertions(+) + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index aed9363..c9ac4ea 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -568,6 +568,16 @@ static void serial8250_clear_fifos(struct uart_8250_port *p) + } + } + ++void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p) ++{ ++ unsigned char fcr; ++ ++ serial8250_clear_fifos(p); ++ fcr = uart_config[p->port.type].fcr; ++ serial_out(p, UART_FCR, fcr); ++} ++EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos); ++ + /* + * IER sleep support. UARTs which have EFRs need the "extended + * capability" bit enabled. Note that on XR16C850s, we need to +diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h +index 2868a1d..c9d0ebe 100644 +--- a/drivers/tty/serial/8250/8250.h ++++ b/drivers/tty/serial/8250/8250.h +@@ -96,6 +96,8 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) + up->port.serial_out(&up->port, offset, value); + } + ++void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); ++ + #if defined(__alpha__) && !defined(CONFIG_PCI) + /* + * Digital did something really horribly wrong with the OUT1 and OUT2 +diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c +index 3614973..5a4de9a 100644 +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -17,6 +17,7 @@ + #include <linux/slab.h> + #include <linux/delay.h> + #include <linux/tty.h> ++#include <linux/serial_reg.h> + #include <linux/serial_core.h> + #include <linux/8250_pci.h> + #include <linux/bitops.h> +@@ -1092,11 +1093,49 @@ static int skip_tx_en_setup(struct serial_private *priv, + return pci_default_setup(priv, board, port, idx); + } + ++static void kt_handle_break(struct uart_port *p) ++{ ++ struct uart_8250_port *up = ++ container_of(p, struct uart_8250_port, port); ++ /* ++ * On receipt of a BI, serial device in Intel ME (Intel ++ * management engine) needs to have its fifos cleared for sane ++ * SOL (Serial Over Lan) output. ++ */ ++ serial8250_clear_and_reinit_fifos(up); ++} ++ ++static unsigned int kt_serial_in(struct uart_port *p, int offset) ++{ ++ struct uart_8250_port *up = ++ container_of(p, struct uart_8250_port, port); ++ unsigned int val; ++ ++ /* ++ * When the Intel ME (management engine) gets reset its serial ++ * port registers could return 0 momentarily. Functions like ++ * serial8250_console_write, read and save the IER, perform ++ * some operation and then restore it. In order to avoid ++ * setting IER register inadvertently to 0, if the value read ++ * is 0, double check with ier value in uart_8250_port and use ++ * that instead. up->ier should be the same value as what is ++ * currently configured. ++ */ ++ val = inb(p->iobase + offset); ++ if (offset == UART_IER) { ++ if (val == 0) ++ val = up->ier; ++ } ++ return val; ++} ++ + static int kt_serial_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_port *port, int idx) + { + port->flags |= UPF_BUG_THRE; ++ port->serial_in = kt_serial_in; ++ port->handle_break = kt_handle_break; + return skip_tx_en_setup(priv, board, port, idx); + } + +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial-8250_pci-fix-suspend-resume-vs-init-exit-quirks.patch b/patches.kzm9d/serial-8250_pci-fix-suspend-resume-vs-init-exit-quirks.patch new file mode 100644 index 0000000000000..5b6e0aa2d3617 --- /dev/null +++ b/patches.kzm9d/serial-8250_pci-fix-suspend-resume-vs-init-exit-quirks.patch @@ -0,0 +1,85 @@ +From koba@kmckk.co.jp Wed Oct 3 04:26:47 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:22:55 +0900 +Subject: [PATCH 03/26] serial/8250_pci: fix suspend/resume vs init/exit quirks +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Dan Williams <dan.j.williams@intel.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-4-git-send-email-koba@kmckk.co.jp> + + +From: Dan Williams <dan.j.williams@intel.com> + +Commit e86ff4a6 "serial/8250_pci: init-quirk msi support for kt serial +controller" introduced a regression in suspend/resume by causing msi's +to be enabled twice without an intervening disable. + +00:16.3 Serial controller: Intel Corporation Patsburg KT Controller (rev 05) (prog-if 02 [16550]) + Subsystem: Intel Corporation Device 7270 + Flags: bus master, 66MHz, fast devsel, latency 0, IRQ 72 + I/O ports at 4080 [size=8] + Memory at d1c30000 (32-bit, non-prefetchable) [size=4K] + Capabilities: [c8] Power Management version 3 + Capabilities: [d0] MSI: Enable+ Count=1/1 Maskable- 64bit+ + Kernel driver in use: serial + +[ 365.250523] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:16.3/msi_irqs' +[ 365.250525] Modules linked in: nls_utf8 ipv6 uinput sg iTCO_wdt + iTCO_vendor_support ioatdma dca i2c_i801 i2c_core wmi sd_mod ahci libahci isci + libsas libata scsi_transport_sas [last unloaded: scsi_wait_scan] +[ 365.250540] Pid: 9030, comm: kworker/u:1 Tainted: G W 3.3.0-isci-3.0.213+ #1 +[ 365.250542] Call Trace: +[ 365.250545] [<ffffffff8115e955>] ? sysfs_add_one+0x99/0xad +[ 365.250548] [<ffffffff8102db8b>] warn_slowpath_common+0x85/0x9e +[ 365.250551] [<ffffffff8102dc96>] warn_slowpath_fmt+0x6e/0x70 +[ 365.250555] [<ffffffff8115e8fa>] ? sysfs_add_one+0x3e/0xad +[ 365.250558] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44 +[ 365.250561] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44 +[ 365.250564] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44 +[ 365.250567] [<ffffffff8115e8b4>] ? sysfs_pathname+0x3c/0x44 +[ 365.250570] [<ffffffff8115e955>] sysfs_add_one+0x99/0xad +[ 365.250573] [<ffffffff8115f031>] create_dir+0x72/0xa5 +[ 365.250577] [<ffffffff8115f194>] sysfs_create_dir+0xa2/0xbe +[ 365.250581] [<ffffffff81262463>] kobject_add_internal+0x126/0x1f8 +[ 365.250585] [<ffffffff8126255b>] kset_register+0x26/0x3f +[ 365.250588] [<ffffffff8126275a>] kset_create_and_add+0x62/0x7c +[ 365.250592] [<ffffffff81293619>] populate_msi_sysfs+0x34/0x103 +[ 365.250595] [<ffffffff81293e1c>] pci_enable_msi_block+0x1b3/0x216 +[ 365.250599] [<ffffffff81303f7c>] try_enable_msi+0x13/0x17 +[ 365.250603] [<ffffffff81303fb3>] pciserial_resume_ports+0x21/0x42 +[ 365.250607] [<ffffffff81304041>] pciserial_resume_one+0x50/0x57 +[ 365.250610] [<ffffffff81283e1a>] pci_legacy_resume+0x38/0x47 +[ 365.250613] [<ffffffff81283e7d>] pci_pm_restore+0x54/0x87 +[ 365.250616] [<ffffffff81283e29>] ? pci_legacy_resume+0x47/0x47 +[ 365.250619] [<ffffffff8131e9e8>] dpm_run_callback+0x48/0x7b +[ 365.250623] [<ffffffff8131f39a>] device_resume+0x342/0x394 +[ 365.250626] [<ffffffff8131f5b7>] async_resume+0x21/0x49 + +That patch has since been reverted, but by inspection it seems that +pciserial_suspend_ports() should be invoking .exit() quirks to release +resources acquired during .init(). + +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Dan Williams <dan.j.williams@intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit 5f1a38952b7e932a1c169c28917b9a831f641bcc) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250_pci.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/tty/serial/8250/8250_pci.c ++++ b/drivers/tty/serial/8250/8250_pci.c +@@ -2834,6 +2834,12 @@ void pciserial_suspend_ports(struct seri + for (i = 0; i < priv->nr; i++) + if (priv->line[i] >= 0) + serial8250_suspend_port(priv->line[i]); ++ ++ /* ++ * Ensure that every init quirk is properly torn down ++ */ ++ if (priv->quirk->exit) ++ priv->quirk->exit(priv->dev); + } + EXPORT_SYMBOL_GPL(pciserial_suspend_ports); + diff --git a/patches.kzm9d/serial8250-add-dl_read-dl_write-callbacks.patch b/patches.kzm9d/serial8250-add-dl_read-dl_write-callbacks.patch new file mode 100644 index 0000000000000..fb35a611b766e --- /dev/null +++ b/patches.kzm9d/serial8250-add-dl_read-dl_write-callbacks.patch @@ -0,0 +1,206 @@ +From koba@kmckk.co.jp Wed Oct 3 04:26:58 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:22:56 +0900 +Subject: [PATCH 04/26] serial8250: Add dl_read()/dl_write() callbacks +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-5-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Convert serial_dl_read() and serial_dl_write() from macro +to 8250 specific callbacks. This change makes it easier to +support 8250 hardware with non-standard DLL and DLM register +configurations such as Alchemy, RM9K and upcoming Emma Mobile +UART hardware. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit cc419fa0d38c425e4ea7bffeed931b07b0a3e461) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250.c | 117 ++++++++++++++++++++++------------------ + drivers/tty/serial/8250/8250.h | 14 +++++ + 2 files changed, 78 insertions(+), 53 deletions(-) + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index c9ac4ea..590ee85 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -284,6 +284,66 @@ static const struct serial8250_config uart_config[] = { + }, + }; + ++/* Uart divisor latch read */ ++static int default_dl_read(struct uart_8250_port *up) ++{ ++ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; ++} ++ ++/* Uart divisor latch write */ ++static void default_dl_write(struct uart_8250_port *up, int value) ++{ ++ serial_out(up, UART_DLL, value & 0xff); ++ serial_out(up, UART_DLM, value >> 8 & 0xff); ++} ++ ++#if defined(CONFIG_MIPS_ALCHEMY) ++/* Au1x00 haven't got a standard divisor latch */ ++static int _serial_dl_read(struct uart_8250_port *up) ++{ ++ if (up->port.iotype == UPIO_AU) ++ return __raw_readl(up->port.membase + 0x28); ++ else ++ return default_dl_read(up); ++} ++ ++static void _serial_dl_write(struct uart_8250_port *up, int value) ++{ ++ if (up->port.iotype == UPIO_AU) ++ __raw_writel(value, up->port.membase + 0x28); ++ else ++ default_dl_write(up, value); ++} ++#elif defined(CONFIG_SERIAL_8250_RM9K) ++static int _serial_dl_read(struct uart_8250_port *up) ++{ ++ return (up->port.iotype == UPIO_RM9000) ? ++ (((__raw_readl(up->port.membase + 0x10) << 8) | ++ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) : ++ default_dl_read(up); ++} ++ ++static void _serial_dl_write(struct uart_8250_port *up, int value) ++{ ++ if (up->port.iotype == UPIO_RM9000) { ++ __raw_writel(value, up->port.membase + 0x08); ++ __raw_writel(value >> 8, up->port.membase + 0x10); ++ } else { ++ default_dl_write(up, value); ++ } ++} ++#else ++static int _serial_dl_read(struct uart_8250_port *up) ++{ ++ return default_dl_read(up); ++} ++ ++static void _serial_dl_write(struct uart_8250_port *up, int value) ++{ ++ default_dl_write(up, value); ++} ++#endif ++ + #if defined(CONFIG_MIPS_ALCHEMY) + + /* Au1x00 UART hardware has a weird register layout */ +@@ -434,6 +494,10 @@ static void set_io_from_upio(struct uart_port *p) + { + struct uart_8250_port *up = + container_of(p, struct uart_8250_port, port); ++ ++ up->dl_read = _serial_dl_read; ++ up->dl_write = _serial_dl_write; ++ + switch (p->iotype) { + case UPIO_HUB6: + p->serial_in = hub6_serial_in; +@@ -481,59 +545,6 @@ serial_port_out_sync(struct uart_port *p, int offset, int value) + } + } + +-/* Uart divisor latch read */ +-static inline int _serial_dl_read(struct uart_8250_port *up) +-{ +- return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; +-} +- +-/* Uart divisor latch write */ +-static inline void _serial_dl_write(struct uart_8250_port *up, int value) +-{ +- serial_out(up, UART_DLL, value & 0xff); +- serial_out(up, UART_DLM, value >> 8 & 0xff); +-} +- +-#if defined(CONFIG_MIPS_ALCHEMY) +-/* Au1x00 haven't got a standard divisor latch */ +-static int serial_dl_read(struct uart_8250_port *up) +-{ +- if (up->port.iotype == UPIO_AU) +- return __raw_readl(up->port.membase + 0x28); +- else +- return _serial_dl_read(up); +-} +- +-static void serial_dl_write(struct uart_8250_port *up, int value) +-{ +- if (up->port.iotype == UPIO_AU) +- __raw_writel(value, up->port.membase + 0x28); +- else +- _serial_dl_write(up, value); +-} +-#elif defined(CONFIG_SERIAL_8250_RM9K) +-static int serial_dl_read(struct uart_8250_port *up) +-{ +- return (up->port.iotype == UPIO_RM9000) ? +- (((__raw_readl(up->port.membase + 0x10) << 8) | +- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) : +- _serial_dl_read(up); +-} +- +-static void serial_dl_write(struct uart_8250_port *up, int value) +-{ +- if (up->port.iotype == UPIO_RM9000) { +- __raw_writel(value, up->port.membase + 0x08); +- __raw_writel(value >> 8, up->port.membase + 0x10); +- } else { +- _serial_dl_write(up, value); +- } +-} +-#else +-#define serial_dl_read(up) _serial_dl_read(up) +-#define serial_dl_write(up, value) _serial_dl_write(up, value) +-#endif +- + /* + * For the 16C950 + */ +diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h +index c9d0ebe..f9719d1 100644 +--- a/drivers/tty/serial/8250/8250.h ++++ b/drivers/tty/serial/8250/8250.h +@@ -37,6 +37,10 @@ struct uart_8250_port { + unsigned char lsr_saved_flags; + #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA + unsigned char msr_saved_flags; ++ ++ /* 8250 specific callbacks */ ++ int (*dl_read)(struct uart_8250_port *); ++ void (*dl_write)(struct uart_8250_port *, int); + }; + + struct old_serial_port { +@@ -98,6 +102,16 @@ static inline void serial_out(struct uart_8250_port *up, int offset, int value) + + void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p); + ++static inline int serial_dl_read(struct uart_8250_port *up) ++{ ++ return up->dl_read(up); ++} ++ ++static inline void serial_dl_write(struct uart_8250_port *up, int value) ++{ ++ up->dl_write(up, value); ++} ++ + #if defined(__alpha__) && !defined(CONFIG_PCI) + /* + * Digital did something really horribly wrong with the OUT1 and OUT2 +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial8250-clean-up-default-map-and-dl-code.patch b/patches.kzm9d/serial8250-clean-up-default-map-and-dl-code.patch new file mode 100644 index 0000000000000..f1cbc6536d77f --- /dev/null +++ b/patches.kzm9d/serial8250-clean-up-default-map-and-dl-code.patch @@ -0,0 +1,140 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:25 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:22:59 +0900 +Subject: [PATCH 07/26] serial8250: Clean up default map and dl code +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-8-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Get rid of unused functions and macros now when +Alchemy and RM9K are converted over to callbacks. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit e8155629ff19e05722ba057d1521baec270d780e) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250.c | 38 ++++++++++++-------------------------- + 1 file changed, 12 insertions(+), 26 deletions(-) + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index cc398b1..662188d 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -285,28 +285,18 @@ static const struct serial8250_config uart_config[] = { + }; + + /* Uart divisor latch read */ +-static int default_dl_read(struct uart_8250_port *up) ++static int default_serial_dl_read(struct uart_8250_port *up) + { + return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8; + } + + /* Uart divisor latch write */ +-static void default_dl_write(struct uart_8250_port *up, int value) ++static void default_serial_dl_write(struct uart_8250_port *up, int value) + { + serial_out(up, UART_DLL, value & 0xff); + serial_out(up, UART_DLM, value >> 8 & 0xff); + } + +-static int _serial_dl_read(struct uart_8250_port *up) +-{ +- return default_dl_read(up); +-} +- +-static void _serial_dl_write(struct uart_8250_port *up, int value) +-{ +- default_dl_write(up, value); +-} +- + #ifdef CONFIG_MIPS_ALCHEMY + + /* Au1x00 UART hardware has a weird register layout */ +@@ -403,57 +393,53 @@ static void rm9k_serial_dl_write(struct uart_8250_port *up, int value) + + #endif + +-/* sane hardware needs no mapping */ +-#define map_8250_in_reg(up, offset) (offset) +-#define map_8250_out_reg(up, offset) (offset) +- + static unsigned int hub6_serial_in(struct uart_port *p, int offset) + { +- offset = map_8250_in_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + outb(p->hub6 - 1 + offset, p->iobase); + return inb(p->iobase + 1); + } + + static void hub6_serial_out(struct uart_port *p, int offset, int value) + { +- offset = map_8250_out_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + outb(p->hub6 - 1 + offset, p->iobase); + outb(value, p->iobase + 1); + } + + static unsigned int mem_serial_in(struct uart_port *p, int offset) + { +- offset = map_8250_in_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + return readb(p->membase + offset); + } + + static void mem_serial_out(struct uart_port *p, int offset, int value) + { +- offset = map_8250_out_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + writeb(value, p->membase + offset); + } + + static void mem32_serial_out(struct uart_port *p, int offset, int value) + { +- offset = map_8250_out_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + writel(value, p->membase + offset); + } + + static unsigned int mem32_serial_in(struct uart_port *p, int offset) + { +- offset = map_8250_in_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + return readl(p->membase + offset); + } + + static unsigned int io_serial_in(struct uart_port *p, int offset) + { +- offset = map_8250_in_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + return inb(p->iobase + offset); + } + + static void io_serial_out(struct uart_port *p, int offset, int value) + { +- offset = map_8250_out_reg(p, offset) << p->regshift; ++ offset = offset << p->regshift; + outb(value, p->iobase + offset); + } + +@@ -464,8 +450,8 @@ static void set_io_from_upio(struct uart_port *p) + struct uart_8250_port *up = + container_of(p, struct uart_8250_port, port); + +- up->dl_read = _serial_dl_read; +- up->dl_write = _serial_dl_write; ++ up->dl_read = default_serial_dl_read; ++ up->dl_write = default_serial_dl_write; + + switch (p->iotype) { + case UPIO_HUB6: +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial8250-em-add-dt-support.patch b/patches.kzm9d/serial8250-em-add-dt-support.patch new file mode 100644 index 0000000000000..98b908efcf354 --- /dev/null +++ b/patches.kzm9d/serial8250-em-add-dt-support.patch @@ -0,0 +1,47 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:39 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:03 +0900 +Subject: [PATCH 11/26] serial8250-em: Add DT support +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-12-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Update the 8250_em driver to support DT. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit 3e62c413fb0c75c8cfaf086d00a9ecc6b55009d6) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250_em.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c +index be6c289..3a0363e 100644 +--- a/drivers/tty/serial/8250/8250_em.c ++++ b/drivers/tty/serial/8250/8250_em.c +@@ -163,9 +163,16 @@ static int __devexit serial8250_em_remove(struct platform_device *pdev) + return 0; + } + ++static const struct of_device_id serial8250_em_dt_ids[] __devinitconst = { ++ { .compatible = "renesas,em-uart", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, serial8250_em_dt_ids); ++ + static struct platform_driver serial8250_em_platform_driver = { + .driver = { + .name = "serial8250-em", ++ .of_match_table = serial8250_em_dt_ids, + .owner = THIS_MODULE, + }, + .probe = serial8250_em_probe, +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial8250-em-clk_get-is_err-error-handling-fix.patch b/patches.kzm9d/serial8250-em-clk_get-is_err-error-handling-fix.patch new file mode 100644 index 0000000000000..340ffc59ac1c7 --- /dev/null +++ b/patches.kzm9d/serial8250-em-clk_get-is_err-error-handling-fix.patch @@ -0,0 +1,44 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:34 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:02 +0900 +Subject: [PATCH 10/26] serial8250-em: clk_get() IS_ERR() error handling fix +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-11-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Update the 8250_em driver to correctly handle the case +where no clock is associated with the device. + +The return value of clk_get() needs to be checked with +IS_ERR() to avoid NULL pointer referencing. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit 94e792ab66d696aad2e52c91bae4cfbeefe4c9f6) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250_em.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c +index ff42542..be6c289 100644 +--- a/drivers/tty/serial/8250/8250_em.c ++++ b/drivers/tty/serial/8250/8250_em.c +@@ -110,8 +110,9 @@ static int __devinit serial8250_em_probe(struct platform_device *pdev) + } + + priv->sclk = clk_get(&pdev->dev, "sclk"); +- if (!priv->sclk) { ++ if (IS_ERR(priv->sclk)) { + dev_err(&pdev->dev, "unable to get clock\n"); ++ ret = PTR_ERR(priv->sclk); + goto err1; + } + +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial8250-em-emma-mobile-uart-driver-v2.patch b/patches.kzm9d/serial8250-em-emma-mobile-uart-driver-v2.patch new file mode 100644 index 0000000000000..117636e6e3330 --- /dev/null +++ b/patches.kzm9d/serial8250-em-emma-mobile-uart-driver-v2.patch @@ -0,0 +1,256 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:32 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:01 +0900 +Subject: [PATCH 09/26] serial8250-em: Emma Mobile UART driver V2 +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-10-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +This is V2 of the Emma Mobile 8250 platform driver. + +The hardware itself has according to the data sheet +up to 64 byte FIFOs but at this point we only make +use of the 16550 compatible mode. + +To support this piece of hardware the common UART +registers need to be remapped, and the access size +differences need to be handled. + +The DLL and DLM registers can due to offset collision +not be remapped easily, and because of that this +driver makes use of ->dl_read() and ->dl_write() +callbacks. This in turn requires a registration +function that takes 8250-specific paramenters. + +Future potential enhancements include DT support, +early platform driver console and fine grained PM. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Alan Cox <alan@linux.intel.com> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit 22886ee96895b7a9f9d06da4dc9420b61b4ef1f7) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250_em.c | 178 +++++++++++++++++++++++++++++++++++++ + drivers/tty/serial/8250/Kconfig | 8 ++ + drivers/tty/serial/8250/Makefile | 1 + + 3 files changed, 187 insertions(+) + create mode 100644 drivers/tty/serial/8250/8250_em.c + +diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c +new file mode 100644 +index 0000000..ff42542 +--- /dev/null ++++ b/drivers/tty/serial/8250/8250_em.c +@@ -0,0 +1,178 @@ ++/* ++ * Renesas Emma Mobile 8250 driver ++ * ++ * Copyright (C) 2012 Magnus Damm ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include <linux/device.h> ++#include <linux/init.h> ++#include <linux/io.h> ++#include <linux/module.h> ++#include <linux/serial_8250.h> ++#include <linux/serial_core.h> ++#include <linux/serial_reg.h> ++#include <linux/platform_device.h> ++#include <linux/clk.h> ++#include <linux/slab.h> ++ ++#include "8250.h" ++ ++#define UART_DLL_EM 9 ++#define UART_DLM_EM 10 ++ ++struct serial8250_em_priv { ++ struct clk *sclk; ++ int line; ++}; ++ ++static void serial8250_em_serial_out(struct uart_port *p, int offset, int value) ++{ ++ switch (offset) { ++ case UART_TX: /* TX @ 0x00 */ ++ writeb(value, p->membase); ++ break; ++ case UART_FCR: /* FCR @ 0x0c (+1) */ ++ case UART_LCR: /* LCR @ 0x10 (+1) */ ++ case UART_MCR: /* MCR @ 0x14 (+1) */ ++ case UART_SCR: /* SCR @ 0x20 (+1) */ ++ writel(value, p->membase + ((offset + 1) << 2)); ++ break; ++ case UART_IER: /* IER @ 0x04 */ ++ value &= 0x0f; /* only 4 valid bits - not Xscale */ ++ /* fall-through */ ++ case UART_DLL_EM: /* DLL @ 0x24 (+9) */ ++ case UART_DLM_EM: /* DLM @ 0x28 (+9) */ ++ writel(value, p->membase + (offset << 2)); ++ } ++} ++ ++static unsigned int serial8250_em_serial_in(struct uart_port *p, int offset) ++{ ++ switch (offset) { ++ case UART_RX: /* RX @ 0x00 */ ++ return readb(p->membase); ++ case UART_MCR: /* MCR @ 0x14 (+1) */ ++ case UART_LSR: /* LSR @ 0x18 (+1) */ ++ case UART_MSR: /* MSR @ 0x1c (+1) */ ++ case UART_SCR: /* SCR @ 0x20 (+1) */ ++ return readl(p->membase + ((offset + 1) << 2)); ++ case UART_IER: /* IER @ 0x04 */ ++ case UART_IIR: /* IIR @ 0x08 */ ++ case UART_DLL_EM: /* DLL @ 0x24 (+9) */ ++ case UART_DLM_EM: /* DLM @ 0x28 (+9) */ ++ return readl(p->membase + (offset << 2)); ++ } ++ return 0; ++} ++ ++static int serial8250_em_serial_dl_read(struct uart_8250_port *up) ++{ ++ return serial_in(up, UART_DLL_EM) | serial_in(up, UART_DLM_EM) << 8; ++} ++ ++static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value) ++{ ++ serial_out(up, UART_DLL_EM, value & 0xff); ++ serial_out(up, UART_DLM_EM, value >> 8 & 0xff); ++} ++ ++static int __devinit serial8250_em_probe(struct platform_device *pdev) ++{ ++ struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ struct serial8250_em_priv *priv; ++ struct uart_8250_port up; ++ int ret = -EINVAL; ++ ++ if (!regs || !irq) { ++ dev_err(&pdev->dev, "missing registers or irq\n"); ++ goto err0; ++ } ++ ++ priv = kzalloc(sizeof(*priv), GFP_KERNEL); ++ if (!priv) { ++ dev_err(&pdev->dev, "unable to allocate private data\n"); ++ ret = -ENOMEM; ++ goto err0; ++ } ++ ++ priv->sclk = clk_get(&pdev->dev, "sclk"); ++ if (!priv->sclk) { ++ dev_err(&pdev->dev, "unable to get clock\n"); ++ goto err1; ++ } ++ ++ memset(&up, 0, sizeof(up)); ++ up.port.mapbase = regs->start; ++ up.port.irq = irq->start; ++ up.port.type = PORT_UNKNOWN; ++ up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP; ++ up.port.dev = &pdev->dev; ++ up.port.private_data = priv; ++ ++ clk_enable(priv->sclk); ++ up.port.uartclk = clk_get_rate(priv->sclk); ++ ++ up.port.iotype = UPIO_MEM32; ++ up.port.serial_in = serial8250_em_serial_in; ++ up.port.serial_out = serial8250_em_serial_out; ++ up.dl_read = serial8250_em_serial_dl_read; ++ up.dl_write = serial8250_em_serial_dl_write; ++ ++ ret = serial8250_register_8250_port(&up); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "unable to register 8250 port\n"); ++ goto err2; ++ } ++ ++ priv->line = ret; ++ platform_set_drvdata(pdev, priv); ++ return 0; ++ ++ err2: ++ clk_disable(priv->sclk); ++ clk_put(priv->sclk); ++ err1: ++ kfree(priv); ++ err0: ++ return ret; ++} ++ ++static int __devexit serial8250_em_remove(struct platform_device *pdev) ++{ ++ struct serial8250_em_priv *priv = platform_get_drvdata(pdev); ++ ++ serial8250_unregister_port(priv->line); ++ clk_disable(priv->sclk); ++ clk_put(priv->sclk); ++ kfree(priv); ++ return 0; ++} ++ ++static struct platform_driver serial8250_em_platform_driver = { ++ .driver = { ++ .name = "serial8250-em", ++ .owner = THIS_MODULE, ++ }, ++ .probe = serial8250_em_probe, ++ .remove = __devexit_p(serial8250_em_remove), ++}; ++ ++module_platform_driver(serial8250_em_platform_driver); ++ ++MODULE_AUTHOR("Magnus Damm"); ++MODULE_DESCRIPTION("Renesas Emma Mobile 8250 Driver"); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig +index 591f801..8bc7ecb 100644 +--- a/drivers/tty/serial/8250/Kconfig ++++ b/drivers/tty/serial/8250/Kconfig +@@ -278,3 +278,11 @@ config SERIAL_8250_DW + help + Selecting this option will enable handling of the extra features + present in the Synopsys DesignWare APB UART. ++ ++config SERIAL_8250_EM ++ tristate "Support for Emma Mobile intergrated serial port" ++ depends on SERIAL_8250 && ARM && HAVE_CLK ++ help ++ Selecting this option will add support for the integrated serial ++ port hardware found on the Emma Mobile line of processors. ++ If unsure, say N. +diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile +index 867bba7..3f35eac 100644 +--- a/drivers/tty/serial/8250/Makefile ++++ b/drivers/tty/serial/8250/Makefile +@@ -18,3 +18,4 @@ obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o + obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o + obj-$(CONFIG_SERIAL_8250_FSL) += 8250_fsl.o + obj-$(CONFIG_SERIAL_8250_DW) += 8250_dw.o ++obj-$(CONFIG_SERIAL_8250_EM) += 8250_em.o +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial8250-introduce-serial8250_register_8250_port.patch b/patches.kzm9d/serial8250-introduce-serial8250_register_8250_port.patch new file mode 100644 index 0000000000000..100457132cc36 --- /dev/null +++ b/patches.kzm9d/serial8250-introduce-serial8250_register_8250_port.patch @@ -0,0 +1,176 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:28 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:23:00 +0900 +Subject: [PATCH 08/26] serial8250: Introduce serial8250_register_8250_port() +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-9-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Introduce yet another 8250 registration function. +This time it is serial8250_register_8250_port() and it +allows us to register 8250 hardware instances using struct +uart_8250_port. The new function makes it possible to +register 8250 hardware that makes use of 8250 specific +callbacks such as ->dl_read() and ->dl_write(). + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit f73fa05b90eb8c0dd3230c364cf1107f4f8f3848) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250.c | 91 ++++++++++++++++++++++++++-------------- + include/linux/serial_8250.h | 1 + + 2 files changed, 60 insertions(+), 32 deletions(-) + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index 662188d..47d061b 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -3112,7 +3112,7 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * + } + + /** +- * serial8250_register_port - register a serial port ++ * serial8250_register_8250_port - register a serial port + * @port: serial port template + * + * Configure the serial port specified by the request. If the +@@ -3124,52 +3124,56 @@ static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port * + * + * On success the port is ready to use and the line number is returned. + */ +-int serial8250_register_port(struct uart_port *port) ++int serial8250_register_8250_port(struct uart_8250_port *up) + { + struct uart_8250_port *uart; + int ret = -ENOSPC; + +- if (port->uartclk == 0) ++ if (up->port.uartclk == 0) + return -EINVAL; + + mutex_lock(&serial_mutex); + +- uart = serial8250_find_match_or_unused(port); ++ uart = serial8250_find_match_or_unused(&up->port); + if (uart) { + uart_remove_one_port(&serial8250_reg, &uart->port); + +- uart->port.iobase = port->iobase; +- uart->port.membase = port->membase; +- uart->port.irq = port->irq; +- uart->port.irqflags = port->irqflags; +- uart->port.uartclk = port->uartclk; +- uart->port.fifosize = port->fifosize; +- uart->port.regshift = port->regshift; +- uart->port.iotype = port->iotype; +- uart->port.flags = port->flags | UPF_BOOT_AUTOCONF; +- uart->port.mapbase = port->mapbase; +- uart->port.private_data = port->private_data; +- if (port->dev) +- uart->port.dev = port->dev; +- +- if (port->flags & UPF_FIXED_TYPE) +- serial8250_init_fixed_type_port(uart, port->type); ++ uart->port.iobase = up->port.iobase; ++ uart->port.membase = up->port.membase; ++ uart->port.irq = up->port.irq; ++ uart->port.irqflags = up->port.irqflags; ++ uart->port.uartclk = up->port.uartclk; ++ uart->port.fifosize = up->port.fifosize; ++ uart->port.regshift = up->port.regshift; ++ uart->port.iotype = up->port.iotype; ++ uart->port.flags = up->port.flags | UPF_BOOT_AUTOCONF; ++ uart->port.mapbase = up->port.mapbase; ++ uart->port.private_data = up->port.private_data; ++ if (up->port.dev) ++ uart->port.dev = up->port.dev; ++ ++ if (up->port.flags & UPF_FIXED_TYPE) ++ serial8250_init_fixed_type_port(uart, up->port.type); + + set_io_from_upio(&uart->port); + /* Possibly override default I/O functions. */ +- if (port->serial_in) +- uart->port.serial_in = port->serial_in; +- if (port->serial_out) +- uart->port.serial_out = port->serial_out; +- if (port->handle_irq) +- uart->port.handle_irq = port->handle_irq; ++ if (up->port.serial_in) ++ uart->port.serial_in = up->port.serial_in; ++ if (up->port.serial_out) ++ uart->port.serial_out = up->port.serial_out; ++ if (up->port.handle_irq) ++ uart->port.handle_irq = up->port.handle_irq; + /* Possibly override set_termios call */ +- if (port->set_termios) +- uart->port.set_termios = port->set_termios; +- if (port->pm) +- uart->port.pm = port->pm; +- if (port->handle_break) +- uart->port.handle_break = port->handle_break; ++ if (up->port.set_termios) ++ uart->port.set_termios = up->port.set_termios; ++ if (up->port.pm) ++ uart->port.pm = up->port.pm; ++ if (up->port.handle_break) ++ uart->port.handle_break = up->port.handle_break; ++ if (up->dl_read) ++ uart->dl_read = up->dl_read; ++ if (up->dl_write) ++ uart->dl_write = up->dl_write; + + if (serial8250_isa_config != NULL) + serial8250_isa_config(0, &uart->port, +@@ -3183,6 +3187,29 @@ int serial8250_register_port(struct uart_port *port) + + return ret; + } ++EXPORT_SYMBOL(serial8250_register_8250_port); ++ ++/** ++ * serial8250_register_port - register a serial port ++ * @port: serial port template ++ * ++ * Configure the serial port specified by the request. If the ++ * port exists and is in use, it is hung up and unregistered ++ * first. ++ * ++ * The port is then probed and if necessary the IRQ is autodetected ++ * If this fails an error is returned. ++ * ++ * On success the port is ready to use and the line number is returned. ++ */ ++int serial8250_register_port(struct uart_port *port) ++{ ++ struct uart_8250_port up; ++ ++ memset(&up, 0, sizeof(up)); ++ memcpy(&up.port, port, sizeof(*port)); ++ return serial8250_register_8250_port(&up); ++} + EXPORT_SYMBOL(serial8250_register_port); + + /** +diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h +index a522fd9..10dbce5 100644 +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -69,6 +69,7 @@ enum { + struct uart_port; + struct uart_8250_port; + ++int serial8250_register_8250_port(struct uart_8250_port *); + int serial8250_register_port(struct uart_port *); + void serial8250_unregister_port(int line); + void serial8250_suspend_port(int line); +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial8250-use-dl_read-dl_write-on-alchemy.patch b/patches.kzm9d/serial8250-use-dl_read-dl_write-on-alchemy.patch new file mode 100644 index 0000000000000..0930be9641544 --- /dev/null +++ b/patches.kzm9d/serial8250-use-dl_read-dl_write-on-alchemy.patch @@ -0,0 +1,144 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:03 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:22:57 +0900 +Subject: [PATCH 05/26] serial8250: Use dl_read()/dl_write() on Alchemy +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-6-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Convert the 8250 Alchemy support code to make +use of the new dl_read()/dl_write() callbacks. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit 6b4160313c239d61c3907b2aaaeeec156911c9d1) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250.c | 67 ++++++++++++++++------------------------ + 1 file changed, 26 insertions(+), 41 deletions(-) + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index 590ee85..2d62c89 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -297,24 +297,7 @@ static void default_dl_write(struct uart_8250_port *up, int value) + serial_out(up, UART_DLM, value >> 8 & 0xff); + } + +-#if defined(CONFIG_MIPS_ALCHEMY) +-/* Au1x00 haven't got a standard divisor latch */ +-static int _serial_dl_read(struct uart_8250_port *up) +-{ +- if (up->port.iotype == UPIO_AU) +- return __raw_readl(up->port.membase + 0x28); +- else +- return default_dl_read(up); +-} +- +-static void _serial_dl_write(struct uart_8250_port *up, int value) +-{ +- if (up->port.iotype == UPIO_AU) +- __raw_writel(value, up->port.membase + 0x28); +- else +- default_dl_write(up, value); +-} +-#elif defined(CONFIG_SERIAL_8250_RM9K) ++#if defined(CONFIG_SERIAL_8250_RM9K) + static int _serial_dl_read(struct uart_8250_port *up) + { + return (up->port.iotype == UPIO_RM9000) ? +@@ -344,7 +327,7 @@ static void _serial_dl_write(struct uart_8250_port *up, int value) + } + #endif + +-#if defined(CONFIG_MIPS_ALCHEMY) ++#ifdef CONFIG_MIPS_ALCHEMY + + /* Au1x00 UART hardware has a weird register layout */ + static const u8 au_io_in_map[] = { +@@ -365,22 +348,32 @@ static const u8 au_io_out_map[] = { + [UART_MCR] = 6, + }; + +-/* sane hardware needs no mapping */ +-static inline int map_8250_in_reg(struct uart_port *p, int offset) ++static unsigned int au_serial_in(struct uart_port *p, int offset) + { +- if (p->iotype != UPIO_AU) +- return offset; +- return au_io_in_map[offset]; ++ offset = au_io_in_map[offset] << p->regshift; ++ return __raw_readl(p->membase + offset); + } + +-static inline int map_8250_out_reg(struct uart_port *p, int offset) ++static void au_serial_out(struct uart_port *p, int offset, int value) + { +- if (p->iotype != UPIO_AU) +- return offset; +- return au_io_out_map[offset]; ++ offset = au_io_out_map[offset] << p->regshift; ++ __raw_writel(value, p->membase + offset); ++} ++ ++/* Au1x00 haven't got a standard divisor latch */ ++static int au_serial_dl_read(struct uart_8250_port *up) ++{ ++ return __raw_readl(up->port.membase + 0x28); + } + +-#elif defined(CONFIG_SERIAL_8250_RM9K) ++static void au_serial_dl_write(struct uart_8250_port *up, int value) ++{ ++ __raw_writel(value, up->port.membase + 0x28); ++} ++ ++#endif ++ ++#if defined(CONFIG_SERIAL_8250_RM9K) + + static const u8 + regmap_in[8] = { +@@ -464,18 +457,6 @@ static unsigned int mem32_serial_in(struct uart_port *p, int offset) + return readl(p->membase + offset); + } + +-static unsigned int au_serial_in(struct uart_port *p, int offset) +-{ +- offset = map_8250_in_reg(p, offset) << p->regshift; +- return __raw_readl(p->membase + offset); +-} +- +-static void au_serial_out(struct uart_port *p, int offset, int value) +-{ +- offset = map_8250_out_reg(p, offset) << p->regshift; +- __raw_writel(value, p->membase + offset); +-} +- + static unsigned int io_serial_in(struct uart_port *p, int offset) + { + offset = map_8250_in_reg(p, offset) << p->regshift; +@@ -515,10 +496,14 @@ static void set_io_from_upio(struct uart_port *p) + p->serial_out = mem32_serial_out; + break; + ++#ifdef CONFIG_MIPS_ALCHEMY + case UPIO_AU: + p->serial_in = au_serial_in; + p->serial_out = au_serial_out; ++ up->dl_read = au_serial_dl_read; ++ up->dl_write = au_serial_dl_write; + break; ++#endif + + default: + p->serial_in = io_serial_in; +-- +1.7.9.5 + diff --git a/patches.kzm9d/serial8250-use-dl_read-dl_write-on-rm9k.patch b/patches.kzm9d/serial8250-use-dl_read-dl_write-on-rm9k.patch new file mode 100644 index 0000000000000..267fe1acb7eed --- /dev/null +++ b/patches.kzm9d/serial8250-use-dl_read-dl_write-on-rm9k.patch @@ -0,0 +1,145 @@ +From koba@kmckk.co.jp Wed Oct 3 04:27:18 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:22:58 +0900 +Subject: [PATCH 06/26] serial8250: Use dl_read()/dl_write() on RM9K +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-7-git-send-email-koba@kmckk.co.jp> + + +From: Magnus Damm <damm@opensource.se> + +Convert the 8250 RM9K support code to make +use of the new dl_read()/dl_write() callbacks. + +Signed-off-by: Magnus Damm <damm@opensource.se> +Acked-by: Arnd Bergmann <arnd@arndb.de> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit 28bf4cf22dcd936f93dd6063696b1accdc1d5207) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + drivers/tty/serial/8250/8250.c | 62 +++++++++++++++++++--------------------- + 1 file changed, 29 insertions(+), 33 deletions(-) + +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index 2d62c89..cc398b1 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -297,25 +297,6 @@ static void default_dl_write(struct uart_8250_port *up, int value) + serial_out(up, UART_DLM, value >> 8 & 0xff); + } + +-#if defined(CONFIG_SERIAL_8250_RM9K) +-static int _serial_dl_read(struct uart_8250_port *up) +-{ +- return (up->port.iotype == UPIO_RM9000) ? +- (((__raw_readl(up->port.membase + 0x10) << 8) | +- (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff) : +- default_dl_read(up); +-} +- +-static void _serial_dl_write(struct uart_8250_port *up, int value) +-{ +- if (up->port.iotype == UPIO_RM9000) { +- __raw_writel(value, up->port.membase + 0x08); +- __raw_writel(value >> 8, up->port.membase + 0x10); +- } else { +- default_dl_write(up, value); +- } +-} +-#else + static int _serial_dl_read(struct uart_8250_port *up) + { + return default_dl_read(up); +@@ -325,7 +306,6 @@ static void _serial_dl_write(struct uart_8250_port *up, int value) + { + default_dl_write(up, value); + } +-#endif + + #ifdef CONFIG_MIPS_ALCHEMY + +@@ -373,7 +353,7 @@ static void au_serial_dl_write(struct uart_8250_port *up, int value) + + #endif + +-#if defined(CONFIG_SERIAL_8250_RM9K) ++#ifdef CONFIG_SERIAL_8250_RM9K + + static const u8 + regmap_in[8] = { +@@ -397,28 +377,36 @@ static const u8 + [UART_SCR] = 0x2c + }; + +-static inline int map_8250_in_reg(struct uart_port *p, int offset) ++static unsigned int rm9k_serial_in(struct uart_port *p, int offset) + { +- if (p->iotype != UPIO_RM9000) +- return offset; +- return regmap_in[offset]; ++ offset = regmap_in[offset] << p->regshift; ++ return readl(p->membase + offset); + } + +-static inline int map_8250_out_reg(struct uart_port *p, int offset) ++static void rm9k_serial_out(struct uart_port *p, int offset, int value) + { +- if (p->iotype != UPIO_RM9000) +- return offset; +- return regmap_out[offset]; ++ offset = regmap_out[offset] << p->regshift; ++ writel(value, p->membase + offset); + } + +-#else ++static int rm9k_serial_dl_read(struct uart_8250_port *up) ++{ ++ return ((__raw_readl(up->port.membase + 0x10) << 8) | ++ (__raw_readl(up->port.membase + 0x08) & 0xff)) & 0xffff; ++} ++ ++static void rm9k_serial_dl_write(struct uart_8250_port *up, int value) ++{ ++ __raw_writel(value, up->port.membase + 0x08); ++ __raw_writel(value >> 8, up->port.membase + 0x10); ++} ++ ++#endif + + /* sane hardware needs no mapping */ + #define map_8250_in_reg(up, offset) (offset) + #define map_8250_out_reg(up, offset) (offset) + +-#endif +- + static unsigned int hub6_serial_in(struct uart_port *p, int offset) + { + offset = map_8250_in_reg(p, offset) << p->regshift; +@@ -490,12 +478,20 @@ static void set_io_from_upio(struct uart_port *p) + p->serial_out = mem_serial_out; + break; + +- case UPIO_RM9000: + case UPIO_MEM32: + p->serial_in = mem32_serial_in; + p->serial_out = mem32_serial_out; + break; + ++#ifdef CONFIG_SERIAL_8250_RM9K ++ case UPIO_RM9000: ++ p->serial_in = rm9k_serial_in; ++ p->serial_out = rm9k_serial_out; ++ up->dl_read = rm9k_serial_dl_read; ++ up->dl_write = rm9k_serial_dl_write; ++ break; ++#endif ++ + #ifdef CONFIG_MIPS_ALCHEMY + case UPIO_AU: + p->serial_in = au_serial_in; +-- +1.7.9.5 + diff --git a/patches.kzm9d/tegra-serial8250-add-handle_break-uart_port-op.patch b/patches.kzm9d/tegra-serial8250-add-handle_break-uart_port-op.patch new file mode 100644 index 0000000000000..d16ce543e38c8 --- /dev/null +++ b/patches.kzm9d/tegra-serial8250-add-handle_break-uart_port-op.patch @@ -0,0 +1,330 @@ +From koba@kmckk.co.jp Wed Oct 3 04:24:29 2012 +From: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Date: Wed, 3 Oct 2012 20:22:53 +0900 +Subject: [PATCH 01/26] tegra, serial8250: add ->handle_break() uart_port op +To: greg@kroah.com +Cc: ltsi-dev@lists.linuxfoundation.org, horms@verge.net.au, damm@opensource.se, Dan Williams <dan.j.williams@intel.com>, Nhan H Mai <nhan.h.mai@intel.com>, Colin Cross <ccross@android.com>, Olof Johansson <olof@lixom.net>, Grant Likely <grant.likely@secretlab.ca>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Tetsuyuki Kobayashi <koba@kmckk.co.jp> +Message-ID: <1349263398-13152-2-git-send-email-koba@kmckk.co.jp> + + +From: Dan Williams <dan.j.williams@intel.com> + +The "KT" serial port has another use case for a "received break" quirk, +so before adding another special case to the 8250 core take this +opportunity to push such quirks out of the core and into a uart_port op. + +Stephen says: +"If the callback function is to no longer live in 8250.c itself, + arch/arm/mach-tegra/devices.c isn't logically a good place to put it, + and that file will be going away once we get rid of all the board files + and move solely to device tree." + +...so since 8250_pci.c houses all the quirks for pci serial devices this +quirk is similarly housed in of_serial.c. Once the open firmware +conversion completes the infrastructure details +(include/linux/of_serial.h, and the export) can all be removed to make +this self contained to of_serial.c. + +Acked-by: Arnd Bergmann <arnd@arndb.de> +Cc: Nhan H Mai <nhan.h.mai@intel.com> +Cc: Colin Cross <ccross@android.com> +Cc: Olof Johansson <olof@lixom.net> +[stephen: kill CONFIG_SERIAL_TEGRA in favor just using CONFIG_ARCH_TEGRA] +Cc: Grant Likely <grant.likely@secretlab.ca> +Acked-by: Sudhakar Mamillapalli <sudhakar@fb.com> +Reported-by: Alan Cox <alan@lxorguk.ukuu.org.uk> +Acked-by: Alan Cox <alan@linux.intel.com> +Signed-off-by: Dan Williams <dan.j.williams@intel.com> +Acked-by: Stephen Warren <swarren@wwwdotorg.org> +Tested-by: Stephen Warren <swarren@wwwdotorg.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +(cherry picked from commit bf03f65b7967df5807ddef7b99f8a41d4c94fc70) + +Signed-off-by: Tetsuyuki Kobayashi <koba@kmckk.co.jp> +--- + arch/arm/mach-tegra/board-harmony.c | 2 ++ + arch/arm/mach-tegra/board-paz00.c | 3 +++ + arch/arm/mach-tegra/board-seaboard.c | 2 ++ + arch/arm/mach-tegra/board-trimslice.c | 2 ++ + drivers/tty/serial/8250/8250.c | 34 +++------------------------------ + drivers/tty/serial/of_serial.c | 26 +++++++++++++++++++++++++ + include/linux/of_serial.h | 17 +++++++++++++++++ + include/linux/serial_8250.h | 1 + + include/linux/serial_core.h | 5 +++++ + 9 files changed, 61 insertions(+), 31 deletions(-) + create mode 100644 include/linux/of_serial.h + +diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c +index c00aadb..222182e 100644 +--- a/arch/arm/mach-tegra/board-harmony.c ++++ b/arch/arm/mach-tegra/board-harmony.c +@@ -19,6 +19,7 @@ + #include <linux/init.h> + #include <linux/platform_device.h> + #include <linux/serial_8250.h> ++#include <linux/of_serial.h> + #include <linux/clk.h> + #include <linux/dma-mapping.h> + #include <linux/pda_power.h> +@@ -52,6 +53,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { + .irq = INT_UARTD, + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, + .type = PORT_TEGRA, ++ .handle_break = tegra_serial_handle_break, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = 216000000, +diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c +index 330afdf..d0735c7 100644 +--- a/arch/arm/mach-tegra/board-paz00.c ++++ b/arch/arm/mach-tegra/board-paz00.c +@@ -21,6 +21,7 @@ + #include <linux/init.h> + #include <linux/platform_device.h> + #include <linux/serial_8250.h> ++#include <linux/of_serial.h> + #include <linux/clk.h> + #include <linux/dma-mapping.h> + #include <linux/gpio_keys.h> +@@ -55,6 +56,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { + .irq = INT_UARTA, + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, + .type = PORT_TEGRA, ++ .handle_break = tegra_serial_handle_break, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = 216000000, +@@ -65,6 +67,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { + .irq = INT_UARTC, + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, + .type = PORT_TEGRA, ++ .handle_break = tegra_serial_handle_break, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = 216000000, +diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c +index d669847..5b687b8 100644 +--- a/arch/arm/mach-tegra/board-seaboard.c ++++ b/arch/arm/mach-tegra/board-seaboard.c +@@ -18,6 +18,7 @@ + #include <linux/init.h> + #include <linux/platform_device.h> + #include <linux/serial_8250.h> ++#include <linux/of_serial.h> + #include <linux/i2c.h> + #include <linux/delay.h> + #include <linux/input.h> +@@ -47,6 +48,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { + /* Memory and IRQ filled in before registration */ + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, + .type = PORT_TEGRA, ++ .handle_break = tegra_serial_handle_break, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = 216000000, +diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c +index cd52820a..f735858 100644 +--- a/arch/arm/mach-tegra/board-trimslice.c ++++ b/arch/arm/mach-tegra/board-trimslice.c +@@ -22,6 +22,7 @@ + #include <linux/init.h> + #include <linux/platform_device.h> + #include <linux/serial_8250.h> ++#include <linux/of_serial.h> + #include <linux/io.h> + #include <linux/i2c.h> + #include <linux/gpio.h> +@@ -48,6 +49,7 @@ static struct plat_serial8250_port debug_uart_platform_data[] = { + .irq = INT_UARTA, + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, + .type = PORT_TEGRA, ++ .handle_break = tegra_serial_handle_break, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = 216000000, +diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c +index d537431..aed9363 100644 +--- a/drivers/tty/serial/8250/8250.c ++++ b/drivers/tty/serial/8250/8250.c +@@ -1332,27 +1332,6 @@ static void serial8250_enable_ms(struct uart_port *port) + } + + /* +- * Clear the Tegra rx fifo after a break +- * +- * FIXME: This needs to become a port specific callback once we have a +- * framework for this +- */ +-static void clear_rx_fifo(struct uart_8250_port *up) +-{ +- unsigned int status, tmout = 10000; +- do { +- status = serial_in(up, UART_LSR); +- if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) +- status = serial_in(up, UART_RX); +- else +- break; +- if (--tmout == 0) +- break; +- udelay(1); +- } while (1); +-} +- +-/* + * serial8250_rx_chars: processes according to the passed in LSR + * value, and returns the remaining LSR bits not handled + * by this Rx routine. +@@ -1386,20 +1365,10 @@ serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr) + up->lsr_saved_flags = 0; + + if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) { +- /* +- * For statistics only +- */ + if (lsr & UART_LSR_BI) { + lsr &= ~(UART_LSR_FE | UART_LSR_PE); + port->icount.brk++; + /* +- * If tegra port then clear the rx fifo to +- * accept another break/character. +- */ +- if (port->type == PORT_TEGRA) +- clear_rx_fifo(up); +- +- /* + * We do the SysRQ and SAK checking + * here because otherwise the break + * may get masked by ignore_status_mask +@@ -3038,6 +3007,7 @@ static int __devinit serial8250_probe(struct platform_device *dev) + port.serial_in = p->serial_in; + port.serial_out = p->serial_out; + port.handle_irq = p->handle_irq; ++ port.handle_break = p->handle_break; + port.set_termios = p->set_termios; + port.pm = p->pm; + port.dev = &dev->dev; +@@ -3210,6 +3180,8 @@ int serial8250_register_port(struct uart_port *port) + uart->port.set_termios = port->set_termios; + if (port->pm) + uart->port.pm = port->pm; ++ if (port->handle_break) ++ uart->port.handle_break = port->handle_break; + + if (serial8250_isa_config != NULL) + serial8250_isa_config(0, &uart->port, +diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c +index e8c9cee..5410c06 100644 +--- a/drivers/tty/serial/of_serial.c ++++ b/drivers/tty/serial/of_serial.c +@@ -12,10 +12,13 @@ + #include <linux/init.h> + #include <linux/module.h> + #include <linux/slab.h> ++#include <linux/delay.h> + #include <linux/serial_core.h> + #include <linux/serial_8250.h> ++#include <linux/serial_reg.h> + #include <linux/of_address.h> + #include <linux/of_irq.h> ++#include <linux/of_serial.h> + #include <linux/of_platform.h> + #include <linux/nwpserial.h> + +@@ -24,6 +27,26 @@ struct of_serial_info { + int line; + }; + ++#ifdef CONFIG_ARCH_TEGRA ++void tegra_serial_handle_break(struct uart_port *p) ++{ ++ unsigned int status, tmout = 10000; ++ ++ do { ++ status = p->serial_in(p, UART_LSR); ++ if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) ++ status = p->serial_in(p, UART_RX); ++ else ++ break; ++ if (--tmout == 0) ++ break; ++ udelay(1); ++ } while (1); ++} ++/* FIXME remove this export when tegra finishes conversion to open firmware */ ++EXPORT_SYMBOL_GPL(tegra_serial_handle_break); ++#endif ++ + /* + * Fill a struct uart_port for a given device node + */ +@@ -84,6 +107,9 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev, + | UPF_FIXED_PORT | UPF_FIXED_TYPE; + port->dev = &ofdev->dev; + ++ if (type == PORT_TEGRA) ++ port->handle_break = tegra_serial_handle_break; ++ + return 0; + } + +diff --git a/include/linux/of_serial.h b/include/linux/of_serial.h +new file mode 100644 +index 0000000..4a73ed8 +--- /dev/null ++++ b/include/linux/of_serial.h +@@ -0,0 +1,17 @@ ++#ifndef __LINUX_OF_SERIAL_H ++#define __LINUX_OF_SERIAL_H ++ ++/* ++ * FIXME remove this file when tegra finishes conversion to open firmware, ++ * expectation is that all quirks will then be self-contained in ++ * drivers/tty/serial/of_serial.c. ++ */ ++#ifdef CONFIG_ARCH_TEGRA ++extern void tegra_serial_handle_break(struct uart_port *port); ++#else ++static inline void tegra_serial_handle_break(struct uart_port *port) ++{ ++} ++#endif ++ ++#endif /* __LINUX_OF_SERIAL */ +diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h +index 8f012f8..a522fd9 100644 +--- a/include/linux/serial_8250.h ++++ b/include/linux/serial_8250.h +@@ -38,6 +38,7 @@ struct plat_serial8250_port { + int (*handle_irq)(struct uart_port *); + void (*pm)(struct uart_port *, unsigned int state, + unsigned old); ++ void (*handle_break)(struct uart_port *); + }; + + /* +diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h +index 2db407a..65db992 100644 +--- a/include/linux/serial_core.h ++++ b/include/linux/serial_core.h +@@ -310,6 +310,7 @@ struct uart_port { + int (*handle_irq)(struct uart_port *); + void (*pm)(struct uart_port *, unsigned int state, + unsigned int old); ++ void (*handle_break)(struct uart_port *); + unsigned int irq; /* irq number */ + unsigned long irqflags; /* irq flags */ + unsigned int uartclk; /* base uart clock */ +@@ -533,6 +534,10 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch) + static inline int uart_handle_break(struct uart_port *port) + { + struct uart_state *state = port->state; ++ ++ if (port->handle_break) ++ port->handle_break(port); ++ + #ifdef SUPPORT_SYSRQ + if (port->cons && port->cons->index == port->line) { + if (!port->sysrq) { +-- +1.7.9.5 + @@ -637,3 +637,30 @@ patches.kzm9g/arm-shmobile-kzm9g-defconfig-enable-inotify_user.patch patches.kzm9g/arm-shmobile-sh73a0-fixup-reloc_base-of-intca_irq_pins_desc.patch +############################################################################# +# kzm9d board support +# +patches.kzm9d/tegra-serial8250-add-handle_break-uart_port-op.patch +patches.kzm9d/serial-8250_pci-clear-fifos-for-intel-me-serial-over-lan-device-on-bi.patch +patches.kzm9d/serial-8250_pci-fix-suspend-resume-vs-init-exit-quirks.patch +patches.kzm9d/serial8250-add-dl_read-dl_write-callbacks.patch +patches.kzm9d/serial8250-use-dl_read-dl_write-on-alchemy.patch +patches.kzm9d/serial8250-use-dl_read-dl_write-on-rm9k.patch +patches.kzm9d/serial8250-clean-up-default-map-and-dl-code.patch +patches.kzm9d/serial8250-introduce-serial8250_register_8250_port.patch +patches.kzm9d/serial8250-em-emma-mobile-uart-driver-v2.patch +patches.kzm9d/serial8250-em-clk_get-is_err-error-handling-fix.patch +patches.kzm9d/serial8250-em-add-dt-support.patch +patches.kzm9d/clockevents-make-clockevents_config-a-global-symbol.patch +patches.kzm9d/clocksource-em_sti-emma-mobile-sti-driver.patch +patches.kzm9d/clocksource-em_sti-add-dt-support.patch +patches.kzm9d/gpio-emma-mobile-gpio-driver-v2.patch +patches.kzm9d/mach-shmobile-emma-mobile-ev2-soc-base-support-v3.patch +patches.kzm9d/mach-shmobile-kzm9d-board-support-v3.patch +patches.kzm9d/mach-shmobile-emma-mobile-ev2-smp-support-v3.patch +patches.kzm9d/mach-shmobile-emma-mobile-ev2-gpio-support-v3.patch +patches.kzm9d/mach-shmobile-kzm9d-board-ethernet-support-v3.patch +patches.kzm9d/arm-mach-shmobile-kzm9d-add-defconfig.patch +patches.kzm9d/mach-shmobile-emma-mobile-ev2-dt-support-v3.patch +patches.kzm9d/mach-shmobile-use-dt_machine-for-kzm9d-v3.patch +patches.kzm9d/arm-mach-shmobile-fix-build-when-smp-is-enabled-and-emev2-is-not-enabled.patch |