From: Pierre Ossman <drzeus-list@drzeus.cx>
To: David Brownell <david-b@pacbell.net>
Cc: linux-kernel@vger.kernel.org
Subject: Re: mmc_spi stopped working
Date: Sat, 27 Oct 2007 14:52:33 +0200 [thread overview]
Message-ID: <20071027145233.39e986e3@poseidon.drzeus.cx> (raw)
In-Reply-To: <200710241537.10566.david-b@pacbell.net>
[-- Attachment #1: Type: text/plain, Size: 1639 bytes --]
On Wed, 24 Oct 2007 15:37:10 -0700
David Brownell <david-b@pacbell.net> wrote:
> On Monday 22 October 2007, Pierre Ossman wrote:
> >
> > I've been testing a bit more here, and I can't get this particular bug.
>
> It's not just a bug, it's a regression ... a new bug which
> was introduced by some patch. ;)
>
It's a bug in the card, which is what I was referring to. ;)
>
> SPI works fine on all the MMC and SD cards I've got here,
> other than the minor glitch fixed by the "don't just probe"
> patch I sent.
>
Lucky you. :)
> As you know, to be spec-conformant they *must* support SPI.
I never recall which of the different specs require SPI (not all do).
> Agreed, there are too many vendors who don't appear to value
> following specs. If those cards which are using the MMC or
> SD trade marks, you might notify the relevant consortium and
> asking them to fix those vendors. ;)
>
Hah! The SD and MMC boys seem to have no interest in people following the specs, considering all the shite that is out there.
>
> > As for your card, could you send me a dump as I'm unable to produce
> > the issue here?
>
> I'm not sure what you mean by "dump", but appended the sysfs attributes
> produced after I disabled that new "just probe" mechanism.
>
A dmesg with MMC_DEBUG so that I can see just how the card misbehaves.
Also, I see you're dying for my decodecid and decodecsd progs. ;)
I've included both.
Rgds
--
-- Pierre Ossman
Linux kernel, MMC maintainer http://www.kernel.org
PulseAudio, core developer http://pulseaudio.org
rdesktop, core developer http://www.rdesktop.org
[-- Attachment #2: crc7.c --]
[-- Type: text/x-csrc, Size: 925 bytes --]
#include "crc7.h"
#define CRC7_POLYNOMIAL 0x89 /* x^7 + x^3 + 1 */
static unsigned char crc7_syndrome_table[256];
/*
* Generate a table of CRC-7 syndromes for x^7 * each possible input byte
*/
void
gen_crc7_syndrome_table (void)
{
int i, j, syndrome;
for (i = 0; i < 256; ++i)
{
syndrome = ((i & 0x80) != 0)? i ^ CRC7_POLYNOMIAL : i;
for (j = 0; j < 7; ++j)
{
if (((syndrome <<= 1) & 0x80) != 0)
{
syndrome ^= CRC7_POLYNOMIAL;
}
}
crc7_syndrome_table[i] = (unsigned char) syndrome;
}
}
unsigned char
calc_crc7(unsigned long* resp)
{
unsigned char crc7_accum = 0;
unsigned char byte;
int i, j;
for (i = 0;i < 4;i++)
{
for (j = 0;j < 4;j++)
{
if ((i == 3) && (j == 3))
break;
byte = resp[i] >> (24 - 8 * j);
crc7_accum = crc7_syndrome_table[(crc7_accum << 1) ^ byte];
}
}
return crc7_accum;
}
[-- Attachment #3: crc7.h --]
[-- Type: text/x-chdr, Size: 83 bytes --]
void gen_crc7_syndrome_table (void);
unsigned char calc_crc7(unsigned long* resp);
[-- Attachment #4: decode.h --]
[-- Type: text/x-chdr, Size: 383 bytes --]
#define UNSTUFF_BITS(resp,start,size) \
({ \
const unsigned long __mask = (1 << (size)) - 1; \
const int __off = 3 - ((start) / 32); \
const int __shft = (start) & 31; \
unsigned long __res; \
\
__res = resp[__off] >> __shft; \
if ((size) + __shft >= 32) \
__res |= resp[__off-1] << (32 - __shft); \
__res & __mask; \
})
[-- Attachment #5: decodecid.c --]
[-- Type: text/x-csrc, Size: 1317 bytes --]
#include <stdlib.h>
#include <stdio.h>
#include "crc7.h"
#include "decode.h"
int main(int argc, char** argv)
{
int i, j;
int temp, e, m;
char ch;
unsigned long resp[4];
if (argc != 2)
return -1;
if (strlen(argv[1]) != 8 * 4)
return -1;
for (i = 0;i < 4;i++)
{
resp[i] = 0;
for (j = 0;j < 8;j++)
{
resp[i] <<= 4;
ch = tolower(argv[1][i * 8 + j]);
if (isdigit(ch))
resp[i] |= ch - '0';
else if (isxdigit(ch))
resp[i] |= ch - 'a' + 0xA;
else
return -1;
}
}
printf("Manufacturer ID: %d\n", UNSTUFF_BITS(resp, 120, 8));
printf("OEM/Application ID: %d\n", UNSTUFF_BITS(resp, 104, 16));
printf("Product name: %c%c%c%c%c%c\n",
(char)UNSTUFF_BITS(resp, 96, 8),
(char)UNSTUFF_BITS(resp, 88, 8),
(char)UNSTUFF_BITS(resp, 80, 8),
(char)UNSTUFF_BITS(resp, 72, 8),
(char)UNSTUFF_BITS(resp, 64, 8),
(char)UNSTUFF_BITS(resp, 56, 8));
printf("Product revision: %d:%d\n",
UNSTUFF_BITS(resp, 52, 4),
UNSTUFF_BITS(resp, 48, 4));
printf("Serial: %08x\n", UNSTUFF_BITS(resp, 16, 32));
printf("Manufacturing date: %d/%d\n",
UNSTUFF_BITS(resp, 12, 4) + 1997,
UNSTUFF_BITS(resp, 8, 4));
gen_crc7_syndrome_table();
printf("CRC: ");
if (UNSTUFF_BITS(resp, 1, 7) == calc_crc7(resp))
printf("OK");
else
printf("Fail");
printf("\n");
return 0;
}
[-- Attachment #6: decodecsd.c --]
[-- Type: text/x-csrc, Size: 5411 bytes --]
#include <stdlib.h>
#include <stdio.h>
#include "crc7.h"
#include "decode.h"
static const unsigned int tran_exp[] = {
10000, 100000, 1000000, 10000000,
0, 0, 0, 0
};
static const unsigned char tran_mant[] = {
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};
static const unsigned int tacc_exp[] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
};
static const unsigned int tacc_mant[] = {
0, 10, 12, 13, 15, 20, 25, 30,
35, 40, 45, 50, 55, 60, 70, 80,
};
static const unsigned int min_cur[] = {
5, 10, 50, 100, 250, 350, 600, 1000,
};
static const unsigned int max_cur[] = {
10, 50, 100, 250, 350, 450, 800, 2000,
};
int main(int argc, char** argv)
{
int i, j;
int temp, e, m;
char ch;
unsigned long resp[4];
if (argc != 2)
return -1;
if (strlen(argv[1]) != 8 * 4)
return -1;
for (i = 0;i < 4;i++)
{
resp[i] = 0;
for (j = 0;j < 8;j++)
{
resp[i] <<= 4;
ch = tolower(argv[1][i * 8 + j]);
if (isdigit(ch))
resp[i] |= ch - '0';
else if (isxdigit(ch))
resp[i] |= ch - 'a' + 0xA;
else
return -1;
}
}
printf("CSD Version: ");
temp = UNSTUFF_BITS(resp, 126, 2);
switch (temp)
{
case 0:
printf("v1.0");
break;
case 1:
printf("v1.1");
break;
case 2:
printf("v1.2");
break;
default:
printf("Unknown [%d]", temp);
}
printf("\n");
printf("MMCA Version: ");
temp = UNSTUFF_BITS(resp, 122, 4);
switch (temp)
{
case 0:
printf("v1.0 to v1.2");
break;
case 1:
printf("v1.4");
break;
case 2:
printf("v2.0 to v2.2");
break;
case 3:
printf("v3.1 to v3.3");
break;
default:
printf("Unknown [%d]", temp);
}
printf("\n");
m = UNSTUFF_BITS(resp, 115, 4);
e = UNSTUFF_BITS(resp, 112, 3);
printf("TACC: %d ns\n", (tacc_exp[e] * tacc_mant[m] + 9) / 10);
printf("NSAC: %d clks\n", UNSTUFF_BITS(resp, 104, 8) * 100);
m = UNSTUFF_BITS(resp, 99, 4);
e = UNSTUFF_BITS(resp, 96, 3);
printf("Max rate: %d kHz\n", tran_exp[e] * tran_mant[m] / 1000);
printf("Command classes: ");
temp = UNSTUFF_BITS(resp, 84, 12);
for (i = 0;i < 12;i++)
{
if (temp & (1 << i))
{
switch (i)
{
case 0:
printf("basic, ");
break;
case 1:
printf("stream read, ");
break;
case 2:
printf("block read, ");
break;
case 3:
printf("stream write, ");
break;
case 4:
printf("block write, ");
break;
case 5:
printf("erase, ");
break;
case 6:
printf("write prot., ");
break;
case 7:
printf("lock, ");
break;
case 8:
printf("app. specific, ");
break;
case 9:
printf("I/O mode, ");
break;
default:
printf("class %d, ", i);
}
}
}
printf("\n");
temp = 1 << UNSTUFF_BITS(resp, 80, 4);
printf("Read block size: %d bytes\n", temp);
temp = 1 << UNSTUFF_BITS(resp, 22, 4);
printf("Write block size: %d bytes\n", temp);
printf("Partial read: ");
if (UNSTUFF_BITS(resp, 79, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("Partial write: ");
if (UNSTUFF_BITS(resp, 21, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("Read misalign: ");
if (UNSTUFF_BITS(resp, 77, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("Write misalign: ");
if (UNSTUFF_BITS(resp, 78, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("DSR: ");
if (UNSTUFF_BITS(resp, 76, 1))
printf("Yes");
else
printf("No");
printf("\n");
e = UNSTUFF_BITS(resp, 47, 3);
m = UNSTUFF_BITS(resp, 62, 12);
printf("Capacity: %d blocks %d %d\n", ((1 + m) << (e + 2)), m, e);
printf("Min read current: %0.1f mA\n",
(float)min_cur[UNSTUFF_BITS(resp, 59, 3)]/10);
printf("Max read current: %0.1f mA\n",
(float)max_cur[UNSTUFF_BITS(resp, 56, 3)]/10);
printf("Min write current: %0.1f mA\n",
(float)min_cur[UNSTUFF_BITS(resp, 53, 3)]/10);
printf("Max write current: %0.1f mA\n",
(float)max_cur[UNSTUFF_BITS(resp, 50, 3)]/10);
m = UNSTUFF_BITS(resp, 42, 5);
e = UNSTUFF_BITS(resp, 37, 5);
printf("Erase group size: %d blocks\n", (m+1) * (e+1));
printf("WP group size: %d erase group(s)\n", UNSTUFF_BITS(resp, 32, 5));
printf("WP enable: ");
if (UNSTUFF_BITS(resp, 31, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("R2W factor: %d\n", UNSTUFF_BITS(resp, 26, 3));
printf("Content protect: ");
if (UNSTUFF_BITS(resp, 16, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("File format: ");
if (UNSTUFF_BITS(resp, 15, 1))
printf("Reserved");
else
{
switch (UNSTUFF_BITS(resp, 10, 2))
{
case 0:
printf("Hard disk");
break;
case 1:
printf("Floppy");
break;
case 2:
printf("Universal");
break;
case 3:
printf("Unknown");
break;
}
}
printf("\n");
printf("Copy: ");
if (UNSTUFF_BITS(resp, 14, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("Perm write protect: ");
if (UNSTUFF_BITS(resp, 13, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("Tmp write protect: ");
if (UNSTUFF_BITS(resp, 12, 1))
printf("Yes");
else
printf("No");
printf("\n");
printf("ECC: ");
switch (UNSTUFF_BITS(resp, 8, 2))
{
case 0:
printf("none");
break;
case 1:
printf("BCH(512,512)");
break;
default:
printf("Reserved");
}
printf("\n");
gen_crc7_syndrome_table();
printf("CRC: ");
if (UNSTUFF_BITS(resp, 1, 7) == calc_crc7(resp))
printf("OK");
else
printf("Fail");
printf("\n");
return 0;
}
[-- Attachment #7: Makefile --]
[-- Type: application/octet-stream, Size: 117 bytes --]
all: decodecsd decodecid
decodecsd: crc7.o crc7.h decode.h
decodecid: crc7.o crc7.h decode.h
crc7.o: crc7.c crc7.h
prev parent reply other threads:[~2007-10-27 12:52 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-17 19:19 mmc_spi stopped working Pierre Ossman
2007-10-17 19:37 ` David Brownell
2007-10-17 19:52 ` Pierre Ossman
[not found] ` <20071017215217.177cdb14-mgABNEgzgxm+PRNnhPf8W5YgPPQkE1Si@public.gmane.org>
2007-10-24 22:27 ` David Brownell
2007-10-24 22:27 ` David Brownell
[not found] ` <200710241527.46458.david-b-yBeKhBN/0LDR7s880joybQ@public.gmane.org>
2007-10-27 13:00 ` Pierre Ossman
2007-10-27 13:00 ` Pierre Ossman
2007-10-22 18:03 ` Pierre Ossman
2007-10-24 22:37 ` David Brownell
2007-10-27 12:52 ` Pierre Ossman [this message]
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=20071027145233.39e986e3@poseidon.drzeus.cx \
--to=drzeus-list@drzeus.cx \
--cc=david-b@pacbell.net \
--cc=linux-kernel@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.