Home | History | Annotate | Line # | Download | only in bfin
dv-eth_phy.c revision 1.1.1.4.2.1
      1          1.1  christos /* Ethernet Physical Receiver model.
      2          1.1  christos 
      3  1.1.1.4.2.1  pgoyette    Copyright (C) 2010-2016 Free Software Foundation, Inc.
      4          1.1  christos    Contributed by Analog Devices, Inc.
      5          1.1  christos 
      6          1.1  christos    This file is part of simulators.
      7          1.1  christos 
      8          1.1  christos    This program is free software; you can redistribute it and/or modify
      9          1.1  christos    it under the terms of the GNU General Public License as published by
     10          1.1  christos    the Free Software Foundation; either version 3 of the License, or
     11          1.1  christos    (at your option) any later version.
     12          1.1  christos 
     13          1.1  christos    This program is distributed in the hope that it will be useful,
     14          1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15          1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16          1.1  christos    GNU General Public License for more details.
     17          1.1  christos 
     18          1.1  christos    You should have received a copy of the GNU General Public License
     19          1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     20          1.1  christos 
     21          1.1  christos #include "config.h"
     22          1.1  christos 
     23          1.1  christos #include "sim-main.h"
     24          1.1  christos #include "devices.h"
     25          1.1  christos 
     26      1.1.1.2  christos #if defined (HAVE_LINUX_MII_H) && defined (HAVE_LINUX_TYPES_H)
     27          1.1  christos 
     28          1.1  christos /* Workaround old/broken linux headers.  */
     29      1.1.1.2  christos #include <linux/types.h>
     30          1.1  christos #include <linux/mii.h>
     31          1.1  christos 
     32          1.1  christos #define REG_PHY_SIZE 0x20
     33          1.1  christos 
     34          1.1  christos struct eth_phy
     35          1.1  christos {
     36          1.1  christos   bu32 base;
     37          1.1  christos   bu16 regs[REG_PHY_SIZE];
     38          1.1  christos };
     39          1.1  christos #define reg_base()      offsetof(struct eth_phy, regs[0])
     40          1.1  christos #define reg_offset(reg) (offsetof(struct eth_phy, reg) - reg_base())
     41          1.1  christos #define reg_idx(reg)    (reg_offset (reg) / 4)
     42          1.1  christos 
     43          1.1  christos static const char * const reg_names[] =
     44          1.1  christos {
     45          1.1  christos   [MII_BMCR       ] = "MII_BMCR",
     46          1.1  christos   [MII_BMSR       ] = "MII_BMSR",
     47          1.1  christos   [MII_PHYSID1    ] = "MII_PHYSID1",
     48          1.1  christos   [MII_PHYSID2    ] = "MII_PHYSID2",
     49          1.1  christos   [MII_ADVERTISE  ] = "MII_ADVERTISE",
     50          1.1  christos   [MII_LPA        ] = "MII_LPA",
     51          1.1  christos   [MII_EXPANSION  ] = "MII_EXPANSION",
     52          1.1  christos #ifdef MII_CTRL1000
     53          1.1  christos   [MII_CTRL1000   ] = "MII_CTRL1000",
     54          1.1  christos #endif
     55          1.1  christos #ifdef MII_STAT1000
     56          1.1  christos   [MII_STAT1000   ] = "MII_STAT1000",
     57          1.1  christos #endif
     58          1.1  christos #ifdef MII_ESTATUS
     59          1.1  christos   [MII_ESTATUS    ] = "MII_ESTATUS",
     60          1.1  christos #endif
     61          1.1  christos   [MII_DCOUNTER   ] = "MII_DCOUNTER",
     62          1.1  christos   [MII_FCSCOUNTER ] = "MII_FCSCOUNTER",
     63          1.1  christos   [MII_NWAYTEST   ] = "MII_NWAYTEST",
     64          1.1  christos   [MII_RERRCOUNTER] = "MII_RERRCOUNTER",
     65          1.1  christos   [MII_SREVISION  ] = "MII_SREVISION",
     66          1.1  christos   [MII_RESV1      ] = "MII_RESV1",
     67          1.1  christos   [MII_LBRERROR   ] = "MII_LBRERROR",
     68          1.1  christos   [MII_PHYADDR    ] = "MII_PHYADDR",
     69          1.1  christos   [MII_RESV2      ] = "MII_RESV2",
     70          1.1  christos   [MII_TPISTATUS  ] = "MII_TPISTATUS",
     71          1.1  christos   [MII_NCONFIG    ] = "MII_NCONFIG",
     72          1.1  christos };
     73          1.1  christos #define mmr_name(off) (reg_names[off] ? : "<INV>")
     74          1.1  christos #define mmr_off reg_off
     75          1.1  christos 
     76          1.1  christos static unsigned
     77          1.1  christos eth_phy_io_write_buffer (struct hw *me, const void *source,
     78          1.1  christos 			 int space, address_word addr, unsigned nr_bytes)
     79          1.1  christos {
     80          1.1  christos   struct eth_phy *phy = hw_data (me);
     81          1.1  christos   bu16 reg_off;
     82          1.1  christos   bu16 value;
     83          1.1  christos   bu16 *valuep;
     84          1.1  christos 
     85          1.1  christos   value = dv_load_2 (source);
     86          1.1  christos 
     87          1.1  christos   reg_off = addr - phy->base;
     88          1.1  christos   valuep = (void *)((unsigned long)phy + reg_base() + reg_off);
     89          1.1  christos 
     90          1.1  christos   HW_TRACE_WRITE ();
     91          1.1  christos 
     92          1.1  christos   switch (reg_off)
     93          1.1  christos     {
     94          1.1  christos     case MII_BMCR:
     95          1.1  christos       *valuep = value;
     96          1.1  christos       break;
     97          1.1  christos     case MII_PHYSID1:
     98          1.1  christos     case MII_PHYSID2:
     99          1.1  christos       /* Discard writes to these.  */
    100          1.1  christos       break;
    101          1.1  christos     default:
    102          1.1  christos       /* XXX: Discard writes to unknown regs ?  */
    103          1.1  christos       *valuep = value;
    104          1.1  christos       break;
    105          1.1  christos     }
    106          1.1  christos 
    107          1.1  christos   return nr_bytes;
    108          1.1  christos }
    109          1.1  christos 
    110          1.1  christos static unsigned
    111          1.1  christos eth_phy_io_read_buffer (struct hw *me, void *dest,
    112          1.1  christos 			int space, address_word addr, unsigned nr_bytes)
    113          1.1  christos {
    114          1.1  christos   struct eth_phy *phy = hw_data (me);
    115          1.1  christos   bu16 reg_off;
    116          1.1  christos   bu16 *valuep;
    117          1.1  christos 
    118          1.1  christos   reg_off = addr - phy->base;
    119          1.1  christos   valuep = (void *)((unsigned long)phy + reg_base() + reg_off);
    120          1.1  christos 
    121          1.1  christos   HW_TRACE_READ ();
    122          1.1  christos 
    123          1.1  christos   switch (reg_off)
    124          1.1  christos     {
    125          1.1  christos     case MII_BMCR:
    126          1.1  christos       dv_store_2 (dest, *valuep);
    127          1.1  christos       break;
    128          1.1  christos     case MII_BMSR:
    129          1.1  christos       /* XXX: Let people control this ?  */
    130          1.1  christos       *valuep = BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF |
    131          1.1  christos 		BMSR_ANEGCOMPLETE | BMSR_ANEGCAPABLE | BMSR_LSTATUS;
    132          1.1  christos       dv_store_2 (dest, *valuep);
    133          1.1  christos       break;
    134          1.1  christos     case MII_LPA:
    135          1.1  christos       /* XXX: Let people control this ?  */
    136          1.1  christos       *valuep = LPA_100FULL | LPA_100HALF | LPA_10FULL | LPA_10HALF;
    137          1.1  christos       dv_store_2 (dest, *valuep);
    138          1.1  christos       break;
    139          1.1  christos     default:
    140          1.1  christos       dv_store_2 (dest, *valuep);
    141          1.1  christos       break;
    142          1.1  christos     }
    143          1.1  christos 
    144          1.1  christos   return nr_bytes;
    145          1.1  christos }
    146          1.1  christos 
    147          1.1  christos static void
    148          1.1  christos attach_eth_phy_regs (struct hw *me, struct eth_phy *phy)
    149          1.1  christos {
    150          1.1  christos   address_word attach_address;
    151          1.1  christos   int attach_space;
    152          1.1  christos   unsigned attach_size;
    153          1.1  christos   reg_property_spec reg;
    154          1.1  christos 
    155          1.1  christos   if (hw_find_property (me, "reg") == NULL)
    156          1.1  christos     hw_abort (me, "Missing \"reg\" property");
    157          1.1  christos 
    158          1.1  christos   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    159          1.1  christos     hw_abort (me, "\"reg\" property must contain three addr/size entries");
    160          1.1  christos 
    161          1.1  christos   hw_unit_address_to_attach_address (hw_parent (me),
    162          1.1  christos 				     &reg.address,
    163          1.1  christos 				     &attach_space, &attach_address, me);
    164          1.1  christos   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
    165          1.1  christos 
    166          1.1  christos   if (attach_size != REG_PHY_SIZE)
    167          1.1  christos     hw_abort (me, "\"reg\" size must be %#x", REG_PHY_SIZE);
    168          1.1  christos 
    169          1.1  christos   hw_attach_address (hw_parent (me),
    170          1.1  christos 		     0, attach_space, attach_address, attach_size, me);
    171          1.1  christos 
    172          1.1  christos   phy->base = attach_address;
    173          1.1  christos }
    174          1.1  christos 
    175          1.1  christos static void
    176          1.1  christos eth_phy_finish (struct hw *me)
    177          1.1  christos {
    178          1.1  christos   struct eth_phy *phy;
    179          1.1  christos 
    180          1.1  christos   phy = HW_ZALLOC (me, struct eth_phy);
    181          1.1  christos 
    182          1.1  christos   set_hw_data (me, phy);
    183          1.1  christos   set_hw_io_read_buffer (me, eth_phy_io_read_buffer);
    184          1.1  christos   set_hw_io_write_buffer (me, eth_phy_io_write_buffer);
    185          1.1  christos 
    186          1.1  christos   attach_eth_phy_regs (me, phy);
    187          1.1  christos 
    188          1.1  christos   /* Initialize the PHY.  */
    189          1.1  christos   phy->regs[MII_PHYSID1] = 0;    /* Unassigned Vendor */
    190          1.1  christos   phy->regs[MII_PHYSID2] = 0xAD; /* Product */
    191          1.1  christos }
    192          1.1  christos 
    193          1.1  christos #else
    194          1.1  christos 
    195          1.1  christos static void
    196          1.1  christos eth_phy_finish (struct hw *me)
    197          1.1  christos {
    198          1.1  christos   HW_TRACE ((me, "No linux/mii.h support found"));
    199          1.1  christos }
    200          1.1  christos 
    201          1.1  christos #endif
    202          1.1  christos 
    203          1.1  christos const struct hw_descriptor dv_eth_phy_descriptor[] =
    204          1.1  christos {
    205          1.1  christos   {"eth_phy", eth_phy_finish,},
    206          1.1  christos   {NULL, NULL},
    207          1.1  christos };
    208