1432 lines
40 KiB
C
1432 lines
40 KiB
C
/*
|
||
* Copyright (c) 2015 Samsung Electronics Co., Ltd.
|
||
* http://www.samsung.com
|
||
*
|
||
* Author: Sung-Hyun Na <sunghyun.na@samsung.com>
|
||
* Author: Minho Lee <minho55.lee@samsung.com>
|
||
*
|
||
* Chip Abstraction Layer for USB PHY
|
||
*
|
||
* This program is free software; you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License version 2 as
|
||
* published by the Free Software Foundation.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*/
|
||
|
||
#ifdef __KERNEL__
|
||
|
||
#ifndef __EXCITE__
|
||
#include <linux/delay.h>
|
||
#include <linux/io.h>
|
||
#endif
|
||
|
||
#include <linux/platform_device.h>
|
||
|
||
#else
|
||
|
||
#include "types.h"
|
||
#include "customfunctions.h"
|
||
#include "mct.h"
|
||
|
||
#endif
|
||
|
||
#include "phy-samsung-usb-cal.h"
|
||
#include "phy-samsung-usb3-cal.h"
|
||
|
||
#define USB_SS_TX_TUNE_PCS
|
||
|
||
//#define USB_MUX_UTMI_ENABLE
|
||
|
||
enum exynos_usbcon_cr {
|
||
USBCON_CR_ADDR = 0,
|
||
USBCON_CR_DATA = 1,
|
||
USBCON_CR_READ = 18,
|
||
USBCON_CR_WRITE = 19,
|
||
};
|
||
|
||
static u16 samsung_exynos_cal_cr_access(struct exynos_usbphy_info *usbphy_info,
|
||
enum exynos_usbcon_cr cr_bit, u16 data)
|
||
{
|
||
void __iomem *base;
|
||
u32 phyreg0;
|
||
u32 phyreg1;
|
||
u32 loop;
|
||
u32 loop_cnt;
|
||
|
||
if (usbphy_info->used_phy_port != -1) {
|
||
if (usbphy_info->used_phy_port == 0)
|
||
base = usbphy_info->regs_base;
|
||
else
|
||
base = usbphy_info->regs_base_2nd;
|
||
|
||
} else
|
||
base = usbphy_info->regs_base;
|
||
|
||
/* Clear CR port register */
|
||
phyreg0 = readl(base + EXYNOS_USBCON_PHYREG0);
|
||
phyreg0 &= ~(0xfffff);
|
||
writel(phyreg0, base + EXYNOS_USBCON_PHYREG0);
|
||
|
||
/* Set Data for cr port */
|
||
phyreg0 &= ~PHYREG0_CR_DATA_MASK;
|
||
phyreg0 |= PHYREG0_CR_DATA_IN(data);
|
||
writel(phyreg0, base + EXYNOS_USBCON_PHYREG0);
|
||
|
||
if (cr_bit == USBCON_CR_ADDR)
|
||
loop = 1;
|
||
else
|
||
loop = 2;
|
||
|
||
for (loop_cnt = 0; loop_cnt < loop; loop_cnt++) {
|
||
u32 trigger_bit = 0;
|
||
u32 handshake_cnt = 2;
|
||
/* Trigger cr port */
|
||
if (cr_bit == USBCON_CR_ADDR)
|
||
trigger_bit = PHYREG0_CR_CR_CAP_ADDR;
|
||
else {
|
||
if (loop_cnt == 0)
|
||
trigger_bit = PHYREG0_CR_CR_CAP_DATA;
|
||
else {
|
||
if (cr_bit == USBCON_CR_READ)
|
||
trigger_bit = PHYREG0_CR_READ;
|
||
else
|
||
trigger_bit = PHYREG0_CR_WRITE;
|
||
}
|
||
}
|
||
/* Handshake Procedure */
|
||
do {
|
||
u32 usec = 100;
|
||
if (handshake_cnt == 2)
|
||
phyreg0 |= trigger_bit;
|
||
else
|
||
phyreg0 &= ~trigger_bit;
|
||
writel(phyreg0, base + EXYNOS_USBCON_PHYREG0);
|
||
|
||
/* Handshake */
|
||
do {
|
||
phyreg1 = readl(base + EXYNOS_USBCON_PHYREG1);
|
||
if ((handshake_cnt == 2)
|
||
&& (phyreg1 & PHYREG1_CR_ACK))
|
||
break;
|
||
else if ((handshake_cnt == 1)
|
||
&& !(phyreg1 & PHYREG1_CR_ACK))
|
||
break;
|
||
|
||
udelay(1);
|
||
} while (usec-- > 0);
|
||
|
||
if (!usec)
|
||
pr_err("CRPORT handshake timeout1 (0x%08x)\n",
|
||
phyreg0);
|
||
|
||
udelay(5);
|
||
handshake_cnt--;
|
||
} while (handshake_cnt != 0);
|
||
udelay(50);
|
||
}
|
||
return (u16) ((phyreg1 & PHYREG1_CR_DATA_OUT_MASK) >> 1);
|
||
}
|
||
|
||
void samsung_exynos_cal_cr_write(struct exynos_usbphy_info *usbphy_info,
|
||
u16 addr, u16 data)
|
||
{
|
||
samsung_exynos_cal_cr_access(usbphy_info, USBCON_CR_ADDR, addr);
|
||
samsung_exynos_cal_cr_access(usbphy_info, USBCON_CR_WRITE, data);
|
||
}
|
||
|
||
u16 samsung_exynos_cal_cr_read(struct exynos_usbphy_info *usbphy_info, u16 addr)
|
||
{
|
||
samsung_exynos_cal_cr_access(usbphy_info, USBCON_CR_ADDR, addr);
|
||
return samsung_exynos_cal_cr_access(usbphy_info, USBCON_CR_READ, 0);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_tune_fix_rxeq(
|
||
struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
u16 reg;
|
||
struct exynos_usbphy_ss_tune *tune = usbphy_info->ss_tune;
|
||
|
||
if (!tune)
|
||
return;
|
||
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, 0x1006);
|
||
reg &= ~(1 << 6);
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1006, reg);
|
||
|
||
udelay(10);
|
||
|
||
reg |= (1 << 7);
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1006, reg);
|
||
|
||
udelay(10);
|
||
|
||
reg &= ~(0x7 << 0x8);
|
||
reg |= (tune->fix_rxeq_value << 8);
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1006, reg);
|
||
|
||
udelay(10);
|
||
|
||
reg |= (1 << 11);
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1006, reg);
|
||
|
||
printk("Reg RX_OVRD_IN_HI : 0x%x\n",
|
||
samsung_exynos_cal_cr_read(usbphy_info, 0x1006));
|
||
|
||
printk("Reg RX_CDR_CDR_FSM_DEBUG : 0x%x\n",
|
||
samsung_exynos_cal_cr_read(usbphy_info, 0x101c));
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_tune_adaptive_eq(
|
||
struct exynos_usbphy_info *usbphy_info, u8 eq_fix)
|
||
{
|
||
u16 reg;
|
||
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, 0x1006);
|
||
if (eq_fix) {
|
||
reg |= (1 << 6);
|
||
reg &= ~(1 << 7);
|
||
} else {
|
||
reg &= ~(1 << 6);
|
||
reg |= (1 << 7);
|
||
}
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1006, reg);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_tune_chg_rxeq(
|
||
struct exynos_usbphy_info *usbphy_info, u8 eq_val)
|
||
{
|
||
u16 reg;
|
||
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, 0x1006);
|
||
reg &= ~(0x7 << 0x8);
|
||
reg |= ((eq_val & 0x7) << 8);
|
||
reg |= (1 << 11);
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1006, reg);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_dp_altmode_set_phy_enable(
|
||
struct exynos_usbphy_info *usbphy_info, int dp_phy_port)
|
||
{
|
||
void __iomem *base;
|
||
u32 reg;
|
||
u32 powerdown_ssp;
|
||
|
||
if (dp_phy_port != -1) {
|
||
if (dp_phy_port == 0)
|
||
base = usbphy_info->regs_base;
|
||
else
|
||
base = usbphy_info->regs_base_2nd;
|
||
|
||
} else
|
||
base = usbphy_info->regs_base;
|
||
|
||
/* powerdown_ssp -> disable */
|
||
reg = readl(base + EXYNOS_USBCON_PHYTEST);
|
||
powerdown_ssp = PHYTEST_POWERDOWN_SSP_EXT(reg);
|
||
|
||
/* when reverse connection as DP Alt mode, usb hs of phy0 should not be reset. */
|
||
if (dp_phy_port == 0 && powerdown_ssp == 0)
|
||
return;
|
||
|
||
reg &= ~PHYTEST_POWERDOWN_SSP;
|
||
writel(reg, base + EXYNOS_USBCON_PHYTEST);
|
||
|
||
/* PHY_RESET_SEL -> 1 */
|
||
reg = readl(base + EXYNOS_USBCON_PHYPARAM1);
|
||
reg |= PHYPARAM1_PHY_RESET_SEL;
|
||
writel(reg, base + EXYNOS_USBCON_PHYPARAM1);
|
||
|
||
/* phy_sw_rst -> 1 */
|
||
reg = readl(base + EXYNOS_USBCON_LINKSYSTEM);
|
||
reg |= LINKSYSTEM_PHY_SW_RESET;
|
||
writel(reg, base + EXYNOS_USBCON_LINKSYSTEM);
|
||
|
||
udelay(10);
|
||
|
||
/* phy_sw_rst -> 0 */
|
||
reg = readl(base + EXYNOS_USBCON_LINKSYSTEM);
|
||
reg &= ~LINKSYSTEM_PHY_SW_RESET;
|
||
writel(reg, base + EXYNOS_USBCON_LINKSYSTEM);
|
||
|
||
udelay(10);
|
||
|
||
/* PHY_RESET_SEL -> 0 */
|
||
reg = readl(base + EXYNOS_USBCON_PHYPARAM1);
|
||
reg &= ~PHYPARAM1_PHY_RESET_SEL;
|
||
writel(reg, base + EXYNOS_USBCON_PHYPARAM1);
|
||
|
||
udelay(75);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_dp_altmode_clear_phy_enable(
|
||
struct exynos_usbphy_info *usbphy_info, int dp_phy_port)
|
||
{
|
||
void __iomem *base;
|
||
u32 reg;
|
||
|
||
if (dp_phy_port != -1) {
|
||
if (dp_phy_port == 0)
|
||
base = usbphy_info->regs_base;
|
||
else
|
||
base = usbphy_info->regs_base_2nd;
|
||
|
||
} else
|
||
base = usbphy_info->regs_base;
|
||
|
||
/* powerdown_ssp -> enable */
|
||
reg = readl(base + EXYNOS_USBCON_PHYTEST);
|
||
reg |= PHYTEST_POWERDOWN_SSP;
|
||
writel(reg, base + EXYNOS_USBCON_PHYTEST);
|
||
|
||
/* PHY_RESET_SEL -> 1 */
|
||
reg = readl(base + EXYNOS_USBCON_PHYPARAM1);
|
||
reg |= PHYPARAM1_PHY_RESET_SEL;
|
||
writel(reg, base + EXYNOS_USBCON_PHYPARAM1);
|
||
|
||
/* phy_sw_rst -> 1 */
|
||
reg = readl(base + EXYNOS_USBCON_LINKSYSTEM);
|
||
reg |= LINKSYSTEM_PHY_SW_RESET;
|
||
writel(reg, base + EXYNOS_USBCON_LINKSYSTEM);
|
||
|
||
udelay(10);
|
||
|
||
/* phy_sw_rst -> 0 */
|
||
reg = readl(base + EXYNOS_USBCON_LINKSYSTEM);
|
||
reg &= ~LINKSYSTEM_PHY_SW_RESET;
|
||
writel(reg, base + EXYNOS_USBCON_LINKSYSTEM);
|
||
|
||
udelay(10);
|
||
|
||
/* PHY_RESET_SEL -> 0 */
|
||
reg = readl(base + EXYNOS_USBCON_PHYPARAM1);
|
||
reg &= ~PHYPARAM1_PHY_RESET_SEL;
|
||
writel(reg, base + EXYNOS_USBCON_PHYPARAM1);
|
||
|
||
udelay(75);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_dp_altmode_set_ss_disable(
|
||
struct exynos_usbphy_info *usbphy_info, int dp_phy_port)
|
||
{
|
||
u32 addr, reg;
|
||
|
||
/* backup used_phy_port */
|
||
int used_phy_port_org = usbphy_info->used_phy_port;
|
||
usbphy_info->used_phy_port = dp_phy_port;
|
||
|
||
/* SUP.MPLL_OVRD_IN_LO 16<31><36>h11
|
||
[1] MPLL_EN_OVRD = 1
|
||
[0] MPLL_EN = 0 */
|
||
addr = 0x0011;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<0)) | 0x2<<0;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.TX_OVRD_IN_LO 16'h1N00
|
||
[9] TX_CM_EN_OVRD = 1
|
||
[8] TX_CM_EN = 0 */
|
||
addr = 0x1000;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<8)) | 0x2<<8;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_LO 16'h1N05
|
||
[13] RX_LOS_EN_OVRD = 1
|
||
[12] RX_LOS_EN = 1 */
|
||
addr = 0x1005;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<12)) | 0x3<<12;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.TX_OVRD_IN_LO 16'h1N00
|
||
[7] TX_EN_OVRD = 1
|
||
[6] TX_EN = 0
|
||
[5] TX_DATA_EN_OVRD = 1
|
||
[4] TX_DATA_EN = 0 */
|
||
addr = 0x1000;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0xf<<4)) | 0xa<<4;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_LO 16'h1N05
|
||
[5] RX_DATA_EN_OVRD = 1
|
||
[4] RX_DATA_EN = 0
|
||
[3] RX_PLL_EN_OVRD = 1
|
||
[2] RX_PLL_EN = 0*/
|
||
addr = 0x1005;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0xf<<2)) | 0xa<<2;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_LO 16'h1N05
|
||
[11] RX_TERM_EN_OVRD = 1
|
||
[10] RX_TERM_EN = 0*/
|
||
addr = 0x1005;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x2<<10)) | 0x2<<10;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_HI 16'h1N06
|
||
[13] RX_RESET_OVRD = 1
|
||
[12] RX_RESET = 1*/
|
||
addr = 0x1006;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<12)) | 0x3<<12;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* restore used_phy_port */
|
||
usbphy_info->used_phy_port = used_phy_port_org;
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_dp_altmode_clear_ss_disable(
|
||
struct exynos_usbphy_info *usbphy_info, int dp_phy_port)
|
||
{
|
||
u32 addr, reg;
|
||
|
||
/* backup used_phy_port */
|
||
int used_phy_port_org = usbphy_info->used_phy_port;
|
||
usbphy_info->used_phy_port = dp_phy_port;
|
||
|
||
/* SUP.MPLL_OVRD_IN_LO 16<31><36>h11
|
||
[1] MPLL_EN_OVRD = 0
|
||
[0] MPLL_EN = 0*/
|
||
addr = 0x0011;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<0)) | 0x0<<0;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.TX_OVRD_IN_LO 16'h1N00
|
||
[9] TX_CM_EN_OVRD = 0
|
||
[8] TX_CM_EN = 0 */
|
||
addr = 0x1000;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<8)) | 0x0<<8;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_LO 16'h1N05
|
||
[13] RX_LOS_EN_OVRD = 0
|
||
[12] RX_LOS_EN = 0 */
|
||
addr = 0x1005;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<12)) | 0x0<<12;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.TX_OVRD_IN_LO 16'h1N00
|
||
[7] TX_EN_OVRD = 0
|
||
[6] TX_EN = 0
|
||
[5] TX_DATA_EN_OVRD = 0
|
||
[4] TX_DATA_EN = 0 */
|
||
addr = 0x1000;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0xf<<4)) | 0x0<<4;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_LO 16'h1N05
|
||
[5] RX_DATA_EN_OVRD = 0
|
||
[4] RX_DATA_EN = 0
|
||
[3] RX_PLL_EN_OVRD = 0
|
||
[2] RX_PLL_EN = 0 */
|
||
addr = 0x1005;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0xf<<2)) | 0x0<<2;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_LO 16'h1N05
|
||
[11] RX_TERM_EN_OVRD = 0
|
||
[10] RX_TERM_EN = 0*/
|
||
addr = 0x1005;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x2<<10)) | 0x0<<10;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* LANEN.RX_OVRD_IN_HI 16'h1N06
|
||
[13] RX_RESET_OVRD = 0
|
||
[12] RX_RESET = 0*/
|
||
addr = 0x1006;
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, addr);
|
||
reg = (reg & ~(0x3<<12)) | 0x0<<12;
|
||
samsung_exynos_cal_cr_write(usbphy_info, addr, reg);
|
||
|
||
/* restore used_phy_port */
|
||
usbphy_info->used_phy_port = used_phy_port_org;
|
||
}
|
||
|
||
static void exynos_cal_ss_enable(struct exynos_usbphy_info *info,
|
||
u32 *arg_phyclkrst, u8 port_num)
|
||
{
|
||
u32 phyclkrst = *arg_phyclkrst;
|
||
u32 phypipe;
|
||
u32 phyparam0;
|
||
u32 phyreg0;
|
||
void *reg_base;
|
||
|
||
if (port_num == 0)
|
||
reg_base = info->regs_base;
|
||
else
|
||
reg_base = info->regs_base_2nd;
|
||
|
||
if (info->common_block_disable) {
|
||
/* Disable Common Block in suspend/sleep mode */
|
||
if (info->version < EXYNOS_USBCON_VER_01_0_1)
|
||
phyclkrst &= ~PHYCLKRST_COMMONONN;
|
||
else
|
||
phyclkrst |= PHYCLKRST_COMMONONN;
|
||
} else {
|
||
/* Enable Common Block in suspend/sleep mode */
|
||
if (info->version < EXYNOS_USBCON_VER_01_0_1)
|
||
phyclkrst |= PHYCLKRST_COMMONONN;
|
||
else
|
||
phyclkrst &= ~PHYCLKRST_COMMONONN;
|
||
}
|
||
/* Disable Common block control by link */
|
||
phyclkrst &= ~PHYCLKRST_EN_UTMISUSPEND;
|
||
|
||
/* Digital Supply Mode : normal operating mode */
|
||
phyclkrst |= PHYCLKRST_RETENABLEN;
|
||
|
||
/* ref. clock enable for ss function */
|
||
phyclkrst |= PHYCLKRST_REF_SSP_EN;
|
||
|
||
phyparam0 = readl(info->regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
if (info->refsel == USBPHY_REFSEL_DIFF_PAD)
|
||
phyparam0 |= PHYPARAM0_REF_USE_PAD;
|
||
else
|
||
phyparam0 &= ~PHYPARAM0_REF_USE_PAD;
|
||
writel(phyparam0, reg_base + EXYNOS_USBCON_PHYPARAM0);
|
||
|
||
if (info->version >= EXYNOS_USBCON_VER_01_0_1)
|
||
phyreg0 = readl(reg_base + EXYNOS_USBCON_PHYREG0);
|
||
|
||
switch (info->refclk) {
|
||
case USBPHY_REFCLK_DIFF_100MHZ:
|
||
phyclkrst &= ~PHYCLKRST_MPLL_MULTIPLIER_MASK;
|
||
phyclkrst |= PHYCLKRST_MPLL_MULTIPLIER(0x00);
|
||
phyclkrst &= ~PHYCLKRST_REF_CLKDIV2;
|
||
if (info->version == EXYNOS_USBCON_VER_01_0_1) {
|
||
phyreg0 &= ~PHYREG0_SSC_REFCLKSEL_MASK;
|
||
phyreg0 |= PHYREG0_SSC_REFCLKSEL(0x00);
|
||
} else {
|
||
phyclkrst &= ~PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||
phyclkrst |= PHYCLKRST_SSC_REFCLKSEL(0x00);
|
||
}
|
||
break;
|
||
case USBPHY_REFCLK_DIFF_26MHZ:
|
||
case USBPHY_REFCLK_DIFF_52MHZ:
|
||
phyclkrst &= ~PHYCLKRST_MPLL_MULTIPLIER_MASK;
|
||
phyclkrst |= PHYCLKRST_MPLL_MULTIPLIER(0x60);
|
||
if (info->refclk & 0x40)
|
||
phyclkrst |= PHYCLKRST_REF_CLKDIV2;
|
||
else
|
||
phyclkrst &= ~PHYCLKRST_REF_CLKDIV2;
|
||
if (info->version == EXYNOS_USBCON_VER_01_0_1) {
|
||
phyreg0 &= ~PHYREG0_SSC_REFCLKSEL_MASK;
|
||
phyreg0 |= PHYREG0_SSC_REFCLKSEL(0x108);
|
||
} else {
|
||
phyclkrst &= ~PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||
phyclkrst |= PHYCLKRST_SSC_REFCLKSEL(0x108);
|
||
}
|
||
break;
|
||
case USBPHY_REFCLK_DIFF_24MHZ:
|
||
case USBPHY_REFCLK_EXT_24MHZ:
|
||
phyclkrst &= ~PHYCLKRST_MPLL_MULTIPLIER_MASK;
|
||
phyclkrst |= PHYCLKRST_MPLL_MULTIPLIER(0x00);
|
||
phyclkrst &= ~PHYCLKRST_REF_CLKDIV2;
|
||
if (info->version != EXYNOS_USBCON_VER_01_0_1) {
|
||
phyclkrst &= ~PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||
phyclkrst |= PHYCLKRST_SSC_REFCLKSEL(0x88);
|
||
} else {
|
||
phyreg0 &= ~PHYREG0_SSC_REFCLKSEL_MASK;
|
||
phyreg0 |= PHYREG0_SSC_REFCLKSEL(0x88);
|
||
}
|
||
break;
|
||
case USBPHY_REFCLK_DIFF_20MHZ:
|
||
case USBPHY_REFCLK_DIFF_19_2MHZ:
|
||
phyclkrst &= ~PHYCLKRST_MPLL_MULTIPLIER_MASK;
|
||
phyclkrst &= ~PHYCLKRST_REF_CLKDIV2;
|
||
if (info->version == EXYNOS_USBCON_VER_01_0_1)
|
||
phyreg0 &= ~PHYREG0_SSC_REFCLKSEL_MASK;
|
||
else
|
||
phyclkrst &= ~PHYCLKRST_SSC_REFCLKSEL_MASK;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
/* SSC Enable */
|
||
if (info->ss_tune) {
|
||
u32 range = info->ss_tune->ssc_range;
|
||
|
||
if (info->ss_tune->enable_ssc)
|
||
phyclkrst |= PHYCLKRST_SSC_EN;
|
||
else
|
||
phyclkrst &= ~PHYCLKRST_SSC_EN;
|
||
|
||
if (info->version != EXYNOS_USBCON_VER_01_0_1) {
|
||
phyclkrst &= ~PHYCLKRST_SSC_RANGE_MASK;
|
||
phyclkrst |= PHYCLKRST_SSC_RANGE(range);
|
||
} else {
|
||
phyreg0 &= ~PHYREG0_SSC_RANGE_MASK;
|
||
phyreg0 |= PHYREG0_SSC_RAMGE(range);
|
||
}
|
||
} else {
|
||
/* Default Value : SSC Enable */
|
||
phyclkrst |= PHYCLKRST_SSC_EN;
|
||
if (info->version != EXYNOS_USBCON_VER_01_0_1) {
|
||
phyclkrst &= ~PHYCLKRST_SSC_RANGE_MASK;
|
||
phyclkrst |= PHYCLKRST_SSC_RANGE(0x0);
|
||
} else {
|
||
phyreg0 &= ~PHYREG0_SSC_RANGE_MASK;
|
||
phyreg0 |= PHYREG0_SSC_RAMGE(0x0);
|
||
}
|
||
}
|
||
|
||
/* Select UTMI CLOCK 0 : PHY CLOCK, 1 : FREE CLOCK */
|
||
phypipe = readl(reg_base + EXYNOS_USBCON_PHYPIPE);
|
||
phypipe |= PHYPIPE_PHY_CLOCK_SEL;
|
||
writel(phypipe, reg_base + EXYNOS_USBCON_PHYPIPE);
|
||
|
||
if (info->version >= EXYNOS_USBCON_VER_01_0_1)
|
||
writel(phyreg0, reg_base + EXYNOS_USBCON_PHYREG0);
|
||
|
||
*arg_phyclkrst = phyclkrst;
|
||
}
|
||
|
||
static void exynos_cal_ss_power_down(struct exynos_usbphy_info *info, bool en)
|
||
{
|
||
u32 phytest;
|
||
u32 phyutmi;
|
||
|
||
phytest = readl(info->regs_base + EXYNOS_USBCON_PHYTEST);
|
||
if (en == 1) {
|
||
phytest &= ~PHYTEST_POWERDOWN_HSP;
|
||
phytest &= ~PHYTEST_POWERDOWN_SSP;
|
||
writel(phytest, info->regs_base + EXYNOS_USBCON_PHYTEST);
|
||
if (info->used_phy_port == 1) {
|
||
void *reg_base = info->regs_base_2nd;
|
||
#if 0 /* when reverse connection as DP Alt mode, early set powerdown_ssp of phy0 to 0. */
|
||
phytest |= PHYTEST_POWERDOWN_SSP;
|
||
writel(phytest, info->regs_base + EXYNOS_USBCON_PHYTEST);
|
||
#endif
|
||
|
||
phytest = readl(reg_base + EXYNOS_USBCON_PHYTEST);
|
||
phytest &= ~PHYTEST_POWERDOWN_SSP;
|
||
writel(phytest, reg_base + EXYNOS_USBCON_PHYTEST);
|
||
|
||
/* force suspend phy1 hs */
|
||
phyutmi = readl(reg_base + EXYNOS_USBCON_PHYUTMI);
|
||
phyutmi |= PHYUTMI_FORCESLEEP;
|
||
phyutmi |= PHYUTMI_FORCESUSPEND;
|
||
writel(phyutmi, reg_base + EXYNOS_USBCON_PHYUTMI);
|
||
}
|
||
} else {
|
||
phytest |= PHYTEST_POWERDOWN_HSP;
|
||
phytest |= PHYTEST_POWERDOWN_SSP;
|
||
writel(phytest, info->regs_base + EXYNOS_USBCON_PHYTEST);
|
||
if (info->used_phy_port == 1) {
|
||
void *reg_base = info->regs_base_2nd;
|
||
|
||
phytest = readl(reg_base + EXYNOS_USBCON_PHYTEST);
|
||
phytest |= PHYTEST_POWERDOWN_HSP;
|
||
phytest |= PHYTEST_POWERDOWN_SSP;
|
||
writel(phytest, reg_base + EXYNOS_USBCON_PHYTEST);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void exynos_cal_hs_enable(struct exynos_usbphy_info *info,
|
||
u32 *arg_phyclkrst)
|
||
{
|
||
u32 phyclkrst = *arg_phyclkrst;
|
||
u32 hsphyplltune;
|
||
|
||
if(info->version == EXYNOS_USBCON_VER_02_1_2)
|
||
hsphyplltune = readl(info->regs_base + EXYNOS_USBCON_HSPHYPLLTUNE_K1);
|
||
else
|
||
hsphyplltune = readl(info->regs_base + EXYNOS_USBCON_HSPHYPLLTUNE);
|
||
|
||
if ((info->version & 0xf0) >= 0x10) {
|
||
/* Disable Common block control by link */
|
||
phyclkrst |= PHYCLKRST_EN_UTMISUSPEND;
|
||
phyclkrst |= PHYCLKRST_COMMONONN;
|
||
} else {
|
||
phyclkrst |= PHYCLKRST_EN_UTMISUSPEND;
|
||
phyclkrst |= PHYCLKRST_COMMONONN;
|
||
}
|
||
|
||
/* Change PHY PLL Tune value */
|
||
if (info->refclk == USBPHY_REFCLK_EXT_24MHZ)
|
||
hsphyplltune |= HSPHYPLLTUNE_PLL_B_TUNE;
|
||
else
|
||
hsphyplltune &= ~HSPHYPLLTUNE_PLL_B_TUNE;
|
||
hsphyplltune |= HSPHYPLLTUNE_PLL_P_TUNE(0xe);
|
||
|
||
if(info->version == EXYNOS_USBCON_VER_02_1_2)
|
||
writel(hsphyplltune, info->regs_base + EXYNOS_USBCON_HSPHYPLLTUNE_K1);
|
||
else
|
||
writel(hsphyplltune, info->regs_base + EXYNOS_USBCON_HSPHYPLLTUNE);
|
||
|
||
*arg_phyclkrst = phyclkrst;
|
||
}
|
||
|
||
static void exynos_cal_hs_power_down(struct exynos_usbphy_info *info, bool en)
|
||
{
|
||
u32 hsphyctrl;
|
||
|
||
hsphyctrl = readl(info->regs_base + EXYNOS_USBCON_HSPHYCTRL);
|
||
if (en) {
|
||
if(info->version == EXYNOS_USBCON_VER_02_1_2)
|
||
hsphyctrl &= ~HSPHYCTRL_SIDDQ_K1;
|
||
else
|
||
hsphyctrl &= ~HSPHYCTRL_SIDDQ;
|
||
hsphyctrl &= ~HSPHYCTRL_PHYSWRST;
|
||
hsphyctrl &= ~HSPHYCTRL_PHYSWRSTALL;
|
||
} else {
|
||
if(info->version == EXYNOS_USBCON_VER_02_1_2)
|
||
hsphyctrl |= HSPHYCTRL_SIDDQ_K1;
|
||
else
|
||
hsphyctrl |= HSPHYCTRL_SIDDQ;
|
||
}
|
||
writel(hsphyctrl, info->regs_base + EXYNOS_USBCON_HSPHYCTRL);
|
||
}
|
||
|
||
static void exynos_cal_usbphy_q_ch(void *regs_base, u8 enable)
|
||
{
|
||
u32 phy_resume;
|
||
|
||
if (enable) {
|
||
/* WA for Q-channel: disable all q-act from usb */
|
||
phy_resume = readl(regs_base + EXYNOS_USBCON_PHYRESUME);
|
||
phy_resume |= PHYRESUME_DIS_ID0_QACT;
|
||
phy_resume |= PHYRESUME_DIS_VBUSVALID_QACT;
|
||
phy_resume |= PHYRESUME_DIS_BVALID_QACT;
|
||
phy_resume |= PHYRESUME_DIS_LINKGATE_QACT;
|
||
//phy_resume |= PHYRESUME_DIS_BUSPEND_QACT;
|
||
phy_resume &= ~PHYRESUME_FORCE_QACT;
|
||
udelay(500);
|
||
writel(phy_resume, regs_base + EXYNOS_USBCON_PHYRESUME);
|
||
udelay(500);
|
||
phy_resume = readl(regs_base + EXYNOS_USBCON_PHYRESUME);
|
||
phy_resume |= PHYRESUME_FORCE_QACT;
|
||
udelay(500);
|
||
writel(phy_resume, regs_base + EXYNOS_USBCON_PHYRESUME);
|
||
} else {
|
||
phy_resume = readl(regs_base + EXYNOS_USBCON_PHYRESUME);
|
||
phy_resume &= ~PHYRESUME_FORCE_QACT;
|
||
phy_resume |= PHYRESUME_DIS_ID0_QACT;
|
||
phy_resume |= PHYRESUME_DIS_VBUSVALID_QACT;
|
||
phy_resume |= PHYRESUME_DIS_BVALID_QACT;
|
||
phy_resume |= PHYRESUME_DIS_LINKGATE_QACT;
|
||
//phy_resume |= PHYRESUME_DIS_BUSPEND_QACT;
|
||
writel(phy_resume, regs_base + EXYNOS_USBCON_PHYRESUME);
|
||
}
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_enable(struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 version = usbphy_info->version;
|
||
enum exynos_usbphy_refclk refclkfreq = usbphy_info->refclk;
|
||
u32 phyutmi;
|
||
u32 phyclkrst;
|
||
u32 linkport;
|
||
|
||
/* check phycon version */
|
||
if (!usbphy_info->hw_version) {
|
||
u32 phyversion = readl(regs_base);
|
||
|
||
if (!phyversion) {
|
||
usbphy_info->hw_version = -1;
|
||
usbphy_info->used_phy_port = -1;
|
||
} else {
|
||
usbphy_info->hw_version = phyversion;
|
||
usbphy_info->regs_base += 4;
|
||
regs_base = usbphy_info->regs_base;
|
||
|
||
if (usbphy_info->regs_base_2nd)
|
||
usbphy_info->regs_base_2nd += 4;
|
||
}
|
||
}
|
||
|
||
/* Set force q-channel */
|
||
if ((version & 0xf) >= 0x01)
|
||
exynos_cal_usbphy_q_ch(regs_base, 1);
|
||
|
||
/* Select PHY MUX */
|
||
if (usbphy_info->used_phy_port != -1) {
|
||
u32 physel;
|
||
|
||
physel = readl(regs_base + EXYNOS_USBCON_PHYSELECTION);
|
||
if (usbphy_info->used_phy_port == 0) {
|
||
physel &= ~PHYSEL_PIPE;
|
||
physel &= ~PHYSEL_PIPE_CLK;
|
||
#if defined(USB_MUX_UTMI_ENABLE)
|
||
/* UE_TASK: for utmi 2nd port test : will be removed */
|
||
physel &= ~PHYSEL_UTMI_CLK;
|
||
physel &= ~PHYSEL_UTMI;
|
||
physel &= ~PHYSEL_SIDEBAND;
|
||
#endif
|
||
} else {
|
||
physel |= PHYSEL_PIPE;
|
||
physel |= PHYSEL_PIPE_CLK;
|
||
#if defined(USB_MUX_UTMI_ENABLE)
|
||
/* UE_TASK: for utmi 2nd port test : will be removed */
|
||
physel |= PHYSEL_UTMI_CLK;
|
||
physel |= PHYSEL_UTMI;
|
||
physel |= PHYSEL_SIDEBAND;
|
||
#endif
|
||
}
|
||
writel(physel, regs_base + EXYNOS_USBCON_PHYSELECTION);
|
||
}
|
||
|
||
/* set phy clock & control HS phy */
|
||
phyclkrst = readl(regs_base + EXYNOS_USBCON_PHYCLKRST);
|
||
|
||
/* assert port_reset */
|
||
phyclkrst |= PHYCLKRST_PORTRESET;
|
||
|
||
/* Select Reference clock source path */
|
||
phyclkrst &= ~PHYCLKRST_REFCLKSEL_MASK;
|
||
phyclkrst |= PHYCLKRST_REFCLKSEL(usbphy_info->refsel);
|
||
|
||
/* Select ref clk */
|
||
phyclkrst &= ~PHYCLKRST_FSEL_MASK;
|
||
phyclkrst |= PHYCLKRST_FSEL(refclkfreq & 0x3f);
|
||
|
||
/* Additional control for 3.0 PHY */
|
||
if ((EXYNOS_USBCON_VER_01_0_0 <= version)
|
||
&& (version <= EXYNOS_USBCON_VER_01_MAX)) {
|
||
exynos_cal_ss_enable(usbphy_info, &phyclkrst, 0);
|
||
/* select used phy port */
|
||
if (usbphy_info->used_phy_port == 1) {
|
||
void *reg_2nd = usbphy_info->regs_base_2nd;
|
||
|
||
exynos_cal_ss_enable(usbphy_info, &phyclkrst, 1);
|
||
|
||
writel(phyclkrst,
|
||
reg_2nd + EXYNOS_USBCON_PHYCLKRST);
|
||
udelay(10);
|
||
|
||
phyclkrst &= ~PHYCLKRST_PORTRESET;
|
||
writel(phyclkrst,
|
||
reg_2nd + EXYNOS_USBCON_PHYCLKRST);
|
||
|
||
phyclkrst |= PHYCLKRST_PORTRESET;
|
||
}
|
||
} else if ((EXYNOS_USBCON_VER_02_0_0 <= version)
|
||
&& (version <= EXYNOS_USBCON_VER_02_MAX))
|
||
exynos_cal_hs_enable(usbphy_info, &phyclkrst);
|
||
|
||
writel(phyclkrst, regs_base + EXYNOS_USBCON_PHYCLKRST);
|
||
udelay(10);
|
||
|
||
phyclkrst &= ~PHYCLKRST_PORTRESET;
|
||
writel(phyclkrst, regs_base + EXYNOS_USBCON_PHYCLKRST);
|
||
|
||
if ((EXYNOS_USBCON_VER_01_0_0 <= version)
|
||
&& (version <= EXYNOS_USBCON_VER_01_MAX)) {
|
||
exynos_cal_ss_power_down(usbphy_info, 1);
|
||
} else if (version >= EXYNOS_USBCON_VER_02_0_0
|
||
&& version <= EXYNOS_USBCON_VER_02_MAX) {
|
||
exynos_cal_hs_power_down(usbphy_info, 1);
|
||
}
|
||
udelay(500);
|
||
|
||
/* release force_sleep & force_suspend */
|
||
phyutmi = readl(regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
phyutmi &= ~PHYUTMI_FORCESLEEP;
|
||
phyutmi &= ~PHYUTMI_FORCESUSPEND;
|
||
|
||
/* DP/DM Pull Down Control */
|
||
phyutmi &= ~PHYUTMI_DMPULLDOWN;
|
||
phyutmi &= ~PHYUTMI_DPPULLDOWN;
|
||
|
||
/* Set VBUSVALID signal if VBUS pad is not used */
|
||
if (usbphy_info->not_used_vbus_pad) {
|
||
u32 linksystem;
|
||
|
||
linksystem = readl(regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
linksystem |= LINKSYSTEM_FORCE_BVALID;
|
||
linksystem |= LINKSYSTEM_FORCE_VBUSVALID;
|
||
writel(linksystem, regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
#if defined(USB_MUX_UTMI_ENABLE)
|
||
/* UE_TASK: for utmi 2nd port test : will be removed */
|
||
if (usbphy_info->regs_base_2nd && usbphy_info->used_phy_port == 1) {
|
||
linksystem = readl(usbphy_info->regs_base_2nd + EXYNOS_USBCON_LINKSYSTEM);
|
||
linksystem |= LINKSYSTEM_FORCE_BVALID;
|
||
linksystem |= LINKSYSTEM_FORCE_VBUSVALID;
|
||
writel(linksystem, usbphy_info->regs_base_2nd + EXYNOS_USBCON_LINKSYSTEM);
|
||
}
|
||
#endif
|
||
phyutmi |= PHYUTMI_VBUSVLDEXTSEL;
|
||
phyutmi |= PHYUTMI_VBUSVLDEXT;
|
||
}
|
||
|
||
/* disable OTG block and VBUS valid comparator */
|
||
phyutmi &= ~PHYUTMI_DRVVBUS;
|
||
phyutmi |= PHYUTMI_OTGDISABLE;
|
||
writel(phyutmi, regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
|
||
#if defined(USB_MUX_UTMI_ENABLE)
|
||
/* UE_TASK: for utmi 2nd port test : will be removed */
|
||
if (usbphy_info->regs_base_2nd && usbphy_info->used_phy_port == 1)
|
||
writel(phyutmi, usbphy_info->regs_base_2nd + EXYNOS_USBCON_PHYUTMI);
|
||
#endif
|
||
|
||
/* OVC io usage */
|
||
linkport = readl(regs_base + EXYNOS_USBCON_LINKPORT);
|
||
if (usbphy_info->use_io_for_ovc) {
|
||
linkport &= ~LINKPORT_HOST_PORT_OVCR_U3_SEL;
|
||
linkport &= ~LINKPORT_HOST_PORT_OVCR_U2_SEL;
|
||
} else {
|
||
linkport |= LINKPORT_HOST_PORT_OVCR_U3_SEL;
|
||
linkport |= LINKPORT_HOST_PORT_OVCR_U2_SEL;
|
||
}
|
||
writel(linkport, regs_base + EXYNOS_USBCON_LINKPORT);
|
||
|
||
if ((EXYNOS_USBCON_VER_02_0_0 <= version)
|
||
&& (version <= EXYNOS_USBCON_VER_02_MAX)) {
|
||
|
||
u32 hsphyctrl;
|
||
|
||
hsphyctrl = readl(regs_base + EXYNOS_USBCON_HSPHYCTRL);
|
||
hsphyctrl |= HSPHYCTRL_PHYSWRST;
|
||
writel(hsphyctrl, regs_base + EXYNOS_USBCON_HSPHYCTRL);
|
||
udelay(20);
|
||
hsphyctrl = readl(regs_base + EXYNOS_USBCON_HSPHYCTRL);
|
||
hsphyctrl &= ~HSPHYCTRL_PHYSWRST;
|
||
writel(hsphyctrl, regs_base + EXYNOS_USBCON_HSPHYCTRL);
|
||
}
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_late_enable(
|
||
struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
u32 version = usbphy_info->version;
|
||
struct exynos_usbphy_ss_tune *tune = usbphy_info->ss_tune;
|
||
|
||
if (EXYNOS_USBCON_VER_01_0_0 <= version
|
||
&& version <= EXYNOS_USBCON_VER_01_MAX) {
|
||
/* Set RXDET_MEAS_TIME[11:4] each reference clock */
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1010, 0x80);
|
||
if (tune) {
|
||
#if defined(USB_SS_TX_TUNE_PCS)
|
||
samsung_exynos_cal_cr_write(usbphy_info,
|
||
0x1002, 0x4000 |
|
||
(tune->tx_deemphasis_3p5db << 7) |
|
||
tune->tx_swing_full);
|
||
#else
|
||
samsung_exynos_cal_cr_write(usbphy_info, 0x1002, 0x0);
|
||
#endif
|
||
/* Set RX_SCOPE_LFPS_EN */
|
||
if (tune->rx_decode_mode) {
|
||
samsung_exynos_cal_cr_write(usbphy_info,
|
||
0x1026, 0x1);
|
||
}
|
||
if (tune->set_crport_level_en) {
|
||
/* Enable override los_bias, los_level and
|
||
* tx_vboost_lvl, Set los_bias to 0x5 and
|
||
* los_level to 0x9 */
|
||
samsung_exynos_cal_cr_write(usbphy_info,
|
||
0x15, 0xA409);
|
||
/* Set TX_VBOOST_LEVLE to tune->tx_boost_level */
|
||
samsung_exynos_cal_cr_write(usbphy_info,
|
||
0x12, tune->tx_boost_level<<13);
|
||
}
|
||
/* to set the charge pump proportional current */
|
||
if (tune->set_crport_mpll_charge_pump) {
|
||
samsung_exynos_cal_cr_write(usbphy_info,
|
||
0x30, 0xC0);
|
||
}
|
||
if (tune->enable_fixed_rxeq_mode) {
|
||
samsung_exynos_cal_usb3phy_tune_fix_rxeq(
|
||
usbphy_info);
|
||
}
|
||
}
|
||
|
||
/* when reverse connection as DP Alt mode, early set ss_disable for power reduction. */
|
||
if (usbphy_info->used_phy_port == 1)
|
||
samsung_exynos_cal_usb3phy_dp_altmode_set_ss_disable(usbphy_info, 0);
|
||
|
||
}
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_disable(struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 version = usbphy_info->version;
|
||
u32 phyutmi;
|
||
u32 phyclkrst;
|
||
|
||
phyclkrst = readl(regs_base + EXYNOS_USBCON_PHYCLKRST);
|
||
phyclkrst |= PHYCLKRST_EN_UTMISUSPEND;
|
||
phyclkrst |= PHYCLKRST_COMMONONN;
|
||
phyclkrst |= PHYCLKRST_RETENABLEN;
|
||
phyclkrst &= ~PHYCLKRST_REF_SSP_EN;
|
||
phyclkrst &= ~PHYCLKRST_SSC_EN;
|
||
/* Select Reference clock source path */
|
||
phyclkrst &= ~PHYCLKRST_REFCLKSEL_MASK;
|
||
phyclkrst |= PHYCLKRST_REFCLKSEL(usbphy_info->refsel);
|
||
|
||
/* Select ref clk */
|
||
phyclkrst &= ~PHYCLKRST_FSEL_MASK;
|
||
phyclkrst |= PHYCLKRST_FSEL(usbphy_info->refclk & 0x3f);
|
||
writel(phyclkrst, regs_base + EXYNOS_USBCON_PHYCLKRST);
|
||
|
||
phyutmi = readl(regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
phyutmi &= ~PHYUTMI_IDPULLUP;
|
||
phyutmi &= ~PHYUTMI_DRVVBUS;
|
||
phyutmi |= PHYUTMI_FORCESUSPEND;
|
||
phyutmi |= PHYUTMI_FORCESLEEP;
|
||
if (usbphy_info->not_used_vbus_pad) {
|
||
phyutmi &= ~PHYUTMI_VBUSVLDEXTSEL;
|
||
phyutmi &= ~PHYUTMI_VBUSVLDEXT;
|
||
}
|
||
writel(phyutmi, regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
|
||
if ((EXYNOS_USBCON_VER_01_0_0 <= version)
|
||
&& (version <= EXYNOS_USBCON_VER_01_MAX)) {
|
||
exynos_cal_ss_power_down(usbphy_info, 0);
|
||
} else if (version >= EXYNOS_USBCON_VER_02_0_0
|
||
&& version <= EXYNOS_USBCON_VER_02_MAX) {
|
||
exynos_cal_hs_power_down(usbphy_info, 0);
|
||
}
|
||
|
||
/* Clear VBUSVALID signal if VBUS pad is not used */
|
||
if (usbphy_info->not_used_vbus_pad) {
|
||
u32 linksystem;
|
||
|
||
linksystem = readl(regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
linksystem &= ~LINKSYSTEM_FORCE_BVALID;
|
||
linksystem &= ~LINKSYSTEM_FORCE_VBUSVALID;
|
||
writel(linksystem, regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
}
|
||
|
||
/* Set force q-channel */
|
||
if ((version & 0xf) >= 0x01)
|
||
exynos_cal_usbphy_q_ch(regs_base, 0);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_config_host_mode(
|
||
struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 phyutmi;
|
||
|
||
phyutmi = readl(regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
phyutmi |= PHYUTMI_DMPULLDOWN;
|
||
phyutmi |= PHYUTMI_DPPULLDOWN;
|
||
phyutmi &= ~PHYUTMI_VBUSVLDEXTSEL;
|
||
phyutmi &= ~PHYUTMI_VBUSVLDEXT;
|
||
writel(phyutmi, regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_enable_dp_pullup(
|
||
struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 phyutmi;
|
||
|
||
phyutmi = readl(regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
phyutmi |= PHYUTMI_VBUSVLDEXT;
|
||
writel(phyutmi, regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_disable_dp_pullup(
|
||
struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 phyutmi;
|
||
|
||
phyutmi = readl(regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
phyutmi &= ~PHYUTMI_VBUSVLDEXT;
|
||
writel(phyutmi, regs_base + EXYNOS_USBCON_PHYUTMI);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_tune_each(
|
||
struct exynos_usbphy_info *usbphy_info,
|
||
enum exynos_usbphy_tune_para para,
|
||
int val)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 reg;
|
||
|
||
#if defined(USB_MUX_UTMI_ENABLE)
|
||
/* UE_TASK: for utmi 2nd port test : will be removed */
|
||
if (usbphy_info->regs_base_2nd && usbphy_info->used_phy_port == 1)
|
||
regs_base = usbphy_info->regs_base_2nd;
|
||
#endif
|
||
|
||
if (para < 0x10000) {
|
||
struct exynos_usbphy_hs_tune *tune = usbphy_info->hs_tune;
|
||
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
switch ((int) para) {
|
||
case USBPHY_TUNE_HS_COMPDIS:
|
||
reg &= ~PHYPARAM0_COMPDISTUNE_MASK;
|
||
reg |= PHYPARAM0_COMPDISTUNE(val);
|
||
if (tune)
|
||
tune->compdis = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_OTG:
|
||
reg &= ~PHYPARAM0_OTGTUNE_MASK;
|
||
reg |= PHYPARAM0_OTGTUNE(val);
|
||
if (tune)
|
||
tune->otg = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_SQRX:
|
||
reg &= ~PHYPARAM0_SQRXTUNE_MASK;
|
||
reg |= PHYPARAM0_SQRXTUNE(val);
|
||
if (tune)
|
||
tune->rx_sqrx = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_TXFSLS:
|
||
reg &= ~PHYPARAM0_TXFSLSTUNE_MASK;
|
||
reg |= PHYPARAM0_TXFSLSTUNE(val);
|
||
if (tune)
|
||
tune->tx_fsls = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_TXHSXV:
|
||
reg &= ~PHYPARAM0_TXHSXVTUNE_MASK;
|
||
reg |= PHYPARAM0_TXHSXVTUNE(val);
|
||
if (tune)
|
||
tune->tx_hsxv = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_TXPREEMP:
|
||
reg &= ~PHYPARAM0_TXPREEMPAMPTUNE_MASK;
|
||
reg |= PHYPARAM0_TXPREEMPAMPTUNE(val);
|
||
if (tune)
|
||
tune->tx_pre_emp = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_TXPREEMP_PLUS:
|
||
if (val)
|
||
reg |= PHYPARAM0_TXPREEMPPULSETUNE;
|
||
else
|
||
reg &= ~PHYPARAM0_TXPREEMPPULSETUNE;
|
||
if (tune)
|
||
tune->tx_pre_emp_puls = val & 0x1;
|
||
break;
|
||
case USBPHY_TUNE_HS_TXRES:
|
||
reg &= ~PHYPARAM0_TXRESTUNE_MASK;
|
||
reg |= PHYPARAM0_TXRESTUNE(val);
|
||
if (tune)
|
||
tune->tx_res = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_TXRISE:
|
||
reg &= ~PHYPARAM0_TXRISETUNE_MASK;
|
||
reg |= PHYPARAM0_TXRISETUNE(val);
|
||
if (tune)
|
||
tune->tx_rise = val;
|
||
break;
|
||
case USBPHY_TUNE_HS_TXVREF:
|
||
reg &= ~PHYPARAM0_TXVREFTUNE_MASK;
|
||
reg |= PHYPARAM0_TXVREFTUNE(val);
|
||
if (tune)
|
||
tune->tx_vref = val;
|
||
break;
|
||
}
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
} else {
|
||
struct exynos_usbphy_ss_tune *tune = usbphy_info->ss_tune;
|
||
|
||
if (usbphy_info->used_phy_port != -1) {
|
||
if (usbphy_info->used_phy_port == 0)
|
||
regs_base = usbphy_info->regs_base;
|
||
else
|
||
regs_base = usbphy_info->regs_base_2nd;
|
||
}
|
||
|
||
switch ((int) para) {
|
||
case USBPHY_TUNE_SS_FIX_EQ:
|
||
samsung_exynos_cal_usb3phy_tune_adaptive_eq(usbphy_info,
|
||
val);
|
||
if (tune)
|
||
tune->enable_fixed_rxeq_mode = val & 0x1;
|
||
break;
|
||
case USBPHY_TUNE_SS_RX_EQ:
|
||
samsung_exynos_cal_usb3phy_tune_chg_rxeq(usbphy_info,
|
||
val);
|
||
if (tune)
|
||
tune->fix_rxeq_value = val & 0xf;
|
||
break;
|
||
case USBPHY_TUNE_SS_TX_BOOST:
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM2);
|
||
reg &= ~PHYPARAM2_TX_VBOOST_LVL_MASK;
|
||
reg |= PHYPARAM2_TX_VBOOST_LVL(val);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM2);
|
||
if (tune)
|
||
tune->tx_boost_level = val;
|
||
break;
|
||
case USBPHY_TUNE_SS_TX_SWING:
|
||
#if !defined(USB_SS_TX_TUNE_PCS)
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
reg &= ~PHYPARAM1_PCS_TXSWING_FULL_MASK;
|
||
reg |= PHYPARAM1_PCS_TXSWING_FULL(val);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
#else
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, 0x1002);
|
||
reg &= ~0x7f;
|
||
reg |= val;
|
||
samsung_exynos_cal_cr_write(usbphy_info,
|
||
0x1002, 0x4000 | reg);
|
||
#endif
|
||
if (tune)
|
||
tune->tx_swing_full = val;
|
||
break;
|
||
case USBPHY_TUNE_SS_TX_DEEMPHASIS:
|
||
#if !defined(USB_SS_TX_TUNE_PCS)
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
reg &= ~PHYPARAM1_PCS_TXDEEMPH_3P5DB_MASK;
|
||
reg |= PHYPARAM1_PCS_TXDEEMPH_3P5DB(val);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
#else
|
||
reg = samsung_exynos_cal_cr_read(usbphy_info, 0x1002);
|
||
reg &= ~(0x3f << 7);
|
||
reg |= (val & 0x3f) << 7;
|
||
samsung_exynos_cal_cr_write(usbphy_info,
|
||
0x1002, 0x4000 | reg);
|
||
#endif
|
||
if (tune)
|
||
tune->tx_deemphasis_3p5db = val;
|
||
break;
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_hs_tune_extract(
|
||
struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
struct exynos_usbphy_hs_tune *hs_tune;
|
||
u32 reg;
|
||
|
||
hs_tune = usbphy_info->hs_tune;
|
||
|
||
if (!hs_tune)
|
||
return;
|
||
|
||
reg = readl(usbphy_info->regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
|
||
hs_tune->tx_vref = PHYPARAM0_TXVREFTUNE_EXT(reg);
|
||
hs_tune->tx_rise = PHYPARAM0_TXRISETUNE_EXT(reg);
|
||
hs_tune->tx_res = PHYPARAM0_TXRESTUNE_EXT(reg);
|
||
hs_tune->tx_pre_emp_puls = PHYPARAM0_TXPREEMPPULSETUNE_EXT(reg);
|
||
hs_tune->tx_pre_emp = PHYPARAM0_TXPREEMPAMPTUNE_EXT(reg);
|
||
hs_tune->tx_hsxv = PHYPARAM0_TXHSXVTUNE_EXT(reg);
|
||
hs_tune->tx_fsls = PHYPARAM0_TXFSLSTUNE_EXT(reg);
|
||
hs_tune->rx_sqrx = PHYPARAM0_SQRXTUNE_EXT(reg);
|
||
hs_tune->otg = PHYPARAM0_OTGTUNE_EXT(reg);
|
||
hs_tune->compdis = PHYPARAM0_COMPDISTUNE_EXT(reg);
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_tune_dev(struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 reg;
|
||
|
||
#if defined(USB_MUX_UTMI_ENABLE)
|
||
/* UE_TASK: for utmi 2nd port test : will be removed */
|
||
if (usbphy_info->regs_base_2nd && usbphy_info->used_phy_port == 1)
|
||
regs_base = usbphy_info->regs_base_2nd;
|
||
#endif
|
||
|
||
/* Set the LINK Version Control and Frame Adjust Value */
|
||
reg = readl(regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
reg &= ~LINKSYSTEM_FLADJ_MASK;
|
||
reg |= LINKSYSTEM_FLADJ(0x20);
|
||
reg |= LINKSYSTEM_XHCI_VERSION_CONTROL;
|
||
writel(reg, regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
|
||
/* Tuning the HS Block of phy */
|
||
if (usbphy_info->hs_tune) {
|
||
struct exynos_usbphy_hs_tune *tune = usbphy_info->hs_tune;
|
||
|
||
/* Set tune value for 2.0(HS/FS) function */
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
/* TX VREF TUNE */
|
||
reg &= ~PHYPARAM0_TXVREFTUNE_MASK;
|
||
reg |= PHYPARAM0_TXVREFTUNE(tune->tx_vref);
|
||
/* TX RISE TUNE */
|
||
reg &= ~PHYPARAM0_TXRISETUNE_MASK;
|
||
reg |= PHYPARAM0_TXRISETUNE(tune->tx_rise);
|
||
/* TX RES TUNE */
|
||
reg &= ~PHYPARAM0_TXRESTUNE_MASK;
|
||
reg |= PHYPARAM0_TXRESTUNE(tune->tx_res);
|
||
/* TX PRE EMPHASIS PULS */
|
||
if (tune->tx_pre_emp_puls)
|
||
reg |= PHYPARAM0_TXPREEMPPULSETUNE;
|
||
else
|
||
reg &= ~PHYPARAM0_TXPREEMPPULSETUNE;
|
||
/* TX PRE EMPHASIS */
|
||
reg &= ~PHYPARAM0_TXPREEMPAMPTUNE_MASK;
|
||
reg |= PHYPARAM0_TXPREEMPAMPTUNE(tune->tx_pre_emp);
|
||
/* TX HS XV TUNE */
|
||
reg &= ~PHYPARAM0_TXHSXVTUNE_MASK;
|
||
reg |= PHYPARAM0_TXHSXVTUNE(tune->tx_hsxv);
|
||
/* TX FSLS TUNE */
|
||
reg &= ~PHYPARAM0_TXFSLSTUNE_MASK;
|
||
reg |= PHYPARAM0_TXFSLSTUNE(tune->tx_fsls);
|
||
/* RX SQ TUNE */
|
||
reg &= ~PHYPARAM0_SQRXTUNE_MASK;
|
||
reg |= PHYPARAM0_SQRXTUNE(tune->rx_sqrx);
|
||
/* OTG TUNE */
|
||
reg &= ~PHYPARAM0_OTGTUNE_MASK;
|
||
reg |= PHYPARAM0_OTGTUNE(tune->otg);
|
||
/* COM DIS TUNE */
|
||
reg &= ~PHYPARAM0_COMPDISTUNE_MASK;
|
||
reg |= PHYPARAM0_COMPDISTUNE(tune->compdis);
|
||
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
}
|
||
|
||
/* Tuning the SS Block of phy */
|
||
if (usbphy_info->ss_tune) {
|
||
struct exynos_usbphy_ss_tune *tune = usbphy_info->ss_tune;
|
||
|
||
if (usbphy_info->used_phy_port != -1) {
|
||
if (usbphy_info->used_phy_port == 0)
|
||
regs_base = usbphy_info->regs_base;
|
||
else
|
||
regs_base = usbphy_info->regs_base_2nd;
|
||
}
|
||
#if !defined(USB_SS_TX_TUNE_PCS)
|
||
/* Set the PHY Signal Quality Tuning Value */
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
/* TX SWING FULL */
|
||
reg &= ~PHYPARAM1_PCS_TXSWING_FULL_MASK;
|
||
reg |= PHYPARAM1_PCS_TXSWING_FULL(tune->tx_swing_full);
|
||
/* TX DE EMPHASIS 3.5 dB */
|
||
reg &= ~PHYPARAM1_PCS_TXDEEMPH_3P5DB_MASK;
|
||
reg |= PHYPARAM1_PCS_TXDEEMPH_3P5DB(
|
||
tune->tx_deemphasis_3p5db);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
#endif
|
||
|
||
/* Set vboost value for eye diagram */
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM2);
|
||
/* TX VBOOST Value */
|
||
reg &= ~PHYPARAM2_TX_VBOOST_LVL_MASK;
|
||
reg |= PHYPARAM2_TX_VBOOST_LVL(tune->tx_boost_level);
|
||
/* LOS BIAS */
|
||
reg &= ~PHYPARAM2_LOS_BIAS_MASK;
|
||
reg |= PHYPARAM2_LOS_BIAS(tune->los_bias);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM2);
|
||
|
||
/*
|
||
* Set pcs_rx_los_mask_val for 14nm PHY to mask the abnormal
|
||
* LFPS and glitches
|
||
*/
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPCSVAL);
|
||
reg &= ~PHYPCSVAL_PCS_RX_LOS_MASK_VAL_MASK;
|
||
reg |= PHYPCSVAL_PCS_RX_LOS_MASK_VAL(tune->los_mask_val);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPCSVAL);
|
||
}
|
||
}
|
||
|
||
void samsung_exynos_cal_usb3phy_tune_host(
|
||
struct exynos_usbphy_info *usbphy_info)
|
||
{
|
||
void __iomem *regs_base = usbphy_info->regs_base;
|
||
u32 reg;
|
||
|
||
#if defined(USB_MUX_UTMI_ENABLE)
|
||
/* UE_TASK: for utmi 2nd port test : will be removed */
|
||
if (usbphy_info->regs_base_2nd && usbphy_info->used_phy_port == 1)
|
||
regs_base = usbphy_info->regs_base_2nd;
|
||
#endif
|
||
|
||
/* Set the LINK Version Control and Frame Adjust Value */
|
||
reg = readl(regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
reg &= ~LINKSYSTEM_FLADJ_MASK;
|
||
reg |= LINKSYSTEM_FLADJ(0x20);
|
||
reg |= LINKSYSTEM_XHCI_VERSION_CONTROL;
|
||
writel(reg, regs_base + EXYNOS_USBCON_LINKSYSTEM);
|
||
|
||
/* Tuning the HS Block of phy */
|
||
if (usbphy_info->hs_tune) {
|
||
struct exynos_usbphy_hs_tune *tune = usbphy_info->hs_tune;
|
||
|
||
/* Set tune value for 2.0(HS/FS) function */
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
/* TX VREF TUNE */
|
||
reg &= ~PHYPARAM0_TXVREFTUNE_MASK;
|
||
reg |= PHYPARAM0_TXVREFTUNE(tune->tx_vref);
|
||
/* TX RISE TUNE */
|
||
reg &= ~PHYPARAM0_TXRISETUNE_MASK;
|
||
reg |= PHYPARAM0_TXRISETUNE(tune->tx_rise);
|
||
/* TX RES TUNE */
|
||
reg &= ~PHYPARAM0_TXRESTUNE_MASK;
|
||
reg |= PHYPARAM0_TXRESTUNE(tune->tx_res);
|
||
/* TX PRE EMPHASIS PULS */
|
||
if (tune->tx_pre_emp_puls)
|
||
reg |= PHYPARAM0_TXPREEMPPULSETUNE;
|
||
else
|
||
reg &= ~PHYPARAM0_TXPREEMPPULSETUNE;
|
||
/* TX PRE EMPHASIS */
|
||
reg &= ~PHYPARAM0_TXPREEMPAMPTUNE_MASK;
|
||
reg |= PHYPARAM0_TXPREEMPAMPTUNE(tune->tx_pre_emp);
|
||
/* TX HS XV TUNE */
|
||
reg &= ~PHYPARAM0_TXHSXVTUNE_MASK;
|
||
reg |= PHYPARAM0_TXHSXVTUNE(tune->tx_hsxv);
|
||
/* TX FSLS TUNE */
|
||
reg &= ~PHYPARAM0_TXFSLSTUNE_MASK;
|
||
reg |= PHYPARAM0_TXFSLSTUNE(tune->tx_fsls);
|
||
/* RX SQ TUNE */
|
||
reg &= ~PHYPARAM0_SQRXTUNE_MASK;
|
||
reg |= PHYPARAM0_SQRXTUNE(tune->rx_sqrx);
|
||
/* OTG TUNE */
|
||
reg &= ~PHYPARAM0_OTGTUNE_MASK;
|
||
reg |= PHYPARAM0_OTGTUNE(tune->otg);
|
||
/* COM DIS TUNE */
|
||
reg &= ~PHYPARAM0_COMPDISTUNE_MASK;
|
||
reg |= PHYPARAM0_COMPDISTUNE(tune->compdis);
|
||
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM0);
|
||
}
|
||
|
||
/* Tuning the SS Block of phy */
|
||
if (usbphy_info->ss_tune) {
|
||
struct exynos_usbphy_ss_tune *tune = usbphy_info->ss_tune;
|
||
|
||
if (usbphy_info->used_phy_port != -1) {
|
||
if (usbphy_info->used_phy_port == 0)
|
||
regs_base = usbphy_info->regs_base;
|
||
else
|
||
regs_base = usbphy_info->regs_base_2nd;
|
||
}
|
||
#if !defined(USB_SS_TX_TUNE_PCS)
|
||
/* Set the PHY Signal Quality Tuning Value */
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
/* TX SWING FULL */
|
||
reg &= ~PHYPARAM1_PCS_TXSWING_FULL_MASK;
|
||
reg |= PHYPARAM1_PCS_TXSWING_FULL(tune->tx_swing_full);
|
||
/* TX DE EMPHASIS 3.5 dB */
|
||
reg &= ~PHYPARAM1_PCS_TXDEEMPH_3P5DB_MASK;
|
||
reg |= PHYPARAM1_PCS_TXDEEMPH_3P5DB(
|
||
tune->tx_deemphasis_3p5db);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM1);
|
||
#endif
|
||
|
||
/* Set vboost value for eye diagram */
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPARAM2);
|
||
/* TX VBOOST Value */
|
||
reg &= ~PHYPARAM2_TX_VBOOST_LVL_MASK;
|
||
reg |= PHYPARAM2_TX_VBOOST_LVL(tune->tx_boost_level);
|
||
/* LOS BIAS */
|
||
reg &= ~PHYPARAM2_LOS_BIAS_MASK;
|
||
reg |= PHYPARAM2_LOS_BIAS(tune->los_bias);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPARAM2);
|
||
|
||
/*
|
||
* Set pcs_rx_los_mask_val for 14nm PHY to mask the abnormal
|
||
* LFPS and glitches
|
||
*/
|
||
reg = readl(regs_base + EXYNOS_USBCON_PHYPCSVAL);
|
||
reg &= ~PHYPCSVAL_PCS_RX_LOS_MASK_VAL_MASK;
|
||
reg |= PHYPCSVAL_PCS_RX_LOS_MASK_VAL(tune->los_mask_val);
|
||
writel(reg, regs_base + EXYNOS_USBCON_PHYPCSVAL);
|
||
}
|
||
}
|