예제 #1
0
static int __init post_cpu_init(void)
{
	unsigned int reg;
	void __iomem *base;

	if (cpu_is_mx51() || cpu_is_mx53()) {
		if (cpu_is_mx51())
			base = MX51_IO_ADDRESS(MX51_AIPS1_BASE_ADDR);
		else
			base = MX53_IO_ADDRESS(MX53_AIPS1_BASE_ADDR);

		__raw_writel(0x0, base + 0x40);
		__raw_writel(0x0, base + 0x44);
		__raw_writel(0x0, base + 0x48);
		__raw_writel(0x0, base + 0x4C);
		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
		__raw_writel(reg, base + 0x50);

		if (cpu_is_mx51())
			base = MX51_IO_ADDRESS(MX51_AIPS2_BASE_ADDR);
		else
			base = MX53_IO_ADDRESS(MX53_AIPS2_BASE_ADDR);

		__raw_writel(0x0, base + 0x40);
		__raw_writel(0x0, base + 0x44);
		__raw_writel(0x0, base + 0x48);
		__raw_writel(0x0, base + 0x4C);
		reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
		__raw_writel(reg, base + 0x50);
	}

	return 0;
}
예제 #2
0
static int fsl_usb_host_init_ext(struct platform_device *pdev)
{
	iomux_v3_cfg_t usbh1stp_func = MX51_PAD_USBH1_STP__USBH1_STP;
	int ret;
	struct clk *usb_clk;

	/* the usb_ahb_clk will be enabled in usb_otg_init */
	usb_ahb_clk = clk_get(NULL, "usb_ahb_clk");

	if (cpu_is_mx53()) {
		usb_clk = clk_get(NULL, "usboh3_clk");
		clk_enable(usb_clk);
		usb_oh3_clk = usb_clk;

		usb_clk = clk_get(NULL, "usb_phy2_clk");
		clk_enable(usb_clk);
		usb_phy2_clk = usb_clk;
	} else if (cpu_is_mx50()) {
		usb_clk = clk_get(NULL, "usb_phy2_clk");
		clk_enable(usb_clk);
		usb_phy2_clk = usb_clk;
	} else if (cpu_is_mx51()) {
		usb_clk = clk_get(NULL, "usboh3_clk");
		clk_enable(usb_clk);
		usb_oh3_clk = usb_clk;
	}

	ret = fsl_usb_host_init(pdev);
	if (ret)
		return ret;

	if (cpu_is_mx51()) {
		/* setback USBH1_STP to be function */
#if 0	/* Jasper: Need to do... */
		mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0);
		mxc_iomux_set_pad(MX51_PIN_USBH1_STP, PAD_CTL_SRE_FAST |
				  PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE |
				  PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE |
				  PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS |
				  PAD_CTL_DRV_VOT_LOW);
		gpio_free(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP));
#endif
		mxc_iomux_v3_setup_pad(usbh1stp_func);
		gpio_free(MX5X_USBH1_STP);
	}

	/* disable remote wakeup irq */
	USBCTRL &= ~UCTRL_H1WIE;
	return 0;
}
예제 #3
0
void force_freq_change(void)
{
	u32 reg;
	int rate;
	u32 flags;

#ifndef DVFS_SW_WORKAROUND
	/* Increase the LP domain voltage first. */
	mx37_set_lp_voltage(LP_NORMAL_VOLTAGE);
	udelay(100);
#endif

	freq_increased = 0;
	spin_lock_irqsave(&mxc_dvfs_per_lock, flags);

//	printk("force_freq_change\n");
	reg = __raw_readl(MXC_DVFS_PER_PMCR0);
	reg |= MXC_DVFSPMCR0_UDCS;
	__raw_writel(reg, MXC_DVFS_PER_PMCR0);

	if (cpu_is_mx51()) {
		/*Change the DDR freq to 133Mhz. */
		clk_set_rate(ddr_hf_clk, clk_round_rate(ddr_hf_clk, 200000000));
	}

#ifndef DVFS_SW_WORKAROUND
	reg = __raw_readl(MXC_GPC_CNTR);
	reg |= MXC_GPCCNTR_FUPD;
	__raw_writel(reg, MXC_GPC_CNTR);
	reg = __raw_readl(MXC_GPC_VCR);
	reg &= ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
	      MXC_GPCVCR_VCNT_MASK);
	reg |= (1 << MXC_GPCVCR_VINC_OFFSET |
		1 << MXC_GPCVCR_VCNTU_OFFSET |
		20 << MXC_GPCVCR_VCNT_OFFSET);
	__raw_writel(reg, MXC_GPC_VCR);
	reg = __raw_readl(MXC_GPC_CNTR);
	reg &= ~MXC_GPCCNTR_ADU;
	reg |= MXC_GPCCNTR_STRT;

	__raw_writel(reg, MXC_GPC_CNTR);
	while (__raw_readl(MXC_GPC_CNTR) & 0x4000) {
		udelay(10);
	}
	freq_increased = 1;

#else
	//Set the frequencies manually
	rate = clk_get_rate(axi_b_clk);
	clk_set_rate(axi_b_clk, clk_round_rate(axi_b_clk, 130000000));
	rate = clk_get_rate(ahb_clk);
	clk_set_rate(ahb_clk, clk_round_rate(ahb_clk, 130000000));
#endif
#ifndef DVFS_SW_WORKAROUND
	clk_set_parent(main_bus_clk, clk_get(NULL, "pll2"));
