From: Ben Whitten <ben.whit...@lairdtech.com> As part of changing our internal pointers to our priv data we add the spi_device temporarily for downstream burst read/writes. Just pass firmware pointer to the load and remove redundant size checks, as both MCUs have the same program size add a define.
Use devm_kzalloc for automatic cleanup on failure to load firmware, manually cleaup this memory on success. Convert firmware loading to regmap functions. Signed-off-by: Ben Whitten <ben.whit...@lairdtech.com> --- drivers/net/lora/sx1301.c | 109 ++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 72 deletions(-) diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c index 249551b..4cec524 100644 --- a/drivers/net/lora/sx1301.c +++ b/drivers/net/lora/sx1301.c @@ -284,6 +284,7 @@ struct spi_sx1301 { struct sx1301_priv { struct device *dev; + struct spi_device *spi; struct lora_priv lora; struct gpio_desc *rst_gpio; u8 cur_page; @@ -515,93 +516,73 @@ static int sx1301_arb_ram_read(struct sx1301_priv *priv, u8 addr, u8 *val) return 0; } -static int sx1301_load_firmware(struct spi_device *spi, int mcu, const u8 *data, size_t len) +static int sx1301_load_firmware(struct sx1301_priv *priv, int mcu, const struct firmware *fw) { u8 *buf; - u8 val, rst, select_mux; int ret; + unsigned int read; + enum sx1301_fields rst, select_mux; - if (len > 8192) + if (fw->size > SX1301_MCU_FW_BYTE) return -EINVAL; switch (mcu) { case 0: - rst = REG_0_MCU_RST_0; - select_mux = REG_0_MCU_SELECT_MUX_0; + rst = F_MCU_RST_0; + select_mux = F_MCU_SELECT_MUX_0; break; case 1: - rst = REG_0_MCU_RST_1; - select_mux = REG_0_MCU_SELECT_MUX_1; + rst = F_MCU_RST_1; + select_mux = F_MCU_SELECT_MUX_1; break; default: return -EINVAL; } - ret = sx1301_page_read(spi, 0, REG_0_MCU, &val); - if (ret) { - dev_err(&spi->dev, "MCU read failed\n"); + ret = sx1301_field_write(priv, rst, 1); + if (ret) return ret; - } - - val |= rst; - val &= ~select_mux; - - ret = sx1301_page_write(spi, 0, REG_0_MCU, val); - if (ret) { - dev_err(&spi->dev, "MCU reset / select mux write failed\n"); + ret = sx1301_field_write(priv, select_mux, 0); + if (ret) return ret; - } - ret = sx1301_write(spi, REG_MCU_PROM_ADDR, 0); - if (ret) { - dev_err(&spi->dev, "MCU prom addr write failed\n"); + /* Load firmware into the data register */ + ret = regmap_write(priv->regmap, SX1301_MPA, 0); + if (ret) return ret; - } - ret = sx1301_write_burst(spi, REG_MCU_PROM_DATA, data, len); + ret = sx1301_write_burst(priv->spi, REG_MCU_PROM_DATA, fw->data, fw->size); if (ret) { - dev_err(&spi->dev, "MCU prom data write failed\n"); + dev_err(priv->dev, "MCU prom data write failed\n"); return ret; } - ret = sx1301_read(spi, REG_MCU_PROM_DATA, &val); + ret = regmap_read(priv->regmap, SX1301_MPD, &read); if (ret) { - dev_err(&spi->dev, "MCU prom data dummy read failed\n"); + dev_err(priv->dev, "MCU prom data dummy read failed\n"); return ret; } - buf = kzalloc(len, GFP_KERNEL); + buf = devm_kzalloc(priv->dev, fw->size, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = sx1301_read_burst(spi, REG_MCU_PROM_DATA, buf, len); + ret = sx1301_read_burst(priv->spi, REG_MCU_PROM_DATA, buf, fw->size); if (ret) { - dev_err(&spi->dev, "MCU prom data read failed\n"); - kfree(buf); + dev_err(priv->dev, "MCU prom data read failed\n"); return ret; } - if (memcmp(data, buf, len)) { - dev_err(&spi->dev, "MCU prom data read does not match data written\n"); - kfree(buf); + if (memcmp(fw->data, buf, fw->size)) { + dev_err(priv->dev, "MCU prom data read does not match data written\n"); return -ENXIO; } - kfree(buf); + devm_kfree(priv->dev, buf); - ret = sx1301_page_read(spi, 0, REG_0_MCU, &val); - if (ret) { - dev_err(&spi->dev, "MCU read (1) failed\n"); - return ret; - } - - val |= select_mux; - - ret = sx1301_page_write(spi, 0, REG_0_MCU, val); - if (ret) { - dev_err(&spi->dev, "MCU reset / select mux write (1) failed\n"); + ret = sx1301_field_write(priv, select_mux, 1); + if (ret) return ret; - } return 0; } @@ -613,18 +594,13 @@ static int sx1301_agc_calibrate(struct spi_device *spi) u8 val; int ret; - ret = request_firmware(&fw, "sx1301_agc_calibration.bin", &spi->dev); + ret = request_firmware(&fw, "sx1301_agc_calibration.bin", priv->dev); if (ret) { dev_err(&spi->dev, "agc cal firmware file load failed\n"); return ret; } - if (fw->size != 8192) { - dev_err(&spi->dev, "unexpected agc cal firmware size\n"); - return -EINVAL; - } - - ret = sx1301_load_firmware(spi, 1, fw->data, fw->size); + ret = sx1301_load_firmware(priv, 1, fw); release_firmware(fw); if (ret) { dev_err(&spi->dev, "agc cal firmware load failed\n"); @@ -741,36 +717,24 @@ static int sx1301_load_all_firmware(struct spi_device *spi) u8 val; int ret; - ret = request_firmware(&fw, "sx1301_arb.bin", &spi->dev); + ret = request_firmware(&fw, "sx1301_arb.bin", priv->dev); if (ret) { - dev_err(&spi->dev, "arb firmware file load failed\n"); + dev_err(priv->dev, "arb firmware file load failed\n"); return ret; } - if (fw->size != 8192) { - dev_err(&spi->dev, "unexpected arb firmware size\n"); - release_firmware(fw); - return -EINVAL; - } - - ret = sx1301_load_firmware(spi, 0, fw->data, fw->size); + ret = sx1301_load_firmware(priv, 0, fw); release_firmware(fw); if (ret) return ret; - ret = request_firmware(&fw, "sx1301_agc.bin", &spi->dev); + ret = request_firmware(&fw, "sx1301_agc.bin", priv->dev); if (ret) { - dev_err(&spi->dev, "agc firmware file load failed\n"); + dev_err(priv->dev, "agc firmware file load failed\n"); return ret; } - if (fw->size != 8192) { - dev_err(&spi->dev, "unexpected agc firmware size\n"); - release_firmware(fw); - return -EINVAL; - } - - ret = sx1301_load_firmware(spi, 1, fw->data, fw->size); + ret = sx1301_load_firmware(priv, 1, fw); release_firmware(fw); if (ret) return ret; @@ -886,6 +850,7 @@ static int sx1301_probe(struct spi_device *spi) spi_set_drvdata(spi, netdev); SET_NETDEV_DEV(netdev, &spi->dev); priv->dev = &spi->dev; + priv->spi = spi; priv->regmap = devm_regmap_init_spi(spi, &sx1301_regmap_config); if (IS_ERR(priv->regmap)) { -- 2.7.4