Home | History | Annotate | Line # | Download | only in bfin
dv-eth_phy.c revision 1.1.1.10
      1       1.1  christos /* Ethernet Physical Receiver model.
      2       1.1  christos 
      3  1.1.1.10  christos    Copyright (C) 2010-2024 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.1.9  christos /* This must come before any other includes.  */
     22   1.1.1.9  christos #include "defs.h"
     23       1.1  christos 
     24       1.1  christos #include "sim-main.h"
     25       1.1  christos #include "devices.h"
     26       1.1  christos 
     27   1.1.1.2  christos #if defined (HAVE_LINUX_MII_H) && defined (HAVE_LINUX_TYPES_H)
     28       1.1  christos 
     29       1.1  christos /* Workaround old/broken linux headers.  */
     30   1.1.1.2  christos #include <linux/types.h>
     31       1.1  christos #include <linux/mii.h>
     32       1.1  christos 
     33       1.1  christos #define REG_PHY_SIZE 0x20
     34       1.1  christos 
     35       1.1  christos struct eth_phy
     36       1.1  christos {
     37       1.1  christos   bu32 base;
     38       1.1  christos   bu16 regs[REG_PHY_SIZE];
     39       1.1  christos };
     40       1.1  christos #define reg_base()      offsetof(struct eth_phy, regs[0])
     41       1.1  christos #define reg_offset(reg) (offsetof(struct eth_phy, reg) - reg_base())
     42       1.1  christos #define reg_idx(reg)    (reg_offset (reg) / 4)
     43       1.1  christos 
     44       1.1  christos static const char * const reg_names[] =
     45       1.1  christos {
     46       1.1  christos   [MII_BMCR       ] = "MII_BMCR",
     47       1.1  christos   [MII_BMSR       ] = "MII_BMSR",
     48       1.1  christos   [MII_PHYSID1    ] = "MII_PHYSID1",
     49       1.1  christos   [MII_PHYSID2    ] = "MII_PHYSID2",
     50       1.1  christos   [MII_ADVERTISE  ] = "MII_ADVERTISE",
     51       1.1  christos   [MII_LPA        ] = "MII_LPA",
     52       1.1  christos   [MII_EXPANSION  ] = "MII_EXPANSION",
     53       1.1  christos #ifdef MII_CTRL1000
     54       1.1  christos   [MII_CTRL1000   ] = "MII_CTRL1000",
     55       1.1  christos #endif
     56       1.1  christos #ifdef MII_STAT1000
     57       1.1  christos   [MII_STAT1000   ] = "MII_STAT1000",
     58       1.1  christos #endif
     59       1.1  christos #ifdef MII_ESTATUS
     60       1.1  christos   [MII_ESTATUS    ] = "MII_ESTATUS",
     61       1.1  christos #endif
     62       1.1  christos   [MII_DCOUNTER   ] = "MII_DCOUNTER",
     63       1.1  christos   [MII_FCSCOUNTER ] = "MII_FCSCOUNTER",
     64       1.1  christos   [MII_NWAYTEST   ] = "MII_NWAYTEST",
     65       1.1  christos   [MII_RERRCOUNTER] = "MII_RERRCOUNTER",
     66       1.1  christos   [MII_SREVISION  ] = "MII_SREVISION",
     67       1.1  christos   [MII_RESV1      ] = "MII_RESV1",
     68       1.1  christos   [MII_LBRERROR   ] = "MII_LBRERROR",
     69       1.1  christos   [MII_PHYADDR    ] = "MII_PHYADDR",
     70       1.1  christos   [MII_RESV2      ] = "MII_RESV2",
     71       1.1  christos   [MII_TPISTATUS  ] = "MII_TPISTATUS",
     72       1.1  christos   [MII_NCONFIG    ] = "MII_NCONFIG",
     73       1.1  christos };
     74       1.1  christos #define mmr_name(off) (reg_names[off] ? : "<INV>")
     75       1.1  christos #define mmr_off reg_off
     76       1.1  christos 
     77       1.1  christos static unsigned
     78       1.1  christos eth_phy_io_write_buffer (struct hw *me, const void *source,
     79       1.1  christos 			 int space, address_word addr, unsigned nr_bytes)
     80       1.1  christos {
     81       1.1  christos   struct eth_phy *phy = hw_data (me);
     82       1.1  christos   bu16 reg_off;
     83       1.1  christos   bu16 value;
     84       1.1  christos   bu16 *valuep;
     85       1.1  christos 
     86       1.1  christos   value = dv_load_2 (source);
     87       1.1  christos 
     88       1.1  christos   reg_off = addr - phy->base;
     89   1.1.1.9  christos   valuep = (void *)((uintptr_t)phy + reg_base() + reg_off);
     90       1.1  christos 
     91       1.1  christos   HW_TRACE_WRITE ();
     92       1.1  christos 
     93       1.1  christos   switch (reg_off)
     94       1.1  christos     {
     95       1.1  christos     case MII_BMCR:
     96       1.1  christos       *valuep = value;
     97       1.1  christos       break;
     98       1.1  christos     case MII_PHYSID1:
     99       1.1  christos     case MII_PHYSID2:
    100       1.1  christos       /* Discard writes to these.  */
    101       1.1  christos       break;
    102       1.1  christos     default:
    103       1.1  christos       /* XXX: Discard writes to unknown regs ?  */
    104       1.1  christos       *valuep = value;
    105       1.1  christos       break;
    106       1.1  christos     }
    107       1.1  christos 
    108       1.1  christos   return nr_bytes;
    109       1.1  christos }
    110       1.1  christos 
    111       1.1  christos static unsigned
    112       1.1  christos eth_phy_io_read_buffer (struct hw *me, void *dest,
    113       1.1  christos 			int space, address_word addr, unsigned nr_bytes)
    114       1.1  christos {
    115       1.1  christos   struct eth_phy *phy = hw_data (me);
    116       1.1  christos   bu16 reg_off;
    117       1.1  christos   bu16 *valuep;
    118       1.1  christos 
    119       1.1  christos   reg_off = addr - phy->base;
    120   1.1.1.9  christos   valuep = (void *)((uintptr_t)phy + reg_base() + reg_off);
    121       1.1  christos 
    122       1.1  christos   HW_TRACE_READ ();
    123       1.1  christos 
    124       1.1  christos   switch (reg_off)
    125       1.1  christos     {
    126       1.1  christos     case MII_BMCR:
    127       1.1  christos       dv_store_2 (dest, *valuep);
    128       1.1  christos       break;
    129       1.1  christos     case MII_BMSR:
    130       1.1  christos       /* XXX: Let people control this ?  */
    131       1.1  christos       *valuep = BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | BMSR_10HALF |
    132       1.1  christos 		BMSR_ANEGCOMPLETE | BMSR_ANEGCAPABLE | BMSR_LSTATUS;
    133       1.1  christos       dv_store_2 (dest, *valuep);
    134       1.1  christos       break;
    135       1.1  christos     case MII_LPA:
    136       1.1  christos       /* XXX: Let people control this ?  */
    137       1.1  christos       *valuep = LPA_100FULL | LPA_100HALF | LPA_10FULL | LPA_10HALF;
    138       1.1  christos       dv_store_2 (dest, *valuep);
    139       1.1  christos       break;
    140       1.1  christos     default:
    141       1.1  christos       dv_store_2 (dest, *valuep);
    142       1.1  christos       break;
    143       1.1  christos     }
    144       1.1  christos 
    145       1.1  christos   return nr_bytes;
    146       1.1  christos }
    147       1.1  christos 
    148       1.1  christos static void
    149       1.1  christos attach_eth_phy_regs (struct hw *me, struct eth_phy *phy)
    150       1.1  christos {
    151       1.1  christos   address_word attach_address;
    152       1.1  christos   int attach_space;
    153       1.1  christos   unsigned attach_size;
    154       1.1  christos   reg_property_spec reg;
    155       1.1  christos 
    156       1.1  christos   if (hw_find_property (me, "reg") == NULL)
    157       1.1  christos     hw_abort (me, "Missing \"reg\" property");
    158       1.1  christos 
    159       1.1  christos   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    160       1.1  christos     hw_abort (me, "\"reg\" property must contain three addr/size entries");
    161       1.1  christos 
    162       1.1  christos   hw_unit_address_to_attach_address (hw_parent (me),
    163       1.1  christos 				     &reg.address,
    164       1.1  christos 				     &attach_space, &attach_address, me);
    165       1.1  christos   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
    166       1.1  christos 
    167       1.1  christos   if (attach_size != REG_PHY_SIZE)
    168       1.1  christos     hw_abort (me, "\"reg\" size must be %#x", REG_PHY_SIZE);
    169       1.1  christos 
    170       1.1  christos   hw_attach_address (hw_parent (me),
    171       1.1  christos 		     0, attach_space, attach_address, attach_size, me);
    172       1.1  christos 
    173       1.1  christos   phy->base = attach_address;
    174       1.1  christos }
    175       1.1  christos 
    176       1.1  christos static void
    177       1.1  christos eth_phy_finish (struct hw *me)
    178       1.1  christos {
    179       1.1  christos   struct eth_phy *phy;
    180       1.1  christos 
    181       1.1  christos   phy = HW_ZALLOC (me, struct eth_phy);
    182       1.1  christos 
    183       1.1  christos   set_hw_data (me, phy);
    184       1.1  christos   set_hw_io_read_buffer (me, eth_phy_io_read_buffer);
    185       1.1  christos   set_hw_io_write_buffer (me, eth_phy_io_write_buffer);
    186       1.1  christos 
    187       1.1  christos   attach_eth_phy_regs (me, phy);
    188       1.1  christos 
    189       1.1  christos   /* Initialize the PHY.  */
    190       1.1  christos   phy->regs[MII_PHYSID1] = 0;    /* Unassigned Vendor */
    191       1.1  christos   phy->regs[MII_PHYSID2] = 0xAD; /* Product */
    192       1.1  christos }
    193       1.1  christos 
    194       1.1  christos #else
    195       1.1  christos 
    196       1.1  christos static void
    197       1.1  christos eth_phy_finish (struct hw *me)
    198       1.1  christos {
    199       1.1  christos   HW_TRACE ((me, "No linux/mii.h support found"));
    200       1.1  christos }
    201       1.1  christos 
    202       1.1  christos #endif
    203       1.1  christos 
    204       1.1  christos const struct hw_descriptor dv_eth_phy_descriptor[] =
    205       1.1  christos {
    206       1.1  christos   {"eth_phy", eth_phy_finish,},
    207       1.1  christos   {NULL, NULL},
    208       1.1  christos };
    209