diff options
| author | Jesse Gilles <jgilles@multitech.com> | 2014-11-04 11:23:21 -0600 |
|---|---|---|
| committer | Jesse Gilles <jgilles@multitech.com> | 2014-11-04 11:23:21 -0600 |
| commit | 812befa503067ad2bae5de58962ff38321c369ca (patch) | |
| tree | b472b5118f62e97f760a5b23f3a72130e5ce235b /recipes-kernel/linux | |
| download | meta-multitech-812befa503067ad2bae5de58962ff38321c369ca.tar.gz meta-multitech-812befa503067ad2bae5de58962ff38321c369ca.tar.bz2 meta-multitech-812befa503067ad2bae5de58962ff38321c369ca.zip | |
initial commit with MTCDT support
Diffstat (limited to 'recipes-kernel/linux')
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 |