#endif

	spin_unlock_irqrestore(&mxc_dvfs_per_lock, flags);

}
예제 #4
0
파일: iomux.c 프로젝트: vasubabu/kernel
static inline void *_get_sw_pad(void)
{
	if (cpu_is_mx51())
		return IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_START_MX51;
	else
		return IO_ADDRESS(IOMUXC_BASE_ADDR) + PAD_I_START_MX53;
}
static inline void __iomem *_get_pll_base(struct clk *pll)
{
	if (cpu_is_mx51())
		return _mx51_get_pll_base(pll);
	else
		return _mx53_get_pll_base(pll);
}
예제 #6
0
int set_low_bus_freq(void)
{
	if (busfreq_suspended)
		return 0;
	if (bus_freq_scaling_initialized) {
		/* can not enter low bus freq, when cpu is in higher freq
		 * or only have one working point */
		if ((clk_get_rate(cpu_clk) >
				cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate)
			|| (cpu_wp_nr == 1)) {
			return 0;
		}

		mutex_lock(&bus_freq_mutex);

		stop_dvfs_per();

		stop_sdram_autogating();

		if (cpu_is_mx50())
			enter_lpapm_mode_mx50();
		else if (cpu_is_mx51())
			enter_lpapm_mode_mx51();
		else
			enter_lpapm_mode_mx53();
		mutex_unlock(&bus_freq_mutex);
	}
	return 0;
}
예제 #7
0
파일: iomux.c 프로젝트: vasubabu/kernel
/*!
 * This function configures input path.
 *
 * @param  input        index of input select register as defined in \b #iomux_input_select_t
 * @param  config       the binary value of elements defined in \b #iomux_input_config_t
 *      */
