+++ /dev/null
-From b00b5eafa7e8d059bd0ce844e66f648916953270 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 3 Jan 2016 19:11:22 +0100
-Subject: [PATCH 2/3] phy: ralink-usb: add driver for Mediatek/Ralink
-
-Add a driver to setup the USB phy on Mediatek/Ralink SoCs.
-The driver is trivial and only sets up power and host mode.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- .../devicetree/bindings/phy/ralink-usb-phy.txt | 17 ++
- drivers/phy/Kconfig | 8 +
- drivers/phy/Makefile | 1 +
- drivers/phy/phy-ralink-usb.c | 171 ++++++++++++++++++++
- 4 files changed, 197 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/phy/ralink-usb-phy.txt
- create mode 100644 drivers/phy/phy-ralink-usb.c
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/phy/ralink-usb-phy.txt
-@@ -0,0 +1,17 @@
-+Mediatek/Ralink USB PHY
-+
-+Required properties:
-+ - compatible: ralink,rt3352-usbphy or mediatek,mt7620-usbphy
-+ - #phy-cells: should be 0
-+ - resets: the two reset controllers for host and device
-+ - reset-names: the names of the 2 reset controllers
-+
-+Example:
-+
-+usbphy: phy {
-+ compatible = "mediatek,mt7620-usbphy";
-+ #phy-cells = <0>;
-+
-+ resets = <&rstctrl 22 &rstctrl 25>;
-+ reset-names = "host", "device";
-+};
---- a/drivers/phy/Kconfig
-+++ b/drivers/phy/Kconfig
-@@ -429,6 +429,14 @@ config PHY_XGENE
- help
- This option enables support for APM X-Gene SoC multi-purpose PHY.
-
-+config PHY_RALINK_USB
-+ tristate "Ralink USB PHY driver"
-+ select GENERIC_PHY
-+ depends on RALINK
-+ help
-+ This option enables support for the Ralink USB PHY found inside
-+ RT3352 and MT7620.
-+
- config PHY_STIH407_USB
- tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family"
- depends on RESET_CONTROLLER
---- a/drivers/phy/Makefile
-+++ b/drivers/phy/Makefile
-@@ -60,3 +60,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-
- obj-$(CONFIG_PHY_CYGNUS_PCIE) += phy-bcm-cygnus-pcie.o
- obj-$(CONFIG_ARCH_TEGRA) += tegra/
- obj-$(CONFIG_PHY_NS2_PCIE) += phy-bcm-ns2-pcie.o
-+obj-$(CONFIG_PHY_RALINK_USB) += phy-ralink-usb.o
---- /dev/null
-+++ b/drivers/phy/phy-ralink-usb.c
-@@ -0,0 +1,228 @@
-+/*
-+ * Allwinner ralink USB phy driver
-+ *
-+ * Copyright (C) 2016 John Crispin <blogic@openwrt.org>
-+ *
-+ * Based on code from
-+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
-+ *
-+ * 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/delay.h>
-+#include <linux/err.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/mutex.h>
-+#include <linux/phy/phy.h>
-+#include <linux/platform_device.h>
-+#include <linux/reset.h>
-+#include <linux/of_platform.h>
-+
-+#include <asm/mach-ralink/ralink_regs.h>
-+
-+#define RT_SYSC_REG_SYSCFG1 0x014
-+#define RT_SYSC_REG_CLKCFG1 0x030
-+#define RT_SYSC_REG_USB_PHY_CFG 0x05c
-+
-+#define OFS_U2_PHY_AC0 0x800
-+#define OFS_U2_PHY_AC1 0x804
-+#define OFS_U2_PHY_AC2 0x808
-+#define OFS_U2_PHY_ACR0 0x810
-+#define OFS_U2_PHY_ACR1 0x814
-+#define OFS_U2_PHY_ACR2 0x818
-+#define OFS_U2_PHY_ACR3 0x81C
-+#define OFS_U2_PHY_ACR4 0x820
-+#define OFS_U2_PHY_AMON0 0x824
-+#define OFS_U2_PHY_DCR0 0x860
-+#define OFS_U2_PHY_DCR1 0x864
-+#define OFS_U2_PHY_DTM0 0x868
-+#define OFS_U2_PHY_DTM1 0x86C
-+
-+#define RT_RSTCTRL_UDEV BIT(25)
-+#define RT_RSTCTRL_UHST BIT(22)
-+#define RT_SYSCFG1_USB0_HOST_MODE BIT(10)
-+
-+#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25)
-+#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22)
-+#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20)
-+#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18)
-+
-+#define USB_PHY_UTMI_8B60M BIT(1)
-+#define UDEV_WAKEUP BIT(0)
-+
-+struct ralink_usb_phy {
-+ struct reset_control *rstdev;
-+ struct reset_control *rsthost;
-+ u32 clk;
-+ struct phy *phy;
-+ void __iomem *base;
-+};
-+
-+static void u2_phy_w32(struct ralink_usb_phy *phy, u32 val, u32 reg)
-+{
-+ iowrite32(val, phy->base + reg);
-+}
-+
-+static u32 u2_phy_r32(struct ralink_usb_phy *phy, u32 reg)
-+{
-+ return ioread32(phy->base + reg);
-+}
-+
-+static void
-+u2_phy_init(struct ralink_usb_phy *phy)
-+{
-+ u2_phy_r32(phy, OFS_U2_PHY_AC2);
-+ u2_phy_r32(phy, OFS_U2_PHY_ACR0);
-+ u2_phy_r32(phy, OFS_U2_PHY_DCR0);
-+
-+ u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
-+ u2_phy_r32(phy, OFS_U2_PHY_DCR0);
-+ u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
-+ u2_phy_r32(phy, OFS_U2_PHY_DCR0);
-+ u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
-+ u2_phy_r32(phy, OFS_U2_PHY_DCR0);
-+ u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
-+ u2_phy_r32(phy, OFS_U2_PHY_DCR0);
-+ u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
-+ u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
-+ u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
-+ u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
-+}
-+
-+static int ralink_usb_phy_power_on(struct phy *_phy)
-+{
-+ struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
-+ u32 t;
-+
-+ /* enable the phy */
-+ rt_sysc_m32(0, phy->clk, RT_SYSC_REG_CLKCFG1);
-+
-+ /* setup host mode */
-+ rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1);
-+
-+ /* deassert the reset lines */
-+ reset_control_deassert(phy->rsthost);
-+ reset_control_deassert(phy->rstdev);
-+
-+ /*
-+ * The SDK kernel had a delay of 100ms. however on device
-+ * testing showed that 10ms is enough
-+ */
-+ mdelay(10);
-+
-+ if (!IS_ERR(phy->base))
-+ u2_phy_init(phy);
-+
-+ /* print some status info */
-+ t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG);
-+ dev_info(&phy->phy->dev, "remote usb device wakeup %s\n",
-+ (t & UDEV_WAKEUP) ? ("enabled") : ("disabled"));
-+ if (t & USB_PHY_UTMI_8B60M)
-+ dev_info(&phy->phy->dev, "UTMI 8bit 60MHz\n");
-+ else
-+ dev_info(&phy->phy->dev, "UTMI 16bit 30MHz\n");
-+
-+ return 0;
-+}
-+
-+static int ralink_usb_phy_power_off(struct phy *_phy)
-+{
-+ struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
-+
-+ /* assert the reset lines */
-+ reset_control_assert(phy->rstdev);
-+ reset_control_assert(phy->rsthost);
-+
-+ /* disable the phy */
-+ rt_sysc_m32(phy->clk, 0, RT_SYSC_REG_CLKCFG1);
-+
-+ return 0;
-+}
-+
-+static struct phy_ops ralink_usb_phy_ops = {
-+ .power_on = ralink_usb_phy_power_on,
-+ .power_off = ralink_usb_phy_power_off,
-+ .owner = THIS_MODULE,
-+};
-+
-+static const struct of_device_id ralink_usb_phy_of_match[] = {
-+ {
-+ .compatible = "ralink,rt3352-usbphy",
-+ .data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN |
-+ RT_CLKCFG1_UPHY0_CLK_EN)
-+ },
-+ {
-+ .compatible = "mediatek,mt7620-usbphy",
-+ .data = (void *) (MT7620_CLKCFG1_UPHY1_CLK_EN |
-+ MT7620_CLKCFG1_UPHY0_CLK_EN) },
-+ { },
-+};
-+MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match);
-+
-+static int ralink_usb_phy_probe(struct platform_device *pdev)
-+{
-+ struct resource *res;
-+ struct device *dev = &pdev->dev;
-+ struct phy_provider *phy_provider;
-+ const struct of_device_id *match;
-+ struct ralink_usb_phy *phy;
-+
-+ phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
-+ if (!phy)
-+ return -ENOMEM;
-+
-+ match = of_match_device(ralink_usb_phy_of_match, &pdev->dev);
-+ if (!match)
-+ return -ENODEV;
-+
-+ phy->clk = (int) match->data;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ phy->base = devm_ioremap_resource(&pdev->dev, res);
-+
-+ phy->rsthost = devm_reset_control_get(&pdev->dev, "host");
-+ if (IS_ERR(phy->rsthost)) {
-+ dev_err(dev, "host reset is missing\n");
-+ return PTR_ERR(phy->rsthost);
-+ }
-+
-+ phy->rstdev = devm_reset_control_get(&pdev->dev, "device");
-+ if (IS_ERR(phy->rstdev)) {
-+ dev_err(dev, "device reset is missing\n");
-+ return PTR_ERR(phy->rstdev);
-+ }
-+
-+ phy->phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops);
-+ if (IS_ERR(phy->phy)) {
-+ dev_err(dev, "failed to create PHY\n");
-+ return PTR_ERR(phy->phy);
-+ }
-+ phy_set_drvdata(phy->phy, phy);
-+
-+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-+
-+ return PTR_ERR_OR_ZERO(phy_provider);
-+}
-+
-+static struct platform_driver ralink_usb_phy_driver = {
-+ .probe = ralink_usb_phy_probe,
-+ .driver = {
-+ .of_match_table = ralink_usb_phy_of_match,
-+ .name = "ralink-usb-phy",
-+ }
-+};
-+module_platform_driver(ralink_usb_phy_driver);
-+
-+MODULE_DESCRIPTION("Ralink USB phy driver");
-+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
-+MODULE_LICENSE("GPL v2");
+++ /dev/null
-From 975e76214cd2516eb6cfff4c3eec581872645e88 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Thu, 19 Sep 2013 01:50:59 +0200
-Subject: [PATCH 31/53] uvc: add iPassion iP2970 support
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/media/usb/uvc/uvc_driver.c | 12 +++
- drivers/media/usb/uvc/uvc_status.c | 2 +
- drivers/media/usb/uvc/uvc_video.c | 147 ++++++++++++++++++++++++++++++++++++
- drivers/media/usb/uvc/uvcvideo.h | 5 +-
- 4 files changed, 165 insertions(+), 1 deletion(-)
-
---- a/drivers/media/usb/uvc/uvc_driver.c
-+++ b/drivers/media/usb/uvc/uvc_driver.c
-@@ -2670,6 +2670,18 @@ static struct usb_device_id uvc_ids[] =
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_FORCE_Y8 },
-+ /* iPassion iP2970 */
-+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
-+ | USB_DEVICE_ID_MATCH_INT_INFO,
-+ .idVendor = 0x1B3B,
-+ .idProduct = 0x2970,
-+ .bInterfaceClass = USB_CLASS_VIDEO,
-+ .bInterfaceSubClass = 1,
-+ .bInterfaceProtocol = 0,
-+ .driver_info = UVC_QUIRK_PROBE_MINMAX
-+ | UVC_QUIRK_STREAM_NO_FID
-+ | UVC_QUIRK_MOTION
-+ | UVC_QUIRK_SINGLE_ISO },
- /* Generic USB Video Class */
- { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
- { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
---- a/drivers/media/usb/uvc/uvc_status.c
-+++ b/drivers/media/usb/uvc/uvc_status.c
-@@ -139,6 +139,7 @@ static void uvc_status_complete(struct u
- switch (dev->status[0] & 0x0f) {
- case UVC_STATUS_TYPE_CONTROL:
- uvc_event_control(dev, dev->status, len);
-+ dev->motion = 1;
- break;
-
- case UVC_STATUS_TYPE_STREAMING:
-@@ -182,6 +183,7 @@ int uvc_status_init(struct uvc_device *d
- }
-
- pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress);
-+ dev->motion = 0;
-
- /* For high-speed interrupt endpoints, the bInterval value is used as
- * an exponent of two. Some developers forgot about it.
---- a/drivers/media/usb/uvc/uvc_video.c
-+++ b/drivers/media/usb/uvc/uvc_video.c
-@@ -21,6 +21,11 @@
- #include <linux/wait.h>
- #include <linux/atomic.h>
- #include <asm/unaligned.h>
-+#include <linux/skbuff.h>
-+#include <linux/kobject.h>
-+#include <linux/netlink.h>
-+#include <linux/kobject.h>
-+#include <linux/workqueue.h>
-
- #include <media/v4l2-common.h>
-
-@@ -1087,9 +1092,149 @@ static void uvc_video_decode_data(struct
- }
- }
-
-+struct bh_priv {
-+ unsigned long seen;
-+};
-+
-+struct bh_event {
-+ const char *name;
-+ struct sk_buff *skb;
-+ struct work_struct work;
-+};
-+
-+#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, "webcam", ##args )
-+#define BH_DBG(fmt, args...) do {} while (0)
-+#define BH_SKB_SIZE 2048
-+
-+extern u64 uevent_next_seqnum(void);
-+static int seen = 0;
-+
-+static int bh_event_add_var(struct bh_event *event, int argv,
-+ const char *format, ...)
-+{
-+ static char buf[128];
-+ char *s;
-+ va_list args;
-+ int len;
-+
-+ if (argv)
-+ return 0;
-+
-+ va_start(args, format);
-+ len = vsnprintf(buf, sizeof(buf), format, args);
-+ va_end(args);
-+
-+ if (len >= sizeof(buf)) {
-+ BH_ERR("buffer size too small\n");
-+ WARN_ON(1);
-+ return -ENOMEM;
-+ }
-+
-+ s = skb_put(event->skb, len + 1);
-+ strcpy(s, buf);
-+
-+ BH_DBG("added variable '%s'\n", s);
-+
-+ return 0;
-+}
-+
-+static int motion_hotplug_fill_event(struct bh_event *event)
-+{
-+ int s = jiffies;
-+ int ret;
-+
-+ if (!seen)
-+ seen = jiffies;
-+
-+ ret = bh_event_add_var(event, 0, "HOME=%s", "/");
-+ if (ret)
-+ return ret;
-+
-+ ret = bh_event_add_var(event, 0, "PATH=%s",
-+ "/sbin:/bin:/usr/sbin:/usr/bin");
-+ if (ret)
-+ return ret;
-+
-+ ret = bh_event_add_var(event, 0, "SUBSYSTEM=usb");
-+ if (ret)
-+ return ret;
-+
-+ ret = bh_event_add_var(event, 0, "ACTION=motion");
-+ if (ret)
-+ return ret;
-+
-+ ret = bh_event_add_var(event, 0, "SEEN=%d", s - seen);
-+ if (ret)
-+ return ret;
-+ seen = s;
-+
-+ ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum());
-+
-+ return ret;
-+}
-+
-+static void motion_hotplug_work(struct work_struct *work)
-+{
-+ struct bh_event *event = container_of(work, struct bh_event, work);
-+ int ret = 0;
-+
-+ event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL);
-+ if (!event->skb)
-+ goto out_free_event;
-+
-+ ret = bh_event_add_var(event, 0, "%s@", "add");
-+ if (ret)
-+ goto out_free_skb;
-+
-+ ret = motion_hotplug_fill_event(event);
-+ if (ret)
-+ goto out_free_skb;
-+
-+ NETLINK_CB(event->skb).dst_group = 1;
-+ broadcast_uevent(event->skb, 0, 1, GFP_KERNEL);
-+
-+out_free_skb:
-+ if (ret) {
-+ BH_ERR("work error %d\n", ret);
-+ kfree_skb(event->skb);
-+ }
-+out_free_event:
-+ kfree(event);
-+}
-+
-+static int motion_hotplug_create_event(void)
-+{
-+ struct bh_event *event;
-+
-+ event = kzalloc(sizeof(*event), GFP_KERNEL);
-+ if (!event)
-+ return -ENOMEM;
-+
-+ event->name = "motion";
-+
-+ INIT_WORK(&event->work, (void *)(void *)motion_hotplug_work);
-+ schedule_work(&event->work);
-+
-+ return 0;
-+}
-+
-+#define MOTION_FLAG_OFFSET 4
- static void uvc_video_decode_end(struct uvc_streaming *stream,
- struct uvc_buffer *buf, const __u8 *data, int len)
- {
-+ if ((stream->dev->quirks & UVC_QUIRK_MOTION) &&
-+ (data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) {
-+ u8 *mem;
-+ buf->state = UVC_BUF_STATE_READY;
-+ mem = (u8 *) (buf->mem + MOTION_FLAG_OFFSET);
-+ if ( stream->dev->motion ) {
-+ stream->dev->motion = 0;
-+ motion_hotplug_create_event();
-+ } else {
-+ *mem &= 0x7f;
-+ }
-+ }
-+
- /* Mark the buffer as done if the EOF marker is set. */
- if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) {
- uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n");
-@@ -1503,6 +1648,8 @@ static int uvc_init_video_isoc(struct uv
- if (npackets == 0)
- return -ENOMEM;
-
-+ if (stream->dev->quirks & UVC_QUIRK_SINGLE_ISO)
-+ npackets = 1;
- size = npackets * psize;
-
- for (i = 0; i < UVC_URBS; ++i) {
---- a/drivers/media/usb/uvc/uvcvideo.h
-+++ b/drivers/media/usb/uvc/uvcvideo.h
-@@ -164,7 +164,9 @@
- #define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200
- #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400
- #define UVC_QUIRK_FORCE_Y8 0x00000800
--
-+#define UVC_QUIRK_MOTION 0x00001000
-+#define UVC_QUIRK_SINGLE_ISO 0x00002000
-+
- /* Format flags */
- #define UVC_FMT_FLAG_COMPRESSED 0x00000001
- #define UVC_FMT_FLAG_STREAM 0x00000002
-@@ -562,6 +564,7 @@ struct uvc_device {
- __u8 *status;
- struct input_dev *input;
- char input_phys[64];
-+ int motion;
- };
-
- enum uvc_handle_state {
+++ /dev/null
-From a758e0870c6d1e4b0272f6e7f9efa9face5534bb Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sun, 27 Jul 2014 09:49:07 +0100
-Subject: [PATCH 32/53] USB: dwc2: add device_reset()
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/usb/dwc2/hcd.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/usb/dwc2/hcd.c
-+++ b/drivers/usb/dwc2/hcd.c
-@@ -47,6 +47,7 @@
- #include <linux/io.h>
- #include <linux/slab.h>
- #include <linux/usb.h>
-+#include <linux/reset.h>
-
- #include <linux/usb/hcd.h>
- #include <linux/usb/ch11.h>
-@@ -4983,6 +4984,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso
-
- retval = -ENOMEM;
-
-+ device_reset(hsotg->dev);
-+
- hcfg = dwc2_readl(hsotg->regs + HCFG);
- dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg);
-
+++ /dev/null
-From 8e72a3a1be8f6328bd7ef491332ba541547b6086 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 15 Jul 2013 00:38:51 +0200
-Subject: [PATCH 36/53] mtd: fix cfi cmdset 0002 erase status check
-
----
- drivers/mtd/chips/cfi_cmdset_0002.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/mtd/chips/cfi_cmdset_0002.c
-+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -2289,7 +2289,7 @@ static int __xipram do_erase_chip(struct
- chip->erase_suspended = 0;
- }
-
-- if (chip_ready(map, adr))
-+ if (chip_good(map, adr, map_word_ff(map)))
- break;
-
- if (time_after(jiffies, timeo)) {
-@@ -2378,7 +2378,7 @@ static int __xipram do_erase_oneblock(st
- chip->erase_suspended = 0;
- }
-
-- if (chip_ready(map, adr)) {
-+ if (chip_good(map, adr, map_word_ff(map))) {
- xip_enable(map, chip, adr);
- break;
- }
+++ /dev/null
-From ee9081b2726a5ca8cde5497afdc5425e21ff8f8b Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 15 Jul 2013 00:39:21 +0200
-Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write
-
----
- drivers/mtd/chips/cfi_cmdset_0002.c | 9 +++++++--
- 1 file changed, 7 insertions(+), 2 deletions(-)
-
---- a/drivers/mtd/chips/cfi_cmdset_0002.c
-+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
-@@ -40,7 +40,7 @@
- #include <linux/mtd/xip.h>
-
- #define AMD_BOOTLOC_BUG
--#define FORCE_WORD_WRITE 0
-+#define FORCE_WORD_WRITE 1
-
- #define MAX_WORD_RETRIES 3
-
-@@ -51,7 +51,9 @@
-
- static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
- static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
-+#if !FORCE_WORD_WRITE
- static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
-+#endif
- static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *);
- static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *);
- static void cfi_amdstd_sync (struct mtd_info *);
-@@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m
- }
- #endif
-
-+#if !FORCE_WORD_WRITE
- static void fixup_use_write_buffers(struct mtd_info *mtd)
- {
- struct map_info *map = mtd->priv;
-@@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru
- mtd->_write = cfi_amdstd_write_buffers;
- }
- }
-+#endif /* !FORCE_WORD_WRITE */
-
- /* Atmel chips don't use the same PRI format as AMD chips */
- static void fixup_convert_atmel_pri(struct mtd_info *mtd)
-@@ -1787,6 +1791,7 @@ static int cfi_amdstd_write_words(struct
- /*
- * FIXME: interleaved mode not tested, and probably not supported!
- */
-+#if !FORCE_WORD_WRITE
- static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
- unsigned long adr, const u_char *buf,
- int len)
-@@ -1915,7 +1920,6 @@ static int __xipram do_write_buffer(stru
- return ret;
- }
-
--
- static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
- {
-@@ -1990,6 +1994,7 @@ static int cfi_amdstd_write_buffers(stru
-
- return 0;
- }
-+#endif /* !FORCE_WORD_WRITE */
-
- /*
- * Wait for the flash chip to become ready to write data
+++ /dev/null
-From da6015e7f19d749f135f7ac55c4ec47b06faa868 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Fri, 9 Aug 2013 20:12:59 +0200
-Subject: [PATCH 41/53] DT: Add documentation for spi-rt2880
-
-Describe the SPI master found on the MIPS based Ralink RT2880 SoC.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- .../devicetree/bindings/spi/spi-rt2880.txt | 28 ++++++++++++++++++++
- 1 file changed, 28 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/spi/spi-rt2880.txt
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/spi/spi-rt2880.txt
-@@ -0,0 +1,28 @@
-+Ralink SoC RT2880 SPI master controller.
-+
-+This SPI controller is found on most wireless SoCs made by ralink.
-+
-+Required properties:
-+- compatible : "ralink,rt2880-spi"
-+- reg : The register base for the controller.
-+- #address-cells : <1>, as required by generic SPI binding.
-+- #size-cells : <0>, also as required by generic SPI binding.
-+
-+Child nodes as per the generic SPI binding.
-+
-+Example:
-+
-+ spi@b00 {
-+ compatible = "ralink,rt2880-spi";
-+ reg = <0xb00 0x100>;
-+
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ m25p80@0 {
-+ compatible = "m25p80";
-+ reg = <0>;
-+ spi-max-frequency = <10000000>;
-+ };
-+ };
-+
+++ /dev/null
-From fc8f96309c21c1bc3276427309cd7d361347d66e Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Mon, 7 Dec 2015 17:16:50 +0100
-Subject: [PATCH 52/53] pwm: add mediatek support
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
----
- drivers/pwm/Kconfig | 9 +++
- drivers/pwm/Makefile | 1 +
- drivers/pwm/pwm-mediatek.c | 173 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 183 insertions(+)
- create mode 100644 drivers/pwm/pwm-mediatek.c
-
---- a/drivers/pwm/Kconfig
-+++ b/drivers/pwm/Kconfig
-@@ -282,6 +282,15 @@ config PWM_MTK_DISP
- To compile this driver as a module, choose M here: the module
- will be called pwm-mtk-disp.
-
-+config PWM_MEDIATEK
-+ tristate "Mediatek PWM support"
-+ depends on RALINK && OF
-+ help
-+ Generic PWM framework driver for Mediatek ARM SoC.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called pwm-mxs.
-+
- config PWM_MXS
- tristate "Freescale MXS PWM support"
- depends on ARCH_MXS && OF
---- a/drivers/pwm/Makefile
-+++ b/drivers/pwm/Makefile
-@@ -25,6 +25,7 @@ obj-$(CONFIG_PWM_LPSS) += pwm-lpss.o
- obj-$(CONFIG_PWM_LPSS_PCI) += pwm-lpss-pci.o
- obj-$(CONFIG_PWM_LPSS_PLATFORM) += pwm-lpss-platform.o
- obj-$(CONFIG_PWM_MESON) += pwm-meson.o
-+obj-$(CONFIG_PWM_MEDIATEK) += pwm-mediatek.o
- obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
- obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
- obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
---- /dev/null
-+++ b/drivers/pwm/pwm-mediatek.c
-@@ -0,0 +1,173 @@
-+/*
-+ * Mediatek Pulse Width Modulator driver
-+ *
-+ * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
-+ *
-+ * This file is licensed under the terms of the GNU General Public
-+ * License version 2. This program is licensed "as is" without any
-+ * warranty of any kind, whether express or implied.
-+ */
-+
-+#include <linux/err.h>
-+#include <linux/io.h>
-+#include <linux/ioport.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/pwm.h>
-+#include <linux/slab.h>
-+#include <linux/types.h>
-+
-+#define NUM_PWM 4
-+
-+/* PWM registers and bits definitions */
-+#define PWMCON 0x00
-+#define PWMHDUR 0x04
-+#define PWMLDUR 0x08
-+#define PWMGDUR 0x0c
-+#define PWMWAVENUM 0x28
-+#define PWMDWIDTH 0x2c
-+#define PWMTHRES 0x30
-+
-+/**
-+ * struct mtk_pwm_chip - struct representing pwm chip
-+ *
-+ * @mmio_base: base address of pwm chip
-+ * @chip: linux pwm chip representation
-+ */
-+struct mtk_pwm_chip {
-+ void __iomem *mmio_base;
-+ struct pwm_chip chip;
-+};
-+
-+static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip)
-+{
-+ return container_of(chip, struct mtk_pwm_chip, chip);
-+}
-+
-+static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num,
-+ unsigned long offset)
-+{
-+ return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset);
-+}
-+
-+static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip,
-+ unsigned int num, unsigned long offset,
-+ unsigned long val)
-+{
-+ iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset);
-+}
-+
-+static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-+ int duty_ns, int period_ns)
-+{
-+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
-+ u32 resolution = 100 / 4;
-+ u32 clkdiv = 0;
-+
-+ while (period_ns / resolution > 8191) {
-+ clkdiv++;
-+ resolution *= 2;
-+ }
-+
-+ if (clkdiv > 7)
-+ return -1;
-+
-+ mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv);
-+ mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution);
-+ mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution);
-+ return 0;
-+}
-+
-+static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
-+{
-+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
-+ u32 val;
-+
-+ val = ioread32(pc->mmio_base);
-+ val |= BIT(pwm->hwpwm);
-+ iowrite32(val, pc->mmio_base);
-+
-+ return 0;
-+}
-+
-+static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
-+{
-+ struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
-+ u32 val;
-+
-+ val = ioread32(pc->mmio_base);
-+ val &= ~BIT(pwm->hwpwm);
-+ iowrite32(val, pc->mmio_base);
-+}
-+
-+static const struct pwm_ops mtk_pwm_ops = {
-+ .config = mtk_pwm_config,
-+ .enable = mtk_pwm_enable,
-+ .disable = mtk_pwm_disable,
-+ .owner = THIS_MODULE,
-+};
-+
-+static int mtk_pwm_probe(struct platform_device *pdev)
-+{
-+ struct mtk_pwm_chip *pc;
-+ struct resource *r;
-+ int ret;
-+
-+ pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
-+ if (!pc)
-+ return -ENOMEM;
-+
-+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ pc->mmio_base = devm_ioremap_resource(&pdev->dev, r);
-+ if (IS_ERR(pc->mmio_base))
-+ return PTR_ERR(pc->mmio_base);
-+
-+ platform_set_drvdata(pdev, pc);
-+
-+ pc->chip.dev = &pdev->dev;
-+ pc->chip.ops = &mtk_pwm_ops;
-+ pc->chip.base = -1;
-+ pc->chip.npwm = NUM_PWM;
-+
-+ ret = pwmchip_add(&pc->chip);
-+ if (ret < 0)
-+ dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
-+
-+ return ret;
-+}
-+
-+static int mtk_pwm_remove(struct platform_device *pdev)
-+{
-+ struct mtk_pwm_chip *pc = platform_get_drvdata(pdev);
-+ int i;
-+
-+ for (i = 0; i < NUM_PWM; i++)
-+ pwm_disable(&pc->chip.pwms[i]);
-+
-+ return pwmchip_remove(&pc->chip);
-+}
-+
-+static const struct of_device_id mtk_pwm_of_match[] = {
-+ { .compatible = "mediatek,mt7628-pwm" },
-+ { }
-+};
-+
-+MODULE_DEVICE_TABLE(of, mtk_pwm_of_match);
-+
-+static struct platform_driver mtk_pwm_driver = {
-+ .driver = {
-+ .name = "mtk-pwm",
-+ .owner = THIS_MODULE,
-+ .of_match_table = mtk_pwm_of_match,
-+ },
-+ .probe = mtk_pwm_probe,
-+ .remove = mtk_pwm_remove,
-+};
-+
-+module_platform_driver(mtk_pwm_driver);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
-+MODULE_ALIAS("platform:mtk-pwm");
+++ /dev/null
-mtd: spi-nor: add support for switching between 3-byte and 4-byte addressing on w25q256 flash
-
-On some devices the flash chip needs to be in 3-byte addressing mode during
-reboot, otherwise the boot loader will fail to start.
-This mode however does not allow regular reads/writes onto the upper 16M
-half. W25Q256 has separate read commands for reading from >16M, however
-it does not have any separate write commands.
-This patch changes the code to leave the chip in 3-byte mode most of the
-time and only switch during erase/write cycles that go to >16M
-addresses.
-
-Signed-off-by: Felix Fietkau <nbd@nbd.name>
----
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -85,6 +85,10 @@ struct flash_info {
- * Use dedicated 4byte address op codes
- * to support memory size above 128Mib.
- */
-+#define SPI_NOR_4B_READ_OP BIT(12) /*
-+ * Like SPI_NOR_4B_OPCODES, but for read
-+ * op code only.
-+ */
- };
-
- #define JEDEC_MFR(info) ((info)->id[0])
-@@ -250,6 +254,15 @@ static inline u8 spi_nor_convert_3to4_er
- ARRAY_SIZE(spi_nor_3to4_erase));
- }
-
-+static void spi_nor_set_4byte_read(struct spi_nor *nor,
-+ const struct flash_info *info)
-+{
-+ nor->addr_width = 3;
-+ nor->ext_addr = 0;
-+ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
-+ nor->flags |= SNOR_F_4B_EXT_ADDR;
-+}
-+
- static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
- const struct flash_info *info)
- {
-@@ -467,6 +480,36 @@ static int spi_nor_erase_sector(struct s
- return nor->write_reg(nor, nor->erase_opcode, buf, nor->addr_width);
- }
-
-+static int spi_nor_check_ext_addr(struct spi_nor *nor, u32 addr)
-+{
-+ bool ext_addr;
-+ int ret;
-+ u8 cmd;
-+
-+ if (!(nor->flags & SNOR_F_4B_EXT_ADDR))
-+ return 0;
-+
-+ ext_addr = !!(addr & 0xff000000);
-+ if (nor->ext_addr == ext_addr)
-+ return 0;
-+
-+ cmd = ext_addr ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
-+ write_enable(nor);
-+ ret = nor->write_reg(nor, cmd, NULL, 0);
-+ if (ret)
-+ return ret;
-+
-+ cmd = 0;
-+ ret = nor->write_reg(nor, SPINOR_OP_WREAR, &cmd, 1);
-+ if (ret)
-+ return ret;
-+
-+ nor->addr_width = 3 + ext_addr;
-+ nor->ext_addr = ext_addr;
-+ write_disable(nor);
-+ return 0;
-+}
-+
- /*
- * Erase an address range on the nor chip. The address range may extend
- * one or more erase sectors. Return an error is there is a problem erasing.
-@@ -492,6 +535,10 @@ static int spi_nor_erase(struct mtd_info
- if (ret)
- return ret;
-
-+ ret = spi_nor_check_ext_addr(nor, addr + len);
-+ if (ret)
-+ return ret;
-+
- /* whole-chip erase? */
- if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) {
- unsigned long timeout;
-@@ -542,6 +589,7 @@ static int spi_nor_erase(struct mtd_info
- write_disable(nor);
-
- erase_err:
-+ spi_nor_check_ext_addr(nor, 0);
- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE);
-
- instr->state = ret ? MTD_ERASE_FAILED : MTD_ERASE_DONE;
-@@ -834,7 +882,9 @@ static int spi_nor_lock(struct mtd_info
- if (ret)
- return ret;
-
-+ spi_nor_check_ext_addr(nor, ofs + len);
- ret = nor->flash_lock(nor, ofs, len);
-+ spi_nor_check_ext_addr(nor, 0);
-
- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
- return ret;
-@@ -849,7 +899,9 @@ static int spi_nor_unlock(struct mtd_inf
- if (ret)
- return ret;
-
-+ spi_nor_check_ext_addr(nor, ofs + len);
- ret = nor->flash_unlock(nor, ofs, len);
-+ spi_nor_check_ext_addr(nor, 0);
-
- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
- return ret;
-@@ -1151,7 +1203,7 @@ static const struct flash_info spi_nor_i
- { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
-- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
-+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_READ_OP) },
-
- /* Catalyst / On Semiconductor -- non-JEDEC */
- { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-@@ -1205,6 +1257,9 @@ static int spi_nor_read(struct mtd_info
- if (ret)
- return ret;
-
-+ if (nor->flags & SNOR_F_4B_EXT_ADDR)
-+ nor->addr_width = 4;
-+
- while (len) {
- loff_t addr = from;
-
-@@ -1229,6 +1284,18 @@ static int spi_nor_read(struct mtd_info
- ret = 0;
-
- read_err:
-+ if (nor->flags & SNOR_F_4B_EXT_ADDR) {
-+ u8 val = 0;
-+
-+ if ((from + len) & 0xff000000) {
-+ write_enable(nor);
-+ nor->write_reg(nor, SPINOR_OP_WREAR, &val, 1);
-+ write_disable(nor);
-+ }
-+
-+ nor->addr_width = 3;
-+ }
-+
- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
- return ret;
- }
-@@ -1330,6 +1397,10 @@ static int spi_nor_write(struct mtd_info
- if (ret)
- return ret;
-
-+ ret = spi_nor_check_ext_addr(nor, to + len);
-+ if (ret < 0)
-+ return ret;
-+
- for (i = 0; i < len; ) {
- ssize_t written;
- loff_t addr = to + i;
-@@ -1377,6 +1448,7 @@ static int spi_nor_write(struct mtd_info
- }
-
- write_err:
-+ spi_nor_check_ext_addr(nor, 0);
- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
- return ret;
- }
-@@ -1719,8 +1791,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 ||
-- info->flags & SPI_NOR_4B_OPCODES)
-+ if (info->flags & SPI_NOR_4B_READ_OP)
-+ spi_nor_set_4byte_read(nor, info);
-+ 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);
---- a/include/linux/mtd/spi-nor.h
-+++ b/include/linux/mtd/spi-nor.h
-@@ -90,6 +90,7 @@
- /* Used for Macronix and Winbond flashes. */
- #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
- #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
-+#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */
-
- /* Used for Spansion flashes only. */
- #define SPINOR_OP_BRWR 0x17 /* Bank register write */
-@@ -141,6 +142,7 @@ enum spi_nor_option_flags {
- SNOR_F_NO_OP_CHIP_ERASE = BIT(2),
- SNOR_F_S3AN_ADDR_DEFAULT = BIT(3),
- SNOR_F_READY_XSR_RDY = BIT(4),
-+ SNOR_F_4B_EXT_ADDR = BIT(5),
- };
-
- /**
-@@ -188,6 +190,7 @@ struct spi_nor {
- enum read_mode flash_read;
- bool sst_write_second;
- u32 flags;
-+ u8 ext_addr;
- u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
-
- int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
+++ /dev/null
---- a/drivers/mtd/spi-nor/spi-nor.c
-+++ b/drivers/mtd/spi-nor/spi-nor.c
-@@ -1453,6 +1453,67 @@ write_err:
- return ret;
- }
-
-+static int spi_nor_chunked_write(struct mtd_info *mtd, loff_t _to, size_t _len,
-+ size_t *_retlen, const u_char *_buf)
-+{
-+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
-+ u32 addr_width = nor->addr_width + !!(nor->flags & SNOR_F_4B_EXT_ADDR);
-+ int chunk_size;
-+ int retlen = 0;
-+ int ret;
-+
-+ chunk_size = nor->chunk_size;
-+ if (!chunk_size)
-+ chunk_size = _len;
-+
-+ if (addr_width > 3)
-+ chunk_size -= addr_width - 3;
-+
-+ while (retlen < _len) {
-+ size_t len = min_t(int, chunk_size, _len - retlen);
-+ const u_char *buf = _buf + retlen;
-+ loff_t to = _to + retlen;
-+
-+ if (nor->flags & SNOR_F_SST)
-+ ret = sst_write(mtd, to, len, &retlen, buf);
-+ else
-+ ret = spi_nor_write(mtd, to, len, &retlen, buf);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ *_retlen += retlen;
-+ return 0;
-+}
-+
-+static int spi_nor_chunked_read(struct mtd_info *mtd, loff_t _from, size_t _len,
-+ size_t *_retlen, u_char *_buf)
-+{
-+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
-+ int chunk_size;
-+ int ret;
-+
-+ chunk_size = nor->chunk_size;
-+ if (!chunk_size)
-+ chunk_size = _len;
-+
-+ *_retlen = 0;
-+ while (*_retlen < _len) {
-+ size_t len = min_t(int, chunk_size, _len - *_retlen);
-+ u_char *buf = _buf + *_retlen;
-+ loff_t from = _from + *_retlen;
-+ int retlen = 0;
-+
-+ ret = spi_nor_read(mtd, from, len, &retlen, buf);
-+ if (ret)
-+ return ret;
-+
-+ *_retlen += retlen;
-+ }
-+
-+ return 0;
-+}
-+
- static int macronix_quad_enable(struct spi_nor *nor)
- {
- int ret, val;
-@@ -1704,10 +1765,12 @@ int spi_nor_scan(struct spi_nor *nor, co
- }
-
- /* sst nor chips use AAI word program */
-- if (info->flags & SST_WRITE)
-+ if (info->flags & SST_WRITE) {
- mtd->_write = sst_write;
-- else
-+ nor->flags |= SNOR_F_SST;
-+ } else {
- mtd->_write = spi_nor_write;
-+ }
-
- if (info->flags & USE_FSR)
- nor->flags |= SNOR_F_USE_FSR;
-@@ -1739,11 +1802,20 @@ int spi_nor_scan(struct spi_nor *nor, co
- mtd->writebufsize = nor->page_size;
-
- if (np) {
-+ u32 val;
-+
- /* If we were instantiated by DT, use it */
- if (of_property_read_bool(np, "m25p,fast-read"))
- nor->flash_read = SPI_NOR_FAST;
- else
- nor->flash_read = SPI_NOR_NORMAL;
-+
-+ if (!of_property_read_u32(np, "m25p,chunked-io", &val)) {
-+ dev_info(dev, "using chunked io (size=%d)\n", val);
-+ mtd->_read = spi_nor_chunked_read;
-+ mtd->_write = spi_nor_chunked_write;
-+ nor->chunk_size = val;
-+ }
- } else {
- /* If we weren't instantiated by DT, default to fast-read */
- nor->flash_read = SPI_NOR_FAST;
---- a/include/linux/mtd/spi-nor.h
-+++ b/include/linux/mtd/spi-nor.h
-@@ -143,6 +143,7 @@ enum spi_nor_option_flags {
- SNOR_F_S3AN_ADDR_DEFAULT = BIT(3),
- SNOR_F_READY_XSR_RDY = BIT(4),
- SNOR_F_4B_EXT_ADDR = BIT(5),
-+ SNOR_F_SST = BIT(6),
- };
-
- /**
-@@ -182,6 +183,7 @@ struct spi_nor {
- struct mutex lock;
- struct device *dev;
- u32 page_size;
-+ u16 chunk_size;
- u8 addr_width;
- u8 erase_opcode;
- u8 read_opcode;
+++ /dev/null
---- a/drivers/usb/dwc2/platform.c
-+++ b/drivers/usb/dwc2/platform.c
-@@ -616,6 +616,12 @@ static int dwc2_driver_probe(struct plat
- if (retval)
- return retval;
-
-+ /* Enable USB port before any regs access */
-+ if (dwc2_readl(hsotg->regs + PCGCTL) & 0x0f) {
-+ dwc2_writel(0x00, hsotg->regs + PCGCTL);
-+ /* TODO: mdelay(25) here? vendor driver don't use it */
-+ }
-+
- retval = dwc2_get_dr_mode(hsotg);
- if (retval)
- goto error;
+++ /dev/null
---- a/arch/mips/pci/pci-mt7620.c
-+++ b/arch/mips/pci/pci-mt7620.c
-@@ -33,7 +33,6 @@
- #define RALINK_GPIOMODE 0x60
-
- #define PPLL_CFG1 0x9c
--#define PDRV_SW_SET BIT(23)
-
- #define PPLL_DRV 0xa0
- #define PDRV_SW_SET (1<<31)
+++ /dev/null
---- a/drivers/misc/Makefile
-+++ b/drivers/misc/Makefile
-@@ -54,6 +54,7 @@ obj-$(CONFIG_ECHO) += echo/
- obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
- obj-$(CONFIG_CXL_BASE) += cxl/
- obj-$(CONFIG_PANEL) += panel.o
-+obj-$(CONFIG_SOC_MT7620) += linkit.o
-
- lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o
- lkdtm-$(CONFIG_LKDTM) += lkdtm_bugs.o
---- /dev/null
-+++ b/drivers/misc/linkit.c
-@@ -0,0 +1,84 @@
-+/*
-+ * 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
-+ * publishhed by the Free Software Foundation.
-+ *
-+ * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/of.h>
-+#include <linux/mtd/mtd.h>
-+#include <linux/gpio.h>
-+
-+#define LINKIT_LATCH_GPIO 11
-+
-+struct linkit_hw_data {
-+ char board[16];
-+ char rev[16];
-+};
-+
-+static void sanify_string(char *s)
-+{
-+ int i;
-+
-+ for (i = 0; i < 15; i++)
-+ if (s[i] <= 0x20)
-+ s[i] = '\0';
-+ s[15] = '\0';
-+}
-+
-+static int linkit_probe(struct platform_device *pdev)
-+{
-+ struct linkit_hw_data hw;
-+ struct mtd_info *mtd;
-+ size_t retlen;
-+ int ret;
-+
-+ mtd = get_mtd_device_nm("factory");
-+ if (IS_ERR(mtd))
-+ return PTR_ERR(mtd);
-+
-+ ret = mtd_read(mtd, 0x400, sizeof(hw), &retlen, (u_char *) &hw);
-+ put_mtd_device(mtd);
-+
-+ sanify_string(hw.board);
-+ sanify_string(hw.rev);
-+
-+ dev_info(&pdev->dev, "Version : %s\n", hw.board);
-+ dev_info(&pdev->dev, "Revision : %s\n", hw.rev);
-+
-+ if (!strcmp(hw.board, "LINKITS7688")) {
-+ dev_info(&pdev->dev, "setting up bootstrap latch\n");
-+
-+ if (devm_gpio_request(&pdev->dev, LINKIT_LATCH_GPIO, "bootstrap")) {
-+ dev_err(&pdev->dev, "failed to setup bootstrap gpio\n");
-+ return -1;
-+ }
-+ gpio_direction_output(LINKIT_LATCH_GPIO, 0);
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id linkit_match[] = {
-+ { .compatible = "mediatek,linkit" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, linkit_match);
-+
-+static struct platform_driver linkit_driver = {
-+ .probe = linkit_probe,
-+ .driver = {
-+ .name = "mtk-linkit",
-+ .owner = THIS_MODULE,
-+ .of_match_table = linkit_match,
-+ },
-+};
-+
-+int __init linkit_init(void)
-+{
-+ return platform_driver_register(&linkit_driver);
-+}
-+late_initcall_sync(linkit_init);
+++ /dev/null
---- a/arch/mips/include/asm/mach-ralink/mt7620.h
-+++ b/arch/mips/include/asm/mach-ralink/mt7620.h
-@@ -115,9 +115,14 @@
- #define MT7620_GPIO_MODE_WDT_MASK 0x3
- #define MT7620_GPIO_MODE_WDT_SHIFT 21
-
-+#define MT7620_GPIO_MODE_MDIO 0
-+#define MT7620_GPIO_MODE_MDIO_REFCLK 1
-+#define MT7620_GPIO_MODE_MDIO_GPIO 2
-+#define MT7620_GPIO_MODE_MDIO_MASK 0x3
-+#define MT7620_GPIO_MODE_MDIO_SHIFT 7
-+
- #define MT7620_GPIO_MODE_I2C 0
- #define MT7620_GPIO_MODE_UART1 5
--#define MT7620_GPIO_MODE_MDIO 8
- #define MT7620_GPIO_MODE_RGMII1 9
- #define MT7620_GPIO_MODE_RGMII2 10
- #define MT7620_GPIO_MODE_SPI 11
---- a/arch/mips/ralink/mt7620.c
-+++ b/arch/mips/ralink/mt7620.c
-@@ -55,7 +55,10 @@ static int dram_type;
- static struct rt2880_pmx_func i2c_grp[] = { FUNC("i2c", 0, 1, 2) };
- static struct rt2880_pmx_func spi_grp[] = { FUNC("spi", 0, 3, 4) };
- static struct rt2880_pmx_func uartlite_grp[] = { FUNC("uartlite", 0, 15, 2) };
--static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 22, 2) };
-+static struct rt2880_pmx_func mdio_grp[] = {
-+ FUNC("mdio", MT7620_GPIO_MODE_MDIO, 22, 2),
-+ FUNC("refclk", MT7620_GPIO_MODE_MDIO_REFCLK, 22, 2),
-+};
- static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 24, 12) };
- static struct rt2880_pmx_func refclk_grp[] = { FUNC("spi refclk", 0, 37, 3) };
- static struct rt2880_pmx_func ephy_grp[] = { FUNC("ephy", 0, 40, 5) };
-@@ -92,7 +95,8 @@ static struct rt2880_pmx_group mt7620a_p
- GRP("uartlite", uartlite_grp, 1, MT7620_GPIO_MODE_UART1),
- GRP_G("wdt", wdt_grp, MT7620_GPIO_MODE_WDT_MASK,
- MT7620_GPIO_MODE_WDT_GPIO, MT7620_GPIO_MODE_WDT_SHIFT),
-- GRP("mdio", mdio_grp, 1, MT7620_GPIO_MODE_MDIO),
-+ GRP_G("mdio", mdio_grp, MT7620_GPIO_MODE_MDIO_MASK,
-+ MT7620_GPIO_MODE_MDIO_GPIO, MT7620_GPIO_MODE_MDIO_SHIFT),
- GRP("rgmii1", rgmii1_grp, 1, MT7620_GPIO_MODE_RGMII1),
- GRP("spi refclk", refclk_grp, 1, MT7620_GPIO_MODE_SPI_REF_CLK),
- GRP_G("pcie", pcie_rst_grp, MT7620_GPIO_MODE_PCIE_MASK,
+++ /dev/null
---- a/arch/mips/ralink/mt7620.c
-+++ b/arch/mips/ralink/mt7620.c
-@@ -513,6 +513,7 @@ void __init ralink_clk_init(void)
- unsigned long sys_rate;
- unsigned long dram_rate;
- unsigned long periph_rate;
-+ unsigned long pcmi2s_rate;
-
- xtal_rate = mt7620_get_xtal_rate();
-
-@@ -527,6 +528,7 @@ void __init ralink_clk_init(void)
- cpu_rate = MHZ(575);
- dram_rate = sys_rate = cpu_rate / 3;
- periph_rate = MHZ(40);
-+ pcmi2s_rate = MHZ(480);
-
- ralink_clk_add("10000d00.uartlite", periph_rate);
- ralink_clk_add("10000e00.uartlite", periph_rate);
-@@ -538,6 +540,7 @@ void __init ralink_clk_init(void)
- dram_rate = mt7620_get_dram_rate(pll_rate);
- sys_rate = mt7620_get_sys_rate(cpu_rate);
- periph_rate = mt7620_get_periph_rate(xtal_rate);
-+ pcmi2s_rate = periph_rate;
-
- pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"),
- RINT(xtal_rate), RFRAC(xtal_rate),
-@@ -559,6 +562,8 @@ void __init ralink_clk_init(void)
- ralink_clk_add("cpu", cpu_rate);
- ralink_clk_add("10000100.timer", periph_rate);
- ralink_clk_add("10000120.watchdog", periph_rate);
-+ ralink_clk_add("10000900.i2c", periph_rate);
-+ ralink_clk_add("10000a00.i2s", pcmi2s_rate);
- ralink_clk_add("10000b00.spi", sys_rate);
- ralink_clk_add("10000b40.spi", sys_rate);
- ralink_clk_add("10000c00.uartlite", periph_rate);
---- a/arch/mips/ralink/rt288x.c
-+++ b/arch/mips/ralink/rt288x.c
-@@ -65,6 +65,7 @@ void __init ralink_clk_init(void)
- ralink_clk_add("300100.timer", cpu_rate / 2);
- ralink_clk_add("300120.watchdog", cpu_rate / 2);
- ralink_clk_add("300500.uart", cpu_rate / 2);
-+ ralink_clk_add("300900.i2c", cpu_rate / 2);
- ralink_clk_add("300c00.uartlite", cpu_rate / 2);
- ralink_clk_add("400000.ethernet", cpu_rate / 2);
- ralink_clk_add("480000.wmac", wmac_rate);
---- a/arch/mips/ralink/rt305x.c
-+++ b/arch/mips/ralink/rt305x.c
-@@ -189,6 +189,8 @@ void __init ralink_clk_init(void)
-
- ralink_clk_add("cpu", cpu_rate);
- ralink_clk_add("sys", sys_rate);
-+ ralink_clk_add("10000900.i2c", uart_rate);
-+ ralink_clk_add("10000a00.i2s", uart_rate);
- ralink_clk_add("10000b00.spi", sys_rate);
- ralink_clk_add("10000b40.spi", sys_rate);
- ralink_clk_add("10000100.timer", wdt_rate);
---- a/arch/mips/ralink/rt3883.c
-+++ b/arch/mips/ralink/rt3883.c
-@@ -98,6 +98,8 @@ void __init ralink_clk_init(void)
- ralink_clk_add("10000100.timer", sys_rate);
- ralink_clk_add("10000120.watchdog", sys_rate);
- ralink_clk_add("10000500.uart", 40000000);
-+ ralink_clk_add("10000900.i2c", 40000000);
-+ ralink_clk_add("10000a00.i2s", 40000000);
- ralink_clk_add("10000b00.spi", sys_rate);
- ralink_clk_add("10000b40.spi", sys_rate);
- ralink_clk_add("10000c00.uartlite", 40000000);
+++ /dev/null
-From 8b61a1a33e41456ebeafa0ebe7ec0fccf859861e Mon Sep 17 00:00:00 2001
-From: Nikolay Martynov <mar.kolya@gmail.com>
-Date: Wed, 25 Nov 2015 20:43:46 -0500
-Subject: [PATCH] mtd: nand: Fix Spansion sparearea size detection
-
-According to datasheet S34ML02G2 and S34ML04G2 have
-larger sparea area size than was detected.
-
-Signed-off-by: Nikolay Martynov <mar.kolya@gmail.com>
----
- drivers/mtd/nand/nand_base.c | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
---- a/drivers/mtd/nand/nand_base.c
-+++ b/drivers/mtd/nand/nand_base.c
-@@ -3861,6 +3861,7 @@ static void nand_decode_ext_id(struct mt
- /*
- * Field definitions are in the following datasheets:
- * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-+ * Spansion S34ML02G2 (p.33)
- * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
- * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22)
- *
-@@ -3958,6 +3959,19 @@ static void nand_decode_ext_id(struct mt
- *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
-
- /*
-+ * Spansion S34ML0[24]G2 have oobsize twice as large
-+ * as S34ML01G2 encoded in the same bit. We
-+ * differinciate them by their ID length
-+ */
-+ if (id_data[0] == NAND_MFR_AMD
-+ && (id_data[1] == 0xda
-+ || id_data[1] == 0xdc
-+ || id_data[1] == 0xca
-+ || id_data[1] == 0xcc)) {
-+ mtd->oobsize *= 2;
-+ }
-+
-+ /*
- * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
- * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
- * follows:
+++ /dev/null
---- a/arch/mips/pci/pci-mt7620.c
-+++ b/arch/mips/pci/pci-mt7620.c
-@@ -35,6 +35,7 @@
- #define PPLL_CFG1 0x9c
-
- #define PPLL_DRV 0xa0
-+#define PPLL_LD (1<<23)
- #define PDRV_SW_SET (1<<31)
- #define LC_CKDRVPD (1<<19)
- #define LC_CKDRVOHZ (1<<18)
-@@ -242,8 +243,8 @@ static int mt7620_pci_hw_init(struct pla
- rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
- mdelay(100);
-
-- if (!(rt_sysc_r32(PPLL_CFG1) & PDRV_SW_SET)) {
-- dev_err(&pdev->dev, "MT7620 PPLL unlock\n");
-+ if (!(rt_sysc_r32(PPLL_CFG1) & PPLL_LD)) {
-+ dev_err(&pdev->dev, "MT7620 PPLL is unlocked, aborting init\n");
- reset_control_assert(rstpcie0);
- rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
- return -1;