aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux')
-rw-r--r--recipes-kernel/linux/files/0001-tty-don-t-deadlock-while-flushing-workqueue-quark.patch7
-rw-r--r--recipes-kernel/linux/files/0002-driver-core-constify-data-for-class_find_devic-quark.patch41
-rw-r--r--recipes-kernel/linux/files/0003-TTY-mark-tty_get_device-call-with-the-proper-c-quark.patch10
-rw-r--r--recipes-kernel/linux/files/0004-pwm-Add-sysfs-interface-quark.patch17
-rw-r--r--recipes-kernel/linux/files/0005-drivers-pwm-sysfs.c-add-export.h-RTC-50404-quark.patch7
-rw-r--r--recipes-kernel/linux/files/0006-core-Quark-patch-quark.patch48
-rw-r--r--recipes-kernel/linux/files/0007-Quark-Platform-Code-quark.patch1005
-rw-r--r--recipes-kernel/linux/files/0008-Quark-UART-quark.patch909
-rw-r--r--recipes-kernel/linux/files/0009-EFI-capsule-update-quark.patch36
-rw-r--r--recipes-kernel/linux/files/0010-Quark-SDIO-host-controller-quark.patch9
-rw-r--r--recipes-kernel/linux/files/0011-Quark-USB-host-quark.patch11
-rw-r--r--recipes-kernel/linux/files/0012-USB-gadget-serial-quark.patch42
-rw-r--r--recipes-kernel/linux/files/0013-Quark-stmmac-Ethernet-quark.patch104
-rw-r--r--recipes-kernel/linux/files/0014-Quark-GPIO-2-2-quark.patch145
-rw-r--r--recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch442
-rw-r--r--recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch1128
-rw-r--r--recipes-kernel/linux/files/0017-Quark-I2C-quark.patch11
-rw-r--r--recipes-kernel/linux/files/0018-Quark-sensors-quark.patch89
-rw-r--r--recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch7
-rw-r--r--recipes-kernel/linux/files/0020-Quark-IIO-quark.patch1079
-rw-r--r--recipes-kernel/linux/files/0021-Quark-SPI-flash-quark.patch7
-rw-r--r--recipes-kernel/linux/files/quark-standard.scc6
-rw-r--r--recipes-kernel/linux/files/quark.cfg31
23 files changed, 3783 insertions, 1408 deletions
diff --git a/recipes-kernel/linux/files/0001-tty-don-t-deadlock-while-flushing-workqueue-quark.patch b/recipes-kernel/linux/files/0001-tty-don-t-deadlock-while-flushing-workqueue-quark.patch
index 4d0fd37..b4c3b77 100644
--- a/recipes-kernel/linux/files/0001-tty-don-t-deadlock-while-flushing-workqueue-quark.patch
+++ b/recipes-kernel/linux/files/0001-tty-don-t-deadlock-while-flushing-workqueue-quark.patch
@@ -107,8 +107,8 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 852e4a8152b427c3f318bb0e1b5e938d64dcdc32)
---
- drivers/tty/tty_ldisc.c | 10 +++++-----
- 1 files changed, 5 insertions(+), 5 deletions(-)
+ drivers/tty/tty_ldisc.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index c578229..78f1be2 100644
@@ -137,6 +137,3 @@ index c578229..78f1be2 100644
if (o_tty)
tty_ldisc_kill(o_tty);
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0002-driver-core-constify-data-for-class_find_devic-quark.patch b/recipes-kernel/linux/files/0002-driver-core-constify-data-for-class_find_devic-quark.patch
index bf633cd..9829454 100644
--- a/recipes-kernel/linux/files/0002-driver-core-constify-data-for-class_find_devic-quark.patch
+++ b/recipes-kernel/linux/files/0002-driver-core-constify-data-for-class_find_devic-quark.patch
@@ -23,25 +23,25 @@ Acked-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 9f3b795a626ee79574595e06d1437fe0c7d51d29)
---
- drivers/base/class.c | 4 ++--
- drivers/base/core.c | 4 ++--
- drivers/gpio/gpiolib.c | 2 +-
- drivers/isdn/mISDN/core.c | 4 ++--
- drivers/net/phy/mdio_bus.c | 2 +-
- drivers/power/power_supply_core.c | 4 ++--
- drivers/rtc/interface.c | 6 +++---
- drivers/scsi/hosts.c | 4 ++--
- drivers/scsi/osd/osd_uld.c | 26 +++++++++-----------------
- drivers/scsi/scsi_transport_iscsi.c | 4 ++--
- drivers/spi/spi.c | 4 ++--
- drivers/uwb/lc-rc.c | 21 ++++++++++-----------
- include/linux/device.h | 4 ++--
- include/linux/power_supply.h | 2 +-
- include/linux/rtc.h | 2 +-
- init/do_mounts.c | 4 ++--
- kernel/power/suspend_test.c | 11 +++++------
- net/ieee802154/wpan-class.c | 5 ++---
- net/nfc/core.c | 4 ++--
+ drivers/base/class.c | 4 ++--
+ drivers/base/core.c | 4 ++--
+ drivers/gpio/gpiolib.c | 2 +-
+ drivers/isdn/mISDN/core.c | 4 ++--
+ drivers/net/phy/mdio_bus.c | 2 +-
+ drivers/power/power_supply_core.c | 4 ++--
+ drivers/rtc/interface.c | 6 +++---
+ drivers/scsi/hosts.c | 4 ++--
+ drivers/scsi/osd/osd_uld.c | 26 +++++++++-----------------
+ drivers/scsi/scsi_transport_iscsi.c | 4 ++--
+ drivers/spi/spi.c | 4 ++--
+ drivers/uwb/lc-rc.c | 21 ++++++++++-----------
+ include/linux/device.h | 4 ++--
+ include/linux/power_supply.h | 2 +-
+ include/linux/rtc.h | 2 +-
+ init/do_mounts.c | 4 ++--
+ kernel/power/suspend_test.c | 11 +++++------
+ net/ieee802154/wpan-class.c | 5 ++---
+ net/nfc/core.c | 4 ++--
19 files changed, 53 insertions(+), 64 deletions(-)
diff --git a/drivers/base/class.c b/drivers/base/class.c
@@ -490,6 +490,3 @@ index aa64ea4..0f4a6de 100644
return dev->idx == *idx;
}
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0003-TTY-mark-tty_get_device-call-with-the-proper-c-quark.patch b/recipes-kernel/linux/files/0003-TTY-mark-tty_get_device-call-with-the-proper-c-quark.patch
index ab3eb1e..7dc7701 100644
--- a/recipes-kernel/linux/files/0003-TTY-mark-tty_get_device-call-with-the-proper-c-quark.patch
+++ b/recipes-kernel/linux/files/0003-TTY-mark-tty_get_device-call-with-the-proper-c-quark.patch
@@ -1,7 +1,8 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Date: Wed, 6 Feb 2013 15:59:18 -0800
-Subject: [PATCH 03/21] TTY: mark tty_get_device call with the proper const values
+Subject: [PATCH 03/21] TTY: mark tty_get_device call with the proper const
+ values
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
@@ -14,8 +15,8 @@ Cc: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 6e9430ac57e8c1f41ab24ef7fbb3d452c7eb7246)
---
- drivers/tty/tty_io.c | 4 ++--
- 1 files changed, 2 insertions(+), 2 deletions(-)
+ drivers/tty/tty_io.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index da9fde8..6b20fd6 100644
@@ -33,6 +34,3 @@ index da9fde8..6b20fd6 100644
return dev->devt == *devt;
}
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0004-pwm-Add-sysfs-interface-quark.patch b/recipes-kernel/linux/files/0004-pwm-Add-sysfs-interface-quark.patch
index fb4ee30..f19eb64 100644
--- a/recipes-kernel/linux/files/0004-pwm-Add-sysfs-interface-quark.patch
+++ b/recipes-kernel/linux/files/0004-pwm-Add-sysfs-interface-quark.patch
@@ -26,13 +26,13 @@ Cc: Rob Landley <rob@landley.net>
Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
(cherry picked from commit 76abbdde2d95a3807d0dc6bf9f84d03d0dbd4f3d)
---
- Documentation/ABI/testing/sysfs-class-pwm | 79 +++++++
- Documentation/pwm.txt | 37 +++
- drivers/pwm/Kconfig | 4 +
- drivers/pwm/Makefile | 1 +
- drivers/pwm/core.c | 25 ++-
- drivers/pwm/sysfs.c | 352 +++++++++++++++++++++++++++++
- include/linux/pwm.h | 29 +++-
+ Documentation/ABI/testing/sysfs-class-pwm | 79 +++++++
+ Documentation/pwm.txt | 37 ++++
+ drivers/pwm/Kconfig | 4 +
+ drivers/pwm/Makefile | 1 +
+ drivers/pwm/core.c | 25 ++-
+ drivers/pwm/sysfs.c | 352 ++++++++++++++++++++++++++++++
+ include/linux/pwm.h | 29 ++-
7 files changed, 524 insertions(+), 3 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-class-pwm
create mode 100644 drivers/pwm/sysfs.c
@@ -679,6 +679,3 @@ index 6d661f3..6842d11 100644
+#endif /* CONFIG_PWM_SYSFS */
+
#endif /* __LINUX_PWM_H */
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0005-drivers-pwm-sysfs.c-add-export.h-RTC-50404-quark.patch b/recipes-kernel/linux/files/0005-drivers-pwm-sysfs.c-add-export.h-RTC-50404-quark.patch
index 3d2ade0..8d44b83 100644
--- a/recipes-kernel/linux/files/0005-drivers-pwm-sysfs.c-add-export.h-RTC-50404-quark.patch
+++ b/recipes-kernel/linux/files/0005-drivers-pwm-sysfs.c-add-export.h-RTC-50404-quark.patch
@@ -6,8 +6,8 @@ Subject: [PATCH 05/21] drivers/pwm/sysfs.c: add export.h - RTC #50404
Resolve THIS_MODULE macro.
(cherry picked from commit b594e3ef2c9f7a2c61188e76a1c228f1d30556eb)
---
- drivers/pwm/sysfs.c | 1 +
- 1 files changed, 1 insertions(+), 0 deletions(-)
+ drivers/pwm/sysfs.c | 1 +
+ 1 file changed, 1 insertion(+)
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index 8ca5de3..4cd6d78 100644
@@ -21,6 +21,3 @@ index 8ca5de3..4cd6d78 100644
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/err.h>
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0006-core-Quark-patch-quark.patch b/recipes-kernel/linux/files/0006-core-Quark-patch-quark.patch
index 81841a5..37c57f6 100644
--- a/recipes-kernel/linux/files/0006-core-Quark-patch-quark.patch
+++ b/recipes-kernel/linux/files/0006-core-Quark-patch-quark.patch
@@ -1,23 +1,25 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Bryan O'Donoghue <bryan.odonoghue@intel.com>
-Date: Thu, 13 Feb 2014 16:41:02 +0000
+Date: Fri, 18 Apr 2014 10:11:00 +0100
Subject: [PATCH 06/21] core Quark patch
---
- arch/x86/Kconfig | 23 +
+ arch/x86/Kconfig | 25 +-
arch/x86/include/asm/imr.h | 22 +
- arch/x86/include/asm/qrk.h | 85 +
+ arch/x86/include/asm/qrk.h | 78 +
arch/x86/include/asm/serial.h | 6 +
arch/x86/kernel/cpu/intel.c | 11 +
arch/x86/kernel/setup.c | 5 +-
arch/x86/platform/efi/efi-bgrt.c | 20 +-
include/linux/efi-bgrt.h | 2 +
- 8 files changed, 168 insertions(+), 6 deletions(-)
+ meta/cfg/kernel-cache/bsp/quark/quark.cfg | 3063 +++++++++++++++++++++++++++++
+ 9 files changed, 3225 insertions(+), 7 deletions(-)
create mode 100644 arch/x86/include/asm/imr.h
create mode 100644 arch/x86/include/asm/qrk.h
+ create mode 100644 meta/cfg/kernel-cache/bsp/quark/quark.cfg
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 0694d09..2c881ac 100644
+index 0694d09..a10027f 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -417,6 +417,15 @@ config X86_INTEL_CE
@@ -50,6 +52,15 @@ index 0694d09..2c881ac 100644
config X86_VISWS
bool "SGI 320/540 (Visual Workstation)"
depends on X86_32 && PCI && X86_MPPARSE && PCI_GODIRECT
+@@ -1169,7 +1185,7 @@ config ARCH_PHYS_ADDR_T_64BIT
+
+ config ARCH_DMA_ADDR_T_64BIT
+ def_bool y
+- depends on X86_64 || HIGHMEM64G
++ depends on X86_64 || HIGHMEM64G && !INTEL_QUARK_X1000_SOC
+
+ config DIRECT_GBPAGES
+ bool "Enable 1GB pages for kernel pagetables" if EXPERT
@@ -1524,6 +1540,13 @@ config EFI_STUB
See Documentation/x86/efi-stub.txt for more information.
@@ -94,28 +105,21 @@ index 0000000..876d499
+#endif /* _ASM_X86_IMR_H */
diff --git a/arch/x86/include/asm/qrk.h b/arch/x86/include/asm/qrk.h
new file mode 100644
-index 0000000..bd65b86
+index 0000000..ed4dab4
--- /dev/null
+++ b/arch/x86/include/asm/qrk.h
-@@ -0,0 +1,85 @@
+@@ -0,0 +1,78 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+#ifndef _ASM_X86_QRK_H
+#define _ASM_X86_QRK_H
@@ -316,4 +320,4 @@ index 051b21f..165426b 100644
+static inline bool efi_bgrt_probe(void) { return false; }
#endif /* !CONFIG_ACPI_BGRT */
-
+
diff --git a/recipes-kernel/linux/files/0007-Quark-Platform-Code-quark.patch b/recipes-kernel/linux/files/0007-Quark-Platform-Code-quark.patch
index 21f2d7f..d8797fc 100644
--- a/recipes-kernel/linux/files/0007-Quark-Platform-Code-quark.patch
+++ b/recipes-kernel/linux/files/0007-Quark-Platform-Code-quark.patch
@@ -1,34 +1,35 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Quark Team <noreply@intel.com>
-Date: Wed, 26 Feb 2014 14:40:08 +0000
+Date: Thu, 10 Apr 2014 11:58:52 +0100
Subject: [PATCH 07/21] Quark Platform Code
---
drivers/platform/x86/Kconfig | 4 +
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/quark/Kconfig | 41 +
- drivers/platform/x86/quark/Makefile | 14 +
- drivers/platform/x86/quark/intel_qrk_audio_ctrl.c | 514 +++++++++
- drivers/platform/x86/quark/intel_qrk_audio_ctrl.h | 45 +
- drivers/platform/x86/quark/intel_qrk_board_data.c | 260 +++++
- drivers/platform/x86/quark/intel_qrk_esram.c | 1144 ++++++++++++++++++++
- drivers/platform/x86/quark/intel_qrk_esram.h | 107 ++
- drivers/platform/x86/quark/intel_qrk_esram_test.c | 602 ++++++++++
- drivers/platform/x86/quark/intel_qrk_esram_test.h | 43 +
- drivers/platform/x86/quark/intel_qrk_imr.c | 697 ++++++++++++
- drivers/platform/x86/quark/intel_qrk_imr.h | 157 +++
- drivers/platform/x86/quark/intel_qrk_imr_kernel.c | 139 +++
- drivers/platform/x86/quark/intel_qrk_imr_test.c | 357 ++++++
- .../x86/quark/intel_qrk_plat_clanton_hill.c | 226 ++++
- .../x86/quark/intel_qrk_plat_clanton_peak.c | 227 ++++
- .../platform/x86/quark/intel_qrk_plat_cross_hill.c | 392 +++++++
- .../platform/x86/quark/intel_qrk_plat_galileo.c | 398 +++++++
- .../platform/x86/quark/intel_qrk_plat_kips_bay.c | 176 +++
- drivers/platform/x86/quark/intel_qrk_sb.c | 253 +++++
- drivers/platform/x86/quark/intel_qrk_thermal.c | 360 ++++++
- include/linux/intel_qrk_sb.h | 92 ++
- include/linux/platform_data/quark.h | 44 +
- 24 files changed, 6293 insertions(+), 0 deletions(-)
+ drivers/platform/x86/quark/Makefile | 15 +
+ drivers/platform/x86/quark/intel_qrk_audio_ctrl.c | 507 +++++++++
+ drivers/platform/x86/quark/intel_qrk_audio_ctrl.h | 38 +
+ drivers/platform/x86/quark/intel_qrk_board_data.c | 257 +++++
+ drivers/platform/x86/quark/intel_qrk_esram.c | 1137 ++++++++++++++++++++
+ drivers/platform/x86/quark/intel_qrk_esram.h | 100 ++
+ drivers/platform/x86/quark/intel_qrk_esram_test.c | 595 ++++++++++
+ drivers/platform/x86/quark/intel_qrk_esram_test.h | 36 +
+ drivers/platform/x86/quark/intel_qrk_imr.c | 690 ++++++++++++
+ drivers/platform/x86/quark/intel_qrk_imr.h | 150 +++
+ drivers/platform/x86/quark/intel_qrk_imr_kernel.c | 132 +++
+ drivers/platform/x86/quark/intel_qrk_imr_test.c | 350 ++++++
+ .../x86/quark/intel_qrk_plat_clanton_hill.c | 219 ++++
+ .../x86/quark/intel_qrk_plat_clanton_peak.c | 220 ++++
+ .../platform/x86/quark/intel_qrk_plat_cross_hill.c | 430 ++++++++
+ .../platform/x86/quark/intel_qrk_plat_galileo.c | 391 +++++++
+ .../x86/quark/intel_qrk_plat_galileo_gen2.c | 392 +++++++
+ .../platform/x86/quark/intel_qrk_plat_kips_bay.c | 169 +++
+ drivers/platform/x86/quark/intel_qrk_sb.c | 246 +++++
+ drivers/platform/x86/quark/intel_qrk_thermal.c | 353 ++++++
+ include/linux/intel_qrk_sb.h | 85 ++
+ include/linux/platform_data/quark.h | 37 +
+ 25 files changed, 6595 insertions(+)
create mode 100644 drivers/platform/x86/quark/Kconfig
create mode 100644 drivers/platform/x86/quark/Makefile
create mode 100644 drivers/platform/x86/quark/intel_qrk_audio_ctrl.c
@@ -46,6 +47,7 @@ Subject: [PATCH 07/21] Quark Platform Code
create mode 100644 drivers/platform/x86/quark/intel_qrk_plat_clanton_peak.c
create mode 100644 drivers/platform/x86/quark/intel_qrk_plat_cross_hill.c
create mode 100644 drivers/platform/x86/quark/intel_qrk_plat_galileo.c
+ create mode 100644 drivers/platform/x86/quark/intel_qrk_plat_galileo_gen2.c
create mode 100644 drivers/platform/x86/quark/intel_qrk_plat_kips_bay.c
create mode 100644 drivers/platform/x86/quark/intel_qrk_sb.c
create mode 100644 drivers/platform/x86/quark/intel_qrk_thermal.c
@@ -125,16 +127,17 @@ index 0000000..0e2c722
+
diff --git a/drivers/platform/x86/quark/Makefile b/drivers/platform/x86/quark/Makefile
new file mode 100644
-index 0000000..0a03469
+index 0000000..8c917a5
--- /dev/null
+++ b/drivers/platform/x86/quark/Makefile
-@@ -0,0 +1,14 @@
+@@ -0,0 +1,15 @@
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_board_data.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_plat_clanton_hill.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_plat_clanton_peak.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_plat_cross_hill.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_plat_kips_bay.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_plat_galileo.o
++obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_plat_galileo_gen2.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_sb.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_imr.o
+obj-$(CONFIG_INTEL_QUARK_X1000_SOC) += intel_qrk_imr_kernel.o
@@ -145,30 +148,23 @@ index 0000000..0a03469
+obj-$(CONFIG_INTEL_QRK_AUDIO_CTRL) += intel_qrk_audio_ctrl.o
diff --git a/drivers/platform/x86/quark/intel_qrk_audio_ctrl.c b/drivers/platform/x86/quark/intel_qrk_audio_ctrl.c
new file mode 100644
-index 0000000..ffc3791
+index 0000000..8d03f76
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_audio_ctrl.c
-@@ -0,0 +1,514 @@
+@@ -0,0 +1,507 @@
+/*
+ * Intel Quark platform audio control driver
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ *
+ * The Intel Clanton Hill platform hardware design includes an audio subsystem
+ * with a number of interconnected audio interfaces. This driver enables
@@ -665,30 +661,23 @@ index 0000000..ffc3791
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/platform/x86/quark/intel_qrk_audio_ctrl.h b/drivers/platform/x86/quark/intel_qrk_audio_ctrl.h
new file mode 100644
-index 0000000..581d0e2
+index 0000000..d4f05ad
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_audio_ctrl.h
-@@ -0,0 +1,45 @@
+@@ -0,0 +1,38 @@
+/*
+ * Intel Quark platform audio control driver
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ *
+ * See intel_qrk_audio_ctrl.c for a detailed description
+ *
@@ -716,28 +705,21 @@ index 0000000..581d0e2
+#endif /* __INTEL_QRK_AUDIO_CTRL_H__ */
diff --git a/drivers/platform/x86/quark/intel_qrk_board_data.c b/drivers/platform/x86/quark/intel_qrk_board_data.c
new file mode 100644
-index 0000000..db7f76a
+index 0000000..c9d4f99
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_board_data.c
-@@ -0,0 +1,260 @@
+@@ -0,0 +1,257 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark Legacy Platform Data accessor layer
@@ -849,6 +831,10 @@ index 0000000..db7f76a
+ .name = "Galileo",
+ .id = -1,
+ },
++ {
++ .name = "GalileoGen2",
++ .id = -1,
++ },
+
+};
+
@@ -982,28 +968,21 @@ index 0000000..db7f76a
+
diff --git a/drivers/platform/x86/quark/intel_qrk_esram.c b/drivers/platform/x86/quark/intel_qrk_esram.c
new file mode 100644
-index 0000000..55adb41
+index 0000000..62ae521
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_esram.c
-@@ -0,0 +1,1144 @@
+@@ -0,0 +1,1137 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark eSRAM overlay driver
@@ -2132,28 +2111,21 @@ index 0000000..55adb41
+
diff --git a/drivers/platform/x86/quark/intel_qrk_esram.h b/drivers/platform/x86/quark/intel_qrk_esram.h
new file mode 100644
-index 0000000..71aaba1
+index 0000000..a4c9636
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_esram.h
-@@ -0,0 +1,107 @@
+@@ -0,0 +1,100 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark eSRAM overlay driver
@@ -2245,28 +2217,21 @@ index 0000000..71aaba1
+#endif /* __INTEL_QRK_ESRAM_H__ */
diff --git a/drivers/platform/x86/quark/intel_qrk_esram_test.c b/drivers/platform/x86/quark/intel_qrk_esram_test.c
new file mode 100644
-index 0000000..544ad57
+index 0000000..c337dc5
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_esram_test.c
-@@ -0,0 +1,602 @@
+@@ -0,0 +1,595 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/**
+ * intel_qrk_esram_test.c
@@ -2853,28 +2818,21 @@ index 0000000..544ad57
+module_exit(intel_qrk_esram_test_exit);
diff --git a/drivers/platform/x86/quark/intel_qrk_esram_test.h b/drivers/platform/x86/quark/intel_qrk_esram_test.h
new file mode 100644
-index 0000000..35ad2d8
+index 0000000..5adf7ca
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_esram_test.h
-@@ -0,0 +1,43 @@
+@@ -0,0 +1,36 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/**
+ * intel_qrk_esram_test.h
@@ -2902,28 +2860,21 @@ index 0000000..35ad2d8
+
diff --git a/drivers/platform/x86/quark/intel_qrk_imr.c b/drivers/platform/x86/quark/intel_qrk_imr.c
new file mode 100644
-index 0000000..8865307
+index 0000000..fcae59a
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_imr.c
-@@ -0,0 +1,697 @@
+@@ -0,0 +1,690 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark IMR driver
@@ -3605,28 +3556,21 @@ index 0000000..8865307
+
diff --git a/drivers/platform/x86/quark/intel_qrk_imr.h b/drivers/platform/x86/quark/intel_qrk_imr.h
new file mode 100644
-index 0000000..9f16c61
+index 0000000..a6f4730
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_imr.h
-@@ -0,0 +1,157 @@
+@@ -0,0 +1,150 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark IMR driver
@@ -3768,28 +3712,21 @@ index 0000000..9f16c61
+#endif
diff --git a/drivers/platform/x86/quark/intel_qrk_imr_kernel.c b/drivers/platform/x86/quark/intel_qrk_imr_kernel.c
new file mode 100644
-index 0000000..fdfaea3
+index 0000000..1cf922d
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_imr_kernel.c
-@@ -0,0 +1,139 @@
+@@ -0,0 +1,132 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark IMR driver
@@ -3913,28 +3850,21 @@ index 0000000..fdfaea3
+module_exit(intel_qrk_imr_runt_exit);
diff --git a/drivers/platform/x86/quark/intel_qrk_imr_test.c b/drivers/platform/x86/quark/intel_qrk_imr_test.c
new file mode 100644
-index 0000000..4f2096a
+index 0000000..549bb61
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_imr_test.c
-@@ -0,0 +1,357 @@
+@@ -0,0 +1,350 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark IMR Test module
@@ -4276,28 +4206,21 @@ index 0000000..4f2096a
+
diff --git a/drivers/platform/x86/quark/intel_qrk_plat_clanton_hill.c b/drivers/platform/x86/quark/intel_qrk_plat_clanton_hill.c
new file mode 100644
-index 0000000..3c489e8
+index 0000000..baa277c
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_plat_clanton_hill.c
-@@ -0,0 +1,226 @@
+@@ -0,0 +1,219 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark Legacy Platform Data Layout.conf accessor
@@ -4508,28 +4431,21 @@ index 0000000..3c489e8
+
diff --git a/drivers/platform/x86/quark/intel_qrk_plat_clanton_peak.c b/drivers/platform/x86/quark/intel_qrk_plat_clanton_peak.c
new file mode 100644
-index 0000000..9edcef7
+index 0000000..b0a8255
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_plat_clanton_peak.c
-@@ -0,0 +1,227 @@
+@@ -0,0 +1,220 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Clanton Peak board entry point
@@ -4741,28 +4657,21 @@ index 0000000..9edcef7
+MODULE_ALIAS("platform:"DRIVER_NAME);
diff --git a/drivers/platform/x86/quark/intel_qrk_plat_cross_hill.c b/drivers/platform/x86/quark/intel_qrk_plat_cross_hill.c
new file mode 100644
-index 0000000..eb1960a
+index 0000000..74cb09f
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_plat_cross_hill.c
-@@ -0,0 +1,392 @@
+@@ -0,0 +1,430 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * CrossHill board entry point
@@ -4791,10 +4700,28 @@ index 0000000..eb1960a
+#define SPI_BPEAK_ID2_GPIO 15
+#define SPI_BPEAK_ID3_GPIO 14
+
++/*
++ * GPIO number for eADC interrupt (MAX78M6610+LMU)
++ */
++#define GPIO_78M6610_INT 2
++
+static int nc_gpio_reg;
+static int sc_gpio_reg;
+
+static int cross_hill_probe;
++/*
++ * GPIOs used as interrupts by MAX78M6610+LMU eADC
++ *
++ * Extend this array adding new elements at the end.
++ */
++static struct gpio crh_eadc_int_gpios[] = {
++ {
++ GPIO_78M6610_INT,
++ GPIOF_IN,
++ "max78m6610-int"
++ },
++};
++
+
+/*
+ * Blackburn Peak SPI daughterboard ID values
@@ -4872,6 +4799,7 @@ index 0000000..eb1960a
+
+};
+
++/* For compatibility reason, new SPI energy modules must be added at the end */
+static struct spi_board_info spi_energy_adc_devs[] = {
+ {
+ .modalias = "max78m6610_lmu",
@@ -4881,6 +4809,7 @@ index 0000000..eb1960a
+ .bus_num = 1,
+ .chip_select = 0,
+ .controller_data = &qrk_ffrd_spi_1_cs_0,
++ .irq = -1,
+ },
+};
+
@@ -5004,8 +4933,33 @@ index 0000000..eb1960a
+
+ case QRK_SPI_BPEAK_ID_ADC_MAXIM:
+ {
-+ return spi_register_board_info(spi_energy_adc_devs,
++ ret = gpio_request_array(crh_eadc_int_gpios,
++ ARRAY_SIZE(crh_eadc_int_gpios));
++ if (ret) {
++ pr_err("%s: Failed to allocate eADC interrupt GPIO pins!\n",
++ __func__);
++ return ret;
++ }
++ ret = gpio_to_irq(GPIO_78M6610_INT);
++ if (ret < 0) {
++ pr_err("%s: Failed to request IRQ for GPIO %u!\n",
++ __func__, GPIO_78M6610_INT);
++ goto error_gpio_free;
++ }
++ spi_energy_adc_devs[0].irq = ret;
++ ret = spi_register_board_info(spi_energy_adc_devs,
+ ARRAY_SIZE(spi_energy_adc_devs));
++ if (ret) {
++ pr_err("%s: Failed to register eADC module!\n",
++ __func__);
++ goto error_gpio_free;
++ }
++ return 0;
++error_gpio_free:
++ gpio_free_array(crh_eadc_int_gpios,
++ ARRAY_SIZE(crh_eadc_int_gpios));
++ spi_energy_adc_devs[0].irq = -1;
++ return ret;
+ }
+ case QRK_SPI_BPEAK_ID_ZB_EXEGIN_ATMEL:
+ {
@@ -5139,28 +5093,21 @@ index 0000000..eb1960a
+
diff --git a/drivers/platform/x86/quark/intel_qrk_plat_galileo.c b/drivers/platform/x86/quark/intel_qrk_plat_galileo.c
new file mode 100644
-index 0000000..0df0ac0
+index 0000000..a45f6a0
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_plat_galileo.c
-@@ -0,0 +1,398 @@
+@@ -0,0 +1,391 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark Legacy Platform Data Layout.conf accessor
@@ -5541,30 +5488,421 @@ index 0000000..0df0ac0
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
-diff --git a/drivers/platform/x86/quark/intel_qrk_plat_kips_bay.c b/drivers/platform/x86/quark/intel_qrk_plat_kips_bay.c
+diff --git a/drivers/platform/x86/quark/intel_qrk_plat_galileo_gen2.c b/drivers/platform/x86/quark/intel_qrk_plat_galileo_gen2.c
new file mode 100644
-index 0000000..5e94b4b
+index 0000000..7c09add
--- /dev/null
-+++ b/drivers/platform/x86/quark/intel_qrk_plat_kips_bay.c
-@@ -0,0 +1,176 @@
++++ b/drivers/platform/x86/quark/intel_qrk_plat_galileo_gen2.c
+@@ -0,0 +1,392 @@
+/*
++ * Intel Quark Legacy Platform Data Layout.conf accessor
++ *
++ * Simple Legacy SPI flash access layer
++ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
++ * This program is distributed in the hope 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.
++ * Author : Bryan O'Donoghue <bryan.odonoghue@linux.intel.com> 2013
++ */
++
++#include <linux/errno.h>
++#include <linux/gpio.h>
++#include <linux/i2c.h>
++#include <linux/i2c/at24.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/module.h>
++#include <linux/mfd/intel_qrk_gip_pdata.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++#include <linux/printk.h>
++#include <linux/spi/pxa2xx_spi.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/flash.h>
++#include <linux/i2c/pca953x.h>
++
++#define DRIVER_NAME "GalileoGen2"
++#define GPIO_RESTRICT_NAME "qrk-gpio-restrict-sc"
++#define LPC_SCH_SPINAME "spi-lpc-sch"
++
++#define GPIO_PCAL9555A_EXP2_INT 9
++
++/* Option to allow GPIO 10 to be used for SPI1 chip-select */
++static int gpio_cs;
++
++module_param(gpio_cs, int, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(gpio_cs, "Enable GPIO chip-select for SPI channel 1");
++
++/* Galileo Gen2 boards require i2c master to operate @400kHz 'fast mode' */
++static struct intel_qrk_gip_pdata gip_pdata = {
++ .i2c_std_mode = 0,
++};
++static struct intel_qrk_gip_pdata *galileo_gen2_gip_get_pdata(void)
++{
++ return &gip_pdata;
++}
++
++/******************************************************************************
++ * Texas Instruments ADC1x8S102 SPI Device Platform Data
++ ******************************************************************************/
++#include "linux/platform_data/adc1x8s102.h"
++
++/* Maximum input voltage allowed for each ADC input, in milliVolts */
++#define ADC1x8S102_MAX_EXT_VIN 5000
++
++static const struct adc1x8s102_platform_data adc1x8s102_platform_data = {
++ .ext_vin = ADC1x8S102_MAX_EXT_VIN
++};
++
++#include "linux/i2c/pca953x.h"
++#define PCAL9555A_GPIO_BASE_OFFSET 16
++
++static struct pca953x_platform_data pcal9555a_platform_data_exp0 = {
++ .gpio_base = PCAL9555A_GPIO_BASE_OFFSET,
++ .irq_base = -1,
++};
++
++static struct pca953x_platform_data pcal9555a_platform_data_exp1 = {
++ .gpio_base = PCAL9555A_GPIO_BASE_OFFSET + 16,
++ .irq_base = -1,
++};
++
++static struct pca953x_platform_data pcal9555a_platform_data_exp2 = {
++ .gpio_base = PCAL9555A_GPIO_BASE_OFFSET + 32,
++};
++
++#include "linux/platform_data/pca9685.h"
++
++static struct pca9685_pdata pca9685_platform_data = {
++ .chan_mapping = {
++ PWM_CH_GPIO, PWM_CH_PWM,
++ PWM_CH_GPIO, PWM_CH_PWM,
++ PWM_CH_GPIO, PWM_CH_PWM,
++ PWM_CH_GPIO, PWM_CH_PWM,
++ PWM_CH_GPIO, PWM_CH_PWM,
++ PWM_CH_GPIO, PWM_CH_PWM,
++ PWM_CH_GPIO, PWM_CH_GPIO,
++ PWM_CH_GPIO, PWM_CH_GPIO,
++ PWM_CH_DISABLED /* ALL_LED disabled */
++ },
++ .gpio_base = PCAL9555A_GPIO_BASE_OFFSET + 48,
++};
++
++/******************************************************************************
++ * Intel Galileo Gen2 i2c clients
++ ******************************************************************************/
++#define EEPROM_ADDR 0x54
++#define PCAL9555A_EXP0_ADDR 0x25
++#define PCAL9555A_EXP1_ADDR 0x26
++#define PCAL9555A_EXP2_ADDR 0x27
++#define PCA9685_ADDR 0x47
++
++static struct i2c_board_info probed_i2c_eeprom;
++static struct i2c_board_info probed_i2c_pcal9555a_exp0 = {
++ .platform_data = &pcal9555a_platform_data_exp0,
++};
++static struct i2c_board_info probed_i2c_pcal9555a_exp1 = {
++ .platform_data = &pcal9555a_platform_data_exp1,
++};
++static struct i2c_board_info probed_i2c_pcal9555a_exp2 = {
++ .platform_data = &pcal9555a_platform_data_exp2,
++};
++static struct i2c_board_info probed_i2c_pca9685 = {
++ .platform_data = &pca9685_platform_data,
++};
++
++static const unsigned short eeprom_i2c_addr[] = {
++ EEPROM_ADDR, I2C_CLIENT_END
++};
++static const unsigned short pcal9555a_exp0_i2c_addr[] = {
++ PCAL9555A_EXP0_ADDR, I2C_CLIENT_END
++};
++static const unsigned short pcal9555a_exp1_i2c_addr[] = {
++ PCAL9555A_EXP1_ADDR, I2C_CLIENT_END
++};
++static const unsigned short pcal9555a_exp2_i2c_addr[] = {
++ PCAL9555A_EXP2_ADDR, I2C_CLIENT_END
++};
++static const unsigned short pca9685_i2c_addr[] = {
++ PCA9685_ADDR, I2C_CLIENT_END
++};
++
++static int i2c_probe(struct i2c_adapter *adap, unsigned short addr)
++{
++ /* Always return success: the I2C clients are already known. */
++ return 1;
++}
++
++/******************************************************************************
++ * Intel Quark SPI Controller Data
++ ******************************************************************************/
++static struct pxa2xx_spi_chip qrk_ffrd_spi_0_cs_0 = {
++ .gpio_cs = 8,
++};
++
++static struct pxa2xx_spi_chip qrk_ffrd_spi_1_cs_0 = {
++ .gpio_cs = 10,
++};
++
++#define LPC_SCH_SPI_BUS_ID 0x03
++
++/* TODO: extract this data from layout.conf encoded in flash */
++struct mtd_partition galileo_gen2_ilb_partitions[] = {
++ {
++ .name = "grub",
++ .size = 4096,
++ .offset = 0,
++ },
++ {
++ .name = "grub.conf",
++ .size = 0xA00,
++ .offset = 0x50500,
++ },
++ {
++ .name = "layout.conf",
++ .size = 4096,
++ .offset = 0x708000,
++ },
++ {
++ .name = "sketch",
++ .size = 0x40000,
++ .offset = 0x750000,
++ },
++ {
++ .name = "raw",
++ .size = 8192000,
++ .offset = 0,
++
++ },
++};
++
++static struct flash_platform_data ilb_flash = {
++ .type = "s25fl064k",
++ .parts = galileo_gen2_ilb_partitions,
++ .nr_parts = ARRAY_SIZE(galileo_gen2_ilb_partitions),
++};
++
++static struct spi_board_info spi0_onboard_devs[] = {
++ {
++ .modalias = "m25p80",
++ .platform_data = &ilb_flash,
++ .bus_num = LPC_SCH_SPI_BUS_ID,
++ .chip_select = 0,
++ },
++ {
++ .modalias = "adc1x8s102",
++ .max_speed_hz = 16667000,
++ .platform_data = &adc1x8s102_platform_data,
++ .mode = SPI_MODE_3,
++ .bus_num = 0,
++ .chip_select = 0,
++ .controller_data = &qrk_ffrd_spi_0_cs_0,
++ },
++};
++
++static struct spi_board_info spi1_onboard_devs_gpiocs[] = {
++ {
++ .modalias = "spidev",
++ .chip_select = 0,
++ .controller_data = NULL,
++ .max_speed_hz = 50000000,
++ .bus_num = 1,
++ .controller_data = &qrk_ffrd_spi_1_cs_0,
++ },
++};
++
++static struct spi_board_info spi1_onboard_devs[] = {
++ {
++ .modalias = "spidev",
++ .chip_select = 0,
++ .controller_data = NULL,
++ .max_speed_hz = 50000000,
++ .bus_num = 1,
++ },
++};
++
++
++/**
++ * intel_qrk_spi_add_onboard_devs
++ *
++ * @return 0 on success or standard errnos on failure
++ *
++ * Registers onboard SPI device(s) present on the Izmir platform
++ */
++static int intel_qrk_spi_add_onboard_devs(void)
++{
++ int ret = 0;
++
++ ret = spi_register_board_info(spi0_onboard_devs,
++ ARRAY_SIZE(spi0_onboard_devs));
++ if (ret)
++ return ret;
++
++ if (gpio_cs)
++ return spi_register_board_info(spi1_onboard_devs_gpiocs,
++ ARRAY_SIZE(spi1_onboard_devs_gpiocs));
++ else
++ return spi_register_board_info(spi1_onboard_devs,
++ ARRAY_SIZE(spi1_onboard_devs));
++}
++
++
++static struct gpio reserved_gpios[] = {
++ {
++ GPIO_PCAL9555A_EXP2_INT,
++ GPIOF_IN,
++ "pcal9555a-exp2-int",
++ },
++};
++
++/**
++ * intel_qrk_gpio_restrict_probe
++ *
++ * Make GPIOs pertaining to Firmware inaccessible by requesting them. The
++ * GPIOs are never released nor accessed by this driver.
++ *
++ * Registers devices which are dependent on this GPIO driver
++ */
++static int intel_qrk_gpio_restrict_probe(struct platform_device *pdev)
++{
++ int ret = 0;
++ struct i2c_adapter *i2c_adap = NULL;
++ struct i2c_client *client = NULL;
++
++ /* Need to tell the PCA953X driver which GPIO IRQ to use for signalling
++ * interrupts. We can't get the IRQ until the GPIO driver is loaded.
++ * Hence, we defer registration of the I2C devices until now
++ */
++ i2c_adap = i2c_get_adapter(0);
++ if (NULL == i2c_adap) {
++ pr_info("%s: i2c adapter not ready yet. Deferring..\n",
++ __func__);
++ return -EPROBE_DEFER;
++ }
++
++ ret = gpio_request_array(reserved_gpios, ARRAY_SIZE(reserved_gpios));
++ if (ret) {
++ dev_err(&client->dev, "failed to request reserved gpios\n");
++ goto end;
++ }
++
++ strlcpy(probed_i2c_eeprom.type, "24c08", I2C_NAME_SIZE);
++ client = i2c_new_probed_device(i2c_adap, &probed_i2c_eeprom,
++ eeprom_i2c_addr, i2c_probe);
++ if (client == NULL) {
++ pr_err("%s: Failed to probe 24c08 I2C device\n", __func__);
++ ret = -ENODEV;
++ goto end;
++ }
++
++ strlcpy(probed_i2c_pcal9555a_exp0.type, "pcal9555a", I2C_NAME_SIZE);
++ client = i2c_new_probed_device(i2c_adap, &probed_i2c_pcal9555a_exp0,
++ pcal9555a_exp0_i2c_addr, i2c_probe);
++ if (client == NULL) {
++ pr_err("%s: Failed to probe pcal9555a I2C device\n", __func__);
++ ret = -ENODEV;
++ goto end;
++ }
++
++ strlcpy(probed_i2c_pcal9555a_exp1.type, "pcal9555a", I2C_NAME_SIZE);
++ client = i2c_new_probed_device(i2c_adap, &probed_i2c_pcal9555a_exp1,
++ pcal9555a_exp1_i2c_addr, i2c_probe);
++ if (client == NULL) {
++ pr_err("%s: Failed to probe pcal9555a I2C device\n", __func__);
++ ret = -ENODEV;
++ goto end;
++ }
++
++ strlcpy(probed_i2c_pcal9555a_exp2.type, "pcal9555a", I2C_NAME_SIZE);
++ probed_i2c_pcal9555a_exp2.irq = gpio_to_irq(GPIO_PCAL9555A_EXP2_INT);
++ client = i2c_new_probed_device(i2c_adap, &probed_i2c_pcal9555a_exp2,
++ pcal9555a_exp2_i2c_addr, i2c_probe);
++ if (client == NULL) {
++ pr_err("%s: Failed to probe pcal9555a I2C device\n", __func__);
++ ret = -ENODEV;
++ goto end;
++ }
++
++ strlcpy(probed_i2c_pca9685.type, "pca9685", I2C_NAME_SIZE);
++ client = i2c_new_probed_device(i2c_adap, &probed_i2c_pca9685,
++ pca9685_i2c_addr, i2c_probe);
++ if (client == NULL) {
++ pr_err("%s: Failed to probe pca9685 I2C device\n", __func__);
++ ret = -ENODEV;
++ goto end;
++ }
++
++ ret = intel_qrk_spi_add_onboard_devs();
++
++end:
++ i2c_put_adapter(i2c_adap);
++
++ return ret;
++}
++
++static struct platform_driver gpio_restrict_pdriver = {
++ .driver = {
++ .name = GPIO_RESTRICT_NAME,
++ .owner = THIS_MODULE,
++ },
++ .probe = intel_qrk_gpio_restrict_probe,
++};
++
++static int intel_qrk_plat_galileo_gen2_probe(struct platform_device *pdev)
++{
++ /* Assign GIP driver handle for board-specific settings */
++ intel_qrk_gip_get_pdata = galileo_gen2_gip_get_pdata;
++
++ /* gpio */
++ return platform_driver_register(&gpio_restrict_pdriver);
++}
++
++static int intel_qrk_plat_galileo_gen2_remove(struct platform_device *pdev)
++{
++ return 0;
++}
++
++static struct platform_driver qrk_galileo_driver = {
++ .driver = {
++ .name = DRIVER_NAME,
++ .owner = THIS_MODULE,
++ },
++ .probe = intel_qrk_plat_galileo_gen2_probe,
++ .remove = intel_qrk_plat_galileo_gen2_remove,
++};
++
++module_platform_driver(qrk_galileo_driver);
++
++MODULE_AUTHOR("Bryan O'Donoghue <bryan.odonoghue@intel.com>");
++MODULE_DESCRIPTION("Galileo Gen2 BSP Data");
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_ALIAS("platform:"DRIVER_NAME);
+diff --git a/drivers/platform/x86/quark/intel_qrk_plat_kips_bay.c b/drivers/platform/x86/quark/intel_qrk_plat_kips_bay.c
+new file mode 100644
+index 0000000..7a33d36
+--- /dev/null
++++ b/drivers/platform/x86/quark/intel_qrk_plat_kips_bay.c
+@@ -0,0 +1,169 @@
++/*
++ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark Legacy Platform Data Layout.conf accessor
@@ -5725,28 +6063,21 @@ index 0000000..5e94b4b
+
diff --git a/drivers/platform/x86/quark/intel_qrk_sb.c b/drivers/platform/x86/quark/intel_qrk_sb.c
new file mode 100644
-index 0000000..658c41f
+index 0000000..17e4ddd
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_sb.c
-@@ -0,0 +1,253 @@
+@@ -0,0 +1,246 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark side-band driver
@@ -5984,28 +6315,21 @@ index 0000000..658c41f
+subsys_initcall(intel_qrk_sb_init);
diff --git a/drivers/platform/x86/quark/intel_qrk_thermal.c b/drivers/platform/x86/quark/intel_qrk_thermal.c
new file mode 100644
-index 0000000..d603d8b
+index 0000000..189bb5c
--- /dev/null
+++ b/drivers/platform/x86/quark/intel_qrk_thermal.c
-@@ -0,0 +1,360 @@
+@@ -0,0 +1,353 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark Thermal driver
@@ -6350,28 +6674,21 @@ index 0000000..d603d8b
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/include/linux/intel_qrk_sb.h b/include/linux/intel_qrk_sb.h
new file mode 100644
-index 0000000..65d9b5e
+index 0000000..4290070
--- /dev/null
+++ b/include/linux/intel_qrk_sb.h
-@@ -0,0 +1,92 @@
+@@ -0,0 +1,85 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark side-band driver
@@ -6448,28 +6765,21 @@ index 0000000..65d9b5e
+#endif /* __INTEL_QRK_SB_H__ */
diff --git a/include/linux/platform_data/quark.h b/include/linux/platform_data/quark.h
new file mode 100644
-index 0000000..85f5508
+index 0000000..e9b2d55d
--- /dev/null
+++ b/include/linux/platform_data/quark.h
-@@ -0,0 +1,44 @@
+@@ -0,0 +1,37 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark platform data definition
@@ -6496,6 +6806,3 @@ index 0000000..85f5508
+}plat_dataid_t;
+
+#endif /* _PDATA_QUARK_H */
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0008-Quark-UART-quark.patch b/recipes-kernel/linux/files/0008-Quark-UART-quark.patch
index 15b0ffd..336e171 100644
--- a/recipes-kernel/linux/files/0008-Quark-UART-quark.patch
+++ b/recipes-kernel/linux/files/0008-Quark-UART-quark.patch
@@ -1,6 +1,6 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Bryan O'Donoghue <bryan.odonoghue@intel.com>
-Date: Thu, 13 Feb 2014 13:03:44 +0000
+Date: Thu, 24 Apr 2014 13:32:03 +0100
Subject: [PATCH 08/21] Quark UART
---
@@ -8,23 +8,23 @@ Subject: [PATCH 08/21] Quark UART
drivers/dma/Makefile | 1 +
drivers/dma/intel_mid_dma.c | 1460 -----------------------
drivers/dma/intel_mid_dma/Makefile | 3 +
- drivers/dma/intel_mid_dma_core.c | 1295 +++++++++++++++++++++
- drivers/dma/intel_mid_dma_pci.c | 290 +++++
- drivers/dma/intel_mid_dma_regs.h | 107 +--
- drivers/dma/intel_qrk_dma_pci.c | 155 +++
+ drivers/dma/intel_mid_dma_core.c | 1336 ++++++++++++++++++++++
+ drivers/dma/intel_mid_dma_pci.c | 292 +++++
+ drivers/dma/intel_mid_dma_regs.h | 109 +-
+ drivers/dma/intel_qrk_dma_pci.c | 147 +++
drivers/tty/serial/8250/8250.c | 53 +
drivers/tty/serial/8250/8250_pci.c | 52 +-
drivers/tty/serial/Kconfig | 20 +
drivers/tty/serial/Makefile | 1 +
- drivers/tty/serial/intel_quark_uart.c | 2032 +++++++++++++++++++++++++++++++++
- include/linux/intel_mid_dma.h | 186 +++
- 14 files changed, 4099 insertions(+), 1562 deletions(-)
+ drivers/tty/serial/intel_quark_uart.c | 2034 +++++++++++++++++++++++++++++++++
+ include/linux/intel_mid_dma.h | 189 +++
+ 14 files changed, 4147 insertions(+), 1556 deletions(-)
delete mode 100644 drivers/dma/intel_mid_dma.c
create mode 100644 drivers/dma/intel_mid_dma/Makefile
create mode 100644 drivers/dma/intel_mid_dma_core.c
create mode 100644 drivers/dma/intel_mid_dma_pci.c
create mode 100644 drivers/dma/intel_qrk_dma_pci.c
- create mode 100644 drivers/tty/serial/intel_quark_uart.c
+ create mode 100755 drivers/tty/serial/intel_quark_uart.c
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d4c1218..9867547 100644
@@ -1536,10 +1536,10 @@ index 0000000..6ec8b97
+
diff --git a/drivers/dma/intel_mid_dma_core.c b/drivers/dma/intel_mid_dma_core.c
new file mode 100644
-index 0000000..aeb7fd3
+index 0000000..b869d6c
--- /dev/null
+++ b/drivers/dma/intel_mid_dma_core.c
-@@ -0,0 +1,1295 @@
+@@ -0,0 +1,1336 @@
+/*
+ * intel_mid_dma_core.c - Intel Langwell DMA Drivers
+ *
@@ -1585,13 +1585,6 @@ index 0000000..aeb7fd3
+#define LNW_PERIPHRAL_STATUS 0x0
+#define LNW_PERIPHRAL_MASK 0x8
+
-+#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask) \
-+ ((kernel_ulong_t)&(struct intel_mid_dma_probe_info) { \
-+ .max_chan = (_max_chan), \
-+ .ch_base = (_ch_base), \
-+ .block_size = (_block_size), \
-+ .pimr_mask = (_pimr_mask), \
-+ })
+
+/*****************************************************************************
+Utility Functions*/
@@ -1677,7 +1670,7 @@ index 0000000..aeb7fd3
+ *
+ * UnMasks the DMA periphral interrupt,
+ * this is valid for DMAC1 family controllers only
-+ * This controller should have periphral mask registers already mapped
++ * This controller should have peripheral mask registers already mapped
+ */
+void dmac1_unmask_periphral_intr(struct intel_mid_dma_chan *midc)
+{
@@ -1770,6 +1763,7 @@ index 0000000..aeb7fd3
+ spin_unlock_bh(&midc->lock);
+ }
+}
++
+/**
+ * midc_dostart - begin a DMA transaction
+ * @midc: channel for which txn is to be started
@@ -1790,8 +1784,9 @@ index 0000000..aeb7fd3
+ /* The tasklet will hopefully advance the queue... */
+ return;
+ }
-+ midc->busy = true;
++
+ /*write registers and en*/
++ midc->busy = true;
+ iowrite32(first->sar, midc->ch_regs + SAR);
+ iowrite32(first->dar, midc->ch_regs + DAR);
+ iowrite32(first->lli_phys, midc->ch_regs + LLP);
@@ -1828,7 +1823,6 @@ index 0000000..aeb7fd3
+ dma_cookie_complete(txd);
+ callback_txd = txd->callback;
+ param_txd = txd->callback_param;
-+
+ if (desc->lli != NULL) {
+ /*clear the DONE bit of completed LLI in memory*/
+ llitem = desc->lli + desc->current_lli;
@@ -1857,6 +1851,7 @@ index 0000000..aeb7fd3
+ spin_lock_bh(&midc->lock);
+
+}
++
+/**
+ * midc_scan_descriptors - check the descriptors in channel
+ * mark completed when tx is completete
@@ -1877,7 +1872,8 @@ index 0000000..aeb7fd3
+ midc_descriptor_complete(midc, desc);
+ }
+ return;
-+ }
++}
++
+/**
+ * midc_lli_fill_sg - Helper function to convert
+ * SG list to Linked List Items.
@@ -1923,7 +1919,7 @@ index 0000000..aeb7fd3
+ pr_debug("MDMA: LLI is configured in circular mode\n");
+ lli_next = desc->lli_phys;
+ } else {
-+ lli_next = 0;
++ lli_next = (dma_addr_t)lli_bloc_desc; /* Needs to be !0 */
+ ctl_lo.ctlx.llp_dst_en = 0;
+ ctl_lo.ctlx.llp_src_en = 0;
+ }
@@ -1941,11 +1937,10 @@ index 0000000..aeb7fd3
+ lli_bloc_desc->sar = mids->dma_slave.src_addr;
+ lli_bloc_desc->dar = sg_phy_addr;
+ }
-+ /*Copy values into block descriptor in system memroy*/
++ /*Copy values into block descriptor in system memory*/
+ lli_bloc_desc->llp = lli_next;
+ lli_bloc_desc->ctl_lo = ctl_lo.ctl_lo;
+ lli_bloc_desc->ctl_hi = ctl_hi.ctl_hi;
-+
+ lli_bloc_desc++;
+ }
+ /*Copy very first LLI values to descriptor*/
@@ -2094,7 +2089,6 @@ index 0000000..aeb7fd3
+ return 0;
+}
+
-+
+/**
+ * intel_mid_dma_prep_memcpy - Prep memcpy txn
+ * @chan: chan for DMA transfer
@@ -2131,11 +2125,11 @@ index 0000000..aeb7fd3
+ mids = midc->mid_slave;
+ BUG_ON(!mids);
+
-+ pr_debug("MDMA:called for DMA %x CH %d Length %zu\n",
-+ midc->dma->pci_id, midc->ch_id, len);
-+ pr_debug("MDMA:Cfg passed Mode %x, Dirn %x, HS %x, Width %x\n",
++ pr_debug("MDMA:called for DMA %x CH %d Length %zu src_addr 0x%08x dst 0x%08x\n",
++ midc->dma->pci_id, midc->ch_id, len, (u32)src, (u32)dest);
++ pr_debug("MDMA:Cfg passed Mode %x, Dirn %d, Handshake %s, Width %x\n",
+ mids->cfg_mode, mids->dma_slave.direction,
-+ mids->hs_mode, mids->dma_slave.src_addr_width);
++ mids->hs_mode == LNW_DMA_HW_HS ? "hardware" : "software" , mids->dma_slave.src_addr_width);
+
+ /*calculate CFG_LO*/
+ if (mids->hs_mode == LNW_DMA_SW_HS) {
@@ -2171,6 +2165,13 @@ index 0000000..aeb7fd3
+ cfg_hi.cfgx.protctl = 0x1; /*default value*/
+ cfg_hi.cfgx.src_per = cfg_hi.cfgx.dst_per =
+ midc->ch_id - midc->dma->chan_base;
++ /* Quark - set polarity active low - make a param */
++ if(midc->dma->is_quark){
++ cfg_lo.cfgx.dst_hs_pol = 0x1;
++ cfg_lo.cfgx.src_hs_pol = 0x1;
++ cfg_lo.cfgx.hs_sel_dst = 0x00;
++ cfg_lo.cfgx.hs_sel_src = 0x01;
++ }
+ }
+ }
+
@@ -2180,13 +2181,18 @@ index 0000000..aeb7fd3
+ width = mids->dma_slave.src_addr_width;
+
+ ctl_hi.ctlx.block_ts = get_block_ts(len, width, midc->dma->block_size);
-+ pr_debug("MDMA:calc len %d for block size %d\n",
++ pr_debug("MDMA:calc len (block_ts) %d for block size %d\n",
+ ctl_hi.ctlx.block_ts, midc->dma->block_size);
+ /*calculate CTL_LO*/
+ ctl_lo.ctl_lo = 0;
+ ctl_lo.ctlx.int_en = 1;
-+ ctl_lo.ctlx.dst_msize = mids->dma_slave.src_maxburst;
-+ ctl_lo.ctlx.src_msize = mids->dma_slave.dst_maxburst;
++ /* Note Quark: original driver inverted these two values - need to
++ * resolve before integration - have we missed a trick ? */
++ ctl_lo.ctlx.dst_msize = mids->dma_slave.dst_maxburst;
++ ctl_lo.ctlx.src_msize = mids->dma_slave.src_maxburst;
++ pr_debug("MDMA:Cfg dst_msize 0x%x src_msize 0x%x\n", ctl_lo.ctlx.src_msize, ctl_lo.ctlx.dst_msize);
++ pr_debug("MDMA:Cfg mids->dma_slave.dst_maxburst 0x%x mids->dma_slave.src_maxburst 0x%x\n", mids->dma_slave.src_maxburst,
++mids->dma_slave.dst_maxburst);
+
+ /*
+ * Here we need some translation from "enum dma_slave_buswidth"
@@ -2215,9 +2221,8 @@ index 0000000..aeb7fd3
+ }
+ }
+
-+ pr_debug("MDMA:Calc CTL LO %x, CTL HI %x, CFG LO %x, CFG HI %x\n",
++ pr_debug("MDMA:Calc CTL LO 0x%x, CTL HI 0x%x, CFG LO 0x%x CFG HI 0x%x\n",
+ ctl_lo.ctl_lo, ctl_hi.ctl_hi, cfg_lo.cfg_lo, cfg_hi.cfg_hi);
-+
+ enable_dma_interrupt(midc);
+
+ desc = midc_desc_get(midc);
@@ -2276,7 +2281,7 @@ index 0000000..aeb7fd3
+ mids = midc->mid_slave;
+ BUG_ON(!mids);
+
-+ if (!midc->dma->pimr_mask) {
++ if (!midc->dma->is_quark && !midc->dma->pimr_mask) {
+ /* We can still handle sg list with only one item */
+ if (sg_len == 1) {
+ txd = intel_mid_dma_prep_memcpy(chan,
@@ -2294,7 +2299,8 @@ index 0000000..aeb7fd3
+ pr_debug("MDMA: SG Length = %d, direction = %d, Flags = %#lx\n",
+ sg_len, direction, flags);
+
-+ txd = intel_mid_dma_prep_memcpy(chan, 0, 0, sg_dma_len(sgl), flags);
++ txd = intel_mid_dma_prep_memcpy(chan, mids->dma_slave.dst_addr,
++ mids->dma_slave.src_addr, sg_dma_len(sgl), flags);
+ if (NULL == txd) {
+ pr_err("MDMA: Prep memcpy failed\n");
+ return NULL;
@@ -2553,23 +2559,21 @@ index 0000000..aeb7fd3
+irqreturn_t intel_mid_dma_interrupt(int irq, void *data)
+{
+ struct middma_device *mid = data;
-+ u32 tfr_status, err_status;
++ u32 tfr_status, err_status, block_status;
+ int call_tasklet = 0;
+
+ tfr_status = ioread32(mid->dma_base + RAW_TFR);
++ block_status = ioread32(mid->dma_base + RAW_BLOCK);
+ err_status = ioread32(mid->dma_base + RAW_ERR);
-+ if (!tfr_status && !err_status)
++ if (!tfr_status && !err_status && !block_status){
+ return IRQ_NONE;
++ }
+
+ /*DMA Interrupt*/
-+#if 0
+ pr_debug("MDMA:Got an interrupt on irq %d\n", irq);
-+ pr_debug("MDMA: Status %x, Mask %x\n", tfr_status, mid->intr_mask);
-+#else
-+ pr_info("MDMA:Got an interrupt on irq %d\n", irq);
-+ pr_info("MDMA: Status %x, Mask %x\n", tfr_status, mid->intr_mask);
++ pr_debug("MDMA: raw_tfr %x, raw_err %x raw_block %x Mask %x\n",
++ tfr_status, err_status, block_status, mid->intr_mask);
+
-+#endif
+ tfr_status &= mid->intr_mask;
+ if (tfr_status) {
+ /*need to disable intr*/
@@ -2586,7 +2590,7 @@ index 0000000..aeb7fd3
+ }
+ if (call_tasklet)
+ tasklet_schedule(&mid->tasklet);
-+
++
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(intel_mid_dma_interrupt);
@@ -2763,7 +2767,9 @@ index 0000000..aeb7fd3
+* @state: PM message
+*
+* This function is called by OS when a power event occurs
++* TBD in 1.1 release
+*/
++#if 0
+static int dma_suspend(struct device *dev)
+{
+ struct pci_dev *pci = to_pci_dev(dev);
@@ -2775,15 +2781,18 @@ index 0000000..aeb7fd3
+ if (device->ch[i].in_use)
+ return -EAGAIN;
+ }
-+#if 0
-+ dmac1_mask_periphral_intr(device);
-+#endif
++
++ if(!device->is_quark){
++ dmac1_mask_periphral_intr(device);
++ }
++
+ device->state = SUSPENDED;
+ pci_save_state(pci);
+ pci_disable_device(pci);
+ pci_set_power_state(pci, PCI_D3hot);
+ return 0;
+}
++#endif
+
+/**
+* dma_resume - PCI resume function
@@ -2802,6 +2811,16 @@ index 0000000..aeb7fd3
+ return 0;
+}
+
++/*
++* dma_runtime_suspend - PCI suspend function
++*
++* @pci: PCI device structure
++* @state: PM message
++*
++* This function is called by OS when a power event occurs
++* TBD in 1.1 release
++*/
++#if 0
+static int dma_runtime_suspend(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -2810,7 +2829,18 @@ index 0000000..aeb7fd3
+ device->state = SUSPENDED;
+ return 0;
+}
++#endif
+
++/*
++* dma_runtime_resume - PCI suspend function
++*
++* @pci: PCI device structure
++* @state: PM message
++*
++* This function is called by OS when a power event occurs
++* TBD in 1.1 release
++*/
++#if 0
+static int dma_runtime_resume(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -2820,7 +2850,18 @@ index 0000000..aeb7fd3
+ iowrite32(REG_BIT0, device->dma_base + DMA_CFG);
+ return 0;
+}
++#endif
+
++/*
++* dma_runtime_idle - PCI suspend function
++*
++* @pci: PCI device structure
++* @state: PM message
++*
++* This function is called by OS when a power event occurs
++* TBD in 1.1 release
++*/
++#if 0
+static int dma_runtime_idle(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
@@ -2834,13 +2875,13 @@ index 0000000..aeb7fd3
+
+ return pm_schedule_suspend(dev, 0);
+}
-+
++#endif
diff --git a/drivers/dma/intel_mid_dma_pci.c b/drivers/dma/intel_mid_dma_pci.c
new file mode 100644
-index 0000000..bd753b9
+index 0000000..b0d3ab1
--- /dev/null
+++ b/drivers/dma/intel_mid_dma_pci.c
-@@ -0,0 +1,290 @@
+@@ -0,0 +1,292 @@
+/*
+ * intel_mid_dma.c - Intel Langwell DMA Drivers
+ *
@@ -2866,6 +2907,7 @@ index 0000000..bd753b9
+ *
+ *
+ */
++#define DEBUG
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
@@ -2873,19 +2915,19 @@ index 0000000..bd753b9
+#include <linux/module.h>
+
+#include "intel_mid_dma_regs.h"
-+//#include "intel_mid_dma_core.h"
+
+#define INTEL_MID_DMAC1_ID 0x0814
+#define INTEL_MID_DMAC2_ID 0x0813
+#define INTEL_MID_GP_DMAC2_ID 0x0827
+#define INTEL_MFLD_DMAC1_ID 0x0830
+
-+#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask) \
++#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask, _is_quark) \
+ ((kernel_ulong_t)&(struct intel_mid_dma_probe_info) { \
+ .max_chan = (_max_chan), \
+ .ch_base = (_ch_base), \
+ .block_size = (_block_size), \
+ .pimr_mask = (_pimr_mask), \
++ .is_quark = (_is_quark), \
+ })
+
+/**
@@ -2948,6 +2990,7 @@ index 0000000..bd753b9
+ device->chan_base = info->ch_base;
+ device->block_size = info->block_size;
+ device->pimr_mask = info->pimr_mask;
++ device->is_quark = info->is_quark;
+
+ err = mid_setup_dma(pdev, device);
+ if (err)
@@ -3085,10 +3128,10 @@ index 0000000..bd753b9
+* PCI stuff
+*/
+static struct pci_device_id intel_mid_dma_ids[] = {
-+ { PCI_VDEVICE(INTEL, INTEL_MID_DMAC1_ID), INFO(2, 6, 4095, 0x200020)},
-+ { PCI_VDEVICE(INTEL, INTEL_MID_DMAC2_ID), INFO(2, 0, 2047, 0)},
-+ { PCI_VDEVICE(INTEL, INTEL_MID_GP_DMAC2_ID), INFO(2, 0, 2047, 0)},
-+ { PCI_VDEVICE(INTEL, INTEL_MFLD_DMAC1_ID), INFO(4, 0, 4095, 0x400040)},
++ { PCI_VDEVICE(INTEL, INTEL_MID_DMAC1_ID), INFO(2, 6, 4095, 0x200020, 0)},
++ { PCI_VDEVICE(INTEL, INTEL_MID_DMAC2_ID), INFO(2, 0, 2047, 0, 0)},
++ { PCI_VDEVICE(INTEL, INTEL_MID_GP_DMAC2_ID), INFO(2, 0, 2047, 0, 0)},
++ { PCI_VDEVICE(INTEL, INTEL_MFLD_DMAC1_ID), INFO(4, 0, 4095, 0x400040, 0)},
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, intel_mid_dma_ids);
@@ -3132,7 +3175,7 @@ index 0000000..bd753b9
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION(INTEL_MID_DMA_DRIVER_VERSION);
diff --git a/drivers/dma/intel_mid_dma_regs.h b/drivers/dma/intel_mid_dma_regs.h
-index 17b4219..4b2ba69 100644
+index 17b4219..f3d5597 100644
--- a/drivers/dma/intel_mid_dma_regs.h
+++ b/drivers/dma/intel_mid_dma_regs.h
@@ -27,6 +27,7 @@
@@ -3143,7 +3186,7 @@ index 17b4219..4b2ba69 100644
#include <linux/pci_ids.h>
#define INTEL_MID_DMA_DRIVER_VERSION "1.1.0"
-@@ -158,115 +159,17 @@ union intel_mid_dma_cfg_hi {
+@@ -158,114 +159,29 @@ union intel_mid_dma_cfg_hi {
};
@@ -3237,12 +3280,15 @@ index 17b4219..4b2ba69 100644
- struct list_head desc_node;
- struct dma_async_tx_descriptor txd;
- size_t len;
-- dma_addr_t sar;
-- dma_addr_t dar;
++#if CONFIG_INTEL_QUARK_X1000_SOC
++struct intel_mid_dma_lli {
+ dma_addr_t sar;
+ dma_addr_t dar;
- u32 cfg_hi;
- u32 cfg_lo;
-- u32 ctl_lo;
-- u32 ctl_hi;
++ dma_addr_t llp;
+ u32 ctl_lo;
+ u32 ctl_hi;
- struct pci_pool *lli_pool;
- struct intel_mid_dma_lli *lli;
- dma_addr_t lli_phys;
@@ -3253,13 +3299,24 @@ index 17b4219..4b2ba69 100644
- enum dma_status status;
- enum dma_slave_buswidth width; /*width of DMA txn*/
- enum intel_mid_dma_mode cfg_mode; /*mode configuration*/
--
++ u32 sstatx;
++ u32 dstatx;
++} __attribute__ ((packed));
+
-};
--
++#else
+
struct intel_mid_dma_lli {
dma_addr_t sar;
- dma_addr_t dar;
-@@ -294,6 +197,14 @@ static inline struct intel_mid_dma_slave *to_intel_mid_dma_slave
+@@ -275,6 +191,7 @@ struct intel_mid_dma_lli {
+ u32 ctl_hi;
+ } __attribute__ ((packed));
+
++#endif
+ static inline int test_ch_en(void __iomem *dma, u32 ch_no)
+ {
+ u32 en_reg = ioread32(dma + DMA_CHAN_EN);
+@@ -294,6 +211,14 @@ static inline struct intel_mid_dma_slave *to_intel_mid_dma_slave
}
@@ -3276,28 +3333,21 @@ index 17b4219..4b2ba69 100644
#endif /*__INTEL_MID_DMAC_REGS_H__*/
diff --git a/drivers/dma/intel_qrk_dma_pci.c b/drivers/dma/intel_qrk_dma_pci.c
new file mode 100644
-index 0000000..cbac334
+index 0000000..c826ad7
--- /dev/null
+++ b/drivers/dma/intel_qrk_dma_pci.c
-@@ -0,0 +1,155 @@
+@@ -0,0 +1,147 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+
+/*
@@ -3316,7 +3366,6 @@ index 0000000..cbac334
+#include <linux/intel_mid_dma.h>
+#include <linux/module.h>
+
-+//#include "intel_mid_dma_core.h"
+#include "intel_mid_dma_regs.h"
+
+/**
@@ -3648,11 +3697,11 @@ index df1b998..ccbc063 100644
obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o
obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
diff --git a/drivers/tty/serial/intel_quark_uart.c b/drivers/tty/serial/intel_quark_uart.c
-new file mode 100644
-index 0000000..5c0a01a
+new file mode 100755
+index 0000000..5bb6a00
--- /dev/null
+++ b/drivers/tty/serial/intel_quark_uart.c
-@@ -0,0 +1,2032 @@
+@@ -0,0 +1,2034 @@
+/*
+ *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
+ *Copyright (C) 2014 Intel Corporation.
@@ -3693,6 +3742,9 @@ index 0000000..5c0a01a
+#include <linux/intel_mid_dma.h>
+#include <linux/debugfs.h>
+#include <linux/dmaengine.h>
++#include <linux/spinlock.h>
++#include <linux/wait.h>
++#include <linux/workqueue.h>
+
+enum {
+ QUARK_UART_HANDLED_RX_INT_SHIFT,
@@ -3708,25 +3760,27 @@ index 0000000..5c0a01a
+ QUARK_UART_2LINE,
+};
+
-+#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask) \
++#define INFO(_max_chan, _ch_base, _block_size, _pimr_mask, _is_quark) \
+ ((kernel_ulong_t)&(struct intel_mid_dma_probe_info) { \
+ .max_chan = (_max_chan), \
+ .ch_base = (_ch_base), \
+ .block_size = (_block_size), \
+ .pimr_mask = (_pimr_mask), \
++ .is_quark = (_is_quark), \
+ })
+
+#define QUARK_UART_DRIVER_DEVICE "ttyQRK"
+#define QUARK_UART_FIFO_LEN 16
-+//#define __QRK_DMA_DEBUG /* TODO: remove all code of this type */
-+
++#define QUARK_UART_MAXBURST 0x20
++#define QUARK_FIFO_FASTER_LEN (QUARK_UART_MAXBURST/2)
+/* Set the max number of UART port
-+ * Intel EG20T QUARK: 4 port
-+ * LAPIS Semiconductor ML7213 IOH: 3 port
-+ * LAPIS Semiconductor ML7223 IOH: 2 port
++ * Intel QUARK X1000 : 2 port
+*/
+#define QUARK_UART_NR 2
+
++/* Set the AHB address for DMA transfers */
++#define QUARK_UART_AHB_REG_BASE 0xFFFFF000
++
+#define QUARK_UART_HANDLED_RX_INT (1<<((QUARK_UART_HANDLED_RX_INT_SHIFT)<<1))
+#define QUARK_UART_HANDLED_TX_INT (1<<((QUARK_UART_HANDLED_TX_INT_SHIFT)<<1))
+#define QUARK_UART_HANDLED_RX_ERR_INT (1<<((\
@@ -3737,17 +3791,17 @@ index 0000000..5c0a01a
+
+#define QUARK_UART_HANDLED_LS_INT (1<<((QUARK_UART_HANDLED_LS_INT_SHIFT)<<1))
+
-+#define QUARK_UART_RBR 0x00
-+#define QUARK_UART_THR 0x00
++#define QUARK_UART_RBR 0x00
++#define QUARK_UART_THR 0x00
+
-+#define QUARK_UART_IER_MASK (QUARK_UART_IER_ERBFI|QUARK_UART_IER_ETBEI|\
-+ QUARK_UART_IER_ELSI|QUARK_UART_IER_EDSSI)
-+#define QUARK_UART_IER_ERBFI 0x00000001
-+#define QUARK_UART_IER_ETBEI 0x00000002
-+#define QUARK_UART_IER_ELSI 0x00000004
-+#define QUARK_UART_IER_EDSSI 0x00000008
++#define QUARK_UART_IER_MASK (QUARK_UART_IER_ERBFI|QUARK_UART_IER_ETBEI|\
++ QUARK_UART_IER_ELSI|QUARK_UART_IER_EDSSI)
++#define QUARK_UART_IER_ERBFI 0x00000001
++#define QUARK_UART_IER_ETBEI 0x00000002
++#define QUARK_UART_IER_ELSI 0x00000004
++#define QUARK_UART_IER_EDSSI 0x00000008
+
-+#define QUARK_UART_IIR_IP 0x00000001
++#define QUARK_UART_IIR_IP 0x00000001
+#define QUARK_UART_IIR_IID 0x00000006
+#define QUARK_UART_IIR_MSI 0x00000000
+#define QUARK_UART_IIR_TRI 0x00000002
@@ -3756,7 +3810,7 @@ index 0000000..5c0a01a
+#define QUARK_UART_IIR_TOI 0x00000008
+#define QUARK_UART_IIR_FIFO256 0x00000020
+#define QUARK_UART_IIR_FIFO64 QUARK_UART_IIR_FIFO256
-+#define QUARK_UART_IIR_FE 0x000000C0
++#define QUARK_UART_IIR_FE 0x000000C0
+
+#define QUARK_UART_FCR_FIFOE 0x00000001
+#define QUARK_UART_FCR_RFR 0x00000002
@@ -3775,56 +3829,56 @@ index 0000000..5c0a01a
+#define QUARK_UART_FCR_RFTL4 QUARK_UART_FCR_RFTL64
+#define QUARK_UART_FCR_RFTL8 QUARK_UART_FCR_RFTL128
+#define QUARK_UART_FCR_RFTL14 QUARK_UART_FCR_RFTL224
-+#define QUARK_UART_FCR_RFTL_SHIFT 6
++#define QUARK_UART_FCR_RFTL_SHIFT 6
+
-+#define QUARK_UART_LCR_WLS 0x00000003
-+#define QUARK_UART_LCR_STB 0x00000004
-+#define QUARK_UART_LCR_PEN 0x00000008
-+#define QUARK_UART_LCR_EPS 0x00000010
++#define QUARK_UART_LCR_WLS 0x00000003
++#define QUARK_UART_LCR_STB 0x00000004
++#define QUARK_UART_LCR_PEN 0x00000008
++#define QUARK_UART_LCR_EPS 0x00000010
+#define QUARK_UART_LCR_SP 0x00000020
+#define QUARK_UART_LCR_SB 0x00000040
-+#define QUARK_UART_LCR_DLAB 0x00000080
++#define QUARK_UART_LCR_DLAB 0x00000080
+#define QUARK_UART_LCR_NP 0x00000000
+#define QUARK_UART_LCR_OP QUARK_UART_LCR_PEN
+#define QUARK_UART_LCR_EP (QUARK_UART_LCR_PEN | QUARK_UART_LCR_EPS)
+#define QUARK_UART_LCR_1P (QUARK_UART_LCR_PEN | QUARK_UART_LCR_SP)
+#define QUARK_UART_LCR_0P (QUARK_UART_LCR_PEN | QUARK_UART_LCR_EPS |\
-+ QUARK_UART_LCR_SP)
++ QUARK_UART_LCR_SP)
+
-+#define QUARK_UART_LCR_5BIT 0x00000000
-+#define QUARK_UART_LCR_6BIT 0x00000001
-+#define QUARK_UART_LCR_7BIT 0x00000002
-+#define QUARK_UART_LCR_8BIT 0x00000003
++#define QUARK_UART_LCR_5BIT 0x00000000
++#define QUARK_UART_LCR_6BIT 0x00000001
++#define QUARK_UART_LCR_7BIT 0x00000002
++#define QUARK_UART_LCR_8BIT 0x00000003
+
-+#define QUARK_UART_MCR_DTR 0x00000001
-+#define QUARK_UART_MCR_RTS 0x00000002
-+#define QUARK_UART_MCR_OUT 0x0000000C
-+#define QUARK_UART_MCR_LOOP 0x00000010
-+#define QUARK_UART_MCR_AFE 0x00000020
++#define QUARK_UART_MCR_DTR 0x00000001
++#define QUARK_UART_MCR_RTS 0x00000002
++#define QUARK_UART_MCR_OUT 0x0000000C
++#define QUARK_UART_MCR_LOOP 0x00000010
++#define QUARK_UART_MCR_AFE 0x00000020
+
+#define QUARK_UART_LSR_DR 0x00000001
-+#define QUARK_UART_LSR_ERR (1<<7)
-+
-+#define QUARK_UART_MSR_DCTS 0x00000001
-+#define QUARK_UART_MSR_DDSR 0x00000002
-+#define QUARK_UART_MSR_TERI 0x00000004
-+#define QUARK_UART_MSR_DDCD 0x00000008
-+#define QUARK_UART_MSR_CTS 0x00000010
-+#define QUARK_UART_MSR_DSR 0x00000020
++#define QUARK_UART_LSR_ERR (1<<7)
++
++#define QUARK_UART_MSR_DCTS 0x00000001
++#define QUARK_UART_MSR_DDSR 0x00000002
++#define QUARK_UART_MSR_TERI 0x00000004
++#define QUARK_UART_MSR_DDCD 0x00000008
++#define QUARK_UART_MSR_CTS 0x00000010
++#define QUARK_UART_MSR_DSR 0x00000020
+#define QUARK_UART_MSR_RI 0x00000040
-+#define QUARK_UART_MSR_DCD 0x00000080
-+#define QUARK_UART_MSR_DELTA (QUARK_UART_MSR_DCTS | QUARK_UART_MSR_DDSR |\
-+ QUARK_UART_MSR_TERI | QUARK_UART_MSR_DDCD)
++#define QUARK_UART_MSR_DCD 0x00000080
++#define QUARK_UART_MSR_DELTA (QUARK_UART_MSR_DCTS | QUARK_UART_MSR_DDSR |\
++ QUARK_UART_MSR_TERI | QUARK_UART_MSR_DDCD)
+
-+#define QUARK_UART_DLL 0x00
-+#define QUARK_UART_DLM 0x01
++#define QUARK_UART_DLL 0x00
++#define QUARK_UART_DLM 0x01
+
+#define QUARK_UART_BRCSR 0x0E
+
-+#define QUARK_UART_IID_RLS (QUARK_UART_IIR_REI)
-+#define QUARK_UART_IID_RDR (QUARK_UART_IIR_RRI)
-+#define QUARK_UART_IID_RDR_TO (QUARK_UART_IIR_RRI | QUARK_UART_IIR_TOI)
-+#define QUARK_UART_IID_THRE (QUARK_UART_IIR_TRI)
++#define QUARK_UART_IID_RLS (QUARK_UART_IIR_REI)
++#define QUARK_UART_IID_RDR (QUARK_UART_IIR_RRI)
++#define QUARK_UART_IID_RDR_TO (QUARK_UART_IIR_RRI | QUARK_UART_IIR_TOI)
++#define QUARK_UART_IID_THRE (QUARK_UART_IIR_TRI)
+#define QUARK_UART_IID_MS (QUARK_UART_IIR_MSI)
+
+#define QUARK_UART_HAL_PARITY_NONE (QUARK_UART_LCR_NP)
@@ -3844,29 +3898,29 @@ index 0000000..5c0a01a
+#define QUARK_UART_HAL_CLR_ALL_FIFO (QUARK_UART_HAL_CLR_TX_FIFO | \
+ QUARK_UART_HAL_CLR_RX_FIFO)
+
-+#define QUARK_UART_HAL_DMA_MODE0 0
++#define QUARK_UART_HAL_DMA_MODE0 0
+#define QUARK_UART_HAL_FIFO_DIS 0
+#define QUARK_UART_HAL_FIFO16 (QUARK_UART_FCR_FIFOE)
+#define QUARK_UART_HAL_FIFO256 (QUARK_UART_FCR_FIFOE | \
+ QUARK_UART_FCR_FIFO256)
+#define QUARK_UART_HAL_FIFO64 (QUARK_UART_HAL_FIFO256)
+#define QUARK_UART_HAL_TRIGGER1 (QUARK_UART_FCR_RFTL1)
-+#define QUARK_UART_HAL_TRIGGER64 (QUARK_UART_FCR_RFTL64)
-+#define QUARK_UART_HAL_TRIGGER128 (QUARK_UART_FCR_RFTL128)
-+#define QUARK_UART_HAL_TRIGGER224 (QUARK_UART_FCR_RFTL224)
-+#define QUARK_UART_HAL_TRIGGER16 (QUARK_UART_FCR_RFTL16)
-+#define QUARK_UART_HAL_TRIGGER32 (QUARK_UART_FCR_RFTL32)
-+#define QUARK_UART_HAL_TRIGGER56 (QUARK_UART_FCR_RFTL56)
++#define QUARK_UART_HAL_TRIGGER64 (QUARK_UART_FCR_RFTL64)
++#define QUARK_UART_HAL_TRIGGER128 (QUARK_UART_FCR_RFTL128)
++#define QUARK_UART_HAL_TRIGGER224 (QUARK_UART_FCR_RFTL224)
++#define QUARK_UART_HAL_TRIGGER16 (QUARK_UART_FCR_RFTL16)
++#define QUARK_UART_HAL_TRIGGER32 (QUARK_UART_FCR_RFTL32)
++#define QUARK_UART_HAL_TRIGGER56 (QUARK_UART_FCR_RFTL56)
+#define QUARK_UART_HAL_TRIGGER4 (QUARK_UART_FCR_RFTL4)
+#define QUARK_UART_HAL_TRIGGER8 (QUARK_UART_FCR_RFTL8)
-+#define QUARK_UART_HAL_TRIGGER14 (QUARK_UART_FCR_RFTL14)
-+#define QUARK_UART_HAL_TRIGGER_L (QUARK_UART_FCR_RFTL64)
-+#define QUARK_UART_HAL_TRIGGER_M (QUARK_UART_FCR_RFTL128)
-+#define QUARK_UART_HAL_TRIGGER_H (QUARK_UART_FCR_RFTL224)
++#define QUARK_UART_HAL_TRIGGER14 (QUARK_UART_FCR_RFTL14)
++#define QUARK_UART_HAL_TRIGGER_L (QUARK_UART_FCR_RFTL64)
++#define QUARK_UART_HAL_TRIGGER_M (QUARK_UART_FCR_RFTL128)
++#define QUARK_UART_HAL_TRIGGER_H (QUARK_UART_FCR_RFTL224)
+
+#define QUARK_UART_HAL_RX_INT (QUARK_UART_IER_ERBFI)
+#define QUARK_UART_HAL_TX_INT (QUARK_UART_IER_ETBEI)
-+#define QUARK_UART_HAL_RX_ERR_INT (QUARK_UART_IER_ELSI)
++#define QUARK_UART_HAL_RX_ERR_INT (QUARK_UART_IER_ELSI)
+#define QUARK_UART_HAL_MS_INT (QUARK_UART_IER_EDSSI)
+#define QUARK_UART_HAL_ALL_INT (QUARK_UART_IER_MASK)
+
@@ -3910,36 +3964,36 @@ index 0000000..5c0a01a
+ unsigned int dmsr;
+ unsigned int fcr;
+ unsigned int mcr;
-+ unsigned int use_dma;
++ unsigned int ier;
++ bool use_dma;
+ struct dma_async_tx_descriptor *desc_tx;
+ struct dma_async_tx_descriptor *desc_rx;
-+#if 1
-+ struct dma_chan *chan_tx;
-+ struct dma_chan *chan_rx;
++ struct dma_chan *tx_chan;
++ struct dma_chan *rx_chan;
+ struct middma_device mid_dma;
+ struct quark_uart_buffer txbuf;
+ struct quark_uart_buffer rxbuf;
+ struct intel_mid_dma_slave dmas_rx;
+ struct intel_mid_dma_slave dmas_tx;
-+#else
-+ struct quark_dma_slave param_tx;
-+ struct quark_dma_slave param_rx;
-+ struct dma_chan *chan_tx;
-+ struct dma_chan *chan_rx;
-+#endif
+ struct scatterlist *sg_tx_p;
+ int nent;
+ struct scatterlist sg_rx;
+ int tx_dma_use;
+ void *rx_buf_virt;
+ dma_addr_t rx_buf_dma;
-+
+ struct dentry *debugfs;
-+
++ struct work_struct work;
++ int dma_tx_in_flight;
+ /* protect the x1000_port private structure and io access to membase */
+ spinlock_t lock;
++ struct dma_slave_config tx_conf;
++ struct dma_slave_config rx_conf;
++ wait_queue_head_t w_queue;
++
+};
+
++static struct uart_driver quark_uart_driver;
++
+/**
+ * struct quark_uart_driver_data - private data structure for UART-DMA
+ * @port_type: The number of DMA channel
@@ -3950,19 +4004,16 @@ index 0000000..5c0a01a
+ int line_no;
+};
+
-+#if 0
-+static unsigned int mem_serial_in(struct uart_port *p, int offset)
++/**
++ * intel_qrk_dma_chan_filter
++ *
++ * Simple descriptor disjunct function
++ */
++static bool intel_qrk_dma_chan_filter(struct dma_chan * chan, void *param)
+{
-+ offset = offset << p->regshift;
-+ return readb(p->membase + offset);
++ return 1;
+}
+
-+static void mem_serial_out(struct uart_port *p, int offset, int value)
-+{
-+ offset = offset << p->regshift;
-+ writeb(value, p->membase + offset);
-+}
-+#endif
+
+/**
+ * serial_in
@@ -3999,6 +4050,7 @@ index 0000000..5c0a01a
+static struct x1000_port *quark_uart_ports[QUARK_UART_NR];
+#endif
+static unsigned int default_baud = 115200;
++static bool use_dma = true;
+static const int trigger_level_256[4] = { 1, 64, 128, 224 };
+static const int trigger_level_64[4] = { 1, 16, 32, 56 };
+static const int trigger_level_16[4] = { 1, 4, 8, 14 };
@@ -4008,7 +4060,6 @@ index 0000000..5c0a01a
+
+#define QUARK_REGS_BUFSIZE 1024
+
-+
+static ssize_t port_show_regs(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
@@ -4059,6 +4110,7 @@ index 0000000..5c0a01a
+ return ret;
+}
+
++
+static const struct file_operations port_regs_ops = {
+ .owner = THIS_MODULE,
+ .open = simple_open,
@@ -4077,24 +4129,17 @@ index 0000000..5c0a01a
+ unsigned int flag)
+{
+ u8 ier = serial_in(priv, UART_IER);
-+#ifdef __QRK_DMA_DEBUG
-+// pr_info("%s read IER %x\n", __func__, ier);
-+#endif
+ ier |= flag & QUARK_UART_IER_MASK;
++ priv->ier = ier;
+ serial_out(priv, UART_IER, ier);
-+#ifdef __QRK_DMA_DEBUG
-+// pr_info("%s wrote IER %x\n", __func__, ier);
-+#endif
+}
+
+static void quark_uart_hal_disable_interrupt(struct x1000_port *priv,
+ unsigned int flag)
+{
-+#ifdef __QRK_DMA_DEBUG
-+// pr_info("%s entry\n", __func__);
-+#endif
+ u8 ier = serial_in(priv, UART_IER);
+ ier &= ~(flag & QUARK_UART_IER_MASK);
++ priv->ier = ier;
+ serial_out(priv, UART_IER, ier);
+}
+
@@ -4133,11 +4178,6 @@ index 0000000..5c0a01a
+ lcr |= bits;
+ lcr |= stb;
+
-+#ifdef __QRK_DMA_DEBUG
-+ /* TODO: change this back to dev_dbg - BOD */
-+ dev_info(priv->port.dev, "%s:baud = %u, div = %04x, lcr = %02x (%lu)\n",
-+ __func__, baud, div, lcr, jiffies);
-+#endif
+ serial_out(priv, UART_LCR, QUARK_UART_LCR_DLAB);
+ serial_out(priv, QUARK_UART_DLL, dll);
+ serial_out(priv, QUARK_UART_DLM, dlm);
@@ -4205,22 +4245,15 @@ index 0000000..5c0a01a
+ trigger_level_1[trigger >> QUARK_UART_FCR_RFTL_SHIFT];
+ break;
+ }
-+#if 0
+ fcr =
+ dmamode | fifo_size | trigger | QUARK_UART_FCR_RFR | QUARK_UART_FCR_TFR;
-+#else
-+ fcr =
-+ fifo_size | trigger | QUARK_UART_FCR_RFR | QUARK_UART_FCR_TFR;
+
-+#endif
+ serial_out(priv, UART_FCR, QUARK_UART_FCR_FIFOE);
+ serial_out(priv,
+ UART_FCR, QUARK_UART_FCR_FIFOE | QUARK_UART_FCR_RFR | QUARK_UART_FCR_TFR);
+ serial_out(priv, UART_FCR, fcr);
+ priv->fcr = fcr;
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s FCR set to %x\n", __func__, priv->fcr);
-+#endif
++
+ return 0;
+}
+
@@ -4346,101 +4379,6 @@ index 0000000..5c0a01a
+ return room;
+}
+
-+static void quark_free_dma(struct uart_port *port)
-+{
-+ struct x1000_port *priv;
-+ priv = container_of(port, struct x1000_port, port);
-+
-+ if (priv->chan_tx) {
-+ dma_release_channel(priv->chan_tx);
-+ priv->chan_tx = NULL;
-+ }
-+ if (priv->chan_rx) {
-+ dma_release_channel(priv->chan_rx);
-+ priv->chan_rx = NULL;
-+ }
-+
-+ if (priv->rx_buf_dma) {
-+ dma_free_coherent(port->dev, port->fifosize, priv->rx_buf_virt,
-+ priv->rx_buf_dma);
-+ priv->rx_buf_virt = NULL;
-+ priv->rx_buf_dma = 0;
-+ }
-+
-+ return;
-+}
-+
-+static bool filter(struct dma_chan *chan, void *slave)
-+{
-+ #if 0
-+ struct quark_dma_slave *param = slave;
-+
-+ if ((chan->chan_id == param->chan_id) && (param->dma_dev ==
-+ chan->device->dev)) {
-+ chan->private = param;
-+ return true;
-+ } else {
-+ return false;
-+ }
-+ #else
-+ return true;
-+ #endif
-+}
-+
-+static void quark_request_dma(struct uart_port *port)
-+{
-+ dma_cap_mask_t mask;
-+ struct dma_chan *chan;
-+ struct pci_dev *dma_dev;
-+#if 0
-+ struct quark_dma_slave *param;
-+#endif
-+ struct x1000_port *priv =
-+ container_of(port, struct x1000_port, port);
-+ dma_cap_zero(mask);
-+ dma_cap_set(DMA_SLAVE, mask);
-+
-+ dma_dev = pci_get_bus_and_slot(priv->pdev->bus->number,
-+ PCI_DEVFN(0xa, 0)); /* Get DMA's dev
-+ information */
-+ /* Set Tx DMA */
-+#if 0
-+ param = &priv->param_tx;
-+ param->dma_dev = &dma_dev->dev;
-+ param->chan_id = priv->port.line * 2; /* Tx = 0, 2, 4, ... */
-+
-+ param->tx_reg = port->mapbase + UART_TX;
-+#endif
-+ chan = dma_request_channel(mask, filter, &priv->dmas_tx);
-+ if (!chan) {
-+ dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Tx)\n",
-+ __func__);
-+ return;
-+ }
-+ priv->chan_tx = chan;
-+#if 0
-+ /* Set Rx DMA */
-+ param = &priv->param_rx;
-+ param->dma_dev = &dma_dev->dev;
-+ param->chan_id = priv->port.line * 2 + 1; /* Rx = Tx + 1 */
-+
-+ param->rx_reg = port->mapbase + UART_RX;
-+#endif
-+ chan = dma_request_channel(mask, filter, &priv->dmas_rx);
-+ if (!chan) {
-+ dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",
-+ __func__);
-+ dma_release_channel(priv->chan_tx);
-+ priv->chan_tx = NULL;
-+ return;
-+ }
-+
-+ /* Get Consistent memory for DMA */
-+ priv->rx_buf_virt = dma_alloc_coherent(port->dev, port->fifosize,
-+ &priv->rx_buf_dma, GFP_KERNEL);
-+ priv->chan_rx = chan;
-+}
-+
+static void quark_dma_rx_complete(void *arg)
+{
+ struct x1000_port *priv = arg;
@@ -4464,18 +4402,32 @@ index 0000000..5c0a01a
+ struct circ_buf *xmit = &port->state->xmit;
+ struct scatterlist *sg = priv->sg_tx_p;
+ int i;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
+
+ for (i = 0; i < priv->nent; i++, sg++) {
+ xmit->tail += sg_dma_len(sg);
+ port->icount.tx += sg_dma_len(sg);
+ }
-+ xmit->tail &= UART_XMIT_SIZE - 1;
++ /* Make sure that xmit->head and xmit->tail are equal
++ to zero at the end of a transaction */
++ if(priv->tx_dma_use == 0)
++ xmit->head = xmit->tail = 0;
++ else
++ xmit->tail &= UART_XMIT_SIZE - 1;
+ async_tx_ack(priv->desc_tx);
+ dma_unmap_sg(port->dev, sg, priv->nent, DMA_TO_DEVICE);
+ priv->tx_dma_use = 0;
+ priv->nent = 0;
++ priv->tx_empty = 1;
+ kfree(priv->sg_tx_p);
++
+ quark_uart_hal_enable_interrupt(priv, QUARK_UART_HAL_TX_INT);
++ priv->dma_tx_in_flight = 0;
++ wake_up(&priv->w_queue);
++
++ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static int pop_tx(struct x1000_port *priv, int size)
@@ -4548,10 +4500,21 @@ index 0000000..5c0a01a
+
+ sg_dma_address(sg) = priv->rx_buf_dma;
+
-+ desc = dmaengine_prep_slave_sg(priv->chan_rx,
-+ sg, 1, DMA_DEV_TO_MEM,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ /* Configure RX */
++ priv->rx_conf.dst_addr = sg_dma_address(sg);
++ priv->rx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ priv->rx_conf.dst_maxburst = LNW_DMA_MSIZE_1;
++
++ priv->rx_conf.src_addr = QUARK_UART_AHB_REG_BASE + QUARK_UART_THR; /* Wants an AHB address */
++ priv->rx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
++ priv->rx_conf.src_maxburst = LNW_DMA_MSIZE_4;
++ priv->rx_conf.direction = DMA_DEV_TO_MEM;
++ priv->rx_conf.device_fc = false;
+
++ dmaengine_slave_config(priv->rx_chan, &priv->rx_conf);
++ desc = dmaengine_prep_slave_sg(priv->rx_chan,
++ sg, 1, DMA_DEV_TO_MEM,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc)
+ return 0;
+
@@ -4559,7 +4522,7 @@ index 0000000..5c0a01a
+ desc->callback = quark_dma_rx_complete;
+ desc->callback_param = priv;
+ desc->tx_submit(desc);
-+ dma_async_issue_pending(priv->chan_rx);
++ dma_async_issue_pending(priv->rx_chan);
+
+ return QUARK_UART_HANDLED_RX_INT;
+}
@@ -4574,9 +4537,10 @@ index 0000000..5c0a01a
+ int tx_empty;
+
+ if (!priv->start_tx) {
-+ dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
++ dev_dbg(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
+ __func__, jiffies);
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_TX_INT);
++ wake_up(&priv->w_queue);
+ priv->tx_empty = 1;
+ return 0;
+ }
@@ -4600,15 +4564,17 @@ index 0000000..5c0a01a
+ }
+
+ priv->tx_empty = tx_empty;
-+
+ if (tx_empty) {
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_TX_INT);
-+ uart_write_wakeup(port);
++ wake_up(&priv->w_queue);
++ if (port->state->port.tty != NULL)
++ uart_write_wakeup(port);
+ }
+
+ return QUARK_UART_HANDLED_TX_INT;
+}
+
++
+static unsigned int dma_handle_tx(struct x1000_port *priv)
+{
+ struct uart_port *port = &priv->port;
@@ -4617,17 +4583,18 @@ index 0000000..5c0a01a
+ int nent;
+ int fifo_size;
+ int tx_empty;
-+ struct dma_async_tx_descriptor *desc;
+ int num;
+ int i;
+ int bytes;
+ int size;
+ int rem;
++ int ret;
+
+ if (!priv->start_tx) {
-+ dev_info(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
++ dev_dbg(priv->port.dev, "%s:Tx isn't started. (%lu)\n",
+ __func__, jiffies);
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_TX_INT);
++ wake_up(&priv->w_queue);
+ priv->tx_empty = 1;
+ return 0;
+ }
@@ -4636,11 +4603,12 @@ index 0000000..5c0a01a
+ dev_dbg(priv->port.dev, "%s:Tx is not completed. (%lu)\n",
+ __func__, jiffies);
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_TX_INT);
++ wake_up(&priv->w_queue);
+ priv->tx_empty = 1;
+ return 0;
+ }
+
-+ fifo_size = max(priv->fifo_size, 1);
++ fifo_size = QUARK_UART_MAXBURST;
+ tx_empty = 1;
+ if (pop_tx_x(priv, xmit->buf)) {
+ quark_uart_hal_write(priv, xmit->buf, 1);
@@ -4652,15 +4620,37 @@ index 0000000..5c0a01a
+ bytes = min((int)CIRC_CNT(xmit->head, xmit->tail,
+ UART_XMIT_SIZE), CIRC_CNT_TO_END(xmit->head,
+ xmit->tail, UART_XMIT_SIZE));
++
+ if (!bytes) {
+ dev_dbg(priv->port.dev, "%s 0 bytes return\n", __func__);
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_TX_INT);
-+ uart_write_wakeup(port);
++ wake_up(&priv->w_queue);
++ if (port->state->port.tty != NULL)
++ uart_write_wakeup(port);
+ return 0;
+ }
+
++ /* DMA block doesn't do !dword aligned */
++ if (bytes % 0x04){
++ if (bytes < 4){
++ ret = handle_tx(priv);
++ /* DMA transactions want to start DWORD aligned */
++ xmit->head = xmit->tail = 0;
++ return ret;
++ }
++ bytes &= 0xFFFFFFFC;
++ }
++
++ /* For small payloads its just faster to write the FIFO directly */
++ if (bytes < QUARK_FIFO_FASTER_LEN){
++ ret = handle_tx(priv);
++ /* DMA transactions want to start DWORD aligned */
++ xmit->head = xmit->tail = 0;
++ return ret;
++ }
++
+ if (bytes > fifo_size) {
-+ num = bytes / fifo_size + 1;
++ num = bytes / fifo_size;
+ size = fifo_size;
+ rem = bytes % fifo_size;
+ } else {
@@ -4684,6 +4674,7 @@ index 0000000..5c0a01a
+ sg = priv->sg_tx_p;
+
+ for (i = 0; i < num; i++, sg++) {
++ BUG_ON((int)xmit->buf & ~PAGE_MASK);
+ if (i == (num - 1))
+ sg_set_page(sg, virt_to_page(xmit->buf),
+ rem, fifo_size * i);
@@ -4705,28 +4696,18 @@ index 0000000..5c0a01a
+ fifo_size * i;
+ sg_dma_address(sg) = (sg_dma_address(sg) &
+ ~(UART_XMIT_SIZE - 1)) + sg->offset;
++
+ if (i == (nent - 1))
-+ sg_dma_len(sg) = rem;
++ sg_dma_len(sg) = bytes;
+ else
+ sg_dma_len(sg) = size;
++ bytes -= size;
+ }
+
-+ desc = dmaengine_prep_slave_sg(priv->chan_tx,
-+ priv->sg_tx_p, nent, DMA_MEM_TO_DEV,
-+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-+ if (!desc) {
-+ dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
-+ __func__);
-+ return 0;
-+ }
-+ dma_sync_sg_for_device(port->dev, priv->sg_tx_p, nent, DMA_TO_DEVICE);
-+ priv->desc_tx = desc;
-+ desc->callback = quark_dma_tx_complete;
-+ desc->callback_param = priv;
-+
-+ desc->tx_submit(desc);
-+
-+ dma_async_issue_pending(priv->chan_tx);
++ priv->dma_tx_in_flight = 1;
++ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_TX_INT);
++ wake_up(&priv->w_queue);
++ schedule_work(&priv->work);
+
+ return QUARK_UART_HANDLED_TX_INT;
+}
@@ -4772,6 +4753,42 @@ index 0000000..5c0a01a
+ #define unmask_pvm(x)
+#endif
+
++static void quark_uart_work(struct work_struct *work)
++{
++ struct x1000_port *priv = container_of(work, struct x1000_port,work);
++ struct dma_async_tx_descriptor *desc;
++
++ if (priv == NULL) {
++ pr_err("ERR_X1000: tasklet Null param\n");
++ return;
++ }
++ /* Configure TX */
++ priv->tx_conf.src_addr = sg_dma_address(priv->sg_tx_p);
++ priv->tx_conf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
++ priv->tx_conf.src_maxburst = LNW_DMA_MSIZE_1;
++ priv->tx_conf.dst_addr = QUARK_UART_AHB_REG_BASE + QUARK_UART_THR; /* Wants an AHB address */
++ priv->tx_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
++ priv->tx_conf.dst_maxburst = LNW_DMA_MSIZE_4;
++ priv->tx_conf.direction = DMA_MEM_TO_DEV;
++ priv->tx_conf.device_fc = false;
++
++ dmaengine_slave_config(priv->tx_chan, &priv->tx_conf);
++ desc = dmaengine_prep_slave_sg(priv->tx_chan,
++ priv->sg_tx_p, priv->nent, DMA_MEM_TO_DEV,
++ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
++ if (!desc) {
++ dev_err(priv->port.dev, "%s:device_prep_slave_sg Failed\n",
++ __func__);
++ return;
++ }
++ dma_sync_sg_for_device(priv->port.dev, priv->sg_tx_p, priv->nent, DMA_TO_DEVICE);
++ priv->desc_tx = desc;
++ desc->callback = quark_dma_tx_complete;
++ desc->callback_param = priv;
++ desc->tx_submit(desc);
++ dma_async_issue_pending(priv->tx_chan);
++}
++
+static irqreturn_t quark_uart_interrupt(int irq, void *dev_id)
+{
+ struct x1000_port *priv = dev_id;
@@ -4801,18 +4818,9 @@ index 0000000..5c0a01a
+ }
+ break;
+ case QUARK_UART_IID_RDR: /* Received Data Ready */
-+ if (priv->use_dma) {
-+ quark_uart_hal_disable_interrupt(priv,
-+ QUARK_UART_HAL_RX_INT |
-+ QUARK_UART_HAL_RX_ERR_INT);
-+ ret = dma_handle_rx(priv);
-+ if (!ret)
-+ quark_uart_hal_enable_interrupt(priv,
-+ QUARK_UART_HAL_RX_INT |
-+ QUARK_UART_HAL_RX_ERR_INT);
-+ } else {
-+ ret = handle_rx(priv);
-+ }
++
++ (void)dma_handle_rx; /*Not worth setup time*/
++ ret = handle_rx(priv);
+ break;
+ case QUARK_UART_IID_RDR_TO: /* Received Data Ready
+ (FIFO Timeout) */
@@ -4821,7 +4829,6 @@ index 0000000..5c0a01a
+ case QUARK_UART_IID_THRE: /* Transmitter Holding Register
+ Empty */
+ if (priv->use_dma)
-+
+ ret = dma_handle_tx(priv);
+ else
+ ret = handle_tx(priv);
@@ -4909,45 +4916,48 @@ index 0000000..5c0a01a
+static void quark_uart_stop_tx(struct uart_port *port)
+{
+ struct x1000_port *priv;
++ unsigned long flags;
+ priv = container_of(port, struct x1000_port, port);
++
++ spin_lock_irqsave(&priv->lock, flags);
+ priv->start_tx = 0;
+ priv->tx_dma_use = 0;
++
++ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void quark_uart_start_tx(struct uart_port *port)
+{
+ struct x1000_port *priv;
+
++ unsigned long flags;
+ priv = container_of(port, struct x1000_port, port);
+
++ spin_lock_irqsave(&priv->lock, flags);
+ if (priv->use_dma) {
+ if (priv->tx_dma_use) {
+ dev_dbg(priv->port.dev, "%s : Tx DMA is NOT empty.\n",
+ __func__);
-+ return;
++ goto done;
+ }
+ }
+
-+#ifdef __QRK_DMA_DEBUG
-+ unsigned char iid = quark_uart_hal_get_iid(priv);
-+ pr_info("%s enable interrupt IER %x FCR %x iid %x\n", __func__, serial_in(priv, UART_IER),
-+ serial_in(priv, UART_FCR), iid);
-+#endif
+ priv->start_tx = 1;
-+ quark_uart_hal_enable_interrupt(priv, QUARK_UART_HAL_TX_INT);
++ if( priv->dma_tx_in_flight == 0)
++ quark_uart_hal_enable_interrupt(priv, QUARK_UART_HAL_TX_INT);
++
++done:
++ spin_unlock_irqrestore(&priv->lock, flags);
++
+}
+
+static void quark_uart_stop_rx(struct uart_port *port)
+{
+ struct x1000_port *priv;
-+
+ priv = container_of(port, struct x1000_port, port);
++
++ wait_event(priv->w_queue,!(priv->ier & QUARK_UART_HAL_TX_INT) && !priv->dma_tx_in_flight);
+ priv->start_rx = 0;
-+#ifdef __QRK_DMA_DEBUG
-+ unsigned char iid;
-+ iid = quark_uart_hal_get_iid(priv);
-+ pr_info("%s IID is 0x%x USR 0x%x LSR 0x%x MSR 0x%x\n", __func__, iid, serial_in(priv,31), serial_in(priv, UART_LSR), serial_in(priv, UART_MSR));
-+#endif
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_RX_INT |
+ QUARK_UART_HAL_RX_ERR_INT);
+}
@@ -4987,9 +4997,7 @@ index 0000000..5c0a01a
+ priv->uartclk = port->uartclk;
+ else
+ port->uartclk = priv->uartclk;
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s entry fifo size %d!\n", __func__, priv->fifo_size);
-+#endif
++
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_ALL_INT);
+ ret = quark_uart_hal_set_line(priv, default_baud,
+ QUARK_UART_HAL_PARITY_NONE, QUARK_UART_HAL_8BIT,
@@ -5031,28 +5039,14 @@ index 0000000..5c0a01a
+ }
+
+ priv->trigger_level = trigger_level;
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s setting FCR fifo_size %d FIFO trig %d\n", __func__, fifo_size, priv->trigger);
-+#endif
+ ret = quark_uart_hal_set_fifo(priv, QUARK_UART_HAL_DMA_MODE0,
+ fifo_size, priv->trigger);
+ if (ret < 0)
+ return ret;
-+
-+ if (priv->use_dma)
-+ quark_request_dma(port);
-+
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s enable interrupt IER %x FCR %x USR %x\n", __func__, serial_in(priv, UART_IER),
-+ serial_in(priv, UART_FCR), serial_in(priv, 31));
-+#endif
+ priv->start_rx = 1;
+ quark_uart_hal_enable_interrupt(priv, QUARK_UART_HAL_RX_INT |
+ QUARK_UART_HAL_RX_ERR_INT);
+ uart_update_timeout(port, CS8, default_baud);
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s exit IER %x FCR %x USR %x\n", __func__, serial_in(priv, UART_IER), serial_in(priv, UART_FCR), serial_in(priv, 31));
-+#endif
+ return 0;
+}
+
@@ -5061,10 +5055,10 @@ index 0000000..5c0a01a
+ struct x1000_port *priv;
+ int ret;
+
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s called!\n", __func__);
-+#endif
+ priv = container_of(port, struct x1000_port, port);
++
++ wait_event(priv->w_queue, !(priv->dma_tx_in_flight));
++
+ quark_uart_hal_disable_interrupt(priv, QUARK_UART_HAL_ALL_INT);
+ quark_uart_hal_fifo_reset(priv, QUARK_UART_HAL_CLR_ALL_FIFO);
+ ret = quark_uart_hal_set_fifo(priv, QUARK_UART_HAL_DMA_MODE0,
@@ -5072,8 +5066,6 @@ index 0000000..5c0a01a
+ if (ret)
+ dev_err(priv->port.dev,
+ "quark_uart_hal_set_fifo Failed(ret=%d)\n", ret);
-+
-+ quark_free_dma(port);
+}
+
+/* Change the port parameters, including word length, parity, stop
@@ -5125,7 +5117,6 @@ index 0000000..5c0a01a
+ termios->c_cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
-+
+ spin_lock_irqsave(&priv->lock, flags);
+ spin_lock(&port->lock);
+
@@ -5160,23 +5151,6 @@ index 0000000..5c0a01a
+
+static int quark_uart_request_port(struct uart_port *port)
+{
-+#if 0
-+ struct x1000_port *priv;
-+ int ret;
-+ void __iomem *membase;
-+
-+ priv = container_of(port, struct x1000_port, port);
-+ ret = pci_request_regions(priv->pdev, KBUILD_MODNAME);
-+ if (ret < 0)
-+ return -EBUSY;
-+
-+ membase = pci_iomap(priv->pdev, 1, 0);
-+ if (!membase) {
-+ pci_release_regions(priv->pdev);
-+ return -EBUSY;
-+ }
-+ priv->membase = port->membase = membase;
-+#endif
+ return 0;
+}
+
@@ -5184,9 +5158,6 @@ index 0000000..5c0a01a
+{
+ struct x1000_port *priv;
+
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s entry!\n", __func__);
-+#endif
+ priv = container_of(port, struct x1000_port, port);
+ if (type & UART_CONFIG_TYPE) {
+ port->type = priv->port_type;
@@ -5198,25 +5169,20 @@ index 0000000..5c0a01a
+ struct serial_struct *serinfo)
+{
+ struct x1000_port *priv;
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s entry point !\n", __func__);
-+#endif
+ priv = container_of(port, struct x1000_port, port);
++
+ if (serinfo->flags & UPF_LOW_LATENCY) {
+ dev_info(priv->port.dev,
+ "QUARK UART : Use PIO Mode (without DMA)\n");
-+ priv->use_dma = 0;
++ priv->use_dma = false;
+ serinfo->flags &= ~UPF_LOW_LATENCY;
+ } else {
-+#ifndef CONFIG_QUARK_DMA
-+ dev_err(priv->port.dev, "%s : QUARK DMA is not Loaded.\n",
-+ __func__);
-+ return -EOPNOTSUPP;
-+#endif
+ dev_info(priv->port.dev, "QUARK UART : Use DMA Mode\n");
++ #if 0
+ if (!priv->use_dma)
+ quark_request_dma(port);
-+ priv->use_dma = 1;
++ #endif
++ priv->use_dma = true;
+ }
+
+ return 0;
@@ -5318,7 +5284,7 @@ index 0000000..5c0a01a
+ .startup = quark_uart_startup,
+ .shutdown = quark_uart_shutdown,
+ .set_termios = quark_uart_set_termios,
-+/* .pm = quark_uart_pm, Not supported yet */
++/* .pm = quark_uart_pm, Not supported yet */
+/* .set_wake = quark_uart_set_wake, Not supported yet */
+ .type = quark_uart_type,
+ .release_port = quark_uart_release_port,
@@ -5365,7 +5331,7 @@ index 0000000..5c0a01a
+ if (priv->port.sysrq) {
+ /* call to uart_handle_sysrq_char already took the priv lock */
+ priv_locked = 0;
-+ /* serial8250_handle_port() already took the port lock */
++ /* serialquark_uart_handle_port() already took the port lock */
+ port_locked = 0;
+ } else if (oops_in_progress) {
+ priv_locked = spin_trylock(&priv->lock);
@@ -5426,8 +5392,6 @@ index 0000000..5c0a01a
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
-+static struct uart_driver quark_uart_driver;
-+
+static struct console quark_console = {
+ .name = QUARK_UART_DRIVER_DEVICE,
+ .write = quark_console_write,
@@ -5447,31 +5411,29 @@ index 0000000..5c0a01a
+ .owner = THIS_MODULE,
+ .driver_name = KBUILD_MODNAME,
+ .dev_name = QUARK_UART_DRIVER_DEVICE,
-+ .major = 0,
-+ .minor = 0,
+ .nr = QUARK_UART_NR,
+ .cons = QUARK_CONSOLE,
+};
+
++static int line_no; /* eek! TODO */
++
+static struct x1000_port *quark_uart_init_port(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct x1000_port *priv;
+ int ret, len;
++ dma_cap_mask_t mask;
+ unsigned char *rxbuf;
+ char name[32]; /* for debugfs file name */
+ struct intel_mid_dma_probe_info * info = NULL;
+
-+ dev_info(&pdev->dev,"QUARK UART-DMA (ID: %04x:%04x) pdev->irq %d\n",
++ dev_dbg(&pdev->dev,"QUARK UART-DMA (ID: %04x:%04x) pdev->irq %d\n",
+ pdev->vendor, pdev->device, pdev->irq);
+
+ info = (void*)id->driver_data;
+ dev_info(&pdev->dev,"QUARK UART-DMA : CH %d base %d block len %d per mask %x\n",
+ info->max_chan, info->ch_base, info->block_size, info->pimr_mask);
-+#if 0
-+ board = &drv_dat[id->driver_data];
-+ port_type = board->port_type;
-+#endif
++
+ priv = kzalloc(sizeof(struct x1000_port), GFP_KERNEL);
+ if (priv == NULL)
+ goto init_port_alloc_err;
@@ -5480,10 +5442,12 @@ index 0000000..5c0a01a
+ if (!rxbuf)
+ goto init_port_free_txbuf;
+
++ priv->mid_dma.pdev = pci_dev_get(pdev);
+ pci_set_master(pdev);
+
+ spin_lock_init(&priv->lock);
+
++ /* UART regs */
+ priv->mapbase = pci_resource_start(pdev, 0);
+ len = pci_resource_len(pdev, 0);
+ priv->membase = ioremap_nocache(priv->mapbase, len);
@@ -5492,6 +5456,54 @@ index 0000000..5c0a01a
+ goto init_port_free_txbuf;
+ }
+
++ /* DMA driver */
++ priv->mid_dma.max_chan = info->max_chan; /* Max channels */
++ priv->mid_dma.chan_base = info->ch_base; /* Index start */
++ priv->mid_dma.block_size = info->block_size; /* MAX DMA block */
++ priv->mid_dma.pimr_mask = info->pimr_mask; /* Per int regs bool */
++ priv->mid_dma.is_quark = info->is_quark;
++
++ ret = intel_qrk_dma_probe(pdev, &priv->mid_dma);
++ if(ret != 0){
++ dev_err(&pdev->dev, "Unable to init DMA sub-system\n");
++ goto init_port_free_uart_iomem;
++ }
++
++ /* Request DMA channels TODO: move to startup() once debugged on hw */
++ dma_cap_zero(mask);
++ dma_cap_set(DMA_SLAVE, mask);
++
++ priv->rx_chan = dma_request_channel(mask, intel_qrk_dma_chan_filter, &priv->dmas_rx);
++ if(priv->rx_chan == NULL){
++ dev_err(&pdev->dev, "Unable to hook DMA RX channel\n");
++ goto init_port_free_dma_iomem;
++ };
++ priv->rx_buf_virt = dma_alloc_coherent(&pdev->dev, QUARK_UART_FIFO_LEN,
++ &priv->rx_buf_dma, GFP_KERNEL);
++ if (priv->rx_buf_virt == NULL){
++ dev_err(&pdev->dev, "Unable to allocate %d bytes for DMA\n",
++ QUARK_UART_FIFO_LEN);
++ goto init_port_free_dma_iomem;
++ }
++
++ priv->dmas_rx.hs_mode = LNW_DMA_HW_HS;
++ priv->dmas_rx.cfg_mode = LNW_DMA_PER_TO_MEM;
++ /* Configure RX */
++
++ priv->tx_chan = dma_request_channel(mask, intel_qrk_dma_chan_filter, &priv->dmas_tx);
++ if(priv->tx_chan == NULL){
++ dev_err(&pdev->dev, "Unable to hook DMA RX channel\n");
++ goto init_port_free_dma_iomem;
++ };
++ priv->dmas_tx.hs_mode = LNW_DMA_HW_HS;
++ priv->dmas_tx.cfg_mode = LNW_DMA_MEM_TO_PER;
++
++ dev_info(&pdev->dev, "using %s for DMA RX %s for DMA TX DMA %s\n",
++ dev_name(&priv->rx_chan->dev->device),
++ dev_name(&priv->tx_chan->dev->device), use_dma ?
++ "enabled" : "disabled");
++
++ /* Setup UART port descriptor */
+ priv->pdev = pdev;
+ priv->tx_empty = 1;
+ priv->rxbuf.buf = rxbuf;
@@ -5507,8 +5519,10 @@ index 0000000..5c0a01a
+ priv->port.ops = &quark_uart_ops;
+ priv->port.flags = UPF_BOOT_AUTOCONF;
+ priv->port.fifosize = QUARK_UART_FIFO_LEN;
-+ priv->port.line = pdev->dev.id;
-+ priv->trigger = QUARK_UART_HAL_TRIGGER_M;
++ priv->port.line = line_no;
++ priv->trigger = QUARK_UART_HAL_TRIGGER_L;
++ priv->use_dma = use_dma;
++ use_dma = 0;
+
+ spin_lock_init(&priv->port.lock);
+ pci_set_drvdata(pdev, priv);
@@ -5517,33 +5531,41 @@ index 0000000..5c0a01a
+
+ ret = request_irq(pdev->irq, quark_uart_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, priv);
-+#ifdef __QRK_DMA_DEBUG
-+ pr_info("%s request_irq %d use_dma %d irq=%d\n", __func__, ret, priv->use_dma, pdev->irq);
-+#endif
-+ if (ret < 0)
++ if (ret < 0){
++ dev_err(&pdev->dev, "Unable to request irq %d err %d\n",
++ pdev->irq, ret);
+ goto init_port_hal_free;
++ }
+
+#ifdef CONFIG_SERIAL_QUARK_UART_CONSOLE
-+ quark_uart_ports[board->line_no] = priv;
++ quark_uart_ports[line_no++] = priv;
+#endif
+ ret = uart_add_one_port(&quark_uart_driver, &priv->port);
+
-+ if (ret < 0)
++ if (ret < 0){
++ dev_err(&pdev->dev, "uart_add_one_port fail %d\n", ret);
+ goto init_port_hal_free;
++ }
+
+#ifdef CONFIG_DEBUG_FS
+ snprintf(name, sizeof(name), "uart%d_regs", pdev->dev.id);
+ priv->debugfs = debugfs_create_file(name, S_IFREG | S_IRUGO,
+ NULL, priv, &port_regs_ops);
+#endif
-+
++ INIT_WORK(&priv->work, quark_uart_work);
++ init_waitqueue_head(&priv->w_queue);
+ return priv;
+
+init_port_hal_free:
-+#ifdef CONFIG_SERIAL_QUARK_UART_CONSOLE
-+ quark_uart_ports[board->line_no] = NULL;
-+#endif
+ free_page((unsigned long)rxbuf);
++init_port_free_dma_iomem:
++init_port_free_uart_iomem:
++ if (sg_dma_address(&priv->sg_rx))
++ dma_free_coherent(priv->port.dev, priv->port.fifosize,
++ sg_virt(&priv->sg_rx),
++ sg_dma_address(&priv->sg_rx));
++
++ iounmap(priv->membase);
+init_port_free_txbuf:
+ kfree(priv);
+init_port_alloc_err:
@@ -5551,13 +5573,31 @@ index 0000000..5c0a01a
+ return NULL;
+}
+
-+static void quark_uart_exit_port(struct x1000_port *priv)
++static void quark_uart_exit_port(struct pci_dev *pdev, struct x1000_port *priv)
+{
+
+#ifdef CONFIG_DEBUG_FS
+ if (priv->debugfs)
+ debugfs_remove(priv->debugfs);
+#endif
++ /* Shutdown DMA */
++ intel_qrk_dma_remove(pdev, &priv->mid_dma);
++
++ /* TODO: move to remove() when h/w proved out */
++ if (priv->tx_chan) {
++ dma_release_channel(priv->tx_chan);
++ priv->tx_chan = NULL;
++ }
++ if (priv->rx_chan) {
++ dma_release_channel(priv->rx_chan);
++ priv->rx_chan = NULL;
++ }
++
++ if (sg_dma_address(&priv->sg_rx))
++ dma_free_coherent(priv->port.dev, priv->port.fifosize,
++ sg_virt(&priv->sg_rx),
++ sg_dma_address(&priv->sg_rx));
++
+ free_irq(priv->port.irq, priv);
+ uart_remove_one_port(&quark_uart_driver, &priv->port);
+ pci_set_drvdata(priv->pdev, NULL);
@@ -5573,7 +5613,7 @@ index 0000000..5c0a01a
+#ifdef CONFIG_SERIAL_QUARK_UART_CONSOLE
+ quark_uart_ports[priv->port.line] = NULL;
+#endif
-+ quark_uart_exit_port(priv);
++ quark_uart_exit_port(pdev, priv);
+ pci_disable_device(pdev);
+ kfree(priv);
+ return;
@@ -5583,6 +5623,10 @@ index 0000000..5c0a01a
+{
+ struct x1000_port *priv = pci_get_drvdata(pdev);
+
++ /* Suspend DMA regs */
++ intel_qrk_dma_suspend(&priv->mid_dma);
++
++ /* Suspend UART regs */
+ uart_suspend_port(&quark_uart_driver, &priv->port);
+
+ pci_save_state(pdev);
@@ -5605,8 +5649,12 @@ index 0000000..5c0a01a
+ return ret;
+ }
+
++ /* Resume UART regs */
+ uart_resume_port(&quark_uart_driver, &priv->port);
+
++ /* Resume DMA regs */
++ intel_qrk_dma_resume(&priv->mid_dma);
++
+ return 0;
+}
+#else
@@ -5616,7 +5664,7 @@ index 0000000..5c0a01a
+
+struct pci_device_id quark_uart_pci_ids[] = {
+ /* channels = 2, offset = 0, block size = FIFO_LEN, pimr = 0 */
-+ { PCI_VDEVICE(INTEL, 0x0936), INFO(2, 0, QUARK_UART_FIFO_LEN, 0)},
++ { PCI_VDEVICE(INTEL, 0x0936), INFO(2, 0, QUARK_UART_FIFO_LEN, 0, 1)},
+ { 0 }
+};
+
@@ -5685,8 +5733,11 @@ index 0000000..5c0a01a
+module_param(default_baud, uint, S_IRUGO);
+MODULE_PARM_DESC(default_baud,
+ "Default BAUD for initial driver state and console (default 115200)");
++module_param(use_dma, bool, S_IRUGO);
++MODULE_PARM_DESC(use_dma,
++ "Use DMA (default true)");
diff --git a/include/linux/intel_mid_dma.h b/include/linux/intel_mid_dma.h
-index 10496bd..8dd64e9 100644
+index 10496bd..717458b 100644
--- a/include/linux/intel_mid_dma.h
+++ b/include/linux/intel_mid_dma.h
@@ -26,8 +26,10 @@
@@ -5700,7 +5751,7 @@ index 10496bd..8dd64e9 100644
/*DMA mode configurations*/
enum intel_mid_dma_mode {
-@@ -73,4 +75,188 @@ struct intel_mid_dma_slave {
+@@ -73,4 +75,191 @@ struct intel_mid_dma_slave {
struct dma_slave_config dma_slave;
};
@@ -5801,6 +5852,7 @@ index 10496bd..8dd64e9 100644
+ int block_size;
+ bool ispci_fn;
+ unsigned int pimr_mask;
++ unsigned int is_quark;
+ enum intel_mid_dma_state state;
+};
+
@@ -5811,12 +5863,14 @@ index 10496bd..8dd64e9 100644
+ * @ch_base: offset from register base
+ * @block_size: TBD
+ * @pimr_mask: indicates if mask registers to be mapped
++ * @is_quark: indicates if this is quark silicon
+ */
+struct intel_mid_dma_probe_info {
+ u8 max_chan;
+ u8 ch_base;
+ u16 block_size;
+ u32 pimr_mask;
++ u8 is_quark;
+};
+
+
@@ -5889,6 +5943,3 @@ index 10496bd..8dd64e9 100644
+
+
#endif /*__INTEL_MID_DMA_H__*/
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0009-EFI-capsule-update-quark.patch b/recipes-kernel/linux/files/0009-EFI-capsule-update-quark.patch
index ff299ee..1f7e88f 100644
--- a/recipes-kernel/linux/files/0009-EFI-capsule-update-quark.patch
+++ b/recipes-kernel/linux/files/0009-EFI-capsule-update-quark.patch
@@ -4,10 +4,10 @@ Date: Mon, 24 Feb 2014 18:41:59 +0000
Subject: [PATCH 09/21] EFI capsule update
---
- arch/x86/platform/efi/Makefile | 3 +-
- arch/x86/platform/efi/efi.c | 12 +-
- arch/x86/platform/efi/efi_capsule_update.c | 331 ++++++++++++++++++++++++++++
- 3 files changed, 342 insertions(+), 4 deletions(-)
+ arch/x86/platform/efi/Makefile | 3 +-
+ arch/x86/platform/efi/efi.c | 12 +-
+ arch/x86/platform/efi/efi_capsule_update.c | 324 +++++++++++++++++++++++++++++
+ 3 files changed, 335 insertions(+), 4 deletions(-)
create mode 100644 arch/x86/platform/efi/efi_capsule_update.c
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
@@ -58,28 +58,21 @@ index e2cd38f..0e22b5f4 100644
size = md->num_pages << EFI_PAGE_SHIFT;
diff --git a/arch/x86/platform/efi/efi_capsule_update.c b/arch/x86/platform/efi/efi_capsule_update.c
new file mode 100644
-index 0000000..3420e35
+index 0000000..c380392
--- /dev/null
+++ b/arch/x86/platform/efi/efi_capsule_update.c
-@@ -0,0 +1,331 @@
+@@ -0,0 +1,324 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+#define DEBUG
+#include <asm/qrk.h>
@@ -393,6 +386,3 @@ index 0000000..3420e35
+
+module_init(efi_capsule_update_init);
+module_exit(efi_capsule_update_exit);
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0010-Quark-SDIO-host-controller-quark.patch b/recipes-kernel/linux/files/0010-Quark-SDIO-host-controller-quark.patch
index 990af2d..a5a7c21 100644
--- a/recipes-kernel/linux/files/0010-Quark-SDIO-host-controller-quark.patch
+++ b/recipes-kernel/linux/files/0010-Quark-SDIO-host-controller-quark.patch
@@ -4,9 +4,9 @@ Date: Thu, 20 Feb 2014 15:16:30 +0000
Subject: [PATCH 10/21] Quark SDIO host controller
---
- drivers/mmc/host/sdhci-pci.c | 12 ++++++++++++
- include/linux/pci_ids.h | 2 ++
- 2 files changed, 14 insertions(+), 0 deletions(-)
+ drivers/mmc/host/sdhci-pci.c | 12 ++++++++++++
+ include/linux/pci_ids.h | 2 ++
+ 2 files changed, 14 insertions(+)
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index c7dd0cb..e5759b7 100644
@@ -58,6 +58,3 @@ index 0eb6579..b5bb350 100644
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN 0x1c41
#define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX 0x1c5f
#define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0 0x1d40
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0011-Quark-USB-host-quark.patch b/recipes-kernel/linux/files/0011-Quark-USB-host-quark.patch
index 62a97a1..bff26cd 100644
--- a/recipes-kernel/linux/files/0011-Quark-USB-host-quark.patch
+++ b/recipes-kernel/linux/files/0011-Quark-USB-host-quark.patch
@@ -4,10 +4,10 @@ Date: Thu, 13 Feb 2014 13:03:44 +0000
Subject: [PATCH 11/21] Quark USB host
---
- drivers/usb/host/ehci-pci.c | 4 +++
- drivers/usb/host/pci-quirks.c | 42 +++++++++++++++++++++++++++++++++++++++++
- drivers/usb/host/pci-quirks.h | 2 +
- 3 files changed, 48 insertions(+), 0 deletions(-)
+ drivers/usb/host/ehci-pci.c | 4 ++++
+ drivers/usb/host/pci-quirks.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ drivers/usb/host/pci-quirks.h | 2 ++
+ 3 files changed, 48 insertions(+)
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 170b939..5eac9db 100644
@@ -90,6 +90,3 @@ index 7f69a39..80ffdee 100644
void usb_enable_xhci_ports(struct pci_dev *xhci_pdev);
void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
#else
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0012-USB-gadget-serial-quark.patch b/recipes-kernel/linux/files/0012-USB-gadget-serial-quark.patch
index 2d7d88f..804281a 100644
--- a/recipes-kernel/linux/files/0012-USB-gadget-serial-quark.patch
+++ b/recipes-kernel/linux/files/0012-USB-gadget-serial-quark.patch
@@ -1,14 +1,14 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Bryan O'Donoghue <bryan.odonoghue@intel.com>
-Date: Thu, 13 Feb 2014 16:41:02 +0000
+Date: Thu, 8 May 2014 14:28:54 +0100
Subject: [PATCH 12/21] USB gadget serial
---
- Documentation/usb/linux-cdc-acm.inf | 4 +-
- drivers/usb/gadget/Kconfig | 5 +-
- drivers/usb/gadget/pch_udc.c | 142 ++++++++++++++++++++++------------
- drivers/usb/gadget/serial.c | 24 +++++-
- 4 files changed, 118 insertions(+), 57 deletions(-)
+ Documentation/usb/linux-cdc-acm.inf | 4 +-
+ drivers/usb/gadget/Kconfig | 5 +-
+ drivers/usb/gadget/pch_udc.c | 147 ++++++++++++++++++++++++------------
+ drivers/usb/gadget/serial.c | 24 +++++-
+ 4 files changed, 123 insertions(+), 57 deletions(-)
diff --git a/Documentation/usb/linux-cdc-acm.inf b/Documentation/usb/linux-cdc-acm.inf
index f0ffc27..e56f074 100644
@@ -51,7 +51,7 @@ index 14625fd..1ab9996 100644
# LAST -- dummy/emulated controller
#
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
-index 6490c00..df96b3b 100644
+index 6490c00..618261f 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -6,6 +6,7 @@
@@ -99,7 +99,7 @@ index 6490c00..df96b3b 100644
#define PCI_VENDOR_ID_ROHM 0x10DB
#define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D
#define PCI_DEVICE_ID_ML7831_IOH_UDC 0x8808
-@@ -2779,55 +2788,70 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev)
+@@ -2779,55 +2788,75 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev)
{
struct pch_udc_dev *dev = (struct pch_udc_dev *) pdev;
u32 dev_intr, ep_intr;
@@ -115,7 +115,7 @@ index 6490c00..df96b3b 100644
- /* The controller is reset */
- pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
- return IRQ_HANDLED;
-+ int i, events = 0;
++ int i, events = 0, count = 0;
+
+ mask_pvm(dev->pdev);
+ do {
@@ -136,6 +136,7 @@ index 6490c00..df96b3b 100644
+ /* Clear device interrupts */
+ pch_udc_write_device_interrupts(dev, dev_intr);
+ events = 1;
++ count = 1;
}
- if (dev_intr)
- /* Clear device interrupts */
@@ -158,6 +159,7 @@ index 6490c00..df96b3b 100644
+ /* Clear ep interrupts */
+ pch_udc_write_ep_interrupts(dev, ep_intr);
+ events = 1;
++ count = 1;
}
- /* Process Control Out interrupts, if present */
- if (ep_intr & UDC_EPINT_OUT_EP0)
@@ -169,7 +171,10 @@ index 6490c00..df96b3b 100644
- pch_udc_postsvc_epinters(dev, i);
+ if (!dev_intr && !ep_intr){
+ unmask_pvm(dev->pdev);
-+ return IRQ_NONE;
++ if (count)
++ return IRQ_HANDLED;
++ else
++ return IRQ_NONE;
+ }
+ spin_lock(&dev->lock);
+ if (dev_intr){
@@ -181,7 +186,7 @@ index 6490c00..df96b3b 100644
+ if (ep_intr & UDC_EPINT_IN_EP0) {
+ pch_udc_svc_control_in(dev);
+ pch_udc_postsvc_epinters(dev, 0);
-+ }
+ }
+ /* Process Control Out interrupts, if present */
+ if (ep_intr & UDC_EPINT_OUT_EP0)
+ pch_udc_svc_control_out(dev);
@@ -191,7 +196,7 @@ index 6490c00..df96b3b 100644
+ pch_udc_svc_data_in(dev, i);
+ pch_udc_postsvc_epinters(dev, i);
+ }
- }
++ }
+ /* Process data out end point interrupts */
+ for (i = UDC_EPINT_OUT_SHIFT + 1;
+ i < (UDC_EPINT_OUT_SHIFT + PCH_UDC_USED_EP_NUM);
@@ -215,7 +220,7 @@ index 6490c00..df96b3b 100644
return IRQ_HANDLED;
}
-@@ -3108,7 +3132,7 @@ static void pch_udc_remove(struct pci_dev *pdev)
+@@ -3108,7 +3137,7 @@ static void pch_udc_remove(struct pci_dev *pdev)
iounmap(dev->base_addr);
if (dev->mem_region)
release_mem_region(dev->phys_addr,
@@ -224,7 +229,7 @@ index 6490c00..df96b3b 100644
if (dev->active)
pci_disable_device(pdev);
if (dev->registered)
-@@ -3184,9 +3208,16 @@ static int pch_udc_probe(struct pci_dev *pdev,
+@@ -3184,9 +3213,16 @@ static int pch_udc_probe(struct pci_dev *pdev,
dev->active = 1;
pci_set_drvdata(pdev, dev);
@@ -243,7 +248,7 @@ index 6490c00..df96b3b 100644
if (!request_mem_region(resource, len, KBUILD_MODNAME)) {
dev_err(&pdev->dev, "%s: pci device used already\n", __func__);
-@@ -3213,6 +3244,12 @@ static int pch_udc_probe(struct pci_dev *pdev,
+@@ -3213,6 +3249,12 @@ static int pch_udc_probe(struct pci_dev *pdev,
retval = -ENODEV;
goto finished;
}
@@ -256,7 +261,7 @@ index 6490c00..df96b3b 100644
if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
dev)) {
dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,
-@@ -3223,7 +3260,7 @@ static int pch_udc_probe(struct pci_dev *pdev,
+@@ -3223,7 +3265,7 @@ static int pch_udc_probe(struct pci_dev *pdev,
dev->irq = pdev->irq;
dev->irq_registered = 1;
@@ -265,7 +270,7 @@ index 6490c00..df96b3b 100644
pci_try_set_mwi(pdev);
/* device struct setup */
-@@ -3261,6 +3298,11 @@ finished:
+@@ -3261,6 +3303,11 @@ finished:
static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
{
@@ -343,6 +348,3 @@ index 44752f5..e02a4c9 100644
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
device_desc.idProduct =
cpu_to_le16(GS_PRODUCT_ID);
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0013-Quark-stmmac-Ethernet-quark.patch b/recipes-kernel/linux/files/0013-Quark-stmmac-Ethernet-quark.patch
index 99ce791..45ab5a1 100644
--- a/recipes-kernel/linux/files/0013-Quark-stmmac-Ethernet-quark.patch
+++ b/recipes-kernel/linux/files/0013-Quark-stmmac-Ethernet-quark.patch
@@ -1,24 +1,24 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Krzysztof Sywula <krzysztof.m.sywula@intel.com>
-Date: Thu, 20 Feb 2014 15:16:30 +0000
+Date: Wed, 9 Apr 2014 15:29:52 +0100
Subject: [PATCH 13/21] Quark stmmac Ethernet
---
- drivers/net/ethernet/stmicro/stmmac/Kconfig | 25 +-
- drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
- drivers/net/ethernet/stmicro/stmmac/common.h | 14 +-
- drivers/net/ethernet/stmicro/stmmac/descs.h | 45 ++-
- drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 64 ++-
- .../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 139 ++++-
- .../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 9 +-
- .../net/ethernet/stmicro/stmmac/dwmac100_core.c | 6 +-
- drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 1 +
- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 76 ++
- .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 21 +-
- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 163 ++++-
- drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 263 +++++++-
- drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 723 ++++++++++++++++++++
- 14 files changed, 1476 insertions(+), 74 deletions(-)
+ drivers/net/ethernet/stmicro/stmmac/Kconfig | 25 +-
+ drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
+ drivers/net/ethernet/stmicro/stmmac/common.h | 14 +-
+ drivers/net/ethernet/stmicro/stmmac/descs.h | 45 +-
+ drivers/net/ethernet/stmicro/stmmac/dwmac1000.h | 64 +-
+ .../net/ethernet/stmicro/stmmac/dwmac1000_core.c | 139 +++-
+ .../net/ethernet/stmicro/stmmac/dwmac1000_dma.c | 9 +-
+ .../net/ethernet/stmicro/stmmac/dwmac100_core.c | 6 +-
+ drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 1 +
+ drivers/net/ethernet/stmicro/stmmac/stmmac.h | 76 +++
+ .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 21 +-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 163 ++++-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 275 +++++++-
+ drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c | 723 +++++++++++++++++++++
+ 14 files changed, 1488 insertions(+), 74 deletions(-)
create mode 100644 drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -1153,10 +1153,10 @@ index b75f4b2..aaccd3a 100644
free_netdev(ndev);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
-index 064eaac..f7afcad 100644
+index 064eaac..ac32842 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
-@@ -23,32 +23,194 @@
+@@ -23,31 +23,205 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/
@@ -1183,7 +1183,9 @@ index 064eaac..f7afcad 100644
+MODULE_PARM_DESC(enable_msi, "Enable PCI MSI mode");
+
+static int bus_id = 1;
++#if 0
+static char stmmac_mac_data[MAX_INTERFACES][ETH_ALEN];
++#endif
+
+struct stmmac_qrk_mac_data {
+ int phy_addr;
@@ -1252,6 +1254,16 @@ index 064eaac..f7afcad 100644
+ .bus_id = 2,
+ .name = "Galileo",
+ },
++ {
++ .phy_addr = 1,
++ .bus_id = 1,
++ .name = "GalileoGen2",
++ },
++ {
++ .phy_addr = -1, /* not connected */
++ .bus_id = 2,
++ .name = "GalileoGen2",
++ },
+};
+
+
@@ -1270,26 +1282,10 @@ index 064eaac..f7afcad 100644
+
+ return -1;
+}
-
--static void stmmac_default_data(void)
++
+static int stmmac_default_data(struct plat_stmmacenet_data *plat_dat,
+ int mdio_bus_id, const struct pci_device_id *id)
- {
-- memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
-- plat_dat.bus_id = 1;
-- plat_dat.phy_addr = 0;
-- plat_dat.interface = PHY_INTERFACE_MODE_GMII;
-- plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
-- plat_dat.has_gmac = 1;
-- plat_dat.force_sf_dma_mode = 1;
--
-- mdio_data.phy_reset = NULL;
-- mdio_data.phy_mask = 0;
-- plat_dat.mdio_bus_data = &mdio_data;
--
-- dma_cfg.pbl = 32;
-- dma_cfg.burst_len = DMA_AXI_BLEN_256;
-- plat_dat.dma_cfg = &dma_cfg;
++{
+ int phy_addr = 0;
+ memset(plat_dat, 0, sizeof(struct plat_stmmacenet_data));
+
@@ -1342,8 +1338,9 @@ index 064eaac..f7afcad 100644
+ }
+
+ return 0;
- }
++}
+-static void stmmac_default_data(void)
+#if 0
+/**
+ * stmmac_pci_find_mac
@@ -1355,7 +1352,22 @@ index 064eaac..f7afcad 100644
+ * a random one for itself in any case
+ */
+void stmmac_pci_find_mac (struct stmmac_priv * priv, unsigned int mdio_bus_id)
-+{
+ {
+- memset(&plat_dat, 0, sizeof(struct plat_stmmacenet_data));
+- plat_dat.bus_id = 1;
+- plat_dat.phy_addr = 0;
+- plat_dat.interface = PHY_INTERFACE_MODE_GMII;
+- plat_dat.clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
+- plat_dat.has_gmac = 1;
+- plat_dat.force_sf_dma_mode = 1;
+-
+- mdio_data.phy_reset = NULL;
+- mdio_data.phy_mask = 0;
+- plat_dat.mdio_bus_data = &mdio_data;
+-
+- dma_cfg.pbl = 32;
+- dma_cfg.burst_len = DMA_AXI_BLEN_256;
+- plat_dat.dma_cfg = &dma_cfg;
+ unsigned int id = mdio_bus_id - 1;
+ if (priv == NULL || id >= MAX_INTERFACES)
+ return;
@@ -1364,13 +1376,12 @@ index 064eaac..f7afcad 100644
+ (char*)&stmmac_mac_data[id]) == 0){
+ memcpy(priv->dev->dev_addr, &stmmac_mac_data[id], ETH_ALEN);
+ }
-+}
+ }
+#endif
-+
+
/**
* stmmac_pci_probe
- *
-@@ -67,8 +229,21 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+@@ -67,8 +241,21 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
int ret = 0;
void __iomem *addr = NULL;
struct stmmac_priv *priv = NULL;
@@ -1392,7 +1403,7 @@ index 064eaac..f7afcad 100644
/* Enable pci device */
ret = pci_enable_device(pdev);
if (ret) {
-@@ -96,30 +271,51 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
+@@ -96,30 +283,51 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
break;
}
pci_set_master(pdev);
@@ -1449,7 +1460,7 @@ index 064eaac..f7afcad 100644
return ret;
}
-@@ -138,6 +334,21 @@ static void stmmac_pci_remove(struct pci_dev *pdev)
+@@ -138,6 +346,21 @@ static void stmmac_pci_remove(struct pci_dev *pdev)
stmmac_dvr_remove(ndev);
pci_set_drvdata(pdev, NULL);
@@ -1471,7 +1482,7 @@ index 064eaac..f7afcad 100644
pci_iounmap(pdev, priv->ioaddr);
pci_release_regions(pdev);
pci_disable_device(pdev);
-@@ -167,12 +378,10 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
+@@ -167,12 +390,10 @@ static int stmmac_pci_resume(struct pci_dev *pdev)
}
#endif
@@ -2214,6 +2225,3 @@ index 0000000..8552d0c
+ }
+}
+
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0014-Quark-GPIO-2-2-quark.patch b/recipes-kernel/linux/files/0014-Quark-GPIO-2-2-quark.patch
index 9017515..bc6490e 100644
--- a/recipes-kernel/linux/files/0014-Quark-GPIO-2-2-quark.patch
+++ b/recipes-kernel/linux/files/0014-Quark-GPIO-2-2-quark.patch
@@ -1,18 +1,21 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Dan O'Donovan <danielx.o'donovan@intel.com>
-Date: Thu, 13 Feb 2014 16:42:31 +0000
+Date: Wed, 26 Mar 2014 17:36:09 +0000
Subject: [PATCH 14/21] Quark GPIO 2/2
---
- drivers/gpio/gpio-sch.c | 749 ++++++++++++++++++++++++++++++++++++++++-------
- 1 files changed, 638 insertions(+), 111 deletions(-)
+ drivers/gpio/gpio-sch.c | 783 +++++++++++++++++++++++++++++++++++++++++-------
+ 1 file changed, 672 insertions(+), 111 deletions(-)
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
-index edae963..faabd97 100644
+index edae963..a2b5bdc 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
-@@ -28,6 +28,8 @@
+@@ -26,8 +26,11 @@
+ #include <linux/acpi.h>
+ #include <linux/platform_device.h>
#include <linux/pci_ids.h>
++#include <linux/uio_driver.h>
#include <linux/gpio.h>
+#include <linux/interrupt.h>
@@ -20,7 +23,7 @@ index edae963..faabd97 100644
static DEFINE_SPINLOCK(gpio_lock);
-@@ -35,83 +37,168 @@ static DEFINE_SPINLOCK(gpio_lock);
+@@ -35,83 +38,170 @@ static DEFINE_SPINLOCK(gpio_lock);
#define CGIO (0x04)
#define CGLV (0x08)
@@ -49,6 +52,8 @@ index edae963..faabd97 100644
+
+static unsigned long gpio_ba;
+
++static struct uio_info *info;
++
+static int irq_num;
+
+struct sch_gpio_core_int_regvals {
@@ -223,7 +228,7 @@ index edae963..faabd97 100644
static struct gpio_chip sch_gpio_core = {
.label = "sch_gpio_core",
.owner = THIS_MODULE,
-@@ -119,63 +206,198 @@ static struct gpio_chip sch_gpio_core = {
+@@ -119,63 +209,198 @@ static struct gpio_chip sch_gpio_core = {
.get = sch_gpio_core_get,
.direction_output = sch_gpio_core_direction_out,
.set = sch_gpio_core_set,
@@ -236,29 +241,29 @@ index edae963..faabd97 100644
{
- u8 curr_dirs;
+ u32 gpio_num = 0;
-
-- spin_lock(&gpio_lock);
++
+ gpio_num = d->irq - chip_ptr->irq_base_core;
+ sch_gpio_reg_set_if_clear(CGGPE, gpio_num);
+}
-- curr_dirs = inb(gpio_ba + RGIO);
+- spin_lock(&gpio_lock);
+static void sch_gpio_core_irq_disable(struct irq_data *d)
+{
+ u32 gpio_num = 0;
-- if (!(curr_dirs & (1 << gpio_num)))
-- outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
+- curr_dirs = inb(gpio_ba + RGIO);
+ gpio_num = d->irq - chip_ptr->irq_base_core;
+ sch_gpio_reg_clear_if_set(CGGPE, gpio_num);
+}
-- spin_unlock(&gpio_lock);
-- return 0;
+- if (!(curr_dirs & (1 << gpio_num)))
+- outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
+static void sch_gpio_core_irq_ack(struct irq_data *d)
+{
+ u32 gpio_num = 0;
-+
+
+- spin_unlock(&gpio_lock);
+- return 0;
+ gpio_num = d->irq - chip_ptr->irq_base_core;
+ sch_gpio_reg_set(CGTS, gpio_num, 1);
}
@@ -305,8 +310,10 @@ index edae963..faabd97 100644
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ return ret;
-+}
-+
+ }
+
+-static void sch_gpio_resume_set(struct gpio_chip *gc,
+- unsigned gpio_num, int val)
+static struct irq_chip sch_irq_core = {
+ .irq_ack = sch_gpio_core_irq_ack,
+ .irq_set_type = sch_gpio_core_irq_type,
@@ -315,7 +322,8 @@ index edae963..faabd97 100644
+};
+
+static void sch_gpio_core_irqs_init(struct sch_gpio *chip, unsigned int num)
-+{
+ {
+- u8 curr_vals;
+ int i;
+
+ for (i = 0; i < num; i++) {
@@ -325,16 +333,14 @@ index edae963..faabd97 100644
+ handle_simple_irq,
+ "sch_gpio_irq_core");
+ }
- }
++}
--static void sch_gpio_resume_set(struct gpio_chip *gc,
-- unsigned gpio_num, int val)
+- spin_lock(&gpio_lock);
+static void sch_gpio_core_irqs_deinit(struct sch_gpio *chip, unsigned int num)
- {
-- u8 curr_vals;
++{
+ int i;
-- spin_lock(&gpio_lock);
+- curr_vals = inb(gpio_ba + RGLV);
+ for (i = 0; i < num; i++) {
+ irq_set_chip_data(i + chip->irq_base_core, 0);
+ irq_set_chip_and_handler_name(i + chip->irq_base_core,
@@ -342,7 +348,10 @@ index edae963..faabd97 100644
+ }
+}
-- curr_vals = inb(gpio_ba + RGLV);
+- if (val)
+- outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
+- else
+- outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
+static void sch_gpio_core_irq_disable_all(struct sch_gpio *chip,
+ unsigned int num)
+{
@@ -360,11 +369,7 @@ index edae963..faabd97 100644
+ /* clear any pending interrupt */
+ sch_gpio_reg_set(CGTS, gpio_num, 1);
+ }
-
-- if (val)
-- outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
-- else
-- outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
++
+ spin_unlock_irqrestore(&gpio_lock, flags);
- spin_unlock(&gpio_lock);
@@ -387,26 +392,26 @@ index edae963..faabd97 100644
- sch_gpio_resume_set(gc, gpio_num, val);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+}
-
-- spin_lock(&gpio_lock);
++
+void sch_gpio_core_restore_state(struct sch_gpio_core_int_regvals *regs)
+{
+ unsigned long flags = 0;
+ spin_lock_irqsave(&gpio_lock, flags);
-- curr_dirs = inb(gpio_ba + RGIO);
-- if (curr_dirs & (1 << gpio_num))
-- outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
+- spin_lock(&gpio_lock);
+ outb(regs->cgtpe, gpio_ba + CGTPE);
+ outb(regs->cgtne, gpio_ba + CGTNE);
+ outb(regs->cggpe, gpio_ba + CGGPE);
+ outb(regs->cgsmi, gpio_ba + CGSMI);
+ outb(regs->cgnmien, gpio_ba + CGNMIEN);
-- spin_unlock(&gpio_lock);
+- curr_dirs = inb(gpio_ba + RGIO);
+- if (curr_dirs & (1 << gpio_num))
+- outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+}
-+
+
+- spin_unlock(&gpio_lock);
+static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
+ unsigned gpio_num)
+{
@@ -414,9 +419,9 @@ index edae963..faabd97 100644
+ spin_lock_irqsave(&gpio_lock, flags);
+ sch_gpio_reg_set_if_clear(RGIO, gpio_num);
+ spin_unlock_irqrestore(&gpio_lock, flags);
- return 0;
- }
-
++ return 0;
++}
++
+static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+ int res;
@@ -441,9 +446,9 @@ index edae963..faabd97 100644
+ spin_lock_irqsave(&gpio_lock, flags);
+ sch_gpio_reg_clear_if_set(RGIO, gpio_num);
+ spin_unlock_irqrestore(&gpio_lock, flags);
-+ return 0;
-+}
-+
+ return 0;
+ }
+
+static int sch_gpio_resume_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+ return chip_ptr->irq_base_resume + offset;
@@ -452,13 +457,13 @@ index edae963..faabd97 100644
static struct gpio_chip sch_gpio_resume = {
.label = "sch_gpio_resume",
.owner = THIS_MODULE,
-@@ -183,13 +405,203 @@ static struct gpio_chip sch_gpio_resume = {
+@@ -183,17 +408,212 @@ static struct gpio_chip sch_gpio_resume = {
.get = sch_gpio_resume_get,
.direction_output = sch_gpio_resume_direction_out,
.set = sch_gpio_resume_set,
+ .to_irq = sch_gpio_resume_to_irq,
-+};
-+
+ };
+
+static void sch_gpio_resume_irq_enable(struct irq_data *d)
+{
+ u32 gpio_num = 0;
@@ -530,8 +535,8 @@ index edae963..faabd97 100644
+ .irq_set_type = sch_gpio_resume_irq_type,
+ .irq_enable = sch_gpio_resume_irq_enable,
+ .irq_disable = sch_gpio_resume_irq_disable,
- };
-
++};
++
+static void sch_gpio_resume_irqs_init(struct sch_gpio *chip, unsigned int num)
+{
+ int i;
@@ -656,7 +661,16 @@ index edae963..faabd97 100644
id = pdev->id;
if (!id)
return -ENODEV;
-@@ -203,46 +615,56 @@ static int sch_gpio_probe(struct platform_device *pdev)
+
++ /* Get UIO memory */
++ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
++ if (!info)
++ return -ENOMEM;
++
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res)
+ return -EBUSY;
+@@ -203,46 +623,56 @@ static int sch_gpio_probe(struct platform_device *pdev)
gpio_ba = res->start;
@@ -752,7 +766,7 @@ index edae963..faabd97 100644
}
sch_gpio_core.dev = &pdev->dev;
-@@ -256,44 +678,147 @@ static int sch_gpio_probe(struct platform_device *pdev)
+@@ -256,44 +686,173 @@ static int sch_gpio_probe(struct platform_device *pdev)
if (err < 0)
goto err_sch_gpio_resume;
@@ -796,8 +810,26 @@ index edae963..faabd97 100644
+ sch_gpio_core_irqs_init(chip, sch_gpio_core.ngpio);
+ sch_gpio_resume_irqs_init(chip, sch_gpio_resume.ngpio);
+
++ /* UIO */
++ info->port[0].name = "gpio_regs";
++ info->port[0].start = res->start;
++ info->port[0].size = resource_size(res);
++ info->port[0].porttype = UIO_PORT_X86;
++ info->name = "sch_gpio";
++ info->version = "0.0.1";
++
++ if (uio_register_device(&pdev->dev, info))
++ goto err_sch_uio_register;
++
++ pr_info("%s UIO port addr 0x%04x size %lu porttype %d\n",
++ __func__, (unsigned int)info->port[0].start,
++ info->port[0].size, info->port[0].porttype);
++
return 0;
++err_sch_uio_register:
++ free_irq(irq_num, chip);
++
+err_sch_request_irq:
+ platform_device_unregister(&qrk_gpio_restrict_pdev);
+
@@ -830,6 +862,9 @@ index edae963..faabd97 100644
+ kfree(chip);
+ chip_ptr = 0;
+
++ if (info != NULL)
++ kfree(info);
++
return err;
}
@@ -844,6 +879,11 @@ index edae963..faabd97 100644
- int err;
- err = gpiochip_remove(&sch_gpio_core);
++ if (info != NULL) {
++ uio_unregister_device(info);
++ kfree(info);
++ }
++
+ sch_gpio_resume_irqs_deinit(chip, sch_gpio_resume.ngpio);
+ sch_gpio_core_irqs_deinit(chip, sch_gpio_core.ngpio);
+
@@ -908,7 +948,7 @@ index edae963..faabd97 100644
return 0;
}
-@@ -304,6 +829,8 @@ static struct platform_driver sch_gpio_driver = {
+@@ -304,6 +863,8 @@ static struct platform_driver sch_gpio_driver = {
},
.probe = sch_gpio_probe,
.remove = sch_gpio_remove,
@@ -917,6 +957,3 @@ index edae963..faabd97 100644
};
module_platform_driver(sch_gpio_driver);
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch b/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch
index ec541dc..4fabc14 100644
--- a/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch
+++ b/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch
@@ -1,17 +1,18 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Josef Ahmad <josef.ahmad@linux.intel.com>
-Date: Tue, 11 Feb 2014 16:28:26 +0000
+Date: Wed, 9 Apr 2014 16:57:30 +0100
Subject: [PATCH 15/21] Quark GPIO 1/2
---
- drivers/gpio/Kconfig | 7 ++-
- drivers/gpio/gpiolib.c | 130 ++++++++++++++++++++++++++++++++++++++++++++
- include/asm-generic/gpio.h | 4 ++
- include/linux/gpio.h | 10 ++++
- 4 files changed, 149 insertions(+), 2 deletions(-)
+ drivers/gpio/Kconfig | 9 +-
+ drivers/gpio/gpio-pca953x.c | 235 ++++++++++++++++++++++++++++++++++----------
+ drivers/gpio/gpiolib.c | 130 ++++++++++++++++++++++++
+ include/asm-generic/gpio.h | 4 +
+ include/linux/gpio.h | 10 ++
+ 5 files changed, 332 insertions(+), 56 deletions(-)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
-index 682de75..afab416 100644
+index 682de75..447e51a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -243,13 +243,14 @@ config GPIO_VR41XX
@@ -40,6 +41,430 @@ index 682de75..afab416 100644
config GPIO_ICH
tristate "Intel ICH GPIO"
+@@ -363,7 +366,7 @@ config GPIO_PCA953X
+
+ config GPIO_PCA953X_IRQ
+ bool "Interrupt controller support for PCA953x"
+- depends on GPIO_PCA953X=y
++ depends on GPIO_PCA953X
+ help
+ Say yes here to enable the pca953x to be used as an interrupt
+ controller. It requires the driver to be built in the kernel.
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index cc102d2..6ac3b87 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -29,6 +29,12 @@
+ #define PCA953X_INVERT 2
+ #define PCA953X_DIRECTION 3
+
++#define PCAL953X_IN_LATCH 34
++#define PCAL953X_PUPD_EN 35
++#define PCAL953X_PUPD_SEL 36
++#define PCAL953X_INT_MASK 37
++#define PCAL953X_INT_STAT 38
++
+ #define REG_ADDR_AI 0x80
+
+ #define PCA957X_IN 0
+@@ -44,29 +50,32 @@
+ #define PCA_INT 0x0100
+ #define PCA953X_TYPE 0x1000
+ #define PCA957X_TYPE 0x2000
++#define PCAL953X_TYPE 0x4000
++
+
+ static const struct i2c_device_id pca953x_id[] = {
+- { "pca9534", 8 | PCA953X_TYPE | PCA_INT, },
+- { "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
+- { "pca9536", 4 | PCA953X_TYPE, },
+- { "pca9537", 4 | PCA953X_TYPE | PCA_INT, },
+- { "pca9538", 8 | PCA953X_TYPE | PCA_INT, },
+- { "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
+- { "pca9554", 8 | PCA953X_TYPE | PCA_INT, },
+- { "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
+- { "pca9556", 8 | PCA953X_TYPE, },
+- { "pca9557", 8 | PCA953X_TYPE, },
+- { "pca9574", 8 | PCA957X_TYPE | PCA_INT, },
+- { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
+-
+- { "max7310", 8 | PCA953X_TYPE, },
+- { "max7312", 16 | PCA953X_TYPE | PCA_INT, },
+- { "max7313", 16 | PCA953X_TYPE | PCA_INT, },
+- { "max7315", 8 | PCA953X_TYPE | PCA_INT, },
+- { "pca6107", 8 | PCA953X_TYPE | PCA_INT, },
+- { "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
+- { "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
+- { "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
++ { "pca9534", 8 | PCA953X_TYPE | PCA_INT, },
++ { "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
++ { "pca9536", 4 | PCA953X_TYPE, },
++ { "pca9537", 4 | PCA953X_TYPE | PCA_INT, },
++ { "pca9538", 8 | PCA953X_TYPE | PCA_INT, },
++ { "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
++ { "pca9554", 8 | PCA953X_TYPE | PCA_INT, },
++ { "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
++ { "pcal9555a", 16 | PCAL953X_TYPE | PCA_INT, },
++ { "pca9556", 8 | PCA953X_TYPE, },
++ { "pca9557", 8 | PCA953X_TYPE, },
++ { "pca9574", 8 | PCA957X_TYPE | PCA_INT, },
++ { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
++
++ { "max7310", 8 | PCA953X_TYPE, },
++ { "max7312", 16 | PCA953X_TYPE | PCA_INT, },
++ { "max7313", 16 | PCA953X_TYPE | PCA_INT, },
++ { "max7315", 8 | PCA953X_TYPE | PCA_INT, },
++ { "pca6107", 8 | PCA953X_TYPE | PCA_INT, },
++ { "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
++ { "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
++ { "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
+ { }
+ };
+ MODULE_DEVICE_TABLE(i2c, pca953x_id);
+@@ -75,6 +84,8 @@ struct pca953x_chip {
+ unsigned gpio_start;
+ u32 reg_output;
+ u32 reg_direction;
++ u32 reg_pupd_en;
++ u32 reg_pupd_sel;
+ struct mutex i2c_lock;
+
+ #ifdef CONFIG_GPIO_PCA953X_IRQ
+@@ -105,9 +116,9 @@ static int pca953x_write_reg(struct pca953x_chip *chip, int reg, u32 val)
+ (reg << 2) | REG_ADDR_AI,
+ 3,
+ (u8 *) &val);
+- }
+- else {
++ } else {
+ switch (chip->chip_type) {
++ case PCAL953X_TYPE:
+ case PCA953X_TYPE:
+ ret = i2c_smbus_write_word_data(chip->client,
+ reg << 1, val);
+@@ -139,8 +150,7 @@ static int pca953x_read_reg(struct pca953x_chip *chip, int reg, u32 *val)
+ if (chip->gpio_chip.ngpio <= 8) {
+ ret = i2c_smbus_read_byte_data(chip->client, reg);
+ *val = ret;
+- }
+- else if (chip->gpio_chip.ngpio == 24) {
++ } else if (chip->gpio_chip.ngpio == 24) {
+ *val = 0;
+ ret = i2c_smbus_read_i2c_block_data(chip->client,
+ (reg << 2) | REG_ADDR_AI,
+@@ -172,6 +182,7 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+ reg_val = chip->reg_direction | (1u << off);
+
+ switch (chip->chip_type) {
++ case PCAL953X_TYPE:
+ case PCA953X_TYPE:
+ offset = PCA953X_DIRECTION;
+ break;
+@@ -207,6 +218,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
+ reg_val = chip->reg_output & ~(1u << off);
+
+ switch (chip->chip_type) {
++ case PCAL953X_TYPE:
+ case PCA953X_TYPE:
+ offset = PCA953X_OUTPUT;
+ break;
+@@ -223,6 +235,7 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc,
+ /* then direction */
+ reg_val = chip->reg_direction & ~(1u << off);
+ switch (chip->chip_type) {
++ case PCAL953X_TYPE:
+ case PCA953X_TYPE:
+ offset = PCA953X_DIRECTION;
+ break;
+@@ -251,6 +264,7 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+
+ mutex_lock(&chip->i2c_lock);
+ switch (chip->chip_type) {
++ case PCAL953X_TYPE:
+ case PCA953X_TYPE:
+ offset = PCA953X_INPUT;
+ break;
+@@ -286,6 +300,7 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+ reg_val = chip->reg_output & ~(1u << off);
+
+ switch (chip->chip_type) {
++ case PCAL953X_TYPE:
+ case PCA953X_TYPE:
+ offset = PCA953X_OUTPUT;
+ break;
+@@ -302,6 +317,60 @@ exit:
+ mutex_unlock(&chip->i2c_lock);
+ }
+
++static int pca953x_gpio_set_drive(struct gpio_chip *gc,
++ unsigned off, unsigned mode)
++{
++ struct pca953x_chip *chip;
++ u32 pupd_en_reg_val, pupd_sel_reg_val;
++ int ret = 0;
++
++ chip = container_of(gc, struct pca953x_chip, gpio_chip);
++
++ if (chip->chip_type != PCAL953X_TYPE)
++ return -EINVAL;
++
++ mutex_lock(&chip->i2c_lock);
++
++ switch (mode) {
++ case GPIOF_DRIVE_PULLUP:
++ pupd_en_reg_val = chip->reg_pupd_en | (1u << off);
++ pupd_sel_reg_val = chip->reg_pupd_sel | (1u << off);
++ break;
++ case GPIOF_DRIVE_PULLDOWN:
++ pupd_en_reg_val = chip->reg_pupd_en | (1u << off);
++ pupd_sel_reg_val = chip->reg_pupd_sel & ~(1u << off);
++ break;
++ case GPIOF_DRIVE_STRONG:
++ case GPIOF_DRIVE_HIZ:
++ pupd_en_reg_val = chip->reg_pupd_en & ~(1u << off);
++ pupd_sel_reg_val = chip->reg_pupd_sel;
++ break;
++ default:
++ ret = -EINVAL;
++ goto exit;
++ }
++
++ if (pupd_en_reg_val != chip->reg_pupd_en) {
++ ret = pca953x_write_reg(chip, PCAL953X_PUPD_EN,
++ pupd_en_reg_val);
++ if (ret)
++ goto exit;
++ chip->reg_pupd_en = pupd_en_reg_val;
++ }
++
++ if (pupd_sel_reg_val != chip->reg_pupd_sel) {
++ ret = pca953x_write_reg(chip, PCAL953X_PUPD_SEL,
++ pupd_sel_reg_val);
++ if (ret)
++ goto exit;
++ chip->reg_pupd_sel = pupd_sel_reg_val;
++ }
++
++exit:
++ mutex_unlock(&chip->i2c_lock);
++ return ret;
++}
++
+ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+ {
+ struct gpio_chip *gc;
+@@ -320,6 +389,9 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+ gc->dev = &chip->client->dev;
+ gc->owner = THIS_MODULE;
+ gc->names = chip->names;
++
++ if (chip->chip_type == PCAL953X_TYPE)
++ gc->set_drive = pca953x_gpio_set_drive;
+ }
+
+ #ifdef CONFIG_GPIO_PCA953X_IRQ
+@@ -368,6 +440,15 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
+ new_irqs &= ~(1 << level);
+ }
+
++ if (chip->chip_type == PCAL953X_TYPE) {
++ /* Enable latch on interrupt-enabled inputs */
++ pca953x_write_reg(chip, PCAL953X_IN_LATCH,
++ chip->irq_mask);
++ /* Unmask enabled interrupts */
++ pca953x_write_reg(chip, PCAL953X_INT_MASK,
++ ~chip->irq_mask);
++ }
++
+ mutex_unlock(&chip->irq_lock);
+ }
+
+@@ -412,6 +493,24 @@ static u32 pca953x_irq_pending(struct pca953x_chip *chip)
+ u32 trigger;
+ int ret, offset = 0;
+
++ if (chip->chip_type == PCAL953X_TYPE) {
++ /* Read the current interrupt status from the device */
++ ret = pca953x_read_reg(chip, PCAL953X_INT_STAT, &pending);
++ if (ret)
++ return 0;
++
++ /* Check latched inputs and clear interrupt status */
++ ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat);
++ if (ret)
++ return 0;
++
++ /* Apply filter for rising/falling edge selection */
++ pending &= (~cur_stat & chip->irq_trig_fall) |
++ (cur_stat & chip->irq_trig_raise);
++
++ return pending;
++ }
++
+ switch (chip->chip_type) {
+ case PCA953X_TYPE:
+ offset = PCA953X_INPUT;
+@@ -468,37 +567,43 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
+ int irq_base)
+ {
+ struct i2c_client *client = chip->client;
+- int ret, offset = 0;
++ int ret = 0, offset = 0;
++ unsigned long flags;
+ u32 temporary;
+
+ if (irq_base != -1
+ && (id->driver_data & PCA_INT)) {
+ int lvl;
+
+- switch (chip->chip_type) {
+- case PCA953X_TYPE:
+- offset = PCA953X_INPUT;
+- break;
+- case PCA957X_TYPE:
+- offset = PCA957X_IN;
+- break;
++ if (chip->chip_type != PCAL953X_TYPE) {
++ switch (chip->chip_type) {
++ case PCA953X_TYPE:
++ offset = PCA953X_INPUT;
++ break;
++ case PCA957X_TYPE:
++ offset = PCA957X_IN;
++ break;
++ }
++ ret = pca953x_read_reg(chip, offset, &temporary);
++ chip->irq_stat = temporary;
++ if (ret)
++ goto out_failed;
++
++ /*
++ * There is no way to know which GPIO line generated the
++ * interrupt. We have to rely on the previous read for
++ * this purpose.
++ */
++ chip->irq_stat &= chip->reg_direction;
+ }
+- ret = pca953x_read_reg(chip, offset, &temporary);
+- chip->irq_stat = temporary;
+- if (ret)
+- goto out_failed;
+-
+- /*
+- * There is no way to know which GPIO line generated the
+- * interrupt. We have to rely on the previous read for
+- * this purpose.
+- */
+- chip->irq_stat &= chip->reg_direction;
+ mutex_init(&chip->irq_lock);
+
+- chip->irq_base = irq_alloc_descs(-1, irq_base, chip->gpio_chip.ngpio, -1);
+- if (chip->irq_base < 0)
++ chip->irq_base = irq_alloc_descs(-1, irq_base,
++ chip->gpio_chip.ngpio, -1);
++ if (chip->irq_base < 0) {
++ ret = chip->irq_base;
+ goto out_failed;
++ }
+
+ chip->domain = irq_domain_add_legacy(client->dev.of_node,
+ chip->gpio_chip.ngpio,
+@@ -525,10 +630,15 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
+ #endif
+ }
+
++ if (chip->chip_type == PCAL953X_TYPE)
++ flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
++ else
++ flags = IRQF_TRIGGER_LOW | IRQF_ONESHOT;
++
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ pca953x_irq_handler,
+- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
++ flags,
+ dev_name(&client->dev), chip);
+ if (ret) {
+ dev_err(&client->dev, "failed to request irq %d\n",
+@@ -537,6 +647,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
+ }
+
+ chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
++ } else {
++ chip->irq_base = -1;
+ }
+
+ return 0;
+@@ -594,7 +706,8 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
+
+ *gpio_base = -1;
+ val = of_get_property(node, "linux,gpio-base", &size);
+- WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!", __func__);
++ WARN(val, "%s: device-tree property 'linux,gpio-base' is deprecated!",
++ __func__);
+ if (val) {
+ if (size != sizeof(*val))
+ dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
+@@ -604,7 +717,8 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, u32 *invert)
+ }
+
+ val = of_get_property(node, "polarity", NULL);
+- WARN(val, "%s: device-tree property 'polarity' is deprecated!", __func__);
++ WARN(val, "%s: device-tree property 'polarity' is deprecated!",
++ __func__);
+ if (val)
+ *invert = *val;
+ }
+@@ -620,6 +734,18 @@ static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+ {
+ int ret;
+
++ if (chip->chip_type == PCAL953X_TYPE) {
++ ret = pca953x_read_reg(chip, PCAL953X_PUPD_EN,
++ &chip->reg_pupd_en);
++ if (ret)
++ goto out;
++
++ ret = pca953x_read_reg(chip, PCAL953X_PUPD_SEL,
++ &chip->reg_pupd_sel);
++ if (ret)
++ goto out;
++ }
++
+ ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
+ if (ret)
+ goto out;
+@@ -688,15 +814,18 @@ static int pca953x_probe(struct i2c_client *client,
+ } else {
+ pca953x_get_alt_pdata(client, &chip->gpio_start, &invert);
+ #ifdef CONFIG_OF_GPIO
+- /* If I2C node has no interrupts property, disable GPIO interrupts */
+- if (of_find_property(client->dev.of_node, "interrupts", NULL) == NULL)
++ /* If I2C node has no interrupts property, disable
++ * GPIO interrupts */
++ if (of_find_property(client->dev.of_node,
++ "interrupts", NULL) == NULL)
+ irq_base = -1;
+ #endif
+ }
+
+ chip->client = client;
+
+- chip->chip_type = id->driver_data & (PCA953X_TYPE | PCA957X_TYPE);
++ chip->chip_type = id->driver_data &
++ (PCAL953X_TYPE | PCA953X_TYPE | PCA957X_TYPE);
+
+ mutex_init(&chip->i2c_lock);
+
+@@ -705,7 +834,7 @@ static int pca953x_probe(struct i2c_client *client,
+ */
+ pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
+
+- if (chip->chip_type == PCA953X_TYPE)
++ if (chip->chip_type & (PCA953X_TYPE | PCAL953X_TYPE))
+ ret = device_pca953x_init(chip, invert);
+ else
+ ret = device_pca957x_init(chip, invert);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5359ca7..5e897ff 100644
--- a/drivers/gpio/gpiolib.c
@@ -267,6 +692,3 @@ index bfe6656..cadd9d2 100644
static inline int gpio_get_value(unsigned gpio)
{
/* GPIO can never have been requested or set as {in,out}put */
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch b/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch
index 8488759..811e609 100644
--- a/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch
+++ b/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch
@@ -1,22 +1,27 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Josef Ahmad <josef.ahmad@linux.intel.com>
-Date: Tue, 25 Feb 2014 12:09:04 +0000
+Date: Mon, 31 Mar 2014 18:03:09 +0100
Subject: [PATCH 16/21] Quark GIP + Cypress I/O expander
---
- drivers/mfd/Kconfig | 38 +
- drivers/mfd/Makefile | 8 +
- drivers/mfd/cy8c9540a.c | 970 ++++++++++++++++++++++++++
- drivers/mfd/intel_qrk_gip.h | 104 +++
- drivers/mfd/intel_qrk_gip_core.c | 335 +++++++++
- drivers/mfd/intel_qrk_gip_gpio.c | 659 ++++++++++++++++++
- drivers/mfd/intel_qrk_gip_i2c.c | 248 +++++++
- drivers/mfd/intel_qrk_gip_pdata.c | 25 +
- drivers/mfd/intel_qrk_gip_test.c | 1131 +++++++++++++++++++++++++++++++
+ drivers/mfd/Kconfig | 48 ++
+ drivers/mfd/Makefile | 10 +
+ drivers/mfd/cy8c9540a.c | 963 ++++++++++++++++++++++++++
+ drivers/mfd/intel_qrk_gip.h | 97 +++
+ drivers/mfd/intel_qrk_gip_core.c | 328 +++++++++
+ drivers/mfd/intel_qrk_gip_gpio.c | 652 ++++++++++++++++++
+ drivers/mfd/intel_qrk_gip_i2c.c | 241 +++++++
+ drivers/mfd/intel_qrk_gip_pdata.c | 18 +
+ drivers/mfd/intel_qrk_gip_test.c | 1124 +++++++++++++++++++++++++++++++
drivers/mfd/lpc_sch.c | 76 ++-
- include/linux/mfd/cy8c9540a.h | 38 +
- include/linux/mfd/intel_qrk_gip_pdata.h | 32 +
- 12 files changed, 3651 insertions(+), 13 deletions(-)
+ drivers/mfd/pca9685-core.c | 283 ++++++++
+ drivers/mfd/pca9685-gpio.c | 108 +++
+ drivers/mfd/pca9685-pwm.c | 262 +++++++
+ drivers/mfd/pca9685.h | 110 +++
+ include/linux/mfd/cy8c9540a.h | 31 +
+ include/linux/mfd/intel_qrk_gip_pdata.h | 25 +
+ include/linux/platform_data/pca9685.h | 51 ++
+ 17 files changed, 4414 insertions(+), 13 deletions(-)
create mode 100644 drivers/mfd/cy8c9540a.c
create mode 100644 drivers/mfd/intel_qrk_gip.h
create mode 100644 drivers/mfd/intel_qrk_gip_core.c
@@ -24,14 +29,19 @@ Subject: [PATCH 16/21] Quark GIP + Cypress I/O expander
create mode 100644 drivers/mfd/intel_qrk_gip_i2c.c
create mode 100644 drivers/mfd/intel_qrk_gip_pdata.c
create mode 100644 drivers/mfd/intel_qrk_gip_test.c
+ create mode 100644 drivers/mfd/pca9685-core.c
+ create mode 100644 drivers/mfd/pca9685-gpio.c
+ create mode 100644 drivers/mfd/pca9685-pwm.c
+ create mode 100644 drivers/mfd/pca9685.h
create mode 100644 include/linux/mfd/cy8c9540a.h
create mode 100644 include/linux/mfd/intel_qrk_gip_pdata.h
+ create mode 100644 include/linux/platform_data/pca9685.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
-index ff553ba..b8029bd 100644
+index ff553ba..74358c2 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
-@@ -907,6 +907,44 @@ config MFD_TIMBERDALE
+@@ -907,6 +907,54 @@ config MFD_TIMBERDALE
The timberdale FPGA can be found on the Intel Atom development board
for in-vehicle infontainment, called Russellville.
@@ -44,6 +54,16 @@ index ff553ba..b8029bd 100644
+ Select this option to enable support for the CY8C9540 I/O expander.
+ This device provides 40 interrupt-capable GPIOs, 8 PWMs and an EEPROM.
+
++config MFD_PCA9685
++ tristate "NPX Semiconductors PCA9685 (PWM/GPIO) driver"
++ depends on GPIOLIB && I2C && PWM
++ select REGMAP_I2C
++ help
++ NPX PCA9685 I2C-bus PWM controller with GPIO output interface support.
++ The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+.
++ Additionally, the driver allows the channels to be configured as GPIO
++ interface (output only).
++
+config INTEL_QRK_GIP
+ tristate "Intel Quark GIP"
+ depends on PCI && X86 && INTEL_QUARK_X1000_SOC
@@ -77,14 +97,16 @@ index ff553ba..b8029bd 100644
tristate "Intel SCH LPC"
depends on PCI
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
-index 8b977f8..b17d50c 100644
+index 8b977f8..38706ff 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
-@@ -123,6 +123,14 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
+@@ -123,6 +123,16 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
+obj-$(CONFIG_CY8C9540A) += cy8c9540a.o
++pca9685-objs := pca9685-core.o pca9685-gpio.o pca9685-pwm.o
++obj-$(CONFIG_MFD_PCA9685) += pca9685.o
+obj-$(CONFIG_INTEL_QRK_GIP) += intel_qrk_gip.o
+intel_qrk_gip-objs := intel_qrk_gip_core.o \
+ intel_qrk_gip_gpio.o \
@@ -97,28 +119,21 @@ index 8b977f8..b17d50c 100644
obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o
diff --git a/drivers/mfd/cy8c9540a.c b/drivers/mfd/cy8c9540a.c
new file mode 100644
-index 0000000..444e5ab
+index 0000000..9e3966a
--- /dev/null
+++ b/drivers/mfd/cy8c9540a.c
-@@ -0,0 +1,970 @@
+@@ -0,0 +1,963 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+
+/*
@@ -1073,28 +1088,21 @@ index 0000000..444e5ab
+
diff --git a/drivers/mfd/intel_qrk_gip.h b/drivers/mfd/intel_qrk_gip.h
new file mode 100644
-index 0000000..d1e8316
+index 0000000..3dfc487
--- /dev/null
+++ b/drivers/mfd/intel_qrk_gip.h
-@@ -0,0 +1,104 @@
+@@ -0,0 +1,97 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark GIP (GPIO/I2C) driver
@@ -1183,28 +1191,21 @@ index 0000000..d1e8316
+#endif /* __INTEL_QRKGIP_H__ */
diff --git a/drivers/mfd/intel_qrk_gip_core.c b/drivers/mfd/intel_qrk_gip_core.c
new file mode 100644
-index 0000000..8b8727b
+index 0000000..44209f0
--- /dev/null
+++ b/drivers/mfd/intel_qrk_gip_core.c
-@@ -0,0 +1,335 @@
+@@ -0,0 +1,328 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark GIP (GPIO/I2C) PCI driver
@@ -1524,28 +1525,21 @@ index 0000000..8b8727b
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/mfd/intel_qrk_gip_gpio.c b/drivers/mfd/intel_qrk_gip_gpio.c
new file mode 100644
-index 0000000..ef19e2f
+index 0000000..f823957
--- /dev/null
+++ b/drivers/mfd/intel_qrk_gip_gpio.c
-@@ -0,0 +1,659 @@
+@@ -0,0 +1,652 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark GIP (GPIO/I2C) - GPIO-specific PCI and core driver
@@ -2189,28 +2183,21 @@ index 0000000..ef19e2f
+}
diff --git a/drivers/mfd/intel_qrk_gip_i2c.c b/drivers/mfd/intel_qrk_gip_i2c.c
new file mode 100644
-index 0000000..9ecbeb5
+index 0000000..08e8f9d
--- /dev/null
+++ b/drivers/mfd/intel_qrk_gip_i2c.c
-@@ -0,0 +1,248 @@
+@@ -0,0 +1,241 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark GIP (GPIO/I2C) - I2C-specific PCI driver
@@ -2443,28 +2430,21 @@ index 0000000..9ecbeb5
+}
diff --git a/drivers/mfd/intel_qrk_gip_pdata.c b/drivers/mfd/intel_qrk_gip_pdata.c
new file mode 100644
-index 0000000..a764215
+index 0000000..cc230be
--- /dev/null
+++ b/drivers/mfd/intel_qrk_gip_pdata.c
-@@ -0,0 +1,25 @@
+@@ -0,0 +1,18 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+
+#include <linux/module.h>
@@ -2474,28 +2454,21 @@ index 0000000..a764215
+EXPORT_SYMBOL_GPL(intel_qrk_gip_get_pdata);
diff --git a/drivers/mfd/intel_qrk_gip_test.c b/drivers/mfd/intel_qrk_gip_test.c
new file mode 100644
-index 0000000..2b07e9e
+index 0000000..e444c81
--- /dev/null
+++ b/drivers/mfd/intel_qrk_gip_test.c
-@@ -0,0 +1,1131 @@
+@@ -0,0 +1,1124 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+/*
+ * Intel Quark GIP (GPIO/I2C) Test module
@@ -3735,30 +3708,810 @@ index 5624fcb..4afc687 100644
if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC
|| id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) {
pci_read_config_dword(dev, WDTBASE, &base_addr_cfg);
-diff --git a/include/linux/mfd/cy8c9540a.h b/include/linux/mfd/cy8c9540a.h
+diff --git a/drivers/mfd/pca9685-core.c b/drivers/mfd/pca9685-core.c
new file mode 100644
-index 0000000..a32c6f0
+index 0000000..11cb8d9
--- /dev/null
-+++ b/include/linux/mfd/cy8c9540a.h
-@@ -0,0 +1,38 @@
++++ b/drivers/mfd/pca9685-core.c
+@@ -0,0 +1,283 @@
+/*
++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface
++ * support.
++ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+.
++ * Additionally, the driver allows the channels to be configured as GPIO
++ * interface (output only).
++ */
++
++#include <linux/i2c.h>
++#include <linux/module.h>
++#include <linux/pwm.h>
++#include <linux/gpio.h>
++#include <linux/regmap.h>
++#include <linux/slab.h>
++
++#include "pca9685.h"
++
++static unsigned int en_invrt;
++module_param(en_invrt, uint, 0);
++MODULE_PARM_DESC(en_invrt, "Enable output logic state inverted mode");
++
++static unsigned int en_open_dr;
++module_param(en_open_dr, uint, 0);
++MODULE_PARM_DESC(en_open_dr,
++ "The outputs are configured with an open-drain structure");
++
++static int gpio_base = -1; /* requests dynamic ID allocation */
++module_param(gpio_base, int, 0);
++MODULE_PARM_DESC(gpio_base, "GPIO base number");
++
++static unsigned int pwm_period = PWM_PERIOD_DEF; /* PWM clock period */
++module_param(pwm_period, uint, 0);
++MODULE_PARM_DESC(pwm_period, "PWM clock period (nanoseconds)");
++
++static bool pca9685_register_volatile(struct device *dev, unsigned int reg)
++{
++ if (unlikely(reg == PCA9685_MODE1))
++ return true;
++ else
++ return false;
++}
++
++static struct regmap_config pca9685_regmap_i2c_config = {
++ .reg_bits = 8,
++ .val_bits = 8,
++ .max_register = PCA9685_NUMREGS,
++ .volatile_reg = pca9685_register_volatile,
++ .cache_type = REGCACHE_RBTREE,
++};
++
++ssize_t pca9685_pwm_period_sysfs_show(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct pca9685 *pca = dev_get_drvdata(dev);
++
++ return scnprintf(buf, PAGE_SIZE, "%u\n", pca->pwm_period);
++}
++
++ssize_t pca9685_pwm_period_sysfs_store(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf, size_t count)
++{
++ struct pca9685 *pca = dev_get_drvdata(dev);
++ unsigned period_ns;
++ int ret;
++
++ sscanf(buf, "%u", &period_ns);
++
++ ret = pca9685_update_prescale(pca, period_ns, true);
++ if (ret)
++ return ret;
++
++ return count;
++}
++
++/* Sysfs attribute to allow PWM clock period adjustment at run-time
++ * NOTE: All active channels will switch off momentarily if the
++ * PWM clock period is changed
++ */
++static DEVICE_ATTR(pwm_period, S_IWUSR | S_IRUGO,
++ pca9685_pwm_period_sysfs_show,
++ pca9685_pwm_period_sysfs_store);
++
++static int pca9685_probe(struct i2c_client *client,
++ const struct i2c_device_id *id)
++{
++ struct pca9685_pdata *pdata;
++ struct pca9685 *pca;
++ int ret;
++ int mode2;
++
++ pca = devm_kzalloc(&client->dev, sizeof(*pca), GFP_KERNEL);
++ if (unlikely(!pca))
++ return -ENOMEM;
++
++ pdata = client->dev.platform_data;
++ if (likely(pdata)) {
++ memcpy(pca->chan_mapping, pdata->chan_mapping,
++ ARRAY_SIZE(pca->chan_mapping));
++ pca->gpio_base = pdata->gpio_base;
++ en_invrt = pdata->en_invrt;
++ en_open_dr = pdata->en_open_dr;
++ } else {
++ dev_warn(&client->dev,
++ "Platform data not provided."
++ "Using default or mod params configuration.\n");
++ pca->gpio_base = gpio_base;
++ memset(pca->chan_mapping, PWM_CH_UNDEFINED,
++ ARRAY_SIZE(pca->chan_mapping));
++ }
++
++ if (unlikely(!i2c_check_functionality(client->adapter,
++ I2C_FUNC_I2C |
++ I2C_FUNC_SMBUS_BYTE_DATA))) {
++ dev_err(&client->dev,
++ "i2c adapter doesn't support required functionality\n");
++ return -EIO;
++ }
++
++ pca->regmap = devm_regmap_init_i2c(client, &pca9685_regmap_i2c_config);
++ if (IS_ERR(pca->regmap)) {
++ ret = PTR_ERR(pca->regmap);
++ dev_err(&client->dev, "Failed to initialize register map: %d\n",
++ ret);
++ return ret;
++ }
++
++ i2c_set_clientdata(client, pca);
++
++ /* registration of GPIO chip */
++ pca->gpio_chip.label = "pca9685-gpio";
++ pca->gpio_chip.owner = THIS_MODULE;
++ pca->gpio_chip.set = pca9685_gpio_set;
++ pca->gpio_chip.get = pca9685_gpio_get;
++ pca->gpio_chip.can_sleep = 1;
++ pca->gpio_chip.ngpio = PCA9685_MAXCHAN;
++ pca->gpio_chip.base = pca->gpio_base;
++ pca->gpio_chip.request = pca9685_gpio_request;
++ pca->gpio_chip.free = pca9685_gpio_free;
++
++ mutex_init(&pca->lock);
++
++ ret = gpiochip_add(&pca->gpio_chip);
++ if (unlikely(ret < 0)) {
++ dev_err(&client->dev, "Could not register gpiochip, %d\n", ret);
++ goto err;
++ }
++
++ /* configure initial PWM settings */
++ ret = pca9685_init_pwm_regs(pca, pwm_period);
++ if (ret) {
++ pr_err("Failed to initialize PWM registers\n");
++ goto err_gpiochip;
++ }
++
++ /* registration of PWM chip */
++
++ regmap_read(pca->regmap, PCA9685_MODE2, &mode2);
++
++ /* update mode2 register */
++ if (en_invrt)
++ mode2 |= MODE2_INVRT;
++ else
++ mode2 &= ~MODE2_INVRT;
++
++ if (en_open_dr)
++ mode2 &= ~MODE2_OUTDRV;
++ else
++ mode2 |= MODE2_OUTDRV;
++
++ regmap_write(pca->regmap, PCA9685_MODE2, mode2);
++
++ pca->pwm_chip.ops = &pca9685_pwm_ops;
++ /* add an extra channel for ALL_LED */
++ pca->pwm_chip.npwm = PCA9685_MAXCHAN + 1;
++ pca->pwm_chip.dev = &client->dev;
++ pca->pwm_chip.base = -1;
++
++ ret = pwmchip_add(&pca->pwm_chip);
++ if (unlikely(ret < 0)) {
++ dev_err(&client->dev, "pwmchip_add failed %d\n", ret);
++ goto err_gpiochip;
++ }
++
++ /* Also create a sysfs interface, providing a cmd line config option */
++ ret = sysfs_create_file(&client->dev.kobj, &dev_attr_pwm_period.attr);
++ if (unlikely(ret < 0)) {
++ dev_err(&client->dev, "sysfs_create_file failed %d\n", ret);
++ goto err_pwmchip;
++ }
++
++ return ret;
++
++err_pwmchip:
++ if (unlikely(pwmchip_remove(&pca->pwm_chip)))
++ dev_warn(&client->dev, "%s failed\n", "pwmchip_remove()");
++
++err_gpiochip:
++ if (unlikely(gpiochip_remove(&pca->gpio_chip)))
++ dev_warn(&client->dev, "%s failed\n", "gpiochip_remove()");
++err:
++ mutex_destroy(&pca->lock);
++
++ return ret;
++}
++
++static int pca9685_remove(struct i2c_client *client)
++{
++ struct pca9685 *pca = i2c_get_clientdata(client);
++ int ret;
++
++ regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP,
++ MODE1_SLEEP);
++
++ ret = gpiochip_remove(&pca->gpio_chip);
++ if (unlikely(ret))
++ dev_err(&client->dev, "%s failed, %d\n",
++ "gpiochip_remove()", ret);
++
++ sysfs_remove_file(&client->dev.kobj, &dev_attr_pwm_period.attr);
++
++ ret = pwmchip_remove(&pca->pwm_chip);
++ if (unlikely(ret))
++ dev_err(&client->dev, "%s failed, %d\n",
++ "pwmchip_remove()", ret);
++
++ mutex_destroy(&pca->lock);
++
++ return ret;
++}
++
++static const struct i2c_device_id pca9685_id[] = {
++ { "pca9685", 0 },
++ { /* sentinel */ },
++};
++MODULE_DEVICE_TABLE(i2c, pca9685_id);
++
++static struct i2c_driver pca9685_i2c_driver = {
++ .driver = {
++ .name = "mfd-pca9685",
++ .owner = THIS_MODULE,
++ },
++ .probe = pca9685_probe,
++ .remove = pca9685_remove,
++ .id_table = pca9685_id,
++};
++
++static int __init pca9685_init(void)
++{
++ if (unlikely((pwm_period < PWM_PERIOD_MIN) ||
++ (PWM_PERIOD_MAX < pwm_period))) {
++ pr_err("Invalid PWM period specified (valid range: %d-%d)\n",
++ PWM_PERIOD_MIN, PWM_PERIOD_MAX);
++ return -EINVAL;
++ }
++
++ return i2c_add_driver(&pca9685_i2c_driver);
++}
++/* register after i2c postcore initcall */
++subsys_initcall(pca9685_init);
++
++static void __exit pca9685_exit(void)
++{
++ i2c_del_driver(&pca9685_i2c_driver);
++}
++module_exit(pca9685_exit);
++
++MODULE_AUTHOR("Wojciech Ziemba <wojciech.ziemba@emutex.com>");
++MODULE_DESCRIPTION("NPX Semiconductors PCA9685 (PWM/GPIO) driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/pca9685-gpio.c b/drivers/mfd/pca9685-gpio.c
+new file mode 100644
+index 0000000..7cfff86
+--- /dev/null
++++ b/drivers/mfd/pca9685-gpio.c
+@@ -0,0 +1,108 @@
++/*
++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface
++ * support.
++ *
++ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
++ * This program is distributed in the hope 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.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+.
++ * Additionally, the driver allows the channels to be configured as GPIO
++ * interface (output only).
++ */
++
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/gpio.h>
++#include <linux/pwm.h>
++#include <linux/regmap.h>
++
++#include "pca9685.h"
++
++static inline struct pca9685 *gpio_to_pca(struct gpio_chip *gpio_chip)
++{
++ return container_of(gpio_chip, struct pca9685, gpio_chip);
++}
++
++static inline int is_gpio_allowed(const struct pca9685 *pca, unsigned channel)
++{
++ return pca->chan_mapping[channel] & PWM_CH_GPIO;
++}
++
++int pca9685_gpio_request(struct gpio_chip *chip, unsigned offset)
++{
++ struct pca9685 *pca;
++ struct pwm_device *pwm;
++ int ret = 0;
++ pca = gpio_to_pca(chip);
++
++ /* validate channel constrains */
++ if (!is_gpio_allowed(pca, offset))
++ return -ENODEV;
++
++ /* return busy if channel is already allocated for pwm */
++ pwm = &pca->pwm_chip.pwms[offset];
++ if (test_bit(PWMF_REQUESTED, &pwm->flags))
++ return -EBUSY;
++
++ /* clear the on counter */
++ regmap_write(pca->regmap, LED_N_ON_L(offset), 0x0);
++ regmap_write(pca->regmap, LED_N_ON_H(offset), 0x0);
++
++ /* clear the off counter */
++ regmap_write(pca->regmap, LED_N_OFF_L(offset), 0x0);
++ ret = regmap_write(pca->regmap, LED_N_OFF_H(offset), 0x0);
++
++ clear_sleep_bit(pca);
++
++ return ret;
++}
++
++void pca9685_gpio_free(struct gpio_chip *chip, unsigned offset)
++{
++ struct pca9685 *pca;
++
++ pca = gpio_to_pca(chip);
++
++ /* clear the on counter reg */
++ regmap_write(pca->regmap, LED_N_ON_L(offset), 0x0);
++ regmap_write(pca->regmap, LED_N_ON_H(offset), 0x0);
++
++ set_sleep_bit(pca);
++
++ return;
++}
++
++void pca9685_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++ struct pca9685 *pca;
++
++ pca = gpio_to_pca(chip);
++
++ /* set the full-on bit */
++ regmap_write(pca->regmap, LED_N_ON_H(offset), (value << 4) & LED_FULL);
++
++ return;
++}
++
++int pca9685_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++ struct pca9685 *pca;
++ unsigned int val;
++
++ pca = gpio_to_pca(chip);
++
++ /* read the full-on bit */
++ regmap_read(pca->regmap, LED_N_ON_H(offset), &val);
++
++ return !!val;
++}
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/pca9685-pwm.c b/drivers/mfd/pca9685-pwm.c
+new file mode 100644
+index 0000000..13f82b8
+--- /dev/null
++++ b/drivers/mfd/pca9685-pwm.c
+@@ -0,0 +1,262 @@
++/*
++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface
++ * support.
++ *
++ * Copyright(c) 2013 Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+.
++ * Additionally, the driver allows the channels to be configured as GPIO
++ * interface (output only).
++ */
++
++#include <linux/module.h>
++#include <linux/pwm.h>
++#include <linux/gpio.h>
++#include <linux/regmap.h>
++#include <linux/platform_device.h>
++#include <linux/delay.h>
++
++#include "pca9685.h"
++
++static inline struct pca9685 *pwm_to_pca(struct pwm_chip *pwm_chip)
++{
++ return container_of(pwm_chip, struct pca9685, pwm_chip);
++}
++
++static inline int period_ns_to_prescale(unsigned period_ns)
++{
++ return (DIV_ROUND_CLOSEST(OSC_CLK_MHZ * period_ns,
++ SAMPLE_RES * 1000)) - 1;
++}
++
++static inline int is_pwm_allowed(const struct pca9685 *pca, unsigned channel)
++{
++ return pca->chan_mapping[channel] & PWM_CH_PWM;
++}
++
++int pca9685_update_prescale(struct pca9685 *pca, unsigned period_ns,
++ bool reconfigure_channels)
++{
++ int pre_scale, i;
++ struct pwm_device *pwm;
++ unsigned long long duty_scale;
++ unsigned long long new_duty_ns;
++
++ if (unlikely((period_ns < PWM_PERIOD_MIN) ||
++ (PWM_PERIOD_MAX < period_ns))) {
++ pr_err("Invalid PWM period specified (valid range: %d-%d)\n",
++ PWM_PERIOD_MIN, PWM_PERIOD_MAX);
++ return -EINVAL;
++ }
++
++ mutex_lock(&pca->lock);
++
++ /* update pre_scale to the closest period */
++ pre_scale = period_ns_to_prescale(period_ns);
++ /* ensure sleep-mode bit is set
++ * NOTE: All active channels will switch off for at least 500 usecs
++ */
++ regmap_update_bits(pca->regmap, PCA9685_MODE1,
++ MODE1_SLEEP, MODE1_SLEEP);
++ regmap_write(pca->regmap, PCA9685_PRESCALE, pre_scale);
++ /* clear sleep mode flag if at least 1 channel is active */
++ if (pca->active_cnt > 0) {
++ regmap_update_bits(pca->regmap, PCA9685_MODE1,
++ MODE1_SLEEP, 0x0);
++ usleep_range(MODE1_RESTART_DELAY, MODE1_RESTART_DELAY * 2);
++ regmap_update_bits(pca->regmap, PCA9685_MODE1,
++ MODE1_RESTART, MODE1_RESTART);
++ }
++
++ if (reconfigure_channels) {
++ for (i = 0; i < pca->pwm_chip.npwm; i++) {
++ pwm = &pca->pwm_chip.pwms[i];
++ pwm->period = period_ns;
++ if (pwm->duty_cycle > 0) {
++ /* Scale the rise time to maintain duty cycle */
++ duty_scale = period_ns;
++ duty_scale *= 1000000;
++ do_div(duty_scale, pca->pwm_period);
++ new_duty_ns = duty_scale * pwm->duty_cycle;
++ do_div(new_duty_ns, 1000000);
++ /* Update the duty_cycle */
++ pwm_config(pwm, (int)new_duty_ns, pwm->period);
++ }
++ }
++ }
++ pca->pwm_period = period_ns;
++
++ mutex_unlock(&pca->lock);
++ return 0;
++}
++
++int pca9685_init_pwm_regs(struct pca9685 *pca, unsigned period_ns)
++{
++ int ret, chan;
++
++ /* set MODE1_SLEEP */
++ ret = regmap_update_bits(pca->regmap, PCA9685_MODE1,
++ MODE1_SLEEP, MODE1_SLEEP);
++ if (unlikely(ret < 0))
++ return ret;
++
++ /* configure the initial PWM clock period */
++ ret = pca9685_update_prescale(pca, period_ns, false);
++ if (unlikely(ret < 0))
++ return ret;
++
++ /* reset PWM channel registers to power-on default values */
++ for (chan = 0; chan < PCA9685_MAXCHAN; chan++) {
++ ret = regmap_write(pca->regmap, LED_N_ON_L(chan), 0);
++ if (unlikely(ret < 0))
++ return ret;
++ ret = regmap_write(pca->regmap, LED_N_ON_H(chan), 0);
++ if (unlikely(ret < 0))
++ return ret;
++ ret = regmap_write(pca->regmap, LED_N_OFF_L(chan), 0);
++ if (unlikely(ret < 0))
++ return ret;
++ ret = regmap_write(pca->regmap, LED_N_OFF_H(chan), LED_FULL);
++ if (unlikely(ret < 0))
++ return ret;
++ }
++ /* reset ALL_LED registers to power-on default values */
++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_ON_L, 0);
++ if (unlikely(ret < 0))
++ return ret;
++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_ON_H, 0);
++ if (unlikely(ret < 0))
++ return ret;
++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_L, 0);
++ if (unlikely(ret < 0))
++ return ret;
++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_H, LED_FULL);
++ if (unlikely(ret < 0))
++ return ret;
++
++ return ret;
++}
++
++static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
++ int duty_ns, int period_ns)
++{
++ struct pca9685 *pca = pwm_to_pca(chip);
++ unsigned long long duty;
++ unsigned int reg_on_h,
++ reg_off_l,
++ reg_off_h;
++ int full_off;
++
++ /* Changing PWM period for a single channel at run-time not allowed.
++ * The PCA9685 PWM clock is shared across all PWM channels
++ */
++ if (unlikely(period_ns != pwm->period))
++ return -EPERM;
++
++ if (unlikely(pwm->hwpwm >= PCA9685_MAXCHAN)) {
++ reg_on_h = PCA9685_ALL_LED_ON_H;
++ reg_off_l = PCA9685_ALL_LED_OFF_L;
++ reg_off_h = PCA9685_ALL_LED_OFF_H;
++ } else {
++ reg_on_h = LED_N_ON_H(pwm->hwpwm);
++ reg_off_l = LED_N_OFF_L(pwm->hwpwm);
++ reg_off_h = LED_N_OFF_H(pwm->hwpwm);
++ }
++
++ duty = SAMPLE_RES * (unsigned long long)duty_ns;
++ duty = DIV_ROUND_UP_ULL(duty, period_ns);
++
++ if (duty >= SAMPLE_RES) /* set the LED_FULL bit */
++ return regmap_write(pca->regmap, reg_on_h, LED_FULL);
++ else /* clear the LED_FULL bit */
++ regmap_write(pca->regmap, reg_on_h, 0x00);
++
++ full_off = !test_bit(PWMF_ENABLED, &pwm->flags) << 4;
++
++ regmap_write(pca->regmap, reg_off_l, (int)duty & 0xff);
++
++ return regmap_write(pca->regmap, reg_off_h,
++ ((int)duty >> 8 | full_off) & 0x1f);
++}
++
++static int pca9685_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct pca9685 *pca = pwm_to_pca(chip);
++ int ret;
++
++ unsigned int reg_off_h;
++
++ if (unlikely(pwm->hwpwm >= PCA9685_MAXCHAN))
++ reg_off_h = PCA9685_ALL_LED_OFF_H;
++ else
++ reg_off_h = LED_N_OFF_H(pwm->hwpwm);
++
++ /* clear the full-off bit */
++ ret = regmap_update_bits(pca->regmap, reg_off_h, LED_FULL, 0x0);
++
++ clear_sleep_bit(pca);
++
++ return ret;
++}
++
++static void pca9685_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct pca9685 *pca = pwm_to_pca(chip);
++
++ unsigned int reg_off_h;
++
++ if (unlikely(pwm->hwpwm >= PCA9685_MAXCHAN))
++ reg_off_h = PCA9685_ALL_LED_OFF_H;
++ else
++ reg_off_h = LED_N_OFF_H(pwm->hwpwm);
++
++ /* set the LED_OFF counter. */
++ regmap_update_bits(pca->regmap, reg_off_h, LED_FULL, LED_FULL);
++
++ set_sleep_bit(pca);
++
++ return;
++}
++
++static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
++{
++ struct pca9685 *pca;
++ struct gpio_chip *gpio_chip;
++ unsigned channel = pwm->hwpwm;
++
++ pca = pwm_to_pca(chip);
++
++ /* validate channel constrains */
++ if (!is_pwm_allowed(pca, channel))
++ return -ENODEV;
++
++ /* return busy if channel is already allocated for gpio */
++ gpio_chip = &pca->gpio_chip;
++
++ if ((channel < PCA9685_MAXCHAN) &&
++ (gpiochip_is_requested(gpio_chip, channel)))
++ return -EBUSY;
++
++ pwm->period = pca->pwm_period;
++
++ return 0;
++}
++
++const struct pwm_ops pca9685_pwm_ops = {
++ .enable = pca9685_pwm_enable,
++ .disable = pca9685_pwm_disable,
++ .config = pca9685_pwm_config,
++ .request = pca9685_pwm_request,
++ .owner = THIS_MODULE,
++};
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mfd/pca9685.h b/drivers/mfd/pca9685.h
+new file mode 100644
+index 0000000..3627097
+--- /dev/null
++++ b/drivers/mfd/pca9685.h
+@@ -0,0 +1,110 @@
++/*
++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface
++ * support.
++ *
++ * Copyright(c) 2013 Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+.
++ * Additionally, the driver allows the channels to be configured as GPIO
++ * interface (output only).
++ */
++
++#ifndef __LINUX_MFD_PCA9685_H
++#define __LINUX_MFD_PCA9685_H
++
++#include <linux/mutex.h>
++#include <linux/gpio.h>
++#include <linux/pwm.h>
++#include <linux/platform_data/pca9685.h>
++
++#define PCA9685_MODE1 0x00
++#define PCA9685_MODE2 0x01
++#define PCA9685_SUBADDR1 0x02
++#define PCA9685_SUBADDR2 0x03
++#define PCA9685_SUBADDR3 0x04
++#define PCA9685_LEDX_ON_L 0x06
++#define PCA9685_LEDX_ON_H 0x07
++#define PCA9685_LEDX_OFF_L 0x08
++#define PCA9685_LEDX_OFF_H 0x09
++
++#define PCA9685_ALL_LED_ON_L 0xFA
++#define PCA9685_ALL_LED_ON_H 0xFB
++#define PCA9685_ALL_LED_OFF_L 0xFC
++#define PCA9685_ALL_LED_OFF_H 0xFD
++#define PCA9685_PRESCALE 0xFE
++
++#define PCA9685_NUMREGS 0xFF
++
++#define LED_FULL (1 << 4)
++#define MODE1_SLEEP (1 << 4)
++#define MODE1_RESTART (1 << 7)
++
++#define MODE1_RESTART_DELAY 500
++
++#define LED_N_ON_H(N) (PCA9685_LEDX_ON_H + (4 * (N)))
++#define LED_N_ON_L(N) (PCA9685_LEDX_ON_L + (4 * (N)))
++#define LED_N_OFF_H(N) (PCA9685_LEDX_OFF_H + (4 * (N)))
++#define LED_N_OFF_L(N) (PCA9685_LEDX_OFF_L + (4 * (N)))
++
++#define OSC_CLK_MHZ 25 /* 25 MHz */
++#define SAMPLE_RES 4096 /* 12 bits */
++#define PWM_PERIOD_MIN 666666 /* ~1525 Hz */
++#define PWM_PERIOD_MAX 41666666 /* 24 Hz */
++#define PWM_PERIOD_DEF 5000000 /* default 200 Hz */
++
++struct pca9685 {
++ struct gpio_chip gpio_chip;
++ struct pwm_chip pwm_chip;
++ struct regmap *regmap;
++ struct mutex lock; /* mutual exclusion semaphore */
++ /* Array of channel allocation constrains */
++ /* add an extra channel for ALL_LED */
++ u8 chan_mapping[PCA9685_MAXCHAN + 1];
++ int gpio_base;
++ int active_cnt;
++ int pwm_exported_cnt;
++ int pwm_period;
++};
++
++extern const struct pwm_ops pca9685_pwm_ops;
++
++int pca9685_gpio_request(struct gpio_chip *chip, unsigned offset);
++void pca9685_gpio_free(struct gpio_chip *chip, unsigned offset);
++void pca9685_gpio_set(struct gpio_chip *chip, unsigned offset, int value);
++int pca9685_gpio_get(struct gpio_chip *chip, unsigned offset);
++
++int pca9685_init_pwm_regs(struct pca9685 *pca, unsigned period_ns);
++int pca9685_update_prescale(struct pca9685 *pca, unsigned period_ns,
++ bool reconfigure_channels);
++
++static inline void set_sleep_bit(struct pca9685 *pca)
++{
++ mutex_lock(&pca->lock);
++ /* set sleep mode flag if no more active LED channel*/
++ if (--pca->active_cnt == 0)
++ regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP,
++ MODE1_SLEEP);
++ mutex_unlock(&pca->lock);
++}
++
++static inline void clear_sleep_bit(struct pca9685 *pca)
++{
++ mutex_lock(&pca->lock);
++ /* clear sleep mode flag if at least 1 LED channel is active */
++ if (pca->active_cnt++ == 0)
++ regmap_update_bits(pca->regmap, PCA9685_MODE1,
++ MODE1_SLEEP, 0x0);
++
++ mutex_unlock(&pca->lock);
++}
++
++#endif /* __LINUX_MFD_PCA9685_H */
+diff --git a/include/linux/mfd/cy8c9540a.h b/include/linux/mfd/cy8c9540a.h
+new file mode 100644
+index 0000000..4d79825
+--- /dev/null
++++ b/include/linux/mfd/cy8c9540a.h
+@@ -0,0 +1,31 @@
++/*
++ * Copyright(c) 2013 Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
+ */
+
+#ifndef LINUX_CY8C9540A_PDATA_H
@@ -3781,28 +4534,21 @@ index 0000000..a32c6f0
+#endif
diff --git a/include/linux/mfd/intel_qrk_gip_pdata.h b/include/linux/mfd/intel_qrk_gip_pdata.h
new file mode 100644
-index 0000000..1378f5c
+index 0000000..eab17d9
--- /dev/null
+++ b/include/linux/mfd/intel_qrk_gip_pdata.h
-@@ -0,0 +1,32 @@
+@@ -0,0 +1,25 @@
+/*
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+
+#ifndef LINUX_INTEL_QRK_GIP_DATA_H
@@ -3817,6 +4563,60 @@ index 0000000..1378f5c
+extern struct intel_qrk_gip_pdata *(*intel_qrk_gip_get_pdata)(void);
+
+#endif
---
-1.7.4.1
-
+diff --git a/include/linux/platform_data/pca9685.h b/include/linux/platform_data/pca9685.h
+new file mode 100644
+index 0000000..903d30d
+--- /dev/null
++++ b/include/linux/platform_data/pca9685.h
+@@ -0,0 +1,51 @@
++/*
++ * Platform data for pca9685 driver
++ *
++ * Copyright(c) 2013 Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
++ */
++
++#ifndef _PLAT_PCA9685_H_
++#define _PLAT_PCA9685_H_
++
++#define PCA9685_MAXCHAN 16
++#define MODE2_INVRT (1 << 4)
++#define MODE2_OUTDRV (1 << 2)
++
++/* PWM channel allocation flags */
++enum {
++ PWM_CH_DISABLED = 0,
++ PWM_CH_PWM = 1 << 0,
++ PWM_CH_GPIO = 1 << 1,
++ /* allow PWM or GPIO */
++ PWM_CH_UNDEFINED = PWM_CH_PWM | PWM_CH_GPIO,
++};
++
++/**
++ * struct pca9685_pdata - Platform data for pca9685 driver
++ * @chan_mapping: Array of channel allocation constrains
++ * @gpio_base: GPIO base
++ * mode2_flags: mode2 register modification flags: INVRT and OUTDRV
++ **/
++struct pca9685_pdata {
++ /* Array of channel allocation constrains */
++ /* add an extra channel for ALL_LED */
++ u8 chan_mapping[PCA9685_MAXCHAN + 1];
++ /* GPIO base */
++ int gpio_base;
++ /* mode2 flags */
++ u8 en_invrt:1, /* enable output logic state inverted mode */
++ en_open_dr:1, /* enable if outputs are configured with an
++ open-drain structure */
++ unused:6;
++};
++
++#endif /* _PLAT_PCA9685_H_ */
diff --git a/recipes-kernel/linux/files/0017-Quark-I2C-quark.patch b/recipes-kernel/linux/files/0017-Quark-I2C-quark.patch
index a730cca..03a3ada 100644
--- a/recipes-kernel/linux/files/0017-Quark-I2C-quark.patch
+++ b/recipes-kernel/linux/files/0017-Quark-I2C-quark.patch
@@ -4,10 +4,10 @@ Date: Tue, 13 Aug 2013 10:22:38 +0100
Subject: [PATCH 17/21] Quark I2C
---
- drivers/i2c/busses/Kconfig | 19 +++---
- drivers/i2c/busses/i2c-designware-core.c | 99 ++++++++++++++++++++++++++--
- drivers/i2c/busses/i2c-designware-core.h | 12 ++++
- drivers/i2c/busses/i2c-designware-pcidrv.c | 18 +++--
+ drivers/i2c/busses/Kconfig | 19 +++---
+ drivers/i2c/busses/i2c-designware-core.c | 99 +++++++++++++++++++++++++++---
+ drivers/i2c/busses/i2c-designware-core.h | 12 ++++
+ drivers/i2c/busses/i2c-designware-pcidrv.c | 18 +++---
4 files changed, 123 insertions(+), 25 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
@@ -412,6 +412,3 @@ index 6add851..62ad7dc 100644
r = i2c_dw_init(dev);
if (r)
goto err_iounmap;
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0018-Quark-sensors-quark.patch b/recipes-kernel/linux/files/0018-Quark-sensors-quark.patch
index e59a7de..7f9de6c 100644
--- a/recipes-kernel/linux/files/0018-Quark-sensors-quark.patch
+++ b/recipes-kernel/linux/files/0018-Quark-sensors-quark.patch
@@ -4,24 +4,24 @@ Date: Mon, 24 Feb 2014 18:41:59 +0000
Subject: [PATCH 18/21] Quark sensors
---
- drivers/iio/accel/Kconfig | 8 +
- drivers/iio/accel/Makefile | 2 +
- drivers/iio/accel/lis331dlh_intel_qrk.c | 735 ++++++++++++++++++++
- drivers/iio/common/Kconfig | 1 +
- drivers/iio/common/Makefile | 1 +
- drivers/iio/common/st_sensors/Kconfig | 14 +
- drivers/iio/common/st_sensors/Makefile | 10 +
- drivers/iio/common/st_sensors/st_sensors_buffer.c | 115 +++
- drivers/iio/common/st_sensors/st_sensors_core.c | 447 ++++++++++++
- drivers/iio/common/st_sensors/st_sensors_i2c.c | 81 +++
- drivers/iio/common/st_sensors/st_sensors_spi.c | 128 ++++
- drivers/iio/common/st_sensors/st_sensors_trigger.c | 77 ++
- drivers/iio/industrialio-buffer.c | 6 +-
- include/linux/iio/common/st_sensors.h | 289 ++++++++
- include/linux/iio/common/st_sensors_i2c.h | 20 +
- include/linux/iio/common/st_sensors_spi.h | 20 +
- include/linux/platform_data/lis331dlh_intel_qrk.h | 36 +
- 17 files changed, 1987 insertions(+), 3 deletions(-)
+ drivers/iio/accel/Kconfig | 8 +
+ drivers/iio/accel/Makefile | 2 +
+ drivers/iio/accel/lis331dlh_intel_qrk.c | 728 +++++++++++++++++++++
+ drivers/iio/common/Kconfig | 1 +
+ drivers/iio/common/Makefile | 1 +
+ drivers/iio/common/st_sensors/Kconfig | 14 +
+ drivers/iio/common/st_sensors/Makefile | 10 +
+ drivers/iio/common/st_sensors/st_sensors_buffer.c | 115 ++++
+ drivers/iio/common/st_sensors/st_sensors_core.c | 447 +++++++++++++
+ drivers/iio/common/st_sensors/st_sensors_i2c.c | 81 +++
+ drivers/iio/common/st_sensors/st_sensors_spi.c | 128 ++++
+ drivers/iio/common/st_sensors/st_sensors_trigger.c | 77 +++
+ drivers/iio/industrialio-buffer.c | 6 +-
+ include/linux/iio/common/st_sensors.h | 289 ++++++++
+ include/linux/iio/common/st_sensors_i2c.h | 20 +
+ include/linux/iio/common/st_sensors_spi.h | 20 +
+ include/linux/platform_data/lis331dlh_intel_qrk.h | 29 +
+ 17 files changed, 1973 insertions(+), 3 deletions(-)
create mode 100644 drivers/iio/accel/lis331dlh_intel_qrk.c
create mode 100644 drivers/iio/common/st_sensors/Kconfig
create mode 100644 drivers/iio/common/st_sensors/Makefile
@@ -65,30 +65,23 @@ index 5bc6855..81f8085 100644
+obj-$(CONFIG_IIO_LIS331DLH_INTEL_QRK) += lis331dlh_intel_qrk.o
diff --git a/drivers/iio/accel/lis331dlh_intel_qrk.c b/drivers/iio/accel/lis331dlh_intel_qrk.c
new file mode 100644
-index 0000000..6b49c6f
+index 0000000..fe868fd
--- /dev/null
+++ b/drivers/iio/accel/lis331dlh_intel_qrk.c
-@@ -0,0 +1,735 @@
+@@ -0,0 +1,728 @@
+/*
+ * Intel Clanton Hill platform accelerometer driver
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ *
+ * Derived from STMicroelectronics accelerometers driver by Denis Ciocca
+ *
@@ -2110,30 +2103,23 @@ index 0000000..d964a35
+#endif /* ST_SENSORS_SPI_H */
diff --git a/include/linux/platform_data/lis331dlh_intel_qrk.h b/include/linux/platform_data/lis331dlh_intel_qrk.h
new file mode 100644
-index 0000000..703c927
+index 0000000..f0d914c
--- /dev/null
+++ b/include/linux/platform_data/lis331dlh_intel_qrk.h
-@@ -0,0 +1,36 @@
+@@ -0,0 +1,29 @@
+/*
+ * Platform data for Intel Clanton Hill platform accelerometer driver
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * 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.
-+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ *
+ */
+
@@ -2150,6 +2136,3 @@ index 0000000..703c927
+};
+
+#endif /* LINUX_PLATFORM_DATA_LIS331DLH_INTEL_QRK_H_ */
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch b/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch
index 7c89b92..417f57f 100644
--- a/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch
+++ b/recipes-kernel/linux/files/0019-Quark-SC-SPI-quark.patch
@@ -4,10 +4,10 @@ Date: Thu, 13 Feb 2014 16:41:02 +0000
Subject: [PATCH 19/21] Quark SC SPI
---
- drivers/spi/Kconfig | 39 ++-
+ drivers/spi/Kconfig | 39 +-
drivers/spi/Makefile | 1 +
drivers/spi/spi-gpio.c | 2 +-
- drivers/spi/spi-pxa2xx-pci.c | 129 ++++-
+ drivers/spi/spi-pxa2xx-pci.c | 129 +++-
drivers/spi/spi-pxa2xx.c | 1290 +++++++++++++++++++++++++++-------------
include/linux/pxa2xx_ssp.h | 25 +
include/linux/spi/pxa2xx_spi.h | 15 +-
@@ -2344,6 +2344,3 @@ index f629189..307d218 100644
#define SPI_LSB_FIRST 0x08 /* per-word bits-on-wire */
#define SPI_3WIRE 0x10 /* SI/SO signals shared */
#define SPI_LOOP 0x20 /* loopback mode */
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0020-Quark-IIO-quark.patch b/recipes-kernel/linux/files/0020-Quark-IIO-quark.patch
index 809c203..03622f9 100644
--- a/recipes-kernel/linux/files/0020-Quark-IIO-quark.patch
+++ b/recipes-kernel/linux/files/0020-Quark-IIO-quark.patch
@@ -1,21 +1,25 @@
From xxxx Mon Sep 17 00:00:00 2001
From: Dan O'Donovan <dan.odonovan@emutex.com>
-Date: Fri, 14 Feb 2014 14:10:33 +0000
+Date: Wed, 9 Apr 2014 15:34:37 +0100
Subject: [PATCH 20/21] Quark IIO
---
drivers/iio/adc/ad7298.c | 20 +-
- drivers/staging/iio/adc/Kconfig | 13 +
- drivers/staging/iio/adc/Makefile | 1 +
- drivers/staging/iio/adc/max78m6610_lmu.c | 2235 ++++++++++++++++++++++++
+ drivers/staging/iio/adc/Kconfig | 24 +
+ drivers/staging/iio/adc/Makefile | 2 +
+ drivers/staging/iio/adc/adc1x8s102.c | 387 ++++
+ drivers/staging/iio/adc/max78m6610_lmu.c | 2575 ++++++++++++++++++++++++
drivers/staging/iio/trigger/Kconfig | 11 +
drivers/staging/iio/trigger/Makefile | 1 +
drivers/staging/iio/trigger/iio-trig-hrtimer.c | 288 +++
include/linux/platform_data/ad7298.h | 5 +
- include/linux/platform_data/max78m6610_lmu.h | 34 +
- 9 files changed, 2603 insertions(+), 5 deletions(-)
+ include/linux/platform_data/adc1x8s102.h | 30 +
+ include/linux/platform_data/max78m6610_lmu.h | 27 +
+ 11 files changed, 3365 insertions(+), 5 deletions(-)
+ create mode 100644 drivers/staging/iio/adc/adc1x8s102.c
create mode 100644 drivers/staging/iio/adc/max78m6610_lmu.c
create mode 100644 drivers/staging/iio/trigger/iio-trig-hrtimer.c
+ create mode 100644 include/linux/platform_data/adc1x8s102.h
create mode 100644 include/linux/platform_data/max78m6610_lmu.h
diff --git a/drivers/iio/adc/ad7298.c b/drivers/iio/adc/ad7298.c
@@ -78,10 +82,10 @@ index b34d754..60491e4 100644
if (st->ext_ref) {
st->reg = regulator_get(&spi->dev, "vref");
diff --git a/drivers/staging/iio/adc/Kconfig b/drivers/staging/iio/adc/Kconfig
-index fb8c239..1309fac 100644
+index fb8c239..d9fef7a 100644
--- a/drivers/staging/iio/adc/Kconfig
+++ b/drivers/staging/iio/adc/Kconfig
-@@ -137,4 +137,17 @@ config SPEAR_ADC
+@@ -137,4 +137,28 @@ config SPEAR_ADC
Say yes here to build support for the integrated ADC inside the
ST SPEAr SoC. Provides direct access via sysfs.
@@ -97,43 +101,441 @@ index fb8c239..1309fac 100644
+ To compile this driver as a module, choose M here: the
+ module will be called max78m6610_lmu.
+
++config ADC1x8S102
++ tristate "Texas Instruments ADC1x8S102 driver"
++ depends on SPI
++ select IIO_BUFFER
++ select IIO_TRIGGERED_BUFFER
++ help
++ Say yes here to build support for Texas Instruments ADC1x8S102 ADC.
++ Provides direct access via sysfs.
++
++ To compile this driver as a module, choose M here: the module will
++ be called adc1x8s102
+
endmenu
diff --git a/drivers/staging/iio/adc/Makefile b/drivers/staging/iio/adc/Makefile
-index d285596..2c4e7e1 100644
+index d285596..5a2f486 100644
--- a/drivers/staging/iio/adc/Makefile
+++ b/drivers/staging/iio/adc/Makefile
-@@ -21,3 +21,4 @@ obj-$(CONFIG_AD7280) += ad7280a.o
+@@ -21,3 +21,5 @@ obj-$(CONFIG_AD7280) += ad7280a.o
obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o
obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
obj-$(CONFIG_SPEAR_ADC) += spear_adc.o
+obj-$(CONFIG_MAX78M6610_LMU) += max78m6610_lmu.o
++obj-$(CONFIG_ADC1x8S102) += adc1x8s102.o
+diff --git a/drivers/staging/iio/adc/adc1x8s102.c b/drivers/staging/iio/adc/adc1x8s102.c
+new file mode 100644
+index 0000000..b4de3a9
+--- /dev/null
++++ b/drivers/staging/iio/adc/adc1x8s102.c
+@@ -0,0 +1,387 @@
++/*
++ * ADC1x8S102 SPI ADC driver
++ *
++ * Copyright(c) 2013 Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * This IIO device driver is is designed to work with the following
++ * analog to digital converters from Texas Instruments:
++ * ADC108S102
++ * ADC128S102
++ * The communication with ADC chip is via the SPI bus (mode 3).
++ */
++
++
++#include <linux/iio/iio.h>
++#include <linux/iio/buffer.h>
++#include <linux/iio/types.h>
++#include <linux/iio/triggered_buffer.h>
++#include <linux/iio/trigger_consumer.h>
++
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/spi/spi.h>
++
++#include <linux/platform_data/adc1x8s102.h>
++#include <linux/regulator/consumer.h>
++
++/*
++ * Defining the ADC resolution being 12 bits, we can use the same driver for
++ * both ADC108S102 (10 bits resolution) and ADC128S102 (12 bits resolution)
++ * chips. The ADC108S102 effectively returns a 12-bit result with the 2
++ * least-significant bits unset.
++ */
++#define ADC1x8S102_BITS 12
++#define ADC1x8S102_MAX_CHANNELS 8
++
++/* 16-bit SPI command format:
++ * [15:14] Ignored
++ * [13:11] 3-bit channel address
++ * [10:0] Ignored
++ */
++#define ADC1x8S102_CMD(ch) (((ch) << (8)) << (3))
++
++/*
++ * 16-bit SPI response format:
++ * [15:12] Zeros
++ * [11:0] 12-bit ADC sample (for ADC108S102, [1:0] will always be 0).
++ */
++#define ADC1x8S102_RES_DATA(res) (res & ((1 << ADC1x8S102_BITS) - 1))
++
++struct adc1x8s102_state {
++ struct spi_device *spi;
++ struct regulator *reg;
++ u16 ext_vin;
++ /* SPI transfer used by triggered buffer handler*/
++ struct spi_transfer ring_xfer;
++ /* SPI transfer used by direct scan */
++ struct spi_transfer scan_single_xfer;
++ /* SPI message used by ring_xfer SPI transfer */
++ struct spi_message ring_msg;
++ /* SPI message used by scan_single_xfer SPI transfer */
++ struct spi_message scan_single_msg;
++
++ /* SPI message buffers:
++ * tx_buf: |C0|C1|C2|C3|C4|C5|C6|C7|XX|
++ * rx_buf: |XX|R0|R1|R2|R3|R4|R5|R6|R7|tt|tt|tt|tt|
++ *
++ * tx_buf: 8 channel read commands, plus 1 dummy command
++ * rx_buf: 1 dummy response, 8 channel responses, plus 64-bit timestamp
++ */
++ __be16 rx_buf[13] ____cacheline_aligned;
++ __be16 tx_buf[9];
++
++};
++
++#define ADC1X8S102_V_CHAN(index) \
++ { \
++ .type = IIO_VOLTAGE, \
++ .indexed = 1, \
++ .channel = index, \
++ .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \
++ IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \
++ .address = index, \
++ .scan_index = index, \
++ .scan_type = { \
++ .sign = 'u', \
++ .realbits = ADC1x8S102_BITS, \
++ .storagebits = 16, \
++ .endianness = IIO_BE, \
++ }, \
++ }
++
++static const struct iio_chan_spec adc1x8s102_channels[] = {
++ ADC1X8S102_V_CHAN(0),
++ ADC1X8S102_V_CHAN(1),
++ ADC1X8S102_V_CHAN(2),
++ ADC1X8S102_V_CHAN(3),
++ ADC1X8S102_V_CHAN(4),
++ ADC1X8S102_V_CHAN(5),
++ ADC1X8S102_V_CHAN(6),
++ ADC1X8S102_V_CHAN(7),
++ IIO_CHAN_SOFT_TIMESTAMP(8),
++};
++
++
++static int adc1x8s102_update_scan_mode(struct iio_dev *indio_dev,
++ unsigned long const *active_scan_mask)
++{
++ struct adc1x8s102_state *st;
++ int i, j;
++
++ st = iio_priv(indio_dev);
++
++ /* Fill in the first x shorts of tx_buf with the number of channels
++ * enabled for sampling by the triggered buffer
++ */
++ for (i = 0, j = 0; i < ADC1x8S102_MAX_CHANNELS; i++) {
++ if (test_bit(i, active_scan_mask)) {
++ st->tx_buf[j] = cpu_to_be16(ADC1x8S102_CMD(i));
++ j++;
++ }
++ }
++ /* One dummy command added, to clock in the last response */
++ st->tx_buf[j] = 0x00;
++
++ /* build SPI ring message */
++ st->ring_xfer.tx_buf = &st->tx_buf[0];
++ st->ring_xfer.rx_buf = &st->rx_buf[0];
++ st->ring_xfer.len = (j + 1) * sizeof(__be16);
++
++ spi_message_init(&st->ring_msg);
++ spi_message_add_tail(&st->ring_xfer, &st->ring_msg);
++
++ return 0;
++}
++
++
++static irqreturn_t adc1x8s102_trigger_handler(int irq, void *p)
++{
++ struct iio_poll_func *pf = p;
++ struct iio_dev *indio_dev;
++ struct adc1x8s102_state *st;
++ s64 time_ns = 0;
++ int b_sent;
++
++ indio_dev = pf->indio_dev;
++ st = iio_priv(indio_dev);
++
++ b_sent = spi_sync(st->spi, &st->ring_msg);
++ if (b_sent)
++ goto done;
++ if (indio_dev->scan_timestamp) {
++ time_ns = iio_get_time_ns();
++ memcpy((u8 *)st->rx_buf + st->ring_xfer.len, &time_ns,
++ sizeof(time_ns));
++ }
++
++ /* Skip the dummy response in the first slot */
++ iio_push_to_buffers(indio_dev, (u8 *)&st->rx_buf[1]);
++done:
++ iio_trigger_notify_done(indio_dev->trig);
++
++ return IRQ_HANDLED;
++}
++
++
++/*
++ * returns:
++ * positive (>=0) value => SUCCESS
++ * negative value => FAILURE
++ */
++static int adc1x8s102_scan_direct(struct adc1x8s102_state *st, unsigned ch)
++{
++ int ret;
++
++ if (ch >= ADC1x8S102_MAX_CHANNELS) {
++ dev_err(&st->spi->dev, "AD channel number too big: %u\n", ch);
++ return -1;
++ }
++
++ st->tx_buf[0] = cpu_to_be16(ADC1x8S102_CMD(ch));
++ ret = spi_sync(st->spi, &st->scan_single_msg);
++ if (ret)
++ return ret;
++
++ /* Skip the dummy response in the first slot */
++ return be16_to_cpu(st->rx_buf[1]);
++}
++
++
++/*
++ * returns:
++ * positive (>=0) value => SUCCESS
++ * negative value => FAILURE
++ */
++static int adc1x8s102_read_raw(struct iio_dev *indio_dev,
++ struct iio_chan_spec const *chan,
++ int *val,
++ int *val2,
++ long m)
++{
++ int ret;
++ struct adc1x8s102_state *st;
++
++ st = iio_priv(indio_dev);
++
++ switch (m) {
++ case IIO_CHAN_INFO_RAW:
++ mutex_lock(&indio_dev->mlock);
++ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
++ ret = -EBUSY;
++ dev_warn(&st->spi->dev,
++ "indio_dev->currentmode is INDIO_BUFFER_TRIGGERED\n");
++ } else {
++ ret = adc1x8s102_scan_direct(st, chan->address);
++ }
++ mutex_unlock(&indio_dev->mlock);
++
++ if (ret < 0)
++ return ret;
++ *val = ADC1x8S102_RES_DATA(ret);
++
++ return IIO_VAL_INT;
++ case IIO_CHAN_INFO_SCALE:
++ switch (chan->type) {
++ case IIO_VOLTAGE:
++ if (NULL != st->reg)
++ *val = regulator_get_voltage(st->reg) / 1000;
++ else
++ *val = st->ext_vin;
++
++ *val2 = chan->scan_type.realbits;
++ return IIO_VAL_FRACTIONAL_LOG2;
++ default:
++ dev_warn(&st->spi->dev,
++ "Invalid channel type %u for channel %d\n",
++ chan->type, chan->channel);
++ return -EINVAL;
++ }
++ default:
++ dev_warn(&st->spi->dev, "Invalid IIO_CHAN_INFO: %lu\n", m);
++ return -EINVAL;
++ }
++}
++
++
++
++static const struct iio_info adc1x8s102_info = {
++ .read_raw = &adc1x8s102_read_raw,
++ .update_scan_mode = &adc1x8s102_update_scan_mode,
++ .driver_module = THIS_MODULE,
++};
++
++
++static int adc1x8s102_probe(struct spi_device *spi)
++{
++ struct adc1x8s102_platform_data *pdata = spi->dev.platform_data;
++ struct adc1x8s102_state *st;
++ struct iio_dev *indio_dev = iio_device_alloc(sizeof(*st));
++ int ret;
++
++ if (NULL == indio_dev) {
++ dev_crit(&spi->dev, "Cannot allocate memory for indio_dev\n");
++ return -ENOMEM;
++ }
++
++ st = iio_priv(indio_dev);
++ if (NULL == pdata) {
++ dev_err(&spi->dev, "Cannot get adc1x8s102 platform data\n");
++ return -EFAULT;
++ }
++ st->ext_vin = pdata->ext_vin;
++
++ /* Use regulator, if available. */
++ st->reg = regulator_get(&spi->dev, "vref");
++ if (IS_ERR(st->reg)) {
++ ret = PTR_ERR(st->reg);
++ dev_warn(&spi->dev,
++ "Cannot get 'vref' regulator\n");
++ goto error_free;
++ }
++ ret = regulator_enable(st->reg);
++ if (ret < 0) {
++ dev_warn(&spi->dev,
++ "Cannot enable vref regulator\n");
++ goto error_put_reg;
++ }
++
++ spi_set_drvdata(spi, indio_dev);
++ st->spi = spi;
++
++ indio_dev->name = spi_get_device_id(spi)->name;
++ indio_dev->dev.parent = &spi->dev;
++ indio_dev->modes = INDIO_DIRECT_MODE;
++ indio_dev->channels = adc1x8s102_channels;
++ indio_dev->num_channels = ARRAY_SIZE(adc1x8s102_channels);
++ indio_dev->info = &adc1x8s102_info;
++
++ /* Setup default message */
++ st->scan_single_xfer.tx_buf = st->tx_buf;
++ st->scan_single_xfer.rx_buf = st->rx_buf;
++ st->scan_single_xfer.len = 2 * sizeof(__be16);
++ st->scan_single_xfer.cs_change = 0;
++
++ spi_message_init(&st->scan_single_msg);
++ spi_message_add_tail(&st->scan_single_xfer, &st->scan_single_msg);
++
++ ret = iio_triggered_buffer_setup(indio_dev, NULL,
++ &adc1x8s102_trigger_handler, NULL);
++ if (ret)
++ goto error_disable_reg;
++
++ ret = iio_device_register(indio_dev);
++ if (ret) {
++ dev_err(&spi->dev,
++ "Failed to register IIO device\n");
++ goto error_cleanup_ring;
++ }
++ return 0;
++
++error_cleanup_ring:
++ iio_triggered_buffer_cleanup(indio_dev);
++error_disable_reg:
++ regulator_disable(st->reg);
++error_put_reg:
++ regulator_put(st->reg);
++error_free:
++ iio_device_free(indio_dev);
++
++ return ret;
++}
++
++
++static int adc1x8s102_remove(struct spi_device *spi)
++{
++ struct iio_dev *indio_dev;
++ struct adc1x8s102_state *st;
++
++ indio_dev = spi_get_drvdata(spi);
++ if (NULL == indio_dev) {
++ dev_err(&spi->dev, "Cannot get spi_device drvdata\n");
++ return -EFAULT;
++ }
++
++ st = iio_priv(indio_dev);
++
++ iio_device_unregister(indio_dev);
++
++ iio_triggered_buffer_cleanup(indio_dev);
++
++ regulator_disable(st->reg);
++ regulator_put(st->reg);
++
++ iio_device_free(indio_dev);
++
++ return 0;
++}
++
++
++static const struct spi_device_id adc1x8s102_id[] = {
++ {"adc1x8s102", 0},
++ {}
++};
++MODULE_DEVICE_TABLE(spi, adc1x8s102_id);
++
++static struct spi_driver adc1x8s102_driver = {
++ .driver = {
++ .name = "adc1x8s102",
++ .owner = THIS_MODULE,
++ },
++ .probe = adc1x8s102_probe,
++ .remove = adc1x8s102_remove,
++ .id_table = adc1x8s102_id,
++};
++module_spi_driver(adc1x8s102_driver);
++
++MODULE_AUTHOR("Bogdan Pricop <bogdan.pricop@emutex.com>");
++MODULE_DESCRIPTION("Texas Instruments ADC1x8S102 driver");
++MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/iio/adc/max78m6610_lmu.c b/drivers/staging/iio/adc/max78m6610_lmu.c
new file mode 100644
-index 0000000..c427517
+index 0000000..ebb2a85
--- /dev/null
+++ b/drivers/staging/iio/adc/max78m6610_lmu.c
-@@ -0,0 +1,2235 @@
+@@ -0,0 +1,2575 @@
+/*
+ * max78m6610+lmu SPI protocol driver
+ *
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ *
+ * This SPI protocol driver is developed for the Maxim 78M6610+LMU (eADC).
+ * The driver is developed as a part of the Quark BSP where integrated into
@@ -219,8 +621,8 @@ index 0000000..c427517
+#define STATUS_MASK_RELAY1 (1 << 2)
+#define STATUS_MASK_RELAY2 (1 << 1)
+#define STATUS_MASK_RESET (1)
-+#define STATUS_MASK_STICKY (0x73FFF0)
-+#define STATUS_MASK_IGNORE (0x00000F)
++#define STATUS_MASK_STICKY (0x73FFF1)
++#define STATUS_MASK_IGNORE (0x00000E)
+
+#define VSURG_VAL 0x13 /* Voltage surge alarm threshold */
+#define VSAG_VAL 0x14 /* Voltage sag alarm threshold */
@@ -283,6 +685,23 @@ index 0000000..c427517
+#define SPI_TB_WRITE(x) ((SPI_TB_ADDR_MASK_5_0(x) << 2)\
+ | SPI_OP_WRITE)
+
++#define TIMER_PERIOD_MS 90
++#define TIMER_PERIOD msecs_to_jiffies(TIMER_PERIOD_MS)
++
++#define MASK0_INT (STATUS_MASK_OV_AMP2 \
++ | STATUS_MASK_OV_AMP1 \
++ | STATUS_MASK_OV_WATT2 \
++ | STATUS_MASK_OV_WATT1 \
++ | STATUS_MASK_VB_SURGE \
++ | STATUS_MASK_VA_SURGE \
++ | STATUS_MASK_UN_VRMSB \
++ | STATUS_MASK_OV_VRMSB \
++ | STATUS_MASK_UN_VRMSA \
++ | STATUS_MASK_OV_VRMSA \
++ | STATUS_MASK_VB_SAG \
++ | STATUS_MASK_VA_SAG)
++
++
+/**
+ * max78m6610_lmu_channels structure maps eADC measurement features to
+ * IIO channels on the IIO sysfs user interface
@@ -930,6 +1349,7 @@ index 0000000..c427517
+ dev_t cdev_no;
+ struct class *cl;
+ u8 *bbuffer;
++ struct timer_list max78m6610_timer;
+};
+
+/**
@@ -1090,7 +1510,7 @@ index 0000000..c427517
+ ret = -EIO;
+ }
+
-+ return 0;
++ return ret;
+}
+
+/**
@@ -1630,8 +2050,11 @@ index 0000000..c427517
+ return -1;
+}
+
++static inline int __max78m6610_lmu_mask0_set(struct max78m6610_lmu_state *st);
++static inline int __max78m6610_lmu_mask0_reset(struct max78m6610_lmu_state *st);
++
+/**
-+ * max78m6610_lmu_flash_save_cmd
++ * max78m6610_lmu_status_scan
+ *
+ * @param indio_dev: iio_dev pointer
+ *
@@ -1644,9 +2067,12 @@ index 0000000..c427517
+static int max78m6610_lmu_status_scan(struct iio_dev *indio_dev)
+{
+ struct max78m6610_lmu_state *st = iio_priv(indio_dev);
-+ unsigned status;
+ int ret;
+ u64 timestamp_ns = iio_get_time_ns();
++ static unsigned old_status;
++ unsigned new_status = 0x00;
++ u16 event_active;
++
+
+ mutex_lock(&indio_dev->mlock);
+ if (indio_dev->currentmode == INDIO_BUFFER_TRIGGERED) {
@@ -1654,151 +2080,228 @@ index 0000000..c427517
+ goto exit_unlock;
+ }
+
-+ ret = __max78m6610_lmu_spi_reg_read(st, STATUS, &status);
++ /* Disable eADC interrupts - special-reset MASK0 */
++ ret = __max78m6610_lmu_mask0_reset(st);
+ if (ret) {
-+ pr_err("Failed to read STATUS register\n");
++ pr_err("Failed to disable interrupts from MASK0!\n");
+ goto exit_unlock;
+ }
+
-+ status &= ~STATUS_MASK_IGNORE;
-+
-+ /* Nothing more to do if no interesting status bits are set */
-+ if (!status)
++ ret = __max78m6610_lmu_spi_reg_read(st, STATUS, &new_status);
++ if (ret) {
++ pr_err("Failed to read STATUS register\n");
+ goto exit_unlock;
++ }
++ new_status &= ~STATUS_MASK_IGNORE;
+
+ /* Not all of the event types used below are ideal, but there is a
+ * limited set available and we want to use different event types for
+ * the different events (e.g sag vs. min-threshold) to allow user
+ * applications to distinguish them
+ */
-+ if (status & STATUS_MASK_VA_SAG) {
++ if ((new_status & STATUS_MASK_VA_SAG) ^
++ (old_status & STATUS_MASK_VA_SAG)) {
++ event_active = !!(new_status & STATUS_MASK_VA_SAG);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
-+ IIO_EV_TYPE_MAG,
-+ IIO_EV_DIR_FALLING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_FALLING,
++ IIO_EV_TYPE_MAG,
++ 0 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_VB_SAG) {
++ if ((new_status & STATUS_MASK_VB_SAG) ^
++ (old_status & STATUS_MASK_VB_SAG)) {
++ event_active = !!(new_status & STATUS_MASK_VB_SAG);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
-+ IIO_EV_TYPE_MAG,
-+ IIO_EV_DIR_FALLING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_FALLING,
++ IIO_EV_TYPE_MAG,
++ 1 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_OV_VRMSA) {
++ if ((new_status & STATUS_MASK_OV_VRMSA) ^
++ (old_status & STATUS_MASK_OV_VRMSA)) {
++ event_active = !!(new_status & STATUS_MASK_OV_VRMSA);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_THRESH,
++ 0 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_UN_VRMSA) {
++ if ((new_status & STATUS_MASK_UN_VRMSA) ^
++ (old_status & STATUS_MASK_UN_VRMSA)) {
++ event_active = !!(new_status & STATUS_MASK_UN_VRMSA);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_FALLING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_FALLING,
++ IIO_EV_TYPE_THRESH,
++ 0 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_OV_VRMSB) {
++ if ((new_status & STATUS_MASK_OV_VRMSB) ^
++ (old_status & STATUS_MASK_OV_VRMSB)) {
++ event_active = !!(new_status & STATUS_MASK_OV_VRMSB);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_THRESH,
++ 1 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_UN_VRMSB) {
++ if ((new_status & STATUS_MASK_UN_VRMSB) ^
++ (old_status & STATUS_MASK_UN_VRMSB)) {
++ event_active = !!(new_status & STATUS_MASK_UN_VRMSB);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_FALLING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_FALLING,
++ IIO_EV_TYPE_THRESH,
++ 1 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_VA_SURGE) {
++ if ((new_status & STATUS_MASK_VA_SURGE) ^
++ (old_status & STATUS_MASK_VA_SURGE)) {
++ event_active = !!(new_status & STATUS_MASK_VA_SURGE);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
-+ IIO_EV_TYPE_MAG,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_MAG,
++ 0 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_VB_SURGE) {
++ if ((new_status & STATUS_MASK_VB_SURGE) ^
++ (old_status & STATUS_MASK_VB_SURGE)) {
++ event_active = !!(new_status & STATUS_MASK_VB_SURGE);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 1,
-+ IIO_EV_TYPE_MAG,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_VOLTAGE,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_MAG,
++ 1 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_OV_WATT1) {
++ if ((new_status & STATUS_MASK_OV_WATT1) ^
++ (old_status & STATUS_MASK_OV_WATT1)) {
++ event_active = !!(new_status & STATUS_MASK_OV_WATT1);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_POWER, 0,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_POWER,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_THRESH,
++ 0 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_OV_WATT2) {
++ if ((new_status & STATUS_MASK_OV_WATT2) ^
++ (old_status & STATUS_MASK_OV_WATT2)) {
++ event_active = !!(new_status & STATUS_MASK_OV_WATT2);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_POWER, 1,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_POWER,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_THRESH,
++ 1 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_OV_AMP1) {
++ if ((new_status & STATUS_MASK_OV_AMP1) ^
++ (old_status & STATUS_MASK_OV_AMP1)) {
++ event_active = !!(new_status & STATUS_MASK_OV_AMP1);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_CURRENT, 0,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_CURRENT,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_THRESH,
++ 0 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
-+ if (status & STATUS_MASK_OV_AMP2) {
++ if ((new_status & STATUS_MASK_OV_AMP2) ^
++ (old_status & STATUS_MASK_OV_AMP2)) {
++ event_active = !!(new_status & STATUS_MASK_OV_AMP2);
+ iio_push_event(indio_dev,
-+ IIO_UNMOD_EVENT_CODE(IIO_CURRENT, 1,
-+ IIO_EV_TYPE_THRESH,
-+ IIO_EV_DIR_RISING),
-+ timestamp_ns);
++ IIO_EVENT_CODE(IIO_CURRENT,
++ 0 /* diff */,
++ IIO_NO_MOD,
++ IIO_EV_DIR_RISING,
++ IIO_EV_TYPE_THRESH,
++ 1 /* chan */,
++ 0 /* chan1 */,
++ event_active /* chan2 */),
++ timestamp_ns);
+ }
+
++ /* Write reset register, clearing only bits that we've processed and
++ * RESET bit if it was set at the time of the last read of STATUS */
+ ret = __max78m6610_lmu_spi_reg_write(st, STATUS_RESET,
-+ status & STATUS_MASK_STICKY);
++ new_status & STATUS_MASK_STICKY);
+ if (ret) {
+ pr_err("Failed to write STATUS_RESET register\n");
+ goto exit_unlock;
+ }
+
++ /* Save the current state of STATUS to be used next time as reference*/
++ old_status = new_status;
++ if (new_status & STATUS_MASK_STICKY) {
++ mod_timer(&st->max78m6610_timer, jiffies + TIMER_PERIOD);
++ } else {
++ del_timer(&st->max78m6610_timer);
++ /* Re-enable eADC interrupts by restoring the content
++ * of MASK0 register */
++ ret = __max78m6610_lmu_mask0_set(st);
++ if (ret) {
++ pr_err("Failed to restore MASK0 register!\n");
++ goto exit_unlock;
++ }
++ }
++ mutex_unlock(&indio_dev->mlock);
++ return ret;
++
+exit_unlock:
++ /* if something failed setup the timer to fire again no matter what */
++ mod_timer(&st->max78m6610_timer, jiffies + TIMER_PERIOD);
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
-+/**
-+ * max78m6610_lmu_write_status_scan
-+ *
-+ * @param dev: device descriptor associated with sysfs attribute node
-+ * @param attr: device sysfs attribute descriptor
-+ * @param buf: data written by user to the attribute node
-+ * @param len: length in bytes of data written by user
-+ *
-+ * This handles a write to this sysfs node from user-space, and invokes a
-+ * read of the status register on the MAX78M6610+LMU if an appropriate value
-+ * is written. Valid input character values are 1, y and Y
-+ */
-+static ssize_t max78m6610_lmu_write_status_scan(struct device *dev,
-+ struct device_attribute *attr,
-+ const char *buf, size_t len)
-+{
-+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-+ int ret = 0;
-+
-+ if (len < 1)
-+ return -1;
-+ switch (buf[0]) {
-+ case '1':
-+ case 'y':
-+ case 'Y':
-+ ret = max78m6610_lmu_status_scan(indio_dev);
-+ return ret ? ret : len;
-+ }
-+ return -1;
-+}
+
+/**
+ * max78m6610_lmu_write_int
@@ -1852,16 +2355,20 @@ index 0000000..c427517
+ .attrs = max78m6610_lmu_attributes,
+};
+
-+/* Provides an option to poll for events (useful if interrupts unavailable) */
-+static IIO_DEVICE_ATTR(do_status_scan, S_IWUSR, NULL,
-+ max78m6610_lmu_write_status_scan, 0);
++/* Provides an option to poll for events (useful if interrupts unavailable)
++ * The option to poll for events is no longer supported, but we need to have at
++ * least 1 event attribute to enable the IIO events.
++ * That's why this attribute is created with no _show and no _store handlers.
++ * */
++static IIO_DEVICE_ATTR(null, S_IWUSR, NULL, NULL, 0);
++
+
+/* Need to have at least 1 event attribute to enable IIO events.
+ * Purposely not setting .event_mask for the channels because that would
+ * enable the IIO events sysfs entries which are not suitable for this driver
+ */
+static struct attribute *max78m6610_lmu_event_attributes[] = {
-+ &iio_dev_attr_do_status_scan.dev_attr.attr,
++ &iio_dev_attr_null.dev_attr.attr,
+ NULL,
+};
+
@@ -2212,11 +2719,239 @@ index 0000000..c427517
+ return 0;
+}
+
++
++/* Spinlock used to lock the external and timer interrupt handlers */
++static DEFINE_SPINLOCK(max78m6610_spinlock);
++
++/* Pointer used to pass iio_dev from top-half to bottom-half handler */
++static void *wq_indio_dev;
++
++/* Workqueue used for deffering the work in the bottom-half handler */
++static void max78m6610_lmu_irq_do_work(struct work_struct *max78m6610_lmu_wq);
++static DECLARE_WORK(max78m6610_lmu_wq, max78m6610_lmu_irq_do_work);
++
++
++/* max78m6610_lmu_irq_do_work
++ *
++ * @param max78m6610_lmu_wq: working item
++ *
++ * Worker function of the work queue which does the bottom-half processing of
++ * MAX78M6610 IRQ.
++ */
++static void max78m6610_lmu_irq_do_work(struct work_struct *max78m6610_lmu_wq)
++{
++ int ret = 0x00;
++
++ ret = max78m6610_lmu_status_scan((struct iio_dev *)wq_indio_dev);
++
++ if (ret)
++ pr_err("MAX78M6610 status scan failed; return code: %d\n", ret);
++}
++
++
++
++/* max78m6610_lmu_irq_handler
++ *
++ * @param irq: IRQ number
++ * @param private: The dev_id cookie passed to request_irq()
++ *
++ * @return:
++ * IRQ_NONE interrupt was not from this device
++ * IRQ_HANDLED interrupt was handled by this device
++ * IRQ_WAKE_THREAD handler requests to wake the handler thread
++ *
++ * Interrupt handler for eADC IRQ.
++ */
++static irqreturn_t max78m6610_lmu_irq_handler(int irq, void *private)
++{
++ spin_lock(&max78m6610_spinlock);
++
++ wq_indio_dev = private;
++ schedule_work(&max78m6610_lmu_wq);
++
++ spin_unlock(&max78m6610_spinlock);
++ return IRQ_HANDLED;
++}
++
++
++/* __max78m6610_lmu_mask0_reset
++ *
++ * @param indio_dev: iio_dev pointer
++ * @return 0 on success, non-zero errno otherwise
++ *
++ * Clears all bits of MASK0 register except RELAY2 bit.
++ *
++ * If MASK0 register is completely cleared (write 0x00 to it) while the MP0
++ * bit is already active, the MP0 bit is not de-activated.
++ * If MASK0 register's value != 0x00 and MASK0 & STATUS == 0, the MP0 bit is
++ * de-activated.
++ *
++ * (MP0 pin == 0) && (MASK0 & STATUS == 0) && (MASK0 != 0) => MP0 = 1
++ * (interrupt line is de-asserted)
++ */
++static inline int __max78m6610_lmu_mask0_reset(struct max78m6610_lmu_state *st)
++{
++ return __max78m6610_lmu_spi_reg_write(st, MASK0, STATUS_MASK_RELAY2);
++}
++
++
++/* __max78m6610_lmu_mask0_set
++ *
++ * @param st: eADC state structure
++ * @return 0 on success, non-zero errno otherwise
++ *
++ * Sets on eADC chip the MASK0 bits corresponding to the events we want to
++ * receive an interrupt for.
++ * If one wants to modify the events which the driver receives interrupt for, he
++ * must modify MASK0_INT macro
++ */
++static inline int __max78m6610_lmu_mask0_set(struct max78m6610_lmu_state *st)
++{
++ return __max78m6610_lmu_spi_reg_write(st, MASK0, MASK0_INT);
++}
++
++
++/* max78m6610_lmu_mask0_set_default
++ *
++ * @param indio_dev: IIO device
++ * @return 0 on success, non-zero errno otherwise
++ *
++ * Read MASK0 register, check if it's default value is already MASK0_INT,
++ * otherwise set MASK0 = MASK0_INT and save defaults into flash in order to
++ * change MASK0 default value.
++ */
++static int max78m6610_lmu_mask0_set_default(struct iio_dev *indio_dev)
++{
++ int ret = 0;
++ unsigned mask0 = 0x00;
++ struct max78m6610_lmu_state *st = iio_priv(indio_dev);
++
++ /* Read MASK0 value */
++ mutex_lock(&indio_dev->mlock);
++ ret = __max78m6610_lmu_spi_reg_read(st, MASK0, &mask0);
++ if (ret) {
++ pr_err("Failed to read MASK0 register! ret: %d\n", ret);
++ goto error_unlock;
++ }
++ mutex_unlock(&indio_dev->mlock);
++ if (mask0 != MASK0_INT) {
++ /* Tell eADC what events to generate interrupt for */
++ mutex_lock(&indio_dev->mlock);
++ ret = __max78m6610_lmu_mask0_set(st);
++ if (ret) {
++ pr_err("Failed to enable interrupts on eADC side!\n");
++ goto error_unlock;
++ }
++ mutex_unlock(&indio_dev->mlock);
++
++ /* Save MASK0 default to flash */
++ ret = max78m6610_lmu_flash_save_cmd(indio_dev);
++ if (ret) {
++ pr_err("Failed to save MASK0 default to flash!\n");
++ goto error_ret;
++ }
++ }
++ return 0;
++
++error_unlock:
++ mutex_unlock(&indio_dev->mlock);
++error_ret:
++ return ret;
++}
++
++
++/*
++ * max78m6610_lmu_irq_init
++ *
++ * @param indio_dev: IIO device
++ * @return 0 on success, non-zero errno otherwise
++ *
++ * Allocate memory for IIO triger, request the IRQ for eADC, set IIO triger
++ * parent and operations; register IIO trigger; set this trigger as default
++ * trigger; configure MASK0 default value.
++ */
++static int max78m6610_lmu_irq_init(struct iio_dev *indio_dev)
++{
++ struct max78m6610_lmu_state *st = iio_priv(indio_dev);
++ int ret = 0;
++
++ if (st->spi->irq < 0) {
++ pr_warn("MAX78M6610+LMU IRQ not set. spi->irq: %d\n",
++ st->spi->irq);
++ return 0;
++ }
++
++ ret = request_irq(st->spi->irq, max78m6610_lmu_irq_handler,
++ IRQF_TRIGGER_FALLING, spi_get_device_id(st->spi)->name,
++ indio_dev);
++ if (ret) {
++ pr_err("Failed to request IRQ %d: request_irg returned %d.\n",
++ st->spi->irq, ret);
++ goto error_ret;
++ }
++
++ /* Check and set MASK0 default */
++ ret = max78m6610_lmu_mask0_set_default(indio_dev);
++ if (ret) {
++ pr_err("Failed to set MASK0 default!\n");
++ goto error_free_irq;
++ }
++
++ return 0;
++
++error_free_irq:
++ free_irq(st->spi->irq, indio_dev);
++error_ret:
++ return ret;
++}
++
++
++/* max78m6610_lmu_irq_remove
++ *
++ * @param indio_dev: IIO device
++ * @return N/A
++ *
++ * Unregister IIO trigger, release the IRQ and free IIO triger memory
++ */
++static void max78m6610_lmu_irq_remove(struct iio_dev *indio_dev)
++{
++ int ret;
++ u32 mask0 = 0x00;
++ struct max78m6610_lmu_state *st = iio_priv(indio_dev);
++
++ if (st->spi->irq < 0)
++ return;
++ /* Instruct MAX78M6610+LMU chip to stop generating interrupts on MP0 */
++ mutex_lock(&indio_dev->mlock);
++ ret = __max78m6610_lmu_spi_reg_write(st, MASK0, mask0);
++ if (ret)
++ pr_warn("Failed to write MASK0 register.\n");
++ mutex_unlock(&indio_dev->mlock);
++
++ free_irq(st->spi->irq, indio_dev);
++}
++
++/* max78m6610_lmu_timer_handler
++ *
++ * @param data: unused
++ * @reutnr N/A
++ *
++ * max78m6610_timer interrupt handler
++ */
++static void max78m6610_lmu_timer_handler(unsigned long data)
++{
++ spin_lock(&max78m6610_spinlock);
++ if (NULL != wq_indio_dev)
++ schedule_work(&max78m6610_lmu_wq);
++ spin_unlock(&max78m6610_spinlock);
++}
++
++
+/**
+ * max78m6610_lmu_probe
+ *
+ * @param spi: spi device pointer
-+ * @return: return 0 or standard errorids if failure
++ * @return: return 0 or standard error ids if failure
+ *
+ * device driver probe funciton for iio_dev struct initialisation.
+ */
@@ -2269,9 +3004,17 @@ index 0000000..c427517
+ ret = max78m6610_lmu_chrdev_init(st);
+ if (ret)
+ goto error_cleanup_ring;
++ /* Init the external GPIO interrupt */
++ ret = max78m6610_lmu_irq_init(indio_dev);
++ if (ret)
++ goto error_cleanup_chrdev;
++ /* Initialise the timer */
++ setup_timer(&st->max78m6610_timer, max78m6610_lmu_timer_handler, 0);
+
+ return 0;
+
++error_cleanup_chrdev:
++ max78m6610_lmu_chrdev_remove(st);
+error_cleanup_ring:
+ iio_triggered_buffer_cleanup(indio_dev);
+error_free:
@@ -2293,8 +3036,14 @@ index 0000000..c427517
+ struct iio_dev *indio_dev = spi_get_drvdata(spi);
+ struct max78m6610_lmu_state *st = iio_priv(indio_dev);
+
++ del_timer(&st->max78m6610_timer);
++
++ max78m6610_lmu_irq_remove(indio_dev);
++
+ max78m6610_lmu_chrdev_remove(st);
++
+ iio_device_unregister(indio_dev);
++
+ iio_triggered_buffer_cleanup(indio_dev);
+ iio_device_free(indio_dev);
+
@@ -2697,31 +3446,60 @@ index fbf8adf..721ed6f 100644
};
#endif /* IIO_ADC_AD7298_H_ */
+diff --git a/include/linux/platform_data/adc1x8s102.h b/include/linux/platform_data/adc1x8s102.h
+new file mode 100644
+index 0000000..a32a499
+--- /dev/null
++++ b/include/linux/platform_data/adc1x8s102.h
+@@ -0,0 +1,30 @@
++/*
++ * ADC1x8S102 SPI ADC driver
++ *
++ * Copyright(c) 2013 Intel Corporation.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope 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.
++ */
++
++
++#ifndef __LINUX_PLATFORM_DATA_ADC1x8S102_H__
++#define __LINUX_PLATFORM_DATA_ADC1x8S102_H__
++
++
++/**
++ * struct adc1x8s102_platform_data - Platform data for the adc1x8s102 ADC driver
++ * @ext_vin: External input voltage range for all voltage input channels
++ * This is the voltage level of pin VA in millivolts
++ **/
++struct adc1x8s102_platform_data {
++ u16 ext_vin;
++};
++
++#endif /* __LINUX_PLATFORM_DATA_ADC1x8S102_H__ */
diff --git a/include/linux/platform_data/max78m6610_lmu.h b/include/linux/platform_data/max78m6610_lmu.h
new file mode 100644
-index 0000000..d05d513
+index 0000000..457124d
--- /dev/null
+++ b/include/linux/platform_data/max78m6610_lmu.h
-@@ -0,0 +1,34 @@
+@@ -0,0 +1,27 @@
+/*
+ * Platform data for max78m6610+lmu SPI protocol driver
+ * Copyright(c) 2013 Intel Corporation.
+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of version 2 of the GNU General Public License as
-+ * published by the Free Software Foundation.
-+ *
-+ * 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.
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
+ *
-+ * Contact Information:
-+ * Intel Corporation
++ * This program is distributed in the hope 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.
+ */
+
+#ifndef __LINUX_PLATFORM_DATA_MAX78M6610_LMU_H__
@@ -2737,6 +3515,3 @@ index 0000000..d05d513
+};
+
+#endif /* IIO_ADC_MAX78M6610_LMU_H_ */
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/0021-Quark-SPI-flash-quark.patch b/recipes-kernel/linux/files/0021-Quark-SPI-flash-quark.patch
index 3d493cb..9cbc396 100644
--- a/recipes-kernel/linux/files/0021-Quark-SPI-flash-quark.patch
+++ b/recipes-kernel/linux/files/0021-Quark-SPI-flash-quark.patch
@@ -4,8 +4,8 @@ Date: Tue, 11 Feb 2014 16:28:26 +0000
Subject: [PATCH 21/21] Quark SPI flash
---
- drivers/mtd/devices/Kconfig | 5 +++++
- drivers/mtd/devices/Makefile | 3 +--
+ drivers/mtd/devices/Kconfig | 5 +++++
+ drivers/mtd/devices/Makefile | 3 +--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
@@ -36,6 +36,3 @@ index 395733a..4c8e399 100644
-CFLAGS_docg3.o += -I$(src)
\ No newline at end of file
+CFLAGS_docg3.o += -I$(src)
---
-1.7.4.1
-
diff --git a/recipes-kernel/linux/files/quark-standard.scc b/recipes-kernel/linux/files/quark-standard.scc
new file mode 100644
index 0000000..0aaa7dd
--- /dev/null
+++ b/recipes-kernel/linux/files/quark-standard.scc
@@ -0,0 +1,6 @@
+define KMACHINE quark
+define KTYPE standard
+define KARCH i386
+
+kconf hardware quark.cfg
+
diff --git a/recipes-kernel/linux/files/quark.cfg b/recipes-kernel/linux/files/quark.cfg
index 30b2e33..2a4db12 100644
--- a/recipes-kernel/linux/files/quark.cfg
+++ b/recipes-kernel/linux/files/quark.cfg
@@ -388,7 +388,6 @@ CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_HIGHMEM=y
CONFIG_X86_PAE=y
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
-CONFIG_ARCH_DMA_ADDR_T_64BIT=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
@@ -657,7 +656,18 @@ CONFIG_BQL=y
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
+CONFIG_CAN=m
+CONFIG_CAN_RAW=m
+CONFIG_CAN_BCM=m
+# CONFIG_CAN_GW is not set
+
+#
+# CAN Device Drivers
+#
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_SLCAN=m
+# CONFIG_CAN_DEV is not set
+# CONFIG_CAN_DEBUG_DEVICES is not set
# CONFIG_IRDA is not set
CONFIG_BT=m
CONFIG_BT_RFCOMM=m
@@ -733,6 +743,8 @@ CONFIG_EXTRA_FIRMWARE=""
CONFIG_DEBUG_DEVRES=y
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_REGMAP=y
+CONFIG_REGMAP_I2C=m
CONFIG_DMA_SHARED_BUFFER=y
# CONFIG_CMA is not set
@@ -1212,7 +1224,7 @@ CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_PNP is not set
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_FIX_EARLYCON_MEM=y
-CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PCI=m
CONFIG_SERIAL_8250_NR_UARTS=8
CONFIG_SERIAL_8250_RUNTIME_UARTS=2
CONFIG_SERIAL_8250_EXTENDED=y
@@ -1235,7 +1247,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
# CONFIG_SERIAL_ALTERA_UART is not set
# CONFIG_SERIAL_IFX6X60 is not set
-CONFIG_SERIAL_QUARK_UART=m
+CONFIG_SERIAL_QUARK_UART=y
+CONFIG_SERIAL_QUARK_UART_CONSOLE=y
# CONFIG_SERIAL_PCH_UART is not set
# CONFIG_SERIAL_ARC is not set
# CONFIG_TTY_PRINTK is not set
@@ -1394,7 +1407,8 @@ CONFIG_GPIO_SCH=m
#
# CONFIG_GPIO_MAX7300 is not set
# CONFIG_GPIO_MAX732X is not set
-# CONFIG_GPIO_PCA953X is not set
+CONFIG_GPIO_PCA953X=m
+CONFIG_GPIO_PCA953X_IRQ=y
# CONFIG_GPIO_PCF857X is not set
# CONFIG_GPIO_SX150X is not set
# CONFIG_GPIO_ADP5588 is not set
@@ -1526,6 +1540,7 @@ CONFIG_MFD_CORE=y
# CONFIG_MFD_CS5535 is not set
# CONFIG_MFD_TIMBERDALE is not set
CONFIG_CY8C9540A=m
+CONFIG_MFD_PCA9685=m
CONFIG_INTEL_QRK_GIP=m
CONFIG_INTEL_QRK_GIP_TEST=m
CONFIG_LPC_SCH=y
@@ -2279,7 +2294,7 @@ CONFIG_DMADEVICES=y
#
# DMA Devices
#
-CONFIG_INTEL_MID_DMAC=m
+CONFIG_INTEL_MID_DMAC=y
# CONFIG_INTEL_IOATDMA is not set
# CONFIG_TIMB_DMA is not set
# CONFIG_PCH_DMA is not set
@@ -2363,6 +2378,7 @@ CONFIG_STAGING=y
# CONFIG_ADT7410 is not set
# CONFIG_AD7280 is not set
CONFIG_MAX78M6610_LMU=m
+CONFIG_ADC1x8S102=m
#
# Analog digital bi-direction converters
@@ -2997,6 +3013,7 @@ CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_PADLOCK is not set
# CONFIG_CRYPTO_DEV_GEODE is not set
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
# CONFIG_ASYMMETRIC_KEY_TYPE is not set
CONFIG_HAVE_KVM=y
# CONFIG_VIRTUALIZATION is not set
@@ -3028,6 +3045,8 @@ CONFIG_CRC32_SLICEBY8=y
# CONFIG_CRC8 is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
# CONFIG_XZ_DEC is not set
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y