From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bin Liu Subject: Re: [PATCH v2 4/4] usb: musb: Add support for MediaTek musb controller Date: Tue, 15 Jan 2019 14:38:15 -0600 Message-ID: <20190115203815.GD18026@uda0271908> References: <1547516626-5084-1-git-send-email-min.guo@mediatek.com> <1547516626-5084-5-git-send-email-min.guo@mediatek.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Content-Disposition: inline In-Reply-To: <1547516626-5084-5-git-send-email-min.guo@mediatek.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: min.guo@mediatek.com 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 List-Id: linux-mediatek@lists.infradead.org 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. 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? > +#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. > +{ > + 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: > +{ 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. > + > +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. > + 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. > + > 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. > + > +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. > + > + 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(); > + > + /* 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. > } > > 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; > 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; > > #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. > * @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(). > > /* > 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: Bin Liu Message-Id: <20190115203815.GD18026@uda0271908> Date: Tue, 15 Jan 2019 14:38:15 -0600 To: min.guo@mediatek.com 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: SGkgTWluLAoKdmVyeSBjbG9zZSwgdGhhbmtzLgpCZWxvdyBJIHRyaWVkIHRvIGV4cGxhaW4gYSBm dXJ0aGVyIGNsZWFudXAgaW4gbXVzYl9jbGVhcmIvdygpIGFuZAptdXNiX2dldC9zZXRfdG9nZ2xl KCkgaW1wbGVtZW50YXRpb24uIFBsZWFzZSBsZXQgbWUga25vdyBpZiBpdCBpcyBub3QKY2xlYXIu CgpCYXNpY2FsbHksIHdlIGRvbid0IG5lZWQgbXVzYl9kZWZhdWx0X2NsZWFyYi93KCksIGp1c3Qg YXNzaWduIHRoZQptdXNiX2lvIGZ1bmN0aW9uIHBvaW50ZXJzIHRvIG11c2JfcmVhZGIvdygpLgoK VGhlbiB0aGUgbXRrIHBsYXRmb3JtIG11c2JfY2xlYXJiL3coKSBjYWxscyBtdXNiX3JlYWRiL3co KSBhbmQKbXVzYl93cml0ZWIvdygpIHRvIGhhbmRsZSBXMUMuCgpPbiBUdWUsIEphbiAxNSwgMjAx OSBhdCAwOTo0Mzo0NkFNICswODAwLCBtaW4uZ3VvQG1lZGlhdGVrLmNvbSB3cm90ZToKPiBGcm9t OiBNaW4gR3VvIDxtaW4uZ3VvQG1lZGlhdGVrLmNvbT4KPiAKPiBUaGlzIGFkZHMgc3VwcG9ydCBm b3IgTWVkaWFUZWsgbXVzYiBjb250cm9sbGVyIGluCj4gaG9zdCwgcGVyaXBoZXJhbCBhbmQgb3Rn IG1vZGUuCj4gVGhlcmUgYXJlIHNvbWUgcXVpcmsgb2YgTWVkaWFUZWsgbXVzYiBjb250cm9sbGVy LCBzdWNoIGFzOgo+ICAtVzFDIGludGVycnVwdCBzdGF0dXMgcmVnaXN0ZXJzCj4gIC1Qcml2YXRl IGRhdGEgdG9nZ2xlIHJlZ2lzdGVycwo+ICAtTm8gZGVkaWNhdGVkIERNQSBpbnRlcnJ1cHQgbGlu ZQo+IAo+IFNpZ25lZC1vZmYtYnk6IE1pbiBHdW8gPG1pbi5ndW9AbWVkaWF0ZWsuY29tPgo+IFNp Z25lZC1vZmYtYnk6IFlvbmdsb25nIFd1IDx5b25nbG9uZy53dUBtZWRpYXRlay5jb20+Cj4gLS0t Cj4gIGRyaXZlcnMvdXNiL211c2IvS2NvbmZpZyAgICAgfCAgIDggKy0KPiAgZHJpdmVycy91c2Iv bXVzYi9NYWtlZmlsZSAgICB8ICAgMSArCj4gIGRyaXZlcnMvdXNiL211c2IvbWVkaWF0ZWsuYyAg fCA2MTcgKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKwo+ICBkcml2 ZXJzL3VzYi9tdXNiL211c2JfY29yZS5jIHwgIDY5ICsrKysrCj4gIGRyaXZlcnMvdXNiL211c2Iv bXVzYl9jb3JlLmggfCAgIDkgKwo+ICBkcml2ZXJzL3VzYi9tdXNiL211c2JfZG1hLmggIHwgICA5 ICsKPiAgZHJpdmVycy91c2IvbXVzYi9tdXNiX2hvc3QuYyB8ICAyNiArLQo+ICBkcml2ZXJzL3Vz Yi9tdXNiL211c2JfaW8uaCAgIHwgICA2ICsKPiAgZHJpdmVycy91c2IvbXVzYi9tdXNiaHNkbWEu YyB8ICA1NSArKy0tCj4gIDkgZmlsZXMgY2hhbmdlZCwgNzYyIGluc2VydGlvbnMoKyksIDM4IGRl bGV0aW9ucygtKQo+ICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJpdmVycy91c2IvbXVzYi9tZWRpYXRl ay5jCj4gCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL211c2IvS2NvbmZpZyBiL2RyaXZlcnMv dXNiL211c2IvS2NvbmZpZwo+IGluZGV4IGFkMDg4OTUuLmI3MmI3YzEgMTAwNjQ0Cj4gLS0tIGEv ZHJpdmVycy91c2IvbXVzYi9LY29uZmlnCj4gKysrIGIvZHJpdmVycy91c2IvbXVzYi9LY29uZmln Cj4gQEAgLTExNSw2ICsxMTUsMTIgQEAgY29uZmlnIFVTQl9NVVNCX0paNDc0MAo+ICAJZGVwZW5k cyBvbiBVU0JfTVVTQl9HQURHRVQKPiAgCWRlcGVuZHMgb24gVVNCX09UR19CTEFDS0xJU1RfSFVC Cj4gIAo+ICtjb25maWcgVVNCX01VU0JfTUVESUFURUsKPiArCXRyaXN0YXRlICJNZWRpYVRlayBw bGF0Zm9ybXMiCj4gKwlkZXBlbmRzIG9uIEFSQ0hfTUVESUFURUsgfHwgQ09NUElMRV9URVNUCj4g KwlkZXBlbmRzIG9uIE5PUF9VU0JfWENFSVYKPiArCWRlcGVuZHMgb24gR0VORVJJQ19QSFkKPiAr Cj4gIGNvbmZpZyBVU0JfTVVTQl9BTTMzNVhfQ0hJTEQKPiAgCXRyaXN0YXRlCj4gIAo+IEBAIC0x NDEsNyArMTQ3LDcgQEAgY29uZmlnIFVTQl9VWDUwMF9ETUEKPiAgCj4gIGNvbmZpZyBVU0JfSU5W RU5UUkFfRE1BCj4gIAlib29sICdJbnZlbnRyYScKPiAtCWRlcGVuZHMgb24gVVNCX01VU0JfT01B UDJQTFVTCj4gKwlkZXBlbmRzIG9uIFVTQl9NVVNCX09NQVAyUExVUyB8fCBVU0JfTVVTQl9NRURJ QVRFSwo+ICAJaGVscAo+ICAJICBFbmFibGUgRE1BIHRyYW5zZmVycyB1c2luZyBNZW50b3IncyBl bmdpbmUuCj4gIAo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi9tdXNiL01ha2VmaWxlIGIvZHJp dmVycy91c2IvbXVzYi9NYWtlZmlsZQo+IGluZGV4IDNhODhjNzkuLjYzZDgyZDAgMTAwNjQ0Cj4g LS0tIGEvZHJpdmVycy91c2IvbXVzYi9NYWtlZmlsZQo+ICsrKyBiL2RyaXZlcnMvdXNiL211c2Iv TWFrZWZpbGUKPiBAQCAtMjQsNiArMjQsNyBAQCBvYmotJChDT05GSUdfVVNCX01VU0JfREE4WFgp CQkJKz0gZGE4eHgubwo+ICBvYmotJChDT05GSUdfVVNCX01VU0JfVVg1MDApCQkJKz0gdXg1MDAu bwo+ICBvYmotJChDT05GSUdfVVNCX01VU0JfSlo0NzQwKQkJCSs9IGp6NDc0MC5vCj4gIG9iai0k KENPTkZJR19VU0JfTVVTQl9TVU5YSSkJCQkrPSBzdW54aS5vCj4gK29iai0kKENPTkZJR19VU0Jf TVVTQl9NRURJQVRFSykgICAgICAJCSs9IG1lZGlhdGVrLm8KPiAgCj4gIAo+ICBvYmotJChDT05G SUdfVVNCX01VU0JfQU0zMzVYX0NISUxEKQkJKz0gbXVzYl9hbTMzNXgubwo+IGRpZmYgLS1naXQg YS9kcml2ZXJzL3VzYi9tdXNiL21lZGlhdGVrLmMgYi9kcml2ZXJzL3VzYi9tdXNiL21lZGlhdGVr LmMKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAuLjcyMjE5ODkKPiAtLS0g L2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy91c2IvbXVzYi9tZWRpYXRlay5jCj4gQEAgLTAsMCAr MSw2MTcgQEAKPiArLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAKPiArLyoKPiAr ICogQ29weXJpZ2h0IChDKSAyMDE4IE1lZGlhVGVrIEluYy4KPiArICoKPiArICogQXV0aG9yOgo+ ICsgKiAgTWluIEd1byA8bWluLmd1b0BtZWRpYXRlay5jb20+Cj4gKyAqICBZb25nbG9uZyBXdSA8 eW9uZ2xvbmcud3VAbWVkaWF0ZWsuY29tPgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9j bGsuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+Cj4gKyNpbmNsdWRlIDxsaW51 eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgo+ICsjaW5j bHVkZSA8bGludXgvdXNiL3VzYl9waHlfZ2VuZXJpYy5oPgo+ICsjaW5jbHVkZSAibXVzYl9jb3Jl LmgiCj4gKyNpbmNsdWRlICJtdXNiX2RtYS5oIgo+ICsKPiArI2RlZmluZSBVU0JfTDFJTlRTCTB4 MDBhMAo+ICsjZGVmaW5lIFVTQl9MMUlOVE0JMHgwMGE0Cj4gKyNkZWZpbmUgTVRLX01VU0JfVFhG VU5DQUREUgkweDA0ODAKPiArCj4gKy8qIE1lZGlhVGVrIGNvbnRyb2xsZXIgdG9nZ2xlIGVuYWJs ZSBhbmQgc3RhdHVzIHJlZyAqLwo+ICsjZGVmaW5lIE1VU0JfUlhUT0cJCTB4ODAKPiArI2RlZmlu ZSBNVVNCX1JYVE9HRU4JCTB4ODIKPiArI2RlZmluZSBNVVNCX1RYVE9HCQkweDg0Cj4gKyNkZWZp bmUgTVVTQl9UWFRPR0VOCQkweDg2Cj4gKwo+ICsjZGVmaW5lIFRYX0lOVF9TVEFUVVMJCUJJVCgw KQo+ICsjZGVmaW5lIFJYX0lOVF9TVEFUVVMJCUJJVCgxKQo+ICsjZGVmaW5lIFVTQkNPTV9JTlRf U1RBVFVTCUJJVCgyKQoKbWlzc2luZyBhIFRBQiBmb3IgdGhlIGFsaWdubWVudD8KCj4gKyNkZWZp bmUgRE1BX0lOVF9TVEFUVVMJCUJJVCgzKQo+ICsKPiArI2RlZmluZSBETUFfSU5UUl9TVEFUVVNf TVNLCQlHRU5NQVNLKDcsIDApCj4gKyNkZWZpbmUgRE1BX0lOVFJfVU5NQVNLX1NFVF9NU0sJR0VO TUFTSygzMSwgMjQpCj4gKwo+ICtlbnVtIG10a192YnVzX2lkX3N0YXRlIHsKPiArCU1US19JRF9G TE9BVCA9IDEsCj4gKwlNVEtfSURfR1JPVU5ELAo+ICsJTVRLX1ZCVVNfT0ZGLAo+ICsJTVRLX1ZC VVNfVkFMSUQsCj4gK307Cj4gKwo+ICtzdHJ1Y3QgbXRrX2dsdWUgewo+ICsJc3RydWN0IGRldmlj ZSAqZGV2Owo+ICsJc3RydWN0IG11c2IgKm11c2I7Cj4gKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNl ICptdXNiX3BkZXY7Cj4gKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICp1c2JfcGh5Owo+ICsJc3Ry dWN0IHBoeSAqcGh5Owo+ICsJc3RydWN0IHVzYl9waHkgKnhjZWl2Owo+ICsJZW51bSBwaHlfbW9k ZSBwaHlfbW9kZTsKPiArCXN0cnVjdCBjbGsgKm1haW47Cj4gKwlzdHJ1Y3QgY2xrICptY3U7Cj4g KwlzdHJ1Y3QgY2xrICp1bml2cGxsOwo+ICsJc3RydWN0IHJlZ3VsYXRvciAqdmJ1czsKPiArCXN0 cnVjdCBleHRjb25fZGV2ICplZGV2Owo+ICsJc3RydWN0IG5vdGlmaWVyX2Jsb2NrIHZidXNfbmI7 Cj4gKwlzdHJ1Y3Qgbm90aWZpZXJfYmxvY2sgaWRfbmI7Cj4gK307Cj4gKwo+ICtzdGF0aWMgaW50 IG10a19tdXNiX2Nsa3NfZ2V0KHN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSkKPiArewo+ICsJc3RydWN0 IGRldmljZSAqZGV2ID0gZ2x1ZS0+ZGV2Owo+ICsKPiArCWdsdWUtPm1haW4gPSBkZXZtX2Nsa19n ZXQoZGV2LCAibWFpbiIpOwo+ICsJaWYgKElTX0VSUihnbHVlLT5tYWluKSkgewo+ICsJCWRldl9l cnIoZGV2LCAiZmFpbCB0byBnZXQgbWFpbiBjbG9ja1xuIik7Cj4gKwkJcmV0dXJuIFBUUl9FUlIo Z2x1ZS0+bWFpbik7Cj4gKwl9Cj4gKwo+ICsJZ2x1ZS0+bWN1ID0gZGV2bV9jbGtfZ2V0KGRldiwg Im1jdSIpOwo+ICsJaWYgKElTX0VSUihnbHVlLT5tY3UpKSB7Cj4gKwkJZGV2X2VycihkZXYsICJm YWlsIHRvIGdldCBtY3UgY2xvY2tcbiIpOwo+ICsJCXJldHVybiBQVFJfRVJSKGdsdWUtPm1jdSk7 Cj4gKwl9Cj4gKwo+ICsJZ2x1ZS0+dW5pdnBsbCA9IGRldm1fY2xrX2dldChkZXYsICJ1bml2cGxs Iik7Cj4gKwlpZiAoSVNfRVJSKGdsdWUtPnVuaXZwbGwpKSB7Cj4gKwkJZGV2X2VycihkZXYsICJm YWlsIHRvIGdldCB1bml2cGxsIGNsb2NrXG4iKTsKPiArCQlyZXR1cm4gUFRSX0VSUihnbHVlLT51 bml2cGxsKTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGludCBt dGtfbXVzYl9jbGtzX2VuYWJsZShzdHJ1Y3QgbXRrX2dsdWUgKmdsdWUpCj4gK3sKPiArCWludCBy ZXQ7Cj4gKwo+ICsJcmV0ID0gY2xrX3ByZXBhcmVfZW5hYmxlKGdsdWUtPm1haW4pOwo+ICsJaWYg KHJldCkgewo+ICsJCWRldl9lcnIoZ2x1ZS0+ZGV2LCAiZmFpbGVkIHRvIGVuYWJsZSBtYWluIGNs b2NrXG4iKTsKPiArCQlnb3RvIGVycl9tYWluX2NsazsKPiArCX0KPiArCj4gKwlyZXQgPSBjbGtf cHJlcGFyZV9lbmFibGUoZ2x1ZS0+bWN1KTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKGds dWUtPmRldiwgImZhaWxlZCB0byBlbmFibGUgbWN1IGNsb2NrXG4iKTsKPiArCQlnb3RvIGVycl9t Y3VfY2xrOwo+ICsJfQo+ICsKPiArCXJldCA9IGNsa19wcmVwYXJlX2VuYWJsZShnbHVlLT51bml2 cGxsKTsKPiArCWlmIChyZXQpIHsKPiArCQlkZXZfZXJyKGdsdWUtPmRldiwgImZhaWxlZCB0byBl bmFibGUgdW5pdnBsbCBjbG9ja1xuIik7Cj4gKwkJZ290byBlcnJfdW5pdnBsbF9jbGs7Cj4gKwl9 Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gKwo+ICtlcnJfdW5pdnBsbF9jbGs6Cj4gKwljbGtfZGlzYWJs ZV91bnByZXBhcmUoZ2x1ZS0+bWN1KTsKPiArZXJyX21jdV9jbGs6Cj4gKwljbGtfZGlzYWJsZV91 bnByZXBhcmUoZ2x1ZS0+bWFpbik7Cj4gK2Vycl9tYWluX2NsazoKPiArCXJldHVybiByZXQ7Cj4g K30KPiArCj4gK3N0YXRpYyB2b2lkIG10a19tdXNiX2Nsa3NfZGlzYWJsZShzdHJ1Y3QgbXRrX2ds dWUgKmdsdWUpCj4gK3sKPiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShnbHVlLT51bml2cGxsKTsK PiArCWNsa19kaXNhYmxlX3VucHJlcGFyZShnbHVlLT5tY3UpOwo+ICsJY2xrX2Rpc2FibGVfdW5w cmVwYXJlKGdsdWUtPm1haW4pOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBtdGtfbXVzYl9zZXRf dmJ1cyhzdHJ1Y3QgbXVzYiAqbXVzYiwgaW50IGlzX29uKQo+ICt7Cj4gKwlzdHJ1Y3QgZGV2aWNl ICpkZXYgPSBtdXNiLT5jb250cm9sbGVyOwo+ICsJc3RydWN0IG10a19nbHVlICpnbHVlID0gZGV2 X2dldF9kcnZkYXRhKGRldi0+cGFyZW50KTsKPiArCWludCByZXQ7Cj4gKwo+ICsJLyogdmJ1cyBp cyBvcHRpb25hbCAqLwo+ICsJaWYgKCFnbHVlLT52YnVzKQo+ICsJCXJldHVybjsKPiArCj4gKwlk ZXZfZGJnKG11c2ItPmNvbnRyb2xsZXIsICIlcywgaXNfb249JWRcclxuIiwgX19mdW5jX18sIGlz X29uKTsKPiArCWlmIChpc19vbikgewo+ICsJCXJldCA9IHJlZ3VsYXRvcl9lbmFibGUoZ2x1ZS0+ dmJ1cyk7Cj4gKwkJaWYgKHJldCkgewo+ICsJCQlkZXZfZXJyKGdsdWUtPmRldiwgImZhaWwgdG8g ZW5hYmxlIHZidXMgcmVndWxhdG9yXG4iKTsKPiArCQkJcmV0dXJuOwo+ICsJCX0KPiArCX0gZWxz ZSB7Cj4gKwkJcmVndWxhdG9yX2Rpc2FibGUoZ2x1ZS0+dmJ1cyk7Cj4gKwl9Cj4gK30KPiArCj4g Ky8qCj4gKyAqIHN3aXRjaCB0byBob3N0OiAtPiBNVEtfVkJVU19PRkYgLS0+IE1US19JRF9HUk9V TkQKPiArICogc3dpdGNoIHRvIGRldmljZTogLT4gTVRLX0lEX0ZMT0FUIC0tPiBNVEtfVkJVU19W QUxJRAo+ICsgKi8KPiArc3RhdGljIHZvaWQgbXRrX211c2Jfc2V0X21haWxib3goc3RydWN0IG10 a19nbHVlICpnbHVlLAo+ICsJZW51bSBtdGtfdmJ1c19pZF9zdGF0ZSBzdGF0dXMpCgphZGQgb25l IG1vcmUgVEFCIGZvciBwYXJhbXMuCgo+ICt7Cj4gKwlzdHJ1Y3QgbXVzYiAqbXVzYiA9IGdsdWUt Pm11c2I7Cj4gKwl1OCBkZXZjdGwgPSAwOwo+ICsKPiArCWRldl9kYmcoZ2x1ZS0+ZGV2LCAibWFp bGJveCBzdGF0ZSglZClcbiIsIHN0YXR1cyk7Cj4gKwlzd2l0Y2ggKHN0YXR1cykgewo+ICsJY2Fz ZSBNVEtfSURfR1JPVU5EOgo+ICsJCXBoeV9wb3dlcl9vbihnbHVlLT5waHkpOwo+ICsJCWRldmN0 bCA9IHJlYWRiKG11c2ItPm1yZWdzICsgTVVTQl9ERVZDVEwpOwo+ICsJCW11c2ItPnhjZWl2LT5v dGctPnN0YXRlID0gT1RHX1NUQVRFX0FfV0FJVF9WUklTRTsKPiArCQltdGtfbXVzYl9zZXRfdmJ1 cyhtdXNiLCAxKTsKPiArCQlnbHVlLT5waHlfbW9kZSA9IFBIWV9NT0RFX1VTQl9IT1NUOwo+ICsJ CXBoeV9zZXRfbW9kZShnbHVlLT5waHksIGdsdWUtPnBoeV9tb2RlKTsKPiArCQlkZXZjdGwgfD0g TVVTQl9ERVZDVExfU0VTU0lPTjsKPiArCQltdXNiX3dyaXRlYihtdXNiLT5tcmVncywgTVVTQl9E RVZDVEwsIGRldmN0bCk7Cj4gKwkJTVVTQl9IU1RfTU9ERShtdXNiKTsKPiArCQlicmVhazsKPiAr CS8qCj4gKwkgKiBNVEtfSURfRkxPQVQgcHJvY2VzcyBpcyB0aGUgc2FtZSBhcyBNVEtfVkJVU19W QUxJRAo+ICsJICogZXhjZXB0IHRoYXQgdHVybiBvZmYgVkJVUwo+ICsJICovCj4gKwljYXNlIE1U S19JRF9GTE9BVDoKPiArCQltdGtfbXVzYl9zZXRfdmJ1cyhtdXNiLCAwKTsKPiArCQkvKiBmYWxs IHRocm91Z2ggKi8KPiArCWNhc2UgTVRLX1ZCVVNfT0ZGOgo+ICsJCW11c2ItPnhjZWl2LT5vdGct PnN0YXRlID0gT1RHX1NUQVRFX0JfSURMRTsKPiArCQlkZXZjdGwgJj0gfk1VU0JfREVWQ1RMX1NF U1NJT047Cj4gKwkJbXVzYl93cml0ZWIobXVzYi0+bXJlZ3MsIE1VU0JfREVWQ1RMLCBkZXZjdGwp Owo+ICsJCXBoeV9wb3dlcl9vZmYoZ2x1ZS0+cGh5KTsKPiArCQlicmVhazsKPiArCWNhc2UgTVRL X1ZCVVNfVkFMSUQ6Cj4gKwkJcGh5X3Bvd2VyX29uKGdsdWUtPnBoeSk7Cj4gKwkJZ2x1ZS0+cGh5 X21vZGUgPSBQSFlfTU9ERV9VU0JfREVWSUNFOwo+ICsJCXBoeV9zZXRfbW9kZShnbHVlLT5waHks IGdsdWUtPnBoeV9tb2RlKTsKPiArCQlNVVNCX0RFVl9NT0RFKG11c2IpOwo+ICsJCWJyZWFrOwo+ ICsJZGVmYXVsdDoKPiArCQlkZXZfZXJyKGdsdWUtPmRldiwgImludmFsaWQgc3RhdGVcbiIpOwo+ ICsJfQo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IG10a19tdXNiX2lkX25vdGlmaWVyKHN0cnVjdCBu b3RpZmllcl9ibG9jayAqbmIsCj4gKwl1bnNpZ25lZCBsb25nIGV2ZW50LCB2b2lkICpwdHIpCj4g K3sKPiArCXN0cnVjdCBtdGtfZ2x1ZSAqZ2x1ZSA9IGNvbnRhaW5lcl9vZihuYiwgc3RydWN0IG10 a19nbHVlLCBpZF9uYik7Cj4gKwo+ICsJaWYgKGV2ZW50KQo+ICsJCW10a19tdXNiX3NldF9tYWls Ym94KGdsdWUsIE1US19JRF9HUk9VTkQpOwo+ICsJZWxzZQo+ICsJCW10a19tdXNiX3NldF9tYWls Ym94KGdsdWUsIE1US19JRF9GTE9BVCk7Cj4gKwo+ICsJcmV0dXJuIE5PVElGWV9ET05FOwo+ICt9 Cj4gKwo+ICtzdGF0aWMgaW50IG10a19tdXNiX3ZidXNfbm90aWZpZXIoc3RydWN0IG5vdGlmaWVy X2Jsb2NrICpuYiwKPiArCXVuc2lnbmVkIGxvbmcgZXZlbnQsIHZvaWQgKnB0cikKPiArewo+ICsJ c3RydWN0IG10a19nbHVlICpnbHVlID0gY29udGFpbmVyX29mKG5iLCBzdHJ1Y3QgbXRrX2dsdWUs IHZidXNfbmIpOwo+ICsKPiArCWlmIChldmVudCkKPiArCQltdGtfbXVzYl9zZXRfbWFpbGJveChn bHVlLCBNVEtfVkJVU19WQUxJRCk7Cj4gKwllbHNlCj4gKwkJbXRrX211c2Jfc2V0X21haWxib3go Z2x1ZSwgTVRLX1ZCVVNfT0ZGKTsKPiArCj4gKwlyZXR1cm4gTk9USUZZX0RPTkU7Cj4gK30KPiAr Cj4gK3N0YXRpYyB2b2lkIG10a19vdGdfc3dpdGNoX2luaXQoc3RydWN0IG10a19nbHVlICpnbHVl KQo+ICt7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCS8qIGV4dGNvbiBpcyBvcHRpb25hbCAqLwo+ICsJ aWYgKCFnbHVlLT5lZGV2KQo+ICsJCXJldHVybjsKPiArCj4gKwlnbHVlLT52YnVzX25iLm5vdGlm aWVyX2NhbGwgPSBtdGtfbXVzYl92YnVzX25vdGlmaWVyOwo+ICsJcmV0ID0gZGV2bV9leHRjb25f cmVnaXN0ZXJfbm90aWZpZXIoZ2x1ZS0+ZGV2LCBnbHVlLT5lZGV2LCBFWFRDT05fVVNCLAo+ICsJ CQkJCSZnbHVlLT52YnVzX25iKTsKPiArCWlmIChyZXQgPCAwKQo+ICsJCWRldl9lcnIoZ2x1ZS0+ ZGV2LCAiZmFpbGVkIHRvIHJlZ2lzdGVyIG5vdGlmaWVyIGZvciBVU0JcbiIpOwo+ICsKPiArCWds dWUtPmlkX25iLm5vdGlmaWVyX2NhbGwgPSBtdGtfbXVzYl9pZF9ub3RpZmllcjsKPiArCXJldCA9 IGRldm1fZXh0Y29uX3JlZ2lzdGVyX25vdGlmaWVyKGdsdWUtPmRldiwgZ2x1ZS0+ZWRldiwKPiAr CQkJCQlFWFRDT05fVVNCX0hPU1QsICZnbHVlLT5pZF9uYik7Cj4gKwlpZiAocmV0IDwgMCkKPiAr CQlkZXZfZXJyKGdsdWUtPmRldiwgImZhaWxlZCB0byByZWdpc3RlciBub3RpZmllciBmb3IgVVNC LUhPU1RcbiIpOwo+ICsKPiArCWRldl9kYmcoZ2x1ZS0+ZGV2LCAiRVhUQ09OX1VTQjogJWQsIEVY VENPTl9VU0JfSE9TVDogJWRcbiIsCj4gKwkJZXh0Y29uX2dldF9zdGF0ZShnbHVlLT5lZGV2LCBF WFRDT05fVVNCKSwKPiArCQlleHRjb25fZ2V0X3N0YXRlKGdsdWUtPmVkZXYsIEVYVENPTl9VU0Jf SE9TVCkpOwo+ICsKPiArCS8qIGRlZmF1bHQgYXMgaG9zdCwgc3dpdGNoIHRvIGRldmljZSBtb2Rl IGlmIG5lZWRlZCAqLwo+ICsJaWYgKGV4dGNvbl9nZXRfc3RhdGUoZ2x1ZS0+ZWRldiwgRVhUQ09O X1VTQl9IT1NUKSA9PSBmYWxzZSkKPiArCQltdGtfbXVzYl9zZXRfbWFpbGJveChnbHVlLCBNVEtf SURfRkxPQVQpOwo+ICsJaWYgKGV4dGNvbl9nZXRfc3RhdGUoZ2x1ZS0+ZWRldiwgRVhUQ09OX1VT QikgPT0gdHJ1ZSkKPiArCQltdGtfbXVzYl9zZXRfbWFpbGJveChnbHVlLCBNVEtfVkJVU19WQUxJ RCk7Cj4gK30KPiArCj4gK3N0YXRpYyBpcnFyZXR1cm5fdCBnZW5lcmljX2ludGVycnVwdChpbnQg aXJxLCB2b2lkICpfX2hjaSkKPiArewo+ICsJdW5zaWduZWQgbG9uZyBmbGFnczsKPiArCWlycXJl dHVybl90IHJldHZhbCA9IElSUV9OT05FOwo+ICsJc3RydWN0IG11c2IgKm11c2IgPSBfX2hjaTsK PiArCj4gKwlzcGluX2xvY2tfaXJxc2F2ZSgmbXVzYi0+bG9jaywgZmxhZ3MpOwo+ICsJbXVzYi0+ aW50X3VzYiA9IG11c2JfcmVhZGIobXVzYi0+bXJlZ3MsIE1VU0JfSU5UUlVTQikgJgo+ICsJICAg IG11c2JfcmVhZGIobXVzYi0+bXJlZ3MsIE1VU0JfSU5UUlVTQkUpOwo+ICsJbXVzYi0+aW50X3R4 ID0gbXVzYl9yZWFkdyhtdXNiLT5tcmVncywgTVVTQl9JTlRSVFgpCj4gKwkgICAgJiBtdXNiX3Jl YWR3KG11c2ItPm1yZWdzLCBNVVNCX0lOVFJUWEUpOwo+ICsJbXVzYi0+aW50X3J4ID0gbXVzYl9y ZWFkdyhtdXNiLT5tcmVncywgTVVTQl9JTlRSUlgpCj4gKwkgICAgJiBtdXNiX3JlYWR3KG11c2It Pm1yZWdzLCBNVVNCX0lOVFJSWEUpOwo+ICsJLyogTWVkaWFUZWsgY29udHJvbGxlciBpbnRlcnJ1 cHQgc3RhdHVzIGlzIFcxQyAqLwo+ICsJbXVzYl9jbGVhcncobXVzYi0+bXJlZ3MsIE1VU0JfSU5U UlJYLCBtdXNiLT5pbnRfcngpOwo+ICsJbXVzYl9jbGVhcncobXVzYi0+bXJlZ3MsIE1VU0JfSU5U UlRYLCBtdXNiLT5pbnRfdHgpOwo+ICsJbXVzYl9jbGVhcmIobXVzYi0+bXJlZ3MsIE1VU0JfSU5U UlVTQiwgbXVzYi0+aW50X3VzYik7Cj4gKwo+ICsJaWYgKG11c2ItPmludF91c2IgfHwgbXVzYi0+ aW50X3R4IHx8IG11c2ItPmludF9yeCkKPiArCQlyZXR2YWwgPSBtdXNiX2ludGVycnVwdChtdXNi KTsKPiArCj4gKwlzcGluX3VubG9ja19pcnFyZXN0b3JlKCZtdXNiLT5sb2NrLCBmbGFncyk7Cj4g Kwo+ICsJcmV0dXJuIHJldHZhbDsKPiArfQo+ICsKPiArc3RhdGljIGlycXJldHVybl90IG10a19t dXNiX2ludGVycnVwdChpbnQgaXJxLCB2b2lkICpkZXZfaWQpCj4gK3sKPiArCWlycXJldHVybl90 IHJldHZhbCA9IElSUV9OT05FOwo+ICsJc3RydWN0IG11c2IgKm11c2IgPSAoc3RydWN0IG11c2Ig KilkZXZfaWQ7Cj4gKwl1MzIgbDFfaW50czsKPiArCj4gKwlsMV9pbnRzID0gbXVzYl9yZWFkbCht dXNiLT5tcmVncywgVVNCX0wxSU5UUykgJgo+ICsJCQltdXNiX3JlYWRsKG11c2ItPm1yZWdzLCBV U0JfTDFJTlRNKTsKPiArCj4gKwlpZiAobDFfaW50cyAmIChUWF9JTlRfU1RBVFVTIHwgUlhfSU5U X1NUQVRVUyB8IFVTQkNPTV9JTlRfU1RBVFVTKSkKPiArCQlyZXR2YWwgPSBnZW5lcmljX2ludGVy cnVwdChpcnEsIG11c2IpOwo+ICsKPiArI2lmIGRlZmluZWQoQ09ORklHX1VTQl9JTlZFTlRSQV9E TUEpCj4gKwlpZiAobDFfaW50cyAmIERNQV9JTlRfU1RBVFVTKQo+ICsJCXJldHZhbCA9IGRtYV9j b250cm9sbGVyX2lycShpcnEsIG11c2ItPmRtYV9jb250cm9sbGVyKTsKPiArI2VuZGlmCj4gKwly ZXR1cm4gcmV0dmFsOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdTMyIG10a19tdXNiX2J1c2N0bF9vZmZz ZXQodTggZXBudW0sIHUxNiBvZmZzZXQpCj4gK3sKPiArCXJldHVybiBNVEtfTVVTQl9UWEZVTkNB RERSICsgb2Zmc2V0ICsgOCAqIGVwbnVtOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCBtdGtfbXVz Yl9jbGVhcmIodm9pZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBpbnQgb2Zmc2V0LCB1OCBkYXRh KQoKcmVtb3ZlICd1OCBkYXRhJyBwYXJhbWV0ZXIsIHRoZW4gYWRkOgoKPiArewoKCXU4IGRhdGE7 Cgo+ICsJLyogVzFDICovCglkYXRhID0gbXVzYl9yZWFkYihhZGRyLCBvZmZzZXQpOwo+ICsJbXVz Yl93cml0ZWIoYWRkciwgb2Zmc2V0LCBkYXRhKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgbXRr X211c2JfY2xlYXJ3KHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTE2 IGRhdGEpCj4gK3sKPiArCS8qIFcxQyAqLwo+ICsJbXVzYl93cml0ZXcoYWRkciwgb2Zmc2V0LCBk YXRhKTsKPiArfQoKc2ltaWxhciBhcyBtdGtfbXVzYl9jbGVhcmIoKSBhYm92ZS4KCj4gKwo+ICtz dGF0aWMgaW50IG10a19tdXNiX2luaXQoc3RydWN0IG11c2IgKm11c2IpCj4gK3sKPiArCXN0cnVj dCBkZXZpY2UgKmRldiA9IG11c2ItPmNvbnRyb2xsZXI7Cj4gKwlzdHJ1Y3QgbXRrX2dsdWUgKmds dWUgPSBkZXZfZ2V0X2RydmRhdGEoZGV2LT5wYXJlbnQpOwo+ICsJaW50IHJldDsKCltzbmlwXQoK PiArCWlmIChwZGF0YS0+bW9kZSA9PSBVU0JfRFJfTU9ERV9PVEcpCj4gKwkJbXRrX290Z19zd2l0 Y2hfaW5pdChnbHVlKTsKPiArCj4gKwlkZXZfaW5mbyhkZXYsICJVU0IgcHJvYmUgZG9uZSFcbiIp OwoKbm90IHJlYWxseSB1c2VmdWwsIGNhbiBiZSByZW1vdmVkLgoKPiArCXJldHVybiAwOwo+ICsK PiArZXJyX2RldmljZV9yZWdpc3RlcjoKPiArCW10a19tdXNiX2Nsa3NfZGlzYWJsZShnbHVlKTsK PiArZXJyX2VuYWJsZV9jbGs6Cj4gKwlwbV9ydW50aW1lX3B1dF9zeW5jKGRldik7Cj4gKwlwbV9y dW50aW1lX2Rpc2FibGUoZGV2KTsKPiArZXJyX3VucmVnaXN0ZXJfdXNiX3BoeToKPiArCXVzYl9w aHlfZ2VuZXJpY191bnJlZ2lzdGVyKGdsdWUtPnVzYl9waHkpOwo+ICsJcmV0dXJuIHJldDsKPiAr fQo+ICsKPiArc3RhdGljIGludCBtdGtfbXVzYl9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2Rldmlj ZSAqcGRldikKPiArewo+ICsJc3RydWN0IG10a19nbHVlICpnbHVlID0gcGxhdGZvcm1fZ2V0X2Ry dmRhdGEocGRldik7Cj4gKwlzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICp1c2JfcGh5ID0gZ2x1ZS0+ dXNiX3BoeTsKPiArCj4gKwlwbGF0Zm9ybV9kZXZpY2VfdW5yZWdpc3RlcihnbHVlLT5tdXNiX3Bk ZXYpOwo+ICsJdXNiX3BoeV9nZW5lcmljX3VucmVnaXN0ZXIodXNiX3BoeSk7Cj4gKwo+ICsJcmV0 dXJuIDA7Cj4gK30KPiArCj4gKyNpZmRlZiBDT05GSUdfT0YKPiArc3RhdGljIGNvbnN0IHN0cnVj dCBvZl9kZXZpY2VfaWQgbXRrX211c2JfbWF0Y2hbXSA9IHsKPiArCXsuY29tcGF0aWJsZSA9ICJt ZWRpYXRlayxtdGstbXVzYiIsfSwKPiArCXt9LAo+ICt9Owo+ICtNT0RVTEVfREVWSUNFX1RBQkxF KG9mLCBtdGtfbXVzYl9tYXRjaCk7Cj4gKyNlbmRpZgo+ICsKPiArc3RhdGljIHN0cnVjdCBwbGF0 Zm9ybV9kcml2ZXIgbXRrX211c2JfZHJpdmVyID0gewo+ICsJLnByb2JlID0gbXRrX211c2JfcHJv YmUsCj4gKwkucmVtb3ZlID0gbXRrX211c2JfcmVtb3ZlLAo+ICsJLmRyaXZlciA9IHsKPiArCQkg ICAubmFtZSA9ICJtdXNiLW10ayIsCj4gKwkJICAgLm9mX21hdGNoX3RhYmxlID0gb2ZfbWF0Y2hf cHRyKG10a19tdXNiX21hdGNoKSwKPiArCX0sCj4gK307Cj4gKwo+ICttb2R1bGVfcGxhdGZvcm1f ZHJpdmVyKG10a19tdXNiX2RyaXZlcik7Cj4gKwo+ICtNT0RVTEVfREVTQ1JJUFRJT04oIk1lZGlh VGVrIE1VU0IgR2x1ZSBMYXllciIpOwo+ICtNT0RVTEVfQVVUSE9SKCJNaW4gR3VvIDxtaW4uZ3Vv QG1lZGlhdGVrLmNvbT4iKTsKPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCB2MiIpOwo+IGRpZmYgLS1n aXQgYS9kcml2ZXJzL3VzYi9tdXNiL211c2JfY29yZS5jIGIvZHJpdmVycy91c2IvbXVzYi9tdXNi X2NvcmUuYwo+IGluZGV4IGI3ZDU2MjcuLjJjMGQxMDIgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy91 c2IvbXVzYi9tdXNiX2NvcmUuYwo+ICsrKyBiL2RyaXZlcnMvdXNiL211c2IvbXVzYl9jb3JlLmMK PiBAQCAtMjYwLDYgKzI2MCwxMSBAQCBzdGF0aWMgdm9pZCBtdXNiX2RlZmF1bHRfd3JpdGViKHZv aWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgb2Zmc2V0LCB1OCBkYXRhKQo+ICAJX19yYXdfd3Jp dGViKGRhdGEsIGFkZHIgKyBvZmZzZXQpOwo+ICB9Cj4gIAo+ICtzdGF0aWMgdm9pZAo+ICttdXNi X2RlZmF1bHRfY2xlYXJiKHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwg dTggZGF0YSkKPiArewo+ICt9Cgpkb24ndCBuZWVkIHRoaXMsIHVzZSBtdXNiX3JlYWRiKCkgZm9y IHRoZSBmdW5jdGlvbiBwb2ludGVyLgoKPiArCj4gIHN0YXRpYyB1MTYgbXVzYl9kZWZhdWx0X3Jl YWR3KGNvbnN0IHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgb2Zmc2V0KQo+ICB7Cj4gIAl1 MTYgZGF0YSA9IF9fcmF3X3JlYWR3KGFkZHIgKyBvZmZzZXQpOwo+IEBAIC0yNzQsNiArMjc5LDQz IEBAIHN0YXRpYyB2b2lkIG11c2JfZGVmYXVsdF93cml0ZXcodm9pZCBfX2lvbWVtICphZGRyLCB1 bnNpZ25lZCBvZmZzZXQsIHUxNiBkYXRhKQo+ICAJX19yYXdfd3JpdGV3KGRhdGEsIGFkZHIgKyBv ZmZzZXQpOwo+ICB9Cj4gIAo+ICtzdGF0aWMgdm9pZAo+ICttdXNiX2RlZmF1bHRfY2xlYXJ3KHZv aWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTE2IGRhdGEpCj4gK3sKPiAr fQoKZG9uJ3QgbmVlZCB0aGlzLCB1c2UgbXVzYl9yZWFkdygpIGZvciB0aGUgZnVuY3Rpb24gcG9p bnRlci4KCj4gKwo+ICtzdGF0aWMgdTE2IG11c2JfZGVmYXVsdF9nZXRfdG9nZ2xlKHN0cnVjdCBt dXNiX3FoICpxaCwgaW50IGlzX2luKQo+ICt7Cj4gKwl2b2lkIF9faW9tZW0gKmVwaW8gPSBxaC0+ aHdfZXAtPnJlZ3M7Cj4gKwl1MTYgY3NyOwo+ICsKPiArCWlmIChpc19pbikKPiArCQljc3IgPSBt dXNiX3JlYWR3KGVwaW8sIE1VU0JfUlhDU1IpICYgTVVTQl9SWENTUl9IX0RBVEFUT0dHTEU7Cj4g KwllbHNlCj4gKwkJY3NyID0gbXVzYl9yZWFkdyhlcGlvLCBNVVNCX1RYQ1NSKSAmIE1VU0JfVFhD U1JfSF9EQVRBVE9HR0xFOwo+ICsKPiArCXJldHVybiBjc3I7Cj4gK30KPiArCj4gK3N0YXRpYyB1 MTYgbXVzYl9kZWZhdWx0X3NldF90b2dnbGUoc3RydWN0IG11c2JfcWggKnFoLCBpbnQgaXNfaW4s Cj4gKwlzdHJ1Y3QgdXJiICp1cmIpCj4gK3sKPiArCXUxNiBjc3IgPSAwOwo+ICsJdTE2IHRvZ2ds ZSA9IDA7CgpubyBuZWVkIHRvIGFzc2lnbiB0aGVtIDAuCgo+ICsKPiArCXRvZ2dsZSA9IHVzYl9n ZXR0b2dnbGUodXJiLT5kZXYsIHFoLT5lcG51bSwgIWlzX2luKTsKPiArCj4gKwlpZiAoaXNfaW4p Cj4gKwkJY3NyID0gdG9nZ2xlID8gKE1VU0JfUlhDU1JfSF9XUl9EQVRBVE9HR0xFCj4gKwkJCQl8 IE1VU0JfUlhDU1JfSF9EQVRBVE9HR0xFKSA6IDA7Cj4gKwllbHNlCj4gKwkJY3NyIHw9IHRvZ2ds ZSA/IChNVVNCX1RYQ1NSX0hfV1JfREFUQVRPR0dMRQo+ICsJCQkJfCBNVVNCX1RYQ1NSX0hfREFU QVRPR0dMRSkKPiArCQkJCTogTVVTQl9UWENTUl9DTFJEQVRBVE9HOwo+ICsKPiArCXJldHVybiBj c3I7Cj4gK30KPiArCj4gIC8qCj4gICAqIExvYWQgYW4gZW5kcG9pbnQncyBGSUZPCj4gICAqLwo+ IEBAIC0zNzAsMTIgKzQxMiwxOCBAQCBzdGF0aWMgdm9pZCBtdXNiX2RlZmF1bHRfcmVhZF9maWZv KHN0cnVjdCBtdXNiX2h3X2VwICpod19lcCwgdTE2IGxlbiwgdTggKmRzdCkKPiAgdm9pZCAoKm11 c2Jfd3JpdGViKSh2b2lkIF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCwgdTggZGF0YSk7 Cj4gIEVYUE9SVF9TWU1CT0xfR1BMKG11c2Jfd3JpdGViKTsKPiAgCj4gK3ZvaWQgKCptdXNiX2Ns ZWFyYikodm9pZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBpbnQgb2Zmc2V0LCB1OCBkYXRhKTsK PiArRVhQT1JUX1NZTUJPTF9HUEwobXVzYl9jbGVhcmIpOwo+ICsKPiAgdTE2ICgqbXVzYl9yZWFk dykoY29uc3Qgdm9pZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBvZmZzZXQpOwo+ICBFWFBPUlRf U1lNQk9MX0dQTChtdXNiX3JlYWR3KTsKPiAgCj4gIHZvaWQgKCptdXNiX3dyaXRldykodm9pZCBf X2lvbWVtICphZGRyLCB1bnNpZ25lZCBvZmZzZXQsIHUxNiBkYXRhKTsKPiAgRVhQT1JUX1NZTUJP TF9HUEwobXVzYl93cml0ZXcpOwo+ICAKPiArdm9pZCAoKm11c2JfY2xlYXJ3KSh2b2lkIF9faW9t ZW0gKmFkZHIsIHVuc2lnbmVkIGludCBvZmZzZXQsIHUxNiBkYXRhKTsKPiArRVhQT1JUX1NZTUJP TF9HUEwobXVzYl9jbGVhcncpOwo+ICsKPiAgdTMyIG11c2JfcmVhZGwoY29uc3Qgdm9pZCBfX2lv bWVtICphZGRyLCB1bnNpZ25lZCBvZmZzZXQpCj4gIHsKPiAgCXUzMiBkYXRhID0gX19yYXdfcmVh ZGwoYWRkciArIG9mZnNldCk7Cj4gQEAgLTEwMjgsNiArMTA3NiwxMSBAQCBzdGF0aWMgdm9pZCBt dXNiX2Rpc2FibGVfaW50ZXJydXB0cyhzdHJ1Y3QgbXVzYiAqbXVzYikKPiAgCXRlbXAgPSBtdXNi X3JlYWRiKG1iYXNlLCBNVVNCX0lOVFJVU0IpOwo+ICAJdGVtcCA9IG11c2JfcmVhZHcobWJhc2Us IE1VU0JfSU5UUlRYKTsKPiAgCXRlbXAgPSBtdXNiX3JlYWR3KG1iYXNlLCBNVVNCX0lOVFJSWCk7 CgpyZXBsYWNlIHRoZSAzIGxpbmUgYWJvdmUgd2l0aAoJbXVzYl9jbGVhcmIvdygpOwoKPiArCj4g KwkvKiBzb21lIHBsYXRmb3JtIG5lZWRzIGNsZWFyIHBlbmRpbmcgaW50ZXJydXB0cyBieSBtYW51 YWwgKi8KPiArCW11c2JfY2xlYXJiKG1iYXNlLCBNVVNCX0lOVFJVU0IsIG11c2JfcmVhZGIobWJh c2UsIE1VU0JfSU5UUlVTQikpOwo+ICsJbXVzYl9jbGVhcncobWJhc2UsIE1VU0JfSU5UUlJYLCBt dXNiX3JlYWR3KG1iYXNlLCBNVVNCX0lOVFJSWCkpOwo+ICsJbXVzYl9jbGVhcncobWJhc2UsIE1V U0JfSU5UUlRYLCBtdXNiX3JlYWR3KG1iYXNlLCBNVVNCX0lOVFJUWCkpOwoKdGhlbiB0aG9zZSBh cmUgbm8gbG9uZ2VyIG5lZWRlZC4KCj4gIH0KPiAgCj4gIHN0YXRpYyB2b2lkIG11c2JfZW5hYmxl X2ludGVycnVwdHMoc3RydWN0IG11c2IgKm11c2IpCj4gQEAgLTIxOTIsNiArMjI0NSw4IEBAIHN0 YXRpYyB2b2lkIG11c2JfZGVhc3NlcnRfcmVzZXQoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQo+ ICAJbXVzYl93cml0ZWIgPSBtdXNiX2RlZmF1bHRfd3JpdGViOwo+ICAJbXVzYl9yZWFkdyA9IG11 c2JfZGVmYXVsdF9yZWFkdzsKPiAgCW11c2Jfd3JpdGV3ID0gbXVzYl9kZWZhdWx0X3dyaXRldzsK PiArCW11c2JfY2xlYXJiID0gbXVzYl9kZWZhdWx0X2NsZWFyYjsKPiArCW11c2JfY2xlYXJ3ID0g bXVzYl9kZWZhdWx0X2NsZWFydzsKPiAgCj4gIAkvKiBUaGUgbXVzYl9wbGF0Zm9ybV9pbml0KCkg Y2FsbDoKPiAgCSAqICAgLSBhZGp1c3RzIG11c2ItPm1yZWdzCj4gQEAgLTIyNTIsMTAgKzIzMDcs MTQgQEAgc3RhdGljIHZvaWQgbXVzYl9kZWFzc2VydF9yZXNldChzdHJ1Y3Qgd29ya19zdHJ1Y3Qg KndvcmspCj4gIAkJbXVzYl9yZWFkYiA9IG11c2ItPm9wcy0+cmVhZGI7Cj4gIAlpZiAobXVzYi0+ b3BzLT53cml0ZWIpCj4gIAkJbXVzYl93cml0ZWIgPSBtdXNiLT5vcHMtPndyaXRlYjsKPiArCWlm IChtdXNiLT5vcHMtPmNsZWFyYikKPiArCQltdXNiX2NsZWFyYiA9IG11c2ItPm9wcy0+Y2xlYXJi OwoJZWxzZQoJCW11c2JfY2xlYXJiID0gbXVzYl9yZWFkYjsKCj4gIAlpZiAobXVzYi0+b3BzLT5y ZWFkdykKPiAgCQltdXNiX3JlYWR3ID0gbXVzYi0+b3BzLT5yZWFkdzsKPiAgCWlmIChtdXNiLT5v cHMtPndyaXRldykKPiAgCQltdXNiX3dyaXRldyA9IG11c2ItPm9wcy0+d3JpdGV3Owo+ICsJaWYg KG11c2ItPm9wcy0+Y2xlYXJ3KQo+ICsJCW11c2JfY2xlYXJ3ID0gbXVzYi0+b3BzLT5jbGVhcnc7 CgllbHNlCgkJbXVzYl9jbGVhcncgPSBtdXNiX3JlYWR3Owo+ICAKPiAgI2lmbmRlZiBDT05GSUdf TVVTQl9QSU9fT05MWQo+ICAJaWYgKCFtdXNiLT5vcHMtPmRtYV9pbml0IHx8ICFtdXNiLT5vcHMt PmRtYV9leGl0KSB7Cj4gQEAgLTIyNzcsNiArMjMzNiwxNiBAQCBzdGF0aWMgdm9pZCBtdXNiX2Rl YXNzZXJ0X3Jlc2V0KHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKPiAgCWVsc2UKPiAgCQltdXNi LT5pby53cml0ZV9maWZvID0gbXVzYl9kZWZhdWx0X3dyaXRlX2ZpZm87Cj4gIAo+ICsJaWYgKG11 c2ItPm9wcy0+Z2V0X3RvZ2dsZSkKPiArCQltdXNiLT5pby5nZXRfdG9nZ2xlID0gbXVzYi0+b3Bz LT5nZXRfdG9nZ2xlOwo+ICsJZWxzZQo+ICsJCW11c2ItPmlvLmdldF90b2dnbGUgPSBtdXNiX2Rl ZmF1bHRfZ2V0X3RvZ2dsZTsKPiArCj4gKwlpZiAobXVzYi0+b3BzLT5zZXRfdG9nZ2xlKQo+ICsJ CW11c2ItPmlvLnNldF90b2dnbGUgPSBtdXNiLT5vcHMtPnNldF90b2dnbGU7Cj4gKwllbHNlCj4g KwkJbXVzYi0+aW8uc2V0X3RvZ2dsZSA9IG11c2JfZGVmYXVsdF9zZXRfdG9nZ2xlOwo+ICsKPiAg CWlmICghbXVzYi0+eGNlaXYtPmlvX29wcykgewo+ICAJCW11c2ItPnhjZWl2LT5pb19kZXYgPSBt dXNiLT5jb250cm9sbGVyOwo+ICAJCW11c2ItPnhjZWl2LT5pb19wcml2ID0gbXVzYi0+bXJlZ3M7 Cj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdXNiL211c2IvbXVzYl9jb3JlLmggYi9kcml2ZXJzL3Vz Yi9tdXNiL211c2JfY29yZS5oCj4gaW5kZXggMDQyMDNiNy4uNzFkY2E4MCAxMDA2NDQKPiAtLS0g YS9kcml2ZXJzL3VzYi9tdXNiL211c2JfY29yZS5oCj4gKysrIGIvZHJpdmVycy91c2IvbXVzYi9t dXNiX2NvcmUuaAo+IEBAIC0yNyw2ICsyNyw3IEBACj4gIHN0cnVjdCBtdXNiOwo+ICBzdHJ1Y3Qg bXVzYl9od19lcDsKPiAgc3RydWN0IG11c2JfZXA7Cj4gK3N0cnVjdCBtdXNiX3FoOwo+ICAKPiAg LyogSGVscGVyIGRlZmluZXMgZm9yIHN0cnVjdCBtdXNiLT5od3ZlcnMgKi8KPiAgI2RlZmluZSBN VVNCX0hXVkVSU19NQUpPUih4KQkoKHggPj4gMTApICYgMHgxZikKPiBAQCAtMTE5LDEwICsxMjAs MTQgQEAgZW51bSBtdXNiX2dfZXAwX3N0YXRlIHsKPiAgICogQGZpZm9fb2Zmc2V0OiByZXR1cm5z IHRoZSBmaWZvIG9mZnNldAo+ICAgKiBAcmVhZGI6CXJlYWQgOCBiaXRzCj4gICAqIEB3cml0ZWI6 CXdyaXRlIDggYml0cwo+ICsgKiBAY2xlYXJiOgljbGVhciA4IGJpdHMsCgphZGQgImNvdWxkIGJl IGNsZWFyLW9uLXJlYWQgb3IgVzFDIiB0byBnaXZlIG1vcmUgaW5mby4KCj4gICAqIEByZWFkdzoJ cmVhZCAxNiBiaXRzCj4gICAqIEB3cml0ZXc6CXdyaXRlIDE2IGJpdHMKPiArICogQGNsZWFydzoJ Y2xlYXIgMTYgYml0cwo+ICAgKiBAcmVhZF9maWZvOglyZWFkcyB0aGUgZmlmbwo+ICAgKiBAd3Jp dGVfZmlmbzoJd3JpdGVzIHRvIGZpZm8KPiArICogQGdldF90b2dnbGU6CXBsYXRmb3JtIHNwZWNp ZmljIGdldCB0b2dnbGUgZnVuY3Rpb24KPiArICogQHNldF90b2dnbGU6CXBsYXRmb3JtIHNwZWNp ZmljIHNldCB0b2dnbGUgZnVuY3Rpb24KPiAgICogQGRtYV9pbml0OglwbGF0Zm9ybSBzcGVjaWZp YyBkbWEgaW5pdCBmdW5jdGlvbgo+ICAgKiBAZG1hX2V4aXQ6CXBsYXRmb3JtIHNwZWNpZmljIGRt YSBleGl0IGZ1bmN0aW9uCj4gICAqIEBpbml0Ogl0dXJucyBvbiBjbG9ja3MsIHNldHMgdXAgcGxh dGZvcm0tc3BlY2lmaWMgcmVnaXN0ZXJzLCBldGMKPiBAQCAtMTYzLDEwICsxNjgsMTQgQEAgc3Ry dWN0IG11c2JfcGxhdGZvcm1fb3BzIHsKPiAgCXUzMgkoKmJ1c2N0bF9vZmZzZXQpKHU4IGVwbnVt LCB1MTYgb2Zmc2V0KTsKPiAgCXU4CSgqcmVhZGIpKGNvbnN0IHZvaWQgX19pb21lbSAqYWRkciwg dW5zaWduZWQgb2Zmc2V0KTsKPiAgCXZvaWQJKCp3cml0ZWIpKHZvaWQgX19pb21lbSAqYWRkciwg dW5zaWduZWQgb2Zmc2V0LCB1OCBkYXRhKTsKPiArCXZvaWQJKCpjbGVhcmIpKHZvaWQgX19pb21l bSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwgdTggZGF0YSk7Cj4gIAl1MTYJKCpyZWFkdyko Y29uc3Qgdm9pZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBvZmZzZXQpOwo+ICAJdm9pZAkoKndy aXRldykodm9pZCBfX2lvbWVtICphZGRyLCB1bnNpZ25lZCBvZmZzZXQsIHUxNiBkYXRhKTsKPiAr CXZvaWQJKCpjbGVhcncpKHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwg dTE2IGRhdGEpOwo+ICAJdm9pZAkoKnJlYWRfZmlmbykoc3RydWN0IG11c2JfaHdfZXAgKmh3X2Vw LCB1MTYgbGVuLCB1OCAqYnVmKTsKPiAgCXZvaWQJKCp3cml0ZV9maWZvKShzdHJ1Y3QgbXVzYl9o d19lcCAqaHdfZXAsIHUxNiBsZW4sIGNvbnN0IHU4ICpidWYpOwo+ICsJdTE2CSgqZ2V0X3RvZ2ds ZSkoc3RydWN0IG11c2JfcWggKnFoLCBpbnQgaXNfaW4pOwo+ICsJdTE2CSgqc2V0X3RvZ2dsZSko c3RydWN0IG11c2JfcWggKnFoLCBpbnQgaXNfaW4sIHN0cnVjdCB1cmIgKnVyYik7Cj4gIAlzdHJ1 Y3QgZG1hX2NvbnRyb2xsZXIgKgo+ICAJCSgqZG1hX2luaXQpIChzdHJ1Y3QgbXVzYiAqbXVzYiwg dm9pZCBfX2lvbWVtICpiYXNlKTsKPiAgCXZvaWQJKCpkbWFfZXhpdCkoc3RydWN0IGRtYV9jb250 cm9sbGVyICpjKTsKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy91c2IvbXVzYi9tdXNiX2RtYS5oIGIv ZHJpdmVycy91c2IvbXVzYi9tdXNiX2RtYS5oCj4gaW5kZXggOGY2MDI3MS4uMDUxMDNlYSAxMDA2 NDQKPiAtLS0gYS9kcml2ZXJzL3VzYi9tdXNiL211c2JfZG1hLmgKPiArKysgYi9kcml2ZXJzL3Vz Yi9tdXNiL211c2JfZG1hLmgKPiBAQCAtMzUsNiArMzUsMTIgQEAKPiAgICogICAgd2hldGhlciBz aGFyZWQgd2l0aCB0aGUgSW52ZW50cmEgY29yZSBvciBzZXBhcmF0ZS4KPiAgICovCj4gIAo+ICsj ZGVmaW5lIE1VU0JfSFNETUFfQkFTRQkJMHgyMDAKPiArI2RlZmluZSBNVVNCX0hTRE1BX0lOVFIJ CShNVVNCX0hTRE1BX0JBU0UgKyAwKQo+ICsjZGVmaW5lIE1VU0JfSFNETUFfQ09OVFJPTAkJMHg0 Cj4gKyNkZWZpbmUgTVVTQl9IU0RNQV9BRERSRVNTCQkweDgKPiArI2RlZmluZSBNVVNCX0hTRE1B X0NPVU5UCQkweGMKPiArCj4gICNkZWZpbmUJRE1BX0FERFJfSU5WQUxJRAkofihkbWFfYWRkcl90 KTApCj4gIAo+ICAjaWZkZWYgQ09ORklHX01VU0JfUElPX09OTFkKPiBAQCAtMTkxLDYgKzE5Nyw5 IEBAIHN0YXRpYyBpbmxpbmUgdm9pZCBtdXNiX2RtYV9jb250cm9sbGVyX2Rlc3Ryb3koc3RydWN0 IGRtYV9jb250cm9sbGVyICpkKSB7IH0KPiAgZXh0ZXJuIHN0cnVjdCBkbWFfY29udHJvbGxlciAq Cj4gIG11c2Joc19kbWFfY29udHJvbGxlcl9jcmVhdGUoc3RydWN0IG11c2IgKm11c2IsIHZvaWQg X19pb21lbSAqYmFzZSk7Cj4gIGV4dGVybiB2b2lkIG11c2Joc19kbWFfY29udHJvbGxlcl9kZXN0 cm95KHN0cnVjdCBkbWFfY29udHJvbGxlciAqYyk7Cj4gK2V4dGVybiBzdHJ1Y3QgZG1hX2NvbnRy b2xsZXIgKgo+ICttdXNiaHNfZG1hX2NvbnRyb2xsZXJfY3JlYXRlX25vaXJxKHN0cnVjdCBtdXNi ICptdXNiLCB2b2lkIF9faW9tZW0gKmJhc2UpOwo+ICtleHRlcm4gaXJxcmV0dXJuX3QgZG1hX2Nv bnRyb2xsZXJfaXJxKGludCBpcnEsIHZvaWQgKnByaXZhdGVfZGF0YSk7Cj4gIAo+ICBleHRlcm4g c3RydWN0IGRtYV9jb250cm9sbGVyICoKPiAgdHVzYl9kbWFfY29udHJvbGxlcl9jcmVhdGUoc3Ry dWN0IG11c2IgKm11c2IsIHZvaWQgX19pb21lbSAqYmFzZSk7Cj4gZGlmZiAtLWdpdCBhL2RyaXZl cnMvdXNiL211c2IvbXVzYl9ob3N0LmMgYi9kcml2ZXJzL3VzYi9tdXNiL211c2JfaG9zdC5jCj4g aW5kZXggMTZkMGJhNC4uYmE2NmY0NCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL3VzYi9tdXNiL211 c2JfaG9zdC5jCj4gKysrIGIvZHJpdmVycy91c2IvbXVzYi9tdXNiX2hvc3QuYwo+IEBAIC0yOTAs MzkgKzI5MCwyMyBAQCBzdGF0aWMgdm9pZCBtdXNiX2dpdmViYWNrKHN0cnVjdCBtdXNiICptdXNi LCBzdHJ1Y3QgdXJiICp1cmIsIGludCBzdGF0dXMpCj4gIHN0YXRpYyBpbmxpbmUgdm9pZCBtdXNi X3NhdmVfdG9nZ2xlKHN0cnVjdCBtdXNiX3FoICpxaCwgaW50IGlzX2luLAo+ICAJCQkJICAgIHN0 cnVjdCB1cmIgKnVyYikKPiAgewo+IC0Jdm9pZCBfX2lvbWVtCQkqZXBpbyA9IHFoLT5od19lcC0+ cmVnczsKPiAtCXUxNgkJCWNzcjsKPiArCXN0cnVjdCBtdXNiICptdXNiID0gcWgtPmh3X2VwLT5t dXNiOwo+ICsJdTE2IGNzcjsKPiAgCj4gIAkvKgo+ICAJICogRklYTUU6IHRoZSBjdXJyZW50IE1l bnRvciBETUEgY29kZSBzZWVtcyB0byBoYXZlCj4gIAkgKiBwcm9ibGVtcyBnZXR0aW5nIHRvZ2ds ZSBjb3JyZWN0Lgo+ICAJICovCj4gLQo+IC0JaWYgKGlzX2luKQo+IC0JCWNzciA9IG11c2JfcmVh ZHcoZXBpbywgTVVTQl9SWENTUikgJiBNVVNCX1JYQ1NSX0hfREFUQVRPR0dMRTsKPiAtCWVsc2UK PiAtCQljc3IgPSBtdXNiX3JlYWR3KGVwaW8sIE1VU0JfVFhDU1IpICYgTVVTQl9UWENTUl9IX0RB VEFUT0dHTEU7Cj4gLQo+ICsJY3NyID0gbXVzYi0+aW8uZ2V0X3RvZ2dsZShxaCwgaXNfaW4pOwo+ ICAJdXNiX3NldHRvZ2dsZSh1cmItPmRldiwgcWgtPmVwbnVtLCAhaXNfaW4sIGNzciA/IDEgOiAw KTsKPiAgfQo+ICAKPiAgc3RhdGljIGlubGluZSB1MTYgbXVzYl9zZXRfdG9nZ2xlKHN0cnVjdCBt dXNiX3FoICpxaCwgaW50IGlzX2luLAo+ICAJc3RydWN0IHVyYiAqdXJiKQo+ICB7Cj4gLQl1MTYg Y3NyID0gMDsKPiAtCXUxNiB0b2dnbGUgPSAwOwo+IC0KPiAtCXRvZ2dsZSA9IHVzYl9nZXR0b2dn bGUodXJiLT5kZXYsIHFoLT5lcG51bSwgIWlzX2luKTsKPiAtCj4gLQlpZiAoaXNfaW4pCj4gLQkJ Y3NyID0gdG9nZ2xlID8gKE1VU0JfUlhDU1JfSF9XUl9EQVRBVE9HR0xFCj4gLQkJCQl8IE1VU0Jf UlhDU1JfSF9EQVRBVE9HR0xFKSA6IDA7Cj4gLQllbHNlCj4gLQkJY3NyID0gdG9nZ2xlID8gKE1V U0JfVFhDU1JfSF9XUl9EQVRBVE9HR0xFCj4gLQkJCQl8IE1VU0JfVFhDU1JfSF9EQVRBVE9HR0xF KQo+IC0JCQkJOiBNVVNCX1RYQ1NSX0NMUkRBVEFUT0c7Cj4gKwlzdHJ1Y3QgbXVzYiAqbXVzYiA9 IHFoLT5od19lcC0+bXVzYjsKPiAgCj4gLQlyZXR1cm4gY3NyOwo+ICsJcmV0dXJuIG11c2ItPmlv LnNldF90b2dnbGUocWgsIGlzX2luLCB1cmIpOwo+ICB9CgpUaG9zZSB0d28gZnVuY3Rpb25zIC0g bXVzYl9zYXZlX3RvZ2dsZSgpIGFuZCBtdXNiX3NldF90b2dnbGUoKSBhcmUgdmVyeQpzaG9ydCBu b3csIHdlIGNhbiBnZXQgcmlkIG9mIHRoZW0sIGFuZCBkaXJlY3RseSB1c2UKbXVzYi0+aW8uZ2V0 L3NldF90b2dnbGUoKS4KCj4gIAo+ICAvKgo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3VzYi9tdXNi L211c2JfaW8uaCBiL2RyaXZlcnMvdXNiL211c2IvbXVzYl9pby5oCj4gaW5kZXggODA1OGE1OC4u OWJhZTA5YiAxMDA2NDQKPiAtLS0gYS9kcml2ZXJzL3VzYi9tdXNiL211c2JfaW8uaAo+ICsrKyBi L2RyaXZlcnMvdXNiL211c2IvbXVzYl9pby5oCj4gQEAgLTIyLDYgKzIyLDggQEAKPiAgICogQHJl YWRfZmlmbzoJcGxhdGZvcm0gc3BlY2lmaWMgZnVuY3Rpb24gdG8gcmVhZCBmaWZvCj4gICAqIEB3 cml0ZV9maWZvOglwbGF0Zm9ybSBzcGVjaWZpYyBmdW5jdGlvbiB0byB3cml0ZSBmaWZvCj4gICAq IEBidXNjdGxfb2Zmc2V0OiBwbGF0Zm9ybSBzcGVjaWZpYyBmdW5jdGlvbiB0byBnZXQgYnVzY3Rs IG9mZnNldAo+ICsgKiBAZ2V0X3RvZ2dsZTogcGxhdGZvcm0gc3BlY2lmaWMgZnVuY3Rpb24gdG8g Z2V0IHRvZ2dsZQo+ICsgKiBAc2V0X3RvZ2dsZTogcGxhdGZvcm0gc3BlY2lmaWMgZnVuY3Rpb24g dG8gc2V0IHRvZ2dsZQo+ICAgKi8KPiAgc3RydWN0IG11c2JfaW8gewo+ICAJdTMyCSgqZXBfb2Zm c2V0KSh1OCBlcG51bSwgdTE2IG9mZnNldCk7Cj4gQEAgLTMwLDEzICszMiwxNyBAQCBzdHJ1Y3Qg bXVzYl9pbyB7Cj4gIAl2b2lkCSgqcmVhZF9maWZvKShzdHJ1Y3QgbXVzYl9od19lcCAqaHdfZXAs IHUxNiBsZW4sIHU4ICpidWYpOwo+ICAJdm9pZAkoKndyaXRlX2ZpZm8pKHN0cnVjdCBtdXNiX2h3 X2VwICpod19lcCwgdTE2IGxlbiwgY29uc3QgdTggKmJ1Zik7Cj4gIAl1MzIJKCpidXNjdGxfb2Zm c2V0KSh1OCBlcG51bSwgdTE2IG9mZnNldCk7Cj4gKwl1MTYJKCpnZXRfdG9nZ2xlKShzdHJ1Y3Qg bXVzYl9xaCAqcWgsIGludCBpc19pbik7Cj4gKwl1MTYJKCpzZXRfdG9nZ2xlKShzdHJ1Y3QgbXVz Yl9xaCAqcWgsIGludCBpc19pbiwgc3RydWN0IHVyYiAqdXJiKTsKPiAgfTsKPiAgCj4gIC8qIERv IG5vdCBhZGQgbmV3IGVudHJpZXMgaGVyZSwgYWRkIHRoZW0gdGhlIHN0cnVjdCBtdXNiX2lvIGlu c3RlYWQgKi8KPiAgZXh0ZXJuIHU4ICgqbXVzYl9yZWFkYikoY29uc3Qgdm9pZCBfX2lvbWVtICph ZGRyLCB1bnNpZ25lZCBvZmZzZXQpOwo+ICBleHRlcm4gdm9pZCAoKm11c2Jfd3JpdGViKSh2b2lk IF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCwgdTggZGF0YSk7Cj4gK2V4dGVybiB2b2lk ICgqbXVzYl9jbGVhcmIpKHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNldCwg dTggZGF0YSk7Cj4gIGV4dGVybiB1MTYgKCptdXNiX3JlYWR3KShjb25zdCB2b2lkIF9faW9tZW0g KmFkZHIsIHVuc2lnbmVkIG9mZnNldCk7Cj4gIGV4dGVybiB2b2lkICgqbXVzYl93cml0ZXcpKHZv aWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgb2Zmc2V0LCB1MTYgZGF0YSk7Cj4gK2V4dGVybiB2 b2lkICgqbXVzYl9jbGVhcncpKHZvaWQgX19pb21lbSAqYWRkciwgdW5zaWduZWQgaW50IG9mZnNl dCwgdTE2IGRhdGEpOwo+ICBleHRlcm4gdTMyIG11c2JfcmVhZGwoY29uc3Qgdm9pZCBfX2lvbWVt ICphZGRyLCB1bnNpZ25lZCBvZmZzZXQpOwo+ICBleHRlcm4gdm9pZCBtdXNiX3dyaXRlbCh2b2lk IF9faW9tZW0gKmFkZHIsIHVuc2lnbmVkIG9mZnNldCwgdTMyIGRhdGEpOwo+ICAKPiBkaWZmIC0t Z2l0IGEvZHJpdmVycy91c2IvbXVzYi9tdXNiaHNkbWEuYyBiL2RyaXZlcnMvdXNiL211c2IvbXVz YmhzZG1hLmMKPiBpbmRleCBhNjg4ZjdmLi5iMDVmZTY4IDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMv dXNiL211c2IvbXVzYmhzZG1hLmMKPiArKysgYi9kcml2ZXJzL3VzYi9tdXNiL211c2Joc2RtYS5j Cj4gQEAgLTEwLDEyICsxMCw3IEBACj4gICNpbmNsdWRlIDxsaW51eC9wbGF0Zm9ybV9kZXZpY2Uu aD4KPiAgI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KPiAgI2luY2x1ZGUgIm11c2JfY29yZS5oIgo+ IC0KPiAtI2RlZmluZSBNVVNCX0hTRE1BX0JBU0UJCTB4MjAwCj4gLSNkZWZpbmUgTVVTQl9IU0RN QV9JTlRSCQkoTVVTQl9IU0RNQV9CQVNFICsgMCkKPiAtI2RlZmluZSBNVVNCX0hTRE1BX0NPTlRS T0wJCTB4NAo+IC0jZGVmaW5lIE1VU0JfSFNETUFfQUREUkVTUwkJMHg4Cj4gLSNkZWZpbmUgTVVT Ql9IU0RNQV9DT1VOVAkJMHhjCj4gKyNpbmNsdWRlICJtdXNiX2RtYS5oIgo+ICAKPiAgI2RlZmlu ZSBNVVNCX0hTRE1BX0NIQU5ORUxfT0ZGU0VUKF9iY2hhbm5lbCwgX29mZnNldCkJCVwKPiAgCQko TVVTQl9IU0RNQV9CQVNFICsgKF9iY2hhbm5lbCA8PCA0KSArIF9vZmZzZXQpCj4gQEAgLTI2OCw3 ICsyNjMsNyBAQCBzdGF0aWMgaW50IGRtYV9jaGFubmVsX2Fib3J0KHN0cnVjdCBkbWFfY2hhbm5l bCAqY2hhbm5lbCkKPiAgCXJldHVybiAwOwo+ICB9Cj4gIAo+IC1zdGF0aWMgaXJxcmV0dXJuX3Qg ZG1hX2NvbnRyb2xsZXJfaXJxKGludCBpcnEsIHZvaWQgKnByaXZhdGVfZGF0YSkKPiAraXJxcmV0 dXJuX3QgZG1hX2NvbnRyb2xsZXJfaXJxKGludCBpcnEsIHZvaWQgKnByaXZhdGVfZGF0YSkKPiAg ewo+ICAJc3RydWN0IG11c2JfZG1hX2NvbnRyb2xsZXIgKmNvbnRyb2xsZXIgPSBwcml2YXRlX2Rh dGE7Cj4gIAlzdHJ1Y3QgbXVzYiAqbXVzYiA9IGNvbnRyb2xsZXItPnByaXZhdGVfZGF0YTsKPiBA QCAtMjkxLDYgKzI4Niw5IEBAIHN0YXRpYyBpcnFyZXR1cm5fdCBkbWFfY29udHJvbGxlcl9pcnEo aW50IGlycSwgdm9pZCAqcHJpdmF0ZV9kYXRhKQo+ICAKPiAgCWludF9oc2RtYSA9IG11c2JfcmVh ZGIobWJhc2UsIE1VU0JfSFNETUFfSU5UUik7Cj4gIAo+ICsJLyogc29tZSBwbGF0Zm9ybSBuZWVk cyBjbGVhciBwZW5kaW5nIGludGVycnVwdHMgYnkgbWFudWFsICovCj4gKwltdXNiX2NsZWFyYiht dXNiLT5tcmVncywgTVVTQl9IU0RNQV9JTlRSLCBpbnRfaHNkbWEpOwo+ICsKPiAgCWlmICghaW50 X2hzZG1hKSB7Cj4gIAkJbXVzYl9kYmcobXVzYiwgInNwdXJpb3VzIERNQSBpcnEiKTsKPiAgCj4g QEAgLTM4Miw2ICszODAsNyBAQCBzdGF0aWMgaXJxcmV0dXJuX3QgZG1hX2NvbnRyb2xsZXJfaXJx KGludCBpcnEsIHZvaWQgKnByaXZhdGVfZGF0YSkKPiAgCXNwaW5fdW5sb2NrX2lycXJlc3RvcmUo Jm11c2ItPmxvY2ssIGZsYWdzKTsKPiAgCXJldHVybiByZXR2YWw7Cj4gIH0KPiArRVhQT1JUX1NZ TUJPTF9HUEwoZG1hX2NvbnRyb2xsZXJfaXJxKTsKPiAgCj4gIHZvaWQgbXVzYmhzX2RtYV9jb250 cm9sbGVyX2Rlc3Ryb3koc3RydWN0IGRtYV9jb250cm9sbGVyICpjKQo+ICB7Cj4gQEAgLTM5Nywx OCArMzk2LDEwIEBAIHZvaWQgbXVzYmhzX2RtYV9jb250cm9sbGVyX2Rlc3Ryb3koc3RydWN0IGRt YV9jb250cm9sbGVyICpjKQo+ICB9Cj4gIEVYUE9SVF9TWU1CT0xfR1BMKG11c2Joc19kbWFfY29u dHJvbGxlcl9kZXN0cm95KTsKPiAgCj4gLXN0cnVjdCBkbWFfY29udHJvbGxlciAqbXVzYmhzX2Rt YV9jb250cm9sbGVyX2NyZWF0ZShzdHJ1Y3QgbXVzYiAqbXVzYiwKPiArc3RhdGljIHN0cnVjdCBt dXNiX2RtYV9jb250cm9sbGVyICpkbWFfY29udHJvbGxlcl9hbGxvYyhzdHJ1Y3QgbXVzYiAqbXVz YiwKPiAgCQkJCQkJICAgIHZvaWQgX19pb21lbSAqYmFzZSkKPiAgewo+ICAJc3RydWN0IG11c2Jf ZG1hX2NvbnRyb2xsZXIgKmNvbnRyb2xsZXI7Cj4gLQlzdHJ1Y3QgZGV2aWNlICpkZXYgPSBtdXNi LT5jb250cm9sbGVyOwo+IC0Jc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldiA9IHRvX3BsYXRm b3JtX2RldmljZShkZXYpOwo+IC0JaW50IGlycSA9IHBsYXRmb3JtX2dldF9pcnFfYnluYW1lKHBk ZXYsICJkbWEiKTsKPiAtCj4gLQlpZiAoaXJxIDw9IDApIHsKPiAtCQlkZXZfZXJyKGRldiwgIk5v IERNQSBpbnRlcnJ1cHQgbGluZSFcbiIpOwo+IC0JCXJldHVybiBOVUxMOwo+IC0JfQo+ICAKPiAg CWNvbnRyb2xsZXIgPSBremFsbG9jKHNpemVvZigqY29udHJvbGxlciksIEdGUF9LRVJORUwpOwo+ ICAJaWYgKCFjb250cm9sbGVyKQo+IEBAIC00MjIsNiArNDEzLDI1IEBAIHN0cnVjdCBkbWFfY29u dHJvbGxlciAqbXVzYmhzX2RtYV9jb250cm9sbGVyX2NyZWF0ZShzdHJ1Y3QgbXVzYiAqbXVzYiwK PiAgCWNvbnRyb2xsZXItPmNvbnRyb2xsZXIuY2hhbm5lbF9yZWxlYXNlID0gZG1hX2NoYW5uZWxf cmVsZWFzZTsKPiAgCWNvbnRyb2xsZXItPmNvbnRyb2xsZXIuY2hhbm5lbF9wcm9ncmFtID0gZG1h X2NoYW5uZWxfcHJvZ3JhbTsKPiAgCWNvbnRyb2xsZXItPmNvbnRyb2xsZXIuY2hhbm5lbF9hYm9y dCA9IGRtYV9jaGFubmVsX2Fib3J0Owo+ICsJcmV0dXJuIGNvbnRyb2xsZXI7Cj4gK30KPiArCj4g K3N0cnVjdCBkbWFfY29udHJvbGxlciAqbXVzYmhzX2RtYV9jb250cm9sbGVyX2NyZWF0ZShzdHJ1 Y3QgbXVzYiAqbXVzYiwKPiArCQkJCQkJICAgIHZvaWQgX19pb21lbSAqYmFzZSkKPiArewo+ICsJ c3RydWN0IG11c2JfZG1hX2NvbnRyb2xsZXIgKmNvbnRyb2xsZXI7Cj4gKwlzdHJ1Y3QgZGV2aWNl ICpkZXYgPSBtdXNiLT5jb250cm9sbGVyOwo+ICsJc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRl diA9IHRvX3BsYXRmb3JtX2RldmljZShkZXYpOwo+ICsJaW50IGlycSA9IHBsYXRmb3JtX2dldF9p cnFfYnluYW1lKHBkZXYsICJkbWEiKTsKPiArCj4gKwlpZiAoaXJxIDw9IDApIHsKPiArCQlkZXZf ZXJyKGRldiwgIk5vIERNQSBpbnRlcnJ1cHQgbGluZSFcbiIpOwo+ICsJCXJldHVybiBOVUxMOwo+ ICsJfQo+ICsKPiArCWNvbnRyb2xsZXIgPSBkbWFfY29udHJvbGxlcl9hbGxvYyhtdXNiLCBiYXNl KTsKPiArCWlmICghY29udHJvbGxlcikKPiArCQlyZXR1cm4gTlVMTDsKPiAgCj4gIAlpZiAocmVx dWVzdF9pcnEoaXJxLCBkbWFfY29udHJvbGxlcl9pcnEsIDAsCj4gIAkJCWRldl9uYW1lKG11c2It PmNvbnRyb2xsZXIpLCAmY29udHJvbGxlci0+Y29udHJvbGxlcikpIHsKPiBAQCAtNDM2LDMgKzQ0 NiwxNiBAQCBzdHJ1Y3QgZG1hX2NvbnRyb2xsZXIgKm11c2Joc19kbWFfY29udHJvbGxlcl9jcmVh dGUoc3RydWN0IG11c2IgKm11c2IsCj4gIAlyZXR1cm4gJmNvbnRyb2xsZXItPmNvbnRyb2xsZXI7 Cj4gIH0KPiAgRVhQT1JUX1NZTUJPTF9HUEwobXVzYmhzX2RtYV9jb250cm9sbGVyX2NyZWF0ZSk7 Cj4gKwo+ICtzdHJ1Y3QgZG1hX2NvbnRyb2xsZXIgKm11c2Joc19kbWFfY29udHJvbGxlcl9jcmVh dGVfbm9pcnEoc3RydWN0IG11c2IgKm11c2IsCj4gKwkJCQkJCSAgICB2b2lkIF9faW9tZW0gKmJh c2UpCj4gK3sKPiArCXN0cnVjdCBtdXNiX2RtYV9jb250cm9sbGVyICpjb250cm9sbGVyOwo+ICsK PiArCWNvbnRyb2xsZXIgPSBkbWFfY29udHJvbGxlcl9hbGxvYyhtdXNiLCBiYXNlKTsKPiArCWlm ICghY29udHJvbGxlcikKPiArCQlyZXR1cm4gTlVMTDsKPiArCj4gKwlyZXR1cm4gJmNvbnRyb2xs ZXItPmNvbnRyb2xsZXI7Cj4gK30KPiArRVhQT1JUX1NZTUJPTF9HUEwobXVzYmhzX2RtYV9jb250 cm9sbGVyX2NyZWF0ZV9ub2lycSk7CgpyZWdhcmRzLAotQmluLgo= 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=-9.3 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,URIBL_BLOCKED,USER_AGENT_MUTT autolearn=ham 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 33A94C43387 for ; Tue, 15 Jan 2019 20:38:36 +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 EEB0120656 for ; Tue, 15 Jan 2019 20:38:35 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="s+Dc0aaq"; dkim=fail reason="signature verification failed" (1024-bit key) header.d=ti.com header.i=@ti.com header.b="C5Su3ZOV" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org EEB0120656 Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=ti.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:In-Reply-To:MIME-Version:References: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=z0peWDqcsSFAJrPHLRSDrG+PMjE+QksvU7g7ePAhppE=; b=s+Dc0aaqSfWl9I v1WBzDOFv3UwGT3fPQ+X8CysqByBGgmG9uP4cT0av6wHp3dOQwn9BFmlp6yeivmRrkPghPaAOtJuj dR4nBOm9/KGUvRW9KHXEYvbbohJswa5FJEuI0I4yO06jW7+OFXCg7q9eW2jEGQmX+sIwfy9Xu6FQ/ JELlzoyLhMA8fz7roG+FBAB8Zc8dDs3doNbemSY7ZANIdc/K3JMbyL+fxM6cp+8G5i2MTyPYOgYiV bAsY1/l6fQC9ERKXxN5kytoGxXNJZ1+iL3DeeZPxUv7rxWgb0bn9b5HSu3T4RIle9iOKnhRqdtLVf MlKPGKsWW7lNkY9O6IYg==; 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 1gjVTj-0001uN-3x; Tue, 15 Jan 2019 20:38:31 +0000 Received: from lelv0143.ext.ti.com ([198.47.23.248]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gjVTd-0001t8-E6; Tue, 15 Jan 2019 20:38:28 +0000 Received: from fllv0034.itg.ti.com ([10.64.40.246]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id x0FKcGrL128867; Tue, 15 Jan 2019 14:38:16 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1547584696; bh=/pgd+Ll8xsTZnWJrMPDfx9mKFYkkMbjqzeko7eVi3u0=; h=Date:From:To:CC:Subject:References:In-Reply-To; b=C5Su3ZOVLI1qrwvPYnHaYdkAY5n80BF1EDlDnRiyAmsEDBu4NS1zdcqjF3XS6mrr/ GWyLQiBfNZLhnNLSC93HQSZ60SB0zxynBOcctd7O6ncR2+4aavPC3ZlSWGk2aacVN3 /mdmiYsWzdGfrEOUgU3YZQ5j75ov6QldL41Bsve4= Received: from DFLE104.ent.ti.com (dfle104.ent.ti.com [10.64.6.25]) by fllv0034.itg.ti.com (8.15.2/8.15.2) with ESMTPS id x0FKcGl2057464 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Tue, 15 Jan 2019 14:38:16 -0600 Received: from DFLE104.ent.ti.com (10.64.6.25) by DFLE104.ent.ti.com (10.64.6.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Tue, 15 Jan 2019 14:38:15 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DFLE104.ent.ti.com (10.64.6.25) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Tue, 15 Jan 2019 14:38:15 -0600 Received: from localhost (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id x0FKcF8r024607; Tue, 15 Jan 2019 14:38:15 -0600 Date: Tue, 15 Jan 2019 14:38:15 -0600 From: Bin Liu To: Subject: Re: [PATCH v2 4/4] usb: musb: Add support for MediaTek musb controller Message-ID: <20190115203815.GD18026@uda0271908> Mail-Followup-To: Bin Liu , min.guo@mediatek.com, 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 References: <1547516626-5084-1-git-send-email-min.guo@mediatek.com> <1547516626-5084-5-git-send-email-min.guo@mediatek.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <1547516626-5084-5-git-send-email-min.guo@mediatek.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190115_123825_625061_D1349CC0 X-CRM114-Status: GOOD ( 29.96 ) 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 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. 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? > +#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. > +{ > + 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: > +{ 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. > + > +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. > + 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. > + > 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. > + > +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. > + > + 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(); > + > + /* 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. > } > > 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; > 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; > > #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. > * @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(). > > /* > 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