Esempio n. 1
0
static void mshci_hi_sdio_set_power(struct platform_device *dev, int val)
{
	struct mshci_host *host = platform_get_drvdata(dev);
	struct himci_host * hi_host = (struct himci_host *)(host->private);
	/*int ret = -1;*/
	u32 loop_count = 1000; /* wait 10S */
	u32 i = 0;

	himci_assert(host);
	himci_assert(hi_host);

	for (i = 0; i < loop_count; i++) {
		if (MMC_HOST_BUSY == host->working || host->mrq) {
			msleep(10);
		} else {
			break;
		}
	}
#if 0
	if (val) {
		printk("%s:val=%d, set io to normal mode\n", __func__, val);
		host->mmc->ios.power_mode = MMC_POWER_UP;
		host->mmc->ios.timing = MMC_TIMING_LEGACY;
		host->mmc->ios.bus_width = MMC_BUS_WIDTH_1;
		host->mmc->ios.clock = 0;
		host->mmc->ops->set_ios(host->mmc, &host->mmc->ios);

		ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, NORMAL);
		if (ret) {
			himci_error("failed to blockmux_set");
		}
		msleep(10);

		host->mmc->ios.power_mode = MMC_POWER_ON;
		host->mmc->ios.clock = 400000;
		host->mmc->ops->set_ios(host->mmc, &host->mmc->ios);

		//to do w00215368
		//blockmux_set(hi_host->piomux_block, hi_host->pblock_config, NORMAL);
	} else {
		printk("%s:val=%d, set io to lowpower mode\n", __func__, val);
		host->mmc->ios.clock = 0;
		host->mmc->ios.power_mode = MMC_POWER_OFF;
		host->mmc->ios.bus_width = MMC_BUS_WIDTH_1;
		host->mmc->ios.timing = MMC_TIMING_LEGACY;

		ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, LOWPOWER);
		if (ret) {
			himci_error("failed to blockmux_set");
		}
	}
