[PATCH 8/9] esdhc-4 esdhc: fsl esdhc driver based on platform sdhci api

Wolfram Sang w.sang at pengutronix.de
Tue Sep 7 06:28:17 EDT 2010


Hi Richard,

for easier reading, I removed the parts of the code we were not talking
about.

> > +static unsigned int sdhci_fsl_get_ro(struct sdhci_host *host) {
> > +	struct sdhci_fsl_host *fsl_host = sdhci_priv(host);
> > +
> > +	return fsl_host->pdata->wp_status(host->mmc->parent);
> > +}
> 
> Is there really no way to route the WP-GPIO to the SD_WP pin of the
> controller (sigh)? Still, I'd think we can be more abstract by using the
> gpiolib and just pass the gpio number in the platform-data?
> [<Zhu Richard-r65037>] Up to now, refer to the limitations of the HW
> design on the different boards, the WP-GPIO mechanism is used.
> About the more abstract method by passing the GPIO number in the
> platform-data.
> Do you means that just pass the GPIO number in the sdhci_pltfm_data
> defined in sdhci_pltfm_data.h file?

Yes, sdhci_pltfm.h would need such a member.

> I don't think we can do that, because the WP-GPIO pins maybe different
> refer to different boards.

Sure, the original information which GPIO the current board uses must
come from some kind of platform_data-struct special to the board in
question. The main thing I was after is that a gpio-number might be
enough for that, no need for a function pointer. The handling of that
GPIO could then be taken into sdhci-esdhc.c (should be generic, request
it and set it to input).

> > +
> > +static void sdhci_fsl_set_clock(struct sdhci_host *host, unsigned int
> 
> > +clock) {
> > +	/*This variable holds the value of clock divider, prescaler */
> > +	int div = 0, prescaler = 1;
> > +	int clk_rate = 0;
> > +	u32 clk;
> > +	unsigned long timeout;
> > +	struct sdhci_fsl_host *fsl_host = sdhci_priv(host);
> > +
> > +	if (clock == 0) {
> > +		host->clock = 0;
> > +		clk = readl(host->ioaddr + SDHCI_CLOCK_CONTROL);
> > +		writel(clk & (~FSL_SDHCI_CLOCK_HLK_EN),
> > +				host->ioaddr + SDHCI_CLOCK_CONTROL);
> > +		return;
> > +	}
> > +
> > +	clk_rate = clk_get_rate(fsl_host->clk_input);
> > +	clk = readl(host->ioaddr + SDHCI_CLOCK_CONTROL) &
> ~FSL_SDHCI_CLOCK_MASK;
> > +	/* precaler can't be set to zero in CLK_CTL reg */
> > +	clk |= (prescaler << 8);
> > +	writel(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
> > +
> > +	if (clock == sdhci_fsl_get_min_clock(host))
> > +		prescaler = 0x10;
> > +
> > +	while (prescaler <= 0x80) {
> > +		for (div = 0; div <= 0xF; div++) {
> > +			int x;
> > +			if (prescaler != 0)
> > +				x = (clk_rate / (div + 1)) / (prescaler
> * 2);
> > +			else
> > +				x = clk_rate / (div + 1);
> > +
> > +			dev_dbg(&fsl_host->pdev->dev, "x=%d, clock=%d
> %d\n",
> > +					x, clock, div);
> > +			if (x <= clock)
> > +				break;
> > +		}
> > +		if (div < 0x10)
> > +			break;
> > +
> > +		prescaler <<= 1;
> > +	}
> > +	dev_dbg(&fsl_host->pdev->dev, "prescaler = 0x%x, divider =
> 0x%x\n",
> > +			prescaler, div);
> > +	clk |= (prescaler << 8) | (div << 4);
> > +
> > +	/* Configure the clock control register */
> > +	clk |= readl(host->ioaddr + SDHCI_CLOCK_CONTROL)
> > +		& (~FSL_SDHCI_CLOCK_MASK);
> > +	clk |= FSL_SDHCI_CLOCK_HLK_EN;
> > +	writel(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
> > +
> > +	/* Wait max 10 ms */
> > +	timeout = 5000;
> > +	while (timeout > 0) {
> > +		timeout--;
> > +		udelay(20);
> > +	}
> > +	writel(clk | FSL_SDHCI_CLOCK_SD_EN, host->ioaddr + 
> > +SDHCI_CLOCK_CONTROL);
> > +
> > +	host->clock = (clk_rate / (div + 1)) / (prescaler * 2); }
> 
> Do you know if there is an improvement over the set_clock-routine in
> sdhic-of-esdhc.c?
> [<Zhu Richard-r65037>] Accepted.

Does that mean there is one or there is none? :)

> > +
> > +static void sdhci_fsl_set_bus(struct sdhci_host *host, unsigned int 
> > +bus_width) {
> > +	u32 ctrl;
> > +
> > +	ctrl = readl(host->ioaddr + SDHCI_HOST_CONTROL);
> > +
> > +	if (bus_width == MMC_BUS_WIDTH_4) {
> > +		ctrl &= ~FSL_SDHCI_CTRL_8BITBUS;
> > +		ctrl |= SDHCI_CTRL_4BITBUS;
> > +	} else if (bus_width == MMC_BUS_WIDTH_8) {
> > +		ctrl &= ~SDHCI_CTRL_4BITBUS;
> > +		ctrl |= FSL_SDHCI_CTRL_8BITBUS;
> > +	} else if (bus_width == MMC_BUS_WIDTH_1) {
> > +		ctrl &= ~SDHCI_CTRL_4BITBUS;
> > +		ctrl &= ~FSL_SDHCI_CTRL_8BITBUS;
> > +	}
> 
> I'd be careful with the 8Bit-mode for now. We need some to deal with it
> correctly in sdhci.c first.
> [<Zhu Richard-r65037>] Are there some problems in the 8bits bus_width in
> sdhci.c file?
> I find that the sdhci.c had been support the 8bits bus_width.

Yes, it was added recently, but it might have issues. See here:

http://thread.gmane.org/gmane.linux.kernel.mmc/3370

> > +	host->quirks = SDHCI_QUIRK_BROKEN_ADMA
> 
> Why did you add all the DMA-stuff and mark it as broken then?
> Is there a problem with the engine?
> [<Zhu Richard-r65037>] The ADMA is broken, and I still can't find the
> root cause.
> I would enable the ADMA feature later.
> Up to now, the Simple DMA and PIO mode are enabled.

Ok, thanks. Better to leave all ADMA stuff out for now, then.

Did you have the chance to test/review my RFC yet?

Kind regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100907/b3731b9d/attachment-0001.sig>


More information about the linux-arm-kernel mailing list