uboot/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Marvell International Ltd. and its affiliates
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0
   5 */
   6
   7#include <common.h>
   8#include <spl.h>
   9#include <asm/io.h>
  10#include <asm/arch/cpu.h>
  11#include <asm/arch/soc.h>
  12
  13#include "ctrl_pex.h"
  14#include "sys_env_lib.h"
  15
  16int hws_pex_config(const struct serdes_map *serdes_map, u8 count)
  17{
  18        u32 pex_idx, tmp, next_busno, first_busno, temp_pex_reg,
  19            temp_reg, addr, dev_id, ctrl_mode;
  20        enum serdes_type serdes_type;
  21        u32 idx;
  22
  23        DEBUG_INIT_FULL_S("\n### hws_pex_config ###\n");
  24
  25        for (idx = 0; idx < count; idx++) {
  26                serdes_type = serdes_map[idx].serdes_type;
  27                /* configuration for PEX only */
  28                if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
  29                    (serdes_type != PEX2) && (serdes_type != PEX3))
  30                        continue;
  31
  32                if ((serdes_type != PEX0) &&
  33                    ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
  34                     (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
  35                        /* for PEX by4 - relevant for the first port only */
  36                        continue;
  37                }
  38
  39                pex_idx = serdes_type - PEX0;
  40                tmp = reg_read(PEX_CAPABILITIES_REG(pex_idx));
  41                tmp &= ~(0xf << 20);
  42                tmp |= (0x4 << 20);
  43                reg_write(PEX_CAPABILITIES_REG(pex_idx), tmp);
  44        }
  45
  46        tmp = reg_read(SOC_CTRL_REG);
  47        tmp &= ~0x03;
  48
  49        for (idx = 0; idx < count; idx++) {
  50                serdes_type = serdes_map[idx].serdes_type;
  51                if ((serdes_type != PEX0) &&
  52                    ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
  53                     (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
  54                        /* for PEX by4 - relevant for the first port only */
  55                        continue;
  56                }
  57
  58                switch (serdes_type) {
  59                case PEX0:
  60                        tmp |= 0x1 << PCIE0_ENABLE_OFFS;
  61                        break;
  62                case PEX1:
  63                        tmp |= 0x1 << PCIE1_ENABLE_OFFS;
  64                        break;
  65                case PEX2:
  66                        tmp |= 0x1 << PCIE2_ENABLE_OFFS;
  67                        break;
  68                case PEX3:
  69                        tmp |= 0x1 << PCIE3_ENABLE_OFFS;
  70                        break;
  71                default:
  72                        break;
  73                }
  74        }
  75
  76        reg_write(SOC_CTRL_REG, tmp);
  77
  78        /* Support gen1/gen2 */
  79        DEBUG_INIT_FULL_S("Support gen1/gen2\n");
  80        next_busno = 0;
  81        mdelay(150);
  82
  83        for (idx = 0; idx < count; idx++) {
  84                serdes_type = serdes_map[idx].serdes_type;
  85                DEBUG_INIT_FULL_S(" serdes_type=0x");
  86                DEBUG_INIT_FULL_D(serdes_type, 8);
  87                DEBUG_INIT_FULL_S("\n");
  88                DEBUG_INIT_FULL_S(" idx=0x");
  89                DEBUG_INIT_FULL_D(idx, 8);
  90                DEBUG_INIT_FULL_S("\n");
  91
  92                /* Configuration for PEX only */
  93                if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
  94                    (serdes_type != PEX2) && (serdes_type != PEX3))
  95                        continue;
  96
  97                if ((serdes_type != PEX0) &&
  98                    ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
  99                     (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
 100                        /* for PEX by4 - relevant for the first port only */
 101                        continue;
 102                }
 103
 104                pex_idx = serdes_type - PEX0;
 105                tmp = reg_read(PEX_DBG_STATUS_REG(pex_idx));
 106
 107                first_busno = next_busno;
 108                if ((tmp & 0x7f) != 0x7e) {
 109                        DEBUG_INIT_S("PCIe, Idx ");
 110                        DEBUG_INIT_D(pex_idx, 1);
 111                        DEBUG_INIT_S(": detected no link\n");
 112                        continue;
 113                }
 114
 115                next_busno++;
 116                temp_pex_reg = reg_read((PEX_CFG_DIRECT_ACCESS
 117                                         (pex_idx, PEX_LINK_CAPABILITY_REG)));
 118                temp_pex_reg &= 0xf;
 119                if (temp_pex_reg != 0x2)
 120                        continue;
 121
 122                temp_reg = (reg_read(PEX_CFG_DIRECT_ACCESS(
 123                                             pex_idx,
 124                                             PEX_LINK_CTRL_STAT_REG)) &
 125                            0xf0000) >> 16;
 126
 127                /* Check if the link established is GEN1 */
 128                DEBUG_INIT_FULL_S
 129                        ("Checking if the link established is gen1\n");
 130                if (temp_reg != 0x1)
 131                        continue;
 132
 133                pex_local_bus_num_set(pex_idx, first_busno);
 134                pex_local_dev_num_set(pex_idx, 1);
 135                DEBUG_INIT_FULL_S("PCIe, Idx ");
 136                DEBUG_INIT_FULL_D(pex_idx, 1);
 137
 138                DEBUG_INIT_S(":** Link is Gen1, check the EP capability\n");
 139                /* link is Gen1, check the EP capability */
 140                addr = pex_config_read(pex_idx, first_busno, 0, 0, 0x34) & 0xff;
 141                DEBUG_INIT_FULL_C("pex_config_read: return addr=0x%x", addr, 4);
 142                if (addr == 0xff) {
 143                        DEBUG_INIT_FULL_C
 144                                ("pex_config_read: return 0xff -->PCIe (%d): Detected No Link.",
 145                                 pex_idx, 1);
 146                        continue;
 147                }
 148
 149                while ((pex_config_read(pex_idx, first_busno, 0, 0, addr)
 150                        & 0xff) != 0x10) {
 151                        addr = (pex_config_read(pex_idx, first_busno, 0,
 152                                                0, addr) & 0xff00) >> 8;
 153                }
 154
 155                /* Check for Gen2 and above */
 156                if ((pex_config_read(pex_idx, first_busno, 0, 0,
 157                                     addr + 0xc) & 0xf) < 0x2) {
 158                        DEBUG_INIT_S("PCIe, Idx ");
 159                        DEBUG_INIT_D(pex_idx, 1);
 160                        DEBUG_INIT_S(": remains Gen1\n");
 161                        continue;
 162                }
 163
 164                tmp = reg_read(PEX_LINK_CTRL_STATUS2_REG(pex_idx));
 165                DEBUG_RD_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
 166                tmp &= ~(BIT(0) | BIT(1));
 167                tmp |= BIT(1);
 168                tmp |= BIT(6);  /* Select Deemphasize (-3.5d_b) */
 169                reg_write(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
 170                DEBUG_WR_REG(PEX_LINK_CTRL_STATUS2_REG(pex_idx), tmp);
 171
 172                tmp = reg_read(PEX_CTRL_REG(pex_idx));
 173                DEBUG_RD_REG(PEX_CTRL_REG(pex_idx), tmp);
 174                tmp |= BIT(10);
 175                reg_write(PEX_CTRL_REG(pex_idx), tmp);
 176                DEBUG_WR_REG(PEX_CTRL_REG(pex_idx), tmp);
 177
 178                /*
 179                 * We need to wait 10ms before reading the PEX_DBG_STATUS_REG
 180                 * in order not to read the status of the former state
 181                 */
 182                mdelay(10);
 183
 184                DEBUG_INIT_S("PCIe, Idx ");
 185                DEBUG_INIT_D(pex_idx, 1);
 186                DEBUG_INIT_S
 187                        (": Link upgraded to Gen2 based on client capabilities\n");
 188        }
 189
 190        /* Update pex DEVICE ID */
 191        ctrl_mode = sys_env_model_get();
 192
 193        for (idx = 0; idx < count; idx++) {
 194                serdes_type = serdes_map[idx].serdes_type;
 195                /* configuration for PEX only */
 196                if ((serdes_type != PEX0) && (serdes_type != PEX1) &&
 197                    (serdes_type != PEX2) && (serdes_type != PEX3))
 198                        continue;
 199
 200                if ((serdes_type != PEX0) &&
 201                    ((serdes_map[idx].serdes_mode == PEX_ROOT_COMPLEX_X4) ||
 202                     (serdes_map[idx].serdes_mode == PEX_END_POINT_X4))) {
 203                        /* for PEX by4 - relevant for the first port only */
 204                        continue;
 205                }
 206
 207                pex_idx = serdes_type - PEX0;
 208                dev_id = reg_read(PEX_CFG_DIRECT_ACCESS
 209                                  (pex_idx, PEX_DEVICE_AND_VENDOR_ID));
 210                dev_id &= 0xffff;
 211                dev_id |= ((ctrl_mode << 16) & 0xffff0000);
 212                reg_write(PEX_CFG_DIRECT_ACCESS
 213                          (pex_idx, PEX_DEVICE_AND_VENDOR_ID), dev_id);
 214        }
 215        DEBUG_INIT_FULL_C("Update PEX Device ID ", ctrl_mode, 4);
 216
 217        return MV_OK;
 218}
 219
 220int pex_local_bus_num_set(u32 pex_if, u32 bus_num)
 221{
 222        u32 pex_status;
 223
 224        DEBUG_INIT_FULL_S("\n### pex_local_bus_num_set ###\n");
 225
 226        if (bus_num >= MAX_PEX_BUSSES) {
 227                DEBUG_INIT_C("pex_local_bus_num_set: Illegal bus number %d\n",
 228                             bus_num, 4);
 229                return MV_BAD_PARAM;
 230        }
 231
 232        pex_status = reg_read(PEX_STATUS_REG(pex_if));
 233        pex_status &= ~PXSR_PEX_BUS_NUM_MASK;
 234        pex_status |=
 235            (bus_num << PXSR_PEX_BUS_NUM_OFFS) & PXSR_PEX_BUS_NUM_MASK;
 236        reg_write(PEX_STATUS_REG(pex_if), pex_status);
 237
 238        return MV_OK;
 239}
 240
 241int pex_local_dev_num_set(u32 pex_if, u32 dev_num)
 242{
 243        u32 pex_status;
 244
 245        DEBUG_INIT_FULL_S("\n### pex_local_dev_num_set ###\n");
 246
 247        pex_status = reg_read(PEX_STATUS_REG(pex_if));
 248        pex_status &= ~PXSR_PEX_DEV_NUM_MASK;
 249        pex_status |=
 250            (dev_num << PXSR_PEX_DEV_NUM_OFFS) & PXSR_PEX_DEV_NUM_MASK;
 251        reg_write(PEX_STATUS_REG(pex_if), pex_status);
 252
 253        return MV_OK;
 254}
 255
 256/*
 257 * pex_config_read - Read from configuration space
 258 *
 259 * DESCRIPTION:
 260 *       This function performs a 32 bit read from PEX configuration space.
 261 *       It supports both type 0 and type 1 of Configuration Transactions
 262 *       (local and over bridge). In order to read from local bus segment, use
 263 *       bus number retrieved from pex_local_bus_num_get(). Other bus numbers
 264 *       will result configuration transaction of type 1 (over bridge).
 265 *
 266 * INPUT:
 267 *       pex_if   - PEX interface number.
 268 *       bus      - PEX segment bus number.
 269 *       dev      - PEX device number.
 270 *       func     - Function number.
 271 *       reg_offs - Register offset.
 272 *
 273 * OUTPUT:
 274 *       None.
 275 *
 276 * RETURN:
 277 *       32bit register data, 0xffffffff on error
 278 */
 279u32 pex_config_read(u32 pex_if, u32 bus, u32 dev, u32 func, u32 reg_off)
 280{
 281        u32 pex_data = 0;
 282        u32 local_dev, local_bus;
 283        u32 pex_status;
 284
 285        pex_status = reg_read(PEX_STATUS_REG(pex_if));
 286        local_dev =
 287            ((pex_status & PXSR_PEX_DEV_NUM_MASK) >> PXSR_PEX_DEV_NUM_OFFS);
 288        local_bus =
 289            ((pex_status & PXSR_PEX_BUS_NUM_MASK) >> PXSR_PEX_BUS_NUM_OFFS);
 290
 291        /*
 292         * In PCI Express we have only one device number
 293         * and this number is the first number we encounter
 294         * else that the local_dev
 295         * spec pex define return on config read/write on any device
 296         */
 297        if (bus == local_bus) {
 298                if (local_dev == 0) {
 299                        /*
 300                         * if local dev is 0 then the first number we encounter
 301                         * after 0 is 1
 302                         */
 303                        if ((dev != 1) && (dev != local_dev))
 304                                return MV_ERROR;
 305                } else {
 306                        /*
 307                         * if local dev is not 0 then the first number we
 308                         * encounter is 0
 309                         */
 310                        if ((dev != 0) && (dev != local_dev))
 311                                return MV_ERROR;
 312                }
 313        }
 314
 315        /* Creating PEX address to be passed */
 316        pex_data = (bus << PXCAR_BUS_NUM_OFFS);
 317        pex_data |= (dev << PXCAR_DEVICE_NUM_OFFS);
 318        pex_data |= (func << PXCAR_FUNC_NUM_OFFS);
 319        /* Legacy register space */
 320        pex_data |= (reg_off & PXCAR_REG_NUM_MASK);
 321        /* Extended register space */
 322        pex_data |= (((reg_off & PXCAR_REAL_EXT_REG_NUM_MASK) >>
 323                      PXCAR_REAL_EXT_REG_NUM_OFFS) << PXCAR_EXT_REG_NUM_OFFS);
 324        pex_data |= PXCAR_CONFIG_EN;
 325
 326        /* Write the address to the PEX configuration address register */
 327        reg_write(PEX_CFG_ADDR_REG(pex_if), pex_data);
 328
 329        /*
 330         * In order to let the PEX controller absorbed the address
 331         * of the read transaction we perform a validity check that
 332         * the address was written
 333         */
 334        if (pex_data != reg_read(PEX_CFG_ADDR_REG(pex_if)))
 335                return MV_ERROR;
 336
 337        /* Cleaning Master Abort */
 338        reg_bit_set(PEX_CFG_DIRECT_ACCESS(pex_if, PEX_STATUS_AND_COMMAND),
 339                    PXSAC_MABORT);
 340        /* Read the Data returned in the PEX Data register */
 341        pex_data = reg_read(PEX_CFG_DATA_REG(pex_if));
 342
 343        DEBUG_INIT_FULL_C(" --> ", pex_data, 4);
 344
 345        return pex_data;
 346}
 347