+++ /dev/null
-From cd4b1e34655d46950c065d9284b596cd8d7b28cd Mon Sep 17 00:00:00 2001
-From: John Youn <johnyoun@synopsys.com>
-Date: Thu, 3 Nov 2016 17:55:45 -0700
-Subject: [PATCH] usb: dwc2: Remove unnecessary kfree
-
-This shouldn't be freed by the HCD as it is owned by the core and
-allocated with devm_kzalloc.
-
-Signed-off-by: John Youn <johnyoun@synopsys.com>
-Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
----
- drivers/usb/dwc2/hcd.c | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/drivers/usb/dwc2/hcd.c
-+++ b/drivers/usb/dwc2/hcd.c
-@@ -5185,7 +5185,6 @@ error3:
- error2:
- usb_put_hcd(hcd);
- error1:
-- kfree(hsotg->core_params);
-
- #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
- kfree(hsotg->last_frame_num_array);
+++ /dev/null
-From be5e5099183301fb7920f8f6b66bd3ac1f820a97 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 16 Jan 2017 17:28:18 +0100
-Subject: [PATCH] mtd: bcm47xxsflash: use platform_(set|get)_drvdata
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-We have generic place & helpers for storing platform driver data so
-there is no reason for using custom priv pointer.
-
-This allows cleaning up struct bcma_sflash from unneeded fields.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Kalle Valo <kvalo@codeaurora.org>
-Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/devices/bcm47xxsflash.c | 6 +++---
- include/linux/bcma/bcma_driver_chipcommon.h | 3 ---
- 2 files changed, 3 insertions(+), 6 deletions(-)
-
---- a/drivers/mtd/devices/bcm47xxsflash.c
-+++ b/drivers/mtd/devices/bcm47xxsflash.c
-@@ -284,7 +284,6 @@ static int bcm47xxsflash_bcma_probe(stru
- b47s = devm_kzalloc(dev, sizeof(*b47s), GFP_KERNEL);
- if (!b47s)
- return -ENOMEM;
-- sflash->priv = b47s;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
-@@ -320,6 +319,8 @@ static int bcm47xxsflash_bcma_probe(stru
- b47s->size = sflash->size;
- bcm47xxsflash_fill_mtd(b47s, &pdev->dev);
-
-+ platform_set_drvdata(pdev, b47s);
-+
- err = mtd_device_parse_register(&b47s->mtd, probes, NULL, NULL, 0);
- if (err) {
- pr_err("Failed to register MTD device: %d\n", err);
-@@ -335,8 +336,7 @@ static int bcm47xxsflash_bcma_probe(stru
-
- static int bcm47xxsflash_bcma_remove(struct platform_device *pdev)
- {
-- struct bcma_sflash *sflash = dev_get_platdata(&pdev->dev);
-- struct bcm47xxsflash *b47s = sflash->priv;
-+ struct bcm47xxsflash *b47s = platform_get_drvdata(pdev);
-
- mtd_device_unregister(&b47s->mtd);
- iounmap(b47s->window);
---- a/include/linux/bcma/bcma_driver_chipcommon.h
-+++ b/include/linux/bcma/bcma_driver_chipcommon.h
-@@ -593,9 +593,6 @@ struct bcma_sflash {
- u32 blocksize;
- u16 numblocks;
- u32 size;
--
-- struct mtd_info *mtd;
-- void *priv;
- };
- #endif
-
+++ /dev/null
-From ccc38234fdc70120be79e7fb2df5c27ca5cd4c8a Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 8 Feb 2017 23:53:44 +0100
-Subject: [PATCH] mtd: bcm47xxsflash: support reading flash out of mapping
- window
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-For reading flash content we use MMIO but it's possible to read only
-first 16 MiB this way. It's simply an arch design/limitation.
-To support flash sizes bigger than 16 MiB implement indirect access
-using ChipCommon registers.
-This has been tested using MX25L25635F.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/devices/bcm47xxsflash.c | 24 +++++++++++++++++++++---
- drivers/mtd/devices/bcm47xxsflash.h | 3 +++
- 2 files changed, 24 insertions(+), 3 deletions(-)
-
---- a/drivers/mtd/devices/bcm47xxsflash.c
-+++ b/drivers/mtd/devices/bcm47xxsflash.c
-@@ -105,15 +105,33 @@ static int bcm47xxsflash_read(struct mtd
- size_t *retlen, u_char *buf)
- {
- struct bcm47xxsflash *b47s = mtd->priv;
-+ size_t orig_len = len;
-
- /* Check address range */
- if ((from + len) > mtd->size)
- return -EINVAL;
-
-- memcpy_fromio(buf, b47s->window + from, len);
-- *retlen = len;
-+ /* Read as much as possible using fast MMIO window */
-+ if (from < BCM47XXSFLASH_WINDOW_SZ) {
-+ size_t memcpy_len;
-
-- return len;
-+ memcpy_len = min(len, (size_t)(BCM47XXSFLASH_WINDOW_SZ - from));
-+ memcpy_fromio(buf, b47s->window + from, memcpy_len);
-+ from += memcpy_len;
-+ len -= memcpy_len;
-+ buf += memcpy_len;
-+ }
-+
-+ /* Use indirect access for content out of the window */
-+ for (; len; len--) {
-+ b47s->cc_write(b47s, BCMA_CC_FLASHADDR, from++);
-+ bcm47xxsflash_cmd(b47s, OPCODE_ST_READ4B);
-+ *buf++ = b47s->cc_read(b47s, BCMA_CC_FLASHDATA);
-+ }
-+
-+ *retlen = orig_len;
-+
-+ return orig_len;
- }
-
- static int bcm47xxsflash_write_st(struct mtd_info *mtd, u32 offset, size_t len,
---- a/drivers/mtd/devices/bcm47xxsflash.h
-+++ b/drivers/mtd/devices/bcm47xxsflash.h
-@@ -3,6 +3,8 @@
-
- #include <linux/mtd/mtd.h>
-
-+#define BCM47XXSFLASH_WINDOW_SZ SZ_16M
-+
- /* Used for ST flashes only. */
- #define OPCODE_ST_WREN 0x0006 /* Write Enable */
- #define OPCODE_ST_WRDIS 0x0004 /* Write Disable */
-@@ -16,6 +18,7 @@
- #define OPCODE_ST_RES 0x03ab /* Read Electronic Signature */
- #define OPCODE_ST_CSA 0x1000 /* Keep chip select asserted */
- #define OPCODE_ST_SSE 0x0220 /* Sub-sector Erase */
-+#define OPCODE_ST_READ4B 0x6313 /* Read Data Bytes in 4Byte addressing mode */
-
- /* Used for Atmel flashes only. */
- #define OPCODE_AT_READ 0x07e8
+++ /dev/null
-From b522d7b0ebe3539340c2a6d46d787ae3d33bcb92 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 10 Jan 2017 23:15:24 +0100
-Subject: [PATCH] mtd: bcm47xxpart: move TRX parsing code to separated function
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This change simplifies main parsing loop logic a bit. In future it may
-be useful for moving TRX support to separated module / parser (if we
-implement support for them at some point).
-Finally parsing TRX at the end puts us in a better position as we have
-better flash layout knowledge. It may be useful e.g. if it appears there
-is more than 1 TRX partition.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/bcm47xxpart.c | 121 ++++++++++++++++++++++++++++------------------
- 1 file changed, 74 insertions(+), 47 deletions(-)
-
---- a/drivers/mtd/bcm47xxpart.c
-+++ b/drivers/mtd/bcm47xxpart.c
-@@ -83,6 +83,67 @@ out_default:
- return "rootfs";
- }
-
-+static int bcm47xxpart_parse_trx(struct mtd_info *master,
-+ struct mtd_partition *trx,
-+ struct mtd_partition *parts,
-+ size_t parts_len)
-+{
-+ struct trx_header header;
-+ size_t bytes_read;
-+ int curr_part = 0;
-+ int i, err;
-+
-+ if (parts_len < 3) {
-+ pr_warn("No enough space to add TRX partitions!\n");
-+ return -ENOMEM;
-+ }
-+
-+ err = mtd_read(master, trx->offset, sizeof(header), &bytes_read,
-+ (uint8_t *)&header);
-+ if (err && !mtd_is_bitflip(err)) {
-+ pr_err("mtd_read error while reading TRX header: %d\n", err);
-+ return err;
-+ }
-+
-+ i = 0;
-+
-+ /* We have LZMA loader if offset[2] points to sth */
-+ if (header.offset[2]) {
-+ bcm47xxpart_add_part(&parts[curr_part++], "loader",
-+ trx->offset + header.offset[i], 0);
-+ i++;
-+ }
-+
-+ if (header.offset[i]) {
-+ bcm47xxpart_add_part(&parts[curr_part++], "linux",
-+ trx->offset + header.offset[i], 0);
-+ i++;
-+ }
-+
-+ if (header.offset[i]) {
-+ size_t offset = trx->offset + header.offset[i];
-+ const char *name = bcm47xxpart_trx_data_part_name(master,
-+ offset);
-+
-+ bcm47xxpart_add_part(&parts[curr_part++], name, offset, 0);
-+ i++;
-+ }
-+
-+ /*
-+ * Assume that every partition ends at the beginning of the one it is
-+ * followed by.
-+ */
-+ for (i = 0; i < curr_part; i++) {
-+ u64 next_part_offset = (i < curr_part - 1) ?
-+ parts[i + 1].offset :
-+ trx->offset + trx->size;
-+
-+ parts[i].size = next_part_offset - parts[i].offset;
-+ }
-+
-+ return curr_part;
-+}
-+
- static int bcm47xxpart_parse(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-@@ -93,9 +154,7 @@ static int bcm47xxpart_parse(struct mtd_
- size_t bytes_read;
- uint32_t offset;
- uint32_t blocksize = master->erasesize;
-- struct trx_header *trx;
- int trx_part = -1;
-- int last_trx_part = -1;
- int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, };
- int err;
-
-@@ -182,54 +241,14 @@ static int bcm47xxpart_parse(struct mtd_
-
- /* TRX */
- if (buf[0x000 / 4] == TRX_MAGIC) {
-- if (BCM47XXPART_MAX_PARTS - curr_part < 4) {
-- pr_warn("Not enough partitions left to register trx, scanning stopped!\n");
-- break;
-- }
--
-- trx = (struct trx_header *)buf;
-+ struct trx_header *trx;
-
- trx_part = curr_part;
- bcm47xxpart_add_part(&parts[curr_part++], "firmware",
- offset, 0);
-
-- i = 0;
-- /* We have LZMA loader if offset[2] points to sth */
-- if (trx->offset[2]) {
-- bcm47xxpart_add_part(&parts[curr_part++],
-- "loader",
-- offset + trx->offset[i],
-- 0);
-- i++;
-- }
--
-- if (trx->offset[i]) {
-- bcm47xxpart_add_part(&parts[curr_part++],
-- "linux",
-- offset + trx->offset[i],
-- 0);
-- i++;
-- }
--
-- /*
-- * Pure rootfs size is known and can be calculated as:
-- * trx->length - trx->offset[i]. We don't fill it as
-- * we want to have jffs2 (overlay) in the same mtd.
-- */
-- if (trx->offset[i]) {
-- const char *name;
--
-- name = bcm47xxpart_trx_data_part_name(master, offset + trx->offset[i]);
-- bcm47xxpart_add_part(&parts[curr_part++],
-- name,
-- offset + trx->offset[i],
-- 0);
-- i++;
-- }
--
-- last_trx_part = curr_part - 1;
--
- /* Jump to the end of TRX */
-+ trx = (struct trx_header *)buf;
- offset = roundup(offset + trx->length, blocksize);
- /* Next loop iteration will increase the offset */
- offset -= blocksize;
-@@ -307,9 +326,17 @@ static int bcm47xxpart_parse(struct mtd_
- parts[i + 1].offset : master->size;
-
- parts[i].size = next_part_offset - parts[i].offset;
-- if (i == last_trx_part && trx_part >= 0)
-- parts[trx_part].size = next_part_offset -
-- parts[trx_part].offset;
-+ }
-+
-+ /* If there was TRX parse it now */
-+ if (trx_part >= 0) {
-+ int num_parts;
-+
-+ num_parts = bcm47xxpart_parse_trx(master, &parts[trx_part],
-+ parts + curr_part,
-+ BCM47XXPART_MAX_PARTS - curr_part);
-+ if (num_parts > 0)
-+ curr_part += num_parts;
- }
-
- *pparts = parts;
+++ /dev/null
-From 89a0d9a9f1941a086a82bc7cd73d275cec98ba14 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 10 Jan 2017 23:15:25 +0100
-Subject: [PATCH] mtd: bcm47xxpart: support layouts with multiple TRX
- partitions
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Some devices may have an extra TRX partition used as failsafe one. If
-we detect such partition we should set a proper name for it and don't
-parse it.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/bcm47xxpart.c | 56 ++++++++++++++++++++++++++++++++++++++---------
- 1 file changed, 46 insertions(+), 10 deletions(-)
-
---- a/drivers/mtd/bcm47xxpart.c
-+++ b/drivers/mtd/bcm47xxpart.c
-@@ -9,6 +9,7 @@
- *
- */
-
-+#include <linux/bcm47xx_nvram.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/slab.h>
-@@ -144,6 +145,30 @@ static int bcm47xxpart_parse_trx(struct
- return curr_part;
- }
-
-+/**
-+ * bcm47xxpart_bootpartition - gets index of TRX partition used by bootloader
-+ *
-+ * Some devices may have more than one TRX partition. In such case one of them
-+ * is the main one and another a failsafe one. Bootloader may fallback to the
-+ * failsafe firmware if it detects corruption of the main image.
-+ *
-+ * This function provides info about currently used TRX partition. It's the one
-+ * containing kernel started by the bootloader.
-+ */
-+static int bcm47xxpart_bootpartition(void)
-+{
-+ char buf[4];
-+ int bootpartition;
-+
-+ /* Check CFE environment variable */
-+ if (bcm47xx_nvram_getenv("bootpartition", buf, sizeof(buf)) > 0) {
-+ if (!kstrtoint(buf, 0, &bootpartition))
-+ return bootpartition;
-+ }
-+
-+ return 0;
-+}
-+
- static int bcm47xxpart_parse(struct mtd_info *master,
- const struct mtd_partition **pparts,
- struct mtd_part_parser_data *data)
-@@ -154,7 +179,8 @@ static int bcm47xxpart_parse(struct mtd_
- size_t bytes_read;
- uint32_t offset;
- uint32_t blocksize = master->erasesize;
-- int trx_part = -1;
-+ int trx_parts[2]; /* Array with indexes of TRX partitions */
-+ int trx_num = 0; /* Number of found TRX partitions */
- int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, };
- int err;
-
-@@ -243,7 +269,11 @@ static int bcm47xxpart_parse(struct mtd_
- if (buf[0x000 / 4] == TRX_MAGIC) {
- struct trx_header *trx;
-
-- trx_part = curr_part;
-+ if (trx_num >= ARRAY_SIZE(trx_parts))
-+ pr_warn("No enough space to store another TRX found at 0x%X\n",
-+ offset);
-+ else
-+ trx_parts[trx_num++] = curr_part;
- bcm47xxpart_add_part(&parts[curr_part++], "firmware",
- offset, 0);
-
-@@ -329,14 +359,20 @@ static int bcm47xxpart_parse(struct mtd_
- }
-
- /* If there was TRX parse it now */
-- if (trx_part >= 0) {
-- int num_parts;
-+ for (i = 0; i < trx_num; i++) {
-+ struct mtd_partition *trx = &parts[trx_parts[i]];
-
-- num_parts = bcm47xxpart_parse_trx(master, &parts[trx_part],
-- parts + curr_part,
-- BCM47XXPART_MAX_PARTS - curr_part);
-- if (num_parts > 0)
-- curr_part += num_parts;
-+ if (i == bcm47xxpart_bootpartition()) {
-+ int num_parts;
-+
-+ num_parts = bcm47xxpart_parse_trx(master, trx,
-+ parts + curr_part,
-+ BCM47XXPART_MAX_PARTS - curr_part);
-+ if (num_parts > 0)
-+ curr_part += num_parts;
-+ } else {
-+ trx->name = "failsafe";
-+ }
- }
-
- *pparts = parts;
+++ /dev/null
-From 355445b86f0f61125409e1217be4f0a8ee362116 Mon Sep 17 00:00:00 2001
-From: Ash Benz <ash.benz@bk.ru>
-Date: Sat, 19 Nov 2016 07:51:49 +0800
-Subject: [PATCH] mtd: spi-nor: add Macronix mx25u25635f to list of known
- devices.
-
-Signed-off-by: Ash Benz <ash.benz@bk.ru>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -872,6 +872,7 @@ static const struct flash_info spi_nor_i
- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
- { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
-+ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K) },
- { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
- { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
- { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
+++ /dev/null
-From 807c16253319ee6ccf8873ae64f070f7eb532cd5 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jo=C3=ABl=20Esponde?= <joel.esponde@honeywell.com>
-Date: Wed, 23 Nov 2016 12:47:40 +0100
-Subject: [PATCH] mtd: spi-nor: fix spansion quad enable
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-With the S25FL127S nor flash part, each writing to the configuration
-register takes hundreds of ms. During that time, no more accesses to
-the flash should be done (even reads).
-
-This commit adds a wait loop after the register writing until the flash
-finishes its work.
-
-This issue could make rootfs mounting fail when the latter was done too
-much closely to this quad enable bit setting step. And in this case, a
-driver as UBIFS may try to recover the filesystem and may broke it
-completely.
-
-Signed-off-by: Joël Esponde <joel.esponde@honeywell.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1263,6 +1263,13 @@ static int spansion_quad_enable(struct s
- return ret;
- }
-
-+ ret = spi_nor_wait_till_ready(nor);
-+ if (ret) {
-+ dev_err(nor->dev,
-+ "timeout while writing configuration register\n");
-+ return ret;
-+ }
-+
- /* read back and check it */
- ret = read_cr(nor);
- if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
+++ /dev/null
-From 4287916d7bab2806305d3296b4cf261fa49d959b Mon Sep 17 00:00:00 2001
-From: Heiner Kallweit <hkallweit1@gmail.com>
-Date: Thu, 27 Oct 2016 23:13:26 +0200
-Subject: [PATCH] mtd: spi-nor: fix flags for s25fl128s
-
-The Spansion S25FL128S also supports dual read mode.
-In addition remove flag SECT_4K. 4K erases are supported,
-but not uniformly.
-
-Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
-Reviewed-by: Jagan Teki <jteki@openedev.com>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -906,7 +906,7 @@ static const struct flash_info spi_nor_i
- { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
- { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
- { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
-- { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
-+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
+++ /dev/null
-From 022a400f90ceeb26405edd5e077d56e2f38c8123 Mon Sep 17 00:00:00 2001
-From: Sean Nyekjaer <sean.nyekjaer@prevas.dk>
-Date: Wed, 5 Oct 2016 10:59:49 +0200
-Subject: [PATCH] mtd: spi-nor: add support for s25fl208k
-
-Signed-off-by: Sean Nyekjaer <sean.nyekjaer@prevas.dk>
-Reviewed-by: Jagan Teki <jagan@openedev.com>
-Acked-by: Marek Vasut <marex@denx.de>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -922,6 +922,7 @@ static const struct flash_info spi_nor_i
- { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) },
- { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) },
- { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) },
-+ { "s25fl208k", INFO(0x014014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ) },
-
- /* SST -- large erase sizes are "overlays", "sectors" are 4K */
- { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
+++ /dev/null
-From b08618c929b289699a496b8d45a4e1a014187e56 Mon Sep 17 00:00:00 2001
-From: Jagan Teki <jteki@openedev.com>
-Date: Tue, 26 Jul 2016 14:07:54 +0530
-Subject: [PATCH] mtd: spi-nor: Add at25df321 spi-nor flash support
-
-Add Atmel at25df321 spi-nor flash to the list of spi_nor_ids.
-
-Cc: Brian Norris <computersforpeace@gmail.com>
-Cc: Wenyou Yang <wenyou.yang@atmel.com>
-Signed-off-by: Jagan Teki <jteki@openedev.com>
-Acked-by: Wenyou Yang <wenyou.yang@atmel.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -799,6 +799,7 @@ static const struct flash_info spi_nor_i
- { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
-
- { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
-+ { "at25df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
- { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
- { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
-
+++ /dev/null
-From 61e4611864b396c7e9040b7335f25d3921bc87cd Mon Sep 17 00:00:00 2001
-From: Moritz Fischer <moritz.fischer@ettus.com>
-Date: Fri, 15 Jul 2016 10:03:48 -0700
-Subject: [PATCH] mtd: spi-nor: Add support for N25Q016A
-
-This commit adds support in the spi-nor driver for the
-N25Q016A, a 16Mbit SPI NOR flash from Micron.
-
-Cc: David Woodhouse <dwmw2@infradead.org>
-Cc: Brian Norris <computersforpeace@gmail.com>
-Cc: Jagan Teki <jteki@openedev.com>
-
-Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
-Reviewed-by: Jagan Teki <jteki@openedev.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -879,6 +879,7 @@ static const struct flash_info spi_nor_i
- { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
-
- /* Micron */
-+ { "n25q016a", INFO(0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) },
- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) },
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) },
+++ /dev/null
-From edd0c8f4932dbf3e21036cb443ba5bdf7449d02b Mon Sep 17 00:00:00 2001
-From: IWAMOTO Masahiko <iwamoto@allied-telesis.co.jp>
-Date: Wed, 5 Oct 2016 08:22:52 +0000
-Subject: [PATCH] mtd: spi-nor: Add support for mr25h40
-
-Add Everspin mr25h40 512KB MRAM to the list of supported chips.
-
-Signed-off-by: Masahiko Iwamoto <iwamoto@allied-telesis.co.jp>
-Reviewed-by: Jagan Teki <jagan@openedev.com>
-Acked-by: Marek Vasut <marex@denx.de>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -826,6 +826,7 @@ static const struct flash_info spi_nor_i
- /* Everspin */
- { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-+ { "mr25h40", CAT25_INFO(512 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-
- /* Fujitsu */
- { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
+++ /dev/null
-From 61cba34bd6c1bddfc38f94cc3f80bdfefcc3393b Mon Sep 17 00:00:00 2001
-From: Ricardo Ribalda <ricardo.ribalda@gmail.com>
-Date: Fri, 2 Dec 2016 12:31:44 +0100
-Subject: [PATCH] mtd: spi-nor: Add support for S3AN spi-nor devices
-
-Xilinx Spartan-3AN FPGAs contain an In-System Flash where they keep
-their configuration data and (optionally) some user data.
-
-The protocol of this flash follows most of the spi-nor standard. With
-the following differences:
-
-- Page size might not be a power of two.
-- The address calculation (default addressing mode).
-- The spi nor commands used.
-
-Protocol is described on Xilinx User Guide UG333
-
-Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
-Cc: Boris Brezillon <boris.brezillon@free-electrons.com>
-Cc: Brian Norris <computersforpeace@gmail.com>
-Cc: Marek Vasut <marek.vasut@gmail.com>
-Reviewed-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 154 ++++++++++++++++++++++++++++++++++++++++--
- include/linux/mtd/spi-nor.h | 12 ++++
- 2 files changed, 161 insertions(+), 5 deletions(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -75,6 +75,12 @@ struct flash_info {
- * bit. Must be used with
- * SPI_NOR_HAS_LOCK.
- */
-+#define SPI_S3AN BIT(10) /*
-+ * Xilinx Spartan 3AN In-System Flash
-+ * (MFR cannot be used for probing
-+ * because it has the same value as
-+ * ATMEL flashes)
-+ */
- };
-
- #define JEDEC_MFR(info) ((info)->id[0])
-@@ -217,6 +223,21 @@ static inline int set_4byte(struct spi_n
- return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1);
- }
- }
-+
-+static int s3an_sr_ready(struct spi_nor *nor)
-+{
-+ int ret;
-+ u8 val;
-+
-+ ret = nor->read_reg(nor, SPINOR_OP_XRDSR, &val, 1);
-+ if (ret < 0) {
-+ dev_err(nor->dev, "error %d reading XRDSR\n", (int) ret);
-+ return ret;
-+ }
-+
-+ return !!(val & XSR_RDY);
-+}
-+
- static inline int spi_nor_sr_ready(struct spi_nor *nor)
- {
- int sr = read_sr(nor);
-@@ -238,7 +259,11 @@ static inline int spi_nor_fsr_ready(stru
- static int spi_nor_ready(struct spi_nor *nor)
- {
- int sr, fsr;
-- sr = spi_nor_sr_ready(nor);
-+
-+ if (nor->flags & SNOR_F_READY_XSR_RDY)
-+ sr = s3an_sr_ready(nor);
-+ else
-+ sr = spi_nor_sr_ready(nor);
- if (sr < 0)
- return sr;
- fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1;
-@@ -320,6 +345,24 @@ static void spi_nor_unlock_and_unprep(st
- }
-
- /*
-+ * This code converts an address to the Default Address Mode, that has non
-+ * power of two page sizes. We must support this mode because it is the default
-+ * mode supported by Xilinx tools, it can access the whole flash area and
-+ * changing over to the Power-of-two mode is irreversible and corrupts the
-+ * original data.
-+ * Addr can safely be unsigned int, the biggest S3AN device is smaller than
-+ * 4 MiB.
-+ */
-+static loff_t spi_nor_s3an_addr_convert(struct spi_nor *nor, unsigned int addr)
-+{
-+ unsigned int offset = addr;
-+
-+ offset %= nor->page_size;
-+
-+ return ((addr - offset) << 1) | offset;
-+}
-+
-+/*
- * Initiate the erasure of a single sector
- */
- static int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
-@@ -327,6 +370,9 @@ static int spi_nor_erase_sector(struct s
- u8 buf[SPI_NOR_MAX_ADDR_WIDTH];
- int i;
-
-+ if (nor->flags & SNOR_F_S3AN_ADDR_DEFAULT)
-+ addr = spi_nor_s3an_addr_convert(nor, addr);
-+
- if (nor->erase)
- return nor->erase(nor, addr);
-
-@@ -368,7 +414,7 @@ static int spi_nor_erase(struct mtd_info
- return ret;
-
- /* whole-chip erase? */
-- if (len == mtd->size) {
-+ if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
- unsigned long timeout;
-
- write_enable(nor);
-@@ -782,6 +828,19 @@ static int spi_nor_is_locked(struct mtd_
- .addr_width = (_addr_width), \
- .flags = (_flags),
-
-+#define S3AN_INFO(_jedec_id, _n_sectors, _page_size) \
-+ .id = { \
-+ ((_jedec_id) >> 16) & 0xff, \
-+ ((_jedec_id) >> 8) & 0xff, \
-+ (_jedec_id) & 0xff \
-+ }, \
-+ .id_len = 3, \
-+ .sector_size = (8*_page_size), \
-+ .n_sectors = (_n_sectors), \
-+ .page_size = _page_size, \
-+ .addr_width = 3, \
-+ .flags = SPI_NOR_NO_FR | SPI_S3AN,
-+
- /* NOTE: double check command sets and memory organization when you add
- * more nor chips. This current list focusses on newer chips, which
- * have been converging on command sets which including JEDEC ID.
-@@ -1014,6 +1073,13 @@ static const struct flash_info spi_nor_i
- { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
- { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-+
-+ /* Xilinx S3AN Internal Flash */
-+ { "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
-+ { "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
-+ { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
-+ { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
-+ { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
- { },
- };
-
-@@ -1054,7 +1120,12 @@ static int spi_nor_read(struct mtd_info
- return ret;
-
- while (len) {
-- ret = nor->read(nor, from, len, buf);
-+ loff_t addr = from;
-+
-+ if (nor->flags & SNOR_F_S3AN_ADDR_DEFAULT)
-+ addr = spi_nor_s3an_addr_convert(nor, addr);
-+
-+ ret = nor->read(nor, addr, len, buf);
- if (ret == 0) {
- /* We shouldn't see 0-length reads */
- ret = -EIO;
-@@ -1175,8 +1246,23 @@ static int spi_nor_write(struct mtd_info
-
- for (i = 0; i < len; ) {
- ssize_t written;
-+ loff_t addr = to + i;
-
-- page_offset = (to + i) & (nor->page_size - 1);
-+ /*
-+ * If page_size is a power of two, the offset can be quickly
-+ * calculated with an AND operation. On the other cases we
-+ * need to do a modulus operation (more expensive).
-+ * Power of two numbers have only one bit set and we can use
-+ * the instruction hweight32 to detect if we need to do a
-+ * modulus (do_div()) or not.
-+ */
-+ if (hweight32(nor->page_size) == 1) {
-+ page_offset = addr & (nor->page_size - 1);
-+ } else {
-+ uint64_t aux = addr;
-+
-+ page_offset = do_div(aux, nor->page_size);
-+ }
- WARN_ONCE(page_offset,
- "Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
- page_offset);
-@@ -1184,8 +1270,11 @@ static int spi_nor_write(struct mtd_info
- page_remain = min_t(size_t,
- nor->page_size - page_offset, len - i);
-
-+ if (nor->flags & SNOR_F_S3AN_ADDR_DEFAULT)
-+ addr = spi_nor_s3an_addr_convert(nor, addr);
-+
- write_enable(nor);
-- ret = nor->write(nor, to + i, page_remain, buf + i);
-+ ret = nor->write(nor, addr, page_remain, buf + i);
- if (ret < 0)
- goto write_err;
- written = ret;
-@@ -1319,6 +1408,47 @@ static int spi_nor_check(struct spi_nor
- return 0;
- }
-
-+static int s3an_nor_scan(const struct flash_info *info, struct spi_nor *nor)
-+{
-+ int ret;
-+ u8 val;
-+
-+ ret = nor->read_reg(nor, SPINOR_OP_XRDSR, &val, 1);
-+ if (ret < 0) {
-+ dev_err(nor->dev, "error %d reading XRDSR\n", (int) ret);
-+ return ret;
-+ }
-+
-+ nor->erase_opcode = SPINOR_OP_XSE;
-+ nor->program_opcode = SPINOR_OP_XPP;
-+ nor->read_opcode = SPINOR_OP_READ;
-+ nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
-+
-+ /*
-+ * This flashes have a page size of 264 or 528 bytes (known as
-+ * Default addressing mode). It can be changed to a more standard
-+ * Power of two mode where the page size is 256/512. This comes
-+ * with a price: there is 3% less of space, the data is corrupted
-+ * and the page size cannot be changed back to default addressing
-+ * mode.
-+ *
-+ * The current addressing mode can be read from the XRDSR register
-+ * and should not be changed, because is a destructive operation.
-+ */
-+ if (val & XSR_PAGESIZE) {
-+ /* Flash in Power of 2 mode */
-+ nor->page_size = (nor->page_size == 264) ? 256 : 512;
-+ nor->mtd.writebufsize = nor->page_size;
-+ nor->mtd.size = 8 * nor->page_size * info->n_sectors;
-+ nor->mtd.erasesize = 8 * nor->page_size;
-+ } else {
-+ /* Flash in Default addressing mode */
-+ nor->flags |= SNOR_F_S3AN_ADDR_DEFAULT;
-+ }
-+
-+ return 0;
-+}
-+
- int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
- {
- const struct flash_info *info = NULL;
-@@ -1367,6 +1497,14 @@ int spi_nor_scan(struct spi_nor *nor, co
- mutex_init(&nor->lock);
-
- /*
-+ * Make sure the XSR_RDY flag is set before calling
-+ * spi_nor_wait_till_ready(). Xilinx S3AN share MFR
-+ * with Atmel spi-nor
-+ */
-+ if (info->flags & SPI_S3AN)
-+ nor->flags |= SNOR_F_READY_XSR_RDY;
-+
-+ /*
- * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
- * with the software protection bits set
- */
-@@ -1524,6 +1662,12 @@ int spi_nor_scan(struct spi_nor *nor, co
-
- nor->read_dummy = spi_nor_read_dummy_cycles(nor);
-
-+ if (info->flags & SPI_S3AN) {
-+ ret = s3an_nor_scan(info, nor);
-+ if (ret)
-+ return ret;
-+ }
-+
- dev_info(dev, "%s (%lld Kbytes)\n", info->name,
- (long long)mtd->size >> 10);
-
---- a/include/linux/mtd/spi-nor.h
-+++ b/include/linux/mtd/spi-nor.h
-@@ -68,6 +68,15 @@
- #define SPINOR_OP_WRDI 0x04 /* Write disable */
- #define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
-
-+/* Used for S3AN flashes only */
-+#define SPINOR_OP_XSE 0x50 /* Sector erase */
-+#define SPINOR_OP_XPP 0x82 /* Page program */
-+#define SPINOR_OP_XRDSR 0xd7 /* Read status register */
-+
-+#define XSR_PAGESIZE BIT(0) /* Page size in Po2 or Linear */
-+#define XSR_RDY BIT(7) /* Ready */
-+
-+
- /* Used for Macronix and Winbond flashes. */
- #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
- #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
-@@ -119,6 +128,9 @@ enum spi_nor_ops {
- enum spi_nor_option_flags {
- SNOR_F_USE_FSR = BIT(0),
- SNOR_F_HAS_SR_TB = BIT(1),
-+ SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
-+ SNOR_F_S3AN_ADDR_DEFAULT = BIT(3),
-+ SNOR_F_READY_XSR_RDY = BIT(4),
- };
-
- /**
+++ /dev/null
-From 1e99d0d51ec97bf48edd277658004ce030543d98 Mon Sep 17 00:00:00 2001
-From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Date: Tue, 6 Dec 2016 17:01:41 +0100
-Subject: [PATCH] mtd: spi-nor: improve macronix_quad_enable()
-
-The patch checks whether the Quad Enable bit is already set in the Status
-Register. If so, the function exits immediately with a successful return
-code.
-
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Reviewed-by: Jagan Teki <jagan@openedev.com>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1305,6 +1305,9 @@ static int macronix_quad_enable(struct s
- val = read_sr(nor);
- if (val < 0)
- return val;
-+ if (val & SR_QUAD_EN_MX)
-+ return 0;
-+
- write_enable(nor);
-
- write_sr(nor, val | SR_QUAD_EN_MX);
+++ /dev/null
-From dc176595bf184e89bf28fdf91cbc1d050dfe63b3 Mon Sep 17 00:00:00 2001
-From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Date: Tue, 6 Dec 2016 18:14:24 +0100
-Subject: [PATCH] mtd: spi-nor: remove WARN_ONCE() message in spi_nor_write()
-
-This patch removes the WARN_ONCE() test in spi_nor_write().
-This macro triggers the display of a warning message almost every time we
-use a UBI file-system because a write operation is performed at offset 64,
-which is in the middle of the SPI NOR memory page. This is a valid
-operation for ubifs.
-
-Hence this warning is pretty annoying and useless so we just remove it.
-
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Suggested-by: Richard Weinberger <richard@nod.at>
-Suggested-by: Andras Szemzo <szemzo.andras@gmail.com>
-Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 3 ---
- 1 file changed, 3 deletions(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1263,9 +1263,6 @@ static int spi_nor_write(struct mtd_info
-
- page_offset = do_div(aux, nor->page_size);
- }
-- WARN_ONCE(page_offset,
-- "Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
-- page_offset);
- /* the size of data remaining on the first page */
- page_remain = min_t(size_t,
- nor->page_size - page_offset, len - i);
+++ /dev/null
-From 05aba5763dcf35eddc58aaf99c9f16d19730e0a8 Mon Sep 17 00:00:00 2001
-From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Date: Thu, 27 Oct 2016 11:55:39 +0200
-Subject: [PATCH] mtd: spi-nor: rename SPINOR_OP_* macros of the 4-byte address
- op codes
-
-This patch renames the SPINOR_OP_* macros of the 4-byte address
-instruction set so the new names all share a common pattern: the 4-byte
-address name is built from the 3-byte address name appending the "_4B"
-suffix.
-
-The patch also introduces new op codes to support other SPI protocols such
-as SPI 1-4-4 and SPI 1-2-2.
-
-This is a transitional patch and will help a later patch of spi-nor.c
-to automate the translation from the 3-byte address op codes into their
-4-byte address version.
-
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Acked-by: Mark Brown <broonie@kernel.org>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
----
- drivers/mtd/devices/serial_flash_cmds.h | 7 -------
- drivers/mtd/devices/st_spi_fsm.c | 28 ++++++++++++++--------------
- drivers/mtd/spi-nor/spi-nor.c | 8 ++++----
- drivers/spi/spi-bcm-qspi.c | 6 +++---
- include/linux/mtd/spi-nor.h | 22 ++++++++++++++++------
- 5 files changed, 37 insertions(+), 34 deletions(-)
-
---- a/drivers/mtd/devices/serial_flash_cmds.h
-+++ b/drivers/mtd/devices/serial_flash_cmds.h
-@@ -18,19 +18,12 @@
- #define SPINOR_OP_RDVCR 0x85
-
- /* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */
--#define SPINOR_OP_READ_1_2_2 0xbb /* DUAL I/O READ */
--#define SPINOR_OP_READ_1_4_4 0xeb /* QUAD I/O READ */
--
- #define SPINOR_OP_WRITE 0x02 /* PAGE PROGRAM */
- #define SPINOR_OP_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
- #define SPINOR_OP_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
- #define SPINOR_OP_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
- #define SPINOR_OP_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */
-
--/* READ commands with 32-bit addressing */
--#define SPINOR_OP_READ4_1_2_2 0xbc
--#define SPINOR_OP_READ4_1_4_4 0xec
--
- /* Configuration flags */
- #define FLASH_FLAG_SINGLE 0x000000ff
- #define FLASH_FLAG_READ_WRITE 0x00000001
---- a/drivers/mtd/devices/st_spi_fsm.c
-+++ b/drivers/mtd/devices/st_spi_fsm.c
-@@ -507,13 +507,13 @@ static struct seq_rw_config n25q_read3_c
- * - 'FAST' variants configured for 8 dummy cycles (see note above.)
- */
- static struct seq_rw_config n25q_read4_configs[] = {
-- {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ4_1_4_4, 0, 4, 4, 0x00, 0, 8},
-- {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8},
-- {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ4_1_2_2, 0, 2, 2, 0x00, 0, 8},
-- {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8},
-- {FLASH_FLAG_READ_FAST, SPINOR_OP_READ4_FAST, 0, 1, 1, 0x00, 0, 8},
-- {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ4, 0, 1, 1, 0x00, 0, 0},
-- {0x00, 0, 0, 0, 0, 0x00, 0, 0},
-+ {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B, 0, 4, 4, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B, 0, 1, 4, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B, 0, 2, 2, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B, 0, 1, 2, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_FAST, SPINOR_OP_READ_FAST_4B, 0, 1, 1, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ_4B, 0, 1, 1, 0x00, 0, 0},
-+ {0x00, 0, 0, 0, 0, 0x00, 0, 0},
- };
-
- /*
-@@ -553,13 +553,13 @@ static int stfsm_mx25_en_32bit_addr_seq(
- * entering a state that is incompatible with the SPIBoot Controller.
- */
- static struct seq_rw_config stfsm_s25fl_read4_configs[] = {
-- {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ4_1_4_4, 0, 4, 4, 0x00, 2, 4},
-- {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8},
-- {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ4_1_2_2, 0, 2, 2, 0x00, 4, 0},
-- {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8},
-- {FLASH_FLAG_READ_FAST, SPINOR_OP_READ4_FAST, 0, 1, 1, 0x00, 0, 8},
-- {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ4, 0, 1, 1, 0x00, 0, 0},
-- {0x00, 0, 0, 0, 0, 0x00, 0, 0},
-+ {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B, 0, 4, 4, 0x00, 2, 4},
-+ {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B, 0, 1, 4, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B, 0, 2, 2, 0x00, 4, 0},
-+ {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B, 0, 1, 2, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_FAST, SPINOR_OP_READ_FAST_4B, 0, 1, 1, 0x00, 0, 8},
-+ {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ_4B, 0, 1, 1, 0x00, 0, 0},
-+ {0x00, 0, 0, 0, 0, 0x00, 0, 0},
- };
-
- static struct seq_rw_config stfsm_s25fl_write4_configs[] = {
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1632,16 +1632,16 @@ int spi_nor_scan(struct spi_nor *nor, co
- /* Dedicated 4-byte command set */
- switch (nor->flash_read) {
- case SPI_NOR_QUAD:
-- nor->read_opcode = SPINOR_OP_READ4_1_1_4;
-+ nor->read_opcode = SPINOR_OP_READ_1_1_4_4B;
- break;
- case SPI_NOR_DUAL:
-- nor->read_opcode = SPINOR_OP_READ4_1_1_2;
-+ nor->read_opcode = SPINOR_OP_READ_1_1_2_4B;
- break;
- case SPI_NOR_FAST:
-- nor->read_opcode = SPINOR_OP_READ4_FAST;
-+ nor->read_opcode = SPINOR_OP_READ_FAST_4B;
- break;
- case SPI_NOR_NORMAL:
-- nor->read_opcode = SPINOR_OP_READ4;
-+ nor->read_opcode = SPINOR_OP_READ_4B;
- break;
- }
- nor->program_opcode = SPINOR_OP_PP_4B;
---- a/drivers/spi/spi-bcm-qspi.c
-+++ b/drivers/spi/spi-bcm-qspi.c
-@@ -371,7 +371,7 @@ static int bcm_qspi_bspi_set_flex_mode(s
- /* default mode, does not need flex_cmd */
- flex_mode = 0;
- else
-- command = SPINOR_OP_READ4_FAST;
-+ command = SPINOR_OP_READ_FAST_4B;
- break;
- case SPI_NBITS_DUAL:
- bpc = 0x00000001;
-@@ -384,7 +384,7 @@ static int bcm_qspi_bspi_set_flex_mode(s
- } else {
- command = SPINOR_OP_READ_1_1_2;
- if (spans_4byte)
-- command = SPINOR_OP_READ4_1_1_2;
-+ command = SPINOR_OP_READ_1_1_2_4B;
- }
- break;
- case SPI_NBITS_QUAD:
-@@ -399,7 +399,7 @@ static int bcm_qspi_bspi_set_flex_mode(s
- } else {
- command = SPINOR_OP_READ_1_1_4;
- if (spans_4byte)
-- command = SPINOR_OP_READ4_1_1_4;
-+ command = SPINOR_OP_READ_1_1_4_4B;
- }
- break;
- default:
---- a/include/linux/mtd/spi-nor.h
-+++ b/include/linux/mtd/spi-nor.h
-@@ -43,9 +43,13 @@
- #define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
- #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
- #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
--#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
--#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
-+#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */
-+#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */
-+#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */
-+#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */
- #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
-+#define SPINOR_OP_PP_1_1_4 0x32 /* Quad page program */
-+#define SPINOR_OP_PP_1_4_4 0x38 /* Quad page program */
- #define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
- #define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
- #define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */
-@@ -56,11 +60,17 @@
- #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
-
- /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
--#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
--#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
--#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
--#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
-+#define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */
-+#define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */
-+#define SPINOR_OP_READ_1_1_2_4B 0x3c /* Read data bytes (Dual Output SPI) */
-+#define SPINOR_OP_READ_1_2_2_4B 0xbc /* Read data bytes (Dual I/O SPI) */
-+#define SPINOR_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */
-+#define SPINOR_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */
- #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
-+#define SPINOR_OP_PP_1_1_4_4B 0x34 /* Quad page program */
-+#define SPINOR_OP_PP_1_4_4_4B 0x3e /* Quad page program */
-+#define SPINOR_OP_BE_4K_4B 0x21 /* Erase 4KiB block */
-+#define SPINOR_OP_BE_32K_4B 0x5c /* Erase 32KiB block */
- #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
-
- /* Used for SST flashes only. */
+++ /dev/null
-From 3274ba26f27becfc4193ec6e229288140651f240 Mon Sep 17 00:00:00 2001
-From: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Date: Thu, 27 Oct 2016 12:03:57 +0200
-Subject: [PATCH] mtd: spi-nor: add a stateless method to support memory size
- above 128Mib
-
-This patch provides an alternative mean to support memory above 16MiB
-(128Mib) by replacing 3byte address op codes by their associated 4byte
-address versions.
-
-Using the dedicated 4byte address op codes doesn't change the internal
-state of the SPI NOR memory as opposed to using other means such as
-updating a Base Address Register (BAR) and sending command to enter/leave
-the 4byte mode.
-
-Hence when a CPU reset occurs, early bootloaders don't need to be aware
-of BAR value or 4byte mode being enabled: they can still access the first
-16MiB of the SPI NOR memory using the regular 3byte address op codes.
-
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
-Tested-by: Vignesh R <vigneshr@ti.com>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 101 +++++++++++++++++++++++++++++++++---------
- 1 file changed, 80 insertions(+), 21 deletions(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -81,6 +81,10 @@ struct flash_info {
- * because it has the same value as
- * ATMEL flashes)
- */
-+#define SPI_NOR_4B_OPCODES BIT(11) /*
-+ * Use dedicated 4byte address op codes
-+ * to support memory size above 128Mib.
-+ */
- };
-
- #define JEDEC_MFR(info) ((info)->id[0])
-@@ -194,6 +198,78 @@ static inline struct spi_nor *mtd_to_spi
- return mtd->priv;
- }
-
-+
-+static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
-+{
-+ size_t i;
-+
-+ for (i = 0; i < size; i++)
-+ if (table[i][0] == opcode)
-+ return table[i][1];
-+
-+ /* No conversion found, keep input op code. */
-+ return opcode;
-+}
-+
-+static inline u8 spi_nor_convert_3to4_read(u8 opcode)
-+{
-+ static const u8 spi_nor_3to4_read[][2] = {
-+ { SPINOR_OP_READ, SPINOR_OP_READ_4B },
-+ { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B },
-+ { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B },
-+ { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B },
-+ { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B },
-+ { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B },
-+ };
-+
-+ return spi_nor_convert_opcode(opcode, spi_nor_3to4_read,
-+ ARRAY_SIZE(spi_nor_3to4_read));
-+}
-+
-+static inline u8 spi_nor_convert_3to4_program(u8 opcode)
-+{
-+ static const u8 spi_nor_3to4_program[][2] = {
-+ { SPINOR_OP_PP, SPINOR_OP_PP_4B },
-+ { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B },
-+ { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B },
-+ };
-+
-+ return spi_nor_convert_opcode(opcode, spi_nor_3to4_program,
-+ ARRAY_SIZE(spi_nor_3to4_program));
-+}
-+
-+static inline u8 spi_nor_convert_3to4_erase(u8 opcode)
-+{
-+ static const u8 spi_nor_3to4_erase[][2] = {
-+ { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B },
-+ { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B },
-+ { SPINOR_OP_SE, SPINOR_OP_SE_4B },
-+ };
-+
-+ return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase,
-+ ARRAY_SIZE(spi_nor_3to4_erase));
-+}
-+
-+static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
-+ const struct flash_info *info)
-+{
-+ /* Do some manufacturer fixups first */
-+ switch (JEDEC_MFR(info)) {
-+ case SNOR_MFR_SPANSION:
-+ /* No small sector erase for 4-byte command set */
-+ nor->erase_opcode = SPINOR_OP_SE;
-+ nor->mtd.erasesize = info->sector_size;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
-+ nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode);
-+ nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
-+}
-+
- /* Enable/disable 4-byte addressing mode. */
- static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
- int enable)
-@@ -1628,27 +1704,10 @@ int spi_nor_scan(struct spi_nor *nor, co
- else if (mtd->size > 0x1000000) {
- /* enable 4-byte addressing if the device exceeds 16MiB */
- nor->addr_width = 4;
-- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
-- /* Dedicated 4-byte command set */
-- switch (nor->flash_read) {
-- case SPI_NOR_QUAD:
-- nor->read_opcode = SPINOR_OP_READ_1_1_4_4B;
-- break;
-- case SPI_NOR_DUAL:
-- nor->read_opcode = SPINOR_OP_READ_1_1_2_4B;
-- break;
-- case SPI_NOR_FAST:
-- nor->read_opcode = SPINOR_OP_READ_FAST_4B;
-- break;
-- case SPI_NOR_NORMAL:
-- nor->read_opcode = SPINOR_OP_READ_4B;
-- break;
-- }
-- nor->program_opcode = SPINOR_OP_PP_4B;
-- /* No small sector erase for 4-byte command set */
-- nor->erase_opcode = SPINOR_OP_SE_4B;
-- mtd->erasesize = info->sector_size;
-- } else
-+ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
-+ info->flags & SPI_NOR_4B_OPCODES)
-+ spi_nor_set_4byte_opcodes(nor, info);
-+ else
- set_4byte(nor, info, 1);
- } else {
- nor->addr_width = 3;
+++ /dev/null
-From 252c36bb9c7b98b356f033d16ea83d20fb8b4d3e Mon Sep 17 00:00:00 2001
-From: Victor Shyba <victor1984@riseup.net>
-Date: Mon, 2 Jan 2017 22:34:30 -0300
-Subject: [PATCH] mtd: spi-nor: Add lock/unlock support for f25l32pa
-
-This chip has write protection enabled on power-up,
-so this flag is necessary to support write operations.
-
-Signed-off-by: Victor Shyba <victor1984@riseup.net>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -956,7 +956,7 @@ static const struct flash_info spi_nor_i
- { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) },
-
- /* ESMT */
-- { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) },
-+ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
-
- /* Everspin */
- { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+++ /dev/null
-From 5f0e0758efddef5b06994a76d8c7f0b8a4c1daae Mon Sep 17 00:00:00 2001
-From: Ricardo Ribalda <ricardo.ribalda@gmail.com>
-Date: Wed, 18 Jan 2017 17:40:16 +0100
-Subject: [PATCH] mtd: spi-nor: Fix S3AN addressing calculation
-
-The page calculation under spi_nor_s3an_addr_convert() was wrong. On
-Default Address Mode we need to perform a divide by page_size.
-
-Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 9 ++++++---
- 1 file changed, 6 insertions(+), 3 deletions(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -431,11 +431,14 @@ static void spi_nor_unlock_and_unprep(st
- */
- static loff_t spi_nor_s3an_addr_convert(struct spi_nor *nor, unsigned int addr)
- {
-- unsigned int offset = addr;
-+ unsigned int offset;
-+ unsigned int page;
-
-- offset %= nor->page_size;
-+ offset = addr % nor->page_size;
-+ page = addr / nor->page_size;
-+ page <<= (nor->page_size > 512) ? 10 : 9;
-
-- return ((addr - offset) << 1) | offset;
-+ return page | offset;
- }
-
- /*
+++ /dev/null
-From 4c5747a390acc9d1da3b332507c8bae7a8ddfc48 Mon Sep 17 00:00:00 2001
-From: Kamal Dasu <kdasu.kdev@gmail.com>
-Date: Fri, 20 Jan 2017 14:25:51 -0500
-Subject: [PATCH] mtd: spi-nor: Add support for gd25q16
-
-Add GigaDevice GD25Q16 (16M-bit) to supported list.
-
-Signed-off-by: Kamal Dasu <kdasu.kdev@gmail.com>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 5 +++++
- 1 file changed, 5 insertions(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -971,6 +971,11 @@ static const struct flash_info spi_nor_i
-
- /* GigaDevice */
- {
-+ "gd25q16", INFO(0xc84015, 0, 64 * 1024, 32,
-+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-+ SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-+ },
-+ {
- "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64,
- SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
- SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+++ /dev/null
-From a4077ce5871304f8a78f80b74b18b6052a410f1a Mon Sep 17 00:00:00 2001
-From: "Andrey Jr. Melnikov" <temnota.am@gmail.com>
-Date: Thu, 8 Dec 2016 19:57:08 +0300
-Subject: [PATCH] mtd: nand: Add Winbond manufacturer id
-
-Add WINBOND manufacturer id.
-
-Signed-off-by: Andrey Jr. Melnikov <temnota.am@gmail.com>
-Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
----
- drivers/mtd/nand/nand_ids.c | 1 +
- include/linux/mtd/nand.h | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/mtd/nand/nand_ids.c
-+++ b/drivers/mtd/nand/nand_ids.c
-@@ -182,6 +182,7 @@ struct nand_manufacturers nand_manuf_ids
- {NAND_MFR_SANDISK, "SanDisk"},
- {NAND_MFR_INTEL, "Intel"},
- {NAND_MFR_ATO, "ATO"},
-+ {NAND_MFR_WINBOND, "Winbond"},
- {0x0, "Unknown"}
- };
-
---- a/include/linux/mtd/nand.h
-+++ b/include/linux/mtd/nand.h
-@@ -928,6 +928,7 @@ static inline void nand_set_controller_d
- #define NAND_MFR_SANDISK 0x45
- #define NAND_MFR_INTEL 0x89
- #define NAND_MFR_ATO 0x9b
-+#define NAND_MFR_WINBOND 0xef
-
- /* The maximum expected count of bytes in the NAND ID sequence */
- #define NAND_MAX_ID_LEN 8
+++ /dev/null
-From 6080ef6e7c0a0592cbcca11200d879faf65e27d4 Mon Sep 17 00:00:00 2001
-From: Jeff Westfahl <jeff.westfahl@ni.com>
-Date: Tue, 10 Jan 2017 13:30:17 -0600
-Subject: [PATCH] mtd: introduce function max_bad_blocks
-
-If implemented, 'max_bad_blocks' returns the maximum number of bad
-blocks to reserve for a MTD. An implementation for NAND is coming soon.
-
-Signed-off-by: Jeff Westfahl <jeff.westfahl@ni.com>
-Signed-off-by: Zach Brown <zach.brown@ni.com>
-Acked-by: Boris Brezillon <boris.brezillon@free-electron.com>
-Acked-by: Brian Norris <computersforpeace@gmail.com>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 10 ++++++++++
- include/linux/mtd/mtd.h | 13 +++++++++++++
- 2 files changed, 23 insertions(+)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -349,6 +349,14 @@ static const struct mtd_ooblayout_ops pa
- .free = part_ooblayout_free,
- };
-
-+static int part_max_bad_blocks(struct mtd_info *mtd, loff_t ofs, size_t len)
-+{
-+ struct mtd_part *part = mtd_to_part(mtd);
-+
-+ return part->master->_max_bad_blocks(part->master,
-+ ofs + part->offset, len);
-+}
-+
- static inline void free_partition(struct mtd_part *p)
- {
- kfree(p->mtd.name);
-@@ -475,6 +483,8 @@ static struct mtd_part *allocate_partiti
- slave->mtd._block_isbad = part_block_isbad;
- if (master->_block_markbad)
- slave->mtd._block_markbad = part_block_markbad;
-+ if (master->_max_bad_blocks)
-+ slave->mtd._max_bad_blocks = part_max_bad_blocks;
-
- if (master->_get_device)
- slave->mtd._get_device = part_get_device;
---- a/include/linux/mtd/mtd.h
-+++ b/include/linux/mtd/mtd.h
-@@ -322,6 +322,7 @@ struct mtd_info {
- int (*_block_isreserved) (struct mtd_info *mtd, loff_t ofs);
- int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
- int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
-+ int (*_max_bad_blocks) (struct mtd_info *mtd, loff_t ofs, size_t len);
- int (*_suspend) (struct mtd_info *mtd);
- void (*_resume) (struct mtd_info *mtd);
- void (*_reboot) (struct mtd_info *mtd);
-@@ -397,6 +398,18 @@ static inline int mtd_oobavail(struct mt
- return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
- }
-
-+static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
-+ loff_t ofs, size_t len)
-+{
-+ if (!mtd->_max_bad_blocks)
-+ return -ENOTSUPP;
-+
-+ if (mtd->size < (len + ofs) || ofs < 0)
-+ return -EINVAL;
-+
-+ return mtd->_max_bad_blocks(mtd, ofs, len);
-+}
-+
- int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
- struct mtd_pairing_info *info);
- int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
+++ /dev/null
-From 42e9401bd1467d22c4dc4d2c637347b874e6a80b Mon Sep 17 00:00:00 2001
-From: Sascha Hauer <s.hauer@pengutronix.de>
-Date: Thu, 9 Feb 2017 11:50:24 +0100
-Subject: [PATCH] mtd: Add partition device node to mtd partition devices
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The user visible change here is that mtd partitions get an of_node link
-in sysfs.
-
-Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
-Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 1 +
- drivers/mtd/ofpart.c | 1 +
- include/linux/mtd/partitions.h | 1 +
- 3 files changed, 3 insertions(+)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -432,6 +432,7 @@ static struct mtd_part *allocate_partiti
- slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ?
- &master->dev :
- master->dev.parent;
-+ slave->mtd.dev.of_node = part->of_node;
-
- slave->mtd._read = part_read;
- slave->mtd._write = part_write;
---- a/drivers/mtd/ofpart.c
-+++ b/drivers/mtd/ofpart.c
-@@ -108,6 +108,7 @@ static int parse_ofpart_partitions(struc
-
- parts[i].offset = of_read_number(reg, a_cells);
- parts[i].size = of_read_number(reg + a_cells, s_cells);
-+ parts[i].of_node = pp;
-
- partname = of_get_property(pp, "label", &len);
- if (!partname)
---- a/include/linux/mtd/partitions.h
-+++ b/include/linux/mtd/partitions.h
-@@ -41,6 +41,7 @@ struct mtd_partition {
- uint64_t size; /* partition size */
- uint64_t offset; /* offset within the master MTD space */
- uint32_t mask_flags; /* master MTD flags to mask out for this partition */
-+ struct device_node *of_node;
- };
-
- #define MTDPART_OFS_RETAIN (-3)
+++ /dev/null
-From b0fcb4b413028376894feaaaf62bcb09ab1b52f2 Mon Sep 17 00:00:00 2001
-From: Mathias Kresin <dev@kresin.me>
-Date: Thu, 13 Apr 2017 09:23:54 +0200
-Subject: [PATCH] mtd: spi-nor: enable stateless 4b op codes for mx25u25635f
-
-All required stateless 4-byte op codes are supported by this flash
-chip. The stateless 4-byte support can't be autodetected due to a
-missing 4-byte Address Instruction Table in SFDP.
-
-Fixes hangs on reboot for SoCs expecting the flash chip in 3byte mode.
-
-Signed-off-by: Mathias Kresin <dev@kresin.me>
-Acked-by: Marek Vasut <marek.vasut@gmail.com>
-Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1017,7 +1017,7 @@ static const struct flash_info spi_nor_i
- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
- { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
-- { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K) },
-+ { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
- { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
- { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
- { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
+++ /dev/null
-From 1eeef2d7483a7e3f8d2dd2a5b9939b3b814dc549 Mon Sep 17 00:00:00 2001
-From: Chris Packham <chris.packham@alliedtelesis.co.nz>
-Date: Fri, 9 Jun 2017 15:58:31 +1200
-Subject: [PATCH] mtd: handle partitioning on devices with 0 erasesize
-
-erasesize is meaningful for flash devices but for SRAM there is no
-concept of an erase block so erasesize is set to 0. When partitioning
-these devices instead of ensuring partitions fall on erasesize
-boundaries we ensure they fall on writesize boundaries.
-
-Helped-by: Boris Brezillon <boris.brezillon@free-electrons.com>
-Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
-Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 26 +++++++++++++++++---------
- 1 file changed, 17 insertions(+), 9 deletions(-)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -393,8 +393,12 @@ static struct mtd_part *allocate_partiti
- const struct mtd_partition *part, int partno,
- uint64_t cur_offset)
- {
-+ int wr_alignment = (master->flags & MTD_NO_ERASE) ? master->writesize:
-+ master->erasesize;
- struct mtd_part *slave;
-+ u32 remainder;
- char *name;
-+ u64 tmp;
-
- /* allocate the partition structure */
- slave = kzalloc(sizeof(*slave), GFP_KERNEL);
-@@ -499,10 +503,11 @@ static struct mtd_part *allocate_partiti
- if (slave->offset == MTDPART_OFS_APPEND)
- slave->offset = cur_offset;
- if (slave->offset == MTDPART_OFS_NXTBLK) {
-+ tmp = cur_offset;
- slave->offset = cur_offset;
-- if (mtd_mod_by_eb(cur_offset, master) != 0) {
-- /* Round up to next erasesize */
-- slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize;
-+ remainder = do_div(tmp, wr_alignment);
-+ if (remainder) {
-+ slave->offset += wr_alignment - remainder;
- printk(KERN_NOTICE "Moving partition %d: "
- "0x%012llx -> 0x%012llx\n", partno,
- (unsigned long long)cur_offset, (unsigned long long)slave->offset);
-@@ -567,19 +572,22 @@ static struct mtd_part *allocate_partiti
- slave->mtd.erasesize = master->erasesize;
- }
-
-- if ((slave->mtd.flags & MTD_WRITEABLE) &&
-- mtd_mod_by_eb(slave->offset, &slave->mtd)) {
-+ tmp = slave->offset;
-+ remainder = do_div(tmp, wr_alignment);
-+ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
- /* Doesn't start on a boundary of major erase size */
- /* FIXME: Let it be writable if it is on a boundary of
- * _minor_ erase size though */
- slave->mtd.flags &= ~MTD_WRITEABLE;
-- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
-+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
- part->name);
- }
-- if ((slave->mtd.flags & MTD_WRITEABLE) &&
-- mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
-+
-+ tmp = slave->mtd.size;
-+ remainder = do_div(tmp, wr_alignment);
-+ if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
- slave->mtd.flags &= ~MTD_WRITEABLE;
-- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
-+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
- part->name);
- }
-
+++ /dev/null
-From 01f9c7240a900d5676a8496496f2974dd36996b1 Mon Sep 17 00:00:00 2001
-From: Brian Norris <computersforpeace@gmail.com>
-Date: Tue, 23 May 2017 07:30:20 +0200
-Subject: [PATCH] mtd: partitions: factor out code calling parser
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This code is going to be reused for parsers matched using OF so let's
-factor it out to make this easier.
-
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 33 ++++++++++++++++++++++++---------
- 1 file changed, 24 insertions(+), 9 deletions(-)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -807,6 +807,27 @@ static const char * const default_mtd_pa
- NULL
- };
-
-+static int mtd_part_do_parse(struct mtd_part_parser *parser,
-+ struct mtd_info *master,
-+ struct mtd_partitions *pparts,
-+ struct mtd_part_parser_data *data)
-+{
-+ int ret;
-+
-+ ret = (*parser->parse_fn)(master, &pparts->parts, data);
-+ pr_debug("%s: parser %s: %i\n", master->name, parser->name, ret);
-+ if (ret <= 0)
-+ return ret;
-+
-+ pr_notice("%d %s partitions found on MTD device %s\n", ret,
-+ parser->name, master->name);
-+
-+ pparts->nr_parts = ret;
-+ pparts->parser = parser;
-+
-+ return ret;
-+}
-+
- /**
- * parse_mtd_partitions - parse MTD partitions
- * @master: the master partition (describes whole MTD device)
-@@ -847,16 +868,10 @@ int parse_mtd_partitions(struct mtd_info
- parser ? parser->name : NULL);
- if (!parser)
- continue;
-- ret = (*parser->parse_fn)(master, &pparts->parts, data);
-- pr_debug("%s: parser %s: %i\n",
-- master->name, parser->name, ret);
-- if (ret > 0) {
-- printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
-- ret, parser->name, master->name);
-- pparts->nr_parts = ret;
-- pparts->parser = parser;
-+ ret = mtd_part_do_parse(parser, master, pparts, data);
-+ /* Found partitions! */
-+ if (ret > 0)
- return 0;
-- }
- mtd_part_parser_put(parser);
- /*
- * Stash the first error we see; only report it if no parser
+++ /dev/null
-From 08263a9ae664b24fa777d20b365601534842b236 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 21 Jun 2017 08:26:42 +0200
-Subject: [PATCH] mtd: partitions: add helper for deleting partition
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-There are two similar functions handling deletion. One handles single
-partition and another the whole MTD flash device. They share (duplicate)
-some code so it makes sense to add a small helper for that part.
-
-Function del_mtd_partitions has been moved a bit to keep all deleting
-stuff together.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 75 +++++++++++++++++++++++++++++----------------------
- 1 file changed, 43 insertions(+), 32 deletions(-)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -363,32 +363,6 @@ static inline void free_partition(struct
- kfree(p);
- }
-
--/*
-- * This function unregisters and destroy all slave MTD objects which are
-- * attached to the given master MTD object.
-- */
--
--int del_mtd_partitions(struct mtd_info *master)
--{
-- struct mtd_part *slave, *next;
-- int ret, err = 0;
--
-- mutex_lock(&mtd_partitions_mutex);
-- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
-- if (slave->master == master) {
-- ret = del_mtd_device(&slave->mtd);
-- if (ret < 0) {
-- err = ret;
-- continue;
-- }
-- list_del(&slave->list);
-- free_partition(slave);
-- }
-- mutex_unlock(&mtd_partitions_mutex);
--
-- return err;
--}
--
- static struct mtd_part *allocate_partition(struct mtd_info *master,
- const struct mtd_partition *part, int partno,
- uint64_t cur_offset)
-@@ -675,6 +649,48 @@ int mtd_add_partition(struct mtd_info *m
- }
- EXPORT_SYMBOL_GPL(mtd_add_partition);
-
-+/**
-+ * __mtd_del_partition - delete MTD partition
-+ *
-+ * @priv: internal MTD struct for partition to be deleted
-+ *
-+ * This function must be called with the partitions mutex locked.
-+ */
-+static int __mtd_del_partition(struct mtd_part *priv)
-+{
-+ int err;
-+
-+ err = del_mtd_device(&priv->mtd);
-+ if (err)
-+ return err;
-+
-+ list_del(&priv->list);
-+ free_partition(priv);
-+
-+ return 0;
-+}
-+
-+/*
-+ * This function unregisters and destroy all slave MTD objects which are
-+ * attached to the given master MTD object.
-+ */
-+int del_mtd_partitions(struct mtd_info *master)
-+{
-+ struct mtd_part *slave, *next;
-+ int ret, err = 0;
-+
-+ mutex_lock(&mtd_partitions_mutex);
-+ list_for_each_entry_safe(slave, next, &mtd_partitions, list)
-+ if (slave->master == master) {
-+ ret = __mtd_del_partition(slave);
-+ if (ret < 0)
-+ err = ret;
-+ }
-+ mutex_unlock(&mtd_partitions_mutex);
-+
-+ return err;
-+}
-+
- int mtd_del_partition(struct mtd_info *master, int partno)
- {
- struct mtd_part *slave, *next;
-@@ -686,12 +702,7 @@ int mtd_del_partition(struct mtd_info *m
- (slave->mtd.index == partno)) {
- sysfs_remove_files(&slave->mtd.dev.kobj,
- mtd_partition_attrs);
-- ret = del_mtd_device(&slave->mtd);
-- if (ret < 0)
-- break;
--
-- list_del(&slave->list);
-- free_partition(slave);
-+ ret = __mtd_del_partition(slave);
- break;
- }
- mutex_unlock(&mtd_partitions_mutex);
+++ /dev/null
-From c5ceaba74083daf619bdb34d4871e297a177eebf Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 21 Jun 2017 08:26:43 +0200
-Subject: [PATCH] mtd: partitions: remove sysfs files when deleting all
- master's partitions
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-When support for sysfs "offset" file was added it missed to update the
-del_mtd_partitions function. It deletes partitions just like
-mtd_del_partition does so both should also take care of removing sysfs
-files.
-
-This change moves sysfs_remove_files call to the shared function to fix
-this issue.
-
-Fixes: a62c24d755291 ("mtd: part: Add sysfs variable for offset of partition")
-Cc: Dan Ehrenberg <dehrenberg@chromium.org>
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -660,6 +660,8 @@ static int __mtd_del_partition(struct mt
- {
- int err;
-
-+ sysfs_remove_files(&priv->mtd.dev.kobj, mtd_partition_attrs);
-+
- err = del_mtd_device(&priv->mtd);
- if (err)
- return err;
-@@ -700,8 +702,6 @@ int mtd_del_partition(struct mtd_info *m
- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
- if ((slave->master == master) &&
- (slave->mtd.index == partno)) {
-- sysfs_remove_files(&slave->mtd.dev.kobj,
-- mtd_partition_attrs);
- ret = __mtd_del_partition(slave);
- break;
- }
+++ /dev/null
-From 0a9d72b69da6d8dae1abd7990c6c4c749846ef3e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 21 Jun 2017 08:26:44 +0200
-Subject: [PATCH] mtd: partitions: rename "master" to the "parent" where
- appropriate
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This prepares mtd subsystem for the new feature: subpartitions. In some
-cases flash device partition can be a container with extra subpartitions
-(volumes).
-
-So far there was a flat structure implemented. One master (flash device)
-could be partitioned into few partitions. Every partition got its master
-and it was enough to get things running.
-
-To support subpartitions we need to store pointer to the parent for each
-partition. This is required to implement more natural tree structure and
-handle all recursion and offsets calculation.
-
-To make code consistent this patch renamed "master" to the "parent" in
-places where we can be dealing with subpartitions.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 204 ++++++++++++++++++++++++++------------------------
- 1 file changed, 105 insertions(+), 99 deletions(-)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -37,10 +37,16 @@
- static LIST_HEAD(mtd_partitions);
- static DEFINE_MUTEX(mtd_partitions_mutex);
-
--/* Our partition node structure */
-+/**
-+ * struct mtd_part - our partition node structure
-+ *
-+ * @mtd: struct holding partition details
-+ * @parent: parent mtd - flash device or another partition
-+ * @offset: partition offset relative to the *flash device*
-+ */
- struct mtd_part {
- struct mtd_info mtd;
-- struct mtd_info *master;
-+ struct mtd_info *parent;
- uint64_t offset;
- struct list_head list;
- };
-@@ -67,15 +73,15 @@ static int part_read(struct mtd_info *mt
- struct mtd_ecc_stats stats;
- int res;
-
-- stats = part->master->ecc_stats;
-- res = part->master->_read(part->master, from + part->offset, len,
-+ stats = part->parent->ecc_stats;
-+ res = part->parent->_read(part->parent, from + part->offset, len,
- retlen, buf);
- if (unlikely(mtd_is_eccerr(res)))
- mtd->ecc_stats.failed +=
-- part->master->ecc_stats.failed - stats.failed;
-+ part->parent->ecc_stats.failed - stats.failed;
- else
- mtd->ecc_stats.corrected +=
-- part->master->ecc_stats.corrected - stats.corrected;
-+ part->parent->ecc_stats.corrected - stats.corrected;
- return res;
- }
-
-@@ -84,7 +90,7 @@ static int part_point(struct mtd_info *m
- {
- struct mtd_part *part = mtd_to_part(mtd);
-
-- return part->master->_point(part->master, from + part->offset, len,
-+ return part->parent->_point(part->parent, from + part->offset, len,
- retlen, virt, phys);
- }
-
-@@ -92,7 +98,7 @@ static int part_unpoint(struct mtd_info
- {
- struct mtd_part *part = mtd_to_part(mtd);
-
-- return part->master->_unpoint(part->master, from + part->offset, len);
-+ return part->parent->_unpoint(part->parent, from + part->offset, len);
- }
-
- static unsigned long part_get_unmapped_area(struct mtd_info *mtd,
-@@ -103,7 +109,7 @@ static unsigned long part_get_unmapped_a
- struct mtd_part *part = mtd_to_part(mtd);
-
- offset += part->offset;
-- return part->master->_get_unmapped_area(part->master, len, offset,
-+ return part->parent->_get_unmapped_area(part->parent, len, offset,
- flags);
- }
-
-@@ -132,7 +138,7 @@ static int part_read_oob(struct mtd_info
- return -EINVAL;
- }
-
-- res = part->master->_read_oob(part->master, from + part->offset, ops);
-+ res = part->parent->_read_oob(part->parent, from + part->offset, ops);
- if (unlikely(res)) {
- if (mtd_is_bitflip(res))
- mtd->ecc_stats.corrected++;
-@@ -146,7 +152,7 @@ static int part_read_user_prot_reg(struc
- size_t len, size_t *retlen, u_char *buf)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_read_user_prot_reg(part->master, from, len,
-+ return part->parent->_read_user_prot_reg(part->parent, from, len,
- retlen, buf);
- }
-
-@@ -154,7 +160,7 @@ static int part_get_user_prot_info(struc
- size_t *retlen, struct otp_info *buf)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_get_user_prot_info(part->master, len, retlen,
-+ return part->parent->_get_user_prot_info(part->parent, len, retlen,
- buf);
- }
-
-@@ -162,7 +168,7 @@ static int part_read_fact_prot_reg(struc
- size_t len, size_t *retlen, u_char *buf)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_read_fact_prot_reg(part->master, from, len,
-+ return part->parent->_read_fact_prot_reg(part->parent, from, len,
- retlen, buf);
- }
-
-@@ -170,7 +176,7 @@ static int part_get_fact_prot_info(struc
- size_t *retlen, struct otp_info *buf)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_get_fact_prot_info(part->master, len, retlen,
-+ return part->parent->_get_fact_prot_info(part->parent, len, retlen,
- buf);
- }
-
-@@ -178,7 +184,7 @@ static int part_write(struct mtd_info *m
- size_t *retlen, const u_char *buf)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_write(part->master, to + part->offset, len,
-+ return part->parent->_write(part->parent, to + part->offset, len,
- retlen, buf);
- }
-
-@@ -186,7 +192,7 @@ static int part_panic_write(struct mtd_i
- size_t *retlen, const u_char *buf)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_panic_write(part->master, to + part->offset, len,
-+ return part->parent->_panic_write(part->parent, to + part->offset, len,
- retlen, buf);
- }
-
-@@ -199,14 +205,14 @@ static int part_write_oob(struct mtd_inf
- return -EINVAL;
- if (ops->datbuf && to + ops->len > mtd->size)
- return -EINVAL;
-- return part->master->_write_oob(part->master, to + part->offset, ops);
-+ return part->parent->_write_oob(part->parent, to + part->offset, ops);
- }
-
- static int part_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
- size_t len, size_t *retlen, u_char *buf)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_write_user_prot_reg(part->master, from, len,
-+ return part->parent->_write_user_prot_reg(part->parent, from, len,
- retlen, buf);
- }
-
-@@ -214,14 +220,14 @@ static int part_lock_user_prot_reg(struc
- size_t len)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_lock_user_prot_reg(part->master, from, len);
-+ return part->parent->_lock_user_prot_reg(part->parent, from, len);
- }
-
- static int part_writev(struct mtd_info *mtd, const struct kvec *vecs,
- unsigned long count, loff_t to, size_t *retlen)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_writev(part->master, vecs, count,
-+ return part->parent->_writev(part->parent, vecs, count,
- to + part->offset, retlen);
- }
-
-@@ -231,7 +237,7 @@ static int part_erase(struct mtd_info *m
- int ret;
-
- instr->addr += part->offset;
-- ret = part->master->_erase(part->master, instr);
-+ ret = part->parent->_erase(part->parent, instr);
- if (ret) {
- if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
- instr->fail_addr -= part->offset;
-@@ -257,51 +263,51 @@ EXPORT_SYMBOL_GPL(mtd_erase_callback);
- static int part_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_lock(part->master, ofs + part->offset, len);
-+ return part->parent->_lock(part->parent, ofs + part->offset, len);
- }
-
- static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_unlock(part->master, ofs + part->offset, len);
-+ return part->parent->_unlock(part->parent, ofs + part->offset, len);
- }
-
- static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_is_locked(part->master, ofs + part->offset, len);
-+ return part->parent->_is_locked(part->parent, ofs + part->offset, len);
- }
-
- static void part_sync(struct mtd_info *mtd)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- part->master->_sync(part->master);
-+ part->parent->_sync(part->parent);
- }
-
- static int part_suspend(struct mtd_info *mtd)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_suspend(part->master);
-+ return part->parent->_suspend(part->parent);
- }
-
- static void part_resume(struct mtd_info *mtd)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- part->master->_resume(part->master);
-+ part->parent->_resume(part->parent);
- }
-
- static int part_block_isreserved(struct mtd_info *mtd, loff_t ofs)
- {
- struct mtd_part *part = mtd_to_part(mtd);
- ofs += part->offset;
-- return part->master->_block_isreserved(part->master, ofs);
-+ return part->parent->_block_isreserved(part->parent, ofs);
- }
-
- static int part_block_isbad(struct mtd_info *mtd, loff_t ofs)
- {
- struct mtd_part *part = mtd_to_part(mtd);
- ofs += part->offset;
-- return part->master->_block_isbad(part->master, ofs);
-+ return part->parent->_block_isbad(part->parent, ofs);
- }
-
- static int part_block_markbad(struct mtd_info *mtd, loff_t ofs)
-@@ -310,7 +316,7 @@ static int part_block_markbad(struct mtd
- int res;
-
- ofs += part->offset;
-- res = part->master->_block_markbad(part->master, ofs);
-+ res = part->parent->_block_markbad(part->parent, ofs);
- if (!res)
- mtd->ecc_stats.badblocks++;
- return res;
-@@ -319,13 +325,13 @@ static int part_block_markbad(struct mtd
- static int part_get_device(struct mtd_info *mtd)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- return part->master->_get_device(part->master);
-+ return part->parent->_get_device(part->parent);
- }
-
- static void part_put_device(struct mtd_info *mtd)
- {
- struct mtd_part *part = mtd_to_part(mtd);
-- part->master->_put_device(part->master);
-+ part->parent->_put_device(part->parent);
- }
-
- static int part_ooblayout_ecc(struct mtd_info *mtd, int section,
-@@ -333,7 +339,7 @@ static int part_ooblayout_ecc(struct mtd
- {
- struct mtd_part *part = mtd_to_part(mtd);
-
-- return mtd_ooblayout_ecc(part->master, section, oobregion);
-+ return mtd_ooblayout_ecc(part->parent, section, oobregion);
- }
-
- static int part_ooblayout_free(struct mtd_info *mtd, int section,
-@@ -341,7 +347,7 @@ static int part_ooblayout_free(struct mt
- {
- struct mtd_part *part = mtd_to_part(mtd);
-
-- return mtd_ooblayout_free(part->master, section, oobregion);
-+ return mtd_ooblayout_free(part->parent, section, oobregion);
- }
-
- static const struct mtd_ooblayout_ops part_ooblayout_ops = {
-@@ -353,7 +359,7 @@ static int part_max_bad_blocks(struct mt
- {
- struct mtd_part *part = mtd_to_part(mtd);
-
-- return part->master->_max_bad_blocks(part->master,
-+ return part->parent->_max_bad_blocks(part->parent,
- ofs + part->offset, len);
- }
-
-@@ -363,12 +369,12 @@ static inline void free_partition(struct
- kfree(p);
- }
-
--static struct mtd_part *allocate_partition(struct mtd_info *master,
-+static struct mtd_part *allocate_partition(struct mtd_info *parent,
- const struct mtd_partition *part, int partno,
- uint64_t cur_offset)
- {
-- int wr_alignment = (master->flags & MTD_NO_ERASE) ? master->writesize:
-- master->erasesize;
-+ int wr_alignment = (parent->flags & MTD_NO_ERASE) ? parent->writesize:
-+ parent->erasesize;
- struct mtd_part *slave;
- u32 remainder;
- char *name;
-@@ -379,25 +385,25 @@ static struct mtd_part *allocate_partiti
- name = kstrdup(part->name, GFP_KERNEL);
- if (!name || !slave) {
- printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
-- master->name);
-+ parent->name);
- kfree(name);
- kfree(slave);
- return ERR_PTR(-ENOMEM);
- }
-
- /* set up the MTD object for this partition */
-- slave->mtd.type = master->type;
-- slave->mtd.flags = master->flags & ~part->mask_flags;
-+ slave->mtd.type = parent->type;
-+ slave->mtd.flags = parent->flags & ~part->mask_flags;
- slave->mtd.size = part->size;
-- slave->mtd.writesize = master->writesize;
-- slave->mtd.writebufsize = master->writebufsize;
-- slave->mtd.oobsize = master->oobsize;
-- slave->mtd.oobavail = master->oobavail;
-- slave->mtd.subpage_sft = master->subpage_sft;
-- slave->mtd.pairing = master->pairing;
-+ slave->mtd.writesize = parent->writesize;
-+ slave->mtd.writebufsize = parent->writebufsize;
-+ slave->mtd.oobsize = parent->oobsize;
-+ slave->mtd.oobavail = parent->oobavail;
-+ slave->mtd.subpage_sft = parent->subpage_sft;
-+ slave->mtd.pairing = parent->pairing;
-
- slave->mtd.name = name;
-- slave->mtd.owner = master->owner;
-+ slave->mtd.owner = parent->owner;
-
- /* NOTE: Historically, we didn't arrange MTDs as a tree out of
- * concern for showing the same data in multiple partitions.
-@@ -408,70 +414,70 @@ static struct mtd_part *allocate_partiti
- * distinguish between the master and the partition in sysfs.
- */
- slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ?
-- &master->dev :
-- master->dev.parent;
-+ &parent->dev :
-+ parent->dev.parent;
- slave->mtd.dev.of_node = part->of_node;
-
- slave->mtd._read = part_read;
- slave->mtd._write = part_write;
-
-- if (master->_panic_write)
-+ if (parent->_panic_write)
- slave->mtd._panic_write = part_panic_write;
-
-- if (master->_point && master->_unpoint) {
-+ if (parent->_point && parent->_unpoint) {
- slave->mtd._point = part_point;
- slave->mtd._unpoint = part_unpoint;
- }
-
-- if (master->_get_unmapped_area)
-+ if (parent->_get_unmapped_area)
- slave->mtd._get_unmapped_area = part_get_unmapped_area;
-- if (master->_read_oob)
-+ if (parent->_read_oob)
- slave->mtd._read_oob = part_read_oob;
-- if (master->_write_oob)
-+ if (parent->_write_oob)
- slave->mtd._write_oob = part_write_oob;
-- if (master->_read_user_prot_reg)
-+ if (parent->_read_user_prot_reg)
- slave->mtd._read_user_prot_reg = part_read_user_prot_reg;
-- if (master->_read_fact_prot_reg)
-+ if (parent->_read_fact_prot_reg)
- slave->mtd._read_fact_prot_reg = part_read_fact_prot_reg;
-- if (master->_write_user_prot_reg)
-+ if (parent->_write_user_prot_reg)
- slave->mtd._write_user_prot_reg = part_write_user_prot_reg;
-- if (master->_lock_user_prot_reg)
-+ if (parent->_lock_user_prot_reg)
- slave->mtd._lock_user_prot_reg = part_lock_user_prot_reg;
-- if (master->_get_user_prot_info)
-+ if (parent->_get_user_prot_info)
- slave->mtd._get_user_prot_info = part_get_user_prot_info;
-- if (master->_get_fact_prot_info)
-+ if (parent->_get_fact_prot_info)
- slave->mtd._get_fact_prot_info = part_get_fact_prot_info;
-- if (master->_sync)
-+ if (parent->_sync)
- slave->mtd._sync = part_sync;
-- if (!partno && !master->dev.class && master->_suspend &&
-- master->_resume) {
-+ if (!partno && !parent->dev.class && parent->_suspend &&
-+ parent->_resume) {
- slave->mtd._suspend = part_suspend;
- slave->mtd._resume = part_resume;
- }
-- if (master->_writev)
-+ if (parent->_writev)
- slave->mtd._writev = part_writev;
-- if (master->_lock)
-+ if (parent->_lock)
- slave->mtd._lock = part_lock;
-- if (master->_unlock)
-+ if (parent->_unlock)
- slave->mtd._unlock = part_unlock;
-- if (master->_is_locked)
-+ if (parent->_is_locked)
- slave->mtd._is_locked = part_is_locked;
-- if (master->_block_isreserved)
-+ if (parent->_block_isreserved)
- slave->mtd._block_isreserved = part_block_isreserved;
-- if (master->_block_isbad)
-+ if (parent->_block_isbad)
- slave->mtd._block_isbad = part_block_isbad;
-- if (master->_block_markbad)
-+ if (parent->_block_markbad)
- slave->mtd._block_markbad = part_block_markbad;
-- if (master->_max_bad_blocks)
-+ if (parent->_max_bad_blocks)
- slave->mtd._max_bad_blocks = part_max_bad_blocks;
-
-- if (master->_get_device)
-+ if (parent->_get_device)
- slave->mtd._get_device = part_get_device;
-- if (master->_put_device)
-+ if (parent->_put_device)
- slave->mtd._put_device = part_put_device;
-
- slave->mtd._erase = part_erase;
-- slave->master = master;
-+ slave->parent = parent;
- slave->offset = part->offset;
-
- if (slave->offset == MTDPART_OFS_APPEND)
-@@ -489,25 +495,25 @@ static struct mtd_part *allocate_partiti
- }
- if (slave->offset == MTDPART_OFS_RETAIN) {
- slave->offset = cur_offset;
-- if (master->size - slave->offset >= slave->mtd.size) {
-- slave->mtd.size = master->size - slave->offset
-+ if (parent->size - slave->offset >= slave->mtd.size) {
-+ slave->mtd.size = parent->size - slave->offset
- - slave->mtd.size;
- } else {
- printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
-- part->name, master->size - slave->offset,
-+ part->name, parent->size - slave->offset,
- slave->mtd.size);
- /* register to preserve ordering */
- goto out_register;
- }
- }
- if (slave->mtd.size == MTDPART_SIZ_FULL)
-- slave->mtd.size = master->size - slave->offset;
-+ slave->mtd.size = parent->size - slave->offset;
-
- printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,
- (unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);
-
- /* let's do some sanity checks */
-- if (slave->offset >= master->size) {
-+ if (slave->offset >= parent->size) {
- /* let's register it anyway to preserve ordering */
- slave->offset = 0;
- slave->mtd.size = 0;
-@@ -515,16 +521,16 @@ static struct mtd_part *allocate_partiti
- part->name);
- goto out_register;
- }
-- if (slave->offset + slave->mtd.size > master->size) {
-- slave->mtd.size = master->size - slave->offset;
-+ if (slave->offset + slave->mtd.size > parent->size) {
-+ slave->mtd.size = parent->size - slave->offset;
- printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n",
-- part->name, master->name, (unsigned long long)slave->mtd.size);
-+ part->name, parent->name, (unsigned long long)slave->mtd.size);
- }
-- if (master->numeraseregions > 1) {
-+ if (parent->numeraseregions > 1) {
- /* Deal with variable erase size stuff */
-- int i, max = master->numeraseregions;
-+ int i, max = parent->numeraseregions;
- u64 end = slave->offset + slave->mtd.size;
-- struct mtd_erase_region_info *regions = master->eraseregions;
-+ struct mtd_erase_region_info *regions = parent->eraseregions;
-
- /* Find the first erase regions which is part of this
- * partition. */
-@@ -543,7 +549,7 @@ static struct mtd_part *allocate_partiti
- BUG_ON(slave->mtd.erasesize == 0);
- } else {
- /* Single erase size */
-- slave->mtd.erasesize = master->erasesize;
-+ slave->mtd.erasesize = parent->erasesize;
- }
-
- tmp = slave->offset;
-@@ -566,17 +572,17 @@ static struct mtd_part *allocate_partiti
- }
-
- mtd_set_ooblayout(&slave->mtd, &part_ooblayout_ops);
-- slave->mtd.ecc_step_size = master->ecc_step_size;
-- slave->mtd.ecc_strength = master->ecc_strength;
-- slave->mtd.bitflip_threshold = master->bitflip_threshold;
-+ slave->mtd.ecc_step_size = parent->ecc_step_size;
-+ slave->mtd.ecc_strength = parent->ecc_strength;
-+ slave->mtd.bitflip_threshold = parent->bitflip_threshold;
-
-- if (master->_block_isbad) {
-+ if (parent->_block_isbad) {
- uint64_t offs = 0;
-
- while (offs < slave->mtd.size) {
-- if (mtd_block_isreserved(master, offs + slave->offset))
-+ if (mtd_block_isreserved(parent, offs + slave->offset))
- slave->mtd.ecc_stats.bbtblocks++;
-- else if (mtd_block_isbad(master, offs + slave->offset))
-+ else if (mtd_block_isbad(parent, offs + slave->offset))
- slave->mtd.ecc_stats.badblocks++;
- offs += slave->mtd.erasesize;
- }
-@@ -610,7 +616,7 @@ static int mtd_add_partition_attrs(struc
- return ret;
- }
-
--int mtd_add_partition(struct mtd_info *master, const char *name,
-+int mtd_add_partition(struct mtd_info *parent, const char *name,
- long long offset, long long length)
- {
- struct mtd_partition part;
-@@ -623,7 +629,7 @@ int mtd_add_partition(struct mtd_info *m
- return -EINVAL;
-
- if (length == MTDPART_SIZ_FULL)
-- length = master->size - offset;
-+ length = parent->size - offset;
-
- if (length <= 0)
- return -EINVAL;
-@@ -633,7 +639,7 @@ int mtd_add_partition(struct mtd_info *m
- part.size = length;
- part.offset = offset;
-
-- new = allocate_partition(master, &part, -1, offset);
-+ new = allocate_partition(parent, &part, -1, offset);
- if (IS_ERR(new))
- return PTR_ERR(new);
-
-@@ -683,7 +689,7 @@ int del_mtd_partitions(struct mtd_info *
-
- mutex_lock(&mtd_partitions_mutex);
- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
-- if (slave->master == master) {
-+ if (slave->parent == master) {
- ret = __mtd_del_partition(slave);
- if (ret < 0)
- err = ret;
-@@ -700,7 +706,7 @@ int mtd_del_partition(struct mtd_info *m
-
- mutex_lock(&mtd_partitions_mutex);
- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
-- if ((slave->master == master) &&
-+ if ((slave->parent == master) &&
- (slave->mtd.index == partno)) {
- ret = __mtd_del_partition(slave);
- break;
-@@ -933,6 +939,6 @@ uint64_t mtd_get_device_size(const struc
- if (!mtd_is_partition(mtd))
- return mtd->size;
-
-- return mtd_to_part(mtd)->master->size;
-+ return mtd_to_part(mtd)->parent->size;
- }
- EXPORT_SYMBOL_GPL(mtd_get_device_size);
+++ /dev/null
-From 97519dc52b44af054d7654776e78eaa211cf1842 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 21 Jun 2017 08:26:45 +0200
-Subject: [PATCH] mtd: partitions: add support for subpartitions
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Some flash device partitions can be containers with extra subpartitions
-(volumes). All callbacks are already capable of this additional level of
-indirection.
-
-This patch makes sure we always display subpartitions using a tree
-structure and takes care of deleting subpartitions when parent gets
-removed.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 23 ++++++++++++++++-------
- 1 file changed, 16 insertions(+), 7 deletions(-)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -413,7 +413,7 @@ static struct mtd_part *allocate_partiti
- * parent conditional on that option. Note, this is a way to
- * distinguish between the master and the partition in sysfs.
- */
-- slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) ?
-+ slave->mtd.dev.parent = IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER) || mtd_is_partition(parent) ?
- &parent->dev :
- parent->dev.parent;
- slave->mtd.dev.of_node = part->of_node;
-@@ -664,8 +664,17 @@ EXPORT_SYMBOL_GPL(mtd_add_partition);
- */
- static int __mtd_del_partition(struct mtd_part *priv)
- {
-+ struct mtd_part *child, *next;
- int err;
-
-+ list_for_each_entry_safe(child, next, &mtd_partitions, list) {
-+ if (child->parent == &priv->mtd) {
-+ err = __mtd_del_partition(child);
-+ if (err)
-+ return err;
-+ }
-+ }
-+
- sysfs_remove_files(&priv->mtd.dev.kobj, mtd_partition_attrs);
-
- err = del_mtd_device(&priv->mtd);
-@@ -680,16 +689,16 @@ static int __mtd_del_partition(struct mt
-
- /*
- * This function unregisters and destroy all slave MTD objects which are
-- * attached to the given master MTD object.
-+ * attached to the given MTD object.
- */
--int del_mtd_partitions(struct mtd_info *master)
-+int del_mtd_partitions(struct mtd_info *mtd)
- {
- struct mtd_part *slave, *next;
- int ret, err = 0;
-
- mutex_lock(&mtd_partitions_mutex);
- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
-- if (slave->parent == master) {
-+ if (slave->parent == mtd) {
- ret = __mtd_del_partition(slave);
- if (ret < 0)
- err = ret;
-@@ -699,14 +708,14 @@ int del_mtd_partitions(struct mtd_info *
- return err;
- }
-
--int mtd_del_partition(struct mtd_info *master, int partno)
-+int mtd_del_partition(struct mtd_info *mtd, int partno)
- {
- struct mtd_part *slave, *next;
- int ret = -EINVAL;
-
- mutex_lock(&mtd_partitions_mutex);
- list_for_each_entry_safe(slave, next, &mtd_partitions, list)
-- if ((slave->parent == master) &&
-+ if ((slave->parent == mtd) &&
- (slave->mtd.index == partno)) {
- ret = __mtd_del_partition(slave);
- break;
-@@ -939,6 +948,6 @@ uint64_t mtd_get_device_size(const struc
- if (!mtd_is_partition(mtd))
- return mtd->size;
-
-- return mtd_to_part(mtd)->parent->size;
-+ return mtd_get_device_size(mtd_to_part(mtd)->parent);
- }
- EXPORT_SYMBOL_GPL(mtd_get_device_size);
+++ /dev/null
-From 1a0915be192606fee64830b9c5d70b7ed59426b6 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 21 Jun 2017 08:26:46 +0200
-Subject: [PATCH] mtd: partitions: add support for partition parsers
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Some devices have partitions that are kind of containers with extra
-subpartitions / volumes instead of e.g. a simple filesystem data. To
-support such cases we need to first create normal flash device
-partitions and then take care of these special ones.
-
-It's very common case for home routers. Depending on the vendor there
-are formats like TRX, Seama, TP-Link, WRGG & more. All of them are used
-to embed few partitions into a single one / single firmware file.
-
-Ideally all vendors would use some well documented / standardized format
-like UBI (and some probably start doing so), but there are still
-countless devices on the market using these poor vendor specific
-formats.
-
-This patch extends MTD subsystem by allowing to specify list of parsers
-that should be tried for a given partition. Supporting such poor formats
-is highly unlikely to be the top priority so these changes try to
-minimize maintenance cost to the minimum. It reuses existing code for
-these new parsers and just adds a one property and one new function.
-
-This implementation requires setting partition parsers in a flash
-parser. A proper change of bcm47xxpart will follow and in the future we
-will hopefully also find a solution for doing it with ofpart
-("fixed-partitions").
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/mtdpart.c | 31 +++++++++++++++++++++++++++++++
- include/linux/mtd/partitions.h | 7 +++++++
- 2 files changed, 38 insertions(+)
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -369,6 +369,35 @@ static inline void free_partition(struct
- kfree(p);
- }
-
-+/**
-+ * mtd_parse_part - parse MTD partition looking for subpartitions
-+ *
-+ * @slave: part that is supposed to be a container and should be parsed
-+ * @types: NULL-terminated array with names of partition parsers to try
-+ *
-+ * Some partitions are kind of containers with extra subpartitions (volumes).
-+ * There can be various formats of such containers. This function tries to use
-+ * specified parsers to analyze given partition and registers found
-+ * subpartitions on success.
-+ */
-+static int mtd_parse_part(struct mtd_part *slave, const char *const *types)
-+{
-+ struct mtd_partitions parsed;
-+ int err;
-+
-+ err = parse_mtd_partitions(&slave->mtd, types, &parsed, NULL);
-+ if (err)
-+ return err;
-+ else if (!parsed.nr_parts)
-+ return -ENOENT;
-+
-+ err = add_mtd_partitions(&slave->mtd, parsed.parts, parsed.nr_parts);
-+
-+ mtd_part_parser_cleanup(&parsed);
-+
-+ return err;
-+}
-+
- static struct mtd_part *allocate_partition(struct mtd_info *parent,
- const struct mtd_partition *part, int partno,
- uint64_t cur_offset)
-@@ -758,6 +787,8 @@ int add_mtd_partitions(struct mtd_info *
-
- add_mtd_device(&slave->mtd);
- mtd_add_partition_attrs(slave);
-+ if (parts[i].types)
-+ mtd_parse_part(slave, parts[i].types);
-
- cur_offset = slave->offset + slave->mtd.size;
- }
---- a/include/linux/mtd/partitions.h
-+++ b/include/linux/mtd/partitions.h
-@@ -20,6 +20,12 @@
- *
- * For each partition, these fields are available:
- * name: string that will be used to label the partition's MTD device.
-+ * types: some partitions can be containers using specific format to describe
-+ * embedded subpartitions / volumes. E.g. many home routers use "firmware"
-+ * partition that contains at least kernel and rootfs. In such case an
-+ * extra parser is needed that will detect these dynamic partitions and
-+ * report them to the MTD subsystem. If set this property stores an array
-+ * of parser names to use when looking for subpartitions.
- * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
- * will extend to the end of the master MTD device.
- * offset: absolute starting position within the master MTD device; if
-@@ -38,6 +44,7 @@
-
- struct mtd_partition {
- const char *name; /* identifier string */
-+ const char *const *types; /* names of parsers to use if any */
- uint64_t size; /* partition size */
- uint64_t offset; /* offset within the master MTD space */
- uint32_t mask_flags; /* master MTD flags to mask out for this partition */
+++ /dev/null
-From 99352afe8f169c95b294b6b9a8d0e18cd9e3c2a0 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 21 Jun 2017 08:26:47 +0200
-Subject: [PATCH] mtd: extract TRX parser out of bcm47xxpart into a separated
- module
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This makes TRX parsing code reusable with other platforms and parsers.
-
-Please note this patch doesn't really change anything in the existing
-code, just moves it. There is still some place for improvement (e.g.
-working on non-hacky method of checking rootfs format) but it's not
-really a subject of this change.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
----
- drivers/mtd/Kconfig | 4 ++
- drivers/mtd/Makefile | 1 +
- drivers/mtd/bcm47xxpart.c | 99 ++----------------------------
- drivers/mtd/parsers/Kconfig | 8 +++
- drivers/mtd/parsers/Makefile | 1 +
- drivers/mtd/parsers/parser_trx.c | 126 +++++++++++++++++++++++++++++++++++++++
- 6 files changed, 145 insertions(+), 94 deletions(-)
- create mode 100644 drivers/mtd/parsers/Kconfig
- create mode 100644 drivers/mtd/parsers/Makefile
- create mode 100644 drivers/mtd/parsers/parser_trx.c
-
---- a/drivers/mtd/Kconfig
-+++ b/drivers/mtd/Kconfig
-@@ -155,6 +155,10 @@ config MTD_BCM47XX_PARTS
- This provides partitions parser for devices based on BCM47xx
- boards.
-
-+menu "Partition parsers"
-+source "drivers/mtd/parsers/Kconfig"
-+endmenu
-+
- comment "User Modules And Translation Layers"
-
- #
---- a/drivers/mtd/Makefile
-+++ b/drivers/mtd/Makefile
-@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
- obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
- obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
- obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
-+obj-y += parsers/
-
- # 'Users' - code which presents functionality to userspace.
- obj-$(CONFIG_MTD_BLKDEVS) += mtd_blkdevs.o
---- a/drivers/mtd/bcm47xxpart.c
-+++ b/drivers/mtd/bcm47xxpart.c
-@@ -43,7 +43,8 @@
- #define ML_MAGIC2 0x26594131
- #define TRX_MAGIC 0x30524448
- #define SHSQ_MAGIC 0x71736873 /* shsq (weird ZTE H218N endianness) */
--#define UBI_EC_MAGIC 0x23494255 /* UBI# */
-+
-+static const char * const trx_types[] = { "trx", NULL };
-
- struct trx_header {
- uint32_t magic;
-@@ -62,89 +63,6 @@ static void bcm47xxpart_add_part(struct
- part->mask_flags = mask_flags;
- }
-
--static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master,
-- size_t offset)
--{
-- uint32_t buf;
-- size_t bytes_read;
-- int err;
--
-- err = mtd_read(master, offset, sizeof(buf), &bytes_read,
-- (uint8_t *)&buf);
-- if (err && !mtd_is_bitflip(err)) {
-- pr_err("mtd_read error while parsing (offset: 0x%X): %d\n",
-- offset, err);
-- goto out_default;
-- }
--
-- if (buf == UBI_EC_MAGIC)
-- return "ubi";
--
--out_default:
-- return "rootfs";
--}
--
--static int bcm47xxpart_parse_trx(struct mtd_info *master,
-- struct mtd_partition *trx,
-- struct mtd_partition *parts,
-- size_t parts_len)
--{
-- struct trx_header header;
-- size_t bytes_read;
-- int curr_part = 0;
-- int i, err;
--
-- if (parts_len < 3) {
-- pr_warn("No enough space to add TRX partitions!\n");
-- return -ENOMEM;
-- }
--
-- err = mtd_read(master, trx->offset, sizeof(header), &bytes_read,
-- (uint8_t *)&header);
-- if (err && !mtd_is_bitflip(err)) {
-- pr_err("mtd_read error while reading TRX header: %d\n", err);
-- return err;
-- }
--
-- i = 0;
--
-- /* We have LZMA loader if offset[2] points to sth */
-- if (header.offset[2]) {
-- bcm47xxpart_add_part(&parts[curr_part++], "loader",
-- trx->offset + header.offset[i], 0);
-- i++;
-- }
--
-- if (header.offset[i]) {
-- bcm47xxpart_add_part(&parts[curr_part++], "linux",
-- trx->offset + header.offset[i], 0);
-- i++;
-- }
--
-- if (header.offset[i]) {
-- size_t offset = trx->offset + header.offset[i];
-- const char *name = bcm47xxpart_trx_data_part_name(master,
-- offset);
--
-- bcm47xxpart_add_part(&parts[curr_part++], name, offset, 0);
-- i++;
-- }
--
-- /*
-- * Assume that every partition ends at the beginning of the one it is
-- * followed by.
-- */
-- for (i = 0; i < curr_part; i++) {
-- u64 next_part_offset = (i < curr_part - 1) ?
-- parts[i + 1].offset :
-- trx->offset + trx->size;
--
-- parts[i].size = next_part_offset - parts[i].offset;
-- }
--
-- return curr_part;
--}
--
- /**
- * bcm47xxpart_bootpartition - gets index of TRX partition used by bootloader
- *
-@@ -362,17 +280,10 @@ static int bcm47xxpart_parse(struct mtd_
- for (i = 0; i < trx_num; i++) {
- struct mtd_partition *trx = &parts[trx_parts[i]];
-
-- if (i == bcm47xxpart_bootpartition()) {
-- int num_parts;
--
-- num_parts = bcm47xxpart_parse_trx(master, trx,
-- parts + curr_part,
-- BCM47XXPART_MAX_PARTS - curr_part);
-- if (num_parts > 0)
-- curr_part += num_parts;
-- } else {
-+ if (i == bcm47xxpart_bootpartition())
-+ trx->types = trx_types;
-+ else
- trx->name = "failsafe";
-- }
- }
-
- *pparts = parts;
---- /dev/null
-+++ b/drivers/mtd/parsers/Kconfig
-@@ -0,0 +1,8 @@
-+config MTD_PARSER_TRX
-+ tristate "Parser for TRX format partitions"
-+ depends on MTD && (BCM47XX || ARCH_BCM_5301X || COMPILE_TEST)
-+ help
-+ TRX is a firmware format used by Broadcom on their devices. It
-+ may contain up to 3/4 partitions (depending on the version).
-+ This driver will parse TRX header and report at least two partitions:
-+ kernel and rootfs.
---- /dev/null
-+++ b/drivers/mtd/parsers/Makefile
-@@ -0,0 +1 @@
-+obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
---- /dev/null
-+++ b/drivers/mtd/parsers/parser_trx.c
-@@ -0,0 +1,126 @@
-+/*
-+ * Parser for TRX format partitions
-+ *
-+ * Copyright (C) 2012 - 2017 Rafał Miłecki <rafal@milecki.pl>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ *
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+
-+#define TRX_PARSER_MAX_PARTS 4
-+
-+/* Magics */
-+#define TRX_MAGIC 0x30524448
-+#define UBI_EC_MAGIC 0x23494255 /* UBI# */
-+
-+struct trx_header {
-+ uint32_t magic;
-+ uint32_t length;
-+ uint32_t crc32;
-+ uint16_t flags;
-+ uint16_t version;
-+ uint32_t offset[3];
-+} __packed;
-+
-+static const char *parser_trx_data_part_name(struct mtd_info *master,
-+ size_t offset)
-+{
-+ uint32_t buf;
-+ size_t bytes_read;
-+ int err;
-+
-+ err = mtd_read(master, offset, sizeof(buf), &bytes_read,
-+ (uint8_t *)&buf);
-+ if (err && !mtd_is_bitflip(err)) {
-+ pr_err("mtd_read error while parsing (offset: 0x%X): %d\n",
-+ offset, err);
-+ goto out_default;
-+ }
-+
-+ if (buf == UBI_EC_MAGIC)
-+ return "ubi";
-+
-+out_default:
-+ return "rootfs";
-+}
-+
-+static int parser_trx_parse(struct mtd_info *mtd,
-+ const struct mtd_partition **pparts,
-+ struct mtd_part_parser_data *data)
-+{
-+ struct mtd_partition *parts;
-+ struct mtd_partition *part;
-+ struct trx_header trx;
-+ size_t bytes_read;
-+ uint8_t curr_part = 0, i = 0;
-+ int err;
-+
-+ parts = kzalloc(sizeof(struct mtd_partition) * TRX_PARSER_MAX_PARTS,
-+ GFP_KERNEL);
-+ if (!parts)
-+ return -ENOMEM;
-+
-+ err = mtd_read(mtd, 0, sizeof(trx), &bytes_read, (uint8_t *)&trx);
-+ if (err) {
-+ pr_err("MTD reading error: %d\n", err);
-+ kfree(parts);
-+ return err;
-+ }
-+
-+ if (trx.magic != TRX_MAGIC) {
-+ kfree(parts);
-+ return -ENOENT;
-+ }
-+
-+ /* We have LZMA loader if there is address in offset[2] */
-+ if (trx.offset[2]) {
-+ part = &parts[curr_part++];
-+ part->name = "loader";
-+ part->offset = trx.offset[i];
-+ i++;
-+ }
-+
-+ if (trx.offset[i]) {
-+ part = &parts[curr_part++];
-+ part->name = "linux";
-+ part->offset = trx.offset[i];
-+ i++;
-+ }
-+
-+ if (trx.offset[i]) {
-+ part = &parts[curr_part++];
-+ part->name = parser_trx_data_part_name(mtd, trx.offset[i]);
-+ part->offset = trx.offset[i];
-+ i++;
-+ }
-+
-+ /*
-+ * Assume that every partition ends at the beginning of the one it is
-+ * followed by.
-+ */
-+ for (i = 0; i < curr_part; i++) {
-+ u64 next_part_offset = (i < curr_part - 1) ?
-+ parts[i + 1].offset : mtd->size;
-+
-+ parts[i].size = next_part_offset - parts[i].offset;
-+ }
-+
-+ *pparts = parts;
-+ return i;
-+};
-+
-+static struct mtd_part_parser mtd_parser_trx = {
-+ .parse_fn = parser_trx_parse,
-+ .name = "trx",
-+};
-+module_mtd_part_parser(mtd_parser_trx);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_DESCRIPTION("Parser for TRX format partitions");
+++ /dev/null
-From 2c77c57d22adb05b21cdb333a0c42bdfa0e19835 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 16 Jan 2018 16:45:41 +0100
-Subject: [PATCH] mtd: move code adding master MTD out of
- mtd_add_device_partitions()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This change is a small cleanup of mtd_device_parse_register(). When
-using MTD_PARTITIONED_MASTER it makes sure a master MTD is registered
-before dealing with partitions. The advantage of this is not mixing
-code handling master MTD with code handling partitions.
-
-This commit doesn't change any behavior except from a slightly different
-failure code path. The new code may need to call del_mtd_device when
-something goes wrong.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
----
- drivers/mtd/mtdcore.c | 25 +++++++++++++------------
- 1 file changed, 13 insertions(+), 12 deletions(-)
-
---- a/drivers/mtd/mtdcore.c
-+++ b/drivers/mtd/mtdcore.c
-@@ -631,20 +631,12 @@ static int mtd_add_device_partitions(str
- {
- const struct mtd_partition *real_parts = parts->parts;
- int nbparts = parts->nr_parts;
-- int ret;
-
-- if (nbparts == 0 || IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
-- ret = add_mtd_device(mtd);
-- if (ret)
-- return ret;
-- }
-+ if (!nbparts && !device_is_registered(&mtd->dev))
-+ return add_mtd_device(mtd);
-
-- if (nbparts > 0) {
-- ret = add_mtd_partitions(mtd, real_parts, nbparts);
-- if (ret && IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
-- del_mtd_device(mtd);
-- return ret;
-- }
-+ if (nbparts > 0)
-+ return add_mtd_partitions(mtd, real_parts, nbparts);
-
- return 0;
- }
-@@ -704,6 +696,12 @@ int mtd_device_parse_register(struct mtd
-
- mtd_set_dev_defaults(mtd);
-
-+ if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
-+ ret = add_mtd_device(mtd);
-+ if (ret)
-+ return ret;
-+ }
-+
- memset(&parsed, 0, sizeof(parsed));
-
- ret = parse_mtd_partitions(mtd, types, &parsed, parser_data);
-@@ -743,6 +741,9 @@ int mtd_device_parse_register(struct mtd
- out:
- /* Cleanup any parsed partitions */
- mtd_part_parser_cleanup(&parsed);
-+ if (ret && device_is_registered(&mtd->dev))
-+ del_mtd_device(mtd);
-+
- return ret;
- }
- EXPORT_SYMBOL_GPL(mtd_device_parse_register);
+++ /dev/null
-From 0dbe4ea78d69756efeb0bba0764f6bd4a9ee9567 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 16 Jan 2018 16:45:42 +0100
-Subject: [PATCH] mtd: get rid of the mtd_add_device_partitions()
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This simplifies code a bit by:
-1) Avoiding an extra (tiny) function
-2) Checking for amount of parsed (found) partitions just once
-3) Avoiding clearing/filling struct mtd_partitions manually
-
-With this commit proper functions are called directly from the
-mtd_device_parse_register(). It doesn't need to use minor tricks like
-memsetting struct to 0 to trigger an expected
-mtd_add_device_partitions() behavior.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
----
- drivers/mtd/mtdcore.c | 43 ++++++++++++-------------------------------
- 1 file changed, 12 insertions(+), 31 deletions(-)
-
---- a/drivers/mtd/mtdcore.c
-+++ b/drivers/mtd/mtdcore.c
-@@ -626,21 +626,6 @@ out_error:
- return ret;
- }
-
--static int mtd_add_device_partitions(struct mtd_info *mtd,
-- struct mtd_partitions *parts)
--{
-- const struct mtd_partition *real_parts = parts->parts;
-- int nbparts = parts->nr_parts;
--
-- if (!nbparts && !device_is_registered(&mtd->dev))
-- return add_mtd_device(mtd);
--
-- if (nbparts > 0)
-- return add_mtd_partitions(mtd, real_parts, nbparts);
--
-- return 0;
--}
--
- /*
- * Set a few defaults based on the parent devices, if not provided by the
- * driver
-@@ -691,7 +676,7 @@ int mtd_device_parse_register(struct mtd
- const struct mtd_partition *parts,
- int nr_parts)
- {
-- struct mtd_partitions parsed;
-+ struct mtd_partitions parsed = { };
- int ret;
-
- mtd_set_dev_defaults(mtd);
-@@ -702,24 +687,20 @@ int mtd_device_parse_register(struct mtd
- return ret;
- }
-
-- memset(&parsed, 0, sizeof(parsed));
--
-+ /* Prefer parsed partitions over driver-provided fallback */
- ret = parse_mtd_partitions(mtd, types, &parsed, parser_data);
-- if ((ret < 0 || parsed.nr_parts == 0) && parts && nr_parts) {
-- /* Fall back to driver-provided partitions */
-- parsed = (struct mtd_partitions){
-- .parts = parts,
-- .nr_parts = nr_parts,
-- };
-- } else if (ret < 0) {
-- /* Didn't come up with parsed OR fallback partitions */
-- pr_info("mtd: failed to find partitions; one or more parsers reports errors (%d)\n",
-- ret);
-- /* Don't abort on errors; we can still use unpartitioned MTD */
-- memset(&parsed, 0, sizeof(parsed));
-+ if (!ret && parsed.nr_parts) {
-+ parts = parsed.parts;
-+ nr_parts = parsed.nr_parts;
- }
-
-- ret = mtd_add_device_partitions(mtd, &parsed);
-+ if (nr_parts)
-+ ret = add_mtd_partitions(mtd, parts, nr_parts);
-+ else if (!device_is_registered(&mtd->dev))
-+ ret = add_mtd_device(mtd);
-+ else
-+ ret = 0;
-+
- if (ret)
- goto out;
-
+++ /dev/null
---- a/drivers/bcma/main.c
-+++ b/drivers/bcma/main.c
-@@ -136,17 +136,17 @@ static bool bcma_is_core_needed_early(u1
- return false;
- }
-
--static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
-+static struct device_node *bcma_of_find_child_device(struct device *parent,
- struct bcma_device *core)
- {
- struct device_node *node;
- u64 size;
- const __be32 *reg;
-
-- if (!parent || !parent->dev.of_node)
-+ if (!parent->of_node)
- return NULL;
-
-- for_each_child_of_node(parent->dev.of_node, node) {
-+ for_each_child_of_node(parent->of_node, node) {
- reg = of_get_address(node, 0, &size, NULL);
- if (!reg)
- continue;
-@@ -156,7 +156,7 @@ static struct device_node *bcma_of_find_
- return NULL;
- }
-
--static int bcma_of_irq_parse(struct platform_device *parent,
-+static int bcma_of_irq_parse(struct device *parent,
- struct bcma_device *core,
- struct of_phandle_args *out_irq, int num)
- {
-@@ -169,7 +169,7 @@ static int bcma_of_irq_parse(struct plat
- return rc;
- }
-
-- out_irq->np = parent->dev.of_node;
-+ out_irq->np = parent->of_node;
- out_irq->args_count = 1;
- out_irq->args[0] = num;
-
-@@ -177,13 +177,13 @@ static int bcma_of_irq_parse(struct plat
- return of_irq_parse_raw(laddr, out_irq);
- }
-
--static unsigned int bcma_of_get_irq(struct platform_device *parent,
-+static unsigned int bcma_of_get_irq(struct device *parent,
- struct bcma_device *core, int num)
- {
- struct of_phandle_args out_irq;
- int ret;
-
-- if (!IS_ENABLED(CONFIG_OF_IRQ) || !parent || !parent->dev.of_node)
-+ if (!IS_ENABLED(CONFIG_OF_IRQ) || !parent->of_node)
- return 0;
-
- ret = bcma_of_irq_parse(parent, core, &out_irq, num);
-@@ -196,7 +196,7 @@ static unsigned int bcma_of_get_irq(stru
- return irq_create_of_mapping(&out_irq);
- }
-
--static void bcma_of_fill_device(struct platform_device *parent,
-+static void bcma_of_fill_device(struct device *parent,
- struct bcma_device *core)
- {
- struct device_node *node;
-@@ -227,7 +227,7 @@ unsigned int bcma_core_irq(struct bcma_d
- return mips_irq <= 4 ? mips_irq + 2 : 0;
- }
- if (bus->host_pdev)
-- return bcma_of_get_irq(bus->host_pdev, core, num);
-+ return bcma_of_get_irq(&bus->host_pdev->dev, core, num);
- return 0;
- case BCMA_HOSTTYPE_SDIO:
- return 0;
-@@ -253,7 +253,8 @@ void bcma_prepare_core(struct bcma_bus *
- if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) {
- core->dma_dev = &bus->host_pdev->dev;
- core->dev.parent = &bus->host_pdev->dev;
-- bcma_of_fill_device(bus->host_pdev, core);
-+ if (core->dev.parent)
-+ bcma_of_fill_device(core->dev.parent, core);
- } else {
- core->dev.dma_mask = &core->dev.coherent_dma_mask;
- core->dma_dev = &core->dev;
+++ /dev/null
-From 34a5102c3235c470a6c77fba16cb971964d9c136 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 31 Jan 2017 19:37:54 +0100
-Subject: [PATCH 1/3] net: bgmac: allocate struct bgmac just once & don't copy
- it
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-So far were were allocating struct bgmac in 3 places: platform code,
-bcma code and shared bgmac_enet_probe function. The reason for this was
-bgmac_enet_probe:
-1) Requiring early-filled struct bgmac
-2) Calling alloc_etherdev on its own in order to use netdev_priv later
-
-This solution got few drawbacks:
-1) Was duplicating allocating code
-2) Required copying early-filled struct
-3) Resulted in platform/bcma code having access only to unused struct
-
-Solve this situation by simply extracting some probe code into the new
-bgmac_alloc function.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/broadcom/bgmac-bcma.c | 4 +---
- drivers/net/ethernet/broadcom/bgmac-platform.c | 2 +-
- drivers/net/ethernet/broadcom/bgmac.c | 25 +++++++++++++++++--------
- drivers/net/ethernet/broadcom/bgmac.h | 3 ++-
- 4 files changed, 21 insertions(+), 13 deletions(-)
-
---- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
-+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
-@@ -100,12 +100,11 @@ static int bgmac_probe(struct bcma_devic
- const u8 *mac = NULL;
- int err;
-
-- bgmac = kzalloc(sizeof(*bgmac), GFP_KERNEL);
-+ bgmac = bgmac_alloc(&core->dev);
- if (!bgmac)
- return -ENOMEM;
-
- bgmac->bcma.core = core;
-- bgmac->dev = &core->dev;
- bgmac->dma_dev = core->dma_dev;
- bgmac->irq = core->irq;
-
-@@ -292,7 +291,6 @@ static int bgmac_probe(struct bcma_devic
- err1:
- bcma_mdio_mii_unregister(bgmac->mii_bus);
- err:
-- kfree(bgmac);
- bcma_set_drvdata(core, NULL);
-
- return err;
---- a/drivers/net/ethernet/broadcom/bgmac-platform.c
-+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
-@@ -93,7 +93,7 @@ static int bgmac_probe(struct platform_d
- struct resource *regs;
- const u8 *mac_addr;
-
-- bgmac = devm_kzalloc(&pdev->dev, sizeof(*bgmac), GFP_KERNEL);
-+ bgmac = bgmac_alloc(&pdev->dev);
- if (!bgmac)
- return -ENOMEM;
-
---- a/drivers/net/ethernet/broadcom/bgmac.c
-+++ b/drivers/net/ethernet/broadcom/bgmac.c
-@@ -1459,22 +1459,32 @@ static int bgmac_phy_connect(struct bgma
- return 0;
- }
-
--int bgmac_enet_probe(struct bgmac *info)
-+struct bgmac *bgmac_alloc(struct device *dev)
- {
- struct net_device *net_dev;
- struct bgmac *bgmac;
-- int err;
-
- /* Allocation and references */
-- net_dev = alloc_etherdev(sizeof(*bgmac));
-+ net_dev = devm_alloc_etherdev(dev, sizeof(*bgmac));
- if (!net_dev)
-- return -ENOMEM;
-+ return NULL;
-
- net_dev->netdev_ops = &bgmac_netdev_ops;
- net_dev->ethtool_ops = &bgmac_ethtool_ops;
-+
- bgmac = netdev_priv(net_dev);
-- memcpy(bgmac, info, sizeof(*bgmac));
-+ bgmac->dev = dev;
- bgmac->net_dev = net_dev;
-+
-+ return bgmac;
-+}
-+EXPORT_SYMBOL_GPL(bgmac_alloc);
-+
-+int bgmac_enet_probe(struct bgmac *bgmac)
-+{
-+ struct net_device *net_dev = bgmac->net_dev;
-+ int err;
-+
- net_dev->irq = bgmac->irq;
- SET_NETDEV_DEV(net_dev, bgmac->dev);
-
-@@ -1501,7 +1511,7 @@ int bgmac_enet_probe(struct bgmac *info)
- err = bgmac_dma_alloc(bgmac);
- if (err) {
- dev_err(bgmac->dev, "Unable to alloc memory for DMA\n");
-- goto err_netdev_free;
-+ goto err_out;
- }
-
- bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
-@@ -1537,8 +1547,7 @@ err_phy_disconnect:
- phy_disconnect(net_dev->phydev);
- err_dma_free:
- bgmac_dma_free(bgmac);
--err_netdev_free:
-- free_netdev(net_dev);
-+err_out:
-
- return err;
- }
---- a/drivers/net/ethernet/broadcom/bgmac.h
-+++ b/drivers/net/ethernet/broadcom/bgmac.h
-@@ -515,7 +515,8 @@ struct bgmac {
- u32 set);
- };
-
--int bgmac_enet_probe(struct bgmac *info);
-+struct bgmac *bgmac_alloc(struct device *dev);
-+int bgmac_enet_probe(struct bgmac *bgmac);
- void bgmac_enet_remove(struct bgmac *bgmac);
-
- struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 31 Jan 2017 19:37:55 +0100
-Subject: [PATCH] net: bgmac: drop struct bcma_mdio we don't need anymore
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Adding struct bcma_mdio was a workaround for bcma code not having access
-to the struct bgmac used in the core code. Now we don't duplicate this
-struct we can just use it internally in bcma code.
-
-This simplifies code & allows access to all bgmac driver details from
-all places in bcma code.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
-+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
-@@ -166,7 +166,7 @@ static int bgmac_probe(struct bcma_devic
-
- if (!bgmac_is_bcm4707_family(core) &&
- !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
-- mii_bus = bcma_mdio_mii_register(core, bgmac->phyaddr);
-+ mii_bus = bcma_mdio_mii_register(bgmac);
- if (IS_ERR(mii_bus)) {
- err = PTR_ERR(mii_bus);
- goto err;
---- a/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
-+++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
-@@ -12,11 +12,6 @@
- #include <linux/brcmphy.h>
- #include "bgmac.h"
-
--struct bcma_mdio {
-- struct bcma_device *core;
-- u8 phyaddr;
--};
--
- static bool bcma_mdio_wait_value(struct bcma_device *core, u16 reg, u32 mask,
- u32 value, int timeout)
- {
-@@ -37,7 +32,7 @@ static bool bcma_mdio_wait_value(struct
- * PHY ops
- **************************************************/
-
--static u16 bcma_mdio_phy_read(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg)
-+static u16 bcma_mdio_phy_read(struct bgmac *bgmac, u8 phyaddr, u8 reg)
- {
- struct bcma_device *core;
- u16 phy_access_addr;
-@@ -56,12 +51,12 @@ static u16 bcma_mdio_phy_read(struct bcm
- BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT);
- BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE);
-
-- if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
-- core = bcma_mdio->core->bus->drv_gmac_cmn.core;
-+ if (bgmac->bcma.core->id.id == BCMA_CORE_4706_MAC_GBIT) {
-+ core = bgmac->bcma.core->bus->drv_gmac_cmn.core;
- phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
- phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
- } else {
-- core = bcma_mdio->core;
-+ core = bgmac->bcma.core;
- phy_access_addr = BGMAC_PHY_ACCESS;
- phy_ctl_addr = BGMAC_PHY_CNTL;
- }
-@@ -87,7 +82,7 @@ static u16 bcma_mdio_phy_read(struct bcm
- }
-
- /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */
--static int bcma_mdio_phy_write(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg,
-+static int bcma_mdio_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg,
- u16 value)
- {
- struct bcma_device *core;
-@@ -95,12 +90,12 @@ static int bcma_mdio_phy_write(struct bc
- u16 phy_ctl_addr;
- u32 tmp;
-
-- if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
-- core = bcma_mdio->core->bus->drv_gmac_cmn.core;
-+ if (bgmac->bcma.core->id.id == BCMA_CORE_4706_MAC_GBIT) {
-+ core = bgmac->bcma.core->bus->drv_gmac_cmn.core;
- phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
- phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
- } else {
-- core = bcma_mdio->core;
-+ core = bgmac->bcma.core;
- phy_access_addr = BGMAC_PHY_ACCESS;
- phy_ctl_addr = BGMAC_PHY_CNTL;
- }
-@@ -110,8 +105,8 @@ static int bcma_mdio_phy_write(struct bc
- tmp |= phyaddr;
- bcma_write32(core, phy_ctl_addr, tmp);
-
-- bcma_write32(bcma_mdio->core, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
-- if (bcma_read32(bcma_mdio->core, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
-+ bcma_write32(bgmac->bcma.core, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
-+ if (bcma_read32(bgmac->bcma.core, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
- dev_warn(&core->dev, "Error setting MDIO int\n");
-
- tmp = BGMAC_PA_START;
-@@ -132,39 +127,39 @@ static int bcma_mdio_phy_write(struct bc
- }
-
- /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */
--static void bcma_mdio_phy_init(struct bcma_mdio *bcma_mdio)
-+static void bcma_mdio_phy_init(struct bgmac *bgmac)
- {
-- struct bcma_chipinfo *ci = &bcma_mdio->core->bus->chipinfo;
-+ struct bcma_chipinfo *ci = &bgmac->bcma.core->bus->chipinfo;
- u8 i;
-
- if (ci->id == BCMA_CHIP_ID_BCM5356) {
- for (i = 0; i < 5; i++) {
-- bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x008b);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x15, 0x0100);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x12, 0x2aaa);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
-+ bcma_mdio_phy_write(bgmac, i, 0x1f, 0x008b);
-+ bcma_mdio_phy_write(bgmac, i, 0x15, 0x0100);
-+ bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000f);
-+ bcma_mdio_phy_write(bgmac, i, 0x12, 0x2aaa);
-+ bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
- }
- }
- if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) ||
- (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) ||
- (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) {
-- struct bcma_drv_cc *cc = &bcma_mdio->core->bus->drv_cc;
-+ struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;
-
- bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0);
- bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0);
- for (i = 0; i < 5; i++) {
-- bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5284);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x0010);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5296);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x1073);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9073);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x52b6);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9273);
-- bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
-+ bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000f);
-+ bcma_mdio_phy_write(bgmac, i, 0x16, 0x5284);
-+ bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
-+ bcma_mdio_phy_write(bgmac, i, 0x17, 0x0010);
-+ bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000f);
-+ bcma_mdio_phy_write(bgmac, i, 0x16, 0x5296);
-+ bcma_mdio_phy_write(bgmac, i, 0x17, 0x1073);
-+ bcma_mdio_phy_write(bgmac, i, 0x17, 0x9073);
-+ bcma_mdio_phy_write(bgmac, i, 0x16, 0x52b6);
-+ bcma_mdio_phy_write(bgmac, i, 0x17, 0x9273);
-+ bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
- }
- }
- }
-@@ -172,17 +167,17 @@ static void bcma_mdio_phy_init(struct bc
- /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */
- static int bcma_mdio_phy_reset(struct mii_bus *bus)
- {
-- struct bcma_mdio *bcma_mdio = bus->priv;
-- u8 phyaddr = bcma_mdio->phyaddr;
-+ struct bgmac *bgmac = bus->priv;
-+ u8 phyaddr = bgmac->phyaddr;
-
-- if (bcma_mdio->phyaddr == BGMAC_PHY_NOREGS)
-+ if (phyaddr == BGMAC_PHY_NOREGS)
- return 0;
-
-- bcma_mdio_phy_write(bcma_mdio, phyaddr, MII_BMCR, BMCR_RESET);
-+ bcma_mdio_phy_write(bgmac, phyaddr, MII_BMCR, BMCR_RESET);
- udelay(100);
-- if (bcma_mdio_phy_read(bcma_mdio, phyaddr, MII_BMCR) & BMCR_RESET)
-- dev_err(&bcma_mdio->core->dev, "PHY reset failed\n");
-- bcma_mdio_phy_init(bcma_mdio);
-+ if (bcma_mdio_phy_read(bgmac, phyaddr, MII_BMCR) & BMCR_RESET)
-+ dev_err(bgmac->dev, "PHY reset failed\n");
-+ bcma_mdio_phy_init(bgmac);
-
- return 0;
- }
-@@ -202,16 +197,12 @@ static int bcma_mdio_mii_write(struct mi
- return bcma_mdio_phy_write(bus->priv, mii_id, regnum, value);
- }
-
--struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr)
-+struct mii_bus *bcma_mdio_mii_register(struct bgmac *bgmac)
- {
-- struct bcma_mdio *bcma_mdio;
-+ struct bcma_device *core = bgmac->bcma.core;
- struct mii_bus *mii_bus;
- int err;
-
-- bcma_mdio = kzalloc(sizeof(*bcma_mdio), GFP_KERNEL);
-- if (!bcma_mdio)
-- return ERR_PTR(-ENOMEM);
--
- mii_bus = mdiobus_alloc();
- if (!mii_bus) {
- err = -ENOMEM;
-@@ -221,15 +212,12 @@ struct mii_bus *bcma_mdio_mii_register(s
- mii_bus->name = "bcma_mdio mii bus";
- sprintf(mii_bus->id, "%s-%d-%d", "bcma_mdio", core->bus->num,
- core->core_unit);
-- mii_bus->priv = bcma_mdio;
-+ mii_bus->priv = bgmac;
- mii_bus->read = bcma_mdio_mii_read;
- mii_bus->write = bcma_mdio_mii_write;
- mii_bus->reset = bcma_mdio_phy_reset;
- mii_bus->parent = &core->dev;
-- mii_bus->phy_mask = ~(1 << phyaddr);
--
-- bcma_mdio->core = core;
-- bcma_mdio->phyaddr = phyaddr;
-+ mii_bus->phy_mask = ~(1 << bgmac->phyaddr);
-
- err = mdiobus_register(mii_bus);
- if (err) {
-@@ -242,23 +230,17 @@ struct mii_bus *bcma_mdio_mii_register(s
- err_free_bus:
- mdiobus_free(mii_bus);
- err:
-- kfree(bcma_mdio);
- return ERR_PTR(err);
- }
- EXPORT_SYMBOL_GPL(bcma_mdio_mii_register);
-
- void bcma_mdio_mii_unregister(struct mii_bus *mii_bus)
- {
-- struct bcma_mdio *bcma_mdio;
--
- if (!mii_bus)
- return;
-
-- bcma_mdio = mii_bus->priv;
--
- mdiobus_unregister(mii_bus);
- mdiobus_free(mii_bus);
-- kfree(bcma_mdio);
- }
- EXPORT_SYMBOL_GPL(bcma_mdio_mii_unregister);
-
---- a/drivers/net/ethernet/broadcom/bgmac.h
-+++ b/drivers/net/ethernet/broadcom/bgmac.h
-@@ -519,7 +519,7 @@ struct bgmac *bgmac_alloc(struct device
- int bgmac_enet_probe(struct bgmac *bgmac);
- void bgmac_enet_remove(struct bgmac *bgmac);
-
--struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
-+struct mii_bus *bcma_mdio_mii_register(struct bgmac *bgmac);
- void bcma_mdio_mii_unregister(struct mii_bus *mii_bus);
-
- static inline u32 bgmac_read(struct bgmac *bgmac, u16 offset)
+++ /dev/null
-From 8e6f31baba7e2c13ab7e954fe6179420a7545a8b Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 31 Jan 2017 19:37:56 +0100
-Subject: [PATCH 3/3] net: bgmac: use PHY subsystem for initializing PHY
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This adds support for using bgmac with PHYs supported by standalone PHY
-drivers. Having any PHY initialization in bgmac is hacky and shouldn't
-be extended but rather removed if anyone has hardware to test it.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
-+++ b/drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
-@@ -132,6 +132,10 @@ static void bcma_mdio_phy_init(struct bg
- struct bcma_chipinfo *ci = &bgmac->bcma.core->bus->chipinfo;
- u8 i;
-
-+ /* For some legacy hardware we do chipset-based PHY initialization here
-+ * without even detecting PHY ID. It's hacky and should be cleaned as
-+ * soon as someone can test it.
-+ */
- if (ci->id == BCMA_CHIP_ID_BCM5356) {
- for (i = 0; i < 5; i++) {
- bcma_mdio_phy_write(bgmac, i, 0x1f, 0x008b);
-@@ -140,6 +144,7 @@ static void bcma_mdio_phy_init(struct bg
- bcma_mdio_phy_write(bgmac, i, 0x12, 0x2aaa);
- bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
- }
-+ return;
- }
- if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) ||
- (ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) ||
-@@ -161,7 +166,12 @@ static void bcma_mdio_phy_init(struct bg
- bcma_mdio_phy_write(bgmac, i, 0x17, 0x9273);
- bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
- }
-+ return;
- }
-+
-+ /* For all other hw do initialization using PHY subsystem. */
-+ if (bgmac->net_dev && bgmac->net_dev->phydev)
-+ phy_init_hw(bgmac->net_dev->phydev);
- }
-
- /* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */
+++ /dev/null
-From 12acd136913ccdf394eeb2bc8686ff5505368119 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 12 Oct 2017 10:21:26 +0200
-Subject: [PATCH] net: bgmac: enable master mode for BCM54210E and B50212E PHYs
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-There are 4 very similar PHYs:
-0x600d84a1: BCM54210E (rev B0)
-0x600d84a2: BCM54210E (rev B1)
-0x600d84a5: B50212E (rev B0)
-0x600d84a6: B50212E (rev B1)
-that need setting master mode manually. It's because they run in slave
-mode by default with Automatic Slave/Master configuration disabled which
-can lead to unreliable connection with massive ping loss.
-
-So far it was reported for a board with BCM47189 SoC and B50212E B1 PHY
-connected to the bgmac supported ethernet device. Telling PHY driver to
-setup PHY properly solves this issue.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/broadcom/bgmac-bcma.c | 8 +++++++-
- 1 file changed, 7 insertions(+), 1 deletion(-)
-
---- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
-+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
-@@ -166,13 +166,19 @@ static int bgmac_probe(struct bcma_devic
-
- if (!bgmac_is_bcm4707_family(core) &&
- !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
-+ struct phy_device *phydev;
-+
- mii_bus = bcma_mdio_mii_register(bgmac);
- if (IS_ERR(mii_bus)) {
- err = PTR_ERR(mii_bus);
- goto err;
- }
--
- bgmac->mii_bus = mii_bus;
-+
-+ phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr);
-+ if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev &&
-+ (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E)
-+ phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE;
- }
-
- if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
+++ /dev/null
---- a/drivers/bcma/driver_gpio.c
-+++ b/drivers/bcma/driver_gpio.c
-@@ -185,8 +185,7 @@ int bcma_gpio_init(struct bcma_drv_cc *c
- chip->owner = THIS_MODULE;
- chip->parent = bcma_bus_get_host_dev(bus);
- #if IS_BUILTIN(CONFIG_OF)
-- if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
-- chip->of_node = cc->core->dev.of_node;
-+ chip->of_node = cc->core->dev.of_node;
- #endif
- switch (bus->chipinfo.id) {
- case BCMA_CHIP_ID_BCM4707:
---- a/drivers/bcma/main.c
-+++ b/drivers/bcma/main.c
-@@ -201,9 +201,6 @@ static void bcma_of_fill_device(struct d
- {
- struct device_node *node;
-
-- if (!IS_ENABLED(CONFIG_OF_IRQ))
-- return;
--
- node = bcma_of_find_child_device(parent, core);
- if (node)
- core->dev.of_node = node;
-@@ -242,19 +239,18 @@ void bcma_prepare_core(struct bcma_bus *
- core->dev.release = bcma_release_core_dev;
- core->dev.bus = &bcma_bus_type;
- dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
-+ core->dev.parent = bcma_bus_get_host_dev(bus);
-+ if (core->dev.parent)
-+ bcma_of_fill_device(core->dev.parent, core);
-
- switch (bus->hosttype) {
- case BCMA_HOSTTYPE_PCI:
-- core->dev.parent = &bus->host_pci->dev;
- core->dma_dev = &bus->host_pci->dev;
- core->irq = bus->host_pci->irq;
- break;
- case BCMA_HOSTTYPE_SOC:
- if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) {
- core->dma_dev = &bus->host_pdev->dev;
-- core->dev.parent = &bus->host_pdev->dev;
-- if (core->dev.parent)
-- bcma_of_fill_device(core->dev.parent, core);
- } else {
- core->dev.dma_mask = &core->dev.coherent_dma_mask;
- core->dma_dev = &core->dev;
+++ /dev/null
-From: Xo Wang <xow@google.com>
-Date: Fri, 21 Oct 2016 10:20:12 -0700
-Subject: [PATCH] net: phy: broadcom: Update Auxiliary Control Register macros
-
-Add the RXD-to-RXC skew (delay) time bit in the Miscellaneous Control
-shadow register and a mask for the shadow selector field.
-
-Remove a re-definition of MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL.
-
-Signed-off-by: Xo Wang <xow@google.com>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Reviewed-by: Joel Stanley <joel@jms.id.au>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -101,6 +101,7 @@
- * AUXILIARY CONTROL SHADOW ACCESS REGISTERS. (PHY REG 0x18)
- */
- #define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
-+#define MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW 0x0100
- #define MII_BCM54XX_AUXCTL_ACTL_TX_6DB 0x0400
- #define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA 0x0800
-
-@@ -109,7 +110,7 @@
- #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
- #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
-
--#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
-+#define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
-
- /*
- * Broadcom LED source encodings. These are used in BCM5461, BCM5481,
+++ /dev/null
-From: Xo Wang <xow@google.com>
-Date: Fri, 21 Oct 2016 10:20:13 -0700
-Subject: [PATCH] net: phy: broadcom: Add support for BCM54612E
-
-This PHY has internal delays enabled after reset. This clears the
-internal delay enables unless the interface specifically requests them.
-
-Signed-off-by: Xo Wang <xow@google.com>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Reviewed-by: Joel Stanley <joel@jms.id.au>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -337,6 +337,41 @@ static int bcm5481_config_aneg(struct ph
- return ret;
- }
-
-+static int bcm54612e_config_aneg(struct phy_device *phydev)
-+{
-+ int ret;
-+
-+ /* First, auto-negotiate. */
-+ ret = genphy_config_aneg(phydev);
-+
-+ /* Clear TX internal delay unless requested. */
-+ if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
-+ (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
-+ /* Disable TXD to GTXCLK clock delay (default set) */
-+ /* Bit 9 is the only field in shadow register 00011 */
-+ bcm_phy_write_shadow(phydev, 0x03, 0);
-+ }
-+
-+ /* Clear RX internal delay unless requested. */
-+ if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
-+ (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
-+ u16 reg;
-+
-+ /* Errata: reads require filling in the write selector field */
-+ bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
-+ MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
-+ reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
-+ /* Disable RXD to RXC delay (default set) */
-+ reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
-+ /* Clear shadow selector field */
-+ reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
-+ bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
-+ MII_BCM54XX_AUXCTL_MISC_WREN | reg);
-+ }
-+
-+ return ret;
-+}
-+
- static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
- {
- int val;
-@@ -485,6 +520,18 @@ static struct phy_driver broadcom_driver
- .ack_interrupt = bcm_phy_ack_intr,
- .config_intr = bcm_phy_config_intr,
- }, {
-+ .phy_id = PHY_ID_BCM54612E,
-+ .phy_id_mask = 0xfffffff0,
-+ .name = "Broadcom BCM54612E",
-+ .features = PHY_GBIT_FEATURES |
-+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
-+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-+ .config_init = bcm54xx_config_init,
-+ .config_aneg = bcm54612e_config_aneg,
-+ .read_status = genphy_read_status,
-+ .ack_interrupt = bcm_phy_ack_intr,
-+ .config_intr = bcm_phy_config_intr,
-+}, {
- .phy_id = PHY_ID_BCM54616S,
- .phy_id_mask = 0xfffffff0,
- .name = "Broadcom BCM54616S",
-@@ -600,6 +647,7 @@ static struct mdio_device_id __maybe_unu
- { PHY_ID_BCM5411, 0xfffffff0 },
- { PHY_ID_BCM5421, 0xfffffff0 },
- { PHY_ID_BCM5461, 0xfffffff0 },
-+ { PHY_ID_BCM54612E, 0xfffffff0 },
- { PHY_ID_BCM54616S, 0xfffffff0 },
- { PHY_ID_BCM5464, 0xfffffff0 },
- { PHY_ID_BCM5481, 0xfffffff0 },
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -18,6 +18,7 @@
- #define PHY_ID_BCM5421 0x002060e0
- #define PHY_ID_BCM5464 0x002060b0
- #define PHY_ID_BCM5461 0x002060c0
-+#define PHY_ID_BCM54612E 0x03625e60
- #define PHY_ID_BCM54616S 0x03625d10
- #define PHY_ID_BCM57780 0x03625d90
-
+++ /dev/null
-From: Jon Mason <jon.mason@broadcom.com>
-Date: Fri, 4 Nov 2016 01:10:56 -0400
-Subject: [PATCH] net: phy: broadcom: add bcm54xx_auxctl_read
-
-Add a helper function to read the AUXCTL register for the BCM54xx. This
-mirrors the bcm54xx_auxctl_write function already present in the code.
-
-Signed-off-by: Jon Mason <jon.mason@broadcom.com>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -30,6 +30,16 @@ MODULE_DESCRIPTION("Broadcom PHY driver"
- MODULE_AUTHOR("Maciej W. Rozycki");
- MODULE_LICENSE("GPL");
-
-+static int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
-+{
-+ /* The register must be written to both the Shadow Register Select and
-+ * the Shadow Read Register Selector
-+ */
-+ phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum |
-+ regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT);
-+ return phy_read(phydev, MII_BCM54XX_AUX_CTL);
-+}
-+
- static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
- {
- return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -110,6 +110,7 @@
- #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200
- #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
- #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
-+#define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
-
- #define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
-
+++ /dev/null
-From: Jon Mason <jon.mason@broadcom.com>
-Date: Fri, 4 Nov 2016 01:10:58 -0400
-Subject: [PATCH] net: phy: broadcom: Add BCM54810 PHY entry
-
-The BCM54810 PHY requires some semi-unique configuration, which results
-in some additional configuration in addition to the standard config.
-Also, some users of the BCM54810 require the PHY lanes to be swapped.
-Since there is no way to detect this, add a device tree query to see if
-it is applicable.
-
-Inspired-by: Vikas Soni <vsoni@broadcom.com>
-Signed-off-by: Jon Mason <jon.mason@broadcom.com>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -18,7 +18,7 @@
- #include <linux/module.h>
- #include <linux/phy.h>
- #include <linux/brcmphy.h>
--
-+#include <linux/of.h>
-
- #define BRCM_PHY_MODEL(phydev) \
- ((phydev)->drv->phy_id & (phydev)->drv->phy_id_mask)
-@@ -45,6 +45,34 @@ static int bcm54xx_auxctl_write(struct p
- return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
- }
-
-+static int bcm54810_config(struct phy_device *phydev)
-+{
-+ int rc, val;
-+
-+ val = bcm_phy_read_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL);
-+ val &= ~BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN;
-+ rc = bcm_phy_write_exp(phydev, BCM54810_EXP_BROADREACH_LRE_MISC_CTL,
-+ val);
-+ if (rc < 0)
-+ return rc;
-+
-+ val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
-+ val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
-+ val |= MII_BCM54XX_AUXCTL_MISC_WREN;
-+ rc = bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
-+ val);
-+ if (rc < 0)
-+ return rc;
-+
-+ val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
-+ val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
-+ rc = bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
-+ if (rc < 0)
-+ return rc;
-+
-+ return 0;
-+}
-+
- /* Needs SMDSP clock enabled via bcm54xx_phydsp_config() */
- static int bcm50610_a0_workaround(struct phy_device *phydev)
- {
-@@ -217,6 +245,12 @@ static int bcm54xx_config_init(struct ph
- (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
- bcm54xx_adjust_rxrefclk(phydev);
-
-+ if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
-+ err = bcm54810_config(phydev);
-+ if (err)
-+ return err;
-+ }
-+
- bcm54xx_phydsp_config(phydev);
-
- return 0;
-@@ -314,6 +348,7 @@ static int bcm5482_read_status(struct ph
-
- static int bcm5481_config_aneg(struct phy_device *phydev)
- {
-+ struct device_node *np = phydev->mdio.dev.of_node;
- int ret;
-
- /* Aneg firsly. */
-@@ -344,6 +379,14 @@ static int bcm5481_config_aneg(struct ph
- phy_write(phydev, 0x18, reg);
- }
-
-+ if (of_property_read_bool(np, "enet-phy-lane-swap")) {
-+ /* Lane Swap - Undocumented register...magic! */
-+ ret = bcm_phy_write_exp(phydev, MII_BCM54XX_EXP_SEL_ER + 0x9,
-+ 0x11B);
-+ if (ret < 0)
-+ return ret;
-+ }
-+
- return ret;
- }
-
-@@ -578,6 +621,18 @@ static struct phy_driver broadcom_driver
- .ack_interrupt = bcm_phy_ack_intr,
- .config_intr = bcm_phy_config_intr,
- }, {
-+ .phy_id = PHY_ID_BCM54810,
-+ .phy_id_mask = 0xfffffff0,
-+ .name = "Broadcom BCM54810",
-+ .features = PHY_GBIT_FEATURES |
-+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
-+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-+ .config_init = bcm54xx_config_init,
-+ .config_aneg = bcm5481_config_aneg,
-+ .read_status = genphy_read_status,
-+ .ack_interrupt = bcm_phy_ack_intr,
-+ .config_intr = bcm_phy_config_intr,
-+}, {
- .phy_id = PHY_ID_BCM5482,
- .phy_id_mask = 0xfffffff0,
- .name = "Broadcom BCM5482",
-@@ -661,6 +716,7 @@ static struct mdio_device_id __maybe_unu
- { PHY_ID_BCM54616S, 0xfffffff0 },
- { PHY_ID_BCM5464, 0xfffffff0 },
- { PHY_ID_BCM5481, 0xfffffff0 },
-+ { PHY_ID_BCM54810, 0xfffffff0 },
- { PHY_ID_BCM5482, 0xfffffff0 },
- { PHY_ID_BCM50610, 0xfffffff0 },
- { PHY_ID_BCM50610M, 0xfffffff0 },
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -204,7 +204,7 @@ config BROADCOM_PHY
- select BCM_NET_PHYLIB
- ---help---
- Currently supports the BCM5411, BCM5421, BCM5461, BCM54616S, BCM5464,
-- BCM5481 and BCM5482 PHYs.
-+ BCM5481, BCM54810 and BCM5482 PHYs.
-
- config CICADA_PHY
- tristate "Cicada PHYs"
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -13,6 +13,7 @@
- #define PHY_ID_BCM5241 0x0143bc30
- #define PHY_ID_BCMAC131 0x0143bc70
- #define PHY_ID_BCM5481 0x0143bca0
-+#define PHY_ID_BCM54810 0x03625d00
- #define PHY_ID_BCM5482 0x0143bcb0
- #define PHY_ID_BCM5411 0x00206070
- #define PHY_ID_BCM5421 0x002060e0
-@@ -56,6 +57,7 @@
- #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000
- #define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000
- #define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000
-+
- /* Broadcom BCM7xxx specific workarounds */
- #define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff)
- #define PHY_BRCM_7XXX_PATCH(x) ((x) & 0xff)
-@@ -111,6 +113,7 @@
- #define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
- #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
- #define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
-+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN (1 << 8)
-
- #define MII_BCM54XX_AUXCTL_SHDWSEL_MASK 0x0007
-
-@@ -192,6 +195,12 @@
- #define BCM5482_SSD_SGMII_SLAVE_EN 0x0002 /* Slave mode enable */
- #define BCM5482_SSD_SGMII_SLAVE_AD 0x0001 /* Slave auto-detection */
-
-+/* BCM54810 Registers */
-+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL (MII_BCM54XX_EXP_SEL_ER + 0x90)
-+#define BCM54810_EXP_BROADREACH_LRE_MISC_CTL_EN (1 << 0)
-+#define BCM54810_SHD_CLK_CTL 0x3
-+#define BCM54810_SHD_CLK_CTL_GTXCLK_EN (1 << 9)
-+
-
- /*****************************************************************************/
- /* Fast Ethernet Transceiver definitions. */
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Date: Tue, 22 Nov 2016 11:40:54 -0800
-Subject: [PATCH] net: phy: broadcom: Move bcm54xx_auxctl_{read, write} to
- common library
-
-We are going to need these functions to implement support for Broadcom
-Wirespeed, aka downshift.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/bcm-phy-lib.c
-+++ b/drivers/net/phy/bcm-phy-lib.c
-@@ -50,6 +50,23 @@ int bcm_phy_read_exp(struct phy_device *
- }
- EXPORT_SYMBOL_GPL(bcm_phy_read_exp);
-
-+int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
-+{
-+ /* The register must be written to both the Shadow Register Select and
-+ * the Shadow Read Register Selector
-+ */
-+ phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum |
-+ regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT);
-+ return phy_read(phydev, MII_BCM54XX_AUX_CTL);
-+}
-+EXPORT_SYMBOL_GPL(bcm54xx_auxctl_read);
-+
-+int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
-+{
-+ return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
-+}
-+EXPORT_SYMBOL(bcm54xx_auxctl_write);
-+
- int bcm_phy_write_misc(struct phy_device *phydev,
- u16 reg, u16 chl, u16 val)
- {
---- a/drivers/net/phy/bcm-phy-lib.h
-+++ b/drivers/net/phy/bcm-phy-lib.h
-@@ -19,6 +19,9 @@
- int bcm_phy_write_exp(struct phy_device *phydev, u16 reg, u16 val);
- int bcm_phy_read_exp(struct phy_device *phydev, u16 reg);
-
-+int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val);
-+int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum);
-+
- int bcm_phy_write_misc(struct phy_device *phydev,
- u16 reg, u16 chl, u16 value);
- int bcm_phy_read_misc(struct phy_device *phydev,
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -30,21 +30,6 @@ MODULE_DESCRIPTION("Broadcom PHY driver"
- MODULE_AUTHOR("Maciej W. Rozycki");
- MODULE_LICENSE("GPL");
-
--static int bcm54xx_auxctl_read(struct phy_device *phydev, u16 regnum)
--{
-- /* The register must be written to both the Shadow Register Select and
-- * the Shadow Read Register Selector
-- */
-- phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum |
-- regnum << MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT);
-- return phy_read(phydev, MII_BCM54XX_AUX_CTL);
--}
--
--static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
--{
-- return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
--}
--
- static int bcm54810_config(struct phy_device *phydev)
- {
- int rc, val;
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Date: Tue, 22 Nov 2016 11:40:56 -0800
-Subject: [PATCH] net: phy: broadcom: Allow enabling or disabling of EEE
-
-In preparation for adding support for Wirespeed/downshift, we need to
-change bcm_phy_eee_enable() to allow enabling or disabling EEE, so make
-the function take an extra enable/disable boolean parameter and rename
-it to illustrate it sets EEE, not necessarily just enables it.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/bcm7xxx.c
-+++ b/drivers/net/phy/bcm7xxx.c
-@@ -199,7 +199,7 @@ static int bcm7xxx_28nm_config_init(stru
- if (ret)
- return ret;
-
-- ret = bcm_phy_enable_eee(phydev);
-+ ret = bcm_phy_set_eee(phydev, true);
- if (ret)
- return ret;
-
---- a/drivers/net/phy/bcm-cygnus.c
-+++ b/drivers/net/phy/bcm-cygnus.c
-@@ -104,7 +104,7 @@ static int bcm_cygnus_config_init(struct
- return rc;
-
- /* Advertise EEE */
-- rc = bcm_phy_enable_eee(phydev);
-+ rc = bcm_phy_set_eee(phydev, true);
- if (rc)
- return rc;
-
---- a/drivers/net/phy/bcm-phy-lib.c
-+++ b/drivers/net/phy/bcm-phy-lib.c
-@@ -195,7 +195,7 @@ int bcm_phy_enable_apd(struct phy_device
- }
- EXPORT_SYMBOL_GPL(bcm_phy_enable_apd);
-
--int bcm_phy_enable_eee(struct phy_device *phydev)
-+int bcm_phy_set_eee(struct phy_device *phydev, bool enable)
- {
- int val;
-
-@@ -205,7 +205,10 @@ int bcm_phy_enable_eee(struct phy_device
- if (val < 0)
- return val;
-
-- val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
-+ if (enable)
-+ val |= LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X;
-+ else
-+ val &= ~(LPI_FEATURE_EN | LPI_FEATURE_EN_DIG1000X);
-
- phy_write_mmd_indirect(phydev, BRCM_CL45VEN_EEE_CONTROL,
- MDIO_MMD_AN, (u32)val);
-@@ -216,14 +219,17 @@ int bcm_phy_enable_eee(struct phy_device
- if (val < 0)
- return val;
-
-- val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
-+ if (enable)
-+ val |= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
-+ else
-+ val &= ~(MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
-
- phy_write_mmd_indirect(phydev, BCM_CL45VEN_EEE_ADV,
- MDIO_MMD_AN, (u32)val);
-
- return 0;
- }
--EXPORT_SYMBOL_GPL(bcm_phy_enable_eee);
-+EXPORT_SYMBOL_GPL(bcm_phy_set_eee);
-
- MODULE_DESCRIPTION("Broadcom PHY Library");
- MODULE_LICENSE("GPL v2");
---- a/drivers/net/phy/bcm-phy-lib.h
-+++ b/drivers/net/phy/bcm-phy-lib.h
-@@ -36,5 +36,5 @@ int bcm_phy_config_intr(struct phy_devic
-
- int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
-
--int bcm_phy_enable_eee(struct phy_device *phydev);
-+int bcm_phy_set_eee(struct phy_device *phydev, bool enable);
- #endif /* _LINUX_BCM_PHY_LIB_H */
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Date: Tue, 29 Nov 2016 09:57:17 -0800
-Subject: [PATCH] net: phy: broadcom: Add support code for reading PHY counters
-
-Broadcom PHYs expose a number of PHY error counters: receive errors,
-false carrier sense, SerDes BER count, local and remote receive errors.
-Add support code to allow retrieving these error counters. Since the
-Broadcom PHY library code is used by several drivers, make it possible
-for them to specify the storage for the software copy of the statistics.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/bcm-phy-lib.c
-+++ b/drivers/net/phy/bcm-phy-lib.c
-@@ -17,6 +17,7 @@
- #include <linux/mdio.h>
- #include <linux/module.h>
- #include <linux/phy.h>
-+#include <linux/ethtool.h>
-
- #define MII_BCM_CHANNEL_WIDTH 0x2000
- #define BCM_CL45VEN_EEE_ADV 0x3c
-@@ -231,6 +232,75 @@ int bcm_phy_set_eee(struct phy_device *p
- }
- EXPORT_SYMBOL_GPL(bcm_phy_set_eee);
-
-+struct bcm_phy_hw_stat {
-+ const char *string;
-+ u8 reg;
-+ u8 shift;
-+ u8 bits;
-+};
-+
-+/* Counters freeze at either 0xffff or 0xff, better than nothing */
-+static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = {
-+ { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 },
-+ { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 },
-+ { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 },
-+ { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 },
-+ { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 },
-+};
-+
-+int bcm_phy_get_sset_count(struct phy_device *phydev)
-+{
-+ return ARRAY_SIZE(bcm_phy_hw_stats);
-+}
-+EXPORT_SYMBOL_GPL(bcm_phy_get_sset_count);
-+
-+void bcm_phy_get_strings(struct phy_device *phydev, u8 *data)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
-+ memcpy(data + i * ETH_GSTRING_LEN,
-+ bcm_phy_hw_stats[i].string, ETH_GSTRING_LEN);
-+}
-+EXPORT_SYMBOL_GPL(bcm_phy_get_strings);
-+
-+#ifndef UINT64_MAX
-+#define UINT64_MAX (u64)(~((u64)0))
-+#endif
-+
-+/* Caller is supposed to provide appropriate storage for the library code to
-+ * access the shadow copy
-+ */
-+static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow,
-+ unsigned int i)
-+{
-+ struct bcm_phy_hw_stat stat = bcm_phy_hw_stats[i];
-+ int val;
-+ u64 ret;
-+
-+ val = phy_read(phydev, stat.reg);
-+ if (val < 0) {
-+ ret = UINT64_MAX;
-+ } else {
-+ val >>= stat.shift;
-+ val = val & ((1 << stat.bits) - 1);
-+ shadow[i] += val;
-+ ret = shadow[i];
-+ }
-+
-+ return ret;
-+}
-+
-+void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
-+ struct ethtool_stats *stats, u64 *data)
-+{
-+ unsigned int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
-+ data[i] = bcm_phy_get_stat(phydev, shadow, i);
-+}
-+EXPORT_SYMBOL_GPL(bcm_phy_get_stats);
-+
- MODULE_DESCRIPTION("Broadcom PHY Library");
- MODULE_LICENSE("GPL v2");
- MODULE_AUTHOR("Broadcom Corporation");
---- a/drivers/net/phy/bcm-phy-lib.h
-+++ b/drivers/net/phy/bcm-phy-lib.h
-@@ -37,4 +37,10 @@ int bcm_phy_config_intr(struct phy_devic
- int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down);
-
- int bcm_phy_set_eee(struct phy_device *phydev, bool enable);
-+
-+int bcm_phy_get_sset_count(struct phy_device *phydev);
-+void bcm_phy_get_strings(struct phy_device *phydev, u8 *data);
-+void bcm_phy_get_stats(struct phy_device *phydev, u64 *shadow,
-+ struct ethtool_stats *stats, u64 *data);
-+
- #endif /* _LINUX_BCM_PHY_LIB_H */
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -234,6 +234,9 @@
- #define LPI_FEATURE_EN_DIG1000X 0x4000
-
- /* Core register definitions*/
-+#define MII_BRCM_CORE_BASE12 0x12
-+#define MII_BRCM_CORE_BASE13 0x13
-+#define MII_BRCM_CORE_BASE14 0x14
- #define MII_BRCM_CORE_BASE1E 0x1E
- #define MII_BRCM_CORE_EXPB0 0xB0
- #define MII_BRCM_CORE_EXPB1 0xB1
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Date: Fri, 20 Jan 2017 12:36:33 -0800
-Subject: [PATCH] net: phy: bcm7xxx: Add entry for BCM7278
-
-Add support for the BCM7278 28nm process Gigabit Ethernet PHY.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/bcm7xxx.c
-+++ b/drivers/net/phy/bcm7xxx.c
-@@ -334,6 +334,7 @@ static int bcm7xxx_suspend(struct phy_de
-
- static struct phy_driver bcm7xxx_driver[] = {
- BCM7XXX_28NM_GPHY(PHY_ID_BCM7250, "Broadcom BCM7250"),
-+ BCM7XXX_28NM_GPHY(PHY_ID_BCM7278, "Broadcom BCM7278"),
- BCM7XXX_28NM_GPHY(PHY_ID_BCM7364, "Broadcom BCM7364"),
- BCM7XXX_28NM_GPHY(PHY_ID_BCM7366, "Broadcom BCM7366"),
- BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"),
-@@ -348,6 +349,7 @@ static struct phy_driver bcm7xxx_driver[
-
- static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = {
- { PHY_ID_BCM7250, 0xfffffff0, },
-+ { PHY_ID_BCM7278, 0xfffffff0, },
- { PHY_ID_BCM7364, 0xfffffff0, },
- { PHY_ID_BCM7366, 0xfffffff0, },
- { PHY_ID_BCM7346, 0xfffffff0, },
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -24,6 +24,7 @@
- #define PHY_ID_BCM57780 0x03625d90
-
- #define PHY_ID_BCM7250 0xae025280
-+#define PHY_ID_BCM7278 0xae0251a0
- #define PHY_ID_BCM7364 0xae025260
- #define PHY_ID_BCM7366 0x600d8490
- #define PHY_ID_BCM7346 0x600d8650
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Date: Fri, 20 Jan 2017 12:36:34 -0800
-Subject: [PATCH] net: phy: bcm7xxx: Implement EGPHY workaround for 7278
-
-Implement the HW design team recommended workaround in for 7278. Since
-the GPHY now returns its revision information in MII_PHYS_ID[23] we need
-to check whether the revision provided in flags is 0 or not.
-
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/bcm7xxx.c
-+++ b/drivers/net/phy/bcm7xxx.c
-@@ -163,12 +163,43 @@ static int bcm7xxx_28nm_e0_plus_afe_conf
- return 0;
- }
-
-+static int bcm7xxx_28nm_a0_patch_afe_config_init(struct phy_device *phydev)
-+{
-+ /* +1 RC_CAL codes for RL centering for both LT and HT conditions */
-+ bcm_phy_write_misc(phydev, AFE_RXCONFIG_2, 0xd003);
-+
-+ /* Cut master bias current by 2% to compensate for RC_CAL offset */
-+ bcm_phy_write_misc(phydev, DSP_TAP10, 0x791b);
-+
-+ /* Improve hybrid leakage */
-+ bcm_phy_write_misc(phydev, AFE_HPF_TRIM_OTHERS, 0x10e3);
-+
-+ /* Change rx_on_tune 8 to 0xf */
-+ bcm_phy_write_misc(phydev, 0x21, 0x2, 0x87f6);
-+
-+ /* Change 100Tx EEE bandwidth */
-+ bcm_phy_write_misc(phydev, 0x22, 0x2, 0x017d);
-+
-+ /* Enable ffe zero detection for Vitesse interoperability */
-+ bcm_phy_write_misc(phydev, 0x26, 0x2, 0x0015);
-+
-+ r_rc_cal_reset(phydev);
-+
-+ return 0;
-+}
-+
- static int bcm7xxx_28nm_config_init(struct phy_device *phydev)
- {
- u8 rev = PHY_BRCM_7XXX_REV(phydev->dev_flags);
- u8 patch = PHY_BRCM_7XXX_PATCH(phydev->dev_flags);
- int ret = 0;
-
-+ /* Newer devices have moved the revision information back into a
-+ * standard location in MII_PHYS_ID[23]
-+ */
-+ if (rev == 0)
-+ rev = phydev->phy_id & ~phydev->drv->phy_id_mask;
-+
- pr_info_once("%s: %s PHY revision: 0x%02x, patch: %d\n",
- phydev_name(phydev), phydev->drv->name, rev, patch);
-
-@@ -192,6 +223,9 @@ static int bcm7xxx_28nm_config_init(stru
- case 0x10:
- ret = bcm7xxx_28nm_e0_plus_afe_config_init(phydev);
- break;
-+ case 0x01:
-+ ret = bcm7xxx_28nm_a0_patch_afe_config_init(phydev);
-+ break;
- default:
- break;
- }
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Wed, 25 Jan 2017 21:00:25 +0100
-Subject: [PATCH] net: phy: broadcom: use auxctl reading helper in BCM54612E
- code
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Starting with commit 5b4e29005123 ("net: phy: broadcom: add
-bcm54xx_auxctl_read") we have a reading helper so use it and avoid code
-duplication.
-It also means we don't need MII_BCM54XX_AUXCTL_SHDWSEL_MISC define as
-it's the same as MII_BCM54XX_AUXCTL_SHDWSEL_MISC just for reading needs
-(same value shifted by 12 bits).
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -395,10 +395,8 @@ static int bcm54612e_config_aneg(struct
- (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
- u16 reg;
-
-- /* Errata: reads require filling in the write selector field */
-- bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
-- MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC);
-- reg = phy_read(phydev, MII_BCM54XX_AUX_CTL);
-+ reg = bcm54xx_auxctl_read(phydev,
-+ MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
- /* Disable RXD to RXC delay (default set) */
- reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
- /* Clear shadow selector field */
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -111,7 +111,6 @@
-
- #define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000
- #define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200
--#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
- #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
- #define MII_BCM54XX_AUXCTL_SHDWSEL_READ_SHIFT 12
- #define MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN (1 << 8)
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Fri, 27 Jan 2017 14:07:01 +0100
-Subject: [PATCH] net: phy: broadcom: add support for BCM54210E
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-It's Broadcom PHY simply described as single-port
-RGMII 10/100/1000BASE-T PHY. It requires disabling delay skew and GTXCLK
-bits.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -30,6 +30,22 @@ MODULE_DESCRIPTION("Broadcom PHY driver"
- MODULE_AUTHOR("Maciej W. Rozycki");
- MODULE_LICENSE("GPL");
-
-+static int bcm54210e_config_init(struct phy_device *phydev)
-+{
-+ int val;
-+
-+ val = bcm54xx_auxctl_read(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
-+ val &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
-+ val |= MII_BCM54XX_AUXCTL_MISC_WREN;
-+ bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC, val);
-+
-+ val = bcm_phy_read_shadow(phydev, BCM54810_SHD_CLK_CTL);
-+ val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
-+ bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
-+
-+ return 0;
-+}
-+
- static int bcm54810_config(struct phy_device *phydev)
- {
- int rc, val;
-@@ -230,7 +246,11 @@ static int bcm54xx_config_init(struct ph
- (phydev->dev_flags & PHY_BRCM_AUTO_PWRDWN_ENABLE))
- bcm54xx_adjust_rxrefclk(phydev);
-
-- if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
-+ if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54210E) {
-+ err = bcm54210e_config_init(phydev);
-+ if (err)
-+ return err;
-+ } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
- err = bcm54810_config(phydev);
- if (err)
- return err;
-@@ -544,6 +564,17 @@ static struct phy_driver broadcom_driver
- .ack_interrupt = bcm_phy_ack_intr,
- .config_intr = bcm_phy_config_intr,
- }, {
-+ .phy_id = PHY_ID_BCM54210E,
-+ .phy_id_mask = 0xfffffff0,
-+ .name = "Broadcom BCM54210E",
-+ .features = PHY_GBIT_FEATURES,
-+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-+ .config_init = bcm54xx_config_init,
-+ .config_aneg = genphy_config_aneg,
-+ .read_status = genphy_read_status,
-+ .ack_interrupt = bcm_phy_ack_intr,
-+ .config_intr = bcm_phy_config_intr,
-+}, {
- .phy_id = PHY_ID_BCM5461,
- .phy_id_mask = 0xfffffff0,
- .name = "Broadcom BCM5461",
-@@ -694,6 +725,7 @@ module_phy_driver(broadcom_drivers);
- static struct mdio_device_id __maybe_unused broadcom_tbl[] = {
- { PHY_ID_BCM5411, 0xfffffff0 },
- { PHY_ID_BCM5421, 0xfffffff0 },
-+ { PHY_ID_BCM54210E, 0xfffffff0 },
- { PHY_ID_BCM5461, 0xfffffff0 },
- { PHY_ID_BCM54612E, 0xfffffff0 },
- { PHY_ID_BCM54616S, 0xfffffff0 },
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -17,6 +17,7 @@
- #define PHY_ID_BCM5482 0x0143bcb0
- #define PHY_ID_BCM5411 0x00206070
- #define PHY_ID_BCM5421 0x002060e0
-+#define PHY_ID_BCM54210E 0x600d84a0
- #define PHY_ID_BCM5464 0x002060b0
- #define PHY_ID_BCM5461 0x002060c0
- #define PHY_ID_BCM54612E 0x03625e60
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 31 Jan 2017 22:54:54 +0100
-Subject: [PATCH] net: phy: broadcom: rehook BCM54612E specific init
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This extra BCM54612E code in PHY driver isn't really aneg specific. Even
-without it aneg works OK but the problem is no packets pass through PHY.
-
-Moreover putting this code inside config_aneg callback didn't allow
-resuming PHY correctly. When driver called phy_stop and phy_start it was
-putting PHY machine into RESUMING state. After that machine was
-switching into AN and NOLINK without ever calling phy_start_aneg. This
-prevented this extra setup from being called and PHY didn't work.
-
-This change has been verified to fix network on BCM47186B0 SoC device
-with BCM54612E.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -46,6 +46,34 @@ static int bcm54210e_config_init(struct
- return 0;
- }
-
-+static int bcm54612e_config_init(struct phy_device *phydev)
-+{
-+ /* Clear TX internal delay unless requested. */
-+ if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
-+ (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
-+ /* Disable TXD to GTXCLK clock delay (default set) */
-+ /* Bit 9 is the only field in shadow register 00011 */
-+ bcm_phy_write_shadow(phydev, 0x03, 0);
-+ }
-+
-+ /* Clear RX internal delay unless requested. */
-+ if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
-+ (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
-+ u16 reg;
-+
-+ reg = bcm54xx_auxctl_read(phydev,
-+ MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
-+ /* Disable RXD to RXC delay (default set) */
-+ reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MISC_RGMII_SKEW_EN;
-+ /* Clear shadow selector field */
-+ reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
-+ bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
-+ MII_BCM54XX_AUXCTL_MISC_WREN | reg);
-+ }
-+
-+ return 0;
-+}
-+
- static int bcm54810_config(struct phy_device *phydev)
- {
- int rc, val;
-@@ -250,6 +278,10 @@ static int bcm54xx_config_init(struct ph
- err = bcm54210e_config_init(phydev);
- if (err)
- return err;
-+ } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54612E) {
-+ err = bcm54612e_config_init(phydev);
-+ if (err)
-+ return err;
- } else if (BRCM_PHY_MODEL(phydev) == PHY_ID_BCM54810) {
- err = bcm54810_config(phydev);
- if (err)
-@@ -395,39 +427,6 @@ static int bcm5481_config_aneg(struct ph
- return ret;
- }
-
--static int bcm54612e_config_aneg(struct phy_device *phydev)
--{
-- int ret;
--
-- /* First, auto-negotiate. */
-- ret = genphy_config_aneg(phydev);
--
-- /* Clear TX internal delay unless requested. */
-- if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
-- (phydev->interface != PHY_INTERFACE_MODE_RGMII_TXID)) {
-- /* Disable TXD to GTXCLK clock delay (default set) */
-- /* Bit 9 is the only field in shadow register 00011 */
-- bcm_phy_write_shadow(phydev, 0x03, 0);
-- }
--
-- /* Clear RX internal delay unless requested. */
-- if ((phydev->interface != PHY_INTERFACE_MODE_RGMII_ID) &&
-- (phydev->interface != PHY_INTERFACE_MODE_RGMII_RXID)) {
-- u16 reg;
--
-- reg = bcm54xx_auxctl_read(phydev,
-- MII_BCM54XX_AUXCTL_SHDWSEL_MISC);
-- /* Disable RXD to RXC delay (default set) */
-- reg &= ~MII_BCM54XX_AUXCTL_MISC_RXD_RXC_SKEW;
-- /* Clear shadow selector field */
-- reg &= ~MII_BCM54XX_AUXCTL_SHDWSEL_MASK;
-- bcm54xx_auxctl_write(phydev, MII_BCM54XX_AUXCTL_SHDWSEL_MISC,
-- MII_BCM54XX_AUXCTL_MISC_WREN | reg);
-- }
--
-- return ret;
--}
--
- static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)
- {
- int val;
-@@ -594,7 +593,7 @@ static struct phy_driver broadcom_driver
- SUPPORTED_Pause | SUPPORTED_Asym_Pause,
- .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
- .config_init = bcm54xx_config_init,
-- .config_aneg = bcm54612e_config_aneg,
-+ .config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
- .ack_interrupt = bcm_phy_ack_intr,
- .config_intr = bcm_phy_config_intr,
+++ /dev/null
-From 2355a6546a053b1c16ebefd6ce1f0cccc00e1da5 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 12 Oct 2017 10:21:25 +0200
-Subject: [PATCH] net: phy: broadcom: support new device flag for setting
- master mode
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Some of Broadcom's PHYs run by default in slave mode with Automatic
-Slave/Master configuration disabled. It stops them from working properly
-with some devices.
-
-So far it has been verified for BCM54210E and BCM50212E which don't
-work well with Intel's I217-LM and I218-LM:
-http://ark.intel.com/products/60019/Intel-Ethernet-Connection-I217-LM
-http://ark.intel.com/products/71307/Intel-Ethernet-Connection-I218-LM
-I was told there is massive ping loss.
-
-This commit adds support for a new flag which can be set by an ethernet
-driver to fixup PHY setup.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/phy/broadcom.c | 6 ++++++
- include/linux/brcmphy.h | 1 +
- 2 files changed, 7 insertions(+)
-
---- a/drivers/net/phy/broadcom.c
-+++ b/drivers/net/phy/broadcom.c
-@@ -43,6 +43,12 @@ static int bcm54210e_config_init(struct
- val &= ~BCM54810_SHD_CLK_CTL_GTXCLK_EN;
- bcm_phy_write_shadow(phydev, BCM54810_SHD_CLK_CTL, val);
-
-+ if (phydev->dev_flags & PHY_BRCM_EN_MASTER_MODE) {
-+ val = phy_read(phydev, MII_CTRL1000);
-+ val |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
-+ phy_write(phydev, MII_CTRL1000, val);
-+ }
-+
- return 0;
- }
-
---- a/include/linux/brcmphy.h
-+++ b/include/linux/brcmphy.h
-@@ -59,6 +59,7 @@
- #define PHY_BRCM_EXT_IBND_TX_ENABLE 0x00002000
- #define PHY_BRCM_CLEAR_RGMII_MODE 0x00004000
- #define PHY_BRCM_DIS_TXCRXC_NOENRGY 0x00008000
-+#define PHY_BRCM_EN_MASTER_MODE 0x00010000
-
- /* Broadcom BCM7xxx specific workarounds */
- #define PHY_BRCM_7XXX_REV(x) (((x) >> 8) & 0xff)
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 6 Mar 2017 06:19:44 +0100
-Subject: [PATCH] leds: core: add OF variants of LED registering functions
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-These new functions allow passing an additional device_node argument
-that will be internally set for created LED device. Thanks to this LED
-core code and triggers will be able to access DT node for reading extra
-info.
-
-The easiest solution for achieving this was reworking old functions to
-more generic ones & adding simple defines for API compatibility.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
----
- drivers/leds/led-class.c | 26 ++++++++++++++++----------
- include/linux/leds.h | 14 ++++++++++----
- 2 files changed, 26 insertions(+), 14 deletions(-)
-
---- a/drivers/leds/led-class.c
-+++ b/drivers/leds/led-class.c
-@@ -181,11 +181,14 @@ static int led_classdev_next_name(const
- }
-
- /**
-- * led_classdev_register - register a new object of led_classdev class.
-- * @parent: The device to register.
-+ * of_led_classdev_register - register a new object of led_classdev class.
-+ *
-+ * @parent: parent of LED device
- * @led_cdev: the led_classdev structure for this device.
-+ * @np: DT node describing this LED
- */
--int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
-+int of_led_classdev_register(struct device *parent, struct device_node *np,
-+ struct led_classdev *led_cdev)
- {
- char name[64];
- int ret;
-@@ -198,6 +201,7 @@ int led_classdev_register(struct device
- led_cdev, led_cdev->groups, "%s", name);
- if (IS_ERR(led_cdev->dev))
- return PTR_ERR(led_cdev->dev);
-+ led_cdev->dev->of_node = np;
-
- if (ret)
- dev_warn(parent, "Led %s renamed to %s due to name collision",
-@@ -228,7 +232,7 @@ int led_classdev_register(struct device
-
- return 0;
- }
--EXPORT_SYMBOL_GPL(led_classdev_register);
-+EXPORT_SYMBOL_GPL(of_led_classdev_register);
-
- /**
- * led_classdev_unregister - unregisters a object of led_properties class.
-@@ -270,12 +274,14 @@ static void devm_led_classdev_release(st
- }
-
- /**
-- * devm_led_classdev_register - resource managed led_classdev_register()
-- * @parent: The device to register.
-+ * devm_of_led_classdev_register - resource managed led_classdev_register()
-+ *
-+ * @parent: parent of LED device
- * @led_cdev: the led_classdev structure for this device.
- */
--int devm_led_classdev_register(struct device *parent,
-- struct led_classdev *led_cdev)
-+int devm_of_led_classdev_register(struct device *parent,
-+ struct device_node *np,
-+ struct led_classdev *led_cdev)
- {
- struct led_classdev **dr;
- int rc;
-@@ -284,7 +290,7 @@ int devm_led_classdev_register(struct de
- if (!dr)
- return -ENOMEM;
-
-- rc = led_classdev_register(parent, led_cdev);
-+ rc = of_led_classdev_register(parent, np, led_cdev);
- if (rc) {
- devres_free(dr);
- return rc;
-@@ -295,7 +301,7 @@ int devm_led_classdev_register(struct de
-
- return 0;
- }
--EXPORT_SYMBOL_GPL(devm_led_classdev_register);
-+EXPORT_SYMBOL_GPL(devm_of_led_classdev_register);
-
- static int devm_led_classdev_match(struct device *dev, void *res, void *data)
- {
---- a/include/linux/leds.h
-+++ b/include/linux/leds.h
-@@ -109,10 +109,16 @@ struct led_classdev {
- struct mutex led_access;
- };
-
--extern int led_classdev_register(struct device *parent,
-- struct led_classdev *led_cdev);
--extern int devm_led_classdev_register(struct device *parent,
-- struct led_classdev *led_cdev);
-+extern int of_led_classdev_register(struct device *parent,
-+ struct device_node *np,
-+ struct led_classdev *led_cdev);
-+#define led_classdev_register(parent, led_cdev) \
-+ of_led_classdev_register(parent, NULL, led_cdev)
-+extern int devm_of_led_classdev_register(struct device *parent,
-+ struct device_node *np,
-+ struct led_classdev *led_cdev);
-+#define devm_led_classdev_register(parent, led_cdev) \
-+ devm_of_led_classdev_register(parent, NULL, led_cdev)
- extern void led_classdev_unregister(struct led_classdev *led_cdev);
- extern void devm_led_classdev_unregister(struct device *parent,
- struct led_classdev *led_cdev);
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 6 Mar 2017 06:19:45 +0100
-Subject: [PATCH] leds: gpio: use OF variant of LED registering function
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In leds-gpio we support LEDs specified in DT so we should use
-(devm_)of_led_classdev_register. This allows passing DT node as argument
-for use by the LED subsystem.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Acked-by: Pavel Machek <pavel@ucw.cz>
-Signed-off-by: Jacek Anaszewski <jacek.anaszewski@gmail.com>
----
- drivers/leds/leds-gpio.c | 12 ++++++------
- 1 file changed, 6 insertions(+), 6 deletions(-)
-
---- a/drivers/leds/leds-gpio.c
-+++ b/drivers/leds/leds-gpio.c
-@@ -77,7 +77,7 @@ static int gpio_blink_set(struct led_cla
-
- static int create_gpio_led(const struct gpio_led *template,
- struct gpio_led_data *led_dat, struct device *parent,
-- gpio_blink_set_t blink_set)
-+ struct device_node *np, gpio_blink_set_t blink_set)
- {
- int ret, state;
-
-@@ -139,7 +139,7 @@ static int create_gpio_led(const struct
- if (ret < 0)
- return ret;
-
-- return devm_led_classdev_register(parent, &led_dat->cdev);
-+ return devm_of_led_classdev_register(parent, np, &led_dat->cdev);
- }
-
- struct gpio_leds_priv {
-@@ -206,7 +206,7 @@ static struct gpio_leds_priv *gpio_leds_
- if (fwnode_property_present(child, "panic-indicator"))
- led.panic_indicator = 1;
-
-- ret = create_gpio_led(&led, led_dat, dev, NULL);
-+ ret = create_gpio_led(&led, led_dat, dev, np, NULL);
- if (ret < 0) {
- fwnode_handle_put(child);
- return ERR_PTR(ret);
-@@ -240,9 +240,9 @@ static int gpio_led_probe(struct platfor
-
- priv->num_leds = pdata->num_leds;
- for (i = 0; i < priv->num_leds; i++) {
-- ret = create_gpio_led(&pdata->leds[i],
-- &priv->leds[i],
-- &pdev->dev, pdata->gpio_blink_set);
-+ ret = create_gpio_led(&pdata->leds[i], &priv->leds[i],
-+ &pdev->dev, NULL,
-+ pdata->gpio_blink_set);
- if (ret < 0)
- return ret;
- }
+++ /dev/null
-From bcb7dd9ef206f7d646ed8dac6fe7772083714253 Mon Sep 17 00:00:00 2001
-From: Stefan Wahren <stefan.wahren@i2se.com>
-Date: Fri, 31 Mar 2017 20:03:06 +0000
-Subject: [PATCH] thermal: bcm2835: add thermal driver for bcm2835 SoC
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Add basic thermal driver for bcm2835 SoC.
-
-This driver currently make sure that tsense HW block is set up
-correctly.
-
-Tested-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Martin Sperl <kernel@martin.sperl.org>
-Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
-Acked-by: Eric Anholt <eric@anholt.net>
-Acked-by: Eduardo Valentin <edubezval@gmail.com>
-Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
----
- drivers/thermal/Kconfig | 8 +
- drivers/thermal/Makefile | 1 +
- drivers/thermal/bcm2835_thermal.c | 314 ++++++++++++++++++++++++++++++++++++++
- 3 files changed, 323 insertions(+)
- create mode 100644 drivers/thermal/bcm2835_thermal.c
-
---- a/drivers/thermal/Kconfig
-+++ b/drivers/thermal/Kconfig
-@@ -434,4 +434,12 @@ depends on (ARCH_QCOM && OF) || COMPILE_
- source "drivers/thermal/qcom/Kconfig"
- endmenu
-
-+config BCM2835_THERMAL
-+ tristate "Thermal sensors on bcm2835 SoC"
-+ depends on ARCH_BCM2835 || COMPILE_TEST
-+ depends on HAS_IOMEM
-+ depends on THERMAL_OF
-+ help
-+ Support for thermal sensors on Broadcom bcm2835 SoCs.
-+
- endif
---- a/drivers/thermal/Makefile
-+++ b/drivers/thermal/Makefile
-@@ -55,3 +55,4 @@ obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
- obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
- obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
- obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
-+obj-$(CONFIG_BCM2835_THERMAL) += bcm2835_thermal.o
---- /dev/null
-+++ b/drivers/thermal/bcm2835_thermal.c
-@@ -0,0 +1,314 @@
-+/*
-+ * Driver for Broadcom BCM2835 SoC temperature sensor
-+ *
-+ * Copyright (C) 2016 Martin Sperl
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/debugfs.h>
-+#include <linux/device.h>
-+#include <linux/err.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/thermal.h>
-+
-+#define BCM2835_TS_TSENSCTL 0x00
-+#define BCM2835_TS_TSENSSTAT 0x04
-+
-+#define BCM2835_TS_TSENSCTL_PRWDW BIT(0)
-+#define BCM2835_TS_TSENSCTL_RSTB BIT(1)
-+
-+/*
-+ * bandgap reference voltage in 6 mV increments
-+ * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
-+ */
-+#define BCM2835_TS_TSENSCTL_CTRL_BITS 3
-+#define BCM2835_TS_TSENSCTL_CTRL_SHIFT 2
-+#define BCM2835_TS_TSENSCTL_CTRL_MASK \
-+ GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \
-+ BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
-+ BCM2835_TS_TSENSCTL_CTRL_SHIFT)
-+#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 1
-+#define BCM2835_TS_TSENSCTL_EN_INT BIT(5)
-+#define BCM2835_TS_TSENSCTL_DIRECT BIT(6)
-+#define BCM2835_TS_TSENSCTL_CLR_INT BIT(7)
-+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT 8
-+#define BCM2835_TS_TSENSCTL_THOLD_BITS 10
-+#define BCM2835_TS_TSENSCTL_THOLD_MASK \
-+ GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \
-+ BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
-+ BCM2835_TS_TSENSCTL_THOLD_SHIFT)
-+/*
-+ * time how long the block to be asserted in reset
-+ * which based on a clock counter (TSENS clock assumed)
-+ */
-+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 18
-+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 8
-+#define BCM2835_TS_TSENSCTL_REGULEN BIT(26)
-+
-+#define BCM2835_TS_TSENSSTAT_DATA_BITS 10
-+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT 0
-+#define BCM2835_TS_TSENSSTAT_DATA_MASK \
-+ GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \
-+ BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
-+ BCM2835_TS_TSENSSTAT_DATA_SHIFT)
-+#define BCM2835_TS_TSENSSTAT_VALID BIT(10)
-+#define BCM2835_TS_TSENSSTAT_INTERRUPT BIT(11)
-+
-+struct bcm2835_thermal_data {
-+ struct thermal_zone_device *tz;
-+ void __iomem *regs;
-+ struct clk *clk;
-+ struct dentry *debugfsdir;
-+};
-+
-+static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope)
-+{
-+ return offset + slope * adc;
-+}
-+
-+static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
-+{
-+ temp -= offset;
-+ temp /= slope;
-+
-+ if (temp < 0)
-+ temp = 0;
-+ if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
-+ temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
-+
-+ return temp;
-+}
-+
-+static int bcm2835_thermal_get_temp(void *d, int *temp)
-+{
-+ struct bcm2835_thermal_data *data = d;
-+ u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
-+
-+ if (!(val & BCM2835_TS_TSENSSTAT_VALID))
-+ return -EIO;
-+
-+ val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
-+
-+ *temp = bcm2835_thermal_adc2temp(
-+ val,
-+ thermal_zone_get_offset(data->tz),
-+ thermal_zone_get_slope(data->tz));
-+
-+ return 0;
-+}
-+
-+static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
-+ {
-+ .name = "ctl",
-+ .offset = 0
-+ },
-+ {
-+ .name = "stat",
-+ .offset = 4
-+ }
-+};
-+
-+static void bcm2835_thermal_debugfs(struct platform_device *pdev)
-+{
-+ struct thermal_zone_device *tz = platform_get_drvdata(pdev);
-+ struct bcm2835_thermal_data *data = tz->devdata;
-+ struct debugfs_regset32 *regset;
-+
-+ data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
-+ if (!data->debugfsdir)
-+ return;
-+
-+ regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
-+ if (!regset)
-+ return;
-+
-+ regset->regs = bcm2835_thermal_regs;
-+ regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
-+ regset->base = data->regs;
-+
-+ debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);
-+}
-+
-+static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
-+ .get_temp = bcm2835_thermal_get_temp,
-+};
-+
-+/*
-+ * Note: as per Raspberry Foundation FAQ
-+ * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
-+ * the recommended temperature range for the SoC -40C to +85C
-+ * so the trip limit is set to 80C.
-+ * this applies to all the BCM283X SoC
-+ */
-+
-+static const struct of_device_id bcm2835_thermal_of_match_table[] = {
-+ {
-+ .compatible = "brcm,bcm2835-thermal",
-+ },
-+ {
-+ .compatible = "brcm,bcm2836-thermal",
-+ },
-+ {
-+ .compatible = "brcm,bcm2837-thermal",
-+ },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
-+
-+static int bcm2835_thermal_probe(struct platform_device *pdev)
-+{
-+ const struct of_device_id *match;
-+ struct thermal_zone_device *tz;
-+ struct bcm2835_thermal_data *data;
-+ struct resource *res;
-+ int err = 0;
-+ u32 val;
-+ unsigned long rate;
-+
-+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-+ if (!data)
-+ return -ENOMEM;
-+
-+ match = of_match_device(bcm2835_thermal_of_match_table,
-+ &pdev->dev);
-+ if (!match)
-+ return -EINVAL;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ data->regs = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(data->regs)) {
-+ err = PTR_ERR(data->regs);
-+ dev_err(&pdev->dev, "Could not get registers: %d\n", err);
-+ return err;
-+ }
-+
-+ data->clk = devm_clk_get(&pdev->dev, NULL);
-+ if (IS_ERR(data->clk)) {
-+ err = PTR_ERR(data->clk);
-+ if (err != -EPROBE_DEFER)
-+ dev_err(&pdev->dev, "Could not get clk: %d\n", err);
-+ return err;
-+ }
-+
-+ err = clk_prepare_enable(data->clk);
-+ if (err)
-+ return err;
-+
-+ rate = clk_get_rate(data->clk);
-+ if ((rate < 1920000) || (rate > 5000000))
-+ dev_warn(&pdev->dev,
-+ "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n",
-+ data->clk, data->clk);
-+
-+ /* register of thermal sensor and get info from DT */
-+ tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
-+ &bcm2835_thermal_ops);
-+ if (IS_ERR(tz)) {
-+ err = PTR_ERR(tz);
-+ dev_err(&pdev->dev,
-+ "Failed to register the thermal device: %d\n",
-+ err);
-+ goto err_clk;
-+ }
-+
-+ /*
-+ * right now the FW does set up the HW-block, so we are not
-+ * touching the configuration registers.
-+ * But if the HW is not enabled, then set it up
-+ * using "sane" values used by the firmware right now.
-+ */
-+ val = readl(data->regs + BCM2835_TS_TSENSCTL);
-+ if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
-+ int trip_temp, offset, slope;
-+
-+ slope = thermal_zone_get_slope(tz);
-+ offset = thermal_zone_get_offset(tz);
-+ /*
-+ * For now we deal only with critical, otherwise
-+ * would need to iterate
-+ */
-+ err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
-+ if (err < 0) {
-+ err = PTR_ERR(tz);
-+ dev_err(&pdev->dev,
-+ "Not able to read trip_temp: %d\n",
-+ err);
-+ goto err_tz;
-+ }
-+
-+ /* set bandgap reference voltage and enable voltage regulator */
-+ val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
-+ BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
-+ BCM2835_TS_TSENSCTL_REGULEN;
-+
-+ /* use the recommended reset duration */
-+ val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
-+
-+ /* trip_adc value from info */
-+ val |= bcm2835_thermal_temp2adc(trip_temp,
-+ offset,
-+ slope)
-+ << BCM2835_TS_TSENSCTL_THOLD_SHIFT;
-+
-+ /* write the value back to the register as 2 steps */
-+ writel(val, data->regs + BCM2835_TS_TSENSCTL);
-+ val |= BCM2835_TS_TSENSCTL_RSTB;
-+ writel(val, data->regs + BCM2835_TS_TSENSCTL);
-+ }
-+
-+ data->tz = tz;
-+
-+ platform_set_drvdata(pdev, tz);
-+
-+ bcm2835_thermal_debugfs(pdev);
-+
-+ return 0;
-+err_tz:
-+ thermal_zone_of_sensor_unregister(&pdev->dev, tz);
-+err_clk:
-+ clk_disable_unprepare(data->clk);
-+
-+ return err;
-+}
-+
-+static int bcm2835_thermal_remove(struct platform_device *pdev)
-+{
-+ struct thermal_zone_device *tz = platform_get_drvdata(pdev);
-+ struct bcm2835_thermal_data *data = tz->devdata;
-+
-+ debugfs_remove_recursive(data->debugfsdir);
-+ thermal_zone_of_sensor_unregister(&pdev->dev, tz);
-+ clk_disable_unprepare(data->clk);
-+
-+ return 0;
-+}
-+
-+static struct platform_driver bcm2835_thermal_driver = {
-+ .probe = bcm2835_thermal_probe,
-+ .remove = bcm2835_thermal_remove,
-+ .driver = {
-+ .name = "bcm2835_thermal",
-+ .of_match_table = bcm2835_thermal_of_match_table,
-+ },
-+};
-+module_platform_driver(bcm2835_thermal_driver);
-+
-+MODULE_AUTHOR("Martin Sperl");
-+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
-+MODULE_LICENSE("GPL");
+++ /dev/null
-From a94cb7eeecc4104a6874339f90c5d0647359c102 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Mon, 3 Apr 2017 17:48:29 +0200
-Subject: [PATCH] thermal: broadcom: add Northstar thermal driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Northstar is a SoC family commonly used in home routers. This commit
-adds a driver for checking CPU temperature. As Northstar Plus seems to
-also have this IP block this new symbol gets ARCH_BCM_IPROC dependency.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Jon Mason <jon.mason@broadcom.com>
-Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
----
- drivers/thermal/Kconfig | 5 ++
- drivers/thermal/Makefile | 1 +
- drivers/thermal/broadcom/Kconfig | 8 +++
- drivers/thermal/broadcom/Makefile | 1 +
- drivers/thermal/broadcom/ns-thermal.c | 105 ++++++++++++++++++++++++++++++++++
- 5 files changed, 120 insertions(+)
- create mode 100644 drivers/thermal/broadcom/Kconfig
- create mode 100644 drivers/thermal/broadcom/Makefile
- create mode 100644 drivers/thermal/broadcom/ns-thermal.c
-
---- a/drivers/thermal/Kconfig
-+++ b/drivers/thermal/Kconfig
-@@ -381,6 +381,11 @@ config MTK_THERMAL
- Enable this option if you want to have support for thermal management
- controller present in Mediatek SoCs
-
-+menu "Broadcom thermal drivers"
-+depends on ARCH_BCM || COMPILE_TEST
-+source "drivers/thermal/broadcom/Kconfig"
-+endmenu
-+
- menu "Texas Instruments thermal drivers"
- depends on ARCH_HAS_BANDGAP || COMPILE_TEST
- depends on HAS_IOMEM
---- a/drivers/thermal/Makefile
-+++ b/drivers/thermal/Makefile
-@@ -26,6 +26,7 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL) += c
- thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
-
- # platform thermal drivers
-+obj-y += broadcom/
- obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM) += qcom-spmi-temp-alarm.o
- obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
- obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
---- /dev/null
-+++ b/drivers/thermal/broadcom/Kconfig
-@@ -0,0 +1,8 @@
-+config BCM_NS_THERMAL
-+ tristate "Northstar thermal driver"
-+ depends on ARCH_BCM_IPROC || COMPILE_TEST
-+ help
-+ Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
-+ BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
-+ with a thermal sensor that allows checking CPU temperature. This
-+ driver provides support for it.
---- /dev/null
-+++ b/drivers/thermal/broadcom/Makefile
-@@ -0,0 +1 @@
-+obj-$(CONFIG_BCM_NS_THERMAL) += ns-thermal.o
---- /dev/null
-+++ b/drivers/thermal/broadcom/ns-thermal.c
-@@ -0,0 +1,105 @@
-+/*
-+ * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License version 2 as
-+ * published by the Free Software Foundation.
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/of_address.h>
-+#include <linux/platform_device.h>
-+#include <linux/thermal.h>
-+
-+#define PVTMON_CONTROL0 0x00
-+#define PVTMON_CONTROL0_SEL_MASK 0x0000000e
-+#define PVTMON_CONTROL0_SEL_TEMP_MONITOR 0x00000000
-+#define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e
-+#define PVTMON_STATUS 0x08
-+
-+struct ns_thermal {
-+ struct thermal_zone_device *tz;
-+ void __iomem *pvtmon;
-+};
-+
-+static int ns_thermal_get_temp(void *data, int *temp)
-+{
-+ struct ns_thermal *ns_thermal = data;
-+ int offset = thermal_zone_get_offset(ns_thermal->tz);
-+ int slope = thermal_zone_get_slope(ns_thermal->tz);
-+ u32 val;
-+
-+ val = readl(ns_thermal->pvtmon + PVTMON_CONTROL0);
-+ if ((val & PVTMON_CONTROL0_SEL_MASK) != PVTMON_CONTROL0_SEL_TEMP_MONITOR) {
-+ /* Clear current mode selection */
-+ val &= ~PVTMON_CONTROL0_SEL_MASK;
-+
-+ /* Set temp monitor mode (it's the default actually) */
-+ val |= PVTMON_CONTROL0_SEL_TEMP_MONITOR;
-+
-+ writel(val, ns_thermal->pvtmon + PVTMON_CONTROL0);
-+ }
-+
-+ val = readl(ns_thermal->pvtmon + PVTMON_STATUS);
-+ *temp = slope * val + offset;
-+
-+ return 0;
-+}
-+
-+static const struct thermal_zone_of_device_ops ns_thermal_ops = {
-+ .get_temp = ns_thermal_get_temp,
-+};
-+
-+static int ns_thermal_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct ns_thermal *ns_thermal;
-+
-+ ns_thermal = devm_kzalloc(dev, sizeof(*ns_thermal), GFP_KERNEL);
-+ if (!ns_thermal)
-+ return -ENOMEM;
-+
-+ ns_thermal->pvtmon = of_iomap(dev_of_node(dev), 0);
-+ if (WARN_ON(!ns_thermal->pvtmon))
-+ return -ENOENT;
-+
-+ ns_thermal->tz = devm_thermal_zone_of_sensor_register(dev, 0,
-+ ns_thermal,
-+ &ns_thermal_ops);
-+ if (IS_ERR(ns_thermal->tz)) {
-+ iounmap(ns_thermal->pvtmon);
-+ return PTR_ERR(ns_thermal->tz);
-+ }
-+
-+ platform_set_drvdata(pdev, ns_thermal);
-+
-+ return 0;
-+}
-+
-+static int ns_thermal_remove(struct platform_device *pdev)
-+{
-+ struct ns_thermal *ns_thermal = platform_get_drvdata(pdev);
-+
-+ iounmap(ns_thermal->pvtmon);
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id ns_thermal_of_match[] = {
-+ { .compatible = "brcm,ns-thermal", },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, ns_thermal_of_match);
-+
-+static struct platform_driver ns_thermal_driver = {
-+ .probe = ns_thermal_probe,
-+ .remove = ns_thermal_remove,
-+ .driver = {
-+ .name = "ns-thermal",
-+ .of_match_table = ns_thermal_of_match,
-+ },
-+};
-+module_platform_driver(ns_thermal_driver);
-+
-+MODULE_DESCRIPTION("Northstar thermal driver");
-+MODULE_LICENSE("GPL v2");
+++ /dev/null
-From 4f04c210d031667e503d6538a72345a36f3b5d71 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 8 Jun 2017 18:08:32 +0200
-Subject: [PATCH] usb: core: read USB ports from DT in the usbport LED trigger
- driver
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This uses DT info to read relation description of LEDs and USB ports. If
-DT has properly described LEDs, trigger will know when to turn them on.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- drivers/usb/core/ledtrig-usbport.c | 56 ++++++++++++++++++++++++++++++++++++++
- 1 file changed, 56 insertions(+)
-
---- a/drivers/usb/core/ledtrig-usbport.c
-+++ b/drivers/usb/core/ledtrig-usbport.c
-@@ -11,8 +11,10 @@
- #include <linux/device.h>
- #include <linux/leds.h>
- #include <linux/module.h>
-+#include <linux/of.h>
- #include <linux/slab.h>
- #include <linux/usb.h>
-+#include <linux/usb/of.h>
-
- struct usbport_trig_data {
- struct led_classdev *led_cdev;
-@@ -123,6 +125,57 @@ static const struct attribute_group port
- * Adding & removing ports
- ***************************************/
-
-+/**
-+ * usbport_trig_port_observed - Check if port should be observed
-+ */
-+static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data,
-+ struct usb_device *usb_dev, int port1)
-+{
-+ struct device *dev = usbport_data->led_cdev->dev;
-+ struct device_node *led_np = dev->of_node;
-+ struct of_phandle_args args;
-+ struct device_node *port_np;
-+ int count, i;
-+
-+ if (!led_np)
-+ return false;
-+
-+ /* Get node of port being added */
-+ port_np = usb_of_get_child_node(usb_dev->dev.of_node, port1);
-+ if (!port_np)
-+ return false;
-+
-+ /* Amount of trigger sources for this LED */
-+ count = of_count_phandle_with_args(led_np, "trigger-sources",
-+ "#trigger-source-cells");
-+ if (count < 0) {
-+ dev_warn(dev, "Failed to get trigger sources for %s\n",
-+ led_np->full_name);
-+ return false;
-+ }
-+
-+ /* Check list of sources for this specific port */
-+ for (i = 0; i < count; i++) {
-+ int err;
-+
-+ err = of_parse_phandle_with_args(led_np, "trigger-sources",
-+ "#trigger-source-cells", i,
-+ &args);
-+ if (err) {
-+ dev_err(dev, "Failed to get trigger source phandle at index %d: %d\n",
-+ i, err);
-+ continue;
-+ }
-+
-+ of_node_put(args.np);
-+
-+ if (args.np == port_np)
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
- static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
- struct usb_device *usb_dev,
- const char *hub_name, int portnum)
-@@ -141,6 +194,8 @@ static int usbport_trig_add_port(struct
- port->data = usbport_data;
- port->hub = usb_dev;
- port->portnum = portnum;
-+ port->observed = usbport_trig_port_observed(usbport_data, usb_dev,
-+ portnum);
-
- len = strlen(hub_name) + 8;
- port->port_name = kzalloc(len, GFP_KERNEL);
-@@ -255,6 +310,7 @@ static void usbport_trig_activate(struct
- if (err)
- goto err_free;
- usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
-+ usbport_trig_update_count(usbport_data);
-
- /* Notifications */
- usbport_data->nb.notifier_call = usbport_trig_notify,
+++ /dev/null
-From 107c0964cb8db7ca28ac5199426414fdab3c274d Mon Sep 17 00:00:00 2001
-From: "Alexandros C. Couloumbis" <alex@ozo.com>
-Date: Fri, 7 Jul 2017 17:14:51 +0200
-Subject: hack: arch: powerpc: drop register save/restore library from modules
-
-Upstream GCC uses a libgcc function for saving/restoring registers. This
-makes the code bigger, and upstream kernels need to carry that function
-for every single kernel module. Our GCC is patched to avoid those
-references, so we can drop the extra bloat for modules.
-
-lede-commit: e8e1084654f50904e6bf77b70b2de3f137d7b3ec
-Signed-off-by: Alexandros C. Couloumbis <alex@ozo.com>
----
- arch/powerpc/Makefile | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/arch/powerpc/Makefile
-+++ b/arch/powerpc/Makefile
-@@ -188,7 +188,6 @@ else
- CHECKFLAGS += -D__LITTLE_ENDIAN__
- endif
-
--KBUILD_LDFLAGS_MODULE += arch/powerpc/lib/crtsavres.o
-
- ifeq ($(CONFIG_476FPE_ERR46),y)
- KBUILD_LDFLAGS_MODULE += --ppc476-workaround \
+++ /dev/null
-From 3cb240533ab787899dc7f17aa7d6c5b4810e2e58 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Fri, 7 Jul 2017 17:26:01 +0200
-Subject: bcm53xx: bgmac: use srab switch driver
-
-use the srab switch driver on these SoCs.
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/net/ethernet/broadcom/bgmac-bcma.c | 1 +
- drivers/net/ethernet/broadcom/bgmac.c | 24 ++++++++++++++++++++++++
- drivers/net/ethernet/broadcom/bgmac.h | 4 ++++
- 3 files changed, 29 insertions(+)
-
---- a/drivers/net/ethernet/broadcom/bgmac-bcma.c
-+++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c
-@@ -243,6 +243,7 @@ static int bgmac_probe(struct bcma_devic
- bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
- bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
- bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
-+ bgmac->feature_flags |= BGMAC_FEAT_SRAB;
- break;
- case BCMA_CHIP_ID_BCM53573:
- bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
---- a/drivers/net/ethernet/broadcom/bgmac.c
-+++ b/drivers/net/ethernet/broadcom/bgmac.c
-@@ -11,6 +11,7 @@
-
- #include <linux/bcma/bcma.h>
- #include <linux/etherdevice.h>
-+#include <linux/platform_data/b53.h>
- #include <linux/bcm47xx_nvram.h>
- #include "bgmac.h"
-
-@@ -1387,6 +1388,17 @@ static const struct ethtool_ops bgmac_et
- .set_link_ksettings = phy_ethtool_set_link_ksettings,
- };
-
-+static struct b53_platform_data bgmac_b53_pdata = {
-+};
-+
-+static struct platform_device bgmac_b53_dev = {
-+ .name = "b53-srab-switch",
-+ .id = -1,
-+ .dev = {
-+ .platform_data = &bgmac_b53_pdata,
-+ },
-+};
-+
- /**************************************************
- * MII
- **************************************************/
-@@ -1533,6 +1545,14 @@ int bgmac_enet_probe(struct bgmac *bgmac
- net_dev->hw_features = net_dev->features;
- net_dev->vlan_features = net_dev->features;
-
-+ if ((bgmac->feature_flags & BGMAC_FEAT_SRAB) && !bgmac_b53_pdata.regs) {
-+ bgmac_b53_pdata.regs = ioremap_nocache(0x18007000, 0x1000);
-+
-+ err = platform_device_register(&bgmac_b53_dev);
-+ if (!err)
-+ bgmac->b53_device = &bgmac_b53_dev;
-+ }
-+
- err = register_netdev(bgmac->net_dev);
- if (err) {
- dev_err(bgmac->dev, "Cannot register net device\n");
-@@ -1555,6 +1575,10 @@ EXPORT_SYMBOL_GPL(bgmac_enet_probe);
-
- void bgmac_enet_remove(struct bgmac *bgmac)
- {
-+ if (bgmac->b53_device)
-+ platform_device_unregister(&bgmac_b53_dev);
-+ bgmac->b53_device = NULL;
-+
- unregister_netdev(bgmac->net_dev);
- phy_disconnect(bgmac->net_dev->phydev);
- netif_napi_del(&bgmac->napi);
---- a/drivers/net/ethernet/broadcom/bgmac.h
-+++ b/drivers/net/ethernet/broadcom/bgmac.h
-@@ -409,6 +409,7 @@
- #define BGMAC_FEAT_CC4_IF_SW_TYPE BIT(17)
- #define BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII BIT(18)
- #define BGMAC_FEAT_CC7_IF_TYPE_RGMII BIT(19)
-+#define BGMAC_FEAT_SRAB BIT(20)
-
- struct bgmac_slot_info {
- union {
-@@ -513,6 +514,9 @@ struct bgmac {
- u32 (*get_bus_clock)(struct bgmac *bgmac);
- void (*cmn_maskset32)(struct bgmac *bgmac, u16 offset, u32 mask,
- u32 set);
-+
-+ /* platform device for associated switch */
-+ struct platform_device *b53_device;
- };
-
- struct bgmac *bgmac_alloc(struct device *dev);
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 30 Jan 2018 11:55:16 +0100
-Subject: [PATCH V10 1/3] mtd: partitions: add of_match_table parser matching
- for the "ofpart" type
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-In order to properly support compatibility strings as described in the
-bindings/mtd/partition.txt "ofpart" type should be treated as an
-indication for looking into OF. MTD should check "compatible" property
-and search for a matching parser rather than blindly trying the one
-supporting "fixed-partitions".
-
-It also means that existing "fixed-partitions" parser should get renamed
-to use a more meaningful name.
-
-This commit achievies that aim by introducing a new mtd_part_of_parse().
-It works by looking for a matching parser for every string in the
-"compatibility" property (starting with the most specific one).
-
-Please note that driver-specified parsers still take a precedence. It's
-assumed that driver providing a parser type has a good reason for that
-(e.g. having platform data with device-specific info). Also doing
-otherwise could break existing setups. The same applies to using default
-parsers (including "cmdlinepart") as some overwrite DT data with cmdline
-argument.
-
-Partition parsers can now provide an of_match_table to enable
-flash<-->parser matching via device tree as documented in the
-mtd/partition.txt.
-
-This support is currently limited to built-in parsers as it uses
-request_module() and friends. This should be sufficient for most cases
-though as compiling parsers as modules isn't a common choice.
-
-Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Tested-by: Peter Rosin <peda@axentia.se>
----
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -30,6 +30,7 @@
- #include <linux/mtd/mtd.h>
- #include <linux/mtd/partitions.h>
- #include <linux/err.h>
-+#include <linux/of.h>
-
- #include "mtdcore.h"
-
-@@ -886,6 +887,92 @@ static int mtd_part_do_parse(struct mtd_
- }
-
- /**
-+ * mtd_part_get_compatible_parser - find MTD parser by a compatible string
-+ *
-+ * @compat: compatible string describing partitions in a device tree
-+ *
-+ * MTD parsers can specify supported partitions by providing a table of
-+ * compatibility strings. This function finds a parser that advertises support
-+ * for a passed value of "compatible".
-+ */
-+static struct mtd_part_parser *mtd_part_get_compatible_parser(const char *compat)
-+{
-+ struct mtd_part_parser *p, *ret = NULL;
-+
-+ spin_lock(&part_parser_lock);
-+
-+ list_for_each_entry(p, &part_parsers, list) {
-+ const struct of_device_id *matches;
-+
-+ matches = p->of_match_table;
-+ if (!matches)
-+ continue;
-+
-+ for (; matches->compatible[0]; matches++) {
-+ if (!strcmp(matches->compatible, compat) &&
-+ try_module_get(p->owner)) {
-+ ret = p;
-+ break;
-+ }
-+ }
-+
-+ if (ret)
-+ break;
-+ }
-+
-+ spin_unlock(&part_parser_lock);
-+
-+ return ret;
-+}
-+
-+static int mtd_part_of_parse(struct mtd_info *master,
-+ struct mtd_partitions *pparts)
-+{
-+ struct mtd_part_parser *parser;
-+ struct device_node *np;
-+ struct property *prop;
-+ const char *compat;
-+ const char *fixed = "ofpart";
-+ int ret, err = 0;
-+
-+ np = of_get_child_by_name(mtd_get_of_node(master), "partitions");
-+ of_property_for_each_string(np, "compatible", prop, compat) {
-+ parser = mtd_part_get_compatible_parser(compat);
-+ if (!parser)
-+ continue;
-+ ret = mtd_part_do_parse(parser, master, pparts, NULL);
-+ if (ret > 0) {
-+ of_node_put(np);
-+ return ret;
-+ }
-+ mtd_part_parser_put(parser);
-+ if (ret < 0 && !err)
-+ err = ret;
-+ }
-+ of_node_put(np);
-+
-+ /*
-+ * For backward compatibility we have to try the "ofpart"
-+ * parser. It supports old DT format with partitions specified as a
-+ * direct subnodes of a flash device DT node without any compatibility
-+ * specified we could match.
-+ */
-+ parser = mtd_part_parser_get(fixed);
-+ if (!parser && !request_module("%s", fixed))
-+ parser = mtd_part_parser_get(fixed);
-+ if (parser) {
-+ ret = mtd_part_do_parse(parser, master, pparts, NULL);
-+ if (ret > 0)
-+ return ret;
-+ mtd_part_parser_put(parser);
-+ if (ret < 0 && !err)
-+ err = ret;
-+ }
-+
-+ return err;
-+}
-+
-+/**
- * parse_mtd_partitions - parse MTD partitions
- * @master: the master partition (describes whole MTD device)
- * @types: names of partition parsers to try or %NULL
-@@ -917,19 +1004,30 @@ int parse_mtd_partitions(struct mtd_info
- types = default_mtd_part_types;
-
- for ( ; *types; types++) {
-- pr_debug("%s: parsing partitions %s\n", master->name, *types);
-- parser = mtd_part_parser_get(*types);
-- if (!parser && !request_module("%s", *types))
-+ /*
-+ * ofpart is a special type that means OF partitioning info
-+ * should be used. It requires a bit different logic so it is
-+ * handled in a separated function.
-+ */
-+ if (!strcmp(*types, "ofpart")) {
-+ ret = mtd_part_of_parse(master, pparts);
-+ } else {
-+ pr_debug("%s: parsing partitions %s\n", master->name,
-+ *types);
- parser = mtd_part_parser_get(*types);
-- pr_debug("%s: got parser %s\n", master->name,
-- parser ? parser->name : NULL);
-- if (!parser)
-- continue;
-- ret = mtd_part_do_parse(parser, master, pparts, data);
-+ if (!parser && !request_module("%s", *types))
-+ parser = mtd_part_parser_get(*types);
-+ pr_debug("%s: got parser %s\n", master->name,
-+ parser ? parser->name : NULL);
-+ if (!parser)
-+ continue;
-+ ret = mtd_part_do_parse(parser, master, pparts, data);
-+ if (ret <= 0)
-+ mtd_part_parser_put(parser);
-+ }
- /* Found partitions! */
- if (ret > 0)
- return 0;
-- mtd_part_parser_put(parser);
- /*
- * Stash the first error we see; only report it if no parser
- * succeeds
---- a/include/linux/mtd/partitions.h
-+++ b/include/linux/mtd/partitions.h
-@@ -77,6 +77,7 @@ struct mtd_part_parser {
- struct list_head list;
- struct module *owner;
- const char *name;
-+ const struct of_device_id *of_match_table;
- int (*parse_fn)(struct mtd_info *, const struct mtd_partition **,
- struct mtd_part_parser_data *);
- void (*cleanup)(const struct mtd_partition *pparts, int nr_parts);
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Tue, 30 Jan 2018 12:09:58 +0100
-Subject: [PATCH V10 2/3] mtd: rename "ofpart" parser to "fixed-partitions" as
- it fits it better
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Type "ofpart" means that OF should be used to get partitioning info and
-this driver supports "fixed-partitions" binding only. Renaming it should
-lead to less confusion especially when parsers for new compatibility
-strings start to appear.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
----
-
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -932,7 +932,7 @@ static int mtd_part_of_parse(struct mtd_
- struct device_node *np;
- struct property *prop;
- const char *compat;
-- const char *fixed = "ofpart";
-+ const char *fixed = "fixed-partitions";
- int ret, err = 0;
-
- np = of_get_child_by_name(mtd_get_of_node(master), "partitions");
-@@ -952,7 +952,7 @@ static int mtd_part_of_parse(struct mtd_
- of_node_put(np);
-
- /*
-- * For backward compatibility we have to try the "ofpart"
-+ * For backward compatibility we have to try the "fixed-partitions"
- * parser. It supports old DT format with partitions specified as a
- * direct subnodes of a flash device DT node without any compatibility
- * specified we could match.
---- a/drivers/mtd/ofpart.c
-+++ b/drivers/mtd/ofpart.c
-@@ -25,9 +25,9 @@ static bool node_has_compatible(struct d
- return of_get_property(pp, "compatible", NULL);
- }
-
--static int parse_ofpart_partitions(struct mtd_info *master,
-- const struct mtd_partition **pparts,
-- struct mtd_part_parser_data *data)
-+static int parse_fixed_partitions(struct mtd_info *master,
-+ const struct mtd_partition **pparts,
-+ struct mtd_part_parser_data *data)
- {
- struct mtd_partition *parts;
- struct device_node *mtd_node;
-@@ -141,8 +141,8 @@ ofpart_none:
- }
-
- static struct mtd_part_parser ofpart_parser = {
-- .parse_fn = parse_ofpart_partitions,
-- .name = "ofpart",
-+ .parse_fn = parse_fixed_partitions,
-+ .name = "fixed-partitions",
- };
-
- static int parse_ofoldpart_partitions(struct mtd_info *master,
-@@ -230,4 +230,5 @@ MODULE_AUTHOR("Vitaly Wool, David Gibson
- * with the same name. Since we provide the ofoldpart parser, we should have
- * the corresponding alias.
- */
-+MODULE_ALIAS("fixed-partitions");
- MODULE_ALIAS("ofoldpart");
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Thu, 4 Jan 2018 08:05:34 +0100
-Subject: [PATCH V10 3/3] mtd: ofpart: add of_match_table with
- "fixed-partitions"
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This allows using this parser with any flash driver that takes care of
-setting of_node (using mtd_set_of_node helper) correctly. Up to now
-support for "fixed-partitions" DT compatibility string was working only
-with flash drivers that were specifying "ofpart" (manually or by letting
-mtd use the default set of parsers).
-
-This matches existing bindings documentation.
-
-Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
-Reviewed-by: Brian Norris <computersforpeace@gmail.com>
-Tested-by: Brian Norris <computersforpeace@gmail.com>
----
-
---- a/drivers/mtd/ofpart.c
-+++ b/drivers/mtd/ofpart.c
-@@ -140,9 +140,16 @@ ofpart_none:
- return ret;
- }
-
-+static const struct of_device_id parse_ofpart_match_table[] = {
-+ { .compatible = "fixed-partitions" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, parse_ofpart_match_table);
-+
- static struct mtd_part_parser ofpart_parser = {
- .parse_fn = parse_fixed_partitions,
- .name = "fixed-partitions",
-+ .of_match_table = parse_ofpart_match_table,
- };
-
- static int parse_ofoldpart_partitions(struct mtd_info *master,
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Subject: net: phy: at803x: add support for AT8032
-
-Like AT8030, this PHY needs the GPIO reset workaround
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/net/phy/at803x.c
-+++ b/drivers/net/phy/at803x.c
-@@ -62,6 +62,7 @@
-
- #define ATH8030_PHY_ID 0x004dd076
- #define ATH8031_PHY_ID 0x004dd074
-+#define ATH8032_PHY_ID 0x004dd023
- #define ATH8035_PHY_ID 0x004dd072
-
- MODULE_DESCRIPTION("Atheros 803x PHY driver");
-@@ -259,7 +260,8 @@ static int at803x_probe(struct phy_devic
- if (!priv)
- return -ENOMEM;
-
-- if (phydev->drv->phy_id != ATH8030_PHY_ID)
-+ if (phydev->drv->phy_id != ATH8030_PHY_ID &&
-+ phydev->drv->phy_id != ATH8032_PHY_ID)
- goto does_not_require_reset_workaround;
-
- gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
-@@ -335,7 +337,7 @@ static void at803x_link_change_notify(st
- struct at803x_priv *priv = phydev->priv;
-
- /*
-- * Conduct a hardware reset for AT8030 every time a link loss is
-+ * Conduct a hardware reset for AT8030/2 every time a link loss is
- * signalled. This is necessary to circumvent a hardware bug that
- * occurs when the cable is unplugged while TX packets are pending
- * in the FIFO. In such cases, the FIFO enters an error mode it
-@@ -447,6 +449,24 @@ static struct phy_driver at803x_driver[]
- .aneg_done = at803x_aneg_done,
- .ack_interrupt = &at803x_ack_interrupt,
- .config_intr = &at803x_config_intr,
-+}, {
-+ /* ATHEROS 8032 */
-+ .phy_id = ATH8032_PHY_ID,
-+ .name = "Atheros 8032 ethernet",
-+ .phy_id_mask = 0xffffffef,
-+ .probe = at803x_probe,
-+ .config_init = at803x_config_init,
-+ .link_change_notify = at803x_link_change_notify,
-+ .set_wol = at803x_set_wol,
-+ .get_wol = at803x_get_wol,
-+ .suspend = at803x_suspend,
-+ .resume = at803x_resume,
-+ .features = PHY_BASIC_FEATURES,
-+ .flags = PHY_HAS_INTERRUPT,
-+ .config_aneg = genphy_config_aneg,
-+ .read_status = genphy_read_status,
-+ .ack_interrupt = at803x_ack_interrupt,
-+ .config_intr = at803x_config_intr,
- } };
-
- module_phy_driver(at803x_driver);
-@@ -454,6 +474,7 @@ module_phy_driver(at803x_driver);
- static struct mdio_device_id __maybe_unused atheros_tbl[] = {
- { ATH8030_PHY_ID, 0xffffffef },
- { ATH8031_PHY_ID, 0xffffffef },
-+ { ATH8032_PHY_ID, 0xffffffef },
- { ATH8035_PHY_ID, 0xffffffef },
- { }
- };
+++ /dev/null
-From d4c4bc11353f3bea6754f7d21e3612c9f32d1d64 Mon Sep 17 00:00:00 2001
-From: Giuseppe Lippolis <giu.lippolis@gmail.com>
-Date: Mon, 26 Mar 2018 16:34:39 +0200
-Subject: [PATCH] net-usb: add qmi_wwan if on lte modem wistron neweb d18q1
-
-This modem is embedded on dlink dwr-921 router.
- The oem configuration states:
-
- T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
- D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
- P: Vendor=1435 ProdID=0918 Rev= 2.32
- S: Manufacturer=Android
- S: Product=Android
- S: SerialNumber=0123456789ABCDEF
- C:* #Ifs= 7 Cfg#= 1 Atr=80 MxPwr=500mA
- I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option
- E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none)
- E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
- E: Ad=84(I) Atr=03(Int.) MxPS= 64 Ivl=32ms
- E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
- E: Ad=86(I) Atr=03(Int.) MxPS= 64 Ivl=32ms
- E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
- E: Ad=88(I) Atr=03(Int.) MxPS= 64 Ivl=32ms
- E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- I:* If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan
- E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=32ms
- E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- I:* If#= 6 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=(none)
- E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=125us
-
-Tested on openwrt distribution
-
-Signed-off-by: Giuseppe Lippolis <giu.lippolis@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/usb/qmi_wwan.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/net/usb/qmi_wwan.c
-+++ b/drivers/net/usb/qmi_wwan.c
-@@ -809,6 +809,9 @@ static const struct usb_device_id produc
- {QMI_FIXED_INTF(0x0846, 0x68a2, 8)},
- {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
- {QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */
-+ {QMI_FIXED_INTF(0x1435, 0xd181, 3)}, /* Wistron NeWeb D18Q1 */
-+ {QMI_FIXED_INTF(0x1435, 0xd181, 4)}, /* Wistron NeWeb D18Q1 */
-+ {QMI_FIXED_INTF(0x1435, 0xd181, 5)}, /* Wistron NeWeb D18Q1 */
- {QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */
- {QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */
- {QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */
+++ /dev/null
-From 743989254ea9f132517806d8893ca9b6cf9dc86b Mon Sep 17 00:00:00 2001
-From: Pawel Dembicki <paweldembicki@gmail.com>
-Date: Sat, 24 Mar 2018 22:08:14 +0100
-Subject: [PATCH] net: qmi_wwan: add BroadMobi BM806U 2020:2033
-
-BroadMobi BM806U is an Qualcomm MDM9225 based 3G/4G modem.
-Tested hardware BM806U is mounted on D-Link DWR-921-C3 router.
-The USB id is added to qmi_wwan.c to allow QMI communication with
-the BM806U.
-
-Tested on 4.14 kernel and OpenWRT.
-
-Signed-off-by: Pawel Dembicki <paweldembicki@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/usb/qmi_wwan.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/net/usb/qmi_wwan.c
-+++ b/drivers/net/usb/qmi_wwan.c
-@@ -888,6 +888,7 @@ static const struct usb_device_id produc
- {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */
- {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */
- {QMI_FIXED_INTF(0x2001, 0x7e35, 4)}, /* D-Link DWM-222 */
-+ {QMI_FIXED_INTF(0x2020, 0x2033, 4)}, /* BroadMobi BM806U */
- {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */
- {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */
- {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */
+++ /dev/null
-From patchwork Fri Jul 21 18:36:24 2017
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Subject: [2/5] e1000e: Fix wrong comment related to link detection
-From: Benjamin Poirier <bpoirier@suse.com>
-X-Patchwork-Id: 9857489
-Message-Id: <20170721183627.13373-2-bpoirier@suse.com>
-To: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-Cc: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>,
- intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org,
- linux-kernel@vger.kernel.org
-Date: Fri, 21 Jul 2017 11:36:24 -0700
-
-Reading e1000e_check_for_copper_link() shows that get_link_status is set to
-false after link has been detected. Therefore, it stays TRUE until then.
-
-Signed-off-by: Benjamin Poirier <bpoirier@suse.com>
-Tested-by: Aaron Brown <aaron.f.brown@intel.com>
----
- drivers/net/ethernet/intel/e1000e/netdev.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/intel/e1000e/netdev.c
-+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
-@@ -5072,7 +5072,7 @@ static bool e1000e_has_link(struct e1000
-
- /* get_link_status is set on LSC (link status) interrupt or
- * Rx sequence error interrupt. get_link_status will stay
-- * false until the check_for_link establishes link
-+ * true until the check_for_link establishes link
- * for copper adapters ONLY
- */
- switch (hw->phy.media_type) {
-@@ -5090,7 +5090,7 @@ static bool e1000e_has_link(struct e1000
- break;
- case e1000_media_type_internal_serdes:
- ret_val = hw->mac.ops.check_for_link(hw);
-- link_active = adapter->hw.mac.serdes_has_link;
-+ link_active = hw->mac.serdes_has_link;
- break;
- default:
- case e1000_media_type_unknown:
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Subject: fix errors in unresolved weak symbols on arm
-
-lede-commit: 570699d4838a907c3ef9f2819bf19eb72997b32f
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- arch/arm/kernel/module.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/arch/arm/kernel/module.c
-+++ b/arch/arm/kernel/module.c
-@@ -88,6 +88,10 @@ apply_relocate(Elf32_Shdr *sechdrs, cons
- return -ENOEXEC;
- }
-
-+ if ((IS_ERR_VALUE(sym->st_value) || !sym->st_value) &&
-+ ELF_ST_BIND(sym->st_info) == STB_WEAK)
-+ continue;
-+
- loc = dstsec->sh_addr + rel->r_offset;
-
- switch (ELF32_R_TYPE(rel->r_info)) {
+++ /dev/null
-From: Alexey Brodkin <abrodkin@synopsys.com>
-Subject: openwrt: arc - add OWRTDTB section
-
-This change allows OpenWRT to patch resulting kernel binary with
-external .dtb.
-
-That allows us to re-use exactky the same vmlinux on different boards
-given its ARC core configurations match (at least cache line sizes etc).
-
-""patch-dtb" searches for ASCII "OWRTDTB:" strign and copies external
-.dtb right after it, keeping the string in place.
-
-Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
----
- arch/arc/kernel/head.S | 10 ++++++++++
- arch/arc/kernel/setup.c | 4 +++-
- arch/arc/kernel/vmlinux.lds.S | 13 +++++++++++++
- 3 files changed, 26 insertions(+), 1 deletion(-)
-
---- a/arch/arc/kernel/head.S
-+++ b/arch/arc/kernel/head.S
-@@ -49,6 +49,16 @@
- 1:
- .endm
-
-+; Here "patch-dtb" will embed external .dtb
-+; Note "patch-dtb" searches for ASCII "OWRTDTB:" string
-+; and pastes .dtb right after it, hense the string precedes
-+; __image_dtb symbol.
-+ .section .owrt, "aw",@progbits
-+ .ascii "OWRTDTB:"
-+ENTRY(__image_dtb)
-+ .fill 0x4000
-+END(__image_dtb)
-+
- .section .init.text, "ax",@progbits
-
- ;----------------------------------------------------------------
---- a/arch/arc/kernel/setup.c
-+++ b/arch/arc/kernel/setup.c
-@@ -388,6 +388,8 @@ static inline int is_kernel(unsigned lon
- return 0;
- }
-
-+extern struct boot_param_header __image_dtb;
-+
- void __init setup_arch(char **cmdline_p)
- {
- #ifdef CONFIG_ARC_UBOOT_SUPPORT
-@@ -401,7 +403,7 @@ void __init setup_arch(char **cmdline_p)
- #endif
- {
- /* No, so try the embedded one */
-- machine_desc = setup_machine_fdt(__dtb_start);
-+ machine_desc = setup_machine_fdt(&__image_dtb);
- if (!machine_desc)
- panic("Embedded DT invalid\n");
-
---- a/arch/arc/kernel/vmlinux.lds.S
-+++ b/arch/arc/kernel/vmlinux.lds.S
-@@ -30,6 +30,19 @@ SECTIONS
-
- . = CONFIG_LINUX_LINK_BASE;
-
-+ /*
-+ * In OpenWRT we want to patch built binary embedding .dtb of choice.
-+ * This is implemented with "patch-dtb" utility which searches for
-+ * "OWRTDTB:" string in first 16k of image and if it is found
-+ * copies .dtb right after mentioned string.
-+ *
-+ * Note: "OWRTDTB:" won't be overwritten with .dtb, .dtb will follow it.
-+ */
-+ .owrt : {
-+ *(.owrt)
-+ . = ALIGN(PAGE_SIZE);
-+ }
-+
- _int_vec_base_lds = .;
- .vector : {
- *(.vector)
+++ /dev/null
-From: Alexey Brodkin <abrodkin@synopsys.com>
-Subject: arc: enable unaligned access in kernel mode
-
-This enables misaligned access handling even in kernel mode.
-Some wireless drivers (ath9k-htc and mt7601u) use misaligned accesses
-here and there and to cope with that without fixing stuff in the drivers
-we're just gracefully handling it on ARC.
-
-Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
----
- arch/arc/kernel/unaligned.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/arch/arc/kernel/unaligned.c
-+++ b/arch/arc/kernel/unaligned.c
-@@ -206,7 +206,7 @@ int misaligned_fixup(unsigned long addre
- char buf[TASK_COMM_LEN];
-
- /* handle user mode only and only if enabled by sysadmin */
-- if (!user_mode(regs) || !unaligned_enabled)
-+ if (!unaligned_enabled)
- return 1;
-
- if (no_unaligned_warning) {
depends on m
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
-@@ -29,11 +29,13 @@
+@@ -29,10 +29,12 @@
#include <linux/kmod.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/magic.h>
#include <linux/of.h>
#include <linux/err.h>
- #include <linux/of.h>
#include "mtdcore.h"
+#include "mtdsplit/mtdsplit.h"
/* Our partition linked list */
static LIST_HEAD(mtd_partitions);
-@@ -53,6 +55,8 @@ struct mtd_part {
+@@ -46,6 +48,8 @@ struct mtd_part {
struct list_head list;
};
/*
* Given a pointer to the MTD object in the mtd_part structure, we can retrieve
* the pointer to that structure.
-@@ -679,6 +683,7 @@ int mtd_add_partition(struct mtd_info *p
+@@ -650,6 +654,7 @@ int mtd_add_partition(struct mtd_info *m
mutex_unlock(&mtd_partitions_mutex);
add_mtd_device(&new->mtd);
-+ mtd_partition_split(parent, new);
++ mtd_partition_split(master, new);
mtd_add_partition_attrs(new);
-@@ -757,6 +762,35 @@ int mtd_del_partition(struct mtd_info *m
+@@ -682,6 +687,35 @@ int mtd_del_partition(struct mtd_info *m
}
EXPORT_SYMBOL_GPL(mtd_del_partition);
/*
* This function, given a master MTD object and a partition table, creates
* and registers slave MTD objects which are bound to the master according to
-@@ -788,6 +822,7 @@ int add_mtd_partitions(struct mtd_info *
+@@ -713,6 +747,7 @@ int add_mtd_partitions(struct mtd_info *
mutex_unlock(&mtd_partitions_mutex);
add_mtd_device(&slave->mtd);
+ mtd_partition_split(master, slave);
mtd_add_partition_attrs(slave);
- if (parts[i].types)
- mtd_parse_part(slave, parts[i].types);
+
+ cur_offset = slave->offset + slave->mtd.size;
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
-@@ -110,5 +110,7 @@ int mtd_add_partition(struct mtd_info *m
+@@ -101,5 +101,7 @@ int mtd_add_partition(struct mtd_info *m
long long offset, long long length);
int mtd_del_partition(struct mtd_info *master, int partno);
uint64_t mtd_get_device_size(const struct mtd_info *mtd);
+ /* adjust partition offsets */
+ parts[i].offset += slave->offset;
+
-+ mtd_add_partition(slave->parent,
++ mtd_add_partition(slave->master,
+ parts[i].name,
+ parts[i].offset,
+ parts[i].size);
+ if (!mtd_is_partition(mtd))
+ return (struct mtd_info *)mtd;
+
-+ return mtd_to_part(mtd)->parent;
++ return mtd_to_part(mtd)->master;
+}
+EXPORT_SYMBOL_GPL(mtdpart_get_master);
+
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
-@@ -37,6 +37,8 @@
+@@ -36,6 +36,8 @@
#include "mtdcore.h"
#include "mtdsplit/mtdsplit.h"
/* Our partition linked list */
static LIST_HEAD(mtd_partitions);
static DEFINE_MUTEX(mtd_partitions_mutex);
-@@ -242,13 +244,61 @@ static int part_erase(struct mtd_info *m
+@@ -235,13 +237,60 @@ static int part_erase(struct mtd_info *m
struct mtd_part *part = mtd_to_part(mtd);
int ret;
-+
+ instr->partial_start = false;
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
+ size_t readlen = 0;
+ u64 mtd_ofs;
+
-+ instr->erase_buf = kmalloc(part->parent->erasesize, GFP_ATOMIC);
++ instr->erase_buf = kmalloc(part->master->erasesize, GFP_ATOMIC);
+ if (!instr->erase_buf)
+ return -ENOMEM;
+
+ mtd_ofs = part->offset + instr->addr;
-+ instr->erase_buf_ofs = do_div(mtd_ofs, part->parent->erasesize);
++ instr->erase_buf_ofs = do_div(mtd_ofs, part->master->erasesize);
+
+ if (instr->erase_buf_ofs > 0) {
+ instr->addr -= instr->erase_buf_ofs;
-+ ret = mtd_read(part->parent,
++ ret = mtd_read(part->master,
+ instr->addr + part->offset,
-+ part->parent->erasesize,
++ part->master->erasesize,
+ &readlen, instr->erase_buf);
+
+ instr->len += instr->erase_buf_ofs;
+ instr->partial_start = true;
+ } else {
+ mtd_ofs = part->offset + part->mtd.size;
-+ instr->erase_buf_ofs = part->parent->erasesize -
-+ do_div(mtd_ofs, part->parent->erasesize);
++ instr->erase_buf_ofs = part->master->erasesize -
++ do_div(mtd_ofs, part->master->erasesize);
+
+ if (instr->erase_buf_ofs > 0) {
+ instr->len += instr->erase_buf_ofs;
-+ ret = mtd_read(part->parent,
++ ret = mtd_read(part->master,
+ part->offset + instr->addr +
-+ instr->len - part->parent->erasesize,
-+ part->parent->erasesize, &readlen,
++ instr->len - part->master->erasesize,
++ part->master->erasesize, &readlen,
+ instr->erase_buf);
+ } else {
+ ret = 0;
+ }
+
instr->addr += part->offset;
- ret = part->parent->_erase(part->parent, instr);
+ ret = part->master->_erase(part->master, instr);
if (ret) {
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
return ret;
}
-@@ -256,6 +306,25 @@ void mtd_erase_callback(struct erase_inf
+@@ -249,6 +298,25 @@ void mtd_erase_callback(struct erase_inf
{
if (instr->mtd->_erase == part_erase) {
struct mtd_part *part = mtd_to_part(instr->mtd);
+
+ if (instr->mtd->flags & MTD_ERASE_PARTIAL) {
+ if (instr->partial_start) {
-+ part->parent->_write(part->parent,
++ part->master->_write(part->master,
+ instr->addr, instr->erase_buf_ofs,
+ &wrlen, instr->erase_buf);
+ instr->addr += instr->erase_buf_ofs;
+ } else {
+ instr->len -= instr->erase_buf_ofs;
-+ part->parent->_write(part->parent,
++ part->master->_write(part->master,
+ instr->addr + instr->len,
+ instr->erase_buf_ofs, &wrlen,
+ instr->erase_buf +
-+ part->parent->erasesize -
++ part->master->erasesize -
+ instr->erase_buf_ofs);
+ }
+ kfree(instr->erase_buf);
if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
instr->fail_addr -= part->offset;
-@@ -591,19 +660,22 @@ static struct mtd_part *allocate_partiti
- remainder = do_div(tmp, wr_alignment);
- if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
+@@ -564,17 +632,20 @@ static struct mtd_part *allocate_partiti
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+ mtd_mod_by_eb(slave->offset, &slave->mtd)) {
/* Doesn't start on a boundary of major erase size */
- /* FIXME: Let it be writable if it is on a boundary of
- * _minor_ erase size though */
- slave->mtd.flags &= ~MTD_WRITEABLE;
-- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
+- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",
- part->name);
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
-+ if (((u32)slave->mtd.size) > parent->erasesize)
++ if (((u32)slave->mtd.size) > master->erasesize)
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ else
+ slave->mtd.erasesize = slave->mtd.size;
}
-
-- tmp = slave->mtd.size;
-+ tmp = slave->offset + slave->mtd.size;
- remainder = do_div(tmp, wr_alignment);
- if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {
+ if ((slave->mtd.flags & MTD_WRITEABLE) &&
+- mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {
- slave->mtd.flags &= ~MTD_WRITEABLE;
-- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
+- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",
- part->name);
++ mtd_mod_by_eb(slave->offset + slave->mtd.size, &slave->mtd)) {
+ slave->mtd.flags |= MTD_ERASE_PARTIAL;
+
-+ if ((u32)slave->mtd.size > parent->erasesize)
++ if ((u32) slave->mtd.size > master->erasesize)
+ slave->mtd.flags &= ~MTD_WRITEABLE;
+ else
+ slave->mtd.erasesize = slave->mtd.size;
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
-@@ -344,7 +344,16 @@ static int part_lock(struct mtd_info *mt
+@@ -336,7 +336,16 @@ static int part_lock(struct mtd_info *mt
static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
{
struct mtd_part *part = mtd_to_part(mtd);
-- return part->parent->_unlock(part->parent, ofs + part->offset, len);
+- return part->master->_unlock(part->master, ofs + part->offset, len);
+
+ ofs += part->offset;
+
+ if (mtd->flags & MTD_ERASE_PARTIAL) {
+ /* round up len to next erasesize and round down offset to prev block */
-+ len = (mtd_div_by_eb(len, part->parent) + 1) * part->parent->erasesize;
-+ ofs &= ~(part->parent->erasesize - 1);
++ len = (mtd_div_by_eb(len, part->master) + 1) * part->master->erasesize;
++ ofs &= ~(part->master->erasesize - 1);
+ }
+
-+ return part->parent->_unlock(part->parent, ofs, len);
++ return part->master->_unlock(part->master, ofs, len);
}
static int part_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Subject: add patch for including unpartitioned space in the rootfs partition for redboot devices (if applicable)
-
-[john@phrozen.org: used by ixp and others]
-
-lede-commit: 394918851f84e4d00fa16eb900e7700e95091f00
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- drivers/mtd/redboot.c | 19 +++++++++++++------
- 1 file changed, 13 insertions(+), 6 deletions(-)
-
---- a/drivers/mtd/redboot.c
-+++ b/drivers/mtd/redboot.c
-@@ -265,14 +265,21 @@ static int parse_redboot_partitions(stru
- #endif
- names += strlen(names)+1;
-
--#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
- if(fl->next && fl->img->flash_base + fl->img->size + master->erasesize <= fl->next->img->flash_base) {
-- i++;
-- parts[i].offset = parts[i-1].size + parts[i-1].offset;
-- parts[i].size = fl->next->img->flash_base - parts[i].offset;
-- parts[i].name = nullname;
-- }
-+ if (!strcmp(parts[i].name, "rootfs")) {
-+ parts[i].size = fl->next->img->flash_base;
-+ parts[i].size &= ~(master->erasesize - 1);
-+ parts[i].size -= parts[i].offset;
-+#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
-+ nrparts--;
-+ } else {
-+ i++;
-+ parts[i].offset = parts[i-1].size + parts[i-1].offset;
-+ parts[i].size = fl->next->img->flash_base - parts[i].offset;
-+ parts[i].name = nullname;
- #endif
-+ }
-+ }
- tmp_fl = fl;
- fl = fl->next;
- kfree(tmp_fl);
+++ /dev/null
-From: Florian Fainelli <f.fainelli@gmail.com>
-Subject: Add myloader partition table parser
-
-[john@phozen.org: shoud be upstreamable]
-
-lede-commit: d8bf22859b51faa09d22c056fe221a45d2f7a3b8
-Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
----
- drivers/mtd/Kconfig | 16 ++++++++++++++++
- drivers/mtd/Makefile | 1 +
- 2 files changed, 17 insertions(+)
-
---- a/drivers/mtd/Kconfig
-+++ b/drivers/mtd/Kconfig
-@@ -178,6 +178,22 @@ menu "Partition parsers"
- source "drivers/mtd/parsers/Kconfig"
- endmenu
-
-+config MTD_MYLOADER_PARTS
-+ tristate "MyLoader partition parsing"
-+ depends on ADM5120 || ATH25 || ATH79
-+ ---help---
-+ MyLoader is a bootloader which allows the user to define partitions
-+ in flash devices, by putting a table in the second erase block
-+ on the device, similar to a partition table. This table gives the
-+ offsets and lengths of the user defined partitions.
-+
-+ If you need code which can detect and parse these tables, and
-+ register MTD 'partitions' corresponding to each image detected,
-+ enable this option.
-+
-+ You will still need the parsing functions to be called by the driver
-+ for your particular device. It won't happen automatically.
-+
- comment "User Modules And Translation Layers"
-
- #
---- a/drivers/mtd/Makefile
-+++ b/drivers/mtd/Makefile
-@@ -15,6 +15,7 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
- obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
- obj-$(CONFIG_MTD_BCM63XX_PARTS) += bcm63xxpart.o
- obj-$(CONFIG_MTD_BCM47XX_PARTS) += bcm47xxpart.o
-+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
- obj-y += parsers/
-
- # 'Users' - code which presents functionality to userspace.
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-Subject: [PATCH] mtd: bcm47xxpart: check for bad blocks when calculating offsets
-
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
----
-
---- a/drivers/mtd/parsers/parser_trx.c
-+++ b/drivers/mtd/parsers/parser_trx.c
-@@ -29,6 +29,33 @@ struct trx_header {
- uint32_t offset[3];
- } __packed;
-
-+/*
-+ * Calculate real end offset (address) for a given amount of data. It checks
-+ * all blocks skipping bad ones.
-+ */
-+static size_t parser_trx_real_offset(struct mtd_info *mtd, size_t bytes)
-+{
-+ size_t real_offset = 0;
-+
-+ if (mtd_block_isbad(mtd, real_offset))
-+ pr_warn("Base offset shouldn't be at bad block");
-+
-+ while (bytes >= mtd->erasesize) {
-+ bytes -= mtd->erasesize;
-+ real_offset += mtd->erasesize;
-+ while (mtd_block_isbad(mtd, real_offset)) {
-+ real_offset += mtd->erasesize;
-+
-+ if (real_offset >= mtd->size)
-+ return real_offset - mtd->erasesize;
-+ }
-+ }
-+
-+ real_offset += bytes;
-+
-+ return real_offset;
-+}
-+
- static const char *parser_trx_data_part_name(struct mtd_info *master,
- size_t offset)
- {
-@@ -83,21 +110,21 @@ static int parser_trx_parse(struct mtd_i
- if (trx.offset[2]) {
- part = &parts[curr_part++];
- part->name = "loader";
-- part->offset = trx.offset[i];
-+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
- i++;
- }
-
- if (trx.offset[i]) {
- part = &parts[curr_part++];
- part->name = "linux";
-- part->offset = trx.offset[i];
-+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
- i++;
- }
-
- if (trx.offset[i]) {
- part = &parts[curr_part++];
- part->name = parser_trx_data_part_name(mtd, trx.offset[i]);
-- part->offset = trx.offset[i];
-+ part->offset = parser_trx_real_offset(mtd, trx.offset[i]);
- i++;
- }
-
+++ /dev/null
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
-Subject: mtd: bcm47xxpart: detect T_Meter partition
-
-It can be found on many Netgear devices. It consists of many 0x30 blocks
-starting with 4D 54.
-
-Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
----
- drivers/mtd/bcm47xxpart.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/mtd/bcm47xxpart.c
-+++ b/drivers/mtd/bcm47xxpart.c
-@@ -39,6 +39,7 @@
- #define NVRAM_HEADER 0x48534C46 /* FLSH */
- #define POT_MAGIC1 0x54544f50 /* POTT */
- #define POT_MAGIC2 0x504f /* OP */
-+#define T_METER_MAGIC 0x4D540000 /* MT */
- #define ML_MAGIC1 0x39685a42
- #define ML_MAGIC2 0x26594131
- #define TRX_MAGIC 0x30524448
-@@ -182,6 +183,15 @@ static int bcm47xxpart_parse(struct mtd_
- MTD_WRITEABLE);
- continue;
- }
-+
-+ /* T_Meter */
-+ if ((le32_to_cpu(buf[0x000 / 4]) & 0xFFFF0000) == T_METER_MAGIC &&
-+ (le32_to_cpu(buf[0x030 / 4]) & 0xFFFF0000) == T_METER_MAGIC &&
-+ (le32_to_cpu(buf[0x060 / 4]) & 0xFFFF0000) == T_METER_MAGIC) {
-+ bcm47xxpart_add_part(&parts[curr_part++], "T_Meter", offset,
-+ MTD_WRITEABLE);
-+ continue;
-+ }
-
- /* TRX */
- if (buf[0x000 / 4] == TRX_MAGIC) {
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Fri, 23 Feb 2018 17:12:16 +0100
-Subject: [PATCH] mtd: m25p80: allow fallback from spi_flash_read to regular
- SPI transfer
-
-Some flash controllers, e.g. on the ath79 platform can support a fast
-flash read via memory mapping, but only if the flash chip is in
-3-byte address mode.
-
-Since spi_flash_read_supported does not have access to the same data as
-spi_flash_read, the driver can't detect an unsupported call until m25p80
-has decided to use spi_flash_read.
-
-Allow the driver to indicate a fallback to a regular SPI transfer by
-returning -EOPNOTSUPP
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/mtd/devices/m25p80.c
-+++ b/drivers/mtd/devices/m25p80.c
-@@ -155,9 +155,11 @@ static ssize_t m25p80_read(struct spi_no
- msg.data_nbits = m25p80_rx_nbits(nor);
-
- ret = spi_flash_read(spi, &msg);
-- if (ret < 0)
-- return ret;
-- return msg.retlen;
-+ if (ret != -EOPNOTSUPP) {
-+ if (ret < 0)
-+ return ret;
-+ return msg.retlen;
-+ }
- }
-
- spi_message_init(&m);
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Subject: kernel: disable cfi cmdset 0002 erase suspend
-
-on some platforms, erase suspend leads to data corruption and lockups when write
-ops collide with erase ops. this has been observed on the buffalo wzr-hp-g300nh.
-rather than play whack-a-mole with a hard to reproduce issue on a variety of devices,
-simply disable erase suspend, as it will usually not produce any useful gain on
-the small filesystems used on embedded hardware.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- drivers/mtd/chips/cfi_cmdset_0002.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/mtd/chips/cfi_cmdset_0002.c
-+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -807,7 +807,7 @@ static int get_chip(struct map_info *map
- return 0;
-
- case FL_ERASING:
-- if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
-+ if (1 /* no suspend */ || !cfip || !(cfip->EraseSuspend & (0x1|0x2)) ||
- !(mode == FL_READY || mode == FL_POINT ||
- (mode == FL_WRITING && (cfip->EraseSuspend & 0x2))))
- goto sleep;
+++ /dev/null
-From: George Kashperko <george@znau.edu.ua>
-Subject: Issue map read after Write Buffer Load command to ensure chip is ready to receive data.
-
-Signed-off-by: George Kashperko <george@znau.edu.ua>
----
- drivers/mtd/chips/cfi_cmdset_0002.c | 1 +
- 1 file changed, 1 insertion(+)
---- a/drivers/mtd/chips/cfi_cmdset_0002.c
-+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -1828,6 +1828,7 @@ static int __xipram do_write_buffer(stru
-
- /* Write Buffer Load */
- map_write(map, CMD(0x25), cmd_adr);
-+ (void) map_read(map, cmd_adr);
-
- chip->state = FL_WRITING_TO_BUFFER;
-
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Subject: Disable software protection bits for Macronix flashes.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1595,6 +1595,7 @@ int spi_nor_scan(struct spi_nor *nor, co
-
- if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
- JEDEC_MFR(info) == SNOR_MFR_INTEL ||
-+ JEDEC_MFR(info) == SNOR_MFR_MACRONIX ||
- JEDEC_MFR(info) == SNOR_MFR_SST ||
- info->flags & SPI_NOR_HAS_LOCK) {
- write_enable(nor);
+++ /dev/null
-From: Matthias Schiffer <mschiffer@universe-factory.net>
-Date: Tue, 9 Jan 2018 20:41:48 +0100
-Subject: [PATCH] Revert "mtd: spi-nor: fix Spansion regressions (aliased with
- Winbond)"
-
-This reverts commit 67b9bcd36906e12a15ffec19463afbbd6a41660e.
-
-The underlying issue breaking Spansion flash has been fixed with "mtd: spi-nor:
-wait until lock/unlock operations are ready" and "mtd: spi-nor: wait for SR_WIP
-to clear on initial unlock", so we can support unlocking for Winbond flash
-again.
-
-Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
----
- drivers/mtd/spi-nor/spi-nor.c | 4 +++-
- 1 file changed, 3 insertions(+), 1 deletion(-)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1597,6 +1597,7 @@ int spi_nor_scan(struct spi_nor *nor, co
- JEDEC_MFR(info) == SNOR_MFR_INTEL ||
- JEDEC_MFR(info) == SNOR_MFR_MACRONIX ||
- JEDEC_MFR(info) == SNOR_MFR_SST ||
-+ JEDEC_MFR(info) == SNOR_MFR_WINBOND ||
- info->flags & SPI_NOR_HAS_LOCK) {
- write_enable(nor);
- write_sr(nor, 0);
-@@ -1615,7 +1616,8 @@ int spi_nor_scan(struct spi_nor *nor, co
-
- /* NOR protection support for STmicro/Micron chips and similar */
- if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
-- info->flags & SPI_NOR_HAS_LOCK) {
-+ JEDEC_MFR(info) == SNOR_MFR_WINBOND ||
-+ info->flags & SPI_NOR_HAS_LOCK) {
- nor->flash_lock = stm_lock;
- nor->flash_unlock = stm_unlock;
- nor->flash_is_locked = stm_is_locked;
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Date: Sat, 4 Nov 2017 07:40:23 +0100
-Subject: [PATCH] mtd: spi-nor: support limiting 4K sectors support based on
- flash size
-
-Some devices need 4K sectors to be able to deal with small flash chips.
-For instance, w25x05 is 64 KiB in size, and without 4K sectors, the
-entire chip is just one erase block.
-On bigger flash chip sizes, using 4K sectors can significantly slow down
-many operations, including using a writable filesystem. There are several
-platforms where it makes sense to use a single kernel on both kinds of
-devices.
-
-To support this properly, allow configuring an upper flash chip size
-limit for 4K sectors support.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
-
---- a/drivers/mtd/spi-nor/Kconfig
-+++ b/drivers/mtd/spi-nor/Kconfig
-@@ -29,6 +29,17 @@ config MTD_SPI_NOR_USE_4K_SECTORS
- Please note that some tools/drivers/filesystems may not work with
- 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
-
-+config MTD_SPI_NOR_USE_4K_SECTORS_LIMIT
-+ int "Maximum flash chip size to use 4K sectors on (in KiB)"
-+ depends on MTD_SPI_NOR_USE_4K_SECTORS
-+ default "4096"
-+ help
-+ There are many flash chips that support 4K sectors, but are so large
-+ that using them significantly slows down writing large amounts of
-+ data or using a writable filesystem.
-+ Any flash chip larger than the size specified in this option will
-+ not use 4K sectors.
-+
- config SPI_ATMEL_QUADSPI
- tristate "Atmel Quad SPI Controller"
- depends on ARCH_AT91 || (ARM && COMPILE_TEST)
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1642,10 +1642,12 @@ int spi_nor_scan(struct spi_nor *nor, co
-
- #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
- /* prefer "small sector" erase if possible */
-- if (info->flags & SECT_4K) {
-+ if ((info->flags & SECT_4K) && (mtd->size <=
-+ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) {
- nor->erase_opcode = SPINOR_OP_BE_4K;
- mtd->erasesize = 4096;
-- } else if (info->flags & SECT_4K_PMC) {
-+ } else if ((info->flags & SECT_4K_PMC) && (mtd->size <=
-+ CONFIG_MTD_SPI_NOR_USE_4K_SECTORS_LIMIT * 1024)) {
- nor->erase_opcode = SPINOR_OP_BE_4K_PMC;
- mtd->erasesize = 4096;
- } else
+++ /dev/null
-From: Piotr Dymacz <pepe2k@gmail.com>
-Subject: kernel/mtd: add support for EON EN25Q128
-
-Signed-off-by: Piotr Dymacz <pepe2k@gmail.com>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -954,6 +954,7 @@ static const struct flash_info spi_nor_i
- { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
- { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
- { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
-+ { "en25q128", INFO(0x1c3018, 0, 64 * 1024, 256, SECT_4K) },
- { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
- { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
- { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) },
+++ /dev/null
-From: André Valentin <avalentin@marcant.net>
-Subject: linux/mtd: add id for mx25u3235f needed by ZyXEL NBG6817
-
-Signed-off-by: André Valentin <avalentin@marcant.net>
----
- drivers/mtd/spi-nor/spi-nor.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1014,6 +1014,7 @@ static const struct flash_info spi_nor_i
- { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, SECT_4K) },
- { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
-+ { "mx25u3235f", INFO(0xc22536, 0, 64 * 1024, 64, 0) },
- { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
- { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
+++ /dev/null
-From b02f3405c935a28200db26b63e42086057565cf4 Mon Sep 17 00:00:00 2001
-From: Hauke Mehrtens <hauke@hauke-m.de>
-Date: Sat, 31 Mar 2018 20:09:54 +0200
-Subject: [PATCH] mtd: spi-nor: Add support for XM25QH64A and XM25QH128A
-
-These devices are produced by Wuhan Xinxin Semiconductor Manufacturing
-Corp. (XMC) and found on some routers from Chinese manufactures.
-
-The data sheets can be found here:
-http://www.xmcwh.com/Uploads/2018-03-01/5a9799e4cb355.pdf
-http://www.xmcwh.com/Uploads/2018-02-05/5a77e6dbe968b.pdf
-
-Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
----
- drivers/mtd/spi-nor/spi-nor.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1166,6 +1166,10 @@ static const struct flash_info spi_nor_i
- { "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
- { "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
- { "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
-+
-+ /* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */
-+ { "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-+ { "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
- { },
- };
-
+++ /dev/null
-From: Jonas Gorski <jogo@openwrt.org>
-Subject: ipv6: allow rejecting with "source address failed policy"
-
-RFC6204 L-14 requires rejecting traffic from invalid addresses with
-ICMPv6 Destination Unreachable, Code 5 (Source address failed ingress/
-egress policy) on the LAN side, so add an appropriate rule for that.
-
-Signed-off-by: Jonas Gorski <jogo@openwrt.org>
----
- include/net/netns/ipv6.h | 1 +
- include/uapi/linux/fib_rules.h | 4 +++
- include/uapi/linux/rtnetlink.h | 1 +
- net/ipv4/fib_semantics.c | 4 +++
- net/ipv4/fib_trie.c | 1 +
- net/ipv4/ipmr.c | 1 +
- net/ipv6/fib6_rules.c | 4 +++
- net/ipv6/ip6mr.c | 2 ++
- net/ipv6/route.c | 58 +++++++++++++++++++++++++++++++++++++++++-
- 9 files changed, 75 insertions(+), 1 deletion(-)
-
---- a/include/net/netns/ipv6.h
-+++ b/include/net/netns/ipv6.h
-@@ -66,6 +66,7 @@ struct netns_ipv6 {
- unsigned long ip6_rt_last_gc;
- #ifdef CONFIG_IPV6_MULTIPLE_TABLES
- struct rt6_info *ip6_prohibit_entry;
-+ struct rt6_info *ip6_policy_failed_entry;
- struct rt6_info *ip6_blk_hole_entry;
- struct fib6_table *fib6_local_tbl;
- struct fib_rules_ops *fib6_rules_ops;
---- a/include/uapi/linux/fib_rules.h
-+++ b/include/uapi/linux/fib_rules.h
-@@ -66,6 +66,10 @@ enum {
- FR_ACT_BLACKHOLE, /* Drop without notification */
- FR_ACT_UNREACHABLE, /* Drop with ENETUNREACH */
- FR_ACT_PROHIBIT, /* Drop with EACCES */
-+ FR_ACT_RES9,
-+ FR_ACT_RES10,
-+ FR_ACT_RES11,
-+ FR_ACT_POLICY_FAILED, /* Drop with EACCES */
- __FR_ACT_MAX,
- };
-
---- a/include/uapi/linux/rtnetlink.h
-+++ b/include/uapi/linux/rtnetlink.h
-@@ -215,6 +215,7 @@ enum {
- RTN_THROW, /* Not in this table */
- RTN_NAT, /* Translate this address */
- RTN_XRESOLVE, /* Use external resolver */
-+ RTN_POLICY_FAILED, /* Failed ingress/egress policy */
- __RTN_MAX
- };
-
---- a/net/ipv4/fib_semantics.c
-+++ b/net/ipv4/fib_semantics.c
-@@ -138,6 +138,10 @@ const struct fib_prop fib_props[RTN_MAX
- .error = -EINVAL,
- .scope = RT_SCOPE_NOWHERE,
- },
-+ [RTN_POLICY_FAILED] = {
-+ .error = -EACCES,
-+ .scope = RT_SCOPE_UNIVERSE,
-+ },
- };
-
- static void rt_fibinfo_free(struct rtable __rcu **rtp)
---- a/net/ipv4/fib_trie.c
-+++ b/net/ipv4/fib_trie.c
-@@ -2396,6 +2396,7 @@ static const char *const rtn_type_names[
- [RTN_THROW] = "THROW",
- [RTN_NAT] = "NAT",
- [RTN_XRESOLVE] = "XRESOLVE",
-+ [RTN_POLICY_FAILED] = "POLICY_FAILED",
- };
-
- static inline const char *rtn_type(char *buf, size_t len, unsigned int t)
---- a/net/ipv4/ipmr.c
-+++ b/net/ipv4/ipmr.c
-@@ -157,6 +157,7 @@ static int ipmr_rule_action(struct fib_r
- case FR_ACT_UNREACHABLE:
- return -ENETUNREACH;
- case FR_ACT_PROHIBIT:
-+ case FR_ACT_POLICY_FAILED:
- return -EACCES;
- case FR_ACT_BLACKHOLE:
- default:
---- a/net/ipv6/fib6_rules.c
-+++ b/net/ipv6/fib6_rules.c
-@@ -77,6 +77,10 @@ static int fib6_rule_action(struct fib_r
- err = -EACCES;
- rt = net->ipv6.ip6_prohibit_entry;
- goto discard_pkt;
-+ case FR_ACT_POLICY_FAILED:
-+ err = -EACCES;
-+ rt = net->ipv6.ip6_policy_failed_entry;
-+ goto discard_pkt;
- }
-
- tb_id = fib_rule_get_table(rule, arg);
---- a/net/ipv6/ip6mr.c
-+++ b/net/ipv6/ip6mr.c
-@@ -167,6 +167,8 @@ static int ip6mr_rule_action(struct fib_
- return -ENETUNREACH;
- case FR_ACT_PROHIBIT:
- return -EACCES;
-+ case FR_ACT_POLICY_FAILED:
-+ return -EACCES;
- case FR_ACT_BLACKHOLE:
- default:
- return -EINVAL;
---- a/net/ipv6/route.c
-+++ b/net/ipv6/route.c
-@@ -91,6 +91,8 @@ static int ip6_pkt_discard(struct sk_bu
- static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
- static int ip6_pkt_prohibit(struct sk_buff *skb);
- static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb);
-+static int ip6_pkt_policy_failed(struct sk_buff *skb);
-+static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb);
- static void ip6_link_failure(struct sk_buff *skb);
- static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
- struct sk_buff *skb, u32 mtu);
-@@ -300,6 +302,21 @@ static const struct rt6_info ip6_prohibi
- .rt6i_ref = ATOMIC_INIT(1),
- };
-
-+static const struct rt6_info ip6_policy_failed_entry_template = {
-+ .dst = {
-+ .__refcnt = ATOMIC_INIT(1),
-+ .__use = 1,
-+ .obsolete = DST_OBSOLETE_FORCE_CHK,
-+ .error = -EACCES,
-+ .input = ip6_pkt_policy_failed,
-+ .output = ip6_pkt_policy_failed_out,
-+ },
-+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
-+ .rt6i_protocol = RTPROT_KERNEL,
-+ .rt6i_metric = ~(u32) 0,
-+ .rt6i_ref = ATOMIC_INIT(1),
-+};
-+
- static const struct rt6_info ip6_blk_hole_entry_template = {
- .dst = {
- .__refcnt = ATOMIC_INIT(1),
-@@ -1967,6 +1984,11 @@ static struct rt6_info *ip6_route_info_c
- rt->dst.output = ip6_pkt_prohibit_out;
- rt->dst.input = ip6_pkt_prohibit;
- break;
-+ case RTN_POLICY_FAILED:
-+ rt->dst.error = -EACCES;
-+ rt->dst.output = ip6_pkt_policy_failed_out;
-+ rt->dst.input = ip6_pkt_policy_failed;
-+ break;
- case RTN_THROW:
- case RTN_UNREACHABLE:
- default:
-@@ -2610,6 +2632,17 @@ static int ip6_pkt_prohibit_out(struct n
- return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
- }
-
-+static int ip6_pkt_policy_failed(struct sk_buff *skb)
-+{
-+ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_INNOROUTES);
-+}
-+
-+static int ip6_pkt_policy_failed_out(struct net *net, struct sock *sk, struct sk_buff *skb)
-+{
-+ skb->dev = skb_dst(skb)->dev;
-+ return ip6_pkt_drop(skb, ICMPV6_POLICY_FAIL, IPSTATS_MIB_OUTNOROUTES);
-+}
-+
- /*
- * Allocate a dst for local (unicast / anycast) address.
- */
-@@ -2845,7 +2878,8 @@ static int rtm_to_fib6_config(struct sk_
- if (rtm->rtm_type == RTN_UNREACHABLE ||
- rtm->rtm_type == RTN_BLACKHOLE ||
- rtm->rtm_type == RTN_PROHIBIT ||
-- rtm->rtm_type == RTN_THROW)
-+ rtm->rtm_type == RTN_THROW ||
-+ rtm->rtm_type == RTN_POLICY_FAILED)
- cfg->fc_flags |= RTF_REJECT;
-
- if (rtm->rtm_type == RTN_LOCAL)
-@@ -3217,6 +3251,9 @@ static int rt6_fill_node(struct net *net
- case -EACCES:
- rtm->rtm_type = RTN_PROHIBIT;
- break;
-+ case -EPERM:
-+ rtm->rtm_type = RTN_POLICY_FAILED;
-+ break;
- case -EAGAIN:
- rtm->rtm_type = RTN_THROW;
- break;
-@@ -3493,6 +3530,8 @@ static int ip6_route_dev_notify(struct n
- #ifdef CONFIG_IPV6_MULTIPLE_TABLES
- net->ipv6.ip6_prohibit_entry->dst.dev = dev;
- net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
-+ net->ipv6.ip6_policy_failed_entry->dst.dev = dev;
-+ net->ipv6.ip6_policy_failed_entry->rt6i_idev = in6_dev_get(dev);
- net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
- net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
- #endif
-@@ -3719,6 +3758,17 @@ static int __net_init ip6_route_net_init
- net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
- dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
- ip6_template_metrics, true);
-+
-+ net->ipv6.ip6_policy_failed_entry =
-+ kmemdup(&ip6_policy_failed_entry_template,
-+ sizeof(*net->ipv6.ip6_policy_failed_entry), GFP_KERNEL);
-+ if (!net->ipv6.ip6_policy_failed_entry)
-+ goto out_ip6_blk_hole_entry;
-+ net->ipv6.ip6_policy_failed_entry->dst.path =
-+ (struct dst_entry *)net->ipv6.ip6_policy_failed_entry;
-+ net->ipv6.ip6_policy_failed_entry->dst.ops = &net->ipv6.ip6_dst_ops;
-+ dst_init_metrics(&net->ipv6.ip6_policy_failed_entry->dst,
-+ ip6_template_metrics, true);
- #endif
-
- net->ipv6.sysctl.flush_delay = 0;
-@@ -3737,6 +3787,8 @@ out:
- return ret;
-
- #ifdef CONFIG_IPV6_MULTIPLE_TABLES
-+out_ip6_blk_hole_entry:
-+ kfree(net->ipv6.ip6_blk_hole_entry);
- out_ip6_prohibit_entry:
- kfree(net->ipv6.ip6_prohibit_entry);
- out_ip6_null_entry:
-@@ -3754,6 +3806,7 @@ static void __net_exit ip6_route_net_exi
- #ifdef CONFIG_IPV6_MULTIPLE_TABLES
- kfree(net->ipv6.ip6_prohibit_entry);
- kfree(net->ipv6.ip6_blk_hole_entry);
-+ kfree(net->ipv6.ip6_policy_failed_entry);
- #endif
- dst_entries_destroy(&net->ipv6.ip6_dst_ops);
- }
-@@ -3827,6 +3880,9 @@ void __init ip6_route_init_special_entri
- init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
- init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
- init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
-+ init_net.ipv6.ip6_policy_failed_entry->dst.dev = init_net.loopback_dev;
-+ init_net.ipv6.ip6_policy_failed_entry->rt6i_idev =
-+ in6_dev_get(init_net.loopback_dev);
- #endif
- }
-
+++ /dev/null
-From: Gabor Juhos <juhosg@openwrt.org>
-Subject: net: phy: allow to configure AR803x PHYs via platform data
-
-Add a patch for the at803x phy driver, in order to be able
-to configure some register settings via platform data.
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/net/phy/at803x.c | 56 ++++++++++++++++++++++++++++++++
- include/linux/platform_data/phy-at803x.h | 11 +++++++
- 2 files changed, 67 insertions(+)
- create mode 100644 include/linux/platform_data/phy-at803x.h
-
---- a/drivers/net/phy/at803x.c
-+++ b/drivers/net/phy/at803x.c
-@@ -12,12 +12,14 @@
- */
-
- #include <linux/phy.h>
-+#include <linux/mdio.h>
- #include <linux/module.h>
- #include <linux/string.h>
- #include <linux/netdevice.h>
- #include <linux/etherdevice.h>
- #include <linux/of_gpio.h>
- #include <linux/gpio/consumer.h>
-+#include <linux/platform_data/phy-at803x.h>
-
- #define AT803X_INTR_ENABLE 0x12
- #define AT803X_INTR_ENABLE_AUTONEG_ERR BIT(15)
-@@ -45,6 +47,11 @@
- #define AT803X_REG_CHIP_CONFIG 0x1f
- #define AT803X_BT_BX_REG_SEL 0x8000
-
-+#define AT803X_PCS_SMART_EEE_CTRL3 0x805D
-+#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_MASK 0x3
-+#define AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT 12
-+#define AT803X_SMART_EEE_CTRL3_LPI_EN BIT(8)
-+
- #define AT803X_DEBUG_ADDR 0x1D
- #define AT803X_DEBUG_DATA 0x1E
-
-@@ -72,6 +79,7 @@ MODULE_LICENSE("GPL");
- struct at803x_priv {
- bool phy_reset:1;
- struct gpio_desc *gpiod_reset;
-+ int prev_speed;
- };
-
- struct at803x_context {
-@@ -276,8 +284,16 @@ does_not_require_reset_workaround:
- return 0;
- }
-
-+static void at803x_disable_smarteee(struct phy_device *phydev)
-+{
-+ phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_PCS_SMART_EEE_CTRL3,
-+ 1 << AT803X_SMART_EEE_CTRL3_LPI_TX_DELAY_SEL_SHIFT);
-+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
-+}
-+
- static int at803x_config_init(struct phy_device *phydev)
- {
-+ struct at803x_platform_data *pdata;
- int ret;
-
- ret = genphy_config_init(phydev);
-@@ -298,6 +314,26 @@ static int at803x_config_init(struct phy
- return ret;
- }
-
-+ pdata = dev_get_platdata(&phydev->mdio.dev);
-+ if (pdata) {
-+ if (pdata->disable_smarteee)
-+ at803x_disable_smarteee(phydev);
-+
-+ if (pdata->enable_rgmii_rx_delay)
-+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0, 0,
-+ AT803X_DEBUG_RX_CLK_DLY_EN);
-+ else
-+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_0,
-+ AT803X_DEBUG_RX_CLK_DLY_EN, 0);
-+
-+ if (pdata->enable_rgmii_tx_delay)
-+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0,
-+ AT803X_DEBUG_TX_CLK_DLY_EN);
-+ else
-+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5,
-+ AT803X_DEBUG_TX_CLK_DLY_EN, 0);
-+ }
-+
- return 0;
- }
-
-@@ -335,6 +371,8 @@ static int at803x_config_intr(struct phy
- static void at803x_link_change_notify(struct phy_device *phydev)
- {
- struct at803x_priv *priv = phydev->priv;
-+ struct at803x_platform_data *pdata;
-+ pdata = dev_get_platdata(&phydev->mdio.dev);
-
- /*
- * Conduct a hardware reset for AT8030/2 every time a link loss is
-@@ -363,6 +401,24 @@ static void at803x_link_change_notify(st
- } else {
- priv->phy_reset = false;
- }
-+ if (pdata && pdata->fixup_rgmii_tx_delay &&
-+ phydev->speed != priv->prev_speed) {
-+ switch (phydev->speed) {
-+ case SPEED_10:
-+ case SPEED_100:
-+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5, 0,
-+ AT803X_DEBUG_TX_CLK_DLY_EN);
-+ break;
-+ case SPEED_1000:
-+ at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_5,
-+ AT803X_DEBUG_TX_CLK_DLY_EN, 0);
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ priv->prev_speed = phydev->speed;
-+ }
- }
-
- static int at803x_aneg_done(struct phy_device *phydev)
---- /dev/null
-+++ b/include/linux/platform_data/phy-at803x.h
-@@ -0,0 +1,11 @@
-+#ifndef _PHY_AT803X_PDATA_H
-+#define _PHY_AT803X_PDATA_H
-+
-+struct at803x_platform_data {
-+ int disable_smarteee:1;
-+ int enable_rgmii_tx_delay:1;
-+ int enable_rgmii_rx_delay:1;
-+ int fixup_rgmii_tx_delay:1;
-+};
-+
-+#endif /* _PHY_AT803X_PDATA_H */
+++ /dev/null
-From: Roman Yeryomin <roman@advem.lv>
-Subject: kernel: add at803x fix for sgmii mode
-
-Some (possibly broken) bootloaders incorreclty initialize at8033
-phy. This patch enables sgmii autonegotiation mode.
-
-[john@phrozen.org: felix added this to his upstream queue]
-
-Signed-off-by: Roman Yeryomin <roman@advem.lv>
----
- drivers/net/phy/at803x.c | 25 +++++++++++++++++++++++++
- 1 file changed, 25 insertions(+)
-
---- a/drivers/net/phy/at803x.c
-+++ b/drivers/net/phy/at803x.c
-@@ -55,6 +55,10 @@
- #define AT803X_DEBUG_ADDR 0x1D
- #define AT803X_DEBUG_DATA 0x1E
-
-+#define AT803X_REG_CHIP_CONFIG 0x1f
-+#define AT803X_BT_BX_REG_SEL 0x8000
-+#define AT803X_SGMII_ANEG_EN 0x1000
-+
- #define AT803X_MODE_CFG_MASK 0x0F
- #define AT803X_MODE_CFG_SGMII 0x01
-
-@@ -295,6 +299,27 @@ static int at803x_config_init(struct phy
- {
- struct at803x_platform_data *pdata;
- int ret;
-+ u32 v;
-+
-+ if (phydev->drv->phy_id == ATH8031_PHY_ID &&
-+ phydev->interface == PHY_INTERFACE_MODE_SGMII)
-+ {
-+ v = phy_read(phydev, AT803X_REG_CHIP_CONFIG);
-+ /* select SGMII/fiber page */
-+ ret = phy_write(phydev, AT803X_REG_CHIP_CONFIG,
-+ v & ~AT803X_BT_BX_REG_SEL);
-+ if (ret)
-+ return ret;
-+ /* enable SGMII autonegotiation */
-+ ret = phy_write(phydev, MII_BMCR, AT803X_SGMII_ANEG_EN);
-+ if (ret)
-+ return ret;
-+ /* select copper page */
-+ ret = phy_write(phydev, AT803X_REG_CHIP_CONFIG,
-+ v | AT803X_BT_BX_REG_SEL);
-+ if (ret)
-+ return ret;
-+ }
-
- ret = genphy_config_init(phydev);
- if (ret < 0)
+++ /dev/null
-From: Gabor Juhos <juhosg@openwrt.org>
-Subject: debloat: add kernel config option to disabling common PCI quirks
-
-Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
----
- drivers/pci/Kconfig | 6 ++++++
- drivers/pci/quirks.c | 6 ++++++
- 2 files changed, 12 insertions(+)
-
---- a/drivers/pci/Kconfig
-+++ b/drivers/pci/Kconfig
-@@ -71,6 +71,12 @@ config XEN_PCIDEV_FRONTEND
- The PCI device frontend driver allows the kernel to import arbitrary
- PCI devices from a PCI backend to support PCI driver domains.
-
-+config PCI_DISABLE_COMMON_QUIRKS
-+ bool "PCI disable common quirks"
-+ depends on PCI
-+ help
-+ If you don't know what to do here, say N.
-+
- config HT_IRQ
- bool "Interrupts on hypertransport devices"
- default y
---- a/drivers/pci/quirks.c
-+++ b/drivers/pci/quirks.c
-@@ -41,6 +41,7 @@ static void quirk_mmio_always_on(struct
- DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_BRIDGE_HOST, 8, quirk_mmio_always_on);
-
-+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
- /* The Mellanox Tavor device gives false positive parity errors
- * Mark this device with a broken_parity_status, to allow
- * PCI scanning code to "skip" this now blacklisted device.
-@@ -3038,6 +3039,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_I
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
-
-+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
-
- /*
- * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. To
-@@ -3094,6 +3096,8 @@ static void fixup_debug_report(struct pc
- }
- }
-
-+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
-+
- /*
- * Some BIOS implementations leave the Intel GPU interrupts enabled,
- * even though no one is handling them (f.e. i915 driver is never loaded).
-@@ -3128,6 +3132,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
- DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq);
-
-+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
-+
- /*
- * PCI devices which are on Intel chips can skip the 10ms delay
- * before entering D3 mode.
+++ /dev/null
-From: Felix Fietkau <nbd@nbd.name>
-Subject: debloat: disable common USB quirks
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- drivers/usb/host/pci-quirks.c | 16 ++++++++++++++++
- drivers/usb/host/pci-quirks.h | 18 +++++++++++++++++-
- include/linux/usb/hcd.h | 7 +++++++
- 3 files changed, 40 insertions(+), 1 deletion(-)
-
---- a/drivers/usb/host/pci-quirks.c
-+++ b/drivers/usb/host/pci-quirks.c
-@@ -107,6 +107,8 @@ struct amd_chipset_type {
- u8 rev;
- };
-
-+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
-+
- static struct amd_chipset_info {
- struct pci_dev *nb_dev;
- struct pci_dev *smbus_dev;
-@@ -511,6 +513,10 @@ void usb_amd_dev_put(void)
- }
- EXPORT_SYMBOL_GPL(usb_amd_dev_put);
-
-+#endif /* CONFIG_PCI_DISABLE_COMMON_QUIRKS */
-+
-+#if IS_ENABLED(CONFIG_USB_UHCI_HCD)
-+
- /*
- * Make sure the controller is completely inactive, unable to
- * generate interrupts or do DMA.
-@@ -590,8 +596,17 @@ reset_needed:
- uhci_reset_hc(pdev, base);
- return 1;
- }
-+#else
-+int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base)
-+{
-+ return 0;
-+}
-+
-+#endif
- EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc);
-
-+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
-+
- static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask)
- {
- u16 cmd;
-@@ -1158,3 +1173,4 @@ static void quirk_usb_early_handoff(stru
- }
- DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff);
-+#endif
---- a/drivers/usb/host/pci-quirks.h
-+++ b/drivers/usb/host/pci-quirks.h
-@@ -4,6 +4,9 @@
- #ifdef CONFIG_PCI
- void uhci_reset_hc(struct pci_dev *pdev, unsigned long base);
- int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base);
-+#endif /* CONFIG_PCI */
-+
-+#if defined(CONFIG_PCI) && !defined(CONFIG_PCI_DISABLE_COMMON_QUIRKS)
- int usb_amd_find_chipset_info(void);
- int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev);
- bool usb_amd_hang_symptom_quirk(void);
-@@ -17,12 +20,25 @@ void usb_disable_xhci_ports(struct pci_d
- void sb800_prefetch(struct device *dev, int on);
- #else
- struct pci_dev;
-+static inline int usb_amd_find_chipset_info(void)
-+{
-+ return 0;
-+}
-+static inline bool usb_amd_hang_symptom_quirk(void)
-+{
-+ return false;
-+}
-+static inline bool usb_amd_prefetch_quirk(void)
-+{
-+ return false;
-+}
- static inline void usb_amd_quirk_pll_disable(void) {}
- static inline void usb_amd_quirk_pll_enable(void) {}
- static inline void usb_asmedia_modifyflowcontrol(struct pci_dev *pdev) {}
- static inline void usb_amd_dev_put(void) {}
- static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
- static inline void sb800_prefetch(struct device *dev, int on) {}
-+static inline void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) {}
- #endif /* CONFIG_PCI */
-
- #endif /* __LINUX_USB_PCI_QUIRKS_H */
---- a/include/linux/usb/hcd.h
-+++ b/include/linux/usb/hcd.h
-@@ -461,7 +461,14 @@ extern int usb_hcd_pci_probe(struct pci_
- extern void usb_hcd_pci_remove(struct pci_dev *dev);
- extern void usb_hcd_pci_shutdown(struct pci_dev *dev);
-
-+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
- extern int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev);
-+#else
-+static inline int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *dev)
-+{
-+ return 0;
-+}
-+#endif
-
- #ifdef CONFIG_PM
- extern const struct dev_pm_ops usb_hcd_pci_pm_ops;
+++ /dev/null
-From: Alexey Brodkin <abrodkin@synopsys.com>
-Subject: usb: Remove annoying warning about bogus URB
-
-When ath9k-htc Wi-Fi dongle is used with generic OHCI controller
-infinite stream of warnings appears in debug console like this:
--------------------------->8----------------------
-usb 1-1: new full-speed USB device number 2 using ohci-platform
-usb 1-1: ath9k_htc: Firmware ath9k_htc/htc_9271-1.4.0.fw requested
-usb 1-1: ath9k_htc: Transferred FW: ath9k_htc/htc_9271-1.4.0.fw, size:
-51008
-------------[ cut here ]------------
-WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449
-usb_submit_urb+0x1b4/0x498()
-usb 1-1: BOGUS urb xfer, pipe 1 != type 3
-Modules linked in:
-CPU: 0 PID: 19 Comm: kworker/0:1 Not tainted
-4.4.0-rc4-00017-g00e2d79-dirty #3
-Workqueue: events request_firmware_work_func
-
-Stack Trace:
- arc_unwind_core.constprop.1+0xa4/0x110
----[ end trace 649ef8c342817fc2 ]---
-------------[ cut here ]------------
-WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449
-usb_submit_urb+0x1b4/0x498()
-usb 1-1: BOGUS urb xfer, pipe 1 != type 3
-Modules linked in:
-CPU: 0 PID: 19 Comm: kworker/0:1 Tainted: G W
-4.4.0-rc4-00017-g00e2d79-dirty #3
-Workqueue: events request_firmware_work_func
-
-Stack Trace:
- arc_unwind_core.constprop.1+0xa4/0x110
----[ end trace 649ef8c342817fc3 ]---
-------------[ cut here ]------------
--------------------------->8----------------------
-
-There're some discussions in mailing lists proposing to disable
-that particular check alltogether and magically all seem to work
-fine with muted warning.
-
-Anyways new thread on that regard could be found here:
-http://lists.infradead.org/pipermail/linux-snps-arc/2016-July/001310.html
-
-Let's see what comes out of that new discussion, hopefully patching
-of generic USB stuff won't be required then.
-
-Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
----
- drivers/usb/core/urb.c | 5 -----
- 1 file changed, 5 deletions(-)
-
---- a/drivers/usb/core/urb.c
-+++ b/drivers/usb/core/urb.c
-@@ -321,9 +321,6 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb);
- */
- int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
- {
-- static int pipetypes[4] = {
-- PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
-- };
- int xfertype, max;
- struct usb_device *dev;
- struct usb_host_endpoint *ep;
-@@ -441,11 +438,6 @@ int usb_submit_urb(struct urb *urb, gfp_
- * cause problems in HCDs if they get it wrong.
- */
-
-- /* Check that the pipe's type matches the endpoint's type */
-- if (usb_pipetype(urb->pipe) != pipetypes[xfertype])
-- dev_WARN(&dev->dev, "BOGUS urb xfer, pipe %x != type %x\n",
-- usb_pipetype(urb->pipe), pipetypes[xfertype]);
--
- /* Check against a simple/standard policy */
- allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT | URB_DIR_MASK |
- URB_FREE_BUFFER);
+++ /dev/null
-From: Alexey Brodkin <abrodkin@synopsys.com>
-Subject: usb: Remove annoying warning about bogus URB
-
-When ath9k-htc Wi-Fi dongle is used with generic OHCI controller
-infinite stream of warnings appears in debug console like this:
--------------------------->8----------------------
-usb 1-1: new full-speed USB device number 2 using ohci-platform
-usb 1-1: ath9k_htc: Firmware ath9k_htc/htc_9271-1.4.0.fw requested
-usb 1-1: ath9k_htc: Transferred FW: ath9k_htc/htc_9271-1.4.0.fw, size:
-51008
-------------[ cut here ]------------
-WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449
-usb_submit_urb+0x1b4/0x498()
-usb 1-1: BOGUS urb xfer, pipe 1 != type 3
-Modules linked in:
-CPU: 0 PID: 19 Comm: kworker/0:1 Not tainted
-4.4.0-rc4-00017-g00e2d79-dirty #3
-Workqueue: events request_firmware_work_func
-
-Stack Trace:
-arc_unwind_core.constprop.1+0xa4/0x110
----[ end trace 649ef8c342817fc2 ]---
-------------[ cut here ]------------
-WARNING: CPU: 0 PID: 19 at drivers/usb/core/urb.c:449
-usb_submit_urb+0x1b4/0x498()
-usb 1-1: BOGUS urb xfer, pipe 1 != type 3
-Modules linked in:
-CPU: 0 PID: 19 Comm: kworker/0:1 Tainted: G W
-4.4.0-rc4-00017-g00e2d79-dirty #3
-Workqueue: events request_firmware_work_func
-
-Stack Trace:
-arc_unwind_core.constprop.1+0xa4/0x110
----[ end trace 649ef8c342817fc3 ]---
-------------[ cut here ]------------
--------------------------->8----------------------
-
-There're some discussions in mailing lists proposing to disable
-that particular check alltogether and magically all seem to work
-fine with muted warning.
-
-Anyways new thread on that regard could be found here:
-http://lists.infradead.org/pipermail/linux-snps-arc/2016-July/001310.html
-
-Let's see what comes out of that new discussion, hopefully patching
-of generic USB stuff won't be required then.
-
-Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
----
- drivers/leds/Makefile | 1 +
- drivers/leds/trigger/Kconfig | 7 +++++++
- 2 files changed, 8 insertions(+)
-
---- a/drivers/leds/Makefile
-+++ b/drivers/leds/Makefile
-@@ -77,3 +77,4 @@ obj-$(CONFIG_LEDS_DAC124S085) += leds-d
-
- # LED Triggers
- obj-$(CONFIG_LEDS_TRIGGERS) += trigger/
-+obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
---- a/drivers/leds/trigger/Kconfig
-+++ b/drivers/leds/trigger/Kconfig
-@@ -126,4 +126,11 @@ config LEDS_TRIGGER_PANIC
- a different trigger.
- If unsure, say Y.
-
-+config LEDS_TRIGGER_NETDEV
-+ tristate "LED Netdev Trigger"
-+ depends on NET && LEDS_TRIGGERS
-+ help
-+ This allows LEDs to be controlled by network device activity.
-+ If unsure, say Y.
-+
- endif # LEDS_TRIGGERS
+++ /dev/null
-From: Daniel Golle <daniel@makrotopia.org>
-Subject: libata: add ledtrig support
-
-This adds a LED trigger for each ATA port indicating disk activity.
-
-As this is needed only on specific platforms (NAS SoCs and such),
-these platforms should define ARCH_WANTS_LIBATA_LEDS if there
-are boards with LED(s) intended to indicate ATA disk activity and
-need the OS to take care of that.
-In that way, if not selected, LED trigger support not will be
-included in libata-core and both, codepaths and structures remain
-untouched.
-
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
- drivers/ata/Kconfig | 16 ++++++++++++++++
- drivers/ata/libata-core.c | 41 +++++++++++++++++++++++++++++++++++++++++
- include/linux/libata.h | 9 +++++++++
- 3 files changed, 66 insertions(+)
-
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -46,6 +46,22 @@ config ATA_VERBOSE_ERROR
-
- If unsure, say Y.
-
-+config ARCH_WANT_LIBATA_LEDS
-+ bool
-+
-+config ATA_LEDS
-+ bool "support ATA port LED triggers"
-+ depends on ARCH_WANT_LIBATA_LEDS
-+ select NEW_LEDS
-+ select LEDS_CLASS
-+ select LEDS_TRIGGERS
-+ default y
-+ help
-+ This option adds a LED trigger for each registered ATA port.
-+ It is used to drive disk activity leds connected via GPIO.
-+
-+ If unsure, say N.
-+
- config ATA_ACPI
- bool "ATA ACPI Support"
- depends on ACPI
---- a/drivers/ata/libata-core.c
-+++ b/drivers/ata/libata-core.c
-@@ -731,6 +731,19 @@ u64 ata_tf_read_block(const struct ata_t
- return block;
- }
-
-+#ifdef CONFIG_ATA_LEDS
-+#define LIBATA_BLINK_DELAY 20 /* ms */
-+static inline void ata_led_act(struct ata_port *ap)
-+{
-+ unsigned long led_delay = LIBATA_BLINK_DELAY;
-+
-+ if (unlikely(!ap->ledtrig))
-+ return;
-+
-+ led_trigger_blink_oneshot(ap->ledtrig, &led_delay, &led_delay, 0);
-+}
-+#endif
-+
- /**
- * ata_build_rw_tf - Build ATA taskfile for given read/write request
- * @tf: Target ATA taskfile
-@@ -4985,6 +4998,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
- if (tag < 0)
- return NULL;
- }
-+#ifdef CONFIG_ATA_LEDS
-+ ata_led_act(ap);
-+#endif
-
- qc = __ata_qc_from_tag(ap, tag);
- qc->tag = tag;
-@@ -5886,6 +5902,9 @@ struct ata_port *ata_port_alloc(struct a
- ap->stats.unhandled_irq = 1;
- ap->stats.idle_irq = 1;
- #endif
-+#ifdef CONFIG_ATA_LEDS
-+ ap->ledtrig = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
-+#endif
- ata_sff_port_init(ap);
-
- return ap;
-@@ -5907,6 +5926,12 @@ static void ata_host_release(struct devi
-
- kfree(ap->pmp_link);
- kfree(ap->slave_link);
-+#ifdef CONFIG_ATA_LEDS
-+ if (ap->ledtrig) {
-+ led_trigger_unregister(ap->ledtrig);
-+ kfree(ap->ledtrig);
-+ };
-+#endif
- kfree(ap);
- host->ports[i] = NULL;
- }
-@@ -6353,7 +6378,23 @@ int ata_host_register(struct ata_host *h
- host->ports[i]->print_id = atomic_inc_return(&ata_print_id);
- host->ports[i]->local_port_no = i + 1;
- }
-+#ifdef CONFIG_ATA_LEDS
-+ for (i = 0; i < host->n_ports; i++) {
-+ if (unlikely(!host->ports[i]->ledtrig))
-+ continue;
-
-+ snprintf(host->ports[i]->ledtrig_name,
-+ sizeof(host->ports[i]->ledtrig_name), "ata%u",
-+ host->ports[i]->print_id);
-+
-+ host->ports[i]->ledtrig->name = host->ports[i]->ledtrig_name;
-+
-+ if (led_trigger_register(host->ports[i]->ledtrig)) {
-+ kfree(host->ports[i]->ledtrig);
-+ host->ports[i]->ledtrig = NULL;
-+ }
-+ }
-+#endif
- /* Create associated sysfs transport objects */
- for (i = 0; i < host->n_ports; i++) {
- rc = ata_tport_add(host->dev,host->ports[i]);
---- a/include/linux/libata.h
-+++ b/include/linux/libata.h
-@@ -38,6 +38,9 @@
- #include <linux/acpi.h>
- #include <linux/cdrom.h>
- #include <linux/sched.h>
-+#ifdef CONFIG_ATA_LEDS
-+#include <linux/leds.h>
-+#endif
-
- /*
- * Define if arch has non-standard setup. This is a _PCI_ standard
-@@ -883,6 +886,12 @@ struct ata_port {
- #ifdef CONFIG_ATA_ACPI
- struct ata_acpi_gtm __acpi_init_gtm; /* use ata_acpi_init_gtm() */
- #endif
-+
-+#ifdef CONFIG_ATA_LEDS
-+ struct led_trigger *ledtrig;
-+ char ledtrig_name[8];
-+#endif
-+
- /* owned by EH */
- u8 sector_buf[ATA_SECT_SIZE] ____cacheline_aligned;
- };
+++ /dev/null
-From: John Crispin <john@phrozen.org>
-Subject: serial: do not accept sysrq characters via serial port
-
-many embedded boards have a disconnected TTL level serial which can
-generate some garbage that can lead to spurious false sysrq detects.
-
-[john@phrozen.org: sent upstream 22.12.2016]
-
-Signed-off-by: John Crispin <john@phrozen.org>
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
- include/linux/serial_core.h | 2 +-
- lib/Kconfig.debug | 5 +++++
- 2 files changed, 6 insertions(+), 1 deletion(-)
-
---- a/include/linux/serial_core.h
-+++ b/include/linux/serial_core.h
-@@ -448,7 +448,7 @@ extern void uart_handle_cts_change(struc
- extern void uart_insert_char(struct uart_port *port, unsigned int status,
- unsigned int overrun, unsigned int ch, unsigned int flag);
-
--#ifdef SUPPORT_SYSRQ
-+#if defined(SUPPORT_SYSRQ) && defined(CONFIG_MAGIC_SYSRQ_SERIAL)
- static inline int
- uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
- {
---- a/lib/Kconfig.debug
-+++ b/lib/Kconfig.debug
-@@ -396,6 +396,11 @@ config MAGIC_SYSRQ_DEFAULT_ENABLE
- This may be set to 1 or 0 to enable or disable them all, or
- to a bitmask as described in Documentation/sysrq.txt.
-
-+config MAGIC_SYSRQ_SERIAL
-+ bool "Enable magic SysRq key over serial"
-+ depends on MAGIC_SYSRQ
-+ default y
-+
- config DEBUG_KERNEL
- bool "Kernel debugging"
- help