void mxc_iomux_set_input(iomux_input_select_t input, u32 config)
{
	void __iomem *reg;

	if (cpu_is_mx51_rev(CHIP_REV_2_0) < 0) {
		if (input == MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT)
			input -= 4;
		else if (input == MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT)
			input -= 3;
		else if (input >= MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT)
			input -= 2;
		else if (input >= MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT)
			input -= 5;
		else if (input >= MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT)
			input -= 3;
		else if (input >= MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT)
			input -= 2;
		else if (input >= MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT)
			input -= 1;

		reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_MX51_TO1;
	} else if (cpu_is_mx51()) {
		reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_MX51;
	} else
		reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_MX53;

	BUG_ON(input >= MUX_INPUT_NUM_MUX);
	__raw_writel(config, reg);
}
예제 #8
0
int fsl_udc_clk_init(struct platform_device *pdev)
{
	struct fsl_usb2_platform_data *pdata;
	unsigned long freq;
	int ret;

	pdata = pdev->dev.platform_data;

	if (!cpu_is_mx35() && !cpu_is_mx25()) {
		mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");
		if (IS_ERR(mxc_ahb_clk))
			return PTR_ERR(mxc_ahb_clk);

		ret = clk_enable(mxc_ahb_clk);
		if (ret < 0) {
			dev_err(&pdev->dev, "clk_enable(\"usb_ahb\") failed\n");
			goto eenahb;
		}
	}

	/* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
	mxc_usb_clk = clk_get(&pdev->dev, "usb");
	if (IS_ERR(mxc_usb_clk)) {
		dev_err(&pdev->dev, "clk_get(\"usb\") failed\n");
		ret = PTR_ERR(mxc_usb_clk);
		goto egusb;
	}

	if (!cpu_is_mx51()) {
		freq = clk_get_rate(mxc_usb_clk);
		if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
		    (freq < 59999000 || freq > 60001000)) {
			dev_err(&pdev->dev, "USB_CLK=%lu, should be 60MHz\n", freq);
			ret = -EINVAL;
			goto eclkrate;
		}
	}

	ret = clk_enable(mxc_usb_clk);
	if (ret < 0) {
		dev_err(&pdev->dev, "clk_enable(\"usb_clk\") failed\n");
		goto eenusb;
	}

	return 0;

eenusb:
eclkrate:
	clk_put(mxc_usb_clk);
	mxc_usb_clk = NULL;
egusb:
	if (!cpu_is_mx35())
		clk_disable(mxc_ahb_clk);
eenahb:
	if (!cpu_is_mx35())
		clk_put(mxc_ahb_clk);
	return ret;
}
예제 #9
0
void __init mx5_usbh1_init(void)
{
	if (cpu_is_mx51()) {
		usbh1_config.phy_mode = FSL_USB2_PHY_ULPI;
		usbh1_config.transceiver = "isp1504";
		usbh1_config.gpio_usb_active = gpio_usbh1_active;
		usbh1_config.gpio_usb_inactive = gpio_usbh1_inactive;
	}
	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
}
예제 #10
0
/*
 * Returns:
 *	the silicon revision of the cpu
 *	-EINVAL - not a mx51
 */
int mx51_revision(void)
{
	if (!cpu_is_mx51())
		return -EINVAL;

	if (cpu_silicon_rev == -1)
		query_silicon_parameter();

	return cpu_silicon_rev;
}
예제 #11
0
/*
 * Returns:
 *	the silicon revision of the cpu
 *	-EINVAL - not a mx51
 */
int mx51_revision(void)
{
	if (!cpu_is_mx51())
		return -EINVAL;

	if (cpu_silicon_rev == -1)
		cpu_silicon_rev = get_mx51_srev();

	return cpu_silicon_rev;
}
예제 #12
0
/*
 * Returns:
 *	the silicon revision of the cpu
 *	-EINVAL - not a mx51
 */
int mx51_revision(void)
{
	if (!cpu_is_mx51())
		return -EINVAL;

	if (mx5_cpu_rev == -1)
		mx5_cpu_rev = get_mx51_srev();

	return mx5_cpu_rev;
}
예제 #13
0
/*
 * All versions of the silicon before Rev. 3 have broken NEON implementations.
 * Dependent on link order - so the assumption is that vfp_init is called
 * before us.
 */
static int __init mx51_neon_fixup(void)
{
	if (!cpu_is_mx51())
		return 0;

	if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
		elf_hwcap &= ~HWCAP_NEON;
		pr_info("Turning off NEON support, detected broken NEON implementation\n");
	}
	return 0;
}
예제 #14
0
/******************************************************************************
*
* CAUTION: NONE
*
* MODIFICATION HISTORY:
*
* Date         Person     Change
* 30/07/2003   MW         Initial Creation
******************************************************************************/
void sah_Intr_Release(void)
{

	int irq_sah = MX53_INT_SAHARA_H0;

	if (cpu_is_mx51())
		irq_sah = MX51_MXC_INT_SAHARA_H0;

	/* Release the Interrupt. */
	free_irq(irq_sah, NULL);
}
예제 #15
0
static void force_freq_change(void)
{
	u32 reg;
	int retry = 50;

	freq_increased = 0;

	reg = __raw_readl(dvfsper_plt_data->membase + MXC_DVFS_PER_PMCR0);
	reg |= MXC_DVFSPMCR0_UDCS;
	__raw_writel(reg, dvfsper_plt_data->membase + MXC_DVFS_PER_PMCR0);

	if (cpu_is_mx51()) {
		/*Change the DDR freq to 133Mhz. */
		clk_set_rate(ddr_hf_clk, clk_round_rate(ddr_hf_clk, 200000000));
	}

#ifndef DVFS_SW_WORKAROUND
	reg = __raw_readl(dvfsper_plt_data->gpc_cntr_reg_addr);
	reg |= MXC_GPCCNTR_FUPD;
	__raw_writel(reg, dvfsper_plt_data->gpc_cntr_reg_addr);
	reg = __raw_readl(dvfsper_plt_data->gpc_vcr_reg_addr);
	reg &= ~(MXC_GPCVCR_VINC_MASK | MXC_GPCVCR_VCNTU_MASK |
	      MXC_GPCVCR_VCNT_MASK);
	reg |= (1 << MXC_GPCVCR_VINC_OFFSET |
		1 << MXC_GPCVCR_VCNTU_OFFSET |
		20 << MXC_GPCVCR_VCNT_OFFSET);
	__raw_writel(reg, dvfsper_plt_data->gpc_vcr_reg_addr);
	reg = __raw_readl(dvfsper_plt_data->gpc_cntr_reg_addr);
	reg &= ~MXC_GPCCNTR_ADU;
	reg |= MXC_GPCCNTR_STRT;
	__raw_writel(reg, dvfsper_plt_data->gpc_cntr_reg_addr);
	while ((__raw_readl(
			dvfsper_plt_data->gpc_cntr_reg_addr) & 0x4000)
			&& retry > 0) {
		udelay(30);
		retry--;
	}
	freq_increased = 1;
	if (retry <= 0)
		printk(KERN_ERR "Cannot stop DVFS-PER\n");
#else
	/* Set the frequencies manually */
	rate = clk_get_rate(axi_b_clk);
	clk_set_rate(axi_b_clk, clk_round_rate(axi_b_clk, 130000000));
	rate = clk_get_rate(ahb_clk);
	clk_set_rate(ahb_clk, clk_round_rate(ahb_clk, 130000000));
#endif
	dvfs_per_low_freq = 0;

#ifndef DVFS_SW_WORKAROUND
	clk_set_parent(main_bus_clk, pll2);
#endif
}
예제 #16
0
static int __init mx5_pm_init(void)
{
	if (gpc_dvfs_clk == NULL)
		gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");

	if (!IS_ERR(gpc_dvfs_clk)) {
		if (cpu_is_mx51())
			suspend_set_ops(&mx5_suspend_ops);
	} else
		return -EPERM;

	return 0;
}
예제 #17
0
void __init mx5_usbh1_init(void)
{
	if (cpu_is_mx51()) {
		usbh1_config.phy_mode = FSL_USB2_PHY_ULPI;
		usbh1_config.transceiver = "isp1504";
		usbh1_config.gpio_usb_active = gpio_usbh1_active;
		usbh1_config.gpio_usb_inactive = gpio_usbh1_inactive;
	}
	if (cpu_is_mx53() || cpu_is_mx50()) {
		mxc_usbh1_device.resource[0].start	-= MX53_OFFSET;
		mxc_usbh1_device.resource[0].end	-= MX53_OFFSET;
	}
	mxc_register_device(&mxc_usbh1_device, &usbh1_config);
	usbh1_config.wakeup_pdata = &usbh1_wakeup_config;
	mxc_register_device(&mxc_usbh1_wakeup_device, &usbh1_wakeup_config);
}
예제 #18
0
static int fsl_usb_host_init_ext(struct platform_device *pdev)
{
	int ret;
	struct clk *usb_clk;

	if (cpu_is_mx53()) {
		usb_clk = clk_get(NULL, "usboh3_clk");
		clk_enable(usb_clk);
		clk_put(usb_clk);

		usb_clk = clk_get(&pdev->dev, "usb_phy2_clk");
		clk_enable(usb_clk);
		clk_put(usb_clk);

		/*derive clock from oscillator */
		usb_clk = clk_get(NULL, "usb_utmi_clk");
		clk_disable(usb_clk);
		clk_put(usb_clk);
	} else if (cpu_is_mx50()) {
		usb_clk = clk_get(&pdev->dev, "usb_phy2_clk");
		clk_enable(usb_clk);
		clk_put(usb_clk);
	}

	ret = fsl_usb_host_init(pdev);
	if (ret)
		return ret;

	if (cpu_is_mx51()) {
		/* setback USBH1_STP to be function */
		mxc_request_iomux(MX51_PIN_USBH1_STP, IOMUX_CONFIG_ALT0);
		mxc_iomux_set_pad(MX51_PIN_USBH1_STP, PAD_CTL_SRE_FAST |
				  PAD_CTL_DRV_HIGH | PAD_CTL_ODE_OPENDRAIN_NONE |
				  PAD_CTL_PUE_KEEPER | PAD_CTL_PKE_ENABLE |
				  PAD_CTL_HYS_ENABLE | PAD_CTL_DDR_INPUT_CMOS |
				  PAD_CTL_DRV_VOT_LOW);
		gpio_free(IOMUX_TO_GPIO(MX51_PIN_USBH1_STP));
	}

	/* disable remote wakeup irq */
	USBCTRL &= ~UCTRL_H1WIE;
	return 0;
}
예제 #19
0
파일: usb_h1.c 프로젝트: pocketbook/801
static void fsl_usb_host_uninit_ext(struct fsl_usb2_platform_data *pdata)
{
	if (cpu_is_mx53()) {
		clk_disable(usb_oh3_clk);
		clk_put(usb_oh3_clk);

		clk_disable(usb_phy2_clk);
		clk_put(usb_phy2_clk);
	} else if (cpu_is_mx50()) {
		clk_disable(usb_phy2_clk);
		clk_put(usb_phy2_clk);
	} else if (cpu_is_mx51()) {
		clk_disable(usb_oh3_clk);
		clk_put(usb_oh3_clk);
	}

	fsl_usb_host_uninit(pdata);
	/* usb_ahb_clk will be disabled at usb_common.c */
	clk_put(usb_ahb_clk);
}
예제 #20
0
/******************************************************************************
*
* CAUTION: NONE
*
* MODIFICATION HISTORY:
*
* Date         Person     Change
* 30/07/2003   MW         Initial Creation
******************************************************************************/
int sah_Intr_Init(wait_queue_head_t * wait_queue)
{

#ifdef DIAG_DRV_INTERRUPT
	char err_string[200];
#endif

	int result;

	int irq_sah = MX53_INT_SAHARA_H0;

	if (cpu_is_mx51())
		irq_sah = MX51_MXC_INT_SAHARA_H0;

#ifdef KERNEL_TEST
	SAHARA_INT_PTR = sah_Intr_Top_Half;
#endif

	/* Set queue used by the interrupt handler to match the driver interface */
	int_queue = wait_queue;

	/* Request use of the Interrupt line. */
	result = request_irq(irq_sah,
			     sah_Intr_Top_Half, 0, SAHARA_NAME, NULL);

#ifdef DIAG_DRV_INTERRUPT
	if (result != 0) {
		sprintf(err_string, "Cannot use SAHARA interrupt line %d. "
			"request_irq() return code is %i.", irq_sah, result);
		LOG_KDIAG(err_string);
	} else {
		sprintf(err_string,
			"SAHARA driver registered for interrupt %d. ",
			irq_sah);
		LOG_KDIAG(err_string);
	}
#endif

	return result;
}
예제 #21
0
static void usbh2_set_ulpi_xcvr(void)
{
	u32 tmp;

	pr_debug("%s\n", __func__);

	UH2_USBCMD &= ~UCMD_RUN_STOP;
	while (UH2_USBCMD & UCMD_RUN_STOP)
		;

	UH2_USBCMD |= UCMD_RESET;
	while (UH2_USBCMD & UCMD_RESET)

	USBCTRL_HOST2 &= ~(UCTRL_H2SIC_MASK | UCTRL_BPE);
	USBCTRL_HOST2 &= ~UCTRL_H2WIE;	/* wakeup intr enable */
	USBCTRL_HOST2 &= ~UCTRL_H2UIE;	/* ULPI intr enable */
	USB_CTRL_1 |= USB_CTRL_UH2_EXT_CLK_EN;
	if (cpu_is_mx53())
		USB_CTRL_1 |= USB_CTRL_UH2_CLK_FROM_ULPI_PHY;
	if (cpu_is_mx51())/* not tested */
		USBCTRL_HOST2 |= (1 << 12);
	/* must set ULPI phy before turning off clock */
	tmp = UH2_PORTSC1 & ~PORTSC_PTS_MASK;
	tmp |= PORTSC_PTS_ULPI;
	UH2_PORTSC1 = tmp;
	if (cpu_is_mx53()) {
		/* turn off the internal 60MHZ clk  */
		USB_CLKONOFF_CTRL |= (1 << 21);
	}
	UH2_USBCMD |= UCMD_RESET;	/* reset the controller */

	/* allow controller to reset, and leave time for
	 * the ULPI transceiver to reset too.
	 */
	msleep(100);

	/* Turn off the usbpll for ulpi tranceivers */
	clk_disable(usb_clk);
}
예제 #22
0
static int
utp_ioctl(struct inode *inode, struct file *file,
	      unsigned int cmd, unsigned long arg)
{
	int cpu_id = 0;
	switch (cmd) {
	case UTP_GET_CPU_ID:
/* Currently, it only supports below SoC for manufacture tool
 * The naming rule
 * 1. The numberic for SoC string
 * 2. If there is next SoC version, and the corresponding utp
 * operation will be differ, then, need to add '1' next to SoC
 * name. Such as the next 50 SoC version is: cpu_is = 501
 */
#ifdef CONFIG_ARCH_MXS
		if (cpu_is_mx23())
			cpu_id = 23;
		else if (cpu_is_mx28())
			cpu_id = 28;
#endif
#ifdef CONFIG_ARCH_MXC
		if (cpu_is_mx25())
			cpu_id = 25;
		else if (cpu_is_mx35())
			cpu_id = 35;
		else if (cpu_is_mx51())
			cpu_id = 51;
		else if (cpu_is_mx53())
			cpu_id = 53;
		else if (cpu_is_mx50())
			cpu_id = 50;
#endif
		return put_user(cpu_id, (int __user *)arg);
	default:
		return -ENOIOCTLCMD;
	}
}
예제 #23
0
void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata)
{
	pr_debug("%s\n", __func__);

	if (pdata->xcvr_ops && pdata->xcvr_ops->uninit)
		pdata->xcvr_ops->uninit(pdata->xcvr_ops);

	pdata->regs = NULL;

	pdata->gpio_usb_inactive();
	if (pdata->xcvr_type == PORTSC_PTS_SERIAL) {
		/* Workaround an IC issue for 2.6.26 kernal:
		 * when turn off root hub port power, EHCI set
		 * PORTSC reserved bits to be 0, but PTS with 0
		 * means UTMI interface, so here force the Host2
		 * port use the internal 60Mhz.
		 */
		if (cpu_is_mx35())
			USBCTRL |= UCTRL_XCSH2;
		clk_disable(usb_clk);
	}

	/* disable board power supply for xcvr */
	if (pdata->xcvr_pwr) {
		if (pdata->xcvr_pwr->regu1)
			regulator_disable(pdata->xcvr_pwr->regu1);
		if (pdata->xcvr_pwr->regu2)
			regulator_disable(pdata->xcvr_pwr->regu2);
	}

	if (cpu_is_mx51()) {
		usb_clk = clk_get(NULL, "usboh3_clk");
		clk_disable(usb_clk);
		clk_put(usb_clk);
	}
}
예제 #24
0
void fsl_usb_host_uninit(struct fsl_usb2_platform_data *pdata)
{
	pr_debug("%s\n", __func__);

	if (pdata->xcvr_ops && pdata->xcvr_ops->uninit)
		pdata->xcvr_ops->uninit(pdata->xcvr_ops);

	pdata->regs = NULL;

	pdata->gpio_usb_inactive();
	if (pdata->xcvr_type == PORTSC_PTS_SERIAL)
		clk_disable(usb_clk);
	else if ((pdata->xcvr_type == PORTSC_PTS_ULPI)
		 && (machine_is_mx31_3ds())) {
		usbh2_put_xcvr_power(&(pdata->xcvr_pwr->usb_pdev->dev));
		kfree(pdata->xcvr_pwr);
	}

	if (cpu_is_mx51()) {
		usb_clk = clk_get(NULL, "usboh3_clk");
		clk_disable(usb_clk);
		clk_put(usb_clk);
	}
}
예제 #25
0
static int ehci_mxc_drv_probe(struct platform_device *pdev)
{
	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
	struct usb_hcd *hcd;
	struct resource *res;
	int irq, ret;
	unsigned int flags;
	struct ehci_mxc_priv *priv;
	struct device *dev = &pdev->dev;
	struct ehci_hcd *ehci;

	dev_info(&pdev->dev, "initializing i.MX USB Controller\n");

	if (!pdata) {
		dev_err(dev, "No platform data given, bailing out.\n");
		return -EINVAL;
	}

	irq = platform_get_irq(pdev, 0);

	hcd = usb_create_hcd(&ehci_mxc_hc_driver, dev, dev_name(dev));
	if (!hcd)
		return -ENOMEM;

	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		ret = -ENOMEM;
		goto err_alloc;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "Found HC with no register addr. Check setup!\n");
		ret = -ENODEV;
		goto err_get_resource;
	}

	hcd->rsrc_start = res->start;
	hcd->rsrc_len = resource_size(res);

	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
		dev_dbg(dev, "controller already in use\n");
		ret = -EBUSY;
		goto err_request_mem;
	}

	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
	if (!hcd->regs) {
		dev_err(dev, "error mapping memory\n");
		ret = -EFAULT;
		goto err_ioremap;
	}

	/* enable clocks */
	priv->usbclk = clk_get(dev, "usb");
	if (IS_ERR(priv->usbclk)) {
		ret = PTR_ERR(priv->usbclk);
		goto err_clk;
	}
	clk_enable(priv->usbclk);

	if (!cpu_is_mx35() && !cpu_is_mx25()) {
		priv->ahbclk = clk_get(dev, "usb_ahb");
		if (IS_ERR(priv->ahbclk)) {
			ret = PTR_ERR(priv->ahbclk);
			goto err_clk_ahb;
		}
		clk_enable(priv->ahbclk);
	}

	/* "dr" device has its own clock on i.MX51 */
	if (cpu_is_mx51() && (pdev->id == 0)) {
		priv->phy1clk = clk_get(dev, "usb_phy1");
		if (IS_ERR(priv->phy1clk)) {
			ret = PTR_ERR(priv->phy1clk);
			goto err_clk_phy;
		}
		clk_enable(priv->phy1clk);
	}


	/* call platform specific init function */
	if (pdata->init) {
		ret = pdata->init(pdev);
		if (ret) {
			dev_err(dev, "platform init failed\n");
			goto err_init;
		}
		/* platforms need some time to settle changed IO settings */
		mdelay(10);
	}

	ehci = hcd_to_ehci(hcd);

	/* EHCI registers start at offset 0x100 */
	ehci->caps = hcd->regs + 0x100;
	ehci->regs = hcd->regs + 0x100 +
		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));

	/* set up the PORTSCx register */
	ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);

	/* is this really needed? */
	msleep(10);

	/* Initialize the transceiver */
	if (pdata->otg) {
		pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
		ret = otg_init(pdata->otg);
		if (ret) {
			dev_err(dev, "unable to init transceiver, probably missing\n");
			ret = -ENODEV;
			goto err_add;
		}
		ret = otg_set_vbus(pdata->otg, 1);
		if (ret) {
			dev_err(dev, "unable to enable vbus on transceiver\n");
			goto err_add;
		}
	}

	priv->hcd = hcd;
	platform_set_drvdata(pdev, priv);

	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
	if (ret)
		goto err_add;

	if (pdata->otg) {
		/*
		 * efikamx and efikasb have some hardware bug which is
		 * preventing usb to work unless CHRGVBUS is set.
		 * It's in violation of USB specs
		 */
		if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) {
			flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL);
			flags |= ULPI_OTG_CTRL_CHRGVBUS;
			ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL);
			if (ret) {
				dev_err(dev, "unable to set CHRVBUS\n");
				goto err_add;
			}
		}
	}

	return 0;

