| .. | .. | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 1 | 2 | /* | 
|---|
| 2 |  | - * Xilinx Spartan6 Slave Serial SPI Driver | 
|---|
|  | 3 | + * Xilinx Spartan6 and 7 Series Slave Serial SPI Driver | 
|---|
| 3 | 4 | * | 
|---|
| 4 | 5 | * Copyright (C) 2017 DENX Software Engineering | 
|---|
| 5 | 6 | * | 
|---|
| 6 | 7 | * Anatolij Gustschin <agust@denx.de> | 
|---|
| 7 |  | - * | 
|---|
| 8 |  | - * This program is free software; you can redistribute it and/or modify it | 
|---|
| 9 |  | - * under the terms and conditions of the GNU General Public License, | 
|---|
| 10 |  | - * version 2, as published by the Free Software Foundation. | 
|---|
| 11 | 8 | * | 
|---|
| 12 | 9 | * Manage Xilinx FPGA firmware that is loaded over SPI using | 
|---|
| 13 | 10 | * the slave serial configuration interface. | 
|---|
| .. | .. | 
|---|
| 26 | 23 | struct xilinx_spi_conf { | 
|---|
| 27 | 24 | struct spi_device *spi; | 
|---|
| 28 | 25 | struct gpio_desc *prog_b; | 
|---|
|  | 26 | +	struct gpio_desc *init_b; | 
|---|
| 29 | 27 | struct gpio_desc *done; | 
|---|
| 30 | 28 | }; | 
|---|
| 31 | 29 |  | 
|---|
| 32 |  | -static enum fpga_mgr_states xilinx_spi_state(struct fpga_manager *mgr) | 
|---|
|  | 30 | +static int get_done_gpio(struct fpga_manager *mgr) | 
|---|
| 33 | 31 | { | 
|---|
| 34 | 32 | struct xilinx_spi_conf *conf = mgr->priv; | 
|---|
|  | 33 | +	int ret; | 
|---|
| 35 | 34 |  | 
|---|
| 36 |  | -	if (!gpiod_get_value(conf->done)) | 
|---|
|  | 35 | +	ret = gpiod_get_value(conf->done); | 
|---|
|  | 36 | + | 
|---|
|  | 37 | +	if (ret < 0) | 
|---|
|  | 38 | +		dev_err(&mgr->dev, "Error reading DONE (%d)\n", ret); | 
|---|
|  | 39 | + | 
|---|
|  | 40 | +	return ret; | 
|---|
|  | 41 | +} | 
|---|
|  | 42 | + | 
|---|
|  | 43 | +static enum fpga_mgr_states xilinx_spi_state(struct fpga_manager *mgr) | 
|---|
|  | 44 | +{ | 
|---|
|  | 45 | +	if (!get_done_gpio(mgr)) | 
|---|
| 37 | 46 | return FPGA_MGR_STATE_RESET; | 
|---|
| 38 | 47 |  | 
|---|
| 39 | 48 | return FPGA_MGR_STATE_UNKNOWN; | 
|---|
|  | 49 | +} | 
|---|
|  | 50 | + | 
|---|
|  | 51 | +/** | 
|---|
|  | 52 | + * wait_for_init_b - wait for the INIT_B pin to have a given state, or wait | 
|---|
|  | 53 | + * a given delay if the pin is unavailable | 
|---|
|  | 54 | + * | 
|---|
|  | 55 | + * @mgr:        The FPGA manager object | 
|---|
|  | 56 | + * @value:      Value INIT_B to wait for (1 = asserted = low) | 
|---|
|  | 57 | + * @alt_udelay: Delay to wait if the INIT_B GPIO is not available | 
|---|
|  | 58 | + * | 
|---|
|  | 59 | + * Returns 0 when the INIT_B GPIO reached the given state or -ETIMEDOUT if | 
|---|
|  | 60 | + * too much time passed waiting for that. If no INIT_B GPIO is available | 
|---|
|  | 61 | + * then always return 0. | 
|---|
|  | 62 | + */ | 
|---|
|  | 63 | +static int wait_for_init_b(struct fpga_manager *mgr, int value, | 
|---|
|  | 64 | +			   unsigned long alt_udelay) | 
|---|
|  | 65 | +{ | 
|---|
|  | 66 | +	struct xilinx_spi_conf *conf = mgr->priv; | 
|---|
|  | 67 | +	unsigned long timeout = jiffies + msecs_to_jiffies(1000); | 
|---|
|  | 68 | + | 
|---|
|  | 69 | +	if (conf->init_b) { | 
|---|
|  | 70 | +		while (time_before(jiffies, timeout)) { | 
|---|
|  | 71 | +			int ret = gpiod_get_value(conf->init_b); | 
|---|
|  | 72 | + | 
|---|
|  | 73 | +			if (ret == value) | 
|---|
|  | 74 | +				return 0; | 
|---|
|  | 75 | + | 
|---|
|  | 76 | +			if (ret < 0) { | 
|---|
|  | 77 | +				dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret); | 
|---|
|  | 78 | +				return ret; | 
|---|
|  | 79 | +			} | 
|---|
|  | 80 | + | 
|---|
|  | 81 | +			usleep_range(100, 400); | 
|---|
|  | 82 | +		} | 
|---|
|  | 83 | + | 
|---|
|  | 84 | +		dev_err(&mgr->dev, "Timeout waiting for INIT_B to %s\n", | 
|---|
|  | 85 | +			value ? "assert" : "deassert"); | 
|---|
|  | 86 | +		return -ETIMEDOUT; | 
|---|
|  | 87 | +	} | 
|---|
|  | 88 | + | 
|---|
|  | 89 | +	udelay(alt_udelay); | 
|---|
|  | 90 | + | 
|---|
|  | 91 | +	return 0; | 
|---|
| 40 | 92 | } | 
|---|
| 41 | 93 |  | 
|---|
| 42 | 94 | static int xilinx_spi_write_init(struct fpga_manager *mgr, | 
|---|
| .. | .. | 
|---|
| 44 | 96 | const char *buf, size_t count) | 
|---|
| 45 | 97 | { | 
|---|
| 46 | 98 | struct xilinx_spi_conf *conf = mgr->priv; | 
|---|
| 47 |  | -	const size_t prog_latency_7500us = 7500; | 
|---|
| 48 |  | -	const size_t prog_pulse_1us = 1; | 
|---|
|  | 99 | +	int err; | 
|---|
| 49 | 100 |  | 
|---|
| 50 | 101 | if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) { | 
|---|
| 51 |  | -		dev_err(&mgr->dev, "Partial reconfiguration not supported.\n"); | 
|---|
|  | 102 | +		dev_err(&mgr->dev, "Partial reconfiguration not supported\n"); | 
|---|
| 52 | 103 | return -EINVAL; | 
|---|
| 53 | 104 | } | 
|---|
| 54 | 105 |  | 
|---|
| 55 | 106 | gpiod_set_value(conf->prog_b, 1); | 
|---|
| 56 | 107 |  | 
|---|
| 57 |  | -	udelay(prog_pulse_1us); /* min is 500 ns */ | 
|---|
|  | 108 | +	err = wait_for_init_b(mgr, 1, 1); /* min is 500 ns */ | 
|---|
|  | 109 | +	if (err) { | 
|---|
|  | 110 | +		gpiod_set_value(conf->prog_b, 0); | 
|---|
|  | 111 | +		return err; | 
|---|
|  | 112 | +	} | 
|---|
| 58 | 113 |  | 
|---|
| 59 | 114 | gpiod_set_value(conf->prog_b, 0); | 
|---|
| 60 | 115 |  | 
|---|
| 61 |  | -	if (gpiod_get_value(conf->done)) { | 
|---|
|  | 116 | +	err = wait_for_init_b(mgr, 0, 0); | 
|---|
|  | 117 | +	if (err) | 
|---|
|  | 118 | +		return err; | 
|---|
|  | 119 | + | 
|---|
|  | 120 | +	if (get_done_gpio(mgr)) { | 
|---|
| 62 | 121 | dev_err(&mgr->dev, "Unexpected DONE pin state...\n"); | 
|---|
| 63 | 122 | return -EIO; | 
|---|
| 64 | 123 | } | 
|---|
| 65 | 124 |  | 
|---|
| 66 | 125 | /* program latency */ | 
|---|
| 67 |  | -	usleep_range(prog_latency_7500us, prog_latency_7500us + 100); | 
|---|
|  | 126 | +	usleep_range(7500, 7600); | 
|---|
| 68 | 127 | return 0; | 
|---|
| 69 | 128 | } | 
|---|
| 70 | 129 |  | 
|---|
| .. | .. | 
|---|
| 111 | 170 | struct fpga_image_info *info) | 
|---|
| 112 | 171 | { | 
|---|
| 113 | 172 | struct xilinx_spi_conf *conf = mgr->priv; | 
|---|
| 114 |  | -	unsigned long timeout; | 
|---|
|  | 173 | +	unsigned long timeout = jiffies + usecs_to_jiffies(info->config_complete_timeout_us); | 
|---|
|  | 174 | +	bool expired = false; | 
|---|
|  | 175 | +	int done; | 
|---|
| 115 | 176 | int ret; | 
|---|
| 116 | 177 |  | 
|---|
| 117 |  | -	if (gpiod_get_value(conf->done)) | 
|---|
| 118 |  | -		return xilinx_spi_apply_cclk_cycles(conf); | 
|---|
|  | 178 | +	/* | 
|---|
|  | 179 | +	 * This loop is carefully written such that if the driver is | 
|---|
|  | 180 | +	 * scheduled out for more than 'timeout', we still check for DONE | 
|---|
|  | 181 | +	 * before giving up and we apply 8 extra CCLK cycles in all cases. | 
|---|
|  | 182 | +	 */ | 
|---|
|  | 183 | +	while (!expired) { | 
|---|
|  | 184 | +		expired = time_after(jiffies, timeout); | 
|---|
| 119 | 185 |  | 
|---|
| 120 |  | -	timeout = jiffies + usecs_to_jiffies(info->config_complete_timeout_us); | 
|---|
| 121 |  | - | 
|---|
| 122 |  | -	while (time_before(jiffies, timeout)) { | 
|---|
|  | 186 | +		done = get_done_gpio(mgr); | 
|---|
|  | 187 | +		if (done < 0) | 
|---|
|  | 188 | +			return done; | 
|---|
| 123 | 189 |  | 
|---|
| 124 | 190 | ret = xilinx_spi_apply_cclk_cycles(conf); | 
|---|
| 125 | 191 | if (ret) | 
|---|
| 126 | 192 | return ret; | 
|---|
| 127 | 193 |  | 
|---|
| 128 |  | -		if (gpiod_get_value(conf->done)) | 
|---|
| 129 |  | -			return xilinx_spi_apply_cclk_cycles(conf); | 
|---|
|  | 194 | +		if (done) | 
|---|
|  | 195 | +			return 0; | 
|---|
| 130 | 196 | } | 
|---|
| 131 | 197 |  | 
|---|
| 132 |  | -	dev_err(&mgr->dev, "Timeout after config data transfer.\n"); | 
|---|
|  | 198 | +	if (conf->init_b) { | 
|---|
|  | 199 | +		ret = gpiod_get_value(conf->init_b); | 
|---|
|  | 200 | + | 
|---|
|  | 201 | +		if (ret < 0) { | 
|---|
|  | 202 | +			dev_err(&mgr->dev, "Error reading INIT_B (%d)\n", ret); | 
|---|
|  | 203 | +			return ret; | 
|---|
|  | 204 | +		} | 
|---|
|  | 205 | + | 
|---|
|  | 206 | +		dev_err(&mgr->dev, | 
|---|
|  | 207 | +			ret ? "CRC error or invalid device\n" | 
|---|
|  | 208 | +			: "Missing sync word or incomplete bitstream\n"); | 
|---|
|  | 209 | +	} else { | 
|---|
|  | 210 | +		dev_err(&mgr->dev, "Timeout after config data transfer\n"); | 
|---|
|  | 211 | +	} | 
|---|
|  | 212 | + | 
|---|
| 133 | 213 | return -ETIMEDOUT; | 
|---|
| 134 | 214 | } | 
|---|
| 135 | 215 |  | 
|---|
| .. | .. | 
|---|
| 144 | 224 | { | 
|---|
| 145 | 225 | struct xilinx_spi_conf *conf; | 
|---|
| 146 | 226 | struct fpga_manager *mgr; | 
|---|
| 147 |  | -	int ret; | 
|---|
| 148 | 227 |  | 
|---|
| 149 | 228 | conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); | 
|---|
| 150 | 229 | if (!conf) | 
|---|
| .. | .. | 
|---|
| 154 | 233 |  | 
|---|
| 155 | 234 | /* PROGRAM_B is active low */ | 
|---|
| 156 | 235 | conf->prog_b = devm_gpiod_get(&spi->dev, "prog_b", GPIOD_OUT_LOW); | 
|---|
| 157 |  | -	if (IS_ERR(conf->prog_b)) { | 
|---|
| 158 |  | -		dev_err(&spi->dev, "Failed to get PROGRAM_B gpio: %ld\n", | 
|---|
| 159 |  | -			PTR_ERR(conf->prog_b)); | 
|---|
| 160 |  | -		return PTR_ERR(conf->prog_b); | 
|---|
| 161 |  | -	} | 
|---|
|  | 236 | +	if (IS_ERR(conf->prog_b)) | 
|---|
|  | 237 | +		return dev_err_probe(&spi->dev, PTR_ERR(conf->prog_b), | 
|---|
|  | 238 | +				     "Failed to get PROGRAM_B gpio\n"); | 
|---|
|  | 239 | + | 
|---|
|  | 240 | +	conf->init_b = devm_gpiod_get_optional(&spi->dev, "init-b", GPIOD_IN); | 
|---|
|  | 241 | +	if (IS_ERR(conf->init_b)) | 
|---|
|  | 242 | +		return dev_err_probe(&spi->dev, PTR_ERR(conf->init_b), | 
|---|
|  | 243 | +				     "Failed to get INIT_B gpio\n"); | 
|---|
| 162 | 244 |  | 
|---|
| 163 | 245 | conf->done = devm_gpiod_get(&spi->dev, "done", GPIOD_IN); | 
|---|
| 164 |  | -	if (IS_ERR(conf->done)) { | 
|---|
| 165 |  | -		dev_err(&spi->dev, "Failed to get DONE gpio: %ld\n", | 
|---|
| 166 |  | -			PTR_ERR(conf->done)); | 
|---|
| 167 |  | -		return PTR_ERR(conf->done); | 
|---|
| 168 |  | -	} | 
|---|
|  | 246 | +	if (IS_ERR(conf->done)) | 
|---|
|  | 247 | +		return dev_err_probe(&spi->dev, PTR_ERR(conf->done), | 
|---|
|  | 248 | +				     "Failed to get DONE gpio\n"); | 
|---|
| 169 | 249 |  | 
|---|
| 170 |  | -	mgr = fpga_mgr_create(&spi->dev, "Xilinx Slave Serial FPGA Manager", | 
|---|
| 171 |  | -			      &xilinx_spi_ops, conf); | 
|---|
|  | 250 | +	mgr = devm_fpga_mgr_create(&spi->dev, | 
|---|
|  | 251 | +				   "Xilinx Slave Serial FPGA Manager", | 
|---|
|  | 252 | +				   &xilinx_spi_ops, conf); | 
|---|
| 172 | 253 | if (!mgr) | 
|---|
| 173 | 254 | return -ENOMEM; | 
|---|
| 174 | 255 |  | 
|---|
| 175 | 256 | spi_set_drvdata(spi, mgr); | 
|---|
| 176 | 257 |  | 
|---|
| 177 |  | -	ret = fpga_mgr_register(mgr); | 
|---|
| 178 |  | -	if (ret) | 
|---|
| 179 |  | -		fpga_mgr_free(mgr); | 
|---|
| 180 |  | - | 
|---|
| 181 |  | -	return ret; | 
|---|
|  | 258 | +	return fpga_mgr_register(mgr); | 
|---|
| 182 | 259 | } | 
|---|
| 183 | 260 |  | 
|---|
| 184 | 261 | static int xilinx_spi_remove(struct spi_device *spi) | 
|---|