uboot/board/gdsys/common/ihs_mdio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2014
   4 * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
   5 */
   6
   7#include <common.h>
   8
   9#include <miiphy.h>
  10#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  11#include <gdsys_fpga.h>
  12#else
  13#include <fdtdec.h>
  14#include <dm.h>
  15#include <regmap.h>
  16#endif
  17
  18#include "ihs_mdio.h"
  19
  20#ifndef CONFIG_GDSYS_LEGACY_DRIVERS
  21enum {
  22        REG_MDIO_CONTROL = 0x0,
  23        REG_MDIO_ADDR_DATA = 0x2,
  24        REG_MDIO_RX_DATA = 0x4,
  25};
  26
  27static inline u16 read_reg(struct udevice *fpga, uint base, uint addr)
  28{
  29        struct regmap *map;
  30        u8 *ptr;
  31
  32        regmap_init_mem(dev_ofnode(fpga), &map);
  33        ptr = regmap_get_range(map, 0);
  34
  35        return in_le16((u16 *)(ptr + base + addr));
  36}
  37
  38static inline void write_reg(struct udevice *fpga, uint base, uint addr,
  39                             u16 val)
  40{
  41        struct regmap *map;
  42        u8 *ptr;
  43
  44        regmap_init_mem(dev_ofnode(fpga), &map);
  45        ptr = regmap_get_range(map, 0);
  46
  47        out_le16((u16 *)(ptr + base + addr), val);
  48}
  49#endif
  50
  51static inline u16 read_control(struct ihs_mdio_info *info)
  52{
  53        u16 val;
  54#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  55        FPGA_GET_REG(info->fpga, mdio.control, &val);
  56#else
  57        val = read_reg(info->fpga, info->base, REG_MDIO_CONTROL);
  58#endif
  59        return val;
  60}
  61
  62static inline void write_control(struct ihs_mdio_info *info, u16 val)
  63{
  64#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  65        FPGA_SET_REG(info->fpga, mdio.control, val);
  66#else
  67        write_reg(info->fpga, info->base, REG_MDIO_CONTROL, val);
  68#endif
  69}
  70
  71static inline void write_addr_data(struct ihs_mdio_info *info, u16 val)
  72{
  73#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  74        FPGA_SET_REG(info->fpga, mdio.address_data, val);
  75#else
  76        write_reg(info->fpga, info->base, REG_MDIO_ADDR_DATA, val);
  77#endif
  78}
  79
  80static inline u16 read_rx_data(struct ihs_mdio_info *info)
  81{
  82        u16 val;
  83#ifdef CONFIG_GDSYS_LEGACY_DRIVERS
  84        FPGA_GET_REG(info->fpga, mdio.rx_data, &val);
  85#else
  86        val = read_reg(info->fpga, info->base, REG_MDIO_RX_DATA);
  87#endif
  88        return val;
  89}
  90
  91static int ihs_mdio_idle(struct mii_dev *bus)
  92{
  93        struct ihs_mdio_info *info = bus->priv;
  94        u16 val;
  95        unsigned int ctr = 0;
  96
  97        do {
  98                val = read_control(info);
  99                udelay(100);
 100                if (ctr++ > 10)
 101                        return -1;
 102        } while (!(val & (1 << 12)));
 103
 104        return 0;
 105}
 106
 107static int ihs_mdio_reset(struct mii_dev *bus)
 108{
 109        ihs_mdio_idle(bus);
 110
 111        return 0;
 112}
 113
 114static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr,
 115                         int regnum)
 116{
 117        struct ihs_mdio_info *info = bus->priv;
 118        u16 val;
 119
 120        ihs_mdio_idle(bus);
 121
 122        write_control(info,
 123                      ((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10));
 124
 125        /* wait for rx data available */
 126        udelay(100);
 127
 128        val = read_rx_data(info);
 129
 130        return val;
 131}
 132
 133static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
 134                          int regnum, u16 value)
 135{
 136        struct ihs_mdio_info *info = bus->priv;
 137
 138        ihs_mdio_idle(bus);
 139
 140        write_addr_data(info, value);
 141        write_control(info, ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10));
 142
 143        return 0;
 144}
 145
 146int ihs_mdio_init(struct ihs_mdio_info *info)
 147{
 148        struct mii_dev *bus = mdio_alloc();
 149
 150        if (!bus) {
 151                printf("Failed to allocate FSL MDIO bus\n");
 152                return -1;
 153        }
 154
 155        bus->read = ihs_mdio_read;
 156        bus->write = ihs_mdio_write;
 157        bus->reset = ihs_mdio_reset;
 158        strcpy(bus->name, info->name);
 159
 160        bus->priv = info;
 161
 162        return mdio_register(bus);
 163}
 164