Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
6e58ddeb
Commit
6e58ddeb
authored
Sep 18, 2004
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://bk.arm.linux.org.uk/linux-2.6-mmc
into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents
6e544044
201ee40f
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
143 additions
and
61 deletions
+143
-61
drivers/mmc/mmc.c
drivers/mmc/mmc.c
+110
-47
drivers/mmc/mmc_sysfs.c
drivers/mmc/mmc_sysfs.c
+18
-8
include/linux/mmc/card.h
include/linux/mmc/card.h
+15
-6
No files found.
drivers/mmc/mmc.c
View file @
6e58ddeb
...
...
@@ -300,58 +300,121 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
return
ocr
;
}
static
void
mmc_decode_cid
(
struct
mmc_cid
*
cid
,
u32
*
resp
)
#define UNSTUFF_BITS(resp,start,size) \
({ \
const u32 __mask = (1 << (size)) - 1; \
const int __off = 3 - ((start) / 32); \
const int __shft = (start) & 31; \
u32 __res; \
\
__res = resp[__off] >> __shft; \
if ((size) + __shft >= 32) \
__res |= resp[__off-1] << (32 - __shft); \
__res & __mask; \
})
/*
* Given the decoded CSD structure, decode the raw CID to our CID structure.
*/
static
void
mmc_decode_cid
(
struct
mmc_card
*
card
)
{
memset
(
cid
,
0
,
sizeof
(
struct
mmc_cid
));
cid
->
manfid
=
resp
[
0
]
>>
8
;
cid
->
prod_name
[
0
]
=
resp
[
0
];
cid
->
prod_name
[
1
]
=
resp
[
1
]
>>
24
;
cid
->
prod_name
[
2
]
=
resp
[
1
]
>>
16
;
cid
->
prod_name
[
3
]
=
resp
[
1
]
>>
8
;
cid
->
prod_name
[
4
]
=
resp
[
1
];
cid
->
prod_name
[
5
]
=
resp
[
2
]
>>
24
;
cid
->
prod_name
[
6
]
=
resp
[
2
]
>>
16
;
cid
->
prod_name
[
7
]
=
'\0'
;
cid
->
hwrev
=
(
resp
[
2
]
>>
12
)
&
15
;
cid
->
fwrev
=
(
resp
[
2
]
>>
8
)
&
15
;
cid
->
serial
=
(
resp
[
2
]
&
255
)
<<
16
|
(
resp
[
3
]
>>
16
);
cid
->
month
=
(
resp
[
3
]
>>
12
)
&
15
;
cid
->
year
=
(
resp
[
3
]
>>
8
)
&
15
;
u32
*
resp
=
card
->
raw_cid
;
memset
(
&
card
->
cid
,
0
,
sizeof
(
struct
mmc_cid
));
/*
* The selection of the format here is guesswork based upon
* information people have sent to date.
*/
switch
(
card
->
csd
.
mmca_vsn
)
{
case
0
:
/* MMC v1.? */
case
1
:
/* MMC v1.4 */
card
->
cid
.
manfid
=
UNSTUFF_BITS
(
resp
,
104
,
24
);
card
->
cid
.
prod_name
[
0
]
=
UNSTUFF_BITS
(
resp
,
96
,
8
);
card
->
cid
.
prod_name
[
1
]
=
UNSTUFF_BITS
(
resp
,
88
,
8
);
card
->
cid
.
prod_name
[
2
]
=
UNSTUFF_BITS
(
resp
,
80
,
8
);
card
->
cid
.
prod_name
[
3
]
=
UNSTUFF_BITS
(
resp
,
72
,
8
);
card
->
cid
.
prod_name
[
4
]
=
UNSTUFF_BITS
(
resp
,
64
,
8
);
card
->
cid
.
prod_name
[
5
]
=
UNSTUFF_BITS
(
resp
,
56
,
8
);
card
->
cid
.
prod_name
[
6
]
=
UNSTUFF_BITS
(
resp
,
48
,
8
);
card
->
cid
.
hwrev
=
UNSTUFF_BITS
(
resp
,
44
,
4
);
card
->
cid
.
fwrev
=
UNSTUFF_BITS
(
resp
,
40
,
4
);
card
->
cid
.
serial
=
UNSTUFF_BITS
(
resp
,
16
,
24
);
card
->
cid
.
month
=
UNSTUFF_BITS
(
resp
,
12
,
4
);
card
->
cid
.
year
=
UNSTUFF_BITS
(
resp
,
8
,
4
)
+
1997
;
break
;
case
2
:
/* MMC v2.x ? */
case
3
:
/* MMC v3.x ? */
card
->
cid
.
manfid
=
UNSTUFF_BITS
(
resp
,
120
,
8
);
card
->
cid
.
oemid
=
UNSTUFF_BITS
(
resp
,
104
,
16
);
card
->
cid
.
prod_name
[
0
]
=
UNSTUFF_BITS
(
resp
,
96
,
8
);
card
->
cid
.
prod_name
[
1
]
=
UNSTUFF_BITS
(
resp
,
88
,
8
);
card
->
cid
.
prod_name
[
2
]
=
UNSTUFF_BITS
(
resp
,
80
,
8
);
card
->
cid
.
prod_name
[
3
]
=
UNSTUFF_BITS
(
resp
,
72
,
8
);
card
->
cid
.
prod_name
[
4
]
=
UNSTUFF_BITS
(
resp
,
64
,
8
);
card
->
cid
.
prod_name
[
5
]
=
UNSTUFF_BITS
(
resp
,
56
,
8
);
card
->
cid
.
serial
=
UNSTUFF_BITS
(
resp
,
16
,
32
);
card
->
cid
.
month
=
UNSTUFF_BITS
(
resp
,
12
,
4
);
card
->
cid
.
year
=
UNSTUFF_BITS
(
resp
,
8
,
4
)
+
1997
;
break
;
default:
printk
(
"%s: card has unknown MMCA version %d
\n
"
,
card
->
host
->
host_name
,
card
->
csd
.
mmca_vsn
);
mmc_card_set_bad
(
card
);
break
;
}
}
static
void
mmc_decode_csd
(
struct
mmc_csd
*
csd
,
u32
*
resp
)
/*
* Given a 128-bit response, decode to our card CSD structure.
*/
static
void
mmc_decode_csd
(
struct
mmc_card
*
card
)
{
unsigned
int
e
,
m
;
struct
mmc_csd
*
csd
=
&
card
->
csd
;
unsigned
int
e
,
m
,
csd_struct
;
u32
*
resp
=
card
->
raw_csd
;
csd
->
mmc_prot
=
(
resp
[
0
]
>>
26
)
&
15
;
m
=
(
resp
[
0
]
>>
19
)
&
15
;
e
=
(
resp
[
0
]
>>
16
)
&
7
;
/*
* We only understand CSD structure v1.1 and v2.
* v2 has extra information in bits 15, 11 and 10.
*/
csd_struct
=
UNSTUFF_BITS
(
resp
,
126
,
2
);
if
(
csd_struct
!=
1
&&
csd_struct
!=
2
)
{
printk
(
"%s: unrecognised CSD structure version %d
\n
"
,
card
->
host
->
host_name
,
csd_struct
);
mmc_card_set_bad
(
card
);
return
;
}
csd
->
mmca_vsn
=
UNSTUFF_BITS
(
resp
,
122
,
4
);
m
=
UNSTUFF_BITS
(
resp
,
115
,
4
);
e
=
UNSTUFF_BITS
(
resp
,
112
,
3
);
csd
->
tacc_ns
=
(
tacc_exp
[
e
]
*
tacc_mant
[
m
]
+
9
)
/
10
;
csd
->
tacc_clks
=
((
resp
[
0
]
>>
8
)
&
255
)
*
100
;
csd
->
tacc_clks
=
UNSTUFF_BITS
(
resp
,
104
,
8
)
*
100
;
m
=
(
resp
[
0
]
>>
3
)
&
15
;
e
=
resp
[
0
]
&
7
;
m
=
UNSTUFF_BITS
(
resp
,
99
,
4
)
;
e
=
UNSTUFF_BITS
(
resp
,
96
,
3
)
;
csd
->
max_dtr
=
tran_exp
[
e
]
*
tran_mant
[
m
];
csd
->
cmdclass
=
(
resp
[
1
]
>>
20
)
&
0xfff
;
csd
->
cmdclass
=
UNSTUFF_BITS
(
resp
,
84
,
12
)
;
e
=
(
resp
[
2
]
>>
15
)
&
7
;
m
=
(
resp
[
1
]
<<
2
|
resp
[
2
]
>>
30
)
&
0x3fff
;
e
=
UNSTUFF_BITS
(
resp
,
47
,
3
)
;
m
=
UNSTUFF_BITS
(
resp
,
62
,
12
)
;
csd
->
capacity
=
(
1
+
m
)
<<
(
e
+
2
);
csd
->
read_blkbits
=
(
resp
[
1
]
>>
16
)
&
15
;
csd
->
read_blkbits
=
UNSTUFF_BITS
(
resp
,
80
,
4
)
;
}
/*
* Locate a MMC card on this MMC host given a CID.
* Locate a MMC card on this MMC host given a
raw
CID.
*/
static
struct
mmc_card
*
mmc_find_card
(
struct
mmc_host
*
host
,
struct
mmc_cid
*
cid
)
static
struct
mmc_card
*
mmc_find_card
(
struct
mmc_host
*
host
,
u32
*
raw_cid
)
{
struct
mmc_card
*
card
;
list_for_each_entry
(
card
,
&
host
->
cards
,
node
)
{
if
(
memcmp
(
&
card
->
cid
,
cid
,
sizeof
(
struct
mmc
_cid
))
==
0
)
if
(
memcmp
(
card
->
raw_cid
,
raw_cid
,
sizeof
(
card
->
raw
_cid
))
==
0
)
return
card
;
}
return
NULL
;
...
...
@@ -361,7 +424,7 @@ mmc_find_card(struct mmc_host *host, struct mmc_cid *cid)
* Allocate a new MMC card, and assign a unique RCA.
*/
static
struct
mmc_card
*
mmc_alloc_card
(
struct
mmc_host
*
host
,
struct
mmc_cid
*
cid
,
unsigned
int
*
frca
)
mmc_alloc_card
(
struct
mmc_host
*
host
,
u32
*
raw_
cid
,
unsigned
int
*
frca
)
{
struct
mmc_card
*
card
,
*
c
;
unsigned
int
rca
=
*
frca
;
...
...
@@ -371,7 +434,7 @@ mmc_alloc_card(struct mmc_host *host, struct mmc_cid *cid, unsigned int *frca)
return
ERR_PTR
(
-
ENOMEM
);
mmc_init_card
(
card
,
host
);
memcpy
(
&
card
->
cid
,
cid
,
sizeof
(
struct
mmc
_cid
));
memcpy
(
card
->
raw_cid
,
raw_cid
,
sizeof
(
card
->
raw
_cid
));
again:
list_for_each_entry
(
c
,
&
host
->
cards
,
node
)
...
...
@@ -456,7 +519,7 @@ static int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
* to be discovered. Add new cards to the list.
*
* Create a mmc_card entry for each discovered card, assigning
* it an RCA, and save the
CID
.
* it an RCA, and save the
raw CID for decoding later
.
*/
static
void
mmc_discover_cards
(
struct
mmc_host
*
host
)
{
...
...
@@ -465,7 +528,6 @@ static void mmc_discover_cards(struct mmc_host *host)
while
(
1
)
{
struct
mmc_command
cmd
;
struct
mmc_cid
cid
;
cmd
.
opcode
=
MMC_ALL_SEND_CID
;
cmd
.
arg
=
0
;
...
...
@@ -482,11 +544,9 @@ static void mmc_discover_cards(struct mmc_host *host)
break
;
}
mmc_decode_cid
(
&
cid
,
cmd
.
resp
);
card
=
mmc_find_card
(
host
,
&
cid
);
card
=
mmc_find_card
(
host
,
cmd
.
resp
);
if
(
!
card
)
{
card
=
mmc_alloc_card
(
host
,
&
cid
,
&
first_rca
);
card
=
mmc_alloc_card
(
host
,
cmd
.
resp
,
&
first_rca
);
if
(
IS_ERR
(
card
))
{
err
=
PTR_ERR
(
card
);
break
;
...
...
@@ -502,7 +562,7 @@ static void mmc_discover_cards(struct mmc_host *host)
err
=
mmc_wait_for_cmd
(
host
,
&
cmd
,
CMD_RETRIES
);
if
(
err
!=
MMC_ERR_NONE
)
card
->
state
|=
MMC_STATE_DEAD
;
mmc_card_set_dead
(
card
)
;
}
}
...
...
@@ -523,11 +583,14 @@ static void mmc_read_csds(struct mmc_host *host)
err
=
mmc_wait_for_cmd
(
host
,
&
cmd
,
CMD_RETRIES
);
if
(
err
!=
MMC_ERR_NONE
)
{
card
->
state
|=
MMC_STATE_DEAD
;
mmc_card_set_dead
(
card
)
;
continue
;
}
mmc_decode_csd
(
&
card
->
csd
,
cmd
.
resp
);
memcpy
(
card
->
raw_csd
,
cmd
.
resp
,
sizeof
(
card
->
raw_csd
));
mmc_decode_csd
(
card
);
mmc_decode_cid
(
card
);
}
}
...
...
@@ -573,7 +636,7 @@ static void mmc_check_cards(struct mmc_host *host)
if
(
err
==
MMC_ERR_NONE
)
continue
;
card
->
state
|=
MMC_STATE_DEAD
;
mmc_card_set_dead
(
card
)
;
}
}
...
...
@@ -678,9 +741,9 @@ static void mmc_rescan(void *data)
*/
if
(
!
mmc_card_present
(
card
)
&&
!
mmc_card_dead
(
card
))
{
if
(
mmc_register_card
(
card
))
card
->
state
|=
MMC_STATE_DEAD
;
mmc_card_set_dead
(
card
)
;
else
card
->
state
|=
MMC_STATE_PRESENT
;
mmc_card_set_present
(
card
)
;
}
/*
...
...
drivers/mmc/mmc_sysfs.c
View file @
6e58ddeb
...
...
@@ -31,11 +31,12 @@ static void mmc_release_card(struct device *dev)
/*
* This currently matches any MMC driver to any MMC card - drivers
* themselves make the decision whether to drive this card in their
* probe method.
* probe method.
However, we force "bad" cards to fail.
*/
static
int
mmc_bus_match
(
struct
device
*
dev
,
struct
device_driver
*
drv
)
{
return
1
;
struct
mmc_card
*
card
=
dev_to_mmc_card
(
dev
);
return
!
mmc_card_bad
(
card
);
}
static
int
...
...
@@ -66,8 +67,9 @@ mmc_bus_hotplug(struct device *dev, char **envp, int num_envp, char *buf,
i
=
0
;
add_env
(
"MMC_CCC=%s"
,
ccc
);
add_env
(
"MMC_MANFID=%03x"
,
card
->
cid
.
manfid
);
add_env
(
"MMC_SLOT_NAME=%s"
,
card
->
dev
.
bus_id
);
add_env
(
"MMC_MANFID=%06x"
,
card
->
cid
.
manfid
);
add_env
(
"MMC_NAME=%s"
,
mmc_card_name
(
card
));
add_env
(
"MMC_OEMID=%04x"
,
card
->
cid
.
oemid
);
return
0
;
}
...
...
@@ -157,20 +159,28 @@ static ssize_t mmc_dev_show_##name (struct device *dev, char *buf) \
} \
static DEVICE_ATTR(name, S_IRUGO, mmc_dev_show_##name, NULL)
MMC_ATTR
(
date
,
"%02d/%04d
\n
"
,
card
->
cid
.
month
,
1997
+
card
->
cid
.
year
);
MMC_ATTR
(
cid
,
"%08x%08x%08x%08x
\n
"
,
card
->
raw_cid
[
0
],
card
->
raw_cid
[
1
],
card
->
raw_cid
[
2
],
card
->
raw_cid
[
3
]);
MMC_ATTR
(
csd
,
"%08x%08x%08x%08x
\n
"
,
card
->
raw_csd
[
0
],
card
->
raw_csd
[
1
],
card
->
raw_csd
[
2
],
card
->
raw_csd
[
3
]);
MMC_ATTR
(
date
,
"%02d/%04d
\n
"
,
card
->
cid
.
month
,
card
->
cid
.
year
);
MMC_ATTR
(
fwrev
,
"0x%x
\n
"
,
card
->
cid
.
fwrev
);
MMC_ATTR
(
hwrev
,
"0x%x
\n
"
,
card
->
cid
.
hwrev
);
MMC_ATTR
(
manfid
,
"0x%03x
\n
"
,
card
->
cid
.
manfid
);
MMC_ATTR
(
serial
,
"0x%06x
\n
"
,
card
->
cid
.
serial
);
MMC_ATTR
(
manfid
,
"0x%06x
\n
"
,
card
->
cid
.
manfid
);
MMC_ATTR
(
name
,
"%s
\n
"
,
card
->
cid
.
prod_name
);
MMC_ATTR
(
oemid
,
"0x%04x
\n
"
,
card
->
cid
.
oemid
);
MMC_ATTR
(
serial
,
"0x%08x
\n
"
,
card
->
cid
.
serial
);
static
struct
device_attribute
*
mmc_dev_attributes
[]
=
{
&
dev_attr_cid
,
&
dev_attr_csd
,
&
dev_attr_date
,
&
dev_attr_fwrev
,
&
dev_attr_hwrev
,
&
dev_attr_manfid
,
&
dev_attr_serial
,
&
dev_attr_name
,
&
dev_attr_oemid
,
&
dev_attr_serial
,
};
/*
...
...
include/linux/mmc/card.h
View file @
6e58ddeb
...
...
@@ -14,16 +14,17 @@
struct
mmc_cid
{
unsigned
int
manfid
;
unsigned
int
serial
;
char
prod_name
[
8
];
unsigned
int
serial
;
unsigned
short
oemid
;
unsigned
short
year
;
unsigned
char
hwrev
;
unsigned
char
fwrev
;
unsigned
char
month
;
unsigned
char
year
;
};
struct
mmc_csd
{
unsigned
char
mmc
_prot
;
unsigned
char
mmc
a_vsn
;
unsigned
short
cmdclass
;
unsigned
short
tacc_clks
;
unsigned
int
tacc_ns
;
...
...
@@ -43,14 +44,22 @@ struct mmc_card {
struct
device
dev
;
/* the device */
unsigned
int
rca
;
/* relative card address of device */
unsigned
int
state
;
/* (our) card state */
#define MMC_STATE_PRESENT (1<<0)
#define MMC_STATE_DEAD (1<<1)
#define MMC_STATE_PRESENT (1<<0)
/* present in sysfs */
#define MMC_STATE_DEAD (1<<1)
/* device no longer in stack */
#define MMC_STATE_BAD (1<<2)
/* unrecognised device */
u32
raw_cid
[
4
];
/* raw card CID */
u32
raw_csd
[
4
];
/* raw card CSD */
struct
mmc_cid
cid
;
/* card identification */
struct
mmc_csd
csd
;
/* card specific */
};
#define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD)
#define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
#define mmc_card_dead(c) ((c)->state & MMC_STATE_DEAD)
#define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD)
#define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
#define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD)
#define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD)
#define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) ((c)->dev.bus_id)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment