first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef _LPDP_PHY_H
|
||||
#define _LPDP_PHY_H
|
||||
|
||||
int lpdp_init(const char *dt_path);
|
||||
void lpdp_quiesce(void);
|
||||
int lpdp_initialize_phy_and_pll();
|
||||
void lpdp_init_finalize();
|
||||
void lpdp_phy_reset();
|
||||
int lpdp_set_link_rate(uint32_t lr);
|
||||
int lpdp_get_link_rate(uint32_t *link_rate);
|
||||
int lpdp_phy_set_adjustment_levels(uint32_t lane, uint32_t voltage_swing, uint32_t eq,
|
||||
bool *voltage_max_reached, bool *eq_max_reached);
|
||||
bool lpdp_get_supports_downspread();
|
||||
int lpdp_set_downspread(bool value);
|
||||
int lpdp_get_downspread(void);
|
||||
int lpdp_phy_get_adjustment_levels(uint32_t lane, uint32_t *voltage_swing, uint32_t *eq);
|
||||
void lpdp_phy_set_lane_count(const uint32_t lane_count);
|
||||
void lpdp_phy_configure_alpm(bool enable);
|
||||
|
||||
#endif //_LPDP_PHY_H
|
||||
@@ -0,0 +1,809 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
#include <arch.h>
|
||||
#include <platform.h>
|
||||
#include <platform/int.h>
|
||||
#include <platform/clocks.h>
|
||||
#include <platform/soc/hwclocks.h>
|
||||
#include <platform/soc/hwisr.h>
|
||||
#include <platform/soc/hwregbase.h>
|
||||
#include <platform/soc/pmgr.h>
|
||||
#include <sys.h>
|
||||
#include <sys/task.h>
|
||||
#include <sys/callout.h>
|
||||
|
||||
#include <drivers/displayport/displayport.h>
|
||||
#include <drivers/displayport.h>
|
||||
#include <drivers/lpdp_phy/lpdp_phy.h>
|
||||
#include "regs_v1.h"
|
||||
|
||||
#if WITH_DEVICETREE
|
||||
#include <lib/devicetree.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// debug support
|
||||
|
||||
#define LPDP_DEBUG_MASK ( \
|
||||
LPDP_DEBUG_INIT | \
|
||||
LPDP_DEBUG_ERROR | \
|
||||
LPDP_DEBUG_INFO | \
|
||||
LPDP_DEBUG_PLL | \
|
||||
LPDP_DEBUG_PHY | \
|
||||
0)
|
||||
|
||||
#undef LPDP_DEBUG_MASK
|
||||
#define LPDP_DEBUG_MASK (LPDP_DEBUG_INIT | LPDP_DEBUG_ERROR)
|
||||
|
||||
#define LPDP_DEBUG_INIT (1<<16) // initialisation
|
||||
#define LPDP_DEBUG_ERROR (1<<17) // errors
|
||||
#define LPDP_DEBUG_INFO (1<<18) // info
|
||||
#define LPDP_DEBUG_PLL (1<<24) // PLL
|
||||
#define LPDP_DEBUG_PHY (1<<25) // PLL
|
||||
#define LPDP_DEBUG_ALWAYS (1<<31) // unconditional output
|
||||
|
||||
#define debug(_fac, _fmt, _args...) \
|
||||
do { \
|
||||
if ((LPDP_DEBUG_ ## _fac) & (LPDP_DEBUG_MASK | LPDP_DEBUG_ALWAYS)) \
|
||||
dprintf(DEBUG_CRITICAL, "DP: %s, %d: " _fmt, __FUNCTION__, __LINE__, ##_args); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define kMaxLaneCount 4
|
||||
#define kLinkRatePhysical_162gbpsi 1620000000ULL
|
||||
#define kLinkRatePhysical_270gps 2700000000ULL
|
||||
|
||||
//ERRORS
|
||||
#define RET_SUCCESS 0
|
||||
#define RET_ERROR -1
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// typedefs, enums, structs
|
||||
|
||||
enum {
|
||||
kDPAuxTranscationStatus_None = -1,
|
||||
kDPAuxTranscationStatus_Success,
|
||||
kDPAuxTranscationStatus_IODefer,
|
||||
kDPAuxTranscationStatus_IOError,
|
||||
kDPAuxTranscationStatus_OtherError
|
||||
};
|
||||
|
||||
enum {
|
||||
kBaseVoltageType_Neg_120mV,
|
||||
kBaseVoltageType_Neg_80mV,
|
||||
kBaseVoltageType_Neg_40mV,
|
||||
kBaseVoltageType_Pos_0mV,
|
||||
kBaseVoltageType_Pos_40mV,
|
||||
kBaseVoltageType_Pos_80mV,
|
||||
kBaseVoltageType_Pos_120mV,
|
||||
kBaseVoltageType_Pos_160mV
|
||||
};
|
||||
|
||||
/*
|
||||
Device tree calibration data formats:
|
||||
|
||||
link-calibration-type: t700x-fixed
|
||||
link-calibration-data: ${ VS DE }
|
||||
|
||||
link-calibration-type: t700x-training-table
|
||||
link-calibration-data: ${ VS DE VS DE VS DE VS DE } // voltage swing level 0, pre-emphasis levels 0~3
|
||||
link-calibration-data: ${ VS DE VS DE VS DE 00 00 } // voltage swing level 1, pre-emphasis levels 0~3
|
||||
link-calibration-data: ${ VS DE VS DE 00 00 00 00 } // voltage swing level 2, pre-emphasis levels 0~3
|
||||
link-calibration-data: ${ VS DE 00 00 00 00 00 00 } // voltage swing level 3, pre-emphasis level 0~3
|
||||
*/
|
||||
|
||||
struct lpdp_port_calibration {
|
||||
uint8_t swing;
|
||||
uint8_t deemphasis;
|
||||
} __attribute__((packed));
|
||||
|
||||
#if WITH_HW_DISPLAY_EDP
|
||||
#include <target/lpdp_settings.h>
|
||||
|
||||
#ifndef LPDP_PORT_CALIBRATION_TABLE_FIXED
|
||||
#error LPDP_PORT_CALIBRATION_TABLE_FIXED not defined
|
||||
#endif
|
||||
|
||||
#else
|
||||
static struct lpdp_port_calibration lpdp_port_calibration_table[kDPVoltageLevelMax+1][kDPEQLevelMax+1];
|
||||
#endif
|
||||
|
||||
struct pll_timing {
|
||||
// reference clock frequency in MHz
|
||||
unsigned int ref_mhz;
|
||||
|
||||
// sequencer configuration
|
||||
unsigned int ref_div : 5; // sequencer divisor
|
||||
unsigned int setup_count : 8; // sequencer ticks
|
||||
unsigned int start_count : 8; // sequencer ticks
|
||||
unsigned int pwrdn_count : 14; // sequencer ticks
|
||||
unsigned int reset_count : 8; // sequencer ticks
|
||||
unsigned int update_count : 8; // sequencer ticks
|
||||
unsigned int finish_count : 8; // sequencer ticks
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
lpdp_pll_state_off = 0,
|
||||
lpdp_pll_state_on = 1,
|
||||
lpdp_pll_state_unknown = 2,
|
||||
} lpdp_pll_state_t;
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY local variables
|
||||
static uint32_t _linkRate;
|
||||
static bool lpdp_pll_state = true;
|
||||
static uint32_t lpdp_voltage_levels[kMaxLaneCount];
|
||||
static uint32_t lpdp_voltage_base[kMaxLaneCount];
|
||||
static uint32_t lpdp_eq_levels[kMaxLaneCount];
|
||||
static uint32_t lpdp_voltage_levels[kMaxLaneCount];
|
||||
static bool lpdp_port_calibration_table_fixed;
|
||||
static uint32_t pll_vco_rctrl;
|
||||
static struct pll_timing lpdp_pll_timing;
|
||||
static uint32_t t_cal_duration_microseconds;
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY local functions
|
||||
static void set_bias_power_enable(bool enable);
|
||||
static void set_aux_power_enable(bool enable);
|
||||
static void set_lane_power_controls(unsigned int first, unsigned int limit, uint32_t mask, uint32_t bits);
|
||||
static void set_lane_power_enable(bool enable);
|
||||
static bool lpdp_get_pll_is_locked();
|
||||
static void set_aux_voltage_swing(uint32_t vreg_adj);
|
||||
static void set_lane_adjustment_levels(unsigned int lane, uint8_t vreg_adj, uint8_t eq);
|
||||
static int update_pll_dividers(uint32_t lr);
|
||||
static int lpdp_power_pll(bool poweron);
|
||||
static int lpdp_power_down_pll();
|
||||
static int lpdp_power_up_pll();
|
||||
static int lpdp_phy_impedance_calibration(void);
|
||||
static unsigned int micro_seconds_for_count(struct pll_timing *tm, unsigned int count);
|
||||
static unsigned int get_sleep_to_power_down_duration(struct pll_timing *tm);
|
||||
static unsigned int get_power_down_duration(struct pll_timing *tm);
|
||||
static unsigned int get_reset_duration(struct pll_timing *tm);
|
||||
static unsigned int get_reset_to_update_duration(struct pll_timing *tm);
|
||||
static unsigned int get_lock_duration(struct pll_timing *tm);
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY global functions
|
||||
|
||||
int lpdp_init(const char *dt_path)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kMaxLaneCount; i++)
|
||||
lpdp_voltage_base[i] = kBaseVoltageType_Pos_0mV;
|
||||
|
||||
t_cal_duration_microseconds = 1000; // 1ms
|
||||
|
||||
lpdp_pll_state = lpdp_pll_state_unknown;
|
||||
|
||||
// Note: 200uS is the worst-case from pll_pwrdn to PLL locked under all
|
||||
// conditions and settings per <rdar://problem/15238851>.
|
||||
// The period from pll_pwrdn to PLL locked is:
|
||||
// reset_count + update_count + finish_count
|
||||
|
||||
lpdp_pll_timing.ref_mhz = 24;
|
||||
lpdp_pll_timing.ref_div = 24; // ref clock ticks per (1µs) sequencer tick
|
||||
lpdp_pll_timing.setup_count = 4; // µs
|
||||
lpdp_pll_timing.start_count = 1; // µs
|
||||
lpdp_pll_timing.pwrdn_count = 10; // µs
|
||||
lpdp_pll_timing.reset_count = 100; // µs
|
||||
lpdp_pll_timing.update_count = 5; // µs
|
||||
lpdp_pll_timing.finish_count = 50; // µs
|
||||
|
||||
#if WITH_HW_DISPLAY_EDP
|
||||
lpdp_port_calibration_table_fixed = LPDP_PORT_CALIBRATION_TABLE_FIXED;
|
||||
#else
|
||||
#if WITH_DEVICETREE
|
||||
DTNodePtr node;
|
||||
char * prop_name;
|
||||
void * prop_data;
|
||||
uint32_t prop_size;
|
||||
|
||||
// Copy DT settings in to local copy
|
||||
if ( FindNode(0, dt_path, &node) ) {
|
||||
|
||||
prop_name = "link-calibration-type";
|
||||
if ( FindProperty(node, &prop_name, &prop_data, &prop_size) ) {
|
||||
if (strcmp("t700x-training-table", prop_data) == 0) {
|
||||
lpdp_port_calibration_table_fixed = false;
|
||||
} else if (strcmp("t700x-fixed", prop_data) != 0) {
|
||||
lpdp_port_calibration_table_fixed = true;
|
||||
} else {
|
||||
panic("Unknown DT LPDP Calibration Table Type.");
|
||||
}
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Type.");
|
||||
}
|
||||
|
||||
// gather calibration data from DeviceTree
|
||||
prop_name = "link-calibration-data";
|
||||
if ( FindProperty(node, &prop_name, &prop_data, &prop_size) ) {
|
||||
uint32_t table_size = (lpdp_port_calibration_table_fixed) ?
|
||||
sizeof(struct lpdp_port_calibration) : sizeof(struct lpdp_port_calibration) * 16;
|
||||
if ( prop_size != table_size ) {
|
||||
debug(ERROR, "calibration-data size mismatch, expected:%d, read:%d \n",
|
||||
table_size, prop_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bcopy(prop_data, (void *)lpdp_port_calibration_table, prop_size);
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Data.");
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
||||
{
|
||||
debug(ERROR, "Missing DT LPDP Calibration Table. Using Defaults");
|
||||
lpdp_port_calibration_table_fixed = true;
|
||||
lpdp_port_calibration_table[0][0].swing = LPDP_PHY_LANE_x_VREG_ADJ_MAX;
|
||||
lpdp_port_calibration_table[0][0].deemphasis = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//the block should had been properly reset. validating such assumption
|
||||
assert(rLPDP_PHY_GEN_CTRL & (LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_LANE_PD_OW));
|
||||
assert(rLPDP_PLL_GEN & LPDP_PLL_GEN_RST);
|
||||
|
||||
//extract Configuration of PLL
|
||||
//PMGR should have programmed correctly
|
||||
//we save the value to pass to the OS.
|
||||
pll_vco_rctrl = rLPDP_PLL_CLK;
|
||||
if (pll_vco_rctrl & LPDP_PLL_CLK_VCO_RCTRL_SEL_ENABLE)
|
||||
pll_vco_rctrl = ((pll_vco_rctrl >> LPDP_PLL_CLK_VCO_RCTRL_OW_SHIFT) & LPDP_PLL_CLK_VCO_RCTRL_OW_MASK);
|
||||
else
|
||||
pll_vco_rctrl = 0;
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_initialize_phy_and_pll(void)
|
||||
{
|
||||
int ret = RET_SUCCESS;
|
||||
int i;
|
||||
|
||||
// ensure lane_pd_ow=1 (default) to allow software control of lane power
|
||||
rLPDP_PHY_GEN_CTRL |= (LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_SLEEP_SW | LPDP_PHY_GEN_CTRL_LANE_PD_OW);
|
||||
|
||||
// perform PHY impedance calibration
|
||||
ret = lpdp_phy_impedance_calibration();
|
||||
// panic if impedance calibration procedure failed
|
||||
if ( ret != 0 ) {
|
||||
panic("lpdp impedance calibration failed\n");
|
||||
}
|
||||
|
||||
for (i = 0 ; i < kMaxLaneCount; i++) {
|
||||
set_lane_adjustment_levels(i, LPDP_PHY_LANE_VREG_ADJ_360_mV, 0);
|
||||
}
|
||||
|
||||
//TODO!!
|
||||
set_aux_voltage_swing(0xC);
|
||||
|
||||
// power up all lanes [LANE_x.hi_z=0, LANE_x.ldo_pwrdn=0, LANE_x.pwrdn=0]
|
||||
set_lane_power_enable(true);
|
||||
|
||||
//configure PLL to an initial value
|
||||
//the pll vco's value should have been set by the PMGR since it depends on fuses.
|
||||
lpdp_set_link_rate(kLinkRate162Gbps);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lpdp_init_finalize(void)
|
||||
{
|
||||
//remove the overrides
|
||||
rLPDP_PHY_GEN_CTRL &= ~(LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_LANE_PD_OW);
|
||||
}
|
||||
|
||||
void lpdp_quiesce()
|
||||
{
|
||||
// power down all lanes [LANE_x.hi_z=1, LANE_x.ldo_pwrdn=1, LANE_x.pwrdn=1]
|
||||
set_lane_power_enable(false);
|
||||
|
||||
// power down AUX channel [AUX_CTRL.pwrdn=1]
|
||||
set_aux_power_enable(false);
|
||||
|
||||
// power down PHY's central bias [GEN_CTRL.bias_pwrdn=1]
|
||||
set_bias_power_enable(false);
|
||||
|
||||
// assert lpdp_sleep, pll_pwrdn, and pll_reset
|
||||
lpdp_power_pll(false);
|
||||
|
||||
}
|
||||
|
||||
int lpdp_set_link_rate(uint32_t lr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
debug(PHY, "Setting link rate to 0x%02x\n", (uint8_t)lr);
|
||||
|
||||
// Block clock output during PLL setup
|
||||
rLPDP_PLL_CLK |= LPDP_PLL_CLK_VCO_BLK_VCLK;
|
||||
|
||||
// assert lpdp_sleep, pll_pwrdn, and pll_reset
|
||||
lpdp_power_pll(false);
|
||||
|
||||
// initialize link rate to 0
|
||||
_linkRate = kLinkRate000Gbps;
|
||||
|
||||
// if the target link rate is nonzero, reconfigure and power up the PLL
|
||||
if ( lr > kLinkRate000Gbps ) {
|
||||
|
||||
// update PLL dividers for new link rate
|
||||
if (update_pll_dividers(lr)) {
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// power up PLL and wait for lock,
|
||||
// if this fails, power it back down and leave link rate at 0
|
||||
if (lpdp_power_pll(true)) {
|
||||
ret = -1;
|
||||
lpdp_power_pll(false);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// finally, update the current link rate
|
||||
_linkRate = lr;
|
||||
}
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lpdp_get_link_rate(uint32_t *link_rate)
|
||||
{
|
||||
*link_rate = _linkRate;
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_phy_set_adjustment_levels(uint32_t lane, uint32_t voltage_swing, uint32_t eq,
|
||||
bool *voltage_max_reached, bool *eq_max_reached)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if ( lane > kMaxLaneCount )
|
||||
return -1;
|
||||
|
||||
debug(PHY, "lane=%d voltage=%d eq=%d\n", lane, voltage_swing, eq);
|
||||
|
||||
if (voltage_swing > kDPVoltageLevelMax) {
|
||||
voltage_swing = kDPVoltageLevelMax;
|
||||
}
|
||||
|
||||
if (eq > kDPEQLevelMax) {
|
||||
eq = kDPEQLevelMax;
|
||||
}
|
||||
|
||||
if (lpdp_port_calibration_table_fixed) {
|
||||
set_lane_adjustment_levels(lane,
|
||||
lpdp_port_calibration_table[0][0].swing,
|
||||
lpdp_port_calibration_table[0][0].deemphasis);
|
||||
} else {
|
||||
set_lane_adjustment_levels(lane,
|
||||
lpdp_port_calibration_table[voltage_swing][eq].swing,
|
||||
lpdp_port_calibration_table[voltage_swing][eq].deemphasis);
|
||||
}
|
||||
|
||||
if (voltage_max_reached) {
|
||||
*voltage_max_reached = (voltage_swing == kDPVoltageLevelMax);
|
||||
}
|
||||
|
||||
if (eq_max_reached) {
|
||||
*eq_max_reached = (eq == kDPEQLevelMax);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lpdp_phy_reset()
|
||||
{
|
||||
lpdp_phy_impedance_calibration();
|
||||
}
|
||||
|
||||
bool lpdp_get_supports_downspread()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int lpdp_set_downspread(bool value)
|
||||
{
|
||||
//not supported but needs to succeed.. hence noop
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_get_downspread(void)
|
||||
{
|
||||
//not supported but needs to succeed.. hence noop
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_phy_get_adjustment_levels(uint32_t lane, uint32_t *voltage_swing, uint32_t *eq)
|
||||
{
|
||||
if (eq)
|
||||
*eq = lpdp_eq_levels[lane];
|
||||
|
||||
if (voltage_swing)
|
||||
*voltage_swing = lpdp_voltage_levels[lane];
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
void lpdp_phy_set_lane_count(const uint32_t lane_count)
|
||||
{
|
||||
// enable active lanes
|
||||
set_lane_power_controls(0, lane_count, LPDP_PHY_LANE_HI_Z, 0);
|
||||
|
||||
// disable inactive lanes
|
||||
set_lane_power_controls(lane_count, kMaxLaneCount, LPDP_PHY_LANE_HI_Z, LPDP_PHY_LANE_HI_Z);
|
||||
}
|
||||
|
||||
#if WITH_DEVICETREE
|
||||
|
||||
#include <lib/devicetree.h>
|
||||
|
||||
int lpdp_phy_update_device_tree(DTNode *lpdp_node)
|
||||
{
|
||||
u_int32_t propSize;
|
||||
char *propName;
|
||||
void *propData;
|
||||
|
||||
if (lpdp_node == NULL) {
|
||||
return RET_ERROR;
|
||||
}
|
||||
propName = "pll_vco_rctrl";
|
||||
if (FindProperty(lpdp_node, &propName, &propData, &propSize)) {
|
||||
if (pll_vco_rctrl == 0) {
|
||||
((char **)propData)[0] = "~";
|
||||
} else {
|
||||
((u_int32_t *)propData)[0] = pll_vco_rctrl;
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_HW_DISPLAY_EDP
|
||||
// Copy local settings to the DT
|
||||
propName = "link-calibration-type";
|
||||
if ( FindProperty(lpdp_node, &propName, &propData, &propSize) ) {
|
||||
memset(propData, 0, propSize);
|
||||
if (lpdp_port_calibration_table_fixed) {
|
||||
if (propSize < strlen("t700x-fixed") + 1) {
|
||||
panic("link-calibration-type DT entry too small.");
|
||||
}
|
||||
snprintf(propData, propSize, "t700x-fixed");
|
||||
} else {
|
||||
if (propSize < strlen("t700x-training-table") + 1) {
|
||||
panic("link-calibration-type DT entry too small.");
|
||||
}
|
||||
snprintf(propData, propSize, "t700x-training-table");
|
||||
}
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Type.");
|
||||
}
|
||||
|
||||
propName = "link-calibration-data";
|
||||
if ( FindProperty(lpdp_node, &propName, &propData, &propSize) ) {
|
||||
memset(propData, 0, propSize);
|
||||
uint32_t table_size = (lpdp_port_calibration_table_fixed) ?
|
||||
sizeof(struct lpdp_port_calibration) : sizeof(struct lpdp_port_calibration) * 16;
|
||||
if (propSize < table_size) {
|
||||
panic("link-calibration-data table too small.");
|
||||
}
|
||||
bcopy((void *)lpdp_port_calibration_table, propData, table_size);
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Data.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
#endif //WITH_DEVICETREE
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY local functions
|
||||
|
||||
static int lpdp_phy_impedance_calibration( void )
|
||||
{
|
||||
int i;
|
||||
uint32_t calibration_result = 0;
|
||||
bool complete;
|
||||
unsigned int pd, pu;
|
||||
int result = RET_SUCCESS;
|
||||
|
||||
//start calibration pull down first
|
||||
rLPDP_PHY_CAL_CTRL |= LPDP_PHY_CAL_CTRL_AUTOZERO_BYP | LPDP_PHY_CAL_CTRL_RST;
|
||||
|
||||
// clear cal_pwrdn
|
||||
rLPDP_PHY_CAL_CTRL &= ~LPDP_PHY_CAL_CTRL_PWRDN;
|
||||
|
||||
for (i = 0 ; i < kMaxLaneCount; i++) {
|
||||
set_lane_adjustment_levels(i, LPDP_PHY_LANE_x_VREG_ADJ_MAX, 0);
|
||||
}
|
||||
|
||||
set_aux_voltage_swing(LPDP_PHY_AUX_CTRL_VREG_ADJ_MAX);
|
||||
|
||||
// Wait at least 1ms
|
||||
spin( 1000 );
|
||||
|
||||
// Wait at least 21us
|
||||
spin( 21 );
|
||||
|
||||
// Let the pull down calibration start
|
||||
rLPDP_PHY_CAL_CTRL &= ~LPDP_PHY_CAL_CTRL_RST;
|
||||
|
||||
// Wait for calibration to complete
|
||||
spin(t_cal_duration_microseconds);
|
||||
|
||||
calibration_result = rLPDP_PHY_CAL_RESULT;
|
||||
complete = (calibration_result & LPDP_PHY_CAL_RESULT_COMPLETE) != 0;
|
||||
pd = LPDP_PHY_CAL_RESULT_PD(calibration_result);
|
||||
pu = LPDP_PHY_CAL_RESULT_PU(calibration_result);
|
||||
|
||||
if (!complete || pd < 6 || pu < 6)
|
||||
result = RET_ERROR;
|
||||
|
||||
// Set cal_pwrdn to 1
|
||||
rLPDP_PHY_CAL_CTRL |= LPDP_PHY_CAL_CTRL_PWRDN;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void set_bias_power_enable(bool enable)
|
||||
{
|
||||
uint32_t rmw = rLPDP_PHY_GEN_CTRL;
|
||||
rmw &= ~( LPDP_PHY_GEN_CTRL_BIAS_PWRDN);
|
||||
rmw |= ( enable ? 0 : LPDP_PHY_GEN_CTRL_BIAS_PWRDN);
|
||||
rLPDP_PHY_GEN_CTRL = rmw;
|
||||
}
|
||||
|
||||
static void set_aux_power_enable(bool enable)
|
||||
{
|
||||
uint32_t rmw = rLPDP_PHY_AUX_CTRL;
|
||||
rmw &= ~(LPDP_PHY_AUX_CTRL_PWRDN);
|
||||
rmw |= ( enable ? 0 : LPDP_PHY_AUX_CTRL_PWRDN);
|
||||
rLPDP_PHY_AUX_CTRL = rmw;
|
||||
}
|
||||
|
||||
static void set_lane_power_enable(bool enable)
|
||||
{
|
||||
uint32_t bits = enable ? 0 : LPDP_PHY_LANE_x_FULL_DISABLE;
|
||||
|
||||
// Reference:
|
||||
// Asg_lpdptx Specification:
|
||||
// • "Theory of Operations" subsection "Shutdown"
|
||||
|
||||
// Note that LPDP_PHY.GEN_CTRL.lane_pd_ow must be 1 for this to work
|
||||
set_lane_power_controls(0, kMaxLaneCount, LPDP_PHY_LANE_x_FULL_DISABLE, bits);
|
||||
}
|
||||
|
||||
static void set_lane_power_controls(unsigned int first, unsigned int limit, uint32_t mask, uint32_t bits)
|
||||
{
|
||||
// Reference:
|
||||
// Asg_lpdptx Specification:
|
||||
// • "Theory of Operations" subsection "Lane enable and disable"
|
||||
|
||||
for (unsigned int i = first; i < limit; i++) {
|
||||
// allow at least 5ns between lane power/enable state changes
|
||||
spin(1);
|
||||
|
||||
// set power state of lane 'i'
|
||||
uint32_t rmw = rLPDP_PHY_LANE(i);
|
||||
rmw &= ~mask;
|
||||
rmw |= bits;
|
||||
rLPDP_PHY_LANE(i) = rmw;
|
||||
}
|
||||
}
|
||||
|
||||
static bool lpdp_get_pll_is_locked()
|
||||
{
|
||||
return (rLPDP_PLL_LOCK & LPDP_PLL_LOCK_OUT_ON);
|
||||
}
|
||||
|
||||
static void set_aux_voltage_swing(uint32_t vreg_adj)
|
||||
{
|
||||
uint32_t rmw = rLPDP_PHY_AUX_CTRL;
|
||||
rmw &= ~LPDP_PHY_AUX_CTRL_VREG_ADJ_MASK;
|
||||
rmw |= vreg_adj << LPDP_PHY_AUX_CTRL_VREG_ADJ_SHIFT;
|
||||
rLPDP_PHY_AUX_CTRL = rmw;
|
||||
}
|
||||
|
||||
static void set_lane_adjustment_levels(unsigned int lane, uint8_t voltage_swing, uint8_t eq)
|
||||
{
|
||||
uint32_t rmw = rLPDP_PHY_LANE(lane);
|
||||
rmw &= ~(LPDP_PHY_LANE_DE_ENABLE | LPDP_PHY_LANE_x_VREG_ADJ_MASK);
|
||||
rmw |= (LPDP_PHY_LANE_VREG_ADJ(voltage_swing) | ((eq) ? LPDP_PHY_LANE_DE_ENABLE : 0));
|
||||
rLPDP_PHY_LANE(lane) = rmw;
|
||||
|
||||
lpdp_voltage_levels[lane] = voltage_swing;
|
||||
lpdp_eq_levels[lane] = eq;
|
||||
}
|
||||
|
||||
//TODO: Get the correct values for gclk_div
|
||||
static int update_pll_dividers(uint32_t lr)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t fb;
|
||||
uint32_t pre;
|
||||
|
||||
// determine feedback and pre-divider ratios
|
||||
switch ( lr ) {
|
||||
case kLinkRate000Gbps:
|
||||
fb = pre = 0;
|
||||
break;
|
||||
|
||||
case kLinkRate162Gbps:
|
||||
fb = 135;
|
||||
pre = 4;
|
||||
break;
|
||||
|
||||
case kLinkRate270Gbps:
|
||||
fb = 225;
|
||||
pre = 4;
|
||||
break;
|
||||
|
||||
case kLinkRate324Gbps:
|
||||
fb = 135;
|
||||
pre = 2;
|
||||
break;
|
||||
|
||||
case kLinkRate540Gbps: // Not supported on Fiji/Capri
|
||||
fb = 225;
|
||||
pre = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug(ERROR, "unsupported link rate: %u", lr);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Set new PLL divider ratios
|
||||
uint32_t rmw = rLPDP_PLL_IDIV;
|
||||
rmw &= ~LPDP_PLL_IDIV_FB_MASK;
|
||||
rmw |= (fb << LPDP_PLL_IDIV_FB_SHIFT);
|
||||
rmw &= ~LPDP_PLL_IDIV_PRE_MASK;
|
||||
rmw |= (pre << LPDP_PLL_IDIV_PRE_SHIFT);
|
||||
rLPDP_PLL_IDIV = rmw;
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lpdp_power_pll(bool poweron)
|
||||
{
|
||||
int result = RET_ERROR;
|
||||
|
||||
if ((lpdp_pll_state != lpdp_pll_state_unknown) && (lpdp_pll_state == poweron))
|
||||
return RET_SUCCESS;
|
||||
|
||||
lpdp_pll_state = poweron;
|
||||
if (poweron)
|
||||
result = lpdp_power_up_pll();
|
||||
else
|
||||
result = lpdp_power_down_pll();
|
||||
return result;
|
||||
}
|
||||
|
||||
static int lpdp_power_down_pll()
|
||||
{
|
||||
rLPDP_PHY_GEN_CTRL |= (LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_SLEEP_SW);
|
||||
|
||||
spin(31); //> 30 ns
|
||||
|
||||
rLPDP_PLL_GEN |= (LPDP_PLL_GEN_PWRDN | LPDP_PLL_GEN_RST);
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
static int lpdp_power_up_pll()
|
||||
{
|
||||
// Note: powerDownPll() must be called first
|
||||
assert(rLPDP_PHY_GEN_CTRL & LPDP_PHY_GEN_CTRL_SEQ_OW);
|
||||
assert(rLPDP_PHY_GEN_CTRL & LPDP_PHY_GEN_CTRL_SLEEP_SW);
|
||||
assert(rLPDP_PLL_GEN & LPDP_PLL_GEN_PWRDN);
|
||||
assert(rLPDP_PLL_GEN & LPDP_PLL_GEN_RST);
|
||||
|
||||
//spin(get_power_down_duration(&lpdp_pll_timing));
|
||||
spin(10);
|
||||
|
||||
// de-assert pll_pwrdn after at least 10µS
|
||||
rLPDP_PLL_GEN &= ~LPDP_PLL_GEN_PWRDN;
|
||||
|
||||
//spin(get_reset_duration(&lpdp_pll_timing));
|
||||
spin(100);
|
||||
|
||||
// de-assert pll_reset after at least 100µS
|
||||
rLPDP_PLL_GEN &= ~LPDP_PLL_GEN_RST;
|
||||
|
||||
//spin(get_reset_to_update_duration(&lpdp_pll_timing));
|
||||
spin(5);
|
||||
|
||||
// assert pll_update_divn for at least 1µS
|
||||
rLPDP_PLL_IDIV |= LPDP_PLL_IDIV_UPDT;
|
||||
spin(1);
|
||||
rLPDP_PLL_IDIV &= ~LPDP_PLL_IDIV_UPDT;
|
||||
|
||||
// wait for PLL lock
|
||||
//spin(get_lock_duration(&lpdp_pll_timing));
|
||||
spin(50);
|
||||
|
||||
// check for PLL lock, bail if not locked
|
||||
if (!lpdp_get_pll_is_locked()) {
|
||||
printf("failed to lock lpdp pll\n");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
// Enable clock output after PLL is locked
|
||||
rLPDP_PLL_CLK &= ~LPDP_PLL_CLK_VCO_BLK_VCLK;
|
||||
|
||||
// de-assert lpdp_sleep
|
||||
|
||||
// Note: The sleep signal is used by the LPDP PHY to gate-off PLL clock;
|
||||
// see <rdar://problem/15238851>.
|
||||
rLPDP_PHY_GEN_CTRL &= ~LPDP_PHY_GEN_CTRL_SLEEP_SW;
|
||||
|
||||
// wait at least 1µS for output driver ready
|
||||
spin(2);
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
void lpdp_phy_configure_alpm(bool enable)
|
||||
{
|
||||
|
||||
if (enable) {
|
||||
// Clear Sequencer overwrite and Lane power-down overwrite
|
||||
rLPDP_PHY_GEN_CTRL &= ~(LPDP_PHY_GEN_CTRL_SLEEP_SW | LPDP_PHY_GEN_CTRL_LANE_PD_OW);
|
||||
|
||||
// Program ALPM PHY Sequence Timers
|
||||
rLPDP_GEN_SEQ_1 = LPDP_GEN_SEQ_1_START_COUNT(lpdp_pll_timing.start_count);
|
||||
rLPDP_GEN_SEQ_1 |= LPDP_GEN_SEQ_1_SETUP_COUNT(lpdp_pll_timing.setup_count);
|
||||
//Hardcodede value to be fixed in <rdar://problem/16786136> Make display_config a void * for future flexibility
|
||||
rLPDP_GEN_SEQ_2 = 1873;
|
||||
rLPDP_GEN_SEQ_3 = lpdp_pll_timing.reset_count;
|
||||
rLPDP_GEN_SEQ_4 = LPDP_GEN_SEQ_4_FINISH_COUNT(lpdp_pll_timing.finish_count);
|
||||
rLPDP_GEN_SEQ_4 |= LPDP_GEN_SEQ_4_UPDATE_COUNT(lpdp_pll_timing.update_count);
|
||||
}
|
||||
}
|
||||
|
||||
// convenience methods for conversion to µs (for software use)
|
||||
|
||||
static unsigned int micro_seconds_for_count(struct pll_timing *tm, unsigned int count) {
|
||||
// Note: Normally, ref_mhz == ref_div, but it is not assumed.
|
||||
// Values are rounded up.
|
||||
return ((count * tm->ref_div) + tm->ref_mhz - 1) / tm->ref_mhz;
|
||||
}
|
||||
|
||||
static unsigned int get_sleep_to_power_down_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->start_count);
|
||||
}
|
||||
|
||||
static unsigned int get_power_down_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->pwrdn_count);
|
||||
}
|
||||
|
||||
static unsigned int get_reset_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->reset_count);
|
||||
}
|
||||
|
||||
static unsigned int get_reset_to_update_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->update_count);
|
||||
}
|
||||
|
||||
static unsigned int get_lock_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->finish_count);
|
||||
}
|
||||
@@ -0,0 +1,996 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2015 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
#include <arch.h>
|
||||
#include <platform.h>
|
||||
#include <platform/int.h>
|
||||
#include <platform/clocks.h>
|
||||
#include <platform/soc/hwclocks.h>
|
||||
#include <platform/soc/hwisr.h>
|
||||
#include <platform/soc/hwregbase.h>
|
||||
#include <platform/soc/pmgr.h>
|
||||
#include <sys.h>
|
||||
#include <sys/task.h>
|
||||
#include <sys/callout.h>
|
||||
|
||||
#include <drivers/displayport/displayport.h>
|
||||
#include <drivers/displayport.h>
|
||||
#include <drivers/lpdp_phy/lpdp_phy.h>
|
||||
#include "regs_v2.h"
|
||||
|
||||
#if WITH_DEVICETREE
|
||||
#include <lib/devicetree.h>
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// debug support
|
||||
|
||||
#define LPDP_DEBUG_MASK ( \
|
||||
LPDP_DEBUG_INIT | \
|
||||
LPDP_DEBUG_ERROR | \
|
||||
LPDP_DEBUG_INFO | \
|
||||
LPDP_DEBUG_PLL | \
|
||||
LPDP_DEBUG_PHY | \
|
||||
0)
|
||||
|
||||
#undef LPDP_DEBUG_MASK
|
||||
#define LPDP_DEBUG_MASK (LPDP_DEBUG_INIT | LPDP_DEBUG_ERROR)
|
||||
|
||||
#define LPDP_DEBUG_INIT (1<<16) // initialisation
|
||||
#define LPDP_DEBUG_ERROR (1<<17) // errors
|
||||
#define LPDP_DEBUG_INFO (1<<18) // info
|
||||
#define LPDP_DEBUG_PLL (1<<24) // PLL
|
||||
#define LPDP_DEBUG_PHY (1<<25) // PLL
|
||||
#define LPDP_DEBUG_ALWAYS (1<<31) // unconditional output
|
||||
|
||||
#define debug(_fac, _fmt, _args...) \
|
||||
do { \
|
||||
if ((LPDP_DEBUG_ ## _fac) & (LPDP_DEBUG_MASK | LPDP_DEBUG_ALWAYS)) \
|
||||
dprintf(DEBUG_CRITICAL, "DP: %s, %d: " _fmt, __FUNCTION__, __LINE__, ##_args); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define kMaxLaneCount 4
|
||||
#define kLinkRatePhysical_162gbpsi 1620000000ULL
|
||||
#define kLinkRatePhysical_270gps 2700000000ULL
|
||||
|
||||
//ERRORS
|
||||
#define RET_SUCCESS 0
|
||||
#define RET_ERROR -1
|
||||
|
||||
#ifndef LPDP_PHY_VERSION
|
||||
#error LPDP_PHY_VERSION undefined
|
||||
#endif
|
||||
|
||||
#ifndef LPDP_LINK_CAL_TABLE_VERSION
|
||||
#error LPDP_LINK_CAL_TABLE_VERSION undefined
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// typedefs, enums, structs
|
||||
|
||||
enum {
|
||||
kDPAuxTranscationStatus_None = -1,
|
||||
kDPAuxTranscationStatus_Success,
|
||||
kDPAuxTranscationStatus_IODefer,
|
||||
kDPAuxTranscationStatus_IOError,
|
||||
kDPAuxTranscationStatus_OtherError
|
||||
};
|
||||
|
||||
enum {
|
||||
kBaseVoltageType_Neg_120mV,
|
||||
kBaseVoltageType_Neg_80mV,
|
||||
kBaseVoltageType_Neg_40mV,
|
||||
kBaseVoltageType_Pos_0mV,
|
||||
kBaseVoltageType_Pos_40mV,
|
||||
kBaseVoltageType_Pos_80mV,
|
||||
kBaseVoltageType_Pos_120mV,
|
||||
kBaseVoltageType_Pos_160mV
|
||||
};
|
||||
|
||||
/*
|
||||
Device tree calibration data formats:
|
||||
|
||||
link-calibration-type: t700x-fixed
|
||||
link-calibration-data: ${ VS DE }
|
||||
|
||||
link-calibration-type: t700x-training-table
|
||||
link-calibration-data: ${ VS DE VS DE VS DE VS DE } // voltage swing level 0, pre-emphasis levels 0~3
|
||||
link-calibration-data: ${ VS DE VS DE VS DE 00 00 } // voltage swing level 1, pre-emphasis levels 0~3
|
||||
link-calibration-data: ${ VS DE VS DE 00 00 00 00 } // voltage swing level 2, pre-emphasis levels 0~3
|
||||
link-calibration-data: ${ VS DE 00 00 00 00 00 00 } // voltage swing level 3, pre-emphasis level 0~3
|
||||
|
||||
link-calibration-type: s800x-fixed
|
||||
link-calibration-data: $VS $R
|
||||
|
||||
link-calibration-type: s800x-training-table
|
||||
link-calibration-data: $VS $R $VS $R $VS $R $VS $R // voltage swing level 0, pre-emphasis levels 0~3
|
||||
link-calibration-data: $VS $R $VS $R $VS $R $00 $00 // voltage swing level 1, pre-emphasis levels 0~3
|
||||
link-calibration-data: $VS $R $VS $R $00 $00 $00 $00 // voltage swing level 2, pre-emphasis levels 0~3
|
||||
link-calibration-data: $VS $R $00 $00 $00 $00 $00 $00 // voltage swing level 3, pre-emphasis level 0~3
|
||||
*/
|
||||
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 2
|
||||
struct lpdp_port_calibration {
|
||||
uint8_t swing;
|
||||
uint8_t deemphasis;
|
||||
} __attribute__((packed));
|
||||
|
||||
static const char *training_table_text = "t700x-training-table";
|
||||
static const char *fixed_text = "t700x-fixed";
|
||||
#else
|
||||
struct lpdp_port_calibration {
|
||||
uint32_t swing;
|
||||
uint32_t r;
|
||||
} __attribute__((packed));
|
||||
|
||||
static const char *training_table_text = "s800x-training-table";
|
||||
static const char *fixed_text = "s800x-fixed";
|
||||
#endif
|
||||
|
||||
#if WITH_HW_DISPLAY_EDP
|
||||
#include <target/lpdp_settings.h>
|
||||
|
||||
#ifndef LPDP_PORT_CALIBRATION_TABLE_FIXED
|
||||
#error LPDP_PORT_CALIBRATION_TABLE_FIXED not defined
|
||||
#endif
|
||||
|
||||
#else
|
||||
static struct lpdp_port_calibration lpdp_port_calibration_table[kDPVoltageLevelMax+1][kDPEQLevelMax+1];
|
||||
#endif
|
||||
|
||||
struct pll_timing {
|
||||
// reference clock frequency in MHz
|
||||
unsigned int ref_mhz;
|
||||
|
||||
// sequencer configuration
|
||||
unsigned int ref_div : 5; // sequencer divisor
|
||||
unsigned int setup_count : 8; // sequencer ticks
|
||||
unsigned int start_count : 8; // sequencer ticks
|
||||
unsigned int pwrdn_count : 14; // sequencer ticks
|
||||
unsigned int reset_count : 8; // sequencer ticks
|
||||
unsigned int update_count : 8; // sequencer ticks
|
||||
unsigned int finish_count : 8; // sequencer ticks
|
||||
unsigned int wakeup_count : 8; // sequencer ticks
|
||||
unsigned int hold_count : 8; // sequencer ticks
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
lpdp_pll_state_off = 0,
|
||||
lpdp_pll_state_on = 1,
|
||||
lpdp_pll_state_unknown = 2,
|
||||
} lpdp_pll_state_t;
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY local variables
|
||||
static addr_t __base_address = LPDP_PHY_BASE_ADDR;
|
||||
static uint32_t _linkRate;
|
||||
static bool lpdp_pll_state = true;
|
||||
static uint32_t lpdp_voltage_levels[kMaxLaneCount];
|
||||
static uint32_t lpdp_voltage_base[kMaxLaneCount];
|
||||
static uint32_t lpdp_eq_levels[kMaxLaneCount];
|
||||
static uint32_t lpdp_voltage_levels[kMaxLaneCount];
|
||||
static bool lpdp_port_calibration_table_fixed;
|
||||
static uint32_t pll_vco_rctrl;
|
||||
static struct pll_timing lpdp_pll_timing;
|
||||
static uint32_t t_cal_duration_microseconds;
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY local functions
|
||||
static void set_bias_power_enable(bool enable);
|
||||
static void set_aux_power_enable(bool enable);
|
||||
static void set_lane_power_controls(unsigned int first, unsigned int limit, uint32_t mask, uint32_t bits);
|
||||
static void set_lane_power_enable(bool enable);
|
||||
static bool lpdp_get_pll_is_locked();
|
||||
static void set_aux_voltage_swing(uint32_t vreg_adj);
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
static void set_phy_configure_ldos(uint32_t ldopre_vreg_adj, uint32_t ldoclk_vreg_adj, uint32_t auxvreg_adj);
|
||||
#endif
|
||||
static void enable_phy_ldos();
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 2
|
||||
static void set_lane_adjustment_levels(unsigned int lane, uint8_t vreg_adj, uint8_t eq);
|
||||
#else
|
||||
static void set_lane_adjustment_levels(unsigned int lane, uint32_t vreg_adj, uint32_t r);
|
||||
#endif
|
||||
static int update_pll_dividers(uint32_t lr);
|
||||
static int lpdp_power_pll(bool poweron);
|
||||
static int lpdp_power_down_pll();
|
||||
static int lpdp_power_up_pll();
|
||||
static int lpdp_phy_impedance_calibration(void);
|
||||
static unsigned int micro_seconds_for_count(struct pll_timing *tm, unsigned int count);
|
||||
static unsigned int get_sleep_to_power_down_duration(struct pll_timing *tm);
|
||||
static unsigned int get_power_down_duration(struct pll_timing *tm);
|
||||
static unsigned int get_reset_duration(struct pll_timing *tm);
|
||||
static unsigned int get_reset_to_update_duration(struct pll_timing *tm);
|
||||
static unsigned int get_lock_duration(struct pll_timing *tm);
|
||||
static uint32_t read_reg(uint32_t offset);
|
||||
static void write_reg(uint32_t offset, uint32_t val);
|
||||
static void and_reg(uint32_t offset, uint32_t val);
|
||||
static void or_reg(uint32_t offset, uint32_t val);
|
||||
static void set_bits_in_reg(uint32_t offset, uint32_t pos, uint32_t mask, uint32_t value);
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY global functions
|
||||
|
||||
int lpdp_init(const char *dt_path)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kMaxLaneCount; i++)
|
||||
lpdp_voltage_base[i] = kBaseVoltageType_Pos_0mV;
|
||||
|
||||
t_cal_duration_microseconds = 1000; // 1ms
|
||||
|
||||
lpdp_pll_state = lpdp_pll_state_unknown;
|
||||
|
||||
// Note: 200uS is the worst-case from pll_pwrdn to PLL locked under all
|
||||
// conditions and settings per <rdar://problem/15238851>.
|
||||
// The period from pll_pwrdn to PLL locked is:
|
||||
// reset_count + update_count + finish_count
|
||||
|
||||
lpdp_pll_timing.ref_mhz = 24;
|
||||
lpdp_pll_timing.ref_div = 24; // ref clock ticks per (1µs) sequencer tick
|
||||
lpdp_pll_timing.setup_count = 4; // µs
|
||||
lpdp_pll_timing.start_count = 1; // µs
|
||||
lpdp_pll_timing.pwrdn_count = 10; // µs
|
||||
lpdp_pll_timing.reset_count = 100; // µs
|
||||
lpdp_pll_timing.update_count = 5; // µs
|
||||
lpdp_pll_timing.finish_count = 50; // µs
|
||||
|
||||
#if WITH_HW_DISPLAY_EDP
|
||||
lpdp_port_calibration_table_fixed = LPDP_PORT_CALIBRATION_TABLE_FIXED;
|
||||
#else
|
||||
#if WITH_DEVICETREE
|
||||
DTNodePtr node;
|
||||
char * prop_name;
|
||||
void * prop_data;
|
||||
uint32_t prop_size;
|
||||
|
||||
// Copy DT settings in to local copy
|
||||
if ( FindNode(0, dt_path, &node) ) {
|
||||
|
||||
prop_name = "link-calibration-type";
|
||||
if ( FindProperty(node, &prop_name, &prop_data, &prop_size) ) {
|
||||
if (strcmp(training_table_text, prop_data) == 0) {
|
||||
lpdp_port_calibration_table_fixed = false;
|
||||
} else if (strcmp(fixed_text, prop_data) == 0) {
|
||||
lpdp_port_calibration_table_fixed = true;
|
||||
} else {
|
||||
panic("Unknown DT LPDP Calibration Table Type.");
|
||||
}
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Type.");
|
||||
}
|
||||
|
||||
// gather calibration data from DeviceTree
|
||||
prop_name = "link-calibration-data";
|
||||
if ( FindProperty(node, &prop_name, &prop_data, &prop_size) ) {
|
||||
uint32_t table_size = (lpdp_port_calibration_table_fixed) ?
|
||||
sizeof(struct lpdp_port_calibration) : sizeof(struct lpdp_port_calibration) * 16;
|
||||
if ( prop_size != table_size ) {
|
||||
debug(ERROR, "calibration-data size mismatch, expected:%d, read:%d \n",
|
||||
table_size, prop_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bcopy(prop_data, (void *)lpdp_port_calibration_table, prop_size);
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Data.");
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
||||
{
|
||||
debug(ERROR, "Missing DT LPDP Calibration Table. Using Defaults\n");
|
||||
lpdp_port_calibration_table_fixed = true;
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 2
|
||||
lpdp_port_calibration_table[0][0].swing = LPDP_PHY_LANE_x_VREG_ADJ_MAX;
|
||||
lpdp_port_calibration_table[0][0].deemphasis = 0;
|
||||
#else
|
||||
lpdp_port_calibration_table[0][0].swing = LPDP_PHY_LANE_x_VREG_ADJ_MAX;
|
||||
lpdp_port_calibration_table[0][0].r = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
//the block should had been properly reset. validating such assumption
|
||||
assert(read_reg(rLPDP_PHY_GEN_CTRL) & (LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_LANE_PD_OW));
|
||||
assert(read_reg(rLPDP_PLL_GEN) & LPDP_PLL_GEN_RST);
|
||||
|
||||
//extract Configuration of PLL
|
||||
//PMGR should have programmed correctly
|
||||
//we save the value to pass to the OS.
|
||||
pll_vco_rctrl = read_reg(rLPDP_PLL_CLK);
|
||||
if (pll_vco_rctrl & LPDP_PLL_CLK_VCO_RCTRL_SEL_ENABLE)
|
||||
pll_vco_rctrl = ((pll_vco_rctrl >> LPDP_PLL_CLK_VCO_RCTRL_OW_SHIFT) & LPDP_PLL_CLK_VCO_RCTRL_OW_MASK);
|
||||
else
|
||||
pll_vco_rctrl = 0;
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_initialize_phy_and_pll(void)
|
||||
{
|
||||
int ret = RET_SUCCESS;
|
||||
int i;
|
||||
|
||||
// ensure lane_pd_ow=1 (default) to allow software control of lane power
|
||||
or_reg(rLPDP_PHY_GEN_CTRL, (LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_SLEEP_SW ));
|
||||
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
for (i = 0 ; i < kMaxLaneCount; i++) {
|
||||
set_lane_adjustment_levels(i, LPDP_PHY_LANE_VREG_ADJ_420_mV, 0);
|
||||
}
|
||||
|
||||
//TODO!!
|
||||
set_aux_voltage_swing(0xA);
|
||||
|
||||
set_phy_configure_ldos(0x4, 0x4, 0x3);
|
||||
#elif LPDP_PHY_VERSION == 2
|
||||
for (i = 0 ; i < kMaxLaneCount; i++) {
|
||||
set_lane_adjustment_levels(i, LPDP_PHY_LANE_VREG_ADJ_450_mV, 0);
|
||||
}
|
||||
|
||||
//TODO!!
|
||||
set_aux_voltage_swing(0x6);
|
||||
#endif
|
||||
|
||||
//reset calibration
|
||||
write_reg(rLPDP_PHY_CAL, 0);
|
||||
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
write_reg(rLPDP_PHY_RESERVED, (1 << 4));
|
||||
#endif
|
||||
|
||||
write_reg(rLPDP_PHY_CLK_CTRL, LPDP_PHY_CLK_CTRL_CLK_ENABLE | LPDP_PHY_CLK_CTRL_CLKDIV5_RESET);
|
||||
|
||||
or_reg(rLPDP_PHY_GEN_CTRL, LPDP_PHY_GEN_CTRL_LANE_PD_OW);
|
||||
|
||||
set_bias_power_enable(true);
|
||||
|
||||
// power up all lanes
|
||||
set_lane_power_enable(true);
|
||||
|
||||
enable_phy_ldos();
|
||||
|
||||
set_aux_power_enable(true);
|
||||
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
and_reg(rLPDP_PHY_BIST, ~LPDP_PHY_BIST_LOOPBACK_SRC_SEL(LPDP_PHY_BIST_LOOPBACK_SRC_SEL_MASK));
|
||||
#endif
|
||||
|
||||
spin(1000); //1 ms
|
||||
spin(10); //10 us
|
||||
|
||||
write_reg(rLPDP_PHY_CAL, LPDP_PHY_CAL_RESET_N);
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
and_reg(rLPDP_PHY_RESERVED, ~(1 << 4));
|
||||
#endif
|
||||
and_reg(rLPDP_PHY_CLK_CTRL, ~LPDP_PHY_CLK_CTRL_CLKDIV5_RESET);
|
||||
|
||||
spin(10); //10 us
|
||||
|
||||
// perform PHY impedance calibration
|
||||
ret = lpdp_phy_impedance_calibration();
|
||||
|
||||
// panic if impedance calibration procedure failed
|
||||
if ( ret != 0 ) {
|
||||
panic("lpdp impedance calibration failed\n");
|
||||
}
|
||||
|
||||
set_lane_power_controls(0, kMaxLaneCount, LPDP_PHY_LANE_HI_Z, 0);
|
||||
|
||||
//configure PLL to an initial value
|
||||
lpdp_set_link_rate(kLinkRate162Gbps);
|
||||
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
write_reg(rLPDP_GEN_DISPLAY_SPLIT, 0);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lpdp_init_finalize(void)
|
||||
{
|
||||
//remove the overrides
|
||||
and_reg(rLPDP_PHY_GEN_CTRL, ~(LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_LANE_PD_OW));
|
||||
}
|
||||
|
||||
void lpdp_quiesce()
|
||||
{
|
||||
// power down all lanes [LANE_x.hi_z=1, LANE_x.ldo_pwrdn=1, LANE_x.pwrdn=1]
|
||||
set_lane_power_enable(false);
|
||||
|
||||
// power down AUX channel [AUX_CTRL.pwrdn=1]
|
||||
set_aux_power_enable(false);
|
||||
|
||||
// power down PHY's central bias [GEN_CTRL.bias_pwrdn=1]
|
||||
set_bias_power_enable(false);
|
||||
|
||||
// assert lpdp_sleep, pll_pwrdn, and pll_reset
|
||||
lpdp_power_pll(false);
|
||||
|
||||
}
|
||||
|
||||
int lpdp_set_link_rate(uint32_t lr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
debug(PHY, "Setting link rate to 0x%02x\n", (uint8_t)lr);
|
||||
|
||||
#if LPDP_PHY_VERSION == 2
|
||||
//<rdar://problem/20158240> Bug Fix for Default Register Value of asg_adppll Calibration Reset
|
||||
or_reg(rLPDP_PLL_FCAL, LPDP_PLL_FCAL_RESET);
|
||||
#endif
|
||||
// Block clock output during PLL setup
|
||||
or_reg(rLPDP_PLL_CLK, LPDP_PLL_CLK_VCO_BLK_VCLK);
|
||||
|
||||
// assert lpdp_sleep, pll_pwrdn, and pll_reset
|
||||
lpdp_power_pll(false);
|
||||
|
||||
// initialize link rate to 0
|
||||
_linkRate = kLinkRate000Gbps;
|
||||
|
||||
// if the target link rate is nonzero, reconfigure and power up the PLL
|
||||
if ( lr > kLinkRate000Gbps ) {
|
||||
|
||||
// update PLL dividers for new link rate
|
||||
if (update_pll_dividers(lr)) {
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// power up PLL and wait for lock,
|
||||
// if this fails, power it back down and leave link rate at 0
|
||||
if (lpdp_power_pll(true)) {
|
||||
ret = -1;
|
||||
lpdp_power_pll(false);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// finally, update the current link rate
|
||||
_linkRate = lr;
|
||||
}
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lpdp_get_link_rate(uint32_t *link_rate)
|
||||
{
|
||||
*link_rate = _linkRate;
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_phy_set_adjustment_levels(uint32_t lane, uint32_t voltage_swing, uint32_t eq,
|
||||
bool *voltage_max_reached, bool *eq_max_reached)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if ( lane > kMaxLaneCount )
|
||||
return -1;
|
||||
|
||||
debug(PHY, "lane=%d voltage=%d eq=%d\n", lane, voltage_swing, eq);
|
||||
|
||||
if (voltage_swing > kDPVoltageLevelMax) {
|
||||
voltage_swing = kDPVoltageLevelMax;
|
||||
}
|
||||
|
||||
if (eq > kDPEQLevelMax) {
|
||||
eq = kDPEQLevelMax;
|
||||
}
|
||||
|
||||
if (lpdp_port_calibration_table_fixed) {
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 2
|
||||
set_lane_adjustment_levels(lane,
|
||||
lpdp_port_calibration_table[0][0].swing,
|
||||
lpdp_port_calibration_table[0][0].deemphasis);
|
||||
#else
|
||||
set_lane_adjustment_levels(lane,
|
||||
lpdp_port_calibration_table[0][0].swing,
|
||||
lpdp_port_calibration_table[0][0].r);
|
||||
#endif
|
||||
} else {
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 2
|
||||
set_lane_adjustment_levels(lane,
|
||||
lpdp_port_calibration_table[voltage_swing][eq].swing,
|
||||
lpdp_port_calibration_table[voltage_swing][eq].deemphasis);
|
||||
#else
|
||||
set_lane_adjustment_levels(lane,
|
||||
lpdp_port_calibration_table[voltage_swing][eq].swing,
|
||||
lpdp_port_calibration_table[voltage_swing][eq].r);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (voltage_max_reached) {
|
||||
*voltage_max_reached = (voltage_swing == kDPVoltageLevelMax);
|
||||
}
|
||||
|
||||
if (eq_max_reached) {
|
||||
*eq_max_reached = (eq == kDPEQLevelMax);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lpdp_phy_reset()
|
||||
{
|
||||
lpdp_phy_impedance_calibration();
|
||||
}
|
||||
|
||||
bool lpdp_get_supports_downspread()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int lpdp_set_downspread(bool value)
|
||||
{
|
||||
//not supported but needs to succeed.. hence noop
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_get_downspread(void)
|
||||
{
|
||||
//not supported but needs to succeed.. hence noop
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
int lpdp_phy_get_adjustment_levels(uint32_t lane, uint32_t *voltage_swing, uint32_t *eq)
|
||||
{
|
||||
if (eq)
|
||||
*eq = lpdp_eq_levels[lane];
|
||||
|
||||
if (voltage_swing)
|
||||
*voltage_swing = lpdp_voltage_levels[lane];
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
void lpdp_phy_set_lane_count(const uint32_t lane_count)
|
||||
{
|
||||
// enable active lanes
|
||||
set_lane_power_controls(0, lane_count, LPDP_PHY_LANE_HI_Z, 0);
|
||||
|
||||
// disable inactive lanes
|
||||
set_lane_power_controls(lane_count, kMaxLaneCount, LPDP_PHY_LANE_HI_Z, LPDP_PHY_LANE_HI_Z);
|
||||
}
|
||||
|
||||
#if WITH_DEVICETREE
|
||||
|
||||
#include <lib/devicetree.h>
|
||||
|
||||
int lpdp_phy_update_device_tree(DTNode *lpdp_node)
|
||||
{
|
||||
u_int32_t propSize;
|
||||
char *propName;
|
||||
void *propData;
|
||||
|
||||
if (lpdp_node == NULL) {
|
||||
return RET_ERROR;
|
||||
}
|
||||
propName = "pll_vco_rctrl";
|
||||
if (FindProperty(lpdp_node, &propName, &propData, &propSize)) {
|
||||
if (pll_vco_rctrl == 0) {
|
||||
((char **)propData)[0] = "~";
|
||||
} else {
|
||||
((u_int32_t *)propData)[0] = pll_vco_rctrl;
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_HW_DISPLAY_EDP
|
||||
// Copy local settings to the DT
|
||||
propName = "link-calibration-type";
|
||||
if ( FindProperty(lpdp_node, &propName, &propData, &propSize) ) {
|
||||
memset(propData, 0, propSize);
|
||||
if (lpdp_port_calibration_table_fixed) {
|
||||
if (propSize < strlen(fixed_text) + 1) {
|
||||
panic("link-calibration-type DT entry too small.");
|
||||
}
|
||||
snprintf(propData, propSize, "%s", fixed_text);
|
||||
} else {
|
||||
if (propSize < strlen(training_table_text) + 1) {
|
||||
panic("link-calibration-type DT entry too small.");
|
||||
}
|
||||
snprintf(propData, propSize, "%s", training_table_text);
|
||||
}
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Type.");
|
||||
}
|
||||
|
||||
propName = "link-calibration-data";
|
||||
if ( FindProperty(lpdp_node, &propName, &propData, &propSize) ) {
|
||||
memset(propData, 0, propSize);
|
||||
uint32_t table_size = (lpdp_port_calibration_table_fixed) ?
|
||||
sizeof(struct lpdp_port_calibration) : sizeof(struct lpdp_port_calibration) * 16;
|
||||
if (propSize < table_size) {
|
||||
panic("link-calibration-data table too small.");
|
||||
}
|
||||
bcopy((void *)lpdp_port_calibration_table, propData, table_size);
|
||||
} else {
|
||||
panic("Missing DT LPDP Calibration Table Data.");
|
||||
}
|
||||
#endif
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
#endif //WITH_DEVICETREE
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////// PHY local functions
|
||||
|
||||
static int lpdp_phy_impedance_calibration( void )
|
||||
{
|
||||
int result = RET_SUCCESS;
|
||||
uint32_t reg;
|
||||
|
||||
// Let the pull down calibration start
|
||||
or_reg(rLPDP_PHY_CAL, LPDP_PHY_CAL_START);
|
||||
|
||||
// Wait for calibration to complete
|
||||
spin(t_cal_duration_microseconds);
|
||||
|
||||
reg = read_reg(rLPDP_PHY_CAL);
|
||||
if (!(reg & LPDP_PHY_CAL_DONE) || (reg & LPDP_PHY_CAL_FAIL)) {
|
||||
printf("impedance Calibration failed rLPDP_PHY_CAL 0x%x\n", reg);
|
||||
result = RET_ERROR;
|
||||
}
|
||||
|
||||
spin(1);
|
||||
|
||||
and_reg(rLPDP_PHY_CAL, ~LPDP_PHY_CAL_START);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void set_bias_power_enable(bool enable)
|
||||
{
|
||||
uint32_t rmw = read_reg(rLPDP_PHY_GEN_CTRL);
|
||||
rmw &= ~( LPDP_PHY_GEN_CTRL_BIAS_PWRDN);
|
||||
rmw |= ( enable ? 0 : LPDP_PHY_GEN_CTRL_BIAS_PWRDN);
|
||||
write_reg(rLPDP_PHY_GEN_CTRL, rmw);
|
||||
}
|
||||
|
||||
static void set_aux_power_enable(bool enable)
|
||||
{
|
||||
uint32_t rmw = read_reg(rLPDP_PHY_AUX_CTRL);
|
||||
rmw &= ~(LPDP_PHY_AUX_CTRL_PWRDN);
|
||||
rmw |= ( enable ? 0 : LPDP_PHY_AUX_CTRL_PWRDN);
|
||||
write_reg(rLPDP_PHY_AUX_CTRL, rmw);
|
||||
}
|
||||
|
||||
static void set_lane_power_enable(bool enable)
|
||||
{
|
||||
uint32_t bits = enable ? 0 : LPDP_PHY_LANE_x_FULL_DISABLE;
|
||||
|
||||
set_lane_power_controls(0, kMaxLaneCount, LPDP_PHY_LANE_x_FULL_DISABLE, bits);
|
||||
}
|
||||
|
||||
static void set_lane_power_controls(unsigned int first, unsigned int limit, uint32_t mask, uint32_t bits)
|
||||
{
|
||||
for (unsigned int i = first; i < limit; i++) {
|
||||
// allow at least 5ns between lane power/enable state changes
|
||||
spin(1);
|
||||
|
||||
// set power state of lane 'i'
|
||||
uint32_t rmw = read_reg(rLPDP_PHY_LANE(i));
|
||||
rmw &= ~mask;
|
||||
rmw |= bits;
|
||||
write_reg(rLPDP_PHY_LANE(i), rmw);
|
||||
}
|
||||
}
|
||||
|
||||
static bool lpdp_get_pll_is_locked()
|
||||
{
|
||||
return (read_reg(rLPDP_PLL_LOCK) & LPDP_PLL_LOCK_OUT_ON);
|
||||
}
|
||||
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
static void set_phy_configure_ldos(uint32_t ldopre_vreg_adj, uint32_t ldoclk_vreg_adj, uint32_t auxvreg_adj)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = read_reg(rLPDP_PHY_PRE_LDO_CTRL);
|
||||
reg &= ~(LPDP_PHY_PRE_LDO_CTR_LDOPRE_VREG_ADJ(0xf));
|
||||
reg |= LPDP_PHY_PRE_LDO_CTR_LDOPRE_VREG_ADJ(ldopre_vreg_adj);
|
||||
write_reg(rLPDP_PHY_PRE_LDO_CTRL, reg);
|
||||
|
||||
reg = read_reg(rLPDP_PHY_CLK_LDO_CTRL);
|
||||
reg &= ~LPDP_PHY_CLK_LDO_CTRL_LDOCLK_VREG_ADJ(0xf);
|
||||
reg |= LPDP_PHY_CLK_LDO_CTRL_LDOCLK_VREG_ADJ(ldoclk_vreg_adj);
|
||||
write_reg(rLPDP_PHY_CLK_LDO_CTRL, reg);
|
||||
|
||||
reg = read_reg(rLPDP_PHY_AUX_LDO_CTRL);
|
||||
reg &= ~LPDP_PHY_AUX_LDO_CTRL_AUXVREG_ADJ(0xf);
|
||||
reg |= LPDP_PHY_AUX_LDO_CTRL_AUXVREG_ADJ(auxvreg_adj);
|
||||
write_reg(rLPDP_PHY_AUX_LDO_CTRL, reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void enable_phy_ldos()
|
||||
{
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
and_reg(rLPDP_PHY_CLK_LDO_CTRL, ~LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN(LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN_MAX));
|
||||
and_reg(rLPDP_PHY_PRE_LDO_CTRL, ~LPDP_PHY_PRE_LDO_CTR_LDOPRE_PWRDN(LPDP_PHY_PRE_LDO_CTR_LDOPRE_PWRDN_MAX));
|
||||
and_reg(rLPDP_PHY_AUX_LDO_CTRL, ~LPDP_PHY_AUX_LDO_CTRL_AUXLDO_PWRDN);
|
||||
#elif LPDP_PHY_VERSION == 2
|
||||
and_reg(rLPDP_PHY_CLK_LDO_CTRL, ~(LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN_SML(LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN_SML_MAX)|
|
||||
LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN(LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN_MAX)));
|
||||
and_reg(rLPDP_PHY_AUX_LDO_CTRL, ~(LPDP_PHY_AUX_LDO_CTRL_LDOPOST_PWRDN_SML|LPDP_PHY_AUX_LDO_CTRL_LDOCLK_PWRDN_SML|
|
||||
LPDP_PHY_AUX_LDO_CTRL_LDOPOST_PWRDN_BIG|LPDP_PHY_AUX_LDO_CTRL_LDOCLK_PWRDN_BIG));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_aux_voltage_swing(uint32_t vreg_adj)
|
||||
{
|
||||
uint32_t rmw = read_reg(rLPDP_PHY_AUX_CTRL);
|
||||
rmw &= ~LPDP_PHY_AUX_CTRL_VREG_ADJ_MASK;
|
||||
rmw |= vreg_adj << LPDP_PHY_AUX_CTRL_VREG_ADJ_SHIFT;
|
||||
write_reg(rLPDP_PHY_AUX_CTRL, rmw);
|
||||
}
|
||||
|
||||
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 2
|
||||
static void set_lane_adjustment_levels(unsigned int lane, uint8_t voltage_swing, uint8_t eq)
|
||||
#else
|
||||
static void set_lane_adjustment_levels(unsigned int lane, uint32_t voltage_swing, uint32_t r)
|
||||
#endif
|
||||
{
|
||||
uint32_t rmw = read_reg(rLPDP_PHY_LANE(lane));
|
||||
rmw &= ~(LPDP_PHY_LANE_x_VREG_ADJ_MASK);
|
||||
rmw |= LPDP_PHY_LANE_VREG_ADJ(voltage_swing);
|
||||
write_reg(rLPDP_PHY_LANE(lane), rmw);
|
||||
|
||||
lpdp_voltage_levels[lane] = voltage_swing;
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 2
|
||||
lpdp_eq_levels[lane] = eq;
|
||||
#else
|
||||
#if LPDP_LINK_CAL_TABLE_VERSION < 3
|
||||
// Maui
|
||||
lpdp_eq_levels[lane] = (((((rLPDP_PHY_CAL_TX & LPDP_PHY_CAL_TX_CODE_FSM_MASK) >> LPDP_PHY_CAL_TX_CODE_FSM_SHIFT) * r) / 2) + (1 << 15)) >> 16;
|
||||
#else
|
||||
// Elba/Malta +
|
||||
lpdp_eq_levels[lane] = ((((((rLPDP_PHY_CAL_TX & LPDP_PHY_CAL_TX_CODE_FSM_MASK) >> LPDP_PHY_CAL_TX_CODE_FSM_SHIFT) + 24) * r) / 2) + (1 << 15)) >> 16;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//TODO: Get the correct values for gclk_div
|
||||
static int update_pll_dividers(uint32_t lr)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t fb;
|
||||
uint32_t pre;
|
||||
|
||||
// determine feedback and pre-divider ratios
|
||||
switch ( lr ) {
|
||||
case kLinkRate000Gbps:
|
||||
fb = pre = 0;
|
||||
break;
|
||||
|
||||
case kLinkRate162Gbps:
|
||||
fb = 135;
|
||||
pre = 4;
|
||||
break;
|
||||
|
||||
case kLinkRate270Gbps:
|
||||
fb = 225;
|
||||
pre = 4;
|
||||
break;
|
||||
|
||||
case kLinkRate324Gbps:
|
||||
fb = 135;
|
||||
pre = 2;
|
||||
break;
|
||||
|
||||
case kLinkRate540Gbps: // Not supported on Fiji/Capri
|
||||
fb = 225;
|
||||
pre = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
debug(ERROR, "unsupported link rate: %u", lr);
|
||||
ret = -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Set new PLL divider ratios
|
||||
uint32_t rmw = read_reg(rLPDP_PLL_IDIV);
|
||||
rmw &= ~LPDP_PLL_IDIV_FB_MASK;
|
||||
rmw |= (fb << LPDP_PLL_IDIV_FB_SHIFT);
|
||||
rmw &= ~LPDP_PLL_IDIV_PRE_MASK;
|
||||
rmw |= (pre << LPDP_PLL_IDIV_PRE_SHIFT);
|
||||
write_reg(rLPDP_PLL_IDIV, rmw);
|
||||
and_reg(rLPDP_PLL_GEN, ~(LPDP_PLL_GEN_GCLK_DIV(LPDP_PLL_GEN_GCLK_DIV_MASK)));
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lpdp_power_pll(bool poweron)
|
||||
{
|
||||
int result = RET_ERROR;
|
||||
|
||||
if ((lpdp_pll_state != lpdp_pll_state_unknown) && (lpdp_pll_state == poweron))
|
||||
return RET_SUCCESS;
|
||||
|
||||
lpdp_pll_state = poweron;
|
||||
if (poweron)
|
||||
result = lpdp_power_up_pll();
|
||||
else
|
||||
result = lpdp_power_down_pll();
|
||||
return result;
|
||||
}
|
||||
|
||||
static int lpdp_power_down_pll()
|
||||
{
|
||||
or_reg(rLPDP_PHY_GEN_CTRL, (LPDP_PHY_GEN_CTRL_SEQ_OW | LPDP_PHY_GEN_CTRL_SLEEP_SW));
|
||||
|
||||
spin(31); //> 30 ns
|
||||
|
||||
// de-assert pll_pwrdn after at least 10µS
|
||||
and_reg(rLPDP_PLL_GEN, ~LPDP_PLL_GEN_PWRDN);
|
||||
|
||||
//spin(get_reset_duration(&lpdp_pll_timing));
|
||||
spin(100);
|
||||
|
||||
or_reg(rLPDP_PLL_CLK, LPDP_PLL_CLK_VCO_BLK_VCLK);
|
||||
// de-assert pll_reset after at least 100µS
|
||||
and_reg(rLPDP_PLL_GEN, ~LPDP_PLL_GEN_RST);
|
||||
or_reg(rLPDP_PLL_GEN, (LPDP_PLL_GEN_PWRDN | LPDP_PLL_GEN_RST));
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
static int lpdp_power_up_pll()
|
||||
{
|
||||
// Note: powerDownPll() must be called first
|
||||
assert(read_reg(rLPDP_PHY_GEN_CTRL & LPDP_PHY_GEN_CTRL_SEQ_OW));
|
||||
assert(read_reg(rLPDP_PHY_GEN_CTRL & LPDP_PHY_GEN_CTRL_SLEEP_SW));
|
||||
assert(read_reg(rLPDP_PLL_GEN & LPDP_PLL_GEN_PWRDN));
|
||||
assert(read_reg(rLPDP_PLL_GEN & LPDP_PLL_GEN_RST));
|
||||
|
||||
//spin(get_power_down_duration(&lpdp_pll_timing));
|
||||
spin(10);
|
||||
|
||||
// de-assert pll_pwrdn after at least 10µS
|
||||
and_reg(rLPDP_PLL_GEN, ~LPDP_PLL_GEN_PWRDN);
|
||||
|
||||
//spin(get_reset_duration(&lpdp_pll_timing));
|
||||
spin(100);
|
||||
|
||||
// de-assert pll_reset after at least 100µS
|
||||
and_reg(rLPDP_PLL_GEN, ~LPDP_PLL_GEN_RST);
|
||||
|
||||
//spin(get_reset_to_update_duration(&lpdp_pll_timing));
|
||||
spin(5);
|
||||
|
||||
// assert pll_update_divn for at least 1µS
|
||||
or_reg(rLPDP_PLL_IDIV, LPDP_PLL_IDIV_UPDT);
|
||||
spin(1);
|
||||
and_reg(rLPDP_PLL_IDIV, ~LPDP_PLL_IDIV_UPDT);
|
||||
|
||||
// wait for PLL lock
|
||||
//spin(get_lock_duration(&lpdp_pll_timing));
|
||||
spin(50);
|
||||
|
||||
// check for PLL lock, bail if not locked
|
||||
if (!lpdp_get_pll_is_locked()) {
|
||||
printf("failed to lock lpdp pll\n");
|
||||
return RET_ERROR;
|
||||
}
|
||||
|
||||
// Enable clock output after PLL is locked
|
||||
and_reg(rLPDP_PLL_CLK, ~LPDP_PLL_CLK_VCO_BLK_VCLK);
|
||||
|
||||
// de-assert lpdp_sleep
|
||||
|
||||
// Note: The sleep signal is used by the LPDP PHY to gate-off PLL clock;
|
||||
// see <rdar://problem/15238851>.
|
||||
and_reg(rLPDP_PHY_GEN_CTRL, ~LPDP_PHY_GEN_CTRL_SLEEP_SW);
|
||||
|
||||
// wait at least 1µS for output driver ready
|
||||
spin(2);
|
||||
|
||||
or_reg(rLPDP_PLL_GEN, LPDP_PLL_GEN_CLKDIV2_RESET_N);
|
||||
|
||||
return RET_SUCCESS;
|
||||
}
|
||||
|
||||
void lpdp_phy_configure_alpm(bool enable)
|
||||
{
|
||||
|
||||
if (enable) {
|
||||
// Clear Sequencer overwrite and Lane power-down overwrite
|
||||
and_reg(rLPDP_PHY_GEN_CTRL, ~(LPDP_PHY_GEN_CTRL_SLEEP_SW | LPDP_PHY_GEN_CTRL_LANE_PD_OW));
|
||||
|
||||
// Program ALPM PHY Sequence Timers
|
||||
write_reg(rLPDP_GEN_SEQ_1, LPDP_GEN_SEQ_1_START_COUNT(lpdp_pll_timing.start_count));
|
||||
or_reg(rLPDP_GEN_SEQ_1, LPDP_GEN_SEQ_1_SETUP_COUNT(lpdp_pll_timing.setup_count));
|
||||
//Hardcodede value to be fixed in <rdar://problem/16786136> Make display_config a void * for future flexibility
|
||||
write_reg(rLPDP_GEN_SEQ_2, 1873);
|
||||
write_reg(rLPDP_GEN_SEQ_3, lpdp_pll_timing.reset_count);
|
||||
write_reg(rLPDP_GEN_SEQ_4, LPDP_GEN_SEQ_4_HOLD_COUNT(lpdp_pll_timing.hold_count));
|
||||
write_reg(rLPDP_GEN_SEQ_5, LPDP_GEN_SEQ_5_FINISH_COUNT(lpdp_pll_timing.finish_count));
|
||||
or_reg(rLPDP_GEN_SEQ_4, LPDP_GEN_SEQ_4_UPDATE_COUNT(lpdp_pll_timing.update_count));
|
||||
write_reg(rLPDP_GEN_SEQ_5, LPDP_GEN_SEQ_5_WAKEUP_COUNT(lpdp_pll_timing.wakeup_count));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// convenience methods for conversion to µs (for software use)
|
||||
|
||||
static unsigned int micro_seconds_for_count(struct pll_timing *tm, unsigned int count) {
|
||||
// Note: Normally, ref_mhz == ref_div, but it is not assumed.
|
||||
// Values are rounded up.
|
||||
return ((count * tm->ref_div) + tm->ref_mhz - 1) / tm->ref_mhz;
|
||||
}
|
||||
|
||||
static unsigned int get_sleep_to_power_down_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->start_count);
|
||||
}
|
||||
|
||||
static unsigned int get_power_down_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->pwrdn_count);
|
||||
}
|
||||
|
||||
static unsigned int get_reset_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->reset_count);
|
||||
}
|
||||
|
||||
static unsigned int get_reset_to_update_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->update_count);
|
||||
}
|
||||
|
||||
static unsigned int get_lock_duration(struct pll_timing *tm) {
|
||||
return micro_seconds_for_count(tm, tm->finish_count);
|
||||
}
|
||||
|
||||
static uint32_t read_reg(uint32_t offset)
|
||||
{
|
||||
volatile uint32_t reg;
|
||||
|
||||
reg = (*(volatile uint32_t *)(__base_address + offset));
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void write_reg(uint32_t offset, uint32_t value)
|
||||
{
|
||||
*(volatile uint32_t *)(__base_address + offset) = value;
|
||||
}
|
||||
|
||||
static void and_reg(uint32_t offset, uint32_t value)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = read_reg(offset);
|
||||
reg &= value;
|
||||
write_reg(offset, reg);
|
||||
}
|
||||
|
||||
static void or_reg(uint32_t offset, uint32_t value)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = read_reg(offset);
|
||||
reg |= value;
|
||||
write_reg(offset, reg);
|
||||
}
|
||||
|
||||
static void set_bits_in_reg(uint32_t offset, uint32_t pos, uint32_t mask, uint32_t value)
|
||||
{
|
||||
uint32_t set = read_reg(offset);
|
||||
|
||||
set &= ~mask;
|
||||
set |= (value << pos);
|
||||
|
||||
write_reg(offset, set);
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef _LPDP_PHY_REGS_H
|
||||
#define _LPDP_PHY_REGS_H
|
||||
|
||||
#define rLPDP_GEN_VERSION (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00000))
|
||||
#define rLPDP_GEN_SEQ_0 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00004))
|
||||
|
||||
#define rLPDP_GEN_SEQ_1 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00008))
|
||||
#define LPDP_GEN_SEQ_1_START_COUNT(n) ((n) << 8)
|
||||
#define LPDP_GEN_SEQ_1_SETUP_COUNT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_GEN_SEQ_2 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0000c))
|
||||
#define rLPDP_GEN_SEQ_3 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00010))
|
||||
|
||||
#define rLPDP_GEN_SEQ_4 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00014))
|
||||
#define LPDP_GEN_SEQ_4_FINISH_COUNT(n) ((n) << 8)
|
||||
#define LPDP_GEN_SEQ_4_UPDATE_COUNT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_GEN_LINE_COUNTER (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00018))
|
||||
#define rLPDP_GEN_SPARE_CONFIG (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0001c))
|
||||
#define rLPDP_GEN_SPARE_STATUS (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00020))
|
||||
#define rLPDP_GEN_AUX_DRIVER (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00024))
|
||||
#define LPDP_GEN_AUX_DRIVER_EXT_SEL (1 << 15)
|
||||
|
||||
#define rLPDP_PHY_GEN_CTRL (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00040))
|
||||
#define LPDP_PHY_GEN_CTRL_SEQ_OW (1 << 7)
|
||||
#define LPDP_PHY_GEN_CTRL_SLEEP_SW (1 << 6)
|
||||
#define LPDP_PHY_GEN_CTRL_LANE_PD_OW (1 << 2)
|
||||
#define LPDP_PHY_GEN_CTRL_BIAS_PWRDN (1 << 0)
|
||||
|
||||
#define rLPDP_PHY_LANE(n) (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00044 + ((n) << 2)))
|
||||
#define rLPDP_PHY_LANE_0 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00044))
|
||||
#define LPDP_PHY_LANE_CM_PRECHARGE_SLEEP(n) ((n) << 13)
|
||||
#define LPDP_PHY_LANE_CM_PRECHARGE_NORMAL(n) ((n) << 11)
|
||||
#define LPDP_PHY_LANE_LDO_PWRDN (1 << 10)
|
||||
#define LPDP_PHY_LANE_PWRDN (1 << 9)
|
||||
#define LPDP_PHY_LANE_HI_Z (1 << 8)
|
||||
#define LPDP_PHY_LANE_DE_ENABLE (1 << 7)
|
||||
#define LPDP_PHY_LANE_PASSMOS_CTRL(n) ((n) << 4)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ(n) ((n) << 0)
|
||||
#define LPDP_PHY_LANE_x_VREG_ADJ_MAX 0xF
|
||||
#define LPDP_PHY_LANE_x_VREG_ADJ_SHIFT 0
|
||||
#define LPDP_PHY_LANE_x_VREG_ADJ_MASK (0xF << LPDP_PHY_LANE_x_VREG_ADJ_SHIFT)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_420_mV (15)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_400_mV (14)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_380_mV (13)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_360_mV (12)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_340_mV (11)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_320_mV (10)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_300_mV (9)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_280_mV (8)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_260_mV (7)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_240_mV (6)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_220_mV (5)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_200_mV (4)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_180_mV (3)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_160_mV (2)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_140_mV (1)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_120_mV (0)
|
||||
#define LPDP_PHY_LANE_x_FULL_DISABLE (LPDP_PHY_LANE_LDO_PWRDN | \
|
||||
LPDP_PHY_LANE_PWRDN | \
|
||||
LPDP_PHY_LANE_HI_Z)
|
||||
|
||||
#define rLPDP_PHY_LANE_1 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00048))
|
||||
#define rLPDP_PHY_LANE_2 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0004c))
|
||||
#define rLPDP_PHY_LANE_3 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00050))
|
||||
#define rLPDP_PHY_PRBS_0 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00054))
|
||||
#define rLPDP_PHY_PRBS_1 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00058))
|
||||
#define rLPDP_PHY_PRBS_2 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0005c))
|
||||
#define rLPDP_PHY_PRBS_3 (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00060))
|
||||
#define rLPDP_PHY_PRBS_ERR (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00064))
|
||||
#define rLPDP_PHY_TEST (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00068))
|
||||
#define rLPDP_PHY_BIST (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0006c))
|
||||
|
||||
#define rLPDP_PHY_CAL_CTRL (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00070))
|
||||
#define LPDP_PHY_CAL_CTRL_AUTOZERO_BYP (1 << 3)
|
||||
#define LPDP_PHY_CAL_CTRL_TYPE_SEL_UP (1 << 2)
|
||||
#define LPDP_PHY_CAL_CTRL_RST (1 << 1)
|
||||
#define LPDP_PHY_CAL_CTRL_PWRDN (1 << 0)
|
||||
|
||||
#define rLPDP_PHY_CAL_EXT (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00074))
|
||||
#define LPDP_PHY_CAL_EXT_CTRL_SEL (1 << 15)
|
||||
|
||||
#define rLPDP_PHY_CAL_RESULT (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00078))
|
||||
#define LPDP_PHY_CAL_RESULT_COMPLETE (1 << 15)
|
||||
#define LPDP_PHY_CAL_RESULT_CO_PD (1 << 14)
|
||||
#define LPDP_PHY_CAL_RESULT_PD(n) (((n) >> 8) & 0x3F)
|
||||
#define LPDP_PHY_CAL_RESULT_CO_PU (1 << 7)
|
||||
#define LPDP_PHY_CAL_RESULT_PU(n) (n & 0x7F)
|
||||
#define rLPDP_PHY_AUX_CTRL (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0007C))
|
||||
#define LPDP_PHY_AUX_CTRL_PWRDN (1 << 4)
|
||||
#define LPDP_PHY_AUX_CTRL_VREG_ADJ_SHIFT 0
|
||||
#define LPDP_PHY_AUX_CTRL_VREG_ADJ_MASK (0xF << LPDP_PHY_AUX_CTRL_VREG_ADJ_SHIFT)
|
||||
#define LPDP_PHY_AUX_CTRL_VREG_ADJ_MAX 0xF
|
||||
|
||||
|
||||
|
||||
#define rLPDP_PLL_GEN (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00080))
|
||||
#define LPDP_PLL_GEN_TEST_SEL_VSSA (0 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_SEL_VDD_SOC (1 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_SEL_VREG_1VA (2 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_SEL_PLL_LOCK_OUT (3 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_SEL_CP_OUT (4 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_SEL_VCO_TOP (5 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_SEL_VREF_CAL (6 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_SEL_VBTST (7 << 10)
|
||||
#define LPDP_PLL_GEN_TEST_EN (1 << 9)
|
||||
#define LPDP_PLL_GEN_GCLK_SEL_VCLK (1 << 8)
|
||||
#define LPDP_PLL_GEN_GCLK_DIV(n) (n << 4)
|
||||
#define LPDP_PLL_GEN_STOP_CLK (1 << 3)
|
||||
#define LPDP_PLL_GEN_BYPASS (1 << 2)
|
||||
#define LPDP_PLL_GEN_RST (1 << 1)
|
||||
#define LPDP_PLL_GEN_PWRDN (1 << 0)
|
||||
|
||||
#define rLPDP_PLL_CLK (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00084))
|
||||
#define LPDP_PLL_CLK_FLIN_SEL (1 << 12)
|
||||
#define LPDP_PLL_CLK_BG_START_SEL (1 << 11)
|
||||
#define LPDP_PLL_CLK_PFDCP_RST_SEL (1 << 10)
|
||||
#define LPDP_PLL_CLK_VCLK_SEL_VCO (1 << 9)
|
||||
#define LPDP_PLL_CLK_VCO_BLK_RSTPD (1 << 8)
|
||||
#define LPDP_PLL_CLK_VCO_BLK_SCLK (1 << 7)
|
||||
#define LPDP_PLL_CLK_VCO_BLK_VCLK (1 << 6)
|
||||
#define LPDP_PLL_CLK_VCO_RCTRL_SEL_ENABLE (1 << 5)
|
||||
#define LPDP_PLL_CLK_VCO_RCTRL_OW_SHIFT 2
|
||||
#define LPDP_PLL_CLK_VCO_RCTRL_OW_MASK (0x7 << LPDP_PLL_CLK_VCO_RCTRL_OW_SHIFT)
|
||||
#define LPDP_PLL_CLK_VCO_PCTRL(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PLL_IDIV (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00088))
|
||||
#define LPDP_PLL_IDIV_UPDT (1 << 14)
|
||||
#define LPDP_PLL_IDIV_FB(n) (n << 5)
|
||||
#define LPDP_PLL_IDIV_PRE(n) (n << 0)
|
||||
#define LPDP_PLL_IDIV_FB_SHIFT 5
|
||||
#define LPDP_PLL_IDIV_FB_MASK (0x1FF << LPDP_PLL_IDIV_FB_SHIFT)
|
||||
#define LPDP_PLL_IDIV_PRE_SHIFT 0
|
||||
#define LPDP_PLL_IDIV_PRE_MASK (0x1F << LPDP_PLL_IDIV_PRE_SHIFT)
|
||||
|
||||
|
||||
#define rLPDP_PLL_CP (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0008C))
|
||||
#define LPDP_PLL_CP_BOOST_MODE (1 << 14)
|
||||
#define LPDP_PLL_CP_BOOST_EN (1 << 13)
|
||||
#define LPDP_PLL_CP_ENABLE (1 << 12)
|
||||
#define LPDP_PLL_CP_RSTN (1 << 11)
|
||||
#define LPDP_PLL_CP_LIN_EN (1 << 10)
|
||||
#define LPDP_PLL_CP_R_SET(n) (n << 3)
|
||||
#define LPDP_PLL_CP_I_SET(n) (n << 0)
|
||||
|
||||
#define rLPDP_PLL_LOCK (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00090))
|
||||
#define LPDP_PLL_LOCK_OUT_OFF (0 << 9)
|
||||
#define LPDP_PLL_LOCK_OUT_ON (1 << 9)
|
||||
#define LPDP_PLL_LOCK_RST_OFF (0 << 8)
|
||||
#define LPDP_PLL_LOCK_RST_ON (1 << 8)
|
||||
#define LPDP_PLL_LOCK_POR_OFF (0 << 7)
|
||||
#define LPDP_PLL_LOCK_POR_ON (1 << 7)
|
||||
#define LPDP_PLL_LOCK_DIV(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PLL_VCO (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00094))
|
||||
#define LPDP_PLL_VCO_BUF_PWRDN_OFF (0 << 14)
|
||||
#define LPDP_PLL_VCO_BUF_PWRDN_ON (1 << 14)
|
||||
#define LPDP_PLL_VCO_DEC_BYPASS_OFF (0 << 13)
|
||||
#define LPDP_PLL_VCO_DEC_BYPASS_ON (1 << 13)
|
||||
#define LPDP_PLL_VCO_REG_PWRDN_OFF (0 << 12)
|
||||
#define LPDP_PLL_VCO_REG_PWRDN_ON (1 << 12)
|
||||
#define LPDP_PLL_VCO_REG_BYPASS_OFF (0 << 11)
|
||||
#define LPDP_PLL_VCO_REG_BYPASS_ON (1 << 11)
|
||||
#define LPDP_PLL_VCO_VREG_ADJ(n) ((n) << 8)
|
||||
#define LPDP_PLL_VCO_K_VCO_CTRL(n) ((n) << 4)
|
||||
#define LPDP_PLL_VCO_RESDIV_SEL(n) ((n) << 1)
|
||||
#define LPDP_PLL_VCO_RESDIV_VREF_EN_OFF (0 << 0)
|
||||
#define LPDP_PLL_VCO_RESDIV_VREF_EN_ON (1 << 0)
|
||||
|
||||
#define rLPDP_PLL_SDM (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x00098))
|
||||
#define rLPDP_PLL_SSC (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x0009c))
|
||||
#define rLPDP_PLL_FMC (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x000a0))
|
||||
#define rLPDP_PLL_SPARE (*(volatile u_int32_t *)(LPDP_PHY_BASE_ADDR + 0x000a4))
|
||||
#endif //_LPDP_PHY_REGS_H
|
||||
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef _LPDP_PHY_REGS_V2_H
|
||||
#define _LPDP_PHY_REGS_V2_H
|
||||
|
||||
#define rLPDP_GEN_VERSION (0x00000)
|
||||
#define rLPDP_GEN_SEQ_0 (0x00004)
|
||||
|
||||
#define rLPDP_GEN_SEQ_1 (0x00008)
|
||||
#define LPDP_GEN_SEQ_1_START_COUNT(n) ((n) << 8)
|
||||
#define LPDP_GEN_SEQ_1_SETUP_COUNT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_GEN_SEQ_2 (0x0000c)
|
||||
#define rLPDP_GEN_SEQ_3 (0x00010)
|
||||
|
||||
#define rLPDP_GEN_SEQ_4 (0x00014)
|
||||
#define LPDP_GEN_SEQ_4_HOLD_COUNT(n) ((n) << 8)
|
||||
#define LPDP_GEN_SEQ_4_UPDATE_COUNT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_GEN_SEQ_5 (0x00018)
|
||||
#define LPDP_GEN_SEQ_5_FINISH_COUNT(n) ((n) << 8)
|
||||
#define LPDP_GEN_SEQ_5_WAKEUP_COUNT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_GEN_LINE_COUNTER (0x0001c)
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
#define rLPDP_GEN_DISPLAY_SPLIT (0x00020)
|
||||
#define rLPDP_GEN_SPARE_CONFIG (0x00024)
|
||||
#define rLPDP_GEN_SPARE_STATUS (0x00028)
|
||||
#elif LPDP_PHY_VERSION == 2
|
||||
#define rLPDP_GEN_SPARE_CONFIG (0x00020)
|
||||
#define rLPDP_GEN_SPARE_STATUS (0x00024)
|
||||
#endif
|
||||
|
||||
#define rLPDP_PHY_GEN_CTRL (0x00100)
|
||||
#define LPDP_PHY_GEN_CTRL_BIAS_START_PULSE_EXT (1 << 12)
|
||||
#define LPDP_PHY_GEN_CTRLBIAS_EXT_START_SEL (1 << 11)
|
||||
#define LPDP_PHY_GEN_CTRL_WAKEUP_SW (1 << 10)
|
||||
#define LPDP_PHY_GEN_CTRL_FIFO_RST_MASK (1 << 9)
|
||||
#define LPDP_PHY_GEN_CTRL_FIFO_RST_HW (1 << 8)
|
||||
#define LPDP_PHY_GEN_CTRL_SEQ_OW (1 << 7)
|
||||
#define LPDP_PHY_GEN_CTRL_SLEEP_SW (1 << 6)
|
||||
#define LPDP_PHY_GEN_CTRL_LANE_PD_OW (1 << 2)
|
||||
#define LPDP_PHY_GEN_CTRL_BIAS_PWRDN (1 << 0)
|
||||
|
||||
#define rLPDP_PHY_LANE(n) (0x00104 + ((n) << 2))
|
||||
#define rLPDP_PHY_LANE_0 (0x00104)
|
||||
#define LPDP_PHY_LANE_CM_PRECHARGE_SLEEP(n) ((n) << 13)
|
||||
#define LPDP_PHY_LANE_CM_PRECHARGE_NORMAL(n) ((n) << 11)
|
||||
#define LPDP_PHY_LANE_LDO_PWRDN (1 << 10)
|
||||
#define LPDP_PHY_LANE_PWRDN (1 << 9)
|
||||
#define LPDP_PHY_LANE_HI_Z (1 << 8)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ(n) ((n) << 0)
|
||||
#define LPDP_PHY_LANE_x_VREG_ADJ_MAX 0xF
|
||||
#define LPDP_PHY_LANE_x_VREG_ADJ_SHIFT 0
|
||||
#define LPDP_PHY_LANE_x_VREG_ADJ_MASK (0xF << LPDP_PHY_LANE_x_VREG_ADJ_SHIFT)
|
||||
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_570_mV (15)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_540_mV (14)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_510_mV (13)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_480_mV (12)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_450_mV (11)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_420_mV (10)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_390_mV (9)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_360_mV (8)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_330_mV (7)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_300_mV (6)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_270_mV (5)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_240_mV (4)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_210_mV (3)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_180_mV (2)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_150_mV (1)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_120_mV (0)
|
||||
#define LPDP_PHY_LANE_x_FULL_DISABLE (LPDP_PHY_LANE_LDO_PWRDN | \
|
||||
LPDP_PHY_LANE_PWRDN)
|
||||
#elif LPDP_PHY_VERSION == 2
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_530_mV (7)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_450_mV (6)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_390_mV (5)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_310_mV (4)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_250_mV (3)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_210_mV (2)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_190_mV (1)
|
||||
#define LPDP_PHY_LANE_VREG_ADJ_170_mV (0)
|
||||
#define LPDP_PHY_LANE_PWRDN_SML (1 << 7)
|
||||
#define LPDP_PHY_LANE_x_FULL_DISABLE (LPDP_PHY_LANE_LDO_PWRDN | \
|
||||
LPDP_PHY_LANE_PWRDN | \
|
||||
LPDP_PHY_LANE_PWRDN_SML)
|
||||
#endif
|
||||
|
||||
#define rLPDP_PHY_LANE_1 (0x00108)
|
||||
#define rLPDP_PHY_LANE_2 (0x0010c)
|
||||
#define rLPDP_PHY_LANE_3 (0x00110)
|
||||
#define rLPDP_PHY_PRBS_0 (0x00114)
|
||||
#define rLPDP_PHY_PRBS_1 (0x00118)
|
||||
#define rLPDP_PHY_PRBS_2 (0x0011c)
|
||||
#define rLPDP_PHY_PRBS_3 (0x00120)
|
||||
#define rLPDP_PHY_PRBS_ERR (0x00124)
|
||||
#define rLPDP_PHY_TEST (0x00128)
|
||||
|
||||
#define rLPDP_PHY_BIST (0x0012c)
|
||||
#define LPDP_PHY_BIST_DEMUX_RST (1 << 8)
|
||||
#define LPDP_PHY_BIST_LOOPBACK_SRC_SEL(n) ((n) << 3)
|
||||
#define LPDP_PHY_BIST_LOOPBACK_SRC_SEL_MASK (0x1f)
|
||||
#define LPDP_PHY_BIST_NONE 0x0
|
||||
#define LPDP_PHY_BIST_LANE0 0x1
|
||||
#define LPDP_PHY_BIST_LANE1 0x2
|
||||
#define LPDP_PHY_BIST_LANE2 0x4
|
||||
#define LPDP_PHY_BIST_LANE3 0x8
|
||||
#define LPDP_PHY_BIST_DEMUX 0x10
|
||||
#define LPDP_PHY_BIST_DEMUX_SEL(n) ((n) << 1)
|
||||
#define LPDP_PHY_BIST_SEL0 0x0
|
||||
#define LPDP_PHY_BIST_SEL1 0x1
|
||||
#define LPDP_PHY_BIST_SEL2 0x2
|
||||
#define LPDP_PHY_BIST_SEL3 0x3
|
||||
#define LPDP_PHY_BIST_ENABLE (1 << 0)
|
||||
|
||||
#define rLPDP_PHY_CAL (0x00130)
|
||||
#define LPDP_PHY_CAL_COMP_OUT (1 << 8)
|
||||
#define LPDP_PHY_CAL_FAIL (1 << 7)
|
||||
#define LPDP_PHY_CAL_DONE (1 << 6)
|
||||
#define LPDP_PHY_CAL_AZ_BYP (1 << 5)
|
||||
#define LPDP_PHY_CAL_MODE_FORCE(n) ((n) << 3)
|
||||
#define LPDP_PHY_CAL_FORCE_EN (1 << 2)
|
||||
#define LPDP_PHY_CAL_START (1 << 1)
|
||||
#define LPDP_PHY_CAL_RESET_N (1 << 0)
|
||||
|
||||
#define rLPDP_PHY_CAL_PD (0x00134)
|
||||
#define LPDP_PHY_CAL_PD_CODE_ERR (1 << 13)
|
||||
#define LPDP_PHY_CAL_PD_EXT_SEL (1 << 12)
|
||||
#define LPDP_PHY_CAL_PD_CODE_FSM(n) ((n) << 6)
|
||||
#define LPDP_PHY_CAL_PD_CODE_EXT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PHY_CAL_PU (0x00138)
|
||||
#define LPDP_PHY_CAL_P_CODE_ERR (1 << 13)
|
||||
#define LPDP_PHY_CAL_P_EXT_SEL (1 << 12)
|
||||
#define LPDP_PHY_CAL_P_CODE_FSM(n) ((n) << 6)
|
||||
#define LPDP_PHY_CAL_P_CODE_EXT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PHY_CAL_TX (0x0013C)
|
||||
#define LPDP_PHY_CAL_TX_EXT_SEL (1 << 12)
|
||||
#define LPDP_PHY_CAL_TX_CODE_FSM_SHIFT (6)
|
||||
#define LPDP_PHY_CAL_TX_CODE_FSM(n) ((n) << LPDP_PHY_CAL_TX_CODE_FSM_SHIFT)
|
||||
#define LPDP_PHY_CAL_TX_CODE_FSM_MASK ((0x3F) << LPDP_PHY_CAL_TX_CODE_FSM_SHIFT)
|
||||
#define LPDP_PHY_CAL_TX_CODE_EXT(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PHY_AUX_CTRL (0x00140)
|
||||
#define LPDP_PHY_AUX_CTRL_TX_AUX_ENABLE (1 << 5)
|
||||
#define LPDP_PHY_AUX_CTRL_PWRDN (1 << 4)
|
||||
#define LPDP_PHY_AUX_CTRL_VREG_ADJ(n) ((n) << 0)
|
||||
#define LPDP_PHY_AUX_CTRL_VREG_ADJ_SHIFT 0
|
||||
#define LPDP_PHY_AUX_CTRL_VREG_ADJ_MASK (0xF << LPDP_PHY_AUX_CTRL_VREG_ADJ_SHIFT)
|
||||
#define LPDP_PHY_AUX_CTRL_VREG_ADJ_MAX 0xF
|
||||
|
||||
#define rLPDP_PHY_AUX_DRIVER (0x00144)
|
||||
#define LPDP_PHY_AUX_DRIVER_EXT_SEL (1 << 15)
|
||||
#define LPDP_PHY_AUX_DRIVER_EXT_PD(n) ((n) << 8)
|
||||
#define LPDP_PHY_AUX_DRIVER_EXT_PU(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PHY_CLK_CTRL (0x00148)
|
||||
#define LPDP_PHY_CLK_CTRL_CLKDIV_SHFTEN (1 << 2)
|
||||
#define LPDP_PHY_CLK_CTRL_CLK_ENABLE (1 << 1)
|
||||
#define LPDP_PHY_CLK_CTRL_CLKDIV5_RESET (1 << 0)
|
||||
|
||||
#define rLPDP_PHY_CLK_LDO_CTRL (0x0014c)
|
||||
#if LPDP_PHY_VERSION == 2
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_REF_ADJ(n) ((n) << 15)
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN_SML(n) ((n) << 11)
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN_SML_MAX (0xf)
|
||||
#endif
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_SB_EN (1 << 10)
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_BGREF_BYPASS (1 << 9)
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_BYPASS (1 << 8)
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_VREG_ADJ(n) ((n) << 4)
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN(n) ((n) << 0)
|
||||
#define LPDP_PHY_CLK_LDO_CTRL_LDOCLK_PWRDN_MAX (0xf)
|
||||
|
||||
#define rLPDP_PHY_PRE_LDO_CTRL (0x00150)
|
||||
#define LPDP_PHY_PRE_LDO_CTR_LDOPRE_SB_EN (1 << 10)
|
||||
#define LPDP_PHY_PRE_LDO_CTR_LDOPRE_BGREF_BYPASS (1 << 9)
|
||||
#define LPDP_PHY_PRE_LDO_CTR_LDOPRE_BYPASS (1 << 8)
|
||||
#define LPDP_PHY_PRE_LDO_CTR_LDOPRE_VREG_ADJ(n) ((n) << 4)
|
||||
#define LPDP_PHY_PRE_LDO_CTR_LDOPRE_PWRDN(n) ((n) << 0)
|
||||
#define LPDP_PHY_PRE_LDO_CTR_LDOPRE_PWRDN_MAX (0xf)
|
||||
|
||||
#define rLPDP_PHY_POST_LDO_CTRL (0x00154)
|
||||
#define LPDP_PHY_POST_LDO_CTRL_LDOPOST_VR_TEST_EN (1 << 12)
|
||||
#define LPDP_PHY_POST_LDO_CTRL_LDOPOST_LEAKEN (1 << 11)
|
||||
#define LPDP_PHY_POST_LDO_CTRL_LDOPOST_SB_EN (1 << 10)
|
||||
#define LPDP_PHY_POST_LDO_CTRL_LDOPOST_BGREF_BYPASS (1 << 9)
|
||||
#if LPDP_PHY_VERSION == 2
|
||||
#define LPDP_PHY_POST_LDO_CTRL_LDOPOST_BYPASS (1 << 0)
|
||||
#endif
|
||||
|
||||
#define rLPDP_PHY_AUX_LDO_CTRL (0x00158)
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_AUXVREG_BGREF_BYPASS (1 << 9)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_AUXVREG_BYPASS (1 << 8)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_AUXVREG_ADJ(n) ((n) << 4)
|
||||
#elif LPDP_PHY_VERSION == 2
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_LDOPOST_REF_ADJ(n) ((n) << 27)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_LDOPOST_PWRDN_BIG (1 << 26)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_LDOPOST_PWRDN_SML (1 << 25)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_LDOCLK_VREG_ADJ(n) ((n) << 21)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_LDOCLK_REF_ADJ(n) ((n) << 18)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_LDOCLK_PWRDN_BIG (1 << 17)
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_LDOCLK_PWRDN_SML (1 << 16)
|
||||
#endif
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_AUX_CM_CTRL(n) ((n) << 1)
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
#define LPDP_PHY_AUX_LDO_CTRL_AUXLDO_PWRDN (1 << 0)
|
||||
#endif
|
||||
|
||||
#define rLPDP_PHY_DE_CTRL (0x0015c)
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
#define LPDP_PHY_DE_CTRL_DE_EN (1 << 2)
|
||||
#elif LPDP_PHY_VERSION == 2
|
||||
#define LPDP_PHY_DE_CTRL_DE2_EN (1 << 6)
|
||||
#define LPDP_PHY_DE_CTRL_DE1_EN (1 << 2)
|
||||
#endif
|
||||
#define LPDP_PHY_DE_CTRL_DE_EN_LSB(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PHY_RESERVED (0x00160)
|
||||
|
||||
#define rLPDP_PLL_GEN (0x00180)
|
||||
#define LPDP_PLL_GEN_CLKDIV2_RESET_N (1 << 15)
|
||||
#define LPDP_PLL_GEN_TEST_SEL(n) ((n) << 10)
|
||||
#define LPDP_PLL_GEN_VSSA 0x0
|
||||
#define LPDP_PLL_GEN_VDD_SOC 0x1
|
||||
#define LPDP_PLL_GEN_VREG_1VA 0x2
|
||||
#define LPDP_PLL_GEN_PLL_LOCK_OUT 0x3
|
||||
#define LPDP_PLL_GEN_CP_OUT 0x4
|
||||
#define LPDP_PLL_GEN_VCO_TOP 0x5
|
||||
#define LPDP_PLL_GEN_VREF_CAL 0x6
|
||||
#define LPDP_PLL_GEN_VBTST 0x7
|
||||
#define LPDP_PLL_GEN_TEST_EN (1 << 9)
|
||||
#define LPDP_PLL_GEN_GCLK_SEL (1 << 8)
|
||||
#define LPDP_PLL_GEN_GCLK_DIV(n) ((n) << 4)
|
||||
#define LPDP_PLL_GEN_GCLK_DIV_MASK (0xf)
|
||||
#define LPDP_PLL_GEN_STOP_CLK (1 << 3)
|
||||
#define LPDP_PLL_GEN_BYPASS (1 << 2)
|
||||
#define LPDP_PLL_GEN_RST (1 << 1)
|
||||
#define LPDP_PLL_GEN_PWRDN (1 << 0)
|
||||
|
||||
#define rLPDP_PLL_CLK (0x00184)
|
||||
#define LPDP_PLL_CLK_FLIN_SEL (1 << 12)
|
||||
#define LPDP_PLL_CLK_BG_START_SEL (1 << 11)
|
||||
#define LPDP_PLL_CLK_PFDCP_RST_SEL (1 << 10)
|
||||
#define LPDP_PLL_CLK_VCLK_SEL_VCO (1 << 9)
|
||||
#define LPDP_PLL_CLK_VCO_BLK_RSTPD (1 << 8)
|
||||
#define LPDP_PLL_CLK_VCO_BLK_SCLK (1 << 7)
|
||||
#define LPDP_PLL_CLK_VCO_BLK_VCLK (1 << 6)
|
||||
#define LPDP_PLL_CLK_VCO_RCTRL_SEL_ENABLE (1 << 5)
|
||||
#define LPDP_PLL_CLK_VCO_RCTRL_OW_SHIFT 2
|
||||
#define LPDP_PLL_CLK_VCO_RCTRL_OW_MASK (0x7 << LPDP_PLL_CLK_VCO_RCTRL_OW_SHIFT)
|
||||
#define LPDP_PLL_CLK_VCO_PCTRL(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PLL_IDIV (0x00188)
|
||||
#define LPDP_PLL_IDIV_UPDT (1 << 14)
|
||||
#define LPDP_PLL_IDIV_FB(n) (n << 5)
|
||||
#define LPDP_PLL_IDIV_PRE(n) (n << 0)
|
||||
#define LPDP_PLL_IDIV_FB_SHIFT 5
|
||||
#define LPDP_PLL_IDIV_FB_MASK (0x1FF << LPDP_PLL_IDIV_FB_SHIFT)
|
||||
#define LPDP_PLL_IDIV_PRE_SHIFT 0
|
||||
#define LPDP_PLL_IDIV_PRE_MASK (0x1F << LPDP_PLL_IDIV_PRE_SHIFT)
|
||||
|
||||
#define rLPDP_PLL_CP (0x0018C)
|
||||
#define LPDP_PLL_CP_BOOST_MODE (1 << 14)
|
||||
#define LPDP_PLL_CP_BOOST_EN (1 << 13)
|
||||
#define LPDP_PLL_CP_ENABLE (1 << 12)
|
||||
#define LPDP_PLL_CP_RSTN (1 << 11)
|
||||
#define LPDP_PLL_CP_LIN_EN (1 << 10)
|
||||
#define LPDP_PLL_CP_R_SET(n) (n << 3)
|
||||
#define LPDP_PLL_CP_I_SET(n) (n << 0)
|
||||
|
||||
#define rLPDP_PLL_LOCK (0x00190)
|
||||
#define LPDP_PLL_LOCK_OUT_OFF (0 << 9)
|
||||
#define LPDP_PLL_LOCK_OUT_ON (1 << 9)
|
||||
#define LPDP_PLL_LOCK_RST_OFF (0 << 8)
|
||||
#define LPDP_PLL_LOCK_RST_ON (1 << 8)
|
||||
#define LPDP_PLL_LOCK_POR_OFF (0 << 7)
|
||||
#define LPDP_PLL_LOCK_POR_ON (1 << 7)
|
||||
#define LPDP_PLL_LOCK_DIV(n) ((n) << 0)
|
||||
|
||||
#define rLPDP_PLL_VCO (0x00194)
|
||||
#define LPDP_PLL_VCO_BUF_PWRDN_OFF (0 << 14)
|
||||
#define LPDP_PLL_VCO_BUF_PWRDN_ON (1 << 14)
|
||||
#define LPDP_PLL_VCO_DEC_BYPASS_OFF (0 << 13)
|
||||
#define LPDP_PLL_VCO_DEC_BYPASS_ON (1 << 13)
|
||||
#define LPDP_PLL_VCO_REG_PWRDN_OFF (0 << 12)
|
||||
#define LPDP_PLL_VCO_REG_PWRDN_ON (1 << 12)
|
||||
#define LPDP_PLL_VCO_REG_BYPASS_OFF (0 << 11)
|
||||
#define LPDP_PLL_VCO_REG_BYPASS_ON (1 << 11)
|
||||
#define LPDP_PLL_VCO_VREG_ADJ(n) ((n) << 8)
|
||||
#define LPDP_PLL_VCO_K_VCO_CTRL(n) ((n) << 4)
|
||||
#define LPDP_PLL_VCO_RESDIV_SEL(n) ((n) << 1)
|
||||
#define LPDP_PLL_VCO_RESDIV_VREF_EN_OFF (0 << 0)
|
||||
#define LPDP_PLL_VCO_RESDIV_VREF_EN_ON (1 << 0)
|
||||
|
||||
#define rLPDP_PLL_SDM (0x00198)
|
||||
#define rLPDP_PLL_SSC (0x0019c)
|
||||
#define rLPDP_PLL_FMC (0x001a0)
|
||||
|
||||
#define rLPDP_PLL_SEL (0x001a4)
|
||||
#define RLPDP_PLL_SEL_REF_OUT (1 << 7)
|
||||
#define RLPDP_PLL_SEL_VCO_OUT (1 << 6)
|
||||
#define RLPDP_PLL_SEL_PLL_OUT (1 << 5)
|
||||
#define RLPDP_PLL_SEL_TESTWRAPPER (1 << 4)
|
||||
#define RLPDP_PLL_SEL_CK_DFT (1 << 3)
|
||||
#define RLPDP_PLL_SEL_REF_DFT (1 << 2)
|
||||
#define RLPDP_PLL_SEL_VCO_DFT (1 << 1)
|
||||
#define RLPDP_PLL_SEL_PLL_DFT (1 << 0)
|
||||
|
||||
#if LPDP_PHY_VERSION < 2
|
||||
#define rLPDP_PLL_SPARE (0x001a8)
|
||||
#elif LPDP_PHY_VERSION == 2
|
||||
#define rLPDP_PLL_LPF (0x001a8)
|
||||
#define rLPDP_PLL_FCAL (0x001ac)
|
||||
#define LPDP_PLL_FCAL_RESET (1 << 18)
|
||||
#define rLPDP_PLL_SPARE (0x001b0)
|
||||
#endif
|
||||
#endif //_LPDP_PHY_REGS_V2_H
|
||||
@@ -0,0 +1,19 @@
|
||||
# Copyright (C) 2013-2014 Apple Computer, Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Computer, Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Computer, Inc.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
ifeq ($(LPDP_VERSION),)
|
||||
$(error "LPDP_VERSION not set")
|
||||
else
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/lpdp_v$(LPDP_VERSION).o
|
||||
endif
|
||||
|
||||
GLOBAL_INCLUDES += $(LOCAL_DIR)/include
|
||||
Reference in new issue
Block a user