root/drivers/staging/rtl8712/rtl871x_eeprom.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. up_clk
  2. down_clk
  3. shift_out_bits
  4. shift_in_bits
  5. standby
  6. wait_eeprom_cmd_done
  7. eeprom_clean
  8. r8712_eeprom_write16
  9. r8712_eeprom_read16

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  * rtl871x_eeprom.c
   4  *
   5  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   6  * Linux device driver for RTL8192SU
   7  *
   8  * Modifications for inclusion into the Linux staging tree are
   9  * Copyright(c) 2010 Larry Finger. All rights reserved.
  10  *
  11  * Contact information:
  12  * WLAN FAE <wlanfae@realtek.com>
  13  * Larry Finger <Larry.Finger@lwfinger.net>
  14  *
  15  ******************************************************************************/
  16 
  17 #define _RTL871X_EEPROM_C_
  18 
  19 #include "osdep_service.h"
  20 #include "drv_types.h"
  21 
  22 static void up_clk(struct _adapter *padapter, u16 *x)
  23 {
  24         *x = *x | _EESK;
  25         r8712_write8(padapter, EE_9346CR, (u8)*x);
  26         udelay(CLOCK_RATE);
  27 }
  28 
  29 static void down_clk(struct _adapter *padapter, u16 *x)
  30 {
  31         *x = *x & ~_EESK;
  32         r8712_write8(padapter, EE_9346CR, (u8)*x);
  33         udelay(CLOCK_RATE);
  34 }
  35 
  36 static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count)
  37 {
  38         u16 x, mask;
  39 
  40         if (padapter->surprise_removed)
  41                 goto out;
  42         mask = 0x01 << (count - 1);
  43         x = r8712_read8(padapter, EE_9346CR);
  44         x &= ~(_EEDO | _EEDI);
  45         do {
  46                 x &= ~_EEDI;
  47                 if (data & mask)
  48                         x |= _EEDI;
  49                 if (padapter->surprise_removed)
  50                         goto out;
  51                 r8712_write8(padapter, EE_9346CR, (u8)x);
  52                 udelay(CLOCK_RATE);
  53                 up_clk(padapter, &x);
  54                 down_clk(padapter, &x);
  55                 mask >>= 1;
  56         } while (mask);
  57         if (padapter->surprise_removed)
  58                 goto out;
  59         x &= ~_EEDI;
  60         r8712_write8(padapter, EE_9346CR, (u8)x);
  61 out:;
  62 }
  63 
  64 static u16 shift_in_bits(struct _adapter *padapter)
  65 {
  66         u16 x, d = 0, i;
  67 
  68         if (padapter->surprise_removed)
  69                 goto out;
  70         x = r8712_read8(padapter, EE_9346CR);
  71         x &= ~(_EEDO | _EEDI);
  72         d = 0;
  73         for (i = 0; i < 16; i++) {
  74                 d <<= 1;
  75                 up_clk(padapter, &x);
  76                 if (padapter->surprise_removed)
  77                         goto out;
  78                 x = r8712_read8(padapter, EE_9346CR);
  79                 x &= ~(_EEDI);
  80                 if (x & _EEDO)
  81                         d |= 1;
  82                 down_clk(padapter, &x);
  83         }
  84 out:
  85         return d;
  86 }
  87 
  88 static void standby(struct _adapter *padapter)
  89 {
  90         u8   x;
  91 
  92         x = r8712_read8(padapter, EE_9346CR);
  93         x &= ~(_EECS | _EESK);
  94         r8712_write8(padapter, EE_9346CR, x);
  95         udelay(CLOCK_RATE);
  96         x |= _EECS;
  97         r8712_write8(padapter, EE_9346CR, x);
  98         udelay(CLOCK_RATE);
  99 }
 100 
 101 static u16 wait_eeprom_cmd_done(struct _adapter *padapter)
 102 {
 103         u8      x;
 104         u16     i;
 105 
 106         standby(padapter);
 107         for (i = 0; i < 200; i++) {
 108                 x = r8712_read8(padapter, EE_9346CR);
 109                 if (x & _EEDO)
 110                         return true;
 111                 udelay(CLOCK_RATE);
 112         }
 113         return false;
 114 }
 115 
 116 static void eeprom_clean(struct _adapter *padapter)
 117 {
 118         u16 x;
 119 
 120         if (padapter->surprise_removed)
 121                 return;
 122         x = r8712_read8(padapter, EE_9346CR);
 123         if (padapter->surprise_removed)
 124                 return;
 125         x &= ~(_EECS | _EEDI);
 126         r8712_write8(padapter, EE_9346CR, (u8)x);
 127         if (padapter->surprise_removed)
 128                 return;
 129         up_clk(padapter, &x);
 130         if (padapter->surprise_removed)
 131                 return;
 132         down_clk(padapter, &x);
 133 }
 134 
 135 void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data)
 136 {
 137         u8 x;
 138         u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
 139 
 140         tmp8_ori = r8712_read8(padapter, 0x102502f1);
 141         tmp8_new = tmp8_ori & 0xf7;
 142         if (tmp8_ori != tmp8_new)
 143                 r8712_write8(padapter, 0x102502f1, tmp8_new);
 144         tmp8_clk_ori = r8712_read8(padapter, 0x10250003);
 145         tmp8_clk_new = tmp8_clk_ori | 0x20;
 146         if (tmp8_clk_new != tmp8_clk_ori)
 147                 r8712_write8(padapter, 0x10250003, tmp8_clk_new);
 148         x = r8712_read8(padapter, EE_9346CR);
 149         x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
 150         x |= _EEM1 | _EECS;
 151         r8712_write8(padapter, EE_9346CR, x);
 152         shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
 153         if (padapter->eeprom_address_size == 8) /*CF+ and SDIO*/
 154                 shift_out_bits(padapter, 0, 6);
 155         else    /* USB */
 156                 shift_out_bits(padapter, 0, 4);
 157         standby(padapter);
 158         /* Erase this particular word.  Write the erase opcode and register
 159          * number in that order. The opcode is 3bits in length; reg is 6
 160          * bits long.
 161          */
 162         standby(padapter);
 163         /* write the new word to the EEPROM
 164          * send the write opcode the EEPORM
 165          */
 166         shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
 167         /* select which word in the EEPROM that we are writing to. */
 168         shift_out_bits(padapter, reg, padapter->eeprom_address_size);
 169         /* write the data to the selected EEPROM word. */
 170         shift_out_bits(padapter, data, 16);
 171         if (wait_eeprom_cmd_done(padapter)) {
 172                 standby(padapter);
 173                 shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
 174                 shift_out_bits(padapter, reg, 4);
 175                 eeprom_clean(padapter);
 176         }
 177         if (tmp8_clk_new != tmp8_clk_ori)
 178                 r8712_write8(padapter, 0x10250003, tmp8_clk_ori);
 179         if (tmp8_new != tmp8_ori)
 180                 r8712_write8(padapter, 0x102502f1, tmp8_ori);
 181 }
 182 
 183 u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg) /*ReadEEprom*/
 184 {
 185         u16 x;
 186         u16 data = 0;
 187         u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
 188 
 189         tmp8_ori = r8712_read8(padapter, 0x102502f1);
 190         tmp8_new = tmp8_ori & 0xf7;
 191         if (tmp8_ori != tmp8_new)
 192                 r8712_write8(padapter, 0x102502f1, tmp8_new);
 193         tmp8_clk_ori = r8712_read8(padapter, 0x10250003);
 194         tmp8_clk_new = tmp8_clk_ori | 0x20;
 195         if (tmp8_clk_new != tmp8_clk_ori)
 196                 r8712_write8(padapter, 0x10250003, tmp8_clk_new);
 197         if (padapter->surprise_removed)
 198                 goto out;
 199         /* select EEPROM, reset bits, set _EECS */
 200         x = r8712_read8(padapter, EE_9346CR);
 201         if (padapter->surprise_removed)
 202                 goto out;
 203         x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
 204         x |= _EEM1 | _EECS;
 205         r8712_write8(padapter, EE_9346CR, (unsigned char)x);
 206         /* write the read opcode and register number in that order
 207          * The opcode is 3bits in length, reg is 6 bits long
 208          */
 209         shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
 210         shift_out_bits(padapter, reg, padapter->eeprom_address_size);
 211         /* Now read the data (16 bits) in from the selected EEPROM word */
 212         data = shift_in_bits(padapter);
 213         eeprom_clean(padapter);
 214 out:
 215         if (tmp8_clk_new != tmp8_clk_ori)
 216                 r8712_write8(padapter, 0x10250003, tmp8_clk_ori);
 217         if (tmp8_new != tmp8_ori)
 218                 r8712_write8(padapter, 0x102502f1, tmp8_ori);
 219         return data;
 220 }

/* [<][>][^][v][top][bottom][index][help] */