uboot/drivers/usb/phy/twl4030.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2009 Wind River Systems, Inc.
   4 * Tom Rix <Tom.Rix@windriver.com>
   5 *
   6 * This is file is based on
   7 * repository git.gitorious.org/u-boot-omap3/mainline.git,
   8 * branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c
   9 *
  10 * This is the unique part of its copyright :
  11 *
  12 * ------------------------------------------------------------------------
  13 *
  14 *  * (C) Copyright 2009 Atin Malaviya (atin.malaviya@gmail.com)
  15 *
  16 * Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c)
  17 * Copyright (C) 2004-2007 Texas Instruments
  18 * Copyright (C) 2008 Nokia Corporation
  19 * Contact: Felipe Balbi <felipe.balbi@nokia.com>
  20 *
  21 * Author: Atin Malaviya (atin.malaviya@gmail.com)
  22 *
  23 * ------------------------------------------------------------------------
  24 */
  25
  26#include <twl4030.h>
  27
  28/* Defines for bits in registers */
  29#define OPMODE_MASK             (3 << 3)
  30#define XCVRSELECT_MASK         (3 << 0)
  31#define CARKITMODE              (1 << 2)
  32#define OTG_ENAB                (1 << 5)
  33#define PHYPWD                  (1 << 0)
  34#define CLOCKGATING_EN          (1 << 2)
  35#define CLK32K_EN               (1 << 1)
  36#define REQ_PHY_DPLL_CLK        (1 << 0)
  37#define PHY_DPLL_CLK            (1 << 0)
  38
  39static int twl4030_usb_write(u8 address, u8 data)
  40{
  41        int ret;
  42
  43        ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, address, data);
  44        if (ret != 0)
  45                printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
  46
  47        return ret;
  48}
  49
  50static int twl4030_usb_read(u8 address)
  51{
  52        u8 data;
  53        int ret;
  54
  55        ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, address, &data);
  56        if (ret == 0)
  57                ret = data;
  58        else
  59                printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
  60
  61        return ret;
  62}
  63
  64static void twl4030_usb_ldo_init(void)
  65{
  66        /* Enable writing to power configuration registers */
  67        twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
  68                             TWL4030_PM_MASTER_PROTECT_KEY, 0xC0);
  69        twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
  70                             TWL4030_PM_MASTER_PROTECT_KEY, 0x0C);
  71
  72        /* put VUSB3V1 LDO in active state */
  73        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  74                             TWL4030_PM_RECEIVER_VUSB_DEDICATED2, 0x00);
  75
  76        /* input to VUSB3V1 LDO is from VBAT, not VBUS */
  77        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  78                             TWL4030_PM_RECEIVER_VUSB_DEDICATED1, 0x14);
  79
  80        /* turn on 3.1V regulator */
  81        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  82                             TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP, 0x20);
  83        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  84                             TWL4030_PM_RECEIVER_VUSB3V1_TYPE, 0x00);
  85
  86        /* turn on 1.5V regulator */
  87        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  88                             TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP, 0x20);
  89        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  90                             TWL4030_PM_RECEIVER_VUSB1V5_TYPE, 0x00);
  91
  92        /* turn on 1.8V regulator */
  93        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  94                             TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP, 0x20);
  95        twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER,
  96                             TWL4030_PM_RECEIVER_VUSB1V8_TYPE, 0x00);
  97
  98        /* disable access to power configuration registers */
  99        twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER,
 100                             TWL4030_PM_MASTER_PROTECT_KEY, 0x00);
 101}
 102
 103static void twl4030_phy_power(void)
 104{
 105        u8 pwr, clk;
 106
 107        /* Power the PHY */
 108        pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
 109        pwr &= ~PHYPWD;
 110        twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
 111        /* Enable clocks */
 112        clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
 113        clk |= CLOCKGATING_EN | CLK32K_EN;
 114        twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
 115}
 116
 117/*
 118 * Initiaze the ULPI interface
 119 * ULPI : Universal Transceiver Macrocell Low Pin Interface
 120 * An interface between the USB link controller like musb and the
 121 * the PHY or transceiver that drives the actual bus.
 122 */
 123int twl4030_usb_ulpi_init(void)
 124{
 125        long timeout = 1000 * 1000; /* 1 sec */;
 126        u8 clk, sts, pwr;
 127
 128        /* twl4030 ldo init */
 129        twl4030_usb_ldo_init();
 130
 131        /* Enable the twl4030 phy */
 132        twl4030_phy_power();
 133
 134        /* Enable DPLL to access PHY registers over I2C */
 135        clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
 136        clk |= REQ_PHY_DPLL_CLK;
 137        twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
 138
 139        /* Check if the PHY DPLL is locked */
 140        sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
 141        while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
 142                udelay(10);
 143                sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
 144                timeout -= 10;
 145        }
 146
 147        /* Final check */
 148        sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
 149        if (!(sts & PHY_DPLL_CLK)) {
 150                printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n");
 151                return -1;
 152        }
 153
 154        /*
 155         * There are two circuit blocks attached to the PHY,
 156         * Carkit and USB OTG.  Disable Carkit and enable USB OTG
 157         */
 158        twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE);
 159        pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL);
 160        pwr |= OTG_ENAB;
 161        twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr);
 162
 163        /* Clear the opmode bits to ensure normal encode */
 164        twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
 165
 166        /* Clear the xcvrselect bits to enable the high speed transeiver */
 167        twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK);
 168
 169        /* Let ULPI control the DPLL clock */
 170        clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
 171        clk &= ~REQ_PHY_DPLL_CLK;
 172        twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
 173
 174        return 0;
 175}
 176