err_add:
	if (pdata && pdata->exit)
		pdata->exit(pdev);
err_init:
	if (priv->phy1clk) {
		clk_disable(priv->phy1clk);
		clk_put(priv->phy1clk);
	}
err_clk_phy:
	if (priv->ahbclk) {
		clk_disable(priv->ahbclk);
		clk_put(priv->ahbclk);
	}
err_clk_ahb:
	clk_disable(priv->usbclk);
	clk_put(priv->usbclk);
err_clk:
	iounmap(hcd->regs);
err_ioremap:
	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_request_mem:
err_get_resource:
	kfree(priv);
err_alloc:
	usb_put_hcd(hcd);
	return ret;
}
예제 #26
0
int mxc_initialize_usb_hw(int port, unsigned int flags)
{
	unsigned int v;
#if defined(CONFIG_ARCH_MX25)
	if (cpu_is_mx25()) {
		v = readl(MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));

		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX35_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_OTG_PM_BIT;

			break;
		case 1: /* H1 port */
			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX35_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX35_H1_TLL_BIT;

			if (flags & MXC_EHCI_INTERNAL_PHY)
				v |= MX35_H1_USBTE_BIT;

			if (flags & MXC_EHCI_IPPUE_DOWN)
				v |= MX35_H1_IPPUE_DOWN_BIT;

			if (flags & MXC_EHCI_IPPUE_UP)
				v |= MX35_H1_IPPUE_UP_BIT;

			break;
		default:
			return -EINVAL;
		}

		writel(v, MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}
