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
4f5381ac
Commit
4f5381ac
authored
Nov 14, 2004
by
Russell King
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[ARM] icside: use MMIO for board specific registers.
parent
64943205
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
139 additions
and
83 deletions
+139
-83
drivers/ide/arm/icside.c
drivers/ide/arm/icside.c
+139
-83
No files found.
drivers/ide/arm/icside.c
View file @
4f5381ac
/*
* linux/drivers/ide/arm/icside.c
*
* Copyright (c) 1996-2003 Russell King.
* Copyright (c) 1996-2004 Russell King.
*
* Please note that this platform does not support 32-bit IDE IO.
*/
#include <linux/config.h>
...
...
@@ -24,19 +26,19 @@
#define ICS_IDENT_OFFSET 0x2280
#define ICS_ARCIN_V5_INTRSTAT 0x000
#define ICS_ARCIN_V5_INTROFFSET 0x00
1
#define ICS_ARCIN_V5_INTRSTAT 0x000
0
#define ICS_ARCIN_V5_INTROFFSET 0x00
04
#define ICS_ARCIN_V5_IDEOFFSET 0xa00
#define ICS_ARCIN_V5_IDEALTOFFSET 0xae0
#define ICS_ARCIN_V5_IDESTEPPING 4
#define ICS_ARCIN_V6_IDEOFFSET_1 0x800
#define ICS_ARCIN_V6_INTROFFSET_1 0x
88
0
#define ICS_ARCIN_V6_INTRSTAT_1 0x
8a4
#define ICS_ARCIN_V6_INTROFFSET_1 0x
220
0
#define ICS_ARCIN_V6_INTRSTAT_1 0x
2290
#define ICS_ARCIN_V6_IDEALTOFFSET_1 0x8e0
#define ICS_ARCIN_V6_IDEOFFSET_2 0xc00
#define ICS_ARCIN_V6_INTROFFSET_2 0x
c8
0
#define ICS_ARCIN_V6_INTRSTAT_2 0x
ca4
#define ICS_ARCIN_V6_INTROFFSET_2 0x
320
0
#define ICS_ARCIN_V6_INTRSTAT_2 0x
3290
#define ICS_ARCIN_V6_IDEALTOFFSET_2 0xce0
#define ICS_ARCIN_V6_IDESTEPPING 4
...
...
@@ -47,28 +49,28 @@ struct cardinfo {
};
static
struct
cardinfo
icside_cardinfo_v5
=
{
ICS_ARCIN_V5_IDEOFFSET
,
ICS_ARCIN_V5_IDEALTOFFSET
,
ICS_ARCIN_V5_IDESTEPPING
.
dataoffset
=
ICS_ARCIN_V5_IDEOFFSET
,
.
ctrloffset
=
ICS_ARCIN_V5_IDEALTOFFSET
,
.
stepping
=
ICS_ARCIN_V5_IDESTEPPING
,
};
static
struct
cardinfo
icside_cardinfo_v6_1
=
{
ICS_ARCIN_V6_IDEOFFSET_1
,
ICS_ARCIN_V6_IDEALTOFFSET_1
,
ICS_ARCIN_V6_IDESTEPPING
.
dataoffset
=
ICS_ARCIN_V6_IDEOFFSET_1
,
.
ctrloffset
=
ICS_ARCIN_V6_IDEALTOFFSET_1
,
.
stepping
=
ICS_ARCIN_V6_IDESTEPPING
,
};
static
struct
cardinfo
icside_cardinfo_v6_2
=
{
ICS_ARCIN_V6_IDEOFFSET_2
,
ICS_ARCIN_V6_IDEALTOFFSET_2
,
ICS_ARCIN_V6_IDESTEPPING
.
dataoffset
=
ICS_ARCIN_V6_IDEOFFSET_2
,
.
ctrloffset
=
ICS_ARCIN_V6_IDEALTOFFSET_2
,
.
stepping
=
ICS_ARCIN_V6_IDESTEPPING
,
};
struct
icside_state
{
unsigned
int
channel
;
unsigned
int
enabled
;
unsigned
long
irq_port
;
unsigned
long
slot_port
;
void
__iomem
*
irq_port
;
void
__iomem
*
ioc_base
;
unsigned
int
type
;
/* parent device... until the IDE core gets one of its own */
struct
device
*
dev
;
...
...
@@ -88,9 +90,8 @@ struct icside_state {
static
void
icside_irqenable_arcin_v5
(
struct
expansion_card
*
ec
,
int
irqnr
)
{
struct
icside_state
*
state
=
ec
->
irq_data
;
unsigned
int
base
=
state
->
irq_port
;
outb
(
0
,
base
+
ICS_ARCIN_V5_INTROFFSET
);
writeb
(
0
,
state
->
irq_port
+
ICS_ARCIN_V5_INTROFFSET
);
}
/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
...
...
@@ -99,9 +100,8 @@ static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
static
void
icside_irqdisable_arcin_v5
(
struct
expansion_card
*
ec
,
int
irqnr
)
{
struct
icside_state
*
state
=
ec
->
irq_data
;
unsigned
int
base
=
state
->
irq_port
;
inb
(
base
+
ICS_ARCIN_V5_INTROFFSET
);
readb
(
state
->
irq_port
+
ICS_ARCIN_V5_INTROFFSET
);
}
static
const
expansioncard_ops_t
icside_ops_arcin_v5
=
{
...
...
@@ -117,18 +117,18 @@ static const expansioncard_ops_t icside_ops_arcin_v5 = {
static
void
icside_irqenable_arcin_v6
(
struct
expansion_card
*
ec
,
int
irqnr
)
{
struct
icside_state
*
state
=
ec
->
irq_data
;
unsigned
int
base
=
state
->
irq_port
;
void
__iomem
*
base
=
state
->
irq_port
;
state
->
enabled
=
1
;
switch
(
state
->
channel
)
{
case
0
:
out
b
(
0
,
base
+
ICS_ARCIN_V6_INTROFFSET_1
);
in
b
(
base
+
ICS_ARCIN_V6_INTROFFSET_2
);
write
b
(
0
,
base
+
ICS_ARCIN_V6_INTROFFSET_1
);
read
b
(
base
+
ICS_ARCIN_V6_INTROFFSET_2
);
break
;
case
1
:
out
b
(
0
,
base
+
ICS_ARCIN_V6_INTROFFSET_2
);
in
b
(
base
+
ICS_ARCIN_V6_INTROFFSET_1
);
write
b
(
0
,
base
+
ICS_ARCIN_V6_INTROFFSET_2
);
read
b
(
base
+
ICS_ARCIN_V6_INTROFFSET_1
);
break
;
}
}
...
...
@@ -142,8 +142,8 @@ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
state
->
enabled
=
0
;
inb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
inb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
readb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
readb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
}
/* Prototype: icside_irqprobe(struct expansion_card *ec)
...
...
@@ -153,8 +153,8 @@ static int icside_irqpending_arcin_v6(struct expansion_card *ec)
{
struct
icside_state
*
state
=
ec
->
irq_data
;
return
in
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTRSTAT_1
)
&
1
||
in
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTRSTAT_2
)
&
1
;
return
read
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTRSTAT_1
)
&
1
||
read
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTRSTAT_2
)
&
1
;
}
static
const
expansioncard_ops_t
icside_ops_arcin_v6
=
{
...
...
@@ -180,17 +180,17 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
if
(
state
->
enabled
&&
!
mask
)
{
switch
(
hwif
->
channel
)
{
case
0
:
out
b
(
0
,
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
in
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
write
b
(
0
,
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
read
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
break
;
case
1
:
out
b
(
0
,
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
in
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
write
b
(
0
,
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
read
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
break
;
}
}
else
{
in
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
in
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
read
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
read
b
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
}
local_irq_restore
(
flags
);
...
...
@@ -452,7 +452,7 @@ static int icside_dma_setup(ide_drive_t *drive)
/*
* Route the DMA signals to the correct interface.
*/
out
b
(
hwif
->
select_data
,
hwif
->
config_data
);
write
b
(
hwif
->
select_data
,
hwif
->
config_data
);
/*
* Select the correct timing for this drive.
...
...
@@ -482,7 +482,7 @@ static int icside_dma_test_irq(ide_drive_t *drive)
ide_hwif_t
*
hwif
=
HWIF
(
drive
);
struct
icside_state
*
state
=
hwif
->
hwif_data
;
return
in
b
(
state
->
irq_port
+
return
read
b
(
state
->
irq_port
+
(
hwif
->
channel
?
ICS_ARCIN_V6_INTRSTAT_2
:
ICS_ARCIN_V6_INTRSTAT_1
))
&
1
;
...
...
@@ -604,12 +604,17 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
{
unsigned
long
slot_port
;
ide_hwif_t
*
hwif
;
void
__iomem
*
base
;
slot_port
=
ecard_address
(
ec
,
ECARD_MEMC
,
0
);
base
=
ioremap
(
ecard_resource_start
(
ec
,
ECARD_RES_MEMC
),
ecard_resource_len
(
ec
,
ECARD_RES_MEMC
));
if
(
!
base
)
return
-
ENOMEM
;
state
->
irq_port
=
slot_port
;
state
->
irq_port
=
base
;
ec
->
irqaddr
=
(
unsigned
char
*
)
ioaddr
(
slot_port
+
ICS_ARCIN_V5_INTRSTAT
)
;
ec
->
irqaddr
=
base
+
ICS_ARCIN_V5_INTRSTAT
;
ec
->
irqmask
=
1
;
ec
->
irq_data
=
state
;
ec
->
ops
=
&
icside_ops_arcin_v5
;
...
...
@@ -617,13 +622,17 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
/*
* Be on the safe side - disable interrupts
*/
i
nb
(
slot_port
+
ICS_ARCIN_V5_INTROFFSET
);
i
cside_irqdisable_arcin_v5
(
ec
,
0
);
hwif
=
icside_setup
(
slot_port
,
&
icside_cardinfo_v5
,
ec
);
if
(
!
hwif
)
{
iounmap
(
base
);
return
-
ENODEV
;
}
state
->
hwif
[
0
]
=
hwif
;
return
hwif
?
0
:
-
ENODEV
;
return
0
;
}
static
int
__init
...
...
@@ -631,23 +640,50 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
{
unsigned
long
slot_port
,
port
;
ide_hwif_t
*
hwif
,
*
mate
;
void
__iomem
*
ioc_base
,
*
easi_base
;
unsigned
int
sel
=
0
;
int
ret
;
slot_port
=
ecard_address
(
ec
,
ECARD_IOC
,
ECARD_FAST
);
port
=
ecard_address
(
ec
,
ECARD_EASI
,
ECARD_FAST
);
if
(
port
==
0
)
port
=
slot_port
;
else
ioc_base
=
ioremap
(
ecard_resource_start
(
ec
,
ECARD_RES_IOCFAST
),
ecard_resource_len
(
ec
,
ECARD_RES_IOCFAST
));
if
(
!
ioc_base
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
easi_base
=
ioc_base
;
if
(
ecard_resource_flags
(
ec
,
ECARD_RES_EASI
))
{
easi_base
=
ioremap
(
ecard_resource_start
(
ec
,
ECARD_RES_EASI
),
ecard_resource_len
(
ec
,
ECARD_RES_EASI
));
if
(
!
easi_base
)
{
ret
=
-
ENOMEM
;
goto
unmap_slot
;
}
/*
* Enable access to the EASI region.
*/
sel
=
1
<<
5
;
}
outb
(
sel
,
slot_port
);
writeb
(
sel
,
ioc_base
);
ec
->
irq_data
=
state
;
ec
->
ops
=
&
icside_ops_arcin_v6
;
state
->
irq_port
=
easi_base
;
state
->
ioc_base
=
ioc_base
;
/*
* Be on the safe side - disable interrupts
*/
inb
(
port
+
ICS_ARCIN_V6_INTROFFSET_1
);
inb
(
port
+
ICS_ARCIN_V6_INTROFFSET_2
);
icside_irqdisable_arcin_v6
(
ec
,
0
);
/*
* Find and register the interfaces.
...
...
@@ -655,23 +691,20 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
hwif
=
icside_setup
(
port
,
&
icside_cardinfo_v6_1
,
ec
);
mate
=
icside_setup
(
port
,
&
icside_cardinfo_v6_2
,
ec
);
if
(
!
hwif
||
!
mate
)
return
-
ENODEV
;
if
(
!
hwif
||
!
mate
)
{
ret
=
-
ENODEV
;
goto
unmap_port
;
}
state
->
irq_port
=
port
;
state
->
slot_port
=
slot_port
;
state
->
hwif
[
0
]
=
hwif
;
state
->
hwif
[
1
]
=
mate
;
ec
->
irq_data
=
state
;
ec
->
ops
=
&
icside_ops_arcin_v6
;
hwif
->
maskproc
=
icside_maskproc
;
hwif
->
channel
=
0
;
hwif
->
hwif_data
=
state
;
hwif
->
mate
=
mate
;
hwif
->
serialized
=
1
;
hwif
->
config_data
=
slot_port
;
hwif
->
config_data
=
(
unsigned
long
)
ioc_base
;
hwif
->
select_data
=
sel
;
hwif
->
hw
.
dma
=
ec
->
dma
;
...
...
@@ -680,7 +713,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
mate
->
hwif_data
=
state
;
mate
->
mate
=
hwif
;
mate
->
serialized
=
1
;
mate
->
config_data
=
slot_port
;
mate
->
config_data
=
(
unsigned
long
)
ioc_base
;
mate
->
select_data
=
sel
|
1
;
mate
->
hw
.
dma
=
ec
->
dma
;
...
...
@@ -690,6 +723,14 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
}
return
0
;
unmap_port:
if
(
easi_base
!=
ioc_base
)
iounmap
(
easi_base
);
unmap_slot:
iounmap
(
ioc_base
);
out:
return
ret
;
}
static
int
__devinit
...
...
@@ -699,10 +740,14 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
void
*
idmem
;
int
ret
;
ret
=
ecard_request_resources
(
ec
);
if
(
ret
)
goto
out
;
state
=
kmalloc
(
sizeof
(
struct
icside_state
),
GFP_KERNEL
);
if
(
!
state
)
{
ret
=
-
ENOMEM
;
goto
out
;
goto
release
;
}
memset
(
state
,
0
,
sizeof
(
state
));
...
...
@@ -725,12 +770,12 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
switch
(
state
->
type
)
{
case
ICS_TYPE_A3IN
:
printk
(
KERN_WARNING
"icside:
A3IN unsupported
\n
"
);
dev_warn
(
&
ec
->
dev
,
"
A3IN unsupported
\n
"
);
ret
=
-
ENODEV
;
break
;
case
ICS_TYPE_A3USER
:
printk
(
KERN_WARNING
"icside:
A3USER unsupported
\n
"
);
dev_warn
(
&
ec
->
dev
,
"
A3USER unsupported
\n
"
);
ret
=
-
ENODEV
;
break
;
...
...
@@ -743,15 +788,19 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
break
;
default:
printk
(
KERN_WARNING
"icside:
unknown interface type
\n
"
);
dev_warn
(
&
ec
->
dev
,
"
unknown interface type
\n
"
);
ret
=
-
ENODEV
;
break
;
}
if
(
ret
==
0
)
if
(
ret
==
0
)
{
ecard_set_drvdata
(
ec
,
state
);
else
goto
out
;
}
kfree
(
state
);
release:
ecard_release_resources
(
ec
);
out:
return
ret
;
}
...
...
@@ -765,7 +814,7 @@ static void __devexit icside_remove(struct expansion_card *ec)
/* FIXME: tell IDE to stop using the interface */
/* Disable interrupts */
i
nb
(
state
->
slot_port
+
ICS_ARCIN_V5_INTROFFSET
);
i
cside_irqdisable_arcin_v5
(
ec
,
0
);
break
;
case
ICS_TYPE_V6
:
...
...
@@ -774,11 +823,10 @@ static void __devexit icside_remove(struct expansion_card *ec)
free_dma
(
ec
->
dma
);
/* Disable interrupts */
inb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
inb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
icside_irqdisable_arcin_v6
(
ec
,
0
);
/* Reset the ROM pointer/EASI selection */
outb
(
0
,
state
->
slot_port
);
writeb
(
0
,
state
->
ioc_base
);
break
;
}
...
...
@@ -786,28 +834,36 @@ static void __devexit icside_remove(struct expansion_card *ec)
ec
->
ops
=
NULL
;
ec
->
irq_data
=
NULL
;
if
(
state
->
ioc_base
)
iounmap
(
state
->
ioc_base
);
if
(
state
->
ioc_base
!=
state
->
irq_port
)
iounmap
(
state
->
irq_port
);
kfree
(
state
);
ecard_release_resources
(
ec
);
}
static
void
icside_shutdown
(
struct
expansion_card
*
ec
)
{
struct
icside_state
*
state
=
ecard_get_drvdata
(
ec
);
unsigned
long
flags
;
switch
(
state
->
type
)
{
case
ICS_TYPE_V5
:
/* Disable interrupts */
inb
(
state
->
slot_port
+
ICS_ARCIN_V5_INTROFFSET
);
break
;
case
ICS_TYPE_V6
:
/* Disable interrupts */
inb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_1
);
inb
(
state
->
irq_port
+
ICS_ARCIN_V6_INTROFFSET_2
);
/*
* Disable interrupts from this card. We need to do
* this before disabling EASI since we may be accessing
* this register via that region.
*/
local_irq_save
(
flags
);
ec
->
ops
->
irqdisable
(
ec
,
0
);
local_irq_restore
(
flags
);
/* Reset the ROM pointer/EASI selection */
outb
(
0
,
state
->
slot_port
);
break
;
}
/*
* Reset the ROM pointer so that we can read the ROM
* after a soft reboot. This also disables access to
* the IDE taskfile via the EASI region.
*/
if
(
state
->
ioc_base
)
writeb
(
0
,
state
->
ioc_base
);
}
static
const
struct
ecard_id
icside_ids
[]
=
{
...
...
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