#endif
}
Esempio n. 2
0
/* set host timing config */
static void mshci_hi_update_timing(struct mshci_host *ms_host, int bsuspend)
{
	struct himci_host * hi_host = (struct himci_host *)(ms_host->private);
	unsigned int config_val;

	if ( get_chipid() == DI_CHIP_ID ) {
		if (bsuspend) {
			config_val = hi_host->suspend_timing_config;
		} else {
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "current signal voltage = %d",
							hi_host->old_sig_voltage);
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "current timing = %d",
							hi_host->old_timing);
			config_val = hi_host->timing_config[hi_host->old_timing + \
							hi_host->old_sig_voltage * (MMC_TIMING_UHS_DDR50 + 1)];
		}

		hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "current timing config = 0x%x",
						config_val);

		if (-1 == config_val) {
			himci_error("invalid config_val");
		}

		writel(0xF << (hi_host->pdev->id * 4),
					IO_ADDRESS(REG_BASE_SCTRL) + REG_SCPERDIS4);
		writel(config_val << (hi_host->pdev->id * 4),
					IO_ADDRESS(REG_BASE_SCTRL) + REG_SCPEREN4);

		hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "new reg val 0x%x",
					readl(IO_ADDRESS(REG_BASE_SCTRL) + REG_SCPERSTAT4));
	}
}
Esempio n. 3
0
static int hi_mci_resume(struct platform_device *dev)
{
	int ret = 0;
	struct mshci_host *ms_host = NULL;
	struct himci_host *hi_host = NULL;   
	int cbp_flag = 0;
	int cbp_ret = 0;
	unsigned int oldclock = 0;

	ms_host = platform_get_drvdata(dev);
	if (!ms_host) {
		printk(KERN_WARNING "the return value of platform_get_drvdata is NULL !\n");
		return -1;
	}
	hi_host = mshci_priv(ms_host);

	cbp_ret = get_hw_config_int("modem/viacbp82d", &cbp_flag, NULL);
	if ((!cbp_ret) || (0 == cbp_flag)) {
		pr_info("%s has no cbp support\n", __func__);
	}

	if ((1 == hi_host->pdev->id)&&(cbp_flag)){
		ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, NORMAL);
		if (ret) {
			himci_error("failed to blockmux_set");
		}
	}

	printk(KERN_INFO "hi_mci_resume is called \n");
	mshci_resume_host(ms_host);

	if (ms_host->quirks & MSHCI_QUIRK_WLAN_DETECTION) {
		if (ms_host->mmc->ios.power_mode != MMC_POWER_OFF) {
			ret = mmc_sdio_resume_ext(ms_host->mmc);
			if (ret) {
				printk("%s, sdio resume error\n", __func__);
				return ret;
			}
		}
	}

	if ((1 == hi_host->pdev->id)&&(cbp_flag)){
		if (ms_host->mmc->ios.power_mode != MMC_POWER_OFF) {
			pr_info("%s cbp resume sdio maxclock = %d, cur_clk=%d\n", __func__, ms_host->max_clk, ms_host->clock);
			ms_host->mmc->ios.clock = ms_host->mmc->f_max;
			ms_host->mmc->ops->set_ios(ms_host->mmc, &ms_host->mmc->ios);
			ms_host->mmc->ops->enable_sdio_irq(ms_host->mmc, 1);
		}
		cbp_host_waked = 1;
		cbp_notifier_call_chain(1, NULL);
	}

    if(0 == hi_host->pdev->id)
    {
        g_ulmmc_suspend_flag = false;
        /*emmc resume 完毕*/
        printk("mmc_blk_resume, clr g_ulmmc_suspend_flag.\n");
    }
	return ret;
}
Esempio n. 4
0
static int __init hi_mci_init(void)
{
	int ret;

	himci_trace(2, "begin");

	ret = platform_device_register(&hi_mci_device);
	if (ret) {
		himci_error("Platform device register is failed!");
		return ret;
	}

	ret = platform_driver_register(&hi_mci_driver);
	if (ret) {
		platform_device_unregister(&hi_mci_device);
		himci_error("Platform driver register is failed!");
		return ret;
	}
	return ret;
}
Esempio n. 5
0
static void hi_mci_detect_card(unsigned long arg)
{
	struct himci_host *host = (struct himci_host *)arg;
	unsigned int i, curr_status, status[3], detect_retry_count = 0;

	himci_assert(host);

	while (1) {
		for (i = 0; i < 3; i++) {
			status[i] = hi_mci_sys_card_detect(host);
			udelay(10);
		}
		if ((status[0] == status[1]) && (status[0] == status[2]))
			break;

		detect_retry_count++;
		if (detect_retry_count >= retry_count) {
			himci_error("this is a dithering,card detect error!");
			goto err;
		}
	}
	curr_status = status[0];
	if (curr_status != host->card_status) {
		himci_trace(2, "begin card_status = %d\n", host->card_status);
		host->card_status = curr_status;
		if (curr_status != CARD_UNPLUGED) {
			hi_mci_init_card(host);
			printk(KERN_INFO "card connected!\n");
		} else
			printk(KERN_INFO "card disconnected!\n");

		mmc_detect_change(host->mmc, 0);
	}
err:
	mod_timer(&host->timer, jiffies + detect_time);
}
Esempio n. 6
0
static int mshci_hi_start_signal_voltage_switch(struct mshci_host *ms_host,
				struct mmc_ios *ios)
{
	struct himci_host *hi_host = (struct himci_host *)(ms_host->private);
	int ret =0;
	struct iomux_pin *pin_temp = NULL;

	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "++");

	himci_assert(ios);
	himci_assert(hi_host);

	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "old_sig_voltage = %d ",
					hi_host->old_sig_voltage);
	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "new_sig_voltage = %d ",
					ios->signal_voltage);
	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "allow_switch_signal_voltage = %d ",
					hi_host->allow_switch_signal_voltage);

	if (hi_host->allow_switch_signal_voltage &&
		(hi_host->old_sig_voltage != ios->signal_voltage)) {
		switch (ios->signal_voltage) {
		case MMC_SIGNAL_VOLTAGE_330:
			/* alter driver 6mA */
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "alter driver 6mA");
			pin_temp = iomux_get_pin(SD_CLK_PIN);
			if (pin_temp) {
				ret = pinmux_setdrivestrength(pin_temp, LEVEL2);
				if (ret < 0)
					himci_error("pinmux_setdrivestrength error");
			} else {
				himci_error("failed to get iomux pin");
			}

			hi_host->old_sig_voltage = ios->signal_voltage;
			/* if there is signal vcc, set vcc to signal voltage */
		    if (hi_host->signal_vcc) {
				ret = regulator_set_voltage(hi_host->signal_vcc, 2600000, 2600000);
				if (ret != 0) {
					himci_error("failed to regulator_set_voltage");
				}
				ret = regulator_enable(hi_host->signal_vcc);
				if (ret) {
					himci_error("failed to regulator_enable");
				}
		    }

			/* update time config*/
			mshci_hi_update_timing(ms_host, 0);
			break;
		case MMC_SIGNAL_VOLTAGE_180:
			/* alter driver 8mA */
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "alter driver 8mA");
			pin_temp = iomux_get_pin(SD_CLK_PIN);
			if (pin_temp) {
				ret = pinmux_setdrivestrength(pin_temp, LEVEL3);
				if (ret < 0)
					himci_error("pinmux_setdrivestrength error");
			} else {
				himci_error("failed to get iomux pin");
			}

			hi_host->old_sig_voltage = ios->signal_voltage;
			/* if there is signal vcc, set vcc to signal voltage */
		    if (hi_host->signal_vcc) {
				ret = regulator_set_voltage(hi_host->signal_vcc, 1800000, 1800000);
				if (ret != 0) {
					himci_error("failed to regulator_set_voltage");
				}
				ret = regulator_enable(hi_host->signal_vcc);
				if (ret) {
					himci_error("failed to regulator_enable");
				}
		    }
			/* update time config*/
			mshci_hi_update_timing(ms_host, 0);
			break;

		case MMC_SIGNAL_VOLTAGE_120:
			/* FIXME */
			/* 1.20v is not support */
			himci_error("1.20V is not supported");
			break;
		default:
			himci_error("unknown signal voltage");
			break;
		}
	}

	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "--");

	return 0;
}
Esempio n. 7
0
void mshci_hi_set_ios(struct mshci_host *ms_host, struct mmc_ios *ios)
{
	struct himci_host * hi_host = (struct himci_host *)(ms_host->private);
	int ret = -1;

	hi_host_trace(HIMCI_TRACE_GEN_API, "++");

	himci_assert(ios);
	himci_assert(hi_host);

	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->power_mode = %d ", ios->power_mode);
	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->clock = %d ", ios->clock);
	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->bus_width = %d ", ios->bus_width);
	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->timing = %d ", ios->timing);

	/* process power */
	if (hi_host->old_power_mode != ios->power_mode) {
		switch (ios->power_mode) {
		case MMC_POWER_OFF:
		    hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "set io to lowpower");
		    if (hi_host->vcc) {
				regulator_disable(hi_host->vcc);
		    }
			if (hi_host->signal_vcc) {
				regulator_disable(hi_host->signal_vcc);
				regulator_set_mode(hi_host->signal_vcc, REGULATOR_MODE_IDLE);
		    }

		    ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, LOWPOWER);
		    if (ret) {
				himci_error("failed to blockmux_set");
		    }

			break;
		case MMC_POWER_UP:
		    hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "set io to normal");

		    ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, NORMAL);
		    if (ret) {
				himci_error("failed to blockmux_set");
		    }

		    if (hi_host->vcc) {
				ret = regulator_set_voltage(hi_host->vcc, 2850000, 2850000);
				if (ret != 0) {
					himci_error("failed to regulator_set_voltage");
				}

				ret = regulator_enable(hi_host->vcc);
				if (ret) {
					himci_error("failed to regulator_enable");
				}
		    }
			if (hi_host->signal_vcc) {
				ret = regulator_set_voltage(hi_host->signal_vcc, 2600000, 2600000);
				if (ret != 0) {
					himci_error("failed to regulator_set_voltage");
				}
				regulator_set_mode(hi_host->signal_vcc, REGULATOR_MODE_NORMAL);
				ret = regulator_enable(hi_host->signal_vcc);
				if (ret) {
					himci_error("failed to regulator_enable");
				}

		    }
			break;
		case MMC_POWER_ON:
			break;
		default:
			himci_error("unknown power supply mode");
			break;
		}
		hi_host->old_power_mode = ios->power_mode;
	}

	/* process timing */
	if (hi_host->old_timing != ios->timing) {

		hi_host->old_timing = ios->timing;

		if ( get_chipid() == DI_CHIP_ID ) {
			mshci_hi_update_timing(ms_host, 0);

			switch (ios->timing) {
			case MMC_TIMING_LEGACY:
				if (hi_host->pdev->id == 1) {
					/* 2 division, 40M */
					writel((0x1<<6) | (0x7<<22),
						IO_ADDRESS(REG_BASE_SCTRL) + REG_SCCLKDIV2);
					ms_host->max_clk = 40*1000*1000;
					ms_host->clock++;
				} else if (hi_host->pdev->id == 0) {
					/* 2 division, 40M */
					writel((0x0<<5) | (0x1<<21),
						IO_ADDRESS(REG_BASE_SCTRL) + REG_SCCLKDIV2);
					ms_host->max_clk = 40*1000*1000;
					ms_host->clock++;
				}
				hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "MMC_TIMING_LEGACY");
				break;
			case MMC_TIMING_UHS_DDR50:
				if (hi_host->pdev->id == 1) {
					/* 1 division, 80M */
					writel((0x0<<6) | (0x7<<22),
						IO_ADDRESS(REG_BASE_SCTRL) + REG_SCCLKDIV2);
					ms_host->max_clk = 80*1000*1000;
					ms_host->clock++;
				} else {
#if 0
					/*
					 * m53980:
					 * debug purpose.
					 * change clock via sctrl configuration
					 */
					printk("clk div a:0x%x\n", readl(IO_ADDRESS(REG_BASE_SCTRL) + REG_SCCLKDIV2));
					writel((0x7)|(0xF<<16), IO_ADDRESS(REG_BASE_SCTRL) + REG_SCCLKDIV2);
					printk("clk div b:0x%x\n", readl(IO_ADDRESS(REG_BASE_SCTRL) + REG_SCCLKDIV2));
#endif
				}
				hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "MMC_TIMING_UHS_DDR50");
				break;
			case MMC_TIMING_UHS_SDR50:
				if (hi_host->pdev->id == 0) {
					writel((0x1<<5) | (0x1<<21),
						IO_ADDRESS(REG_BASE_SCTRL) + REG_SCCLKDIV2);
					ms_host->max_clk = 80*1000*1000;
					ms_host->clock++;
				}
				hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "MMC_TIMING_UHS_SDR50");
				break;
			default:
				break;
			}
		} else {
			ret = clk_set_rate(hi_host->pclk,hi_host->init_tuning_config[0 + (ios->timing + 1) * TUNING_INIT_CONFIG_NUM]);
			if (ret) {
				himci_error("failed to clk_set_rate");
			}
			hi_host->tuning_init_sample =
					(hi_host->init_tuning_config[3 + (ios->timing + 1) * TUNING_INIT_CONFIG_NUM] +
					hi_host->init_tuning_config[4 + (ios->timing + 1) * TUNING_INIT_CONFIG_NUM]) / 2;
			mshci_hi_set_timing(hi_host,
				hi_host->tuning_init_sample,
				hi_host->init_tuning_config[2 + (ios->timing + 1) * TUNING_INIT_CONFIG_NUM],
				hi_host->init_tuning_config[1 + (ios->timing + 1) * TUNING_INIT_CONFIG_NUM]);

			ms_host->max_clk = hi_host->init_tuning_config[5 + (ios->timing + 1) * TUNING_INIT_CONFIG_NUM];

			ms_host->clock++;
		}
	}

	hi_host_trace(HIMCI_TRACE_GEN_API, "--");
}
Esempio n. 8
0
static int __devinit hi_mci_probe(struct platform_device *pdev)
{
	struct mmc_host *mmc;
	struct himci_host *host = NULL;
	int ret = 0, irq;

	himci_trace(2, "begin");
	himci_assert(pdev);

	mmc = mmc_alloc_host(sizeof(struct himci_host), &pdev->dev);
	if (!mmc) {
		himci_error("no mem for hi mci host controller!\n");
		ret = -ENOMEM;
		goto out;
	}
	mmc->ops = &hi_mci_ops;

	mmc->f_min = CONFIG_MMC_CCLK_MIN;
	mmc->f_max = CONFIG_MMC_CCLK_MAX;
	mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED
		| MMC_CAP_MMC_HIGHSPEED;

	/* reload by this controller */
	mmc->max_blk_count = 2048;
	mmc->max_segs = 1024;
	mmc->max_req_size = 65535;/* see IP manual */
	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
	mmc->ocr = mmc->ocr_avail;


	host = mmc_priv(mmc);
	host->dma_vaddr = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
			&host->dma_paddr, GFP_KERNEL);
	if (!host->dma_vaddr) {
		himci_error("no mem for himci dma!\n");
		ret = -ENOMEM;
		goto out;
	}

	host->mmc = mmc;
	host->base = ioremap_nocache(CONFIG_HIMCI_IOBASE, HI_MCI_IO_SIZE);
	if (!host->base) {
		himci_error("no mem for himci base!\n");
		ret = -ENOMEM;
		goto out;
	}

	/* enable mmc clk */
	hi_mci_sys_ctrl_init(host);

	/* enable card */
	spin_lock_init(&host->lock);
	hi_mci_init_card(host);

	host->card_status = hi_mci_sys_card_detect(host);
	init_timer(&host->timer);

	host->timer.function = hi_mci_detect_card;
	host->timer.data = (unsigned long)host;
	host->timer.expires = jiffies + detect_time;
	platform_set_drvdata(pdev, mmc);
	mmc_add_host(mmc);

	add_timer(&host->timer);

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		printk(KERN_ERR "no IRQ defined!\n");
		goto out;
	}

	init_waitqueue_head(&host->intr_wait);

	host->irq = irq;
	ret = request_irq(irq, hisd_irq, 0, DRIVER_NAME, host);
	if (ret) {
		printk(KERN_ERR "request_irq error!\n");
		goto out;
	}

	return 0;
