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
Kirill Smelkov
linux
Commits
dc509d28
Commit
dc509d28
authored
May 14, 2003
by
Dave Jones
Committed by
Linus Torvalds
May 14, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[AGPGART] PPC Uninorth support.
By Paul Mackerras and BenH
parent
40f911f6
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
428 additions
and
0 deletions
+428
-0
drivers/char/agp/Kconfig
drivers/char/agp/Kconfig
+7
-0
drivers/char/agp/Makefile
drivers/char/agp/Makefile
+1
-0
drivers/char/agp/uninorth-agp.c
drivers/char/agp/uninorth-agp.c
+407
-0
include/asm-ppc/agp.h
include/asm-ppc/agp.h
+13
-0
No files found.
drivers/char/agp/Kconfig
View file @
dc509d28
...
@@ -131,3 +131,10 @@ config AGP_ALPHA_CORE
...
@@ -131,3 +131,10 @@ config AGP_ALPHA_CORE
depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL)
depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL)
default AGP
default AGP
config AGP_UNINORTH
tristate "Apple UniNorth AGP support"
depends on AGP && ALL_PPC
help
This option gives you AGP support for Apple machines with a
UniNorth bridge.
drivers/char/agp/Makefile
View file @
dc509d28
...
@@ -11,5 +11,6 @@ obj-$(CONFIG_AGP_INTEL) += intel-agp.o
...
@@ -11,5 +11,6 @@ obj-$(CONFIG_AGP_INTEL) += intel-agp.o
obj-$(CONFIG_AGP_NVIDIA)
+=
nvidia-agp.o
obj-$(CONFIG_AGP_NVIDIA)
+=
nvidia-agp.o
obj-$(CONFIG_AGP_SIS)
+=
sis-agp.o
obj-$(CONFIG_AGP_SIS)
+=
sis-agp.o
obj-$(CONFIG_AGP_SWORKS)
+=
sworks-agp.o
obj-$(CONFIG_AGP_SWORKS)
+=
sworks-agp.o
obj-$(CONFIG_AGP_UNINORTH)
+=
uninorth-agp.o
obj-$(CONFIG_AGP_VIA)
+=
via-agp.o
obj-$(CONFIG_AGP_VIA)
+=
via-agp.o
drivers/char/agp/uninorth-agp.c
0 → 100644
View file @
dc509d28
/*
* UniNorth AGPGART routines.
*/
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/agp_backend.h>
#include <asm/uninorth.h>
#include <asm/pci-bridge.h>
#include "agp.h"
static
int
agp_try_unsupported
__initdata
=
0
;
static
int
uninorth_fetch_size
(
void
)
{
int
i
;
u32
temp
;
struct
aper_size_info_32
*
values
;
pci_read_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_BASE
,
&
temp
);
temp
&=
~
(
0xfffff000
);
values
=
A_SIZE_32
(
agp_bridge
->
driver
->
aperture_sizes
);
for
(
i
=
0
;
i
<
agp_bridge
->
driver
->
num_aperture_sizes
;
i
++
)
{
if
(
temp
==
values
[
i
].
size_value
)
{
agp_bridge
->
previous_size
=
agp_bridge
->
current_size
=
(
void
*
)
(
values
+
i
);
agp_bridge
->
aperture_size_idx
=
i
;
return
values
[
i
].
size
;
}
}
agp_bridge
->
previous_size
=
agp_bridge
->
current_size
=
(
void
*
)
(
values
+
1
);
agp_bridge
->
aperture_size_idx
=
1
;
return
values
[
1
].
size
;
return
0
;
}
static
void
uninorth_tlbflush
(
agp_memory
*
mem
)
{
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
UNI_N_CFG_GART_ENABLE
|
UNI_N_CFG_GART_INVAL
);
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
UNI_N_CFG_GART_ENABLE
);
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
UNI_N_CFG_GART_ENABLE
|
UNI_N_CFG_GART_2xRESET
);
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
UNI_N_CFG_GART_ENABLE
);
}
static
void
uninorth_cleanup
(
void
)
{
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
UNI_N_CFG_GART_ENABLE
|
UNI_N_CFG_GART_INVAL
);
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
0
);
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
UNI_N_CFG_GART_2xRESET
);
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_CTRL
,
0
);
}
static
int
uninorth_configure
(
void
)
{
struct
aper_size_info_32
*
current_size
;
current_size
=
A_SIZE_32
(
agp_bridge
->
current_size
);
printk
(
KERN_INFO
PFX
"configuring for size idx: %d
\n
"
,
current_size
->
size_value
);
/* aperture size and gatt addr */
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_GART_BASE
,
(
agp_bridge
->
gatt_bus_addr
&
0xfffff000
)
|
current_size
->
size_value
);
/* HACK ALERT
* UniNorth seem to be buggy enough not to handle properly when
* the AGP aperture isn't mapped at bus physical address 0
*/
agp_bridge
->
gart_bus_addr
=
0
;
pci_write_config_dword
(
agp_bridge
->
dev
,
UNI_N_CFG_AGP_BASE
,
agp_bridge
->
gart_bus_addr
);
return
0
;
}
static
unsigned
long
uninorth_mask_memory
(
unsigned
long
addr
,
int
type
)
{
return
addr
;
/* | agp_bridge->driver->masks[0].mask;*/
}
static
int
uninorth_insert_memory
(
agp_memory
*
mem
,
off_t
pg_start
,
int
type
)
{
int
i
,
j
,
num_entries
;
void
*
temp
;
temp
=
agp_bridge
->
current_size
;
num_entries
=
A_SIZE_32
(
temp
)
->
num_entries
;
if
(
type
!=
0
||
mem
->
type
!=
0
)
/* We know nothing of memory types */
return
-
EINVAL
;
if
((
pg_start
+
mem
->
page_count
)
>
num_entries
)
return
-
EINVAL
;
j
=
pg_start
;
while
(
j
<
(
pg_start
+
mem
->
page_count
))
{
if
(
!
PGE_EMPTY
(
agp_bridge
,
agp_bridge
->
gatt_table
[
j
]))
return
-
EBUSY
;
j
++
;
}
for
(
i
=
0
,
j
=
pg_start
;
i
<
mem
->
page_count
;
i
++
,
j
++
)
{
agp_bridge
->
gatt_table
[
j
]
=
cpu_to_le32
((
mem
->
memory
[
i
]
&
0xfffff000
)
|
0x00000001UL
);
flush_dcache_range
((
unsigned
long
)
__va
(
mem
->
memory
[
i
]),
(
unsigned
long
)
__va
(
mem
->
memory
[
i
])
+
0x1000
);
}
(
void
)
in_le32
((
volatile
u32
*
)
&
agp_bridge
->
gatt_table
[
pg_start
]);
mb
();
flush_dcache_range
((
unsigned
long
)
&
agp_bridge
->
gatt_table
[
pg_start
],
(
unsigned
long
)
&
agp_bridge
->
gatt_table
[
pg_start
+
mem
->
page_count
]);
uninorth_tlbflush
(
mem
);
return
0
;
}
static
void
uninorth_agp_enable
(
u32
mode
)
{
u32
command
,
scratch
;
int
timeout
;
pci_read_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
+
PCI_AGP_STATUS
,
&
command
);
command
=
agp_collect_device_status
(
mode
,
command
);
command
|=
0x100
;
uninorth_tlbflush
(
NULL
);
timeout
=
0
;
do
{
pci_write_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
+
PCI_AGP_COMMAND
,
command
);
pci_read_config_dword
(
agp_bridge
->
dev
,
agp_bridge
->
capndx
+
PCI_AGP_COMMAND
,
&
scratch
);
}
while
((
scratch
&
0x100
)
==
0
&&
++
timeout
<
1000
);
if
((
scratch
&
0x100
)
==
0
)
printk
(
KERN_ERR
PFX
"failed to write UniNorth AGP command reg
\n
"
);
agp_device_command
(
command
,
0
);
uninorth_tlbflush
(
NULL
);
}
static
int
uninorth_create_gatt_table
(
void
)
{
char
*
table
;
char
*
table_end
;
int
size
;
int
page_order
;
int
num_entries
;
int
i
;
void
*
temp
;
struct
page
*
page
;
/* We can't handle 2 level gatt's */
if
(
agp_bridge
->
driver
->
size_type
==
LVL2_APER_SIZE
)
return
-
EINVAL
;
table
=
NULL
;
i
=
agp_bridge
->
aperture_size_idx
;
temp
=
agp_bridge
->
current_size
;
size
=
page_order
=
num_entries
=
0
;
do
{
size
=
A_SIZE_32
(
temp
)
->
size
;
page_order
=
A_SIZE_32
(
temp
)
->
page_order
;
num_entries
=
A_SIZE_32
(
temp
)
->
num_entries
;
table
=
(
char
*
)
__get_free_pages
(
GFP_KERNEL
,
page_order
);
if
(
table
==
NULL
)
{
i
++
;
agp_bridge
->
current_size
=
A_IDX32
(
agp_bridge
);
}
else
{
agp_bridge
->
aperture_size_idx
=
i
;
}
}
while
(
!
table
&&
(
i
<
agp_bridge
->
driver
->
num_aperture_sizes
));
if
(
table
==
NULL
)
return
-
ENOMEM
;
table_end
=
table
+
((
PAGE_SIZE
*
(
1
<<
page_order
))
-
1
);
for
(
page
=
virt_to_page
(
table
);
page
<=
virt_to_page
(
table_end
);
page
++
)
SetPageReserved
(
page
);
agp_bridge
->
gatt_table_real
=
(
u32
*
)
table
;
agp_bridge
->
gatt_table
=
(
u32
*
)
table
;
agp_bridge
->
gatt_bus_addr
=
virt_to_phys
(
table
);
for
(
i
=
0
;
i
<
num_entries
;
i
++
)
{
agp_bridge
->
gatt_table
[
i
]
=
(
unsigned
long
)
agp_bridge
->
scratch_page
;
}
flush_dcache_range
((
unsigned
long
)
table
,
(
unsigned
long
)
table_end
);
return
0
;
}
static
int
uninorth_free_gatt_table
(
void
)
{
int
page_order
;
char
*
table
,
*
table_end
;
void
*
temp
;
struct
page
*
page
;
temp
=
agp_bridge
->
current_size
;
page_order
=
A_SIZE_32
(
temp
)
->
page_order
;
/* Do not worry about freeing memory, because if this is
* called, then all agp memory is deallocated and removed
* from the table.
*/
table
=
(
char
*
)
agp_bridge
->
gatt_table_real
;
table_end
=
table
+
((
PAGE_SIZE
*
(
1
<<
page_order
))
-
1
);
for
(
page
=
virt_to_page
(
table
);
page
<=
virt_to_page
(
table_end
);
page
++
)
ClearPageReserved
(
page
);
free_pages
((
unsigned
long
)
agp_bridge
->
gatt_table_real
,
page_order
);
return
0
;
}
void
null_cache_flush
(
void
)
{
mb
();
}
/* Setup function */
static
struct
gatt_mask
uninorth_masks
[]
=
{
{
0x00000000
,
0
}
};
static
struct
aper_size_info_32
uninorth_sizes
[
7
]
=
{
#if 0 /* Not sure uninorth supports that high aperture sizes */
{256, 65536, 6, 64},
{128, 32768, 5, 32},
{64, 16384, 4, 16},
#endif
{
32
,
8192
,
3
,
8
},
{
16
,
4096
,
2
,
4
},
{
8
,
2048
,
1
,
2
},
{
4
,
1024
,
0
,
1
}
};
struct
agp_bridge_driver
uninorth_agp_driver
=
{
.
owner
=
THIS_MODULE
,
.
masks
=
uninorth_masks
,
.
aperture_sizes
=
(
void
*
)
uninorth_sizes
,
.
size_type
=
U32_APER_SIZE
,
.
num_aperture_sizes
=
4
,
.
configure
=
uninorth_configure
,
.
fetch_size
=
uninorth_fetch_size
,
.
cleanup
=
uninorth_cleanup
,
.
tlb_flush
=
uninorth_tlbflush
,
.
mask_memory
=
uninorth_mask_memory
,
.
cache_flush
=
null_cache_flush
,
.
agp_enable
=
uninorth_agp_enable
,
.
create_gatt_table
=
uninorth_create_gatt_table
,
.
free_gatt_table
=
uninorth_free_gatt_table
,
.
insert_memory
=
uninorth_insert_memory
,
.
remove_memory
=
agp_generic_remove_memory
,
.
alloc_by_type
=
agp_generic_alloc_by_type
,
.
free_by_type
=
agp_generic_free_by_type
,
.
agp_alloc_page
=
agp_generic_alloc_page
,
.
agp_destroy_page
=
agp_generic_destroy_page
,
.
suspend
=
agp_generic_suspend
,
.
resume
=
agp_generic_resume
,
.
cant_use_aperture
=
1
,
};
struct
agp_device_ids
uninorth_agp_device_ids
[]
__initdata
=
{
{
.
device_id
=
PCI_DEVICE_ID_APPLE_UNI_N_AGP
,
.
chipset_name
=
"UniNorth"
,
},
{
.
device_id
=
PCI_DEVICE_ID_APPLE_UNI_N_AGP_P
,
.
chipset_name
=
"UniNorth/Pangea"
,
},
{
.
device_id
=
PCI_DEVICE_ID_APPLE_UNI_N_AGP15
,
.
chipset_name
=
"UniNorth 1.5"
,
},
{
.
device_id
=
PCI_DEVICE_ID_APPLE_UNI_N_AGP2
,
.
chipset_name
=
"UniNorth 2"
,
},
};
static
int
__init
agp_uninorth_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
struct
agp_device_ids
*
devs
=
uninorth_agp_device_ids
;
struct
agp_bridge_data
*
bridge
;
u8
cap_ptr
;
int
j
;
cap_ptr
=
pci_find_capability
(
pdev
,
PCI_CAP_ID_AGP
);
if
(
cap_ptr
==
0
)
return
-
ENODEV
;
/* probe for known chipsets */
for
(
j
=
0
;
devs
[
j
].
chipset_name
!=
NULL
;
++
j
)
{
if
(
pdev
->
device
==
devs
[
j
].
device_id
)
{
printk
(
KERN_INFO
PFX
"Detected Apple %s chipset
\n
"
,
devs
[
j
].
chipset_name
);
goto
found
;
}
}
if
(
!
agp_try_unsupported
)
{
printk
(
KERN_ERR
PFX
"Unsupported Apple chipset"
" (device id: %04x).
\n
"
,
pdev
->
device
);
printk
(
KERN_ERR
PFX
"You might want to try"
" agp_try_unsupported=1
\n
"
);
return
-
ENODEV
;
}
printk
(
KERN_ERR
PFX
"Trying generic Uninorth routines"
" for device id %04x
\n
"
,
pdev
->
device
);
found:
bridge
=
agp_alloc_bridge
();
if
(
!
bridge
)
return
-
ENOMEM
;
bridge
->
driver
=
&
uninorth_agp_driver
;
bridge
->
dev
=
pdev
;
bridge
->
capndx
=
cap_ptr
;
/* Fill in the mode register */
pci_read_config_dword
(
pdev
,
cap_ptr
+
PCI_AGP_STATUS
,
&
bridge
->
mode
);
pci_set_drvdata
(
pdev
,
bridge
);
return
agp_add_bridge
(
bridge
);
}
static
void
__devexit
agp_uninorth_remove
(
struct
pci_dev
*
pdev
)
{
struct
agp_bridge_data
*
bridge
=
pci_get_drvdata
(
pdev
);
agp_remove_bridge
(
bridge
);
agp_put_bridge
(
bridge
);
}
static
struct
pci_device_id
agp_uninorth_pci_table
[]
__initdata
=
{
{
.
class
=
(
PCI_CLASS_BRIDGE_HOST
<<
8
),
.
class_mask
=
~
0
,
.
vendor
=
PCI_VENDOR_ID_APPLE
,
.
device
=
PCI_ANY_ID
,
.
subvendor
=
PCI_ANY_ID
,
.
subdevice
=
PCI_ANY_ID
,
},
{
}
};
MODULE_DEVICE_TABLE
(
pci
,
agp_uninorth_pci_table
);
static
struct
__initdata
pci_driver
agp_uninorth_pci_driver
=
{
.
name
=
"agpgart-uninorth"
,
.
id_table
=
agp_uninorth_pci_table
,
.
probe
=
agp_uninorth_probe
,
.
remove
=
agp_uninorth_remove
,
};
static
int
__init
agp_uninorth_init
(
void
)
{
return
pci_module_init
(
&
agp_uninorth_pci_driver
);
}
static
void
__exit
agp_uninorth_cleanup
(
void
)
{
pci_unregister_driver
(
&
agp_uninorth_pci_driver
);
}
module_init
(
agp_uninorth_init
);
module_exit
(
agp_uninorth_cleanup
);
MODULE_PARM
(
agp_try_unsupported
,
"1i"
);
MODULE_AUTHOR
(
"Ben Herrenschmidt & Paul Mackerras"
);
MODULE_LICENSE
(
"GPL"
);
include/asm-ppc/agp.h
0 → 100644
View file @
dc509d28
#ifndef AGP_H
#define AGP_H 1
#include <asm/io.h>
/* nothing much needed here */
#define map_page_into_agp(page)
#define unmap_page_from_agp(page)
#define flush_agp_mappings()
#define flush_agp_cache() mb()
#endif
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