Home | History | Annotate | Download | only in musb-new
      1 // SPDX-License-Identifier: GPL-2.0
      2 /*
      3  * Allwinner SUNXI "glue layer"
      4  *
      5  * Copyright  2015 Hans de Goede <hdegoede (at) redhat.com>
      6  * Copyright  2013 Jussi Kivilinna <jussi.kivilinna (at) iki.fi>
      7  *
      8  * Based on the sw_usb "Allwinner OTG Dual Role Controller" code.
      9  *  Copyright 2007-2012 (C) Allwinner Technology Co., Ltd.
     10  *  javen <javen (at) allwinnertech.com>
     11  *
     12  * Based on the DA8xx "glue layer" code.
     13  *  Copyright (c) 2008-2009 MontaVista Software, Inc. <source (at) mvista.com>
     14  *  Copyright (C) 2005-2006 by Texas Instruments
     15  *
     16  * This file is part of the Inventra Controller Driver for Linux.
     17  */
     18 #include <common.h>
     19 #include <dm.h>
     20 #include <generic-phy.h>
     21 #include <phy-sun4i-usb.h>
     22 #include <asm/arch/cpu.h>
     23 #include <asm/arch/clock.h>
     24 #include <asm/arch/gpio.h>
     25 #include <asm-generic/gpio.h>
     26 #include <dm/lists.h>
     27 #include <dm/root.h>
     28 #include <linux/usb/musb.h>
     29 #include "linux-compat.h"
     30 #include "musb_core.h"
     31 #include "musb_uboot.h"
     32 
     33 /******************************************************************************
     34  ******************************************************************************
     35  * From the Allwinner driver
     36  ******************************************************************************
     37  ******************************************************************************/
     38 
     39 /******************************************************************************
     40  * From include/sunxi_usb_bsp.h
     41  ******************************************************************************/
     42 
     43 /* reg offsets */
     44 #define  USBC_REG_o_ISCR	0x0400
     45 #define  USBC_REG_o_PHYCTL	0x0404
     46 #define  USBC_REG_o_PHYBIST	0x0408
     47 #define  USBC_REG_o_PHYTUNE	0x040c
     48 
     49 #define  USBC_REG_o_VEND0	0x0043
     50 
     51 /* Interface Status and Control */
     52 #define  USBC_BP_ISCR_VBUS_VALID_FROM_DATA	30
     53 #define  USBC_BP_ISCR_VBUS_VALID_FROM_VBUS	29
     54 #define  USBC_BP_ISCR_EXT_ID_STATUS		28
     55 #define  USBC_BP_ISCR_EXT_DM_STATUS		27
     56 #define  USBC_BP_ISCR_EXT_DP_STATUS		26
     57 #define  USBC_BP_ISCR_MERGED_VBUS_STATUS	25
     58 #define  USBC_BP_ISCR_MERGED_ID_STATUS		24
     59 
     60 #define  USBC_BP_ISCR_ID_PULLUP_EN		17
     61 #define  USBC_BP_ISCR_DPDM_PULLUP_EN		16
     62 #define  USBC_BP_ISCR_FORCE_ID			14
     63 #define  USBC_BP_ISCR_FORCE_VBUS_VALID		12
     64 #define  USBC_BP_ISCR_VBUS_VALID_SRC		10
     65 
     66 #define  USBC_BP_ISCR_HOSC_EN			7
     67 #define  USBC_BP_ISCR_VBUS_CHANGE_DETECT	6
     68 #define  USBC_BP_ISCR_ID_CHANGE_DETECT		5
     69 #define  USBC_BP_ISCR_DPDM_CHANGE_DETECT	4
     70 #define  USBC_BP_ISCR_IRQ_ENABLE		3
     71 #define  USBC_BP_ISCR_VBUS_CHANGE_DETECT_EN	2
     72 #define  USBC_BP_ISCR_ID_CHANGE_DETECT_EN	1
     73 #define  USBC_BP_ISCR_DPDM_CHANGE_DETECT_EN	0
     74 
     75 /******************************************************************************
     76  * From usbc/usbc.c
     77  ******************************************************************************/
     78 
     79 struct sunxi_musb_config {
     80 	struct musb_hdrc_config *config;
     81 	u8 rst_bit;
     82 	u8 clkgate_bit;
     83 };
     84 
     85 struct sunxi_glue {
     86 	struct musb_host_data mdata;
     87 	struct sunxi_ccm_reg *ccm;
     88 	struct sunxi_musb_config *cfg;
     89 	struct device dev;
     90 	struct phy *phy;
     91 };
     92 #define to_sunxi_glue(d)	container_of(d, struct sunxi_glue, dev)
     93 
     94 static u32 USBC_WakeUp_ClearChangeDetect(u32 reg_val)
     95 {
     96 	u32 temp = reg_val;
     97 
     98 	temp &= ~BIT(USBC_BP_ISCR_VBUS_CHANGE_DETECT);
     99 	temp &= ~BIT(USBC_BP_ISCR_ID_CHANGE_DETECT);
    100 	temp &= ~BIT(USBC_BP_ISCR_DPDM_CHANGE_DETECT);
    101 
    102 	return temp;
    103 }
    104 
    105 static void USBC_EnableIdPullUp(__iomem void *base)
    106 {
    107 	u32 reg_val;
    108 
    109 	reg_val = musb_readl(base, USBC_REG_o_ISCR);
    110 	reg_val |= BIT(USBC_BP_ISCR_ID_PULLUP_EN);
    111 	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
    112 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
    113 }
    114 
    115 static void USBC_EnableDpDmPullUp(__iomem void *base)
    116 {
    117 	u32 reg_val;
    118 
    119 	reg_val = musb_readl(base, USBC_REG_o_ISCR);
    120 	reg_val |= BIT(USBC_BP_ISCR_DPDM_PULLUP_EN);
    121 	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
    122 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
    123 }
    124 
    125 static void USBC_ForceIdToLow(__iomem void *base)
    126 {
    127 	u32 reg_val;
    128 
    129 	reg_val = musb_readl(base, USBC_REG_o_ISCR);
    130 	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_ID);
    131 	reg_val |= (0x02 << USBC_BP_ISCR_FORCE_ID);
    132 	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
    133 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
    134 }
    135 
    136 static void USBC_ForceIdToHigh(__iomem void *base)
    137 {
    138 	u32 reg_val;
    139 
    140 	reg_val = musb_readl(base, USBC_REG_o_ISCR);
    141 	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_ID);
    142 	reg_val |= (0x03 << USBC_BP_ISCR_FORCE_ID);
    143 	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
    144 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
    145 }
    146 
    147 static void USBC_ForceVbusValidToLow(__iomem void *base)
    148 {
    149 	u32 reg_val;
    150 
    151 	reg_val = musb_readl(base, USBC_REG_o_ISCR);
    152 	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
    153 	reg_val |= (0x02 << USBC_BP_ISCR_FORCE_VBUS_VALID);
    154 	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
    155 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
    156 }
    157 
    158 static void USBC_ForceVbusValidToHigh(__iomem void *base)
    159 {
    160 	u32 reg_val;
    161 
    162 	reg_val = musb_readl(base, USBC_REG_o_ISCR);
    163 	reg_val &= ~(0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
    164 	reg_val |= (0x03 << USBC_BP_ISCR_FORCE_VBUS_VALID);
    165 	reg_val = USBC_WakeUp_ClearChangeDetect(reg_val);
    166 	musb_writel(base, USBC_REG_o_ISCR, reg_val);
    167 }
    168 
    169 static void USBC_ConfigFIFO_Base(void)
    170 {
    171 	u32 reg_value;
    172 
    173 	/* config usb fifo, 8kb mode */
    174 	reg_value = readl(SUNXI_SRAMC_BASE + 0x04);
    175 	reg_value &= ~(0x03 << 0);
    176 	reg_value |= BIT(0);
    177 	writel(reg_value, SUNXI_SRAMC_BASE + 0x04);
    178 }
    179 
    180 /******************************************************************************
    181  * Needed for the DFU polling magic
    182  ******************************************************************************/
    183 
    184 static u8 last_int_usb;
    185 
    186 bool dfu_usb_get_reset(void)
    187 {
    188 	return !!(last_int_usb & MUSB_INTR_RESET);
    189 }
    190 
    191 /******************************************************************************
    192  * MUSB Glue code
    193  ******************************************************************************/
    194 
    195 static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
    196 {
    197 	struct musb		*musb = __hci;
    198 	irqreturn_t		retval = IRQ_NONE;
    199 
    200 	/* read and flush interrupts */
    201 	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
    202 	last_int_usb = musb->int_usb;
    203 	if (musb->int_usb)
    204 		musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb);
    205 	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
    206 	if (musb->int_tx)
    207 		musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx);
    208 	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
    209 	if (musb->int_rx)
    210 		musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx);
    211 
    212 	if (musb->int_usb || musb->int_tx || musb->int_rx)
    213 		retval |= musb_interrupt(musb);
    214 
    215 	return retval;
    216 }
    217 
    218 /* musb_core does not call enable / disable in a balanced manner <sigh> */
    219 static bool enabled = false;
    220 
    221 static int sunxi_musb_enable(struct musb *musb)
    222 {
    223 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
    224 	int ret;
    225 
    226 	pr_debug("%s():\n", __func__);
    227 
    228 	musb_ep_select(musb->mregs, 0);
    229 	musb_writeb(musb->mregs, MUSB_FADDR, 0);
    230 
    231 	if (enabled)
    232 		return 0;
    233 
    234 	/* select PIO mode */
    235 	musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
    236 
    237 	if (is_host_enabled(musb)) {
    238 		ret = sun4i_usb_phy_vbus_detect(glue->phy);
    239 		if (ret == 1) {
    240 			printf("A charger is plugged into the OTG: ");
    241 			return -ENODEV;
    242 		}
    243 
    244 		ret = sun4i_usb_phy_id_detect(glue->phy);
    245 		if (ret == 1) {
    246 			printf("No host cable detected: ");
    247 			return -ENODEV;
    248 		}
    249 
    250 		ret = generic_phy_power_on(glue->phy);
    251 		if (ret) {
    252 			pr_err("failed to power on USB PHY\n");
    253 			return ret;
    254 		}
    255 	}
    256 
    257 	USBC_ForceVbusValidToHigh(musb->mregs);
    258 
    259 	enabled = true;
    260 	return 0;
    261 }
    262 
    263 static void sunxi_musb_disable(struct musb *musb)
    264 {
    265 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
    266 	int ret;
    267 
    268 	pr_debug("%s():\n", __func__);
    269 
    270 	if (!enabled)
    271 		return;
    272 
    273 	if (is_host_enabled(musb)) {
    274 		ret = generic_phy_power_off(glue->phy);
    275 		if (ret) {
    276 			pr_err("failed to power off USB PHY\n");
    277 			return;
    278 		}
    279 	}
    280 
    281 	USBC_ForceVbusValidToLow(musb->mregs);
    282 	mdelay(200); /* Wait for the current session to timeout */
    283 
    284 	enabled = false;
    285 }
    286 
    287 static int sunxi_musb_init(struct musb *musb)
    288 {
    289 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
    290 	int ret;
    291 
    292 	pr_debug("%s():\n", __func__);
    293 
    294 	ret = generic_phy_init(glue->phy);
    295 	if (ret) {
    296 		pr_err("failed to init USB PHY\n");
    297 		return ret;
    298 	}
    299 
    300 	musb->isr = sunxi_musb_interrupt;
    301 
    302 	setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0));
    303 	if (glue->cfg->clkgate_bit)
    304 		setbits_le32(&glue->ccm->ahb_gate0,
    305 			     BIT(glue->cfg->clkgate_bit));
    306 #ifdef CONFIG_SUNXI_GEN_SUN6I
    307 	setbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0));
    308 	if (glue->cfg->rst_bit)
    309 		setbits_le32(&glue->ccm->ahb_reset0_cfg,
    310 			     BIT(glue->cfg->rst_bit));
    311 #endif
    312 
    313 	USBC_ConfigFIFO_Base();
    314 	USBC_EnableDpDmPullUp(musb->mregs);
    315 	USBC_EnableIdPullUp(musb->mregs);
    316 
    317 	if (is_host_enabled(musb)) {
    318 		/* Host mode */
    319 		USBC_ForceIdToLow(musb->mregs);
    320 	} else {
    321 		/* Peripheral mode */
    322 		USBC_ForceIdToHigh(musb->mregs);
    323 	}
    324 	USBC_ForceVbusValidToHigh(musb->mregs);
    325 
    326 	return 0;
    327 }
    328 
    329 static void sunxi_musb_pre_root_reset_end(struct musb *musb)
    330 {
    331 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
    332 
    333 	sun4i_usb_phy_set_squelch_detect(glue->phy, false);
    334 }
    335 
    336 static void sunxi_musb_post_root_reset_end(struct musb *musb)
    337 {
    338 	struct sunxi_glue *glue = to_sunxi_glue(musb->controller);
    339 
    340 	sun4i_usb_phy_set_squelch_detect(glue->phy, true);
    341 }
    342 
    343 static const struct musb_platform_ops sunxi_musb_ops = {
    344 	.init		= sunxi_musb_init,
    345 	.enable		= sunxi_musb_enable,
    346 	.disable	= sunxi_musb_disable,
    347 	.pre_root_reset_end = sunxi_musb_pre_root_reset_end,
    348 	.post_root_reset_end = sunxi_musb_post_root_reset_end,
    349 };
    350 
    351 /* Allwinner OTG supports up to 5 endpoints */
    352 #define SUNXI_MUSB_MAX_EP_NUM		6
    353 #define SUNXI_MUSB_RAM_BITS		11
    354 
    355 static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
    356 	MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
    357 	MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
    358 	MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
    359 	MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
    360 	MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
    361 	MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
    362 	MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
    363 	MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
    364 	MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
    365 	MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
    366 };
    367 
    368 /* H3/V3s OTG supports only 4 endpoints */
    369 #define SUNXI_MUSB_MAX_EP_NUM_H3	5
    370 
    371 static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = {
    372 	MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
    373 	MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
    374 	MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
    375 	MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
    376 	MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
    377 	MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
    378 	MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
    379 	MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
    380 };
    381 
    382 static struct musb_hdrc_config musb_config = {
    383 	.fifo_cfg       = sunxi_musb_mode_cfg,
    384 	.fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg),
    385 	.multipoint	= true,
    386 	.dyn_fifo	= true,
    387 	.num_eps	= SUNXI_MUSB_MAX_EP_NUM,
    388 	.ram_bits	= SUNXI_MUSB_RAM_BITS,
    389 };
    390 
    391 static struct musb_hdrc_config musb_config_h3 = {
    392 	.fifo_cfg       = sunxi_musb_mode_cfg_h3,
    393 	.fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg_h3),
    394 	.multipoint	= true,
    395 	.dyn_fifo	= true,
    396 	.soft_con       = true,
    397 	.num_eps	= SUNXI_MUSB_MAX_EP_NUM_H3,
    398 	.ram_bits	= SUNXI_MUSB_RAM_BITS,
    399 };
    400 
    401 static int musb_usb_probe(struct udevice *dev)
    402 {
    403 	struct sunxi_glue *glue = dev_get_priv(dev);
    404 	struct musb_host_data *host = &glue->mdata;
    405 	struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
    406 	struct musb_hdrc_platform_data pdata;
    407 	void *base = dev_read_addr_ptr(dev);
    408 	struct phy phy;
    409 	int ret;
    410 
    411 	if (!base)
    412 		return -EINVAL;
    413 
    414 	glue->cfg = (struct sunxi_musb_config *)dev_get_driver_data(dev);
    415 	if (!glue->cfg)
    416 		return -EINVAL;
    417 
    418 	glue->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
    419 	if (IS_ERR(glue->ccm))
    420 		return PTR_ERR(glue->ccm);
    421 
    422 	ret = generic_phy_get_by_name(dev, "usb", &phy);
    423 	if (ret) {
    424 		pr_err("failed to get usb PHY\n");
    425 		return ret;
    426 	}
    427 
    428 	glue->phy = &phy;
    429 	priv->desc_before_addr = true;
    430 
    431 	memset(&pdata, 0, sizeof(pdata));
    432 	pdata.power = 250;
    433 	pdata.platform_ops = &sunxi_musb_ops;
    434 	pdata.config = glue->cfg->config;
    435 
    436 #ifdef CONFIG_USB_MUSB_HOST
    437 	pdata.mode = MUSB_HOST;
    438 	host->host = musb_init_controller(&pdata, &glue->dev, base);
    439 	if (!host->host)
    440 		return -EIO;
    441 
    442 	ret = musb_lowlevel_init(host);
    443 	if (!ret)
    444 		printf("Allwinner mUSB OTG (Host)\n");
    445 #else
    446 	pdata.mode = MUSB_PERIPHERAL;
    447 	ret = musb_register(&pdata, &glue->dev, base);
    448 	if (!ret)
    449 		printf("Allwinner mUSB OTG (Peripheral)\n");
    450 #endif
    451 
    452 	return ret;
    453 }
    454 
    455 static int musb_usb_remove(struct udevice *dev)
    456 {
    457 	struct sunxi_glue *glue = dev_get_priv(dev);
    458 	struct musb_host_data *host = &glue->mdata;
    459 	int ret;
    460 
    461 	if (generic_phy_valid(glue->phy)) {
    462 		ret = generic_phy_exit(glue->phy);
    463 		if (ret) {
    464 			pr_err("failed to exit %s USB PHY\n", dev->name);
    465 			return ret;
    466 		}
    467 	}
    468 
    469 	musb_stop(host->host);
    470 
    471 #ifdef CONFIG_SUNXI_GEN_SUN6I
    472 	clrbits_le32(&glue->ccm->ahb_reset0_cfg, BIT(AHB_GATE_OFFSET_USB0));
    473 	if (glue->cfg->rst_bit)
    474 		clrbits_le32(&glue->ccm->ahb_reset0_cfg,
    475 			     BIT(glue->cfg->rst_bit));
    476 #endif
    477 	clrbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0));
    478 	if (glue->cfg->clkgate_bit)
    479 		clrbits_le32(&glue->ccm->ahb_gate0,
    480 			     BIT(glue->cfg->clkgate_bit));
    481 
    482 	free(host->host);
    483 	host->host = NULL;
    484 
    485 	return 0;
    486 }
    487 
    488 static const struct sunxi_musb_config sun4i_a10_cfg = {
    489 	.config = &musb_config,
    490 };
    491 
    492 static const struct sunxi_musb_config sun8i_h3_cfg = {
    493 	.config = &musb_config_h3,
    494 	.rst_bit = 23,
    495 	.clkgate_bit = 23,
    496 };
    497 
    498 static const struct udevice_id sunxi_musb_ids[] = {
    499 	{ .compatible = "allwinner,sun4i-a10-musb",
    500 			.data = (ulong)&sun4i_a10_cfg },
    501 	{ .compatible = "allwinner,sun6i-a31-musb",
    502 			.data = (ulong)&sun4i_a10_cfg },
    503 	{ .compatible = "allwinner,sun8i-a33-musb",
    504 			.data = (ulong)&sun4i_a10_cfg },
    505 	{ .compatible = "allwinner,sun8i-h3-musb",
    506 			.data = (ulong)&sun8i_h3_cfg },
    507 	{ }
    508 };
    509 
    510 U_BOOT_DRIVER(usb_musb) = {
    511 	.name		= "sunxi-musb",
    512 #ifdef CONFIG_USB_MUSB_HOST
    513 	.id		= UCLASS_USB,
    514 #else
    515 	.id		= UCLASS_USB_DEV_GENERIC,
    516 #endif
    517 	.of_match	= sunxi_musb_ids,
    518 	.probe		= musb_usb_probe,
    519 	.remove		= musb_usb_remove,
    520 #ifdef CONFIG_USB_MUSB_HOST
    521 	.ops		= &musb_usb_ops,
    522 #endif
    523 	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
    524 	.priv_auto_alloc_size = sizeof(struct sunxi_glue),
    525 };
    526