summaryrefslogtreecommitdiff
path: root/recipes-kernel/linux
diff options
context:
space:
mode:
authorJesse Gilles <jgilles@multitech.com>2014-11-04 11:23:21 -0600
committerJesse Gilles <jgilles@multitech.com>2014-11-04 11:23:21 -0600
commit812befa503067ad2bae5de58962ff38321c369ca (patch)
treeb472b5118f62e97f760a5b23f3a72130e5ce235b /recipes-kernel/linux
downloadmeta-multitech-812befa503067ad2bae5de58962ff38321c369ca.tar.gz
meta-multitech-812befa503067ad2bae5de58962ff38321c369ca.tar.bz2
meta-multitech-812befa503067ad2bae5de58962ff38321c369ca.zip
initial commit with MTCDT support
Diffstat (limited to 'recipes-kernel/linux')
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-add-num_accessory_ports-config-option.patch22
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-at91-gpio-pullup.patch42
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-at91sam9_wdt-10second-timeout.patch14
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-mci-force-detect.patch29
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-pmecc-debug-bitflips.patch22
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-spi.patch37
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-cdc-acm-ignore-exar-devices.patch35
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-deglitch.patch165
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-pullups.patch301
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12-release-rfcomm-port-fix.patch78
-rw-r--r--recipes-kernel/linux/linux-3.12.27/linux-3.12.27-option-telit.patch39
-rw-r--r--recipes-kernel/linux/linux-3.12.27/mtcdt/defconfig2876
-rw-r--r--recipes-kernel/linux/linux-3.12.27/mtcdt/linux-3.12-eeprom-setup-mtcdt.patch164
-rw-r--r--recipes-kernel/linux/linux-3.12.27/mtcdt/linux-3.12-mtcdt-device-tree.patch448
-rw-r--r--recipes-kernel/linux/linux_3.12.27.bb40
15 files changed, 4312 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-add-num_accessory_ports-config-option.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-add-num_accessory_ports-config-option.patch
new file mode 100644
index 0000000..d1bd7cd
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-add-num_accessory_ports-config-option.patch
@@ -0,0 +1,22 @@
+Index: linux-3.12.13/arch/arm/Kconfig
+===================================================================
+--- linux-3.12.13.orig/arch/arm/Kconfig 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/arch/arm/Kconfig 2014-09-11 14:57:00.908030666 -0500
+@@ -276,6 +276,17 @@
+
+ source "kernel/Kconfig.freezer"
+
++menu "MTS"
++
++config MTS_NUM_ACCESSORY_PORTS
++ int "Number of accessory ports in the MTS product"
++ default 0
++ help
++ Enter the number of accessory ports on your MTS device.
++ If unsure, say '0'.
++
++endmenu
++
+ menu "System Type"
+
+ config MMU
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-at91-gpio-pullup.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-at91-gpio-pullup.patch
new file mode 100644
index 0000000..583a205
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-at91-gpio-pullup.patch
@@ -0,0 +1,42 @@
+Index: linux-3.12.13/arch/arm/mach-at91/gpio.c
+===================================================================
+--- linux-3.12.13.orig/arch/arm/mach-at91/gpio.c 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/arch/arm/mach-at91/gpio.c 2014-03-07 09:13:09.931501303 -0600
+@@ -294,6 +294,25 @@
+ }
+ EXPORT_SYMBOL(at91_set_gpio_output);
+
++/*
++ * configure pin for output and enable/disable pullup
++ */
++int __init_or_module at91_set_gpio_output_with_pullup(unsigned pin, int value, int use_pullup)
++{
++ void __iomem *pio = pin_to_controller(pin);
++ unsigned mask = pin_to_mask(pin);
++
++ if (!pio)
++ return -EINVAL;
++
++ __raw_writel(mask, pio + PIO_IDR);
++ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
++ __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
++ __raw_writel(mask, pio + PIO_OER);
++ __raw_writel(mask, pio + PIO_PER);
++ return 0;
++}
++EXPORT_SYMBOL(at91_set_gpio_output_with_pullup);
+
+ /*
+ * enable/disable the glitch filter; mostly used with IRQ handling.
+Index: linux-3.12.13/arch/arm/mach-at91/include/mach/gpio.h
+===================================================================
+--- linux-3.12.13.orig/arch/arm/mach-at91/include/mach/gpio.h 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/arch/arm/mach-at91/include/mach/gpio.h 2014-03-07 09:13:39.331501866 -0600
+@@ -195,6 +195,7 @@
+ extern int __init_or_module at91_set_D_periph(unsigned pin, int use_pullup);
+ extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
+ extern int __init_or_module at91_set_gpio_output(unsigned pin, int value);
++extern int __init_or_module at91_set_gpio_output_with_pullup(unsigned pin, int value, int use_pullup);
+ extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on);
+ extern int __init_or_module at91_set_debounce(unsigned pin, int is_on, int div);
+ extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on);
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-at91sam9_wdt-10second-timeout.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-at91sam9_wdt-10second-timeout.patch
new file mode 100644
index 0000000..7f4b38c
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-at91sam9_wdt-10second-timeout.patch
@@ -0,0 +1,14 @@
+Index: linux-3.12.13/drivers/watchdog/at91sam9_wdt.c
+===================================================================
+--- linux-3.12.13.orig/drivers/watchdog/at91sam9_wdt.c 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/drivers/watchdog/at91sam9_wdt.c 2014-04-10 16:50:56.032692627 -0500
+@@ -49,7 +49,8 @@
+ #define ticks_to_ms(t) (((t + 1) * 1000) >> 8)
+
+ /* Hardware timeout in seconds */
+-#define WDT_HW_TIMEOUT 2
++/* MTCDT: use longer timeout */
++#define WDT_HW_TIMEOUT 10
+
+ /* Timer heartbeat (500ms) */
+ #define WDT_TIMEOUT (HZ/2)
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-mci-force-detect.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-mci-force-detect.patch
new file mode 100644
index 0000000..2efdf51
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-mci-force-detect.patch
@@ -0,0 +1,29 @@
+Index: linux-3.12.13/drivers/mmc/host/atmel-mci.c
+===================================================================
+--- linux-3.12.13.orig/drivers/mmc/host/atmel-mci.c 2014-04-10 13:32:40.012723945 -0500
++++ linux-3.12.13/drivers/mmc/host/atmel-mci.c 2014-04-10 13:36:46.088723297 -0500
+@@ -1447,6 +1447,9 @@
+ slot->detect_is_active_high);
+ dev_dbg(&mmc->class_dev, "card is %spresent\n",
+ present ? "" : "not ");
++ } else {
++ // jjg - assume card is present if detect pin is unset
++ present = 1;
+ }
+
+ return present;
+@@ -2205,8 +2208,12 @@
+ }
+ }
+
+- if (!gpio_is_valid(slot->detect_pin))
+- mmc->caps |= MMC_CAP_NEEDS_POLL;
++ // jjg - if detect pin isn't set, don't poll -- just assume device
++ // is there and mark it non-removable
++ if (!gpio_is_valid(slot->detect_pin)) {
++ dev_info(&host->pdev->dev,"No detect pin, marking non-removable and assuming device is present\n");
++ mmc->caps |= MMC_CAP_NONREMOVABLE;
++ }
+
+ if (gpio_is_valid(slot->wp_pin)) {
+ if (gpio_request(slot->wp_pin, "mmc_wp")) {
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-pmecc-debug-bitflips.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-pmecc-debug-bitflips.patch
new file mode 100644
index 0000000..391cb4c
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-pmecc-debug-bitflips.patch
@@ -0,0 +1,22 @@
+Index: linux-3.12.27/drivers/mtd/nand/atmel_nand.c
+===================================================================
+--- linux-3.12.27.orig/drivers/mtd/nand/atmel_nand.c 2014-10-01 17:01:10.339848160 -0500
++++ linux-3.12.27/drivers/mtd/nand/atmel_nand.c 2014-10-01 17:04:33.872624626 -0500
+@@ -836,7 +836,7 @@
+ *(buf + byte_pos) ^= (1 << bit_pos);
+
+ pos = sector_num * host->pmecc_sector_size + byte_pos;
+- dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
++ printk(KERN_DEBUG, "atmel_nand: Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
+ pos, bit_pos, err_byte, *(buf + byte_pos));
+ } else {
+ /* Bit flip in OOB area */
+@@ -846,7 +846,7 @@
+ ecc[tmp] ^= (1 << bit_pos);
+
+ pos = tmp + nand_chip->ecc.layout->eccpos[0];
+- dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
++ printk(KERN_DEBUG, "atmel_nand: Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
+ pos, bit_pos, err_byte, ecc[tmp]);
+ }
+
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-spi.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-spi.patch
new file mode 100644
index 0000000..898bf74
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-atmel-spi.patch
@@ -0,0 +1,37 @@
+Index: linux-3.12.13/drivers/spi/spi-atmel.c
+===================================================================
+--- linux-3.12.13.orig/drivers/spi/spi-atmel.c 2014-04-04 15:00:11.677055454 -0500
++++ linux-3.12.13/drivers/spi/spi-atmel.c 2014-04-04 15:36:28.973123089 -0500
+@@ -291,26 +291,15 @@
+ unsigned active = spi->mode & SPI_CS_HIGH;
+ u32 mr;
+
++ mr = spi_readl(as, MR);
+ if (atmel_spi_is_v2(as)) {
+- spi_writel(as, CSR0 + 4 * spi->chip_select, asd->csr);
+- /* For the low SPI version, there is a issue that PDC transfer
+- * on CS1,2,3 needs SPI_CSR0.BITS config as SPI_CSR1,2,3.BITS
++ /* mtcdt: always use CSR0
++ * old 2.6.39 kernel did this and it worked for supporting more than 4 slaves
+ */
+ spi_writel(as, CSR0, asd->csr);
+- if (as->caps.has_wdrbt) {
+- spi_writel(as, MR,
+- SPI_BF(PCS, ~(0x01 << spi->chip_select))
+- | SPI_BIT(WDRBT)
+- | SPI_BIT(MODFDIS)
+- | SPI_BIT(MSTR));
+- } else {
+- spi_writel(as, MR,
+- SPI_BF(PCS, ~(0x01 << spi->chip_select))
+- | SPI_BIT(MODFDIS)
+- | SPI_BIT(MSTR));
+- }
+-
+- mr = spi_readl(as, MR);
++ mr &= (SPI_BIT(MODFDIS) | SPI_BIT(MSTR) | (as->caps.has_wdrbt ? SPI_BIT(WDRBT) : 0));
++ mr |= SPI_BF(PCS, 0x0e);
++ spi_writel(as, MR, mr);
+ gpio_set_value(asd->npcs_pin, active);
+ } else {
+ u32 cpol = (spi->mode & SPI_CPOL) ? SPI_BIT(CPOL) : 0;
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-cdc-acm-ignore-exar-devices.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-cdc-acm-ignore-exar-devices.patch
new file mode 100644
index 0000000..1a90899
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-cdc-acm-ignore-exar-devices.patch
@@ -0,0 +1,35 @@
+Index: linux-3.12.13/drivers/usb/class/cdc-acm.c
+===================================================================
+--- linux-3.12.13.orig/drivers/usb/class/cdc-acm.c 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/drivers/usb/class/cdc-acm.c 2014-04-14 11:30:29.486386713 -0500
+@@ -949,8 +949,10 @@
+ /* normal quirks */
+ quirks = (unsigned long)id->driver_info;
+
+- if (quirks == IGNORE_DEVICE)
++ if (quirks == IGNORE_DEVICE) {
++ dev_dbg(&intf->dev, "Ignoring device\n");
+ return -ENODEV;
++ }
+
+ num_rx_buf = (quirks == SINGLE_RX_URB) ? 1 : ACM_NR;
+
+@@ -1676,6 +1678,18 @@
+ },
+ #endif
+
++ /* Ignore Exar XR21V141X usb serial chips
++ * This elminates conflicting with the Exar vizzini driver */
++ {USB_DEVICE(0x04e2, 0x1410),
++ .driver_info = IGNORE_DEVICE,
++ },
++ {USB_DEVICE(0x04e2, 0x1412),
++ .driver_info = IGNORE_DEVICE,
++ },
++ {USB_DEVICE(0x04e2, 0x1414),
++ .driver_info = IGNORE_DEVICE,
++ },
++
+ /* control interfaces without any protocol set */
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTO_NONE) },
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-deglitch.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-deglitch.patch
new file mode 100644
index 0000000..b868a36
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-deglitch.patch
@@ -0,0 +1,165 @@
+Index: linux-3.12.13/drivers/gpio/gpiolib.c
+===================================================================
+--- linux-3.12.13.orig/drivers/gpio/gpiolib.c 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/drivers/gpio/gpiolib.c 2014-04-18 10:01:46.221371869 -0500
+@@ -90,6 +90,7 @@
+ static int gpiod_direction_input_pullup(struct gpio_desc *desc, bool pullup);
+ static int gpiod_direction_output(struct gpio_desc *desc, int value);
+ static int gpiod_direction_output_pullup(struct gpio_desc *desc, int value, bool pullup);
++static int gpiod_deglitch(struct gpio_desc *desc, bool enable);
+ static int gpiod_get_direction(const struct gpio_desc *desc);
+ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
+ static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
+@@ -1539,6 +1540,9 @@
+ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+ }
+
++ if (flags & GPIOF_DEGLITCH)
++ err = gpiod_deglitch(desc, (flags & GPIOF_DEGLITCH) ? true : false);
++
+ if (err)
+ goto free_gpio;
+
+@@ -1909,6 +1913,67 @@
+ }
+ EXPORT_SYMBOL_GPL(gpio_direction_output);
+
++static int gpiod_deglitch(struct gpio_desc *desc, bool enable)
++{
++ unsigned long flags;
++ struct gpio_chip *chip;
++ int status = -EINVAL;
++ int offset;
++
++ if (!desc || !desc->chip) {
++ pr_warn("%s: invalid GPIO\n", __func__);
++ return -EINVAL;
++ }
++
++ chip = desc->chip;
++ if (!chip->deglitch) {
++ pr_warn("%s: missing deglitch() operation\n",
++ __func__);
++ return -EIO;
++ }
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ status = gpio_ensure_requested(desc);
++ if (status < 0)
++ goto fail;
++
++ /* now we know the gpio is valid and chip won't vanish */
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ might_sleep_if(chip->can_sleep);
++
++ offset = gpio_chip_hwgpio(desc);
++ if (status) {
++ status = chip->request(chip, offset);
++ if (status < 0) {
++ pr_debug("GPIO-%d: chip request fail, %d\n",
++ desc_to_gpio(desc), status);
++ /* and it's not available to anyone else ...
++ * gpio_request() is the fully clean solution.
++ */
++ goto lose;
++ }
++ }
++
++ status = chip->deglitch(chip, offset, enable);
++lose:
++ return status;
++fail:
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ if (status)
++ pr_debug("%s: gpio-%d status %d\n", __func__,
++ desc_to_gpio(desc), status);
++ return status;
++}
++
++int gpio_deglitch(unsigned gpio, bool enable)
++{
++ return gpiod_deglitch(gpio_to_desc(gpio), enable);
++}
++EXPORT_SYMBOL_GPL(gpio_deglitch);
++
+ /**
+ * gpio_set_debounce - sets @debounce time for a @gpio
+ * @gpio: the gpio to set debounce time
+Index: linux-3.12.13/drivers/pinctrl/pinctrl-at91.c
+===================================================================
+--- linux-3.12.13.orig/drivers/pinctrl/pinctrl-at91.c 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/drivers/pinctrl/pinctrl-at91.c 2014-04-18 10:02:45.041371714 -0500
+@@ -1171,6 +1171,17 @@
+ return 0;
+ }
+
++static int at91_gpio_set_deglitch(struct gpio_chip *chip, unsigned offset, bool enable)
++{
++ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
++ void __iomem *pio = at91_gpio->regbase;
++ unsigned mask = 1 << offset;
++
++ at91_mux_pio3_set_deglitch(pio, mask, enable);
++
++ return 0;
++}
++
+ static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ {
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+@@ -1542,6 +1553,7 @@
+ .get = at91_gpio_get,
+ .direction_output = at91_gpio_direction_output,
+ .direction_output_pullup = at91_gpio_direction_output_pullup,
++ .deglitch = at91_gpio_set_deglitch,
+ .set = at91_gpio_set,
+ .to_irq = at91_gpio_to_irq,
+ .dbg_show = at91_gpio_dbg_show,
+Index: linux-3.12.13/include/asm-generic/gpio.h
+===================================================================
+--- linux-3.12.13.orig/include/asm-generic/gpio.h 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/include/asm-generic/gpio.h 2014-04-18 09:58:13.081372430 -0500
+@@ -67,6 +67,7 @@
+ * returns either the value actually sensed, or zero
+ * @direction_output: configures signal "offset" as output, or returns error
+ * @direction_output_pullup: configures signal "offset" as output with pullup enabled, or returns error
++ * @deglitch: enables deglitch on signal "offset"
+ * @set_debounce: optional hook for setting debounce time for specified gpio in
+ * interrupt triggered gpio chips
+ * @set: assigns output value for signal "offset"
+@@ -121,6 +122,8 @@
+ unsigned offset, int value);
+ int (*direction_output_pullup)(struct gpio_chip *chip,
+ unsigned offset, int value, bool pullup);
++ int (*deglitch)(struct gpio_chip *chip,
++ unsigned offset, bool enable);
+ int (*set_debounce)(struct gpio_chip *chip,
+ unsigned offset, unsigned debounce);
+
+@@ -182,6 +185,7 @@
+ extern int gpio_direction_input_pullup(unsigned gpio, bool pullup);
+ extern int gpio_direction_output(unsigned gpio, int value);
+ extern int gpio_direction_output_pullup(unsigned gpio, int value, bool pullup);
++extern int gpio_deglitch(unsigned gpio, bool enable);
+
+ extern int gpio_set_debounce(unsigned gpio, unsigned debounce);
+
+Index: linux-3.12.13/include/linux/gpio.h
+===================================================================
+--- linux-3.12.13.orig/include/linux/gpio.h 2014-04-18 09:55:28.325372866 -0500
++++ linux-3.12.13/include/linux/gpio.h 2014-04-18 09:57:56.305372474 -0500
+@@ -13,9 +13,11 @@
+ #define GPIOF_INIT_HIGH (1 << 1)
+
+ #define GPIOF_PULLUP (2 << 0)
++#define GPIOF_DEGLITCH (2 << 1)
+
+ #define GPIOF_IN (GPIOF_DIR_IN)
+ #define GPIOF_IN_PULLUP (GPIOF_DIR_IN | GPIOF_PULLUP)
++#define GPIOF_IN_DEGLITCH (GPIOF_DIR_IN | GPIOF_DEGLITCH)
+ #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+ #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-pullups.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-pullups.patch
new file mode 100644
index 0000000..4e1d482
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-gpio-expose-pullups.patch
@@ -0,0 +1,301 @@
+Index: linux-3.12.13/drivers/gpio/gpiolib.c
+===================================================================
+--- linux-3.12.13.orig/drivers/gpio/gpiolib.c 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/drivers/gpio/gpiolib.c 2014-04-18 09:25:31.977377592 -0500
+@@ -87,7 +87,9 @@
+ static int gpiod_request(struct gpio_desc *desc, const char *label);
+ static void gpiod_free(struct gpio_desc *desc);
+ static int gpiod_direction_input(struct gpio_desc *desc);
++static int gpiod_direction_input_pullup(struct gpio_desc *desc, bool pullup);
+ static int gpiod_direction_output(struct gpio_desc *desc, int value);
++static int gpiod_direction_output_pullup(struct gpio_desc *desc, int value, bool pullup);
+ static int gpiod_get_direction(const struct gpio_desc *desc);
+ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
+ static int gpiod_get_value_cansleep(const struct gpio_desc *desc);
+@@ -1523,11 +1525,19 @@
+ if (flags & GPIOF_OPEN_SOURCE)
+ set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+
+- if (flags & GPIOF_DIR_IN)
+- err = gpiod_direction_input(desc);
+- else
+- err = gpiod_direction_output(desc,
+- (flags & GPIOF_INIT_HIGH) ? 1 : 0);
++ if (flags & GPIOF_DIR_IN) {
++ if (flags & GPIOF_PULLUP)
++ err = gpiod_direction_input_pullup(desc, (flags & GPIOF_PULLUP) ? true : false);
++ else
++ err = gpiod_direction_input(desc);
++ } else {
++ if (flags & GPIOF_PULLUP)
++ err = gpiod_direction_output_pullup(desc,
++ (flags & GPIOF_INIT_HIGH) ? 1 : 0, (flags & GPIOF_PULLUP) ? true : false);
++ else
++ err = gpiod_direction_output(desc,
++ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
++ }
+
+ if (err)
+ goto free_gpio;
+@@ -1613,6 +1623,71 @@
+ }
+ EXPORT_SYMBOL_GPL(gpiochip_is_requested);
+
++static int gpiod_direction_input_pullup(struct gpio_desc *desc, bool pullup)
++{
++ unsigned long flags;
++ struct gpio_chip *chip;
++ int status = -EINVAL;
++ int offset;
++
++ if (!desc || !desc->chip) {
++ pr_warn("%s: invalid GPIO\n", __func__);
++ return -EINVAL;
++ }
++
++ chip = desc->chip;
++ if (!chip->get || !chip->direction_input_pullup) {
++ pr_warn("%s: missing get() or direction_input_pullup() operations\n",
++ __func__);
++ return -EIO;
++ }
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ status = gpio_ensure_requested(desc);
++ if (status < 0)
++ goto fail;
++
++ /* now we know the gpio is valid and chip won't vanish */
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ might_sleep_if(chip->can_sleep);
++
++ offset = gpio_chip_hwgpio(desc);
++ if (status) {
++ status = chip->request(chip, offset);
++ if (status < 0) {
++ pr_debug("GPIO-%d: chip request fail, %d\n",
++ desc_to_gpio(desc), status);
++ /* and it's not available to anyone else ...
++ * gpio_request() is the fully clean solution.
++ */
++ goto lose;
++ }
++ }
++
++ status = chip->direction_input_pullup(chip, offset, pullup);
++ if (status == 0)
++ clear_bit(FLAG_IS_OUT, &desc->flags);
++
++ trace_gpio_direction(desc_to_gpio(desc), 1, status);
++lose:
++ return status;
++fail:
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ if (status)
++ pr_debug("%s: gpio-%d status %d\n", __func__,
++ desc_to_gpio(desc), status);
++ return status;
++}
++
++int gpio_direction_input_pullup(unsigned gpio, bool pullup)
++{
++ return gpiod_direction_input_pullup(gpio_to_desc(gpio), pullup);
++}
++EXPORT_SYMBOL_GPL(gpio_direction_input_pullup);
++
+
+ /* Drivers MUST set GPIO direction before making get/set calls. In
+ * some cases this is done in early boot, before IRQs are enabled.
+@@ -1688,6 +1763,79 @@
+ }
+ EXPORT_SYMBOL_GPL(gpio_direction_input);
+
++static int gpiod_direction_output_pullup(struct gpio_desc *desc, int value, bool pullup)
++{
++ unsigned long flags;
++ struct gpio_chip *chip;
++ int status = -EINVAL;
++ int offset;
++
++ if (!desc || !desc->chip) {
++ pr_warn("%s: invalid GPIO\n", __func__);
++ return -EINVAL;
++ }
++
++ /* Open drain pin should not be driven to 1 */
++ if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags))
++ return gpiod_direction_input(desc);
++
++ /* Open source pin should not be driven to 0 */
++ if (!value && test_bit(FLAG_OPEN_SOURCE, &desc->flags))
++ return gpiod_direction_input(desc);
++
++ chip = desc->chip;
++ if (!chip->set || !chip->direction_output_pullup) {
++ pr_warn("%s: missing set() or direction_output_pullup() operations\n",
++ __func__);
++ return -EIO;
++ }
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ status = gpio_ensure_requested(desc);
++ if (status < 0)
++ goto fail;
++
++ /* now we know the gpio is valid and chip won't vanish */
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ might_sleep_if(chip->can_sleep);
++
++ offset = gpio_chip_hwgpio(desc);
++ if (status) {
++ status = chip->request(chip, offset);
++ if (status < 0) {
++ pr_debug("GPIO-%d: chip request fail, %d\n",
++ desc_to_gpio(desc), status);
++ /* and it's not available to anyone else ...
++ * gpio_request() is the fully clean solution.
++ */
++ goto lose;
++ }
++ }
++
++ status = chip->direction_output_pullup(chip, offset, value, pullup);
++ if (status == 0)
++ set_bit(FLAG_IS_OUT, &desc->flags);
++ trace_gpio_value(desc_to_gpio(desc), 0, value);
++ trace_gpio_direction(desc_to_gpio(desc), 0, status);
++lose:
++ return status;
++fail:
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ if (status)
++ pr_debug("%s: gpio-%d status %d\n", __func__,
++ desc_to_gpio(desc), status);
++ return status;
++}
++
++int gpio_direction_output_pullup(unsigned gpio, int value, bool pullup)
++{
++ return gpiod_direction_output_pullup(gpio_to_desc(gpio), value, pullup);
++}
++EXPORT_SYMBOL_GPL(gpio_direction_output_pullup);
++
+ static int gpiod_direction_output(struct gpio_desc *desc, int value)
+ {
+ unsigned long flags;
+Index: linux-3.12.13/drivers/pinctrl/pinctrl-at91.c
+===================================================================
+--- linux-3.12.13.orig/drivers/pinctrl/pinctrl-at91.c 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/drivers/pinctrl/pinctrl-at91.c 2014-04-18 09:25:31.985377595 -0500
+@@ -1112,6 +1112,17 @@
+ return 0;
+ }
+
++static int at91_gpio_direction_input_pullup(struct gpio_chip *chip, unsigned offset, bool pullup)
++{
++ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
++ void __iomem *pio = at91_gpio->regbase;
++ unsigned mask = 1 << offset;
++
++ writel_relaxed(mask, pio + PIO_ODR);
++ at91_mux_set_pullup(pio, mask, pullup);
++ return 0;
++}
++
+ static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+@@ -1146,6 +1157,20 @@
+ return 0;
+ }
+
++static int at91_gpio_direction_output_pullup(struct gpio_chip *chip, unsigned offset,
++ int val, bool pullup)
++{
++ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
++ void __iomem *pio = at91_gpio->regbase;
++ unsigned mask = 1 << offset;
++
++ writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR));
++ writel_relaxed(mask, pio + PIO_OER);
++ at91_mux_set_pullup(pio, mask, pullup);
++
++ return 0;
++}
++
+ static int at91_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+ {
+ struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip);
+@@ -1513,8 +1538,10 @@
+ .request = at91_gpio_request,
+ .free = at91_gpio_free,
+ .direction_input = at91_gpio_direction_input,
++ .direction_input_pullup = at91_gpio_direction_input_pullup,
+ .get = at91_gpio_get,
+ .direction_output = at91_gpio_direction_output,
++ .direction_output_pullup = at91_gpio_direction_output_pullup,
+ .set = at91_gpio_set,
+ .to_irq = at91_gpio_to_irq,
+ .dbg_show = at91_gpio_dbg_show,
+Index: linux-3.12.13/include/linux/gpio.h
+===================================================================
+--- linux-3.12.13.orig/include/linux/gpio.h 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/include/linux/gpio.h 2014-04-18 09:25:31.957377594 -0500
+@@ -12,7 +12,10 @@
+ #define GPIOF_INIT_LOW (0 << 1)
+ #define GPIOF_INIT_HIGH (1 << 1)
+
++#define GPIOF_PULLUP (2 << 0)
++
+ #define GPIOF_IN (GPIOF_DIR_IN)
++#define GPIOF_IN_PULLUP (GPIOF_DIR_IN | GPIOF_PULLUP)
+ #define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+ #define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+
+Index: linux-3.12.13/include/asm-generic/gpio.h
+===================================================================
+--- linux-3.12.13.orig/include/asm-generic/gpio.h 2014-02-22 15:32:50.000000000 -0600
++++ linux-3.12.13/include/asm-generic/gpio.h 2014-04-18 09:26:42.669377408 -0500
+@@ -62,9 +62,11 @@
+ * @get_direction: returns direction for signal "offset", 0=out, 1=in,
+ * (same as GPIOF_DIR_XXX), or negative error
+ * @direction_input: configures signal "offset" as input, or returns error
++ * @direction_input_pullup: configures signal "offset" as input with pullup enabled, or returns error
+ * @get: returns value for signal "offset"; for output signals this
+ * returns either the value actually sensed, or zero
+ * @direction_output: configures signal "offset" as output, or returns error
++ * @direction_output_pullup: configures signal "offset" as output with pullup enabled, or returns error
+ * @set_debounce: optional hook for setting debounce time for specified gpio in
+ * interrupt triggered gpio chips
+ * @set: assigns output value for signal "offset"
+@@ -111,10 +113,14 @@
+ unsigned offset);
+ int (*direction_input)(struct gpio_chip *chip,
+ unsigned offset);
++ int (*direction_input_pullup)(struct gpio_chip *chip,
++ unsigned offset, bool pullup);
+ int (*get)(struct gpio_chip *chip,
+ unsigned offset);
+ int (*direction_output)(struct gpio_chip *chip,
+ unsigned offset, int value);
++ int (*direction_output_pullup)(struct gpio_chip *chip,
++ unsigned offset, int value, bool pullup);
+ int (*set_debounce)(struct gpio_chip *chip,
+ unsigned offset, unsigned debounce);
+
+@@ -173,7 +179,9 @@
+ extern void gpio_free(unsigned gpio);
+
+ extern int gpio_direction_input(unsigned gpio);
++extern int gpio_direction_input_pullup(unsigned gpio, bool pullup);
+ extern int gpio_direction_output(unsigned gpio, int value);
++extern int gpio_direction_output_pullup(unsigned gpio, int value, bool pullup);
+
+ extern int gpio_set_debounce(unsigned gpio, unsigned debounce);
+
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12-release-rfcomm-port-fix.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12-release-rfcomm-port-fix.patch
new file mode 100644
index 0000000..70c41d2
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12-release-rfcomm-port-fix.patch
@@ -0,0 +1,78 @@
+commit 5b899241874dcc1a2b932a668731c80a3a869575
+Author: Gianluca Anzolin <gianluca@sottospazio.it>
+Date: Mon Jan 6 21:23:50 2014 +0100
+
+ Bluetooth: Release RFCOMM port when the last user closes the TTY
+
+ This patch fixes a userspace regression introduced by the commit
+ 29cd718b.
+
+ If the rfcomm device was created with the flag RFCOMM_RELEASE_ONHUP the
+ user space expects that the tty_port is released as soon as the last
+ process closes the tty.
+
+ The current code attempts to release the port in the function
+ rfcomm_dev_state_change(). However it won't get a reference to the
+ relevant tty to send a HUP: at that point the tty is already destroyed
+ and therefore NULL.
+
+ This patch fixes the regression by taking over the tty refcount in the
+ tty install method(). This way the tty_port is automatically released as
+ soon as the tty is destroyed.
+
+ As a consequence the check for RFCOMM_RELEASE_ONHUP flag in the hangup()
+ method is now redundant. Instead we have to be careful with the reference
+ counting in the rfcomm_release_dev() function.
+
+ Signed-off-by: Gianluca Anzolin <gianluca@sottospazio.it>
+ Reported-by: Alexander Holler <holler@ahsoftware.de>
+ Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+
+diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
+index 84fcf9f..a535ef1 100644
+--- a/net/bluetooth/rfcomm/tty.c
++++ b/net/bluetooth/rfcomm/tty.c
+@@ -437,7 +437,8 @@ static int rfcomm_release_dev(void __user *arg)
+ tty_kref_put(tty);
+ }
+
+- if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
++ if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
++ !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+ tty_port_put(&dev->port);
+
+ tty_port_put(&dev->port);
+@@ -670,10 +671,20 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
+
+ /* install the tty_port */
+ err = tty_port_install(&dev->port, driver, tty);
+- if (err)
++ if (err) {
+ rfcomm_tty_cleanup(tty);
++ return err;
++ }
+
+- return err;
++ /* take over the tty_port reference if the port was created with the
++ * flag RFCOMM_RELEASE_ONHUP. This will force the release of the port
++ * when the last process closes the tty. The behaviour is expected by
++ * userspace.
++ */
++ if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
++ tty_port_put(&dev->port);
++
++ return 0;
+ }
+
+ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
+@@ -1010,10 +1021,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
+ BT_DBG("tty %p dev %p", tty, dev);
+
+ tty_port_hangup(&dev->port);
+-
+- if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
+- !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
+- tty_port_put(&dev->port);
+ }
+
+ static int rfcomm_tty_tiocmget(struct tty_struct *tty)
diff --git a/recipes-kernel/linux/linux-3.12.27/linux-3.12.27-option-telit.patch b/recipes-kernel/linux/linux-3.12.27/linux-3.12.27-option-telit.patch
new file mode 100644
index 0000000..9826a33
--- /dev/null
+++ b/recipes-kernel/linux/linux-3.12.27/linux-3.12.27-option-telit.patch
@@ -0,0 +1,39 @@
+Index: linux-3.12.27/drivers/usb/serial/option.c
+===================================================================
+--- linux-3.12.27.orig/drivers/usb/serial/option.c 2014-08-26 07:12:26.000000000 -0500
++++ linux-3.12.27/drivers/usb/serial/option.c 2014-09-04 17:11:17.462024077 -0500
+@@ -267,7 +267,9 @@
+ #define TELIT_PRODUCT_CC864_DUAL 0x1005
+ #define TELIT_PRODUCT_CC864_SINGLE 0x1006
+ #define TELIT_PRODUCT_DE910_DUAL 0x1010
++#define TELIT_PRODUCT_CE910_DUAL 0x1011
+ #define TELIT_PRODUCT_UE910_V2 0x1012