diff options
Diffstat (limited to 'drivers/net/ethernet/smsc')
-rw-r--r-- | drivers/net/ethernet/smsc/epic100.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smc911x.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smc9194.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smc91c92_cs.c | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smc91x.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smc91x.h | 80 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smsc911x.c | 23 | ||||
-rw-r--r-- | drivers/net/ethernet/smsc/smsc9420.c | 10 |
8 files changed, 64 insertions, 59 deletions
diff --git a/drivers/net/ethernet/smsc/epic100.c b/drivers/net/ethernet/smsc/epic100.c index 7186b89269ad..fe9760ffab51 100644 --- a/drivers/net/ethernet/smsc/epic100.c +++ b/drivers/net/ethernet/smsc/epic100.c @@ -313,7 +313,6 @@ static const struct net_device_ops epic_netdev_ops = { .ndo_get_stats = epic_get_stats, .ndo_set_rx_mode = set_rx_mode, .ndo_do_ioctl = netdev_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index cb49c9654f0a..4f19c6166182 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -1753,7 +1753,6 @@ static const struct net_device_ops smc911x_netdev_ops = { .ndo_start_xmit = smc911x_hard_start_xmit, .ndo_tx_timeout = smc911x_timeout, .ndo_set_rx_mode = smc911x_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER diff --git a/drivers/net/ethernet/smsc/smc9194.c b/drivers/net/ethernet/smsc/smc9194.c index d496888b85d3..c8d84679ede7 100644 --- a/drivers/net/ethernet/smsc/smc9194.c +++ b/drivers/net/ethernet/smsc/smc9194.c @@ -809,7 +809,6 @@ static const struct net_device_ops smc_netdev_ops = { .ndo_start_xmit = smc_wait_to_send_packet, .ndo_tx_timeout = smc_timeout, .ndo_set_rx_mode = smc_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/smsc/smc91c92_cs.c b/drivers/net/ethernet/smsc/smc91c92_cs.c index db3c696d7002..f1c75e291e55 100644 --- a/drivers/net/ethernet/smsc/smc91c92_cs.c +++ b/drivers/net/ethernet/smsc/smc91c92_cs.c @@ -294,7 +294,6 @@ static const struct net_device_ops smc_netdev_ops = { .ndo_set_config = s9k_config, .ndo_set_rx_mode = set_rx_mode, .ndo_do_ioctl = smc_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, }; diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 73212590d04a..65077c77082a 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -602,7 +602,8 @@ static void smc_hardware_send_pkt(unsigned long data) SMC_PUSH_DATA(lp, buf, len & ~1); /* Send final ctl word with the last byte if there is one */ - SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp)); + SMC_outw(lp, ((len & 1) ? (0x2000 | buf[len - 1]) : 0), ioaddr, + DATA_REG(lp)); /* * If THROTTLE_TX_PKTS is set, we stop the queue here. This will @@ -1762,7 +1763,6 @@ static const struct net_device_ops smc_netdev_ops = { .ndo_start_xmit = smc_hard_start_xmit, .ndo_tx_timeout = smc_timeout, .ndo_set_rx_mode = smc_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = eth_mac_addr, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2326,6 +2326,8 @@ static int smc_drv_probe(struct platform_device *pdev) if (!device_property_read_u32(&pdev->dev, "reg-shift", &val)) lp->io_shift = val; + lp->cfg.pxa_u16_align4 = + device_property_read_bool(&pdev->dev, "pxa-u16-align4"); } #endif diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index ea8465467469..08b17adf0a65 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -86,11 +86,11 @@ #define SMC_inl(a, r) readl((a) + (r)) #define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) \ +#define SMC_outw(lp, v, a, r) \ do { \ unsigned int __v = v, __smc_r = r; \ if (SMC_16BIT(lp)) \ - __SMC_outw(__v, a, __smc_r); \ + __SMC_outw(lp, __v, a, __smc_r); \ else if (SMC_8BIT(lp)) \ SMC_outw_b(__v, a, __smc_r); \ else \ @@ -107,10 +107,10 @@ #define SMC_IRQ_FLAGS (-1) /* from resource */ /* We actually can't write halfwords properly if not word aligned */ -static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) +static inline void _SMC_outw_align4(u16 val, void __iomem *ioaddr, int reg, + bool use_align4_workaround) { - if ((machine_is_mainstone() || machine_is_stargate2() || - machine_is_pxa_idp()) && reg & 2) { + if (use_align4_workaround) { unsigned int v = val << 16; v |= readl(ioaddr + (reg & ~2)) & 0xffff; writel(v, ioaddr + (reg & ~2)); @@ -119,6 +119,12 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) } } +#define __SMC_outw(lp, v, a, r) \ + _SMC_outw_align4((v), (a), (r), \ + IS_BUILTIN(CONFIG_ARCH_PXA) && ((r) & 2) && \ + (lp)->cfg.pxa_u16_align4) + + #elif defined(CONFIG_SH_SH4202_MICRODEV) #define SMC_CAN_USE_8BIT 0 @@ -129,7 +135,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_inw(a, r) inw((a) + (r) - 0xa0000000) #define SMC_inl(a, r) inl((a) + (r) - 0xa0000000) #define SMC_outb(v, a, r) outb(v, (a) + (r) - 0xa0000000) -#define SMC_outw(v, a, r) outw(v, (a) + (r) - 0xa0000000) +#define SMC_outw(lp, v, a, r) outw(v, (a) + (r) - 0xa0000000) #define SMC_outl(v, a, r) outl(v, (a) + (r) - 0xa0000000) #define SMC_insl(a, r, p, l) insl((a) + (r) - 0xa0000000, p, l) #define SMC_outsl(a, r, p, l) outsl((a) + (r) - 0xa0000000, p, l) @@ -147,7 +153,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_inb(a, r) inb(((u32)a) + (r)) #define SMC_inw(a, r) inw(((u32)a) + (r)) #define SMC_outb(v, a, r) outb(v, ((u32)a) + (r)) -#define SMC_outw(v, a, r) outw(v, ((u32)a) + (r)) +#define SMC_outw(lp, v, a, r) outw(v, ((u32)a) + (r)) #define SMC_insw(a, r, p, l) insw(((u32)a) + (r), p, l) #define SMC_outsw(a, r, p, l) outsw(((u32)a) + (r), p, l) @@ -175,7 +181,7 @@ static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) #define SMC_inw(a, r) readw((a) + (r)) #define SMC_inl(a, r) readl((a) + (r)) #define SMC_outb(v, a, r) writeb(v, (a) + (r)) -#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outw(lp, v, a, r) writew(v, (a) + (r)) #define SMC_outl(v, a, r) writel(v, (a) + (r)) #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) @@ -207,7 +213,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) } #define SMC_inw(a, r) _swapw(readw((a) + (r))) -#define SMC_outw(v, a, r) writew(_swapw(v), (a) + (r)) +#define SMC_outw(lp, v, a, r) writew(_swapw(v), (a) + (r)) #define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l) #define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l) @@ -241,7 +247,7 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) #define SMC_inw(a, r) ioread16((a) + (r)) #define SMC_inl(a, r) ioread32((a) + (r)) #define SMC_outb(v, a, r) iowrite8(v, (a) + (r)) -#define SMC_outw(v, a, r) iowrite16(v, (a) + (r)) +#define SMC_outw(lp, v, a, r) iowrite16(v, (a) + (r)) #define SMC_outl(v, a, r) iowrite32(v, (a) + (r)) #define SMC_insw(a, r, p, l) ioread16_rep((a) + (r), p, l) #define SMC_outsw(a, r, p, l) iowrite16_rep((a) + (r), p, l) @@ -303,6 +309,8 @@ struct smc_local { /* the low address lines on some platforms aren't connected... */ int io_shift; + /* on some platforms a u16 write must be 4-bytes aligned */ + bool half_word_align4; struct smc91x_platdata cfg; }; @@ -457,7 +465,7 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, #if ! SMC_CAN_USE_16BIT -#define SMC_outw(x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg) +#define SMC_outw(lp, x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg) #define SMC_inw(ioaddr, reg) SMC_inw_b(ioaddr, reg) #define SMC_insw(a, r, p, l) BUG() #define SMC_outsw(a, r, p, l) BUG() @@ -909,7 +917,7 @@ static const char * chip_ids[ 16 ] = { else if (SMC_8BIT(lp)) \ SMC_outb(x, ioaddr, PN_REG(lp)); \ else \ - SMC_outw(x, ioaddr, PN_REG(lp)); \ + SMC_outw(lp, x, ioaddr, PN_REG(lp)); \ } while (0) #define SMC_GET_AR(lp) \ @@ -937,7 +945,7 @@ static const char * chip_ids[ 16 ] = { int __mask; \ local_irq_save(__flags); \ __mask = SMC_inw(ioaddr, INT_REG(lp)) & ~0xff; \ - SMC_outw(__mask | (x), ioaddr, INT_REG(lp)); \ + SMC_outw(lp, __mask | (x), ioaddr, INT_REG(lp)); \ local_irq_restore(__flags); \ } \ } while (0) @@ -951,7 +959,7 @@ static const char * chip_ids[ 16 ] = { if (SMC_8BIT(lp)) \ SMC_outb(x, ioaddr, IM_REG(lp)); \ else \ - SMC_outw((x) << 8, ioaddr, INT_REG(lp)); \ + SMC_outw(lp, (x) << 8, ioaddr, INT_REG(lp)); \ } while (0) #define SMC_CURRENT_BANK(lp) SMC_inw(ioaddr, BANK_SELECT) @@ -961,22 +969,22 @@ static const char * chip_ids[ 16 ] = { if (SMC_MUST_ALIGN_WRITE(lp)) \ SMC_outl((x)<<16, ioaddr, 12<<SMC_IO_SHIFT); \ else \ - SMC_outw(x, ioaddr, BANK_SELECT); \ + SMC_outw(lp, x, ioaddr, BANK_SELECT); \ } while (0) #define SMC_GET_BASE(lp) SMC_inw(ioaddr, BASE_REG(lp)) -#define SMC_SET_BASE(lp, x) SMC_outw(x, ioaddr, BASE_REG(lp)) +#define SMC_SET_BASE(lp, x) SMC_outw(lp, x, ioaddr, BASE_REG(lp)) #define SMC_GET_CONFIG(lp) SMC_inw(ioaddr, CONFIG_REG(lp)) -#define SMC_SET_CONFIG(lp, x) SMC_outw(x, ioaddr, CONFIG_REG(lp)) +#define SMC_SET_CONFIG(lp, x) SMC_outw(lp, x, ioaddr, CONFIG_REG(lp)) #define SMC_GET_COUNTER(lp) SMC_inw(ioaddr, COUNTER_REG(lp)) #define SMC_GET_CTL(lp) SMC_inw(ioaddr, CTL_REG(lp)) -#define SMC_SET_CTL(lp, x) SMC_outw(x, ioaddr, CTL_REG(lp)) +#define SMC_SET_CTL(lp, x) SMC_outw(lp, x, ioaddr, CTL_REG(lp)) #define SMC_GET_MII(lp) SMC_inw(ioaddr, MII_REG(lp)) @@ -987,20 +995,20 @@ static const char * chip_ids[ 16 ] = { if (SMC_MUST_ALIGN_WRITE(lp)) \ SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 1)); \ else \ - SMC_outw(x, ioaddr, GP_REG(lp)); \ + SMC_outw(lp, x, ioaddr, GP_REG(lp)); \ } while (0) -#define SMC_SET_MII(lp, x) SMC_outw(x, ioaddr, MII_REG(lp)) +#define SMC_SET_MII(lp, x) SMC_outw(lp, x, ioaddr, MII_REG(lp)) #define SMC_GET_MIR(lp) SMC_inw(ioaddr, MIR_REG(lp)) -#define SMC_SET_MIR(lp, x) SMC_outw(x, ioaddr, MIR_REG(lp)) +#define SMC_SET_MIR(lp, x) SMC_outw(lp, x, ioaddr, MIR_REG(lp)) #define SMC_GET_MMU_CMD(lp) SMC_inw(ioaddr, MMU_CMD_REG(lp)) -#define SMC_SET_MMU_CMD(lp, x) SMC_outw(x, ioaddr, MMU_CMD_REG(lp)) +#define SMC_SET_MMU_CMD(lp, x) SMC_outw(lp, x, ioaddr, MMU_CMD_REG(lp)) -#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp)) +#define SMC_GET_FIFO(lp) SMC_inw(ioaddr, FIFO_REG(lp)) #define SMC_GET_PTR(lp) SMC_inw(ioaddr, PTR_REG(lp)) @@ -1009,14 +1017,14 @@ static const char * chip_ids[ 16 ] = { if (SMC_MUST_ALIGN_WRITE(lp)) \ SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 4, 2)); \ else \ - SMC_outw(x, ioaddr, PTR_REG(lp)); \ + SMC_outw(lp, x, ioaddr, PTR_REG(lp)); \ } while (0) #define SMC_GET_EPH_STATUS(lp) SMC_inw(ioaddr, EPH_STATUS_REG(lp)) #define SMC_GET_RCR(lp) SMC_inw(ioaddr, RCR_REG(lp)) -#define SMC_SET_RCR(lp, x) SMC_outw(x, ioaddr, RCR_REG(lp)) +#define SMC_SET_RCR(lp, x) SMC_outw(lp, x, ioaddr, RCR_REG(lp)) #define SMC_GET_REV(lp) SMC_inw(ioaddr, REV_REG(lp)) @@ -1027,12 +1035,12 @@ static const char * chip_ids[ 16 ] = { if (SMC_MUST_ALIGN_WRITE(lp)) \ SMC_outl((x)<<16, ioaddr, SMC_REG(lp, 8, 0)); \ else \ - SMC_outw(x, ioaddr, RPC_REG(lp)); \ + SMC_outw(lp, x, ioaddr, RPC_REG(lp)); \ } while (0) #define SMC_GET_TCR(lp) SMC_inw(ioaddr, TCR_REG(lp)) -#define SMC_SET_TCR(lp, x) SMC_outw(x, ioaddr, TCR_REG(lp)) +#define SMC_SET_TCR(lp, x) SMC_outw(lp, x, ioaddr, TCR_REG(lp)) #ifndef SMC_GET_MAC_ADDR #define SMC_GET_MAC_ADDR(lp, addr) \ @@ -1049,18 +1057,18 @@ static const char * chip_ids[ 16 ] = { #define SMC_SET_MAC_ADDR(lp, addr) \ do { \ - SMC_outw(addr[0]|(addr[1] << 8), ioaddr, ADDR0_REG(lp)); \ - SMC_outw(addr[2]|(addr[3] << 8), ioaddr, ADDR1_REG(lp)); \ - SMC_outw(addr[4]|(addr[5] << 8), ioaddr, ADDR2_REG(lp)); \ + SMC_outw(lp, addr[0] | (addr[1] << 8), ioaddr, ADDR0_REG(lp)); \ + SMC_outw(lp, addr[2] | (addr[3] << 8), ioaddr, ADDR1_REG(lp)); \ + SMC_outw(lp, addr[4] | (addr[5] << 8), ioaddr, ADDR2_REG(lp)); \ } while (0) #define SMC_SET_MCAST(lp, x) \ do { \ const unsigned char *mt = (x); \ - SMC_outw(mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \ - SMC_outw(mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \ - SMC_outw(mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \ - SMC_outw(mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \ + SMC_outw(lp, mt[0] | (mt[1] << 8), ioaddr, MCAST_REG1(lp)); \ + SMC_outw(lp, mt[2] | (mt[3] << 8), ioaddr, MCAST_REG2(lp)); \ + SMC_outw(lp, mt[4] | (mt[5] << 8), ioaddr, MCAST_REG3(lp)); \ + SMC_outw(lp, mt[6] | (mt[7] << 8), ioaddr, MCAST_REG4(lp)); \ } while (0) #define SMC_PUT_PKT_HDR(lp, status, length) \ @@ -1069,8 +1077,8 @@ static const char * chip_ids[ 16 ] = { SMC_outl((status) | (length)<<16, ioaddr, \ DATA_REG(lp)); \ else { \ - SMC_outw(status, ioaddr, DATA_REG(lp)); \ - SMC_outw(length, ioaddr, DATA_REG(lp)); \ + SMC_outw(lp, status, ioaddr, DATA_REG(lp)); \ + SMC_outw(lp, length, ioaddr, DATA_REG(lp)); \ } \ } while (0) diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index e9b8579e6241..fa5ca0992be6 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -438,9 +438,16 @@ static int smsc911x_request_resources(struct platform_device *pdev) ret = regulator_bulk_get(&pdev->dev, ARRAY_SIZE(pdata->supplies), pdata->supplies); - if (ret) + if (ret) { + /* + * Retry on deferrals, else just report the error + * and try to continue. + */ + if (ret == -EPROBE_DEFER) + return ret; netdev_err(ndev, "couldn't get regulators %d\n", ret); + } /* Request optional RESET GPIO */ pdata->reset_gpiod = devm_gpiod_get_optional(&pdev->dev, @@ -1956,11 +1963,6 @@ static void smsc911x_ethtool_getdrvinfo(struct net_device *dev, sizeof(info->bus_info)); } -static int smsc911x_ethtool_nwayreset(struct net_device *dev) -{ - return phy_start_aneg(dev->phydev); -} - static u32 smsc911x_ethtool_getmsglevel(struct net_device *dev) { struct smsc911x_data *pdata = netdev_priv(dev); @@ -2132,7 +2134,7 @@ static int smsc911x_ethtool_set_eeprom(struct net_device *dev, static const struct ethtool_ops smsc911x_ethtool_ops = { .get_link = ethtool_op_get_link, .get_drvinfo = smsc911x_ethtool_getdrvinfo, - .nway_reset = smsc911x_ethtool_nwayreset, + .nway_reset = phy_ethtool_nway_reset, .get_msglevel = smsc911x_ethtool_getmsglevel, .set_msglevel = smsc911x_ethtool_setmsglevel, .get_regs_len = smsc911x_ethtool_getregslen, @@ -2152,7 +2154,6 @@ static const struct net_device_ops smsc911x_netdev_ops = { .ndo_get_stats = smsc911x_get_stats, .ndo_set_rx_mode = smsc911x_set_multicast_list, .ndo_do_ioctl = smsc911x_do_ioctl, - .ndo_change_mtu = eth_change_mtu, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = smsc911x_set_mac_address, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2584,6 +2585,9 @@ static int smsc911x_suspend(struct device *dev) PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ | PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_); + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + return 0; } @@ -2593,6 +2597,9 @@ static int smsc911x_resume(struct device *dev) struct smsc911x_data *pdata = netdev_priv(ndev); unsigned int to = 100; + pm_runtime_enable(dev); + pm_runtime_resume(dev); + /* Note 3.11 from the datasheet: * "When the LAN9220 is in a power saving state, a write of any * data to the BYTE_TEST register will wake-up the device." diff --git a/drivers/net/ethernet/smsc/smsc9420.c b/drivers/net/ethernet/smsc/smsc9420.c index b7bfed4bc96b..3174aebb322f 100644 --- a/drivers/net/ethernet/smsc/smsc9420.c +++ b/drivers/net/ethernet/smsc/smsc9420.c @@ -254,14 +254,6 @@ static void smsc9420_ethtool_set_msglevel(struct net_device *netdev, u32 data) pd->msg_enable = data; } -static int smsc9420_ethtool_nway_reset(struct net_device *netdev) -{ - if (!netdev->phydev) - return -ENODEV; - - return phy_start_aneg(netdev->phydev); -} - static int smsc9420_ethtool_getregslen(struct net_device *dev) { /* all smsc9420 registers plus all phy registers */ @@ -417,7 +409,7 @@ static const struct ethtool_ops smsc9420_ethtool_ops = { .get_drvinfo = smsc9420_ethtool_get_drvinfo, .get_msglevel = smsc9420_ethtool_get_msglevel, .set_msglevel = smsc9420_ethtool_set_msglevel, - .nway_reset = smsc9420_ethtool_nway_reset, + .nway_reset = phy_ethtool_nway_reset, .get_link = ethtool_op_get_link, .get_eeprom_len = smsc9420_ethtool_get_eeprom_len, .get_eeprom = smsc9420_ethtool_get_eeprom, |