linux/arch/mn10300/unit-asb2364/include/unit/smsc911x.h
<<
>>
Prefs
   1/* Support for the SMSC911x NIC
   2 *
   3 * Copyright (C) 2006 Matsushita Electric Industrial Co., Ltd.
   4 * All Rights Reserved.
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11#ifndef _ASM_UNIT_SMSC911X_H
  12#define _ASM_UNIT_SMSC911X_H
  13
  14#include <linux/netdevice.h>
  15#include <proc/irq.h>
  16#include <unit/fpga-regs.h>
  17
  18#define MN10300_USE_EXT_EEPROM
  19
  20
  21#define SMSC911X_BASE           0xA8000000UL
  22#define SMSC911X_BASE_END       0xA8000100UL
  23#define SMSC911X_IRQ            FPGA_LAN_IRQ
  24
  25/*
  26 * Allow the FPGA to be initialised by the SMSC911x driver
  27 */
  28#undef SMSC_INITIALIZE
  29#define SMSC_INITIALIZE()                                       \
  30do {                                                            \
  31        /* release reset */                                     \
  32        ASB2364_FPGA_REG_RESET_LAN = 0x0001;                    \
  33        SyncExBus();                                            \
  34} while (0)
  35
  36#ifdef MN10300_USE_EXT_EEPROM
  37#include <linux/delay.h>
  38#include <unit/clock.h>
  39
  40#define EEPROM_ADDRESS  0xA0
  41#define MAC_OFFSET      0x0008
  42#define USE_IIC_CH      0       /* 0 or 1 */
  43#define IIC_OFFSET      (0x80000 * USE_IIC_CH)
  44#define IIC_DTRM        __SYSREG(0xd8400000 + IIC_OFFSET, u32)
  45#define IIC_DREC        __SYSREG(0xd8400004 + IIC_OFFSET, u32)
  46#define IIC_MYADD       __SYSREG(0xd8400008 + IIC_OFFSET, u32)
  47#define IIC_CLK         __SYSREG(0xd840000c + IIC_OFFSET, u32)
  48#define IIC_BRST        __SYSREG(0xd8400010 + IIC_OFFSET, u32)
  49#define IIC_HOLD        __SYSREG(0xd8400014 + IIC_OFFSET, u32)
  50#define IIC_BSTS        __SYSREG(0xd8400018 + IIC_OFFSET, u32)
  51#define IIC_ICR         __SYSREG(0xd4000080 + 4 * USE_IIC_CH, u16)
  52
  53#define IIC_CLK_PLS     ((unsigned short)(MN10300_IOCLK / 100000 - 1))
  54#define IIC_CLK_LOW     ((unsigned short)(IIC_CLK_PLS / 2))
  55
  56#define SYS_IIC_DTRM_Bit_STA    ((unsigned short)0x0400)
  57#define SYS_IIC_DTRM_Bit_STO    ((unsigned short)0x0200)
  58#define SYS_IIC_DTRM_Bit_ACK    ((unsigned short)0x0100)
  59#define SYS_IIC_DTRM_Bit_DATA   ((unsigned short)0x00FF)
  60
  61static inline void POLL_INT_REQ(volatile u16 *icr)
  62{
  63        unsigned long flags;
  64        u16 tmp;
  65
  66        while (!(*icr & GxICR_REQUEST))
  67                ;
  68        flags = arch_local_cli_save();
  69        tmp = *icr;
  70        *icr = (tmp & GxICR_LEVEL) | GxICR_DETECT;
  71        tmp = *icr;
  72        arch_local_irq_restore(flags);
  73}
  74
  75/*
  76 * Implement the SMSC911x hook for MAC address retrieval
  77 */
  78#undef smsc_get_mac
  79static inline int smsc_get_mac(struct net_device *dev)
  80{
  81        unsigned char *mac_buf = dev->dev_addr;
  82        int i;
  83        unsigned short value;
  84        unsigned int data;
  85        int mac_length = 6;
  86        int check;
  87        u16 orig_gicr, tmp;
  88        unsigned long flags;
  89
  90        /* save original GnICR and clear GnICR.IE */
  91        flags = arch_local_cli_save();
  92        orig_gicr = IIC_ICR;
  93        IIC_ICR = orig_gicr & GxICR_LEVEL;
  94        tmp = IIC_ICR;
  95        arch_local_irq_restore(flags);
  96
  97        IIC_MYADD = 0x00000008;
  98        IIC_CLK = (IIC_CLK_LOW << 16) + (IIC_CLK_PLS);
  99        /* bus hung recovery */
 100
 101        while (1) {
 102                check = 0;
 103                for (i = 0; i < 3; i++) {
 104                        if ((IIC_BSTS & 0x00000003) == 0x00000003)
 105                                check++;
 106                        udelay(3);
 107                }
 108
 109                if (check == 3) {
 110                        IIC_BRST = 0x00000003;
 111                        break;
 112                } else {
 113                        for (i = 0; i < 3; i++) {
 114                                IIC_BRST = 0x00000002;
 115                                udelay(8);
 116                                IIC_BRST = 0x00000003;
 117                                udelay(8);
 118                        }
 119                }
 120        }
 121
 122        IIC_BRST = 0x00000002;
 123        IIC_BRST = 0x00000003;
 124
 125        value   =  SYS_IIC_DTRM_Bit_STA | SYS_IIC_DTRM_Bit_ACK;
 126        value   |= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
 127                    (unsigned short)0x0000);
 128        IIC_DTRM = value;
 129        POLL_INT_REQ(&IIC_ICR);
 130
 131        /** send offset of MAC address in EEPROM **/
 132        IIC_DTRM = (unsigned char)((MAC_OFFSET & 0xFF00) >> 8);
 133        POLL_INT_REQ(&IIC_ICR);
 134
 135        IIC_DTRM = (unsigned char)(MAC_OFFSET & 0x00FF);
 136        POLL_INT_REQ(&IIC_ICR);
 137
 138        udelay(1000);
 139
 140        value   =  SYS_IIC_DTRM_Bit_STA;
 141        value   |= (((unsigned short)EEPROM_ADDRESS & SYS_IIC_DTRM_Bit_DATA) |
 142                    (unsigned short)0x0001);
 143        IIC_DTRM = value;
 144        POLL_INT_REQ(&IIC_ICR);
 145
 146        IIC_DTRM = 0x00000000;
 147        while (mac_length > 0) {
 148                POLL_INT_REQ(&IIC_ICR);
 149
 150                data = IIC_DREC;
 151                mac_length--;
 152                if (mac_length == 0)
 153                        value = 0x00000300;     /* stop IIC bus */
 154                else if (mac_length == 1)
 155                        value = 0x00000100;     /* no ack */
 156                else
 157                        value = 0x00000000;     /* ack */
 158                IIC_DTRM = value;
 159                *mac_buf++ = (unsigned char)(data & 0xff);
 160        }
 161
 162        /* restore GnICR.LV and GnICR.IE */
 163        flags = arch_local_cli_save();
 164        IIC_ICR = (orig_gicr & (GxICR_LEVEL | GxICR_ENABLE));
 165        tmp = IIC_ICR;
 166        arch_local_irq_restore(flags);
 167
 168        return 0;
 169}
 170#endif /* MN10300_USE_EXT_EEPROM */
 171#endif /* _ASM_UNIT_SMSC911X_H */
 172