mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
Merge commit 'jwb/jwb-next'
This commit is contained in:
293
arch/powerpc/boot/dts/arches.dts
Normal file
293
arch/powerpc/boot/dts/arches.dts
Normal file
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Device Tree Source for AMCC Arches (dual 460GT board)
|
||||
*
|
||||
* (C) Copyright 2008 Applied Micro Circuits Corporation
|
||||
* Victor Gallardo <vgallardo@amcc.com>
|
||||
* Adam Graham <agraham@amcc.com>
|
||||
*
|
||||
* Based on the glacier.dts file
|
||||
* Stefan Roese <sr@denx.de>
|
||||
* Copyright 2008 DENX Software Engineering
|
||||
*
|
||||
* See file CREDITS for list of people who contributed to this
|
||||
* project.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
model = "amcc,arches";
|
||||
compatible = "amcc,arches";
|
||||
dcr-parent = <&{/cpus/cpu@0}>;
|
||||
|
||||
aliases {
|
||||
ethernet0 = &EMAC0;
|
||||
ethernet1 = &EMAC1;
|
||||
ethernet2 = &EMAC2;
|
||||
serial0 = &UART0;
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
model = "PowerPC,460GT";
|
||||
reg = <0x00000000>;
|
||||
clock-frequency = <0>; /* Filled in by U-Boot */
|
||||
timebase-frequency = <0>; /* Filled in by U-Boot */
|
||||
i-cache-line-size = <32>;
|
||||
d-cache-line-size = <32>;
|
||||
i-cache-size = <32768>;
|
||||
d-cache-size = <32768>;
|
||||
dcr-controller;
|
||||
dcr-access-method = "native";
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */
|
||||
};
|
||||
|
||||
UIC0: interrupt-controller0 {
|
||||
compatible = "ibm,uic-460gt","ibm,uic";
|
||||
interrupt-controller;
|
||||
cell-index = <0>;
|
||||
dcr-reg = <0x0c0 0x009>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
UIC1: interrupt-controller1 {
|
||||
compatible = "ibm,uic-460gt","ibm,uic";
|
||||
interrupt-controller;
|
||||
cell-index = <1>;
|
||||
dcr-reg = <0x0d0 0x009>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */
|
||||
interrupt-parent = <&UIC0>;
|
||||
};
|
||||
|
||||
UIC2: interrupt-controller2 {
|
||||
compatible = "ibm,uic-460gt","ibm,uic";
|
||||
interrupt-controller;
|
||||
cell-index = <2>;
|
||||
dcr-reg = <0x0e0 0x009>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <0xa 0x4 0xb 0x4>; /* cascade */
|
||||
interrupt-parent = <&UIC0>;
|
||||
};
|
||||
|
||||
UIC3: interrupt-controller3 {
|
||||
compatible = "ibm,uic-460gt","ibm,uic";
|
||||
interrupt-controller;
|
||||
cell-index = <3>;
|
||||
dcr-reg = <0x0f0 0x009>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupts = <0x10 0x4 0x11 0x4>; /* cascade */
|
||||
interrupt-parent = <&UIC0>;
|
||||
};
|
||||
|
||||
SDR0: sdr {
|
||||
compatible = "ibm,sdr-460gt";
|
||||
dcr-reg = <0x00e 0x002>;
|
||||
};
|
||||
|
||||
CPR0: cpr {
|
||||
compatible = "ibm,cpr-460gt";
|
||||
dcr-reg = <0x00c 0x002>;
|
||||
};
|
||||
|
||||
plb {
|
||||
compatible = "ibm,plb-460gt", "ibm,plb4";
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
clock-frequency = <0>; /* Filled in by U-Boot */
|
||||
|
||||
SDRAM0: sdram {
|
||||
compatible = "ibm,sdram-460gt", "ibm,sdram-405gp";
|
||||
dcr-reg = <0x010 0x002>;
|
||||
};
|
||||
|
||||
MAL0: mcmal {
|
||||
compatible = "ibm,mcmal-460gt", "ibm,mcmal2";
|
||||
dcr-reg = <0x180 0x062>;
|
||||
num-tx-chans = <3>;
|
||||
num-rx-chans = <24>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-parent = <&UIC2>;
|
||||
interrupts = < /*TXEOB*/ 0x6 0x4
|
||||
/*RXEOB*/ 0x7 0x4
|
||||
/*SERR*/ 0x3 0x4
|
||||
/*TXDE*/ 0x4 0x4
|
||||
/*RXDE*/ 0x5 0x4>;
|
||||
desc-base-addr-high = <0x8>;
|
||||
};
|
||||
|
||||
POB0: opb {
|
||||
compatible = "ibm,opb-460gt", "ibm,opb";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>;
|
||||
clock-frequency = <0>; /* Filled in by U-Boot */
|
||||
|
||||
EBC0: ebc {
|
||||
compatible = "ibm,ebc-460gt", "ibm,ebc";
|
||||
dcr-reg = <0x012 0x002>;
|
||||
#address-cells = <2>;
|
||||
#size-cells = <1>;
|
||||
clock-frequency = <0>; /* Filled in by U-Boot */
|
||||
/* ranges property is supplied by U-Boot */
|
||||
interrupts = <0x6 0x4>;
|
||||
interrupt-parent = <&UIC1>;
|
||||
};
|
||||
|
||||
UART0: serial@ef600300 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <0xef600300 0x00000008>;
|
||||
virtual-reg = <0xef600300>;
|
||||
clock-frequency = <0>; /* Filled in by U-Boot */
|
||||
current-speed = <0>; /* Filled in by U-Boot */
|
||||
interrupt-parent = <&UIC1>;
|
||||
interrupts = <0x1 0x4>;
|
||||
};
|
||||
|
||||
IIC0: i2c@ef600700 {
|
||||
compatible = "ibm,iic-460gt", "ibm,iic";
|
||||
reg = <0xef600700 0x00000014>;
|
||||
interrupt-parent = <&UIC0>;
|
||||
interrupts = <0x2 0x4>;
|
||||
};
|
||||
|
||||
IIC1: i2c@ef600800 {
|
||||
compatible = "ibm,iic-460gt", "ibm,iic";
|
||||
reg = <0xef600800 0x00000014>;
|
||||
interrupt-parent = <&UIC0>;
|
||||
interrupts = <0x3 0x4>;
|
||||
};
|
||||
|
||||
TAH0: emac-tah@ef601350 {
|
||||
compatible = "ibm,tah-460gt", "ibm,tah";
|
||||
reg = <0xef601350 0x00000030>;
|
||||
};
|
||||
|
||||
TAH1: emac-tah@ef601450 {
|
||||
compatible = "ibm,tah-460gt", "ibm,tah";
|
||||
reg = <0xef601450 0x00000030>;
|
||||
};
|
||||
|
||||
EMAC0: ethernet@ef600e00 {
|
||||
device_type = "network";
|
||||
compatible = "ibm,emac-460gt", "ibm,emac4sync";
|
||||
interrupt-parent = <&EMAC0>;
|
||||
interrupts = <0x0 0x1>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4
|
||||
/*Wake*/ 0x1 &UIC2 0x14 0x4>;
|
||||
reg = <0xef600e00 0x000000c4>;
|
||||
local-mac-address = [000000000000]; /* Filled in by U-Boot */
|
||||
mal-device = <&MAL0>;
|
||||
mal-tx-channel = <0>;
|
||||
mal-rx-channel = <0>;
|
||||
cell-index = <0>;
|
||||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
phy-mode = "sgmii";
|
||||
phy-map = <0xffffffff>;
|
||||
gpcs-address = <0x0000000a>;
|
||||
tah-device = <&TAH0>;
|
||||
tah-channel = <0>;
|
||||
has-inverted-stacr-oc;
|
||||
has-new-stacr-staopc;
|
||||
};
|
||||
|
||||
EMAC1: ethernet@ef600f00 {
|
||||
device_type = "network";
|
||||
compatible = "ibm,emac-460gt", "ibm,emac4sync";
|
||||
interrupt-parent = <&EMAC1>;
|
||||
interrupts = <0x0 0x1>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = </*Status*/ 0x0 &UIC2 0x11 0x4
|
||||
/*Wake*/ 0x1 &UIC2 0x15 0x4>;
|
||||
reg = <0xef600f00 0x000000c4>;
|
||||
local-mac-address = [000000000000]; /* Filled in by U-Boot */
|
||||
mal-device = <&MAL0>;
|
||||
mal-tx-channel = <1>;
|
||||
mal-rx-channel = <8>;
|
||||
cell-index = <1>;
|
||||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
phy-mode = "sgmii";
|
||||
phy-map = <0x00000000>;
|
||||
gpcs-address = <0x0000000b>;
|
||||
tah-device = <&TAH1>;
|
||||
tah-channel = <1>;
|
||||
has-inverted-stacr-oc;
|
||||
has-new-stacr-staopc;
|
||||
mdio-device = <&EMAC0>;
|
||||
};
|
||||
|
||||
EMAC2: ethernet@ef601100 {
|
||||
device_type = "network";
|
||||
compatible = "ibm,emac-460gt", "ibm,emac4sync";
|
||||
interrupt-parent = <&EMAC2>;
|
||||
interrupts = <0x0 0x1>;
|
||||
#interrupt-cells = <1>;
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
interrupt-map = </*Status*/ 0x0 &UIC2 0x12 0x4
|
||||
/*Wake*/ 0x1 &UIC2 0x16 0x4>;
|
||||
reg = <0xef601100 0x000000c4>;
|
||||
local-mac-address = [000000000000]; /* Filled in by U-Boot */
|
||||
mal-device = <&MAL0>;
|
||||
mal-tx-channel = <2>;
|
||||
mal-rx-channel = <16>;
|
||||
cell-index = <2>;
|
||||
max-frame-size = <9000>;
|
||||
rx-fifo-size = <4096>;
|
||||
tx-fifo-size = <2048>;
|
||||
phy-mode = "sgmii";
|
||||
phy-map = <0x00000001>;
|
||||
gpcs-address = <0x0000000C>;
|
||||
has-inverted-stacr-oc;
|
||||
has-new-stacr-staopc;
|
||||
mdio-device = <&EMAC0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
767
arch/powerpc/configs/44x/arches_defconfig
Normal file
767
arch/powerpc/configs/44x/arches_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -68,6 +68,17 @@
|
||||
#define SDR0_UART3 0x0123
|
||||
#define SDR0_CUST0 0x4000
|
||||
|
||||
/* SDR for 405EZ */
|
||||
#define DCRN_SDR_ICINTSTAT 0x4510
|
||||
#define ICINTSTAT_ICRX 0x80000000
|
||||
#define ICINTSTAT_ICTX0 0x40000000
|
||||
#define ICINTSTAT_ICTX1 0x20000000
|
||||
#define ICINTSTAT_ICTX 0x60000000
|
||||
|
||||
/* SDRs (460EX/460GT) */
|
||||
#define SDR0_ETH_CFG 0x4103
|
||||
#define SDR0_ETH_CFG_ECS 0x00000100 /* EMAC int clk source */
|
||||
|
||||
/*
|
||||
* All those DCR register addresses are offsets from the base address
|
||||
* for the SRAM0 controller (e.g. 0x20 on 440GX). The base address is
|
||||
|
||||
@@ -81,6 +81,17 @@ config WARP
|
||||
See http://www.pikatechnologies.com/ and follow the "PIKA for Computer
|
||||
Telephony Developers" link for more information.
|
||||
|
||||
config ARCHES
|
||||
bool "Arches"
|
||||
depends on 44x
|
||||
default n
|
||||
select PPC44x_SIMPLE
|
||||
select 460EX # Odd since it uses 460GT but the effects are the same
|
||||
select PCI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
help
|
||||
This option enables support for the AMCC Dual PPC460GT evaluation board.
|
||||
|
||||
config CANYONLANDS
|
||||
bool "Canyonlands"
|
||||
depends on 44x
|
||||
@@ -89,6 +100,8 @@ config CANYONLANDS
|
||||
select 460EX
|
||||
select PCI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
select IBM_NEW_EMAC_RGMII
|
||||
select IBM_NEW_EMAC_ZMII
|
||||
help
|
||||
This option enables support for the AMCC PPC460EX evaluation board.
|
||||
|
||||
@@ -100,6 +113,8 @@ config GLACIER
|
||||
select 460EX # Odd since it uses 460GT but the effects are the same
|
||||
select PCI
|
||||
select PPC4xx_PCI_EXPRESS
|
||||
select IBM_NEW_EMAC_RGMII
|
||||
select IBM_NEW_EMAC_ZMII
|
||||
help
|
||||
This option enables support for the AMCC PPC460GT evaluation board.
|
||||
|
||||
@@ -195,8 +210,6 @@ config 460EX
|
||||
bool
|
||||
select PPC_FPU
|
||||
select IBM_NEW_EMAC_EMAC4
|
||||
select IBM_NEW_EMAC_RGMII
|
||||
select IBM_NEW_EMAC_ZMII
|
||||
select IBM_NEW_EMAC_TAH
|
||||
|
||||
# 44x errata/workaround config symbols, selected by the CPU models above
|
||||
|
||||
@@ -50,8 +50,9 @@ machine_device_initcall(ppc44x_simple, ppc44x_device_probe);
|
||||
* board.c file for it rather than adding it to this list.
|
||||
*/
|
||||
static char *board[] __initdata = {
|
||||
"amcc,arches",
|
||||
"amcc,bamboo",
|
||||
"amcc,cayonlands",
|
||||
"amcc,canyonlands",
|
||||
"amcc,glacier",
|
||||
"ibm,ebony",
|
||||
"amcc,katmai",
|
||||
|
||||
@@ -276,9 +276,16 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
|
||||
const int *bus_range;
|
||||
int primary = 0;
|
||||
|
||||
/* Check if device is enabled */
|
||||
if (!of_device_is_available(np)) {
|
||||
printk(KERN_INFO "%s: Port disabled via device-tree\n",
|
||||
np->full_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fetch config space registers address */
|
||||
if (of_address_to_resource(np, 0, &rsrc_cfg)) {
|
||||
printk(KERN_ERR "%s:Can't get PCI config register base !",
|
||||
printk(KERN_ERR "%s: Can't get PCI config register base !",
|
||||
np->full_name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,3 +62,15 @@ config IBM_NEW_EMAC_TAH
|
||||
config IBM_NEW_EMAC_EMAC4
|
||||
bool
|
||||
default n
|
||||
|
||||
config IBM_NEW_EMAC_NO_FLOW_CTRL
|
||||
bool
|
||||
default n
|
||||
|
||||
config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
|
||||
bool
|
||||
default n
|
||||
|
||||
config IBM_NEW_EMAC_MAL_COMMON_ERR
|
||||
bool
|
||||
default n
|
||||
|
||||
@@ -130,6 +130,7 @@ static inline void emac_report_timeout_error(struct emac_instance *dev,
|
||||
const char *error)
|
||||
{
|
||||
if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
|
||||
EMAC_FTR_460EX_PHY_CLK_FIX |
|
||||
EMAC_FTR_440EP_PHY_CLK_FIX))
|
||||
DBG(dev, "%s" NL, error);
|
||||
else if (net_ratelimit())
|
||||
@@ -201,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode)
|
||||
{
|
||||
return phy_mode == PHY_MODE_GMII ||
|
||||
phy_mode == PHY_MODE_RGMII ||
|
||||
phy_mode == PHY_MODE_SGMII ||
|
||||
phy_mode == PHY_MODE_TBI ||
|
||||
phy_mode == PHY_MODE_RTBI;
|
||||
}
|
||||
|
||||
static inline int emac_phy_gpcs(int phy_mode)
|
||||
{
|
||||
return phy_mode == PHY_MODE_TBI ||
|
||||
return phy_mode == PHY_MODE_SGMII ||
|
||||
phy_mode == PHY_MODE_TBI ||
|
||||
phy_mode == PHY_MODE_RTBI;
|
||||
}
|
||||
|
||||
@@ -351,10 +354,24 @@ static int emac_reset(struct emac_instance *dev)
|
||||
emac_tx_disable(dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_DCR_NATIVE
|
||||
/* Enable internal clock source */
|
||||
if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
|
||||
dcri_clrset(SDR0, SDR0_ETH_CFG,
|
||||
0, SDR0_ETH_CFG_ECS << dev->cell_index);
|
||||
#endif
|
||||
|
||||
out_be32(&p->mr0, EMAC_MR0_SRST);
|
||||
while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n)
|
||||
--n;
|
||||
|
||||
#ifdef CONFIG_PPC_DCR_NATIVE
|
||||
/* Enable external clock source */
|
||||
if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
|
||||
dcri_clrset(SDR0, SDR0_ETH_CFG,
|
||||
SDR0_ETH_CFG_ECS << dev->cell_index, 0);
|
||||
#endif
|
||||
|
||||
if (n) {
|
||||
dev->reset_failed = 0;
|
||||
return 0;
|
||||
@@ -547,8 +564,9 @@ static int emac_configure(struct emac_instance *dev)
|
||||
switch (dev->phy.speed) {
|
||||
case SPEED_1000:
|
||||
if (emac_phy_gpcs(dev->phy.mode)) {
|
||||
mr1 |= EMAC_MR1_MF_1000GPCS |
|
||||
EMAC_MR1_MF_IPPA(dev->phy.address);
|
||||
mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA(
|
||||
(dev->phy.gpcs_address != 0xffffffff) ?
|
||||
dev->phy.gpcs_address : dev->phy.address);
|
||||
|
||||
/* Put some arbitrary OUI, Manuf & Rev IDs so we can
|
||||
* identify this GPCS PHY later.
|
||||
@@ -660,8 +678,12 @@ static int emac_configure(struct emac_instance *dev)
|
||||
out_be32(&p->iser, r);
|
||||
|
||||
/* We need to take GPCS PHY out of isolate mode after EMAC reset */
|
||||
if (emac_phy_gpcs(dev->phy.mode))
|
||||
emac_mii_reset_phy(&dev->phy);
|
||||
if (emac_phy_gpcs(dev->phy.mode)) {
|
||||
if (dev->phy.gpcs_address != 0xffffffff)
|
||||
emac_mii_reset_gpcs(&dev->phy);
|
||||
else
|
||||
emac_mii_reset_phy(&dev->phy);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -866,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg)
|
||||
struct emac_instance *dev = netdev_priv(ndev);
|
||||
int res;
|
||||
|
||||
res = __emac_mdio_read(dev->mdio_instance ? dev->mdio_instance : dev,
|
||||
res = __emac_mdio_read((dev->mdio_instance &&
|
||||
dev->phy.gpcs_address != id) ?
|
||||
dev->mdio_instance : dev,
|
||||
(u8) id, (u8) reg);
|
||||
return res;
|
||||
}
|
||||
@@ -875,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
|
||||
{
|
||||
struct emac_instance *dev = netdev_priv(ndev);
|
||||
|
||||
__emac_mdio_write(dev->mdio_instance ? dev->mdio_instance : dev,
|
||||
__emac_mdio_write((dev->mdio_instance &&
|
||||
dev->phy.gpcs_address != id) ?
|
||||
dev->mdio_instance : dev,
|
||||
(u8) id, (u8) reg, (u16) val);
|
||||
}
|
||||
|
||||
@@ -2367,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
|
||||
* XXX I probably should move these settings to the dev tree
|
||||
*/
|
||||
dev->phy.address = -1;
|
||||
dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII;
|
||||
dev->phy.features = SUPPORTED_MII;
|
||||
if (emac_phy_supports_gige(dev->phy_mode))
|
||||
dev->phy.features |= SUPPORTED_1000baseT_Full;
|
||||
else
|
||||
dev->phy.features |= SUPPORTED_100baseT_Full;
|
||||
dev->phy.pause = 1;
|
||||
|
||||
return 0;
|
||||
@@ -2406,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
|
||||
* Note that the busy_phy_map is currently global
|
||||
* while it should probably be per-ASIC...
|
||||
*/
|
||||
dev->phy.address = dev->cell_index;
|
||||
dev->phy.gpcs_address = dev->gpcs_address;
|
||||
if (dev->phy.gpcs_address == 0xffffffff)
|
||||
dev->phy.address = dev->cell_index;
|
||||
}
|
||||
|
||||
emac_configure(dev);
|
||||
@@ -2516,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
||||
dev->phy_address = 0xffffffff;
|
||||
if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0))
|
||||
dev->phy_map = 0xffffffff;
|
||||
if (emac_read_uint_prop(np, "gpcs-address", &dev->gpcs_address, 0))
|
||||
dev->gpcs_address = 0xffffffff;
|
||||
if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1))
|
||||
return -ENXIO;
|
||||
if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0))
|
||||
@@ -2559,6 +2593,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
||||
/* Check EMAC version */
|
||||
if (of_device_is_compatible(np, "ibm,emac4sync")) {
|
||||
dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC);
|
||||
if (of_device_is_compatible(np, "ibm,emac-460ex") ||
|
||||
of_device_is_compatible(np, "ibm,emac-460gt"))
|
||||
dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX;
|
||||
} else if (of_device_is_compatible(np, "ibm,emac4")) {
|
||||
dev->features |= EMAC_FTR_EMAC4;
|
||||
if (of_device_is_compatible(np, "ibm,emac-440gx"))
|
||||
@@ -2567,6 +2604,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
||||
if (of_device_is_compatible(np, "ibm,emac-440ep") ||
|
||||
of_device_is_compatible(np, "ibm,emac-440gr"))
|
||||
dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
|
||||
if (of_device_is_compatible(np, "ibm,emac-405ez"))
|
||||
dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
|
||||
}
|
||||
|
||||
/* Fixup some feature bits based on the device tree */
|
||||
@@ -2824,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev,
|
||||
ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
|
||||
ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
|
||||
|
||||
if (dev->phy_mode == PHY_MODE_SGMII)
|
||||
printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
|
||||
|
||||
if (dev->phy.address >= 0)
|
||||
printk("%s: found %s PHY (0x%02x)\n", ndev->name,
|
||||
dev->phy.def->name, dev->phy.address);
|
||||
|
||||
@@ -190,6 +190,9 @@ struct emac_instance {
|
||||
struct delayed_work link_work;
|
||||
int link_polling;
|
||||
|
||||
/* GPCS PHY infos */
|
||||
u32 gpcs_address;
|
||||
|
||||
/* Shared MDIO if any */
|
||||
u32 mdio_ph;
|
||||
struct of_device *mdio_dev;
|
||||
@@ -317,6 +320,10 @@ struct emac_instance {
|
||||
* The 405EX and 460EX contain the EMAC4SYNC core
|
||||
*/
|
||||
#define EMAC_FTR_EMAC4SYNC 0x00000200
|
||||
/*
|
||||
* Set if we need phy clock workaround for 460ex or 460gt
|
||||
*/
|
||||
#define EMAC_FTR_460EX_PHY_CLK_FIX 0x00000400
|
||||
|
||||
|
||||
/* Right now, we don't quite handle the always/possible masks on the
|
||||
@@ -341,6 +348,10 @@ enum {
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_RGMII
|
||||
EMAC_FTR_HAS_RGMII |
|
||||
#endif
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
|
||||
EMAC_FTR_NO_FLOW_CONTROL_40x |
|
||||
#endif
|
||||
EMAC_FTR_460EX_PHY_CLK_FIX |
|
||||
EMAC_FTR_440EP_PHY_CLK_FIX,
|
||||
};
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "core.h"
|
||||
#include <asm/dcr-regs.h>
|
||||
|
||||
static int mal_count;
|
||||
|
||||
@@ -279,6 +280,10 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
|
||||
mal_schedule_poll(mal);
|
||||
set_mal_dcrn(mal, MAL_TXEOBISR, r);
|
||||
|
||||
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
|
||||
mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
|
||||
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -293,6 +298,10 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
|
||||
mal_schedule_poll(mal);
|
||||
set_mal_dcrn(mal, MAL_RXEOBISR, r);
|
||||
|
||||
if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
|
||||
mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
|
||||
(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -336,6 +345,25 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t mal_int(int irq, void *dev_instance)
|
||||
{
|
||||
struct mal_instance *mal = dev_instance;
|
||||
u32 esr = get_mal_dcrn(mal, MAL_ESR);
|
||||
|
||||
if (esr & MAL_ESR_EVB) {
|
||||
/* descriptor error */
|
||||
if (esr & MAL_ESR_DE) {
|
||||
if (esr & MAL_ESR_CIDT)
|
||||
return mal_rxde(irq, dev_instance);
|
||||
else
|
||||
return mal_txde(irq, dev_instance);
|
||||
} else { /* SERR */
|
||||
return mal_serr(irq, dev_instance);
|
||||
}
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
|
||||
{
|
||||
/* Spinlock-type semantics: only one caller disable poll at a time */
|
||||
@@ -493,6 +521,8 @@ static int __devinit mal_probe(struct of_device *ofdev,
|
||||
unsigned int dcr_base;
|
||||
const u32 *prop;
|
||||
u32 cfg;
|
||||
unsigned long irqflags;
|
||||
irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
|
||||
|
||||
mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
|
||||
if (!mal) {
|
||||
@@ -542,11 +572,21 @@ static int __devinit mal_probe(struct of_device *ofdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
|
||||
mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
|
||||
MAL_FTR_COMMON_ERR_INT);
|
||||
|
||||
mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
|
||||
mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
|
||||
mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2);
|
||||
mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
|
||||
mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
|
||||
|
||||
if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
|
||||
mal->txde_irq = mal->rxde_irq = mal->serr_irq;
|
||||
} else {
|
||||
mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
|
||||
mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
|
||||
}
|
||||
|
||||
if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ ||
|
||||
mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ ||
|
||||
mal->rxde_irq == NO_IRQ) {
|
||||
@@ -608,16 +648,26 @@ static int __devinit mal_probe(struct of_device *ofdev,
|
||||
sizeof(struct mal_descriptor) *
|
||||
mal_rx_bd_offset(mal, i));
|
||||
|
||||
err = request_irq(mal->serr_irq, mal_serr, 0, "MAL SERR", mal);
|
||||
if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
|
||||
irqflags = IRQF_SHARED;
|
||||
hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
|
||||
} else {
|
||||
irqflags = 0;
|
||||
hdlr_serr = mal_serr;
|
||||
hdlr_txde = mal_txde;
|
||||
hdlr_rxde = mal_rxde;
|
||||
}
|
||||
|
||||
err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
|
||||
if (err)
|
||||
goto fail2;
|
||||
err = request_irq(mal->txde_irq, mal_txde, 0, "MAL TX DE", mal);
|
||||
err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
|
||||
if (err)
|
||||
goto fail3;
|
||||
err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
|
||||
if (err)
|
||||
goto fail4;
|
||||
err = request_irq(mal->rxde_irq, mal_rxde, 0, "MAL RX DE", mal);
|
||||
err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
|
||||
if (err)
|
||||
goto fail5;
|
||||
err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
|
||||
|
||||
@@ -213,6 +213,8 @@ struct mal_instance {
|
||||
struct of_device *ofdev;
|
||||
int index;
|
||||
spinlock_t lock;
|
||||
|
||||
unsigned int features;
|
||||
};
|
||||
|
||||
static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
|
||||
@@ -225,6 +227,38 @@ static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
|
||||
dcr_write(mal->dcr_host, reg, val);
|
||||
}
|
||||
|
||||
/* Features of various MAL implementations */
|
||||
|
||||
/* Set if you have interrupt coalescing and you have to clear the SDR
|
||||
* register for TXEOB and RXEOB interrupts to work
|
||||
*/
|
||||
#define MAL_FTR_CLEAR_ICINTSTAT 0x00000001
|
||||
|
||||
/* Set if your MAL has SERR, TXDE, and RXDE OR'd into a single UIC
|
||||
* interrupt
|
||||
*/
|
||||
#define MAL_FTR_COMMON_ERR_INT 0x00000002
|
||||
|
||||
enum {
|
||||
MAL_FTRS_ALWAYS = 0,
|
||||
|
||||
MAL_FTRS_POSSIBLE =
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
|
||||
MAL_FTR_CLEAR_ICINTSTAT |
|
||||
#endif
|
||||
#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
|
||||
MAL_FTR_COMMON_ERR_INT |
|
||||
#endif
|
||||
0,
|
||||
};
|
||||
|
||||
static inline int mal_has_feature(struct mal_instance *dev,
|
||||
unsigned long feature)
|
||||
{
|
||||
return (MAL_FTRS_ALWAYS & feature) ||
|
||||
(MAL_FTRS_POSSIBLE & dev->features & feature);
|
||||
}
|
||||
|
||||
/* Register MAL devices */
|
||||
int mal_init(void);
|
||||
void mal_exit(void);
|
||||
|
||||
@@ -38,6 +38,16 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
|
||||
phy->mdio_write(phy->dev, phy->address, reg, val);
|
||||
}
|
||||
|
||||
static inline int gpcs_phy_read(struct mii_phy *phy, int reg)
|
||||
{
|
||||
return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
|
||||
}
|
||||
|
||||
static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
|
||||
{
|
||||
phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
|
||||
}
|
||||
|
||||
int emac_mii_reset_phy(struct mii_phy *phy)
|
||||
{
|
||||
int val;
|
||||
@@ -62,6 +72,37 @@ int emac_mii_reset_phy(struct mii_phy *phy)
|
||||
return limit <= 0;
|
||||
}
|
||||
|
||||
int emac_mii_reset_gpcs(struct mii_phy *phy)
|
||||
{
|
||||
int val;
|
||||
int limit = 10000;
|
||||
|
||||
val = gpcs_phy_read(phy, MII_BMCR);
|
||||
val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
|
||||
val |= BMCR_RESET;
|
||||
gpcs_phy_write(phy, MII_BMCR, val);
|
||||
|
||||
udelay(300);
|
||||
|
||||
while (limit--) {
|
||||
val = gpcs_phy_read(phy, MII_BMCR);
|
||||
if (val >= 0 && (val & BMCR_RESET) == 0)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
if ((val & BMCR_ISOLATE) && limit > 0)
|
||||
gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
|
||||
|
||||
if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
|
||||
/* Configure GPCS interface to recommended setting for SGMII */
|
||||
gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
|
||||
gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
|
||||
gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX */
|
||||
}
|
||||
|
||||
return limit <= 0;
|
||||
}
|
||||
|
||||
static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
|
||||
{
|
||||
int ctl, adv;
|
||||
@@ -332,6 +373,33 @@ static int m88e1111_init(struct mii_phy *phy)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int m88e1112_init(struct mii_phy *phy)
|
||||
{
|
||||
/*
|
||||
* Marvell 88E1112 PHY needs to have the SGMII MAC
|
||||
* interace (page 2) properly configured to
|
||||
* communicate with the 460EX/GT GPCS interface.
|
||||
*/
|
||||
|
||||
u16 reg_short;
|
||||
|
||||
pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
|
||||
|
||||
/* Set access to Page 2 */
|
||||
phy_write(phy, 0x16, 0x0002);
|
||||
|
||||
phy_write(phy, 0x00, 0x0040); /* 1Gbps */
|
||||
reg_short = (u16)(phy_read(phy, 0x1a));
|
||||
reg_short |= 0x8000; /* bypass Auto-Negotiation */
|
||||
phy_write(phy, 0x1a, reg_short);
|
||||
emac_mii_reset_phy(phy); /* reset MAC interface */
|
||||
|
||||
/* Reset access to Page 0 */
|
||||
phy_write(phy, 0x16, 0x0000);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int et1011c_init(struct mii_phy *phy)
|
||||
{
|
||||
u16 reg_short;
|
||||
@@ -384,11 +452,27 @@ static struct mii_phy_def m88e1111_phy_def = {
|
||||
.ops = &m88e1111_phy_ops,
|
||||
};
|
||||
|
||||
static struct mii_phy_ops m88e1112_phy_ops = {
|
||||
.init = m88e1112_init,
|
||||
.setup_aneg = genmii_setup_aneg,
|
||||
.setup_forced = genmii_setup_forced,
|
||||
.poll_link = genmii_poll_link,
|
||||
.read_link = genmii_read_link
|
||||
};
|
||||
|
||||
static struct mii_phy_def m88e1112_phy_def = {
|
||||
.phy_id = 0x01410C90,
|
||||
.phy_id_mask = 0x0ffffff0,
|
||||
.name = "Marvell 88E1112 Ethernet",
|
||||
.ops = &m88e1112_phy_ops,
|
||||
};
|
||||
|
||||
static struct mii_phy_def *mii_phy_table[] = {
|
||||
&et1011c_phy_def,
|
||||
&cis8201_phy_def,
|
||||
&bcm5248_phy_def,
|
||||
&m88e1111_phy_def,
|
||||
&m88e1112_phy_def,
|
||||
&genmii_phy_def,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -57,6 +57,7 @@ struct mii_phy {
|
||||
or determined automaticaly */
|
||||
int address; /* PHY address */
|
||||
int mode; /* PHY mode */
|
||||
int gpcs_address; /* GPCS PHY address */
|
||||
|
||||
/* 1: autoneg enabled, 0: disabled */
|
||||
int autoneg;
|
||||
@@ -81,5 +82,6 @@ struct mii_phy {
|
||||
*/
|
||||
int emac_mii_phy_probe(struct mii_phy *phy, int address);
|
||||
int emac_mii_reset_phy(struct mii_phy *phy);
|
||||
int emac_mii_reset_gpcs(struct mii_phy *phy);
|
||||
|
||||
#endif /* __IBM_NEWEMAC_PHY_H */
|
||||
|
||||
Reference in New Issue
Block a user