@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/spi/spi.h>
+#include <linux/container_of.h>
/* MachXO2 Programming Guide - sysCONFIG Programming Commands */
#define IDCODE_PUB {0xe0, 0x00, 0x00, 0x00}
@@ -57,13 +58,27 @@
#define MACHXO2_ERR_ESDMEOF 7 /* SDM EOF */
#define MACHXO2_FAIL BIT(13)
+struct machxo2_common_priv {
+};
+
+struct machxo2_spi_priv {
+ struct machxo2_common_priv common;
+ struct spi_device *spi;
+};
+
+static inline struct machxo2_spi_priv *to_machxo2_spi_priv(struct machxo2_common_priv *priv)
+{
+ return container_of(priv, struct machxo2_spi_priv, common);
+}
+
static inline u8 get_err(u32 status)
{
return FIELD_GET(MACHXO2_ERR, status);
}
-static int get_status(struct spi_device *spi, u32 *status)
+static int get_status(struct machxo2_common_priv *priv, u32 *status)
{
+ struct spi_device *spi = to_machxo2_spi_priv(priv)->spi;
struct spi_transfer transfers[2] = {};
u8 cmd[] = LSC_READ_STATUS;
__be32 tmp;
@@ -107,13 +122,13 @@ static void dump_status_reg(u32 status)
!!FIELD_GET(MACHXO2_DVER, status), get_err_string(get_err(status)));
}
-static int machxo2_wait_until_not_busy(struct spi_device *spi)
+static int machxo2_wait_until_not_busy(struct machxo2_common_priv *priv)
{
u32 status;
int ret, loop = 0;
do {
- ret = get_status(spi, &status);
+ ret = get_status(priv, &status);
if (ret)
return ret;
if (++loop >= MACHXO2_MAX_BUSY_LOOP)
@@ -129,8 +144,10 @@ struct machxo2_cmd {
u16 delay_us;
};
-static int machxo2_write_spi(struct spi_device *spi, struct machxo2_cmd *cmds, size_t cmd_count)
+static int machxo2_write_spi(struct machxo2_common_priv *priv,
+ struct machxo2_cmd *cmds, size_t cmd_count)
{
+ struct spi_device *spi = to_machxo2_spi_priv(priv)->spi;
struct spi_transfer *transfers;
int i, ret;
@@ -154,7 +171,7 @@ static int machxo2_write_spi(struct spi_device *spi, struct machxo2_cmd *cmds, s
static int machxo2_cleanup(struct fpga_manager *mgr)
{
- struct spi_device *spi = mgr->priv;
+ struct machxo2_common_priv *priv = mgr->priv;
u8 erase[] = ISC_ERASE;
u8 refresh[] = LSC_REFRESH;
struct machxo2_cmd cmd = {};
@@ -162,18 +179,18 @@ static int machxo2_cleanup(struct fpga_manager *mgr)
cmd.cmd = erase;
cmd.cmd_len = sizeof(erase);
- ret = machxo2_write_spi(spi, &cmd, 1);
+ ret = machxo2_write_spi(priv, &cmd, 1);
if (ret)
goto fail;
- ret = machxo2_wait_until_not_busy(spi);
+ ret = machxo2_wait_until_not_busy(priv);
if (ret)
goto fail;
cmd.cmd = refresh;
cmd.cmd_len = sizeof(refresh);
cmd.delay_us = MACHXO2_REFRESH_USEC;
- ret = machxo2_write_spi(spi, &cmd, 1);
+ ret = machxo2_write_spi(priv, &cmd, 1);
if (ret)
goto fail;
@@ -192,10 +209,10 @@ static bool machxo2_status_done(unsigned long status)
static enum fpga_mgr_states machxo2_spi_state(struct fpga_manager *mgr)
{
- struct spi_device *spi = mgr->priv;
+ struct machxo2_common_priv *priv = mgr->priv;
u32 status;
- get_status(spi, &status);
+ get_status(priv, &status);
if (machxo2_status_done(status))
return FPGA_MGR_STATE_OPERATING;
@@ -206,7 +223,7 @@ static int machxo2_write_init(struct fpga_manager *mgr,
struct fpga_image_info *info,
const char *buf, size_t count)
{
- struct spi_device *spi = mgr->priv;
+ struct machxo2_common_priv *priv = mgr->priv;
u8 enable[] = ISC_ENABLE;
u8 erase[] = ISC_ERASE;
u8 initaddr[] = LSC_INITADDRESS;
@@ -220,7 +237,7 @@ static int machxo2_write_init(struct fpga_manager *mgr,
return -ENOTSUPP;
}
- get_status(spi, &status);
+ get_status(priv, &status);
dump_status_reg(status);
cmd[0].cmd = enable;
@@ -234,11 +251,11 @@ static int machxo2_write_init(struct fpga_manager *mgr,
if (ret)
goto fail;
- ret = machxo2_wait_until_not_busy(spi);
+ ret = machxo2_wait_until_not_busy(priv);
if (ret)
goto fail;
- get_status(spi, &status);
+ get_status(priv, &status);
if (status & MACHXO2_FAIL) {
ret = -EINVAL;
goto fail;
@@ -247,11 +264,11 @@ static int machxo2_write_init(struct fpga_manager *mgr,
cmd[0].cmd = initaddr;
cmd[0].cmd_len = sizeof(initaddr);
- ret = machxo2_write_spi(spi, &cmd[0], 1);
+ ret = machxo2_write_spi(priv, &cmd[0], 1);
if (ret)
goto fail;
- get_status(spi, &status);
+ get_status(priv, &status);
dump_status_reg(status);
return 0;
@@ -264,7 +281,7 @@ static int machxo2_write_init(struct fpga_manager *mgr,
static int machxo2_write(struct fpga_manager *mgr, const char *buf,
size_t count)
{
- struct spi_device *spi = mgr->priv;
+ struct machxo2_common_priv *priv = mgr->priv;
u8 progincr[] = LSC_PROGINCRNV;
u8 payload[MACHXO2_BUF_SIZE];
struct machxo2_cmd cmd = {};
@@ -275,7 +292,7 @@ static int machxo2_write(struct fpga_manager *mgr, const char *buf,
dev_err(&mgr->dev, "Malformed payload.\n");
return -EINVAL;
}
- get_status(spi, &status);
+ get_status(priv, &status);
dump_status_reg(status);
cmd.cmd = payload;
@@ -289,13 +306,13 @@ static int machxo2_write(struct fpga_manager *mgr, const char *buf,
cmd.cmd = payload;
cmd.cmd_len = MACHXO2_BUF_SIZE;
cmd.delay_us = MACHXO2_HIGH_DELAY_USEC;
- ret = machxo2_write_spi(spi, &cmd, 1);
+ ret = machxo2_write_spi(priv, &cmd, 1);
if (ret) {
dev_err(&mgr->dev, "Error loading the bitstream.\n");
return ret;
}
}
- get_status(spi, &status);
+ get_status(priv, &status);
dump_status_reg(status);
return 0;
@@ -304,7 +321,7 @@ static int machxo2_write(struct fpga_manager *mgr, const char *buf,
static int machxo2_write_complete(struct fpga_manager *mgr,
struct fpga_image_info *info)
{
- struct spi_device *spi = mgr->priv;
+ struct machxo2_common_priv *priv = mgr->priv;
struct machxo2_cmd cmd = {};
u8 progdone[] = ISC_PROGRAMDONE;
u8 refresh[] = LSC_REFRESH;
@@ -313,14 +330,14 @@ static int machxo2_write_complete(struct fpga_manager *mgr,
cmd.cmd = progdone;
cmd.cmd_len = sizeof(progdone);
- ret = machxo2_write_spi(spi, &cmd, 1);
+ ret = machxo2_write_spi(priv, &cmd, 1);
if (ret)
goto fail;
- ret = machxo2_wait_until_not_busy(spi);
+ ret = machxo2_wait_until_not_busy(priv);
if (ret)
goto fail;
- get_status(spi, &status);
+ get_status(priv, &status);
dump_status_reg(status);
if (!(status & MACHXO2_DONE)) {
machxo2_cleanup(mgr);
@@ -333,12 +350,12 @@ static int machxo2_write_complete(struct fpga_manager *mgr,
cmd.delay_us = MACHXO2_REFRESH_USEC;
do {
- ret = machxo2_write_spi(spi, &cmd, 1);
+ ret = machxo2_write_spi(priv, &cmd, 1);
if (ret)
goto fail;
/* check refresh status */
- get_status(spi, &status);
+ get_status(priv, &status);
dump_status_reg(status);
if (machxo2_status_done(status))
break;
@@ -349,7 +366,7 @@ static int machxo2_write_complete(struct fpga_manager *mgr,
}
} while (1);
- get_status(spi, &status);
+ get_status(priv, &status);
dump_status_reg(status);
return 0;
@@ -368,6 +385,7 @@ static const struct fpga_manager_ops machxo2_ops = {
static int machxo2_spi_probe(struct spi_device *spi)
{
+ struct machxo2_spi_priv *priv;
struct device *dev = &spi->dev;
struct fpga_manager *mgr;
@@ -376,8 +394,14 @@ static int machxo2_spi_probe(struct spi_device *spi)
return -EINVAL;
}
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->spi = spi;
+
mgr = devm_fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager",
- &machxo2_ops, spi);
+ &machxo2_ops, &priv->common);
return PTR_ERR_OR_ZERO(mgr);
}
This commit introduces a machxo2_common_priv structure which is used instead of holding the driver's spi_device directly as priv member of the fpga_mgr structure. Additionally it serves as a container for a machxo2_spi_priv struct, this prepares the addition of i2c as another bus in a later commit. Signed-off-by: Johannes Zink <j.zink@pengutronix.de> --- drivers/fpga/machxo2-spi.c | 80 +++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 28 deletions(-)