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
2f766895
Commit
2f766895
authored
Sep 04, 2002
by
Paul Mackerras
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
PPC32: Convert the various PCI config space accessors to the new API.
parent
bd039e05
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
337 additions
and
357 deletions
+337
-357
arch/ppc/kernel/Makefile
arch/ppc/kernel/Makefile
+1
-1
arch/ppc/kernel/indirect_pci.c
arch/ppc/kernel/indirect_pci.c
+72
-32
arch/ppc/kernel/pci.c
arch/ppc/kernel/pci.c
+34
-29
arch/ppc/kernel/ppc_ksyms.c
arch/ppc/kernel/ppc_ksyms.c
+1
-0
arch/ppc/platforms/apus_pci.c
arch/ppc/platforms/apus_pci.c
+61
-38
arch/ppc/platforms/chrp_pci.c
arch/ppc/platforms/chrp_pci.c
+80
-110
arch/ppc/platforms/gemini_pci.c
arch/ppc/platforms/gemini_pci.c
+1
-79
arch/ppc/platforms/pmac_pci.c
arch/ppc/platforms/pmac_pci.c
+86
-68
include/asm-ppc/pci-bridge.h
include/asm-ppc/pci-bridge.h
+1
-0
No files found.
arch/ppc/kernel/Makefile
View file @
2f766895
...
...
@@ -60,7 +60,7 @@ obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \
todc_time.o
obj-$(CONFIG_EV64260)
+=
gt64260_common.o gt64260_pic.o
\
indirect_pci.o todc_time.o pci_auto.o
obj-$(CONFIG_GEMINI)
+=
open_pic.o i8259.o
obj-$(CONFIG_GEMINI)
+=
open_pic.o i8259.o
indirect_pci.o
obj-$(CONFIG_K2)
+=
i8259.o indirect_pci.o todc_time.o
\
pci_auto.o
obj-$(CONFIG_LOPEC)
+=
mpc10x_common.o indirect_pci.o pci_auto.o
\
...
...
arch/ppc/kernel/indirect_pci.c
View file @
2f766895
...
...
@@ -24,48 +24,88 @@
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
static
int
indirect_read_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
*
val
)
{
struct
pci_controller
*
hose
=
bus
->
sysdata
;
volatile
unsigned
char
*
cfg_data
;
if
(
ppc_md
.
pci_exclude_device
)
if
(
ppc_md
.
pci_exclude_device
(
bus
->
number
,
devfn
))
return
PCIBIOS_DEVICE_NOT_FOUND
;
#define INDIRECT_PCI_OP(rw, size, type, op, mask) \
static int \
indirect_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
struct pci_controller *hose = dev->sysdata; \
\
if (ppc_md.pci_exclude_device) \
if (ppc_md.pci_exclude_device(dev->bus->number, dev->devfn)) \
return PCIBIOS_DEVICE_NOT_FOUND; \
\
out_be32(hose->cfg_addr, \
((offset & 0xfc) << 24) | (dev->devfn << 16) \
| ((dev->bus->number - hose->bus_offset) << 8) | 0x80); \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
return PCIBIOS_SUCCESSFUL; \
out_be32
(
hose
->
cfg_addr
,
((
offset
&
0xfc
)
<<
24
)
|
(
devfn
<<
16
)
|
((
bus
->
number
-
hose
->
bus_offset
)
<<
8
)
|
0x80
);
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
cfg_data
=
hose
->
cfg_data
+
(
offset
&
3
);
switch
(
len
)
{
case
1
:
*
val
=
in_8
((
u8
*
)
cfg_data
);
break
;
case
2
:
*
val
=
in_le16
((
u16
*
)
cfg_data
);
break
;
default:
*
val
=
in_le32
((
u32
*
)
cfg_data
);
break
;
}
return
PCIBIOS_SUCCESSFUL
;
}
INDIRECT_PCI_OP
(
read
,
byte
,
u8
*
,
in_8
,
3
)
INDIRECT_PCI_OP
(
read
,
word
,
u16
*
,
in_le16
,
2
)
INDIRECT_PCI_OP
(
read
,
dword
,
u32
*
,
in_le32
,
0
)
INDIRECT_PCI_OP
(
write
,
byte
,
u8
,
out_8
,
3
)
INDIRECT_PCI_OP
(
write
,
word
,
u16
,
out_le16
,
2
)
INDIRECT_PCI_OP
(
write
,
dword
,
u32
,
out_le32
,
0
)
static
int
indirect_write_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
val
)
{
struct
pci_controller
*
hose
=
bus
->
sysdata
;
volatile
unsigned
char
*
cfg_data
;
if
(
ppc_md
.
pci_exclude_device
)
if
(
ppc_md
.
pci_exclude_device
(
bus
->
number
,
devfn
))
return
PCIBIOS_DEVICE_NOT_FOUND
;
out_be32
(
hose
->
cfg_addr
,
((
offset
&
0xfc
)
<<
24
)
|
(
devfn
<<
16
)
|
((
bus
->
number
-
hose
->
bus_offset
)
<<
8
)
|
0x80
);
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
cfg_data
=
hose
->
cfg_data
+
(
offset
&
3
);
switch
(
len
)
{
case
1
:
out_8
((
u8
*
)
cfg_data
,
val
);
break
;
case
2
:
out_le16
((
u16
*
)
cfg_data
,
val
);
break
;
default:
out_le32
((
u32
*
)
cfg_data
,
val
);
break
;
}
return
PCIBIOS_SUCCESSFUL
;
}
static
struct
pci_ops
indirect_pci_ops
=
{
indirect_read_config_byte
,
indirect_read_config_word
,
indirect_read_config_dword
,
indirect_write_config_byte
,
indirect_write_config_word
,
indirect_write_config_dword
indirect_read_config
,
indirect_write_config
};
void
__init
setup_indirect_pci
(
struct
pci_controller
*
hose
,
u32
cfg_addr
,
u32
cfg_data
)
{
unsigned
long
base
=
cfg_addr
&
PAGE_MASK
;
char
*
mbase
;
mbase
=
ioremap
(
base
,
PAGE_SIZE
);
hose
->
cfg_addr
=
(
unsigned
int
*
)(
mbase
+
(
cfg_addr
&
~
PAGE_MASK
));
if
((
cfg_data
&
PAGE_MASK
)
!=
base
)
mbase
=
ioremap
(
cfg_data
&
PAGE_MASK
,
PAGE_SIZE
);
hose
->
cfg_data
=
(
unsigned
char
*
)(
mbase
+
(
cfg_data
&
~
PAGE_MASK
));
hose
->
ops
=
&
indirect_pci_ops
;
hose
->
cfg_addr
=
(
unsigned
int
*
)
ioremap
(
cfg_addr
,
4
);
hose
->
cfg_data
=
(
unsigned
char
*
)
ioremap
(
cfg_data
,
4
);
}
arch/ppc/kernel/pci.c
View file @
2f766895
...
...
@@ -816,19 +816,19 @@ scan_OF_childs_for_device(struct device_node* node, u8 bus, u8 dev_fn)
/*
* Scans the OF tree for a device node matching a PCI device
*/
struct
device_node
*
pci_
device_to_OF_node
(
struct
pci_dev
*
dev
)
struct
device_node
*
pci_
busdev_to_OF_node
(
struct
pci_bus
*
bus
,
int
devfn
)
{
struct
pci_controller
*
hose
;
struct
device_node
*
node
;
int
bus
;
int
bus
nr
;
if
(
!
have_of
)
return
NULL
;
/* Lookup the hose */
bus
=
dev
->
bus
->
number
;
hose
=
pci_bus_to_hose
(
bus
);
bus
nr
=
bus
->
number
;
hose
=
pci_bus_to_hose
(
bus
nr
);
if
(
!
hose
)
return
NULL
;
...
...
@@ -839,12 +839,18 @@ pci_device_to_OF_node(struct pci_dev *dev)
/* Fixup bus number according to what OF think it is. */
if
(
pci_to_OF_bus_map
)
bus
=
pci_to_OF_bus_map
[
bus
];
if
(
bus
==
0xff
)
bus
nr
=
pci_to_OF_bus_map
[
busnr
];
if
(
bus
nr
==
0xff
)
return
NULL
;
/* Now, lookup childs of the hose */
return
scan_OF_childs_for_device
(
node
->
child
,
bus
,
dev
->
devfn
);
return
scan_OF_childs_for_device
(
node
->
child
,
busnr
,
devfn
);
}
struct
device_node
*
pci_device_to_OF_node
(
struct
pci_dev
*
dev
)
{
return
pci_busdev_to_OF_node
(
dev
->
bus
,
dev
->
devfn
);
}
/* This routine is meant to be used early during boot, when the
...
...
@@ -1512,31 +1518,33 @@ null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
return PCIBIOS_DEVICE_NOT_FOUND; \
}
NULL_PCI_OP
(
read
,
byte
,
u8
*
)
NULL_PCI_OP
(
read
,
word
,
u16
*
)
NULL_PCI_OP
(
read
,
dword
,
u32
*
)
NULL_PCI_OP
(
write
,
byte
,
u8
)
NULL_PCI_OP
(
write
,
word
,
u16
)
NULL_PCI_OP
(
write
,
dword
,
u32
)
static
int
null_read_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
*
val
)
{
return
PCIBIOS_DEVICE_NOT_FOUND
;
}
static
int
null_write_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
val
)
{
return
PCIBIOS_DEVICE_NOT_FOUND
;
}
static
struct
pci_ops
null_pci_ops
=
{
null_read_config_byte
,
null_read_config_word
,
null_read_config_dword
,
null_write_config_byte
,
null_write_config_word
,
null_write_config_dword
null_read_config
,
null_write_config
};
/*
* These functions are used early on before PCI scanning is done
* and all of the pci_dev and pci_bus structures have been created.
*/
static
struct
pci_
dev
*
fake_pci_
dev
(
struct
pci_controller
*
hose
,
int
busnr
,
int
devfn
)
static
struct
pci_
bus
*
fake_pci_
bus
(
struct
pci_controller
*
hose
,
int
busnr
)
{
static
struct
pci_dev
dev
;
static
struct
pci_bus
bus
;
if
(
hose
==
0
)
{
...
...
@@ -1544,20 +1552,17 @@ fake_pci_dev(struct pci_controller *hose, int busnr, int devfn)
if
(
hose
==
0
)
printk
(
KERN_ERR
"Can't find hose for PCI bus %d!
\n
"
,
busnr
);
}
dev
.
bus
=
&
bus
;
dev
.
sysdata
=
hose
;
dev
.
devfn
=
devfn
;
bus
.
number
=
busnr
;
bus
.
ops
=
hose
?
hose
->
ops
:
&
null_pci_ops
;
return
&
dev
;
return
&
bus
;
}
#define EARLY_PCI_OP(rw, size, type) \
int early_##rw##_config_##size(struct pci_controller *hose, int bus, \
int devfn, int offset, type value) \
{ \
return pci_
##rw##_config_##size(fake_pci_dev(hose, bus, devfn
), \
offset, value);
\
return pci_
bus_##rw##_config_##size(fake_pci_bus(hose, bus
), \
devfn, offset, value);
\
}
EARLY_PCI_OP
(
read
,
byte
,
u8
*
)
...
...
arch/ppc/kernel/ppc_ksyms.c
View file @
2f766895
...
...
@@ -250,6 +250,7 @@ EXPORT_SYMBOL(find_all_nodes);
EXPORT_SYMBOL
(
get_property
);
EXPORT_SYMBOL
(
request_OF_resource
);
EXPORT_SYMBOL
(
release_OF_resource
);
EXPORT_SYMBOL
(
pci_busdev_to_OF_node
);
EXPORT_SYMBOL
(
pci_device_to_OF_node
);
EXPORT_SYMBOL
(
pci_device_from_OF_node
);
EXPORT_SYMBOL
(
pmac_newworld
);
...
...
arch/ppc/platforms/apus_pci.c
View file @
2f766895
...
...
@@ -61,49 +61,72 @@ void *pci_io_base(unsigned int bus)
}
#define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((val), (type *)(addr)); DEFW()
#define cfg_read_bad *val = ~0;
#define cfg_write_bad ;
#define cfg_read_val(val) *val
#define cfg_write_val(val) val
#define APUS_PCI_OP(rw, size, type, op, mask) \
int \
apus_pcibios_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
int fnno = FNNO(dev->devfn); \
int devno = DEVNO(dev->devfn); \
\
if (dev->bus->number > 0 || devno != 1) { \
cfg_##rw##_bad; \
return PCIBIOS_DEVICE_NOT_FOUND; \
} \
/* base address + function offset + offset ^ endianness conversion */
\
cfg_##rw(val, apus_hose->cfg_data + (fnno<<5) + (offset ^ mask), \
type, op); \
\
DPRINTK(#op " b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, v: 0x%x\n", \
dev->bus->number, dev->devfn>>3, dev->devfn&7, \
offset, cfg_##rw##_val(val)); \
return PCIBIOS_SUCCESSFUL; \
int
apus_pcibios_read_config
(
struct
pci_bus
*
bus
,
int
devfn
,
int
offset
,
int
len
,
u32
*
val
)
{
int
fnno
=
FNNO
(
devfn
);
int
devno
=
DEVNO
(
devfn
);
volatile
unsigned
char
*
cfg_data
;
if
(
bus
->
number
>
0
||
devno
!=
1
)
{
*
val
=
~
0
;
return
PCIBIOS_DEVICE_NOT_FOUND
;
}
/* base address + function offset + offset ^ endianness conversion */
/* XXX the fnno<<5 bit seems wacky -- paulus */
cfg_data
=
apus_hose
->
cfg_data
+
(
fnno
<<
5
)
+
(
offset
^
(
len
-
1
));
switch
(
len
)
{
case
1
:
*
val
=
readb
(
cfg_data
);
break
;
case
2
:
*
val
=
readw
(
cfg_data
);
break
;
default:
*
val
=
readl
(
cfg_data
);
break
;
}
DPRINTK
(
"read b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x
\n
"
,
bus
->
number
,
devfn
>>
3
,
devfn
&
7
,
offset
,
len
,
*
val
);
return
PCIBIOS_SUCCESSFUL
;
}
APUS_PCI_OP
(
read
,
byte
,
u8
*
,
readb
,
3
)
APUS_PCI_OP
(
read
,
word
,
u16
*
,
readw
,
2
)
APUS_PCI_OP
(
read
,
dword
,
u32
*
,
readl
,
0
)
APUS_PCI_OP
(
write
,
byte
,
u8
,
writeb
,
3
)
APUS_PCI_OP
(
write
,
word
,
u16
,
writew
,
2
)
APUS_PCI_OP
(
write
,
dword
,
u32
,
writel
,
0
)
int
apus_pcibios_write_config
(
struct
pci_bus
*
bus
,
int
devfn
,
int
offset
,
int
len
,
u32
*
val
)
{
int
fnno
=
FNNO
(
devfn
);
int
devno
=
DEVNO
(
devfn
);
volatile
unsigned
char
*
cfg_data
;
if
(
bus
->
number
>
0
||
devno
!=
1
)
{
return
PCIBIOS_DEVICE_NOT_FOUND
;
}
/* base address + function offset + offset ^ endianness conversion */
/* XXX the fnno<<5 bit seems wacky -- paulus */
cfg_data
=
apus_hose
->
cfg_data
+
(
fnno
<<
5
)
+
(
offset
^
(
len
-
1
));
switch
(
len
)
{
case
1
:
writeb
(
val
,
cfg_data
);
DEFW
();
break
;
case
2
:
writew
(
val
,
cfg_data
);
DEFW
();
break
;
default:
writel
(
val
,
cfg_data
);
DEFW
();
break
;
}
DPRINTK
(
"write b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, l: %d, v: 0x%x
\n
"
,
bus
->
number
,
devfn
>>
3
,
devfn
&
7
,
offset
,
len
,
val
);
return
PCIBIOS_SUCCESSFUL
;
}
static
struct
pci_ops
apus_pci_ops
=
{
apus_pcibios_read_config_byte
,
apus_pcibios_read_config_word
,
apus_pcibios_read_config_dword
,
apus_pcibios_write_config_byte
,
apus_pcibios_write_config_word
,
apus_pcibios_write_config_dword
apus_pcibios_read_config
,
apus_pcibios_write_config
};
static
struct
resource
pci_mem
=
{
"B/CVisionPPC PCI mem"
,
CVPPC_FB_APERTURE_ONE
,
CVPPC_PCI_CONFIG
,
IORESOURCE_MEM
};
...
...
arch/ppc/platforms/chrp_pci.c
View file @
2f766895
...
...
@@ -28,136 +28,108 @@
/* LongTrail */
unsigned
long
gg2_pci_config_base
;
#define pci_config_addr(dev, offset) \
(gg2_pci_config_base | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
volatile
struct
Hydra
*
Hydra
=
NULL
;
/*
* The VLSI Golden Gate II has only 512K of PCI configuration space, so we
* limit the bus number to 3 bits
*/
#define cfg_read(val, addr, type, op) *val = op((type)(addr))
#define cfg_write(val, addr, type, op) op((type *)(addr), (val))
#define cfg_read_bad(val, size) *val = bad_##size;
#define cfg_write_bad(val, size)
#define bad_byte 0xff
#define bad_word 0xffff
#define bad_dword 0xffffffffU
int
__chrp
gg2_read_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
off
,
int
len
,
u32
*
val
)
{
volatile
unsigned
char
*
cfg_data
;
struct
pci_controller
*
hose
=
bus
->
sysdata
;
#define GG2_PCI_OP(rw, size, type, op) \
int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
{ \
if (dev->bus->number > 7) { \
cfg_##rw##_bad(val, size) \
return PCIBIOS_DEVICE_NOT_FOUND; \
} \
cfg_##rw(val, pci_config_addr(dev, off), type, op); \
return PCIBIOS_SUCCESSFUL; \
if
(
bus
->
number
>
7
)
return
PCIBIOS_DEVICE_NOT_FOUND
;
/*
* Note: the caller has already checked that off is
* suitably aligned and that len is 1, 2 or 4.
*/
cfg_data
=
hose
->
cfg_data
+
((
bus
->
number
<<
16
)
|
(
devfn
<<
8
)
|
off
);
switch
(
len
)
{
case
1
:
*
val
=
in_8
((
u8
*
)
cfg_data
);
break
;
case
2
:
*
val
=
in_le16
((
u16
*
)
cfg_data
);
break
;
default:
*
val
=
in_le32
((
u32
*
)
cfg_data
);
break
;
}
return
PCIBIOS_SUCCESSFUL
;
}
GG2_PCI_OP
(
read
,
byte
,
u8
*
,
in_8
)
GG2_PCI_OP
(
read
,
word
,
u16
*
,
in_le16
)
GG2_PCI_OP
(
read
,
dword
,
u32
*
,
in_le32
)
GG2_PCI_OP
(
write
,
byte
,
u8
,
out_8
)
GG2_PCI_OP
(
write
,
word
,
u16
,
out_le16
)
GG2_PCI_OP
(
write
,
dword
,
u32
,
out_le32
)
static
struct
pci_ops
gg2_pci_ops
=
int
__chrp
gg2_write_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
off
,
int
len
,
u32
val
)
{
gg2_read_config_byte
,
gg2_read_config_word
,
gg2_read_config_dword
,
gg2_write_config_byte
,
gg2_write_config_word
,
gg2_write_config_dword
};
/*
* Access functions for PCI config space on IBM "python" host bridges.
*/
#define PYTHON_CFA(b, d, o) (0x80 | ((b) << 8) | ((d) << 16) \
| (((o) & ~3) << 24))
volatile
unsigned
char
*
cfg_data
;
struct
pci_controller
*
hose
=
bus
->
sysdata
;
#define PYTHON_PCI_OP(rw, size, type, op, mask) \
int __chrp \
python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
struct pci_controller *hose = dev->sysdata; \
\
out_be32(hose->cfg_addr, \
PYTHON_CFA(dev->bus->number, dev->devfn, offset)); \
cfg_##rw(val, hose->cfg_data + (offset & mask), type, op); \
return PCIBIOS_SUCCESSFUL; \
if
(
bus
->
number
>
7
)
return
PCIBIOS_DEVICE_NOT_FOUND
;
/*
* Note: the caller has already checked that off is
* suitably aligned and that len is 1, 2 or 4.
*/
cfg_data
=
hose
->
cfg_data
+
((
bus
->
number
<<
16
)
|
(
devfn
<<
8
)
|
off
);
switch
(
len
)
{
case
1
:
out_8
((
u8
*
)
cfg_data
,
val
);
break
;
case
2
:
out_le16
((
u16
*
)
cfg_data
,
val
);
break
;
default:
out_le32
((
u32
*
)
cfg_data
,
val
);
break
;
}
return
PCIBIOS_SUCCESSFUL
;
}
PYTHON_PCI_OP
(
read
,
byte
,
u8
*
,
in_8
,
3
)
PYTHON_PCI_OP
(
read
,
word
,
u16
*
,
in_le16
,
2
)
PYTHON_PCI_OP
(
read
,
dword
,
u32
*
,
in_le32
,
0
)
PYTHON_PCI_OP
(
write
,
byte
,
u8
,
out_8
,
3
)
PYTHON_PCI_OP
(
write
,
word
,
u16
,
out_le16
,
2
)
PYTHON_PCI_OP
(
write
,
dword
,
u32
,
out_le32
,
0
)
static
struct
pci_ops
python_pci_ops
=
static
struct
pci_ops
gg2_pci_ops
=
{
python_read_config_byte
,
python_read_config_word
,
python_read_config_dword
,
python_write_config_byte
,
python_write_config_word
,
python_write_config_dword
gg2_read_config
,
gg2_write_config
};
/*
* Access functions for PCI config space using RTAS calls.
*/
#define RTAS_PCI_READ_OP(size, type, nbytes) \
int __chrp \
rtas_read_config_##size(struct pci_dev *dev, int offset, type val) \
{
\
unsigned long addr = (offset & 0xff) | ((dev
->devfn & 0xff) << 8) \
| ((
dev->bus->number & 0xff) << 16); \
unsigned long ret = ~0UL; \
int rval;
\
\
rval = call_rtas("read-pci-config", 2, 2, &ret, addr,
nbytes); \
*val = ret;
\
return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;
\
int
__chrp
rtas_read_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
*
val
)
{
unsigned
long
addr
=
(
offset
&
0xff
)
|
((
dev
fn
&
0xff
)
<<
8
)
|
((
bus
->
number
&
0xff
)
<<
16
);
unsigned
long
ret
=
~
0UL
;
int
rval
;
rval
=
call_rtas
(
"read-pci-config"
,
2
,
2
,
&
ret
,
addr
,
len
);
*
val
=
ret
;
return
rval
?
PCIBIOS_DEVICE_NOT_FOUND
:
PCIBIOS_SUCCESSFUL
;
}
#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
int __chrp \
rtas_write_config_##size(struct pci_dev *dev, int offset, type val) \
{ \
unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
| ((dev->bus->number & 0xff) << 16); \
int rval; \
\
rval = call_rtas("write-pci-config", 3, 1, NULL, \
addr, nbytes, (ulong)val); \
return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; \
}
int
__chrp
rtas_write_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
val
)
{
unsigned
long
addr
=
(
offset
&
0xff
)
|
((
devfn
&
0xff
)
<<
8
)
|
((
bus
->
number
&
0xff
)
<<
16
);
int
rval
;
RTAS_PCI_READ_OP
(
byte
,
u8
*
,
1
)
RTAS_PCI_READ_OP
(
word
,
u16
*
,
2
)
RTAS_PCI_READ_OP
(
dword
,
u32
*
,
4
)
RTAS_PCI_WRITE_OP
(
byte
,
u8
,
1
)
RTAS_PCI_WRITE_OP
(
word
,
u16
,
2
)
RTAS_PCI_WRITE_OP
(
dword
,
u32
,
4
)
rval
=
call_rtas
(
"write-pci-config"
,
3
,
1
,
NULL
,
addr
,
len
,
val
);
return
rval
?
PCIBIOS_DEVICE_NOT_FOUND
:
PCIBIOS_SUCCESSFUL
;
}
static
struct
pci_ops
rtas_pci_ops
=
{
rtas_read_config_byte
,
rtas_read_config_word
,
rtas_read_config_dword
,
rtas_write_config_byte
,
rtas_write_config_word
,
rtas_write_config_dword
rtas_read_config
,
rtas_write_config
};
volatile
struct
Hydra
*
Hydra
=
NULL
;
int
__init
hydra_init
(
void
)
{
...
...
@@ -203,12 +175,9 @@ static void __init
setup_python
(
struct
pci_controller
*
hose
,
struct
device_node
*
dev
)
{
u32
*
reg
,
val
;
volatile
unsigned
char
*
cfg
;
unsigned
long
addr
=
dev
->
addrs
[
0
].
address
;
hose
->
ops
=
&
python_pci_ops
;
cfg
=
ioremap
(
dev
->
addrs
[
0
].
address
+
0xf8000
,
0x20
);
hose
->
cfg_addr
=
(
volatile
unsigned
int
*
)
cfg
;
hose
->
cfg_data
=
cfg
+
0x10
;
setup_indirect_pci
(
hose
,
addr
+
0xf8000
,
addr
+
0xf8010
);
/* Clear the magic go-slow bit */
reg
=
(
u32
*
)
ioremap
(
dev
->
addrs
[
0
].
address
+
0xf6000
,
0x40
);
...
...
@@ -288,8 +257,9 @@ chrp_find_bridges(void)
setup_grackle
(
hose
);
}
else
if
(
is_longtrail
)
{
hose
->
ops
=
&
gg2_pci_ops
;
gg2_pci_config_base
=
(
unsigned
long
)
hose
->
cfg_data
=
(
unsigned
char
*
)
ioremap
(
GG2_PCI_CONFIG_BASE
,
0x80000
);
gg2_pci_config_base
=
(
unsigned
long
)
hose
->
cfg_data
;
}
else
{
printk
(
"No methods for %s (model %s), using RTAS
\n
"
,
dev
->
full_name
,
model
);
...
...
arch/ppc/platforms/gemini_pci.c
View file @
2f766895
...
...
@@ -13,84 +13,6 @@
#include <asm/uaccess.h>
#include <asm/pci-bridge.h>
#define pci_config_addr(bus,dev,offset) \
(0x80000000 | (bus<<16) | (dev<<8) | offset)
int
gemini_pcibios_read_config_byte
(
struct
pci_dev
*
dev
,
int
offset
,
u8
*
val
)
{
unsigned
long
reg
;
reg
=
grackle_read
(
pci_config_addr
(
dev
->
bus
->
number
,
dev
->
devfn
,
(
offset
&
~
(
0x3
))));
*
val
=
((
reg
>>
((
offset
&
0x3
)
<<
3
))
&
0xff
);
return
PCIBIOS_SUCCESSFUL
;
}
int
gemini_pcibios_read_config_word
(
struct
pci_dev
*
dev
,
int
offset
,
u16
*
val
)
{
unsigned
long
reg
;
reg
=
grackle_read
(
pci_config_addr
(
dev
->
bus
->
number
,
dev
->
devfn
,
(
offset
&
~
(
0x3
))));
*
val
=
((
reg
>>
((
offset
&
0x3
)
<<
3
))
&
0xffff
);
return
PCIBIOS_SUCCESSFUL
;
}
int
gemini_pcibios_read_config_dword
(
struct
pci_dev
*
dev
,
int
offset
,
u32
*
val
)
{
*
val
=
grackle_read
(
pci_config_addr
(
dev
->
bus
->
number
,
dev
->
devfn
,
(
offset
&
~
(
0x3
))));
return
PCIBIOS_SUCCESSFUL
;
}
int
gemini_pcibios_write_config_byte
(
struct
pci_dev
*
dev
,
int
offset
,
u8
val
)
{
unsigned
long
reg
;
int
shifts
=
offset
&
0x3
;
unsigned
int
addr
=
pci_config_addr
(
dev
->
bus
->
number
,
dev
->
devfn
,
(
offset
&
~
(
0x3
)));
reg
=
grackle_read
(
addr
);
reg
=
(
reg
&
~
(
0xff
<<
(
shifts
<<
3
)))
|
(
val
<<
(
shifts
<<
3
));
grackle_write
(
addr
,
reg
);
return
PCIBIOS_SUCCESSFUL
;
}
int
gemini_pcibios_write_config_word
(
struct
pci_dev
*
dev
,
int
offset
,
u16
val
)
{
unsigned
long
reg
;
int
shifts
=
offset
&
0x3
;
unsigned
int
addr
=
pci_config_addr
(
dev
->
bus
->
number
,
dev
->
devfn
,
(
offset
&
~
(
0x3
)));
reg
=
grackle_read
(
addr
);
reg
=
(
reg
&
~
(
0xffff
<<
(
shifts
<<
3
)))
|
(
val
<<
(
shifts
<<
3
));
grackle_write
(
addr
,
reg
);
return
PCIBIOS_SUCCESSFUL
;
}
int
gemini_pcibios_write_config_dword
(
struct
pci_dev
*
dev
,
int
offset
,
u32
val
)
{
grackle_write
(
pci_config_addr
(
dev
->
bus
->
number
,
dev
->
devfn
,
(
offset
&
~
(
0x3
))),
val
);
return
PCIBIOS_SUCCESSFUL
;
}
static
struct
pci_ops
gemini_pci_ops
=
{
gemini_pcibios_read_config_byte
,
gemini_pcibios_read_config_word
,
gemini_pcibios_read_config_dword
,
gemini_pcibios_write_config_byte
,
gemini_pcibios_write_config_word
,
gemini_pcibios_write_config_dword
};
void
__init
gemini_pcibios_fixup
(
void
)
{
int
i
;
...
...
@@ -118,5 +40,5 @@ void __init gemini_find_bridges(void)
hose
=
pcibios_alloc_controller
();
if
(
!
hose
)
return
;
hose
->
ops
=
&
gemini_pci_ops
;
setup_indirect_pci
(
hose
,
0xfec00000
,
0xfee00000
)
;
}
arch/ppc/platforms/pmac_pci.c
View file @
2f766895
...
...
@@ -137,101 +137,118 @@ macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
/* Uninorth will return garbage if we don't read back the value ! */
do
{
out_le32
(
hose
->
cfg_addr
,
caddr
);
}
while
(
in_le32
(
hose
->
cfg_addr
)
!=
caddr
);
}
while
(
in_le32
(
hose
->
cfg_addr
)
!=
caddr
);
offset
&=
has_uninorth
?
0x07
:
0x03
;
return
(
unsigned
int
)(
hose
->
cfg_data
)
+
(
unsigned
int
)
offset
;
}
#define cfg_read(val, addr, type, op, op2) \
*val = op((type)(addr))
#define cfg_write(val, addr, type, op, op2) \
op((type *)(addr), (val)); (void) op2((type *)(addr))
#define cfg_read_bad(val, size) *val = bad_##size
;
#define cfg_write_bad(val, size)
#define bad_byte 0xff
#define bad_word 0xffff
#define bad_dword 0xffffffffU
#define MACRISC_PCI_OP(rw, size, type, op, op2) \
static int __pmac \
macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
{ \
struct pci_controller *hose = dev->sysdata; \
unsigned int addr; \
\
addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \
if (!addr) { \
cfg_##rw##_bad(val, size) \
return PCIBIOS_DEVICE_NOT_FOUND; \
} \
cfg_##rw(val, addr, type, op, op2); \
return PCIBIOS_SUCCESSFUL;
\
static
int
__pmac
macrisc_read_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
*
val
)
{
struct
pci_controller
*
hose
=
bus
->
sysdata
;
unsigned
int
addr
;
addr
=
macrisc_cfg_access
(
hose
,
bus
->
number
,
devfn
,
offset
);
if
(
!
addr
)
return
PCIBIOS_DEVICE_NOT_FOUND
;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch
(
len
)
{
case
1
:
*
val
=
in_8
((
u8
*
)
addr
);
break
;
case
2
:
*
val
=
in_le16
((
u16
*
)
addr
);
break
;
default:
*
val
=
in_le32
((
u32
*
)
addr
);
break
;
}
return
PCIBIOS_SUCCESSFUL
;
}
MACRISC_PCI_OP
(
read
,
byte
,
u8
*
,
in_8
,
x
)
MACRISC_PCI_OP
(
read
,
word
,
u16
*
,
in_le16
,
x
)
MACRISC_PCI_OP
(
read
,
dword
,
u32
*
,
in_le32
,
x
)
MACRISC_PCI_OP
(
write
,
byte
,
u8
,
out_8
,
in_8
)
MACRISC_PCI_OP
(
write
,
word
,
u16
,
out_le16
,
in_le16
)
MACRISC_PCI_OP
(
write
,
dword
,
u32
,
out_le32
,
in_le32
)
static
int
__pmac
macrisc_write_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
val
)
{
struct
pci_controller
*
hose
=
bus
->
sysdata
;
unsigned
int
addr
;
addr
=
macrisc_cfg_access
(
hose
,
bus
->
number
,
devfn
,
offset
);
if
(
!
addr
)
return
PCIBIOS_DEVICE_NOT_FOUND
;
/*
* Note: the caller has already checked that offset is
* suitably aligned and that len is 1, 2 or 4.
*/
switch
(
len
)
{
case
1
:
out_8
((
u8
*
)
addr
,
val
);
(
void
)
in_8
((
u8
*
)
addr
);
break
;
case
2
:
out_le16
((
u16
*
)
addr
,
val
);
(
void
)
in_le16
((
u16
*
)
addr
);
break
;
default:
out_le32
((
u32
*
)
addr
,
val
);
(
void
)
in_le32
((
u32
*
)
addr
);
break
;
}
return
PCIBIOS_SUCCESSFUL
;
}
static
struct
pci_ops
macrisc_pci_ops
=
{
macrisc_read_config_byte
,
macrisc_read_config_word
,
macrisc_read_config_dword
,
macrisc_write_config_byte
,
macrisc_write_config_word
,
macrisc_write_config_dword
macrisc_read_config
,
macrisc_write_config
};
/*
* Verifiy that a specific (bus, dev_fn) exists on chaos
*/
static
int
__pmac
chaos_validate_dev
(
struct
pci_
dev
*
dev
,
int
offset
)
chaos_validate_dev
(
struct
pci_
bus
*
bus
,
int
devfn
,
int
offset
)
{
if
(
pci_device_to_OF_node
(
dev
)
==
0
)
if
(
pci_busdev_to_OF_node
(
bus
,
devfn
)
==
0
)
return
PCIBIOS_DEVICE_NOT_FOUND
;
if
((
dev
->
vendor
==
0x106b
)
&&
(
dev
->
device
==
3
)
&&
(
offset
>=
0x10
)
&&
(
offset
!=
0x14
)
&&
(
offset
!=
0x18
)
&&
(
offset
<=
0x24
))
{
if
(
/*(dev->vendor == 0x106b) && (dev->device == 3) &&*/
(
offset
>=
0x10
)
&&
(
offset
!=
0x14
)
&&
(
offset
!=
0x18
)
&&
(
offset
<=
0x24
))
{
return
PCIBIOS_BAD_REGISTER_NUMBER
;
}
return
PCIBIOS_SUCCESSFUL
;
}
#define CHAOS_PCI_OP(rw, size, type) \
static int __pmac \
chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
{ \
int result = chaos_validate_dev(dev, off); \
if(result == PCIBIOS_BAD_REGISTER_NUMBER) { \
cfg_##rw##_bad(val, size) \
return PCIBIOS_BAD_REGISTER_NUMBER; \
} \
if(result == PCIBIOS_SUCCESSFUL) \
return macrisc_##rw##_config_##size(dev, off, val); \
return result; \
static
int
__pmac
chaos_read_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
*
val
)
{
int
result
=
chaos_validate_dev
(
bus
,
devfn
,
offset
);
if
(
result
==
PCIBIOS_BAD_REGISTER_NUMBER
)
*
val
=
~
0U
;
if
(
result
!=
PCIBIOS_SUCCESSFUL
)
return
result
;
return
macrisc_read_config
(
bus
,
devfn
,
offset
,
len
,
val
);
}
CHAOS_PCI_OP
(
read
,
byte
,
u8
*
)
CHAOS_PCI_OP
(
read
,
word
,
u16
*
)
CHAOS_PCI_OP
(
read
,
dword
,
u32
*
)
CHAOS_PCI_OP
(
write
,
byte
,
u8
)
CHAOS_PCI_OP
(
write
,
word
,
u16
)
CHAOS_PCI_OP
(
write
,
dword
,
u32
)
static
int
__pmac
chaos_write_config
(
struct
pci_bus
*
bus
,
unsigned
int
devfn
,
int
offset
,
int
len
,
u32
val
)
{
int
result
=
chaos_validate_dev
(
bus
,
devfn
,
offset
);
if
(
result
!=
PCIBIOS_SUCCESSFUL
)
return
result
;
return
macrisc_write_config
(
bus
,
devfn
,
offset
,
len
,
val
);
}
static
struct
pci_ops
chaos_pci_ops
=
{
chaos_read_config_byte
,
chaos_read_config_word
,
chaos_read_config_dword
,
chaos_write_config_byte
,
chaos_write_config_word
,
chaos_write_config_dword
chaos_read_config
,
chaos_write_config
};
...
...
@@ -489,7 +506,8 @@ pcibios_fixup_OF_interrupts(void)
* obtained from the OF device-tree
*/
pci_for_each_dev
(
dev
)
{
struct
device_node
*
node
=
pci_device_to_OF_node
(
dev
);
struct
device_node
*
node
;
node
=
pci_device_to_OF_node
(
dev
);
/* this is the node, see if it has interrupts */
if
(
node
&&
node
->
n_intrs
>
0
)
dev
->
irq
=
node
->
intrs
[
0
].
line
;
...
...
include/asm-ppc/pci-bridge.h
View file @
2f766895
...
...
@@ -31,6 +31,7 @@ extern void pci_init_resource(struct resource *res, unsigned long start,
*/
extern
int
pci_device_from_OF_node
(
struct
device_node
*
node
,
u8
*
bus
,
u8
*
devfn
);
extern
struct
device_node
*
pci_busdev_to_OF_node
(
struct
pci_bus
*
,
int
);
extern
struct
device_node
*
pci_device_to_OF_node
(
struct
pci_dev
*
);
extern
void
pci_create_OF_bus_map
(
void
);
...
...
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