out:
	if (host) {
		if (host->base)
			iounmap(host->base);

		if (host->dma_vaddr)
			dma_free_coherent(&pdev->dev, PAGE_SIZE,
					host->dma_vaddr, host->dma_paddr);
	}
	if (mmc)
		mmc_free_host(mmc);

	return ret;
}
Esempio n. 9
0
static int hi_mci_exec_cmd(struct himci_host *host, struct mmc_command *cmd,
		struct mmc_data *data)
{
	union cmd_arg_s  cmd_regs;

	himci_trace(2, "begin");
	himci_assert(host);
	himci_assert(cmd);

	host->cmd = cmd;

	himci_writel(cmd->arg, host->base + MCI_CMDARG);

	cmd_regs.cmd_arg = himci_readl(host->base + MCI_CMD);
	if (data) {
		cmd_regs.bits.data_transfer_expected = 1;
		if (data->flags & (MMC_DATA_WRITE | MMC_DATA_READ))
			cmd_regs.bits.transfer_mode = 0;

		if (data->flags & MMC_DATA_STREAM)
			cmd_regs.bits.transfer_mode = 1;

		if (data->flags & MMC_DATA_WRITE)
			cmd_regs.bits.read_write = 1;
		else if (data->flags & MMC_DATA_READ)
			cmd_regs.bits.read_write = 0;
	} else {
		cmd_regs.bits.data_transfer_expected = 0;
		cmd_regs.bits.transfer_mode = 0;
		cmd_regs.bits.read_write = 0;
	}

