summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Robinson <pbrobinson@gmail.com>2016-12-27 10:37:55 +0000
committerPeter Robinson <pbrobinson@gmail.com>2016-12-27 10:37:55 +0000
commitb4af5e66668194168f88118e061d75bd9f3f7978 (patch)
tree90d9b5cd95017e5e78df8732f0d37429089453a4
parent86cd585a254a1fd8d45451bb69bdc85f0683d02c (diff)
downloadkernel-b4af5e66668194168f88118e061d75bd9f3f7978.tar.gz
kernel-b4af5e66668194168f88118e061d75bd9f3f7978.tar.xz
kernel-b4af5e66668194168f88118e061d75bd9f3f7978.zip
Add upstream bcm283x i2c and clock fixes
-rw-r--r--bcm283x-fixes.patch1003
-rw-r--r--kernel.spec9
2 files changed, 1009 insertions, 3 deletions
diff --git a/bcm283x-fixes.patch b/bcm283x-fixes.patch
new file mode 100644
index 000000000..b9f1b115a
--- /dev/null
+++ b/bcm283x-fixes.patch
@@ -0,0 +1,1003 @@
+From e2474541032db65d02bf88b6a8c2f954654b443f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Mon, 3 Oct 2016 22:06:08 +0200
+Subject: [PATCH 31155/39886] i2c: bcm2835: Fix hang for writing messages
+ larger than 16 bytes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Writing messages larger than the FIFO size results in a hang, rendering
+the machine unusable. This is because the RXD status flag is set on the
+first interrupt which results in bcm2835_drain_rxfifo() stealing bytes
+from the buffer. The controller continues to trigger interrupts waiting
+for the missing bytes, but bcm2835_fill_txfifo() has none to give.
+In this situation wait_for_completion_timeout() apparently is unable to
+stop the madness.
+
+The BCM2835 ARM Peripherals datasheet has this to say about the flags:
+ TXD: is set when the FIFO has space for at least one byte of data.
+ RXD: is set when the FIFO contains at least one byte of data.
+ TXW: is set during a write transfer and the FIFO is less than full.
+ RXR: is set during a read transfer and the FIFO is or more full.
+
+Implementing the logic from the downstream i2c-bcm2708 driver solved
+the hang problem.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Martin Sperl <kernel@martin.sperl.org>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
+index d4f3239..f283b71 100644
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -64,6 +64,7 @@ struct bcm2835_i2c_dev {
+ int irq;
+ struct i2c_adapter adapter;
+ struct completion completion;
++ struct i2c_msg *curr_msg;
+ u32 msg_err;
+ u8 *msg_buf;
+ size_t msg_buf_remaining;
+@@ -126,14 +127,13 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+ return IRQ_HANDLED;
+ }
+
+- if (val & BCM2835_I2C_S_RXD) {
+- bcm2835_drain_rxfifo(i2c_dev);
+- if (!(val & BCM2835_I2C_S_DONE))
+- return IRQ_HANDLED;
+- }
+-
+ if (val & BCM2835_I2C_S_DONE) {
+- if (i2c_dev->msg_buf_remaining)
++ if (i2c_dev->curr_msg->flags & I2C_M_RD) {
++ bcm2835_drain_rxfifo(i2c_dev);
++ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
++ }
++
++ if ((val & BCM2835_I2C_S_RXD) || i2c_dev->msg_buf_remaining)
+ i2c_dev->msg_err = BCM2835_I2C_S_LEN;
+ else
+ i2c_dev->msg_err = 0;
+@@ -141,11 +141,16 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+ return IRQ_HANDLED;
+ }
+
+- if (val & BCM2835_I2C_S_TXD) {
++ if (val & BCM2835_I2C_S_TXW) {
+ bcm2835_fill_txfifo(i2c_dev);
+ return IRQ_HANDLED;
+ }
+
++ if (val & BCM2835_I2C_S_RXR) {
++ bcm2835_drain_rxfifo(i2c_dev);
++ return IRQ_HANDLED;
++ }
++
+ return IRQ_NONE;
+ }
+
+@@ -155,6 +160,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+ u32 c;
+ unsigned long time_left;
+
++ i2c_dev->curr_msg = msg;
+ i2c_dev->msg_buf = msg->buf;
+ i2c_dev->msg_buf_remaining = msg->len;
+ reinit_completion(&i2c_dev->completion);
+--
+2.9.3
+
+From d4030d75c7cbb434b2a3e5f6af5065879d2615a5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Mon, 3 Oct 2016 22:06:09 +0200
+Subject: [PATCH 31156/39886] i2c: bcm2835: Protect against unexpected TXW/RXR
+ interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If an unexpected TXW or RXR interrupt occurs (msg_buf_remaining == 0),
+the driver has no way to fill/drain the FIFO to stop the interrupts.
+In this case the controller has to be disabled and the transfer
+completed to avoid hang.
+
+(CLKT | ERR) and DONE interrupts are completed in their own paths, and
+the controller is disabled in the transfer function after completion.
+Unite the code paths and do disabling inside the interrupt routine.
+
+Clear interrupt status bits in the united completion path instead of
+trying to do it on every interrupt which isn't necessary.
+Only CLKT, ERR and DONE can be cleared that way.
+
+Add the status value to the error value in case of TXW/RXR errors to
+distinguish them from the other S_LEN error.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 40 +++++++++++++++++++++++++++++++---------
+ 1 file changed, 31 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
+index f283b71..d2ba1a4 100644
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -50,8 +50,6 @@
+ #define BCM2835_I2C_S_CLKT BIT(9)
+ #define BCM2835_I2C_S_LEN BIT(10) /* Fake bit for SW error reporting */
+
+-#define BCM2835_I2C_BITMSK_S 0x03FF
+-
+ #define BCM2835_I2C_CDIV_MIN 0x0002
+ #define BCM2835_I2C_CDIV_MAX 0xFFFE
+
+@@ -111,20 +109,26 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev)
+ }
+ }
+
++/*
++ * Note about I2C_C_CLEAR on error:
++ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
++ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through
++ * the state machine to send a NACK and a STOP. Since we're setting CLEAR
++ * without I2CEN, that NACK will be hanging around queued up for next time
++ * we start the engine.
++ */
++
+ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+ {
+ struct bcm2835_i2c_dev *i2c_dev = data;
+ u32 val, err;
+
+ val = bcm2835_i2c_readl(i2c_dev, BCM2835_I2C_S);
+- val &= BCM2835_I2C_BITMSK_S;
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, val);
+
+ err = val & (BCM2835_I2C_S_CLKT | BCM2835_I2C_S_ERR);
+ if (err) {
+ i2c_dev->msg_err = err;
+- complete(&i2c_dev->completion);
+- return IRQ_HANDLED;
++ goto complete;
+ }
+
+ if (val & BCM2835_I2C_S_DONE) {
+@@ -137,21 +141,38 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+ i2c_dev->msg_err = BCM2835_I2C_S_LEN;
+ else
+ i2c_dev->msg_err = 0;
+- complete(&i2c_dev->completion);
+- return IRQ_HANDLED;
++ goto complete;
+ }
+
+ if (val & BCM2835_I2C_S_TXW) {
++ if (!i2c_dev->msg_buf_remaining) {
++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN;
++ goto complete;
++ }
++
+ bcm2835_fill_txfifo(i2c_dev);
+ return IRQ_HANDLED;
+ }
+
+ if (val & BCM2835_I2C_S_RXR) {
++ if (!i2c_dev->msg_buf_remaining) {
++ i2c_dev->msg_err = val | BCM2835_I2C_S_LEN;
++ goto complete;
++ }
++
+ bcm2835_drain_rxfifo(i2c_dev);
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
++
++complete:
++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_S, BCM2835_I2C_S_CLKT |
++ BCM2835_I2C_S_ERR | BCM2835_I2C_S_DONE);
++ complete(&i2c_dev->completion);
++
++ return IRQ_HANDLED;
+ }
+
+ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+@@ -181,8 +202,9 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+
+ time_left = wait_for_completion_timeout(&i2c_dev->completion,
+ BCM2835_I2C_TIMEOUT);
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
+ if (!time_left) {
++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
++ BCM2835_I2C_C_CLEAR);
+ dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+ return -ETIMEDOUT;
+ }
+--
+2.9.3
+
+From 23c9540b3ad1d7473fe40df80074d0fb0bf04869 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Mon, 3 Oct 2016 22:06:10 +0200
+Subject: [PATCH 31157/39886] i2c: bcm2835: Use dev_dbg logging on transfer
+ errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Writing to an AT24C32 generates on average 2x i2c transfer errors per
+32-byte page write. Which amounts to a lot for a 4k write. This is due
+to the fact that the chip doesn't respond during it's internal write
+cycle when the at24 driver tries and retries the next write.
+Only a handful drivers use dev_err() on transfer error, so switch to
+dev_dbg() instead.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
+index d2ba1a4..54d510a 100644
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -216,7 +216,7 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+ (msg->flags & I2C_M_IGNORE_NAK))
+ return 0;
+
+- dev_err(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
++ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+
+ if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+ return -EREMOTEIO;
+--
+2.9.3
+
+From 8d2cc5cc6ee5c0fc48a96bb29af55fc700f66fdf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Mon, 3 Oct 2016 22:06:11 +0200
+Subject: [PATCH 31158/39886] i2c: bcm2835: Can't support I2C_M_IGNORE_NAK
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The controller can't support this flag, so remove it.
+
+Documentation/i2c/i2c-protocol states that all of the message is sent:
+
+I2C_M_IGNORE_NAK:
+ Normally message is interrupted immediately if there is [NA] from the
+ client. Setting this flag treats any [NA] as [A], and all of
+ message is sent.
+
+>From the BCM2835 ARM Peripherals datasheet:
+
+ The ERR field is set when the slave fails to acknowledge either
+ its address or a data byte written to it.
+
+So when the controller doesn't receive an ack, it sets ERR and raises
+an interrupt. In other words, the whole message is not sent.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
+index 54d510a..565ef69 100644
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -212,10 +212,6 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+ if (likely(!i2c_dev->msg_err))
+ return 0;
+
+- if ((i2c_dev->msg_err & BCM2835_I2C_S_ERR) &&
+- (msg->flags & I2C_M_IGNORE_NAK))
+- return 0;
+-
+ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+
+ if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+--
+2.9.3
+
+From ee05fea21b017b81a9477569b6a0c2d8e2946ac9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Mon, 3 Oct 2016 22:06:12 +0200
+Subject: [PATCH 31159/39886] i2c: bcm2835: Add support for Repeated Start
+ Condition
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Documentation/i2c/i2c-protocol states that Combined transactions should
+separate messages with a Start bit and end the whole transaction with a
+Stop bit. This patch adds support for issuing only a Start between
+messages instead of a Stop followed by a Start.
+
+This implementation differs from downstream i2c-bcm2708 in 2 respects:
+- it uses an interrupt to detect that the transfer is active instead
+ of using polling. There is no interrupt for Transfer Active, but by
+ not prefilling the FIFO it's possible to use the TXW interrupt.
+- when resetting/disabling the controller between transfers it writes
+ CLEAR to the control register instead of just zero.
+ Using just zero gave many errors. This might be the reason why
+ downstream had to disable this feature and make it available with a
+ module parameter.
+
+I have run thousands of transfers to a DS1307 (rtc), MMA8451 (accel)
+and AT24C32 (eeprom) in parallel without problems.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Acked-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 101 ++++++++++++++++++++++++---------------
+ 1 file changed, 63 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
+index 565ef69..241e08a 100644
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -63,6 +63,7 @@ struct bcm2835_i2c_dev {
+ struct i2c_adapter adapter;
+ struct completion completion;
+ struct i2c_msg *curr_msg;
++ int num_msgs;
+ u32 msg_err;
+ u8 *msg_buf;
+ size_t msg_buf_remaining;
+@@ -110,6 +111,45 @@ static void bcm2835_drain_rxfifo(struct bcm2835_i2c_dev *i2c_dev)
+ }
+
+ /*
++ * Repeated Start Condition (Sr)
++ * The BCM2835 ARM Peripherals datasheet mentions a way to trigger a Sr when it
++ * talks about reading from a slave with 10 bit address. This is achieved by
++ * issuing a write, poll the I2CS.TA flag and wait for it to be set, and then
++ * issue a read.
++ * A comment in https://github.com/raspberrypi/linux/issues/254 shows how the
++ * firmware actually does it using polling and says that it's a workaround for
++ * a problem in the state machine.
++ * It turns out that it is possible to use the TXW interrupt to know when the
++ * transfer is active, provided the FIFO has not been prefilled.
++ */
++
++static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev)
++{
++ u32 c = BCM2835_I2C_C_ST | BCM2835_I2C_C_I2CEN;
++ struct i2c_msg *msg = i2c_dev->curr_msg;
++ bool last_msg = (i2c_dev->num_msgs == 1);
++
++ if (!i2c_dev->num_msgs)
++ return;
++
++ i2c_dev->num_msgs--;
++ i2c_dev->msg_buf = msg->buf;
++ i2c_dev->msg_buf_remaining = msg->len;
++
++ if (msg->flags & I2C_M_RD)
++ c |= BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
++ else
++ c |= BCM2835_I2C_C_INTT;
++
++ if (last_msg)
++ c |= BCM2835_I2C_C_INTD;
++
++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
++}
++
++/*
+ * Note about I2C_C_CLEAR on error:
+ * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
+ * non-idle state and I2C_C_READ, it sets an abort_rx flag and runs through
+@@ -151,6 +191,12 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+ }
+
+ bcm2835_fill_txfifo(i2c_dev);
++
++ if (i2c_dev->num_msgs && !i2c_dev->msg_buf_remaining) {
++ i2c_dev->curr_msg++;
++ bcm2835_i2c_start_transfer(i2c_dev);
++ }
++
+ return IRQ_HANDLED;
+ }
+
+@@ -175,30 +221,25 @@ static irqreturn_t bcm2835_i2c_isr(int this_irq, void *data)
+ return IRQ_HANDLED;
+ }
+
+-static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+- struct i2c_msg *msg)
++static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
++ int num)
+ {
+- u32 c;
++ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+ unsigned long time_left;
++ int i;
+
+- i2c_dev->curr_msg = msg;
+- i2c_dev->msg_buf = msg->buf;
+- i2c_dev->msg_buf_remaining = msg->len;
+- reinit_completion(&i2c_dev->completion);
+-
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, BCM2835_I2C_C_CLEAR);
++ for (i = 0; i < (num - 1); i++)
++ if (msgs[i].flags & I2C_M_RD) {
++ dev_warn_once(i2c_dev->dev,
++ "only one read message supported, has to be last\n");
++ return -EOPNOTSUPP;
++ }
+
+- if (msg->flags & I2C_M_RD) {
+- c = BCM2835_I2C_C_READ | BCM2835_I2C_C_INTR;
+- } else {
+- c = BCM2835_I2C_C_INTT;
+- bcm2835_fill_txfifo(i2c_dev);
+- }
+- c |= BCM2835_I2C_C_ST | BCM2835_I2C_C_INTD | BCM2835_I2C_C_I2CEN;
++ i2c_dev->curr_msg = msgs;
++ i2c_dev->num_msgs = num;
++ reinit_completion(&i2c_dev->completion);
+
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_A, msg->addr);
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DLEN, msg->len);
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
++ bcm2835_i2c_start_transfer(i2c_dev);
+
+ time_left = wait_for_completion_timeout(&i2c_dev->completion,
+ BCM2835_I2C_TIMEOUT);
+@@ -209,31 +250,15 @@ static int bcm2835_i2c_xfer_msg(struct bcm2835_i2c_dev *i2c_dev,
+ return -ETIMEDOUT;
+ }
+
+- if (likely(!i2c_dev->msg_err))
+- return 0;
++ if (!i2c_dev->msg_err)
++ return num;
+
+ dev_dbg(i2c_dev->dev, "i2c transfer failed: %x\n", i2c_dev->msg_err);
+
+ if (i2c_dev->msg_err & BCM2835_I2C_S_ERR)
+ return -EREMOTEIO;
+- else
+- return -EIO;
+-}
+-
+-static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+- int num)
+-{
+- struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+- int i;
+- int ret = 0;
+-
+- for (i = 0; i < num; i++) {
+- ret = bcm2835_i2c_xfer_msg(i2c_dev, &msgs[i]);
+- if (ret)
+- break;
+- }
+
+- return ret ?: i;
++ return -EIO;
+ }
+
+ static u32 bcm2835_i2c_func(struct i2c_adapter *adap)
+--
+2.9.3
+
+From e13e19e12f66401ce1e21ab491715835852babe7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Mon, 3 Oct 2016 22:06:13 +0200
+Subject: [PATCH 31160/39886] i2c: bcm2835: Support i2c-dev ioctl I2C_TIMEOUT
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use i2c_adapter->timeout for the completion timeout value. The core
+default is 1 second.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
+index 241e08a..d2085dd 100644
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -53,8 +53,6 @@
+ #define BCM2835_I2C_CDIV_MIN 0x0002
+ #define BCM2835_I2C_CDIV_MAX 0xFFFE
+
+-#define BCM2835_I2C_TIMEOUT (msecs_to_jiffies(1000))
+-
+ struct bcm2835_i2c_dev {
+ struct device *dev;
+ void __iomem *regs;
+@@ -242,7 +240,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+ bcm2835_i2c_start_transfer(i2c_dev);
+
+ time_left = wait_for_completion_timeout(&i2c_dev->completion,
+- BCM2835_I2C_TIMEOUT);
++ adap->timeout);
+ if (!time_left) {
+ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
+ BCM2835_I2C_C_CLEAR);
+--
+2.9.3
+
+From 9446f62e8e18057fceb179d947508df2f7253b26 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= <noralf@tronnes.org>
+Date: Mon, 3 Oct 2016 22:06:14 +0200
+Subject: [PATCH 31161/39886] i2c: bcm2835: Add support for dynamic clock
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Support a dynamic clock by reading the frequency and setting the
+divisor in the transfer function instead of during probe.
+
+Signed-off-by: Noralf Trønnes <noralf@tronnes.org>
+Reviewed-by: Martin Sperl <kernel@martin.sperl.org>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ drivers/i2c/busses/i2c-bcm2835.c | 51 +++++++++++++++++++++++++---------------
+ 1 file changed, 32 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-bcm2835.c b/drivers/i2c/busses/i2c-bcm2835.c
+index d2085dd..c3436f6 100644
+--- a/drivers/i2c/busses/i2c-bcm2835.c
++++ b/drivers/i2c/busses/i2c-bcm2835.c
+@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev {
+ void __iomem *regs;
+ struct clk *clk;
+ int irq;
++ u32 bus_clk_rate;
+ struct i2c_adapter adapter;
+ struct completion completion;
+ struct i2c_msg *curr_msg;
+@@ -78,6 +79,30 @@ static inline u32 bcm2835_i2c_readl(struct bcm2835_i2c_dev *i2c_dev, u32 reg)
+ return readl(i2c_dev->regs + reg);
+ }
+
++static int bcm2835_i2c_set_divider(struct bcm2835_i2c_dev *i2c_dev)
++{
++ u32 divider;
++
++ divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk),
++ i2c_dev->bus_clk_rate);
++ /*
++ * Per the datasheet, the register is always interpreted as an even
++ * number, by rounding down. In other words, the LSB is ignored. So,
++ * if the LSB is set, increment the divider to avoid any issue.
++ */
++ if (divider & 1)
++ divider++;
++ if ((divider < BCM2835_I2C_CDIV_MIN) ||
++ (divider > BCM2835_I2C_CDIV_MAX)) {
++ dev_err_ratelimited(i2c_dev->dev, "Invalid clock-frequency\n");
++ return -EINVAL;
++ }
++
++ bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
++
++ return 0;
++}
++
+ static void bcm2835_fill_txfifo(struct bcm2835_i2c_dev *i2c_dev)
+ {
+ u32 val;
+@@ -224,7 +249,7 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+ {
+ struct bcm2835_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+ unsigned long time_left;
+- int i;
++ int i, ret;
+
+ for (i = 0; i < (num - 1); i++)
+ if (msgs[i].flags & I2C_M_RD) {
+@@ -233,6 +258,10 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+ return -EOPNOTSUPP;
+ }
+
++ ret = bcm2835_i2c_set_divider(i2c_dev);
++ if (ret)
++ return ret;
++
+ i2c_dev->curr_msg = msgs;
+ i2c_dev->num_msgs = num;
+ reinit_completion(&i2c_dev->completion);
+@@ -282,7 +311,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
+ {
+ struct bcm2835_i2c_dev *i2c_dev;
+ struct resource *mem, *irq;
+- u32 bus_clk_rate, divider;
+ int ret;
+ struct i2c_adapter *adap;
+
+@@ -306,27 +334,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
+- &bus_clk_rate);
++ &i2c_dev->bus_clk_rate);
+ if (ret < 0) {
+ dev_warn(&pdev->dev,
+ "Could not read clock-frequency property\n");
+- bus_clk_rate = 100000;
+- }
+-
+- divider = DIV_ROUND_UP(clk_get_rate(i2c_dev->clk), bus_clk_rate);
+- /*
+- * Per the datasheet, the register is always interpreted as an even
+- * number, by rounding down. In other words, the LSB is ignored. So,
+- * if the LSB is set, increment the divider to avoid any issue.
+- */
+- if (divider & 1)
+- divider++;
+- if ((divider < BCM2835_I2C_CDIV_MIN) ||
+- (divider > BCM2835_I2C_CDIV_MAX)) {
+- dev_err(&pdev->dev, "Invalid clock-frequency\n");
+- return -ENODEV;
++ i2c_dev->bus_clk_rate = 100000;
+ }
+- bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_DIV, divider);
+
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq) {
+--
+2.9.3
+
+From f2a46926aba1f0c33944901d2420a6a887455ddc Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@free-electrons.com>
+Date: Tue, 22 Nov 2016 12:45:28 -0800
+Subject: [PATCH 08819/13183] clk: bcm2835: Fix ->fixed_divider of pllh_aux
+
+There is no fixed divider on pllh_aux.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Signed-off-by: Eric Anholt <eric@anholt.net>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 8c7763f..836d075 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1596,7 +1596,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
+ .a2w_reg = A2W_PLLH_AUX,
+ .load_mask = CM_PLLH_LOADAUX,
+ .hold_mask = 0,
+- .fixed_divider = 10),
++ .fixed_divider = 1),
+ [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(
+ .name = "pllh_pix",
+ .source_pll = "pllh",
+--
+2.9.3
+
+From 68af4fa8f39b542a6cde7ac19518d88e9b3099dc Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@free-electrons.com>
+Date: Thu, 1 Dec 2016 20:27:21 +0100
+Subject: [PATCH 11732/13183] clk: bcm2835: Avoid overwriting the div info when
+ disabling a pll_div clk
+
+bcm2835_pll_divider_off() is resetting the divider field in the A2W reg
+to zero when disabling the clock.
+
+Make sure we preserve this value by reading the previous a2w_reg value
+first and ORing the result with A2W_PLL_CHANNEL_DISABLE.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Fixes: 41691b8862e2 ("clk: bcm2835: Add support for programming the audio domain clocks")
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 836d075..2acaa77 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -751,7 +751,9 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw)
+ cprman_write(cprman, data->cm_reg,
+ (cprman_read(cprman, data->cm_reg) &
+ ~data->load_mask) | data->hold_mask);
+- cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
++ cprman_write(cprman, data->a2w_reg,
++ cprman_read(cprman, data->a2w_reg) |
++ A2W_PLL_CHANNEL_DISABLE);
+ spin_unlock(&cprman->regs_lock);
+ }
+
+--
+2.9.3
+
+commit 84c39b8b7d46883f7a7514c7d55909831aa846fd
+Author: Arvind Yadav <arvind.yadav.cs@gmail.com>
+Date: Wed Sep 21 23:03:57 2016 +0530
+
+ clocksource/drivers/bcm2835_timer: Unmap region obtained by of_iomap
+
+ Free memory mapping, if bcm2835_timer_init is not successful.
+
+ Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
+ Reviewed-by: Eric Anholt <eric@anholt.net>
+ Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+
+diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
+index e71acf2..f2f29d2 100644
+--- a/drivers/clocksource/bcm2835_timer.c
++++ b/drivers/clocksource/bcm2835_timer.c
+@@ -96,7 +96,7 @@ static int __init bcm2835_timer_init(struct device_node *node)
+ ret = of_property_read_u32(node, "clock-frequency", &freq);
+ if (ret) {
+ pr_err("Can't read clock-frequency");
+- return ret;
++ goto err_iounmap;
+ }
+
+ system_clock = base + REG_COUNTER_LO;
+@@ -108,13 +108,15 @@ static int __init bcm2835_timer_init(struct device_node *node)
+ irq = irq_of_parse_and_map(node, DEFAULT_TIMER);
+ if (irq <= 0) {
+ pr_err("Can't parse IRQ");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err_iounmap;
+ }
+
+ timer = kzalloc(sizeof(*timer), GFP_KERNEL);
+ if (!timer) {
+ pr_err("Can't allocate timer struct\n");
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto err_iounmap;
+ }
+
+ timer->control = base + REG_CONTROL;
+@@ -133,7 +135,7 @@ static int __init bcm2835_timer_init(struct device_node *node)
+ ret = setup_irq(irq, &timer->act);
+ if (ret) {
+ pr_err("Can't set up timer IRQ\n");
+- return ret;
++ goto err_iounmap;
+ }
+
+ clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff);
+@@ -141,6 +143,10 @@ static int __init bcm2835_timer_init(struct device_node *node)
+ pr_info("bcm2835: system timer (irq = %d)\n", irq);
+
+ return 0;
++
++err_iounmap:
++ iounmap(base);
++ return ret;
+ }
+ CLOCKSOURCE_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer",
+ bcm2835_timer_init);
+From 155e8b3b0ee320ae866b97dd31eba8a1f080a772 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@free-electrons.com>
+Date: Thu, 1 Dec 2016 22:00:19 +0100
+Subject: [PATCH 11733/13183] clk: bcm: Support rate change propagation on
+ bcm2835 clocks
+
+Some peripheral clocks, like the VEC (Video EnCoder) clock need to be set
+to a precise rate (in our case 108MHz). With the current implementation,
+where peripheral clocks are not allowed to forward rate change requests
+to their parents, it is impossible to match this requirement unless the
+bootloader has configured things correctly, or a specific rate has been
+assigned through the DT (with the assigned-clk-rates property).
+
+Add a new field to struct bcm2835_clock_data to specify which parent
+clocks accept rate change propagation, and support set rate propagation
+in bcm2835_clock_determine_rate().
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 67 ++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 63 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index 2acaa77..df96fe6 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -436,6 +436,9 @@ struct bcm2835_clock_data {
+ const char *const *parents;
+ int num_mux_parents;
+
++ /* Bitmap encoding which parents accept rate change propagation. */
++ unsigned int set_rate_parent;
++
+ u32 ctl_reg;
+ u32 div_reg;
+
+@@ -1017,10 +1020,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw)
+ return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
+ }
+
++static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
++ int parent_idx,
++ unsigned long rate,
++ u32 *div,
++ unsigned long *prate)
++{
++ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
++ struct bcm2835_cprman *cprman = clock->cprman;
++ const struct bcm2835_clock_data *data = clock->data;
++ unsigned long best_rate;
++ u32 curdiv, mindiv, maxdiv;
++ struct clk_hw *parent;
++
++ parent = clk_hw_get_parent_by_index(hw, parent_idx);
++
++ if (!(BIT(parent_idx) & data->set_rate_parent)) {
++ *prate = clk_hw_get_rate(parent);
++ *div = bcm2835_clock_choose_div(hw, rate, *prate, true);
++
++ return bcm2835_clock_rate_from_divisor(clock, *prate,
++ *div);
++ }
++
++ if (data->frac_bits)
++ dev_warn(cprman->dev,
++ "frac bits are not used when propagating rate change");
++
++ /* clamp to min divider of 2 if we're dealing with a mash clock */
++ mindiv = data->is_mash_clock ? 2 : 1;
++ maxdiv = BIT(data->int_bits) - 1;
++
++ /* TODO: Be smart, and only test a subset of the available divisors. */
++ for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
++ unsigned long tmp_rate;
++
++ tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
++ tmp_rate /= curdiv;
++ if (curdiv == mindiv ||
++ (tmp_rate > best_rate && tmp_rate <= rate))
++ best_rate = tmp_rate;
++
++ if (best_rate == rate)
++ break;
++ }
++
++ *div = curdiv << CM_DIV_FRAC_BITS;
++ *prate = curdiv * best_rate;
++
++ return best_rate;
++}
++
+ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+ {
+- struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct clk_hw *parent, *best_parent = NULL;
+ bool current_parent_is_pllc;
+ unsigned long rate, best_rate = 0;
+@@ -1048,9 +1101,8 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw,
+ if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
+ continue;
+
+- prate = clk_hw_get_rate(parent);
+- div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
+- rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
++ rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
++ &div, &prate);
+ if (rate > best_rate && rate <= req->rate) {
+ best_parent = parent;
+ best_prate = prate;
+@@ -1262,6 +1314,13 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
+ init.name = data->name;
+ init.flags = data->flags | CLK_IGNORE_UNUSED;
+
++ /*
++ * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
++ * rate changes on at least of the parents.
++ */
++ if (data->set_rate_parent)
++ init.flags |= CLK_SET_RATE_PARENT;
++
+ if (data->is_vpu_clock) {
+ init.ops = &bcm2835_vpu_clock_clk_ops;
+ } else {
+--
+2.9.3
+
+From d86d46af84855403c00018be1c3e7bc190f2a6cd Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@free-electrons.com>
+Date: Thu, 1 Dec 2016 22:00:20 +0100
+Subject: [PATCH 11734/13183] clk: bcm: Allow rate change propagation to
+ PLLH_AUX on VEC clock
+
+The VEC clock requires needs to be set at exactly 108MHz. Allow rate
+change propagation on PLLH_AUX to match this requirement wihtout
+impacting other IPs (PLLH is currently only used by the HDMI encoder,
+which cannot be enabled when the VEC encoder is enabled).
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index df96fe6..eaf82f4 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1861,7 +1861,12 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
+ .ctl_reg = CM_VECCTL,
+ .div_reg = CM_VECDIV,
+ .int_bits = 4,
+- .frac_bits = 0),
++ .frac_bits = 0,
++ /*
++ * Allow rate change propagation only on PLLH_AUX which is
++ * assigned index 7 in the parent array.
++ */
++ .set_rate_parent = BIT(7)),
+
+ /* dsi clocks */
+ [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK(
+--
+2.9.3
+
+From 2aab7a2055a1705c9e30920d95a596226999eb21 Mon Sep 17 00:00:00 2001
+From: Boris Brezillon <boris.brezillon@free-electrons.com>
+Date: Mon, 12 Dec 2016 09:00:53 +0100
+Subject: [PATCH 12092/13183] clk: bcm: Fix 'maybe-uninitialized' warning in
+ bcm2835_clock_choose_div_and_prate()
+
+best_rate is reported as potentially uninitialized by gcc.
+
+Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
+Fixes: 155e8b3b0ee3 ("clk: bcm: Support rate change propagation on bcm2835 clocks")
+Reported-by: Stephen Rothwell <sfr@canb.auug.org.au>
+Reviewed-by: Eric Anholt <eric@anholt.net>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+---
+ drivers/clk/bcm/clk-bcm2835.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
+index eaf82f4..0d14409 100644
+--- a/drivers/clk/bcm/clk-bcm2835.c
++++ b/drivers/clk/bcm/clk-bcm2835.c
+@@ -1029,7 +1029,7 @@ static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
+ struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
+ struct bcm2835_cprman *cprman = clock->cprman;
+ const struct bcm2835_clock_data *data = clock->data;
+- unsigned long best_rate;
++ unsigned long best_rate = 0;
+ u32 curdiv, mindiv, maxdiv;
+ struct clk_hw *parent;
+
+--
+2.9.3
+
diff --git a/kernel.spec b/kernel.spec
index 0a11be54e..e15666cd9 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -525,11 +525,13 @@ Patch431: bcm2837-initial-support.patch
Patch432: bcm283x-vc4-fixes.patch
-Patch433: AllWinner-net-emac.patch
+Patch433: bcm283x-fixes.patch
-Patch434: ARM-Drop-fixed-200-Hz-timer-requirement-from-Samsung-platforms.patch
+Patch434: AllWinner-net-emac.patch
-Patch435: imx6sx-Add-UDOO-Neo-support.patch
+Patch435: ARM-Drop-fixed-200-Hz-timer-requirement-from-Samsung-platforms.patch
+
+Patch436: imx6sx-Add-UDOO-Neo-support.patch
Patch460: lib-cpumask-Make-CPUMASK_OFFSTACK-usable-without-deb.patch
@@ -2173,6 +2175,7 @@ fi
* Tue Dec 20 2016 Peter Robinson <pbrobinson@fedoraproject.org>
- Update some ARM options
- Enable some Qualcomm QDF2432 server platform options
+- Add upstream bcm283x i2c and clock fixes
* Thu Dec 15 2016 Laura Abbott <labbott@fedoraproject.org>
- Linux v4.9 rebase