18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * this file included by nicstar.c
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci/*
78c2ecf20Sopenharmony_ci * nicstarmac.c
88c2ecf20Sopenharmony_ci * Read this ForeRunner's MAC address from eprom/eeprom
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_citypedef void __iomem *virt_addr_t;
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#define CYCLE_DELAY 5
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci   This was the original definition
198c2ecf20Sopenharmony_ci#define osp_MicroDelay(microsec) \
208c2ecf20Sopenharmony_ci    do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
218c2ecf20Sopenharmony_ci*/
228c2ecf20Sopenharmony_ci#define osp_MicroDelay(microsec) {unsigned long useconds = (microsec); \
238c2ecf20Sopenharmony_ci                                  udelay((useconds));}
248c2ecf20Sopenharmony_ci/*
258c2ecf20Sopenharmony_ci * The following tables represent the timing diagrams found in
268c2ecf20Sopenharmony_ci * the Data Sheet for the Xicor X25020 EEProm.  The #defines below
278c2ecf20Sopenharmony_ci * represent the bits in the NICStAR's General Purpose register
288c2ecf20Sopenharmony_ci * that must be toggled for the corresponding actions on the EEProm
298c2ecf20Sopenharmony_ci * to occur.
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* Write Data To EEProm from SI line on rising edge of CLK */
338c2ecf20Sopenharmony_ci/* Read Data From EEProm on falling edge of CLK */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define CS_HIGH		0x0002	/* Chip select high */
368c2ecf20Sopenharmony_ci#define CS_LOW		0x0000	/* Chip select low (active low) */
378c2ecf20Sopenharmony_ci#define CLK_HIGH	0x0004	/* Clock high */
388c2ecf20Sopenharmony_ci#define CLK_LOW		0x0000	/* Clock low  */
398c2ecf20Sopenharmony_ci#define SI_HIGH		0x0001	/* Serial input data high */
408c2ecf20Sopenharmony_ci#define SI_LOW		0x0000	/* Serial input data low */
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci/* Read Status Register = 0000 0101b */
438c2ecf20Sopenharmony_ci#if 0
448c2ecf20Sopenharmony_cistatic u_int32_t rdsrtab[] = {
458c2ecf20Sopenharmony_ci	CS_HIGH | CLK_HIGH,
468c2ecf20Sopenharmony_ci	CS_LOW | CLK_LOW,
478c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
488c2ecf20Sopenharmony_ci	CLK_LOW,
498c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
508c2ecf20Sopenharmony_ci	CLK_LOW,
518c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
528c2ecf20Sopenharmony_ci	CLK_LOW,
538c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
548c2ecf20Sopenharmony_ci	CLK_LOW,
558c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
568c2ecf20Sopenharmony_ci	CLK_LOW | SI_HIGH,
578c2ecf20Sopenharmony_ci	CLK_HIGH | SI_HIGH,	/* 1 */
588c2ecf20Sopenharmony_ci	CLK_LOW | SI_LOW,
598c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
608c2ecf20Sopenharmony_ci	CLK_LOW | SI_HIGH,
618c2ecf20Sopenharmony_ci	CLK_HIGH | SI_HIGH	/* 1 */
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci#endif /*  0  */
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/* Read from EEPROM = 0000 0011b */
668c2ecf20Sopenharmony_cistatic u_int32_t readtab[] = {
678c2ecf20Sopenharmony_ci	/*
688c2ecf20Sopenharmony_ci	   CS_HIGH | CLK_HIGH,
698c2ecf20Sopenharmony_ci	 */
708c2ecf20Sopenharmony_ci	CS_LOW | CLK_LOW,
718c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
728c2ecf20Sopenharmony_ci	CLK_LOW,
738c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
748c2ecf20Sopenharmony_ci	CLK_LOW,
758c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
768c2ecf20Sopenharmony_ci	CLK_LOW,
778c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
788c2ecf20Sopenharmony_ci	CLK_LOW,
798c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
808c2ecf20Sopenharmony_ci	CLK_LOW,
818c2ecf20Sopenharmony_ci	CLK_HIGH,		/* 0 */
828c2ecf20Sopenharmony_ci	CLK_LOW | SI_HIGH,
838c2ecf20Sopenharmony_ci	CLK_HIGH | SI_HIGH,	/* 1 */
848c2ecf20Sopenharmony_ci	CLK_LOW | SI_HIGH,
858c2ecf20Sopenharmony_ci	CLK_HIGH | SI_HIGH	/* 1 */
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/* Clock to read from/write to the eeprom */
898c2ecf20Sopenharmony_cistatic u_int32_t clocktab[] = {
908c2ecf20Sopenharmony_ci	CLK_LOW,
918c2ecf20Sopenharmony_ci	CLK_HIGH,
928c2ecf20Sopenharmony_ci	CLK_LOW,
938c2ecf20Sopenharmony_ci	CLK_HIGH,
948c2ecf20Sopenharmony_ci	CLK_LOW,
958c2ecf20Sopenharmony_ci	CLK_HIGH,
968c2ecf20Sopenharmony_ci	CLK_LOW,
978c2ecf20Sopenharmony_ci	CLK_HIGH,
988c2ecf20Sopenharmony_ci	CLK_LOW,
998c2ecf20Sopenharmony_ci	CLK_HIGH,
1008c2ecf20Sopenharmony_ci	CLK_LOW,
1018c2ecf20Sopenharmony_ci	CLK_HIGH,
1028c2ecf20Sopenharmony_ci	CLK_LOW,
1038c2ecf20Sopenharmony_ci	CLK_HIGH,
1048c2ecf20Sopenharmony_ci	CLK_LOW,
1058c2ecf20Sopenharmony_ci	CLK_HIGH,
1068c2ecf20Sopenharmony_ci	CLK_LOW
1078c2ecf20Sopenharmony_ci};
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#define NICSTAR_REG_WRITE(bs, reg, val) \
1108c2ecf20Sopenharmony_ci	while ( readl(bs + STAT) & 0x0200 ) ; \
1118c2ecf20Sopenharmony_ci	writel((val),(base)+(reg))
1128c2ecf20Sopenharmony_ci#define NICSTAR_REG_READ(bs, reg) \
1138c2ecf20Sopenharmony_ci	readl((base)+(reg))
1148c2ecf20Sopenharmony_ci#define NICSTAR_REG_GENERAL_PURPOSE GP
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci/*
1178c2ecf20Sopenharmony_ci * This routine will clock the Read_Status_reg function into the X2520
1188c2ecf20Sopenharmony_ci * eeprom, then pull the result from bit 16 of the NicSTaR's General Purpose
1198c2ecf20Sopenharmony_ci * register.
1208c2ecf20Sopenharmony_ci */
1218c2ecf20Sopenharmony_ci#if 0
1228c2ecf20Sopenharmony_ciu_int32_t nicstar_read_eprom_status(virt_addr_t base)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	u_int32_t val;
1258c2ecf20Sopenharmony_ci	u_int32_t rbyte;
1268c2ecf20Sopenharmony_ci	int32_t i, j;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	/* Send read instruction */
1298c2ecf20Sopenharmony_ci	val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(rdsrtab); i++) {
1328c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1338c2ecf20Sopenharmony_ci				  (val | rdsrtab[i]));
1348c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
1358c2ecf20Sopenharmony_ci	}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	/* Done sending instruction - now pull data off of bit 16, MSB first */
1388c2ecf20Sopenharmony_ci	/* Data clocked out of eeprom on falling edge of clock */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	rbyte = 0;
1418c2ecf20Sopenharmony_ci	for (i = 7, j = 0; i >= 0; i--) {
1428c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1438c2ecf20Sopenharmony_ci				  (val | clocktab[j++]));
1448c2ecf20Sopenharmony_ci		rbyte |= (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
1458c2ecf20Sopenharmony_ci			    & 0x00010000) >> 16) << i);
1468c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1478c2ecf20Sopenharmony_ci				  (val | clocktab[j++]));
1488c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
1498c2ecf20Sopenharmony_ci	}
1508c2ecf20Sopenharmony_ci	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
1518c2ecf20Sopenharmony_ci	osp_MicroDelay(CYCLE_DELAY);
1528c2ecf20Sopenharmony_ci	return rbyte;
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci#endif /*  0  */
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci/*
1578c2ecf20Sopenharmony_ci * This routine will clock the Read_data function into the X2520
1588c2ecf20Sopenharmony_ci * eeprom, followed by the address to read from, through the NicSTaR's General
1598c2ecf20Sopenharmony_ci * Purpose register.
1608c2ecf20Sopenharmony_ci */
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic u_int8_t read_eprom_byte(virt_addr_t base, u_int8_t offset)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	u_int32_t val = 0;
1658c2ecf20Sopenharmony_ci	int i, j = 0;
1668c2ecf20Sopenharmony_ci	u_int8_t tempread = 0;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	/* Send READ instruction */
1718c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(readtab); i++) {
1728c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1738c2ecf20Sopenharmony_ci				  (val | readtab[i]));
1748c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
1758c2ecf20Sopenharmony_ci	}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	/* Next, we need to send the byte address to read from */
1788c2ecf20Sopenharmony_ci	for (i = 7; i >= 0; i--) {
1798c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1808c2ecf20Sopenharmony_ci				  (val | clocktab[j++] | ((offset >> i) & 1)));
1818c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
1828c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1838c2ecf20Sopenharmony_ci				  (val | clocktab[j++] | ((offset >> i) & 1)));
1848c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
1858c2ecf20Sopenharmony_ci	}
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	j = 0;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	/* Now, we can read data from the eeprom by clocking it in */
1908c2ecf20Sopenharmony_ci	for (i = 7; i >= 0; i--) {
1918c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1928c2ecf20Sopenharmony_ci				  (val | clocktab[j++]));
1938c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
1948c2ecf20Sopenharmony_ci		tempread |=
1958c2ecf20Sopenharmony_ci		    (((NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE)
1968c2ecf20Sopenharmony_ci		       & 0x00010000) >> 16) << i);
1978c2ecf20Sopenharmony_ci		NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
1988c2ecf20Sopenharmony_ci				  (val | clocktab[j++]));
1998c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
2008c2ecf20Sopenharmony_ci	}
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE, 2);
2038c2ecf20Sopenharmony_ci	osp_MicroDelay(CYCLE_DELAY);
2048c2ecf20Sopenharmony_ci	return tempread;
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic void nicstar_init_eprom(virt_addr_t base)
2088c2ecf20Sopenharmony_ci{
2098c2ecf20Sopenharmony_ci	u_int32_t val;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/*
2128c2ecf20Sopenharmony_ci	 * turn chip select off
2138c2ecf20Sopenharmony_ci	 */
2148c2ecf20Sopenharmony_ci	val = NICSTAR_REG_READ(base, NICSTAR_REG_GENERAL_PURPOSE) & 0xFFFFFFF0;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
2178c2ecf20Sopenharmony_ci			  (val | CS_HIGH | CLK_HIGH));
2188c2ecf20Sopenharmony_ci	osp_MicroDelay(CYCLE_DELAY);
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
2218c2ecf20Sopenharmony_ci			  (val | CS_HIGH | CLK_LOW));
2228c2ecf20Sopenharmony_ci	osp_MicroDelay(CYCLE_DELAY);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
2258c2ecf20Sopenharmony_ci			  (val | CS_HIGH | CLK_HIGH));
2268c2ecf20Sopenharmony_ci	osp_MicroDelay(CYCLE_DELAY);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	NICSTAR_REG_WRITE(base, NICSTAR_REG_GENERAL_PURPOSE,
2298c2ecf20Sopenharmony_ci			  (val | CS_HIGH | CLK_LOW));
2308c2ecf20Sopenharmony_ci	osp_MicroDelay(CYCLE_DELAY);
2318c2ecf20Sopenharmony_ci}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci/*
2348c2ecf20Sopenharmony_ci * This routine will be the interface to the ReadPromByte function
2358c2ecf20Sopenharmony_ci * above.
2368c2ecf20Sopenharmony_ci */
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic void
2398c2ecf20Sopenharmony_cinicstar_read_eprom(virt_addr_t base,
2408c2ecf20Sopenharmony_ci		   u_int8_t prom_offset, u_int8_t * buffer, u_int32_t nbytes)
2418c2ecf20Sopenharmony_ci{
2428c2ecf20Sopenharmony_ci	u_int i;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	for (i = 0; i < nbytes; i++) {
2458c2ecf20Sopenharmony_ci		buffer[i] = read_eprom_byte(base, prom_offset);
2468c2ecf20Sopenharmony_ci		++prom_offset;
2478c2ecf20Sopenharmony_ci		osp_MicroDelay(CYCLE_DELAY);
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci}
250