From: Pierre Ossman <drzeus-list@drzeus.cx>
To: Anderson Briglia <anderson.briglia@indt.org.br>
Cc: linux-kernel@vger.kernel.org,
Russell King - ARM Linux <linux@arm.linux.org.uk>,
Tony Lindgren <tony@atomide.com>
Subject: Re: [patch 1/5] MMC OMAP driver
Date: Tue, 31 Jan 2006 16:29:27 +0100 [thread overview]
Message-ID: <43DF8257.6040707@drzeus.cx> (raw)
In-Reply-To: <43DF6750.1060505@indt.org.br>
Anderson Briglia wrote:
> Adds OMAP MMC driver.
>
> Signed-off-by: Juha Yrjölä <juha.yrjola@nokia.com>
> Signed-off-by: Tony Lindgren <tony@atomide.com>
>
> +
> + /* Our hardware needs to know exact type */
> + switch (cmd->flags & MMC_RSP_MASK) {
> + case MMC_RSP_NONE:
> + /* resp 0 */
> + break;
> + case MMC_RSP_SHORT:
> + /* resp 1, resp 1b */
> + /* OR resp 3!! (assume this if bus is set opendrain) */
> + if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
> + resptype = 3;
> + else
> + resptype = 1;
> + break;
> + case MMC_RSP_LONG:
> + /* resp 2 */
> + resptype = 2;
> + break;
> + }
Don't do this. If you cannot figure out how the hardware handles the
different types then at least have a simple switch statement over the
types (and of course a failure case for unknown types). Don't try to
deduce the correct mode based on things that aren't strictly related.
> +
> + /* Any data transfer means adtc type (but that information is not
> + * in command structure, so we flagged it into host struct.)
> + * However, telling bc, bcr and ac apart based on response is
> + * not foolproof:
> + * CMD0 = bc = resp0 CMD15 = ac = resp0
> + * CMD2 = bcr = resp2 CMD10 = ac = resp2
> + *
> + * Resolve to best guess with some exception testing:
> + * resp0 -> bc, except CMD15 = ac
> + * rest are ac, except if opendrain
> + */
> + if (host->data) {
> + cmdtype = OMAP_MMC_CMDTYPE_ADTC;
> + } else if (resptype == 0 && cmd->opcode != 15) {
> + cmdtype = OMAP_MMC_CMDTYPE_BC;
> + } else if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) {
> + cmdtype = OMAP_MMC_CMDTYPE_BCR;
> + } else {
> + cmdtype = OMAP_MMC_CMDTYPE_AC;
> + }
Same thing here. If you need the command types then extend the MMC layer
to include those. It's not like it's some closed proprietary black box. :)
> +/* PIO only */
> +static void
> +mmc_omap_sg_to_buf(struct mmc_omap_host *host)
> +{
> + struct scatterlist *sg;
> +
> + sg = host->data->sg + host->sg_idx;
> + host->buffer_bytes_left = sg->length;
> + host->buffer = page_address(sg->page) + sg->offset;
> + if (host->buffer_bytes_left > host->total_bytes_left)
> + host->buffer_bytes_left = host->total_bytes_left;
> +}
> +
Just so you know, this isn't highmem safe. Perhaps that will never be an
issue on OMAP, but still. The solution is not obvious, but it's being
discussed under the thread named "How to map high memory for block io".
> +static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs)
> +{
> + struct mmc_omap_host * host = (struct mmc_omap_host *)dev_id;
> + u16 status;
> + int end_command;
> + int end_transfer;
> + int transfer_error;
> +
> + if (host->cmd == NULL && host->data == NULL) {
> + status = OMAP_MMC_READ(host->base, STAT);
> + printk(KERN_INFO "MMC%d: Spurious interrupt 0x%04x\n", host->id, status);
> + if (status != 0) {
> + OMAP_MMC_WRITE(host->base, STAT, status);
> + OMAP_MMC_WRITE(host->base, IE, 0);
> + }
> + return IRQ_HANDLED;
> + }
> +
Why don't you let the kernel handle spurious interrupts? You sure that
OMAP will never get the ability to share the MMC interrupt with
something else? :)
> + if (status & OMAP_MMC_STAT_CMD_TOUT) {
> + /* Timeouts are routine with some commands */
> + if (host->cmd) {
> + if (host->cmd->opcode != MMC_ALL_SEND_CID &&
> + host->cmd->opcode != MMC_SEND_OP_COND &&
> + host->cmd->opcode != MMC_APP_CMD &&
> + !mmc_omap_cover_is_open(host))
> + printk(KERN_ERR "MMC%d: Command timeout, CMD%d\n",
> + host->id, host->cmd->opcode);
> + host->cmd->error |= MMC_ERR_TIMEOUT;
> + end_command = 1;
> + }
> + }
Bad! This is a text book example of something that should be done in the
MMC layer, not the drivers. Same thing for the other error messages.
> + if (status & OMAP_MMC_STAT_CARD_ERR) {
> + if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) {
> + u32 response = OMAP_MMC_READ(host->base, RSP6)
> + | (OMAP_MMC_READ(host->base, RSP7) << 16);
> + /* STOP sometimes sets must-ignore bits */
> + if (!(response & (R1_CC_ERROR
> + | R1_ILLEGAL_COMMAND
> + | R1_COM_CRC_ERROR))) {
> + end_command = 1;
> + continue;
> + }
> + }
Are you sure this only happens for MMC_STOP_TRANSMISSION or for any stop
command?
> +static inline int is_broken_card(struct mmc_card *card)
> +{
> + int i;
> + struct mmc_cid *c = &card->cid;
> + static const struct broken_card_cid {
> + unsigned int manfid;
> + char prod_name[8];
> + unsigned char hwrev;
> + unsigned char fwrev;
> + } broken_cards[] = {
> + { 0x00150000, "\x30\x30\x30\x30\x30\x30\x15\x00", 0x06, 0x03 },
> + };
> +
> + for (i = 0; i < sizeof(broken_cards)/sizeof(broken_cards[0]); i++) {
> + const struct broken_card_cid *b = broken_cards + i;
> +
> + if (b->manfid != c->manfid)
> + continue;
> + if (memcmp(b->prod_name, c->prod_name, sizeof(b->prod_name)) != 0)
> + continue;
> + if (b->hwrev != c->hwrev || b->fwrev != c->fwrev)
> + continue;
> + return 1;
> + }
> + return 0;
> +}
Again, not something you do in the driver.
> +
> + /* Some cards (vendor left unnamed to protect the guilty) seem to
> + * require this delay after power-up. Otherwise we'll get mysterious
> + * data timeouts.
> + */
Same here.
Rgds
Pierre
next prev parent reply other threads:[~2006-01-31 15:29 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-01-31 13:34 [patch 1/5] MMC OMAP driver Anderson Briglia
2006-01-31 15:29 ` Pierre Ossman [this message]
2006-02-01 12:44 ` Russell King
2006-02-01 19:47 ` Tony Lindgren
2006-02-02 10:40 ` Russell King
2006-02-02 11:45 ` Pierre Ossman
2006-02-02 12:24 ` Russell King
2006-02-17 19:53 ` Carlos Aguiar
2006-02-17 20:08 ` Russell King
2006-02-02 19:34 ` Anderson Briglia
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=43DF8257.6040707@drzeus.cx \
--to=drzeus-list@drzeus.cx \
--cc=anderson.briglia@indt.org.br \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@arm.linux.org.uk \
--cc=tony@atomide.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox