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