[U-Boot] [PATCH v1 7/9] sunxi: mmc support

Ian Campbell ijc at hellion.org.uk
Sun Mar 16 21:38:38 CET 2014


On Fri, 2014-03-14 at 17:36 +0200, Pantelis Antoniou wrote:
> [...]

Thanks for your review. It seems there are still quite a few issues
dating back to the original allwinner dumps here.

@linux-sunxi: if anyone wants to volunteer to help cleanup this
particular driver I'd be very happy -- there's a lot of it!

> +
> > +static void dumpmmcreg(struct sunxi_mmc *reg)
> > +{
> > +	debug("dump mmc registers:\n");
> > +	debug("gctrl     0x%08x\n", reg->gctrl);
> > +	debug("clkcr     0x%08x\n", reg->clkcr);
> > +	debug("timeout   0x%08x\n", reg->timeout);
> > +	debug("width     0x%08x\n", reg->width);
> > +	debug("blksz     0x%08x\n", reg->blksz);
> [...] lots more debug(foo)
> > +}
> 
> ^^^ #ifdef DEBUG here?

I can if you prefer but debug() itself effectively includes the same
ifdef so the end result is already the same.

> [...]

> > +/* support 4 mmc hosts */
> > +struct mmc mmc_dev[4];
> > +struct sunxi_mmc_host mmc_host[4];
> > +
> 
> ^ hosts & mmc structs can be allocated even for SPL now

Can be or must be?

> > +	struct sunxi_mmc_host *mmchost = &mmc_host[sdc_no];
> > +	static struct sunxi_gpio *gpio_c =
> > +	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_C];
> > +	static struct sunxi_gpio *gpio_f =
> > +	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_F];
> > +#if CONFIG_MMC1_PG
> > +	static struct sunxi_gpio *gpio_g =
> > +	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_G];
> > +#endif
> > +	static struct sunxi_gpio *gpio_h =
> > +	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_H];
> > +	static struct sunxi_gpio *gpio_i =
> > +	    &((struct sunxi_gpio_reg *)SUNXI_PIO_BASE)->gpio_bank[SUNXI_GPIO_I];
> > +	struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> > +
> 
> ^ Castings are ugly; rework with a temporary variable.

Ack.

The static's here are odd too and date back to the original alwinner
code dumps. I'll get rid of them too.

> [...]
> > +	case 3:
> > +		/* PI4-CMD, PI5-CLK, PI6~9-D0~D3 : 2 */
> > +		writel(0x2222 << 16, &gpio_i->cfg[0]);
> > +		writel(0x22, &gpio_i->cfg[1]);
> > +		writel(0x555 << 8, &gpio_i->pull[0]);
> > +		writel(0x555 << 8, &gpio_i->drv[0]);
> > +		break;
> > +
> > +	default:
> > +		return -1;
> > +	}
> > +
> 
> Lots of magic constants. I have no idea what's going on here.
> Use a few defines.

Right. These came from the original allwinner dumps so I was worried
that they might be undocumented magic, but actually since the are gpio
frobbing I reckon I can figure them out.

> [...]> +	cmd = (0x1 << 31) | (0x1 << 21) | (0x1 << 13);
> > +	writel(cmd, &mmchost->reg->cmd);
> > +	while ((readl(&mmchost->reg->cmd) & (0x1 << 31)) && timeout--);
> > +	if (!timeout)
> > +		return -1;
> > +
> 
> ^ Eeek! Use udelay and a time based timeout. 

Ack.

> > +	writel(readl(&mmchost->reg->rint), &mmchost->reg->rint);
> > +
> 
> ^ Same here - Not even a timeout?

No loop here though?
[...]

> > +	rval |= (0x1 << 16);
> 
> #define ?

Ack

[...]
> Ambiguous formatting. Use { }

Ack

> [...]
> > +	/* Reset controller */
> > +	writel(0x7, &mmchost->reg->gctrl);
> > +
> 
> Magic value again.

The sum total of the docs for this one are:
	 * GCTRLREG
	 * GCTRL[2]     : DMA reset
	 * GCTRL[5]     : DMA enable

But I'll see what I can do.

[...]
> > +	} else {
> > +		buff = (unsigned int *)data->src;
> > +		for (i = 0; i < (byte_cnt >> 2); i++) {
> > +			while (--timeout &&
> > +				 (readl(&mmchost->reg->status) & (0x1 << 3)));
> > +			if (timeout <= 0)
> > +				goto out;
> > +			writel(buff[i], mmchost->database);
> > +			timeout = 0xfffff;
> > +		}
> > +	}
> > +
> 
> ^ Timeouts using time values? udelay? See above.

Ack.

> [....]
> > +	writel(rval, &mmchost->reg->idie);
> > +	writel((u32) pdes, &mmchost->reg->dlba);
> > +	writel((0x2 << 28) | (0x7 << 16) | (0x01 << 3),
> > +	       &mmchost->reg->ftrglevel);
> > +
> 
> ^ #define again?

Some of these (ftrgllevel) have no docs whatsoever, but I'll do what I
can.

> [...]

> > +	timeout = 0xfffff;
> > +	do {
> > +		status = readl(&mmchost->reg->rint);
> > +		if (!timeout-- || (status & 0xbfc2)) {
> > +			error = status & 0xbfc2;
> > +			debug("cmd timeout %x\n", error);
> > +			error = TIMEOUT;
> > +			goto out;
> > +		}
> 
> ^ Again timeouts without using time values.

I'm getting the picture ;-)

> [...]
> > +int sunxi_mmc_init(int sdc_no)
> > +{
> > +	struct mmc *mmc;
> > +
> > +	memset(&mmc_dev[sdc_no], 0, sizeof(struct mmc));
> > +	memset(&mmc_host[sdc_no], 0, sizeof(struct sunxi_mmc_host));
> > +	mmc = &mmc_dev[sdc_no];
> > +
> > +	sprintf(mmc->name, "SUNXI SD/MMC");
> > +	mmc->priv = &mmc_host[sdc_no];
> > +	mmc->send_cmd = mmc_send_cmd;
> > +	mmc->set_ios = mmc_set_ios;
> > +	mmc->init = mmc_core_init;
> > +
> > +	mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
> > +	mmc->host_caps = MMC_MODE_4BIT;
> > +	mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
> > +
> > +	mmc->f_min = 400000;
> > +	mmc->f_max = 52000000;
> > +
> > +	mmc_resource_init(sdc_no);
> > +	mmc_clk_io_on(sdc_no);
> > +
> > +	mmc_register(mmc);
> > +
> 
> ^ The mmc_registeration sequence has changed, but not landed at master yet.

Do you have a reference handy for this?

Thanks again, sorry this driver is such a mess (I must confess I didn't
look at it that closely when I cherry picked it).

Ian.



More information about the U-Boot mailing list