Загрузка данных
static int fsl_xcvr_ai_write(struct fsl_xcvr *xcvr, u8 reg, u32 data, bool phy)
{
struct device *dev = &xcvr->pdev->dev;
u32 val, idx, tidx;
int ret;
idx = BIT(phy ? 26 : 24);
tidx = BIT(phy ? 27 : 25);
regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_CLR, 0xFF | FSL_XCVR_PHY_AI_CTRL_AI_RWB);
regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET, reg);
regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_WDATA, data);
regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_TOG, idx);
ret = regmap_read_poll_timeout(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL, val,
(val & idx) == ((val & tidx) >> 1),
10, 10000);
if (ret)
dev_err(dev, "AI timeout: failed to set %s reg 0x%02x=0x%08x\n",
phy ? "PHY" : "PLL", reg, data);
return ret;
}
static int fsl_xcvr_ai_read(struct fsl_xcvr *xcvr, u8 reg, u32 *data, bool phy)
{
struct device *dev = &xcvr->pdev->dev;
u32 val, idx, tidx;
int ret;
idx = BIT(phy ? 26 : 24);
tidx = BIT(phy ? 27 : 25);
regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_CLR, 0xFF | FSL_XCVR_PHY_AI_CTRL_AI_RWB);
regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET, reg | FSL_XCVR_PHY_AI_CTRL_AI_RWB);
regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_TOG, idx);
ret = regmap_read_poll_timeout(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL, val,
(val & idx) == ((val & tidx) >> 1),
10, 10000);
if (ret)
dev_err(dev, "AI timeout: failed to read %s reg 0x%02x\n",
phy ? "PHY" : "PLL", reg);
regmap_read(xcvr->regmap, FSL_XCVR_PHY_AI_RDATA, data);
return ret;
}
static int fsl_xcvr_phy_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct fsl_xcvr *xcvr = context;
return fsl_xcvr_ai_read(xcvr, reg, val, 1);
}
static int fsl_xcvr_phy_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct fsl_xcvr *xcvr = context;
return fsl_xcvr_ai_write(xcvr, reg, val, 1);
}
static int fsl_xcvr_pll_reg_read(void *context, unsigned int reg, unsigned int *val)
{
struct fsl_xcvr *xcvr = context;
return fsl_xcvr_ai_read(xcvr, reg, val, 0);
}
static int fsl_xcvr_pll_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct fsl_xcvr *xcvr = context;
return fsl_xcvr_ai_write(xcvr, reg, val, 0);
}
static int fsl_xcvr_en_phy_pll(struct fsl_xcvr *xcvr, u32 freq, bool tx)
{
struct device *dev = &xcvr->pdev->dev;
u32 i, div = 0, log2, val;
int ret;
if (!xcvr->soc_data->use_phy)
return 0;
for (i = 0; i < ARRAY_SIZE(fsl_xcvr_pll_cfg); i++) {
if (fsl_xcvr_pll_cfg[i].fout % freq == 0) {
div = fsl_xcvr_pll_cfg[i].fout / freq;
break;
}
}
if (!div || i >= ARRAY_SIZE(fsl_xcvr_pll_cfg))
return -EINVAL;
log2 = ilog2(div);
/* Release AI interface from reset */
ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,
FSL_XCVR_PHY_AI_CTRL_AI_RESETN);
if (ret < 0) {
dev_err(dev, "Error while setting IER0: %d\n", ret);
return ret;
}
switch (xcvr->soc_data->pll_ver) {
case PLL_MX8MP:
/* PLL: BANDGAP_SET: EN_VBG (enable bandgap) */
regmap_set_bits(xcvr->regmap_pll, FSL_XCVR_PLL_BANDGAP,
FSL_XCVR_PLL_BANDGAP_EN_VBG);
/* PLL: CTRL0: DIV_INTEGER */
regmap_write(xcvr->regmap_pll, FSL_XCVR_PLL_CTRL0, fsl_xcvr_pll_cfg[i].mfi);
/* PLL: NUMERATOR: MFN */
regmap_write(xcvr->regmap_pll, FSL_XCVR_PLL_NUM, fsl_xcvr_pll_cfg[i].mfn);
/* PLL: DENOMINATOR: MFD */
regmap_write(xcvr->regmap_pll, FSL_XCVR_PLL_DEN, fsl_xcvr_pll_cfg[i].mfd);
/* PLL: CTRL0_SET: HOLD_RING_OFF, POWER_UP */
regmap_set_bits(xcvr->regmap_pll, FSL_XCVR_PLL_CTRL0,
FSL_XCVR_PLL_CTRL0_HROFF | FSL_XCVR_PLL_CTRL0_PWP);
udelay(25);
/* PLL: CTRL0: Clear Hold Ring Off */
regmap_clear_bits(xcvr->regmap_pll, FSL_XCVR_PLL_CTRL0,
FSL_XCVR_PLL_CTRL0_HROFF);
udelay(100);
if (tx) { /* TX is enabled for SPDIF only */
/* PLL: POSTDIV: PDIV0 */
regmap_write(xcvr->regmap_pll, FSL_XCVR_PLL_PDIV,
FSL_XCVR_PLL_PDIVx(log2, 0));
/* PLL: CTRL_SET: CLKMUX0_EN */
regmap_set_bits(xcvr->regmap_pll, FSL_XCVR_PLL_CTRL0,
FSL_XCVR_PLL_CTRL0_CM0_EN);
} else if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC RX */
/* PLL: POSTDIV: PDIV1 */
regmap_write(xcvr->regmap_pll, FSL_XCVR_PLL_PDIV,
FSL_XCVR_PLL_PDIVx(log2, 1));
/* PLL: CTRL_SET: CLKMUX1_EN */
regmap_set_bits(xcvr->regmap_pll, FSL_XCVR_PLL_CTRL0,
FSL_XCVR_PLL_CTRL0_CM1_EN);
} else { /* SPDIF / ARC RX */
/* PLL: POSTDIV: PDIV2 */
regmap_write(xcvr->regmap_pll, FSL_XCVR_PLL_PDIV,
FSL_XCVR_PLL_PDIVx(log2, 2));
/* PLL: CTRL_SET: CLKMUX2_EN */
regmap_set_bits(xcvr->regmap_pll, FSL_XCVR_PLL_CTRL0,
FSL_XCVR_PLL_CTRL0_CM2_EN);
}
break;
case PLL_MX95:
val = fsl_xcvr_pll_cfg[i].mfi << FSL_XCVR_GP_PLL_DIV_MFI_SHIFT | div;
regmap_write(xcvr->regmap_pll, FSL_XCVR_GP_PLL_DIV, val);
val = fsl_xcvr_pll_cfg[i].mfn << FSL_XCVR_GP_PLL_NUMERATOR_MFN_SHIFT;
regmap_write(xcvr->regmap_pll, FSL_XCVR_GP_PLL_NUMERATOR, val);
regmap_write(xcvr->regmap_pll, FSL_XCVR_GP_PLL_DENOMINATOR,
fsl_xcvr_pll_cfg[i].mfd);
val = FSL_XCVR_GP_PLL_CTRL_POWERUP | FSL_XCVR_GP_PLL_CTRL_CLKMUX_EN;
regmap_write(xcvr->regmap_pll, FSL_XCVR_GP_PLL_CTRL, val);
break;
default:
dev_err(dev, "Error for PLL version %d\n", xcvr->soc_data->pll_ver);
return -EINVAL;
}
if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC mode */
/* PHY: CTRL_SET: TX_DIFF_OE, PHY_EN */
regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL,
FSL_XCVR_PHY_CTRL_TSDIFF_OE |
FSL_XCVR_PHY_CTRL_PHY_EN);
/* PHY: CTRL2_SET: EARC_TX_MODE */
regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL2,
FSL_XCVR_PHY_CTRL2_EARC_TXMS);
} else if (!tx) { /* SPDIF / ARC RX mode */
if (xcvr->mode == FSL_XCVR_MODE_SPDIF)
/* PHY: CTRL_SET: SPDIF_EN */
regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL,
FSL_XCVR_PHY_CTRL_SPDIF_EN);
else /* PHY: CTRL_SET: ARC RX setup */
regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL,
FSL_XCVR_PHY_CTRL_PHY_EN |
FSL_XCVR_PHY_CTRL_RX_CM_EN |
fsl_xcvr_phy_arc_cfg[xcvr->arc_mode]);
}
dev_dbg(dev, "PLL Fexp: %u, Fout: %u, mfi: %u, mfn: %u, mfd: %d, div: %u, pdiv0: %u\n",
freq, fsl_xcvr_pll_cfg[i].fout, fsl_xcvr_pll_cfg[i].mfi,
fsl_xcvr_pll_cfg[i].mfn, fsl_xcvr_pll_cfg[i].mfd, div, log2);
return 0;
}
static int fsl_xcvr_en_aud_pll(struct fsl_xcvr *xcvr, u32 freq)
{
struct device *dev = &xcvr->pdev->dev;
int ret;
freq = xcvr->soc_data->spdif_only ? freq / 5 : freq;
clk_disable_unprepare(xcvr->phy_clk);
fsl_asoc_reparent_pll_clocks(dev, xcvr->phy_clk,
xcvr->pll8k_clk, xcvr->pll11k_clk, freq);
ret = clk_set_rate(xcvr->phy_clk, freq);
if (ret < 0) {
dev_err(dev, "Error while setting AUD PLL rate: %d\n", ret);
return ret;
}
ret = clk_prepare_enable(xcvr->phy_clk);
if (ret) {
dev_err(dev, "failed to start PHY clock: %d\n", ret);
return ret;
}
if (!xcvr->soc_data->use_phy)
return 0;
/* Release AI interface from reset */
ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,
FSL_XCVR_PHY_AI_CTRL_AI_RESETN);
if (ret < 0) {
dev_err(dev, "Error while setting IER0: %d\n", ret);
return ret;
}
if (xcvr->mode == FSL_XCVR_MODE_EARC) { /* eARC mode */
/* PHY: CTRL_SET: TX_DIFF_OE, PHY_EN */
regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL,
FSL_XCVR_PHY_CTRL_TSDIFF_OE |
FSL_XCVR_PHY_CTRL_PHY_EN);
/* PHY: CTRL2_SET: EARC_TX_MODE */
regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL2,
FSL_XCVR_PHY_CTRL2_EARC_TXMS);
} else { /* SPDIF mode */
/* PHY: CTRL_SET: TX_CLK_AUD_SS | SPDIF_EN */
regmap_set_bits(xcvr->regmap_phy, FSL_XCVR_PHY_CTRL,
FSL_XCVR_PHY_CTRL_TX_CLK_AUD_SS |
FSL_XCVR_PHY_CTRL_SPDIF_EN);
}
dev_dbg(dev, "PLL Fexp: %u\n", freq);
return 0;
}
#define FSL_XCVR_SPDIF_RX_FREQ 175000000