Skip to content

Commit cdea83c

Browse files
Raju Lakkarajudavem330
authored andcommitted
net: lan743x: Add support for EEPROM
Add new the EEPROM read and write access functions and system lock protection to access by devices for PCI11010/PCI11414 chips Signed-off-by: Raju Lakkaraju <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bc1962e commit cdea83c

File tree

3 files changed

+212
-5
lines changed

3 files changed

+212
-5
lines changed

drivers/net/ethernet/microchip/lan743x_ethtool.c

Lines changed: 173 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <linux/phy.h>
88
#include "lan743x_main.h"
99
#include "lan743x_ethtool.h"
10+
#include <linux/sched.h>
11+
#include <linux/iopoll.h>
1012

1113
/* eeprom */
1214
#define LAN743X_EEPROM_MAGIC (0x74A5)
@@ -19,6 +21,10 @@
1921
#define OTP_INDICATOR_1 (0xF3)
2022
#define OTP_INDICATOR_2 (0xF7)
2123

24+
#define LOCK_TIMEOUT_MAX_CNT (100) // 1 sec (10 msce * 100)
25+
26+
#define LAN743X_CSR_READ_OP(offset) lan743x_csr_read(adapter, offset)
27+
2228
static int lan743x_otp_power_up(struct lan743x_adapter *adapter)
2329
{
2430
u32 reg_value;
@@ -149,6 +155,63 @@ static int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset,
149155
return 0;
150156
}
151157

