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