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
bd6fe9e1
Commit
bd6fe9e1
authored
Sep 12, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/home/rmk/linux-2.6-mmc
parents
862aad56
210ce2a7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
229 additions
and
235 deletions
+229
-235
drivers/mmc/wbsd.c
drivers/mmc/wbsd.c
+218
-223
drivers/mmc/wbsd.h
drivers/mmc/wbsd.h
+11
-12
No files found.
drivers/mmc/wbsd.c
View file @
bd6fe9e1
...
...
@@ -93,7 +93,7 @@ static int dma = 2;
static
inline
void
wbsd_unlock_config
(
struct
wbsd_host
*
host
)
{
BUG_ON
(
host
->
config
==
0
);
outb
(
host
->
unlock_code
,
host
->
config
);
outb
(
host
->
unlock_code
,
host
->
config
);
}
...
...
@@ -101,14 +101,14 @@ static inline void wbsd_unlock_config(struct wbsd_host* host)
static
inline
void
wbsd_lock_config
(
struct
wbsd_host
*
host
)
{
BUG_ON
(
host
->
config
==
0
);
outb
(
LOCK_CODE
,
host
->
config
);
}
static
inline
void
wbsd_write_config
(
struct
wbsd_host
*
host
,
u8
reg
,
u8
value
)
{
BUG_ON
(
host
->
config
==
0
);
outb
(
reg
,
host
->
config
);
outb
(
value
,
host
->
config
+
1
);
}
...
...
@@ -116,7 +116,7 @@ static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
static
inline
u8
wbsd_read_config
(
struct
wbsd_host
*
host
,
u8
reg
)
{
BUG_ON
(
host
->
config
==
0
);
outb
(
reg
,
host
->
config
);
return
inb
(
host
->
config
+
1
);
}
...
...
@@ -140,21 +140,21 @@ static inline u8 wbsd_read_index(struct wbsd_host* host, u8 index)
static
void
wbsd_init_device
(
struct
wbsd_host
*
host
)
{
u8
setup
,
ier
;
/*
* Reset chip (SD/MMC part) and fifo.
*/
setup
=
wbsd_read_index
(
host
,
WBSD_IDX_SETUP
);
setup
|=
WBSD_FIFO_RESET
|
WBSD_SOFT_RESET
;
wbsd_write_index
(
host
,
WBSD_IDX_SETUP
,
setup
);
/*
* Set DAT3 to input
*/
setup
&=
~
WBSD_DAT3_H
;
wbsd_write_index
(
host
,
WBSD_IDX_SETUP
,
setup
);
host
->
flags
&=
~
WBSD_FIGNORE_DETECT
;
/*
* Read back default clock.
*/
...
...
@@ -164,12 +164,12 @@ static void wbsd_init_device(struct wbsd_host* host)
* Power down port.
*/
outb
(
WBSD_POWER_N
,
host
->
base
+
WBSD_CSR
);
/*
* Set maximum timeout.
*/
wbsd_write_index
(
host
,
WBSD_IDX_TAAC
,
0x7F
);
/*
* Test for card presence
*/
...
...
@@ -177,7 +177,7 @@ static void wbsd_init_device(struct wbsd_host* host)
host
->
flags
|=
WBSD_FCARD_PRESENT
;
else
host
->
flags
&=
~
WBSD_FCARD_PRESENT
;
/*
* Enable interesting interrupts.
*/
...
...
@@ -200,9 +200,9 @@ static void wbsd_init_device(struct wbsd_host* host)
static
void
wbsd_reset
(
struct
wbsd_host
*
host
)
{
u8
setup
;
printk
(
KERN_ERR
DRIVER_NAME
": Resetting chip
\n
"
);
/*
* Soft reset of chip (SD/MMC part).
*/
...
...
@@ -214,9 +214,9 @@ static void wbsd_reset(struct wbsd_host* host)
static
void
wbsd_request_end
(
struct
wbsd_host
*
host
,
struct
mmc_request
*
mrq
)
{
unsigned
long
dmaflags
;
DBGF
(
"Ending request, cmd (%x)
\n
"
,
mrq
->
cmd
->
opcode
);
if
(
host
->
dma
>=
0
)
{
/*
...
...
@@ -232,7 +232,7 @@ static void wbsd_request_end(struct wbsd_host* host, struct mmc_request* mrq)
*/
wbsd_write_index
(
host
,
WBSD_IDX_DMA
,
0
);
}
host
->
mrq
=
NULL
;
/*
...
...
@@ -275,7 +275,7 @@ static inline int wbsd_next_sg(struct wbsd_host* host)
host
->
offset
=
0
;
host
->
remain
=
host
->
cur_sg
->
length
;
}
return
host
->
num_sg
;
}
...
...
@@ -297,12 +297,12 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
struct
scatterlist
*
sg
;
char
*
dmabuf
=
host
->
dma_buffer
;
char
*
sgbuf
;
size
=
host
->
size
;
sg
=
data
->
sg
;
len
=
data
->
sg_len
;
/*
* Just loop through all entries. Size might not
* be the entire list though so make sure that
...
...
@@ -317,23 +317,23 @@ static inline void wbsd_sg_to_dma(struct wbsd_host* host, struct mmc_data* data)
memcpy
(
dmabuf
,
sgbuf
,
sg
[
i
].
length
);
kunmap_atomic
(
sgbuf
,
KM_BIO_SRC_IRQ
);
dmabuf
+=
sg
[
i
].
length
;
if
(
size
<
sg
[
i
].
length
)
size
=
0
;
else
size
-=
sg
[
i
].
length
;
if
(
size
==
0
)
break
;
}
/*
* Check that we didn't get a request to transfer
* more data than can fit into the SG list.
*/
BUG_ON
(
size
!=
0
);
host
->
size
-=
size
;
}
...
...
@@ -343,12 +343,12 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
struct
scatterlist
*
sg
;
char
*
dmabuf
=
host
->
dma_buffer
;
char
*
sgbuf
;
size
=
host
->
size
;
sg
=
data
->
sg
;
len
=
data
->
sg_len
;
/*
* Just loop through all entries. Size might not
* be the entire list though so make sure that
...
...
@@ -363,30 +363,30 @@ static inline void wbsd_dma_to_sg(struct wbsd_host* host, struct mmc_data* data)
memcpy
(
sgbuf
,
dmabuf
,
sg
[
i
].
length
);
kunmap_atomic
(
sgbuf
,
KM_BIO_SRC_IRQ
);
dmabuf
+=
sg
[
i
].
length
;
if
(
size
<
sg
[
i
].
length
)
size
=
0
;
else
size
-=
sg
[
i
].
length
;
if
(
size
==
0
)
break
;
}
/*
* Check that we didn't get a request to transfer
* more data than can fit into the SG list.
*/
BUG_ON
(
size
!=
0
);
host
->
size
-=
size
;
}
/*
* Command handling
*/
static
inline
void
wbsd_get_short_reply
(
struct
wbsd_host
*
host
,
struct
mmc_command
*
cmd
)
{
...
...
@@ -398,7 +398,7 @@ static inline void wbsd_get_short_reply(struct wbsd_host* host,
cmd
->
error
=
MMC_ERR_INVALID
;
return
;
}
cmd
->
resp
[
0
]
=
wbsd_read_index
(
host
,
WBSD_IDX_RESP12
)
<<
24
;
cmd
->
resp
[
0
]
|=
...
...
@@ -415,7 +415,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
struct
mmc_command
*
cmd
)
{
int
i
;
/*
* Correct response type?
*/
...
...
@@ -424,7 +424,7 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
cmd
->
error
=
MMC_ERR_INVALID
;
return
;
}
for
(
i
=
0
;
i
<
4
;
i
++
)
{
cmd
->
resp
[
i
]
=
...
...
@@ -442,7 +442,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
{
int
i
;
u8
status
,
isr
;
DBGF
(
"Sending cmd (%x)
\n
"
,
cmd
->
opcode
);
/*
...
...
@@ -451,16 +451,16 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* transfer.
*/
host
->
isr
=
0
;
/*
* Send the command (CRC calculated by host).
*/
outb
(
cmd
->
opcode
,
host
->
base
+
WBSD_CMDR
);
for
(
i
=
3
;
i
>=
0
;
i
--
)
outb
((
cmd
->
arg
>>
(
i
*
8
))
&
0xff
,
host
->
base
+
WBSD_CMDR
);
cmd
->
error
=
MMC_ERR_NONE
;
/*
* Wait for the request to complete.
*/
...
...
@@ -477,7 +477,7 @@ static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
* Read back status.
*/
isr
=
host
->
isr
;
/* Card removed? */
if
(
isr
&
WBSD_INT_CARD
)
cmd
->
error
=
MMC_ERR_TIMEOUT
;
...
...
@@ -509,13 +509,13 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
struct
mmc_data
*
data
=
host
->
mrq
->
cmd
->
data
;
char
*
buffer
;
int
i
,
fsr
,
fifo
;
/*
* Handle excessive data.
*/
if
(
data
->
bytes_xfered
==
host
->
size
)
return
;
buffer
=
wbsd_kmap_sg
(
host
)
+
host
->
offset
;
/*
...
...
@@ -527,14 +527,14 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
/*
* The size field in the FSR is broken so we have to
* do some guessing.
*/
*/
if
(
fsr
&
WBSD_FIFO_FULL
)
fifo
=
16
;
else
if
(
fsr
&
WBSD_FIFO_FUTHRE
)
fifo
=
8
;
else
fifo
=
1
;
for
(
i
=
0
;
i
<
fifo
;
i
++
)
{
*
buffer
=
inb
(
host
->
base
+
WBSD_DFR
);
...
...
@@ -543,23 +543,23 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
host
->
remain
--
;
data
->
bytes_xfered
++
;
/*
* Transfer done?
*/
if
(
data
->
bytes_xfered
==
host
->
size
)
{
wbsd_kunmap_sg
(
host
);
wbsd_kunmap_sg
(
host
);
return
;
}
/*
* End of scatter list entry?
*/
if
(
host
->
remain
==
0
)
{
wbsd_kunmap_sg
(
host
);
/*
* Get next entry. Check if last.
*/
...
...
@@ -572,17 +572,17 @@ static void wbsd_empty_fifo(struct wbsd_host* host)
* into the scatter list.
*/
BUG_ON
(
1
);
host
->
size
=
data
->
bytes_xfered
;
return
;
}
buffer
=
wbsd_kmap_sg
(
host
);
}
}
}
wbsd_kunmap_sg
(
host
);
/*
...
...
@@ -599,7 +599,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
struct
mmc_data
*
data
=
host
->
mrq
->
cmd
->
data
;
char
*
buffer
;
int
i
,
fsr
,
fifo
;
/*
* Check that we aren't being called after the
* entire buffer has been transfered.
...
...
@@ -618,7 +618,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
/*
* The size field in the FSR is broken so we have to
* do some guessing.
*/
*/
if
(
fsr
&
WBSD_FIFO_EMPTY
)
fifo
=
0
;
else
if
(
fsr
&
WBSD_FIFO_EMTHRE
)
...
...
@@ -632,9 +632,9 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
buffer
++
;
host
->
offset
++
;
host
->
remain
--
;
data
->
bytes_xfered
++
;
/*
* Transfer done?
*/
...
...
@@ -650,7 +650,7 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
if
(
host
->
remain
==
0
)
{
wbsd_kunmap_sg
(
host
);
/*
* Get next entry. Check if last.
*/
...
...
@@ -663,19 +663,19 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
* into the scatter list.
*/
BUG_ON
(
1
);
host
->
size
=
data
->
bytes_xfered
;
return
;
}
buffer
=
wbsd_kmap_sg
(
host
);
}
}
}
wbsd_kunmap_sg
(
host
);
/*
* The controller stops sending interrupts for
* 'FIFO empty' under certain conditions. So we
...
...
@@ -694,7 +694,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
1
<<
data
->
blksz_bits
,
data
->
blocks
,
data
->
flags
);
DBGF
(
"tsac %d ms nsac %d clk
\n
"
,
data
->
timeout_ns
/
1000000
,
data
->
timeout_clks
);
/*
* Calculate size.
*/
...
...
@@ -708,12 +708,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
wbsd_write_index
(
host
,
WBSD_IDX_TAAC
,
127
);
else
wbsd_write_index
(
host
,
WBSD_IDX_TAAC
,
data
->
timeout_ns
/
1000000
);
if
(
data
->
timeout_clks
>
255
)
wbsd_write_index
(
host
,
WBSD_IDX_NSAC
,
255
);
else
wbsd_write_index
(
host
,
WBSD_IDX_NSAC
,
data
->
timeout_clks
);
/*
* Inform the chip of how large blocks will be
* sent. It needs this to determine when to
...
...
@@ -732,7 +732,7 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
else
if
(
host
->
bus_width
==
MMC_BUS_WIDTH_4
)
{
blksize
=
(
1
<<
data
->
blksz_bits
)
+
2
*
4
;
wbsd_write_index
(
host
,
WBSD_IDX_PBSMSB
,
((
blksize
>>
4
)
&
0xF0
)
|
WBSD_DATA_WIDTH
);
wbsd_write_index
(
host
,
WBSD_IDX_PBSLSB
,
blksize
&
0xFF
);
...
...
@@ -751,12 +751,12 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
setup
=
wbsd_read_index
(
host
,
WBSD_IDX_SETUP
);
setup
|=
WBSD_FIFO_RESET
;
wbsd_write_index
(
host
,
WBSD_IDX_SETUP
,
setup
);
/*
* DMA transfer?
*/
if
(
host
->
dma
>=
0
)
{
{
/*
* The buffer for DMA is only 64 kB.
*/
...
...
@@ -766,17 +766,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
data
->
error
=
MMC_ERR_INVALID
;
return
;
}
/*
* Transfer data from the SG list to
* the DMA buffer.
*/
if
(
data
->
flags
&
MMC_DATA_WRITE
)
wbsd_sg_to_dma
(
host
,
data
);
/*
* Initialise the ISA DMA controller.
*/
*/
dmaflags
=
claim_dma_lock
();
disable_dma
(
host
->
dma
);
clear_dma_ff
(
host
->
dma
);
...
...
@@ -802,17 +802,17 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
* output to a minimum.
*/
host
->
firsterr
=
1
;
/*
* Initialise the SG list.
*/
wbsd_init_sg
(
host
,
data
);
/*
* Turn off DMA.
*/
wbsd_write_index
(
host
,
WBSD_IDX_DMA
,
0
);
/*
* Set up FIFO threshold levels (and fill
* buffer if doing a write).
...
...
@@ -828,8 +828,8 @@ static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
WBSD_FIFOEN_EMPTY
|
8
);
wbsd_fill_fifo
(
host
);
}
}
}
data
->
error
=
MMC_ERR_NONE
;
}
...
...
@@ -838,7 +838,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
unsigned
long
dmaflags
;
int
count
;
u8
status
;
WARN_ON
(
host
->
mrq
==
NULL
);
/*
...
...
@@ -855,7 +855,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{
status
=
wbsd_read_index
(
host
,
WBSD_IDX_STATUS
);
}
while
(
status
&
(
WBSD_BLOCK_READ
|
WBSD_BLOCK_WRITE
));
/*
* DMA transfer?
*/
...
...
@@ -865,7 +865,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
* Disable DMA on the host.
*/
wbsd_write_index
(
host
,
WBSD_IDX_DMA
,
0
);
/*
* Turn of ISA DMA controller.
*/
...
...
@@ -874,7 +874,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
clear_dma_ff
(
host
->
dma
);
count
=
get_dma_residue
(
host
->
dma
);
release_dma_lock
(
dmaflags
);
/*
* Any leftover data?
*/
...
...
@@ -882,7 +882,7 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
{
printk
(
KERN_ERR
DRIVER_NAME
": Incomplete DMA "
"transfer. %d bytes left.
\n
"
,
count
);
data
->
error
=
MMC_ERR_FAILED
;
}
else
...
...
@@ -893,13 +893,13 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
*/
if
(
data
->
flags
&
MMC_DATA_READ
)
wbsd_dma_to_sg
(
host
,
data
);
data
->
bytes_xfered
=
host
->
size
;
}
}
DBGF
(
"Ending data transfer (%d bytes)
\n
"
,
data
->
bytes_xfered
);
wbsd_request_end
(
host
,
host
->
mrq
);
}
...
...
@@ -924,7 +924,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
cmd
=
mrq
->
cmd
;
host
->
mrq
=
mrq
;
/*
* If there is no card in the slot then
* timeout immediatly.
...
...
@@ -941,18 +941,18 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
if
(
cmd
->
data
)
{
wbsd_prepare_data
(
host
,
cmd
->
data
);
if
(
cmd
->
data
->
error
!=
MMC_ERR_NONE
)
goto
done
;
}
wbsd_send_command
(
host
,
cmd
);
/*
* If this is a data transfer the request
* will be finished after the data has
* transfered.
*/
*/
if
(
cmd
->
data
&&
(
cmd
->
error
==
MMC_ERR_NONE
))
{
/*
...
...
@@ -965,7 +965,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
return
;
}
done:
wbsd_request_end
(
host
,
mrq
);
...
...
@@ -976,7 +976,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
{
struct
wbsd_host
*
host
=
mmc_priv
(
mmc
);
u8
clk
,
setup
,
pwr
;
DBGF
(
"clock %uHz busmode %u powermode %u cs %u Vdd %u width %u
\n
"
,
ios
->
clock
,
ios
->
bus_mode
,
ios
->
power_mode
,
ios
->
chip_select
,
ios
->
vdd
,
ios
->
bus_width
);
...
...
@@ -989,7 +989,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
*/
if
(
ios
->
power_mode
==
MMC_POWER_OFF
)
wbsd_init_device
(
host
);
if
(
ios
->
clock
>=
24000000
)
clk
=
WBSD_CLK_24M
;
else
if
(
ios
->
clock
>=
16000000
)
...
...
@@ -1042,7 +1042,7 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
mod_timer
(
&
host
->
ignore_timer
,
jiffies
+
HZ
/
100
);
}
wbsd_write_index
(
host
,
WBSD_IDX_SETUP
,
setup
);
/*
* Store bus width for later. Will be used when
* setting up the data transfer.
...
...
@@ -1128,7 +1128,7 @@ static inline struct mmc_data* wbsd_get_data(struct wbsd_host* host)
WARN_ON
(
!
host
->
mrq
->
cmd
->
data
);
if
(
!
host
->
mrq
->
cmd
->
data
)
return
NULL
;
return
host
->
mrq
->
cmd
->
data
;
}
...
...
@@ -1136,72 +1136,67 @@ static void wbsd_tasklet_card(unsigned long param)
{
struct
wbsd_host
*
host
=
(
struct
wbsd_host
*
)
param
;
u8
csr
;
int
delay
=
-
1
;
spin_lock
(
&
host
->
lock
);
if
(
host
->
flags
&
WBSD_FIGNORE_DETECT
)
{
spin_unlock
(
&
host
->
lock
);
return
;
}
csr
=
inb
(
host
->
base
+
WBSD_CSR
);
WARN_ON
(
csr
==
0xff
);
if
(
csr
&
WBSD_CARDPRESENT
)
{
if
(
!
(
host
->
flags
&
WBSD_FCARD_PRESENT
))
{
DBG
(
"Card inserted
\n
"
);
host
->
flags
|=
WBSD_FCARD_PRESENT
;
spin_unlock
(
&
host
->
lock
);
/*
* Delay card detection to allow electrical connections
* to stabilise.
*/
mmc_detect_change
(
host
->
mmc
,
msecs_to_jiffies
(
500
));
delay
=
500
;
}
else
spin_unlock
(
&
host
->
lock
);
}
else
if
(
host
->
flags
&
WBSD_FCARD_PRESENT
)
{
DBG
(
"Card removed
\n
"
);
host
->
flags
&=
~
WBSD_FCARD_PRESENT
;
if
(
host
->
mrq
)
{
printk
(
KERN_ERR
DRIVER_NAME
": Card removed during transfer!
\n
"
);
wbsd_reset
(
host
);
host
->
mrq
->
cmd
->
error
=
MMC_ERR_FAILED
;
tasklet_schedule
(
&
host
->
finish_tasklet
);
}
/*
* Unlock first since we might get a call back.
*/
spin_unlock
(
&
host
->
lock
);
mmc_detect_change
(
host
->
mmc
,
0
)
;
delay
=
0
;
}
else
spin_unlock
(
&
host
->
lock
);
/*
* Unlock first since we might get a call back.
*/
spin_unlock
(
&
host
->
lock
);
if
(
delay
!=
-
1
)
mmc_detect_change
(
host
->
mmc
,
msecs_to_jiffies
(
delay
));
}
static
void
wbsd_tasklet_fifo
(
unsigned
long
param
)
{
struct
wbsd_host
*
host
=
(
struct
wbsd_host
*
)
param
;
struct
mmc_data
*
data
;
spin_lock
(
&
host
->
lock
);
if
(
!
host
->
mrq
)
goto
end
;
data
=
wbsd_get_data
(
host
);
if
(
!
data
)
goto
end
;
...
...
@@ -1220,7 +1215,7 @@ static void wbsd_tasklet_fifo(unsigned long param)
tasklet_schedule
(
&
host
->
finish_tasklet
);
}
end:
end:
spin_unlock
(
&
host
->
lock
);
}
...
...
@@ -1228,23 +1223,23 @@ static void wbsd_tasklet_crc(unsigned long param)
{
struct
wbsd_host
*
host
=
(
struct
wbsd_host
*
)
param
;
struct
mmc_data
*
data
;
spin_lock
(
&
host
->
lock
);
if
(
!
host
->
mrq
)
goto
end
;
data
=
wbsd_get_data
(
host
);
if
(
!
data
)
goto
end
;
DBGF
(
"CRC error
\n
"
);
data
->
error
=
MMC_ERR_BADCRC
;
tasklet_schedule
(
&
host
->
finish_tasklet
);
end:
end:
spin_unlock
(
&
host
->
lock
);
}
...
...
@@ -1252,23 +1247,23 @@ static void wbsd_tasklet_timeout(unsigned long param)
{
struct
wbsd_host
*
host
=
(
struct
wbsd_host
*
)
param
;
struct
mmc_data
*
data
;
spin_lock
(
&
host
->
lock
);
if
(
!
host
->
mrq
)
goto
end
;
data
=
wbsd_get_data
(
host
);
if
(
!
data
)
goto
end
;
DBGF
(
"Timeout
\n
"
);
data
->
error
=
MMC_ERR_TIMEOUT
;
tasklet_schedule
(
&
host
->
finish_tasklet
);
end:
end:
spin_unlock
(
&
host
->
lock
);
}
...
...
@@ -1276,20 +1271,20 @@ static void wbsd_tasklet_finish(unsigned long param)
{
struct
wbsd_host
*
host
=
(
struct
wbsd_host
*
)
param
;
struct
mmc_data
*
data
;
spin_lock
(
&
host
->
lock
);
WARN_ON
(
!
host
->
mrq
);
if
(
!
host
->
mrq
)
goto
end
;
data
=
wbsd_get_data
(
host
);
if
(
!
data
)
goto
end
;
wbsd_finish_data
(
host
,
data
);
end:
end:
spin_unlock
(
&
host
->
lock
);
}
...
...
@@ -1297,7 +1292,7 @@ static void wbsd_tasklet_block(unsigned long param)
{
struct
wbsd_host
*
host
=
(
struct
wbsd_host
*
)
param
;
struct
mmc_data
*
data
;
spin_lock
(
&
host
->
lock
);
if
((
wbsd_read_index
(
host
,
WBSD_IDX_CRCSTATUS
)
&
WBSD_CRC_MASK
)
!=
...
...
@@ -1306,15 +1301,15 @@ static void wbsd_tasklet_block(unsigned long param)
data
=
wbsd_get_data
(
host
);
if
(
!
data
)
goto
end
;
DBGF
(
"CRC error
\n
"
);
data
->
error
=
MMC_ERR_BADCRC
;
tasklet_schedule
(
&
host
->
finish_tasklet
);
}
end:
end:
spin_unlock
(
&
host
->
lock
);
}
...
...
@@ -1326,7 +1321,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct
wbsd_host
*
host
=
dev_id
;
int
isr
;
isr
=
inb
(
host
->
base
+
WBSD_ISR
);
/*
...
...
@@ -1334,7 +1329,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
*/
if
(
isr
==
0xff
||
isr
==
0x00
)
return
IRQ_NONE
;
host
->
isr
|=
isr
;
/*
...
...
@@ -1352,7 +1347,7 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
tasklet_hi_schedule
(
&
host
->
block_tasklet
);
if
(
isr
&
WBSD_INT_TC
)
tasklet_schedule
(
&
host
->
finish_tasklet
);
return
IRQ_HANDLED
;
}
...
...
@@ -1370,14 +1365,14 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
{
struct
mmc_host
*
mmc
;
struct
wbsd_host
*
host
;
/*
* Allocate MMC structure.
*/
mmc
=
mmc_alloc_host
(
sizeof
(
struct
wbsd_host
),
dev
);
if
(
!
mmc
)
return
-
ENOMEM
;
host
=
mmc_priv
(
mmc
);
host
->
mmc
=
mmc
;
...
...
@@ -1391,37 +1386,37 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
mmc
->
f_max
=
24000000
;
mmc
->
ocr_avail
=
MMC_VDD_32_33
|
MMC_VDD_33_34
;
mmc
->
caps
=
MMC_CAP_4_BIT_DATA
;
spin_lock_init
(
&
host
->
lock
);
/*
* Set up timers
*/
init_timer
(
&
host
->
ignore_timer
);
host
->
ignore_timer
.
data
=
(
unsigned
long
)
host
;
host
->
ignore_timer
.
function
=
wbsd_reset_ignore
;
/*
* Maximum number of segments. Worst case is one sector per segment
* so this will be 64kB/512.
*/
mmc
->
max_hw_segs
=
128
;
mmc
->
max_phys_segs
=
128
;
/*
* Maximum number of sectors in one transfer. Also limited by 64kB
* buffer.
*/
mmc
->
max_sectors
=
128
;
/*
* Maximum segment size. Could be one segment with the maximum number
* of segments.
*/
mmc
->
max_seg_size
=
mmc
->
max_sectors
*
512
;
dev_set_drvdata
(
dev
,
mmc
);
return
0
;
}
...
...
@@ -1429,18 +1424,18 @@ static void __devexit wbsd_free_mmc(struct device* dev)
{
struct
mmc_host
*
mmc
;
struct
wbsd_host
*
host
;
mmc
=
dev_get_drvdata
(
dev
);
if
(
!
mmc
)
return
;
host
=
mmc_priv
(
mmc
);
BUG_ON
(
host
==
NULL
);
del_timer_sync
(
&
host
->
ignore_timer
);
mmc_free_host
(
mmc
);
dev_set_drvdata
(
dev
,
NULL
);
}
...
...
@@ -1452,7 +1447,7 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{
int
i
,
j
,
k
;
int
id
;
/*
* Iterate through all ports, all codes to
* find hardware that is in our known list.
...
...
@@ -1461,32 +1456,32 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
{
if
(
!
request_region
(
config_ports
[
i
],
2
,
DRIVER_NAME
))
continue
;
for
(
j
=
0
;
j
<
sizeof
(
unlock_codes
)
/
sizeof
(
int
);
j
++
)
{
id
=
0xFFFF
;
outb
(
unlock_codes
[
j
],
config_ports
[
i
]);
outb
(
unlock_codes
[
j
],
config_ports
[
i
]);
outb
(
WBSD_CONF_ID_HI
,
config_ports
[
i
]);
id
=
inb
(
config_ports
[
i
]
+
1
)
<<
8
;
outb
(
WBSD_CONF_ID_LO
,
config_ports
[
i
]);
id
|=
inb
(
config_ports
[
i
]
+
1
);
for
(
k
=
0
;
k
<
sizeof
(
valid_ids
)
/
sizeof
(
int
);
k
++
)
{
if
(
id
==
valid_ids
[
k
])
{
{
host
->
chip_id
=
id
;
host
->
config
=
config_ports
[
i
];
host
->
unlock_code
=
unlock_codes
[
i
];
return
0
;
}
}
if
(
id
!=
0xFFFF
)
{
DBG
(
"Unknown hardware (id %x) found at %x
\n
"
,
...
...
@@ -1495,10 +1490,10 @@ static int __devinit wbsd_scan(struct wbsd_host* host)
outb
(
LOCK_CODE
,
config_ports
[
i
]);
}
release_region
(
config_ports
[
i
],
2
);
}
return
-
ENODEV
;
}
...
...
@@ -1510,12 +1505,12 @@ static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
{
if
(
io
&
0x7
)
return
-
EINVAL
;
if
(
!
request_region
(
base
,
8
,
DRIVER_NAME
))
return
-
EIO
;
host
->
base
=
io
;
return
0
;
}
...
...
@@ -1523,12 +1518,12 @@ static void __devexit wbsd_release_regions(struct wbsd_host* host)
{
if
(
host
->
base
)
release_region
(
host
->
base
,
8
);
host
->
base
=
0
;
if
(
host
->
config
)
release_region
(
host
->
config
,
2
);
host
->
config
=
0
;
}
...
...
@@ -1540,10 +1535,10 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
{
if
(
dma
<
0
)
return
;
if
(
request_dma
(
dma
,
DRIVER_NAME
))
goto
err
;
/*
* We need to allocate a special buffer in
* order for ISA to be able to DMA to it.
...
...
@@ -1558,7 +1553,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
*/
host
->
dma_addr
=
dma_map_single
(
host
->
mmc
->
dev
,
host
->
dma_buffer
,
WBSD_DMA_SIZE
,
DMA_BIDIRECTIONAL
);
/*
* ISA DMA must be aligned on a 64k basis.
*/
...
...
@@ -1571,19 +1566,19 @@ static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
goto
kfree
;
host
->
dma
=
dma
;
return
;
kfree:
/*
* If we've gotten here then there is some kind of alignment bug
*/
BUG_ON
(
1
);
dma_unmap_single
(
host
->
mmc
->
dev
,
host
->
dma_addr
,
WBSD_DMA_SIZE
,
DMA_BIDIRECTIONAL
);
host
->
dma_addr
=
(
dma_addr_t
)
NULL
;
kfree
(
host
->
dma_buffer
);
host
->
dma_buffer
=
NULL
;
...
...
@@ -1604,7 +1599,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
kfree
(
host
->
dma_buffer
);
if
(
host
->
dma
>=
0
)
free_dma
(
host
->
dma
);
host
->
dma
=
-
1
;
host
->
dma_buffer
=
NULL
;
host
->
dma_addr
=
(
dma_addr_t
)
NULL
;
...
...
@@ -1617,7 +1612,7 @@ static void __devexit wbsd_release_dma(struct wbsd_host* host)
static
int
__devinit
wbsd_request_irq
(
struct
wbsd_host
*
host
,
int
irq
)
{
int
ret
;
/*
* Allocate interrupt.
*/
...
...
@@ -1625,7 +1620,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
ret
=
request_irq
(
irq
,
wbsd_irq
,
SA_SHIRQ
,
DRIVER_NAME
,
host
);
if
(
ret
)
return
ret
;
host
->
irq
=
irq
;
/*
...
...
@@ -1637,7 +1632,7 @@ static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
tasklet_init
(
&
host
->
timeout_tasklet
,
wbsd_tasklet_timeout
,
(
unsigned
long
)
host
);
tasklet_init
(
&
host
->
finish_tasklet
,
wbsd_tasklet_finish
,
(
unsigned
long
)
host
);
tasklet_init
(
&
host
->
block_tasklet
,
wbsd_tasklet_block
,
(
unsigned
long
)
host
);
return
0
;
}
...
...
@@ -1647,9 +1642,9 @@ static void __devexit wbsd_release_irq(struct wbsd_host* host)
return
;
free_irq
(
host
->
irq
,
host
);
host
->
irq
=
0
;
tasklet_kill
(
&
host
->
card_tasklet
);
tasklet_kill
(
&
host
->
fifo_tasklet
);
tasklet_kill
(
&
host
->
crc_tasklet
);
...
...
@@ -1666,7 +1661,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
int
base
,
int
irq
,
int
dma
)
{
int
ret
;
/*
* Allocate I/O ports.
*/
...
...
@@ -1685,7 +1680,7 @@ static int __devinit wbsd_request_resources(struct wbsd_host* host,
* Allocate DMA.
*/
wbsd_request_dma
(
host
,
dma
);
return
0
;
}
...
...
@@ -1708,7 +1703,7 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
{
/*
* Reset the chip.
*/
*/
wbsd_write_config
(
host
,
WBSD_CONF_SWRST
,
1
);
wbsd_write_config
(
host
,
WBSD_CONF_SWRST
,
0
);
...
...
@@ -1716,23 +1711,23 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
* Select SD/MMC function.
*/
wbsd_write_config
(
host
,
WBSD_CONF_DEVICE
,
DEVICE_SD
);
/*
* Set up card detection.
*/
wbsd_write_config
(
host
,
WBSD_CONF_PINS
,
WBSD_PINS_DETECT_GP11
);
/*
* Configure chip
*/
wbsd_write_config
(
host
,
WBSD_CONF_PORT_HI
,
host
->
base
>>
8
);
wbsd_write_config
(
host
,
WBSD_CONF_PORT_LO
,
host
->
base
&
0xff
);
wbsd_write_config
(
host
,
WBSD_CONF_IRQ
,
host
->
irq
);
if
(
host
->
dma
>=
0
)
wbsd_write_config
(
host
,
WBSD_CONF_DRQ
,
host
->
dma
);
/*
* Enable and power up chip.
*/
...
...
@@ -1743,26 +1738,26 @@ static void __devinit wbsd_chip_config(struct wbsd_host* host)
/*
* Check that configured resources are correct.
*/
static
int
__devinit
wbsd_chip_validate
(
struct
wbsd_host
*
host
)
{
int
base
,
irq
,
dma
;
/*
* Select SD/MMC function.
*/
wbsd_write_config
(
host
,
WBSD_CONF_DEVICE
,
DEVICE_SD
);
/*
* Read configuration.
*/
base
=
wbsd_read_config
(
host
,
WBSD_CONF_PORT_HI
)
<<
8
;
base
|=
wbsd_read_config
(
host
,
WBSD_CONF_PORT_LO
);
irq
=
wbsd_read_config
(
host
,
WBSD_CONF_IRQ
);
dma
=
wbsd_read_config
(
host
,
WBSD_CONF_DRQ
);
/*
* Validate against given configuration.
*/
...
...
@@ -1772,7 +1767,7 @@ static int __devinit wbsd_chip_validate(struct wbsd_host* host)
return
0
;
if
((
dma
!=
host
->
dma
)
&&
(
host
->
dma
!=
-
1
))
return
0
;
return
1
;
}
...
...
@@ -1788,14 +1783,14 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
struct
wbsd_host
*
host
=
NULL
;
struct
mmc_host
*
mmc
=
NULL
;
int
ret
;
ret
=
wbsd_alloc_mmc
(
dev
);
if
(
ret
)
return
ret
;
mmc
=
dev_get_drvdata
(
dev
);
host
=
mmc_priv
(
mmc
);
/*
* Scan for hardware.
*/
...
...
@@ -1814,7 +1809,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
return
ret
;
}
}
/*
* Request resources.
*/
...
...
@@ -1825,7 +1820,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
wbsd_free_mmc
(
dev
);
return
ret
;
}
/*
* See if chip needs to be configured.
*/
...
...
@@ -1842,7 +1837,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
}
else
wbsd_chip_config
(
host
);
/*
* Power Management stuff. No idea how this works.
* Not tested.
...
...
@@ -1860,7 +1855,7 @@ static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
* Reset the chip into a known state.
*/
wbsd_init_device
(
host
);
mmc_add_host
(
mmc
);
printk
(
KERN_INFO
"%s: W83L51xD"
,
mmc_hostname
(
mmc
));
...
...
@@ -1882,12 +1877,12 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
{
struct
mmc_host
*
mmc
=
dev_get_drvdata
(
dev
);
struct
wbsd_host
*
host
;
if
(
!
mmc
)
return
;
host
=
mmc_priv
(
mmc
);
mmc_remove_host
(
mmc
);
if
(
!
pnp
)
...
...
@@ -1900,9 +1895,9 @@ static void __devexit wbsd_shutdown(struct device* dev, int pnp)
wbsd_write_config
(
host
,
WBSD_CONF_ENABLE
,
0
);
wbsd_lock_config
(
host
);
}
wbsd_release_resources
(
host
);
wbsd_free_mmc
(
dev
);
}
...
...
@@ -1932,7 +1927,7 @@ static int __devinit
wbsd_pnp_probe
(
struct
pnp_dev
*
pnpdev
,
const
struct
pnp_device_id
*
dev_id
)
{
int
io
,
irq
,
dma
;
/*
* Get resources from PnP layer.
*/
...
...
@@ -1942,9 +1937,9 @@ wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
dma
=
pnp_dma
(
pnpdev
,
0
);
else
dma
=
-
1
;
DBGF
(
"PnP resources: port %3x irq %d dma %d
\n
"
,
io
,
irq
,
dma
);
return
wbsd_init
(
&
pnpdev
->
dev
,
io
,
irq
,
dma
,
1
);
}
...
...
@@ -1985,7 +1980,7 @@ static struct device_driver wbsd_driver = {
.
bus
=
&
platform_bus_type
,
.
probe
=
wbsd_probe
,
.
remove
=
wbsd_remove
,
.
suspend
=
wbsd_suspend
,
.
resume
=
wbsd_resume
,
};
...
...
@@ -2008,7 +2003,7 @@ static struct pnp_driver wbsd_pnp_driver = {
static
int
__init
wbsd_drv_init
(
void
)
{
int
result
;
printk
(
KERN_INFO
DRIVER_NAME
": Winbond W83L51xD SD/MMC card interface driver, "
DRIVER_VERSION
"
\n
"
);
...
...
@@ -2023,8 +2018,8 @@ static int __init wbsd_drv_init(void)
return
result
;
}
#endif
/* CONFIG_PNP */
#endif
/* CONFIG_PNP */
if
(
nopnp
)
{
result
=
driver_register
(
&
wbsd_driver
);
...
...
@@ -2046,13 +2041,13 @@ static void __exit wbsd_drv_exit(void)
if
(
!
nopnp
)
pnp_unregister_driver
(
&
wbsd_pnp_driver
);
#endif
/* CONFIG_PNP */
#endif
/* CONFIG_PNP */
if
(
nopnp
)
{
platform_device_unregister
(
wbsd_device
);
driver_unregister
(
&
wbsd_driver
);
}
...
...
drivers/mmc/wbsd.h
View file @
bd6fe9e1
...
...
@@ -139,51 +139,50 @@
struct
wbsd_host
{
struct
mmc_host
*
mmc
;
/* MMC structure */
spinlock_t
lock
;
/* Mutex */
int
flags
;
/* Driver states */
#define WBSD_FCARD_PRESENT (1<<0)
/* Card is present */
#define WBSD_FIGNORE_DETECT (1<<1)
/* Ignore card detection */
struct
mmc_request
*
mrq
;
/* Current request */
u8
isr
;
/* Accumulated ISR */
struct
scatterlist
*
cur_sg
;
/* Current SG entry */
unsigned
int
num_sg
;
/* Number of entries left */
void
*
mapped_sg
;
/* vaddr of mapped sg */
unsigned
int
offset
;
/* Offset into current entry */
unsigned
int
remain
;
/* Data left in curren entry */
int
size
;
/* Total size of transfer */
char
*
dma_buffer
;
/* ISA DMA buffer */
dma_addr_t
dma_addr
;
/* Physical address for same */
int
firsterr
;
/* See fifo functions */
u8
clk
;
/* Current clock speed */
unsigned
char
bus_width
;
/* Current bus width */
int
config
;
/* Config port */
u8
unlock_code
;
/* Code to unlock config */
int
chip_id
;
/* ID of controller */
int
base
;
/* I/O port base */
int
irq
;
/* Interrupt */
int
dma
;
/* DMA channel */
struct
tasklet_struct
card_tasklet
;
/* Tasklet structures */
struct
tasklet_struct
fifo_tasklet
;
struct
tasklet_struct
crc_tasklet
;
struct
tasklet_struct
timeout_tasklet
;
struct
tasklet_struct
finish_tasklet
;
struct
tasklet_struct
block_tasklet
;
struct
timer_list
detect_timer
;
/* Card detection timer */
struct
timer_list
ignore_timer
;
/* Ignore detection timer */
};
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