	if (cmd == host->mrq->stop) {
		cmd_regs.bits.stop_abort_cmd = 1;
		cmd_regs.bits.wait_prvdata_complete = 0;
	} else {
		cmd_regs.bits.stop_abort_cmd = 0;
		cmd_regs.bits.wait_prvdata_complete = 1;
	}

	switch (mmc_resp_type(cmd)) {
	case MMC_RSP_NONE:
		cmd_regs.bits.response_expect = 0;
		cmd_regs.bits.response_length = 0;
		cmd_regs.bits.check_response_crc = 0;
		break;
	case MMC_RSP_R1:
	case MMC_RSP_R1B:
		cmd_regs.bits.response_expect = 1;
		cmd_regs.bits.response_length = 0;
		cmd_regs.bits.check_response_crc = 1;
		break;
	case MMC_RSP_R2:
		cmd_regs.bits.response_expect = 1;
		cmd_regs.bits.response_length = 1;
		cmd_regs.bits.check_response_crc = 1;
		break;
	case MMC_RSP_R3:
		cmd_regs.bits.response_expect = 1;
		cmd_regs.bits.response_length = 0;
		cmd_regs.bits.check_response_crc = 0;
		break;
	default:
		himci_error("hi_mci: unhandled response type %02x\n",
				mmc_resp_type(cmd));
		return -EINVAL;
	}

	himci_trace(3, "send cmd of card is cmd->opcode = %d ", cmd->opcode);
	if (cmd->opcode == MMC_GO_IDLE_STATE)
		cmd_regs.bits.send_initialization = 1;
	else
		cmd_regs.bits.send_initialization = 0;

	cmd_regs.bits.card_number = 0;
	cmd_regs.bits.cmd_index = cmd->opcode;
	cmd_regs.bits.send_auto_stop = 0;
	cmd_regs.bits.start_cmd = 1;
	cmd_regs.bits.update_clk_reg_only = 0;
	himci_writel(cmd_regs.cmd_arg, host->base + MCI_CMD);

