]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.9
authorSasha Levin <sashal@kernel.org>
Thu, 2 Jan 2020 02:23:52 +0000 (21:23 -0500)
committerSasha Levin <sashal@kernel.org>
Thu, 2 Jan 2020 02:23:52 +0000 (21:23 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.9/mmc-sdhci-update-the-tuning-failed-messages-to-pr_de.patch [new file with mode: 0644]
queue-4.9/pinctrl-baytrail-really-serialize-all-register-acces.patch [new file with mode: 0644]
queue-4.9/serial-sprd-use-readable-macros-instead-of-magic-num.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch [new file with mode: 0644]

diff --git a/queue-4.9/mmc-sdhci-update-the-tuning-failed-messages-to-pr_de.patch b/queue-4.9/mmc-sdhci-update-the-tuning-failed-messages-to-pr_de.patch
new file mode 100644 (file)
index 0000000..4fb820c
--- /dev/null
@@ -0,0 +1,43 @@
+From 258fbd844872ea7bf1ce97bdb6d5e954af0832b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Dec 2019 17:13:26 +0530
+Subject: mmc: sdhci: Update the tuning failed messages to pr_debug level
+
+From: Faiz Abbas <faiz_abbas@ti.com>
+
+Tuning support in DDR50 speed mode was added in SD Specifications Part1
+Physical Layer Specification v3.01. Its not possible to distinguish
+between v3.00 and v3.01 from the SCR and that is why since
+commit 4324f6de6d2e ("mmc: core: enable CMD19 tuning for DDR50 mode")
+tuning failures are ignored in DDR50 speed mode.
+
+Cards compatible with v3.00 don't respond to CMD19 in DDR50 and this
+error gets printed during enumeration and also if retune is triggered at
+any time during operation. Update the printk level to pr_debug so that
+these errors don't lead to false error reports.
+
+Signed-off-by: Faiz Abbas <faiz_abbas@ti.com>
+Cc: stable@vger.kernel.org # v4.4+
+Link: https://lore.kernel.org/r/20191206114326.15856-1-faiz_abbas@ti.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
+index df306caba296..bd43dc7f4c63 100644
+--- a/drivers/mmc/host/sdhci.c
++++ b/drivers/mmc/host/sdhci.c
+@@ -2098,7 +2098,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
+               spin_lock_irqsave(&host->lock, flags);
+               if (!host->tuning_done) {
+-                      pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n");
++                      pr_debug(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n");
+                       ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
+                       ctrl &= ~SDHCI_CTRL_TUNED_CLK;
+                       ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
+-- 
+2.20.1
+
diff --git a/queue-4.9/pinctrl-baytrail-really-serialize-all-register-acces.patch b/queue-4.9/pinctrl-baytrail-really-serialize-all-register-acces.patch
new file mode 100644 (file)
index 0000000..57ac395
--- /dev/null
@@ -0,0 +1,392 @@
+From aeae7c3fb86ef7d3864f7d216b44c1b856cfe5b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Nov 2019 16:46:41 +0100
+Subject: pinctrl: baytrail: Really serialize all register accesses
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit 40ecab551232972a39cdd8b6f17ede54a3fdb296 ]
+
+Commit 39ce8150a079 ("pinctrl: baytrail: Serialize all register access")
+added a spinlock around all register accesses because:
+
+"There is a hardware issue in Intel Baytrail where concurrent GPIO register
+ access might result reads of 0xffffffff and writes might get dropped
+ completely."
+
+Testing has shown that this does not catch all cases, there are still
+2 problems remaining
+
+1) The original fix uses a spinlock per byt_gpio device / struct,
+additional testing has shown that this is not sufficient concurent
+accesses to 2 different GPIO banks also suffer from the same problem.
+
+This commit fixes this by moving to a single global lock.
+
+2) The original fix did not add a lock around the register accesses in
+the suspend/resume handling.
+
+Since pinctrl-baytrail.c is using normal suspend/resume handlers,
+interrupts are still enabled during suspend/resume handling. Nothing
+should be using the GPIOs when they are being taken down, _but_ the
+GPIOs themselves may still cause interrupts, which are likely to
+use (read) the triggering GPIO. So we need to protect against
+concurrent GPIO register accesses in the suspend/resume handlers too.
+
+This commit fixes this by adding the missing spin_lock / unlock calls.
+
+The 2 fixes together fix the Acer Switch 10 SW5-012 getting completely
+confused after a suspend resume. The DSDT for this device has a bug
+in its _LID method which reprograms the home and power button trigger-
+flags requesting both high and low _level_ interrupts so the IRQs for
+these 2 GPIOs continuously fire. This combined with the saving of
+registers during suspend, triggers concurrent GPIO register accesses
+resulting in saving 0xffffffff as pconf0 value during suspend and then
+when restoring this on resume the pinmux settings get all messed up,
+resulting in various I2C busses being stuck, the wifi no longer working
+and often the tablet simply not coming out of suspend at all.
+
+Cc: stable@vger.kernel.org
+Fixes: 39ce8150a079 ("pinctrl: baytrail: Serialize all register access")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pinctrl/intel/pinctrl-baytrail.c | 81 +++++++++++++-----------
+ 1 file changed, 44 insertions(+), 37 deletions(-)
+
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index fc5b18d3db20..f83a2a60d9c9 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -204,7 +204,6 @@ struct byt_gpio {
+       struct platform_device *pdev;
+       struct pinctrl_dev *pctl_dev;
+       struct pinctrl_desc pctl_desc;
+-      raw_spinlock_t lock;
+       const struct byt_pinctrl_soc_data *soc_data;
+       struct byt_community *communities_copy;
+       struct byt_gpio_pin_context *saved_context;
+@@ -715,6 +714,8 @@ static const struct byt_pinctrl_soc_data *byt_soc_data[] = {
+       NULL,
+ };
++static DEFINE_RAW_SPINLOCK(byt_lock);
++
+ static struct byt_community *byt_get_community(struct byt_gpio *vg,
+                                              unsigned int pin)
+ {
+@@ -856,7 +857,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
+       unsigned long flags;
+       int i;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       for (i = 0; i < group.npins; i++) {
+               void __iomem *padcfg0;
+@@ -876,7 +877,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
+               writel(value, padcfg0);
+       }
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
+@@ -886,7 +887,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
+       unsigned long flags;
+       int i;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       for (i = 0; i < group.npins; i++) {
+               void __iomem *padcfg0;
+@@ -906,7 +907,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
+               writel(value, padcfg0);
+       }
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
+@@ -955,11 +956,11 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
+       unsigned long flags;
+       u32 value;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+       value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
+       writel(value, reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
+@@ -971,7 +972,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
+       u32 value, gpio_mux;
+       unsigned long flags;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       /*
+        * In most cases, func pin mux 000 means GPIO function.
+@@ -993,7 +994,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
+                        "pin %u forcibly re-configured as GPIO\n", offset);
+       }
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       pm_runtime_get(&vg->pdev->dev);
+@@ -1021,7 +1022,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+       unsigned long flags;
+       u32 value;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(val_reg);
+       value &= ~BYT_DIR_MASK;
+@@ -1038,7 +1039,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
+                    "Potential Error: Setting GPIO with direct_irq_en to output");
+       writel(value, val_reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+@@ -1107,11 +1108,11 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
+       u32 conf, pull, val, debounce;
+       u16 arg = 0;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       conf = readl(conf_reg);
+       pull = conf & BYT_PULL_ASSIGN_MASK;
+       val = readl(val_reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+@@ -1138,9 +1139,9 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
+               if (!(conf & BYT_DEBOUNCE_EN))
+                       return -EINVAL;
+-              raw_spin_lock_irqsave(&vg->lock, flags);
++              raw_spin_lock_irqsave(&byt_lock, flags);
+               debounce = readl(db_reg);
+-              raw_spin_unlock_irqrestore(&vg->lock, flags);
++              raw_spin_unlock_irqrestore(&byt_lock, flags);
+               switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
+               case BYT_DEBOUNCE_PULSE_375US:
+@@ -1192,7 +1193,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
+       u32 conf, val, debounce;
+       int i, ret = 0;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       conf = readl(conf_reg);
+       val = readl(val_reg);
+@@ -1300,7 +1301,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
+       if (!ret)
+               writel(conf, conf_reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return ret;
+ }
+@@ -1325,9 +1326,9 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
+       unsigned long flags;
+       u32 val;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       val = readl(reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return !!(val & BYT_LEVEL);
+ }
+@@ -1342,13 +1343,13 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+       if (!reg)
+               return;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       old_val = readl(reg);
+       if (value)
+               writel(old_val | BYT_LEVEL, reg);
+       else
+               writel(old_val & ~BYT_LEVEL, reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+@@ -1361,9 +1362,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+       if (!reg)
+               return -EINVAL;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       if (!(value & BYT_OUTPUT_EN))
+               return GPIOF_DIR_OUT;
+@@ -1406,14 +1407,14 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+               const char *label;
+               unsigned int pin;
+-              raw_spin_lock_irqsave(&vg->lock, flags);
++              raw_spin_lock_irqsave(&byt_lock, flags);
+               pin = vg->soc_data->pins[i].number;
+               reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
+               if (!reg) {
+                       seq_printf(s,
+                                  "Could not retrieve pin %i conf0 reg\n",
+                                  pin);
+-                      raw_spin_unlock_irqrestore(&vg->lock, flags);
++                      raw_spin_unlock_irqrestore(&byt_lock, flags);
+                       continue;
+               }
+               conf0 = readl(reg);
+@@ -1422,11 +1423,11 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+               if (!reg) {
+                       seq_printf(s,
+                                  "Could not retrieve pin %i val reg\n", pin);
+-                      raw_spin_unlock_irqrestore(&vg->lock, flags);
++                      raw_spin_unlock_irqrestore(&byt_lock, flags);
+                       continue;
+               }
+               val = readl(reg);
+-              raw_spin_unlock_irqrestore(&vg->lock, flags);
++              raw_spin_unlock_irqrestore(&byt_lock, flags);
+               comm = byt_get_community(vg, pin);
+               if (!comm) {
+@@ -1510,9 +1511,9 @@ static void byt_irq_ack(struct irq_data *d)
+       if (!reg)
+               return;
+-      raw_spin_lock(&vg->lock);
++      raw_spin_lock(&byt_lock);
+       writel(BIT(offset % 32), reg);
+-      raw_spin_unlock(&vg->lock);
++      raw_spin_unlock(&byt_lock);
+ }
+ static void byt_irq_mask(struct irq_data *d)
+@@ -1536,7 +1537,7 @@ static void byt_irq_unmask(struct irq_data *d)
+       if (!reg)
+               return;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+       switch (irqd_get_trigger_type(d)) {
+@@ -1557,7 +1558,7 @@ static void byt_irq_unmask(struct irq_data *d)
+       writel(value, reg);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+ }
+ static int byt_irq_type(struct irq_data *d, unsigned int type)
+@@ -1571,7 +1572,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
+       if (!reg || offset >= vg->chip.ngpio)
+               return -EINVAL;
+-      raw_spin_lock_irqsave(&vg->lock, flags);
++      raw_spin_lock_irqsave(&byt_lock, flags);
+       value = readl(reg);
+       WARN(value & BYT_DIRECT_IRQ_EN,
+@@ -1593,7 +1594,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
+       else if (type & IRQ_TYPE_LEVEL_MASK)
+               irq_set_handler_locked(d, handle_level_irq);
+-      raw_spin_unlock_irqrestore(&vg->lock, flags);
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+@@ -1629,9 +1630,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
+                       continue;
+               }
+-              raw_spin_lock(&vg->lock);
++              raw_spin_lock(&byt_lock);
+               pending = readl(reg);
+-              raw_spin_unlock(&vg->lock);
++              raw_spin_unlock(&byt_lock);
+               for_each_set_bit(pin, &pending, 32) {
+                       virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
+                       generic_handle_irq(virq);
+@@ -1833,8 +1834,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
+               return PTR_ERR(vg->pctl_dev);
+       }
+-      raw_spin_lock_init(&vg->lock);
+-
+       ret = byt_gpio_probe(vg);
+       if (ret) {
+               pinctrl_unregister(vg->pctl_dev);
+@@ -1852,8 +1851,11 @@ static int byt_gpio_suspend(struct device *dev)
+ {
+       struct platform_device *pdev = to_platform_device(dev);
+       struct byt_gpio *vg = platform_get_drvdata(pdev);
++      unsigned long flags;
+       int i;
++      raw_spin_lock_irqsave(&byt_lock, flags);
++
+       for (i = 0; i < vg->soc_data->npins; i++) {
+               void __iomem *reg;
+               u32 value;
+@@ -1874,6 +1876,7 @@ static int byt_gpio_suspend(struct device *dev)
+               vg->saved_context[i].val = value;
+       }
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+@@ -1881,8 +1884,11 @@ static int byt_gpio_resume(struct device *dev)
+ {
+       struct platform_device *pdev = to_platform_device(dev);
+       struct byt_gpio *vg = platform_get_drvdata(pdev);
++      unsigned long flags;
+       int i;
++      raw_spin_lock_irqsave(&byt_lock, flags);
++
+       for (i = 0; i < vg->soc_data->npins; i++) {
+               void __iomem *reg;
+               u32 value;
+@@ -1920,6 +1926,7 @@ static int byt_gpio_resume(struct device *dev)
+               }
+       }
++      raw_spin_unlock_irqrestore(&byt_lock, flags);
+       return 0;
+ }
+ #endif
+-- 
+2.20.1
+
diff --git a/queue-4.9/serial-sprd-use-readable-macros-instead-of-magic-num.patch b/queue-4.9/serial-sprd-use-readable-macros-instead-of-magic-num.patch
new file mode 100644 (file)
index 0000000..9fab7ae
--- /dev/null
@@ -0,0 +1,36 @@
+From 40b07c218313573e6a5a4175c6f0d032fa5e90e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Dec 2019 20:00:07 +0800
+Subject: serial: sprd: Use readable macros instead of magic number
+
+From: Yonghan Ye <yonghan.ye@unisoc.com>
+
+[ Upstream commit 2b5a997386b0594e671a32c7e429cf59ac8fc54c ]
+
+Define readable macros instead of magic number to make code more readable.
+
+Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
+Acked-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/sprd_serial.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
+index 2e34239ac8a9..ebb1d6658827 100644
+--- a/drivers/tty/serial/sprd_serial.c
++++ b/drivers/tty/serial/sprd_serial.c
+@@ -302,6 +302,9 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
+       if (ims & SPRD_IMSR_TIMEOUT)
+               serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT);
++      if (ims & SPRD_IMSR_BREAK_DETECT)
++              serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT);
++
+       if (ims & (SPRD_IMSR_RX_FIFO_FULL |
+               SPRD_IMSR_BREAK_DETECT | SPRD_IMSR_TIMEOUT))
+               sprd_rx(port);
+-- 
+2.20.1
+
index 7bb3e783516646d4ee947523bdfec01655705d7e..fcbad1f0b59442e17ed71ce3a1ab2c65c3f0075d 100644 (file)
@@ -160,3 +160,7 @@ netfilter-ebtables-compat-reject-all-padding-in-matches-watchers.patch
 netfilter-bridge-make-sure-to-pull-arp-header-in-br_nf_forward_arp.patch
 net-icmp-fix-data-race-in-cmp_global_allow.patch
 hrtimer-annotate-lockless-access-to-timer-state.patch
+tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch
+serial-sprd-use-readable-macros-instead-of-magic-num.patch
+pinctrl-baytrail-really-serialize-all-register-acces.patch
+mmc-sdhci-update-the-tuning-failed-messages-to-pr_de.patch
diff --git a/queue-4.9/tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch b/queue-4.9/tty-serial-atmel-fix-out-of-range-clock-divider-hand.patch
new file mode 100644 (file)
index 0000000..c3795e8
--- /dev/null
@@ -0,0 +1,90 @@
+From fca0c0c2d0dc364878d7597aa31d9dcaf3aece48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Dec 2019 09:54:03 +0100
+Subject: tty/serial: atmel: fix out of range clock divider handling
+
+From: David Engraf <david.engraf@sysgo.com>
+
+[ Upstream commit cb47b9f8630ae3fa3f5fbd0c7003faba7abdf711 ]
+
+Use MCK_DIV8 when the clock divider is > 65535. Unfortunately the mode
+register was already written thus the clock selection is ignored.
+
+Fix by doing the baud rate calulation before setting the mode.
+
+Fixes: 5bf5635ac170 ("tty/serial: atmel: add fractional baud rate support")
+Signed-off-by: David Engraf <david.engraf@sysgo.com>
+Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
+Acked-by: Richard Genoud <richard.genoud@gmail.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20191216085403.17050-1-david.engraf@sysgo.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/atmel_serial.c | 43 ++++++++++++++++---------------
+ 1 file changed, 22 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index 578242239daa..325f9db2da86 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -2200,27 +2200,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+               mode |= ATMEL_US_USMODE_NORMAL;
+       }
+-      /* set the mode, clock divisor, parity, stop bits and data size */
+-      atmel_uart_writel(port, ATMEL_US_MR, mode);
+-
+-      /*
+-       * when switching the mode, set the RTS line state according to the
+-       * new mode, otherwise keep the former state
+-       */
+-      if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
+-              unsigned int rts_state;
+-
+-              if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
+-                      /* let the hardware control the RTS line */
+-                      rts_state = ATMEL_US_RTSDIS;
+-              } else {
+-                      /* force RTS line to low level */
+-                      rts_state = ATMEL_US_RTSEN;
+-              }
+-
+-              atmel_uart_writel(port, ATMEL_US_CR, rts_state);
+-      }
+-
+       /*
+        * Set the baud rate:
+        * Fractional baudrate allows to setup output frequency more
+@@ -2247,6 +2226,28 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+       quot = cd | fp << ATMEL_US_FP_OFFSET;
+       atmel_uart_writel(port, ATMEL_US_BRGR, quot);
++
++      /* set the mode, clock divisor, parity, stop bits and data size */
++      atmel_uart_writel(port, ATMEL_US_MR, mode);
++
++      /*
++       * when switching the mode, set the RTS line state according to the
++       * new mode, otherwise keep the former state
++       */
++      if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
++              unsigned int rts_state;
++
++              if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
++                      /* let the hardware control the RTS line */
++                      rts_state = ATMEL_US_RTSDIS;
++              } else {
++                      /* force RTS line to low level */
++                      rts_state = ATMEL_US_RTSEN;
++              }
++
++              atmel_uart_writel(port, ATMEL_US_CR, rts_state);
++      }
++
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+       atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
+-- 
+2.20.1
+