From mboxrd@z Thu Jan 1 00:00:00 1970 From: Min Guo Subject: Re: [PATCH v2 4/4] usb: musb: Add support for MediaTek musb controller Date: Wed, 16 Jan 2019 10:43:13 +0800 Message-ID: <1547606593.4433.178.camel@mhfsdcap03> References: <1547516626-5084-1-git-send-email-min.guo@mediatek.com> <1547516626-5084-5-git-send-email-min.guo@mediatek.com> <20190115203815.GD18026@uda0271908> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <20190115203815.GD18026@uda0271908> Sender: linux-kernel-owner@vger.kernel.org To: Bin Liu Cc: Rob Herring , Greg Kroah-Hartman , Mark Rutland , Matthias Brugger , Alan Stern , chunfeng.yun@mediatek.com, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Yonglong Wu List-Id: linux-mediatek@lists.infradead.org Hi Bin, On Tue, 2019-01-15 at 14:38 -0600, Bin Liu wrote: > Hi Min, > > very close, thanks. > Below I tried to explain a further cleanup in musb_clearb/w() and > musb_get/set_toggle() implementation. Please let me know if it is not > clear. > > Basically, we don't need musb_default_clearb/w(), just assign the > musb_io function pointers to musb_readb/w(). > > Then the mtk platform musb_clearb/w() calls musb_readb/w() and > musb_writeb/w() to handle W1C. Okay. > On Tue, Jan 15, 2019 at 09:43:46AM +0800, min.guo@mediatek.com wrote: > > From: Min Guo > > > > This adds support for MediaTek musb controller in > > host, peripheral and otg mode. > > There are some quirk of MediaTek musb controller, such as: > > -W1C interrupt status registers > > -Private data toggle registers > > -No dedicated DMA interrupt line > > > > Signed-off-by: Min Guo > > Signed-off-by: Yonglong Wu > > --- > > drivers/usb/musb/Kconfig | 8 +- > > drivers/usb/musb/Makefile | 1 + > > drivers/usb/musb/mediatek.c | 617 +++++++++++++++++++++++++++++++++++++++++++ > > drivers/usb/musb/musb_core.c | 69 +++++ > > drivers/usb/musb/musb_core.h | 9 + > > drivers/usb/musb/musb_dma.h | 9 + > > drivers/usb/musb/musb_host.c | 26 +- > > drivers/usb/musb/musb_io.h | 6 + > > drivers/usb/musb/musbhsdma.c | 55 ++-- > > 9 files changed, 762 insertions(+), 38 deletions(-) > > create mode 100644 drivers/usb/musb/mediatek.c > > > > diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig > > index ad08895..b72b7c1 100644 > > --- a/drivers/usb/musb/Kconfig > > +++ b/drivers/usb/musb/Kconfig > > @@ -115,6 +115,12 @@ config USB_MUSB_JZ4740 > > depends on USB_MUSB_GADGET > > depends on USB_OTG_BLACKLIST_HUB > > > > +config USB_MUSB_MEDIATEK > > + tristate "MediaTek platforms" > > + depends on ARCH_MEDIATEK || COMPILE_TEST > > + depends on NOP_USB_XCEIV > > + depends on GENERIC_PHY > > + > > config USB_MUSB_AM335X_CHILD > > tristate > > > > @@ -141,7 +147,7 @@ config USB_UX500_DMA > > > > config USB_INVENTRA_DMA > > bool 'Inventra' > > - depends on USB_MUSB_OMAP2PLUS > > + depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK > > help > > Enable DMA transfers using Mentor's engine. > > > > diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile > > index 3a88c79..63d82d0 100644 > > --- a/drivers/usb/musb/Makefile > > +++ b/drivers/usb/musb/Makefile > > @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o > > obj-$(CONFIG_USB_MUSB_UX500) += ux500.o > > obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o > > obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o > > +obj-$(CONFIG_USB_MUSB_MEDIATEK) += mediatek.o > > > > > > obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o > > diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c > > new file mode 100644 > > index 0000000..7221989 > > --- /dev/null > > +++ b/drivers/usb/musb/mediatek.c > > @@ -0,0 +1,617 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Copyright (C) 2018 MediaTek Inc. > > + * > > + * Author: > > + * Min Guo > > + * Yonglong Wu > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "musb_core.h" > > +#include "musb_dma.h" > > + > > +#define USB_L1INTS 0x00a0 > > +#define USB_L1INTM 0x00a4 > > +#define MTK_MUSB_TXFUNCADDR 0x0480 > > + > > +/* MediaTek controller toggle enable and status reg */ > > +#define MUSB_RXTOG 0x80 > > +#define MUSB_RXTOGEN 0x82 > > +#define MUSB_TXTOG 0x84 > > +#define MUSB_TXTOGEN 0x86 > > + > > +#define TX_INT_STATUS BIT(0) > > +#define RX_INT_STATUS BIT(1) > > +#define USBCOM_INT_STATUS BIT(2) > > missing a TAB for the alignment? Okay. > > +#define DMA_INT_STATUS BIT(3) > > + > > +#define DMA_INTR_STATUS_MSK GENMASK(7, 0) > > +#define DMA_INTR_UNMASK_SET_MSK GENMASK(31, 24) > > + > > +enum mtk_vbus_id_state { > > + MTK_ID_FLOAT = 1, > > + MTK_ID_GROUND, > > + MTK_VBUS_OFF, > > + MTK_VBUS_VALID, > > +}; > > + > > +struct mtk_glue { > > + struct device *dev; > > + struct musb *musb; > > + struct platform_device *musb_pdev; > > + struct platform_device *usb_phy; > > + struct phy *phy; > > + struct usb_phy *xceiv; > > + enum phy_mode phy_mode; > > + struct clk *main; > > + struct clk *mcu; > > + struct clk *univpll; > > + struct regulator *vbus; > > + struct extcon_dev *edev; > > + struct notifier_block vbus_nb; > > + struct notifier_block id_nb; > > +}; > > + > > +static int mtk_musb_clks_get(struct mtk_glue *glue) > > +{ > > + struct device *dev = glue->dev; > > + > > + glue->main = devm_clk_get(dev, "main"); > > + if (IS_ERR(glue->main)) { > > + dev_err(dev, "fail to get main clock\n"); > > + return PTR_ERR(glue->main); > > + } > > + > > + glue->mcu = devm_clk_get(dev, "mcu"); > > + if (IS_ERR(glue->mcu)) { > > + dev_err(dev, "fail to get mcu clock\n"); > > + return PTR_ERR(glue->mcu); > > + } > > + > > + glue->univpll = devm_clk_get(dev, "univpll"); > > + if (IS_ERR(glue->univpll)) { > > + dev_err(dev, "fail to get univpll clock\n"); > > + return PTR_ERR(glue->univpll); > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_musb_clks_enable(struct mtk_glue *glue) > > +{ > > + int ret; > > + > > + ret = clk_prepare_enable(glue->main); > > + if (ret) { > > + dev_err(glue->dev, "failed to enable main clock\n"); > > + goto err_main_clk; > > + } > > + > > + ret = clk_prepare_enable(glue->mcu); > > + if (ret) { > > + dev_err(glue->dev, "failed to enable mcu clock\n"); > > + goto err_mcu_clk; > > + } > > + > > + ret = clk_prepare_enable(glue->univpll); > > + if (ret) { > > + dev_err(glue->dev, "failed to enable univpll clock\n"); > > + goto err_univpll_clk; > > + } > > + > > + return 0; > > + > > +err_univpll_clk: > > + clk_disable_unprepare(glue->mcu); > > +err_mcu_clk: > > + clk_disable_unprepare(glue->main); > > +err_main_clk: > > + return ret; > > +} > > + > > +static void mtk_musb_clks_disable(struct mtk_glue *glue) > > +{ > > + clk_disable_unprepare(glue->univpll); > > + clk_disable_unprepare(glue->mcu); > > + clk_disable_unprepare(glue->main); > > +} > > + > > +static void mtk_musb_set_vbus(struct musb *musb, int is_on) > > +{ > > + struct device *dev = musb->controller; > > + struct mtk_glue *glue = dev_get_drvdata(dev->parent); > > + int ret; > > + > > + /* vbus is optional */ > > + if (!glue->vbus) > > + return; > > + > > + dev_dbg(musb->controller, "%s, is_on=%d\r\n", __func__, is_on); > > + if (is_on) { > > + ret = regulator_enable(glue->vbus); > > + if (ret) { > > + dev_err(glue->dev, "fail to enable vbus regulator\n"); > > + return; > > + } > > + } else { > > + regulator_disable(glue->vbus); > > + } > > +} > > + > > +/* > > + * switch to host: -> MTK_VBUS_OFF --> MTK_ID_GROUND > > + * switch to device: -> MTK_ID_FLOAT --> MTK_VBUS_VALID > > + */ > > +static void mtk_musb_set_mailbox(struct mtk_glue *glue, > > + enum mtk_vbus_id_state status) > > add one more TAB for params. Okay. > > +{ > > + struct musb *musb = glue->musb; > > + u8 devctl = 0; > > + > > + dev_dbg(glue->dev, "mailbox state(%d)\n", status); > > + switch (status) { > > + case MTK_ID_GROUND: > > + phy_power_on(glue->phy); > > + devctl = readb(musb->mregs + MUSB_DEVCTL); > > + musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; > > + mtk_musb_set_vbus(musb, 1); > > + glue->phy_mode = PHY_MODE_USB_HOST; > > + phy_set_mode(glue->phy, glue->phy_mode); > > + devctl |= MUSB_DEVCTL_SESSION; > > + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); > > + MUSB_HST_MODE(musb); > > + break; > > + /* > > + * MTK_ID_FLOAT process is the same as MTK_VBUS_VALID > > + * except that turn off VBUS > > + */ > > + case MTK_ID_FLOAT: > > + mtk_musb_set_vbus(musb, 0); > > + /* fall through */ > > + case MTK_VBUS_OFF: > > + musb->xceiv->otg->state = OTG_STATE_B_IDLE; > > + devctl &= ~MUSB_DEVCTL_SESSION; > > + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); > > + phy_power_off(glue->phy); > > + break; > > + case MTK_VBUS_VALID: > > + phy_power_on(glue->phy); > > + glue->phy_mode = PHY_MODE_USB_DEVICE; > > + phy_set_mode(glue->phy, glue->phy_mode); > > + MUSB_DEV_MODE(musb); > > + break; > > + default: > > + dev_err(glue->dev, "invalid state\n"); > > + } > > +} > > + > > +static int mtk_musb_id_notifier(struct notifier_block *nb, > > + unsigned long event, void *ptr) > > +{ > > + struct mtk_glue *glue = container_of(nb, struct mtk_glue, id_nb); > > + > > + if (event) > > + mtk_musb_set_mailbox(glue, MTK_ID_GROUND); > > + else > > + mtk_musb_set_mailbox(glue, MTK_ID_FLOAT); > > + > > + return NOTIFY_DONE; > > +} > > + > > +static int mtk_musb_vbus_notifier(struct notifier_block *nb, > > + unsigned long event, void *ptr) > > +{ > > + struct mtk_glue *glue = container_of(nb, struct mtk_glue, vbus_nb); > > + > > + if (event) > > + mtk_musb_set_mailbox(glue, MTK_VBUS_VALID); > > + else > > + mtk_musb_set_mailbox(glue, MTK_VBUS_OFF); > > + > > + return NOTIFY_DONE; > > +} > > + > > +static void mtk_otg_switch_init(struct mtk_glue *glue) > > +{ > > + int ret; > > + > > + /* extcon is optional */ > > + if (!glue->edev) > > + return; > > + > > + glue->vbus_nb.notifier_call = mtk_musb_vbus_notifier; > > + ret = devm_extcon_register_notifier(glue->dev, glue->edev, EXTCON_USB, > > + &glue->vbus_nb); > > + if (ret < 0) > > + dev_err(glue->dev, "failed to register notifier for USB\n"); > > + > > + glue->id_nb.notifier_call = mtk_musb_id_notifier; > > + ret = devm_extcon_register_notifier(glue->dev, glue->edev, > > + EXTCON_USB_HOST, &glue->id_nb); > > + if (ret < 0) > > + dev_err(glue->dev, "failed to register notifier for USB-HOST\n"); > > + > > + dev_dbg(glue->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n", > > + extcon_get_state(glue->edev, EXTCON_USB), > > + extcon_get_state(glue->edev, EXTCON_USB_HOST)); > > + > > + /* default as host, switch to device mode if needed */ > > + if (extcon_get_state(glue->edev, EXTCON_USB_HOST) == false) > > + mtk_musb_set_mailbox(glue, MTK_ID_FLOAT); > > + if (extcon_get_state(glue->edev, EXTCON_USB) == true) > > + mtk_musb_set_mailbox(glue, MTK_VBUS_VALID); > > +} > > + > > +static irqreturn_t generic_interrupt(int irq, void *__hci) > > +{ > > + unsigned long flags; > > + irqreturn_t retval = IRQ_NONE; > > + struct musb *musb = __hci; > > + > > + spin_lock_irqsave(&musb->lock, flags); > > + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB) & > > + musb_readb(musb->mregs, MUSB_INTRUSBE); > > + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX) > > + & musb_readw(musb->mregs, MUSB_INTRTXE); > > + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX) > > + & musb_readw(musb->mregs, MUSB_INTRRXE); > > + /* MediaTek controller interrupt status is W1C */ > > + musb_clearw(musb->mregs, MUSB_INTRRX, musb->int_rx); > > + musb_clearw(musb->mregs, MUSB_INTRTX, musb->int_tx); > > + musb_clearb(musb->mregs, MUSB_INTRUSB, musb->int_usb); > > + > > + if (musb->int_usb || musb->int_tx || musb->int_rx) > > + retval = musb_interrupt(musb); > > + > > + spin_unlock_irqrestore(&musb->lock, flags); > > + > > + return retval; > > +} > > + > > +static irqreturn_t mtk_musb_interrupt(int irq, void *dev_id) > > +{ > > + irqreturn_t retval = IRQ_NONE; > > + struct musb *musb = (struct musb *)dev_id; > > + u32 l1_ints; > > + > > + l1_ints = musb_readl(musb->mregs, USB_L1INTS) & > > + musb_readl(musb->mregs, USB_L1INTM); > > + > > + if (l1_ints & (TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS)) > > + retval = generic_interrupt(irq, musb); > > + > > +#if defined(CONFIG_USB_INVENTRA_DMA) > > + if (l1_ints & DMA_INT_STATUS) > > + retval = dma_controller_irq(irq, musb->dma_controller); > > +#endif > > + return retval; > > +} > > + > > +static u32 mtk_musb_busctl_offset(u8 epnum, u16 offset) > > +{ > > + return MTK_MUSB_TXFUNCADDR + offset + 8 * epnum; > > +} > > + > > +static void mtk_musb_clearb(void __iomem *addr, unsigned int offset, u8 data) > > remove 'u8 data' parameter, then add: Okay. > > +{ > > u8 data; > > > + /* W1C */ > data = musb_readb(addr, offset); > > + musb_writeb(addr, offset, data); > > +} > > + > > +static void mtk_musb_clearw(void __iomem *addr, unsigned int offset, u16 data) > > +{ > > + /* W1C */ > > + musb_writew(addr, offset, data); > > +} > > similar as mtk_musb_clearb() above. Okay. > > + > > +static int mtk_musb_init(struct musb *musb) > > +{ > > + struct device *dev = musb->controller; > > + struct mtk_glue *glue = dev_get_drvdata(dev->parent); > > + int ret; > > [snip] > > > + if (pdata->mode == USB_DR_MODE_OTG) > > + mtk_otg_switch_init(glue); > > + > > + dev_info(dev, "USB probe done!\n"); > > not really useful, can be removed. Okay. > > + return 0; > > + > > +err_device_register: > > + mtk_musb_clks_disable(glue); > > +err_enable_clk: > > + pm_runtime_put_sync(dev); > > + pm_runtime_disable(dev); > > +err_unregister_usb_phy: > > + usb_phy_generic_unregister(glue->usb_phy); > > + return ret; > > +} > > + > > +static int mtk_musb_remove(struct platform_device *pdev) > > +{ > > + struct mtk_glue *glue = platform_get_drvdata(pdev); > > + struct platform_device *usb_phy = glue->usb_phy; > > + > > + platform_device_unregister(glue->musb_pdev); > > + usb_phy_generic_unregister(usb_phy); > > + > > + return 0; > > +} > > + > > +#ifdef CONFIG_OF > > +static const struct of_device_id mtk_musb_match[] = { > > + {.compatible = "mediatek,mtk-musb",}, > > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, mtk_musb_match); > > +#endif > > + > > +static struct platform_driver mtk_musb_driver = { > > + .probe = mtk_musb_probe, > > + .remove = mtk_musb_remove, > > + .driver = { > > + .name = "musb-mtk", > > + .of_match_table = of_match_ptr(mtk_musb_match), > > + }, > > +}; > > + > > +module_platform_driver(mtk_musb_driver); > > + > > +MODULE_DESCRIPTION("MediaTek MUSB Glue Layer"); > > +MODULE_AUTHOR("Min Guo "); > > +MODULE_LICENSE("GPL v2"); > > diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c > > index b7d5627..2c0d102 100644 > > --- a/drivers/usb/musb/musb_core.c > > +++ b/drivers/usb/musb/musb_core.c > > @@ -260,6 +260,11 @@ static void musb_default_writeb(void __iomem *addr, unsigned offset, u8 data) > > __raw_writeb(data, addr + offset); > > } > > > > +static void > > +musb_default_clearb(void __iomem *addr, unsigned int offset, u8 data) > > +{ > > +} > > don't need this, use musb_readb() for the function pointer. Okay. > > + > > static u16 musb_default_readw(const void __iomem *addr, unsigned offset) > > { > > u16 data = __raw_readw(addr + offset); > > @@ -274,6 +279,43 @@ static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data) > > __raw_writew(data, addr + offset); > > } > > > > +static void > > +musb_default_clearw(void __iomem *addr, unsigned int offset, u16 data) > > +{ > > +} > > don't need this, use musb_readw() for the function pointer. Okay. > > + > > +static u16 musb_default_get_toggle(struct musb_qh *qh, int is_in) > > +{ > > + void __iomem *epio = qh->hw_ep->regs; > > + u16 csr; > > + > > + if (is_in) > > + csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; > > + else > > + csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; > > + > > + return csr; > > +} > > + > > +static u16 musb_default_set_toggle(struct musb_qh *qh, int is_in, > > + struct urb *urb) > > +{ > > + u16 csr = 0; > > + u16 toggle = 0; > > no need to assign them 0. Okay. > > + > > + toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in); > > + > > + if (is_in) > > + csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE > > + | MUSB_RXCSR_H_DATATOGGLE) : 0; > > + else > > + csr |= toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE > > + | MUSB_TXCSR_H_DATATOGGLE) > > + : MUSB_TXCSR_CLRDATATOG; > > + > > + return csr; > > +} > > + > > /* > > * Load an endpoint's FIFO > > */ > > @@ -370,12 +412,18 @@ static void musb_default_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) > > void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); > > EXPORT_SYMBOL_GPL(musb_writeb); > > > > +void (*musb_clearb)(void __iomem *addr, unsigned int offset, u8 data); > > +EXPORT_SYMBOL_GPL(musb_clearb); > > + > > u16 (*musb_readw)(const void __iomem *addr, unsigned offset); > > EXPORT_SYMBOL_GPL(musb_readw); > > > > void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); > > EXPORT_SYMBOL_GPL(musb_writew); > > > > +void (*musb_clearw)(void __iomem *addr, unsigned int offset, u16 data); > > +EXPORT_SYMBOL_GPL(musb_clearw); > > + > > u32 musb_readl(const void __iomem *addr, unsigned offset) > > { > > u32 data = __raw_readl(addr + offset); > > @@ -1028,6 +1076,11 @@ static void musb_disable_interrupts(struct musb *musb) > > temp = musb_readb(mbase, MUSB_INTRUSB); > > temp = musb_readw(mbase, MUSB_INTRTX); > > temp = musb_readw(mbase, MUSB_INTRRX); > > replace the 3 line above with > musb_clearb/w(); Okay. > > + > > + /* some platform needs clear pending interrupts by manual */ > > + musb_clearb(mbase, MUSB_INTRUSB, musb_readb(mbase, MUSB_INTRUSB)); > > + musb_clearw(mbase, MUSB_INTRRX, musb_readw(mbase, MUSB_INTRRX)); > > + musb_clearw(mbase, MUSB_INTRTX, musb_readw(mbase, MUSB_INTRTX)); > > then those are no longer needed. Okay. > > } > > > > static void musb_enable_interrupts(struct musb *musb) > > @@ -2192,6 +2245,8 @@ static void musb_deassert_reset(struct work_struct *work) > > musb_writeb = musb_default_writeb; > > musb_readw = musb_default_readw; > > musb_writew = musb_default_writew; > > + musb_clearb = musb_default_clearb; > > + musb_clearw = musb_default_clearw; > > > > /* The musb_platform_init() call: > > * - adjusts musb->mregs > > @@ -2252,10 +2307,14 @@ static void musb_deassert_reset(struct work_struct *work) > > musb_readb = musb->ops->readb; > > if (musb->ops->writeb) > > musb_writeb = musb->ops->writeb; > > + if (musb->ops->clearb) > > + musb_clearb = musb->ops->clearb; > else > musb_clearb = musb_readb; Okay. > > if (musb->ops->readw) > > musb_readw = musb->ops->readw; > > if (musb->ops->writew) > > musb_writew = musb->ops->writew; > > + if (musb->ops->clearw) > > + musb_clearw = musb->ops->clearw; > else > musb_clearw = musb_readw; Okay. > > > > #ifndef CONFIG_MUSB_PIO_ONLY > > if (!musb->ops->dma_init || !musb->ops->dma_exit) { > > @@ -2277,6 +2336,16 @@ static void musb_deassert_reset(struct work_struct *work) > > else > > musb->io.write_fifo = musb_default_write_fifo; > > > > + if (musb->ops->get_toggle) > > + musb->io.get_toggle = musb->ops->get_toggle; > > + else > > + musb->io.get_toggle = musb_default_get_toggle; > > + > > + if (musb->ops->set_toggle) > > + musb->io.set_toggle = musb->ops->set_toggle; > > + else > > + musb->io.set_toggle = musb_default_set_toggle; > > + > > if (!musb->xceiv->io_ops) { > > musb->xceiv->io_dev = musb->controller; > > musb->xceiv->io_priv = musb->mregs; > > diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h > > index 04203b7..71dca80 100644 > > --- a/drivers/usb/musb/musb_core.h > > +++ b/drivers/usb/musb/musb_core.h > > @@ -27,6 +27,7 @@ > > struct musb; > > struct musb_hw_ep; > > struct musb_ep; > > +struct musb_qh; > > > > /* Helper defines for struct musb->hwvers */ > > #define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) > > @@ -119,10 +120,14 @@ enum musb_g_ep0_state { > > * @fifo_offset: returns the fifo offset > > * @readb: read 8 bits > > * @writeb: write 8 bits > > + * @clearb: clear 8 bits, > > add "could be clear-on-read or W1C" to give more info. Okay. > > * @readw: read 16 bits > > * @writew: write 16 bits > > + * @clearw: clear 16 bits > > * @read_fifo: reads the fifo > > * @write_fifo: writes to fifo > > + * @get_toggle: platform specific get toggle function > > + * @set_toggle: platform specific set toggle function > > * @dma_init: platform specific dma init function > > * @dma_exit: platform specific dma exit function > > * @init: turns on clocks, sets up platform-specific registers, etc > > @@ -163,10 +168,14 @@ struct musb_platform_ops { > > u32 (*busctl_offset)(u8 epnum, u16 offset); > > u8 (*readb)(const void __iomem *addr, unsigned offset); > > void (*writeb)(void __iomem *addr, unsigned offset, u8 data); > > + void (*clearb)(void __iomem *addr, unsigned int offset, u8 data); > > u16 (*readw)(const void __iomem *addr, unsigned offset); > > void (*writew)(void __iomem *addr, unsigned offset, u16 data); > > + void (*clearw)(void __iomem *addr, unsigned int offset, u16 data); > > void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); > > void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); > > + u16 (*get_toggle)(struct musb_qh *qh, int is_in); > > + u16 (*set_toggle)(struct musb_qh *qh, int is_in, struct urb *urb); > > struct dma_controller * > > (*dma_init) (struct musb *musb, void __iomem *base); > > void (*dma_exit)(struct dma_controller *c); > > diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h > > index 8f60271..05103ea 100644 > > --- a/drivers/usb/musb/musb_dma.h > > +++ b/drivers/usb/musb/musb_dma.h > > @@ -35,6 +35,12 @@ > > * whether shared with the Inventra core or separate. > > */ > > > > +#define MUSB_HSDMA_BASE 0x200 > > +#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) > > +#define MUSB_HSDMA_CONTROL 0x4 > > +#define MUSB_HSDMA_ADDRESS 0x8 > > +#define MUSB_HSDMA_COUNT 0xc > > + > > #define DMA_ADDR_INVALID (~(dma_addr_t)0) > > > > #ifdef CONFIG_MUSB_PIO_ONLY > > @@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct dma_controller *d) { } > > extern struct dma_controller * > > musbhs_dma_controller_create(struct musb *musb, void __iomem *base); > > extern void musbhs_dma_controller_destroy(struct dma_controller *c); > > +extern struct dma_controller * > > +musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base); > > +extern irqreturn_t dma_controller_irq(int irq, void *private_data); > > > > extern struct dma_controller * > > tusb_dma_controller_create(struct musb *musb, void __iomem *base); > > diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c > > index 16d0ba4..ba66f44 100644 > > --- a/drivers/usb/musb/musb_host.c > > +++ b/drivers/usb/musb/musb_host.c > > @@ -290,39 +290,23 @@ static void musb_giveback(struct musb *musb, struct urb *urb, int status) > > static inline void musb_save_toggle(struct musb_qh *qh, int is_in, > > struct urb *urb) > > { > > - void __iomem *epio = qh->hw_ep->regs; > > - u16 csr; > > + struct musb *musb = qh->hw_ep->musb; > > + u16 csr; > > > > /* > > * FIXME: the current Mentor DMA code seems to have > > * problems getting toggle correct. > > */ > > - > > - if (is_in) > > - csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; > > - else > > - csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; > > - > > + csr = musb->io.get_toggle(qh, is_in); > > usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); > > } > > > > static inline u16 musb_set_toggle(struct musb_qh *qh, int is_in, > > struct urb *urb) > > { > > - u16 csr = 0; > > - u16 toggle = 0; > > - > > - toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in); > > - > > - if (is_in) > > - csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE > > - | MUSB_RXCSR_H_DATATOGGLE) : 0; > > - else > > - csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE > > - | MUSB_TXCSR_H_DATATOGGLE) > > - : MUSB_TXCSR_CLRDATATOG; > > + struct musb *musb = qh->hw_ep->musb; > > > > - return csr; > > + return musb->io.set_toggle(qh, is_in, urb); > > } > > Those two functions - musb_save_toggle() and musb_set_toggle() are very > short now, we can get rid of them, and directly use > musb->io.get/set_toggle(). Okay. > > > > /* > > diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h > > index 8058a58..9bae09b 100644 > > --- a/drivers/usb/musb/musb_io.h > > +++ b/drivers/usb/musb/musb_io.h > > @@ -22,6 +22,8 @@ > > * @read_fifo: platform specific function to read fifo > > * @write_fifo: platform specific function to write fifo > > * @busctl_offset: platform specific function to get busctl offset > > + * @get_toggle: platform specific function to get toggle > > + * @set_toggle: platform specific function to set toggle > > */ > > struct musb_io { > > u32 (*ep_offset)(u8 epnum, u16 offset); > > @@ -30,13 +32,17 @@ struct musb_io { > > void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); > > void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); > > u32 (*busctl_offset)(u8 epnum, u16 offset); > > + u16 (*get_toggle)(struct musb_qh *qh, int is_in); > > + u16 (*set_toggle)(struct musb_qh *qh, int is_in, struct urb *urb); > > }; > > > > /* Do not add new entries here, add them the struct musb_io instead */ > > extern u8 (*musb_readb)(const void __iomem *addr, unsigned offset); > > extern void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); > > +extern void (*musb_clearb)(void __iomem *addr, unsigned int offset, u8 data); > > extern u16 (*musb_readw)(const void __iomem *addr, unsigned offset); > > extern void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); > > +extern void (*musb_clearw)(void __iomem *addr, unsigned int offset, u16 data); > > extern u32 musb_readl(const void __iomem *addr, unsigned offset); > > extern void musb_writel(void __iomem *addr, unsigned offset, u32 data); > > > > diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c > > index a688f7f..b05fe68 100644 > > --- a/drivers/usb/musb/musbhsdma.c > > +++ b/drivers/usb/musb/musbhsdma.c > > @@ -10,12 +10,7 @@ > > #include > > #include > > #include "musb_core.h" > > - > > -#define MUSB_HSDMA_BASE 0x200 > > -#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) > > -#define MUSB_HSDMA_CONTROL 0x4 > > -#define MUSB_HSDMA_ADDRESS 0x8 > > -#define MUSB_HSDMA_COUNT 0xc > > +#include "musb_dma.h" > > > > #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ > > (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) > > @@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel) > > return 0; > > } > > > > -static irqreturn_t dma_controller_irq(int irq, void *private_data) > > +irqreturn_t dma_controller_irq(int irq, void *private_data) > > { > > struct musb_dma_controller *controller = private_data; > > struct musb *musb = controller->private_data; > > @@ -291,6 +286,9 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) > > > > int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); > > > > + /* some platform needs clear pending interrupts by manual */ > > + musb_clearb(musb->mregs, MUSB_HSDMA_INTR, int_hsdma); > > + > > if (!int_hsdma) { > > musb_dbg(musb, "spurious DMA irq"); > > > > @@ -382,6 +380,7 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) > > spin_unlock_irqrestore(&musb->lock, flags); > > return retval; > > } > > +EXPORT_SYMBOL_GPL(dma_controller_irq); > > > > void musbhs_dma_controller_destroy(struct dma_controller *c) > > { > > @@ -397,18 +396,10 @@ void musbhs_dma_controller_destroy(struct dma_controller *c) > > } > > EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy); > > > > -struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > +static struct musb_dma_controller *dma_controller_alloc(struct musb *musb, > > void __iomem *base) > > { > > struct musb_dma_controller *controller; > > - struct device *dev = musb->controller; > > - struct platform_device *pdev = to_platform_device(dev); > > - int irq = platform_get_irq_byname(pdev, "dma"); > > - > > - if (irq <= 0) { > > - dev_err(dev, "No DMA interrupt line!\n"); > > - return NULL; > > - } > > > > controller = kzalloc(sizeof(*controller), GFP_KERNEL); > > if (!controller) > > @@ -422,6 +413,25 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > controller->controller.channel_release = dma_channel_release; > > controller->controller.channel_program = dma_channel_program; > > controller->controller.channel_abort = dma_channel_abort; > > + return controller; > > +} > > + > > +struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > + void __iomem *base) > > +{ > > + struct musb_dma_controller *controller; > > + struct device *dev = musb->controller; > > + struct platform_device *pdev = to_platform_device(dev); > > + int irq = platform_get_irq_byname(pdev, "dma"); > > + > > + if (irq <= 0) { > > + dev_err(dev, "No DMA interrupt line!\n"); > > + return NULL; > > + } > > + > > + controller = dma_controller_alloc(musb, base); > > + if (!controller) > > + return NULL; > > > > if (request_irq(irq, dma_controller_irq, 0, > > dev_name(musb->controller), &controller->controller)) { > > @@ -436,3 +446,16 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > return &controller->controller; > > } > > EXPORT_SYMBOL_GPL(musbhs_dma_controller_create); > > + > > +struct dma_controller *musbhs_dma_controller_create_noirq(struct musb *musb, > > + void __iomem *base) > > +{ > > + struct musb_dma_controller *controller; > > + > > + controller = dma_controller_alloc(musb, base); > > + if (!controller) > > + return NULL; > > + > > + return &controller->controller; > > +} > > +EXPORT_SYMBOL_GPL(musbhs_dma_controller_create_noirq); > > regards, > -Bin. From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [v2,4/4] usb: musb: Add support for MediaTek musb controller From: min.guo@mediatek.com Message-Id: <1547606593.4433.178.camel@mhfsdcap03> Date: Wed, 16 Jan 2019 10:43:13 +0800 To: Bin Liu Cc: Rob Herring , Greg Kroah-Hartman , Mark Rutland , Matthias Brugger , Alan Stern , chunfeng.yun@mediatek.com, linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, Yonglong Wu List-ID: SGkgQmluLAoKT24gVHVlLCAyMDE5LTAxLTE1IGF0IDE0OjM4IC0wNjAwLCBCaW4gTGl1IHdyb3Rl Ogo+IEhpIE1pbiwKPiAKPiB2ZXJ5IGNsb3NlLCB0aGFua3MuCj4gQmVsb3cgSSB0cmllZCB0byBl eHBsYWluIGEgZnVydGhlciBjbGVhbnVwIGluIG11c2JfY2xlYXJiL3coKSBhbmQKPiBtdXNiX2dl dC9zZXRfdG9nZ2xlKCkgaW1wbGVtZW50YXRpb24uIFBsZWFzZSBsZXQgbWUga25vdyBpZiBpdCBp cyBub3QKPiBjbGVhci4KPiAKPiBCYXNpY2FsbHksIHdlIGRvbid0IG5lZWQgbXVzYl9kZWZhdWx0 X2NsZWFyYi93KCksIGp1c3QgYXNzaWduIHRoZQo+IG11c2JfaW8gZnVuY3Rpb24gcG9pbnRlcnMg dG8gbXVzYl9yZWFkYi93KCkuCj4gCj4gVGhlbiB0aGUgbXRrIHBsYXRmb3JtIG11c2JfY2xlYXJi L3coKSBjYWxscyBtdXNiX3JlYWRiL3coKSBhbmQKPiBtdXNiX3dyaXRlYi93KCkgdG8gaGFuZGxl IFcxQy4KCk9rYXkuCgo+IE9uIFR1ZSwgSmFuIDE1LCAyMDE5IGF0IDA5OjQzOjQ2QU0gKzA4MDAs IG1pbi5ndW9AbWVkaWF0ZWsuY29tIHdyb3RlOgo+ID4gRnJvbTogTWluIEd1byA8bWluLmd1b0Bt ZWRpYXRlay5jb20+Cj4gPiAKPiA+IFRoaXMgYWRkcyBzdXBwb3J0IGZvciBNZWRpYVRlayBtdXNi IGNvbnRyb2xsZXIgaW4KPiA+IGhvc3QsIHBlcmlwaGVyYWwgYW5kIG90ZyBtb2RlLgo+ID4gVGhl cmUgYXJlIHNvbWUgcXVpcmsgb2YgTWVkaWFUZWsgbXVzYiBjb250cm9sbGVyLCBzdWNoIGFzOgo+ ID4gIC1XMUMgaW50ZXJydXB0IHN0YXR1cyByZWdpc3RlcnMKPiA+ICAtUHJpdmF0ZSBkYXRhIHRv Z2dsZSByZWdpc3RlcnMKPiA+ICAtTm8gZGVkaWNhdGVkIERNQSBpbnRlcnJ1cHQgbGluZQo+ID4g Cj4gPiBTaWduZWQtb2ZmLWJ5OiBNaW4gR3VvIDxtaW4uZ3VvQG1lZGlhdGVrLmNvbT4KPiA+IFNp Z25lZC1vZmYtYnk6IFlvbmdsb25nIFd1IDx5b25nbG9uZy53dUBtZWRpYXRlay5jb20+Cj4gPiAt LS0KPiA+ICBkcml2ZXJzL3VzYi9tdXNiL0tjb25maWcgICAgIHwgICA4ICstCj4gPiAgZHJpdmVy cy91c2IvbXVzYi9NYWtlZmlsZSAgICB8ICAgMSArCj4gPiAgZHJpdmVycy91c2IvbXVzYi9tZWRp YXRlay5jICB8IDYxNyArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr Cj4gPiAgZHJpdmVycy91c2IvbXVzYi9tdXNiX2NvcmUuYyB8ICA2OSArKysrKwo+ID4gIGRyaXZl cnMvdXNiL211c2IvbXVzYl9jb3JlLmggfCAgIDkgKwo+ID4gIGRyaXZlcnMvdXNiL211c2IvbXVz Yl9kbWEuaCAgfCAgIDkgKwo+ID4gIGRyaXZlcnMvdXNiL211c2IvbXVzYl9ob3N0LmMgfCAgMjYg Ky0KPiA+ICBkcml2ZXJzL3VzYi9tdXNiL211c2JfaW8uaCAgIHwgICA2ICsKPiA+ICBkcml2ZXJz L3VzYi9tdXNiL211c2Joc2RtYS5jIHwgIDU1ICsrLS0KPiA+ICA5IGZpbGVzIGNoYW5nZWQsIDc2 MiBpbnNlcnRpb25zKCspLCAzOCBkZWxldGlvbnMoLSkKPiA+ICBjcmVhdGUgbW9kZSAxMDA2NDQg ZHJpdmVycy91c2IvbXVzYi9tZWRpYXRlay5jCj4gPiAKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJz L3VzYi9tdXNiL0tjb25maWcgYi9kcml2ZXJzL3VzYi9tdXNiL0tjb25maWcKPiA+IGluZGV4IGFk MDg4OTUuLmI3MmI3YzEgMTAwNjQ0Cj4gPiAtLS0gYS9kcml2ZXJzL3VzYi9tdXNiL0tjb25maWcK PiA+ICsrKyBiL2RyaXZlcnMvdXNiL211c2IvS2NvbmZpZwo+ID4gQEAgLTExNSw2ICsxMTUsMTIg QEAgY29uZmlnIFVTQl9NVVNCX0paNDc0MAo+ID4gIAlkZXBlbmRzIG9uIFVTQl9NVVNCX0dBREdF VAo+ID4gIAlkZXBlbmRzIG9uIFVTQl9PVEdfQkxBQ0tMSVNUX0hVQgo+ID4gIAo+ID4gK2NvbmZp ZyBVU0JfTVVTQl9NRURJQVRFSwo+ID4gKwl0cmlzdGF0ZSAiTWVkaWFUZWsgcGxhdGZvcm1zIgo+ ID4gKwlkZXBlbmRzIG9uIEFSQ0hfTUVESUFURUsgfHwgQ09NUElMRV9URVNUCj4gPiArCWRlcGVu ZHMgb24gTk9QX1VTQl9YQ0VJVgo+ID4gKwlkZXBlbmRzIG9uIEdFTkVSSUNfUEhZCj4gPiArCj4g PiAgY29uZmlnIFVTQl9NVVNCX0FNMzM1WF9DSElMRAo+ID4gIAl0cmlzdGF0ZQo+ID4gIAo+ID4g QEAgLTE0MSw3ICsxNDcsNyBAQCBjb25maWcgVVNCX1VYNTAwX0RNQQo+ID4gIAo+ID4gIGNvbmZp ZyBVU0JfSU5WRU5UUkFfRE1BCj4gPiAgCWJvb2wgJ0ludmVudHJhJwo+ID4gLQlkZXBlbmRzIG9u IFVTQl9NVVNCX09NQVAyUExVUwo+ID4gKwlkZXBlbmRzIG9uIFVTQl9NVVNCX09NQVAyUExVUyB8 fCBVU0JfTVVTQl9NRURJQVRFSwo+ID4gIAloZWxwCj4gPiAgCSAgRW5hYmxlIERNQSB0cmFuc2Zl cnMgdXNpbmcgTWVudG9yJ3MgZW5naW5lLgo+ID4gIAo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv dXNiL211c2IvTWFrZWZpbGUgYi9kcml2ZXJzL3VzYi9tdXNiL01ha2VmaWxlCj4gPiBpbmRleCAz YTg4Yzc5Li42M2Q4MmQwIDEwMDY0NAo+ID4gLS0tIGEvZHJpdmVycy91c2IvbXVzYi9NYWtlZmls ZQo+ID4gKysrIGIvZHJpdmVycy91c2IvbXVzYi9NYWtlZmlsZQo+ID4gQEAgLTI0LDYgKzI0LDcg QEAgb2JqLSQoQ09ORklHX1VTQl9NVVNCX0RBOFhYKQkJCSs9IGRhOHh4Lm8KPiA+ICBvYmotJChD T05GSUdfVVNCX01VU0JfVVg1MDApCQkJKz0gdXg1MDAubwo+ID4gIG9iai0kKENPTkZJR19VU0Jf TVVTQl9KWjQ3NDApCQkJKz0gano0NzQwLm8KPiA+ICBvYmotJChDT05GSUdfVVNCX01VU0JfU1VO WEkpCQkJKz0gc3VueGkubwo+ID4gK29iai0kKENPTkZJR19VU0JfTVVTQl9NRURJQVRFSykgICAg ICAJCSs9IG1lZGlhdGVrLm8KPiA+ICAKPiA+ICAKPiA+ICBvYmotJChDT05GSUdfVVNCX01VU0Jf QU0zMzVYX0NISUxEKQkJKz0gbXVzYl9hbTMzNXgubwo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv dXNiL211c2IvbWVkaWF0ZWsuYyBiL2RyaXZlcnMvdXNiL211c2IvbWVkaWF0ZWsuYwo+ID4gbmV3 IGZpbGUgbW9kZSAxMDA2NDQKPiA+IGluZGV4IDAwMDAwMDAuLjcyMjE5ODkKPiA+IC0tLSAvZGV2 L251bGwKPiA+ICsrKyBiL2RyaXZlcnMvdXNiL211c2IvbWVkaWF0ZWsuYwo+ID4gQEAgLTAsMCAr MSw2MTcgQEAKPiA+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ID4gKy8q Cj4gPiArICogQ29weXJpZ2h0IChDKSAyMDE4IE1lZGlhVGVrIEluYy4KPiA+ICsgKgo+ID4gKyAq IEF1dGhvcjoKPiA+ICsgKiAgTWluIEd1byA8bWluLmd1b0BtZWRpYXRlay5jb20+Cj4gPiArICog IFlvbmdsb25nIFd1IDx5b25nbG9uZy53dUBtZWRpYXRlay5jb20+Cj4gPiArICovCj4gPiArCj4g PiArI2luY2x1ZGUgPGxpbnV4L2Nsay5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwcGlu Zy5oPgo+ID4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPiA+ICsjaW5jbHVkZSA8bGludXgv cGxhdGZvcm1fZGV2aWNlLmg+Cj4gPiArI2luY2x1ZGUgPGxpbnV4L3VzYi91c2JfcGh5X2dlbmVy aWMuaD4KPiA+ICsjaW5jbHVkZSAibXVzYl9jb3JlLmgiCj4gPiArI2luY2x1ZGUgIm11c2JfZG1h LmgiCj4gPiArCj4gPiArI2RlZmluZSBVU0JfTDFJTlRTCTB4MDBhMAo+ID4gKyNkZWZpbmUgVVNC X0wxSU5UTQkweDAwYTQKPiA+ICsjZGVmaW5lIE1US19NVVNCX1RYRlVOQ0FERFIJMHgwNDgwCj4g PiArCj4gPiArLyogTWVkaWFUZWsgY29udHJvbGxlciB0b2dnbGUgZW5hYmxlIGFuZCBzdGF0dXMg cmVnICovCj4gPiArI2RlZmluZSBNVVNCX1JYVE9HCQkweDgwCj4gPiArI2RlZmluZSBNVVNCX1JY VE9HRU4JCTB4ODIKPiA+ICsjZGVmaW5lIE1VU0JfVFhUT0cJCTB4ODQKPiA+ICsjZGVmaW5lIE1V U0JfVFhUT0dFTgkJMHg4Ngo+ID4gKwo+ID4gKyNkZWZpbmUgVFhfSU5UX1NUQVRVUwkJQklUKDAp Cj4gPiArI2RlZmluZSBSWF9JTlRfU1RBVFVTCQlCSVQoMSkKPiA+ICsjZGVmaW5lIFVTQkNPTV9J TlRfU1RBVFVTCUJJVCgyKQo+IAo+IG1pc3NpbmcgYSBUQUIgZm9yIHRoZSBhbGlnbm1lbnQ/CgpP a2F5LgoKPiA+ICsjZGVmaW5lIERNQV9JTlRfU1RBVFVTCQlCSVQoMykKPiA+ICsKPiA+ICsjZGVm aW5lIERNQV9JTlRSX1NUQVRVU19NU0sJCUdFTk1BU0soNywgMCkKPiA+ICsjZGVmaW5lIERNQV9J TlRSX1VOTUFTS19TRVRfTVNLCUdFTk1BU0soMzEsIDI0KQo+ID4gKwo+ID4gK2VudW0gbXRrX3Zi dXNfaWRfc3RhdGUgewo+ID4gKwlNVEtfSURfRkxPQVQgPSAxLAo+ID4gKwlNVEtfSURfR1JPVU5E LAo+ID4gKwlNVEtfVkJVU19PRkYsCj4gPiArCU1US19WQlVTX1ZBTElELAo+ID4gK307Cj4gPiAr Cj4gPiArc3RydWN0IG10a19nbHVlIHsKPiA+ICsJc3RydWN0IGRldmljZSAqZGV2Owo+ID4gKwlz dHJ1Y3QgbXVzYiAqbXVzYjsKPiA+ICsJc3RydWN0IHBsYXRmb3JtX2RldmljZSAqbXVzYl9wZGV2 Owo+ID4gKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICp1c2JfcGh5Owo+ID4gKwlzdHJ1Y3QgcGh5 ICpwaHk7Cj4gPiArCXN0cnVjdCB1c2JfcGh5ICp4Y2VpdjsKPiA+ICsJZW51bSBwaHlfbW9kZSBw aHlfbW9kZTsKPiA+ICsJc3RydWN0IGNsayAqbWFpbjsKPiA+ICsJc3RydWN0IGNsayAqbWN1Owo+ ID4gKwlzdHJ1Y3QgY2xrICp1bml2cGxsOwo+ID4gKwlzdHJ1Y3QgcmVndWxhdG9yICp2YnVzOwo+ ID4gKwlzdHJ1Y3QgZXh0Y29uX2RldiAqZWRldjsKPiA+ICsJc3RydWN0IG5vdGlmaWVyX2Jsb2Nr IHZidXNfbmI7Cj4gPiArCXN0cnVjdCBub3RpZmllcl9ibG9jayBpZF9uYjsKPiA+ICt9Owo+ID4g Kwo+ID4gK3N0YXRpYyBpbnQgbXRrX211c2JfY2xrc19nZXQoc3RydWN0IG10a19nbHVlICpnbHVl KQo+ID4gK3sKPiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gZ2x1ZS0+ZGV2Owo+ID4gKwo+ID4g KwlnbHVlLT5tYWluID0gZGV2bV9jbGtfZ2V0KGRldiwgIm1haW4iKTsKPiA+ICsJaWYgKElTX0VS UihnbHVlLT5tYWluKSkgewo+ID4gKwkJZGV2X2VycihkZXYsICJmYWlsIHRvIGdldCBtYWluIGNs b2NrXG4iKTsKPiA+ICsJCXJldHVybiBQVFJfRVJSKGdsdWUtPm1haW4pOwo+ID4gKwl9Cj4gPiAr Cj4gPiArCWdsdWUtPm1jdSA9IGRldm1fY2xrX2dldChkZXYsICJtY3UiKTsKPiA+ICsJaWYgKElT X0VSUihnbHVlLT5tY3UpKSB7Cj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWwgdG8gZ2V0IG1jdSBj bG9ja1xuIik7Cj4gPiArCQlyZXR1cm4gUFRSX0VSUihnbHVlLT5tY3UpOwo+ID4gKwl9Cj4gPiAr Cj4gPiArCWdsdWUtPnVuaXZwbGwgPSBkZXZtX2Nsa19nZXQoZGV2LCAidW5pdnBsbCIpOwo+ID4g KwlpZiAoSVNfRVJSKGdsdWUtPnVuaXZwbGwpKSB7Cj4gPiArCQlkZXZfZXJyKGRldiwgImZhaWwg dG8gZ2V0IHVuaXZwbGwgY2xvY2tcbiIpOwo+ID4gKwkJcmV0dXJuIFBUUl9FUlIoZ2x1ZS0+dW5p dnBsbCk7Cj4gPiArCX0KPiA+ICsKPiA+ICsJcmV0dXJuIDA7Cj4gPiArfQo+ID4gKwo+ID4gK3N0 YXRpYyBpbnQgbXRrX211c2JfY2xrc19lbmFibGUoc3RydWN0IG10a19nbHVlICpnbHVlKQo+ID4g K3sKPiA+ICsJaW50IHJldDsKPiA+ICsKPiA+ICsJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGds dWUtPm1haW4pOwo+ID4gKwlpZiAocmV0KSB7Cj4gPiArCQlkZXZfZXJyKGdsdWUtPmRldiwgImZh aWxlZCB0byBlbmFibGUgbWFpbiBjbG9ja1xuIik7Cj4gPiArCQlnb3RvIGVycl9tYWluX2NsazsK PiA+ICsJfQo+ID4gKwo+ID4gKwlyZXQgPSBjbGtfcHJlcGFyZV9lbmFibGUoZ2x1ZS0+bWN1KTsK PiA+ICsJaWYgKHJldCkgewo+ID4gKwkJZGV2X2VycihnbHVlLT5kZXYsICJmYWlsZWQgdG8gZW5h YmxlIG1jdSBjbG9ja1xuIik7Cj4gPiArCQlnb3RvIGVycl9tY3VfY2xrOwo+ID4gKwl9Cj4gPiAr Cj4gPiArCXJldCA9IGNsa19wcmVwYXJlX2VuYWJsZShnbHVlLT51bml2cGxsKTsKPiA+ICsJaWYg KHJldCkgewo+ID4gKwkJZGV2X2VycihnbHVlLT5kZXYsICJmYWlsZWQgdG8gZW5hYmxlIHVuaXZw bGwgY2xvY2tcbiIpOwo+ID4gKwkJZ290byBlcnJfdW5pdnBsbF9jbGs7Cj4gPiArCX0KPiA+ICsK PiA+ICsJcmV0dXJuIDA7Cj4gPiArCj4gPiArZXJyX3VuaXZwbGxfY2xrOgo+ID4gKwljbGtfZGlz YWJsZV91bnByZXBhcmUoZ2x1ZS0+bWN1KTsKPiA+ICtlcnJfbWN1X2NsazoKPiA+ICsJY2xrX2Rp c2FibGVfdW5wcmVwYXJlKGdsdWUtPm1haW4pOwo+ID4gK2Vycl9tYWluX2NsazoKPiA+ICsJcmV0 dXJuIHJldDsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHZvaWQgbXRrX211c2JfY2xrc19kaXNh YmxlKHN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSkKPiA+ICt7Cj4gPiArCWNsa19kaXNhYmxlX3VucHJl cGFyZShnbHVlLT51bml2cGxsKTsKPiA+ICsJY2xrX2Rpc2FibGVfdW5wcmVwYXJlKGdsdWUtPm1j dSk7Cj4gPiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShnbHVlLT5tYWluKTsKPiA+ICt9Cj4gPiAr Cj4gPiArc3RhdGljIHZvaWQgbXRrX211c2Jfc2V0X3ZidXMoc3RydWN0IG11c2IgKm11c2IsIGlu dCBpc19vbikKPiA+ICt7Cj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldiA9IG11c2ItPmNvbnRyb2xs ZXI7Cj4gPiArCXN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSA9IGRldl9nZXRfZHJ2ZGF0YShkZXYtPnBh cmVudCk7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCS8qIHZidXMgaXMgb3B0aW9uYWwgKi8K PiA+ICsJaWYgKCFnbHVlLT52YnVzKQo+ID4gKwkJcmV0dXJuOwo+ID4gKwo+ID4gKwlkZXZfZGJn KG11c2ItPmNvbnRyb2xsZXIsICIlcywgaXNfb249JWRcclxuIiwgX19mdW5jX18sIGlzX29uKTsK PiA+ICsJaWYgKGlzX29uKSB7Cj4gPiArCQlyZXQgPSByZWd1bGF0b3JfZW5hYmxlKGdsdWUtPnZi dXMpOwo+ID4gKwkJaWYgKHJldCkgewo+ID4gKwkJCWRldl9lcnIoZ2x1ZS0+ZGV2LCAiZmFpbCB0 byBlbmFibGUgdmJ1cyByZWd1bGF0b3JcbiIpOwo+ID4gKwkJCXJldHVybjsKPiA+ICsJCX0KPiA+ ICsJfSBlbHNlIHsKPiA+ICsJCXJlZ3VsYXRvcl9kaXNhYmxlKGdsdWUtPnZidXMpOwo+ID4gKwl9 Cj4gPiArfQo+ID4gKwo+ID4gKy8qCj4gPiArICogc3dpdGNoIHRvIGhvc3Q6IC0+IE1US19WQlVT X09GRiAtLT4gTVRLX0lEX0dST1VORAo+ID4gKyAqIHN3aXRjaCB0byBkZXZpY2U6IC0+IE1US19J RF9GTE9BVCAtLT4gTVRLX1ZCVVNfVkFMSUQKPiA+ICsgKi8KPiA+ICtzdGF0aWMgdm9pZCBtdGtf bXVzYl9zZXRfbWFpbGJveChzdHJ1Y3QgbXRrX2dsdWUgKmdsdWUsCj4gPiArCWVudW0gbXRrX3Zi dXNfaWRfc3RhdGUgc3RhdHVzKQo+IAo+IGFkZCBvbmUgbW9yZSBUQUIgZm9yIHBhcmFtcy4KCk9r YXkuCgo+ID4gK3sKPiA+ICsJc3RydWN0IG11c2IgKm11c2IgPSBnbHVlLT5tdXNiOwo+ID4gKwl1 OCBkZXZjdGwgPSAwOwo+ID4gKwo+ID4gKwlkZXZfZGJnKGdsdWUtPmRldiwgIm1haWxib3ggc3Rh dGUoJWQpXG4iLCBzdGF0dXMpOwo+ID4gKwlzd2l0Y2ggKHN0YXR1cykgewo+ID4gKwljYXNlIE1U S19JRF9HUk9VTkQ6Cj4gPiArCQlwaHlfcG93ZXJfb24oZ2x1ZS0+cGh5KTsKPiA+ICsJCWRldmN0 bCA9IHJlYWRiKG11c2ItPm1yZWdzICsgTVVTQl9ERVZDVEwpOwo+ID4gKwkJbXVzYi0+eGNlaXYt Pm90Zy0+c3RhdGUgPSBPVEdfU1RBVEVfQV9XQUlUX1ZSSVNFOwo+ID4gKwkJbXRrX211c2Jfc2V0 X3ZidXMobXVzYiwgMSk7Cj4gPiArCQlnbHVlLT5waHlfbW9kZSA9IFBIWV9NT0RFX1VTQl9IT1NU Owo+ID4gKwkJcGh5X3NldF9tb2RlKGdsdWUtPnBoeSwgZ2x1ZS0+cGh5X21vZGUpOwo+ID4gKwkJ ZGV2Y3RsIHw9IE1VU0JfREVWQ1RMX1NFU1NJT047Cj4gPiArCQltdXNiX3dyaXRlYihtdXNiLT5t cmVncywgTVVTQl9ERVZDVEwsIGRldmN0bCk7Cj4gPiArCQlNVVNCX0hTVF9NT0RFKG11c2IpOwo+ ID4gKwkJYnJlYWs7Cj4gPiArCS8qCj4gPiArCSAqIE1US19JRF9GTE9BVCBwcm9jZXNzIGlzIHRo ZSBzYW1lIGFzIE1US19WQlVTX1ZBTElECj4gPiArCSAqIGV4Y2VwdCB0aGF0IHR1cm4gb2ZmIFZC VVMKPiA+ICsJICovCj4gPiArCWNhc2UgTVRLX0lEX0ZMT0FUOgo+ID4gKwkJbXRrX211c2Jfc2V0 X3ZidXMobXVzYiwgMCk7Cj4gPiArCQkvKiBmYWxsIHRocm91Z2ggKi8KPiA+ICsJY2FzZSBNVEtf VkJVU19PRkY6Cj4gPiArCQltdXNiLT54Y2Vpdi0+b3RnLT5zdGF0ZSA9IE9UR19TVEFURV9CX0lE TEU7Cj4gPiArCQlkZXZjdGwgJj0gfk1VU0JfREVWQ1RMX1NFU1NJT047Cj4gPiArCQltdXNiX3dy aXRlYihtdXNiLT5tcmVncywgTVVTQl9ERVZDVEwsIGRldmN0bCk7Cj4gPiArCQlwaHlfcG93ZXJf b2ZmKGdsdWUtPnBoeSk7Cj4gPiArCQlicmVhazsKPiA+ICsJY2FzZSBNVEtfVkJVU19WQUxJRDoK PiA+ICsJCXBoeV9wb3dlcl9vbihnbHVlLT5waHkpOwo+ID4gKwkJZ2x1ZS0+cGh5X21vZGUgPSBQ SFlfTU9ERV9VU0JfREVWSUNFOwo+ID4gKwkJcGh5X3NldF9tb2RlKGdsdWUtPnBoeSwgZ2x1ZS0+ cGh5X21vZGUpOwo+ID4gKwkJTVVTQl9ERVZfTU9ERShtdXNiKTsKPiA+ICsJCWJyZWFrOwo+ID4g KwlkZWZhdWx0Ogo+ID4gKwkJZGV2X2VycihnbHVlLT5kZXYsICJpbnZhbGlkIHN0YXRlXG4iKTsK PiA+ICsJfQo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50IG10a19tdXNiX2lkX25vdGlmaWVy KHN0cnVjdCBub3RpZmllcl9ibG9jayAqbmIsCj4gPiArCXVuc2lnbmVkIGxvbmcgZXZlbnQsIHZv aWQgKnB0cikKPiA+ICt7Cj4gPiArCXN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSA9IGNvbnRhaW5lcl9v ZihuYiwgc3RydWN0IG10a19nbHVlLCBpZF9uYik7Cj4gPiArCj4gPiArCWlmIChldmVudCkKPiA+ ICsJCW10a19tdXNiX3NldF9tYWlsYm94KGdsdWUsIE1US19JRF9HUk9VTkQpOwo+ID4gKwllbHNl Cj4gPiArCQltdGtfbXVzYl9zZXRfbWFpbGJveChnbHVlLCBNVEtfSURfRkxPQVQpOwo+ID4gKwo+ ID4gKwlyZXR1cm4gTk9USUZZX0RPTkU7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpbnQgbXRr X211c2JfdmJ1c19ub3RpZmllcihzdHJ1Y3Qgbm90aWZpZXJfYmxvY2sgKm5iLAo+ID4gKwl1bnNp Z25lZCBsb25nIGV2ZW50LCB2b2lkICpwdHIpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXRrX2dsdWUg KmdsdWUgPSBjb250YWluZXJfb2YobmIsIHN0cnVjdCBtdGtfZ2x1ZSwgdmJ1c19uYik7Cj4gPiAr Cj4gPiArCWlmIChldmVudCkKPiA+ICsJCW10a19tdXNiX3NldF9tYWlsYm94KGdsdWUsIE1US19W QlVTX1ZBTElEKTsKPiA+ICsJZWxzZQo+ID4gKwkJbXRrX211c2Jfc2V0X21haWxib3goZ2x1ZSwg TVRLX1ZCVVNfT0ZGKTsKPiA+ICsKPiA+ICsJcmV0dXJuIE5PVElGWV9ET05FOwo+ID4gK30KPiA+ ICsKPiA+ICtzdGF0aWMgdm9pZCBtdGtfb3RnX3N3aXRjaF9pbml0KHN0cnVjdCBtdGtfZ2x1ZSAq Z2x1ZSkKPiA+ICt7Cj4gPiArCWludCByZXQ7Cj4gPiArCj4gPiArCS8qIGV4dGNvbiBpcyBvcHRp b25hbCAqLwo+ID4gKwlpZiAoIWdsdWUtPmVkZXYpCj4gPiArCQlyZXR1cm47Cj4gPiArCj4gPiAr CWdsdWUtPnZidXNfbmIubm90aWZpZXJfY2FsbCA9IG10a19tdXNiX3ZidXNfbm90aWZpZXI7Cj4g PiArCXJldCA9IGRldm1fZXh0Y29uX3JlZ2lzdGVyX25vdGlmaWVyKGdsdWUtPmRldiwgZ2x1ZS0+ ZWRldiwgRVhUQ09OX1VTQiwKPiA+ICsJCQkJCSZnbHVlLT52YnVzX25iKTsKPiA+ICsJaWYgKHJl dCA8IDApCj4gPiArCQlkZXZfZXJyKGdsdWUtPmRldiwgImZhaWxlZCB0byByZWdpc3RlciBub3Rp ZmllciBmb3IgVVNCXG4iKTsKPiA+ICsKPiA+ICsJZ2x1ZS0+aWRfbmIubm90aWZpZXJfY2FsbCA9 IG10a19tdXNiX2lkX25vdGlmaWVyOwo+ID4gKwlyZXQgPSBkZXZtX2V4dGNvbl9yZWdpc3Rlcl9u b3RpZmllcihnbHVlLT5kZXYsIGdsdWUtPmVkZXYsCj4gPiArCQkJCQlFWFRDT05fVVNCX0hPU1Qs ICZnbHVlLT5pZF9uYik7Cj4gPiArCWlmIChyZXQgPCAwKQo+ID4gKwkJZGV2X2VycihnbHVlLT5k ZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXIgbm90aWZpZXIgZm9yIFVTQi1IT1NUXG4iKTsKPiA+ICsK PiA+ICsJZGV2X2RiZyhnbHVlLT5kZXYsICJFWFRDT05fVVNCOiAlZCwgRVhUQ09OX1VTQl9IT1NU OiAlZFxuIiwKPiA+ICsJCWV4dGNvbl9nZXRfc3RhdGUoZ2x1ZS0+ZWRldiwgRVhUQ09OX1VTQiks Cj4gPiArCQlleHRjb25fZ2V0X3N0YXRlKGdsdWUtPmVkZXYsIEVYVENPTl9VU0JfSE9TVCkpOwo+ ID4gKwo+ID4gKwkvKiBkZWZhdWx0IGFzIGhvc3QsIHN3aXRjaCB0byBkZXZpY2UgbW9kZSBpZiBu ZWVkZWQgKi8KPiA+ICsJaWYgKGV4dGNvbl9nZXRfc3RhdGUoZ2x1ZS0+ZWRldiwgRVhUQ09OX1VT Ql9IT1NUKSA9PSBmYWxzZSkKPiA+ICsJCW10a19tdXNiX3NldF9tYWlsYm94KGdsdWUsIE1US19J RF9GTE9BVCk7Cj4gPiArCWlmIChleHRjb25fZ2V0X3N0YXRlKGdsdWUtPmVkZXYsIEVYVENPTl9V U0IpID09IHRydWUpCj4gPiArCQltdGtfbXVzYl9zZXRfbWFpbGJveChnbHVlLCBNVEtfVkJVU19W QUxJRCk7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpcnFyZXR1cm5fdCBnZW5lcmljX2ludGVy cnVwdChpbnQgaXJxLCB2b2lkICpfX2hjaSkKPiA+ICt7Cj4gPiArCXVuc2lnbmVkIGxvbmcgZmxh Z3M7Cj4gPiArCWlycXJldHVybl90IHJldHZhbCA9IElSUV9OT05FOwo+ID4gKwlzdHJ1Y3QgbXVz YiAqbXVzYiA9IF9faGNpOwo+ID4gKwo+ID4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmbXVzYi0+bG9j aywgZmxhZ3MpOwo+ID4gKwltdXNiLT5pbnRfdXNiID0gbXVzYl9yZWFkYihtdXNiLT5tcmVncywg TVVTQl9JTlRSVVNCKSAmCj4gPiArCSAgICBtdXNiX3JlYWRiKG11c2ItPm1yZWdzLCBNVVNCX0lO VFJVU0JFKTsKPiA+ICsJbXVzYi0+aW50X3R4ID0gbXVzYl9yZWFkdyhtdXNiLT5tcmVncywgTVVT Ql9JTlRSVFgpCj4gPiArCSAgICAmIG11c2JfcmVhZHcobXVzYi0+bXJlZ3MsIE1VU0JfSU5UUlRY RSk7Cj4gPiArCW11c2ItPmludF9yeCA9IG11c2JfcmVhZHcobXVzYi0+bXJlZ3MsIE1VU0JfSU5U UlJYKQo+ID4gKwkgICAgJiBtdXNiX3JlYWR3KG11c2ItPm1yZWdzLCBNVVNCX0lOVFJSWEUpOwo+ ID4gKwkvKiBNZWRpYVRlayBjb250cm9sbGVyIGludGVycnVwdCBzdGF0dXMgaXMgVzFDICovCj4g PiArCW11c2JfY2xlYXJ3KG11c2ItPm1yZWdzLCBNVVNCX0lOVFJSWCwgbXVzYi0+aW50X3J4KTsK PiA+ICsJbXVzYl9jbGVhcncobXVzYi0+bXJlZ3MsIE1VU0JfSU5UUlRYLCBtdXNiLT5pbnRfdHgp Owo+ID4gKwltdXNiX2NsZWFyYihtdXNiLT5tcmVncywgTVVTQl9JTlRSVVNCLCBtdXNiLT5pbnRf dXNiKTsKPiA+ICsKPiA+ICsJaWYgKG11c2ItPmludF91c2IgfHwgbXVzYi0+aW50X3R4IHx8IG11 c2ItPmludF9yeCkKPiA+ICsJCXJldHZhbCA9IG11c2JfaW50ZXJydXB0KG11c2IpOwo+ID4gKwo+ ID4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZtdXNiLT5sb2NrLCBmbGFncyk7Cj4gPiArCj4g PiArCXJldHVybiByZXR2YWw7Cj4gPiArfQo+ID4gKwo+ID4gK3N0YXRpYyBpcnFyZXR1cm5fdCBt dGtfbXVzYl9pbnRlcnJ1cHQoaW50IGlycSwgdm9pZCAqZGV2X2lkKQo+ID4gK3sKPiA+ICsJaXJx cmV0dXJuX3QgcmV0dmFsID0gSVJRX05PTkU7Cj4gPiArCXN0cnVjdCBtdXNiICptdXNiID0gKHN0 cnVjdCBtdXNiICopZGV2X2lkOwo+ID4gKwl1MzIgbDFfaW50czsKPiA+ICsKPiA+ICsJbDFfaW50 cyA9IG11c2JfcmVhZGwobXVzYi0+bXJlZ3MsIFVTQl9MMUlOVFMpICYKPiA+ICsJCQltdXNiX3Jl YWRsKG11c2ItPm1yZWdzLCBVU0JfTDFJTlRNKTsKPiA+ICsKPiA+ICsJaWYgKGwxX2ludHMgJiAo VFhfSU5UX1NUQVRVUyB8IFJYX0lOVF9TVEFUVVMgfCBVU0JDT01fSU5UX1NUQVRVUykpCj4gPiAr CQlyZXR2YWwgPSBnZW5lcmljX2ludGVycnVwdChpcnEsIG11c2IpOwo+ID4gKwo+ID4gKyNpZiBk ZWZpbmVkKENPTkZJR19VU0JfSU5WRU5UUkFfRE1BKQo+ID4gKwlpZiAobDFfaW50cyAmIERNQV9J TlRfU1RBVFVTKQo+ID4gKwkJcmV0dmFsID0gZG1hX2NvbnRyb2xsZXJfaXJxKGlycSwgbXVzYi0+ ZG1hX2NvbnRyb2xsZXIpOwo+ID4gKyNlbmRpZgo+ID4gKwlyZXR1cm4gcmV0dmFsOwo+ID4gK30K PiA+ICsKPiA+ICtzdGF0aWMgdTMyIG10a19tdXNiX2J1c2N0bF9vZmZzZXQodTggZXBudW0sIHUx NiBvZmZzZXQpCj4gPiArewo+ID4gKwlyZXR1cm4gTVRLX01VU0JfVFhGVU5DQUREUiArIG9mZnNl dCArIDggKiBlcG51bTsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHZvaWQgbXRrX211c2JfY2xl YXJiKHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTggZGF0YSkKPiAK PiByZW1vdmUgJ3U4IGRhdGEnIHBhcmFtZXRlciwgdGhlbiBhZGQ6CgpPa2F5LgoKPiA+ICt7Cj4g Cj4gCXU4IGRhdGE7Cj4gCj4gPiArCS8qIFcxQyAqLwo+IAlkYXRhID0gbXVzYl9yZWFkYihhZGRy LCBvZmZzZXQpOwo+ID4gKwltdXNiX3dyaXRlYihhZGRyLCBvZmZzZXQsIGRhdGEpOwo+ID4gK30K PiA+ICsKPiA+ICtzdGF0aWMgdm9pZCBtdGtfbXVzYl9jbGVhcncodm9pZCBfX2lvbWVtICphZGRy LCB1bnNpZ25lZCBpbnQgb2Zmc2V0LCB1MTYgZGF0YSkKPiA+ICt7Cj4gPiArCS8qIFcxQyAqLwo+ ID4gKwltdXNiX3dyaXRldyhhZGRyLCBvZmZzZXQsIGRhdGEpOwo+ID4gK30KPiAKPiBzaW1pbGFy IGFzIG10a19tdXNiX2NsZWFyYigpIGFib3ZlLgoKT2theS4KCj4gPiArCj4gPiArc3RhdGljIGlu dCBtdGtfbXVzYl9pbml0KHN0cnVjdCBtdXNiICptdXNiKQo+ID4gK3sKPiA+ICsJc3RydWN0IGRl dmljZSAqZGV2ID0gbXVzYi0+Y29udHJvbGxlcjsKPiA+ICsJc3RydWN0IG10a19nbHVlICpnbHVl ID0gZGV2X2dldF9kcnZkYXRhKGRldi0+cGFyZW50KTsKPiA+ICsJaW50IHJldDsKPiAKPiBbc25p cF0KPiAKPiA+ICsJaWYgKHBkYXRhLT5tb2RlID09IFVTQl9EUl9NT0RFX09URykKPiA+ICsJCW10 a19vdGdfc3dpdGNoX2luaXQoZ2x1ZSk7Cj4gPiArCj4gPiArCWRldl9pbmZvKGRldiwgIlVTQiBw cm9iZSBkb25lIVxuIik7Cj4gCj4gbm90IHJlYWxseSB1c2VmdWwsIGNhbiBiZSByZW1vdmVkLgoK T2theS4KCj4gPiArCXJldHVybiAwOwo+ID4gKwo+ID4gK2Vycl9kZXZpY2VfcmVnaXN0ZXI6Cj4g PiArCW10a19tdXNiX2Nsa3NfZGlzYWJsZShnbHVlKTsKPiA+ICtlcnJfZW5hYmxlX2NsazoKPiA+ ICsJcG1fcnVudGltZV9wdXRfc3luYyhkZXYpOwo+ID4gKwlwbV9ydW50aW1lX2Rpc2FibGUoZGV2 KTsKPiA+ICtlcnJfdW5yZWdpc3Rlcl91c2JfcGh5Ogo+ID4gKwl1c2JfcGh5X2dlbmVyaWNfdW5y ZWdpc3RlcihnbHVlLT51c2JfcGh5KTsKPiA+ICsJcmV0dXJuIHJldDsKPiA+ICt9Cj4gPiArCj4g PiArc3RhdGljIGludCBtdGtfbXVzYl9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRl dikKPiA+ICt7Cj4gPiArCXN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSA9IHBsYXRmb3JtX2dldF9kcnZk YXRhKHBkZXYpOwo+ID4gKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICp1c2JfcGh5ID0gZ2x1ZS0+ dXNiX3BoeTsKPiA+ICsKPiA+ICsJcGxhdGZvcm1fZGV2aWNlX3VucmVnaXN0ZXIoZ2x1ZS0+bXVz Yl9wZGV2KTsKPiA+ICsJdXNiX3BoeV9nZW5lcmljX3VucmVnaXN0ZXIodXNiX3BoeSk7Cj4gPiAr Cj4gPiArCXJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICsjaWZkZWYgQ09ORklHX09GCj4gPiAr c3RhdGljIGNvbnN0IHN0cnVjdCBvZl9kZXZpY2VfaWQgbXRrX211c2JfbWF0Y2hbXSA9IHsKPiA+ ICsJey5jb21wYXRpYmxlID0gIm1lZGlhdGVrLG10ay1tdXNiIix9LAo+ID4gKwl7fSwKPiA+ICt9 Owo+ID4gK01PRFVMRV9ERVZJQ0VfVEFCTEUob2YsIG10a19tdXNiX21hdGNoKTsKPiA+ICsjZW5k aWYKPiA+ICsKPiA+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBtdGtfbXVzYl9kcml2 ZXIgPSB7Cj4gPiArCS5wcm9iZSA9IG10a19tdXNiX3Byb2JlLAo+ID4gKwkucmVtb3ZlID0gbXRr X211c2JfcmVtb3ZlLAo+ID4gKwkuZHJpdmVyID0gewo+ID4gKwkJICAgLm5hbWUgPSAibXVzYi1t dGsiLAo+ID4gKwkJICAgLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hfcHRyKG10a19tdXNiX21h dGNoKSwKPiA+ICsJfSwKPiA+ICt9Owo+ID4gKwo+ID4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIo bXRrX211c2JfZHJpdmVyKTsKPiA+ICsKPiA+ICtNT0RVTEVfREVTQ1JJUFRJT04oIk1lZGlhVGVr IE1VU0IgR2x1ZSBMYXllciIpOwo+ID4gK01PRFVMRV9BVVRIT1IoIk1pbiBHdW8gPG1pbi5ndW9A bWVkaWF0ZWsuY29tPiIpOwo+ID4gK01PRFVMRV9MSUNFTlNFKCJHUEwgdjIiKTsKPiA+IGRpZmYg LS1naXQgYS9kcml2ZXJzL3VzYi9tdXNiL211c2JfY29yZS5jIGIvZHJpdmVycy91c2IvbXVzYi9t dXNiX2NvcmUuYwo+ID4gaW5kZXggYjdkNTYyNy4uMmMwZDEwMiAxMDA2NDQKPiA+IC0tLSBhL2Ry aXZlcnMvdXNiL211c2IvbXVzYl9jb3JlLmMKPiA+ICsrKyBiL2RyaXZlcnMvdXNiL211c2IvbXVz Yl9jb3JlLmMKPiA+IEBAIC0yNjAsNiArMjYwLDExIEBAIHN0YXRpYyB2b2lkIG11c2JfZGVmYXVs dF93cml0ZWIodm9pZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBvZmZzZXQsIHU4IGRhdGEpCj4g PiAgCV9fcmF3X3dyaXRlYihkYXRhLCBhZGRyICsgb2Zmc2V0KTsKPiA+ICB9Cj4gPiAgCj4gPiAr c3RhdGljIHZvaWQKPiA+ICttdXNiX2RlZmF1bHRfY2xlYXJiKHZvaWQgX19pb21lbSAqYWRkciwg dW5zaWduZWQgaW50IG9mZnNldCwgdTggZGF0YSkKPiA+ICt7Cj4gPiArfQo+IAo+IGRvbid0IG5l ZWQgdGhpcywgdXNlIG11c2JfcmVhZGIoKSBmb3IgdGhlIGZ1bmN0aW9uIHBvaW50ZXIuCgpPa2F5 LgoKPiA+ICsKPiA+ICBzdGF0aWMgdTE2IG11c2JfZGVmYXVsdF9yZWFkdyhjb25zdCB2b2lkIF9f aW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCkKPiA+ICB7Cj4gPiAgCXUxNiBkYXRhID0gX19y YXdfcmVhZHcoYWRkciArIG9mZnNldCk7Cj4gPiBAQCAtMjc0LDYgKzI3OSw0MyBAQCBzdGF0aWMg dm9pZCBtdXNiX2RlZmF1bHRfd3JpdGV3KHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgb2Zm c2V0LCB1MTYgZGF0YSkKPiA+ICAJX19yYXdfd3JpdGV3KGRhdGEsIGFkZHIgKyBvZmZzZXQpOwo+ ID4gIH0KPiA+ICAKPiA+ICtzdGF0aWMgdm9pZAo+ID4gK211c2JfZGVmYXVsdF9jbGVhcncodm9p ZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBpbnQgb2Zmc2V0LCB1MTYgZGF0YSkKPiA+ICt7Cj4g PiArfQo+IAo+IGRvbid0IG5lZWQgdGhpcywgdXNlIG11c2JfcmVhZHcoKSBmb3IgdGhlIGZ1bmN0 aW9uIHBvaW50ZXIuCgpPa2F5LgoKPiA+ICsKPiA+ICtzdGF0aWMgdTE2IG11c2JfZGVmYXVsdF9n ZXRfdG9nZ2xlKHN0cnVjdCBtdXNiX3FoICpxaCwgaW50IGlzX2luKQo+ID4gK3sKPiA+ICsJdm9p ZCBfX2lvbWVtICplcGlvID0gcWgtPmh3X2VwLT5yZWdzOwo+ID4gKwl1MTYgY3NyOwo+ID4gKwo+ ID4gKwlpZiAoaXNfaW4pCj4gPiArCQljc3IgPSBtdXNiX3JlYWR3KGVwaW8sIE1VU0JfUlhDU1Ip ICYgTVVTQl9SWENTUl9IX0RBVEFUT0dHTEU7Cj4gPiArCWVsc2UKPiA+ICsJCWNzciA9IG11c2Jf cmVhZHcoZXBpbywgTVVTQl9UWENTUikgJiBNVVNCX1RYQ1NSX0hfREFUQVRPR0dMRTsKPiA+ICsK PiA+ICsJcmV0dXJuIGNzcjsKPiA+ICt9Cj4gPiArCj4gPiArc3RhdGljIHUxNiBtdXNiX2RlZmF1 bHRfc2V0X3RvZ2dsZShzdHJ1Y3QgbXVzYl9xaCAqcWgsIGludCBpc19pbiwKPiA+ICsJc3RydWN0 IHVyYiAqdXJiKQo+ID4gK3sKPiA+ICsJdTE2IGNzciA9IDA7Cj4gPiArCXUxNiB0b2dnbGUgPSAw Owo+IAo+IG5vIG5lZWQgdG8gYXNzaWduIHRoZW0gMC4KCk9rYXkuCgo+ID4gKwo+ID4gKwl0b2dn bGUgPSB1c2JfZ2V0dG9nZ2xlKHVyYi0+ZGV2LCBxaC0+ZXBudW0sICFpc19pbik7Cj4gPiArCj4g PiArCWlmIChpc19pbikKPiA+ICsJCWNzciA9IHRvZ2dsZSA/IChNVVNCX1JYQ1NSX0hfV1JfREFU QVRPR0dMRQo+ID4gKwkJCQl8IE1VU0JfUlhDU1JfSF9EQVRBVE9HR0xFKSA6IDA7Cj4gPiArCWVs c2UKPiA+ICsJCWNzciB8PSB0b2dnbGUgPyAoTVVTQl9UWENTUl9IX1dSX0RBVEFUT0dHTEUKPiA+ ICsJCQkJfCBNVVNCX1RYQ1NSX0hfREFUQVRPR0dMRSkKPiA+ICsJCQkJOiBNVVNCX1RYQ1NSX0NM UkRBVEFUT0c7Cj4gPiArCj4gPiArCXJldHVybiBjc3I7Cj4gPiArfQo+ID4gKwo+ID4gIC8qCj4g PiAgICogTG9hZCBhbiBlbmRwb2ludCdzIEZJRk8KPiA+ICAgKi8KPiA+IEBAIC0zNzAsMTIgKzQx MiwxOCBAQCBzdGF0aWMgdm9pZCBtdXNiX2RlZmF1bHRfcmVhZF9maWZvKHN0cnVjdCBtdXNiX2h3 X2VwICpod19lcCwgdTE2IGxlbiwgdTggKmRzdCkKPiA+ICB2b2lkICgqbXVzYl93cml0ZWIpKHZv aWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgb2Zmc2V0LCB1OCBkYXRhKTsKPiA+ICBFWFBPUlRf U1lNQk9MX0dQTChtdXNiX3dyaXRlYik7Cj4gPiAgCj4gPiArdm9pZCAoKm11c2JfY2xlYXJiKSh2 b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIGludCBvZmZzZXQsIHU4IGRhdGEpOwo+ID4gK0VY UE9SVF9TWU1CT0xfR1BMKG11c2JfY2xlYXJiKTsKPiA+ICsKPiA+ICB1MTYgKCptdXNiX3JlYWR3 KShjb25zdCB2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCk7Cj4gPiAgRVhQT1JU X1NZTUJPTF9HUEwobXVzYl9yZWFkdyk7Cj4gPiAgCj4gPiAgdm9pZCAoKm11c2Jfd3JpdGV3KSh2 b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCwgdTE2IGRhdGEpOwo+ID4gIEVYUE9S VF9TWU1CT0xfR1BMKG11c2Jfd3JpdGV3KTsKPiA+ICAKPiA+ICt2b2lkICgqbXVzYl9jbGVhcncp KHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTE2IGRhdGEpOwo+ID4g K0VYUE9SVF9TWU1CT0xfR1BMKG11c2JfY2xlYXJ3KTsKPiA+ICsKPiA+ICB1MzIgbXVzYl9yZWFk bChjb25zdCB2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCkKPiA+ICB7Cj4gPiAg CXUzMiBkYXRhID0gX19yYXdfcmVhZGwoYWRkciArIG9mZnNldCk7Cj4gPiBAQCAtMTAyOCw2ICsx MDc2LDExIEBAIHN0YXRpYyB2b2lkIG11c2JfZGlzYWJsZV9pbnRlcnJ1cHRzKHN0cnVjdCBtdXNi ICptdXNiKQo+ID4gIAl0ZW1wID0gbXVzYl9yZWFkYihtYmFzZSwgTVVTQl9JTlRSVVNCKTsKPiA+ ICAJdGVtcCA9IG11c2JfcmVhZHcobWJhc2UsIE1VU0JfSU5UUlRYKTsKPiA+ICAJdGVtcCA9IG11 c2JfcmVhZHcobWJhc2UsIE1VU0JfSU5UUlJYKTsKPiAKPiByZXBsYWNlIHRoZSAzIGxpbmUgYWJv dmUgd2l0aAo+IAltdXNiX2NsZWFyYi93KCk7CgpPa2F5LgoKPiA+ICsKPiA+ICsJLyogc29tZSBw bGF0Zm9ybSBuZWVkcyBjbGVhciBwZW5kaW5nIGludGVycnVwdHMgYnkgbWFudWFsICovCj4gPiAr CW11c2JfY2xlYXJiKG1iYXNlLCBNVVNCX0lOVFJVU0IsIG11c2JfcmVhZGIobWJhc2UsIE1VU0Jf SU5UUlVTQikpOwo+ID4gKwltdXNiX2NsZWFydyhtYmFzZSwgTVVTQl9JTlRSUlgsIG11c2JfcmVh ZHcobWJhc2UsIE1VU0JfSU5UUlJYKSk7Cj4gPiArCW11c2JfY2xlYXJ3KG1iYXNlLCBNVVNCX0lO VFJUWCwgbXVzYl9yZWFkdyhtYmFzZSwgTVVTQl9JTlRSVFgpKTsKPiAKPiB0aGVuIHRob3NlIGFy ZSBubyBsb25nZXIgbmVlZGVkLgoKT2theS4KCj4gPiAgfQo+ID4gIAo+ID4gIHN0YXRpYyB2b2lk IG11c2JfZW5hYmxlX2ludGVycnVwdHMoc3RydWN0IG11c2IgKm11c2IpCj4gPiBAQCAtMjE5Miw2 ICsyMjQ1LDggQEAgc3RhdGljIHZvaWQgbXVzYl9kZWFzc2VydF9yZXNldChzdHJ1Y3Qgd29ya19z dHJ1Y3QgKndvcmspCj4gPiAgCW11c2Jfd3JpdGViID0gbXVzYl9kZWZhdWx0X3dyaXRlYjsKPiA+ ICAJbXVzYl9yZWFkdyA9IG11c2JfZGVmYXVsdF9yZWFkdzsKPiA+ICAJbXVzYl93cml0ZXcgPSBt dXNiX2RlZmF1bHRfd3JpdGV3Owo+ID4gKwltdXNiX2NsZWFyYiA9IG11c2JfZGVmYXVsdF9jbGVh cmI7Cj4gPiArCW11c2JfY2xlYXJ3ID0gbXVzYl9kZWZhdWx0X2NsZWFydzsKPiA+ICAKPiA+ICAJ LyogVGhlIG11c2JfcGxhdGZvcm1faW5pdCgpIGNhbGw6Cj4gPiAgCSAqICAgLSBhZGp1c3RzIG11 c2ItPm1yZWdzCj4gPiBAQCAtMjI1MiwxMCArMjMwNywxNCBAQCBzdGF0aWMgdm9pZCBtdXNiX2Rl YXNzZXJ0X3Jlc2V0KHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKPiA+ICAJCW11c2JfcmVhZGIg PSBtdXNiLT5vcHMtPnJlYWRiOwo+ID4gIAlpZiAobXVzYi0+b3BzLT53cml0ZWIpCj4gPiAgCQlt dXNiX3dyaXRlYiA9IG11c2ItPm9wcy0+d3JpdGViOwo+ID4gKwlpZiAobXVzYi0+b3BzLT5jbGVh cmIpCj4gPiArCQltdXNiX2NsZWFyYiA9IG11c2ItPm9wcy0+Y2xlYXJiOwo+IAllbHNlCj4gCQlt dXNiX2NsZWFyYiA9IG11c2JfcmVhZGI7CgpPa2F5LgoKPiA+ICAJaWYgKG11c2ItPm9wcy0+cmVh ZHcpCj4gPiAgCQltdXNiX3JlYWR3ID0gbXVzYi0+b3BzLT5yZWFkdzsKPiA+ICAJaWYgKG11c2It Pm9wcy0+d3JpdGV3KQo+ID4gIAkJbXVzYl93cml0ZXcgPSBtdXNiLT5vcHMtPndyaXRldzsKPiA+ ICsJaWYgKG11c2ItPm9wcy0+Y2xlYXJ3KQo+ID4gKwkJbXVzYl9jbGVhcncgPSBtdXNiLT5vcHMt PmNsZWFydzsKPiAJZWxzZQo+IAkJbXVzYl9jbGVhcncgPSBtdXNiX3JlYWR3OwoKT2theS4KCj4g PiAgCj4gPiAgI2lmbmRlZiBDT05GSUdfTVVTQl9QSU9fT05MWQo+ID4gIAlpZiAoIW11c2ItPm9w cy0+ZG1hX2luaXQgfHwgIW11c2ItPm9wcy0+ZG1hX2V4aXQpIHsKPiA+IEBAIC0yMjc3LDYgKzIz MzYsMTYgQEAgc3RhdGljIHZvaWQgbXVzYl9kZWFzc2VydF9yZXNldChzdHJ1Y3Qgd29ya19zdHJ1 Y3QgKndvcmspCj4gPiAgCWVsc2UKPiA+ICAJCW11c2ItPmlvLndyaXRlX2ZpZm8gPSBtdXNiX2Rl ZmF1bHRfd3JpdGVfZmlmbzsKPiA+ICAKPiA+ICsJaWYgKG11c2ItPm9wcy0+Z2V0X3RvZ2dsZSkK PiA+ICsJCW11c2ItPmlvLmdldF90b2dnbGUgPSBtdXNiLT5vcHMtPmdldF90b2dnbGU7Cj4gPiAr CWVsc2UKPiA+ICsJCW11c2ItPmlvLmdldF90b2dnbGUgPSBtdXNiX2RlZmF1bHRfZ2V0X3RvZ2ds ZTsKPiA+ICsKPiA+ICsJaWYgKG11c2ItPm9wcy0+c2V0X3RvZ2dsZSkKPiA+ICsJCW11c2ItPmlv LnNldF90b2dnbGUgPSBtdXNiLT5vcHMtPnNldF90b2dnbGU7Cj4gPiArCWVsc2UKPiA+ICsJCW11 c2ItPmlvLnNldF90b2dnbGUgPSBtdXNiX2RlZmF1bHRfc2V0X3RvZ2dsZTsKPiA+ICsKPiA+ICAJ aWYgKCFtdXNiLT54Y2Vpdi0+aW9fb3BzKSB7Cj4gPiAgCQltdXNiLT54Y2Vpdi0+aW9fZGV2ID0g bXVzYi0+Y29udHJvbGxlcjsKPiA+ICAJCW11c2ItPnhjZWl2LT5pb19wcml2ID0gbXVzYi0+bXJl Z3M7Cj4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvbXVzYi9tdXNiX2NvcmUuaCBiL2RyaXZl cnMvdXNiL211c2IvbXVzYl9jb3JlLmgKPiA+IGluZGV4IDA0MjAzYjcuLjcxZGNhODAgMTAwNjQ0 Cj4gPiAtLS0gYS9kcml2ZXJzL3VzYi9tdXNiL211c2JfY29yZS5oCj4gPiArKysgYi9kcml2ZXJz L3VzYi9tdXNiL211c2JfY29yZS5oCj4gPiBAQCAtMjcsNiArMjcsNyBAQAo+ID4gIHN0cnVjdCBt dXNiOwo+ID4gIHN0cnVjdCBtdXNiX2h3X2VwOwo+ID4gIHN0cnVjdCBtdXNiX2VwOwo+ID4gK3N0 cnVjdCBtdXNiX3FoOwo+ID4gIAo+ID4gIC8qIEhlbHBlciBkZWZpbmVzIGZvciBzdHJ1Y3QgbXVz Yi0+aHd2ZXJzICovCj4gPiAgI2RlZmluZSBNVVNCX0hXVkVSU19NQUpPUih4KQkoKHggPj4gMTAp ICYgMHgxZikKPiA+IEBAIC0xMTksMTAgKzEyMCwxNCBAQCBlbnVtIG11c2JfZ19lcDBfc3RhdGUg ewo+ID4gICAqIEBmaWZvX29mZnNldDogcmV0dXJucyB0aGUgZmlmbyBvZmZzZXQKPiA+ICAgKiBA cmVhZGI6CXJlYWQgOCBiaXRzCj4gPiAgICogQHdyaXRlYjoJd3JpdGUgOCBiaXRzCj4gPiArICog QGNsZWFyYjoJY2xlYXIgOCBiaXRzLAo+IAo+IGFkZCAiY291bGQgYmUgY2xlYXItb24tcmVhZCBv ciBXMUMiIHRvIGdpdmUgbW9yZSBpbmZvLgoKT2theS4KCj4gPiAgICogQHJlYWR3OglyZWFkIDE2 IGJpdHMKPiA+ICAgKiBAd3JpdGV3Ogl3cml0ZSAxNiBiaXRzCj4gPiArICogQGNsZWFydzoJY2xl YXIgMTYgYml0cwo+ID4gICAqIEByZWFkX2ZpZm86CXJlYWRzIHRoZSBmaWZvCj4gPiAgICogQHdy aXRlX2ZpZm86CXdyaXRlcyB0byBmaWZvCj4gPiArICogQGdldF90b2dnbGU6CXBsYXRmb3JtIHNw ZWNpZmljIGdldCB0b2dnbGUgZnVuY3Rpb24KPiA+ICsgKiBAc2V0X3RvZ2dsZToJcGxhdGZvcm0g c3BlY2lmaWMgc2V0IHRvZ2dsZSBmdW5jdGlvbgo+ID4gICAqIEBkbWFfaW5pdDoJcGxhdGZvcm0g c3BlY2lmaWMgZG1hIGluaXQgZnVuY3Rpb24KPiA+ICAgKiBAZG1hX2V4aXQ6CXBsYXRmb3JtIHNw ZWNpZmljIGRtYSBleGl0IGZ1bmN0aW9uCj4gPiAgICogQGluaXQ6CXR1cm5zIG9uIGNsb2Nrcywg c2V0cyB1cCBwbGF0Zm9ybS1zcGVjaWZpYyByZWdpc3RlcnMsIGV0Ywo+ID4gQEAgLTE2MywxMCAr MTY4LDE0IEBAIHN0cnVjdCBtdXNiX3BsYXRmb3JtX29wcyB7Cj4gPiAgCXUzMgkoKmJ1c2N0bF9v ZmZzZXQpKHU4IGVwbnVtLCB1MTYgb2Zmc2V0KTsKPiA+ICAJdTgJKCpyZWFkYikoY29uc3Qgdm9p ZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBvZmZzZXQpOwo+ID4gIAl2b2lkCSgqd3JpdGViKSh2 b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCwgdTggZGF0YSk7Cj4gPiArCXZvaWQJ KCpjbGVhcmIpKHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTggZGF0 YSk7Cj4gPiAgCXUxNgkoKnJlYWR3KShjb25zdCB2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVk IG9mZnNldCk7Cj4gPiAgCXZvaWQJKCp3cml0ZXcpKHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWdu ZWQgb2Zmc2V0LCB1MTYgZGF0YSk7Cj4gPiArCXZvaWQJKCpjbGVhcncpKHZvaWQgX19pb21lbSAq YWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTE2IGRhdGEpOwo+ID4gIAl2b2lkCSgqcmVhZF9m aWZvKShzdHJ1Y3QgbXVzYl9od19lcCAqaHdfZXAsIHUxNiBsZW4sIHU4ICpidWYpOwo+ID4gIAl2 b2lkCSgqd3JpdGVfZmlmbykoc3RydWN0IG11c2JfaHdfZXAgKmh3X2VwLCB1MTYgbGVuLCBjb25z dCB1OCAqYnVmKTsKPiA+ICsJdTE2CSgqZ2V0X3RvZ2dsZSkoc3RydWN0IG11c2JfcWggKnFoLCBp bnQgaXNfaW4pOwo+ID4gKwl1MTYJKCpzZXRfdG9nZ2xlKShzdHJ1Y3QgbXVzYl9xaCAqcWgsIGlu dCBpc19pbiwgc3RydWN0IHVyYiAqdXJiKTsKPiA+ICAJc3RydWN0IGRtYV9jb250cm9sbGVyICoK PiA+ICAJCSgqZG1hX2luaXQpIChzdHJ1Y3QgbXVzYiAqbXVzYiwgdm9pZCBfX2lvbWVtICpiYXNl KTsKPiA+ICAJdm9pZAkoKmRtYV9leGl0KShzdHJ1Y3QgZG1hX2NvbnRyb2xsZXIgKmMpOwo+ID4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL211c2IvbXVzYl9kbWEuaCBiL2RyaXZlcnMvdXNiL211 c2IvbXVzYl9kbWEuaAo+ID4gaW5kZXggOGY2MDI3MS4uMDUxMDNlYSAxMDA2NDQKPiA+IC0tLSBh L2RyaXZlcnMvdXNiL211c2IvbXVzYl9kbWEuaAo+ID4gKysrIGIvZHJpdmVycy91c2IvbXVzYi9t dXNiX2RtYS5oCj4gPiBAQCAtMzUsNiArMzUsMTIgQEAKPiA+ICAgKiAgICB3aGV0aGVyIHNoYXJl ZCB3aXRoIHRoZSBJbnZlbnRyYSBjb3JlIG9yIHNlcGFyYXRlLgo+ID4gICAqLwo+ID4gIAo+ID4g KyNkZWZpbmUgTVVTQl9IU0RNQV9CQVNFCQkweDIwMAo+ID4gKyNkZWZpbmUgTVVTQl9IU0RNQV9J TlRSCQkoTVVTQl9IU0RNQV9CQVNFICsgMCkKPiA+ICsjZGVmaW5lIE1VU0JfSFNETUFfQ09OVFJP TAkJMHg0Cj4gPiArI2RlZmluZSBNVVNCX0hTRE1BX0FERFJFU1MJCTB4OAo+ID4gKyNkZWZpbmUg TVVTQl9IU0RNQV9DT1VOVAkJMHhjCj4gPiArCj4gPiAgI2RlZmluZQlETUFfQUREUl9JTlZBTElE CSh+KGRtYV9hZGRyX3QpMCkKPiA+ICAKPiA+ICAjaWZkZWYgQ09ORklHX01VU0JfUElPX09OTFkK PiA+IEBAIC0xOTEsNiArMTk3LDkgQEAgc3RhdGljIGlubGluZSB2b2lkIG11c2JfZG1hX2NvbnRy b2xsZXJfZGVzdHJveShzdHJ1Y3QgZG1hX2NvbnRyb2xsZXIgKmQpIHsgfQo+ID4gIGV4dGVybiBz dHJ1Y3QgZG1hX2NvbnRyb2xsZXIgKgo+ID4gIG11c2Joc19kbWFfY29udHJvbGxlcl9jcmVhdGUo c3RydWN0IG11c2IgKm11c2IsIHZvaWQgX19pb21lbSAqYmFzZSk7Cj4gPiAgZXh0ZXJuIHZvaWQg bXVzYmhzX2RtYV9jb250cm9sbGVyX2Rlc3Ryb3koc3RydWN0IGRtYV9jb250cm9sbGVyICpjKTsK PiA+ICtleHRlcm4gc3RydWN0IGRtYV9jb250cm9sbGVyICoKPiA+ICttdXNiaHNfZG1hX2NvbnRy b2xsZXJfY3JlYXRlX25vaXJxKHN0cnVjdCBtdXNiICptdXNiLCB2b2lkIF9faW9tZW0gKmJhc2Up Owo+ID4gK2V4dGVybiBpcnFyZXR1cm5fdCBkbWFfY29udHJvbGxlcl9pcnEoaW50IGlycSwgdm9p ZCAqcHJpdmF0ZV9kYXRhKTsKPiA+ICAKPiA+ICBleHRlcm4gc3RydWN0IGRtYV9jb250cm9sbGVy ICoKPiA+ICB0dXNiX2RtYV9jb250cm9sbGVyX2NyZWF0ZShzdHJ1Y3QgbXVzYiAqbXVzYiwgdm9p ZCBfX2lvbWVtICpiYXNlKTsKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi9tdXNiL211c2Jf aG9zdC5jIGIvZHJpdmVycy91c2IvbXVzYi9tdXNiX2hvc3QuYwo+ID4gaW5kZXggMTZkMGJhNC4u YmE2NmY0NCAxMDA2NDQKPiA+IC0tLSBhL2RyaXZlcnMvdXNiL211c2IvbXVzYl9ob3N0LmMKPiA+ ICsrKyBiL2RyaXZlcnMvdXNiL211c2IvbXVzYl9ob3N0LmMKPiA+IEBAIC0yOTAsMzkgKzI5MCwy MyBAQCBzdGF0aWMgdm9pZCBtdXNiX2dpdmViYWNrKHN0cnVjdCBtdXNiICptdXNiLCBzdHJ1Y3Qg dXJiICp1cmIsIGludCBzdGF0dXMpCj4gPiAgc3RhdGljIGlubGluZSB2b2lkIG11c2Jfc2F2ZV90 b2dnbGUoc3RydWN0IG11c2JfcWggKnFoLCBpbnQgaXNfaW4sCj4gPiAgCQkJCSAgICBzdHJ1Y3Qg dXJiICp1cmIpCj4gPiAgewo+ID4gLQl2b2lkIF9faW9tZW0JCSplcGlvID0gcWgtPmh3X2VwLT5y ZWdzOwo+ID4gLQl1MTYJCQljc3I7Cj4gPiArCXN0cnVjdCBtdXNiICptdXNiID0gcWgtPmh3X2Vw LT5tdXNiOwo+ID4gKwl1MTYgY3NyOwo+ID4gIAo+ID4gIAkvKgo+ID4gIAkgKiBGSVhNRTogdGhl IGN1cnJlbnQgTWVudG9yIERNQSBjb2RlIHNlZW1zIHRvIGhhdmUKPiA+ICAJICogcHJvYmxlbXMg Z2V0dGluZyB0b2dnbGUgY29ycmVjdC4KPiA+ICAJICovCj4gPiAtCj4gPiAtCWlmIChpc19pbikK PiA+IC0JCWNzciA9IG11c2JfcmVhZHcoZXBpbywgTVVTQl9SWENTUikgJiBNVVNCX1JYQ1NSX0hf REFUQVRPR0dMRTsKPiA+IC0JZWxzZQo+ID4gLQkJY3NyID0gbXVzYl9yZWFkdyhlcGlvLCBNVVNC X1RYQ1NSKSAmIE1VU0JfVFhDU1JfSF9EQVRBVE9HR0xFOwo+ID4gLQo+ID4gKwljc3IgPSBtdXNi LT5pby5nZXRfdG9nZ2xlKHFoLCBpc19pbik7Cj4gPiAgCXVzYl9zZXR0b2dnbGUodXJiLT5kZXYs IHFoLT5lcG51bSwgIWlzX2luLCBjc3IgPyAxIDogMCk7Cj4gPiAgfQo+ID4gIAo+ID4gIHN0YXRp YyBpbmxpbmUgdTE2IG11c2Jfc2V0X3RvZ2dsZShzdHJ1Y3QgbXVzYl9xaCAqcWgsIGludCBpc19p biwKPiA+ICAJc3RydWN0IHVyYiAqdXJiKQo+ID4gIHsKPiA+IC0JdTE2IGNzciA9IDA7Cj4gPiAt CXUxNiB0b2dnbGUgPSAwOwo+ID4gLQo+ID4gLQl0b2dnbGUgPSB1c2JfZ2V0dG9nZ2xlKHVyYi0+ ZGV2LCBxaC0+ZXBudW0sICFpc19pbik7Cj4gPiAtCj4gPiAtCWlmIChpc19pbikKPiA+IC0JCWNz ciA9IHRvZ2dsZSA/IChNVVNCX1JYQ1NSX0hfV1JfREFUQVRPR0dMRQo+ID4gLQkJCQl8IE1VU0Jf UlhDU1JfSF9EQVRBVE9HR0xFKSA6IDA7Cj4gPiAtCWVsc2UKPiA+IC0JCWNzciA9IHRvZ2dsZSA/ IChNVVNCX1RYQ1NSX0hfV1JfREFUQVRPR0dMRQo+ID4gLQkJCQl8IE1VU0JfVFhDU1JfSF9EQVRB VE9HR0xFKQo+ID4gLQkJCQk6IE1VU0JfVFhDU1JfQ0xSREFUQVRPRzsKPiA+ICsJc3RydWN0IG11 c2IgKm11c2IgPSBxaC0+aHdfZXAtPm11c2I7Cj4gPiAgCj4gPiAtCXJldHVybiBjc3I7Cj4gPiAr CXJldHVybiBtdXNiLT5pby5zZXRfdG9nZ2xlKHFoLCBpc19pbiwgdXJiKTsKPiA+ICB9Cj4gCj4g VGhvc2UgdHdvIGZ1bmN0aW9ucyAtIG11c2Jfc2F2ZV90b2dnbGUoKSBhbmQgbXVzYl9zZXRfdG9n Z2xlKCkgYXJlIHZlcnkKPiBzaG9ydCBub3csIHdlIGNhbiBnZXQgcmlkIG9mIHRoZW0sIGFuZCBk aXJlY3RseSB1c2UKPiBtdXNiLT5pby5nZXQvc2V0X3RvZ2dsZSgpLgoKT2theS4KCj4gPiAgCj4g PiAgLyoKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi9tdXNiL211c2JfaW8uaCBiL2RyaXZl cnMvdXNiL211c2IvbXVzYl9pby5oCj4gPiBpbmRleCA4MDU4YTU4Li45YmFlMDliIDEwMDY0NAo+ ID4gLS0tIGEvZHJpdmVycy91c2IvbXVzYi9tdXNiX2lvLmgKPiA+ICsrKyBiL2RyaXZlcnMvdXNi L211c2IvbXVzYl9pby5oCj4gPiBAQCAtMjIsNiArMjIsOCBAQAo+ID4gICAqIEByZWFkX2ZpZm86 CXBsYXRmb3JtIHNwZWNpZmljIGZ1bmN0aW9uIHRvIHJlYWQgZmlmbwo+ID4gICAqIEB3cml0ZV9m aWZvOglwbGF0Zm9ybSBzcGVjaWZpYyBmdW5jdGlvbiB0byB3cml0ZSBmaWZvCj4gPiAgICogQGJ1 c2N0bF9vZmZzZXQ6IHBsYXRmb3JtIHNwZWNpZmljIGZ1bmN0aW9uIHRvIGdldCBidXNjdGwgb2Zm c2V0Cj4gPiArICogQGdldF90b2dnbGU6IHBsYXRmb3JtIHNwZWNpZmljIGZ1bmN0aW9uIHRvIGdl dCB0b2dnbGUKPiA+ICsgKiBAc2V0X3RvZ2dsZTogcGxhdGZvcm0gc3BlY2lmaWMgZnVuY3Rpb24g dG8gc2V0IHRvZ2dsZQo+ID4gICAqLwo+ID4gIHN0cnVjdCBtdXNiX2lvIHsKPiA+ICAJdTMyCSgq ZXBfb2Zmc2V0KSh1OCBlcG51bSwgdTE2IG9mZnNldCk7Cj4gPiBAQCAtMzAsMTMgKzMyLDE3IEBA IHN0cnVjdCBtdXNiX2lvIHsKPiA+ICAJdm9pZAkoKnJlYWRfZmlmbykoc3RydWN0IG11c2JfaHdf ZXAgKmh3X2VwLCB1MTYgbGVuLCB1OCAqYnVmKTsKPiA+ICAJdm9pZAkoKndyaXRlX2ZpZm8pKHN0 cnVjdCBtdXNiX2h3X2VwICpod19lcCwgdTE2IGxlbiwgY29uc3QgdTggKmJ1Zik7Cj4gPiAgCXUz MgkoKmJ1c2N0bF9vZmZzZXQpKHU4IGVwbnVtLCB1MTYgb2Zmc2V0KTsKPiA+ICsJdTE2CSgqZ2V0 X3RvZ2dsZSkoc3RydWN0IG11c2JfcWggKnFoLCBpbnQgaXNfaW4pOwo+ID4gKwl1MTYJKCpzZXRf dG9nZ2xlKShzdHJ1Y3QgbXVzYl9xaCAqcWgsIGludCBpc19pbiwgc3RydWN0IHVyYiAqdXJiKTsK PiA+ICB9Owo+ID4gIAo+ID4gIC8qIERvIG5vdCBhZGQgbmV3IGVudHJpZXMgaGVyZSwgYWRkIHRo ZW0gdGhlIHN0cnVjdCBtdXNiX2lvIGluc3RlYWQgKi8KPiA+ICBleHRlcm4gdTggKCptdXNiX3Jl YWRiKShjb25zdCB2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCk7Cj4gPiAgZXh0 ZXJuIHZvaWQgKCptdXNiX3dyaXRlYikodm9pZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBvZmZz ZXQsIHU4IGRhdGEpOwo+ID4gK2V4dGVybiB2b2lkICgqbXVzYl9jbGVhcmIpKHZvaWQgX19pb21l bSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTggZGF0YSk7Cj4gPiAgZXh0ZXJuIHUxNiAo Km11c2JfcmVhZHcpKGNvbnN0IHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgb2Zmc2V0KTsK PiA+ICBleHRlcm4gdm9pZCAoKm11c2Jfd3JpdGV3KSh2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2ln bmVkIG9mZnNldCwgdTE2IGRhdGEpOwo+ID4gK2V4dGVybiB2b2lkICgqbXVzYl9jbGVhcncpKHZv aWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTE2IGRhdGEpOwo+ID4gIGV4 dGVybiB1MzIgbXVzYl9yZWFkbChjb25zdCB2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9m ZnNldCk7Cj4gPiAgZXh0ZXJuIHZvaWQgbXVzYl93cml0ZWwodm9pZCBfX2lvbWVtICphZGRyLCB1 bnNpZ25lZCBvZmZzZXQsIHUzMiBkYXRhKTsKPiA+ICAKPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJz L3VzYi9tdXNiL211c2Joc2RtYS5jIGIvZHJpdmVycy91c2IvbXVzYi9tdXNiaHNkbWEuYwo+ID4g aW5kZXggYTY4OGY3Zi4uYjA1ZmU2OCAxMDA2NDQKPiA+IC0tLSBhL2RyaXZlcnMvdXNiL211c2Iv bXVzYmhzZG1hLmMKPiA+ICsrKyBiL2RyaXZlcnMvdXNiL211c2IvbXVzYmhzZG1hLmMKPiA+IEBA IC0xMCwxMiArMTAsNyBAQAo+ID4gICNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2UuaD4K PiA+ICAjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+ID4gICNpbmNsdWRlICJtdXNiX2NvcmUuaCIK PiA+IC0KPiA+IC0jZGVmaW5lIE1VU0JfSFNETUFfQkFTRQkJMHgyMDAKPiA+IC0jZGVmaW5lIE1V U0JfSFNETUFfSU5UUgkJKE1VU0JfSFNETUFfQkFTRSArIDApCj4gPiAtI2RlZmluZSBNVVNCX0hT RE1BX0NPTlRST0wJCTB4NAo+ID4gLSNkZWZpbmUgTVVTQl9IU0RNQV9BRERSRVNTCQkweDgKPiA+ IC0jZGVmaW5lIE1VU0JfSFNETUFfQ09VTlQJCTB4Ywo+ID4gKyNpbmNsdWRlICJtdXNiX2RtYS5o Igo+ID4gIAo+ID4gICNkZWZpbmUgTVVTQl9IU0RNQV9DSEFOTkVMX09GRlNFVChfYmNoYW5uZWws IF9vZmZzZXQpCQlcCj4gPiAgCQkoTVVTQl9IU0RNQV9CQVNFICsgKF9iY2hhbm5lbCA8PCA0KSAr IF9vZmZzZXQpCj4gPiBAQCAtMjY4LDcgKzI2Myw3IEBAIHN0YXRpYyBpbnQgZG1hX2NoYW5uZWxf YWJvcnQoc3RydWN0IGRtYV9jaGFubmVsICpjaGFubmVsKQo+ID4gIAlyZXR1cm4gMDsKPiA+ICB9 Cj4gPiAgCj4gPiAtc3RhdGljIGlycXJldHVybl90IGRtYV9jb250cm9sbGVyX2lycShpbnQgaXJx LCB2b2lkICpwcml2YXRlX2RhdGEpCj4gPiAraXJxcmV0dXJuX3QgZG1hX2NvbnRyb2xsZXJfaXJx KGludCBpcnEsIHZvaWQgKnByaXZhdGVfZGF0YSkKPiA+ICB7Cj4gPiAgCXN0cnVjdCBtdXNiX2Rt YV9jb250cm9sbGVyICpjb250cm9sbGVyID0gcHJpdmF0ZV9kYXRhOwo+ID4gIAlzdHJ1Y3QgbXVz YiAqbXVzYiA9IGNvbnRyb2xsZXItPnByaXZhdGVfZGF0YTsKPiA+IEBAIC0yOTEsNiArMjg2LDkg QEAgc3RhdGljIGlycXJldHVybl90IGRtYV9jb250cm9sbGVyX2lycShpbnQgaXJxLCB2b2lkICpw cml2YXRlX2RhdGEpCj4gPiAgCj4gPiAgCWludF9oc2RtYSA9IG11c2JfcmVhZGIobWJhc2UsIE1V U0JfSFNETUFfSU5UUik7Cj4gPiAgCj4gPiArCS8qIHNvbWUgcGxhdGZvcm0gbmVlZHMgY2xlYXIg cGVuZGluZyBpbnRlcnJ1cHRzIGJ5IG1hbnVhbCAqLwo+ID4gKwltdXNiX2NsZWFyYihtdXNiLT5t cmVncywgTVVTQl9IU0RNQV9JTlRSLCBpbnRfaHNkbWEpOwo+ID4gKwo+ID4gIAlpZiAoIWludF9o c2RtYSkgewo+ID4gIAkJbXVzYl9kYmcobXVzYiwgInNwdXJpb3VzIERNQSBpcnEiKTsKPiA+ICAK PiA+IEBAIC0zODIsNiArMzgwLDcgQEAgc3RhdGljIGlycXJldHVybl90IGRtYV9jb250cm9sbGVy X2lycShpbnQgaXJxLCB2b2lkICpwcml2YXRlX2RhdGEpCj4gPiAgCXNwaW5fdW5sb2NrX2lycXJl c3RvcmUoJm11c2ItPmxvY2ssIGZsYWdzKTsKPiA+ICAJcmV0dXJuIHJldHZhbDsKPiA+ICB9Cj4g PiArRVhQT1JUX1NZTUJPTF9HUEwoZG1hX2NvbnRyb2xsZXJfaXJxKTsKPiA+ICAKPiA+ICB2b2lk IG11c2Joc19kbWFfY29udHJvbGxlcl9kZXN0cm95KHN0cnVjdCBkbWFfY29udHJvbGxlciAqYykK PiA+ICB7Cj4gPiBAQCAtMzk3LDE4ICszOTYsMTAgQEAgdm9pZCBtdXNiaHNfZG1hX2NvbnRyb2xs ZXJfZGVzdHJveShzdHJ1Y3QgZG1hX2NvbnRyb2xsZXIgKmMpCj4gPiAgfQo+ID4gIEVYUE9SVF9T WU1CT0xfR1BMKG11c2Joc19kbWFfY29udHJvbGxlcl9kZXN0cm95KTsKPiA+ICAKPiA+IC1zdHJ1 Y3QgZG1hX2NvbnRyb2xsZXIgKm11c2Joc19kbWFfY29udHJvbGxlcl9jcmVhdGUoc3RydWN0IG11 c2IgKm11c2IsCj4gPiArc3RhdGljIHN0cnVjdCBtdXNiX2RtYV9jb250cm9sbGVyICpkbWFfY29u dHJvbGxlcl9hbGxvYyhzdHJ1Y3QgbXVzYiAqbXVzYiwKPiA+ICAJCQkJCQkgICAgdm9pZCBfX2lv bWVtICpiYXNlKQo+ID4gIHsKPiA+ICAJc3RydWN0IG11c2JfZG1hX2NvbnRyb2xsZXIgKmNvbnRy b2xsZXI7Cj4gPiAtCXN0cnVjdCBkZXZpY2UgKmRldiA9IG11c2ItPmNvbnRyb2xsZXI7Cj4gPiAt CXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9kZXZpY2UoZGV2KTsK PiA+IC0JaW50IGlycSA9IHBsYXRmb3JtX2dldF9pcnFfYnluYW1lKHBkZXYsICJkbWEiKTsKPiA+ IC0KPiA+IC0JaWYgKGlycSA8PSAwKSB7Cj4gPiAtCQlkZXZfZXJyKGRldiwgIk5vIERNQSBpbnRl cnJ1cHQgbGluZSFcbiIpOwo+ID4gLQkJcmV0dXJuIE5VTEw7Cj4gPiAtCX0KPiA+ICAKPiA+ICAJ Y29udHJvbGxlciA9IGt6YWxsb2Moc2l6ZW9mKCpjb250cm9sbGVyKSwgR0ZQX0tFUk5FTCk7Cj4g PiAgCWlmICghY29udHJvbGxlcikKPiA+IEBAIC00MjIsNiArNDEzLDI1IEBAIHN0cnVjdCBkbWFf Y29udHJvbGxlciAqbXVzYmhzX2RtYV9jb250cm9sbGVyX2NyZWF0ZShzdHJ1Y3QgbXVzYiAqbXVz YiwKPiA+ICAJY29udHJvbGxlci0+Y29udHJvbGxlci5jaGFubmVsX3JlbGVhc2UgPSBkbWFfY2hh bm5lbF9yZWxlYXNlOwo+ID4gIAljb250cm9sbGVyLT5jb250cm9sbGVyLmNoYW5uZWxfcHJvZ3Jh bSA9IGRtYV9jaGFubmVsX3Byb2dyYW07Cj4gPiAgCWNvbnRyb2xsZXItPmNvbnRyb2xsZXIuY2hh bm5lbF9hYm9ydCA9IGRtYV9jaGFubmVsX2Fib3J0Owo+ID4gKwlyZXR1cm4gY29udHJvbGxlcjsK PiA+ICt9Cj4gPiArCj4gPiArc3RydWN0IGRtYV9jb250cm9sbGVyICptdXNiaHNfZG1hX2NvbnRy b2xsZXJfY3JlYXRlKHN0cnVjdCBtdXNiICptdXNiLAo+ID4gKwkJCQkJCSAgICB2b2lkIF9faW9t ZW0gKmJhc2UpCj4gPiArewo+ID4gKwlzdHJ1Y3QgbXVzYl9kbWFfY29udHJvbGxlciAqY29udHJv bGxlcjsKPiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gbXVzYi0+Y29udHJvbGxlcjsKPiA+ICsJ c3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiA9IHRvX3BsYXRmb3JtX2RldmljZShkZXYpOwo+ ID4gKwlpbnQgaXJxID0gcGxhdGZvcm1fZ2V0X2lycV9ieW5hbWUocGRldiwgImRtYSIpOwo+ID4g Kwo+ID4gKwlpZiAoaXJxIDw9IDApIHsKPiA+ICsJCWRldl9lcnIoZGV2LCAiTm8gRE1BIGludGVy cnVwdCBsaW5lIVxuIik7Cj4gPiArCQlyZXR1cm4gTlVMTDsKPiA+ICsJfQo+ID4gKwo+ID4gKwlj b250cm9sbGVyID0gZG1hX2NvbnRyb2xsZXJfYWxsb2MobXVzYiwgYmFzZSk7Cj4gPiArCWlmICgh Y29udHJvbGxlcikKPiA+ICsJCXJldHVybiBOVUxMOwo+ID4gIAo+ID4gIAlpZiAocmVxdWVzdF9p cnEoaXJxLCBkbWFfY29udHJvbGxlcl9pcnEsIDAsCj4gPiAgCQkJZGV2X25hbWUobXVzYi0+Y29u dHJvbGxlciksICZjb250cm9sbGVyLT5jb250cm9sbGVyKSkgewo+ID4gQEAgLTQzNiwzICs0NDYs MTYgQEAgc3RydWN0IGRtYV9jb250cm9sbGVyICptdXNiaHNfZG1hX2NvbnRyb2xsZXJfY3JlYXRl KHN0cnVjdCBtdXNiICptdXNiLAo+ID4gIAlyZXR1cm4gJmNvbnRyb2xsZXItPmNvbnRyb2xsZXI7 Cj4gPiAgfQo+ID4gIEVYUE9SVF9TWU1CT0xfR1BMKG11c2Joc19kbWFfY29udHJvbGxlcl9jcmVh dGUpOwo+ID4gKwo+ID4gK3N0cnVjdCBkbWFfY29udHJvbGxlciAqbXVzYmhzX2RtYV9jb250cm9s bGVyX2NyZWF0ZV9ub2lycShzdHJ1Y3QgbXVzYiAqbXVzYiwKPiA+ICsJCQkJCQkgICAgdm9pZCBf X2lvbWVtICpiYXNlKQo+ID4gK3sKPiA+ICsJc3RydWN0IG11c2JfZG1hX2NvbnRyb2xsZXIgKmNv bnRyb2xsZXI7Cj4gPiArCj4gPiArCWNvbnRyb2xsZXIgPSBkbWFfY29udHJvbGxlcl9hbGxvYyht dXNiLCBiYXNlKTsKPiA+ICsJaWYgKCFjb250cm9sbGVyKQo+ID4gKwkJcmV0dXJuIE5VTEw7Cj4g PiArCj4gPiArCXJldHVybiAmY29udHJvbGxlci0+Y29udHJvbGxlcjsKPiA+ICt9Cj4gPiArRVhQ T1JUX1NZTUJPTF9HUEwobXVzYmhzX2RtYV9jb250cm9sbGVyX2NyZWF0ZV9ub2lycSk7Cj4gCj4g cmVnYXJkcywKPiAtQmluLgo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,UNPARSEABLE_RELAY,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE261C43612 for ; Wed, 16 Jan 2019 02:43:33 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A7AA920866 for ; Wed, 16 Jan 2019 02:43:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="e6RCsmp/" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A7AA920866 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=mediatek.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Date:To:From:Subject:Message-ID:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=3hTT2Paek/bUk5zh+2/3kTS/9Q9P/rpZvsf7tmCiLpk=; b=e6RCsmp/E2sG42 vtA54dujsEBQogIEmQ+gSwxomQsG3cuqBMYvjnnGdIQcPlZHnYkjqJm40z22/9VL/ZKjMw0YB+Ain CCIDo2T+pzIPgIVJMjsk81C9+zJY5tlBl361chOQNxPJz5D0boxmEit2UFI/hA1cQfEDrzF/+e1fy Dh12ugLt8J9YAsv9xIpUtif8jZq2ACK5koULX/LuqB+gAkmLXXxL1FT9nzfpfwo7xSeuE5+IraZtL PaZvElE/UoSR1eXSWhg7RG1OT91Xo8D6UTdHmfpJEFfM1YS6XPDnH26tqvGz8vcFlCGbw1DjUHnV4 bSQsdHg3FvzBrs7MaPwA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gjbAt-0006IT-Qa; Wed, 16 Jan 2019 02:43:27 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gjbAo-0006He-Qg; Wed, 16 Jan 2019 02:43:25 +0000 X-UUID: d334aaf18fa44845952f5ee920466a4a-20190115 X-UUID: d334aaf18fa44845952f5ee920466a4a-20190115 Received: from mtkcas67.mediatek.inc [(172.29.193.45)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLS) with ESMTP id 1277027789; Tue, 15 Jan 2019 18:43:18 -0800 Received: from MTKMBS31N2.mediatek.inc (172.27.4.87) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Tue, 15 Jan 2019 18:43:16 -0800 Received: from MTKCAS36.mediatek.inc (172.27.4.186) by MTKMBS31N2.mediatek.inc (172.27.4.87) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Wed, 16 Jan 2019 10:43:14 +0800 Received: from [10.17.3.153] (10.17.3.153) by MTKCAS36.mediatek.inc (172.27.4.170) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Wed, 16 Jan 2019 10:43:13 +0800 Message-ID: <1547606593.4433.178.camel@mhfsdcap03> Subject: Re: [PATCH v2 4/4] usb: musb: Add support for MediaTek musb controller From: Min Guo To: Bin Liu Date: Wed, 16 Jan 2019 10:43:13 +0800 In-Reply-To: <20190115203815.GD18026@uda0271908> References: <1547516626-5084-1-git-send-email-min.guo@mediatek.com> <1547516626-5084-5-git-send-email-min.guo@mediatek.com> <20190115203815.GD18026@uda0271908> X-Mailer: Evolution 3.2.3-0ubuntu6 MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190115_184322_902250_CD5134F4 X-CRM114-Status: GOOD ( 28.35 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mark Rutland , devicetree@vger.kernel.org, Yonglong Wu , Greg Kroah-Hartman , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Matthias Brugger , Rob Herring , Alan Stern , chunfeng.yun@mediatek.com, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org Hi Bin, On Tue, 2019-01-15 at 14:38 -0600, Bin Liu wrote: > Hi Min, > > very close, thanks. > Below I tried to explain a further cleanup in musb_clearb/w() and > musb_get/set_toggle() implementation. Please let me know if it is not > clear. > > Basically, we don't need musb_default_clearb/w(), just assign the > musb_io function pointers to musb_readb/w(). > > Then the mtk platform musb_clearb/w() calls musb_readb/w() and > musb_writeb/w() to handle W1C. Okay. > On Tue, Jan 15, 2019 at 09:43:46AM +0800, min.guo@mediatek.com wrote: > > From: Min Guo > > > > This adds support for MediaTek musb controller in > > host, peripheral and otg mode. > > There are some quirk of MediaTek musb controller, such as: > > -W1C interrupt status registers > > -Private data toggle registers > > -No dedicated DMA interrupt line > > > > Signed-off-by: Min Guo > > Signed-off-by: Yonglong Wu > > --- > > drivers/usb/musb/Kconfig | 8 +- > > drivers/usb/musb/Makefile | 1 + > > drivers/usb/musb/mediatek.c | 617 +++++++++++++++++++++++++++++++++++++++++++ > > drivers/usb/musb/musb_core.c | 69 +++++ > > drivers/usb/musb/musb_core.h | 9 + > > drivers/usb/musb/musb_dma.h | 9 + > > drivers/usb/musb/musb_host.c | 26 +- > > drivers/usb/musb/musb_io.h | 6 + > > drivers/usb/musb/musbhsdma.c | 55 ++-- > > 9 files changed, 762 insertions(+), 38 deletions(-) > > create mode 100644 drivers/usb/musb/mediatek.c > > > > diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig > > index ad08895..b72b7c1 100644 > > --- a/drivers/usb/musb/Kconfig > > +++ b/drivers/usb/musb/Kconfig > > @@ -115,6 +115,12 @@ config USB_MUSB_JZ4740 > > depends on USB_MUSB_GADGET > > depends on USB_OTG_BLACKLIST_HUB > > > > +config USB_MUSB_MEDIATEK > > + tristate "MediaTek platforms" > > + depends on ARCH_MEDIATEK || COMPILE_TEST > > + depends on NOP_USB_XCEIV > > + depends on GENERIC_PHY > > + > > config USB_MUSB_AM335X_CHILD > > tristate > > > > @@ -141,7 +147,7 @@ config USB_UX500_DMA > > > > config USB_INVENTRA_DMA > > bool 'Inventra' > > - depends on USB_MUSB_OMAP2PLUS > > + depends on USB_MUSB_OMAP2PLUS || USB_MUSB_MEDIATEK > > help > > Enable DMA transfers using Mentor's engine. > > > > diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile > > index 3a88c79..63d82d0 100644 > > --- a/drivers/usb/musb/Makefile > > +++ b/drivers/usb/musb/Makefile > > @@ -24,6 +24,7 @@ obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o > > obj-$(CONFIG_USB_MUSB_UX500) += ux500.o > > obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o > > obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o > > +obj-$(CONFIG_USB_MUSB_MEDIATEK) += mediatek.o > > > > > > obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o > > diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c > > new file mode 100644 > > index 0000000..7221989 > > --- /dev/null > > +++ b/drivers/usb/musb/mediatek.c > > @@ -0,0 +1,617 @@ > > +// SPDX-License-Identifier: GPL-2.0 > > +/* > > + * Copyright (C) 2018 MediaTek Inc. > > + * > > + * Author: > > + * Min Guo > > + * Yonglong Wu > > + */ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include "musb_core.h" > > +#include "musb_dma.h" > > + > > +#define USB_L1INTS 0x00a0 > > +#define USB_L1INTM 0x00a4 > > +#define MTK_MUSB_TXFUNCADDR 0x0480 > > + > > +/* MediaTek controller toggle enable and status reg */ > > +#define MUSB_RXTOG 0x80 > > +#define MUSB_RXTOGEN 0x82 > > +#define MUSB_TXTOG 0x84 > > +#define MUSB_TXTOGEN 0x86 > > + > > +#define TX_INT_STATUS BIT(0) > > +#define RX_INT_STATUS BIT(1) > > +#define USBCOM_INT_STATUS BIT(2) > > missing a TAB for the alignment? Okay. > > +#define DMA_INT_STATUS BIT(3) > > + > > +#define DMA_INTR_STATUS_MSK GENMASK(7, 0) > > +#define DMA_INTR_UNMASK_SET_MSK GENMASK(31, 24) > > + > > +enum mtk_vbus_id_state { > > + MTK_ID_FLOAT = 1, > > + MTK_ID_GROUND, > > + MTK_VBUS_OFF, > > + MTK_VBUS_VALID, > > +}; > > + > > +struct mtk_glue { > > + struct device *dev; > > + struct musb *musb; > > + struct platform_device *musb_pdev; > > + struct platform_device *usb_phy; > > + struct phy *phy; > > + struct usb_phy *xceiv; > > + enum phy_mode phy_mode; > > + struct clk *main; > > + struct clk *mcu; > > + struct clk *univpll; > > + struct regulator *vbus; > > + struct extcon_dev *edev; > > + struct notifier_block vbus_nb; > > + struct notifier_block id_nb; > > +}; > > + > > +static int mtk_musb_clks_get(struct mtk_glue *glue) > > +{ > > + struct device *dev = glue->dev; > > + > > + glue->main = devm_clk_get(dev, "main"); > > + if (IS_ERR(glue->main)) { > > + dev_err(dev, "fail to get main clock\n"); > > + return PTR_ERR(glue->main); > > + } > > + > > + glue->mcu = devm_clk_get(dev, "mcu"); > > + if (IS_ERR(glue->mcu)) { > > + dev_err(dev, "fail to get mcu clock\n"); > > + return PTR_ERR(glue->mcu); > > + } > > + > > + glue->univpll = devm_clk_get(dev, "univpll"); > > + if (IS_ERR(glue->univpll)) { > > + dev_err(dev, "fail to get univpll clock\n"); > > + return PTR_ERR(glue->univpll); > > + } > > + > > + return 0; > > +} > > + > > +static int mtk_musb_clks_enable(struct mtk_glue *glue) > > +{ > > + int ret; > > + > > + ret = clk_prepare_enable(glue->main); > > + if (ret) { > > + dev_err(glue->dev, "failed to enable main clock\n"); > > + goto err_main_clk; > > + } > > + > > + ret = clk_prepare_enable(glue->mcu); > > + if (ret) { > > + dev_err(glue->dev, "failed to enable mcu clock\n"); > > + goto err_mcu_clk; > > + } > > + > > + ret = clk_prepare_enable(glue->univpll); > > + if (ret) { > > + dev_err(glue->dev, "failed to enable univpll clock\n"); > > + goto err_univpll_clk; > > + } > > + > > + return 0; > > + > > +err_univpll_clk: > > + clk_disable_unprepare(glue->mcu); > > +err_mcu_clk: > > + clk_disable_unprepare(glue->main); > > +err_main_clk: > > + return ret; > > +} > > + > > +static void mtk_musb_clks_disable(struct mtk_glue *glue) > > +{ > > + clk_disable_unprepare(glue->univpll); > > + clk_disable_unprepare(glue->mcu); > > + clk_disable_unprepare(glue->main); > > +} > > + > > +static void mtk_musb_set_vbus(struct musb *musb, int is_on) > > +{ > > + struct device *dev = musb->controller; > > + struct mtk_glue *glue = dev_get_drvdata(dev->parent); > > + int ret; > > + > > + /* vbus is optional */ > > + if (!glue->vbus) > > + return; > > + > > + dev_dbg(musb->controller, "%s, is_on=%d\r\n", __func__, is_on); > > + if (is_on) { > > + ret = regulator_enable(glue->vbus); > > + if (ret) { > > + dev_err(glue->dev, "fail to enable vbus regulator\n"); > > + return; > > + } > > + } else { > > + regulator_disable(glue->vbus); > > + } > > +} > > + > > +/* > > + * switch to host: -> MTK_VBUS_OFF --> MTK_ID_GROUND > > + * switch to device: -> MTK_ID_FLOAT --> MTK_VBUS_VALID > > + */ > > +static void mtk_musb_set_mailbox(struct mtk_glue *glue, > > + enum mtk_vbus_id_state status) > > add one more TAB for params. Okay. > > +{ > > + struct musb *musb = glue->musb; > > + u8 devctl = 0; > > + > > + dev_dbg(glue->dev, "mailbox state(%d)\n", status); > > + switch (status) { > > + case MTK_ID_GROUND: > > + phy_power_on(glue->phy); > > + devctl = readb(musb->mregs + MUSB_DEVCTL); > > + musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; > > + mtk_musb_set_vbus(musb, 1); > > + glue->phy_mode = PHY_MODE_USB_HOST; > > + phy_set_mode(glue->phy, glue->phy_mode); > > + devctl |= MUSB_DEVCTL_SESSION; > > + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); > > + MUSB_HST_MODE(musb); > > + break; > > + /* > > + * MTK_ID_FLOAT process is the same as MTK_VBUS_VALID > > + * except that turn off VBUS > > + */ > > + case MTK_ID_FLOAT: > > + mtk_musb_set_vbus(musb, 0); > > + /* fall through */ > > + case MTK_VBUS_OFF: > > + musb->xceiv->otg->state = OTG_STATE_B_IDLE; > > + devctl &= ~MUSB_DEVCTL_SESSION; > > + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); > > + phy_power_off(glue->phy); > > + break; > > + case MTK_VBUS_VALID: > > + phy_power_on(glue->phy); > > + glue->phy_mode = PHY_MODE_USB_DEVICE; > > + phy_set_mode(glue->phy, glue->phy_mode); > > + MUSB_DEV_MODE(musb); > > + break; > > + default: > > + dev_err(glue->dev, "invalid state\n"); > > + } > > +} > > + > > +static int mtk_musb_id_notifier(struct notifier_block *nb, > > + unsigned long event, void *ptr) > > +{ > > + struct mtk_glue *glue = container_of(nb, struct mtk_glue, id_nb); > > + > > + if (event) > > + mtk_musb_set_mailbox(glue, MTK_ID_GROUND); > > + else > > + mtk_musb_set_mailbox(glue, MTK_ID_FLOAT); > > + > > + return NOTIFY_DONE; > > +} > > + > > +static int mtk_musb_vbus_notifier(struct notifier_block *nb, > > + unsigned long event, void *ptr) > > +{ > > + struct mtk_glue *glue = container_of(nb, struct mtk_glue, vbus_nb); > > + > > + if (event) > > + mtk_musb_set_mailbox(glue, MTK_VBUS_VALID); > > + else > > + mtk_musb_set_mailbox(glue, MTK_VBUS_OFF); > > + > > + return NOTIFY_DONE; > > +} > > + > > +static void mtk_otg_switch_init(struct mtk_glue *glue) > > +{ > > + int ret; > > + > > + /* extcon is optional */ > > + if (!glue->edev) > > + return; > > + > > + glue->vbus_nb.notifier_call = mtk_musb_vbus_notifier; > > + ret = devm_extcon_register_notifier(glue->dev, glue->edev, EXTCON_USB, > > + &glue->vbus_nb); > > + if (ret < 0) > > + dev_err(glue->dev, "failed to register notifier for USB\n"); > > + > > + glue->id_nb.notifier_call = mtk_musb_id_notifier; > > + ret = devm_extcon_register_notifier(glue->dev, glue->edev, > > + EXTCON_USB_HOST, &glue->id_nb); > > + if (ret < 0) > > + dev_err(glue->dev, "failed to register notifier for USB-HOST\n"); > > + > > + dev_dbg(glue->dev, "EXTCON_USB: %d, EXTCON_USB_HOST: %d\n", > > + extcon_get_state(glue->edev, EXTCON_USB), > > + extcon_get_state(glue->edev, EXTCON_USB_HOST)); > > + > > + /* default as host, switch to device mode if needed */ > > + if (extcon_get_state(glue->edev, EXTCON_USB_HOST) == false) > > + mtk_musb_set_mailbox(glue, MTK_ID_FLOAT); > > + if (extcon_get_state(glue->edev, EXTCON_USB) == true) > > + mtk_musb_set_mailbox(glue, MTK_VBUS_VALID); > > +} > > + > > +static irqreturn_t generic_interrupt(int irq, void *__hci) > > +{ > > + unsigned long flags; > > + irqreturn_t retval = IRQ_NONE; > > + struct musb *musb = __hci; > > + > > + spin_lock_irqsave(&musb->lock, flags); > > + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB) & > > + musb_readb(musb->mregs, MUSB_INTRUSBE); > > + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX) > > + & musb_readw(musb->mregs, MUSB_INTRTXE); > > + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX) > > + & musb_readw(musb->mregs, MUSB_INTRRXE); > > + /* MediaTek controller interrupt status is W1C */ > > + musb_clearw(musb->mregs, MUSB_INTRRX, musb->int_rx); > > + musb_clearw(musb->mregs, MUSB_INTRTX, musb->int_tx); > > + musb_clearb(musb->mregs, MUSB_INTRUSB, musb->int_usb); > > + > > + if (musb->int_usb || musb->int_tx || musb->int_rx) > > + retval = musb_interrupt(musb); > > + > > + spin_unlock_irqrestore(&musb->lock, flags); > > + > > + return retval; > > +} > > + > > +static irqreturn_t mtk_musb_interrupt(int irq, void *dev_id) > > +{ > > + irqreturn_t retval = IRQ_NONE; > > + struct musb *musb = (struct musb *)dev_id; > > + u32 l1_ints; > > + > > + l1_ints = musb_readl(musb->mregs, USB_L1INTS) & > > + musb_readl(musb->mregs, USB_L1INTM); > > + > > + if (l1_ints & (TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS)) > > + retval = generic_interrupt(irq, musb); > > + > > +#if defined(CONFIG_USB_INVENTRA_DMA) > > + if (l1_ints & DMA_INT_STATUS) > > + retval = dma_controller_irq(irq, musb->dma_controller); > > +#endif > > + return retval; > > +} > > + > > +static u32 mtk_musb_busctl_offset(u8 epnum, u16 offset) > > +{ > > + return MTK_MUSB_TXFUNCADDR + offset + 8 * epnum; > > +} > > + > > +static void mtk_musb_clearb(void __iomem *addr, unsigned int offset, u8 data) > > remove 'u8 data' parameter, then add: Okay. > > +{ > > u8 data; > > > + /* W1C */ > data = musb_readb(addr, offset); > > + musb_writeb(addr, offset, data); > > +} > > + > > +static void mtk_musb_clearw(void __iomem *addr, unsigned int offset, u16 data) > > +{ > > + /* W1C */ > > + musb_writew(addr, offset, data); > > +} > > similar as mtk_musb_clearb() above. Okay. > > + > > +static int mtk_musb_init(struct musb *musb) > > +{ > > + struct device *dev = musb->controller; > > + struct mtk_glue *glue = dev_get_drvdata(dev->parent); > > + int ret; > > [snip] > > > + if (pdata->mode == USB_DR_MODE_OTG) > > + mtk_otg_switch_init(glue); > > + > > + dev_info(dev, "USB probe done!\n"); > > not really useful, can be removed. Okay. > > + return 0; > > + > > +err_device_register: > > + mtk_musb_clks_disable(glue); > > +err_enable_clk: > > + pm_runtime_put_sync(dev); > > + pm_runtime_disable(dev); > > +err_unregister_usb_phy: > > + usb_phy_generic_unregister(glue->usb_phy); > > + return ret; > > +} > > + > > +static int mtk_musb_remove(struct platform_device *pdev) > > +{ > > + struct mtk_glue *glue = platform_get_drvdata(pdev); > > + struct platform_device *usb_phy = glue->usb_phy; > > + > > + platform_device_unregister(glue->musb_pdev); > > + usb_phy_generic_unregister(usb_phy); > > + > > + return 0; > > +} > > + > > +#ifdef CONFIG_OF > > +static const struct of_device_id mtk_musb_match[] = { > > + {.compatible = "mediatek,mtk-musb",}, > > + {}, > > +}; > > +MODULE_DEVICE_TABLE(of, mtk_musb_match); > > +#endif > > + > > +static struct platform_driver mtk_musb_driver = { > > + .probe = mtk_musb_probe, > > + .remove = mtk_musb_remove, > > + .driver = { > > + .name = "musb-mtk", > > + .of_match_table = of_match_ptr(mtk_musb_match), > > + }, > > +}; > > + > > +module_platform_driver(mtk_musb_driver); > > + > > +MODULE_DESCRIPTION("MediaTek MUSB Glue Layer"); > > +MODULE_AUTHOR("Min Guo "); > > +MODULE_LICENSE("GPL v2"); > > diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c > > index b7d5627..2c0d102 100644 > > --- a/drivers/usb/musb/musb_core.c > > +++ b/drivers/usb/musb/musb_core.c > > @@ -260,6 +260,11 @@ static void musb_default_writeb(void __iomem *addr, unsigned offset, u8 data) > > __raw_writeb(data, addr + offset); > > } > > > > +static void > > +musb_default_clearb(void __iomem *addr, unsigned int offset, u8 data) > > +{ > > +} > > don't need this, use musb_readb() for the function pointer. Okay. > > + > > static u16 musb_default_readw(const void __iomem *addr, unsigned offset) > > { > > u16 data = __raw_readw(addr + offset); > > @@ -274,6 +279,43 @@ static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data) > > __raw_writew(data, addr + offset); > > } > > > > +static void > > +musb_default_clearw(void __iomem *addr, unsigned int offset, u16 data) > > +{ > > +} > > don't need this, use musb_readw() for the function pointer. Okay. > > + > > +static u16 musb_default_get_toggle(struct musb_qh *qh, int is_in) > > +{ > > + void __iomem *epio = qh->hw_ep->regs; > > + u16 csr; > > + > > + if (is_in) > > + csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; > > + else > > + csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; > > + > > + return csr; > > +} > > + > > +static u16 musb_default_set_toggle(struct musb_qh *qh, int is_in, > > + struct urb *urb) > > +{ > > + u16 csr = 0; > > + u16 toggle = 0; > > no need to assign them 0. Okay. > > + > > + toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in); > > + > > + if (is_in) > > + csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE > > + | MUSB_RXCSR_H_DATATOGGLE) : 0; > > + else > > + csr |= toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE > > + | MUSB_TXCSR_H_DATATOGGLE) > > + : MUSB_TXCSR_CLRDATATOG; > > + > > + return csr; > > +} > > + > > /* > > * Load an endpoint's FIFO > > */ > > @@ -370,12 +412,18 @@ static void musb_default_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) > > void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); > > EXPORT_SYMBOL_GPL(musb_writeb); > > > > +void (*musb_clearb)(void __iomem *addr, unsigned int offset, u8 data); > > +EXPORT_SYMBOL_GPL(musb_clearb); > > + > > u16 (*musb_readw)(const void __iomem *addr, unsigned offset); > > EXPORT_SYMBOL_GPL(musb_readw); > > > > void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); > > EXPORT_SYMBOL_GPL(musb_writew); > > > > +void (*musb_clearw)(void __iomem *addr, unsigned int offset, u16 data); > > +EXPORT_SYMBOL_GPL(musb_clearw); > > + > > u32 musb_readl(const void __iomem *addr, unsigned offset) > > { > > u32 data = __raw_readl(addr + offset); > > @@ -1028,6 +1076,11 @@ static void musb_disable_interrupts(struct musb *musb) > > temp = musb_readb(mbase, MUSB_INTRUSB); > > temp = musb_readw(mbase, MUSB_INTRTX); > > temp = musb_readw(mbase, MUSB_INTRRX); > > replace the 3 line above with > musb_clearb/w(); Okay. > > + > > + /* some platform needs clear pending interrupts by manual */ > > + musb_clearb(mbase, MUSB_INTRUSB, musb_readb(mbase, MUSB_INTRUSB)); > > + musb_clearw(mbase, MUSB_INTRRX, musb_readw(mbase, MUSB_INTRRX)); > > + musb_clearw(mbase, MUSB_INTRTX, musb_readw(mbase, MUSB_INTRTX)); > > then those are no longer needed. Okay. > > } > > > > static void musb_enable_interrupts(struct musb *musb) > > @@ -2192,6 +2245,8 @@ static void musb_deassert_reset(struct work_struct *work) > > musb_writeb = musb_default_writeb; > > musb_readw = musb_default_readw; > > musb_writew = musb_default_writew; > > + musb_clearb = musb_default_clearb; > > + musb_clearw = musb_default_clearw; > > > > /* The musb_platform_init() call: > > * - adjusts musb->mregs > > @@ -2252,10 +2307,14 @@ static void musb_deassert_reset(struct work_struct *work) > > musb_readb = musb->ops->readb; > > if (musb->ops->writeb) > > musb_writeb = musb->ops->writeb; > > + if (musb->ops->clearb) > > + musb_clearb = musb->ops->clearb; > else > musb_clearb = musb_readb; Okay. > > if (musb->ops->readw) > > musb_readw = musb->ops->readw; > > if (musb->ops->writew) > > musb_writew = musb->ops->writew; > > + if (musb->ops->clearw) > > + musb_clearw = musb->ops->clearw; > else > musb_clearw = musb_readw; Okay. > > > > #ifndef CONFIG_MUSB_PIO_ONLY > > if (!musb->ops->dma_init || !musb->ops->dma_exit) { > > @@ -2277,6 +2336,16 @@ static void musb_deassert_reset(struct work_struct *work) > > else > > musb->io.write_fifo = musb_default_write_fifo; > > > > + if (musb->ops->get_toggle) > > + musb->io.get_toggle = musb->ops->get_toggle; > > + else > > + musb->io.get_toggle = musb_default_get_toggle; > > + > > + if (musb->ops->set_toggle) > > + musb->io.set_toggle = musb->ops->set_toggle; > > + else > > + musb->io.set_toggle = musb_default_set_toggle; > > + > > if (!musb->xceiv->io_ops) { > > musb->xceiv->io_dev = musb->controller; > > musb->xceiv->io_priv = musb->mregs; > > diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h > > index 04203b7..71dca80 100644 > > --- a/drivers/usb/musb/musb_core.h > > +++ b/drivers/usb/musb/musb_core.h > > @@ -27,6 +27,7 @@ > > struct musb; > > struct musb_hw_ep; > > struct musb_ep; > > +struct musb_qh; > > > > /* Helper defines for struct musb->hwvers */ > > #define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) > > @@ -119,10 +120,14 @@ enum musb_g_ep0_state { > > * @fifo_offset: returns the fifo offset > > * @readb: read 8 bits > > * @writeb: write 8 bits > > + * @clearb: clear 8 bits, > > add "could be clear-on-read or W1C" to give more info. Okay. > > * @readw: read 16 bits > > * @writew: write 16 bits > > + * @clearw: clear 16 bits > > * @read_fifo: reads the fifo > > * @write_fifo: writes to fifo > > + * @get_toggle: platform specific get toggle function > > + * @set_toggle: platform specific set toggle function > > * @dma_init: platform specific dma init function > > * @dma_exit: platform specific dma exit function > > * @init: turns on clocks, sets up platform-specific registers, etc > > @@ -163,10 +168,14 @@ struct musb_platform_ops { > > u32 (*busctl_offset)(u8 epnum, u16 offset); > > u8 (*readb)(const void __iomem *addr, unsigned offset); > > void (*writeb)(void __iomem *addr, unsigned offset, u8 data); > > + void (*clearb)(void __iomem *addr, unsigned int offset, u8 data); > > u16 (*readw)(const void __iomem *addr, unsigned offset); > > void (*writew)(void __iomem *addr, unsigned offset, u16 data); > > + void (*clearw)(void __iomem *addr, unsigned int offset, u16 data); > > void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); > > void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); > > + u16 (*get_toggle)(struct musb_qh *qh, int is_in); > > + u16 (*set_toggle)(struct musb_qh *qh, int is_in, struct urb *urb); > > struct dma_controller * > > (*dma_init) (struct musb *musb, void __iomem *base); > > void (*dma_exit)(struct dma_controller *c); > > diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h > > index 8f60271..05103ea 100644 > > --- a/drivers/usb/musb/musb_dma.h > > +++ b/drivers/usb/musb/musb_dma.h > > @@ -35,6 +35,12 @@ > > * whether shared with the Inventra core or separate. > > */ > > > > +#define MUSB_HSDMA_BASE 0x200 > > +#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) > > +#define MUSB_HSDMA_CONTROL 0x4 > > +#define MUSB_HSDMA_ADDRESS 0x8 > > +#define MUSB_HSDMA_COUNT 0xc > > + > > #define DMA_ADDR_INVALID (~(dma_addr_t)0) > > > > #ifdef CONFIG_MUSB_PIO_ONLY > > @@ -191,6 +197,9 @@ static inline void musb_dma_controller_destroy(struct dma_controller *d) { } > > extern struct dma_controller * > > musbhs_dma_controller_create(struct musb *musb, void __iomem *base); > > extern void musbhs_dma_controller_destroy(struct dma_controller *c); > > +extern struct dma_controller * > > +musbhs_dma_controller_create_noirq(struct musb *musb, void __iomem *base); > > +extern irqreturn_t dma_controller_irq(int irq, void *private_data); > > > > extern struct dma_controller * > > tusb_dma_controller_create(struct musb *musb, void __iomem *base); > > diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c > > index 16d0ba4..ba66f44 100644 > > --- a/drivers/usb/musb/musb_host.c > > +++ b/drivers/usb/musb/musb_host.c > > @@ -290,39 +290,23 @@ static void musb_giveback(struct musb *musb, struct urb *urb, int status) > > static inline void musb_save_toggle(struct musb_qh *qh, int is_in, > > struct urb *urb) > > { > > - void __iomem *epio = qh->hw_ep->regs; > > - u16 csr; > > + struct musb *musb = qh->hw_ep->musb; > > + u16 csr; > > > > /* > > * FIXME: the current Mentor DMA code seems to have > > * problems getting toggle correct. > > */ > > - > > - if (is_in) > > - csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE; > > - else > > - csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE; > > - > > + csr = musb->io.get_toggle(qh, is_in); > > usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0); > > } > > > > static inline u16 musb_set_toggle(struct musb_qh *qh, int is_in, > > struct urb *urb) > > { > > - u16 csr = 0; > > - u16 toggle = 0; > > - > > - toggle = usb_gettoggle(urb->dev, qh->epnum, !is_in); > > - > > - if (is_in) > > - csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE > > - | MUSB_RXCSR_H_DATATOGGLE) : 0; > > - else > > - csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE > > - | MUSB_TXCSR_H_DATATOGGLE) > > - : MUSB_TXCSR_CLRDATATOG; > > + struct musb *musb = qh->hw_ep->musb; > > > > - return csr; > > + return musb->io.set_toggle(qh, is_in, urb); > > } > > Those two functions - musb_save_toggle() and musb_set_toggle() are very > short now, we can get rid of them, and directly use > musb->io.get/set_toggle(). Okay. > > > > /* > > diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h > > index 8058a58..9bae09b 100644 > > --- a/drivers/usb/musb/musb_io.h > > +++ b/drivers/usb/musb/musb_io.h > > @@ -22,6 +22,8 @@ > > * @read_fifo: platform specific function to read fifo > > * @write_fifo: platform specific function to write fifo > > * @busctl_offset: platform specific function to get busctl offset > > + * @get_toggle: platform specific function to get toggle > > + * @set_toggle: platform specific function to set toggle > > */ > > struct musb_io { > > u32 (*ep_offset)(u8 epnum, u16 offset); > > @@ -30,13 +32,17 @@ struct musb_io { > > void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); > > void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); > > u32 (*busctl_offset)(u8 epnum, u16 offset); > > + u16 (*get_toggle)(struct musb_qh *qh, int is_in); > > + u16 (*set_toggle)(struct musb_qh *qh, int is_in, struct urb *urb); > > }; > > > > /* Do not add new entries here, add them the struct musb_io instead */ > > extern u8 (*musb_readb)(const void __iomem *addr, unsigned offset); > > extern void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); > > +extern void (*musb_clearb)(void __iomem *addr, unsigned int offset, u8 data); > > extern u16 (*musb_readw)(const void __iomem *addr, unsigned offset); > > extern void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); > > +extern void (*musb_clearw)(void __iomem *addr, unsigned int offset, u16 data); > > extern u32 musb_readl(const void __iomem *addr, unsigned offset); > > extern void musb_writel(void __iomem *addr, unsigned offset, u32 data); > > > > diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c > > index a688f7f..b05fe68 100644 > > --- a/drivers/usb/musb/musbhsdma.c > > +++ b/drivers/usb/musb/musbhsdma.c > > @@ -10,12 +10,7 @@ > > #include > > #include > > #include "musb_core.h" > > - > > -#define MUSB_HSDMA_BASE 0x200 > > -#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) > > -#define MUSB_HSDMA_CONTROL 0x4 > > -#define MUSB_HSDMA_ADDRESS 0x8 > > -#define MUSB_HSDMA_COUNT 0xc > > +#include "musb_dma.h" > > > > #define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ > > (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) > > @@ -268,7 +263,7 @@ static int dma_channel_abort(struct dma_channel *channel) > > return 0; > > } > > > > -static irqreturn_t dma_controller_irq(int irq, void *private_data) > > +irqreturn_t dma_controller_irq(int irq, void *private_data) > > { > > struct musb_dma_controller *controller = private_data; > > struct musb *musb = controller->private_data; > > @@ -291,6 +286,9 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) > > > > int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); > > > > + /* some platform needs clear pending interrupts by manual */ > > + musb_clearb(musb->mregs, MUSB_HSDMA_INTR, int_hsdma); > > + > > if (!int_hsdma) { > > musb_dbg(musb, "spurious DMA irq"); > > > > @@ -382,6 +380,7 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data) > > spin_unlock_irqrestore(&musb->lock, flags); > > return retval; > > } > > +EXPORT_SYMBOL_GPL(dma_controller_irq); > > > > void musbhs_dma_controller_destroy(struct dma_controller *c) > > { > > @@ -397,18 +396,10 @@ void musbhs_dma_controller_destroy(struct dma_controller *c) > > } > > EXPORT_SYMBOL_GPL(musbhs_dma_controller_destroy); > > > > -struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > +static struct musb_dma_controller *dma_controller_alloc(struct musb *musb, > > void __iomem *base) > > { > > struct musb_dma_controller *controller; > > - struct device *dev = musb->controller; > > - struct platform_device *pdev = to_platform_device(dev); > > - int irq = platform_get_irq_byname(pdev, "dma"); > > - > > - if (irq <= 0) { > > - dev_err(dev, "No DMA interrupt line!\n"); > > - return NULL; > > - } > > > > controller = kzalloc(sizeof(*controller), GFP_KERNEL); > > if (!controller) > > @@ -422,6 +413,25 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > controller->controller.channel_release = dma_channel_release; > > controller->controller.channel_program = dma_channel_program; > > controller->controller.channel_abort = dma_channel_abort; > > + return controller; > > +} > > + > > +struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > + void __iomem *base) > > +{ > > + struct musb_dma_controller *controller; > > + struct device *dev = musb->controller; > > + struct platform_device *pdev = to_platform_device(dev); > > + int irq = platform_get_irq_byname(pdev, "dma"); > > + > > + if (irq <= 0) { > > + dev_err(dev, "No DMA interrupt line!\n"); > > + return NULL; > > + } > > + > > + controller = dma_controller_alloc(musb, base); > > + if (!controller) > > + return NULL; > > > > if (request_irq(irq, dma_controller_irq, 0, > > dev_name(musb->controller), &controller->controller)) { > > @@ -436,3 +446,16 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb, > > return &controller->controller; > > } > > EXPORT_SYMBOL_GPL(musbhs_dma_controller_create); > > + > > +struct dma_controller *musbhs_dma_controller_create_noirq(struct musb *musb, > > + void __iomem *base) > > +{ > > + struct musb_dma_controller *controller; > > + > > + controller = dma_controller_alloc(musb, base); > > + if (!controller) > > + return NULL; > > + > > + return &controller->controller; > > +} > > +EXPORT_SYMBOL_GPL(musbhs_dma_controller_create_noirq); > > regards, > -Bin. _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel