cs8900.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Cirrus Logic CS8900A Ethernet
  3. *
  4. * (C) 2009 Ben Warren , biggerbadderben@gmail.com
  5. * Converted to use CONFIG_NET_MULTI API
  6. *
  7. * (C) 2003 Wolfgang Denk, wd@denx.de
  8. * Extension to synchronize ethaddr environment variable
  9. * against value in EEPROM
  10. *
  11. * (C) Copyright 2002
  12. * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
  13. * Marius Groeger <mgroeger@sysgo.de>
  14. *
  15. * Copyright (C) 1999 Ben Williamson <benw@pobox.com>
  16. *
  17. * See file CREDITS for list of people who contributed to this
  18. * project.
  19. *
  20. * This program is loaded into SRAM in bootstrap mode, where it waits
  21. * for commands on UART1 to read and write memory, jump to code etc.
  22. * A design goal for this program is to be entirely independent of the
  23. * target board. Anything with a CL-PS7111 or EP7211 should be able to run
  24. * this code in bootstrap mode. All the board specifics can be handled on
  25. * the host.
  26. *
  27. * This program is free software; you can redistribute it and/or modify
  28. * it under the terms of the GNU General Public License as published by
  29. * the Free Software Foundation; either version 2 of the License, or
  30. * (at your option) any later version.
  31. *
  32. * This program is distributed in the hope that it will be useful,
  33. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  34. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  35. * GNU General Public License for more details.
  36. *
  37. * You should have received a copy of the GNU General Public License
  38. * along with this program; if not, write to the Free Software
  39. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  40. */
  41. #include <common.h>
  42. #include <command.h>
  43. #include <asm/io.h>
  44. #include <net.h>
  45. #include <malloc.h>
  46. #include "cs8900.h"
  47. #undef DEBUG
  48. /* packet page register access functions */
  49. #ifdef CONFIG_CS8900_BUS32
  50. #define REG_WRITE(v, a) writel((v),(a))
  51. #define REG_READ(a) readl((a))
  52. /* we don't need 16 bit initialisation on 32 bit bus */
  53. #define get_reg_init_bus(r,d) get_reg((r),(d))
  54. #else
  55. #define REG_WRITE(v, a) writew((v),(a))
  56. #define REG_READ(a) readw((a))
  57. static u16 get_reg_init_bus(struct eth_device *dev, int regno)
  58. {
  59. /* force 16 bit busmode */
  60. struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
  61. uint8_t volatile * const iob = (uint8_t volatile * const)dev->iobase;
  62. readb(iob);
  63. readb(iob + 1);
  64. readb(iob);
  65. readb(iob + 1);
  66. readb(iob);
  67. REG_WRITE(regno, &priv->regs->pptr);
  68. return REG_READ(&priv->regs->pdata);
  69. }
  70. #endif
  71. static u16 get_reg(struct eth_device *dev, int regno)
  72. {
  73. struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
  74. REG_WRITE(regno, &priv->regs->pptr);
  75. return REG_READ(&priv->regs->pdata);
  76. }
  77. static void put_reg(struct eth_device *dev, int regno, u16 val)
  78. {
  79. struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
  80. REG_WRITE(regno, &priv->regs->pptr);
  81. REG_WRITE(val, &priv->regs->pdata);
  82. }
  83. static void cs8900_reset(struct eth_device *dev)
  84. {
  85. int tmo;
  86. u16 us;
  87. /* reset NIC */
  88. put_reg(dev, PP_SelfCTL, get_reg(dev, PP_SelfCTL) | PP_SelfCTL_Reset);
  89. /* wait for 200ms */
  90. udelay(200000);
  91. /* Wait until the chip is reset */
  92. tmo = get_timer(0) + 1 * CONFIG_SYS_HZ;
  93. while ((((us = get_reg_init_bus(dev, PP_SelfSTAT)) &
  94. PP_SelfSTAT_InitD) == 0) && tmo < get_timer(0))
  95. /*NOP*/;
  96. }
  97. static void cs8900_reginit(struct eth_device *dev)
  98. {
  99. /* receive only error free packets addressed to this card */
  100. put_reg(dev, PP_RxCTL,
  101. PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);
  102. /* do not generate any interrupts on receive operations */
  103. put_reg(dev, PP_RxCFG, 0);
  104. /* do not generate any interrupts on transmit operations */
  105. put_reg(dev, PP_TxCFG, 0);
  106. /* do not generate any interrupts on buffer operations */
  107. put_reg(dev, PP_BufCFG, 0);
  108. /* enable transmitter/receiver mode */
  109. put_reg(dev, PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
  110. }
  111. void cs8900_get_enetaddr(struct eth_device *dev)
  112. {
  113. int i;
  114. /* verify chip id */
  115. if (get_reg_init_bus(dev, PP_ChipID) != 0x630e)
  116. return;
  117. cs8900_reset(dev);
  118. if ((get_reg(dev, PP_SelfSTAT) &
  119. (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) ==
  120. (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) {
  121. /* Load the MAC from EEPROM */
  122. for (i = 0; i < 3; i++) {
  123. u32 Addr;
  124. Addr = get_reg(dev, PP_IA + i * 2);
  125. dev->enetaddr[i * 2] = Addr & 0xFF;
  126. dev->enetaddr[i * 2 + 1] = Addr >> 8;
  127. }
  128. }
  129. }
  130. void cs8900_halt(struct eth_device *dev)
  131. {
  132. /* disable transmitter/receiver mode */
  133. put_reg(dev, PP_LineCTL, 0);
  134. /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */
  135. get_reg_init_bus(dev, PP_ChipID);
  136. }
  137. static int cs8900_init(struct eth_device *dev, bd_t * bd)
  138. {
  139. uchar *enetaddr = dev->enetaddr;
  140. u16 id;
  141. /* verify chip id */
  142. id = get_reg_init_bus(dev, PP_ChipID);
  143. if (id != 0x630e) {
  144. printf ("CS8900 Ethernet chip not found: "
  145. "ID=0x%04x instead 0x%04x\n", id, 0x630e);
  146. return 1;
  147. }
  148. cs8900_reset (dev);
  149. /* set the ethernet address */
  150. put_reg(dev, PP_IA + 0, enetaddr[0] | (enetaddr[1] << 8));
  151. put_reg(dev, PP_IA + 2, enetaddr[2] | (enetaddr[3] << 8));
  152. put_reg(dev, PP_IA + 4, enetaddr[4] | (enetaddr[5] << 8));
  153. cs8900_reginit(dev);
  154. return 0;
  155. }
  156. /* Get a data block via Ethernet */
  157. static int cs8900_recv(struct eth_device *dev)
  158. {
  159. int i;
  160. u16 rxlen;
  161. u16 *addr;
  162. u16 status;
  163. struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
  164. status = get_reg(dev, PP_RER);
  165. if ((status & PP_RER_RxOK) == 0)
  166. return 0;
  167. status = REG_READ(&priv->regs->rtdata);
  168. rxlen = REG_READ(&priv->regs->rtdata);
  169. if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
  170. debug("packet too big!\n");
  171. for (addr = (u16 *) NetRxPackets[0], i = rxlen >> 1; i > 0;
  172. i--)
  173. *addr++ = REG_READ(&priv->regs->rtdata);
  174. if (rxlen & 1)
  175. *addr++ = REG_READ(&priv->regs->rtdata);
  176. /* Pass the packet up to the protocol layers. */
  177. NetReceive (NetRxPackets[0], rxlen);
  178. return rxlen;
  179. }
  180. /* Send a data block via Ethernet. */
  181. static int cs8900_send(struct eth_device *dev,
  182. volatile void *packet, int length)
  183. {
  184. volatile u16 *addr;
  185. int tmo;
  186. u16 s;
  187. struct cs8900_priv *priv = (struct cs8900_priv *)(dev->priv);
  188. retry:
  189. /* initiate a transmit sequence */
  190. REG_WRITE(PP_TxCmd_TxStart_Full, &priv->regs->txcmd);
  191. REG_WRITE(length, &priv->regs->txlen);
  192. /* Test to see if the chip has allocated memory for the packet */
  193. if ((get_reg(dev, PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {
  194. /* Oops... this should not happen! */
  195. debug("cs: unable to send packet; retrying...\n");
  196. for (tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
  197. get_timer(0) < tmo;)
  198. /*NOP*/;
  199. cs8900_reset(dev);
  200. cs8900_reginit(dev);
  201. goto retry;
  202. }
  203. /* Write the contents of the packet */
  204. /* assume even number of bytes */
  205. for (addr = packet; length > 0; length -= 2)
  206. REG_WRITE(*addr++, &priv->regs->rtdata);
  207. /* wait for transfer to succeed */
  208. tmo = get_timer(0) + 5 * CONFIG_SYS_HZ;
  209. while ((s = get_reg(dev, PP_TER) & ~0x1F) == 0) {
  210. if (get_timer(0) >= tmo)
  211. break;
  212. }
  213. /* nothing */ ;
  214. if((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) {
  215. debug("\ntransmission error %#x\n", s);
  216. }
  217. return 0;
  218. }
  219. static void cs8900_e2prom_ready(struct eth_device *dev)
  220. {
  221. while (get_reg(dev, PP_SelfSTAT) & SI_BUSY)
  222. ;
  223. }
  224. /***********************************************************/
  225. /* read a 16-bit word out of the EEPROM */
  226. /***********************************************************/
  227. int cs8900_e2prom_read(struct eth_device *dev,
  228. u8 addr, u16 *value)
  229. {
  230. cs8900_e2prom_ready(dev);
  231. put_reg(dev, PP_EECMD, EEPROM_READ_CMD | addr);
  232. cs8900_e2prom_ready(dev);
  233. *value = get_reg(dev, PP_EEData);
  234. return 0;
  235. }
  236. /***********************************************************/
  237. /* write a 16-bit word into the EEPROM */
  238. /***********************************************************/
  239. int cs8900_e2prom_write(struct eth_device *dev, u8 addr, u16 value)
  240. {
  241. cs8900_e2prom_ready(dev);
  242. put_reg(dev, PP_EECMD, EEPROM_WRITE_EN);
  243. cs8900_e2prom_ready(dev);
  244. put_reg(dev, PP_EEData, value);
  245. put_reg(dev, PP_EECMD, EEPROM_WRITE_CMD | addr);
  246. cs8900_e2prom_ready(dev);
  247. put_reg(dev, PP_EECMD, EEPROM_WRITE_DIS);
  248. cs8900_e2prom_ready(dev);
  249. return 0;
  250. }
  251. int cs8900_initialize(u8 dev_num, int base_addr)
  252. {
  253. struct eth_device *dev;
  254. struct cs8900_priv *priv;
  255. dev = malloc(sizeof(*dev));
  256. if (!dev) {
  257. return 0;
  258. }
  259. memset(dev, 0, sizeof(*dev));
  260. priv = malloc(sizeof(*priv));
  261. if (!priv) {
  262. free(dev);
  263. return 0;
  264. }
  265. memset(priv, 0, sizeof(*priv));
  266. priv->regs = (struct cs8900_regs *)base_addr;
  267. dev->iobase = base_addr;
  268. dev->priv = priv;
  269. dev->init = cs8900_init;
  270. dev->halt = cs8900_halt;
  271. dev->send = cs8900_send;
  272. dev->recv = cs8900_recv;
  273. /* Load MAC address from EEPROM */
  274. cs8900_get_enetaddr(dev);
  275. sprintf(dev->name, "%s-%hu", CS8900_DRIVERNAME, dev_num);
  276. eth_register(dev);
  277. return 0;
  278. }