158+
static int lan743x_hs_syslock_acquire(struct lan743x_adapter *adapter,
159+
u16 timeout)
160+
{
161+
u16 timeout_cnt = 0;
162+
u32 val;
163+
164+
do {
165+
spin_lock(&adapter->eth_syslock_spinlock);
166+
if (adapter->eth_syslock_acquire_cnt == 0) {
167+
lan743x_csr_write(adapter, ETH_SYSTEM_SYS_LOCK_REG,
168+
SYS_LOCK_REG_ENET_SS_LOCK_);
169+
val = lan743x_csr_read(adapter,
170+
ETH_SYSTEM_SYS_LOCK_REG);
171+
if (val & SYS_LOCK_REG_ENET_SS_LOCK_) {
172+
adapter->eth_syslock_acquire_cnt++;
173+
WARN_ON(adapter->eth_syslock_acquire_cnt == 0);
174+
spin_unlock(&adapter->eth_syslock_spinlock);
175+
break;
176+
}
177+
} else {
178+
adapter->eth_syslock_acquire_cnt++;
179+
WARN_ON(adapter->eth_syslock_acquire_cnt == 0);
180+
spin_unlock(&adapter->eth_syslock_spinlock);
181+
break;
182+
}
183+
184+
spin_unlock(&adapter->eth_syslock_spinlock);
185+
186+
if (timeout_cnt++ < timeout)
187+
usleep_range(10000, 11000);
188+
else
189+
return -ETIMEDOUT;
190+
} while (true);
191+
192+
return 0;
193+
}
194+
195+
static void lan743x_hs_syslock_release(struct lan743x_adapter *adapter)
196+
{
197+
u32 val;
198+
199+
spin_lock(&adapter->eth_syslock_spinlock);
200+
WARN_ON(adapter->eth_syslock_acquire_cnt == 0);
201+
202+
if (adapter->eth_syslock_acquire_cnt) {
203+
adapter->eth_syslock_acquire_cnt--;
204+
if (adapter->eth_syslock_acquire_cnt == 0) {
205+
lan743x_csr_write(adapter, ETH_SYSTEM_SYS_LOCK_REG, 0);
206+
val = lan743x_csr_read(adapter,
207+
ETH_SYSTEM_SYS_LOCK_REG);
208+
WARN_ON((val & SYS_LOCK_REG_ENET_SS_LOCK_) != 0);
209+
}
210+
}
211+
212+
spin_unlock(&adapter->eth_syslock_spinlock);
213+
}
214+
152215
static int lan743x_eeprom_wait(struct lan743x_adapter *adapter)
153216
{
154217
unsigned long start_time = jiffies;
@@ -263,6 +326,100 @@ static int lan743x_eeprom_write(struct lan743x_adapter *adapter,
263326
return 0;
264327
}
265328

329+
static int lan743x_hs_eeprom_cmd_cmplt_chk(struct lan743x_adapter *adapter)
330+
{
331+
u32 val;
332+
333+
return readx_poll_timeout(LAN743X_CSR_READ_OP, HS_E2P_CMD, val,
334+
(!(val & HS_E2P_CMD_EPC_BUSY_) ||
335+
(val & HS_E2P_CMD_EPC_TIMEOUT_)),
336+
50, 10000);
337+
}
338+
339+
static int lan743x_hs_eeprom_read(struct lan743x_adapter *adapter,
340+
u32 offset, u32 length, u8 *data)
341+
{
342+
int retval;
343+
u32 val;
344+
int i;
345+
346+
retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
347+
if (retval < 0)
348+
return retval;
349+
350+
retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
351+
lan743x_hs_syslock_release(adapter);
352+
if (retval < 0)
353+
return retval;
354+
355+
for (i = 0; i < length; i++) {
356+
retval = lan743x_hs_syslock_acquire(adapter,
357+
LOCK_TIMEOUT_MAX_CNT);
358+
if (retval < 0)
359+
return retval;
360+
361+
val = HS_E2P_CMD_EPC_BUSY_ | HS_E2P_CMD_EPC_CMD_READ_;
362+
val |= (offset & HS_E2P_CMD_EPC_ADDR_MASK_);
363+
lan743x_csr_write(adapter, HS_E2P_CMD, val);
364+
retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
365+
if (retval < 0) {
366+
lan743x_hs_syslock_release(adapter);
367+
return retval;
368+
}
369+
370+
val = lan743x_csr_read(adapter, HS_E2P_DATA);
371+
372+
lan743x_hs_syslock_release(adapter);
373+
374+
data[i] = val & 0xFF;
375+
offset++;
376+
}
377+
378+
return 0;
379+
}
380+
381+
static int lan743x_hs_eeprom_write(struct lan743x_adapter *adapter,
382+
u32 offset, u32 length, u8 *data)
383+
{
384+
int retval;
385+
u32 val;
386+
int i;
387+
388+
retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
389+
if (retval < 0)
390+
return retval;
391+
392+
retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
393+
lan743x_hs_syslock_release(adapter);
394+
if (retval < 0)
395+
return retval;
396+
397+
for (i = 0; i < length; i++) {
398+
retval = lan743x_hs_syslock_acquire(adapter,
399+
LOCK_TIMEOUT_MAX_CNT);
400+
if (retval < 0)
401+
return retval;
402+
403+
/* Fill data register */
404+
val = data[i];
405+
lan743x_csr_write(adapter, HS_E2P_DATA, val);
406+
407+
/* Send "write" command */
408+
val = HS_E2P_CMD_EPC_BUSY_ | HS_E2P_CMD_EPC_CMD_WRITE_;
409+
val |= (offset & HS_E2P_CMD_EPC_ADDR_MASK_);
410+
lan743x_csr_write(adapter, HS_E2P_CMD, val);
411+
412+
retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
413+
lan743x_hs_syslock_release(adapter);
414+
if (retval < 0)
415+
return retval;
416+
417+
offset++;
418+
}
419+
420+
return 0;
421+
}
422+
266423
static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
267424
struct ethtool_drvinfo *info)
268425
{
@@ -304,10 +461,16 @@ static int lan743x_ethtool_get_eeprom(struct net_device *netdev,
304461
struct lan743x_adapter *adapter = netdev_priv(netdev);
305462
int ret = 0;
306463

307-
if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP)
464+
if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) {
308465
ret = lan743x_otp_read(adapter, ee->offset, ee->len, data);
309-
else
310-
ret = lan743x_eeprom_read(adapter, ee->offset, ee->len, data);
466+
} else {
467+
if (adapter->is_pci11x1x)
468+
ret = lan743x_hs_eeprom_read(adapter, ee->offset,
469+
ee->len, data);
470+
else
471+
ret = lan743x_eeprom_read(adapter, ee->offset,
472+
ee->len, data);
473+
}
311474

312475
return ret;
313476
}
@@ -326,8 +489,13 @@ static int lan743x_ethtool_set_eeprom(struct net_device *netdev,
326489
}
327490
} else {
328491
if (ee->magic == LAN743X_EEPROM_MAGIC) {
329-
ret = lan743x_eeprom_write(adapter, ee->offset,
330-
ee->len, data);
492+
if (adapter->is_pci11x1x)
493+
ret = lan743x_hs_eeprom_write(adapter,
494+
ee->offset,
495+
ee->len, data);
496+
else
497+
ret = lan743x_eeprom_write(adapter, ee->offset,
498+
ee->len, data);
331499
}
332500
}
333501

