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
8a7cd276
Commit
8a7cd276
authored
Aug 06, 2013
by
Alex Deucher
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/radeon/cik: add support for pcie gen1/2/3 switching
Signed-off-by:
Alex Deucher
<
alexander.deucher@amd.com
>
parent
8c68e393
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
218 additions
and
0 deletions
+218
-0
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/cik.c
+161
-0
drivers/gpu/drm/radeon/cikd.h
drivers/gpu/drm/radeon/cikd.h
+57
-0
No files found.
drivers/gpu/drm/radeon/cik.c
View file @
8a7cd276
...
...
@@ -61,6 +61,7 @@ extern void si_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *m
extern
void
si_rlc_fini
(
struct
radeon_device
*
rdev
);
extern
int
si_rlc_init
(
struct
radeon_device
*
rdev
);
static
void
cik_rlc_stop
(
struct
radeon_device
*
rdev
);
static
void
cik_pcie_gen3_enable
(
struct
radeon_device
*
rdev
);
/*
* Indirect registers accessor
...
...
@@ -5949,6 +5950,9 @@ static int cik_startup(struct radeon_device *rdev)
struct
radeon_ring
*
ring
;
int
r
;
/* enable pcie gen2/3 link */
cik_pcie_gen3_enable
(
rdev
);
cik_mc_program
(
rdev
);
if
(
rdev
->
flags
&
RADEON_IS_IGP
)
{
...
...
@@ -7051,3 +7055,160 @@ int cik_uvd_resume(struct radeon_device *rdev)
return
0
;
}
static
void
cik_pcie_gen3_enable
(
struct
radeon_device
*
rdev
)
{
struct
pci_dev
*
root
=
rdev
->
pdev
->
bus
->
self
;
int
bridge_pos
,
gpu_pos
;
u32
speed_cntl
,
mask
,
current_data_rate
;
int
ret
,
i
;
u16
tmp16
;
if
(
radeon_pcie_gen2
==
0
)
return
;
if
(
rdev
->
flags
&
RADEON_IS_IGP
)
return
;
if
(
!
(
rdev
->
flags
&
RADEON_IS_PCIE
))
return
;
ret
=
drm_pcie_get_speed_cap_mask
(
rdev
->
ddev
,
&
mask
);
if
(
ret
!=
0
)
return
;
if
(
!
(
mask
&
(
DRM_PCIE_SPEED_50
|
DRM_PCIE_SPEED_80
)))
return
;
speed_cntl
=
RREG32_PCIE_PORT
(
PCIE_LC_SPEED_CNTL
);
current_data_rate
=
(
speed_cntl
&
LC_CURRENT_DATA_RATE_MASK
)
>>
LC_CURRENT_DATA_RATE_SHIFT
;
if
(
mask
&
DRM_PCIE_SPEED_80
)
{
if
(
current_data_rate
==
2
)
{
DRM_INFO
(
"PCIE gen 3 link speeds already enabled
\n
"
);
return
;
}
DRM_INFO
(
"enabling PCIE gen 3 link speeds, disable with radeon.pcie_gen2=0
\n
"
);
}
else
if
(
mask
&
DRM_PCIE_SPEED_50
)
{
if
(
current_data_rate
==
1
)
{
DRM_INFO
(
"PCIE gen 2 link speeds already enabled
\n
"
);
return
;
}
DRM_INFO
(
"enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0
\n
"
);
}
bridge_pos
=
pci_pcie_cap
(
root
);
if
(
!
bridge_pos
)
return
;
gpu_pos
=
pci_pcie_cap
(
rdev
->
pdev
);
if
(
!
gpu_pos
)
return
;
if
(
mask
&
DRM_PCIE_SPEED_80
)
{
/* re-try equalization if gen3 is not already enabled */
if
(
current_data_rate
!=
2
)
{
u16
bridge_cfg
,
gpu_cfg
;
u16
bridge_cfg2
,
gpu_cfg2
;
u32
max_lw
,
current_lw
,
tmp
;
pci_read_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL
,
&
bridge_cfg
);
pci_read_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL
,
&
gpu_cfg
);
tmp16
=
bridge_cfg
|
PCI_EXP_LNKCTL_HAWD
;
pci_write_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL
,
tmp16
);
tmp16
=
gpu_cfg
|
PCI_EXP_LNKCTL_HAWD
;
pci_write_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL
,
tmp16
);
tmp
=
RREG32_PCIE_PORT
(
PCIE_LC_STATUS1
);
max_lw
=
(
tmp
&
LC_DETECTED_LINK_WIDTH_MASK
)
>>
LC_DETECTED_LINK_WIDTH_SHIFT
;
current_lw
=
(
tmp
&
LC_OPERATING_LINK_WIDTH_MASK
)
>>
LC_OPERATING_LINK_WIDTH_SHIFT
;
if
(
current_lw
<
max_lw
)
{
tmp
=
RREG32_PCIE_PORT
(
PCIE_LC_LINK_WIDTH_CNTL
);
if
(
tmp
&
LC_RENEGOTIATION_SUPPORT
)
{
tmp
&=
~
(
LC_LINK_WIDTH_MASK
|
LC_UPCONFIGURE_DIS
);
tmp
|=
(
max_lw
<<
LC_LINK_WIDTH_SHIFT
);
tmp
|=
LC_UPCONFIGURE_SUPPORT
|
LC_RENEGOTIATE_EN
|
LC_RECONFIG_NOW
;
WREG32_PCIE_PORT
(
PCIE_LC_LINK_WIDTH_CNTL
,
tmp
);
}
}
for
(
i
=
0
;
i
<
10
;
i
++
)
{
/* check status */
pci_read_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_DEVSTA
,
&
tmp16
);
if
(
tmp16
&
PCI_EXP_DEVSTA_TRPND
)
break
;
pci_read_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL
,
&
bridge_cfg
);
pci_read_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL
,
&
gpu_cfg
);
pci_read_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL2
,
&
bridge_cfg2
);
pci_read_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL2
,
&
gpu_cfg2
);
tmp
=
RREG32_PCIE_PORT
(
PCIE_LC_CNTL4
);
tmp
|=
LC_SET_QUIESCE
;
WREG32_PCIE_PORT
(
PCIE_LC_CNTL4
,
tmp
);
tmp
=
RREG32_PCIE_PORT
(
PCIE_LC_CNTL4
);
tmp
|=
LC_REDO_EQ
;
WREG32_PCIE_PORT
(
PCIE_LC_CNTL4
,
tmp
);
mdelay
(
100
);
/* linkctl */
pci_read_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL
,
&
tmp16
);
tmp16
&=
~
PCI_EXP_LNKCTL_HAWD
;
tmp16
|=
(
bridge_cfg
&
PCI_EXP_LNKCTL_HAWD
);
pci_write_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL
,
tmp16
);
pci_read_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL
,
&
tmp16
);
tmp16
&=
~
PCI_EXP_LNKCTL_HAWD
;
tmp16
|=
(
gpu_cfg
&
PCI_EXP_LNKCTL_HAWD
);
pci_write_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL
,
tmp16
);
/* linkctl2 */
pci_read_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL2
,
&
tmp16
);
tmp16
&=
~
((
1
<<
4
)
|
(
7
<<
9
));
tmp16
|=
(
bridge_cfg2
&
((
1
<<
4
)
|
(
7
<<
9
)));
pci_write_config_word
(
root
,
bridge_pos
+
PCI_EXP_LNKCTL2
,
tmp16
);
pci_read_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL2
,
&
tmp16
);
tmp16
&=
~
((
1
<<
4
)
|
(
7
<<
9
));
tmp16
|=
(
gpu_cfg2
&
((
1
<<
4
)
|
(
7
<<
9
)));
pci_write_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL2
,
tmp16
);
tmp
=
RREG32_PCIE_PORT
(
PCIE_LC_CNTL4
);
tmp
&=
~
LC_SET_QUIESCE
;
WREG32_PCIE_PORT
(
PCIE_LC_CNTL4
,
tmp
);
}
}
}
/* set the link speed */
speed_cntl
|=
LC_FORCE_EN_SW_SPEED_CHANGE
|
LC_FORCE_DIS_HW_SPEED_CHANGE
;
speed_cntl
&=
~
LC_FORCE_DIS_SW_SPEED_CHANGE
;
WREG32_PCIE_PORT
(
PCIE_LC_SPEED_CNTL
,
speed_cntl
);
pci_read_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL2
,
&
tmp16
);
tmp16
&=
~
0xf
;
if
(
mask
&
DRM_PCIE_SPEED_80
)
tmp16
|=
3
;
/* gen3 */
else
if
(
mask
&
DRM_PCIE_SPEED_50
)
tmp16
|=
2
;
/* gen2 */
else
tmp16
|=
1
;
/* gen1 */
pci_write_config_word
(
rdev
->
pdev
,
gpu_pos
+
PCI_EXP_LNKCTL2
,
tmp16
);
speed_cntl
=
RREG32_PCIE_PORT
(
PCIE_LC_SPEED_CNTL
);
speed_cntl
|=
LC_INITIATE_LINK_SPEED_CHANGE
;
WREG32_PCIE_PORT
(
PCIE_LC_SPEED_CNTL
,
speed_cntl
);
for
(
i
=
0
;
i
<
rdev
->
usec_timeout
;
i
++
)
{
speed_cntl
=
RREG32_PCIE_PORT
(
PCIE_LC_SPEED_CNTL
);
if
((
speed_cntl
&
LC_INITIATE_LINK_SPEED_CHANGE
)
==
0
)
break
;
udelay
(
1
);
}
}
drivers/gpu/drm/radeon/cikd.h
View file @
8a7cd276
...
...
@@ -35,6 +35,63 @@
#define CG_CLKPIN_CNTL 0xC05001A0
# define XTALIN_DIVIDE (1 << 1)
/* PCIE registers idx/data 0x38/0x3c */
#define PCIE_LC_STATUS1 0x1400028
/* PCIE */
# define LC_REVERSE_RCVR (1 << 0)
# define LC_REVERSE_XMIT (1 << 1)
# define LC_OPERATING_LINK_WIDTH_MASK (0x7 << 2)
# define LC_OPERATING_LINK_WIDTH_SHIFT 2
# define LC_DETECTED_LINK_WIDTH_MASK (0x7 << 5)
# define LC_DETECTED_LINK_WIDTH_SHIFT 5
#define PCIE_LC_LINK_WIDTH_CNTL 0x100100A2
/* PCIE */
# define LC_LINK_WIDTH_SHIFT 0
# define LC_LINK_WIDTH_MASK 0x7
# define LC_LINK_WIDTH_X0 0
# define LC_LINK_WIDTH_X1 1
# define LC_LINK_WIDTH_X2 2
# define LC_LINK_WIDTH_X4 3
# define LC_LINK_WIDTH_X8 4
# define LC_LINK_WIDTH_X16 6
# define LC_LINK_WIDTH_RD_SHIFT 4
# define LC_LINK_WIDTH_RD_MASK 0x70
# define LC_RECONFIG_ARC_MISSING_ESCAPE (1 << 7)
# define LC_RECONFIG_NOW (1 << 8)
# define LC_RENEGOTIATION_SUPPORT (1 << 9)
# define LC_RENEGOTIATE_EN (1 << 10)
# define LC_SHORT_RECONFIG_EN (1 << 11)
# define LC_UPCONFIGURE_SUPPORT (1 << 12)
# define LC_UPCONFIGURE_DIS (1 << 13)
# define LC_DYN_LANES_PWR_STATE(x) ((x) << 21)
# define LC_DYN_LANES_PWR_STATE_MASK (0x3 << 21)
# define LC_DYN_LANES_PWR_STATE_SHIFT 21
#define PCIE_LC_SPEED_CNTL 0x100100A4
/* PCIE */
# define LC_GEN2_EN_STRAP (1 << 0)
# define LC_GEN3_EN_STRAP (1 << 1)
# define LC_TARGET_LINK_SPEED_OVERRIDE_EN (1 << 2)
# define LC_TARGET_LINK_SPEED_OVERRIDE_MASK (0x3 << 3)
# define LC_TARGET_LINK_SPEED_OVERRIDE_SHIFT 3
# define LC_FORCE_EN_SW_SPEED_CHANGE (1 << 5)
# define LC_FORCE_DIS_SW_SPEED_CHANGE (1 << 6)
# define LC_FORCE_EN_HW_SPEED_CHANGE (1 << 7)
# define LC_FORCE_DIS_HW_SPEED_CHANGE (1 << 8)
# define LC_INITIATE_LINK_SPEED_CHANGE (1 << 9)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK (0x3 << 10)
# define LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT 10
# define LC_CURRENT_DATA_RATE_MASK (0x3 << 13)
/* 0/1/2 = gen1/2/3 */
# define LC_CURRENT_DATA_RATE_SHIFT 13
# define LC_CLR_FAILED_SPD_CHANGE_CNT (1 << 16)
# define LC_OTHER_SIDE_EVER_SENT_GEN2 (1 << 18)
# define LC_OTHER_SIDE_SUPPORTS_GEN2 (1 << 19)
# define LC_OTHER_SIDE_EVER_SENT_GEN3 (1 << 20)
# define LC_OTHER_SIDE_SUPPORTS_GEN3 (1 << 21)
#define PCIE_LC_CNTL4 0x100100B6
/* PCIE */
# define LC_REDO_EQ (1 << 5)
# define LC_SET_QUIESCE (1 << 13)
/* direct registers */
#define PCIE_INDEX 0x38
#define PCIE_DATA 0x3C
...
...
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