#endif /* CONFIG_ARCH_MX25 */
#if defined(CONFIG_ARCH_MX3)
	if (cpu_is_mx31()) {
		v = readl(MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));

		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX31_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_OTG_PM_BIT;

			break;
		case 1: /* H1 port */
			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H1_DT_BIT;

			break;
		case 2:	/* H2 port */
			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H2_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H2_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H2_DT_BIT;

			break;
		default:
			return -EINVAL;
		}

		writel(v, MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}

	if (cpu_is_mx35()) {
		v = readl(MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));

		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX35_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_OTG_PM_BIT;

			break;
		case 1: /* H1 port */
			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX35_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX35_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX35_H1_TLL_BIT;

			if (flags & MXC_EHCI_INTERNAL_PHY)
				v |= MX35_H1_USBTE_BIT;

			if (flags & MXC_EHCI_IPPUE_DOWN)
				v |= MX35_H1_IPPUE_DOWN_BIT;

			if (flags & MXC_EHCI_IPPUE_UP)
				v |= MX35_H1_IPPUE_UP_BIT;

			break;
		default:
			return -EINVAL;
		}

		writel(v, MX35_IO_ADDRESS(MX35_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}
#endif /* CONFIG_ARCH_MX3 */
#ifdef CONFIG_MACH_MX27
	if (cpu_is_mx27()) {
		/* On i.MX27 we can use the i.MX31 USBCTRL bits, they
		 * are identical
		 */
		v = readl(MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		switch (port) {
		case 0:	/* OTG port */
			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
					<< MX31_OTG_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_OTG_PM_BIT;
			break;
		case 1: /* H1 port */
			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H1_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H1_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H1_DT_BIT;

			break;
		case 2:	/* H2 port */
			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
			v |= (flags & MXC_EHCI_INTERFACE_MASK)
						<< MX31_H2_SIC_SHIFT;
			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
				v |= MX31_H2_PM_BIT;

			if (!(flags & MXC_EHCI_TTL_ENABLED))
				v |= MX31_H2_DT_BIT;

			break;
		default:
			return -EINVAL;
		}
		writel(v, MX27_IO_ADDRESS(MX27_OTG_BASE_ADDR +
				     USBCTRL_OTGBASE_OFFSET));
		return 0;
	}
#endif /* CONFIG_MACH_MX27 */
#ifdef CONFIG_ARCH_MX51
	if (cpu_is_mx51()) {
		void __iomem *usb_base;
		u32 usbotg_base;
		u32 usbother_base;
		int ret = 0;

		usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);

		switch (port) {
		case 0:	/* OTG port */
			usbotg_base = usb_base + MXC_OTG_OFFSET;
			break;
		case 1:	/* Host 1 port */
			usbotg_base = usb_base + MXC_H1_OFFSET;
			break;
		default:
			printk(KERN_ERR"%s no such port %d\n", __func__, port);
			ret = -ENOENT;
			goto error;
		}
		usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;

		switch (port) {
		case 0:	/*OTG port */
			if (flags & MXC_EHCI_INTERNAL_PHY) {
				v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);

				if (flags & MXC_EHCI_POWER_PINS_ENABLED)
					v |= (MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is not used */
				else
					v &= ~(MXC_OTG_PHYCTRL_OC_DIS_BIT | MXC_OTG_UCTRL_OPM_BIT); /* OC/USBPWR is used */
				__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);

				v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
				if (flags & MXC_EHCI_WAKEUP_ENABLED)
					v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
				else
					v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
				__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
			}
			break;
		case 1:	/* Host 1 */
			/*Host ULPI */
			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
			if (flags & MXC_EHCI_WAKEUP_ENABLED)
				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */
			else
				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);/* HOST1 wakeup/ULPI intr disable */

			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
				v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
			else
				v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);

			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
				v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
			else
				v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);

			v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
			if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
				/* Interrupt Threshold Control:Immediate (no threshold) */
				v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
			__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
			break;
		}

