1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
--- a/drivers/net/ethernet/broadcom/bgmac.c
+++ b/drivers/net/ethernet/broadcom/bgmac.c
@@ -761,6 +761,26 @@ static void bgmac_cmdcfg_maskset(struct
udelay(2);
}
+static void bgmac_write_mac_address(struct bgmac *bgmac, u8 *addr)
+{
+ u32 tmp;
+
+ tmp = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
+ bgmac_write(bgmac, BGMAC_MACADDR_HIGH, tmp);
+ tmp = (addr[4] << 8) | addr[5];
+ bgmac_write(bgmac, BGMAC_MACADDR_LOW, tmp);
+}
+
+static void bgmac_set_rx_mode(struct net_device *net_dev)
+{
+ struct bgmac *bgmac = netdev_priv(net_dev);
+
+ if (net_dev->flags & IFF_PROMISC)
+ bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_PROM, true);
+ else
+ bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_PROM, 0, true);
+}
+
#if 0 /* We don't use that regs yet */
static void bgmac_chip_stats_update(struct bgmac *bgmac)
{
@@ -889,8 +909,10 @@ static void bgmac_chip_reset(struct bgma
sw_type = et_swtype;
} else if (ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg == 9) {
sw_type = BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII;
- } else if (0) {
- /* TODO */
+ } else if ((ci->id != BCMA_CHIP_ID_BCM53572 && ci->pkg == 10) ||
+ (ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg == 9)) {
+ sw_type = BGMAC_CHIPCTL_1_IF_TYPE_RGMII |
+ BGMAC_CHIPCTL_1_SW_TYPE_RGMII;
}
bcma_chipco_chipctl_maskset(cc, 1,
~(BGMAC_CHIPCTL_1_IF_TYPE_MASK |
@@ -948,6 +970,7 @@ static void bgmac_chip_intrs_on(struct b
static void bgmac_chip_intrs_off(struct bgmac *bgmac)
{
bgmac_write(bgmac, BGMAC_INT_MASK, 0);
+ bgmac_read(bgmac, BGMAC_INT_MASK);
}
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/gmac_enable */
@@ -1004,8 +1027,6 @@ static void bgmac_enable(struct bgmac *b
static void bgmac_chip_init(struct bgmac *bgmac, bool full_init)
{
struct bgmac_dma_ring *ring;
- u8 *mac = bgmac->net_dev->dev_addr;
- u32 tmp;
int i;
/* 1 interrupt per received frame */
@@ -1014,21 +1035,14 @@ static void bgmac_chip_init(struct bgmac
/* Enable 802.3x tx flow control (honor received PAUSE frames) */
bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_RPI, 0, true);
- if (bgmac->net_dev->flags & IFF_PROMISC)
- bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_PROM, false);
- else
- bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_PROM, 0, false);
+ bgmac_set_rx_mode(bgmac->net_dev);
- /* Set MAC addr */
- tmp = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
- bgmac_write(bgmac, BGMAC_MACADDR_HIGH, tmp);
- tmp = (mac[4] << 8) | mac[5];
- bgmac_write(bgmac, BGMAC_MACADDR_LOW, tmp);
+ bgmac_write_mac_address(bgmac, bgmac->net_dev->dev_addr);
if (bgmac->loopback)
- bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, true);
+ bgmac_cmdcfg_maskset(bgmac, ~0, BGMAC_CMDCFG_ML, false);
else
- bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_ML, 0, true);
+ bgmac_cmdcfg_maskset(bgmac, ~BGMAC_CMDCFG_ML, 0, false);
bgmac_write(bgmac, BGMAC_RXMAX_LENGTH, 32 + ETHER_MAX_LEN);
@@ -1160,6 +1174,19 @@ static netdev_tx_t bgmac_start_xmit(stru
return bgmac_dma_tx_add(bgmac, ring, skb);
}
+static int bgmac_set_mac_address(struct net_device *net_dev, void *addr)
+{
+ struct bgmac *bgmac = netdev_priv(net_dev);
+ int ret;
+
+ ret = eth_prepare_mac_addr_change(net_dev, addr);
+ if (ret < 0)
+ return ret;
+ bgmac_write_mac_address(bgmac, (u8 *)addr);
+ eth_commit_mac_addr_change(net_dev, addr);
+ return 0;
+}
+
static int bgmac_ioctl(struct net_device *net_dev, struct ifreq *ifr, int cmd)
{
struct bgmac *bgmac = netdev_priv(net_dev);
@@ -1190,7 +1217,9 @@ static const struct net_device_ops bgmac
.ndo_open = bgmac_open,
.ndo_stop = bgmac_stop,
.ndo_start_xmit = bgmac_start_xmit,
- .ndo_set_mac_address = eth_mac_addr, /* generic, sets dev_addr */
+ .ndo_set_rx_mode = bgmac_set_rx_mode,
+ .ndo_set_mac_address = bgmac_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = bgmac_ioctl,
};
@@ -1290,6 +1319,12 @@ static int bgmac_probe(struct bcma_devic
return -ENOTSUPP;
}
+ if (!is_valid_ether_addr(mac)) {
+ dev_err(&core->dev, "Invalid MAC addr: %pM\n", mac);
+ eth_random_addr(mac);
+ dev_warn(&core->dev, "Using random MAC: %pM\n", mac);
+ }
+
/* Allocation and references */
net_dev = alloc_etherdev(sizeof(*bgmac));
if (!net_dev)
--- a/drivers/net/ethernet/broadcom/bgmac.h
+++ b/drivers/net/ethernet/broadcom/bgmac.h
@@ -339,7 +339,7 @@
#define BGMAC_CHIPCTL_1_SW_TYPE_EPHY 0x00000000
#define BGMAC_CHIPCTL_1_SW_TYPE_EPHYMII 0x00000040
#define BGMAC_CHIPCTL_1_SW_TYPE_EPHYRMII 0x00000080
-#define BGMAC_CHIPCTL_1_SW_TYPE_RGMI 0x000000C0
+#define BGMAC_CHIPCTL_1_SW_TYPE_RGMII 0x000000C0
#define BGMAC_CHIPCTL_1_RXC_DLL_BYPASS 0x00010000
#define BGMAC_SPEED_10 0x0001
|