uboot/board/keymile/km_arm/fpga_config.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2012
   3 * Valentin Lontgchamp, Keymile AG, valentin.longchamp@keymile.com
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <i2c.h>
  10#include <linux/errno.h>
  11
  12/* GPIO Pin from kirkwood connected to PROGRAM_B pin of the xilinx FPGA */
  13#define KM_XLX_PROGRAM_B_PIN    39
  14
  15#define BOCO_ADDR       0x10
  16
  17#define ID_REG          0x00
  18#define BOCO2_ID        0x5b
  19
  20static int check_boco2(void)
  21{
  22        int ret;
  23        u8 id;
  24
  25        ret = i2c_read(BOCO_ADDR, ID_REG, 1, &id, 1);
  26        if (ret) {
  27                printf("%s: error reading the BOCO id !!\n", __func__);
  28                return ret;
  29        }
  30
  31        return (id == BOCO2_ID);
  32}
  33
  34static int boco_clear_bits(u8 reg, u8 flags)
  35{
  36        int ret;
  37        u8 regval;
  38
  39        /* give access to the EEPROM from FPGA */
  40        ret = i2c_read(BOCO_ADDR, reg, 1, &regval, 1);
  41        if (ret) {
  42                printf("%s: error reading the BOCO @%#x !!\n",
  43                        __func__, reg);
  44                return ret;
  45        }
  46        regval &= ~flags;
  47        ret = i2c_write(BOCO_ADDR, reg, 1, &regval, 1);
  48        if (ret) {
  49                printf("%s: error writing the BOCO @%#x !!\n",
  50                        __func__, reg);
  51                return ret;
  52        }
  53
  54        return 0;
  55}
  56
  57static int boco_set_bits(u8 reg, u8 flags)
  58{
  59        int ret;
  60        u8 regval;
  61
  62        /* give access to the EEPROM from FPGA */
  63        ret = i2c_read(BOCO_ADDR, reg, 1, &regval, 1);
  64        if (ret) {
  65                printf("%s: error reading the BOCO @%#x !!\n",
  66                        __func__, reg);
  67                return ret;
  68        }
  69        regval |= flags;
  70        ret = i2c_write(BOCO_ADDR, reg, 1, &regval, 1);
  71        if (ret) {
  72                printf("%s: error writing the BOCO @%#x !!\n",
  73                        __func__, reg);
  74                return ret;
  75        }
  76
  77        return 0;
  78}
  79
  80#define SPI_REG         0x06
  81#define CFG_EEPROM      0x02
  82#define FPGA_PROG       0x04
  83#define FPGA_INIT_B     0x10
  84#define FPGA_DONE       0x20
  85
  86static int fpga_done(void)
  87{
  88        int ret = 0;
  89        u8 regval;
  90
  91        /* this is only supported with the boco2 design */
  92        if (!check_boco2())
  93                return 0;
  94
  95        ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &regval, 1);
  96        if (ret) {
  97                printf("%s: error reading the BOCO @%#x !!\n",
  98                        __func__, SPI_REG);
  99                return 0;
 100        }
 101
 102        return regval & FPGA_DONE ? 1 : 0;
 103}
 104
 105int skip;
 106
 107int trigger_fpga_config(void)
 108{
 109        int ret = 0;
 110
 111        /* if the FPGA is already configured, we do not want to
 112         * reconfigure it */
 113        skip = 0;
 114        if (fpga_done()) {
 115                printf("PCIe FPGA config: skipped\n");
 116                skip = 1;
 117                return 0;
 118        }
 119
 120        if (check_boco2()) {
 121                /* we have a BOCO2, this has to be triggered here */
 122
 123                /* make sure the FPGA_can access the EEPROM */
 124                ret = boco_clear_bits(SPI_REG, CFG_EEPROM);
 125                if (ret)
 126                        return ret;
 127
 128                /* trigger the config start */
 129                ret = boco_clear_bits(SPI_REG, FPGA_PROG | FPGA_INIT_B);
 130                if (ret)
 131                        return ret;
 132
 133                /* small delay for the pulse */
 134                udelay(10);
 135
 136                /* up signal for pulse end */
 137                ret = boco_set_bits(SPI_REG, FPGA_PROG);
 138                if (ret)
 139                        return ret;
 140
 141                /* finally, raise INIT_B to remove the config delay */
 142                ret = boco_set_bits(SPI_REG, FPGA_INIT_B);
 143                if (ret)
 144                        return ret;
 145
 146        } else {
 147                /* we do it the old way, with the gpio pin */
 148                kw_gpio_set_valid(KM_XLX_PROGRAM_B_PIN, 1);
 149                kw_gpio_direction_output(KM_XLX_PROGRAM_B_PIN, 0);
 150                /* small delay for the pulse */
 151                udelay(10);
 152                kw_gpio_direction_input(KM_XLX_PROGRAM_B_PIN);
 153        }
 154
 155        return 0;
 156}
 157
 158int wait_for_fpga_config(void)
 159{
 160        int ret = 0;
 161        u8 spictrl;
 162        u32 timeout = 20000;
 163
 164        if (skip)
 165                return 0;
 166
 167        if (!check_boco2()) {
 168                /* we do not have BOCO2, this is not really used */
 169                return 0;
 170        }
 171
 172        printf("PCIe FPGA config:");
 173        do {
 174                ret = i2c_read(BOCO_ADDR, SPI_REG, 1, &spictrl, 1);
 175                if (ret) {
 176                        printf("%s: error reading the BOCO spictrl !!\n",
 177                                __func__);
 178                        return ret;
 179                }
 180                if (timeout-- == 0) {
 181                        printf(" FPGA_DONE timeout\n");
 182                        return -EFAULT;
 183                }
 184                udelay(10);
 185        } while (!(spictrl & FPGA_DONE));
 186
 187        printf(" done\n");
 188
 189        return 0;
 190}
 191
 192#if defined(KM_PCIE_RESET_MPP7)
 193
 194#define KM_PEX_RST_GPIO_PIN     7
 195int fpga_reset(void)
 196{
 197        if (!check_boco2()) {
 198                /* we do not have BOCO2, this is not really used */
 199                return 0;
 200        }
 201
 202        printf("PCIe reset through GPIO7: ");
 203        /* apply PCIe reset via GPIO */
 204        kw_gpio_set_valid(KM_PEX_RST_GPIO_PIN, 1);
 205        kw_gpio_direction_output(KM_PEX_RST_GPIO_PIN, 1);
 206        kw_gpio_set_value(KM_PEX_RST_GPIO_PIN, 0);
 207        udelay(1000*10);
 208        kw_gpio_set_value(KM_PEX_RST_GPIO_PIN, 1);
 209
 210        printf(" done\n");
 211
 212        return 0;
 213}
 214
 215#else
 216
 217#define PRST1           0x4
 218#define PCIE_RST        0x10
 219#define TRAFFIC_RST     0x04
 220
 221int fpga_reset(void)
 222{
 223        int ret = 0;
 224        u8 resets;
 225
 226        if (!check_boco2()) {
 227                /* we do not have BOCO2, this is not really used */
 228                return 0;
 229        }
 230
 231        /* if we have skipped, we only want to reset the PCIe part */
 232        resets = skip ? PCIE_RST : PCIE_RST | TRAFFIC_RST;
 233
 234        ret = boco_clear_bits(PRST1, resets);
 235        if (ret)
 236                return ret;
 237
 238        /* small delay for the pulse */
 239        udelay(10);
 240
 241        ret = boco_set_bits(PRST1, resets);
 242        if (ret)
 243                return ret;
 244
 245        return 0;
 246}
 247#endif
 248
 249/* the FPGA was configured, we configure the BOCO2 so that the EEPROM
 250 * is available from the Bobcat SPI bus */
 251int toggle_eeprom_spi_bus(void)
 252{
 253        int ret = 0;
 254
 255        if (!check_boco2()) {
 256                /* we do not have BOCO2, this is not really used */
 257                return 0;
 258        }
 259
 260        ret = boco_set_bits(SPI_REG, CFG_EEPROM);
 261        if (ret)
 262                return ret;
 263
 264        return 0;
 265}
 266