Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Allwinner sun4i MUSB Glue Layer
0004  *
0005  * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
0006  *
0007  * Based on code from
0008  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
0009  */
0010 
0011 #include <linux/clk.h>
0012 #include <linux/err.h>
0013 #include <linux/extcon.h>
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/module.h>
0017 #include <linux/of.h>
0018 #include <linux/phy/phy-sun4i-usb.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/reset.h>
0021 #include <linux/soc/sunxi/sunxi_sram.h>
0022 #include <linux/usb/musb.h>
0023 #include <linux/usb/of.h>
0024 #include <linux/usb/usb_phy_generic.h>
0025 #include <linux/workqueue.h>
0026 #include "musb_core.h"
0027 
0028 /*
0029  * Register offsets, note sunxi musb has a different layout then most
0030  * musb implementations, we translate the layout in musb_readb & friends.
0031  */
0032 #define SUNXI_MUSB_POWER            0x0040
0033 #define SUNXI_MUSB_DEVCTL           0x0041
0034 #define SUNXI_MUSB_INDEX            0x0042
0035 #define SUNXI_MUSB_VEND0            0x0043
0036 #define SUNXI_MUSB_INTRTX           0x0044
0037 #define SUNXI_MUSB_INTRRX           0x0046
0038 #define SUNXI_MUSB_INTRTXE          0x0048
0039 #define SUNXI_MUSB_INTRRXE          0x004a
0040 #define SUNXI_MUSB_INTRUSB          0x004c
0041 #define SUNXI_MUSB_INTRUSBE         0x0050
0042 #define SUNXI_MUSB_FRAME            0x0054
0043 #define SUNXI_MUSB_TXFIFOSZ         0x0090
0044 #define SUNXI_MUSB_TXFIFOADD            0x0092
0045 #define SUNXI_MUSB_RXFIFOSZ         0x0094
0046 #define SUNXI_MUSB_RXFIFOADD            0x0096
0047 #define SUNXI_MUSB_FADDR            0x0098
0048 #define SUNXI_MUSB_TXFUNCADDR           0x0098
0049 #define SUNXI_MUSB_TXHUBADDR            0x009a
0050 #define SUNXI_MUSB_TXHUBPORT            0x009b
0051 #define SUNXI_MUSB_RXFUNCADDR           0x009c
0052 #define SUNXI_MUSB_RXHUBADDR            0x009e
0053 #define SUNXI_MUSB_RXHUBPORT            0x009f
0054 #define SUNXI_MUSB_CONFIGDATA           0x00c0
0055 
0056 /* VEND0 bits */
0057 #define SUNXI_MUSB_VEND0_PIO_MODE       0
0058 
0059 /* flags */
0060 #define SUNXI_MUSB_FL_ENABLED           0
0061 #define SUNXI_MUSB_FL_HOSTMODE          1
0062 #define SUNXI_MUSB_FL_HOSTMODE_PEND     2
0063 #define SUNXI_MUSB_FL_VBUS_ON           3
0064 #define SUNXI_MUSB_FL_PHY_ON            4
0065 #define SUNXI_MUSB_FL_HAS_SRAM          5
0066 #define SUNXI_MUSB_FL_HAS_RESET         6
0067 #define SUNXI_MUSB_FL_NO_CONFIGDATA     7
0068 #define SUNXI_MUSB_FL_PHY_MODE_PEND     8
0069 
0070 /* Our read/write methods need access and do not get passed in a musb ref :| */
0071 static struct musb *sunxi_musb;
0072 
0073 struct sunxi_glue {
0074     struct device       *dev;
0075     struct musb     *musb;
0076     struct platform_device  *musb_pdev;
0077     struct clk      *clk;
0078     struct reset_control    *rst;
0079     struct phy      *phy;
0080     struct platform_device  *usb_phy;
0081     struct usb_phy      *xceiv;
0082     enum phy_mode       phy_mode;
0083     unsigned long       flags;
0084     struct work_struct  work;
0085     struct extcon_dev   *extcon;
0086     struct notifier_block   host_nb;
0087 };
0088 
0089 /* phy_power_on / off may sleep, so we use a workqueue  */
0090 static void sunxi_musb_work(struct work_struct *work)
0091 {
0092     struct sunxi_glue *glue = container_of(work, struct sunxi_glue, work);
0093     bool vbus_on, phy_on;
0094 
0095     if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
0096         return;
0097 
0098     if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
0099         struct musb *musb = glue->musb;
0100         unsigned long flags;
0101         u8 devctl;
0102 
0103         spin_lock_irqsave(&musb->lock, flags);
0104 
0105         devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL);
0106         if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
0107             set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
0108             musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
0109             MUSB_HST_MODE(musb);
0110             devctl |= MUSB_DEVCTL_SESSION;
0111         } else {
0112             clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
0113             musb->xceiv->otg->state = OTG_STATE_B_IDLE;
0114             MUSB_DEV_MODE(musb);
0115             devctl &= ~MUSB_DEVCTL_SESSION;
0116         }
0117         writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL);
0118 
0119         spin_unlock_irqrestore(&musb->lock, flags);
0120     }
0121 
0122     vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
0123     phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
0124 
0125     if (phy_on != vbus_on) {
0126         if (vbus_on) {
0127             phy_power_on(glue->phy);
0128             set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
0129         } else {
0130             phy_power_off(glue->phy);
0131             clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
0132         }
0133     }
0134 
0135     if (test_and_clear_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags))
0136         phy_set_mode(glue->phy, glue->phy_mode);
0137 }
0138 
0139 static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
0140 {
0141     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0142 
0143     if (is_on) {
0144         set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
0145         musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
0146     } else {
0147         clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
0148     }
0149 
0150     schedule_work(&glue->work);
0151 }
0152 
0153 static void sunxi_musb_pre_root_reset_end(struct musb *musb)
0154 {
0155     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0156 
0157     sun4i_usb_phy_set_squelch_detect(glue->phy, false);
0158 }
0159 
0160 static void sunxi_musb_post_root_reset_end(struct musb *musb)
0161 {
0162     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0163 
0164     sun4i_usb_phy_set_squelch_detect(glue->phy, true);
0165 }
0166 
0167 static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
0168 {
0169     struct musb *musb = __hci;
0170     unsigned long flags;
0171 
0172     spin_lock_irqsave(&musb->lock, flags);
0173 
0174     musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB);
0175     if (musb->int_usb)
0176         writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB);
0177 
0178     if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) {
0179         /* ep0 FADDR must be 0 when (re)entering peripheral mode */
0180         musb_ep_select(musb->mregs, 0);
0181         musb_writeb(musb->mregs, MUSB_FADDR, 0);
0182     }
0183 
0184     musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX);
0185     if (musb->int_tx)
0186         writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX);
0187 
0188     musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX);
0189     if (musb->int_rx)
0190         writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX);
0191 
0192     musb_interrupt(musb);
0193 
0194     spin_unlock_irqrestore(&musb->lock, flags);
0195 
0196     return IRQ_HANDLED;
0197 }
0198 
0199 static int sunxi_musb_host_notifier(struct notifier_block *nb,
0200                     unsigned long event, void *ptr)
0201 {
0202     struct sunxi_glue *glue = container_of(nb, struct sunxi_glue, host_nb);
0203 
0204     if (event)
0205         set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
0206     else
0207         clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
0208 
0209     set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags);
0210     schedule_work(&glue->work);
0211 
0212     return NOTIFY_DONE;
0213 }
0214 
0215 static int sunxi_musb_init(struct musb *musb)
0216 {
0217     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0218     int ret;
0219 
0220     sunxi_musb = musb;
0221     musb->phy = glue->phy;
0222     musb->xceiv = glue->xceiv;
0223 
0224     if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
0225         ret = sunxi_sram_claim(musb->controller->parent);
0226         if (ret)
0227             return ret;
0228     }
0229 
0230     ret = clk_prepare_enable(glue->clk);
0231     if (ret)
0232         goto error_sram_release;
0233 
0234     if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
0235         ret = reset_control_deassert(glue->rst);
0236         if (ret)
0237             goto error_clk_disable;
0238     }
0239 
0240     writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
0241 
0242     /* Register notifier before calling phy_init() */
0243     ret = devm_extcon_register_notifier(glue->dev, glue->extcon,
0244                     EXTCON_USB_HOST, &glue->host_nb);
0245     if (ret)
0246         goto error_reset_assert;
0247 
0248     ret = phy_init(glue->phy);
0249     if (ret)
0250         goto error_reset_assert;
0251 
0252     musb->isr = sunxi_musb_interrupt;
0253 
0254     /* Stop the musb-core from doing runtime pm (not supported on sunxi) */
0255     pm_runtime_get(musb->controller);
0256 
0257     return 0;
0258 
0259 error_reset_assert:
0260     if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
0261         reset_control_assert(glue->rst);
0262 error_clk_disable:
0263     clk_disable_unprepare(glue->clk);
0264 error_sram_release:
0265     if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
0266         sunxi_sram_release(musb->controller->parent);
0267     return ret;
0268 }
0269 
0270 static int sunxi_musb_exit(struct musb *musb)
0271 {
0272     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0273 
0274     pm_runtime_put(musb->controller);
0275 
0276     cancel_work_sync(&glue->work);
0277     if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags))
0278         phy_power_off(glue->phy);
0279 
0280     phy_exit(glue->phy);
0281 
0282     if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
0283         reset_control_assert(glue->rst);
0284 
0285     clk_disable_unprepare(glue->clk);
0286     if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
0287         sunxi_sram_release(musb->controller->parent);
0288 
0289     devm_usb_put_phy(glue->dev, glue->xceiv);
0290 
0291     return 0;
0292 }
0293 
0294 static void sunxi_musb_enable(struct musb *musb)
0295 {
0296     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0297 
0298     glue->musb = musb;
0299 
0300     /* musb_core does not call us in a balanced manner */
0301     if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
0302         return;
0303 
0304     schedule_work(&glue->work);
0305 }
0306 
0307 static void sunxi_musb_disable(struct musb *musb)
0308 {
0309     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0310 
0311     clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
0312 }
0313 
0314 static struct dma_controller *
0315 sunxi_musb_dma_controller_create(struct musb *musb, void __iomem *base)
0316 {
0317     return NULL;
0318 }
0319 
0320 static void sunxi_musb_dma_controller_destroy(struct dma_controller *c)
0321 {
0322 }
0323 
0324 static int sunxi_musb_set_mode(struct musb *musb, u8 mode)
0325 {
0326     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0327     enum phy_mode new_mode;
0328 
0329     switch (mode) {
0330     case MUSB_HOST:
0331         new_mode = PHY_MODE_USB_HOST;
0332         break;
0333     case MUSB_PERIPHERAL:
0334         new_mode = PHY_MODE_USB_DEVICE;
0335         break;
0336     case MUSB_OTG:
0337         new_mode = PHY_MODE_USB_OTG;
0338         break;
0339     default:
0340         dev_err(musb->controller->parent,
0341             "Error requested mode not supported by this kernel\n");
0342         return -EINVAL;
0343     }
0344 
0345     if (glue->phy_mode == new_mode)
0346         return 0;
0347 
0348     if (musb->port_mode != MUSB_OTG) {
0349         dev_err(musb->controller->parent,
0350             "Error changing modes is only supported in dual role mode\n");
0351         return -EINVAL;
0352     }
0353 
0354     if (musb->port1_status & USB_PORT_STAT_ENABLE)
0355         musb_root_disconnect(musb);
0356 
0357     /*
0358      * phy_set_mode may sleep, and we're called with a spinlock held,
0359      * so let sunxi_musb_work deal with it.
0360      */
0361     glue->phy_mode = new_mode;
0362     set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
0363     schedule_work(&glue->work);
0364 
0365     return 0;
0366 }
0367 
0368 static int sunxi_musb_recover(struct musb *musb)
0369 {
0370     struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
0371 
0372     /*
0373      * Schedule a phy_set_mode with the current glue->phy_mode value,
0374      * this will force end the current session.
0375      */
0376     set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
0377     schedule_work(&glue->work);
0378 
0379     return 0;
0380 }
0381 
0382 /*
0383  * sunxi musb register layout
0384  * 0x00 - 0x17  fifo regs, 1 long per fifo
0385  * 0x40 - 0x57  generic control regs (power - frame)
0386  * 0x80 - 0x8f  ep control regs (addressed through hw_ep->regs, indexed)
0387  * 0x90 - 0x97  fifo control regs (indexed)
0388  * 0x98 - 0x9f  multipoint / busctl regs (indexed)
0389  * 0xc0     configdata reg
0390  */
0391 
0392 static u32 sunxi_musb_fifo_offset(u8 epnum)
0393 {
0394     return (epnum * 4);
0395 }
0396 
0397 static u32 sunxi_musb_ep_offset(u8 epnum, u16 offset)
0398 {
0399     WARN_ONCE(offset != 0,
0400           "sunxi_musb_ep_offset called with non 0 offset\n");
0401 
0402     return 0x80; /* indexed, so ignore epnum */
0403 }
0404 
0405 static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
0406 {
0407     return SUNXI_MUSB_TXFUNCADDR + offset;
0408 }
0409 
0410 static u8 sunxi_musb_readb(void __iomem *addr, u32 offset)
0411 {
0412     struct sunxi_glue *glue;
0413 
0414     if (addr == sunxi_musb->mregs) {
0415         /* generic control or fifo control reg access */
0416         switch (offset) {
0417         case MUSB_FADDR:
0418             return readb(addr + SUNXI_MUSB_FADDR);
0419         case MUSB_POWER:
0420             return readb(addr + SUNXI_MUSB_POWER);
0421         case MUSB_INTRUSB:
0422             return readb(addr + SUNXI_MUSB_INTRUSB);
0423         case MUSB_INTRUSBE:
0424             return readb(addr + SUNXI_MUSB_INTRUSBE);
0425         case MUSB_INDEX:
0426             return readb(addr + SUNXI_MUSB_INDEX);
0427         case MUSB_TESTMODE:
0428             return 0; /* No testmode on sunxi */
0429         case MUSB_DEVCTL:
0430             return readb(addr + SUNXI_MUSB_DEVCTL);
0431         case MUSB_TXFIFOSZ:
0432             return readb(addr + SUNXI_MUSB_TXFIFOSZ);
0433         case MUSB_RXFIFOSZ:
0434             return readb(addr + SUNXI_MUSB_RXFIFOSZ);
0435         case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */
0436             glue = dev_get_drvdata(sunxi_musb->controller->parent);
0437             /* A33 saves a reg, and we get to hardcode this */
0438             if (test_bit(SUNXI_MUSB_FL_NO_CONFIGDATA,
0439                      &glue->flags))
0440                 return 0xde;
0441 
0442             return readb(addr + SUNXI_MUSB_CONFIGDATA);
0443         case MUSB_ULPI_BUSCONTROL:
0444             dev_warn(sunxi_musb->controller->parent,
0445                 "sunxi-musb does not have ULPI bus control register\n");
0446             return 0;
0447         /* Offset for these is fixed by sunxi_musb_busctl_offset() */
0448         case SUNXI_MUSB_TXFUNCADDR:
0449         case SUNXI_MUSB_TXHUBADDR:
0450         case SUNXI_MUSB_TXHUBPORT:
0451         case SUNXI_MUSB_RXFUNCADDR:
0452         case SUNXI_MUSB_RXHUBADDR:
0453         case SUNXI_MUSB_RXHUBPORT:
0454             /* multipoint / busctl reg access */
0455             return readb(addr + offset);
0456         default:
0457             dev_err(sunxi_musb->controller->parent,
0458                 "Error unknown readb offset %u\n", offset);
0459             return 0;
0460         }
0461     } else if (addr == (sunxi_musb->mregs + 0x80)) {
0462         /* ep control reg access */
0463         /* sunxi has a 2 byte hole before the txtype register */
0464         if (offset >= MUSB_TXTYPE)
0465             offset += 2;
0466         return readb(addr + offset);
0467     }
0468 
0469     dev_err(sunxi_musb->controller->parent,
0470         "Error unknown readb at 0x%x bytes offset\n",
0471         (int)(addr - sunxi_musb->mregs));
0472     return 0;
0473 }
0474 
0475 static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data)
0476 {
0477     if (addr == sunxi_musb->mregs) {
0478         /* generic control or fifo control reg access */
0479         switch (offset) {
0480         case MUSB_FADDR:
0481             return writeb(data, addr + SUNXI_MUSB_FADDR);
0482         case MUSB_POWER:
0483             return writeb(data, addr + SUNXI_MUSB_POWER);
0484         case MUSB_INTRUSB:
0485             return writeb(data, addr + SUNXI_MUSB_INTRUSB);
0486         case MUSB_INTRUSBE:
0487             return writeb(data, addr + SUNXI_MUSB_INTRUSBE);
0488         case MUSB_INDEX:
0489             return writeb(data, addr + SUNXI_MUSB_INDEX);
0490         case MUSB_TESTMODE:
0491             if (data)
0492                 dev_warn(sunxi_musb->controller->parent,
0493                     "sunxi-musb does not have testmode\n");
0494             return;
0495         case MUSB_DEVCTL:
0496             return writeb(data, addr + SUNXI_MUSB_DEVCTL);
0497         case MUSB_TXFIFOSZ:
0498             return writeb(data, addr + SUNXI_MUSB_TXFIFOSZ);
0499         case MUSB_RXFIFOSZ:
0500             return writeb(data, addr + SUNXI_MUSB_RXFIFOSZ);
0501         case MUSB_ULPI_BUSCONTROL:
0502             dev_warn(sunxi_musb->controller->parent,
0503                 "sunxi-musb does not have ULPI bus control register\n");
0504             return;
0505         /* Offset for these is fixed by sunxi_musb_busctl_offset() */
0506         case SUNXI_MUSB_TXFUNCADDR:
0507         case SUNXI_MUSB_TXHUBADDR:
0508         case SUNXI_MUSB_TXHUBPORT:
0509         case SUNXI_MUSB_RXFUNCADDR:
0510         case SUNXI_MUSB_RXHUBADDR:
0511         case SUNXI_MUSB_RXHUBPORT:
0512             /* multipoint / busctl reg access */
0513             return writeb(data, addr + offset);
0514         default:
0515             dev_err(sunxi_musb->controller->parent,
0516                 "Error unknown writeb offset %u\n", offset);
0517             return;
0518         }
0519     } else if (addr == (sunxi_musb->mregs + 0x80)) {
0520         /* ep control reg access */
0521         if (offset >= MUSB_TXTYPE)
0522             offset += 2;
0523         return writeb(data, addr + offset);
0524     }
0525 
0526     dev_err(sunxi_musb->controller->parent,
0527         "Error unknown writeb at 0x%x bytes offset\n",
0528         (int)(addr - sunxi_musb->mregs));
0529 }
0530 
0531 static u16 sunxi_musb_readw(void __iomem *addr, u32 offset)
0532 {
0533     if (addr == sunxi_musb->mregs) {
0534         /* generic control or fifo control reg access */
0535         switch (offset) {
0536         case MUSB_INTRTX:
0537             return readw(addr + SUNXI_MUSB_INTRTX);
0538         case MUSB_INTRRX:
0539             return readw(addr + SUNXI_MUSB_INTRRX);
0540         case MUSB_INTRTXE:
0541             return readw(addr + SUNXI_MUSB_INTRTXE);
0542         case MUSB_INTRRXE:
0543             return readw(addr + SUNXI_MUSB_INTRRXE);
0544         case MUSB_FRAME:
0545             return readw(addr + SUNXI_MUSB_FRAME);
0546         case MUSB_TXFIFOADD:
0547             return readw(addr + SUNXI_MUSB_TXFIFOADD);
0548         case MUSB_RXFIFOADD:
0549             return readw(addr + SUNXI_MUSB_RXFIFOADD);
0550         case MUSB_HWVERS:
0551             return 0; /* sunxi musb version is not known */
0552         default:
0553             dev_err(sunxi_musb->controller->parent,
0554                 "Error unknown readw offset %u\n", offset);
0555             return 0;
0556         }
0557     } else if (addr == (sunxi_musb->mregs + 0x80)) {
0558         /* ep control reg access */
0559         return readw(addr + offset);
0560     }
0561 
0562     dev_err(sunxi_musb->controller->parent,
0563         "Error unknown readw at 0x%x bytes offset\n",
0564         (int)(addr - sunxi_musb->mregs));
0565     return 0;
0566 }
0567 
0568 static void sunxi_musb_writew(void __iomem *addr, unsigned offset, u16 data)
0569 {
0570     if (addr == sunxi_musb->mregs) {
0571         /* generic control or fifo control reg access */
0572         switch (offset) {
0573         case MUSB_INTRTX:
0574             return writew(data, addr + SUNXI_MUSB_INTRTX);
0575         case MUSB_INTRRX:
0576             return writew(data, addr + SUNXI_MUSB_INTRRX);
0577         case MUSB_INTRTXE:
0578             return writew(data, addr + SUNXI_MUSB_INTRTXE);
0579         case MUSB_INTRRXE:
0580             return writew(data, addr + SUNXI_MUSB_INTRRXE);
0581         case MUSB_FRAME:
0582             return writew(data, addr + SUNXI_MUSB_FRAME);
0583         case MUSB_TXFIFOADD:
0584             return writew(data, addr + SUNXI_MUSB_TXFIFOADD);
0585         case MUSB_RXFIFOADD:
0586             return writew(data, addr + SUNXI_MUSB_RXFIFOADD);
0587         default:
0588             dev_err(sunxi_musb->controller->parent,
0589                 "Error unknown writew offset %u\n", offset);
0590             return;
0591         }
0592     } else if (addr == (sunxi_musb->mregs + 0x80)) {
0593         /* ep control reg access */
0594         return writew(data, addr + offset);
0595     }
0596 
0597     dev_err(sunxi_musb->controller->parent,
0598         "Error unknown writew at 0x%x bytes offset\n",
0599         (int)(addr - sunxi_musb->mregs));
0600 }
0601 
0602 static const struct musb_platform_ops sunxi_musb_ops = {
0603     .quirks     = MUSB_INDEXED_EP,
0604     .init       = sunxi_musb_init,
0605     .exit       = sunxi_musb_exit,
0606     .enable     = sunxi_musb_enable,
0607     .disable    = sunxi_musb_disable,
0608     .fifo_offset    = sunxi_musb_fifo_offset,
0609     .ep_offset  = sunxi_musb_ep_offset,
0610     .busctl_offset  = sunxi_musb_busctl_offset,
0611     .readb      = sunxi_musb_readb,
0612     .writeb     = sunxi_musb_writeb,
0613     .readw      = sunxi_musb_readw,
0614     .writew     = sunxi_musb_writew,
0615     .dma_init   = sunxi_musb_dma_controller_create,
0616     .dma_exit   = sunxi_musb_dma_controller_destroy,
0617     .set_mode   = sunxi_musb_set_mode,
0618     .recover    = sunxi_musb_recover,
0619     .set_vbus   = sunxi_musb_set_vbus,
0620     .pre_root_reset_end = sunxi_musb_pre_root_reset_end,
0621     .post_root_reset_end = sunxi_musb_post_root_reset_end,
0622 };
0623 
0624 /* Allwinner OTG supports up to 5 endpoints */
0625 #define SUNXI_MUSB_MAX_EP_NUM   6
0626 #define SUNXI_MUSB_RAM_BITS 11
0627 
0628 static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
0629     MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
0630     MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
0631     MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
0632     MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
0633     MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
0634     MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
0635     MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
0636     MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
0637     MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
0638     MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
0639 };
0640 
0641 /* H3/V3s OTG supports only 4 endpoints */
0642 #define SUNXI_MUSB_MAX_EP_NUM_H3    5
0643 
0644 static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = {
0645     MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
0646     MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
0647     MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
0648     MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
0649     MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
0650     MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
0651     MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
0652     MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
0653 };
0654 
0655 static const struct musb_hdrc_config sunxi_musb_hdrc_config = {
0656     .fifo_cfg       = sunxi_musb_mode_cfg,
0657     .fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg),
0658     .multipoint = true,
0659     .dyn_fifo   = true,
0660     .num_eps    = SUNXI_MUSB_MAX_EP_NUM,
0661     .ram_bits   = SUNXI_MUSB_RAM_BITS,
0662 };
0663 
0664 static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = {
0665     .fifo_cfg       = sunxi_musb_mode_cfg_h3,
0666     .fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg_h3),
0667     .multipoint = true,
0668     .dyn_fifo   = true,
0669     .num_eps    = SUNXI_MUSB_MAX_EP_NUM_H3,
0670     .ram_bits   = SUNXI_MUSB_RAM_BITS,
0671 };
0672 
0673 
0674 static int sunxi_musb_probe(struct platform_device *pdev)
0675 {
0676     struct musb_hdrc_platform_data  pdata;
0677     struct platform_device_info pinfo;
0678     struct sunxi_glue       *glue;
0679     struct device_node      *np = pdev->dev.of_node;
0680     int ret;
0681 
0682     if (!np) {
0683         dev_err(&pdev->dev, "Error no device tree node found\n");
0684         return -EINVAL;
0685     }
0686 
0687     glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
0688     if (!glue)
0689         return -ENOMEM;
0690 
0691     memset(&pdata, 0, sizeof(pdata));
0692     switch (usb_get_dr_mode(&pdev->dev)) {
0693 #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
0694     case USB_DR_MODE_HOST:
0695         pdata.mode = MUSB_HOST;
0696         glue->phy_mode = PHY_MODE_USB_HOST;
0697         break;
0698 #endif
0699 #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET
0700     case USB_DR_MODE_PERIPHERAL:
0701         pdata.mode = MUSB_PERIPHERAL;
0702         glue->phy_mode = PHY_MODE_USB_DEVICE;
0703         break;
0704 #endif
0705 #ifdef CONFIG_USB_MUSB_DUAL_ROLE
0706     case USB_DR_MODE_OTG:
0707         pdata.mode = MUSB_OTG;
0708         glue->phy_mode = PHY_MODE_USB_OTG;
0709         break;
0710 #endif
0711     default:
0712         dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n");
0713         return -EINVAL;
0714     }
0715     pdata.platform_ops  = &sunxi_musb_ops;
0716     if (!of_device_is_compatible(np, "allwinner,sun8i-h3-musb"))
0717         pdata.config = &sunxi_musb_hdrc_config;
0718     else
0719         pdata.config = &sunxi_musb_hdrc_config_h3;
0720 
0721     glue->dev = &pdev->dev;
0722     INIT_WORK(&glue->work, sunxi_musb_work);
0723     glue->host_nb.notifier_call = sunxi_musb_host_notifier;
0724 
0725     if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
0726         set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
0727 
0728     if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
0729         set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
0730 
0731     if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") ||
0732         of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) {
0733         set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
0734         set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
0735     }
0736 
0737     glue->clk = devm_clk_get(&pdev->dev, NULL);
0738     if (IS_ERR(glue->clk)) {
0739         dev_err(&pdev->dev, "Error getting clock: %ld\n",
0740             PTR_ERR(glue->clk));
0741         return PTR_ERR(glue->clk);
0742     }
0743 
0744     if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
0745         glue->rst = devm_reset_control_get(&pdev->dev, NULL);
0746         if (IS_ERR(glue->rst)) {
0747             if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
0748                 return -EPROBE_DEFER;
0749             dev_err(&pdev->dev, "Error getting reset %ld\n",
0750                 PTR_ERR(glue->rst));
0751             return PTR_ERR(glue->rst);
0752         }
0753     }
0754 
0755     glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
0756     if (IS_ERR(glue->extcon)) {
0757         if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
0758             return -EPROBE_DEFER;
0759         dev_err(&pdev->dev, "Invalid or missing extcon\n");
0760         return PTR_ERR(glue->extcon);
0761     }
0762 
0763     glue->phy = devm_phy_get(&pdev->dev, "usb");
0764     if (IS_ERR(glue->phy)) {
0765         if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
0766             return -EPROBE_DEFER;
0767         dev_err(&pdev->dev, "Error getting phy %ld\n",
0768             PTR_ERR(glue->phy));
0769         return PTR_ERR(glue->phy);
0770     }
0771 
0772     glue->usb_phy = usb_phy_generic_register();
0773     if (IS_ERR(glue->usb_phy)) {
0774         dev_err(&pdev->dev, "Error registering usb-phy %ld\n",
0775             PTR_ERR(glue->usb_phy));
0776         return PTR_ERR(glue->usb_phy);
0777     }
0778 
0779     glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
0780     if (IS_ERR(glue->xceiv)) {
0781         ret = PTR_ERR(glue->xceiv);
0782         dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret);
0783         goto err_unregister_usb_phy;
0784     }
0785 
0786     platform_set_drvdata(pdev, glue);
0787 
0788     memset(&pinfo, 0, sizeof(pinfo));
0789     pinfo.name   = "musb-hdrc";
0790     pinfo.id    = PLATFORM_DEVID_AUTO;
0791     pinfo.parent    = &pdev->dev;
0792     pinfo.fwnode    = of_fwnode_handle(pdev->dev.of_node);
0793     pinfo.of_node_reused = true;
0794     pinfo.res   = pdev->resource;
0795     pinfo.num_res   = pdev->num_resources;
0796     pinfo.data  = &pdata;
0797     pinfo.size_data = sizeof(pdata);
0798 
0799     glue->musb_pdev = platform_device_register_full(&pinfo);
0800     if (IS_ERR(glue->musb_pdev)) {
0801         ret = PTR_ERR(glue->musb_pdev);
0802         dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
0803         goto err_unregister_usb_phy;
0804     }
0805 
0806     return 0;
0807 
0808 err_unregister_usb_phy:
0809     usb_phy_generic_unregister(glue->usb_phy);
0810     return ret;
0811 }
0812 
0813 static int sunxi_musb_remove(struct platform_device *pdev)
0814 {
0815     struct sunxi_glue *glue = platform_get_drvdata(pdev);
0816     struct platform_device *usb_phy = glue->usb_phy;
0817 
0818     platform_device_unregister(glue->musb_pdev);
0819     usb_phy_generic_unregister(usb_phy);
0820 
0821     return 0;
0822 }
0823 
0824 static const struct of_device_id sunxi_musb_match[] = {
0825     { .compatible = "allwinner,sun4i-a10-musb", },
0826     { .compatible = "allwinner,sun6i-a31-musb", },
0827     { .compatible = "allwinner,sun8i-a33-musb", },
0828     { .compatible = "allwinner,sun8i-h3-musb", },
0829     {}
0830 };
0831 MODULE_DEVICE_TABLE(of, sunxi_musb_match);
0832 
0833 static struct platform_driver sunxi_musb_driver = {
0834     .probe = sunxi_musb_probe,
0835     .remove = sunxi_musb_remove,
0836     .driver = {
0837         .name = "musb-sunxi",
0838         .of_match_table = sunxi_musb_match,
0839     },
0840 };
0841 module_platform_driver(sunxi_musb_driver);
0842 
0843 MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer");
0844 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
0845 MODULE_LICENSE("GPL v2");