error:
		iounmap(usb_base);
		return ret;
	}
#endif
	printk(KERN_WARNING
		"%s() unable to setup USBCONTROL for this CPU\n", __func__);
	return -EINVAL;
}
예제 #27
0
int set_high_bus_freq(int high_bus_freq)
{
	u32 reg;
	if (bus_freq_scaling_initialized) {
		mutex_lock(&bus_freq_mutex);
		/*
		 * If the CPU freq is 800MHz, set the bus to the high
		 * setpoint (133MHz) and DDR to 200MHz.
		 */
		if ((clk_get_rate(cpu_clk) >
				cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate)
				|| lp_high_freq)
			high_bus_freq = 1;

		stop_sdram_autogating();

		if (low_bus_freq_mode) {
			/* Relock PLL3 to 133MHz */
			if (cpu_is_mx50())
				exit_lpapm_mode_mx50(high_bus_freq);
			else if (cpu_is_mx51())
				exit_lpapm_mode_mx51();
			else
				exit_lpapm_mode_mx53();
			start_dvfs_per();
		}
		if (bus_freq_scaling_is_active) {
			if (!high_bus_freq_mode && high_bus_freq) {
				if (cpu_is_mx50()) {
					if (med_bus_freq_mode) {
						/* Increase SYS_CLK */
						reg = __raw_readl(MXC_CCM_CLK_SYS);
						reg &= ~MXC_CCM_CLK_SYS_DIV_PLL_MASK;
						reg |= 4 << MXC_CCM_CLK_SYS_DIV_PLL_OFFSET;
						__raw_writel(reg, MXC_CCM_CLK_SYS);

						/* Set the dividers to the default dividers */
						reg = __raw_readl(MXC_CCM_CBCDR);
						reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
							| MXC_CCM_CBCDR_AXI_B_PODF_MASK
							| MXC_CCM_CBCDR_AHB_PODF_MASK
							| MX50_CCM_CBCDR_WEIM_PODF_MASK);
						reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
							|1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
							|2 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
							|0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
						__raw_writel(reg, MXC_CCM_CBCDR);

						while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
							udelay(10);
					}
				} else {
					clk_set_rate(ahb_clk,
						clk_round_rate(ahb_clk,
							lp_normal_rate));
					clk_set_rate(ddr_hf_clk,
						clk_round_rate(ddr_hf_clk,
							ddr_normal_rate));
				}
				/* Set to the high setpoint. */
				high_bus_freq_mode = 1;
				low_bus_freq_mode = 0;
				med_bus_freq_mode = 0;
			} else if (!med_bus_freq_mode && !high_bus_freq) {
				if (cpu_is_mx50()) {
					/* Set the dividers to the medium setpoint dividers */
					reg = __raw_readl(MXC_CCM_CBCDR);
					reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
						| MXC_CCM_CBCDR_AXI_B_PODF_MASK
						| MXC_CCM_CBCDR_AHB_PODF_MASK
						| MX50_CCM_CBCDR_WEIM_PODF_MASK);
					reg |= (1 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
						|3 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
						|5 << MXC_CCM_CBCDR_AHB_PODF_OFFSET
						|0 << MX50_CCM_CBCDR_WEIM_PODF_OFFSET);
					__raw_writel(reg, MXC_CCM_CBCDR);

					while (__raw_readl(MXC_CCM_CDHIPR) & 0xF)
						udelay(10);
					/* Reduce SYS_CLK */
					reg = __raw_readl(MXC_CCM_CLK_SYS);
					reg &= ~MXC_CCM_CLK_SYS_DIV_PLL_MASK;
					reg |= 8 << MXC_CCM_CLK_SYS_DIV_PLL_OFFSET;
					__raw_writel(reg, MXC_CCM_CLK_SYS);
				} else {
					if (cpu_is_mx51())
						clk_set_rate(ddr_hf_clk,
							clk_round_rate(
							ddr_hf_clk,
							ddr_low_rate));
					clk_set_rate(ahb_clk,
					clk_round_rate(
						ahb_clk, lp_med_rate));
				}
				/* Set to the medium setpoint. */
				high_bus_freq_mode = 0;
				low_bus_freq_mode = 0;
				med_bus_freq_mode = 1;
			}
			if (cpu_is_mx50()) {
				if (med_bus_freq_mode &&
					(cur_ddr_rate != ddr_med_rate))
					set_ddr_freq(ddr_med_rate);
				if (high_bus_freq_mode &&
					(cur_ddr_rate != ddr_normal_rate))
					set_ddr_freq(ddr_normal_rate);
			}
		}
		start_sdram_autogating();
		mutex_unlock(&bus_freq_mutex);
	}
	return 0;
}
예제 #28
0
파일: system.c 프로젝트: pocketbook/801
/* set cpu low power mode before WFI instruction */
void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
{
	u32 plat_lpc, arm_srpgcr, ccm_clpcr;
	u32 empgc0 = 0;
	u32 empgc1 = 0;
	int stop_mode = 0;

	/* always allow platform to issue a deep sleep mode request */
	plat_lpc = __raw_readl(arm_plat_base + MXC_CORTEXA8_PLAT_LPC) &
	    ~(MXC_CORTEXA8_PLAT_LPC_DSM);
	ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
	arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
	if (!cpu_is_mx53()) {
		empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
		empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
	}

	switch (mode) {
	case WAIT_CLOCKED:
		break;
	case WAIT_UNCLOCKED:
		ccm_clpcr |= (0x1 << MXC_CCM_CLPCR_LPM_OFFSET);
		break;
	case WAIT_UNCLOCKED_POWER_OFF:
	case STOP_POWER_OFF:
		plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
			    | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
		if (mode == WAIT_UNCLOCKED_POWER_OFF) {
			ccm_clpcr |= (0x1 << MXC_CCM_CLPCR_LPM_OFFSET);
			ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
			ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
			stop_mode = 0;
		} else {
			ccm_clpcr |= (0x2 << MXC_CCM_CLPCR_LPM_OFFSET);
			ccm_clpcr |= (0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET);
			ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
			ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
			stop_mode = 1;
		}

		arm_srpgcr |= MXC_SRPGCR_PCR;
		if (stop_mode && !cpu_is_mx53()) {
			empgc0 |= MXC_SRPGCR_PCR;
			empgc1 |= MXC_SRPGCR_PCR;
		}

		if (tzic_enable_wake(1) != 0)
			return;
		break;
	case STOP_POWER_ON:
		ccm_clpcr |= (0x2 << MXC_CCM_CLPCR_LPM_OFFSET);
		break;
	default:
		printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
		return;
	}

	__raw_writel(plat_lpc, arm_plat_base + MXC_CORTEXA8_PLAT_LPC);
	__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
	if (cpu_is_mx51() || (mx53_revision() >= IMX_CHIP_REVISION_2_0)
		|| (mx50_revision() >= IMX_CHIP_REVISION_1_1))
		__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
	/* Enable NEON SRPG for all but MX50TO1.0. */
	if (!(mx50_revision() == IMX_CHIP_REVISION_1_0))
		__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
	if (stop_mode && !cpu_is_mx53()) {
		__raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
		__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
	}
}
예제 #29
0
/*
 * SSI DAI format configuration.
 * Should only be called when port is inactive (i.e. SSIEN = 0).
 * Note: We don't use the I2S modes but instead manually configure the
 * SSI for I2S.
 */
