blob: 410184979fec6948ba431e451442ad6590ef8e77 [file] [log] [blame]
#include <config.h>
#include <common.h>
#include <asm/arch/gpio_c2000.h>
#include <asm/arch/hardware.h>
#include <asm/arch/clkcore_c2000.h>
#define TDMNTG_REG_RST (1 << 0)
#define FSYNC_FALL_EDGE (1 << 1)
#define NTG_DIV_RST_N (1 << 5)
#define NTG_EN (1 << 0)
#define TDMNTG_ADDR_SPACE_BASEADDR (COMCERTO_APB_CLK_BASE + 0x280)
#define TDM_NTG_CLK_CTRL (TDMNTG_ADDR_SPACE_BASEADDR + 0x00)
#define TDM_NTG_INCR (TDMNTG_ADDR_SPACE_BASEADDR + 0x04)
#define TDM_FSYNC_GEN_CTRL (TDMNTG_ADDR_SPACE_BASEADDR + 0x08)
#define TDM_FSYNC_LOW (TDMNTG_ADDR_SPACE_BASEADDR + 0x0C)
#define TDM_FSYNC_HIGH (TDMNTG_ADDR_SPACE_BASEADDR + 0x10)
#define TDMNTG_DEFAULT_REF_CLK 500000000
/* TDM Divider value to 24 */
#define NTG_TDM_CLK_DIV 24
struct comcerto_tdm_data {
u8 fsoutput; /* Generic Pad Control and Version ID Register[2] */
u8 fspolarity; /* 28 FSYNC_FALL(RISE)_EDGE */
u16 fshwidth; /* High_Phase_Width[10:0] */
u16 fslwidth; /* Low_Phase_Width[26:16]] */
u32 clockhz; /* INC_VALUE[29:0] According to the desired TDM clock output frequency, this field should be configured */
u8 clockout; /* IO Control Register[21] hardware or software control selection IO Control Register[20] pads are input (output) */
u8 tdmmux;
u32 tdmck;
u32 tdmfs;
u32 tdmdx;
u32 tdmdr;
};
//Legerity
static struct comcerto_tdm_data comcerto_tdm_pdata = {
.fsoutput = 1, /* Generic Pad Control and Version ID Register[2] */
.fspolarity = 0, /* 28 FSYNC_FALL(RISE)_EDGE */
.fshwidth = 1, /* High_Phase_Width[10:0] */
.fslwidth = 0xFF, /* Low_Phase_Width[10:0] */
.clockhz = 2048000, /* INC_VALUE[29:0] According to the desired TDM clock output frequency, this field should be configured */
.clockout = 1, /* 0 -> set bit 21, clear bit 20 in COMCERTO_GPIO_IOCTRL_REG
(software control, clock input)
1 -> set bit 21 and 20 in COMCERTO_GPIO_IOCTRL_REG
(software control, clock output)
2 -> clear bit 21 in COMCERTO_GPIO_IOCTRL_REG (hardware control) */
/* TDM interface Muxing:0x0 - TDM block, 0x1 - ZDS block,
0x2 - GPIO[63:60] signals and 0x3 - MSIF block is selected */
.tdmmux = 0x1,
};
static void fsync_output_set(unsigned int fsoutput)
{
if (fsoutput)
{
*(volatile u32*)COMCERTO_GPIO_TDM_MUX = (*(volatile u32*)(COMCERTO_GPIO_TDM_MUX) | (1 << 0));
*(volatile u32*)TDM_FSYNC_GEN_CTRL = (*(volatile u32*)(TDM_FSYNC_GEN_CTRL) | (1 << 0));
}
else
{
*(volatile u32*)COMCERTO_GPIO_TDM_MUX = (*(volatile u32*)(COMCERTO_GPIO_TDM_MUX) & ~(1 << 0));
*(volatile u32*)TDM_FSYNC_GEN_CTRL = (*(volatile u32*)(TDM_FSYNC_GEN_CTRL) & ~(1 << 0));
}
}
static void fsync_polarity_set(unsigned int fspolarity)
{
/* 28 FSYNC_FALL(RISE)_EDGE */
if (fspolarity)
*(volatile u32*)TDM_FSYNC_GEN_CTRL = (*(volatile u32*)(TDM_FSYNC_GEN_CTRL) | FSYNC_FALL_EDGE);
else
*(volatile u32*)TDM_FSYNC_GEN_CTRL = (*(volatile u32*)(TDM_FSYNC_GEN_CTRL) & ~FSYNC_FALL_EDGE);
}
static void fsync_lphase_set(u32 fslwidth)
{
/* Low_Phase_Width 7ff- maximum */
if (fslwidth > 0x7FF) {
printf("%s: Low Phase width value is out of range %#x > 0x7FF", __func__, fslwidth);
return;
}
*(volatile u32*)TDM_FSYNC_LOW = fslwidth;
}
static void fsync_hphase_set(u32 fshwidth)
{
/* High_Phase_Width 7ff- maximum */
if (fshwidth > 0x7FF) {
printf("%s: High Phase width value is out of range %#x > 0x7FF", __func__, fshwidth);
return;
}
*(volatile u32*)TDM_FSYNC_HIGH = fshwidth;
}
static void clock_frequency_set(unsigned long clockhz)
{
/* ntg_incr = 0x192A7371 for 49.152 MHz */
*(volatile u32*)TDM_NTG_INCR = 0x192A7371;
}
static void clock_output_set(unsigned long clockout)
{
switch (clockout) {
case 0:
*(volatile u32*)COMCERTO_GPIO_BOOTSTRAP_OVERRIDE = ((0x2 << 12) | (*(volatile u32*)(COMCERTO_GPIO_BOOTSTRAP_OVERRIDE) & ~(0x3 << 12)));
break;
case 1:
*(volatile u32*)COMCERTO_GPIO_BOOTSTRAP_OVERRIDE = ((0x3 << 12) | (*(volatile u32*)(COMCERTO_GPIO_BOOTSTRAP_OVERRIDE) & ~(0x3 << 12)));
break;
case 2:
*(volatile u32*)COMCERTO_GPIO_BOOTSTRAP_OVERRIDE = ((0x0 << 12) | (*(volatile u32*)(COMCERTO_GPIO_BOOTSTRAP_OVERRIDE) & ~(0x3 << 12)));
break;
default:
printf("%s: Unknown clock output value\n", __func__);
}
}
static void tdm_mux_set(u32 tdmmux)
{
switch (tdmmux){
case 0:
// TDM block selected
*(volatile u32*)COMCERTO_GPIO_MISC_PIN_SELECT_REG = ((0x0 << 4) | (*(volatile u32*)(COMCERTO_GPIO_MISC_PIN_SELECT_REG) & ~(0x3 << 4)));
break;
case 1:
// ZDS (Zarlink) block selected
*(volatile u32*)COMCERTO_GPIO_MISC_PIN_SELECT_REG = ((0x1 << 4) | (*(volatile u32*)(COMCERTO_GPIO_MISC_PIN_SELECT_REG) & ~(0x3 << 4)));
break;
case 2:
// GPIO[63:60] signals selected
*(volatile u32*)COMCERTO_GPIO_MISC_PIN_SELECT_REG = ((0x2 << 4) | (*(volatile u32*)(COMCERTO_GPIO_MISC_PIN_SELECT_REG) & ~(0x3 << 4)));
break;
case 3:
// MSIF (SiLabs) selected
*(volatile u32*)COMCERTO_GPIO_MISC_PIN_SELECT_REG = ((0x3 << 4) | (*(volatile u32*)(COMCERTO_GPIO_MISC_PIN_SELECT_REG) & ~(0x3 << 4)));
break;
default:
printf("%s: Unknown TDM MUX value\n", __func__);
}
}
void c2k_zds_init(void)
{
printf("Initializing ZDS/NTG..\n");
// Take TDM NTG out of reset
*(volatile u32*)TDMNTG_RESET = (*(volatile u32*)(TDMNTG_RESET) & ~TDMNTG_REG_RST);
//PLL2
*(volatile u32*)TDMNTG_REF_CLK_CNTRL = (*(volatile u32*)(TDMNTG_REF_CLK_CNTRL) | ((1 << 2) | (1 << 0)));
// NTG REF CLK is derived from PLL2
*(volatile u32*)TDMNTG_REF_CLK_DIV_CNTRL = 0x3;
*(volatile u32*)TDM_NTG_CLK_CTRL = (NTG_DIV_RST_N | NTG_EN);
*(volatile u32*)TDM_CLK_CNTRL = 0x80; /* NTG = 24 x TDM */
/* Inital configuration of tdm bus */
fsync_polarity_set(comcerto_tdm_pdata.fspolarity);
fsync_lphase_set(comcerto_tdm_pdata.fslwidth);
fsync_hphase_set(comcerto_tdm_pdata.fshwidth);
clock_frequency_set(comcerto_tdm_pdata.clockhz);
clock_output_set(comcerto_tdm_pdata.clockout);
fsync_output_set(comcerto_tdm_pdata.fsoutput);
tdm_mux_set(comcerto_tdm_pdata.tdmmux);
*(volatile u32*)TDM_CLK_CNTRL = 0x18; //remove out of reset
#define COMCERTO_GPIO1_OUTPUT_REG ((COMCERTO_APB_GPIO_BASE + 0xd0))
*(volatile u32*)COMCERTO_GPIO1_OUTPUT_REG = (0x1 << 30);
}