| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Altera Passive Serial SPI Driver |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2017 United Western Technologies, Corporation |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Joshua Clayton <stillcompiling@gmail.com> |
|---|
| 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 Altera FPGA firmware that is loaded over SPI using the passive |
|---|
| 13 | 10 | * serial configuration method. |
|---|
| .. | .. |
|---|
| 73 | 70 | .status_wait_max_us = 3000, /* max(t_CF2ST1) */ |
|---|
| 74 | 71 | .t_cfg_us = 2, /* max { min(t_CFG), max(tCF2ST0) } */ |
|---|
| 75 | 72 | .t_st2ck_us = 10, /* min(t_ST2CK) */ |
|---|
| 73 | +}; |
|---|
| 74 | + |
|---|
| 75 | +/* Array index is enum altera_ps_devtype */ |
|---|
| 76 | +static const struct altera_ps_data *altera_ps_data_map[] = { |
|---|
| 77 | + &c5_data, |
|---|
| 78 | + &a10_data, |
|---|
| 76 | 79 | }; |
|---|
| 77 | 80 | |
|---|
| 78 | 81 | static const struct of_device_id of_ef_match[] = { |
|---|
| .. | .. |
|---|
| 199 | 202 | struct fpga_image_info *info) |
|---|
| 200 | 203 | { |
|---|
| 201 | 204 | struct altera_ps_conf *conf = mgr->priv; |
|---|
| 202 | | - const char dummy[] = {0}; |
|---|
| 205 | + static const char dummy[] = {0}; |
|---|
| 203 | 206 | int ret; |
|---|
| 204 | 207 | |
|---|
| 205 | 208 | if (gpiod_get_value_cansleep(conf->status)) { |
|---|
| .. | .. |
|---|
| 234 | 237 | .write_complete = altera_ps_write_complete, |
|---|
| 235 | 238 | }; |
|---|
| 236 | 239 | |
|---|
| 240 | +static const struct altera_ps_data *id_to_data(const struct spi_device_id *id) |
|---|
| 241 | +{ |
|---|
| 242 | + kernel_ulong_t devtype = id->driver_data; |
|---|
| 243 | + const struct altera_ps_data *data; |
|---|
| 244 | + |
|---|
| 245 | + /* someone added a altera_ps_devtype without adding to the map array */ |
|---|
| 246 | + if (devtype >= ARRAY_SIZE(altera_ps_data_map)) |
|---|
| 247 | + return NULL; |
|---|
| 248 | + |
|---|
| 249 | + data = altera_ps_data_map[devtype]; |
|---|
| 250 | + if (!data || data->devtype != devtype) |
|---|
| 251 | + return NULL; |
|---|
| 252 | + |
|---|
| 253 | + return data; |
|---|
| 254 | +} |
|---|
| 255 | + |
|---|
| 237 | 256 | static int altera_ps_probe(struct spi_device *spi) |
|---|
| 238 | 257 | { |
|---|
| 239 | 258 | struct altera_ps_conf *conf; |
|---|
| 240 | 259 | const struct of_device_id *of_id; |
|---|
| 241 | 260 | struct fpga_manager *mgr; |
|---|
| 242 | | - int ret; |
|---|
| 243 | 261 | |
|---|
| 244 | 262 | conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL); |
|---|
| 245 | 263 | if (!conf) |
|---|
| 246 | 264 | return -ENOMEM; |
|---|
| 247 | 265 | |
|---|
| 248 | | - of_id = of_match_device(of_ef_match, &spi->dev); |
|---|
| 249 | | - if (!of_id) |
|---|
| 250 | | - return -ENODEV; |
|---|
| 266 | + if (spi->dev.of_node) { |
|---|
| 267 | + of_id = of_match_device(of_ef_match, &spi->dev); |
|---|
| 268 | + if (!of_id) |
|---|
| 269 | + return -ENODEV; |
|---|
| 270 | + conf->data = of_id->data; |
|---|
| 271 | + } else { |
|---|
| 272 | + conf->data = id_to_data(spi_get_device_id(spi)); |
|---|
| 273 | + if (!conf->data) |
|---|
| 274 | + return -ENODEV; |
|---|
| 275 | + } |
|---|
| 251 | 276 | |
|---|
| 252 | | - conf->data = of_id->data; |
|---|
| 253 | 277 | conf->spi = spi; |
|---|
| 254 | 278 | conf->config = devm_gpiod_get(&spi->dev, "nconfig", GPIOD_OUT_LOW); |
|---|
| 255 | 279 | if (IS_ERR(conf->config)) { |
|---|
| .. | .. |
|---|
| 278 | 302 | snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s", |
|---|
| 279 | 303 | dev_driver_string(&spi->dev), dev_name(&spi->dev)); |
|---|
| 280 | 304 | |
|---|
| 281 | | - mgr = fpga_mgr_create(&spi->dev, conf->mgr_name, |
|---|
| 282 | | - &altera_ps_ops, conf); |
|---|
| 305 | + mgr = devm_fpga_mgr_create(&spi->dev, conf->mgr_name, |
|---|
| 306 | + &altera_ps_ops, conf); |
|---|
| 283 | 307 | if (!mgr) |
|---|
| 284 | 308 | return -ENOMEM; |
|---|
| 285 | 309 | |
|---|
| 286 | 310 | spi_set_drvdata(spi, mgr); |
|---|
| 287 | 311 | |
|---|
| 288 | | - ret = fpga_mgr_register(mgr); |
|---|
| 289 | | - if (ret) |
|---|
| 290 | | - fpga_mgr_free(mgr); |
|---|
| 291 | | - |
|---|
| 292 | | - return ret; |
|---|
| 312 | + return fpga_mgr_register(mgr); |
|---|
| 293 | 313 | } |
|---|
| 294 | 314 | |
|---|
| 295 | 315 | static int altera_ps_remove(struct spi_device *spi) |
|---|
| .. | .. |
|---|
| 302 | 322 | } |
|---|
| 303 | 323 | |
|---|
| 304 | 324 | static const struct spi_device_id altera_ps_spi_ids[] = { |
|---|
| 305 | | - {"cyclone-ps-spi", 0}, |
|---|
| 325 | + { "cyclone-ps-spi", CYCLONE5 }, |
|---|
| 326 | + { "fpga-passive-serial", CYCLONE5 }, |
|---|
| 327 | + { "fpga-arria10-passive-serial", ARRIA10 }, |
|---|
| 306 | 328 | {} |
|---|
| 307 | 329 | }; |
|---|
| 308 | 330 | MODULE_DEVICE_TABLE(spi, altera_ps_spi_ids); |
|---|