static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
{
	struct imx_ssi *priv = (struct imx_ssi *)cpu_dai->private_data;
	void __iomem *ioaddr = priv->ioaddr;
	u32 stcr = 0, srcr = 0, scr;

	scr = __raw_readl(ioaddr + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET);

	if (scr & SSI_SCR_SSIEN)
		return 0;

	/* DAI mode */
	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
	case SND_SOC_DAIFMT_I2S:
		/* data on rising edge of bclk, frame low 1clk before data */
		stcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0;
		srcr |= SSI_SRCR_RFSI | SSI_SRCR_REFS | SSI_SRCR_RXBIT0;
		break;
	case SND_SOC_DAIFMT_LEFT_J:
		/* data on rising edge of bclk, frame high with data */
		stcr |= SSI_STCR_TXBIT0;
		srcr |= SSI_SRCR_RXBIT0;
		break;
	case SND_SOC_DAIFMT_DSP_B:
		/* data on rising edge of bclk, frame high with data */
		stcr |= SSI_STCR_TFSL;
		srcr |= SSI_SRCR_RFSL;
		break;
	case SND_SOC_DAIFMT_DSP_A:
		/* data on rising edge of bclk, frame high 1clk before data */
		stcr |= SSI_STCR_TFSL | SSI_STCR_TEFS;
		srcr |= SSI_SRCR_RFSL | SSI_SRCR_REFS;
		break;
	}

	/* DAI clock inversion */
	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
	case SND_SOC_DAIFMT_IB_IF:
		stcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI);
		srcr &= ~(SSI_SRCR_RSCKP | SSI_SRCR_RFSI);
		break;
	case SND_SOC_DAIFMT_IB_NF:
		stcr |= SSI_STCR_TFSI;
		stcr &= ~SSI_STCR_TSCKP;
		srcr |= SSI_SRCR_RFSI;
		srcr &= ~SSI_SRCR_RSCKP;
		break;
	case SND_SOC_DAIFMT_NB_IF:
		stcr &= ~SSI_STCR_TFSI;
		stcr |= SSI_STCR_TSCKP;
		srcr &= ~SSI_SRCR_RFSI;
		srcr |= SSI_SRCR_RSCKP;
		break;
	case SND_SOC_DAIFMT_NB_NF:
		stcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP;
		srcr |= SSI_SRCR_RFSI | SSI_SRCR_RSCKP;
		break;
	}

	/* DAI clock master masks */
	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
	case SND_SOC_DAIFMT_CBS_CFS:
		stcr |= SSI_STCR_TFDIR | SSI_STCR_TXDIR;
		if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
		    && priv->network_mode) {
			scr &= ~SSI_SCR_I2S_MODE_MASK;
			scr |= SSI_SCR_I2S_MODE_MSTR;
		}
		break;
	case SND_SOC_DAIFMT_CBM_CFS:
		stcr |= SSI_STCR_TFDIR;
		srcr |= SSI_SRCR_RFDIR;
		break;
	case SND_SOC_DAIFMT_CBS_CFM:
		stcr |= SSI_STCR_TXDIR;
		srcr |= SSI_SRCR_RXDIR;
		break;
	case SND_SOC_DAIFMT_CBM_CFM:
		if (((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
		    && priv->network_mode) {
			scr &= ~SSI_SCR_I2S_MODE_MASK;
			scr |= SSI_SCR_I2S_MODE_SLAVE;
		}
		break;
	}

	/* sync */
	if (priv->sync_mode)
		scr |= SSI_SCR_SYN;

	/* tdm - only for stereo atm */
	if (priv->network_mode)
		scr |= SSI_SCR_NET;
#ifdef CONFIG_MXC_SSI_DUAL_FIFO
	if (cpu_is_mx51() || cpu_is_mx53()) {
		stcr |= SSI_STCR_TFEN1;
		srcr |= SSI_SRCR_RFEN1;
		scr |= SSI_SCR_TCH_EN;
	}
#endif
	__raw_writel(stcr, ioaddr + SSI_STCR);
	__raw_writel(srcr, ioaddr + SSI_SRCR);
	__raw_writel(scr, ioaddr + SSI_SCR);

	SSI_DUMP();
	return 0;
}
예제 #30
0
static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
{
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
	struct clk *clk;
	int err;

	clk = clk_get(mmc_dev(host->mmc), NULL);
	if (IS_ERR(clk)) {
		dev_err(mmc_dev(host->mmc), "clk err\n");
		return PTR_ERR(clk);
	}
	clk_enable(clk);
	pltfm_host->clk = clk;

	if (cpu_is_mx35() || cpu_is_mx51())
		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;

	if (cpu_is_mx25() || cpu_is_mx35()) {
		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
		/* write_protect can't be routed to controller, use gpio */
		sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
	}

	if (boarddata) {
		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
		if (err) {
			dev_warn(mmc_dev(host->mmc),
				"no write-protect pin available!\n");
			boarddata->wp_gpio = err;
		}

		err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
		if (err) {
			dev_warn(mmc_dev(host->mmc),
				"no card-detect pin available!\n");
			goto no_card_detect_pin;
		}

		/* i.MX5x has issues to be researched */
		if (!cpu_is_mx25() && !cpu_is_mx35())
			goto not_supported;

		err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
				 mmc_hostname(host->mmc), host);
		if (err) {
			dev_warn(mmc_dev(host->mmc), "request irq error\n");
			goto no_card_detect_irq;
		}

		sdhci_esdhc_ops.write_l = esdhc_writel_le;
		sdhci_esdhc_ops.read_l = esdhc_readl_le;
		/* Now we have a working card_detect again */
		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
	}

	return 0;

 no_card_detect_irq:
	gpio_free(boarddata->cd_gpio);
 no_card_detect_pin:
	boarddata->cd_gpio = err;
 not_supported:
	return 0;
}