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
65c7b2d6
Commit
65c7b2d6
authored
Jan 25, 2004
by
Benjamin Herrenschmidt
Committed by
David S. Miller
Jan 25, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SUNGEM]: Add support for G5 PowerMAC plus PM fixes.
parent
c1f8218a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
115 additions
and
42 deletions
+115
-42
drivers/net/sungem.c
drivers/net/sungem.c
+75
-34
drivers/net/sungem.h
drivers/net/sungem.h
+3
-0
drivers/net/sungem_phy.c
drivers/net/sungem_phy.c
+37
-8
No files found.
drivers/net/sungem.c
View file @
65c7b2d6
...
...
@@ -103,6 +103,8 @@ static struct pci_device_id gem_pci_tbl[] = {
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0UL
},
{
PCI_VENDOR_ID_APPLE
,
PCI_DEVICE_ID_APPLE_UNI_N_GMAC2
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0UL
},
{
PCI_VENDOR_ID_APPLE
,
PCI_DEVICE_ID_APPLE_K2_GMAC
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0UL
},
{
0
,
}
};
...
...
@@ -778,6 +780,10 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct
gem
*
gp
=
dev
->
priv
;
u32
gem_status
=
readl
(
gp
->
regs
+
GREG_STAT
);
/* Swallow interrupts when shutting the chip down */
if
(
gp
->
hw_running
==
0
)
goto
out
;
spin_lock
(
&
gp
->
lock
);
if
(
gem_status
&
GREG_STAT_ABNORMAL
)
{
...
...
@@ -1240,6 +1246,12 @@ static int gem_mdio_link_not_up(struct gem *gp)
gp
->
lstate
=
link_force_ok
;
return
0
;
case
link_aneg
:
/* We try forced modes after a failed aneg only on PHYs that don't
* have "magic_aneg" bit set, which means they internally do the
* while forced-mode thingy. On these, we just restart aneg
*/
if
(
gp
->
phy_mii
.
def
->
magic_aneg
)
return
1
;
if
(
netif_msg_link
(
gp
))
printk
(
KERN_INFO
"%s: switching to forced 100bt
\n
"
,
gp
->
dev
->
name
);
...
...
@@ -1497,18 +1509,26 @@ static void gem_init_phy(struct gem *gp)
* to schedule instead
*/
pmac_call_feature
(
PMAC_FTR_GMAC_PHY_RESET
,
gp
->
of_node
,
0
,
0
);
mdelay
(
10
);
for
(
j
=
0
;
j
<
3
;
j
++
)
{
/* Some PHYs used by apple have problem getting back to us,
* we _know_ it's actually at addr 0, that's a hack, but
* we _know_ it's actually at addr 0
or 1
, that's a hack, but
* it helps to do that reset now. I suspect some motherboards
* don't wire the PHY reset line properly, thus the PHY doesn't
* come back with the above pmac_call_feature.
*/
gp
->
mii_phy_addr
=
0
;
phy_write
(
gp
,
MII_BMCR
,
BMCR_RESET
);
gp
->
mii_phy_addr
=
1
;
phy_write
(
gp
,
MII_BMCR
,
BMCR_RESET
);
/* We should probably break some locks here and schedule... */
mdelay
(
10
);
/* On K2, we only probe the internal PHY at address 1, other
* addresses tend to return garbage.
*/
if
(
gp
->
pdev
->
device
==
PCI_DEVICE_ID_APPLE_K2_GMAC
)
break
;
for
(
i
=
0
;
i
<
32
;
i
++
)
{
gp
->
mii_phy_addr
=
i
;
if
(
phy_read
(
gp
,
MII_BMCR
)
!=
0xffff
)
...
...
@@ -1770,6 +1790,8 @@ static void gem_init_mac(struct gem *gp)
/* Must be invoked under gp->lock. */
static
void
gem_init_pause_thresholds
(
struct
gem
*
gp
)
{
u32
cfg
;
/* Calculate pause thresholds. Setting the OFF threshold to the
* full RX fifo size effectively disables PAUSE generation which
* is what we do for 10/100 only GEMs which have FIFOs too small
...
...
@@ -1786,17 +1808,28 @@ static void gem_init_pause_thresholds(struct gem *gp)
gp
->
rx_pause_on
=
on
;
}
{
u32
cfg
;
cfg
=
0
;
/* Configure the chip "burst" DMA mode & enable some
* HW bug fixes on Apple version
*/
cfg
=
0
;
if
(
gp
->
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
cfg
|=
GREG_CFG_RONPAULBIT
|
GREG_CFG_ENBUG2FIX
;
#if !defined(CONFIG_SPARC64) && !defined(CONFIG_ALPHA)
cfg
|=
GREG_CFG_IBURST
;
cfg
|=
GREG_CFG_IBURST
;
#endif
cfg
|=
((
31
<<
1
)
&
GREG_CFG_TXDMALIM
);
cfg
|=
((
31
<<
6
)
&
GREG_CFG_RXDMALIM
);
cfg
|=
((
31
<<
1
)
&
GREG_CFG_TXDMALIM
);
cfg
|=
((
31
<<
6
)
&
GREG_CFG_RXDMALIM
);
writel
(
cfg
,
gp
->
regs
+
GREG_CFG
);
/* If Infinite Burst didn't stick, then use different
* thresholds (and Apple bug fixes don't exist)
*/
if
(
readl
(
gp
->
regs
+
GREG_CFG
)
&
GREG_CFG_IBURST
)
{
cfg
=
((
2
<<
1
)
&
GREG_CFG_TXDMALIM
);
cfg
=
((
8
<<
6
)
&
GREG_CFG_RXDMALIM
);
writel
(
cfg
,
gp
->
regs
+
GREG_CFG
);
}
}
}
static
int
gem_check_invariants
(
struct
gem
*
gp
)
...
...
@@ -1931,18 +1964,10 @@ static void gem_apple_powerup(struct gem *gp)
u16
cmd
;
u32
mif_cfg
;
mb
();
pmac_call_feature
(
PMAC_FTR_GMAC_ENABLE
,
gp
->
of_node
,
0
,
1
);
current
->
state
=
TASK_UNINTERRUPTIBLE
;
schedule_timeout
((
21
*
HZ
)
/
1000
);
pci_read_config_word
(
gp
->
pdev
,
PCI_COMMAND
,
&
cmd
);
cmd
|=
PCI_COMMAND_MEMORY
|
PCI_COMMAND_MASTER
|
PCI_COMMAND_INVALIDATE
;
pci_write_config_word
(
gp
->
pdev
,
PCI_COMMAND
,
cmd
);
pci_write_config_byte
(
gp
->
pdev
,
PCI_LATENCY_TIMER
,
6
);
pci_write_config_byte
(
gp
->
pdev
,
PCI_CACHE_LINE_SIZE
,
8
);
mdelay
(
1
);
udelay
(
3
);
mif_cfg
=
readl
(
gp
->
regs
+
MIF_CFG
);
mif_cfg
&=
~
(
MIF_CFG_PSELECT
|
MIF_CFG_POLL
|
MIF_CFG_BBMODE
|
MIF_CFG_MDI1
);
...
...
@@ -1950,8 +1975,6 @@ static void gem_apple_powerup(struct gem *gp)
writel
(
mif_cfg
,
gp
->
regs
+
MIF_CFG
);
writel
(
PCS_DMODE_MGM
,
gp
->
regs
+
PCS_DMODE
);
writel
(
MAC_XIFCFG_OE
,
gp
->
regs
+
MAC_XIFCFG
);
mdelay
(
1
);
}
/* Turn off the chip's clock */
...
...
@@ -1962,10 +1985,17 @@ static void gem_apple_powerdown(struct gem *gp)
#endif
/* CONFIG_PPC_PMAC */
/* Must be invoked
under gp->lock
. */
/* Must be invoked
with no lock held
. */
static
void
gem_stop_phy
(
struct
gem
*
gp
)
{
u32
mifcfg
;
unsigned
long
flags
;
/* Let the chip settle down a bit, it seems that helps
* for sleep mode on some models
*/
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
/
100
);
/* Make sure we aren't polling PHY status change. We
* don't currently use that feature though
...
...
@@ -1976,17 +2006,28 @@ static void gem_stop_phy(struct gem *gp)
if
(
gp
->
wake_on_lan
)
{
/* Setup wake-on-lan */
}
else
}
else
{
writel
(
0
,
gp
->
regs
+
MAC_RXCFG
);
(
void
)
readl
(
gp
->
regs
+
MAC_RXCFG
);
/* Machine sleep will die in strange ways if we
* dont wait a bit here, looks like the chip takes
* some time to really shut down
*/
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule_timeout
(
HZ
/
100
);
}
writel
(
0
,
gp
->
regs
+
MAC_TXCFG
);
writel
(
0
,
gp
->
regs
+
MAC_XIFCFG
);
writel
(
0
,
gp
->
regs
+
TXDMA_CFG
);
writel
(
0
,
gp
->
regs
+
RXDMA_CFG
);
if
(
!
gp
->
wake_on_lan
)
{
spin_lock_irqsave
(
&
gp
->
lock
,
flags
);
gem_stop
(
gp
);
writel
(
MAC_TXRST_CMD
,
gp
->
regs
+
MAC_TXRST
);
writel
(
MAC_RXRST_CMD
,
gp
->
regs
+
MAC_RXRST
);
spin_unlock_irqrestore
(
&
gp
->
lock
,
flags
);
}
if
(
found_mii_phy
(
gp
)
&&
gp
->
phy_mii
.
def
->
ops
->
suspend
)
...
...
@@ -2008,31 +2049,33 @@ static void gem_stop_phy(struct gem *gp)
/* Shut down the chip, must be called with pm_sem held. */
static
void
gem_shutdown
(
struct
gem
*
gp
)
{
/* Make us not-running to avoid timers respawning */
/* Make us not-running to avoid timers respawning
* and swallow irqs
*/
gp
->
hw_running
=
0
;
wmb
();
/* Stop the link timer */
del_timer_sync
(
&
gp
->
link_timer
);
/* Stop the reset task */
while
(
gp
->
reset_task_pending
)
schedule
();
yield
();
/* Actually stop the chip */
spin_lock_irq
(
&
gp
->
lock
);
if
(
gp
->
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
{
gem_stop_phy
(
gp
);
spin_unlock_irq
(
&
gp
->
lock
);
#ifdef CONFIG_PPC_PMAC
/* Power down the chip */
gem_apple_powerdown
(
gp
);
#endif
/* CONFIG_PPC_PMAC */
}
else
{
gem_stop
(
gp
)
;
}
else
{
unsigned
long
flags
;
spin_unlock_irq
(
&
gp
->
lock
);
spin_lock_irqsave
(
&
gp
->
lock
,
flags
);
gem_stop
(
gp
);
spin_unlock_irqrestore
(
&
gp
->
lock
,
flags
);
}
}
...
...
@@ -2692,6 +2735,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
* not have properly shut down the PHY.
*/
#ifdef CONFIG_PPC_PMAC
gp
->
of_node
=
pci_device_to_OF_node
(
pdev
);
if
(
pdev
->
vendor
==
PCI_VENDOR_ID_APPLE
)
gem_apple_powerup
(
gp
);
#endif
...
...
@@ -2725,9 +2769,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
goto
err_out_iounmap
;
}
#ifdef CONFIG_PPC_PMAC
gp
->
of_node
=
pci_device_to_OF_node
(
pdev
);
#endif
if
(
gem_get_device_address
(
gp
))
goto
err_out_free_consistent
;
...
...
drivers/net/sungem.h
View file @
65c7b2d6
...
...
@@ -28,6 +28,9 @@
#define GREG_CFG_IBURST 0x00000001
/* Infinite Burst */
#define GREG_CFG_TXDMALIM 0x0000003e
/* TX DMA grant limit */
#define GREG_CFG_RXDMALIM 0x000007c0
/* RX DMA grant limit */
#define GREG_CFG_RONPAULBIT 0x00000800
/* Use mem read multiple for PCI read
* after infinite burst (Apple) */
#define GREG_CFG_ENBUG2FIX 0x00001000
/* Fix Rx hang after overflow */
/* Global Interrupt Status Register.
*
...
...
drivers/net/sungem_phy.c
View file @
65c7b2d6
...
...
@@ -72,7 +72,7 @@ static int reset_one_mii_phy(struct mii_phy* phy, int phy_id)
int
limit
=
10000
;
val
=
__phy_read
(
phy
,
phy_id
,
MII_BMCR
);
val
&=
~
BMCR_ISOLATE
;
val
&=
~
(
BMCR_ISOLATE
|
BMCR_PDOWN
)
;
val
|=
BMCR_RESET
;
__phy_write
(
phy
,
phy_id
,
MII_BMCR
,
val
);
...
...
@@ -157,7 +157,7 @@ static int bcm5400_init(struct mii_phy* phy)
data
|=
MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP
;
phy_write
(
phy
,
MII_BCM5400_GB_CONTROL
,
data
);
mdelay
(
1
0
);
udelay
(
10
0
);
/* Reset and configure cascaded 10/100 PHY */
(
void
)
reset_one_mii_phy
(
phy
,
0x1f
);
...
...
@@ -217,7 +217,7 @@ static int bcm5401_init(struct mii_phy* phy)
data
|=
MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP
;
phy_write
(
phy
,
MII_BCM5400_GB_CONTROL
,
data
);
m
delay
(
10
);
u
delay
(
10
);
/* Reset and configure cascaded 10/100 PHY */
(
void
)
reset_one_mii_phy
(
phy
,
0x1f
);
...
...
@@ -258,7 +258,7 @@ static int bcm5411_init(struct mii_phy* phy)
data
|=
MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP
;
phy_write
(
phy
,
MII_BCM5400_GB_CONTROL
,
data
);
m
delay
(
10
);
u
delay
(
10
);
/* Reset and configure cascaded 10/100 PHY */
(
void
)
reset_one_mii_phy
(
phy
,
0x1f
);
...
...
@@ -302,6 +302,15 @@ static int bcm5421_init(struct mii_phy* phy)
return
0
;
}
static
int
bcm5421k2_init
(
struct
mii_phy
*
phy
)
{
/* Init code borrowed from OF */
phy_write
(
phy
,
4
,
0x01e1
);
phy_write
(
phy
,
9
,
0x0300
);
return
0
;
}
static
int
bcm54xx_setup_aneg
(
struct
mii_phy
*
phy
,
u32
advertise
)
{
u16
ctl
,
adv
;
...
...
@@ -647,7 +656,7 @@ static struct mii_phy_def bcm5201_phy_def = {
.
phy_id_mask
=
0xfffffff0
,
.
name
=
"BCM5201"
,
.
features
=
MII_BASIC_FEATURES
,
.
magic_aneg
=
0
,
.
magic_aneg
=
1
,
.
ops
=
&
bcm5201_phy_ops
};
...
...
@@ -666,7 +675,7 @@ static struct mii_phy_def bcm5221_phy_def = {
.
phy_id_mask
=
0xfffffff0
,
.
name
=
"BCM5221"
,
.
features
=
MII_BASIC_FEATURES
,
.
magic_aneg
=
0
,
.
magic_aneg
=
1
,
.
ops
=
&
bcm5221_phy_ops
};
...
...
@@ -746,6 +755,25 @@ static struct mii_phy_def bcm5421_phy_def = {
.
ops
=
&
bcm5421_phy_ops
};
/* Broadcom BCM 5421 built-in K2 */
static
struct
mii_phy_ops
bcm5421k2_phy_ops
=
{
.
init
=
bcm5421k2_init
,
.
suspend
=
bcm5411_suspend
,
.
setup_aneg
=
bcm54xx_setup_aneg
,
.
setup_forced
=
bcm54xx_setup_forced
,
.
poll_link
=
genmii_poll_link
,
.
read_link
=
bcm54xx_read_link
,
};
static
struct
mii_phy_def
bcm5421k2_phy_def
=
{
.
phy_id
=
0x002062e0
,
.
phy_id_mask
=
0xfffffff0
,
.
name
=
"BCM5421-K2"
,
.
features
=
MII_GBIT_FEATURES
,
.
magic_aneg
=
1
,
.
ops
=
&
bcm5421k2_phy_ops
};
/* Marvell 88E1101 (Apple seem to deal with 2 different revs,
* I masked out the 8 last bits to get both, but some specs
* would be useful here) --BenH.
...
...
@@ -790,6 +818,7 @@ static struct mii_phy_def* mii_phy_table[] = {
&
bcm5401_phy_def
,
&
bcm5411_phy_def
,
&
bcm5421_phy_def
,
&
bcm5421k2_phy_def
,
&
marvell_phy_def
,
&
genmii_phy_def
,
NULL
...
...
@@ -813,8 +842,8 @@ int mii_phy_probe(struct mii_phy *phy, int mii_id)
goto
fail
;
/* Read ID and find matching entry */
id
=
(
phy_read
(
phy
,
MII_PHYSID1
)
<<
16
|
phy_read
(
phy
,
MII_PHYSID2
))
&
0xfffffff0
;
id
=
(
phy_read
(
phy
,
MII_PHYSID1
)
<<
16
|
phy_read
(
phy
,
MII_PHYSID2
))
;
printk
(
KERN_DEBUG
"PHY ID: %x, addr: %x
\n
"
,
id
,
mii_id
)
;
for
(
i
=
0
;
(
def
=
mii_phy_table
[
i
])
!=
NULL
;
i
++
)
if
((
id
&
def
->
phy_id_mask
)
==
def
->
phy_id
)
break
;
...
...
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