linux/drivers/usb/musb/sunxi.c
<<
>>
Prefs
   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 :| */
  71static struct musb *sunxi_musb;
  72
  73struct 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  */
  90static 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
 139static 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
 153static 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
 160static 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
 167static 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
 199static 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
 215static 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
 259error_reset_assert:
 260        if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 261                reset_control_assert(glue->rst);
 262error_clk_disable:
 263        clk_disable_unprepare(glue->clk);
 264error_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
 270static 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
 294static 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
 307static 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
 314static struct dma_controller *
 315sunxi_musb_dma_controller_create(struct musb *musb, void __iomem *base)
 316{
 317        return NULL;
 318}
 319
 320static void sunxi_musb_dma_controller_destroy(struct dma_controller *c)
 321{
 322}
 323
 324static 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
 368static 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
 392static u32 sunxi_musb_fifo_offset(u8 epnum)
 393{
 394        return (epnum * 4);
 395}
 396
 397static 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
 405static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
 406{
 407        return SUNXI_MUSB_TXFUNCADDR + offset;
 408}
 409
 410static u8 sunxi_musb_readb(void __iomem *addr, u32 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
 471static 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
 523static u16 sunxi_musb_readw(void __iomem *addr, u32 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
 560static 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
 594static 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
 620static 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
 636static 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
 647static 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
 656static 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
 666static 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.fwnode    = of_fwnode_handle(pdev->dev.of_node);
 785        pinfo.of_node_reused = true;
 786        pinfo.res       = pdev->resource;
 787        pinfo.num_res   = pdev->num_resources;
 788        pinfo.data      = &pdata;
 789        pinfo.size_data = sizeof(pdata);
 790
 791        glue->musb_pdev = platform_device_register_full(&pinfo);
 792        if (IS_ERR(glue->musb_pdev)) {
 793                ret = PTR_ERR(glue->musb_pdev);
 794                dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
 795                goto err_unregister_usb_phy;
 796        }
 797
 798        return 0;
 799
 800err_unregister_usb_phy:
 801        usb_phy_generic_unregister(glue->usb_phy);
 802        return ret;
 803}
 804
 805static int sunxi_musb_remove(struct platform_device *pdev)
 806{
 807        struct sunxi_glue *glue = platform_get_drvdata(pdev);
 808        struct platform_device *usb_phy = glue->usb_phy;
 809
 810        platform_device_unregister(glue->musb_pdev);
 811        usb_phy_generic_unregister(usb_phy);
 812
 813        return 0;
 814}
 815
 816static const struct of_device_id sunxi_musb_match[] = {
 817        { .compatible = "allwinner,sun4i-a10-musb", },
 818        { .compatible = "allwinner,sun6i-a31-musb", },
 819        { .compatible = "allwinner,sun8i-a33-musb", },
 820        { .compatible = "allwinner,sun8i-h3-musb", },
 821        {}
 822};
 823MODULE_DEVICE_TABLE(of, sunxi_musb_match);
 824
 825static struct platform_driver sunxi_musb_driver = {
 826        .probe = sunxi_musb_probe,
 827        .remove = sunxi_musb_remove,
 828        .driver = {
 829                .name = "musb-sunxi",
 830                .of_match_table = sunxi_musb_match,
 831        },
 832};
 833module_platform_driver(sunxi_musb_driver);
 834
 835MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer");
 836MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 837MODULE_LICENSE("GPL v2");
 838