linux/drivers/staging/rtl8192u/r8180_93cx6.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  This files contains card eeprom (93c46 or 93c56) programming routines,
   4 *  memory is addressed by 16 bits words.
   5 *
   6 *  This is part of rtl8180 OpenSource driver.
   7 *  Copyright (C) Andrea Merello 2004  <andrea.merello@gmail.com>
   8 *
   9 *  Parts of this driver are based on the GPL part of the
  10 *  official realtek driver.
  11 *
  12 *  Parts of this driver are based on the rtl8180 driver skeleton
  13 *  from Patric Schenke & Andres Salomon.
  14 *
  15 *  Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
  16 *
  17 *  We want to thank the Authors of those projects and the Ndiswrapper
  18 *  project Authors.
  19 */
  20
  21#include "r8180_93cx6.h"
  22
  23static void eprom_cs(struct net_device *dev, short bit)
  24{
  25        u8 cmdreg;
  26        int err;
  27
  28        err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
  29        if (err)
  30                return;
  31        if (bit)
  32                /* enable EPROM */
  33                write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CS_BIT);
  34        else
  35                /* disable EPROM */
  36                write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CS_BIT);
  37
  38        force_pci_posting(dev);
  39        udelay(EPROM_DELAY);
  40}
  41
  42static void eprom_ck_cycle(struct net_device *dev)
  43{
  44        u8 cmdreg;
  45        int err;
  46
  47        err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
  48        if (err)
  49                return;
  50        write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_CK_BIT);
  51        force_pci_posting(dev);
  52        udelay(EPROM_DELAY);
  53
  54        read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
  55        write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_CK_BIT);
  56        force_pci_posting(dev);
  57        udelay(EPROM_DELAY);
  58}
  59
  60static void eprom_w(struct net_device *dev, short bit)
  61{
  62        u8 cmdreg;
  63        int err;
  64
  65        err = read_nic_byte_E(dev, EPROM_CMD, &cmdreg);
  66        if (err)
  67                return;
  68        if (bit)
  69                write_nic_byte_E(dev, EPROM_CMD, cmdreg | EPROM_W_BIT);
  70        else
  71                write_nic_byte_E(dev, EPROM_CMD, cmdreg & ~EPROM_W_BIT);
  72
  73        force_pci_posting(dev);
  74        udelay(EPROM_DELAY);
  75}
  76
  77static short eprom_r(struct net_device *dev)
  78{
  79        u8 bit;
  80        int err;
  81
  82        err = read_nic_byte_E(dev, EPROM_CMD, &bit);
  83        if (err)
  84                return err;
  85
  86        udelay(EPROM_DELAY);
  87
  88        if (bit & EPROM_R_BIT)
  89                return 1;
  90
  91        return 0;
  92}
  93
  94static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
  95{
  96        int i;
  97
  98        for (i = 0; i < len; i++) {
  99                eprom_w(dev, b[i]);
 100                eprom_ck_cycle(dev);
 101        }
 102}
 103
 104int eprom_read(struct net_device *dev, u32 addr)
 105{
 106        struct r8192_priv *priv = ieee80211_priv(dev);
 107        short read_cmd[] = {1, 1, 0};
 108        short addr_str[8];
 109        int i;
 110        int addr_len;
 111        u32 ret;
 112        int err;
 113
 114        ret = 0;
 115        /* enable EPROM programming */
 116        write_nic_byte_E(dev, EPROM_CMD,
 117                       (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT));
 118        force_pci_posting(dev);
 119        udelay(EPROM_DELAY);
 120
 121        if (priv->epromtype == EPROM_93c56) {
 122                addr_str[7] = addr & 1;
 123                addr_str[6] = addr & BIT(1);
 124                addr_str[5] = addr & BIT(2);
 125                addr_str[4] = addr & BIT(3);
 126                addr_str[3] = addr & BIT(4);
 127                addr_str[2] = addr & BIT(5);
 128                addr_str[1] = addr & BIT(6);
 129                addr_str[0] = addr & BIT(7);
 130                addr_len = 8;
 131        } else {
 132                addr_str[5] = addr & 1;
 133                addr_str[4] = addr & BIT(1);
 134                addr_str[3] = addr & BIT(2);
 135                addr_str[2] = addr & BIT(3);
 136                addr_str[1] = addr & BIT(4);
 137                addr_str[0] = addr & BIT(5);
 138                addr_len = 6;
 139        }
 140        eprom_cs(dev, 1);
 141        eprom_ck_cycle(dev);
 142        eprom_send_bits_string(dev, read_cmd, 3);
 143        eprom_send_bits_string(dev, addr_str, addr_len);
 144
 145        /*
 146         * keep chip pin D to low state while reading.
 147         * I'm unsure if it is necessary, but anyway shouldn't hurt
 148         */
 149        eprom_w(dev, 0);
 150
 151        for (i = 0; i < 16; i++) {
 152                /* eeprom needs a clk cycle between writing opcode&adr
 153                 * and reading data. (eeprom outs a dummy 0)
 154                 */
 155                eprom_ck_cycle(dev);
 156                err = eprom_r(dev);
 157                if (err < 0)
 158                        return err;
 159
 160                ret |= err << (15 - i);
 161        }
 162
 163        eprom_cs(dev, 0);
 164        eprom_ck_cycle(dev);
 165
 166        /* disable EPROM programming */
 167        write_nic_byte_E(dev, EPROM_CMD,
 168                       (EPROM_CMD_NORMAL << EPROM_CMD_OPERATING_MODE_SHIFT));
 169        return ret;
 170}
 171