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
4c6ae316
Commit
4c6ae316
authored
Jul 22, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SPARC64]: Finalize TOMATILLO/JIO support, help from bcollins@debian.org.
parent
21acec08
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
146 additions
and
158 deletions
+146
-158
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/pci_schizo.c
+146
-158
No files found.
arch/sparc64/kernel/pci_schizo.c
View file @
4c6ae316
...
...
@@ -102,25 +102,21 @@ static void *schizo_pci_config_mkaddr(struct pci_pbm_info *pbm,
{
if
(
!
pbm
)
return
NULL
;
bus
-=
pbm
->
pci_first_busno
;
return
(
void
*
)
(
SCHIZO_CONFIG_BASE
(
pbm
)
|
SCHIZO_CONFIG_ENCODE
(
bus
,
devfn
,
where
));
}
/* 4 slots on pbm A, and 6 slots on pbm B. In both cases
* slot 0 is the SCHIZO host bridge itself.
*/
/* Just make sure the bus number is in range. */
static
int
schizo_out_of_range
(
struct
pci_pbm_info
*
pbm
,
unsigned
char
bus
,
unsigned
char
devfn
)
{
return
((
pbm
->
parent
==
0
)
||
((
pbm
==
&
pbm
->
parent
->
pbm_B
)
&&
(
bus
==
pbm
->
pci_first_busno
)
&&
PCI_SLOT
(
devfn
)
>
6
)
||
((
pbm
==
&
pbm
->
parent
->
pbm_A
)
&&
(
bus
==
pbm
->
pci_first_busno
)
&&
PCI_SLOT
(
devfn
)
>
4
));
if
(
bus
<
pbm
->
pci_first_busno
||
bus
>
pbm
->
pci_last_busno
)
return
1
;
return
0
;
}
/* SCHIZO PCI configuration space accessors. */
...
...
@@ -175,6 +171,23 @@ static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
return
PCIBIOS_SUCCESSFUL
;
}
pci_config_read32
(
addr
,
value
);
#warning DaveM, reminder, Tomatillo support is hosed.
#if 0
/* Crap how to do this in 2.5.x? I need the pdev :(
* Actually, just move over to more sane domain
* support to deal with this. -DaveM
*/
if (where == PCI_PRIMARY_BUS &&
dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&
*value != 0xffffffff) {
u8 *busp = ((u8 *) value) + 1;
int i;
for (i = 0; i < 3; i++)
busp[i] += pbm->pci_first_busno;
}
#endif
break
;
}
return
PCIBIOS_SUCCESSFUL
;
...
...
@@ -214,6 +227,27 @@ static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
where
);
return
PCIBIOS_SUCCESSFUL
;
}
#warning DaveM, reminder, Tomatillo support is hosed.
#if 0
/* Crap how to do this in 2.5.x? I need the pdev :(
* Actually, just move over to more sane domain
* support to deal with this. -DaveM
*/
if (where == PCI_PRIMARY_BUS &&
dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
u8 *busp = ((u8 *) &value) + 1;
int i;
for (i = 0; i < 3; i++) {
if (busp[i] >= pbm->pci_first_busno)
busp[i] += pbm->pci_first_busno;
else
busp[i] = 0;
}
}
#endif
pci_config_write32
(
addr
,
value
);
}
return
PCIBIOS_SUCCESSFUL
;
...
...
@@ -648,9 +682,7 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm,
static
void
schizo_check_iommu_error
(
struct
pci_controller_info
*
p
,
enum
schizo_error_type
type
)
{
if
(
p
->
pbm_A
.
prom_node
)
schizo_check_iommu_error_pbm
(
&
p
->
pbm_A
,
type
);
if
(
p
->
pbm_B
.
prom_node
)
schizo_check_iommu_error_pbm
(
&
p
->
pbm_B
,
type
);
}
...
...
@@ -1087,7 +1119,8 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
#define SCHIZO_PCICTRL_EEN (1UL << 17UL)
/* Safari/Tomatillo */
#define SCHIZO_PCICTRL_PARK (1UL << 16UL)
/* Safari/Tomatillo */
#define SCHIZO_PCICTRL_PCIRST (1UL << 8UL)
/* Safari */
#define SCHIZO_PCICTRL_ARB (0x3fUL << 0UL)
/* Safari/Tomatillo */
#define SCHIZO_PCICTRL_ARB_S (0x3fUL << 0UL)
/* Safari */
#define SCHIZO_PCICTRL_ARB_T (0xffUL << 0UL)
/* Tomatillo */
/* How the Tomatillo IRQs are routed around is pure guesswork here.
*
...
...
@@ -1097,7 +1130,8 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id, struct pt_regs *
* and thus the registers are mapped to totally different locations.
*
* However, two Tomatillo's look "similar" in that the only difference
* in their PortID is the lowest bit which is software programmable.
* in their PortID is the lowest bit.
*
* So if we were to ignore this lower bit, it certainly looks like two
* PCI bus units of the same Tomatillo. I still have not really
* figured this out...
...
...
@@ -1111,12 +1145,8 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
u64
tmp
,
err_mask
;
int
is_pbm_a
;
pbm
=
&
p
->
pbm_A
;
is_pbm_a
=
1
;
if
(
!
pbm
->
prom_node
)
{
pbm
=
&
p
->
pbm_B
;
is_pbm_a
=
0
;
}
/* Build IRQs and register handlers. */
irq
=
schizo_irq_build
(
pbm
,
NULL
,
(
portid
<<
6
)
|
SCHIZO_UE_INO
);
...
...
@@ -1149,10 +1179,11 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
SCHIZO_PBM_B_REGS_OFF
)
+
schizo_imap_offset
(
SCHIZO_CE_INO
)
+
4
));
pbm
=
&
p
->
pbm_A
;
is_pbm_a
=
1
;
irq
=
schizo_irq_build
(
pbm
,
NULL
,
((
portid
<<
6
)
|
(
is_pbm_a
?
SCHIZO_PCIERR_A_INO
:
SCHIZO_PCIERR_B_INO
)));
SCHIZO_PCIERR_A_INO
));
if
(
request_irq
(
irq
,
schizo_pcierr_intr
,
SA_SHIRQ
,
"TOMATILLO PCIERR"
,
pbm
)
<
0
)
{
prom_printf
(
"%s: Cannot register PciERR interrupt.
\n
"
,
...
...
@@ -1167,6 +1198,25 @@ static void __init tomatillo_register_error_handlers(struct pci_controller_info
SCHIZO_PBM_B_REGS_OFF
)
+
schizo_imap_offset
(
SCHIZO_PCIERR_A_INO
)
+
4
));
pbm
=
&
p
->
pbm_B
;
is_pbm_a
=
0
;
irq
=
schizo_irq_build
(
pbm
,
NULL
,
((
portid
<<
6
)
|
SCHIZO_PCIERR_B_INO
));
if
(
request_irq
(
irq
,
schizo_pcierr_intr
,
SA_SHIRQ
,
"TOMATILLO PCIERR"
,
pbm
)
<
0
)
{
prom_printf
(
"%s: Cannot register PciERR interrupt.
\n
"
,
pbm
->
name
);
prom_halt
();
}
bucket
=
__bucket
(
irq
);
tmp
=
upa_readl
(
bucket
->
imap
);
upa_writel
(
tmp
,
(
base
+
(
is_pbm_a
?
SCHIZO_PBM_A_REGS_OFF
:
SCHIZO_PBM_B_REGS_OFF
)
+
schizo_imap_offset
(
SCHIZO_PCIERR_B_INO
)
+
4
));
irq
=
schizo_irq_build
(
pbm
,
NULL
,
(
portid
<<
6
)
|
SCHIZO_SERR_INO
);
if
(
request_irq
(
irq
,
schizo_safarierr_intr
,
SA_SHIRQ
,
"TOMATILLO SERR"
,
p
)
<
0
)
{
...
...
@@ -1321,7 +1371,6 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
/* Enable PCI Error interrupts and clear error
* bits for each PBM.
*/
if
(
pbm_a
->
prom_node
)
{
tmp
=
schizo_read
(
base
+
SCHIZO_PCIA_CTRL
);
tmp
|=
err_mask
;
schizo_write
(
base
+
SCHIZO_PCIA_CTRL
,
tmp
);
...
...
@@ -1333,9 +1382,7 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
SCHIZO_PCIAFSR_SMA
|
SCHIZO_PCIAFSR_STA
|
SCHIZO_PCIAFSR_SRTRY
|
SCHIZO_PCIAFSR_SPERR
|
SCHIZO_PCIAFSR_STTO
|
SCHIZO_PCIAFSR_SUNUS
));
}
if
(
pbm_b
->
prom_node
)
{
tmp
=
schizo_read
(
base
+
SCHIZO_PCIB_CTRL
);
tmp
|=
err_mask
;
schizo_write
(
base
+
SCHIZO_PCIB_CTRL
,
tmp
);
...
...
@@ -1347,7 +1394,6 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
SCHIZO_PCIAFSR_SMA
|
SCHIZO_PCIAFSR_STA
|
SCHIZO_PCIAFSR_SRTRY
|
SCHIZO_PCIAFSR_SPERR
|
SCHIZO_PCIAFSR_STTO
|
SCHIZO_PCIAFSR_SUNUS
));
}
/* Make all Safari error conditions fatal except unmapped
* errors which we make generate interrupts.
...
...
@@ -1382,23 +1428,14 @@ static void __init schizo_register_error_handlers(struct pci_controller_info *p)
}
/* We have to do the config space accesses by hand, thus... */
#define PBM_BRIDGE_BUS 0x40
#define PBM_BRIDGE_SUBORDINATE 0x41
static
void
__init
pbm_renumber
(
struct
pci_pbm_info
*
pbm
,
u8
orig_busno
)
{
u8
*
addr
,
busno
;
u8
busno
;
int
nbus
;
busno
=
pci_highest_busnum
;
nbus
=
pbm
->
pci_last_busno
-
pbm
->
pci_first_busno
;
addr
=
schizo_pci_config_mkaddr
(
pbm
,
orig_busno
,
0
,
PBM_BRIDGE_BUS
);
pci_config_write8
(
addr
,
busno
);
addr
=
schizo_pci_config_mkaddr
(
pbm
,
busno
,
0
,
PBM_BRIDGE_SUBORDINATE
);
pci_config_write8
(
addr
,
busno
+
nbus
);
pbm
->
pci_first_busno
=
busno
;
pbm
->
pci_last_busno
=
busno
+
nbus
;
pci_highest_busnum
=
busno
+
nbus
+
1
;
...
...
@@ -1408,83 +1445,10 @@ static void __init pbm_renumber(struct pci_pbm_info *pbm, u8 orig_busno)
}
while
(
nbus
--
);
}
/* We have to do the config space accesses by hand here since
* the pci_bus2pbm array is not ready yet.
*/
static
void
__init
pbm_pci_bridge_renumber
(
struct
pci_pbm_info
*
pbm
,
u8
busno
)
{
u32
devfn
,
l
,
class
;
u8
hdr_type
;
int
is_multi
=
0
;
for
(
devfn
=
0
;
devfn
<
0xff
;
++
devfn
)
{
u32
*
dwaddr
;
u8
*
baddr
;
if
(
PCI_FUNC
(
devfn
)
!=
0
&&
is_multi
==
0
)
continue
;
/* Anything there? */
dwaddr
=
schizo_pci_config_mkaddr
(
pbm
,
busno
,
devfn
,
PCI_VENDOR_ID
);
l
=
0xffffffff
;
pci_config_read32
(
dwaddr
,
&
l
);
if
(
l
==
0xffffffff
||
l
==
0x00000000
||
l
==
0x0000ffff
||
l
==
0xffff0000
)
{
is_multi
=
0
;
continue
;
}
baddr
=
schizo_pci_config_mkaddr
(
pbm
,
busno
,
devfn
,
PCI_HEADER_TYPE
);
pci_config_read8
(
baddr
,
&
hdr_type
);
if
(
PCI_FUNC
(
devfn
)
==
0
)
is_multi
=
hdr_type
&
0x80
;
dwaddr
=
schizo_pci_config_mkaddr
(
pbm
,
busno
,
devfn
,
PCI_CLASS_REVISION
);
class
=
0xffffffff
;
pci_config_read32
(
dwaddr
,
&
class
);
if
((
class
>>
16
)
==
PCI_CLASS_BRIDGE_PCI
)
{
u32
buses
=
0xffffffff
;
dwaddr
=
schizo_pci_config_mkaddr
(
pbm
,
busno
,
devfn
,
PCI_PRIMARY_BUS
);
pci_config_read32
(
dwaddr
,
&
buses
);
pbm_pci_bridge_renumber
(
pbm
,
(
buses
>>
8
)
&
0xff
);
buses
&=
0xff000000
;
pci_config_write32
(
dwaddr
,
buses
);
}
}
}
static
void
__init
pbm_bridge_reconfigure
(
struct
pci_controller_info
*
p
)
{
struct
pci_pbm_info
*
pbm
;
u8
*
addr
;
/* Clear out primary/secondary/subordinate bus numbers on
* all PCI-to-PCI bridges under each PBM. The generic bus
* probing will fix them up.
*/
if
(
p
->
pbm_B
.
prom_node
)
pbm_pci_bridge_renumber
(
&
p
->
pbm_B
,
p
->
pbm_B
.
pci_first_busno
);
if
(
p
->
pbm_A
.
prom_node
)
pbm_pci_bridge_renumber
(
&
p
->
pbm_A
,
p
->
pbm_A
.
pci_first_busno
);
if
(
p
->
pbm_A
.
prom_node
)
{
/* If necessary, move PBM A out of the way. */
pbm
=
&
p
->
pbm_A
;
addr
=
schizo_pci_config_mkaddr
(
pbm
,
pbm
->
pci_first_busno
,
0
,
PBM_BRIDGE_BUS
);
pci_config_write8
(
addr
,
0xff
);
addr
=
schizo_pci_config_mkaddr
(
pbm
,
0xff
,
0
,
PBM_BRIDGE_SUBORDINATE
);
pci_config_write8
(
addr
,
0xff
);
}
/* Now we can safely renumber both PBMs. */
if
(
p
->
pbm_B
.
prom_node
)
pbm_renumber
(
&
p
->
pbm_B
,
p
->
pbm_B
.
pci_first_busno
);
if
(
p
->
pbm_A
.
prom_node
)
pbm_renumber
(
&
p
->
pbm_A
,
0xff
);
}
...
...
@@ -1536,20 +1500,20 @@ static void __init pbm_scan_bus(struct pci_controller_info *p,
static
void
__init
__schizo_scan_bus
(
struct
pci_controller_info
*
p
,
int
is_tomatillo
)
{
if
(
!
p
->
pbm_B
.
prom_node
||
!
p
->
pbm_A
.
prom_node
)
{
printk
(
"PCI: One PCI bus module of controller found.
\n
"
);
printk
(
"PCI: Ignoring entire controller.
\n
"
);
return
;
}
pbm_bridge_reconfigure
(
p
);
if
(
p
->
pbm_B
.
prom_node
)
{
pbm_config_busmastering
(
&
p
->
pbm_B
);
p
->
pbm_B
.
is_66mhz_capable
=
prom_getbool
(
p
->
pbm_B
.
prom_node
,
"66mhz-capable"
);
}
if
(
p
->
pbm_A
.
prom_node
)
{
pbm_config_busmastering
(
&
p
->
pbm_A
);
p
->
pbm_A
.
is_66mhz_capable
=
prom_getbool
(
p
->
pbm_A
.
prom_node
,
"66mhz-capable"
);
}
if
(
p
->
pbm_B
.
prom_node
)
pbm_scan_bus
(
p
,
&
p
->
pbm_B
);
if
(
p
->
pbm_A
.
prom_node
)
pbm_scan_bus
(
p
,
&
p
->
pbm_A
);
/* After the PCI bus scan is complete, we can register
...
...
@@ -1641,7 +1605,7 @@ static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
int
is_pbm_a
,
unsigned
long
reg_base
,
int
is_tomatillo
)
{
u64
mem_match
,
mem_mask
;
u64
mem_match
;
u64
io_match
;
u64
a
;
...
...
@@ -1652,10 +1616,14 @@ static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
mem_match
=
reg_base
+
SCHIZO_PCI_B_MEM_MATCH
;
io_match
=
reg_base
+
SCHIZO_PCI_B_IO_MATCH
;
}
mem_mask
=
mem_match
+
0x8UL
;
a
=
schizo_read
(
mem_match
)
&
~
0x8000000000000000UL
;
if
(
is_tomatillo
)
{
a
+=
((
0x3UL
<<
41UL
)
|
((
u64
)
pbm
->
parent
->
portid
<<
36UL
));
}
/* It should be 2GB in size but the decode is set for the full
* 4GB so we have to add the 2G by hand.
*/
...
...
@@ -1668,6 +1636,12 @@ static void schizo_determine_mem_io_space(struct pci_pbm_info *pbm,
*/
a
=
schizo_read
(
io_match
)
&
~
0x8000000000000000UL
;
if
(
is_tomatillo
)
{
a
+=
((
0x3UL
<<
41UL
)
|
((
u64
)
pbm
->
parent
->
portid
<<
36UL
));
}
pbm
->
config_space
=
a
;
printk
(
"%s: Local PCI config space at %016lx
\n
"
,
pbm
->
name
,
pbm
->
config_space
);
...
...
@@ -1883,7 +1857,10 @@ static void __init schizo_pbm_hw_init(struct pci_controller_info *p,
(
is_pbm_a
?
SCHIZO_PCIA_CTRL
:
SCHIZO_PCIB_CTRL
));
tmp
|=
SCHIZO_PCICTRL_ARB
;
if
(
is_tomatillo
)
tmp
|=
SCHIZO_PCICTRL_ARB_T
;
else
tmp
|=
SCHIZO_PCICTRL_ARB_S
;
if
(
is_tomatillo
)
{
#if 0
/* This is the recommended setting, but we'll just
...
...
@@ -1934,6 +1911,10 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
else
pbm
=
&
p
->
pbm_B
;
pbm
->
parent
=
p
;
pbm
->
prom_node
=
prom_node
;
pbm
->
pci_first_slot
=
1
;
sprintf
(
pbm
->
name
,
(
is_tomatillo
?
"TOMATILLO%d PBM%c"
:
...
...
@@ -1945,9 +1926,6 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
p
->
controller_regs
,
is_tomatillo
);
pbm_register_toplevel_resources
(
p
,
pbm
,
is_tomatillo
);
pbm
->
parent
=
p
;
pbm
->
prom_node
=
prom_node
;
pbm
->
pci_first_slot
=
1
;
prom_getstring
(
prom_node
,
"name"
,
pbm
->
prom_name
,
sizeof
(
pbm
->
prom_name
));
...
...
@@ -1993,6 +1971,16 @@ static void __init schizo_pbm_init(struct pci_controller_info *p,
schizo_pbm_strbuf_init
(
p
,
pbm
,
is_pbm_a
,
is_tomatillo
);
}
static
inline
int
portid_compare
(
u32
x
,
u32
y
,
int
is_tomatillo
)
{
if
(
is_tomatillo
)
{
if
(
x
==
(
y
^
1
))
return
1
;
return
0
;
}
return
(
x
==
y
);
}
static
void
__init
__schizo_init
(
int
node
,
char
*
model_name
,
int
is_tomatillo
)
{
struct
linux_prom64_registers
pr_regs
[
4
];
...
...
@@ -2012,10 +2000,10 @@ static void __init __schizo_init(int node, char *model_name, int is_tomatillo)
spin_lock_irqsave
(
&
pci_controller_lock
,
flags
);
for
(
p
=
pci_controller_root
;
p
;
p
=
p
->
next
)
{
if
(
p
->
portid
==
portid
)
{
if
(
p
ortid_compare
(
p
->
portid
,
portid
,
is_tomatillo
)
)
{
spin_unlock_irqrestore
(
&
pci_controller_lock
,
flags
);
is_pbm_a
=
(
p
->
pbm_A
.
prom_node
==
0
);
schizo_pbm_init
(
p
,
node
,
is_pbm_a
,
0
);
schizo_pbm_init
(
p
,
node
,
is_pbm_a
,
is_tomatillo
);
return
;
}
}
...
...
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