	if (hi_mci_wait_cmd(host) != 0) {
		himci_trace(3, "send card cmd is failed!");
		return -EINVAL;
	}
	return 0;
}
Esempio n. 10
0
static int hi_mci_setup_data(struct himci_host *host, struct mmc_data *data)
{
	unsigned int sg_phyaddr, sg_length;
	unsigned int i, ret = 0;
	unsigned int data_size;
	unsigned int max_des, des_cnt;
	struct himci_des *des;

	himci_trace(2, "begin");
	himci_assert(host);
	himci_assert(data);

	host->data = data;

	if (data->flags & MMC_DATA_READ)
		host->dma_dir = DMA_FROM_DEVICE;
	else
		host->dma_dir = DMA_TO_DEVICE;

	host->dma_sg = data->sg;
	host->dma_sg_num = dma_map_sg(mmc_dev(host->mmc),
			data->sg, data->sg_len, host->dma_dir);
	himci_assert(host->dma_sg_num);
	himci_trace(2, "host->dma_sg_num is %d\n", host->dma_sg_num);

	data_size = data->blksz * data->blocks;
	if (data_size > (DMA_BUFFER * MAX_DMA_DES)) {
		himci_error("mci request data_size is too big!\n");
		ret = -1;
		goto out;
	}

	himci_trace(2, "host->dma_paddr is 0x%08X,host->dma_vaddr is 0x%08X\n",
			(unsigned int)host->dma_paddr,
			(unsigned int)host->dma_vaddr);

	max_des = (PAGE_SIZE/sizeof(struct himci_des));
	des = (struct himci_des *)host->dma_vaddr;
	des_cnt = 0;

	for (i = 0; i < host->dma_sg_num; i++) {
		sg_length = sg_dma_len(&data->sg[i]);
		sg_phyaddr = sg_dma_address(&data->sg[i]);
		himci_trace(2, "sg[%d] sg_length is 0x%08X, "
				"sg_phyaddr is 0x%08X\n",
				i, (unsigned int)sg_length,
				(unsigned int)sg_phyaddr);
		while (sg_length) {
			des[des_cnt].idmac_des_ctrl = DMA_DES_OWN
				| DMA_DES_NEXT_DES;
			des[des_cnt].idmac_des_buf_addr = sg_phyaddr;
			/* idmac_des_next_addr is paddr for dma */
			des[des_cnt].idmac_des_next_addr = host->dma_paddr
				+ (des_cnt + 1) * sizeof(struct himci_des);

			if (sg_length >= 0x1F00) {
				des[des_cnt].idmac_des_buf_size = 0x1F00;
				sg_length -= 0x1F00;
				sg_phyaddr += 0x1F00;
			} else {
				/* FIXME:data alignment */
				des[des_cnt].idmac_des_buf_size = sg_length;
				sg_length = 0;
			}

			himci_trace(2, "des[%d] vaddr  is 0x%08X", i,
					(unsigned int)&des[i]);
			himci_trace(2, "des[%d].idmac_des_ctrl is 0x%08X",
			       i, (unsigned int)des[i].idmac_des_ctrl);
			himci_trace(2, "des[%d].idmac_des_buf_size is 0x%08X",
				i, (unsigned int)des[i].idmac_des_buf_size);
			himci_trace(2, "des[%d].idmac_des_buf_addr 0x%08X",
				i, (unsigned int)des[i].idmac_des_buf_addr);
			himci_trace(2, "des[%d].idmac_des_next_addr is 0x%08X",
				i, (unsigned int)des[i].idmac_des_next_addr);
			des_cnt++;
		}

		himci_assert(des_cnt < max_des);
	}
	des[0].idmac_des_ctrl |= DMA_DES_FIRST_DES;
	des[des_cnt - 1].idmac_des_ctrl |= DMA_DES_LAST_DES;
	des[des_cnt - 1].idmac_des_next_addr = 0;
out:
	return ret;
}
Esempio n. 11
0
static int __devinit hi_mci_probe(struct platform_device *pdev)
{
	struct mshci_host *ms_host = NULL;
	struct himci_host *hi_host = NULL;
	struct hisik3_mmc_platform_data *plat = NULL;
	struct resource *memres = NULL;


	int ret = 0, irq;
	int err;
	bool RetVal = 0;
	unsigned long flags;
	unsigned int sdcard_frequency = 0;



    #ifdef CONFIG_MACH_HI6620OEM
    if(1 == pdev->id)
    {
        raw_mmc_turn_on();
    }
    #endif

	himci_trace(HIMCI_TRACE_GEN_API, "++");

	himci_assert(pdev);

	plat = pdev->dev.platform_data;

	himci_trace(HIMCI_TRACE_SIGNIFICANT, "id:%d", pdev->id);

    /*通过读取硬件配置项,或者sdcard时钟配置,只需要SD卡流程走,走一遍*/
    #ifdef CONFIG_MACH_HI6620OEM

    if(1 == pdev->id)
    {
        RetVal = get_hw_config_int("sd_card/sdcard_frequency", &sdcard_frequency, NULL);

    	printk("hsad: sd_card/sdcard_frequency = %d, RetVal = %d\n", sdcard_frequency, RetVal);

        /*读取失败,配置默认值*/
    	if (RetVal == false) {
            printk(KERN_ERR "get board type failed.\n");
            g_sdcard_frequency = 90;
    	}

        /*如果获取配置值异常,则配置默认值*/
    	if ((sdcard_frequency != 100)&&(sdcard_frequency != 90)) {
            printk(KERN_ERR "sdcard_frequency %x is error.\n",sdcard_frequency);
            g_sdcard_frequency = 90;
    	}

    	g_sdcard_frequency = sdcard_frequency;
	}

    #endif

	/* 获取自己定义的数据 */
	if (!plat) {
		himci_error("Platform data not available");
		return -ENOENT;
	}
	if(0 == pdev->id)
	{
	     sema_init(&sem_to_rfile_sync_req,0);
	}

    /*创建硬件信号量IPC_SEM_EMMC*/
    if (0 == pdev->id) {
        mutex_lock(&emmc_mutex);
        emmc_sem_flag = 1;
        mutex_unlock(&emmc_mutex);
    }

	irq = platform_get_irq(pdev, 0);
	memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	if ((!irq) || (!memres)) {
		himci_error("resource error");
		ret = -ENOENT;
        goto err_resource_get;
	}

	himci_trace(HIMCI_TRACE_SIGNIFICANT, "irq:%d,start:0x%x,size:0x%x", irq, \
										memres->start, resource_size(memres));

	ms_host = mshci_alloc_host(&pdev->dev, sizeof(struct himci_host));
	if (IS_ERR(ms_host)) {
		himci_error("mshci_alloc_host() failed\n");
		ret = PTR_ERR(ms_host);
        goto err_resource_get;
	}

	hi_host = mshci_priv(ms_host);
	hi_host->ms_host = ms_host;
	hi_host->pdev = pdev;
	hi_host->dev = &pdev->dev;
	hi_host->plat = plat;


	platform_set_drvdata(pdev, ms_host);

	/* MMC IP rstdis */
	if (plat->rstdis_mmc){
        ret = plat->rstdis_mmc();
        if ( ret < 0 ){
	        goto err_resource_get;
	    }
	}

    /* set emmc clk */

	hi_host->pclk = clk_get(&pdev->dev, plat->clk_mmc_low); /* work clk */

	if (IS_ERR(hi_host->pclk)) {
		himci_error("clk_get clk_mmc_low fail!");
		ret = PTR_ERR(hi_host->pclk);
		goto err_io_clk;
	}
	hi_host->clk_mmc_high= clk_get(&pdev->dev, plat->clk_mmc_high); /* highclk used for tuning */

    if (IS_ERR(hi_host->clk_mmc_high)) {
		himci_error("clk_get clk_mmc_high fail!");
		ret = PTR_ERR(hi_host->clk_mmc_high);
		goto err_io_clk;
	}

    ms_host->pclk = NULL;
    ms_host->clk_ref_counter = CLK_DISABLED;
    ms_host->clk_mmc_high = NULL;

	ms_host->pclk = hi_host->pclk;
	ms_host->clk_mmc_high = hi_host->clk_mmc_high;

	if (ret) {
	    himci_error("failed to clk_set_rate");
	}

    if(ms_host->clk_ref_counter == CLK_DISABLED){
        ret = clk_enable(hi_host->pclk);
        ms_host->clk_ref_counter = CLK_ENABLED;
        if (ret) {
            himci_error("clk_enable failed");
            ret = -ENOENT;
            goto err_clk_ops;
        }
    }



	ms_host->ioaddr = ioremap_nocache(memres->start, resource_size(memres));
	if (!ms_host->ioaddr) {
		himci_error("ioremap_nocache failed");
		ret = -ENXIO;
		goto err_req_regs;
	}

	ms_host->hw_name = "hisi_hi6620_mmc";
	ms_host->hw_mmc_id = hi_host->pdev->id;
	ms_host->ops = &mshci_hi_ops;
	ms_host->quirks = 0;
	ms_host->irq = irq;

	/* Setup quirks for the controller */

	if (plat->quirks) {
		ms_host->quirks |= plat->quirks;
	}

	if (plat->caps & MMC_CAP_CLOCK_GATING) {
		/* there is no reason not to use interral clock gating */
		ms_host->mmc->caps |= plat->caps;
		ms_host->mmc->caps |= MMC_CAP_CLOCK_GATING;
		ms_host->clock_gate = 1;
    } else {
		ms_host->mmc->caps |= plat->caps;
		ms_host->clock_gate = 0;
	}

	ms_host->mmc->caps2 = plat->caps2;

	/* sandisk card need clock longer than spec ask */
	/* sdcard also disable ip clock gate c00261379*/
	if (ms_host->hw_mmc_id == 0 || ms_host->hw_mmc_id == 1)
		ms_host->clock_gate = 0;

	if (plat->ocr_mask)
		ms_host->mmc->ocr_avail |= plat->ocr_mask;


    #ifdef CONFIG_MACH_HI6620OEM
    if (plat->iomux_name){
        hi_host->piomux_block = iomux_get_block(plat->iomux_name);
	    hi_host->pblock_config = iomux_get_blockconfig(plat->iomux_name);
    }

    /* todo requlator */
	if (plat->reg_name_ldo) {
		himci_trace(HIMCI_TRACE_SIGNIFICANT, "devname : %s, regname: %s",
					dev_name(hi_host->dev), plat->reg_name_ldo);
		hi_host->vcc_ldo = regulator_get(hi_host->dev, plat->reg_name_ldo);
		if (!IS_ERR(hi_host->vcc_ldo)) {
			/*
			 * Setup a notifier block to update this if another device
			 * causes the voltage to change
			 */
			hi_host->nb.notifier_call = &mshci_hi_disable_voltage;
			ret = regulator_register_notifier(hi_host->vcc_ldo, &hi_host->nb);
			if (ret) {
				dev_err(&pdev->dev,
					"regulator notifier request failed\n");
			}
		} else {
			dev_err(&pdev->dev, "regulator_get() failed\n");
			hi_host->vcc_ldo = NULL;
		}
	}

	if (plat->reg_name_lvs) {
		himci_trace(HIMCI_TRACE_SIGNIFICANT, "devname : %s, regname: %s",
					dev_name(hi_host->dev), plat->reg_name_lvs);
		hi_host->vcc_lvs = regulator_get(hi_host->dev, plat->reg_name_lvs);
		if (!IS_ERR(hi_host->vcc_lvs)) {
			/*
			 * Setup a notifier block to update this if another device
			 * causes the voltage to change
			 */
			hi_host->nb.notifier_call = &mshci_hi_disable_voltage;
			ret = regulator_register_notifier(hi_host->vcc_lvs, &hi_host->nb);
			if (ret) {
				dev_err(&pdev->dev,
					"regulator notifier request failed\n");
			}
		} else {
			dev_err(&pdev->dev, "regulator_get() failed\n");
			hi_host->vcc_lvs = NULL;
		}
	}
	hi_host->ocp_flag = 0;

	if (plat->signal_reg_name) {
		himci_trace(HIMCI_TRACE_SIGNIFICANT, "devname : %s, signal regname: %s",
						dev_name(hi_host->dev), plat->signal_reg_name);
		hi_host->signal_vcc = regulator_get(hi_host->dev, plat->signal_reg_name);
		if (IS_ERR(hi_host->signal_vcc)) {
			dev_err(&pdev->dev, "regulator_get() failed\n");
			hi_host->signal_vcc = NULL;
		}
	}
    #endif

	if( (1 == pdev->id)&&( (ms_host->quirks & MSHCI_QUIRK_CBP_DETECTION) == 0)) {
		ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, LOWPOWER);
		if (ret) {
			himci_error("failed to blockmux_set");
		}
		mshci_sd_lowpower();
		if (hi_host->vcc_lvs){
			ret = regulator_enable(hi_host->vcc_lvs);
			if (ret) {
				himci_error("failed to regulator_enable LDO7");
			}
			ret = regulator_disable(hi_host->vcc_lvs);
			if (ret) {
			himci_error("failed to regulator_disable LDO7");
			}
		}
		udelay(30);
		if (hi_host->signal_vcc){
			ret = regulator_enable(hi_host->signal_vcc);
			if (ret) {
				himci_error("failed to regulator_enable LDO22");
			}
			ret = regulator_disable(hi_host->signal_vcc);
			if (ret) {
				himci_error("failed to regulator_disable LDO22");
			}
		}
	}else {/*for cbp*/
		ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, NORMAL);
		if (ret) {
			himci_error("failed to blockmux_set");
		}

		if (hi_host->vcc_lvs){
			ret = regulator_enable(hi_host->vcc_lvs);
			if (ret) {
				himci_error("failed to regulator_enable LDO7");
			}
		}
		udelay(30);
		if (hi_host->signal_vcc){
			ret = regulator_enable(hi_host->signal_vcc);
			if (ret) {
				himci_error("failed to regulator_enable LDO22");
			}

			ret = regulator_disable(hi_host->signal_vcc);
			if (ret) {
				himci_error("failed to regulator_disable LDO22");
			}
		}
	}

	hi_host->old_sig_voltage = plat->default_signal_voltage;
	hi_host->old_timing = MMC_TIMING_UHS_DDR50;
	hi_host->timing_config = plat->timing_config;
	hi_host->allow_switch_signal_voltage = plat->allow_switch_signal_voltage;
	hi_host->suspend_timing_config = plat->suspend_timing_config;

	if (ms_host->quirks & MSHCI_QUIRK_WLAN_DETECTION) {
		ms_host->flags |= MSHCI_DEVICE_DEAD;
		ms_host->flags |= MMC_PM_KEEP_POWER;
		ms_host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
	}

	ret = mshci_add_host(ms_host);
	if (ret) {
		dev_err(&pdev->dev, "mshci_add_host() failed\n");
		goto err_add_host;
	}

	if (ms_host->quirks & MSHCI_QUIRK_WLAN_DETECTION) {
		ms_host->flags |= MSHCI_DEVICE_DEAD;
	        ms_host->flags |= MMC_PM_KEEP_POWER;
	        ms_host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
		if (plat->ext_cd_init)
			plat->ext_cd_init(&mshci_hi_notify_change);
		plat->set_power = mshci_hi_sdio_set_power;
	}

	if( (1 == pdev->id)&&( (ms_host->quirks & MSHCI_QUIRK_CBP_DETECTION) != 0)) {
	        ms_host->flags |= MMC_PM_KEEP_POWER;
	        ms_host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
	}


	if (ms_host->quirks & MSHCI_QUIRK_EXTERNAL_CARD_DETECTION) {

		err = gpio_request_one(plat->cd_gpio, GPIOF_IN, "ESDHC_CD");
		if (err) {
			dev_warn(mmc_dev(ms_host->mmc),
				"no card-detect pin available!\n");
			goto no_card_detect_pin;
		}
		/*SD_INT_FIX_suspend DTS:2013082704916 modifier: y00241633*/
		err = request_irq(gpio_to_irq(plat->cd_gpio), mshci_hi_card_detect_gpio,
				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
				 mmc_hostname(ms_host->mmc), ms_host);
		if (err) {
			dev_warn(mmc_dev(ms_host->mmc), "request gpio irq error\n");
			goto no_card_detect_irq;
		}

        if ( plat->sw_gpio ){
            /* only sft has this gpio */
		    err = gpio_request_one(plat->sw_gpio, 0, "ESDHC_POWER_SWITCH");
		    if (err) {
			    dev_warn(mmc_dev(ms_host->mmc),
				    "no card-power-switch pin available!\n");
			    goto no_card_power_switch_pin;
		    }

            /*控制I/O口电平 1V8 or 3V3*/
            gpio_direction_output(plat->sw_gpio, 1);
        }

	}

	return 0;

