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