Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Altera Passive Serial SPI Driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (c) 2017 United Western Technologies, Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  Joshua Clayton <stillcompiling@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * Manage Altera FPGA firmware that is loaded over SPI using the passive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * serial configuration method.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * Firmware must be in binary "rbf" format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * Works on Arria 10, Cyclone V and Stratix V. Should work on Cyclone series.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * May work on other Altera FPGAs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/bitrev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/fpga/fpga-mgr.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) enum altera_ps_devtype {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	CYCLONE5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	ARRIA10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) struct altera_ps_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	enum altera_ps_devtype devtype;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	int status_wait_min_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	int status_wait_max_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	int t_cfg_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	int t_st2ck_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) struct altera_ps_conf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	struct gpio_desc *config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	struct gpio_desc *confd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	struct gpio_desc *status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct spi_device *spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	const struct altera_ps_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	u32 info_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	char mgr_name[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) /*          |   Arria 10  |   Cyclone5  |   Stratix5  |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * t_CF2ST0 |     [; 600] |     [; 600] |     [; 600] |ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * t_CFG    |        [2;] |        [2;] |        [2;] |µs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * t_STATUS | [268; 3000] | [268; 1506] | [268; 1506] |µs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * t_CF2ST1 |    [; 3000] |    [; 1506] |    [; 1506] |µs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * t_CF2CK  |     [3010;] |     [1506;] |     [1506;] |µs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * t_ST2CK  |       [10;] |        [2;] |        [2;] |µs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * t_CD2UM  |  [175; 830] |  [175; 437] |  [175; 437] |µs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) static struct altera_ps_data c5_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	/* these values for Cyclone5 are compatible with Stratix5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	.devtype = CYCLONE5,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	.status_wait_min_us = 268,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	.status_wait_max_us = 1506,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	.t_cfg_us = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	.t_st2ck_us = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) static struct altera_ps_data a10_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	.devtype = ARRIA10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	.status_wait_min_us = 268,  /* min(t_STATUS) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	.status_wait_max_us = 3000, /* max(t_CF2ST1) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	.t_cfg_us = 2,    /* max { min(t_CFG), max(tCF2ST0) } */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	.t_st2ck_us = 10, /* min(t_ST2CK) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) /* Array index is enum altera_ps_devtype */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) static const struct altera_ps_data *altera_ps_data_map[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	&c5_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	&a10_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) static const struct of_device_id of_ef_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	{ .compatible = "altr,fpga-passive-serial", .data = &c5_data },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	{ .compatible = "altr,fpga-arria10-passive-serial", .data = &a10_data },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) MODULE_DEVICE_TABLE(of, of_ef_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static enum fpga_mgr_states altera_ps_state(struct fpga_manager *mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct altera_ps_conf *conf = mgr->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	if (gpiod_get_value_cansleep(conf->status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		return FPGA_MGR_STATE_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	return FPGA_MGR_STATE_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) static inline void altera_ps_delay(int delay_us)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (delay_us > 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		usleep_range(delay_us, delay_us + 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 		udelay(delay_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static int altera_ps_write_init(struct fpga_manager *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 				struct fpga_image_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 				const char *buf, size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	struct altera_ps_conf *conf = mgr->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	int min, max, waits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	conf->info_flags = info->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	if (info->flags & FPGA_MGR_PARTIAL_RECONFIG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		dev_err(&mgr->dev, "Partial reconfiguration not supported.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	gpiod_set_value_cansleep(conf->config, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	/* wait min reset pulse time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	altera_ps_delay(conf->data->t_cfg_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	if (!gpiod_get_value_cansleep(conf->status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		dev_err(&mgr->dev, "Status pin failed to show a reset\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	gpiod_set_value_cansleep(conf->config, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	min = conf->data->status_wait_min_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	max = conf->data->status_wait_max_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	waits = max / min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (max % min)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		waits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	/* wait for max { max(t_STATUS), max(t_CF2ST1) } */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	for (i = 0; i < waits; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		usleep_range(min, min + 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		if (!gpiod_get_value_cansleep(conf->status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			/* wait for min(t_ST2CK)*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 			altera_ps_delay(conf->data->t_st2ck_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	dev_err(&mgr->dev, "Status pin not ready.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) static void rev_buf(char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	u32 *fw32 = (u32 *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	size_t extra_bytes = (len & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	const u32 *fw_end = (u32 *)(buf + len - extra_bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	/* set buffer to lsb first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	while (fw32 < fw_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		*fw32 = bitrev8x4(*fw32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		fw32++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (extra_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		buf = (char *)fw_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		while (extra_bytes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 			*buf = bitrev8(*buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			extra_bytes--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int altera_ps_write(struct fpga_manager *mgr, const char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 			   size_t count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	struct altera_ps_conf *conf = mgr->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	const char *fw_data = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	const char *fw_data_end = fw_data + count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	while (fw_data < fw_data_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 		int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		size_t stride = min_t(size_t, fw_data_end - fw_data, SZ_4K);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		if (!(conf->info_flags & FPGA_MGR_BITSTREAM_LSB_FIRST))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			rev_buf((char *)fw_data, stride);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		ret = spi_write(conf->spi, fw_data, stride);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			dev_err(&mgr->dev, "spi error in firmware write: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 				ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		fw_data += stride;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static int altera_ps_write_complete(struct fpga_manager *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 				    struct fpga_image_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	struct altera_ps_conf *conf = mgr->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	static const char dummy[] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	if (gpiod_get_value_cansleep(conf->status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		dev_err(&mgr->dev, "Error during configuration.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	if (conf->confd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		if (!gpiod_get_raw_value_cansleep(conf->confd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 			dev_err(&mgr->dev, "CONF_DONE is inactive!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	 * After CONF_DONE goes high, send two additional falling edges on DCLK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	 * to begin initialization and enter user mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	ret = spi_write(conf->spi, dummy, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		dev_err(&mgr->dev, "spi error during end sequence: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static const struct fpga_manager_ops altera_ps_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	.state = altera_ps_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	.write_init = altera_ps_write_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	.write = altera_ps_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	.write_complete = altera_ps_write_complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static const struct altera_ps_data *id_to_data(const struct spi_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	kernel_ulong_t devtype = id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	const struct altera_ps_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	/* someone added a altera_ps_devtype without adding to the map array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	if (devtype >= ARRAY_SIZE(altera_ps_data_map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	data = altera_ps_data_map[devtype];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	if (!data || data->devtype != devtype)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static int altera_ps_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	struct altera_ps_conf *conf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	const struct of_device_id *of_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	struct fpga_manager *mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	if (!conf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	if (spi->dev.of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		of_id = of_match_device(of_ef_match, &spi->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		if (!of_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 			return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		conf->data = of_id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		conf->data = id_to_data(spi_get_device_id(spi));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 		if (!conf->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 			return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	conf->spi = spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	conf->config = devm_gpiod_get(&spi->dev, "nconfig", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	if (IS_ERR(conf->config)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		dev_err(&spi->dev, "Failed to get config gpio: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 			PTR_ERR(conf->config));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 		return PTR_ERR(conf->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	conf->status = devm_gpiod_get(&spi->dev, "nstat", GPIOD_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (IS_ERR(conf->status)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		dev_err(&spi->dev, "Failed to get status gpio: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 			PTR_ERR(conf->status));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 		return PTR_ERR(conf->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	conf->confd = devm_gpiod_get_optional(&spi->dev, "confd", GPIOD_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	if (IS_ERR(conf->confd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		dev_err(&spi->dev, "Failed to get confd gpio: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 			PTR_ERR(conf->confd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		return PTR_ERR(conf->confd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	} else if (!conf->confd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		dev_warn(&spi->dev, "Not using confd gpio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	/* Register manager with unique name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		 dev_driver_string(&spi->dev), dev_name(&spi->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	mgr = devm_fpga_mgr_create(&spi->dev, conf->mgr_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 				   &altera_ps_ops, conf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (!mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	spi_set_drvdata(spi, mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	return fpga_mgr_register(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) static int altera_ps_remove(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	struct fpga_manager *mgr = spi_get_drvdata(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	fpga_mgr_unregister(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) static const struct spi_device_id altera_ps_spi_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	{ "cyclone-ps-spi", CYCLONE5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	{ "fpga-passive-serial", CYCLONE5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	{ "fpga-arria10-passive-serial", ARRIA10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) MODULE_DEVICE_TABLE(spi, altera_ps_spi_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static struct spi_driver altera_ps_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		.name = "altera-ps-spi",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		.of_match_table = of_match_ptr(of_ef_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	.id_table = altera_ps_spi_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	.probe = altera_ps_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	.remove = altera_ps_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) module_spi_driver(altera_ps_driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_AUTHOR("Joshua Clayton <stillcompiling@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) MODULE_DESCRIPTION("Module to load Altera FPGA firmware over SPI");