drivers/net/ethernet/microchip/lan743x_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2869,6 +2869,7 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
28692869
adapter->used_tx_channels = PCI11X1X_USED_TX_CHANNELS;
28702870
adapter->max_vector_count = PCI11X1X_MAX_VECTOR_COUNT;
28712871
pci11x1x_strap_get_status(adapter);
2872+
spin_lock_init(&adapter->eth_syslock_spinlock);
28722873
} else {
28732874
adapter->max_tx_channels = LAN743X_MAX_TX_CHANNELS;
28742875
adapter->used_tx_channels = LAN743X_USED_TX_CHANNELS;

drivers/net/ethernet/microchip/lan743x_main.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,40 @@
8686

8787
#define E2P_DATA (0x044)
8888

89+
/* Hearthstone top level & System Reg Addresses */
90+
#define ETH_CTRL_REG_ADDR_BASE (0x0000)
91+
#define ETH_SYS_REG_ADDR_BASE (0x4000)
92+
#define CONFIG_REG_ADDR_BASE (0x0000)
93+
#define ETH_EEPROM_REG_ADDR_BASE (0x0E00)
94+
#define ETH_OTP_REG_ADDR_BASE (0x1000)
95+
#define SYS_LOCK_REG (0x00A0)
96+
#define SYS_LOCK_REG_MAIN_LOCK_ BIT(7)
97+
#define SYS_LOCK_REG_GEN_PERI_LOCK_ BIT(5)
98+
#define SYS_LOCK_REG_SPI_PERI_LOCK_ BIT(4)
99+
#define SYS_LOCK_REG_SMBUS_PERI_LOCK_ BIT(3)
100+
#define SYS_LOCK_REG_UART_SS_LOCK_ BIT(2)
101+
#define SYS_LOCK_REG_ENET_SS_LOCK_ BIT(1)
102+
#define SYS_LOCK_REG_USB_SS_LOCK_ BIT(0)
103+
#define ETH_SYSTEM_SYS_LOCK_REG (ETH_SYS_REG_ADDR_BASE + \
104+
CONFIG_REG_ADDR_BASE + \
105+
SYS_LOCK_REG)
106+
#define HS_EEPROM_REG_ADDR_BASE (ETH_SYS_REG_ADDR_BASE + \
107+
ETH_EEPROM_REG_ADDR_BASE)
108+
#define HS_E2P_CMD (HS_EEPROM_REG_ADDR_BASE + 0x0000)
109+
#define HS_E2P_CMD_EPC_BUSY_ BIT(31)
110+
#define HS_E2P_CMD_EPC_CMD_WRITE_ GENMASK(29, 28)
111+
#define HS_E2P_CMD_EPC_CMD_READ_ (0x0)
112+
#define HS_E2P_CMD_EPC_TIMEOUT_ BIT(17)
113+
#define HS_E2P_CMD_EPC_ADDR_MASK_ GENMASK(15, 0)
114+
#define HS_E2P_DATA (HS_EEPROM_REG_ADDR_BASE + 0x0004)
115+
#define HS_E2P_DATA_MASK_ GENMASK(7, 0)
116+
#define HS_E2P_CFG (HS_EEPROM_REG_ADDR_BASE + 0x0008)
117+
#define HS_E2P_CFG_I2C_PULSE_MASK_ GENMASK(19, 16)
118+
#define HS_E2P_CFG_EEPROM_SIZE_SEL_ BIT(12)
119+
#define HS_E2P_CFG_I2C_BAUD_RATE_MASK_ GENMASK(9, 8)
120+
#define HS_E2P_CFG_TEST_EEPR_TO_BYP_ BIT(0)
121+
#define HS_E2P_PAD_CTL (HS_EEPROM_REG_ADDR_BASE + 0x000C)
122+
89123
#define GPIO_CFG0 (0x050)
90124
#define GPIO_CFG0_GPIO_DIR_BIT_(bit) BIT(16 + (bit))
91125
#define GPIO_CFG0_GPIO_DATA_BIT_(bit) BIT(0 + (bit))
@@ -773,6 +807,10 @@ struct lan743x_adapter {
773807
struct lan743x_rx rx[LAN743X_USED_RX_CHANNELS];
774808
bool is_pci11x1x;
775809
bool is_sgmii_en;
810+
/* protect ethernet syslock */
811+
spinlock_t eth_syslock_spinlock;
812+
bool eth_syslock_en;
813+
u32 eth_syslock_acquire_cnt;
776814
u8 max_tx_channels;
777815
u8 used_tx_channels;
778816
u8 max_vector_count;

0 commit comments

Comments
 (0)