root/drivers/usb/musb/sunxi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sunxi_musb_work
  2. sunxi_musb_set_vbus
  3. sunxi_musb_pre_root_reset_end
  4. sunxi_musb_post_root_reset_end
  5. sunxi_musb_interrupt
  6. sunxi_musb_host_notifier
  7. sunxi_musb_init
  8. sunxi_musb_exit
  9. sunxi_musb_enable
  10. sunxi_musb_disable
  11. sunxi_musb_dma_controller_create
  12. sunxi_musb_dma_controller_destroy
  13. sunxi_musb_set_mode
  14. sunxi_musb_recover
  15. sunxi_musb_fifo_offset
  16. sunxi_musb_ep_offset
  17. sunxi_musb_busctl_offset
  18. sunxi_musb_readb
  19. sunxi_musb_writeb
  20. sunxi_musb_readw
  21. sunxi_musb_writew
  22. sunxi_musb_probe
  23. sunxi_musb_remove

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Allwinner sun4i MUSB Glue Layer
   4  *
   5  * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
   6  *
   7  * Based on code from
   8  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
   9  */
  10 
  11 #include <linux/clk.h>
  12 #include <linux/err.h>
  13 #include <linux/extcon.h>
  14 #include <linux/io.h>
  15 #include <linux/kernel.h>
  16 #include <linux/module.h>
  17 #include <linux/of.h>
  18 #include <linux/phy/phy-sun4i-usb.h>
  19 #include <linux/platform_device.h>
  20 #include <linux/reset.h>
  21 #include <linux/soc/sunxi/sunxi_sram.h>
  22 #include <linux/usb/musb.h>
  23 #include <linux/usb/of.h>
  24 #include <linux/usb/usb_phy_generic.h>
  25 #include <linux/workqueue.h>
  26 #include "musb_core.h"
  27 
  28 /*
  29  * Register offsets, note sunxi musb has a different layout then most
  30  * musb implementations, we translate the layout in musb_readb & friends.
  31  */
  32 #define SUNXI_MUSB_POWER                        0x0040
  33 #define SUNXI_MUSB_DEVCTL                       0x0041
  34 #define SUNXI_MUSB_INDEX                        0x0042
  35 #define SUNXI_MUSB_VEND0                        0x0043
  36 #define SUNXI_MUSB_INTRTX                       0x0044
  37 #define SUNXI_MUSB_INTRRX                       0x0046
  38 #define SUNXI_MUSB_INTRTXE                      0x0048
  39 #define SUNXI_MUSB_INTRRXE                      0x004a
  40 #define SUNXI_MUSB_INTRUSB                      0x004c
  41 #define SUNXI_MUSB_INTRUSBE                     0x0050
  42 #define SUNXI_MUSB_FRAME                        0x0054
  43 #define SUNXI_MUSB_TXFIFOSZ                     0x0090
  44 #define SUNXI_MUSB_TXFIFOADD                    0x0092
  45 #define SUNXI_MUSB_RXFIFOSZ                     0x0094
  46 #define SUNXI_MUSB_RXFIFOADD                    0x0096
  47 #define SUNXI_MUSB_FADDR                        0x0098
  48 #define SUNXI_MUSB_TXFUNCADDR                   0x0098
  49 #define SUNXI_MUSB_TXHUBADDR                    0x009a
  50 #define SUNXI_MUSB_TXHUBPORT                    0x009b
  51 #define SUNXI_MUSB_RXFUNCADDR                   0x009c
  52 #define SUNXI_MUSB_RXHUBADDR                    0x009e
  53 #define SUNXI_MUSB_RXHUBPORT                    0x009f
  54 #define SUNXI_MUSB_CONFIGDATA                   0x00c0
  55 
  56 /* VEND0 bits */
  57 #define SUNXI_MUSB_VEND0_PIO_MODE               0
  58 
  59 /* flags */
  60 #define SUNXI_MUSB_FL_ENABLED                   0
  61 #define SUNXI_MUSB_FL_HOSTMODE                  1
  62 #define SUNXI_MUSB_FL_HOSTMODE_PEND             2
  63 #define SUNXI_MUSB_FL_VBUS_ON                   3
  64 #define SUNXI_MUSB_FL_PHY_ON                    4
  65 #define SUNXI_MUSB_FL_HAS_SRAM                  5
  66 #define SUNXI_MUSB_FL_HAS_RESET                 6
  67 #define SUNXI_MUSB_FL_NO_CONFIGDATA             7
  68 #define SUNXI_MUSB_FL_PHY_MODE_PEND             8
  69 
  70 /* Our read/write methods need access and do not get passed in a musb ref :| */
  71 static struct musb *sunxi_musb;
  72 
  73 struct sunxi_glue {
  74         struct device           *dev;
  75         struct musb             *musb;
  76         struct platform_device  *musb_pdev;
  77         struct clk              *clk;
  78         struct reset_control    *rst;
  79         struct phy              *phy;
  80         struct platform_device  *usb_phy;
  81         struct usb_phy          *xceiv;
  82         enum phy_mode           phy_mode;
  83         unsigned long           flags;
  84         struct work_struct      work;
  85         struct extcon_dev       *extcon;
  86         struct notifier_block   host_nb;
  87 };
  88 
  89 /* phy_power_on / off may sleep, so we use a workqueue  */
  90 static void sunxi_musb_work(struct work_struct *work)
  91 {
  92         struct sunxi_glue *glue = container_of(work, struct sunxi_glue, work);
  93         bool vbus_on, phy_on;
  94 
  95         if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
  96                 return;
  97 
  98         if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
  99                 struct musb *musb = glue->musb;
 100                 unsigned long flags;
 101                 u8 devctl;
 102 
 103                 spin_lock_irqsave(&musb->lock, flags);
 104 
 105                 devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL);
 106                 if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
 107                         set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 108                         musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 109                         MUSB_HST_MODE(musb);
 110                         devctl |= MUSB_DEVCTL_SESSION;
 111                 } else {
 112                         clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 113                         musb->xceiv->otg->state = OTG_STATE_B_IDLE;
 114                         MUSB_DEV_MODE(musb);
 115                         devctl &= ~MUSB_DEVCTL_SESSION;
 116                 }
 117                 writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL);
 118 
 119                 spin_unlock_irqrestore(&musb->lock, flags);
 120         }
 121 
 122         vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 123         phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 124 
 125         if (phy_on != vbus_on) {
 126                 if (vbus_on) {
 127                         phy_power_on(glue->phy);
 128                         set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 129                 } else {
 130                         phy_power_off(glue->phy);
 131                         clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 132                 }
 133         }
 134 
 135         if (test_and_clear_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags))
 136                 phy_set_mode(glue->phy, glue->phy_mode);
 137 }
 138 
 139 static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
 140 {
 141         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 142 
 143         if (is_on) {
 144                 set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 145                 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 146         } else {
 147                 clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 148         }
 149 
 150         schedule_work(&glue->work);
 151 }
 152 
 153 static void sunxi_musb_pre_root_reset_end(struct musb *musb)
 154 {
 155         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 156 
 157         sun4i_usb_phy_set_squelch_detect(glue->phy, false);
 158 }
 159 
 160 static void sunxi_musb_post_root_reset_end(struct musb *musb)
 161 {
 162         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 163 
 164         sun4i_usb_phy_set_squelch_detect(glue->phy, true);
 165 }
 166 
 167 static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
 168 {
 169         struct musb *musb = __hci;
 170         unsigned long flags;
 171 
 172         spin_lock_irqsave(&musb->lock, flags);
 173 
 174         musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB);
 175         if (musb->int_usb)
 176                 writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB);
 177 
 178         if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) {
 179                 /* ep0 FADDR must be 0 when (re)entering peripheral mode */
 180                 musb_ep_select(musb->mregs, 0);
 181                 musb_writeb(musb->mregs, MUSB_FADDR, 0);
 182         }
 183 
 184         musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX);
 185         if (musb->int_tx)
 186                 writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX);
 187 
 188         musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX);
 189         if (musb->int_rx)
 190                 writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX);
 191 
 192         musb_interrupt(musb);
 193 
 194         spin_unlock_irqrestore(&musb->lock, flags);
 195 
 196         return IRQ_HANDLED;
 197 }
 198 
 199 static int sunxi_musb_host_notifier(struct notifier_block *nb,
 200                                     unsigned long event, void *ptr)
 201 {
 202         struct sunxi_glue *glue = container_of(nb, struct sunxi_glue, host_nb);
 203 
 204         if (event)
 205                 set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
 206         else
 207                 clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
 208 
 209         set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags);
 210         schedule_work(&glue->work);
 211 
 212         return NOTIFY_DONE;
 213 }
 214 
 215 static int sunxi_musb_init(struct musb *musb)
 216 {
 217         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 218         int ret;
 219 
 220         sunxi_musb = musb;
 221         musb->phy = glue->phy;
 222         musb->xceiv = glue->xceiv;
 223 
 224         if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
 225                 ret = sunxi_sram_claim(musb->controller->parent);
 226                 if (ret)
 227                         return ret;
 228         }
 229 
 230         ret = clk_prepare_enable(glue->clk);
 231         if (ret)
 232                 goto error_sram_release;
 233 
 234         if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
 235                 ret = reset_control_deassert(glue->rst);
 236                 if (ret)
 237                         goto error_clk_disable;
 238         }
 239 
 240         writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
 241 
 242         /* Register notifier before calling phy_init() */
 243         ret = devm_extcon_register_notifier(glue->dev, glue->extcon,
 244                                         EXTCON_USB_HOST, &glue->host_nb);
 245         if (ret)
 246                 goto error_reset_assert;
 247 
 248         ret = phy_init(glue->phy);
 249         if (ret)
 250                 goto error_reset_assert;
 251 
 252         musb->isr = sunxi_musb_interrupt;
 253 
 254         /* Stop the musb-core from doing runtime pm (not supported on sunxi) */
 255         pm_runtime_get(musb->controller);
 256 
 257         return 0;
 258 
 259 error_reset_assert:
 260         if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 261                 reset_control_assert(glue->rst);
 262 error_clk_disable:
 263         clk_disable_unprepare(glue->clk);
 264 error_sram_release:
 265         if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
 266                 sunxi_sram_release(musb->controller->parent);
 267         return ret;
 268 }
 269 
 270 static int sunxi_musb_exit(struct musb *musb)
 271 {
 272         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 273 
 274         pm_runtime_put(musb->controller);
 275 
 276         cancel_work_sync(&glue->work);
 277         if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags))
 278                 phy_power_off(glue->phy);
 279 
 280         phy_exit(glue->phy);
 281 
 282         if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 283                 reset_control_assert(glue->rst);
 284 
 285         clk_disable_unprepare(glue->clk);
 286         if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
 287                 sunxi_sram_release(musb->controller->parent);
 288 
 289         devm_usb_put_phy(glue->dev, glue->xceiv);
 290 
 291         return 0;
 292 }
 293 
 294 static void sunxi_musb_enable(struct musb *musb)
 295 {
 296         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 297 
 298         glue->musb = musb;
 299 
 300         /* musb_core does not call us in a balanced manner */
 301         if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
 302                 return;
 303 
 304         schedule_work(&glue->work);
 305 }
 306 
 307 static void sunxi_musb_disable(struct musb *musb)
 308 {
 309         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 310 
 311         clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
 312 }
 313 
 314 static struct dma_controller *
 315 sunxi_musb_dma_controller_create(struct musb *musb, void __iomem *base)
 316 {
 317         return NULL;
 318 }
 319 
 320 static void sunxi_musb_dma_controller_destroy(struct dma_controller *c)
 321 {
 322 }
 323 
 324 static int sunxi_musb_set_mode(struct musb *musb, u8 mode)
 325 {
 326         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 327         enum phy_mode new_mode;
 328 
 329         switch (mode) {
 330         case MUSB_HOST:
 331                 new_mode = PHY_MODE_USB_HOST;
 332                 break;
 333         case MUSB_PERIPHERAL:
 334                 new_mode = PHY_MODE_USB_DEVICE;
 335                 break;
 336         case MUSB_OTG:
 337                 new_mode = PHY_MODE_USB_OTG;
 338                 break;
 339         default:
 340                 dev_err(musb->controller->parent,
 341                         "Error requested mode not supported by this kernel\n");
 342                 return -EINVAL;
 343         }
 344 
 345         if (glue->phy_mode == new_mode)
 346                 return 0;
 347 
 348         if (musb->port_mode != MUSB_OTG) {
 349                 dev_err(musb->controller->parent,
 350                         "Error changing modes is only supported in dual role mode\n");
 351                 return -EINVAL;
 352         }
 353 
 354         if (musb->port1_status & USB_PORT_STAT_ENABLE)
 355                 musb_root_disconnect(musb);
 356 
 357         /*
 358          * phy_set_mode may sleep, and we're called with a spinlock held,
 359          * so let sunxi_musb_work deal with it.
 360          */
 361         glue->phy_mode = new_mode;
 362         set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
 363         schedule_work(&glue->work);
 364 
 365         return 0;
 366 }
 367 
 368 static int sunxi_musb_recover(struct musb *musb)
 369 {
 370         struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 371 
 372         /*
 373          * Schedule a phy_set_mode with the current glue->phy_mode value,
 374          * this will force end the current session.
 375          */
 376         set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
 377         schedule_work(&glue->work);
 378 
 379         return 0;
 380 }
 381 
 382 /*
 383  * sunxi musb register layout
 384  * 0x00 - 0x17  fifo regs, 1 long per fifo
 385  * 0x40 - 0x57  generic control regs (power - frame)
 386  * 0x80 - 0x8f  ep control regs (addressed through hw_ep->regs, indexed)
 387  * 0x90 - 0x97  fifo control regs (indexed)
 388  * 0x98 - 0x9f  multipoint / busctl regs (indexed)
 389  * 0xc0         configdata reg
 390  */
 391 
 392 static u32 sunxi_musb_fifo_offset(u8 epnum)
 393 {
 394         return (epnum * 4);
 395 }
 396 
 397 static u32 sunxi_musb_ep_offset(u8 epnum, u16 offset)
 398 {
 399         WARN_ONCE(offset != 0,
 400                   "sunxi_musb_ep_offset called with non 0 offset\n");
 401 
 402         return 0x80; /* indexed, so ignore epnum */
 403 }
 404 
 405 static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
 406 {
 407         return SUNXI_MUSB_TXFUNCADDR + offset;
 408 }
 409 
 410 static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset)
 411 {
 412         struct sunxi_glue *glue;
 413 
 414         if (addr == sunxi_musb->mregs) {
 415                 /* generic control or fifo control reg access */
 416                 switch (offset) {
 417                 case MUSB_FADDR:
 418                         return readb(addr + SUNXI_MUSB_FADDR);
 419                 case MUSB_POWER:
 420                         return readb(addr + SUNXI_MUSB_POWER);
 421                 case MUSB_INTRUSB:
 422                         return readb(addr + SUNXI_MUSB_INTRUSB);
 423                 case MUSB_INTRUSBE:
 424                         return readb(addr + SUNXI_MUSB_INTRUSBE);
 425                 case MUSB_INDEX:
 426                         return readb(addr + SUNXI_MUSB_INDEX);
 427                 case MUSB_TESTMODE:
 428                         return 0; /* No testmode on sunxi */
 429                 case MUSB_DEVCTL:
 430                         return readb(addr + SUNXI_MUSB_DEVCTL);
 431                 case MUSB_TXFIFOSZ:
 432                         return readb(addr + SUNXI_MUSB_TXFIFOSZ);
 433                 case MUSB_RXFIFOSZ:
 434                         return readb(addr + SUNXI_MUSB_RXFIFOSZ);
 435                 case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */
 436                         glue = dev_get_drvdata(sunxi_musb->controller->parent);
 437                         /* A33 saves a reg, and we get to hardcode this */
 438                         if (test_bit(SUNXI_MUSB_FL_NO_CONFIGDATA,
 439                                      &glue->flags))
 440                                 return 0xde;
 441 
 442                         return readb(addr + SUNXI_MUSB_CONFIGDATA);
 443                 /* Offset for these is fixed by sunxi_musb_busctl_offset() */
 444                 case SUNXI_MUSB_TXFUNCADDR:
 445                 case SUNXI_MUSB_TXHUBADDR:
 446                 case SUNXI_MUSB_TXHUBPORT:
 447                 case SUNXI_MUSB_RXFUNCADDR:
 448                 case SUNXI_MUSB_RXHUBADDR:
 449                 case SUNXI_MUSB_RXHUBPORT:
 450                         /* multipoint / busctl reg access */
 451                         return readb(addr + offset);
 452                 default:
 453                         dev_err(sunxi_musb->controller->parent,
 454                                 "Error unknown readb offset %u\n", offset);
 455                         return 0;
 456                 }
 457         } else if (addr == (sunxi_musb->mregs + 0x80)) {
 458                 /* ep control reg access */
 459                 /* sunxi has a 2 byte hole before the txtype register */
 460                 if (offset >= MUSB_TXTYPE)
 461                         offset += 2;
 462                 return readb(addr + offset);
 463         }
 464 
 465         dev_err(sunxi_musb->controller->parent,
 466                 "Error unknown readb at 0x%x bytes offset\n",
 467                 (int)(addr - sunxi_musb->mregs));
 468         return 0;
 469 }
 470 
 471 static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data)
 472 {
 473         if (addr == sunxi_musb->mregs) {
 474                 /* generic control or fifo control reg access */
 475                 switch (offset) {
 476                 case MUSB_FADDR:
 477                         return writeb(data, addr + SUNXI_MUSB_FADDR);
 478                 case MUSB_POWER:
 479                         return writeb(data, addr + SUNXI_MUSB_POWER);
 480                 case MUSB_INTRUSB:
 481                         return writeb(data, addr + SUNXI_MUSB_INTRUSB);
 482                 case MUSB_INTRUSBE:
 483                         return writeb(data, addr + SUNXI_MUSB_INTRUSBE);
 484                 case MUSB_INDEX:
 485                         return writeb(data, addr + SUNXI_MUSB_INDEX);
 486                 case MUSB_TESTMODE:
 487                         if (data)
 488                                 dev_warn(sunxi_musb->controller->parent,
 489                                         "sunxi-musb does not have testmode\n");
 490                         return;
 491                 case MUSB_DEVCTL:
 492                         return writeb(data, addr + SUNXI_MUSB_DEVCTL);
 493                 case MUSB_TXFIFOSZ:
 494                         return writeb(data, addr + SUNXI_MUSB_TXFIFOSZ);
 495                 case MUSB_RXFIFOSZ:
 496                         return writeb(data, addr + SUNXI_MUSB_RXFIFOSZ);
 497                 /* Offset for these is fixed by sunxi_musb_busctl_offset() */
 498                 case SUNXI_MUSB_TXFUNCADDR:
 499                 case SUNXI_MUSB_TXHUBADDR:
 500                 case SUNXI_MUSB_TXHUBPORT:
 501                 case SUNXI_MUSB_RXFUNCADDR:
 502                 case SUNXI_MUSB_RXHUBADDR:
 503                 case SUNXI_MUSB_RXHUBPORT:
 504                         /* multipoint / busctl reg access */
 505                         return writeb(data, addr + offset);
 506                 default:
 507                         dev_err(sunxi_musb->controller->parent,
 508                                 "Error unknown writeb offset %u\n", offset);
 509                         return;
 510                 }
 511         } else if (addr == (sunxi_musb->mregs + 0x80)) {
 512                 /* ep control reg access */
 513                 if (offset >= MUSB_TXTYPE)
 514                         offset += 2;
 515                 return writeb(data, addr + offset);
 516         }
 517 
 518         dev_err(sunxi_musb->controller->parent,
 519                 "Error unknown writeb at 0x%x bytes offset\n",
 520                 (int)(addr - sunxi_musb->mregs));
 521 }
 522 
 523 static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset)
 524 {
 525         if (addr == sunxi_musb->mregs) {
 526                 /* generic control or fifo control reg access */
 527                 switch (offset) {
 528                 case MUSB_INTRTX:
 529                         return readw(addr + SUNXI_MUSB_INTRTX);
 530                 case MUSB_INTRRX:
 531                         return readw(addr + SUNXI_MUSB_INTRRX);
 532                 case MUSB_INTRTXE:
 533                         return readw(addr + SUNXI_MUSB_INTRTXE);
 534                 case MUSB_INTRRXE:
 535                         return readw(addr + SUNXI_MUSB_INTRRXE);
 536                 case MUSB_FRAME:
 537                         return readw(addr + SUNXI_MUSB_FRAME);
 538                 case MUSB_TXFIFOADD:
 539                         return readw(addr + SUNXI_MUSB_TXFIFOADD);
 540                 case MUSB_RXFIFOADD:
 541                         return readw(addr + SUNXI_MUSB_RXFIFOADD);
 542                 case MUSB_HWVERS:
 543                         return 0; /* sunxi musb version is not known */
 544                 default:
 545                         dev_err(sunxi_musb->controller->parent,
 546                                 "Error unknown readw offset %u\n", offset);
 547                         return 0;
 548                 }
 549         } else if (addr == (sunxi_musb->mregs + 0x80)) {
 550                 /* ep control reg access */
 551                 return readw(addr + offset);
 552         }
 553 
 554         dev_err(sunxi_musb->controller->parent,
 555                 "Error unknown readw at 0x%x bytes offset\n",
 556                 (int)(addr - sunxi_musb->mregs));
 557         return 0;
 558 }
 559 
 560 static void sunxi_musb_writew(void __iomem *addr, unsigned offset, u16 data)
 561 {
 562         if (addr == sunxi_musb->mregs) {
 563                 /* generic control or fifo control reg access */
 564                 switch (offset) {
 565                 case MUSB_INTRTX:
 566                         return writew(data, addr + SUNXI_MUSB_INTRTX);
 567                 case MUSB_INTRRX:
 568                         return writew(data, addr + SUNXI_MUSB_INTRRX);
 569                 case MUSB_INTRTXE:
 570                         return writew(data, addr + SUNXI_MUSB_INTRTXE);
 571                 case MUSB_INTRRXE:
 572                         return writew(data, addr + SUNXI_MUSB_INTRRXE);
 573                 case MUSB_FRAME:
 574                         return writew(data, addr + SUNXI_MUSB_FRAME);
 575                 case MUSB_TXFIFOADD:
 576                         return writew(data, addr + SUNXI_MUSB_TXFIFOADD);
 577                 case MUSB_RXFIFOADD:
 578                         return writew(data, addr + SUNXI_MUSB_RXFIFOADD);
 579                 default:
 580                         dev_err(sunxi_musb->controller->parent,
 581                                 "Error unknown writew offset %u\n", offset);
 582                         return;
 583                 }
 584         } else if (addr == (sunxi_musb->mregs + 0x80)) {
 585                 /* ep control reg access */
 586                 return writew(data, addr + offset);
 587         }
 588 
 589         dev_err(sunxi_musb->controller->parent,
 590                 "Error unknown writew at 0x%x bytes offset\n",
 591                 (int)(addr - sunxi_musb->mregs));
 592 }
 593 
 594 static const struct musb_platform_ops sunxi_musb_ops = {
 595         .quirks         = MUSB_INDEXED_EP,
 596         .init           = sunxi_musb_init,
 597         .exit           = sunxi_musb_exit,
 598         .enable         = sunxi_musb_enable,
 599         .disable        = sunxi_musb_disable,
 600         .fifo_offset    = sunxi_musb_fifo_offset,
 601         .ep_offset      = sunxi_musb_ep_offset,
 602         .busctl_offset  = sunxi_musb_busctl_offset,
 603         .readb          = sunxi_musb_readb,
 604         .writeb         = sunxi_musb_writeb,
 605         .readw          = sunxi_musb_readw,
 606         .writew         = sunxi_musb_writew,
 607         .dma_init       = sunxi_musb_dma_controller_create,
 608         .dma_exit       = sunxi_musb_dma_controller_destroy,
 609         .set_mode       = sunxi_musb_set_mode,
 610         .recover        = sunxi_musb_recover,
 611         .set_vbus       = sunxi_musb_set_vbus,
 612         .pre_root_reset_end = sunxi_musb_pre_root_reset_end,
 613         .post_root_reset_end = sunxi_musb_post_root_reset_end,
 614 };
 615 
 616 /* Allwinner OTG supports up to 5 endpoints */
 617 #define SUNXI_MUSB_MAX_EP_NUM   6
 618 #define SUNXI_MUSB_RAM_BITS     11
 619 
 620 static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
 621         MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
 622         MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
 623         MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
 624         MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
 625         MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
 626         MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
 627         MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
 628         MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
 629         MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
 630         MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
 631 };
 632 
 633 /* H3/V3s OTG supports only 4 endpoints */
 634 #define SUNXI_MUSB_MAX_EP_NUM_H3        5
 635 
 636 static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = {
 637         MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
 638         MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
 639         MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
 640         MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
 641         MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
 642         MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
 643         MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
 644         MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
 645 };
 646 
 647 static const struct musb_hdrc_config sunxi_musb_hdrc_config = {
 648         .fifo_cfg       = sunxi_musb_mode_cfg,
 649         .fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg),
 650         .multipoint     = true,
 651         .dyn_fifo       = true,
 652         .num_eps        = SUNXI_MUSB_MAX_EP_NUM,
 653         .ram_bits       = SUNXI_MUSB_RAM_BITS,
 654 };
 655 
 656 static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = {
 657         .fifo_cfg       = sunxi_musb_mode_cfg_h3,
 658         .fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg_h3),
 659         .multipoint     = true,
 660         .dyn_fifo       = true,
 661         .num_eps        = SUNXI_MUSB_MAX_EP_NUM_H3,
 662         .ram_bits       = SUNXI_MUSB_RAM_BITS,
 663 };
 664 
 665 
 666 static int sunxi_musb_probe(struct platform_device *pdev)
 667 {
 668         struct musb_hdrc_platform_data  pdata;
 669         struct platform_device_info     pinfo;
 670         struct sunxi_glue               *glue;
 671         struct device_node              *np = pdev->dev.of_node;
 672         int ret;
 673 
 674         if (!np) {
 675                 dev_err(&pdev->dev, "Error no device tree node found\n");
 676                 return -EINVAL;
 677         }
 678 
 679         glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 680         if (!glue)
 681                 return -ENOMEM;
 682 
 683         memset(&pdata, 0, sizeof(pdata));
 684         switch (usb_get_dr_mode(&pdev->dev)) {
 685 #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
 686         case USB_DR_MODE_HOST:
 687                 pdata.mode = MUSB_HOST;
 688                 glue->phy_mode = PHY_MODE_USB_HOST;
 689                 break;
 690 #endif
 691 #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET
 692         case USB_DR_MODE_PERIPHERAL:
 693                 pdata.mode = MUSB_PERIPHERAL;
 694                 glue->phy_mode = PHY_MODE_USB_DEVICE;
 695                 break;
 696 #endif
 697 #ifdef CONFIG_USB_MUSB_DUAL_ROLE
 698         case USB_DR_MODE_OTG:
 699                 pdata.mode = MUSB_OTG;
 700                 glue->phy_mode = PHY_MODE_USB_OTG;
 701                 break;
 702 #endif
 703         default:
 704                 dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n");
 705                 return -EINVAL;
 706         }
 707         pdata.platform_ops      = &sunxi_musb_ops;
 708         if (!of_device_is_compatible(np, "allwinner,sun8i-h3-musb"))
 709                 pdata.config = &sunxi_musb_hdrc_config;
 710         else
 711                 pdata.config = &sunxi_musb_hdrc_config_h3;
 712 
 713         glue->dev = &pdev->dev;
 714         INIT_WORK(&glue->work, sunxi_musb_work);
 715         glue->host_nb.notifier_call = sunxi_musb_host_notifier;
 716 
 717         if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
 718                 set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
 719 
 720         if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
 721                 set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
 722 
 723         if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") ||
 724             of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) {
 725                 set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
 726                 set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
 727         }
 728 
 729         glue->clk = devm_clk_get(&pdev->dev, NULL);
 730         if (IS_ERR(glue->clk)) {
 731                 dev_err(&pdev->dev, "Error getting clock: %ld\n",
 732                         PTR_ERR(glue->clk));
 733                 return PTR_ERR(glue->clk);
 734         }
 735 
 736         if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
 737                 glue->rst = devm_reset_control_get(&pdev->dev, NULL);
 738                 if (IS_ERR(glue->rst)) {
 739                         if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
 740                                 return -EPROBE_DEFER;
 741                         dev_err(&pdev->dev, "Error getting reset %ld\n",
 742                                 PTR_ERR(glue->rst));
 743                         return PTR_ERR(glue->rst);
 744                 }
 745         }
 746 
 747         glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
 748         if (IS_ERR(glue->extcon)) {
 749                 if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
 750                         return -EPROBE_DEFER;
 751                 dev_err(&pdev->dev, "Invalid or missing extcon\n");
 752                 return PTR_ERR(glue->extcon);
 753         }
 754 
 755         glue->phy = devm_phy_get(&pdev->dev, "usb");
 756         if (IS_ERR(glue->phy)) {
 757                 if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
 758                         return -EPROBE_DEFER;
 759                 dev_err(&pdev->dev, "Error getting phy %ld\n",
 760                         PTR_ERR(glue->phy));
 761                 return PTR_ERR(glue->phy);
 762         }
 763 
 764         glue->usb_phy = usb_phy_generic_register();
 765         if (IS_ERR(glue->usb_phy)) {
 766                 dev_err(&pdev->dev, "Error registering usb-phy %ld\n",
 767                         PTR_ERR(glue->usb_phy));
 768                 return PTR_ERR(glue->usb_phy);
 769         }
 770 
 771         glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 772         if (IS_ERR(glue->xceiv)) {
 773                 ret = PTR_ERR(glue->xceiv);
 774                 dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret);
 775                 goto err_unregister_usb_phy;
 776         }
 777 
 778         platform_set_drvdata(pdev, glue);
 779 
 780         memset(&pinfo, 0, sizeof(pinfo));
 781         pinfo.name       = "musb-hdrc";
 782         pinfo.id        = PLATFORM_DEVID_AUTO;
 783         pinfo.parent    = &pdev->dev;
 784         pinfo.res       = pdev->resource;
 785         pinfo.num_res   = pdev->num_resources;
 786         pinfo.data      = &pdata;
 787         pinfo.size_data = sizeof(pdata);
 788 
 789         glue->musb_pdev = platform_device_register_full(&pinfo);
 790         if (IS_ERR(glue->musb_pdev)) {
 791                 ret = PTR_ERR(glue->musb_pdev);
 792                 dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
 793                 goto err_unregister_usb_phy;
 794         }
 795 
 796         return 0;
 797 
 798 err_unregister_usb_phy:
 799         usb_phy_generic_unregister(glue->usb_phy);
 800         return ret;
 801 }
 802 
 803 static int sunxi_musb_remove(struct platform_device *pdev)
 804 {
 805         struct sunxi_glue *glue = platform_get_drvdata(pdev);
 806         struct platform_device *usb_phy = glue->usb_phy;
 807 
 808         platform_device_unregister(glue->musb_pdev);
 809         usb_phy_generic_unregister(usb_phy);
 810 
 811         return 0;
 812 }
 813 
 814 static const struct of_device_id sunxi_musb_match[] = {
 815         { .compatible = "allwinner,sun4i-a10-musb", },
 816         { .compatible = "allwinner,sun6i-a31-musb", },
 817         { .compatible = "allwinner,sun8i-a33-musb", },
 818         { .compatible = "allwinner,sun8i-h3-musb", },
 819         {}
 820 };
 821 MODULE_DEVICE_TABLE(of, sunxi_musb_match);
 822 
 823 static struct platform_driver sunxi_musb_driver = {
 824         .probe = sunxi_musb_probe,
 825         .remove = sunxi_musb_remove,
 826         .driver = {
 827                 .name = "musb-sunxi",
 828                 .of_match_table = sunxi_musb_match,
 829         },
 830 };
 831 module_platform_driver(sunxi_musb_driver);
 832 
 833 MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer");
 834 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 835 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */