1 /* 2 * Copyright (C) 2011 Jana Rapava <fermata7@gmail.com> 3 * Copyright (C) 2011 CompuLab, Ltd. <www.compulab.co.il> 4 * 5 * Authors: Jana Rapava <fermata7@gmail.com> 6 * Igor Grinberg <grinberg@compulab.co.il> 7 * 8 * Based on: 9 * linux/drivers/usb/otg/ulpi_viewport.c 10 * 11 * Original Copyright follow: 12 * Copyright (C) 2011 Google, Inc. 13 * 14 * SPDX-License-Identifier: GPL-2.0 15 */ 16 17 #include <common.h> 18 #include <asm/io.h> 19 #include <usb/ulpi.h> 20 21 /* ULPI viewport control bits */ 22 #define ULPI_SS (1 << 27) 23 #define ULPI_RWCTRL (1 << 29) 24 #define ULPI_RWRUN (1 << 30) 25 #define ULPI_WU (1 << 31) 26 27 /* 28 * Wait for the ULPI request to complete 29 * 30 * @ulpi_viewport - the address of the viewport 31 * @mask - expected value to wait for 32 * 33 * returns 0 on mask match, ULPI_ERROR on time out. 34 */ 35 static int ulpi_wait(struct ulpi_viewport *ulpi_vp, u32 mask) 36 { 37 int timeout = CONFIG_USB_ULPI_TIMEOUT; 38 39 /* Wait for the bits in mask to become zero. */ 40 while (--timeout) { 41 if ((readl(ulpi_vp->viewport_addr) & mask) == 0) 42 return 0; 43 44 udelay(1); 45 } 46 47 return ULPI_ERROR; 48 } 49 50 /* 51 * Wake the ULPI PHY up for communication 52 * 53 * returns 0 on success. 54 */ 55 static int ulpi_wakeup(struct ulpi_viewport *ulpi_vp) 56 { 57 int err; 58 59 if (readl(ulpi_vp->viewport_addr) & ULPI_SS) 60 return 0; /* already awake */ 61 62 writel(ULPI_WU, ulpi_vp->viewport_addr); 63 64 err = ulpi_wait(ulpi_vp, ULPI_WU); 65 if (err) 66 printf("ULPI wakeup timed out\n"); 67 68 return err; 69 } 70 71 /* 72 * Issue a ULPI read/write request 73 * 74 * @value - the ULPI request 75 */ 76 static int ulpi_request(struct ulpi_viewport *ulpi_vp, u32 value) 77 { 78 int err; 79 80 err = ulpi_wakeup(ulpi_vp); 81 if (err) 82 return err; 83 84 writel(value, ulpi_vp->viewport_addr); 85 86 err = ulpi_wait(ulpi_vp, ULPI_RWRUN); 87 if (err) 88 printf("ULPI request timed out\n"); 89 90 return err; 91 } 92 93 int ulpi_write(struct ulpi_viewport *ulpi_vp, u8 *reg, u32 value) 94 { 95 u32 addr = (uintptr_t)reg & 0xFF; 96 u32 val = ULPI_RWRUN | ULPI_RWCTRL | addr << 16 | (value & 0xff); 97 98 val |= (ulpi_vp->port_num & 0x7) << 24; 99 return ulpi_request(ulpi_vp, val); 100 } 101 102 u32 ulpi_read(struct ulpi_viewport *ulpi_vp, u8 *reg) 103 { 104 int err; 105 u32 val = ULPI_RWRUN | ((uintptr_t)reg & 0xFF) << 16; 106 107 val |= (ulpi_vp->port_num & 0x7) << 24; 108 err = ulpi_request(ulpi_vp, val); 109 if (err) 110 return err; 111 112 return (readl(ulpi_vp->viewport_addr) >> 8) & 0xff; 113 } 114