cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nicstarmac.c (5979B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * this file included by nicstar.c
      4 */
      5
      6/*
      7 * nicstarmac.c
      8 * Read this ForeRunner's MAC address from eprom/eeprom
      9 */
     10
     11#include <linux/kernel.h>
     12
     13typedef void __iomem *virt_addr_t;
     14
     15#define CYCLE_DELAY 5
     16
     17#define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \
     18                                  udelay((useconds));}
     19/*
     20 * The following tables represent the timing diagrams found in
     21 * the Data Sheet for the Xicor X25020 EEProm.  The #defines below
     22 * represent the bits in the NICStAR's General Purpose register
     23 * that must be toggled for the corresponding actions on the EEProm
     24 * to occur.
     25 */
     26
     27/* Write Data To EEProm from SI line on rising edge of CLK */
     28/* Read Data From EEProm on falling edge of CLK */
     29
     30#define CS_HIGH		0x0002	/* Chip select high */
     31#define CS_LOW		0x0000	/* Chip select low (active low) */
     32#define CLK_HIGH	0x0004	/* Clock high */
     33#define CLK_LOW		0x0000	/* Clock low  */
     34#define SI_HIGH		0x0001	/* Serial input data high */
     35#define SI_LOW		0x0000	/* Serial input data low */
     36
     37/* Read Status Register = 0000 0101b */
     38#if 0
     39static u_int32_t rdsrtab[] = {
     40	CS_HIGH | CLK_HIGH,
     41	CS_LOW | CLK_LOW,
     42	CLK_HIGH,		/* 0 */
     43	CLK_LOW,
     44	CLK_HIGH,		/* 0 */
     45	CLK_LOW,
     46	CLK_HIGH,		/* 0 */
     47	CLK_LOW,
     48	CLK_HIGH,		/* 0 */
     49	CLK_LOW,
     50	CLK_HIGH,		/* 0 */
     51	CLK_LOW | SI_HIGH,
     52	CLK_HIGH | SI_HIGH,	/* 1 */
     53	CLK_LOW | SI_LOW,
     54	CLK_HIGH,		/* 0 */
     55	CLK_LOW | SI_HIGH,
     56	CLK_HIGH | SI_HIGH	/* 1 */
     57};
     58#endif /*  0  */
     59
     60/* Read from EEPROM = 0000 0011b */
     61static u_int32_t readtab[] = {
     62	/*
     63	   CS_HIGH | CLK_HIGH,
     64	 */
     65	CS_LOW | CLK_LOW,
     66	CLK_HIGH,		/* 0 */
     67	CLK_LOW,
     68	CLK_HIGH,		/* 0 */
     69	CLK_LOW,
     70	CLK_HIGH,		/* 0 */
     71	CLK_LOW,
     72	CLK_HIGH,		/* 0 */
     73	CLK_LOW,
     74	CLK_HIGH,		/* 0 */
     75	CLK_LOW,
     76	CLK_HIGH,		/* 0 */
     77	CLK_LOW | SI_HIGH,
     78	CLK_HIGH | SI_HIGH,	/* 1 */
     79	CLK_LOW | SI_HIGH,
     80	CLK_HIGH | SI_HIGH	/* 1 */
     81};
     82
     83/* Clock to read from/write to the eeprom */
     84static u_int32_t clocktab[] = {
     85	CLK_LOW,
     86	CLK_HIGH,
     87	CLK_LOW,
     88	CLK_HIGH,
     89	CLK_LOW,
     90	CLK_HIGH,
     91	CLK_LOW,
     92	CLK_HIGH,
     93	CLK_LOW,
     94	CLK_HIGH,
     95	CLK_LOW,
     96	CLK_HIGH,
     97	CLK_LOW,
     98	CLK_HIGH,
     99	CLK_LOW,
    100	CLK_HIGH,
    101	CLK_LOW
    102};
    103
    104#define NICSTAR_REG_WRITE(bs, reg, val) \
    105	while ( readl(bs + STAT) & 0x0200 ) ; \
    106	writel((val),(base)+(reg))
    107#define NICSTAR_REG_READ(bs, reg) \
    108	readl((base)+(reg))
    109#define NICSTAR_REG_GENERAL_PURPOSE GP
    110
    111/*
    112 * This routine will clock the Read_Status_reg function into the X2520
    113 * eeprom, then pull the result from bit 16 of the NicSTaR's General Purpose 
    114 * register.  
    115 */
    116#if 0
    117u_int32_t nicstar_read_eprom_status(virt_addr_t base)
    118{
    119	u_int32_t val;
    120	u_int32_t rbyte;
    121	int32_t i, j;
    122
    123	/* Send read instruction */
    124	val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
    125
    126	for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
    127		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    128				  (val | rdsrtab[i]));
    129		osp_MicroDelay(CYCLE_DELAY);
    130	}
    131
    132	/* Done sending instruction - now pull data off of bit 16, MSB first */
    133	/* Data clocked out of eeprom on falling edge of clock */
    134
    135	rbyte = 0;
    136	for (i = 7, j = 0; i >= 0; i--) {
    137		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    138				  (val | clocktab[j++]));
    139		rbyte |= (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
    140			    & 0x00010000) >> 16) << i);
    141		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    142				  (val | clocktab[j++]));
    143		osp_MicroDelay(CYCLE_DELAY);
    144	}
    145	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
    146	osp_MicroDelay(CYCLE_DELAY);
    147	return rbyte;
    148}
    149#endif /*  0  */
    150
    151/*
    152 * This routine will clock the Read_data function into the X2520
    153 * eeprom, followed by the address to read from, through the NicSTaR's General
    154 * Purpose register.  
    155 */
    156
    157static u_int8_t read_eprom_byte(virt_addr_t base, u_int8_t offset)
    158{
    159	u_int32_t val = 0;
    160	int i, j = 0;
    161	u_int8_t tempread = 0;
    162
    163	val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
    164
    165	/* Send READ instruction */
    166	for (i = 0; i < ARRAY_SIZE(readtab); i++) {
    167		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    168				  (val | readtab[i]));
    169		osp_MicroDelay(CYCLE_DELAY);
    170	}
    171
    172	/* Next, we need to send the byte address to read from */
    173	for (i = 7; i >= 0; i--) {
    174		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    175				  (val | clocktab[j++] | ((offset >> i) & 1)));
    176		osp_MicroDelay(CYCLE_DELAY);
    177		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    178				  (val | clocktab[j++] | ((offset >> i) & 1)));
    179		osp_MicroDelay(CYCLE_DELAY);
    180	}
    181
    182	j = 0;
    183
    184	/* Now, we can read data from the eeprom by clocking it in */
    185	for (i = 7; i >= 0; i--) {
    186		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    187				  (val | clocktab[j++]));
    188		osp_MicroDelay(CYCLE_DELAY);
    189		tempread |=
    190		    (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
    191		       & 0x00010000) >> 16) << i);
    192		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    193				  (val | clocktab[j++]));
    194		osp_MicroDelay(CYCLE_DELAY);
    195	}
    196
    197	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
    198	osp_MicroDelay(CYCLE_DELAY);
    199	return tempread;
    200}
    201
    202static void nicstar_init_eprom(virt_addr_t base)
    203{
    204	u_int32_t val;
    205
    206	/*
    207	 * turn chip select off
    208	 */
    209	val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
    210
    211	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    212			  (val | CS_HIGH | CLK_HIGH));
    213	osp_MicroDelay(CYCLE_DELAY);
    214
    215	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    216			  (val | CS_HIGH | CLK_LOW));
    217	osp_MicroDelay(CYCLE_DELAY);
    218
    219	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    220			  (val | CS_HIGH | CLK_HIGH));
    221	osp_MicroDelay(CYCLE_DELAY);
    222
    223	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
    224			  (val | CS_HIGH | CLK_LOW));
    225	osp_MicroDelay(CYCLE_DELAY);
    226}
    227
    228/*
    229 * This routine will be the interface to the ReadPromByte function
    230 * above.
    231 */
    232
    233static void
    234nicstar_read_eprom(virt_addr_t base,
    235		   u_int8_t prom_offset, u_int8_t * buffer, u_int32_t nbytes)
    236{
    237	u_int i;
    238
    239	for (i = 0; i < nbytes; i++) {
    240		buffer[i] = read_eprom_byte(base, prom_offset);
    241		++prom_offset;
    242		osp_MicroDelay(CYCLE_DELAY);
    243	}
    244}