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