0001
0002
0003
0004
0005
0006
0007
0008
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
0030
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
0057 #define SUNXI_MUSB_VEND0_PIO_MODE 0
0058
0059
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
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
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
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
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
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
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
0359
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
0374
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
0384
0385
0386
0387
0388
0389
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;
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
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;
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:
0436 glue = dev_get_drvdata(sunxi_musb->controller->parent);
0437
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
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
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
0463
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
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
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
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
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
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;
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
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
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
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
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
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");