diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/staging/rtl8192u/r8180_93cx6.c | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | drivers/staging/rtl8192u/r8180_93cx6.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/drivers/staging/rtl8192u/r8180_93cx6.c b/drivers/staging/rtl8192u/r8180_93cx6.c new file mode 100644 index 000000000..2527cea60 --- /dev/null +++ b/drivers/staging/rtl8192u/r8180_93cx6.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * This files contains card eeprom (93c46 or 93c56) programming routines, + * memory is addressed by 16 bits words. + * + * This is part of rtl8180 OpenSource driver. + * Copyright (C) Andrea Merello 2004 <andrea.merello@gmail.com> + * + * Parts of this driver are based on the GPL part of the + * official realtek driver. + * + * Parts of this driver are based on the rtl8180 driver skeleton + * from Patric Schenke & Andres Salomon. + * + * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. + * + * We want to thank the Authors of those projects and the Ndiswrapper + * project Authors. + */ + +#include "r8180_93cx6.h" + +static void eprom_cs(struct net_device *dev, short bit) +{ + u8 cmdreg; + int err; + + err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg); + if (err) + return; + if (bit) + /* enable EPROM */ + write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CS_BIT); + else + /* disable EPROM */ + write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CS_BIT); + + force_pci_posting(dev); + udelay(EPROM_DELAY); +} + +static void eprom_ck_cycle(struct net_device *dev) +{ + u8 cmdreg; + int err; + + err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg); + if (err) + return; + write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CK_BIT); + force_pci_posting(dev); + udelay(EPROM_DELAY); + + read_nic_byte_E(dev, EPROM_CMD, &cmdreg); + write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CK_BIT); + force_pci_posting(dev); + udelay(EPROM_DELAY); +} + +static void eprom_w(struct net_device *dev, short bit) +{ + u8 cmdreg; + int err; + + err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg); + if (err) + return; + if (bit) + write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_W_BIT); + else + write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_W_BIT); + + force_pci_posting(dev); + udelay(EPROM_DELAY); +} + +static short eprom_r(struct net_device *dev) +{ + u8 bit; + int err; + + err = read_nic_byte_E(dev, EPROM_CMD, &bit); + if (err) + return err; + + udelay(EPROM_DELAY); + + if (bit & EPROM_R_BIT) + return 1; + + return 0; +} + +static void eprom_send_bits_string(struct net_device *dev, short b[], int len) +{ + int i; + + for (i = 0; i < len; i++) { + eprom_w(dev, b[i]); + eprom_ck_cycle(dev); + } +} + +int eprom_read(struct net_device *dev, u32 addr) +{ + struct r8192_priv *priv = ieee80211_priv(dev); + short read_cmd[] = {1, 1, 0}; + short addr_str[8]; + int i; + int addr_len; + u32 ret; + int err; + + ret = 0; + /* enable EPROM programming */ + write_nic_byte_E(dev, EPROM_CMD, + (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT)); + force_pci_posting(dev); + udelay(EPROM_DELAY); + + if (priv->epromtype == EPROM_93c56) { + addr_str[7] = addr & 1; + addr_str[6] = addr & BIT(1); + addr_str[5] = addr & BIT(2); + addr_str[4] = addr & BIT(3); + addr_str[3] = addr & BIT(4); + addr_str[2] = addr & BIT(5); + addr_str[1] = addr & BIT(6); + addr_str[0] = addr & BIT(7); + addr_len = 8; + } else { + addr_str[5] = addr & 1; + addr_str[4] = addr & BIT(1); + addr_str[3] = addr & BIT(2); + addr_str[2] = addr & BIT(3); + addr_str[1] = addr & BIT(4); + addr_str[0] = addr & BIT(5); + addr_len = 6; + } + eprom_cs(dev, 1); + eprom_ck_cycle(dev); + eprom_send_bits_string(dev, read_cmd, 3); + eprom_send_bits_string(dev, addr_str, addr_len); + + /* + * keep chip pin D to low state while reading. + * I'm unsure if it is necessary, but anyway shouldn't hurt + */ + eprom_w(dev, 0); + + for (i = 0; i < 16; i++) { + /* eeprom needs a clk cycle between writing opcode&adr + * and reading data. (eeprom outs a dummy 0) + */ + eprom_ck_cycle(dev); + err = eprom_r(dev); + if (err < 0) + return err; + + ret |= err << (15 - i); + } + + eprom_cs(dev, 0); + eprom_ck_cycle(dev); + + /* disable EPROM programming */ + write_nic_byte_E(dev, EPROM_CMD, + (EPROM_CMD_NORMAL << EPROM_CMD_OPERATING_MODE_SHIFT)); + return ret; +} |