no_card_power_switch_pin:
	plat->sw_gpio = err;
no_card_detect_irq:
	gpio_free(plat->cd_gpio);
no_card_detect_pin:
	plat->cd_gpio = err;
err_add_host:
	iounmap(ms_host->ioaddr);
	ms_host->ioaddr = NULL;
err_req_regs:
	spin_lock_irqsave(&ms_host->lock, flags);
	if(ms_host->clk_ref_counter == CLK_ENABLED){
		clk_disable(hi_host->pclk);
		ms_host->clk_ref_counter = CLK_DISABLED;
	}
	spin_unlock_irqrestore(&ms_host->lock, flags);
err_clk_ops:
    clk_put(hi_host->clk_mmc_high);
	clk_put(hi_host->pclk);
err_io_clk:
	mshci_free_host(ms_host);

err_resource_get:

	return ret;
}
Esempio n. 12
0
static int mshci_hi_start_signal_voltage_switch(struct mshci_host *ms_host,
				struct mmc_ios *ios)
{
#if 1
	struct himci_host *hi_host = (struct himci_host *)(ms_host->private);




if (ms_host->quirks & MSHCI_QUIRK_EXTERNAL_CARD_DETECTION) {

	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "++");

	himci_assert(ios);
	himci_assert(hi_host);

	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "old_sig_voltage = %d ",
					hi_host->old_sig_voltage);
	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "new_sig_voltage = %d ",
					ios->signal_voltage);
	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "allow_switch_signal_voltage = %d ",
					hi_host->allow_switch_signal_voltage);

	if (hi_host->allow_switch_signal_voltage &&
		(hi_host->old_sig_voltage != ios->signal_voltage)) {
		switch (ios->signal_voltage) {
		case MMC_SIGNAL_VOLTAGE_330:
#ifdef CONFIG_MACH_HI6620OEM

		printk("yuandan 330 \n");

		hi_host->old_sig_voltage = ios->signal_voltage;

		/*
		3.3V IO 设置
 		LDO7   2.85V
 		LDO22  1.425V
 		*/
		if(ms_host->quirks & MSHCI_QUIRK_EXTERNAL_CARD_DETECTION){
			pmussi_reg_write(SOC_SMART_LDO7_REG_ADJ_ADDR(0),SDMMC_3V3_IO_LDO7_SSI_VALUE);
			pmussi_reg_write(SOC_SMART_ENABLE4_ADDR(0),BIT(SOC_SMART_ENABLE4_en_ldo22_int_START));
		}
		sd_ldo22_need_control = 0;

#endif
			break;
		case MMC_SIGNAL_VOLTAGE_180:
#ifdef CONFIG_MACH_HI6620OEM
		printk("yuandan 180 \n");

		hi_host->old_sig_voltage = ios->signal_voltage;

		/*
		1.8V IO 设置
 		LDO7   1.8V
 		LDO22  0V
 		*/
 		if(ms_host->quirks & MSHCI_QUIRK_EXTERNAL_CARD_DETECTION){
 			pmussi_reg_write(SOC_SMART_LDO7_REG_ADJ_ADDR(0),SDMMC_1V8_IO_LDO7_SSI_VALUE);
			udelay(30);
			pmussi_reg_write(SOC_SMART_DR1_ISET_ADDR(0), SDMMC_DR1_ISET_SSI_VALUE);/* DR1 current control */
			pmussi_reg_write(SOC_SMART_DR2_ISET_ADDR(0), SDMMC_DR2_ISET_SSI_VALUE);/* DR2 current control */
			pmussi_reg_write(SOC_SMART_DR_BRE_CTRL_ADDR(0), SDMMC_DR_CONTROL_SSI_VALUE);/* Turn on DR1 DR2 */
			pmussi_reg_write(SOC_SMART_DISABLE4_ADDR(0),BIT(SOC_SMART_DISABLE4_dis_ldo22_int_START));
		}

		sd_ldo22_need_control = 1;
#endif
			break;

		case MMC_SIGNAL_VOLTAGE_120:
			/* FIXME */
			/* 1.20v is not support */
			himci_error("1.20V is not supported");
			break;
		default:
			himci_error("unknown signal voltage");
			break;
		}
	}

	hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "--");

}
#endif

	return 0;
}
Esempio n. 13
0
void mshci_hi_set_ios(struct mshci_host *ms_host, struct mmc_ios *ios)
{
	struct himci_host * hi_host = (struct himci_host *)(ms_host->private);
	int ret = -1;
	int cbp_flag = 0;

	hi_host_trace(HIMCI_TRACE_GEN_API, "++");

	himci_assert(ios);
	himci_assert(hi_host);

	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->power_mode = %d ", ios->power_mode);
	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->clock = %d ", ios->clock);
	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->bus_width = %d ", ios->bus_width);
	hi_host_trace(HIMCI_TRACE_GEN_INFO, "ios->timing = %d ", ios->timing);

	ret = get_hw_config_int("modem/viacbp82d", &cbp_flag, NULL);
	if ((!ret) || (0 == cbp_flag)) {
		pr_info("%s has no cbp support\n", __func__);
	}

	pr_info("%s mode %d\n", __func__, ios->power_mode);

	/* process power */
	if (hi_host->old_power_mode != ios->power_mode) {
		switch (ios->power_mode) {
		case MMC_POWER_OFF:
			if ((!cbp_flag)&&(1 == ms_host->hw_mmc_id)){
				mshci_sd_power_onoff(ms_host, 0);
				break;
			}
			hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "set io to lowpower");
			if (hi_host->piomux_block && hi_host->pblock_config){
				ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, LOWPOWER);
					if (ret) {
						himci_error("failed to blockmux_set");
					}
			}

			if (hi_host->vcc_lvs){
				ret = regulator_disable(hi_host->vcc_lvs);
				if (ret) {
					himci_error("failed to regulator_enable");
				}
			}

			if (hi_host->vcc_ldo){
				ret = regulator_disable(hi_host->vcc_ldo);
				if (ret) {
					himci_error("failed to regulator_enable");
				}
			}
			break;
		case MMC_POWER_UP:

			hi_host_trace(HIMCI_TRACE_SIGNIFICANT, "set io to normal");
			if ((!cbp_flag)&&(1 == ms_host->hw_mmc_id)){
				mshci_sd_power_onoff(ms_host, 1);
				break;
			}
			if (hi_host->vcc_ldo){
				ret = regulator_enable(hi_host->vcc_ldo);
				if (ret) {
					himci_error("failed to regulator_enable");
				}
			}
			if((1 == hi_host->ms_host->hw_mmc_id)&&(cbp_flag)){
				/*cbp need set as fixed 1.8v*/
				himci_error("sdio regulator_set_voltage 1.8 \n");
				if (hi_host->vcc_lvs) {
					ret = regulator_set_voltage(hi_host->vcc_lvs, SDMMC_1V8_IO_LDO7_180, SDMMC_1V8_IO_LDO7_180);
					if (ret != 0) {
						himci_error("failed to LDO7 regulator_set_voltage 1.8 \n");
					}
				}
			}
            if (hi_host->vcc_lvs){
                    ret = regulator_enable(hi_host->vcc_lvs);
                if (ret) {
                    himci_error("failed to regulator_enable");
                }
            }
            

            if (hi_host->piomux_block && hi_host->pblock_config){
                ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, NORMAL);
                if (ret) {
                    himci_error("failed to blockmux_set");
                }
            }
			break;
		case MMC_POWER_ON:
			break;
		default:
			himci_error("unknown power supply mode");
			break;
		}
		hi_host->old_power_mode = ios->power_mode;
	}

	hi_host_trace(HIMCI_TRACE_GEN_API, "--");
}
Esempio n. 14
0
/*NOT called by VIA*/
static void mshci_sd_power_onoff(struct mshci_host *ms_host,int ispowerup)
{
    struct himci_host * hi_host = (struct himci_host *)(ms_host->private);
    int ret = 0;

    if (sd_ldo22_need_control){/* during power-on or power-off,need to restore sd io if necessary  */       
		pmussi_reg_write(SOC_SMART_ENABLE4_ADDR(0),BIT(SOC_SMART_ENABLE4_en_ldo22_int_START));
		udelay(30);
		pmussi_reg_write(SOC_SMART_LDO7_REG_ADJ_ADDR(0),SDMMC_3V3_IO_LDO7_SSI_VALUE);
		sd_ldo22_need_control = 0;
    }
    if (ispowerup){

        udelay(30);
        if (hi_host->signal_vcc){
            ret = regulator_enable(hi_host->signal_vcc);
            if (ret) {
               himci_error("failed to regulator_enable");
            }
        }
        udelay(30);
        if (hi_host->vcc_lvs){
            ret = regulator_enable(hi_host->vcc_lvs);
            if (ret) {
               himci_error("failed to regulator_enable");
            }
        }

        if (hi_host->vcc_ldo) {
            ret = regulator_set_voltage(hi_host->vcc_ldo, SDMMC_SDCARD_285, SDMMC_SDCARD_285);
            if (ret != 0) {
                himci_error("failed to LDO10 regulator_set_voltage 2.85 \n");
            }
        }
        if (hi_host->vcc_ldo){
            ret = regulator_enable(hi_host->vcc_ldo);
            if (ret) {
                himci_error("failed to regulator_enable");
            }
        }
        ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, NORMAL);
		if (ret) {
		    himci_error("failed to blockmux_set");
		}
    }
    else{
        ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, LOWPOWER);
		if (ret) {
		    himci_error("failed to blockmux_set");
		}
        mshci_sd_lowpower();
		if (hi_host->vcc_ldo){
            ret = regulator_disable(hi_host->vcc_ldo);
            if (ret) {
                himci_error("failed to regulator_disable LDO10");
            }
        }
        if (hi_host->vcc_lvs){
            ret = regulator_disable(hi_host->vcc_lvs);
            if (ret) {
               himci_error("failed to regulator_disable LDO7");
            }
        }
        udelay(30);
        if (hi_host->signal_vcc){
            ret = regulator_disable(hi_host->signal_vcc);
            if (ret) {
               himci_error("failed to regulator_disable LDO22");
            }
        }
    }
}
Esempio n. 15
0
static int hi_mci_suspend(struct platform_device *dev, pm_message_t pm)
{

	struct mshci_host *ms_host = NULL;
	struct himci_host *hi_host = NULL;
	int ret = 0;
	unsigned long flags;
	int cbp_flag = 0;
	int cbp_ret = 0;

	ms_host = platform_get_drvdata(dev);
	if (!ms_host) {
		printk(KERN_ERR "get drvdata failed !\n");
		return -1;
	}
	hi_host = mshci_priv(ms_host);

    if(0 == hi_host->pdev->id)
    {
        g_ulmmc_suspend_flag = true;
        printk("hi_mci_suspend,set g_ulmmc_suspend_flag.");
    }

	cbp_ret = get_hw_config_int("modem/viacbp82d", &cbp_flag, NULL);
	if ((!cbp_ret) || (0 == cbp_flag)) {
		pr_info("%s has no cbp support\n", __func__);
	}

	if ((1 == hi_host->pdev->id)&&(cbp_flag)){
		if (ms_host->mmc->ios.power_mode != MMC_POWER_OFF) {
			pr_info("%s cbp ext suspend sdio\n", __func__);
			if (cbp_in_sdio_tras){
				pr_info("%s cbp_in_sdio_tras %d\n", __func__, cbp_in_sdio_tras);
				return -EAGAIN;
			}
			cbp_clock_enabled = 0;
			cbp_host_waked = 0;
			cbp_notifier_call_chain(0, NULL);

			ms_host->mmc->ios.power_mode = MMC_POWER_UP;
			ms_host->mmc->ios.clock = 0;
			ms_host->mmc->ops->set_ios(ms_host->mmc, &ms_host->mmc->ios);
		}
		ret = blockmux_set(hi_host->piomux_block, hi_host->pblock_config, LOWPOWER);
		if (ret) {
			himci_error("failed to blockmux_set");
		}
	}


	if (ms_host->quirks & MSHCI_QUIRK_WLAN_DETECTION) {
		/* sdio power off */
		if (ms_host->mmc->ios.power_mode != MMC_POWER_OFF) {
			ret = mmc_sdio_suspend_ext(ms_host->mmc);
			if (ret) {
				printk("%s, sdio suspend error\n", __func__);
				return ret;
			}

			ms_host->mmc->ios.power_mode = MMC_POWER_UP;
			hi_host->old_timing = 0;
			hi_host->old_sig_voltage = 0;
		}
	}

    /*sd and emmc share the same suspend and resume*/
    mshci_suspend_host(ms_host, pm);

	spin_lock_irqsave(&ms_host->lock, flags);
	if(ms_host->clk_ref_counter == CLK_ENABLED){
		clk_disable(hi_host->pclk);
		ms_host->clk_ref_counter = CLK_DISABLED;
	}
	spin_unlock_irqrestore(&ms_host->lock, flags);


	return 0;
}