Home | History | Annotate | Download | only in ulpi
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (C) 2011 Jana Rapava <fermata7 (at) gmail.com>
      4  * Copyright (C) 2011 CompuLab, Ltd. <www.compulab.co.il>
      5  *
      6  * Authors: Jana Rapava <fermata7 (at) gmail.com>
      7  *	    Igor Grinberg <grinberg (at) compulab.co.il>
      8  *
      9  * Based on:
     10  * linux/drivers/usb/otg/ulpi.c
     11  * Generic ULPI USB transceiver support
     12  *
     13  * Original Copyright follow:
     14  * Copyright (C) 2009 Daniel Mack <daniel (at) caiaq.de>
     15  *
     16  * Based on sources from
     17  *
     18  *   Sascha Hauer <s.hauer (at) pengutronix.de>
     19  *   Freescale Semiconductors
     20  */
     21 
     22 #include <common.h>
     23 #include <exports.h>
     24 #include <usb/ulpi.h>
     25 
     26 #define ULPI_ID_REGS_COUNT	4
     27 #define ULPI_TEST_VALUE		0x55	/* 0x55 == 0b01010101 */
     28 
     29 static struct ulpi_regs *ulpi = (struct ulpi_regs *)0;
     30 
     31 static int ulpi_integrity_check(struct ulpi_viewport *ulpi_vp)
     32 {
     33 	u32 val, tval = ULPI_TEST_VALUE;
     34 	int err, i;
     35 
     36 	/* Use the 'special' test value to check all bits */
     37 	for (i = 0; i < 2; i++, tval <<= 1) {
     38 		err = ulpi_write(ulpi_vp, &ulpi->scratch, tval);
     39 		if (err)
     40 			return err;
     41 
     42 		val = ulpi_read(ulpi_vp, &ulpi->scratch);
     43 		if (val != tval) {
     44 			printf("ULPI integrity check failed\n");
     45 			return val;
     46 		}
     47 	}
     48 
     49 	return 0;
     50 }
     51 
     52 int ulpi_init(struct ulpi_viewport *ulpi_vp)
     53 {
     54 	u32 val, id = 0;
     55 	u8 *reg = &ulpi->product_id_high;
     56 	int i;
     57 
     58 	/* Assemble ID from four ULPI ID registers (8 bits each). */
     59 	for (i = 0; i < ULPI_ID_REGS_COUNT; i++) {
     60 		val = ulpi_read(ulpi_vp, reg - i);
     61 		if (val == ULPI_ERROR)
     62 			return val;
     63 
     64 		id = (id << 8) | val;
     65 	}
     66 
     67 	/* Split ID into vendor and product ID. */
     68 	debug("ULPI transceiver ID 0x%04x:0x%04x\n", id >> 16, id & 0xffff);
     69 
     70 	return ulpi_integrity_check(ulpi_vp);
     71 }
     72 
     73 int ulpi_select_transceiver(struct ulpi_viewport *ulpi_vp, unsigned speed)
     74 {
     75 	u32 tspeed = ULPI_FC_FULL_SPEED;
     76 	u32 val;
     77 
     78 	switch (speed) {
     79 	case ULPI_FC_HIGH_SPEED:
     80 	case ULPI_FC_FULL_SPEED:
     81 	case ULPI_FC_LOW_SPEED:
     82 	case ULPI_FC_FS4LS:
     83 		tspeed = speed;
     84 		break;
     85 	default:
     86 		printf("ULPI: %s: wrong transceiver speed specified: %u, "
     87 			"falling back to full speed\n", __func__, speed);
     88 	}
     89 
     90 	val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
     91 	if (val == ULPI_ERROR)
     92 		return val;
     93 
     94 	/* clear the previous speed setting */
     95 	val = (val & ~ULPI_FC_XCVRSEL_MASK) | tspeed;
     96 
     97 	return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val);
     98 }
     99 
    100 int ulpi_set_vbus(struct ulpi_viewport *ulpi_vp, int on, int ext_power)
    101 {
    102 	u32 flags = ULPI_OTG_DRVVBUS;
    103 	u8 *reg = on ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
    104 
    105 	if (ext_power)
    106 		flags |= ULPI_OTG_DRVVBUS_EXT;
    107 
    108 	return ulpi_write(ulpi_vp, reg, flags);
    109 }
    110 
    111 int ulpi_set_vbus_indicator(struct ulpi_viewport *ulpi_vp, int external,
    112 			int passthu, int complement)
    113 {
    114 	u32 flags, val;
    115 	u8 *reg;
    116 
    117 	reg = external ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
    118 	val = ulpi_write(ulpi_vp, reg, ULPI_OTG_EXTVBUSIND);
    119 	if (val)
    120 		return val;
    121 
    122 	flags = passthu ? ULPI_IFACE_PASSTHRU : 0;
    123 	flags |= complement ? ULPI_IFACE_EXTVBUS_COMPLEMENT : 0;
    124 
    125 	val = ulpi_read(ulpi_vp, &ulpi->iface_ctrl);
    126 	if (val == ULPI_ERROR)
    127 		return val;
    128 
    129 	val = val & ~(ULPI_IFACE_PASSTHRU & ULPI_IFACE_EXTVBUS_COMPLEMENT);
    130 	val |= flags;
    131 	val = ulpi_write(ulpi_vp, &ulpi->iface_ctrl, val);
    132 	if (val)
    133 		return val;
    134 
    135 	return 0;
    136 }
    137 
    138 int ulpi_set_pd(struct ulpi_viewport *ulpi_vp, int enable)
    139 {
    140 	u32 val = ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN;
    141 	u8 *reg = enable ? &ulpi->otg_ctrl_set : &ulpi->otg_ctrl_clear;
    142 
    143 	return ulpi_write(ulpi_vp, reg, val);
    144 }
    145 
    146 int ulpi_opmode_sel(struct ulpi_viewport *ulpi_vp, unsigned opmode)
    147 {
    148 	u32 topmode = ULPI_FC_OPMODE_NORMAL;
    149 	u32 val;
    150 
    151 	switch (opmode) {
    152 	case ULPI_FC_OPMODE_NORMAL:
    153 	case ULPI_FC_OPMODE_NONDRIVING:
    154 	case ULPI_FC_OPMODE_DISABLE_NRZI:
    155 	case ULPI_FC_OPMODE_NOSYNC_NOEOP:
    156 		topmode = opmode;
    157 		break;
    158 	default:
    159 		printf("ULPI: %s: wrong OpMode specified: %u, "
    160 			"falling back to OpMode Normal\n", __func__, opmode);
    161 	}
    162 
    163 	val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
    164 	if (val == ULPI_ERROR)
    165 		return val;
    166 
    167 	/* clear the previous opmode setting */
    168 	val = (val & ~ULPI_FC_OPMODE_MASK) | topmode;
    169 
    170 	return ulpi_write(ulpi_vp, &ulpi->function_ctrl, val);
    171 }
    172 
    173 int ulpi_serial_mode_enable(struct ulpi_viewport *ulpi_vp, unsigned smode)
    174 {
    175 	switch (smode) {
    176 	case ULPI_IFACE_6_PIN_SERIAL_MODE:
    177 	case ULPI_IFACE_3_PIN_SERIAL_MODE:
    178 		break;
    179 	default:
    180 		printf("ULPI: %s: unrecognized Serial Mode specified: %u\n",
    181 			__func__, smode);
    182 		return ULPI_ERROR;
    183 	}
    184 
    185 	return ulpi_write(ulpi_vp, &ulpi->iface_ctrl_set, smode);
    186 }
    187 
    188 int ulpi_suspend(struct ulpi_viewport *ulpi_vp)
    189 {
    190 	int err;
    191 
    192 	err = ulpi_write(ulpi_vp, &ulpi->function_ctrl_clear,
    193 			ULPI_FC_SUSPENDM);
    194 	if (err)
    195 		printf("ULPI: %s: failed writing the suspend bit\n", __func__);
    196 
    197 	return err;
    198 }
    199 
    200 /*
    201  * Wait for ULPI PHY reset to complete.
    202  * Actual wait for reset must be done in a view port specific way,
    203  * because it involves checking the DIR line.
    204  */
    205 static int __ulpi_reset_wait(struct ulpi_viewport *ulpi_vp)
    206 {
    207 	u32 val;
    208 	int timeout = CONFIG_USB_ULPI_TIMEOUT;
    209 
    210 	/* Wait for the RESET bit to become zero */
    211 	while (--timeout) {
    212 		/*
    213 		 * This function is generic and suppose to work
    214 		 * with any viewport, so we cheat here and don't check
    215 		 * for the error of ulpi_read(), if there is one, then
    216 		 * there will be a timeout.
    217 		 */
    218 		val = ulpi_read(ulpi_vp, &ulpi->function_ctrl);
    219 		if (!(val & ULPI_FC_RESET))
    220 			return 0;
    221 
    222 		udelay(1);
    223 	}
    224 
    225 	printf("ULPI: %s: reset timed out\n", __func__);
    226 
    227 	return ULPI_ERROR;
    228 }
    229 int ulpi_reset_wait(struct ulpi_viewport *ulpi_vp)
    230 	__attribute__((weak, alias("__ulpi_reset_wait")));
    231 
    232 int ulpi_reset(struct ulpi_viewport *ulpi_vp)
    233 {
    234 	int err;
    235 
    236 	err = ulpi_write(ulpi_vp,
    237 			&ulpi->function_ctrl_set, ULPI_FC_RESET);
    238 	if (err) {
    239 		printf("ULPI: %s: failed writing reset bit\n", __func__);
    240 		return err;
    241 	}
    242 
    243 	return ulpi_reset_wait(ulpi_vp);
    244 }
    245