r8180_93cx6.c (3772B)
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}