diff options
Diffstat (limited to 'drivers')
224 files changed, 2784 insertions, 1640 deletions
| diff --git a/drivers/bus/moxtet.c b/drivers/bus/moxtet.c index fd87a59837fa..5eb0fe73ddc4 100644 --- a/drivers/bus/moxtet.c +++ b/drivers/bus/moxtet.c @@ -815,7 +815,7 @@ static int moxtet_probe(struct spi_device *spi)  	return 0;  } -static int moxtet_remove(struct spi_device *spi) +static void moxtet_remove(struct spi_device *spi)  {  	struct moxtet *moxtet = spi_get_drvdata(spi); @@ -828,8 +828,6 @@ static int moxtet_remove(struct spi_device *spi)  	device_for_each_child(moxtet->dev, NULL, __unregister);  	mutex_destroy(&moxtet->lock); - -	return 0;  }  static const struct of_device_id moxtet_dt_ids[] = { diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c index 7c617edff4ca..3170d59d660c 100644 --- a/drivers/char/tpm/st33zp24/i2c.c +++ b/drivers/char/tpm/st33zp24/i2c.c @@ -267,11 +267,8 @@ static int st33zp24_i2c_probe(struct i2c_client *client,  static int st33zp24_i2c_remove(struct i2c_client *client)  {  	struct tpm_chip *chip = i2c_get_clientdata(client); -	int ret; -	ret = st33zp24_remove(chip); -	if (ret) -		return ret; +	st33zp24_remove(chip);  	return 0;  } diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c index a75dafd39445..22d184884694 100644 --- a/drivers/char/tpm/st33zp24/spi.c +++ b/drivers/char/tpm/st33zp24/spi.c @@ -381,16 +381,11 @@ static int st33zp24_spi_probe(struct spi_device *dev)   * @param: client, the spi_device description (TPM SPI description).   * @return: 0 in case of success.   */ -static int st33zp24_spi_remove(struct spi_device *dev) +static void st33zp24_spi_remove(struct spi_device *dev)  {  	struct tpm_chip *chip = spi_get_drvdata(dev); -	int ret; -	ret = st33zp24_remove(chip); -	if (ret) -		return ret; - -	return 0; +	st33zp24_remove(chip);  }  static const struct spi_device_id st33zp24_spi_id[] = { diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index ce9efb73c144..15b393e92c8e 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -511,10 +511,9 @@ _tpm_clean_answer:  }  EXPORT_SYMBOL(st33zp24_probe); -int st33zp24_remove(struct tpm_chip *chip) +void st33zp24_remove(struct tpm_chip *chip)  {  	tpm_chip_unregister(chip); -	return 0;  }  EXPORT_SYMBOL(st33zp24_remove); diff --git a/drivers/char/tpm/st33zp24/st33zp24.h b/drivers/char/tpm/st33zp24/st33zp24.h index 6747be1e2502..b387a476c555 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.h +++ b/drivers/char/tpm/st33zp24/st33zp24.h @@ -34,5 +34,5 @@ int st33zp24_pm_resume(struct device *dev);  int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,  		   struct device *dev, int irq, int io_lpcpd); -int st33zp24_remove(struct tpm_chip *chip); +void st33zp24_remove(struct tpm_chip *chip);  #endif /* __LOCAL_ST33ZP24_H__ */ diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c index aaa59a00eeae..184396b3af50 100644 --- a/drivers/char/tpm/tpm_tis_spi_main.c +++ b/drivers/char/tpm/tpm_tis_spi_main.c @@ -254,13 +254,12 @@ static int tpm_tis_spi_driver_probe(struct spi_device *spi)  static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_spi_resume); -static int tpm_tis_spi_remove(struct spi_device *dev) +static void tpm_tis_spi_remove(struct spi_device *dev)  {  	struct tpm_chip *chip = spi_get_drvdata(dev);  	tpm_chip_unregister(chip);  	tpm_tis_remove(chip); -	return 0;  }  static const struct spi_device_id tpm_tis_spi_id[] = { diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c index 8f02c0b88000..f416f8bc2898 100644 --- a/drivers/clk/clk-lmk04832.c +++ b/drivers/clk/clk-lmk04832.c @@ -1544,14 +1544,12 @@ err_disable_oscin:  	return ret;  } -static int lmk04832_remove(struct spi_device *spi) +static void lmk04832_remove(struct spi_device *spi)  {  	struct lmk04832 *lmk = spi_get_drvdata(spi);  	clk_disable_unprepare(lmk->oscin);  	of_clk_del_provider(spi->dev.of_node); - -	return 0;  }  static const struct spi_device_id lmk04832_id[] = {  	{ "lmk04832", LMK04832 }, diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index 4a55cdf089d6..e00c33310517 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -163,15 +163,13 @@ exit_destroy:  	return ret;  } -static int gen_74x164_remove(struct spi_device *spi) +static void gen_74x164_remove(struct spi_device *spi)  {  	struct gen_74x164_chip *chip = spi_get_drvdata(spi);  	gpiod_set_value_cansleep(chip->gpiod_oe, 0);  	gpiochip_remove(&chip->gpio_chip);  	mutex_destroy(&chip->lock); - -	return 0;  }  static const struct spi_device_id gen_74x164_spi_ids[] = { diff --git a/drivers/gpio/gpio-max3191x.c b/drivers/gpio/gpio-max3191x.c index 51cd6f98d1c7..161c4751c5f7 100644 --- a/drivers/gpio/gpio-max3191x.c +++ b/drivers/gpio/gpio-max3191x.c @@ -443,14 +443,12 @@ static int max3191x_probe(struct spi_device *spi)  	return 0;  } -static int max3191x_remove(struct spi_device *spi) +static void max3191x_remove(struct spi_device *spi)  {  	struct max3191x_chip *max3191x = spi_get_drvdata(spi);  	gpiochip_remove(&max3191x->gpio);  	mutex_destroy(&max3191x->lock); - -	return 0;  }  static int __init max3191x_register_driver(struct spi_driver *sdrv) diff --git a/drivers/gpio/gpio-max7301.c b/drivers/gpio/gpio-max7301.c index 5862d73bf325..11813f41d460 100644 --- a/drivers/gpio/gpio-max7301.c +++ b/drivers/gpio/gpio-max7301.c @@ -64,11 +64,9 @@ static int max7301_probe(struct spi_device *spi)  	return ret;  } -static int max7301_remove(struct spi_device *spi) +static void max7301_remove(struct spi_device *spi)  {  	__max730x_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id max7301_id[] = { diff --git a/drivers/gpio/gpio-mc33880.c b/drivers/gpio/gpio-mc33880.c index 31d2be1bebc8..cd9b16dbe1a9 100644 --- a/drivers/gpio/gpio-mc33880.c +++ b/drivers/gpio/gpio-mc33880.c @@ -134,7 +134,7 @@ exit_destroy:  	return ret;  } -static int mc33880_remove(struct spi_device *spi) +static void mc33880_remove(struct spi_device *spi)  {  	struct mc33880 *mc; @@ -142,8 +142,6 @@ static int mc33880_remove(struct spi_device *spi)  	gpiochip_remove(&mc->chip);  	mutex_destroy(&mc->lock); - -	return 0;  }  static struct spi_driver mc33880_driver = { diff --git a/drivers/gpio/gpio-pisosr.c b/drivers/gpio/gpio-pisosr.c index 8e04054cf07e..81a47ae09ff8 100644 --- a/drivers/gpio/gpio-pisosr.c +++ b/drivers/gpio/gpio-pisosr.c @@ -163,15 +163,13 @@ static int pisosr_gpio_probe(struct spi_device *spi)  	return 0;  } -static int pisosr_gpio_remove(struct spi_device *spi) +static void pisosr_gpio_remove(struct spi_device *spi)  {  	struct pisosr_gpio *gpio = spi_get_drvdata(spi);  	gpiochip_remove(&gpio->chip);  	mutex_destroy(&gpio->lock); - -	return 0;  }  static const struct spi_device_id pisosr_gpio_id_table[] = { diff --git a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c index f043b484055b..ed626fdc08e8 100644 --- a/drivers/gpu/drm/panel/panel-abt-y030xx067a.c +++ b/drivers/gpu/drm/panel/panel-abt-y030xx067a.c @@ -293,15 +293,13 @@ static int y030xx067a_probe(struct spi_device *spi)  	return 0;  } -static int y030xx067a_remove(struct spi_device *spi) +static void y030xx067a_remove(struct spi_device *spi)  {  	struct y030xx067a *priv = spi_get_drvdata(spi);  	drm_panel_remove(&priv->panel);  	drm_panel_disable(&priv->panel);  	drm_panel_unprepare(&priv->panel); - -	return 0;  }  static const struct drm_display_mode y030xx067a_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c index 8e84df9a0033..3dfafa585127 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c @@ -896,14 +896,12 @@ static int ili9322_probe(struct spi_device *spi)  	return 0;  } -static int ili9322_remove(struct spi_device *spi) +static void ili9322_remove(struct spi_device *spi)  {  	struct ili9322 *ili = spi_get_drvdata(spi);  	ili9322_power_off(ili);  	drm_panel_remove(&ili->panel); - -	return 0;  }  /* diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index 2c3378a259b1..a07ef26234e5 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -728,7 +728,7 @@ static int ili9341_probe(struct spi_device *spi)  	return -1;  } -static int ili9341_remove(struct spi_device *spi) +static void ili9341_remove(struct spi_device *spi)  {  	const struct spi_device_id *id = spi_get_device_id(spi);  	struct ili9341 *ili = spi_get_drvdata(spi); @@ -741,7 +741,6 @@ static int ili9341_remove(struct spi_device *spi)  		drm_dev_unplug(drm);  		drm_atomic_helper_shutdown(drm);  	} -	return 0;  }  static void ili9341_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/panel/panel-innolux-ej030na.c b/drivers/gpu/drm/panel/panel-innolux-ej030na.c index c558de3f99be..e3b1daa0cb72 100644 --- a/drivers/gpu/drm/panel/panel-innolux-ej030na.c +++ b/drivers/gpu/drm/panel/panel-innolux-ej030na.c @@ -219,15 +219,13 @@ static int ej030na_probe(struct spi_device *spi)  	return 0;  } -static int ej030na_remove(struct spi_device *spi) +static void ej030na_remove(struct spi_device *spi)  {  	struct ej030na *priv = spi_get_drvdata(spi);  	drm_panel_remove(&priv->panel);  	drm_panel_disable(&priv->panel);  	drm_panel_unprepare(&priv->panel); - -	return 0;  }  static const struct drm_display_mode ej030na_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-lg-lb035q02.c b/drivers/gpu/drm/panel/panel-lg-lb035q02.c index f3183b68704f..9d0d4faa3f58 100644 --- a/drivers/gpu/drm/panel/panel-lg-lb035q02.c +++ b/drivers/gpu/drm/panel/panel-lg-lb035q02.c @@ -203,14 +203,12 @@ static int lb035q02_probe(struct spi_device *spi)  	return 0;  } -static int lb035q02_remove(struct spi_device *spi) +static void lb035q02_remove(struct spi_device *spi)  {  	struct lb035q02_device *lcd = spi_get_drvdata(spi);  	drm_panel_remove(&lcd->panel);  	drm_panel_disable(&lcd->panel); - -	return 0;  }  static const struct of_device_id lb035q02_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-lg-lg4573.c b/drivers/gpu/drm/panel/panel-lg-lg4573.c index 8e5160af1de5..cf246d15b7b6 100644 --- a/drivers/gpu/drm/panel/panel-lg-lg4573.c +++ b/drivers/gpu/drm/panel/panel-lg-lg4573.c @@ -266,14 +266,12 @@ static int lg4573_probe(struct spi_device *spi)  	return 0;  } -static int lg4573_remove(struct spi_device *spi) +static void lg4573_remove(struct spi_device *spi)  {  	struct lg4573 *ctx = spi_get_drvdata(spi);  	lg4573_display_off(ctx);  	drm_panel_remove(&ctx->panel); - -	return 0;  }  static const struct of_device_id lg4573_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c index 6e5ab1debc8b..81c5c541a351 100644 --- a/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c +++ b/drivers/gpu/drm/panel/panel-nec-nl8048hl11.c @@ -212,15 +212,13 @@ static int nl8048_probe(struct spi_device *spi)  	return 0;  } -static int nl8048_remove(struct spi_device *spi) +static void nl8048_remove(struct spi_device *spi)  {  	struct nl8048_panel *lcd = spi_get_drvdata(spi);  	drm_panel_remove(&lcd->panel);  	drm_panel_disable(&lcd->panel);  	drm_panel_unprepare(&lcd->panel); - -	return 0;  }  static const struct of_device_id nl8048_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c index d036853db865..f58cfb10b58a 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt39016.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -292,7 +292,7 @@ static int nt39016_probe(struct spi_device *spi)  	return 0;  } -static int nt39016_remove(struct spi_device *spi) +static void nt39016_remove(struct spi_device *spi)  {  	struct nt39016 *panel = spi_get_drvdata(spi); @@ -300,8 +300,6 @@ static int nt39016_remove(struct spi_device *spi)  	nt39016_disable(&panel->drm_panel);  	nt39016_unprepare(&panel->drm_panel); - -	return 0;  }  static const struct drm_display_mode kd035g6_display_modes[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-db7430.c b/drivers/gpu/drm/panel/panel-samsung-db7430.c index ead479719f00..04640c5256a8 100644 --- a/drivers/gpu/drm/panel/panel-samsung-db7430.c +++ b/drivers/gpu/drm/panel/panel-samsung-db7430.c @@ -314,12 +314,11 @@ static int db7430_probe(struct spi_device *spi)  	return 0;  } -static int db7430_remove(struct spi_device *spi) +static void db7430_remove(struct spi_device *spi)  {  	struct db7430 *db = spi_get_drvdata(spi);  	drm_panel_remove(&db->panel); -	return 0;  }  /* diff --git a/drivers/gpu/drm/panel/panel-samsung-ld9040.c b/drivers/gpu/drm/panel/panel-samsung-ld9040.c index c4b388850a13..01eb211f32f7 100644 --- a/drivers/gpu/drm/panel/panel-samsung-ld9040.c +++ b/drivers/gpu/drm/panel/panel-samsung-ld9040.c @@ -358,14 +358,12 @@ static int ld9040_probe(struct spi_device *spi)  	return 0;  } -static int ld9040_remove(struct spi_device *spi) +static void ld9040_remove(struct spi_device *spi)  {  	struct ld9040 *ctx = spi_get_drvdata(spi);  	ld9040_power_off(ctx);  	drm_panel_remove(&ctx->panel); - -	return 0;  }  static const struct of_device_id ld9040_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c index 1696ceb36aa0..2adb223a895c 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6d27a1.c @@ -291,12 +291,11 @@ static int s6d27a1_probe(struct spi_device *spi)  	return 0;  } -static int s6d27a1_remove(struct spi_device *spi) +static void s6d27a1_remove(struct spi_device *spi)  {  	struct s6d27a1 *ctx = spi_get_drvdata(spi);  	drm_panel_remove(&ctx->panel); -	return 0;  }  static const struct of_device_id s6d27a1_match[] = { diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c index c178d962b0d5..d99afcc672ca 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c @@ -62,10 +62,9 @@ static int s6e63m0_spi_probe(struct spi_device *spi)  			     s6e63m0_spi_dcs_write, false);  } -static int s6e63m0_spi_remove(struct spi_device *spi) +static void s6e63m0_spi_remove(struct spi_device *spi)  {  	s6e63m0_remove(&spi->dev); -	return 0;  }  static const struct of_device_id s6e63m0_spi_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c index 61e565524542..bbc4569cbcdc 100644 --- a/drivers/gpu/drm/panel/panel-sitronix-st7789v.c +++ b/drivers/gpu/drm/panel/panel-sitronix-st7789v.c @@ -387,13 +387,11 @@ static int st7789v_probe(struct spi_device *spi)  	return 0;  } -static int st7789v_remove(struct spi_device *spi) +static void st7789v_remove(struct spi_device *spi)  {  	struct st7789v *ctx = spi_get_drvdata(spi);  	drm_panel_remove(&ctx->panel); - -	return 0;  }  static const struct of_device_id st7789v_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-sony-acx565akm.c b/drivers/gpu/drm/panel/panel-sony-acx565akm.c index ba0b3ead150f..0d7541a33f87 100644 --- a/drivers/gpu/drm/panel/panel-sony-acx565akm.c +++ b/drivers/gpu/drm/panel/panel-sony-acx565akm.c @@ -655,7 +655,7 @@ static int acx565akm_probe(struct spi_device *spi)  	return 0;  } -static int acx565akm_remove(struct spi_device *spi) +static void acx565akm_remove(struct spi_device *spi)  {  	struct acx565akm_panel *lcd = spi_get_drvdata(spi); @@ -666,8 +666,6 @@ static int acx565akm_remove(struct spi_device *spi)  	drm_panel_disable(&lcd->panel);  	drm_panel_unprepare(&lcd->panel); - -	return 0;  }  static const struct of_device_id acx565akm_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c index ba0c00d1a001..4dbf8b88f264 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td028ttec1.c @@ -350,15 +350,13 @@ static int td028ttec1_probe(struct spi_device *spi)  	return 0;  } -static int td028ttec1_remove(struct spi_device *spi) +static void td028ttec1_remove(struct spi_device *spi)  {  	struct td028ttec1_panel *lcd = spi_get_drvdata(spi);  	drm_panel_remove(&lcd->panel);  	drm_panel_disable(&lcd->panel);  	drm_panel_unprepare(&lcd->panel); - -	return 0;  }  static const struct of_device_id td028ttec1_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c index 1866cdb8f9c1..cf4609bb9b1d 100644 --- a/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c +++ b/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c @@ -463,7 +463,7 @@ static int td043mtea1_probe(struct spi_device *spi)  	return 0;  } -static int td043mtea1_remove(struct spi_device *spi) +static void td043mtea1_remove(struct spi_device *spi)  {  	struct td043mtea1_panel *lcd = spi_get_drvdata(spi); @@ -472,8 +472,6 @@ static int td043mtea1_remove(struct spi_device *spi)  	drm_panel_unprepare(&lcd->panel);  	sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group); - -	return 0;  }  static const struct of_device_id td043mtea1_of_match[] = { diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c index e3791dad6830..0b1f5a11a055 100644 --- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c +++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c @@ -450,12 +450,11 @@ static int tpg110_probe(struct spi_device *spi)  	return 0;  } -static int tpg110_remove(struct spi_device *spi) +static void tpg110_remove(struct spi_device *spi)  {  	struct tpg110 *tpg = spi_get_drvdata(spi);  	drm_panel_remove(&tpg->panel); -	return 0;  }  static const struct of_device_id tpg110_match[] = { diff --git a/drivers/gpu/drm/panel/panel-widechips-ws2401.c b/drivers/gpu/drm/panel/panel-widechips-ws2401.c index 8bc976f54b80..236f3cb2b594 100644 --- a/drivers/gpu/drm/panel/panel-widechips-ws2401.c +++ b/drivers/gpu/drm/panel/panel-widechips-ws2401.c @@ -407,12 +407,11 @@ static int ws2401_probe(struct spi_device *spi)  	return 0;  } -static int ws2401_remove(struct spi_device *spi) +static void ws2401_remove(struct spi_device *spi)  {  	struct ws2401 *ws = spi_get_drvdata(spi);  	drm_panel_remove(&ws->panel); -	return 0;  }  /* diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index 9b33c05732aa..ebb025543f8d 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -263,14 +263,12 @@ static int hx8357d_probe(struct spi_device *spi)  	return 0;  } -static int hx8357d_remove(struct spi_device *spi) +static void hx8357d_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void hx8357d_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index bcc181351236..fc8ed245b0bc 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -193,14 +193,12 @@ static int ili9163_probe(struct spi_device *spi)  	return 0;  } -static int ili9163_remove(struct spi_device *spi) +static void ili9163_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void ili9163_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index 976d3209f164..cc92eb9f2a07 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -411,14 +411,12 @@ static int ili9225_probe(struct spi_device *spi)  	return 0;  } -static int ili9225_remove(struct spi_device *spi) +static void ili9225_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void ili9225_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index 37e0c33399c8..5b8cc770ee7b 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -225,14 +225,12 @@ static int ili9341_probe(struct spi_device *spi)  	return 0;  } -static int ili9341_remove(struct spi_device *spi) +static void ili9341_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void ili9341_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index e9a63f4b2993..6d655e18e0aa 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -243,14 +243,12 @@ static int ili9486_probe(struct spi_device *spi)  	return 0;  } -static int ili9486_remove(struct spi_device *spi) +static void ili9486_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void ili9486_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 023de49e7a8e..5e060f6910bb 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -233,14 +233,12 @@ static int mi0283qt_probe(struct spi_device *spi)  	return 0;  } -static int mi0283qt_remove(struct spi_device *spi) +static void mi0283qt_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void mi0283qt_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 97a775c48cea..beeeb170d0b1 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -1140,14 +1140,12 @@ static int repaper_probe(struct spi_device *spi)  	return 0;  } -static int repaper_remove(struct spi_device *spi) +static void repaper_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void repaper_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 51b9b9fb3ead..3f38faa1cd8c 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -360,14 +360,12 @@ static int st7586_probe(struct spi_device *spi)  	return 0;  } -static int st7586_remove(struct spi_device *spi) +static void st7586_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void st7586_shutdown(struct spi_device *spi) diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index fc40dd10efa8..29d618093e94 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -247,14 +247,12 @@ static int st7735r_probe(struct spi_device *spi)  	return 0;  } -static int st7735r_remove(struct spi_device *spi) +static void st7735r_remove(struct spi_device *spi)  {  	struct drm_device *drm = spi_get_drvdata(spi);  	drm_dev_unplug(drm);  	drm_atomic_helper_shutdown(drm); - -	return 0;  }  static void st7735r_shutdown(struct spi_device *spi) diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c index e5bc5ce09f4e..de37bce24fa6 100644 --- a/drivers/hwmon/adcxx.c +++ b/drivers/hwmon/adcxx.c @@ -194,7 +194,7 @@ out_err:  	return status;  } -static int adcxx_remove(struct spi_device *spi) +static void adcxx_remove(struct spi_device *spi)  {  	struct adcxx *adc = spi_get_drvdata(spi);  	int i; @@ -205,8 +205,6 @@ static int adcxx_remove(struct spi_device *spi)  		device_remove_file(&spi->dev, &ad_input[i].dev_attr);  	mutex_unlock(&adc->lock); - -	return 0;  }  static const struct spi_device_id adcxx_ids[] = { diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index 5fcfd57df61e..4c5487aeb3cf 100644 --- a/drivers/hwmon/max1111.c +++ b/drivers/hwmon/max1111.c @@ -254,7 +254,7 @@ err_remove:  	return err;  } -static int max1111_remove(struct spi_device *spi) +static void max1111_remove(struct spi_device *spi)  {  	struct max1111_data *data = spi_get_drvdata(spi); @@ -265,7 +265,6 @@ static int max1111_remove(struct spi_device *spi)  	sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group);  	sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);  	mutex_destroy(&data->drvdata_lock); -	return 0;  }  static const struct spi_device_id max1111_ids[] = { diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c index 4cf4fe6809a3..93e048ee4955 100644 --- a/drivers/hwmon/max31722.c +++ b/drivers/hwmon/max31722.c @@ -100,7 +100,7 @@ static int max31722_probe(struct spi_device *spi)  	return 0;  } -static int max31722_remove(struct spi_device *spi) +static void max31722_remove(struct spi_device *spi)  {  	struct max31722_data *data = spi_get_drvdata(spi);  	int ret; @@ -111,8 +111,6 @@ static int max31722_remove(struct spi_device *spi)  	if (ret)  		/* There is nothing we can do about this ... */  		dev_warn(&spi->dev, "Failed to put device in stand-by mode\n"); - -	return 0;  }  static int __maybe_unused max31722_suspend(struct device *dev) diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c index 9f622e37477b..9040a717b247 100644 --- a/drivers/iio/accel/bma400_spi.c +++ b/drivers/iio/accel/bma400_spi.c @@ -87,11 +87,9 @@ static int bma400_spi_probe(struct spi_device *spi)  	return bma400_probe(&spi->dev, regmap, id->name);  } -static int bma400_spi_remove(struct spi_device *spi) +static void bma400_spi_remove(struct spi_device *spi)  {  	bma400_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id bma400_spi_ids[] = { diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c index 11559567cb39..80007cc2d044 100644 --- a/drivers/iio/accel/bmc150-accel-spi.c +++ b/drivers/iio/accel/bmc150-accel-spi.c @@ -35,11 +35,9 @@ static int bmc150_accel_probe(struct spi_device *spi)  				       true);  } -static int bmc150_accel_remove(struct spi_device *spi) +static void bmc150_accel_remove(struct spi_device *spi)  {  	bmc150_accel_core_remove(&spi->dev); - -	return 0;  }  static const struct acpi_device_id bmc150_accel_acpi_match[] = { diff --git a/drivers/iio/accel/bmi088-accel-spi.c b/drivers/iio/accel/bmi088-accel-spi.c index 758ad2f12896..06d99d9949f3 100644 --- a/drivers/iio/accel/bmi088-accel-spi.c +++ b/drivers/iio/accel/bmi088-accel-spi.c @@ -56,11 +56,9 @@ static int bmi088_accel_probe(struct spi_device *spi)  				       true);  } -static int bmi088_accel_remove(struct spi_device *spi) +static void bmi088_accel_remove(struct spi_device *spi)  {  	bmi088_accel_core_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id bmi088_accel_id[] = { diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c index 441e6b764281..57c451cfb9e5 100644 --- a/drivers/iio/accel/kxsd9-spi.c +++ b/drivers/iio/accel/kxsd9-spi.c @@ -32,11 +32,9 @@ static int kxsd9_spi_probe(struct spi_device *spi)  				  spi_get_device_id(spi)->name);  } -static int kxsd9_spi_remove(struct spi_device *spi) +static void kxsd9_spi_remove(struct spi_device *spi)  {  	kxsd9_common_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id kxsd9_spi_id[] = { diff --git a/drivers/iio/accel/mma7455_spi.c b/drivers/iio/accel/mma7455_spi.c index ecf690692dcc..b746031551a3 100644 --- a/drivers/iio/accel/mma7455_spi.c +++ b/drivers/iio/accel/mma7455_spi.c @@ -22,11 +22,9 @@ static int mma7455_spi_probe(struct spi_device *spi)  	return mma7455_core_probe(&spi->dev, regmap, id->name);  } -static int mma7455_spi_remove(struct spi_device *spi) +static void mma7455_spi_remove(struct spi_device *spi)  {  	mma7455_core_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id mma7455_spi_ids[] = { diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c index 43ecacbdc95a..83c81072511e 100644 --- a/drivers/iio/accel/sca3000.c +++ b/drivers/iio/accel/sca3000.c @@ -1524,7 +1524,7 @@ error_ret:  	return ret;  } -static int sca3000_remove(struct spi_device *spi) +static void sca3000_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct sca3000_state *st = iio_priv(indio_dev); @@ -1535,8 +1535,6 @@ static int sca3000_remove(struct spi_device *spi)  	sca3000_stop_all_interrupts(st);  	if (spi->irq)  		free_irq(spi->irq, indio_dev); - -	return 0;  }  static const struct spi_device_id sca3000_id[] = { diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 1d345d66742d..c17d9b5fbaf6 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c @@ -479,7 +479,7 @@ error_disable_reg:  	return ret;  } -static int ad7266_remove(struct spi_device *spi) +static void ad7266_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad7266_state *st = iio_priv(indio_dev); @@ -488,8 +488,6 @@ static int ad7266_remove(struct spi_device *spi)  	iio_triggered_buffer_cleanup(indio_dev);  	if (!IS_ERR(st->reg))  		regulator_disable(st->reg); - -	return 0;  }  static const struct spi_device_id ad7266_id[] = { diff --git a/drivers/iio/adc/ltc2496.c b/drivers/iio/adc/ltc2496.c index dd956a7c216e..5a55f79f2574 100644 --- a/drivers/iio/adc/ltc2496.c +++ b/drivers/iio/adc/ltc2496.c @@ -78,13 +78,11 @@ static int ltc2496_probe(struct spi_device *spi)  	return ltc2497core_probe(dev, indio_dev);  } -static int ltc2496_remove(struct spi_device *spi) +static void ltc2496_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	ltc2497core_remove(indio_dev); - -	return 0;  }  static const struct of_device_id ltc2496_of_match[] = { diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 8d1cff28cae0..b4c69acb33e3 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -459,15 +459,13 @@ reg_disable:  	return ret;  } -static int mcp320x_remove(struct spi_device *spi) +static void mcp320x_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct mcp320x *adc = iio_priv(indio_dev);  	iio_device_unregister(indio_dev);  	regulator_disable(adc->reg); - -	return 0;  }  static const struct of_device_id mcp320x_dt_ids[] = { diff --git a/drivers/iio/adc/mcp3911.c b/drivers/iio/adc/mcp3911.c index 13535f148c4c..1cb4590fe412 100644 --- a/drivers/iio/adc/mcp3911.c +++ b/drivers/iio/adc/mcp3911.c @@ -321,7 +321,7 @@ reg_disable:  	return ret;  } -static int mcp3911_remove(struct spi_device *spi) +static void mcp3911_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct mcp3911 *adc = iio_priv(indio_dev); @@ -331,8 +331,6 @@ static int mcp3911_remove(struct spi_device *spi)  	clk_disable_unprepare(adc->clki);  	if (adc->vref)  		regulator_disable(adc->vref); - -	return 0;  }  static const struct of_device_id mcp3911_dt_ids[] = { diff --git a/drivers/iio/adc/ti-adc12138.c b/drivers/iio/adc/ti-adc12138.c index 6eb62b564dae..59d75d09604f 100644 --- a/drivers/iio/adc/ti-adc12138.c +++ b/drivers/iio/adc/ti-adc12138.c @@ -503,7 +503,7 @@ err_clk_disable:  	return ret;  } -static int adc12138_remove(struct spi_device *spi) +static void adc12138_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct adc12138 *adc = iio_priv(indio_dev); @@ -514,8 +514,6 @@ static int adc12138_remove(struct spi_device *spi)  		regulator_disable(adc->vref_n);  	regulator_disable(adc->vref_p);  	clk_disable_unprepare(adc->cclk); - -	return 0;  }  static const struct of_device_id adc12138_dt_ids[] = { diff --git a/drivers/iio/adc/ti-ads7950.c b/drivers/iio/adc/ti-ads7950.c index a7efa3eada2c..e3658b969c5b 100644 --- a/drivers/iio/adc/ti-ads7950.c +++ b/drivers/iio/adc/ti-ads7950.c @@ -662,7 +662,7 @@ error_destroy_mutex:  	return ret;  } -static int ti_ads7950_remove(struct spi_device *spi) +static void ti_ads7950_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ti_ads7950_state *st = iio_priv(indio_dev); @@ -672,8 +672,6 @@ static int ti_ads7950_remove(struct spi_device *spi)  	iio_triggered_buffer_cleanup(indio_dev);  	regulator_disable(st->reg);  	mutex_destroy(&st->slock); - -	return 0;  }  static const struct spi_device_id ti_ads7950_id[] = { diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 2e24717d7f55..22c2583eedd0 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -479,7 +479,7 @@ err_regulator_disable:  	return ret;  } -static int ads8688_remove(struct spi_device *spi) +static void ads8688_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ads8688_state *st = iio_priv(indio_dev); @@ -489,8 +489,6 @@ static int ads8688_remove(struct spi_device *spi)  	if (!IS_ERR(st->reg))  		regulator_disable(st->reg); - -	return 0;  }  static const struct spi_device_id ads8688_id[] = { diff --git a/drivers/iio/adc/ti-tlc4541.c b/drivers/iio/adc/ti-tlc4541.c index 403b787f9f7e..2406eda9dfc6 100644 --- a/drivers/iio/adc/ti-tlc4541.c +++ b/drivers/iio/adc/ti-tlc4541.c @@ -224,7 +224,7 @@ error_disable_reg:  	return ret;  } -static int tlc4541_remove(struct spi_device *spi) +static void tlc4541_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct tlc4541_state *st = iio_priv(indio_dev); @@ -232,8 +232,6 @@ static int tlc4541_remove(struct spi_device *spi)  	iio_device_unregister(indio_dev);  	iio_triggered_buffer_cleanup(indio_dev);  	regulator_disable(st->reg); - -	return 0;  }  static const struct of_device_id tlc4541_dt_ids[] = { diff --git a/drivers/iio/amplifiers/ad8366.c b/drivers/iio/amplifiers/ad8366.c index cfcf18a0bce8..1134ae12e531 100644 --- a/drivers/iio/amplifiers/ad8366.c +++ b/drivers/iio/amplifiers/ad8366.c @@ -298,7 +298,7 @@ error_disable_reg:  	return ret;  } -static int ad8366_remove(struct spi_device *spi) +static void ad8366_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad8366_state *st = iio_priv(indio_dev); @@ -308,8 +308,6 @@ static int ad8366_remove(struct spi_device *spi)  	if (!IS_ERR(reg))  		regulator_disable(reg); - -	return 0;  }  static const struct spi_device_id ad8366_id[] = { diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c index 1aee87100038..eafaf4529df5 100644 --- a/drivers/iio/common/ssp_sensors/ssp_dev.c +++ b/drivers/iio/common/ssp_sensors/ssp_dev.c @@ -586,7 +586,7 @@ err_setup_irq:  	return ret;  } -static int ssp_remove(struct spi_device *spi) +static void ssp_remove(struct spi_device *spi)  {  	struct ssp_data *data = spi_get_drvdata(spi); @@ -608,8 +608,6 @@ static int ssp_remove(struct spi_device *spi)  	mutex_destroy(&data->pending_lock);  	mfd_remove_devices(&spi->dev); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/iio/dac/ad5360.c b/drivers/iio/dac/ad5360.c index 2d3b14c407d8..ecbc6a51d60f 100644 --- a/drivers/iio/dac/ad5360.c +++ b/drivers/iio/dac/ad5360.c @@ -521,7 +521,7 @@ error_free_channels:  	return ret;  } -static int ad5360_remove(struct spi_device *spi) +static void ad5360_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad5360_state *st = iio_priv(indio_dev); @@ -531,8 +531,6 @@ static int ad5360_remove(struct spi_device *spi)  	kfree(indio_dev->channels);  	regulator_bulk_disable(st->chip_info->num_vrefs, st->vref_reg); - -	return 0;  }  static const struct spi_device_id ad5360_ids[] = { diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index e38860a6a9f3..82e1d9bd773e 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c @@ -488,11 +488,9 @@ static int ad5380_spi_probe(struct spi_device *spi)  	return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);  } -static int ad5380_spi_remove(struct spi_device *spi) +static void ad5380_spi_remove(struct spi_device *spi)  {  	ad5380_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id ad5380_spi_ids[] = { diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 1c9b54c012a7..14cfabacbea5 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c @@ -491,11 +491,9 @@ static int ad5446_spi_probe(struct spi_device *spi)  		&ad5446_spi_chip_info[id->driver_data]);  } -static int ad5446_spi_remove(struct spi_device *spi) +static void ad5446_spi_remove(struct spi_device *spi)  {  	ad5446_remove(&spi->dev); - -	return 0;  }  static struct spi_driver ad5446_spi_driver = { diff --git a/drivers/iio/dac/ad5449.c b/drivers/iio/dac/ad5449.c index f5e93c6acc9d..bad9bdaafa94 100644 --- a/drivers/iio/dac/ad5449.c +++ b/drivers/iio/dac/ad5449.c @@ -330,7 +330,7 @@ error_disable_reg:  	return ret;  } -static int ad5449_spi_remove(struct spi_device *spi) +static void ad5449_spi_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad5449 *st = iio_priv(indio_dev); @@ -338,8 +338,6 @@ static int ad5449_spi_remove(struct spi_device *spi)  	iio_device_unregister(indio_dev);  	regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg); - -	return 0;  }  static const struct spi_device_id ad5449_spi_ids[] = { diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index b631261efa97..8507573aa13e 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -336,7 +336,7 @@ error_disable_reg:  	return ret;  } -static int ad5504_remove(struct spi_device *spi) +static void ad5504_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad5504_state *st = iio_priv(indio_dev); @@ -345,8 +345,6 @@ static int ad5504_remove(struct spi_device *spi)  	if (!IS_ERR(st->reg))  		regulator_disable(st->reg); - -	return 0;  }  static const struct spi_device_id ad5504_id[] = { diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c index 6bfd7951e18c..0f7abfa75bec 100644 --- a/drivers/iio/dac/ad5592r.c +++ b/drivers/iio/dac/ad5592r.c @@ -130,11 +130,9 @@ static int ad5592r_spi_probe(struct spi_device *spi)  	return ad5592r_probe(&spi->dev, id->name, &ad5592r_rw_ops);  } -static int ad5592r_spi_remove(struct spi_device *spi) +static void ad5592r_spi_remove(struct spi_device *spi)  {  	ad5592r_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id ad5592r_spi_ids[] = { diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index 3c98941b9f99..371e812850eb 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c @@ -293,7 +293,7 @@ error_disable_reg:  	return ret;  } -static int ad5624r_remove(struct spi_device *spi) +static void ad5624r_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad5624r_state *st = iio_priv(indio_dev); @@ -301,8 +301,6 @@ static int ad5624r_remove(struct spi_device *spi)  	iio_device_unregister(indio_dev);  	if (!IS_ERR(st->reg))  		regulator_disable(st->reg); - -	return 0;  }  static const struct spi_device_id ad5624r_id[] = { diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c index 2628810fdbb1..d26fb29b6b04 100644 --- a/drivers/iio/dac/ad5686-spi.c +++ b/drivers/iio/dac/ad5686-spi.c @@ -95,11 +95,9 @@ static int ad5686_spi_probe(struct spi_device *spi)  			    ad5686_spi_write, ad5686_spi_read);  } -static int ad5686_spi_remove(struct spi_device *spi) +static void ad5686_spi_remove(struct spi_device *spi)  {  	ad5686_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id ad5686_spi_id[] = { diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c index e37e095e94fc..4cb8471db81e 100644 --- a/drivers/iio/dac/ad5761.c +++ b/drivers/iio/dac/ad5761.c @@ -394,7 +394,7 @@ disable_regulator_err:  	return ret;  } -static int ad5761_remove(struct spi_device *spi) +static void ad5761_remove(struct spi_device *spi)  {  	struct iio_dev *iio_dev = spi_get_drvdata(spi);  	struct ad5761_state *st = iio_priv(iio_dev); @@ -403,8 +403,6 @@ static int ad5761_remove(struct spi_device *spi)  	if (!IS_ERR_OR_NULL(st->vref_reg))  		regulator_disable(st->vref_reg); - -	return 0;  }  static const struct spi_device_id ad5761_id[] = { diff --git a/drivers/iio/dac/ad5764.c b/drivers/iio/dac/ad5764.c index ae089b9145cb..d235a8047ba0 100644 --- a/drivers/iio/dac/ad5764.c +++ b/drivers/iio/dac/ad5764.c @@ -332,7 +332,7 @@ error_disable_reg:  	return ret;  } -static int ad5764_remove(struct spi_device *spi) +static void ad5764_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad5764_state *st = iio_priv(indio_dev); @@ -341,8 +341,6 @@ static int ad5764_remove(struct spi_device *spi)  	if (st->chip_info->int_vref == 0)  		regulator_bulk_disable(ARRAY_SIZE(st->vref_reg), st->vref_reg); - -	return 0;  }  static const struct spi_device_id ad5764_ids[] = { diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index 7b4579d73d18..2b14914b4050 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c @@ -428,7 +428,7 @@ error_disable_reg_pos:  	return ret;  } -static int ad5791_remove(struct spi_device *spi) +static void ad5791_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad5791_state *st = iio_priv(indio_dev); @@ -439,8 +439,6 @@ static int ad5791_remove(struct spi_device *spi)  	if (!IS_ERR(st->reg_vss))  		regulator_disable(st->reg_vss); - -	return 0;  }  static const struct spi_device_id ad5791_id[] = { diff --git a/drivers/iio/dac/ad8801.c b/drivers/iio/dac/ad8801.c index 5ecfdad54dec..6be35c92d435 100644 --- a/drivers/iio/dac/ad8801.c +++ b/drivers/iio/dac/ad8801.c @@ -193,7 +193,7 @@ error_disable_vrefh_reg:  	return ret;  } -static int ad8801_remove(struct spi_device *spi) +static void ad8801_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ad8801_state *state = iio_priv(indio_dev); @@ -202,8 +202,6 @@ static int ad8801_remove(struct spi_device *spi)  	if (state->vrefl_reg)  		regulator_disable(state->vrefl_reg);  	regulator_disable(state->vrefh_reg); - -	return 0;  }  static const struct spi_device_id ad8801_ids[] = { diff --git a/drivers/iio/dac/ltc1660.c b/drivers/iio/dac/ltc1660.c index f6ec9bf5815e..c76233c9bb72 100644 --- a/drivers/iio/dac/ltc1660.c +++ b/drivers/iio/dac/ltc1660.c @@ -206,15 +206,13 @@ error_disable_reg:  	return ret;  } -static int ltc1660_remove(struct spi_device *spi) +static void ltc1660_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ltc1660_priv *priv = iio_priv(indio_dev);  	iio_device_unregister(indio_dev);  	regulator_disable(priv->vref_reg); - -	return 0;  }  static const struct of_device_id ltc1660_dt_ids[] = { diff --git a/drivers/iio/dac/ltc2632.c b/drivers/iio/dac/ltc2632.c index 53e4b887d372..aed46c80757e 100644 --- a/drivers/iio/dac/ltc2632.c +++ b/drivers/iio/dac/ltc2632.c @@ -372,7 +372,7 @@ static int ltc2632_probe(struct spi_device *spi)  	return iio_device_register(indio_dev);  } -static int ltc2632_remove(struct spi_device *spi) +static void ltc2632_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ltc2632_state *st = iio_priv(indio_dev); @@ -381,8 +381,6 @@ static int ltc2632_remove(struct spi_device *spi)  	if (st->vref_reg)  		regulator_disable(st->vref_reg); - -	return 0;  }  static const struct spi_device_id ltc2632_id[] = { diff --git a/drivers/iio/dac/mcp4922.c b/drivers/iio/dac/mcp4922.c index 0ae414ee1716..cb9e60e71b91 100644 --- a/drivers/iio/dac/mcp4922.c +++ b/drivers/iio/dac/mcp4922.c @@ -172,7 +172,7 @@ error_disable_reg:  	return ret;  } -static int mcp4922_remove(struct spi_device *spi) +static void mcp4922_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct mcp4922_state *state; @@ -180,8 +180,6 @@ static int mcp4922_remove(struct spi_device *spi)  	iio_device_unregister(indio_dev);  	state = iio_priv(indio_dev);  	regulator_disable(state->vref_reg); - -	return 0;  }  static const struct spi_device_id mcp4922_id[] = { diff --git a/drivers/iio/dac/ti-dac082s085.c b/drivers/iio/dac/ti-dac082s085.c index 6beda2193683..4e1156e6deb2 100644 --- a/drivers/iio/dac/ti-dac082s085.c +++ b/drivers/iio/dac/ti-dac082s085.c @@ -313,7 +313,7 @@ err:  	return ret;  } -static int ti_dac_remove(struct spi_device *spi) +static void ti_dac_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ti_dac_chip *ti_dac = iio_priv(indio_dev); @@ -321,8 +321,6 @@ static int ti_dac_remove(struct spi_device *spi)  	iio_device_unregister(indio_dev);  	mutex_destroy(&ti_dac->lock);  	regulator_disable(ti_dac->vref); - -	return 0;  }  static const struct of_device_id ti_dac_of_id[] = { diff --git a/drivers/iio/dac/ti-dac7311.c b/drivers/iio/dac/ti-dac7311.c index 99f275829ec2..e10d17e60ed3 100644 --- a/drivers/iio/dac/ti-dac7311.c +++ b/drivers/iio/dac/ti-dac7311.c @@ -292,7 +292,7 @@ err:  	return ret;  } -static int ti_dac_remove(struct spi_device *spi) +static void ti_dac_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct ti_dac_chip *ti_dac = iio_priv(indio_dev); @@ -300,7 +300,6 @@ static int ti_dac_remove(struct spi_device *spi)  	iio_device_unregister(indio_dev);  	mutex_destroy(&ti_dac->lock);  	regulator_disable(ti_dac->vref); -	return 0;  }  static const struct of_device_id ti_dac_of_id[] = { diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 3d9eba716b69..f3521330f6fb 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -589,7 +589,7 @@ error_disable_clk:  	return ret;  } -static int adf4350_remove(struct spi_device *spi) +static void adf4350_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct adf4350_state *st = iio_priv(indio_dev); @@ -604,8 +604,6 @@ static int adf4350_remove(struct spi_device *spi)  	if (!IS_ERR(reg))  		regulator_disable(reg); - -	return 0;  }  static const struct of_device_id adf4350_of_match[] = { diff --git a/drivers/iio/gyro/bmg160_spi.c b/drivers/iio/gyro/bmg160_spi.c index 745962e1e423..fc2e453527b9 100644 --- a/drivers/iio/gyro/bmg160_spi.c +++ b/drivers/iio/gyro/bmg160_spi.c @@ -27,11 +27,9 @@ static int bmg160_spi_probe(struct spi_device *spi)  	return bmg160_core_probe(&spi->dev, regmap, spi->irq, id->name);  } -static int bmg160_spi_remove(struct spi_device *spi) +static void bmg160_spi_remove(struct spi_device *spi)  {  	bmg160_core_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id bmg160_spi_id[] = { diff --git a/drivers/iio/gyro/fxas21002c_spi.c b/drivers/iio/gyro/fxas21002c_spi.c index 77ceebef4e34..c3ac169facf9 100644 --- a/drivers/iio/gyro/fxas21002c_spi.c +++ b/drivers/iio/gyro/fxas21002c_spi.c @@ -34,11 +34,9 @@ static int fxas21002c_spi_probe(struct spi_device *spi)  	return fxas21002c_core_probe(&spi->dev, regmap, spi->irq, id->name);  } -static int fxas21002c_spi_remove(struct spi_device *spi) +static void fxas21002c_spi_remove(struct spi_device *spi)  {  	fxas21002c_core_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id fxas21002c_spi_id[] = { diff --git a/drivers/iio/health/afe4403.c b/drivers/iio/health/afe4403.c index 273f16dcaff8..856ec901b091 100644 --- a/drivers/iio/health/afe4403.c +++ b/drivers/iio/health/afe4403.c @@ -570,7 +570,7 @@ err_disable_reg:  	return ret;  } -static int afe4403_remove(struct spi_device *spi) +static void afe4403_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	struct afe4403_data *afe = iio_priv(indio_dev); @@ -586,8 +586,6 @@ static int afe4403_remove(struct spi_device *spi)  	ret = regulator_disable(afe->regulator);  	if (ret)  		dev_warn(afe->dev, "Unable to disable regulator\n"); - -	return 0;  }  static const struct spi_device_id afe4403_ids[] = { diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c index c6ed3ea8460a..4c570412d65c 100644 --- a/drivers/iio/magnetometer/bmc150_magn_spi.c +++ b/drivers/iio/magnetometer/bmc150_magn_spi.c @@ -29,11 +29,9 @@ static int bmc150_magn_spi_probe(struct spi_device *spi)  	return bmc150_magn_probe(&spi->dev, regmap, spi->irq, id->name);  } -static int bmc150_magn_spi_remove(struct spi_device *spi) +static void bmc150_magn_spi_remove(struct spi_device *spi)  {  	bmc150_magn_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id bmc150_magn_spi_id[] = { diff --git a/drivers/iio/magnetometer/hmc5843_spi.c b/drivers/iio/magnetometer/hmc5843_spi.c index 89cf59a62c28..a99dd9b33e95 100644 --- a/drivers/iio/magnetometer/hmc5843_spi.c +++ b/drivers/iio/magnetometer/hmc5843_spi.c @@ -74,11 +74,9 @@ static int hmc5843_spi_probe(struct spi_device *spi)  			id->driver_data, id->name);  } -static int hmc5843_spi_remove(struct spi_device *spi) +static void hmc5843_spi_remove(struct spi_device *spi)  {  	hmc5843_common_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id hmc5843_id[] = { diff --git a/drivers/iio/potentiometer/max5487.c b/drivers/iio/potentiometer/max5487.c index 007c2bd324cb..42723c996c9f 100644 --- a/drivers/iio/potentiometer/max5487.c +++ b/drivers/iio/potentiometer/max5487.c @@ -112,7 +112,7 @@ static int max5487_spi_probe(struct spi_device *spi)  	return iio_device_register(indio_dev);  } -static int max5487_spi_remove(struct spi_device *spi) +static void max5487_spi_remove(struct spi_device *spi)  {  	struct iio_dev *indio_dev = spi_get_drvdata(spi);  	int ret; @@ -123,8 +123,6 @@ static int max5487_spi_remove(struct spi_device *spi)  	ret = max5487_write_cmd(spi, MAX5487_COPY_AB_TO_NV);  	if (ret)  		dev_warn(&spi->dev, "Failed to save wiper regs to NV regs\n"); - -	return 0;  }  static const struct spi_device_id max5487_id[] = { diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c index 9fa2dcd71760..7ccd960ced5d 100644 --- a/drivers/iio/pressure/ms5611_spi.c +++ b/drivers/iio/pressure/ms5611_spi.c @@ -107,11 +107,9 @@ static int ms5611_spi_probe(struct spi_device *spi)  			    spi_get_device_id(spi)->driver_data);  } -static int ms5611_spi_remove(struct spi_device *spi) +static void ms5611_spi_remove(struct spi_device *spi)  {  	ms5611_remove(spi_get_drvdata(spi)); - -	return 0;  }  static const struct of_device_id ms5611_spi_matches[] = { diff --git a/drivers/iio/pressure/zpa2326_spi.c b/drivers/iio/pressure/zpa2326_spi.c index 85201a4bae44..ee8ed77536ca 100644 --- a/drivers/iio/pressure/zpa2326_spi.c +++ b/drivers/iio/pressure/zpa2326_spi.c @@ -57,11 +57,9 @@ static int zpa2326_probe_spi(struct spi_device *spi)  			     spi->irq, ZPA2326_DEVICE_ID, regmap);  } -static int zpa2326_remove_spi(struct spi_device *spi) +static void zpa2326_remove_spi(struct spi_device *spi)  {  	zpa2326_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id zpa2326_spi_ids[] = { diff --git a/drivers/input/keyboard/applespi.c b/drivers/input/keyboard/applespi.c index eda1b23002b5..d1f5354d5ea2 100644 --- a/drivers/input/keyboard/applespi.c +++ b/drivers/input/keyboard/applespi.c @@ -1858,7 +1858,7 @@ static void applespi_drain_reads(struct applespi_data *applespi)  	spin_unlock_irqrestore(&applespi->cmd_msg_lock, flags);  } -static int applespi_remove(struct spi_device *spi) +static void applespi_remove(struct spi_device *spi)  {  	struct applespi_data *applespi = spi_get_drvdata(spi); @@ -1871,8 +1871,6 @@ static int applespi_remove(struct spi_device *spi)  	applespi_drain_reads(applespi);  	debugfs_remove_recursive(applespi->debugfs_root); - -	return 0;  }  static void applespi_shutdown(struct spi_device *spi) diff --git a/drivers/input/misc/adxl34x-spi.c b/drivers/input/misc/adxl34x-spi.c index 6e51c9bc619f..91e44d4c66f7 100644 --- a/drivers/input/misc/adxl34x-spi.c +++ b/drivers/input/misc/adxl34x-spi.c @@ -87,13 +87,11 @@ static int adxl34x_spi_probe(struct spi_device *spi)  	return 0;  } -static int adxl34x_spi_remove(struct spi_device *spi) +static void adxl34x_spi_remove(struct spi_device *spi)  {  	struct adxl34x *ac = spi_get_drvdata(spi);  	adxl34x_remove(ac); - -	return 0;  }  static int __maybe_unused adxl34x_spi_suspend(struct device *dev) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index a25a77dd9a32..bed68a68f330 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -1411,13 +1411,11 @@ static int ads7846_probe(struct spi_device *spi)  	return 0;  } -static int ads7846_remove(struct spi_device *spi) +static void ads7846_remove(struct spi_device *spi)  {  	struct ads7846 *ts = spi_get_drvdata(spi);  	ads7846_stop(ts); - -	return 0;  }  static struct spi_driver ads7846_driver = { diff --git a/drivers/input/touchscreen/cyttsp4_spi.c b/drivers/input/touchscreen/cyttsp4_spi.c index 2aec41eb76b7..5d7db84f2749 100644 --- a/drivers/input/touchscreen/cyttsp4_spi.c +++ b/drivers/input/touchscreen/cyttsp4_spi.c @@ -164,12 +164,10 @@ static int cyttsp4_spi_probe(struct spi_device *spi)  	return PTR_ERR_OR_ZERO(ts);  } -static int cyttsp4_spi_remove(struct spi_device *spi) +static void cyttsp4_spi_remove(struct spi_device *spi)  {  	struct cyttsp4 *ts = spi_get_drvdata(spi);  	cyttsp4_remove(ts); - -	return 0;  }  static struct spi_driver cyttsp4_spi_driver = { diff --git a/drivers/input/touchscreen/tsc2005.c b/drivers/input/touchscreen/tsc2005.c index a2f55920b9b2..555dfe98b3c4 100644 --- a/drivers/input/touchscreen/tsc2005.c +++ b/drivers/input/touchscreen/tsc2005.c @@ -64,11 +64,9 @@ static int tsc2005_probe(struct spi_device *spi)  			     tsc2005_cmd);  } -static int tsc2005_remove(struct spi_device *spi) +static void tsc2005_remove(struct spi_device *spi)  {  	tsc200x_remove(&spi->dev); - -	return 0;  }  #ifdef CONFIG_OF diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c index d03cfd3c0bfb..c87686bd7c18 100644 --- a/drivers/leds/leds-cr0014114.c +++ b/drivers/leds/leds-cr0014114.c @@ -266,14 +266,12 @@ static int cr0014114_probe(struct spi_device *spi)  	return 0;  } -static int cr0014114_remove(struct spi_device *spi) +static void cr0014114_remove(struct spi_device *spi)  {  	struct cr0014114 *priv = spi_get_drvdata(spi);  	cancel_delayed_work_sync(&priv->work);  	mutex_destroy(&priv->lock); - -	return 0;  }  static const struct of_device_id cr0014114_dt_ids[] = { diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c index 20dc9b9d7dea..cf5fb1195f87 100644 --- a/drivers/leds/leds-dac124s085.c +++ b/drivers/leds/leds-dac124s085.c @@ -85,15 +85,13 @@ eledcr:  	return ret;  } -static int dac124s085_remove(struct spi_device *spi) +static void dac124s085_remove(struct spi_device *spi)  {  	struct dac124s085	*dac = spi_get_drvdata(spi);  	int i;  	for (i = 0; i < ARRAY_SIZE(dac->leds); i++)  		led_classdev_unregister(&dac->leds[i].ldev); - -	return 0;  }  static struct spi_driver dac124s085_driver = { diff --git a/drivers/leds/leds-el15203000.c b/drivers/leds/leds-el15203000.c index f9eb59a25570..7e7b617bcd56 100644 --- a/drivers/leds/leds-el15203000.c +++ b/drivers/leds/leds-el15203000.c @@ -315,13 +315,11 @@ static int el15203000_probe(struct spi_device *spi)  	return el15203000_probe_dt(priv);  } -static int el15203000_remove(struct spi_device *spi) +static void el15203000_remove(struct spi_device *spi)  {  	struct el15203000 *priv = spi_get_drvdata(spi);  	mutex_destroy(&priv->lock); - -	return 0;  }  static const struct of_device_id el15203000_dt_ids[] = { diff --git a/drivers/leds/leds-spi-byte.c b/drivers/leds/leds-spi-byte.c index f1964c96fb15..2bc5c99daf51 100644 --- a/drivers/leds/leds-spi-byte.c +++ b/drivers/leds/leds-spi-byte.c @@ -130,13 +130,11 @@ static int spi_byte_probe(struct spi_device *spi)  	return 0;  } -static int spi_byte_remove(struct spi_device *spi) +static void spi_byte_remove(struct spi_device *spi)  {  	struct spi_byte_led	*led = spi_get_drvdata(spi);  	mutex_destroy(&led->mutex); - -	return 0;  }  static struct spi_driver spi_byte_driver = { diff --git a/drivers/media/spi/cxd2880-spi.c b/drivers/media/spi/cxd2880-spi.c index 6f2a66bc87fb..6be4e5528879 100644 --- a/drivers/media/spi/cxd2880-spi.c +++ b/drivers/media/spi/cxd2880-spi.c @@ -625,7 +625,7 @@ fail_regulator:  	return ret;  } -static int +static void  cxd2880_spi_remove(struct spi_device *spi)  {  	struct cxd2880_dvb_spi *dvb_spi = spi_get_drvdata(spi); @@ -643,8 +643,6 @@ cxd2880_spi_remove(struct spi_device *spi)  	kfree(dvb_spi);  	pr_info("cxd2880_spi remove ok.\n"); - -	return 0;  }  static const struct spi_device_id cxd2880_spi_id[] = { diff --git a/drivers/media/spi/gs1662.c b/drivers/media/spi/gs1662.c index f86ef1ca1288..75c21a93e6d0 100644 --- a/drivers/media/spi/gs1662.c +++ b/drivers/media/spi/gs1662.c @@ -458,13 +458,11 @@ static int gs_probe(struct spi_device *spi)  	return ret;  } -static int gs_remove(struct spi_device *spi) +static void gs_remove(struct spi_device *spi)  {  	struct v4l2_subdev *sd = spi_get_drvdata(spi);  	v4l2_device_unregister_subdev(sd); - -	return 0;  }  static struct spi_driver gs_driver = { diff --git a/drivers/media/tuners/msi001.c b/drivers/media/tuners/msi001.c index 44247049a319..ad6c72c1ed04 100644 --- a/drivers/media/tuners/msi001.c +++ b/drivers/media/tuners/msi001.c @@ -472,7 +472,7 @@ err:  	return ret;  } -static int msi001_remove(struct spi_device *spi) +static void msi001_remove(struct spi_device *spi)  {  	struct v4l2_subdev *sd = spi_get_drvdata(spi);  	struct msi001_dev *dev = sd_to_msi001_dev(sd); @@ -486,7 +486,6 @@ static int msi001_remove(struct spi_device *spi)  	v4l2_device_unregister_subdev(&dev->sd);  	v4l2_ctrl_handler_free(&dev->hdl);  	kfree(dev); -	return 0;  }  static const struct spi_device_id msi001_id_table[] = { diff --git a/drivers/mfd/arizona-spi.c b/drivers/mfd/arizona-spi.c index 9fe06dda3782..03620c8efe34 100644 --- a/drivers/mfd/arizona-spi.c +++ b/drivers/mfd/arizona-spi.c @@ -206,13 +206,11 @@ static int arizona_spi_probe(struct spi_device *spi)  	return arizona_dev_init(arizona);  } -static int arizona_spi_remove(struct spi_device *spi) +static void arizona_spi_remove(struct spi_device *spi)  {  	struct arizona *arizona = spi_get_drvdata(spi);  	arizona_dev_exit(arizona); - -	return 0;  }  static const struct spi_device_id arizona_spi_ids[] = { diff --git a/drivers/mfd/da9052-spi.c b/drivers/mfd/da9052-spi.c index 5faf3766a5e2..b79a57b45c1e 100644 --- a/drivers/mfd/da9052-spi.c +++ b/drivers/mfd/da9052-spi.c @@ -55,12 +55,11 @@ static int da9052_spi_probe(struct spi_device *spi)  	return da9052_device_init(da9052, id->driver_data);  } -static int da9052_spi_remove(struct spi_device *spi) +static void da9052_spi_remove(struct spi_device *spi)  {  	struct da9052 *da9052 = spi_get_drvdata(spi);  	da9052_device_exit(da9052); -	return 0;  }  static const struct spi_device_id da9052_spi_id[] = { diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index b14d3f98e1eb..3d5ce18aa9ae 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -390,7 +390,7 @@ static int pcap_add_subdev(struct pcap_chip *pcap,  	return ret;  } -static int ezx_pcap_remove(struct spi_device *spi) +static void ezx_pcap_remove(struct spi_device *spi)  {  	struct pcap_chip *pcap = spi_get_drvdata(spi);  	unsigned long flags; @@ -410,8 +410,6 @@ static int ezx_pcap_remove(struct spi_device *spi)  		irq_set_chip_and_handler(i, NULL, NULL);  	destroy_workqueue(pcap->workqueue); - -	return 0;  }  static int ezx_pcap_probe(struct spi_device *spi) diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c index f10e53187f67..9ffab9aafd81 100644 --- a/drivers/mfd/lpc_ich.c +++ b/drivers/mfd/lpc_ich.c @@ -63,6 +63,8 @@  #define SPIBASE_BYT		0x54  #define SPIBASE_BYT_SZ		512  #define SPIBASE_BYT_EN		BIT(1) +#define BYT_BCR			0xfc +#define BYT_BCR_WPD		BIT(0)  #define SPIBASE_LPT		0x3800  #define SPIBASE_LPT_SZ		512 @@ -1084,12 +1086,57 @@ wdt_done:  	return ret;  } +static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data) +{ +	u32 val; + +	val = readl(base + BYT_BCR); +	if (!(val & BYT_BCR_WPD)) { +		val |= BYT_BCR_WPD; +		writel(val, base + BYT_BCR); +		val = readl(base + BYT_BCR); +	} + +	return val & BYT_BCR_WPD; +} + +static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data) +{ +	struct pci_dev *pdev = data; +	u32 bcr; + +	pci_read_config_dword(pdev, BCR, &bcr); +	if (!(bcr & BCR_WPD)) { +		bcr |= BCR_WPD; +		pci_write_config_dword(pdev, BCR, bcr); +		pci_read_config_dword(pdev, BCR, &bcr); +	} + +	return bcr & BCR_WPD; +} + +static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data) +{ +	unsigned int spi = PCI_DEVFN(13, 2); +	struct pci_bus *bus = data; +	u32 bcr; + +	pci_bus_read_config_dword(bus, spi, BCR, &bcr); +	if (!(bcr & BCR_WPD)) { +		bcr |= BCR_WPD; +		pci_bus_write_config_dword(bus, spi, BCR, bcr); +		pci_bus_read_config_dword(bus, spi, BCR, &bcr); +	} + +	return bcr & BCR_WPD; +} +  static int lpc_ich_init_spi(struct pci_dev *dev)  {  	struct lpc_ich_priv *priv = pci_get_drvdata(dev);  	struct resource *res = &intel_spi_res[0];  	struct intel_spi_boardinfo *info; -	u32 spi_base, rcba, bcr; +	u32 spi_base, rcba;  	info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);  	if (!info) @@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)  		if (spi_base & SPIBASE_BYT_EN) {  			res->start = spi_base & ~(SPIBASE_BYT_SZ - 1);  			res->end = res->start + SPIBASE_BYT_SZ - 1; + +			info->set_writeable = lpc_ich_byt_set_writeable;  		}  		break; @@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)  			res->start = spi_base + SPIBASE_LPT;  			res->end = res->start + SPIBASE_LPT_SZ - 1; -			pci_read_config_dword(dev, BCR, &bcr); -			info->writeable = !!(bcr & BCR_WPD); +			info->set_writeable = lpc_ich_lpt_set_writeable; +			info->data = dev;  		}  		break; @@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)  			res->start = spi_base & 0xfffffff0;  			res->end = res->start + SPIBASE_APL_SZ - 1; -			pci_bus_read_config_dword(bus, spi, BCR, &bcr); -			info->writeable = !!(bcr & BCR_WPD); +			info->set_writeable = lpc_ich_bxt_set_writeable; +			info->data = bus;  		}  		pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1); diff --git a/drivers/mfd/madera-spi.c b/drivers/mfd/madera-spi.c index e860f5ff0933..da84eb50e53a 100644 --- a/drivers/mfd/madera-spi.c +++ b/drivers/mfd/madera-spi.c @@ -112,13 +112,11 @@ static int madera_spi_probe(struct spi_device *spi)  	return madera_dev_init(madera);  } -static int madera_spi_remove(struct spi_device *spi) +static void madera_spi_remove(struct spi_device *spi)  {  	struct madera *madera = spi_get_drvdata(spi);  	madera_dev_exit(madera); - -	return 0;  }  static const struct spi_device_id madera_spi_ids[] = { diff --git a/drivers/mfd/mc13xxx-spi.c b/drivers/mfd/mc13xxx-spi.c index 4d8913d647e6..f803527e5819 100644 --- a/drivers/mfd/mc13xxx-spi.c +++ b/drivers/mfd/mc13xxx-spi.c @@ -166,10 +166,9 @@ static int mc13xxx_spi_probe(struct spi_device *spi)  	return mc13xxx_common_init(&spi->dev);  } -static int mc13xxx_spi_remove(struct spi_device *spi) +static void mc13xxx_spi_remove(struct spi_device *spi)  {  	mc13xxx_common_exit(&spi->dev); -	return 0;  }  static struct spi_driver mc13xxx_spi_driver = { diff --git a/drivers/mfd/rsmu_spi.c b/drivers/mfd/rsmu_spi.c index fec2b4ec477c..d2f3d8f1e05a 100644 --- a/drivers/mfd/rsmu_spi.c +++ b/drivers/mfd/rsmu_spi.c @@ -220,13 +220,11 @@ static int rsmu_spi_probe(struct spi_device *client)  	return rsmu_core_init(rsmu);  } -static int rsmu_spi_remove(struct spi_device *client) +static void rsmu_spi_remove(struct spi_device *client)  {  	struct rsmu_ddata *rsmu = spi_get_drvdata(client);  	rsmu_core_exit(rsmu); - -	return 0;  }  static const struct spi_device_id rsmu_spi_id[] = { diff --git a/drivers/mfd/stmpe-spi.c b/drivers/mfd/stmpe-spi.c index 6c5915016be5..ad8055a0e286 100644 --- a/drivers/mfd/stmpe-spi.c +++ b/drivers/mfd/stmpe-spi.c @@ -102,13 +102,11 @@ stmpe_spi_probe(struct spi_device *spi)  	return stmpe_probe(&spi_ci, id->driver_data);  } -static int stmpe_spi_remove(struct spi_device *spi) +static void stmpe_spi_remove(struct spi_device *spi)  {  	struct stmpe *stmpe = spi_get_drvdata(spi);  	stmpe_remove(stmpe); - -	return 0;  }  static const struct of_device_id stmpe_spi_of_match[] = { diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index d701926aa46e..bba38fbc781d 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c @@ -50,13 +50,11 @@ static int tps65912_spi_probe(struct spi_device *spi)  	return tps65912_device_init(tps);  } -static int tps65912_spi_remove(struct spi_device *spi) +static void tps65912_spi_remove(struct spi_device *spi)  {  	struct tps65912 *tps = spi_get_drvdata(spi);  	tps65912_device_exit(tps); - -	return 0;  }  static const struct spi_device_id tps65912_spi_id_table[] = { diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c index a9e75d80ad36..263055bda48b 100644 --- a/drivers/misc/ad525x_dpot-spi.c +++ b/drivers/misc/ad525x_dpot-spi.c @@ -90,10 +90,9 @@ static int ad_dpot_spi_probe(struct spi_device *spi)  			     spi_get_device_id(spi)->name);  } -static int ad_dpot_spi_remove(struct spi_device *spi) +static void ad_dpot_spi_remove(struct spi_device *spi)  {  	ad_dpot_remove(&spi->dev); -	return 0;  }  static const struct spi_device_id ad_dpot_spi_id[] = { diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 1f15399e5cb4..b630625b3024 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -555,14 +555,12 @@ static int eeprom_93xx46_probe(struct spi_device *spi)  	return 0;  } -static int eeprom_93xx46_remove(struct spi_device *spi) +static void eeprom_93xx46_remove(struct spi_device *spi)  {  	struct eeprom_93xx46_dev *edev = spi_get_drvdata(spi);  	if (!(edev->pdata->flags & EE_READONLY))  		device_remove_file(&spi->dev, &dev_attr_erase); - -	return 0;  }  static struct spi_driver eeprom_93xx46_driver = { diff --git a/drivers/misc/lattice-ecp3-config.c b/drivers/misc/lattice-ecp3-config.c index 98828030b5a4..bac4df2e5231 100644 --- a/drivers/misc/lattice-ecp3-config.c +++ b/drivers/misc/lattice-ecp3-config.c @@ -211,13 +211,11 @@ static int lattice_ecp3_probe(struct spi_device *spi)  	return 0;  } -static int lattice_ecp3_remove(struct spi_device *spi) +static void lattice_ecp3_remove(struct spi_device *spi)  {  	struct fpga_data *data = spi_get_drvdata(spi);  	wait_for_completion(&data->fw_loaded); - -	return 0;  }  static const struct spi_device_id lattice_ecp3_id[] = { diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c index 9e40dfb60742..203a108b8883 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c @@ -96,15 +96,13 @@ static int lis302dl_spi_probe(struct spi_device *spi)  	return lis3lv02d_init_device(&lis3_dev);  } -static int lis302dl_spi_remove(struct spi_device *spi) +static void lis302dl_spi_remove(struct spi_device *spi)  {  	struct lis3lv02d *lis3 = spi_get_drvdata(spi);  	lis3lv02d_joystick_disable(lis3);  	lis3lv02d_poweroff(lis3);  	lis3lv02d_remove_fs(&lis3_dev); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index a576181e9db0..106dd204b1a7 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1489,7 +1489,7 @@ nomem:  } -static int mmc_spi_remove(struct spi_device *spi) +static void mmc_spi_remove(struct spi_device *spi)  {  	struct mmc_host		*mmc = dev_get_drvdata(&spi->dev);  	struct mmc_spi_host	*host = mmc_priv(mmc); @@ -1507,7 +1507,6 @@ static int mmc_spi_remove(struct spi_device *spi)  	spi->max_speed_hz = mmc->f_max;  	mmc_spi_put_pdata(spi);  	mmc_free_host(mmc); -	return 0;  }  static const struct spi_device_id mmc_spi_dev_ids[] = { diff --git a/drivers/mtd/devices/mchp23k256.c b/drivers/mtd/devices/mchp23k256.c index a8b31bddf14b..008df9d8898d 100644 --- a/drivers/mtd/devices/mchp23k256.c +++ b/drivers/mtd/devices/mchp23k256.c @@ -209,13 +209,11 @@ static int mchp23k256_probe(struct spi_device *spi)  	return 0;  } -static int mchp23k256_remove(struct spi_device *spi) +static void mchp23k256_remove(struct spi_device *spi)  {  	struct mchp23k256_flash *flash = spi_get_drvdata(spi);  	WARN_ON(mtd_device_unregister(&flash->mtd)); - -	return 0;  }  static const struct of_device_id mchp23k256_of_table[] = { diff --git a/drivers/mtd/devices/mchp48l640.c b/drivers/mtd/devices/mchp48l640.c index 231a10790196..a3fd426df74b 100644 --- a/drivers/mtd/devices/mchp48l640.c +++ b/drivers/mtd/devices/mchp48l640.c @@ -341,13 +341,11 @@ static int mchp48l640_probe(struct spi_device *spi)  	return 0;  } -static int mchp48l640_remove(struct spi_device *spi) +static void mchp48l640_remove(struct spi_device *spi)  {  	struct mchp48l640_flash *flash = spi_get_drvdata(spi);  	WARN_ON(mtd_device_unregister(&flash->mtd)); - -	return 0;  }  static const struct of_device_id mchp48l640_of_table[] = { diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 734878abaa23..134e27328597 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -916,7 +916,7 @@ static int dataflash_probe(struct spi_device *spi)  	return status;  } -static int dataflash_remove(struct spi_device *spi) +static void dataflash_remove(struct spi_device *spi)  {  	struct dataflash	*flash = spi_get_drvdata(spi); @@ -925,8 +925,6 @@ static int dataflash_remove(struct spi_device *spi)  	WARN_ON(mtd_device_unregister(&flash->mtd));  	kfree(flash); - -	return 0;  }  static struct spi_driver dataflash_driver = { diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index 7f124c1bfa40..8813994ce9f4 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c @@ -398,13 +398,11 @@ static int sst25l_probe(struct spi_device *spi)  	return 0;  } -static int sst25l_remove(struct spi_device *spi) +static void sst25l_remove(struct spi_device *spi)  {  	struct sst25l_flash *flash = spi_get_drvdata(spi);  	WARN_ON(mtd_device_unregister(&flash->mtd)); - -	return 0;  }  static struct spi_driver sst25l_driver = { diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig index 5c0e0ec2e6d1..50f4f3484d42 100644 --- a/drivers/mtd/spi-nor/controllers/Kconfig +++ b/drivers/mtd/spi-nor/controllers/Kconfig @@ -26,39 +26,3 @@ config SPI_NXP_SPIFI  	  SPIFI is a specialized controller for connecting serial SPI  	  Flash. Enable this option if you have a device with a SPIFI  	  controller and want to access the Flash as a mtd device. - -config SPI_INTEL_SPI -	tristate - -config SPI_INTEL_SPI_PCI -	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)" -	depends on X86 && PCI -	select SPI_INTEL_SPI -	help -	  This enables PCI support for the Intel PCH/PCU SPI controller in -	  master mode. This controller is present in modern Intel hardware -	  and is used to hold BIOS and other persistent settings. Using -	  this driver it is possible to upgrade BIOS directly from Linux. - -	  Say N here unless you know what you are doing. Overwriting the -	  SPI flash may render the system unbootable. - -	  To compile this driver as a module, choose M here: the module -	  will be called intel-spi-pci. - -config SPI_INTEL_SPI_PLATFORM -	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)" -	depends on X86 -	select SPI_INTEL_SPI -	help -	  This enables platform support for the Intel PCH/PCU SPI -	  controller in master mode. This controller is present in modern -	  Intel hardware and is used to hold BIOS and other persistent -	  settings. Using this driver it is possible to upgrade BIOS -	  directly from Linux. - -	  Say N here unless you know what you are doing. Overwriting the -	  SPI flash may render the system unbootable. - -	  To compile this driver as a module, choose M here: the module -	  will be called intel-spi-platform. diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile index e7abba491d98..6e2a1dc68466 100644 --- a/drivers/mtd/spi-nor/controllers/Makefile +++ b/drivers/mtd/spi-nor/controllers/Makefile @@ -2,6 +2,3 @@  obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o  obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o  obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o -obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o -obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o -obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.h b/drivers/mtd/spi-nor/controllers/intel-spi.h deleted file mode 100644 index f2871179fd34..000000000000 --- a/drivers/mtd/spi-nor/controllers/intel-spi.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Intel PCH/PCU SPI flash driver. - * - * Copyright (C) 2016, Intel Corporation - * Author: Mika Westerberg <mika.westerberg@linux.intel.com> - */ - -#ifndef INTEL_SPI_H -#define INTEL_SPI_H - -#include <linux/platform_data/x86/intel-spi.h> - -struct intel_spi; -struct resource; - -struct intel_spi *intel_spi_probe(struct device *dev, -	struct resource *mem, const struct intel_spi_boardinfo *info); -int intel_spi_remove(struct intel_spi *ispi); - -#endif /* INTEL_SPI_H */ diff --git a/drivers/net/can/m_can/tcan4x5x-core.c b/drivers/net/can/m_can/tcan4x5x-core.c index 04687b15b250..41645a24384c 100644 --- a/drivers/net/can/m_can/tcan4x5x-core.c +++ b/drivers/net/can/m_can/tcan4x5x-core.c @@ -388,7 +388,7 @@ out_power:  	return ret;  } -static int tcan4x5x_can_remove(struct spi_device *spi) +static void tcan4x5x_can_remove(struct spi_device *spi)  {  	struct tcan4x5x_priv *priv = spi_get_drvdata(spi); @@ -397,8 +397,6 @@ static int tcan4x5x_can_remove(struct spi_device *spi)  	tcan4x5x_power_enable(priv->power, 0);  	m_can_class_free_dev(priv->cdev.net); - -	return 0;  }  static const struct of_device_id tcan4x5x_of_match[] = { diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index cfcc14fe3e42..664b8f14d7b0 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -948,7 +948,7 @@ static int hi3110_can_probe(struct spi_device *spi)  	return dev_err_probe(dev, ret, "Probe failed\n");  } -static int hi3110_can_remove(struct spi_device *spi) +static void hi3110_can_remove(struct spi_device *spi)  {  	struct hi3110_priv *priv = spi_get_drvdata(spi);  	struct net_device *net = priv->net; @@ -960,8 +960,6 @@ static int hi3110_can_remove(struct spi_device *spi)  	clk_disable_unprepare(priv->clk);  	free_candev(net); - -	return 0;  }  static int __maybe_unused hi3110_can_suspend(struct device *dev) diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 025e07cb7439..d23edaf22420 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1427,7 +1427,7 @@ out_free:  	return ret;  } -static int mcp251x_can_remove(struct spi_device *spi) +static void mcp251x_can_remove(struct spi_device *spi)  {  	struct mcp251x_priv *priv = spi_get_drvdata(spi);  	struct net_device *net = priv->net; @@ -1442,8 +1442,6 @@ static int mcp251x_can_remove(struct spi_device *spi)  	clk_disable_unprepare(priv->clk);  	free_candev(net); - -	return 0;  }  static int __maybe_unused mcp251x_can_suspend(struct device *dev) diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index b5986df6eca0..65c9b31666a6 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -1966,7 +1966,7 @@ static int mcp251xfd_probe(struct spi_device *spi)  	return err;  } -static int mcp251xfd_remove(struct spi_device *spi) +static void mcp251xfd_remove(struct spi_device *spi)  {  	struct mcp251xfd_priv *priv = spi_get_drvdata(spi);  	struct net_device *ndev = priv->ndev; @@ -1975,8 +1975,6 @@ static int mcp251xfd_remove(struct spi_device *spi)  	mcp251xfd_unregister(priv);  	spi->max_speed_hz = priv->spi_max_speed_hz_orig;  	free_candev(ndev); - -	return 0;  }  static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device) diff --git a/drivers/net/dsa/b53/b53_spi.c b/drivers/net/dsa/b53/b53_spi.c index 2b88f03e5252..0e54b2a0c211 100644 --- a/drivers/net/dsa/b53/b53_spi.c +++ b/drivers/net/dsa/b53/b53_spi.c @@ -314,7 +314,7 @@ static int b53_spi_probe(struct spi_device *spi)  	return 0;  } -static int b53_spi_remove(struct spi_device *spi) +static void b53_spi_remove(struct spi_device *spi)  {  	struct b53_device *dev = spi_get_drvdata(spi); @@ -322,8 +322,6 @@ static int b53_spi_remove(struct spi_device *spi)  		b53_switch_remove(dev);  	spi_set_drvdata(spi, NULL); - -	return 0;  }  static void b53_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/microchip/ksz8795_spi.c b/drivers/net/dsa/microchip/ksz8795_spi.c index b0a7dee27ffc..5f8d94aee774 100644 --- a/drivers/net/dsa/microchip/ksz8795_spi.c +++ b/drivers/net/dsa/microchip/ksz8795_spi.c @@ -87,7 +87,7 @@ static int ksz8795_spi_probe(struct spi_device *spi)  	return 0;  } -static int ksz8795_spi_remove(struct spi_device *spi) +static void ksz8795_spi_remove(struct spi_device *spi)  {  	struct ksz_device *dev = spi_get_drvdata(spi); @@ -95,8 +95,6 @@ static int ksz8795_spi_remove(struct spi_device *spi)  		ksz_switch_remove(dev);  	spi_set_drvdata(spi, NULL); - -	return 0;  }  static void ksz8795_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/microchip/ksz9477_spi.c b/drivers/net/dsa/microchip/ksz9477_spi.c index 43addeabfc25..87ca464dad32 100644 --- a/drivers/net/dsa/microchip/ksz9477_spi.c +++ b/drivers/net/dsa/microchip/ksz9477_spi.c @@ -65,7 +65,7 @@ static int ksz9477_spi_probe(struct spi_device *spi)  	return 0;  } -static int ksz9477_spi_remove(struct spi_device *spi) +static void ksz9477_spi_remove(struct spi_device *spi)  {  	struct ksz_device *dev = spi_get_drvdata(spi); @@ -73,8 +73,6 @@ static int ksz9477_spi_remove(struct spi_device *spi)  		ksz_switch_remove(dev);  	spi_set_drvdata(spi, NULL); - -	return 0;  }  static void ksz9477_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index b513713be610..c2a47c6693b8 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -3346,18 +3346,16 @@ static int sja1105_probe(struct spi_device *spi)  	return dsa_register_switch(priv->ds);  } -static int sja1105_remove(struct spi_device *spi) +static void sja1105_remove(struct spi_device *spi)  {  	struct sja1105_private *priv = spi_get_drvdata(spi);  	if (!priv) -		return 0; +		return;  	dsa_unregister_switch(priv->ds);  	spi_set_drvdata(spi, NULL); - -	return 0;  }  static void sja1105_shutdown(struct spi_device *spi) diff --git a/drivers/net/dsa/vitesse-vsc73xx-spi.c b/drivers/net/dsa/vitesse-vsc73xx-spi.c index 645398901e05..3110895358d8 100644 --- a/drivers/net/dsa/vitesse-vsc73xx-spi.c +++ b/drivers/net/dsa/vitesse-vsc73xx-spi.c @@ -159,18 +159,16 @@ static int vsc73xx_spi_probe(struct spi_device *spi)  	return vsc73xx_probe(&vsc_spi->vsc);  } -static int vsc73xx_spi_remove(struct spi_device *spi) +static void vsc73xx_spi_remove(struct spi_device *spi)  {  	struct vsc73xx_spi *vsc_spi = spi_get_drvdata(spi);  	if (!vsc_spi) -		return 0; +		return;  	vsc73xx_remove(&vsc_spi->vsc);  	spi_set_drvdata(spi, NULL); - -	return 0;  }  static void vsc73xx_spi_shutdown(struct spi_device *spi) diff --git a/drivers/net/ethernet/asix/ax88796c_main.c b/drivers/net/ethernet/asix/ax88796c_main.c index e7a9f9863258..bf70481bb1ca 100644 --- a/drivers/net/ethernet/asix/ax88796c_main.c +++ b/drivers/net/ethernet/asix/ax88796c_main.c @@ -1102,7 +1102,7 @@ err:  	return ret;  } -static int ax88796c_remove(struct spi_device *spi) +static void ax88796c_remove(struct spi_device *spi)  {  	struct ax88796c_device *ax_local = dev_get_drvdata(&spi->dev);  	struct net_device *ndev = ax_local->ndev; @@ -1112,8 +1112,6 @@ static int ax88796c_remove(struct spi_device *spi)  	netif_info(ax_local, probe, ndev, "removing network device %s %s\n",  		   dev_driver_string(&spi->dev),  		   dev_name(&spi->dev)); - -	return 0;  }  #ifdef CONFIG_OF diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c index 0303e727e99f..d167d93e4c12 100644 --- a/drivers/net/ethernet/micrel/ks8851_spi.c +++ b/drivers/net/ethernet/micrel/ks8851_spi.c @@ -452,11 +452,9 @@ static int ks8851_probe_spi(struct spi_device *spi)  	return ks8851_probe_common(netdev, dev, msg_enable);  } -static int ks8851_remove_spi(struct spi_device *spi) +static void ks8851_remove_spi(struct spi_device *spi)  {  	ks8851_remove_common(&spi->dev); - -	return 0;  }  static const struct of_device_id ks8851_match_table[] = { diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c index 634ac7649c43..db5a3edb4c3c 100644 --- a/drivers/net/ethernet/microchip/enc28j60.c +++ b/drivers/net/ethernet/microchip/enc28j60.c @@ -1612,15 +1612,13 @@ error_alloc:  	return ret;  } -static int enc28j60_remove(struct spi_device *spi) +static void enc28j60_remove(struct spi_device *spi)  {  	struct enc28j60_net *priv = spi_get_drvdata(spi);  	unregister_netdev(priv->netdev);  	free_irq(spi->irq, priv);  	free_netdev(priv->netdev); - -	return 0;  }  static const struct of_device_id enc28j60_dt_ids[] = { diff --git a/drivers/net/ethernet/microchip/encx24j600.c b/drivers/net/ethernet/microchip/encx24j600.c index b90efc80fb59..dc1840cb5b10 100644 --- a/drivers/net/ethernet/microchip/encx24j600.c +++ b/drivers/net/ethernet/microchip/encx24j600.c @@ -1093,7 +1093,7 @@ error_out:  	return ret;  } -static int encx24j600_spi_remove(struct spi_device *spi) +static void encx24j600_spi_remove(struct spi_device *spi)  {  	struct encx24j600_priv *priv = dev_get_drvdata(&spi->dev); @@ -1101,8 +1101,6 @@ static int encx24j600_spi_remove(struct spi_device *spi)  	kthread_stop(priv->kworker_task);  	free_netdev(priv->ndev); - -	return 0;  }  static const struct spi_device_id encx24j600_spi_id_table[] = { diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 955cce644392..3c5494afd3c0 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -1001,7 +1001,7 @@ qca_spi_probe(struct spi_device *spi)  	return 0;  } -static int +static void  qca_spi_remove(struct spi_device *spi)  {  	struct net_device *qcaspi_devs = spi_get_drvdata(spi); @@ -1011,8 +1011,6 @@ qca_spi_remove(struct spi_device *spi)  	unregister_netdev(qcaspi_devs);  	free_netdev(qcaspi_devs); - -	return 0;  }  static const struct spi_device_id qca_spi_id[] = { diff --git a/drivers/net/ethernet/vertexcom/mse102x.c b/drivers/net/ethernet/vertexcom/mse102x.c index 89a31783fbb4..25739b182ac7 100644 --- a/drivers/net/ethernet/vertexcom/mse102x.c +++ b/drivers/net/ethernet/vertexcom/mse102x.c @@ -731,7 +731,7 @@ static int mse102x_probe_spi(struct spi_device *spi)  	return 0;  } -static int mse102x_remove_spi(struct spi_device *spi) +static void mse102x_remove_spi(struct spi_device *spi)  {  	struct mse102x_net *mse = dev_get_drvdata(&spi->dev);  	struct mse102x_net_spi *mses = to_mse102x_spi(mse); @@ -741,8 +741,6 @@ static int mse102x_remove_spi(struct spi_device *spi)  	mse102x_remove_device_debugfs(mses);  	unregister_netdev(mse->ndev); - -	return 0;  }  static const struct of_device_id mse102x_match_table[] = { diff --git a/drivers/net/ethernet/wiznet/w5100-spi.c b/drivers/net/ethernet/wiznet/w5100-spi.c index 7779a36da3c8..7c52796273a4 100644 --- a/drivers/net/ethernet/wiznet/w5100-spi.c +++ b/drivers/net/ethernet/wiznet/w5100-spi.c @@ -461,11 +461,9 @@ static int w5100_spi_probe(struct spi_device *spi)  	return w5100_probe(&spi->dev, ops, priv_size, mac, spi->irq, -EINVAL);  } -static int w5100_spi_remove(struct spi_device *spi) +static void w5100_spi_remove(struct spi_device *spi)  {  	w5100_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id w5100_spi_ids[] = { diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index 7db9cbd0f5de..6afdf1622944 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c @@ -1304,7 +1304,7 @@ err_alloc_wq:  	return ret;  } -static int adf7242_remove(struct spi_device *spi) +static void adf7242_remove(struct spi_device *spi)  {  	struct adf7242_local *lp = spi_get_drvdata(spi); @@ -1316,8 +1316,6 @@ static int adf7242_remove(struct spi_device *spi)  	ieee802154_unregister_hw(lp->hw);  	mutex_destroy(&lp->bmux);  	ieee802154_free_hw(lp->hw); - -	return 0;  }  static const struct of_device_id adf7242_of_match[] = { diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 4f5ef8a9a9a8..549d04b5f3d4 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1768,7 +1768,7 @@ free_dev:  	return rc;  } -static int at86rf230_remove(struct spi_device *spi) +static void at86rf230_remove(struct spi_device *spi)  {  	struct at86rf230_local *lp = spi_get_drvdata(spi); @@ -1778,8 +1778,6 @@ static int at86rf230_remove(struct spi_device *spi)  	ieee802154_free_hw(lp->hw);  	at86rf230_debugfs_remove();  	dev_dbg(&spi->dev, "unregistered at86rf230\n"); - -	return 0;  }  static const struct of_device_id at86rf230_of_match[] = { diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 2bc730fd260e..187cbc634ce8 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -831,7 +831,7 @@ static void ca8210_rx_done(struct cas_control *cas_ctl)  finish:;  } -static int ca8210_remove(struct spi_device *spi_device); +static void ca8210_remove(struct spi_device *spi_device);  /**   * ca8210_spi_transfer_complete() - Called when a single spi transfer has @@ -3049,7 +3049,7 @@ static void ca8210_test_interface_clear(struct ca8210_priv *priv)   *   * Return: 0 or linux error code   */ -static int ca8210_remove(struct spi_device *spi_device) +static void ca8210_remove(struct spi_device *spi_device)  {  	struct ca8210_priv *priv;  	struct ca8210_platform_data *pdata; @@ -3089,8 +3089,6 @@ static int ca8210_remove(struct spi_device *spi_device)  		if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS))  			ca8210_test_interface_clear(priv);  	} - -	return 0;  }  /** diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c index 89c046b204e0..1e1f40f628a0 100644 --- a/drivers/net/ieee802154/cc2520.c +++ b/drivers/net/ieee802154/cc2520.c @@ -1213,7 +1213,7 @@ err_hw_init:  	return ret;  } -static int cc2520_remove(struct spi_device *spi) +static void cc2520_remove(struct spi_device *spi)  {  	struct cc2520_private *priv = spi_get_drvdata(spi); @@ -1222,8 +1222,6 @@ static int cc2520_remove(struct spi_device *spi)  	ieee802154_unregister_hw(priv->hw);  	ieee802154_free_hw(priv->hw); - -	return 0;  }  static const struct spi_device_id cc2520_ids[] = { diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c index 383231b85464..c927a5ae0d05 100644 --- a/drivers/net/ieee802154/mcr20a.c +++ b/drivers/net/ieee802154/mcr20a.c @@ -1335,7 +1335,7 @@ free_dev:  	return ret;  } -static int mcr20a_remove(struct spi_device *spi) +static void mcr20a_remove(struct spi_device *spi)  {  	struct mcr20a_local *lp = spi_get_drvdata(spi); @@ -1343,8 +1343,6 @@ static int mcr20a_remove(struct spi_device *spi)  	ieee802154_unregister_hw(lp->hw);  	ieee802154_free_hw(lp->hw); - -	return 0;  }  static const struct of_device_id mcr20a_of_match[] = { diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c index ff83e00b77af..ee4cfbf2c5cc 100644 --- a/drivers/net/ieee802154/mrf24j40.c +++ b/drivers/net/ieee802154/mrf24j40.c @@ -1356,7 +1356,7 @@ err_ret:  	return ret;  } -static int mrf24j40_remove(struct spi_device *spi) +static void mrf24j40_remove(struct spi_device *spi)  {  	struct mrf24j40 *devrec = spi_get_drvdata(spi); @@ -1366,8 +1366,6 @@ static int mrf24j40_remove(struct spi_device *spi)  	ieee802154_free_hw(devrec->hw);  	/* TODO: Will ieee802154_free_device() wait until ->xmit() is  	 * complete? */ - -	return 0;  }  static const struct of_device_id mrf24j40_of_match[] = { diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c index 8b5445a724ce..ff37f8ba6758 100644 --- a/drivers/net/phy/spi_ks8995.c +++ b/drivers/net/phy/spi_ks8995.c @@ -517,7 +517,7 @@ static int ks8995_probe(struct spi_device *spi)  	return 0;  } -static int ks8995_remove(struct spi_device *spi) +static void ks8995_remove(struct spi_device *spi)  {  	struct ks8995_switch *ks = spi_get_drvdata(spi); @@ -526,8 +526,6 @@ static int ks8995_remove(struct spi_device *spi)  	/* assert reset */  	if (ks->pdata && gpio_is_valid(ks->pdata->reset_gpio))  		gpiod_set_value(gpio_to_desc(ks->pdata->reset_gpio), 1); - -	return 0;  }  /* ------------------------------------------------------------------------ */ diff --git a/drivers/net/wan/slic_ds26522.c b/drivers/net/wan/slic_ds26522.c index 8e3b1c717c10..6063552cea9b 100644 --- a/drivers/net/wan/slic_ds26522.c +++ b/drivers/net/wan/slic_ds26522.c @@ -194,10 +194,9 @@ static int slic_ds26522_init_configure(struct spi_device *spi)  	return 0;  } -static int slic_ds26522_remove(struct spi_device *spi) +static void slic_ds26522_remove(struct spi_device *spi)  {  	pr_info("DS26522 module uninstalled\n"); -	return 0;  }  static int slic_ds26522_probe(struct spi_device *spi) diff --git a/drivers/net/wireless/intersil/p54/p54spi.c b/drivers/net/wireless/intersil/p54/p54spi.c index ab0fe8565851..f99b7ba69fc3 100644 --- a/drivers/net/wireless/intersil/p54/p54spi.c +++ b/drivers/net/wireless/intersil/p54/p54spi.c @@ -669,7 +669,7 @@ err_free:  	return ret;  } -static int p54spi_remove(struct spi_device *spi) +static void p54spi_remove(struct spi_device *spi)  {  	struct p54s_priv *priv = spi_get_drvdata(spi); @@ -684,8 +684,6 @@ static int p54spi_remove(struct spi_device *spi)  	mutex_destroy(&priv->mutex);  	p54_free_common(priv->hw); - -	return 0;  } diff --git a/drivers/net/wireless/marvell/libertas/if_spi.c b/drivers/net/wireless/marvell/libertas/if_spi.c index cd9f8ecf171f..ff1c7ec8c450 100644 --- a/drivers/net/wireless/marvell/libertas/if_spi.c +++ b/drivers/net/wireless/marvell/libertas/if_spi.c @@ -1195,7 +1195,7 @@ out:  	return err;  } -static int libertas_spi_remove(struct spi_device *spi) +static void libertas_spi_remove(struct spi_device *spi)  {  	struct if_spi_card *card = spi_get_drvdata(spi);  	struct lbs_private *priv = card->priv; @@ -1212,8 +1212,6 @@ static int libertas_spi_remove(struct spi_device *spi)  	if (card->pdata->teardown)  		card->pdata->teardown(spi);  	free_if_spi_card(card); - -	return 0;  }  static int if_spi_suspend(struct device *dev) diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c index 2c2ed4b09efd..d2db52289399 100644 --- a/drivers/net/wireless/microchip/wilc1000/spi.c +++ b/drivers/net/wireless/microchip/wilc1000/spi.c @@ -240,7 +240,7 @@ free:  	return ret;  } -static int wilc_bus_remove(struct spi_device *spi) +static void wilc_bus_remove(struct spi_device *spi)  {  	struct wilc *wilc = spi_get_drvdata(spi);  	struct wilc_spi *spi_priv = wilc->bus_data; @@ -248,8 +248,6 @@ static int wilc_bus_remove(struct spi_device *spi)  	clk_disable_unprepare(wilc->rtc_clk);  	wilc_netdev_cleanup(wilc);  	kfree(spi_priv); - -	return 0;  }  static const struct of_device_id wilc_of_match[] = { diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c index 271ed2ce2d7f..fe0d220da44d 100644 --- a/drivers/net/wireless/st/cw1200/cw1200_spi.c +++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c @@ -423,7 +423,7 @@ static int cw1200_spi_probe(struct spi_device *func)  }  /* Disconnect Function to be called by SPI stack when device is disconnected */ -static int cw1200_spi_disconnect(struct spi_device *func) +static void cw1200_spi_disconnect(struct spi_device *func)  {  	struct hwbus_priv *self = spi_get_drvdata(func); @@ -435,8 +435,6 @@ static int cw1200_spi_disconnect(struct spi_device *func)  		}  	}  	cw1200_spi_off(dev_get_platdata(&func->dev)); - -	return 0;  }  static int __maybe_unused cw1200_spi_suspend(struct device *dev) diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c index 5b894bd6237e..9df38726e8b0 100644 --- a/drivers/net/wireless/ti/wl1251/spi.c +++ b/drivers/net/wireless/ti/wl1251/spi.c @@ -327,14 +327,12 @@ out_free:  	return ret;  } -static int wl1251_spi_remove(struct spi_device *spi) +static void wl1251_spi_remove(struct spi_device *spi)  {  	struct wl1251 *wl = spi_get_drvdata(spi);  	wl1251_free_hw(wl);  	regulator_disable(wl->vio); - -	return 0;  }  static struct spi_driver wl1251_spi_driver = { diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 354a7e1c3315..7eae1ec2eb2b 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -546,13 +546,11 @@ out_dev_put:  	return ret;  } -static int wl1271_remove(struct spi_device *spi) +static void wl1271_remove(struct spi_device *spi)  {  	struct wl12xx_spi_glue *glue = spi_get_drvdata(spi);  	platform_device_unregister(glue->core); - -	return 0;  }  static struct spi_driver wl1271_spi_driver = { diff --git a/drivers/nfc/nfcmrvl/spi.c b/drivers/nfc/nfcmrvl/spi.c index 5b833a9a83f8..a38e2fcdfd39 100644 --- a/drivers/nfc/nfcmrvl/spi.c +++ b/drivers/nfc/nfcmrvl/spi.c @@ -174,12 +174,11 @@ static int nfcmrvl_spi_probe(struct spi_device *spi)  	return 0;  } -static int nfcmrvl_spi_remove(struct spi_device *spi) +static void nfcmrvl_spi_remove(struct spi_device *spi)  {  	struct nfcmrvl_spi_drv_data *drv_data = spi_get_drvdata(spi);  	nfcmrvl_nci_unregister_dev(drv_data->priv); -	return 0;  }  static const struct of_device_id of_nfcmrvl_spi_match[] __maybe_unused = { diff --git a/drivers/nfc/st-nci/spi.c b/drivers/nfc/st-nci/spi.c index 4e723992e74c..169eacc0a32a 100644 --- a/drivers/nfc/st-nci/spi.c +++ b/drivers/nfc/st-nci/spi.c @@ -263,13 +263,11 @@ static int st_nci_spi_probe(struct spi_device *dev)  	return r;  } -static int st_nci_spi_remove(struct spi_device *dev) +static void st_nci_spi_remove(struct spi_device *dev)  {  	struct st_nci_spi_phy *phy = spi_get_drvdata(dev);  	ndlc_remove(phy->ndlc); - -	return 0;  }  static struct spi_device_id st_nci_spi_id_table[] = { diff --git a/drivers/nfc/st95hf/core.c b/drivers/nfc/st95hf/core.c index b23f47936473..ed704bb77226 100644 --- a/drivers/nfc/st95hf/core.c +++ b/drivers/nfc/st95hf/core.c @@ -1198,7 +1198,7 @@ err_disable_regulator:  	return ret;  } -static int st95hf_remove(struct spi_device *nfc_spi_dev) +static void st95hf_remove(struct spi_device *nfc_spi_dev)  {  	int result = 0;  	unsigned char reset_cmd = ST95HF_COMMAND_RESET; @@ -1236,8 +1236,6 @@ static int st95hf_remove(struct spi_device *nfc_spi_dev)  	/* disable regulator */  	if (stcontext->st95hf_supply)  		regulator_disable(stcontext->st95hf_supply); - -	return 0;  }  /* Register as SPI protocol driver */ diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 29ca9c328df2..21d68664fe08 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -2144,7 +2144,7 @@ err_destroy_lock:  	return ret;  } -static int trf7970a_remove(struct spi_device *spi) +static void trf7970a_remove(struct spi_device *spi)  {  	struct trf7970a *trf = spi_get_drvdata(spi); @@ -2160,8 +2160,6 @@ static int trf7970a_remove(struct spi_device *spi)  	regulator_disable(trf->regulator);  	mutex_destroy(&trf->lock); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/chrome/cros_ec.c b/drivers/platform/chrome/cros_ec.c index fc5aa1525d13..d49a4efe46c8 100644 --- a/drivers/platform/chrome/cros_ec.c +++ b/drivers/platform/chrome/cros_ec.c @@ -302,13 +302,11 @@ EXPORT_SYMBOL(cros_ec_register);   *   * Return: 0 on success or negative error code.   */ -int cros_ec_unregister(struct cros_ec_device *ec_dev) +void cros_ec_unregister(struct cros_ec_device *ec_dev)  {  	if (ec_dev->pd)  		platform_device_unregister(ec_dev->pd);  	platform_device_unregister(ec_dev->ec); - -	return 0;  }  EXPORT_SYMBOL(cros_ec_unregister); diff --git a/drivers/platform/chrome/cros_ec.h b/drivers/platform/chrome/cros_ec.h index 78363dcfdf23..bbca0096868a 100644 --- a/drivers/platform/chrome/cros_ec.h +++ b/drivers/platform/chrome/cros_ec.h @@ -11,7 +11,7 @@  #include <linux/interrupt.h>  int cros_ec_register(struct cros_ec_device *ec_dev); -int cros_ec_unregister(struct cros_ec_device *ec_dev); +void cros_ec_unregister(struct cros_ec_device *ec_dev);  int cros_ec_suspend(struct cros_ec_device *ec_dev);  int cros_ec_resume(struct cros_ec_device *ec_dev); diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c index 30c8938c27d5..22feb0fd4ce7 100644 --- a/drivers/platform/chrome/cros_ec_i2c.c +++ b/drivers/platform/chrome/cros_ec_i2c.c @@ -313,7 +313,9 @@ static int cros_ec_i2c_remove(struct i2c_client *client)  {  	struct cros_ec_device *ec_dev = i2c_get_clientdata(client); -	return cros_ec_unregister(ec_dev); +	cros_ec_unregister(ec_dev); + +	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index d6306d2a096f..7651417b4a25 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -439,7 +439,9 @@ static int cros_ec_lpc_remove(struct platform_device *pdev)  		acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,  					   cros_ec_lpc_acpi_notify); -	return cros_ec_unregister(ec_dev); +	cros_ec_unregister(ec_dev); + +	return 0;  }  static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = { diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 14c4046fa04d..8493af0f680e 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c @@ -786,11 +786,11 @@ static int cros_ec_spi_probe(struct spi_device *spi)  	return 0;  } -static int cros_ec_spi_remove(struct spi_device *spi) +static void cros_ec_spi_remove(struct spi_device *spi)  {  	struct cros_ec_device *ec_dev = spi_get_drvdata(spi); -	return cros_ec_unregister(ec_dev); +	cros_ec_unregister(ec_dev);  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c index 0d46706afd2d..4823bd2819f6 100644 --- a/drivers/platform/olpc/olpc-xo175-ec.c +++ b/drivers/platform/olpc/olpc-xo175-ec.c @@ -648,7 +648,7 @@ static struct olpc_ec_driver olpc_xo175_ec_driver = {  	.ec_cmd = olpc_xo175_ec_cmd,  }; -static int olpc_xo175_ec_remove(struct spi_device *spi) +static void olpc_xo175_ec_remove(struct spi_device *spi)  {  	if (pm_power_off == olpc_xo175_ec_power_off)  		pm_power_off = NULL; @@ -657,8 +657,6 @@ static int olpc_xo175_ec_remove(struct spi_device *spi)  	platform_device_unregister(olpc_ec);  	olpc_ec = NULL; - -	return 0;  }  static int olpc_xo175_ec_probe(struct spi_device *spi) diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c index 2f83adef966e..6d66ab5a8b17 100644 --- a/drivers/rtc/rtc-ds1302.c +++ b/drivers/rtc/rtc-ds1302.c @@ -185,10 +185,9 @@ static int ds1302_probe(struct spi_device *spi)  	return 0;  } -static int ds1302_remove(struct spi_device *spi) +static void ds1302_remove(struct spi_device *spi)  {  	spi_set_drvdata(spi, NULL); -	return 0;  }  #ifdef CONFIG_OF diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index 9ef107b99b65..ed9360486953 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -720,7 +720,7 @@ static int ds1305_probe(struct spi_device *spi)  	return 0;  } -static int ds1305_remove(struct spi_device *spi) +static void ds1305_remove(struct spi_device *spi)  {  	struct ds1305 *ds1305 = spi_get_drvdata(spi); @@ -730,8 +730,6 @@ static int ds1305_remove(struct spi_device *spi)  		devm_free_irq(&spi->dev, spi->irq, ds1305);  		cancel_work_sync(&ds1305->work);  	} - -	return 0;  }  static struct spi_driver ds1305_driver = { diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c index f14ed6c96437..ed5a6ba89a3e 100644 --- a/drivers/rtc/rtc-ds1343.c +++ b/drivers/rtc/rtc-ds1343.c @@ -434,11 +434,9 @@ static int ds1343_probe(struct spi_device *spi)  	return 0;  } -static int ds1343_remove(struct spi_device *spi) +static void ds1343_remove(struct spi_device *spi)  {  	dev_pm_clear_wake_irq(&spi->dev); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index b2a8821971e1..31a2cef3790c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -427,6 +427,45 @@ config SPI_INGENIC  	  To compile this driver as a module, choose M here: the module  	  will be called spi-ingenic. +config SPI_INTEL +	tristate + +config SPI_INTEL_PCI +	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)" +	depends on PCI +	depends on X86 || COMPILE_TEST +	depends on SPI_MEM +	select SPI_INTEL +	help +	  This enables PCI support for the Intel PCH/PCU SPI controller in +	  master mode. This controller is present in modern Intel hardware +	  and is used to hold BIOS and other persistent settings. Using +	  this driver it is possible to upgrade BIOS directly from Linux. + +	  Say N here unless you know what you are doing. Overwriting the +	  SPI flash may render the system unbootable. + +	  To compile this driver as a module, choose M here: the module +	  will be called spi-intel-pci. + +config SPI_INTEL_PLATFORM +	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)" +	depends on X86 || COMPILE_TEST +	depends on SPI_MEM +	select SPI_INTEL +	help +	  This enables platform support for the Intel PCH/PCU SPI +	  controller in master mode. This controller is present in modern +	  Intel hardware and is used to hold BIOS and other persistent +	  settings. Using this driver it is possible to upgrade BIOS +	  directly from Linux. + +	  Say N here unless you know what you are doing. Overwriting the +	  SPI flash may render the system unbootable. + +	  To compile this driver as a module, choose M here: the module +	  will be called spi-intel-platform. +  config SPI_JCORE  	tristate "J-Core SPI Master"  	depends on OF && (SUPERH || COMPILE_TEST) @@ -866,6 +905,17 @@ config SPI_SUN6I  	help  	  This enables using the SPI controller on the Allwinner A31 SoCs. +config SPI_SUNPLUS_SP7021 +	tristate "Sunplus SP7021 SPI controller" +	depends on SOC_SP7021 || COMPILE_TEST +	help +	  This enables Sunplus SP7021 SPI controller driver on the SP7021 SoCs. +	  This driver can also be built as a module. If so, the module will be +	  called as spi-sunplus-sp7021. + +	  If you have a  Sunplus SP7021 platform say Y here. +	  If unsure, say N. +  config SPI_SYNQUACER  	tristate "Socionext's SynQuacer HighSpeed SPI controller"  	depends on ARCH_SYNQUACER || COMPILE_TEST diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index dd7393a6046f..3aa28ed3f761 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -61,6 +61,9 @@ obj-$(CONFIG_SPI_HISI_SFC_V3XX)		+= spi-hisi-sfc-v3xx.o  obj-$(CONFIG_SPI_IMG_SPFI)		+= spi-img-spfi.o  obj-$(CONFIG_SPI_IMX)			+= spi-imx.o  obj-$(CONFIG_SPI_INGENIC)		+= spi-ingenic.o +obj-$(CONFIG_SPI_INTEL)			+= spi-intel.o +obj-$(CONFIG_SPI_INTEL_PCI)		+= spi-intel-pci.o +obj-$(CONFIG_SPI_INTEL_PLATFORM)	+= spi-intel-platform.o  obj-$(CONFIG_SPI_LANTIQ_SSC)		+= spi-lantiq-ssc.o  obj-$(CONFIG_SPI_JCORE)			+= spi-jcore.o  obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o @@ -119,6 +122,7 @@ obj-$(CONFIG_SPI_STM32_QSPI) 		+= spi-stm32-qspi.o  obj-$(CONFIG_SPI_ST_SSC4)		+= spi-st-ssc4.o  obj-$(CONFIG_SPI_SUN4I)			+= spi-sun4i.o  obj-$(CONFIG_SPI_SUN6I)			+= spi-sun6i.o +obj-$(CONFIG_SPI_SUNPLUS_SP7021)	+= spi-sunplus-sp7021.o  obj-$(CONFIG_SPI_SYNQUACER)		+= spi-synquacer.o  obj-$(CONFIG_SPI_TEGRA210_QUAD)		+= spi-tegra210-quad.o  obj-$(CONFIG_SPI_TEGRA114)		+= spi-tegra114.o diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c index 4b3ac7aceaf6..cba6a4486c24 100644 --- a/drivers/spi/spi-amd.c +++ b/drivers/spi/spi-amd.c @@ -12,12 +12,17 @@  #include <linux/platform_device.h>  #include <linux/delay.h>  #include <linux/spi/spi.h> +#include <linux/iopoll.h>  #define AMD_SPI_CTRL0_REG	0x00  #define AMD_SPI_EXEC_CMD	BIT(16)  #define AMD_SPI_FIFO_CLEAR	BIT(20)  #define AMD_SPI_BUSY		BIT(31) +#define AMD_SPI_OPCODE_REG	0x45 +#define AMD_SPI_CMD_TRIGGER_REG	0x47 +#define AMD_SPI_TRIGGER_CMD	BIT(7) +  #define AMD_SPI_OPCODE_MASK	0xFF  #define AMD_SPI_ALT_CS_REG	0x1D @@ -34,10 +39,15 @@  #define AMD_SPI_XFER_TX		1  #define AMD_SPI_XFER_RX		2 +enum amd_spi_versions { +	AMD_SPI_V1 = 1,	/* AMDI0061 */ +	AMD_SPI_V2,	/* AMDI0062 */ +}; +  struct amd_spi {  	void __iomem *io_remap_addr;  	unsigned long io_base_addr; -	u32 rom_addr; +	enum amd_spi_versions version;  };  static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx) @@ -81,14 +91,29 @@ static void amd_spi_select_chip(struct amd_spi *amd_spi, u8 cs)  	amd_spi_setclear_reg8(amd_spi, AMD_SPI_ALT_CS_REG, cs, AMD_SPI_ALT_CS_MASK);  } +static inline void amd_spi_clear_chip(struct amd_spi *amd_spi, u8 chip_select) +{ +	amd_spi_writereg8(amd_spi, AMD_SPI_ALT_CS_REG, chip_select & ~AMD_SPI_ALT_CS_MASK); +} +  static void amd_spi_clear_fifo_ptr(struct amd_spi *amd_spi)  {  	amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR, AMD_SPI_FIFO_CLEAR);  } -static void amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode) +static int amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode)  { -	amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode, AMD_SPI_OPCODE_MASK); +	switch (amd_spi->version) { +	case AMD_SPI_V1: +		amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode, +				       AMD_SPI_OPCODE_MASK); +		return 0; +	case AMD_SPI_V2: +		amd_spi_writereg8(amd_spi, AMD_SPI_OPCODE_REG, cmd_opcode); +		return 0; +	default: +		return -ENODEV; +	}  }  static inline void amd_spi_set_rx_count(struct amd_spi *amd_spi, u8 rx_count) @@ -103,16 +128,22 @@ static inline void amd_spi_set_tx_count(struct amd_spi *amd_spi, u8 tx_count)  static int amd_spi_busy_wait(struct amd_spi *amd_spi)  { -	int timeout = 100000; - -	/* poll for SPI bus to become idle */ -	while (amd_spi_readreg32(amd_spi, AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) { -		usleep_range(10, 20); -		if (timeout-- < 0) -			return -ETIMEDOUT; +	u32 val; +	int reg; + +	switch (amd_spi->version) { +	case AMD_SPI_V1: +		reg = AMD_SPI_CTRL0_REG; +		break; +	case AMD_SPI_V2: +		reg = AMD_SPI_STATUS_REG; +		break; +	default: +		return -ENODEV;  	} -	return 0; +	return readl_poll_timeout(amd_spi->io_remap_addr + reg, val, +				  !(val & AMD_SPI_BUSY), 20, 2000000);  }  static int amd_spi_execute_opcode(struct amd_spi *amd_spi) @@ -123,10 +154,20 @@ static int amd_spi_execute_opcode(struct amd_spi *amd_spi)  	if (ret)  		return ret; -	/* Set ExecuteOpCode bit in the CTRL0 register */ -	amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD, AMD_SPI_EXEC_CMD); - -	return 0; +	switch (amd_spi->version) { +	case AMD_SPI_V1: +		/* Set ExecuteOpCode bit in the CTRL0 register */ +		amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD, +				       AMD_SPI_EXEC_CMD); +		return 0; +	case AMD_SPI_V2: +		/* Trigger the command execution */ +		amd_spi_setclear_reg8(amd_spi, AMD_SPI_CMD_TRIGGER_REG, +				      AMD_SPI_TRIGGER_CMD, AMD_SPI_TRIGGER_CMD); +		return 0; +	default: +		return -ENODEV; +	}  }  static int amd_spi_master_setup(struct spi_device *spi) @@ -196,6 +237,17 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,  	message->actual_length = tx_len + rx_len + 1;  	/* complete the transaction */  	message->status = 0; + +	switch (amd_spi->version) { +	case AMD_SPI_V1: +		break; +	case AMD_SPI_V2: +		amd_spi_clear_chip(amd_spi, message->spi->chip_select); +		break; +	default: +		return -ENODEV; +	} +  	spi_finalize_current_message(master);  	return 0; @@ -241,6 +293,8 @@ static int amd_spi_probe(struct platform_device *pdev)  	}  	dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr); +	amd_spi->version = (enum amd_spi_versions) device_get_match_data(dev); +  	/* Initialize the spi_master fields */  	master->bus_num = 0;  	master->num_chipselect = 4; @@ -266,7 +320,8 @@ err_free_master:  #ifdef CONFIG_ACPI  static const struct acpi_device_id spi_acpi_match[] = { -	{ "AMDI0061", 0 }, +	{ "AMDI0061", AMD_SPI_V1 }, +	{ "AMDI0062", AMD_SPI_V2 },  	{},  };  MODULE_DEVICE_TABLE(acpi, spi_acpi_match); diff --git a/drivers/spi/spi-ath79.c b/drivers/spi/spi-ath79.c index d1e287d2d9cd..607e7a49fb89 100644 --- a/drivers/spi/spi-ath79.c +++ b/drivers/spi/spi-ath79.c @@ -15,6 +15,7 @@  #include <linux/platform_device.h>  #include <linux/io.h>  #include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h>  #include <linux/spi/spi_bitbang.h>  #include <linux/bitops.h>  #include <linux/clk.h> @@ -133,6 +134,38 @@ static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned int nsecs,  	return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);  } +static int ath79_exec_mem_op(struct spi_mem *mem, +			     const struct spi_mem_op *op) +{ +	struct ath79_spi *sp = ath79_spidev_to_sp(mem->spi); + +	/* Ensures that reading is performed on device connected to hardware cs0 */ +	if (mem->spi->chip_select || mem->spi->cs_gpiod) +		return -ENOTSUPP; + +	/* Only use for fast-read op. */ +	if (op->cmd.opcode != 0x0b || op->data.dir != SPI_MEM_DATA_IN || +	    op->addr.nbytes != 3 || op->dummy.nbytes != 1) +		return -ENOTSUPP; + +	/* disable GPIO mode */ +	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0); + +	memcpy_fromio(op->data.buf.in, sp->base + op->addr.val, op->data.nbytes); + +	/* enable GPIO mode */ +	ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO); + +	/* restore IOC register */ +	ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base); + +	return 0; +} + +static const struct spi_controller_mem_ops ath79_mem_ops = { +	.exec_op = ath79_exec_mem_op, +}; +  static int ath79_spi_probe(struct platform_device *pdev)  {  	struct spi_master *master; @@ -154,6 +187,7 @@ static int ath79_spi_probe(struct platform_device *pdev)  	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);  	master->flags = SPI_MASTER_GPIO_SS;  	master->num_chipselect = 3; +	master->mem_ops = &ath79_mem_ops;  	sp->bitbang.master = master;  	sp->bitbang.chipselect = ath79_spi_chipselect; diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 7d709a8c833b..e28521922330 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -22,7 +22,6 @@  #include <linux/of.h>  #include <linux/of_address.h>  #include <linux/of_device.h> -#include <linux/of_gpio.h>  #include <linux/of_irq.h>  #include <linux/regmap.h>  #include <linux/spi/spi.h> @@ -445,25 +444,12 @@ static void bcm2835aux_spi_handle_err(struct spi_master *master,  static int bcm2835aux_spi_setup(struct spi_device *spi)  { -	int ret; -  	/* sanity check for native cs */  	if (spi->mode & SPI_NO_CS)  		return 0; -	if (gpio_is_valid(spi->cs_gpio)) { -		/* with gpio-cs set the GPIO to the correct level -		 * and as output (in case the dt has the gpio not configured -		 * as output but native cs) -		 */ -		ret = gpio_direction_output(spi->cs_gpio, -					    (spi->mode & SPI_CS_HIGH) ? 0 : 1); -		if (ret) -			dev_err(&spi->dev, -				"could not set gpio %i as output: %i\n", -				spi->cs_gpio, ret); - -		return ret; -	} + +	if (spi->cs_gpiod) +		return 0;  	/* for dt-backwards compatibility: only support native on CS0  	 * known things not supported with broken native CS: @@ -519,6 +505,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev)  	master->prepare_message = bcm2835aux_spi_prepare_message;  	master->unprepare_message = bcm2835aux_spi_unprepare_message;  	master->dev.of_node = pdev->dev.of_node; +	master->use_gpio_descriptors = true;  	bs = spi_master_get_devdata(master); diff --git a/drivers/spi/spi-bitbang-txrx.h b/drivers/spi/spi-bitbang-txrx.h index ae61d72c7d28..267342dfa738 100644 --- a/drivers/spi/spi-bitbang-txrx.h +++ b/drivers/spi/spi-bitbang-txrx.h @@ -41,6 +41,8 @@   * chips need ... there may be several reasons you'd need to tweak timings   * in these routines, not just to make it faster or slower to match a   * particular CPU clock rate. + * + * ToDo: Maybe the bitrev macros can be used to improve the code?   */  static inline u32 @@ -106,3 +108,67 @@ bitbang_txrx_be_cpha1(struct spi_device *spi,  	}  	return word;  } + +static inline u32 +bitbang_txrx_le_cpha0(struct spi_device *spi, +		unsigned int nsecs, unsigned int cpol, unsigned int flags, +		u32 word, u8 bits) +{ +	/* if (cpol == 0) this is SPI_MODE_0; else this is SPI_MODE_2 */ + +	u32 oldbit = !(word & 1); +	/* clock starts at inactive polarity */ +	for (; likely(bits); bits--) { + +		/* setup LSB (to slave) on trailing edge */ +		if ((flags & SPI_MASTER_NO_TX) == 0) { +			if ((word & 1) != oldbit) { +				setmosi(spi, word & 1); +				oldbit = word & 1; +			} +		} +		spidelay(nsecs);	/* T(setup) */ + +		setsck(spi, !cpol); +		spidelay(nsecs); + +		/* sample LSB (from slave) on leading edge */ +		word >>= 1; +		if ((flags & SPI_MASTER_NO_RX) == 0) +			word |= getmiso(spi) << (bits - 1); +		setsck(spi, cpol); +	} +	return word; +} + +static inline u32 +bitbang_txrx_le_cpha1(struct spi_device *spi, +		unsigned int nsecs, unsigned int cpol, unsigned int flags, +		u32 word, u8 bits) +{ +	/* if (cpol == 0) this is SPI_MODE_1; else this is SPI_MODE_3 */ + +	u32 oldbit = !(word & 1); +	/* clock starts at inactive polarity */ +	for (; likely(bits); bits--) { + +		/* setup LSB (to slave) on leading edge */ +		setsck(spi, !cpol); +		if ((flags & SPI_MASTER_NO_TX) == 0) { +			if ((word & 1) != oldbit) { +				setmosi(spi, word & 1); +				oldbit = word & 1; +			} +		} +		spidelay(nsecs); /* T(setup) */ + +		setsck(spi, cpol); +		spidelay(nsecs); + +		/* sample LSB (from slave) on trailing edge */ +		word >>= 1; +		if ((flags & SPI_MASTER_NO_RX) == 0) +			word |= getmiso(spi) << (bits - 1); +	} +	return word; +} diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c index 4bc1b93fc276..3ab19be83095 100644 --- a/drivers/spi/spi-cadence-xspi.c +++ b/drivers/spi/spi-cadence-xspi.c @@ -578,10 +578,8 @@ static int cdns_xspi_probe(struct platform_device *pdev)  	}  	cdns_xspi->irq = platform_get_irq(pdev, 0); -	if (cdns_xspi->irq < 0) { -		dev_err(dev, "Failed to get IRQ\n"); +	if (cdns_xspi->irq < 0)  		return -ENXIO; -	}  	ret = devm_request_irq(dev, cdns_xspi->irq, cdns_xspi_irq_handler,  			       IRQF_SHARED, pdev->name, cdns_xspi); diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c index b6c7467f0b59..d403a7a3021d 100644 --- a/drivers/spi/spi-fsi.c +++ b/drivers/spi/spi-fsi.c @@ -25,6 +25,7 @@  #define SPI_FSI_BASE			0x70000  #define SPI_FSI_INIT_TIMEOUT_MS		1000 +#define SPI_FSI_STATUS_TIMEOUT_MS	100  #define SPI_FSI_MAX_RX_SIZE		8  #define SPI_FSI_MAX_TX_SIZE		40 @@ -299,6 +300,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,  				 struct spi_transfer *transfer)  {  	int rc = 0; +	unsigned long end;  	u64 status = 0ULL;  	if (transfer->tx_buf) { @@ -315,10 +317,14 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,  			if (rc)  				return rc; +			end = jiffies + msecs_to_jiffies(SPI_FSI_STATUS_TIMEOUT_MS);  			do {  				rc = fsi_spi_status(ctx, &status, "TX");  				if (rc)  					return rc; + +				if (time_after(jiffies, end)) +					return -ETIMEDOUT;  			} while (status & SPI_FSI_STATUS_TDR_FULL);  			sent += nb; @@ -329,10 +335,14 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,  		u8 *rx = transfer->rx_buf;  		while (transfer->len > recv) { +			end = jiffies + msecs_to_jiffies(SPI_FSI_STATUS_TIMEOUT_MS);  			do {  				rc = fsi_spi_status(ctx, &status, "RX");  				if (rc)  					return rc; + +				if (time_after(jiffies, end)) +					return -ETIMEDOUT;  			} while (!(status & SPI_FSI_STATUS_RDR_FULL));  			rc = fsi_spi_read_reg(ctx, SPI_FSI_DATA_RX, &in); diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c index 0584f4d2fde2..4b12c4964a66 100644 --- a/drivers/spi/spi-gpio.c +++ b/drivers/spi/spi-gpio.c @@ -135,25 +135,37 @@ static inline int getmiso(const struct spi_device *spi)  static u32 spi_gpio_txrx_word_mode0(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  { -	return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits); +	else +		return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);  }  static u32 spi_gpio_txrx_word_mode1(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  { -	return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits); +	else +		return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);  }  static u32 spi_gpio_txrx_word_mode2(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  { -	return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits); +	else +		return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);  }  static u32 spi_gpio_txrx_word_mode3(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  { -	return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits); +	else +		return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);  }  /* @@ -170,28 +182,40 @@ static u32 spi_gpio_spec_txrx_word_mode0(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  {  	flags = spi->master->flags; -	return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha0(spi, nsecs, 0, flags, word, bits); +	else +		return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);  }  static u32 spi_gpio_spec_txrx_word_mode1(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  {  	flags = spi->master->flags; -	return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha1(spi, nsecs, 0, flags, word, bits); +	else +		return bitbang_txrx_be_cpha1(spi, nsecs, 0, flags, word, bits);  }  static u32 spi_gpio_spec_txrx_word_mode2(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  {  	flags = spi->master->flags; -	return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha0(spi, nsecs, 1, flags, word, bits); +	else +		return bitbang_txrx_be_cpha0(spi, nsecs, 1, flags, word, bits);  }  static u32 spi_gpio_spec_txrx_word_mode3(struct spi_device *spi,  		unsigned nsecs, u32 word, u8 bits, unsigned flags)  {  	flags = spi->master->flags; -	return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits); +	if (unlikely(spi->mode & SPI_LSB_FIRST)) +		return bitbang_txrx_le_cpha1(spi, nsecs, 1, flags, word, bits); +	else +		return bitbang_txrx_be_cpha1(spi, nsecs, 1, flags, word, bits);  }  /*----------------------------------------------------------------------*/ @@ -378,7 +402,7 @@ static int spi_gpio_probe(struct platform_device *pdev)  	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);  	master->mode_bits = SPI_3WIRE | SPI_3WIRE_HIZ | SPI_CPHA | SPI_CPOL | -			    SPI_CS_HIGH; +			    SPI_CS_HIGH | SPI_LSB_FIRST;  	if (!spi_gpio->mosi) {  		/* HW configuration without MOSI pin  		 * diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/spi/spi-intel-pci.c index 1bc53b8bb88a..a5ef7a526a7f 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c +++ b/drivers/spi/spi-intel-pci.c @@ -2,34 +2,48 @@  /*   * Intel PCH/PCU SPI flash PCI driver.   * - * Copyright (C) 2016, Intel Corporation + * Copyright (C) 2016 - 2022, Intel Corporation   * Author: Mika Westerberg <mika.westerberg@linux.intel.com>   */ -#include <linux/ioport.h> -#include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include "intel-spi.h" +#include "spi-intel.h"  #define BCR		0xdc  #define BCR_WPD		BIT(0) +static bool intel_spi_pci_set_writeable(void __iomem *base, void *data) +{ +	struct pci_dev *pdev = data; +	u32 bcr; + +	/* Try to make the chip read/write */ +	pci_read_config_dword(pdev, BCR, &bcr); +	if (!(bcr & BCR_WPD)) { +		bcr |= BCR_WPD; +		pci_write_config_dword(pdev, BCR, bcr); +		pci_read_config_dword(pdev, BCR, &bcr); +	} + +	return bcr & BCR_WPD; +} +  static const struct intel_spi_boardinfo bxt_info = {  	.type = INTEL_SPI_BXT, +	.set_writeable = intel_spi_pci_set_writeable,  };  static const struct intel_spi_boardinfo cnl_info = {  	.type = INTEL_SPI_CNL, +	.set_writeable = intel_spi_pci_set_writeable,  };  static int intel_spi_pci_probe(struct pci_dev *pdev,  			       const struct pci_device_id *id)  {  	struct intel_spi_boardinfo *info; -	struct intel_spi *ispi; -	u32 bcr;  	int ret;  	ret = pcim_enable_device(pdev); @@ -41,26 +55,8 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,  	if (!info)  		return -ENOMEM; -	/* Try to make the chip read/write */ -	pci_read_config_dword(pdev, BCR, &bcr); -	if (!(bcr & BCR_WPD)) { -		bcr |= BCR_WPD; -		pci_write_config_dword(pdev, BCR, bcr); -		pci_read_config_dword(pdev, BCR, &bcr); -	} -	info->writeable = !!(bcr & BCR_WPD); - -	ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info); -	if (IS_ERR(ispi)) -		return PTR_ERR(ispi); - -	pci_set_drvdata(pdev, ispi); -	return 0; -} - -static void intel_spi_pci_remove(struct pci_dev *pdev) -{ -	intel_spi_remove(pci_get_drvdata(pdev)); +	info->data = pdev; +	return intel_spi_probe(&pdev->dev, &pdev->resource[0], info);  }  static const struct pci_device_id intel_spi_pci_ids[] = { @@ -70,6 +66,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = {  	{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },  	{ PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info },  	{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info }, +	{ PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info },  	{ PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },  	{ PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },  	{ PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info }, @@ -89,7 +86,6 @@ static struct pci_driver intel_spi_pci_driver = {  	.name = "intel-spi",  	.id_table = intel_spi_pci_ids,  	.probe = intel_spi_pci_probe, -	.remove = intel_spi_pci_remove,  };  module_pci_driver(intel_spi_pci_driver); diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c b/drivers/spi/spi-intel-platform.c index f80f1086f928..2ef09fa35661 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c +++ b/drivers/spi/spi-intel-platform.c @@ -2,20 +2,18 @@  /*   * Intel PCH/PCU SPI flash platform driver.   * - * Copyright (C) 2016, Intel Corporation + * Copyright (C) 2016 - 2022, Intel Corporation   * Author: Mika Westerberg <mika.westerberg@linux.intel.com>   */ -#include <linux/ioport.h>  #include <linux/module.h>  #include <linux/platform_device.h> -#include "intel-spi.h" +#include "spi-intel.h"  static int intel_spi_platform_probe(struct platform_device *pdev)  {  	struct intel_spi_boardinfo *info; -	struct intel_spi *ispi;  	struct resource *mem;  	info = dev_get_platdata(&pdev->dev); @@ -23,24 +21,11 @@ static int intel_spi_platform_probe(struct platform_device *pdev)  		return -EINVAL;  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	ispi = intel_spi_probe(&pdev->dev, mem, info); -	if (IS_ERR(ispi)) -		return PTR_ERR(ispi); - -	platform_set_drvdata(pdev, ispi); -	return 0; -} - -static int intel_spi_platform_remove(struct platform_device *pdev) -{ -	struct intel_spi *ispi = platform_get_drvdata(pdev); - -	return intel_spi_remove(ispi); +	return intel_spi_probe(&pdev->dev, mem, info);  }  static struct platform_driver intel_spi_platform_driver = {  	.probe = intel_spi_platform_probe, -	.remove = intel_spi_platform_remove,  	.driver = {  		.name = "intel-spi",  	}, diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/spi/spi-intel.c index a413892ff449..e937cfe85559 100644 --- a/drivers/mtd/spi-nor/controllers/intel-spi.c +++ b/drivers/spi/spi-intel.c @@ -2,21 +2,21 @@  /*   * Intel PCH/PCU SPI flash driver.   * - * Copyright (C) 2016, Intel Corporation + * Copyright (C) 2016 - 2022, Intel Corporation   * Author: Mika Westerberg <mika.westerberg@linux.intel.com>   */ -#include <linux/err.h> -#include <linux/io.h>  #include <linux/iopoll.h>  #include <linux/module.h> -#include <linux/sched.h> -#include <linux/sizes.h> -#include <linux/mtd/mtd.h> +  #include <linux/mtd/partitions.h>  #include <linux/mtd/spi-nor.h> -#include "intel-spi.h" +#include <linux/spi/flash.h> +#include <linux/spi/spi.h> +#include <linux/spi/spi-mem.h> + +#include "spi-intel.h"  /* Offsets are from @ispi->base */  #define BFPREG				0x00 @@ -92,8 +92,6 @@  /* CPU specifics */  #define BYT_PR				0x74  #define BYT_SSFSTS_CTL			0x90 -#define BYT_BCR				0xfc -#define BYT_BCR_WPD			BIT(0)  #define BYT_FREG_NUM			5  #define BYT_PR_NUM			5 @@ -125,37 +123,43 @@   * struct intel_spi - Driver private data   * @dev: Device pointer   * @info: Pointer to board specific info - * @nor: SPI NOR layer structure   * @base: Beginning of MMIO space   * @pregs: Start of protection registers   * @sregs: Start of software sequencer registers + * @master: Pointer to the SPI controller structure   * @nregions: Maximum number of regions   * @pr_num: Maximum number of protected range registers - * @writeable: Is the chip writeable   * @locked: Is SPI setting locked   * @swseq_reg: Use SW sequencer in register reads/writes   * @swseq_erase: Use SW sequencer in erase operation - * @erase_64k: 64k erase supported   * @atomic_preopcode: Holds preopcode when atomic sequence is requested   * @opcodes: Opcodes which are supported. This are programmed by BIOS   *           before it locks down the controller. + * @mem_ops: Pointer to SPI MEM ops supported by the controller   */  struct intel_spi {  	struct device *dev;  	const struct intel_spi_boardinfo *info; -	struct spi_nor nor;  	void __iomem *base;  	void __iomem *pregs;  	void __iomem *sregs; +	struct spi_controller *master;  	size_t nregions;  	size_t pr_num; -	bool writeable;  	bool locked;  	bool swseq_reg;  	bool swseq_erase; -	bool erase_64k;  	u8 atomic_preopcode;  	u8 opcodes[8]; +	const struct intel_spi_mem_op *mem_ops; +}; + +struct intel_spi_mem_op { +	struct spi_mem_op mem_op; +	u32 replacement_op; +	int (*exec_op)(struct intel_spi *ispi, +		       const struct intel_spi_mem_op *iop, +		       const struct spi_mem_op *op);  };  static bool writeable; @@ -201,9 +205,6 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)  			readl(ispi->sregs + OPMENU1));  	} -	if (ispi->info->type == INTEL_SPI_BYT) -		dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR)); -  	dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC));  	dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC)); @@ -219,9 +220,8 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)  		base = value & PR_BASE_MASK;  		dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x [%c%c]\n", -			 i, base << 12, (limit << 12) | 0xfff, -			 value & PR_WPE ? 'W' : '.', -			 value & PR_RPE ? 'R' : '.'); +			i, base << 12, (limit << 12) | 0xfff, +			value & PR_WPE ? 'W' : '.', value & PR_RPE ? 'R' : '.');  	}  	dev_dbg(ispi->dev, "Flash regions:\n"); @@ -236,7 +236,7 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)  			dev_dbg(ispi->dev, " %02d disabled\n", i);  		else  			dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x\n", -				 i, base << 12, (limit << 12) | 0xfff); +				i, base << 12, (limit << 12) | 0xfff);  	}  	dev_dbg(ispi->dev, "Using %cW sequencer for register access\n", @@ -304,124 +304,12 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi)  				  INTEL_SPI_TIMEOUT * 1000);  } -static int intel_spi_init(struct intel_spi *ispi) +static bool intel_spi_set_writeable(struct intel_spi *ispi)  { -	u32 opmenu0, opmenu1, lvscc, uvscc, val; -	int i; - -	switch (ispi->info->type) { -	case INTEL_SPI_BYT: -		ispi->sregs = ispi->base + BYT_SSFSTS_CTL; -		ispi->pregs = ispi->base + BYT_PR; -		ispi->nregions = BYT_FREG_NUM; -		ispi->pr_num = BYT_PR_NUM; -		ispi->swseq_reg = true; - -		if (writeable) { -			/* Disable write protection */ -			val = readl(ispi->base + BYT_BCR); -			if (!(val & BYT_BCR_WPD)) { -				val |= BYT_BCR_WPD; -				writel(val, ispi->base + BYT_BCR); -				val = readl(ispi->base + BYT_BCR); -			} - -			ispi->writeable = !!(val & BYT_BCR_WPD); -		} - -		break; - -	case INTEL_SPI_LPT: -		ispi->sregs = ispi->base + LPT_SSFSTS_CTL; -		ispi->pregs = ispi->base + LPT_PR; -		ispi->nregions = LPT_FREG_NUM; -		ispi->pr_num = LPT_PR_NUM; -		ispi->swseq_reg = true; -		break; - -	case INTEL_SPI_BXT: -		ispi->sregs = ispi->base + BXT_SSFSTS_CTL; -		ispi->pregs = ispi->base + BXT_PR; -		ispi->nregions = BXT_FREG_NUM; -		ispi->pr_num = BXT_PR_NUM; -		ispi->erase_64k = true; -		break; - -	case INTEL_SPI_CNL: -		ispi->sregs = NULL; -		ispi->pregs = ispi->base + CNL_PR; -		ispi->nregions = CNL_FREG_NUM; -		ispi->pr_num = CNL_PR_NUM; -		break; +	if (!ispi->info->set_writeable) +		return false; -	default: -		return -EINVAL; -	} - -	/* Disable #SMI generation from HW sequencer */ -	val = readl(ispi->base + HSFSTS_CTL); -	val &= ~HSFSTS_CTL_FSMIE; -	writel(val, ispi->base + HSFSTS_CTL); - -	/* -	 * Determine whether erase operation should use HW or SW sequencer. -	 * -	 * The HW sequencer has a predefined list of opcodes, with only the -	 * erase opcode being programmable in LVSCC and UVSCC registers. -	 * If these registers don't contain a valid erase opcode, erase -	 * cannot be done using HW sequencer. -	 */ -	lvscc = readl(ispi->base + LVSCC); -	uvscc = readl(ispi->base + UVSCC); -	if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK)) -		ispi->swseq_erase = true; -	/* SPI controller on Intel BXT supports 64K erase opcode */ -	if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase) -		if (!(lvscc & ERASE_64K_OPCODE_MASK) || -		    !(uvscc & ERASE_64K_OPCODE_MASK)) -			ispi->erase_64k = false; - -	if (ispi->sregs == NULL && (ispi->swseq_reg || ispi->swseq_erase)) { -		dev_err(ispi->dev, "software sequencer not supported, but required\n"); -		return -EINVAL; -	} - -	/* -	 * Some controllers can only do basic operations using hardware -	 * sequencer. All other operations are supposed to be carried out -	 * using software sequencer. -	 */ -	if (ispi->swseq_reg) { -		/* Disable #SMI generation from SW sequencer */ -		val = readl(ispi->sregs + SSFSTS_CTL); -		val &= ~SSFSTS_CTL_FSMIE; -		writel(val, ispi->sregs + SSFSTS_CTL); -	} - -	/* Check controller's lock status */ -	val = readl(ispi->base + HSFSTS_CTL); -	ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN); - -	if (ispi->locked && ispi->sregs) { -		/* -		 * BIOS programs allowed opcodes and then locks down the -		 * register. So read back what opcodes it decided to support. -		 * That's the set we are going to support as well. -		 */ -		opmenu0 = readl(ispi->sregs + OPMENU0); -		opmenu1 = readl(ispi->sregs + OPMENU1); - -		if (opmenu0 && opmenu1) { -			for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) { -				ispi->opcodes[i] = opmenu0 >> i * 8; -				ispi->opcodes[i + 4] = opmenu1 >> i * 8; -			} -		} -	} - -	intel_spi_dump_regs(ispi); - -	return 0; +	return ispi->info->set_writeable(ispi->base, ispi->info->data);  }  static int intel_spi_opcode_index(struct intel_spi *ispi, u8 opcode, int optype) @@ -537,7 +425,6 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,  		default:  			return -EINVAL;  		} -  	}  	writel(val, ispi->sregs + SSFSTS_CTL); @@ -554,31 +441,35 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,  	return 0;  } -static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, -			      size_t len) +static int intel_spi_read_reg(struct intel_spi *ispi, +			      const struct intel_spi_mem_op *iop, +			      const struct spi_mem_op *op)  { -	struct intel_spi *ispi = nor->priv; +	size_t nbytes = op->data.nbytes; +	u8 opcode = op->cmd.opcode;  	int ret;  	/* Address of the first chip */  	writel(0, ispi->base + FADDR);  	if (ispi->swseq_reg) -		ret = intel_spi_sw_cycle(ispi, opcode, len, +		ret = intel_spi_sw_cycle(ispi, opcode, nbytes,  					 OPTYPE_READ_NO_ADDR);  	else -		ret = intel_spi_hw_cycle(ispi, opcode, len); +		ret = intel_spi_hw_cycle(ispi, opcode, nbytes);  	if (ret)  		return ret; -	return intel_spi_read_block(ispi, buf, len); +	return intel_spi_read_block(ispi, op->data.buf.in, nbytes);  } -static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf, -			       size_t len) +static int intel_spi_write_reg(struct intel_spi *ispi, +			       const struct intel_spi_mem_op *iop, +			       const struct spi_mem_op *op)  { -	struct intel_spi *ispi = nor->priv; +	size_t nbytes = op->data.nbytes; +	u8 opcode = op->cmd.opcode;  	int ret;  	/* @@ -623,23 +514,25 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,  	writel(0, ispi->base + FADDR);  	/* Write the value beforehand */ -	ret = intel_spi_write_block(ispi, buf, len); +	ret = intel_spi_write_block(ispi, op->data.buf.out, nbytes);  	if (ret)  		return ret;  	if (ispi->swseq_reg) -		return intel_spi_sw_cycle(ispi, opcode, len, +		return intel_spi_sw_cycle(ispi, opcode, nbytes,  					  OPTYPE_WRITE_NO_ADDR); -	return intel_spi_hw_cycle(ispi, opcode, len); +	return intel_spi_hw_cycle(ispi, opcode, nbytes);  } -static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len, -			      u_char *read_buf) +static int intel_spi_read(struct intel_spi *ispi, +			  const struct intel_spi_mem_op *iop, +			  const struct spi_mem_op *op)  { -	struct intel_spi *ispi = nor->priv; -	size_t block_size, retlen = 0; +	void *read_buf = op->data.buf.in; +	size_t block_size, nbytes = op->data.nbytes; +	u32 addr = op->addr.val;  	u32 val, status; -	ssize_t ret; +	int ret;  	/*  	 * Atomic sequence is not expected with HW sequencer reads. Make @@ -648,24 +541,14 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,  	if (WARN_ON_ONCE(ispi->atomic_preopcode))  		ispi->atomic_preopcode = 0; -	switch (nor->read_opcode) { -	case SPINOR_OP_READ: -	case SPINOR_OP_READ_FAST: -	case SPINOR_OP_READ_4B: -	case SPINOR_OP_READ_FAST_4B: -		break; -	default: -		return -EINVAL; -	} - -	while (len > 0) { -		block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); +	while (nbytes > 0) { +		block_size = min_t(size_t, nbytes, INTEL_SPI_FIFO_SZ);  		/* Read cannot cross 4K boundary */ -		block_size = min_t(loff_t, from + block_size, -				   round_up(from + 1, SZ_4K)) - from; +		block_size = min_t(loff_t, addr + block_size, +				   round_up(addr + 1, SZ_4K)) - addr; -		writel(from, ispi->base + FADDR); +		writel(addr, ispi->base + FADDR);  		val = readl(ispi->base + HSFSTS_CTL);  		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); @@ -686,8 +569,7 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,  			ret = -EACCES;  		if (ret < 0) { -			dev_err(ispi->dev, "read error: %llx: %#x\n", from, -				status); +			dev_err(ispi->dev, "read error: %x: %#x\n", addr, status);  			return ret;  		} @@ -695,34 +577,35 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,  		if (ret)  			return ret; -		len -= block_size; -		from += block_size; -		retlen += block_size; +		nbytes -= block_size; +		addr += block_size;  		read_buf += block_size;  	} -	return retlen; +	return 0;  } -static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len, -			       const u_char *write_buf) +static int intel_spi_write(struct intel_spi *ispi, +			   const struct intel_spi_mem_op *iop, +			   const struct spi_mem_op *op)  { -	struct intel_spi *ispi = nor->priv; -	size_t block_size, retlen = 0; +	size_t block_size, nbytes = op->data.nbytes; +	const void *write_buf = op->data.buf.out; +	u32 addr = op->addr.val;  	u32 val, status; -	ssize_t ret; +	int ret;  	/* Not needed with HW sequencer write, make sure it is cleared */  	ispi->atomic_preopcode = 0; -	while (len > 0) { -		block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ); +	while (nbytes > 0) { +		block_size = min_t(size_t, nbytes, INTEL_SPI_FIFO_SZ);  		/* Write cannot cross 4K boundary */ -		block_size = min_t(loff_t, to + block_size, -				   round_up(to + 1, SZ_4K)) - to; +		block_size = min_t(loff_t, addr + block_size, +				   round_up(addr + 1, SZ_4K)) - addr; -		writel(to, ispi->base + FADDR); +		writel(addr, ispi->base + FADDR);  		val = readl(ispi->base + HSFSTS_CTL);  		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); @@ -753,79 +636,476 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,  			ret = -EACCES;  		if (ret < 0) { -			dev_err(ispi->dev, "write error: %llx: %#x\n", to, -				status); +			dev_err(ispi->dev, "write error: %x: %#x\n", addr, status);  			return ret;  		} -		len -= block_size; -		to += block_size; -		retlen += block_size; +		nbytes -= block_size; +		addr += block_size;  		write_buf += block_size;  	} -	return retlen; +	return 0;  } -static int intel_spi_erase(struct spi_nor *nor, loff_t offs) +static int intel_spi_erase(struct intel_spi *ispi, +			   const struct intel_spi_mem_op *iop, +			   const struct spi_mem_op *op)  { -	size_t erase_size, len = nor->mtd.erasesize; -	struct intel_spi *ispi = nor->priv; -	u32 val, status, cmd; +	u8 opcode = op->cmd.opcode; +	u32 addr = op->addr.val; +	u32 val, status;  	int ret; -	/* If the hardware can do 64k erase use that when possible */ -	if (len >= SZ_64K && ispi->erase_64k) { -		cmd = HSFSTS_CTL_FCYCLE_ERASE_64K; -		erase_size = SZ_64K; -	} else { -		cmd = HSFSTS_CTL_FCYCLE_ERASE; -		erase_size = SZ_4K; +	writel(addr, ispi->base + FADDR); + +	if (ispi->swseq_erase) +		return intel_spi_sw_cycle(ispi, opcode, 0, +					  OPTYPE_WRITE_WITH_ADDR); + +	/* Not needed with HW sequencer erase, make sure it is cleared */ +	ispi->atomic_preopcode = 0; + +	val = readl(ispi->base + HSFSTS_CTL); +	val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); +	val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; +	val |= HSFSTS_CTL_FGO; +	val |= iop->replacement_op; +	writel(val, ispi->base + HSFSTS_CTL); + +	ret = intel_spi_wait_hw_busy(ispi); +	if (ret) +		return ret; + +	status = readl(ispi->base + HSFSTS_CTL); +	if (status & HSFSTS_CTL_FCERR) +		return -EIO; +	if (status & HSFSTS_CTL_AEL) +		return -EACCES; + +	return 0; +} + +static bool intel_spi_cmp_mem_op(const struct intel_spi_mem_op *iop, +				 const struct spi_mem_op *op) +{ +	if (iop->mem_op.cmd.nbytes != op->cmd.nbytes || +	    iop->mem_op.cmd.buswidth != op->cmd.buswidth || +	    iop->mem_op.cmd.dtr != op->cmd.dtr || +	    iop->mem_op.cmd.opcode != op->cmd.opcode) +		return false; + +	if (iop->mem_op.addr.nbytes != op->addr.nbytes || +	    iop->mem_op.addr.dtr != op->addr.dtr) +		return false; + +	if (iop->mem_op.data.dir != op->data.dir || +	    iop->mem_op.data.dtr != op->data.dtr) +		return false; + +	if (iop->mem_op.data.dir != SPI_MEM_NO_DATA) { +		if (iop->mem_op.data.buswidth != op->data.buswidth) +			return false; +	} + +	return true; +} + +static const struct intel_spi_mem_op * +intel_spi_match_mem_op(struct intel_spi *ispi, const struct spi_mem_op *op) +{ +	const struct intel_spi_mem_op *iop; + +	for (iop = ispi->mem_ops; iop->mem_op.cmd.opcode; iop++) { +		if (intel_spi_cmp_mem_op(iop, op)) +			break;  	} -	if (ispi->swseq_erase) { -		while (len > 0) { -			writel(offs, ispi->base + FADDR); +	return iop->mem_op.cmd.opcode ? iop : NULL; +} + +static bool intel_spi_supports_mem_op(struct spi_mem *mem, +				      const struct spi_mem_op *op) +{ +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); +	const struct intel_spi_mem_op *iop; + +	iop = intel_spi_match_mem_op(ispi, op); +	if (!iop) { +		dev_dbg(ispi->dev, "%#x not supported\n", op->cmd.opcode); +		return false; +	} -			ret = intel_spi_sw_cycle(ispi, nor->erase_opcode, -						 0, OPTYPE_WRITE_WITH_ADDR); -			if (ret) -				return ret; +	/* +	 * For software sequencer check that the opcode is actually +	 * present in the opmenu if it is locked. +	 */ +	if (ispi->swseq_reg && ispi->locked) { +		int i; -			offs += erase_size; -			len -= erase_size; +		/* Check if it is in the locked opcodes list */ +		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) { +			if (ispi->opcodes[i] == op->cmd.opcode) +				return true;  		} -		return 0; +		dev_dbg(ispi->dev, "%#x not supported\n", op->cmd.opcode); +		return false;  	} -	/* Not needed with HW sequencer erase, make sure it is cleared */ -	ispi->atomic_preopcode = 0; +	return true; +} -	while (len > 0) { -		writel(offs, ispi->base + FADDR); +static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) +{ +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); +	const struct intel_spi_mem_op *iop; -		val = readl(ispi->base + HSFSTS_CTL); -		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK); -		val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE; -		val |= cmd; -		val |= HSFSTS_CTL_FGO; -		writel(val, ispi->base + HSFSTS_CTL); +	iop = intel_spi_match_mem_op(ispi, op); +	if (!iop) +		return -EOPNOTSUPP; -		ret = intel_spi_wait_hw_busy(ispi); -		if (ret) -			return ret; +	return iop->exec_op(ispi, iop, op); +} -		status = readl(ispi->base + HSFSTS_CTL); -		if (status & HSFSTS_CTL_FCERR) -			return -EIO; -		else if (status & HSFSTS_CTL_AEL) -			return -EACCES; +static const char *intel_spi_get_name(struct spi_mem *mem) +{ +	const struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master); + +	/* +	 * Return name of the flash controller device to be compatible +	 * with the MTD version. +	 */ +	return dev_name(ispi->dev); +} + +static const struct spi_controller_mem_ops intel_spi_mem_ops = { +	.supports_op = intel_spi_supports_mem_op, +	.exec_op = intel_spi_exec_mem_op, +	.get_name = intel_spi_get_name, +}; + +#define INTEL_SPI_OP_ADDR(__nbytes)					\ +	{								\ +		.nbytes = __nbytes,					\ +	} + +#define INTEL_SPI_OP_NO_DATA						\ +	{								\ +		.dir = SPI_MEM_NO_DATA,					\ +	} + +#define INTEL_SPI_OP_DATA_IN(__buswidth)				\ +	{								\ +		.dir = SPI_MEM_DATA_IN,					\ +		.buswidth = __buswidth,					\ +	} + +#define INTEL_SPI_OP_DATA_OUT(__buswidth)				\ +	{								\ +		.dir = SPI_MEM_DATA_OUT,				\ +		.buswidth = __buswidth,					\ +	} + +#define INTEL_SPI_MEM_OP(__cmd, __addr, __data, __exec_op)		\ +	{								\ +		.mem_op = {						\ +			.cmd = __cmd,					\ +			.addr = __addr,					\ +			.data = __data,					\ +		},							\ +		.exec_op = __exec_op,					\ +	} + +#define INTEL_SPI_MEM_OP_REPL(__cmd, __addr, __data, __exec_op, __repl)	\ +	{								\ +		.mem_op = {						\ +			.cmd = __cmd,					\ +			.addr = __addr,					\ +			.data = __data,					\ +		},							\ +		.exec_op = __exec_op,					\ +		.replacement_op = __repl,				\ +	} + +/* + * The controller handles pretty much everything internally based on the + * SFDP data but we want to make sure we only support the operations + * actually possible. Only check buswidth and transfer direction, the + * core validates data. + */ +#define INTEL_SPI_GENERIC_OPS						\ +	/* Status register operations */				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),		\ +			 SPI_MEM_OP_NO_ADDR,				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read_reg),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 1),		\ +			 SPI_MEM_OP_NO_ADDR,				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read_reg),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 1),		\ +			 SPI_MEM_OP_NO_ADDR,				\ +			 INTEL_SPI_OP_DATA_OUT(1),			\ +			 intel_spi_write_reg),				\ +	/* Normal read */						\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),		\ +			 INTEL_SPI_OP_ADDR(3),				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),		\ +			 INTEL_SPI_OP_ADDR(3),				\ +			 INTEL_SPI_OP_DATA_IN(2),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),		\ +			 INTEL_SPI_OP_ADDR(3),				\ +			 INTEL_SPI_OP_DATA_IN(4),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(2),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(4),			\ +			 intel_spi_read),				\ +	/* Fast read */							\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),	\ +			 INTEL_SPI_OP_ADDR(3),				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),	\ +			 INTEL_SPI_OP_ADDR(3),				\ +			 INTEL_SPI_OP_DATA_IN(2),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),	\ +			 INTEL_SPI_OP_ADDR(3),				\ +			 INTEL_SPI_OP_DATA_IN(4),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),	\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),	\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(2),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST, 1),	\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(4),			\ +			 intel_spi_read),				\ +	/* Read with 4-byte address opcode */				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(2),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_4B, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(4),			\ +			 intel_spi_read),				\ +	/* Fast read with 4-byte address opcode */			\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1),	\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(1),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1),	\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(2),			\ +			 intel_spi_read),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_READ_FAST_4B, 1),	\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_IN(4),			\ +			 intel_spi_read),				\ +	/* Write operations */						\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP, 1),		\ +			 INTEL_SPI_OP_ADDR(3),				\ +			 INTEL_SPI_OP_DATA_OUT(1),			\ +			 intel_spi_write),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_OUT(1),			\ +			 intel_spi_write),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_PP_4B, 1),		\ +			 INTEL_SPI_OP_ADDR(4),				\ +			 INTEL_SPI_OP_DATA_OUT(1),			\ +			 intel_spi_write),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 1),		\ +			 SPI_MEM_OP_NO_ADDR,				\ +			 SPI_MEM_OP_NO_DATA,				\ +			 intel_spi_write_reg),				\ +	INTEL_SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 1),		\ +			 SPI_MEM_OP_NO_ADDR,				\ +			 SPI_MEM_OP_NO_DATA,				\ +			 intel_spi_write_reg),				\ +	/* Erase operations */						\ +	INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K, 1),	\ +			      INTEL_SPI_OP_ADDR(3),			\ +			      SPI_MEM_OP_NO_DATA,			\ +			      intel_spi_erase,				\ +			      HSFSTS_CTL_FCYCLE_ERASE),			\ +	INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K, 1),	\ +			      INTEL_SPI_OP_ADDR(4),			\ +			      SPI_MEM_OP_NO_DATA,			\ +			      intel_spi_erase,				\ +			      HSFSTS_CTL_FCYCLE_ERASE),			\ +	INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_BE_4K_4B, 1),	\ +			      INTEL_SPI_OP_ADDR(4),			\ +			      SPI_MEM_OP_NO_DATA,			\ +			      intel_spi_erase,				\ +			      HSFSTS_CTL_FCYCLE_ERASE)			\ + +static const struct intel_spi_mem_op generic_mem_ops[] = { +	INTEL_SPI_GENERIC_OPS, +	{ }, +}; + +static const struct intel_spi_mem_op erase_64k_mem_ops[] = { +	INTEL_SPI_GENERIC_OPS, +	/* 64k sector erase operations */ +	INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE, 1), +			      INTEL_SPI_OP_ADDR(3), +			      SPI_MEM_OP_NO_DATA, +			      intel_spi_erase, +			      HSFSTS_CTL_FCYCLE_ERASE_64K), +	INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE, 1), +			      INTEL_SPI_OP_ADDR(4), +			      SPI_MEM_OP_NO_DATA, +			      intel_spi_erase, +			      HSFSTS_CTL_FCYCLE_ERASE_64K), +	INTEL_SPI_MEM_OP_REPL(SPI_MEM_OP_CMD(SPINOR_OP_SE_4B, 1), +			      INTEL_SPI_OP_ADDR(4), +			      SPI_MEM_OP_NO_DATA, +			      intel_spi_erase, +			      HSFSTS_CTL_FCYCLE_ERASE_64K), +	{ }, +}; + +static int intel_spi_init(struct intel_spi *ispi) +{ +	u32 opmenu0, opmenu1, lvscc, uvscc, val; +	bool erase_64k = false; +	int i; + +	switch (ispi->info->type) { +	case INTEL_SPI_BYT: +		ispi->sregs = ispi->base + BYT_SSFSTS_CTL; +		ispi->pregs = ispi->base + BYT_PR; +		ispi->nregions = BYT_FREG_NUM; +		ispi->pr_num = BYT_PR_NUM; +		ispi->swseq_reg = true; +		break; + +	case INTEL_SPI_LPT: +		ispi->sregs = ispi->base + LPT_SSFSTS_CTL; +		ispi->pregs = ispi->base + LPT_PR; +		ispi->nregions = LPT_FREG_NUM; +		ispi->pr_num = LPT_PR_NUM; +		ispi->swseq_reg = true; +		break; + +	case INTEL_SPI_BXT: +		ispi->sregs = ispi->base + BXT_SSFSTS_CTL; +		ispi->pregs = ispi->base + BXT_PR; +		ispi->nregions = BXT_FREG_NUM; +		ispi->pr_num = BXT_PR_NUM; +		erase_64k = true; +		break; + +	case INTEL_SPI_CNL: +		ispi->sregs = NULL; +		ispi->pregs = ispi->base + CNL_PR; +		ispi->nregions = CNL_FREG_NUM; +		ispi->pr_num = CNL_PR_NUM; +		break; + +	default: +		return -EINVAL; +	} + +	/* Try to disable write protection if user asked to do so */ +	if (writeable && !intel_spi_set_writeable(ispi)) { +		dev_warn(ispi->dev, "can't disable chip write protection\n"); +		writeable = false; +	} + +	/* Disable #SMI generation from HW sequencer */ +	val = readl(ispi->base + HSFSTS_CTL); +	val &= ~HSFSTS_CTL_FSMIE; +	writel(val, ispi->base + HSFSTS_CTL); -		offs += erase_size; -		len -= erase_size; +	/* +	 * Determine whether erase operation should use HW or SW sequencer. +	 * +	 * The HW sequencer has a predefined list of opcodes, with only the +	 * erase opcode being programmable in LVSCC and UVSCC registers. +	 * If these registers don't contain a valid erase opcode, erase +	 * cannot be done using HW sequencer. +	 */ +	lvscc = readl(ispi->base + LVSCC); +	uvscc = readl(ispi->base + UVSCC); +	if (!(lvscc & ERASE_OPCODE_MASK) || !(uvscc & ERASE_OPCODE_MASK)) +		ispi->swseq_erase = true; +	/* SPI controller on Intel BXT supports 64K erase opcode */ +	if (ispi->info->type == INTEL_SPI_BXT && !ispi->swseq_erase) +		if (!(lvscc & ERASE_64K_OPCODE_MASK) || +		    !(uvscc & ERASE_64K_OPCODE_MASK)) +			erase_64k = false; + +	if (!ispi->sregs && (ispi->swseq_reg || ispi->swseq_erase)) { +		dev_err(ispi->dev, "software sequencer not supported, but required\n"); +		return -EINVAL; +	} + +	/* +	 * Some controllers can only do basic operations using hardware +	 * sequencer. All other operations are supposed to be carried out +	 * using software sequencer. +	 */ +	if (ispi->swseq_reg) { +		/* Disable #SMI generation from SW sequencer */ +		val = readl(ispi->sregs + SSFSTS_CTL); +		val &= ~SSFSTS_CTL_FSMIE; +		writel(val, ispi->sregs + SSFSTS_CTL);  	} +	/* Check controller's lock status */ +	val = readl(ispi->base + HSFSTS_CTL); +	ispi->locked = !!(val & HSFSTS_CTL_FLOCKDN); + +	if (ispi->locked && ispi->sregs) { +		/* +		 * BIOS programs allowed opcodes and then locks down the +		 * register. So read back what opcodes it decided to support. +		 * That's the set we are going to support as well. +		 */ +		opmenu0 = readl(ispi->sregs + OPMENU0); +		opmenu1 = readl(ispi->sregs + OPMENU1); + +		if (opmenu0 && opmenu1) { +			for (i = 0; i < ARRAY_SIZE(ispi->opcodes) / 2; i++) { +				ispi->opcodes[i] = opmenu0 >> i * 8; +				ispi->opcodes[i + 4] = opmenu1 >> i * 8; +			} +		} +	} + +	if (erase_64k) { +		dev_dbg(ispi->dev, "Using erase_64k memory operations"); +		ispi->mem_ops = erase_64k_mem_ops; +	} else { +		dev_dbg(ispi->dev, "Using generic memory operations"); +		ispi->mem_ops = generic_mem_ops; +	} + +	intel_spi_dump_regs(ispi);  	return 0;  } @@ -884,9 +1164,12 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,  		/*  		 * If any of the regions have protection bits set, make the  		 * whole partition read-only to be on the safe side. +		 * +		 * Also if the user did not ask the chip to be writeable +		 * mask the bit too.  		 */ -		if (intel_spi_is_protected(ispi, base, limit)) -			ispi->writeable = false; +		if (!writeable || intel_spi_is_protected(ispi, base, limit)) +			part->mask_flags |= MTD_WRITEABLE;  		end = (limit << 12) + 4096;  		if (end > part->size) @@ -894,75 +1177,74 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,  	}  } -static const struct spi_nor_controller_ops intel_spi_controller_ops = { -	.read_reg = intel_spi_read_reg, -	.write_reg = intel_spi_write_reg, -	.read = intel_spi_read, -	.write = intel_spi_write, -	.erase = intel_spi_erase, -}; +static int intel_spi_populate_chip(struct intel_spi *ispi) +{ +	struct flash_platform_data *pdata; +	struct spi_board_info chip; -struct intel_spi *intel_spi_probe(struct device *dev, -	struct resource *mem, const struct intel_spi_boardinfo *info) +	pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL); +	if (!pdata) +		return -ENOMEM; + +	pdata->nr_parts = 1; +	pdata->parts = devm_kcalloc(ispi->dev, sizeof(*pdata->parts), +				    pdata->nr_parts, GFP_KERNEL); +	if (!pdata->parts) +		return -ENOMEM; + +	intel_spi_fill_partition(ispi, pdata->parts); + +	memset(&chip, 0, sizeof(chip)); +	snprintf(chip.modalias, 8, "spi-nor"); +	chip.platform_data = pdata; + +	return spi_new_device(ispi->master, &chip) ? 0 : -ENODEV; +} + +/** + * intel_spi_probe() - Probe the Intel SPI flash controller + * @dev: Pointer to the parent device + * @mem: MMIO resource + * @info: Platform spefific information + * + * Probes Intel SPI flash controller and creates the flash chip device. + * Returns %0 on success and negative errno in case of failure. + */ +int intel_spi_probe(struct device *dev, struct resource *mem, +		    const struct intel_spi_boardinfo *info)  { -	const struct spi_nor_hwcaps hwcaps = { -		.mask = SNOR_HWCAPS_READ | -			SNOR_HWCAPS_READ_FAST | -			SNOR_HWCAPS_PP, -	}; -	struct mtd_partition part; +	struct spi_controller *master;  	struct intel_spi *ispi;  	int ret; -	if (!info || !mem) -		return ERR_PTR(-EINVAL); +	master = devm_spi_alloc_master(dev, sizeof(*ispi)); +	if (!master) +		return -ENOMEM; + +	master->mem_ops = &intel_spi_mem_ops; -	ispi = devm_kzalloc(dev, sizeof(*ispi), GFP_KERNEL); -	if (!ispi) -		return ERR_PTR(-ENOMEM); +	ispi = spi_master_get_devdata(master);  	ispi->base = devm_ioremap_resource(dev, mem);  	if (IS_ERR(ispi->base)) -		return ERR_CAST(ispi->base); +		return PTR_ERR(ispi->base);  	ispi->dev = dev; +	ispi->master = master;  	ispi->info = info; -	ispi->writeable = info->writeable;  	ret = intel_spi_init(ispi);  	if (ret) -		return ERR_PTR(ret); - -	ispi->nor.dev = ispi->dev; -	ispi->nor.priv = ispi; -	ispi->nor.controller_ops = &intel_spi_controller_ops; - -	ret = spi_nor_scan(&ispi->nor, NULL, &hwcaps); -	if (ret) { -		dev_info(dev, "failed to locate the chip\n"); -		return ERR_PTR(ret); -	} - -	intel_spi_fill_partition(ispi, &part); - -	/* Prevent writes if not explicitly enabled */ -	if (!ispi->writeable || !writeable) -		ispi->nor.mtd.flags &= ~MTD_WRITEABLE; +		return ret; -	ret = mtd_device_register(&ispi->nor.mtd, &part, 1); +	ret = devm_spi_register_master(dev, master);  	if (ret) -		return ERR_PTR(ret); +		return ret; -	return ispi; +	return intel_spi_populate_chip(ispi);  }  EXPORT_SYMBOL_GPL(intel_spi_probe); -int intel_spi_remove(struct intel_spi *ispi) -{ -	return mtd_device_unregister(&ispi->nor.mtd); -} -EXPORT_SYMBOL_GPL(intel_spi_remove); -  MODULE_DESCRIPTION("Intel PCH/PCU SPI flash core driver");  MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/spi/spi-intel.h b/drivers/spi/spi-intel.h new file mode 100644 index 000000000000..a4f0327a46ff --- /dev/null +++ b/drivers/spi/spi-intel.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Intel PCH/PCU SPI flash driver. + * + * Copyright (C) 2016 - 2022, Intel Corporation + * Author: Mika Westerberg <mika.westerberg@linux.intel.com> + */ + +#ifndef SPI_INTEL_H +#define SPI_INTEL_H + +#include <linux/platform_data/x86/spi-intel.h> + +struct resource; + +int intel_spi_probe(struct device *dev, struct resource *mem, +		    const struct intel_spi_boardinfo *info); + +#endif /* SPI_INTEL_H */ diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index bcb52601804a..aae26f62ea87 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -906,17 +906,11 @@ static int lantiq_ssc_probe(struct platform_device *pdev)  	struct spi_master *master;  	struct lantiq_ssc_spi *spi;  	const struct lantiq_ssc_hwcfg *hwcfg; -	const struct of_device_id *match;  	u32 id, supports_dma, revision;  	unsigned int num_cs;  	int err; -	match = of_match_device(lantiq_ssc_match, dev); -	if (!match) { -		dev_err(dev, "no device match\n"); -		return -EINVAL; -	} -	hwcfg = match->data; +	hwcfg = of_device_get_match_data(dev);  	master = spi_alloc_master(dev, sizeof(struct lantiq_ssc_spi));  	if (!master) diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c index 37f4443ce9a0..e9d83d65873b 100644 --- a/drivers/spi/spi-mem.c +++ b/drivers/spi/spi-mem.c @@ -854,15 +854,13 @@ static int spi_mem_probe(struct spi_device *spi)  	return memdrv->probe(mem);  } -static int spi_mem_remove(struct spi_device *spi) +static void spi_mem_remove(struct spi_device *spi)  {  	struct spi_mem_driver *memdrv = to_spi_mem_drv(spi->dev.driver);  	struct spi_mem *mem = spi_get_drvdata(spi);  	if (memdrv->remove) -		return memdrv->remove(mem); - -	return 0; +		memdrv->remove(mem);  }  static void spi_mem_shutdown(struct spi_device *spi) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 78a9bca8cc68..03630359ce70 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -23,7 +23,6 @@  #include <linux/clk.h>  #include <linux/spi/spi.h>  #include <linux/fsl_devices.h> -#include <linux/gpio.h>  #include <asm/mpc52xx_psc.h>  enum { @@ -128,17 +127,28 @@ static void mpc512x_psc_spi_activate_cs(struct spi_device *spi)  	out_be32(psc_addr(mps, ccr), ccr);  	mps->bits_per_word = cs->bits_per_word; -	if (mps->cs_control && gpio_is_valid(spi->cs_gpio)) -		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0); +	if (spi->cs_gpiod) { +		if (mps->cs_control) +			/* boardfile override */ +			mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 1 : 0); +		else +			/* gpiolib will deal with the inversion */ +			gpiod_set_value(spi->cs_gpiod, 1); +	}  }  static void mpc512x_psc_spi_deactivate_cs(struct spi_device *spi)  {  	struct mpc512x_psc_spi *mps = spi_master_get_devdata(spi->master); -	if (mps->cs_control && gpio_is_valid(spi->cs_gpio)) -		mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1); - +	if (spi->cs_gpiod) { +		if (mps->cs_control) +			/* boardfile override */ +			mps->cs_control(spi, (spi->mode & SPI_CS_HIGH) ? 0 : 1); +		else +			/* gpiolib will deal with the inversion */ +			gpiod_set_value(spi->cs_gpiod, 0); +	}  }  /* extract and scale size field in txsz or rxsz */ @@ -363,7 +373,6 @@ static int mpc512x_psc_spi_unprep_xfer_hw(struct spi_master *master)  static int mpc512x_psc_spi_setup(struct spi_device *spi)  {  	struct mpc512x_psc_spi_cs *cs = spi->controller_state; -	int ret;  	if (spi->bits_per_word % 8)  		return -EINVAL; @@ -373,18 +382,6 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi)  		if (!cs)  			return -ENOMEM; -		if (gpio_is_valid(spi->cs_gpio)) { -			ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev)); -			if (ret) { -				dev_err(&spi->dev, "can't get CS gpio: %d\n", -					ret); -				kfree(cs); -				return ret; -			} -			gpio_direction_output(spi->cs_gpio, -					spi->mode & SPI_CS_HIGH ? 0 : 1); -		} -  		spi->controller_state = cs;  	} @@ -396,8 +393,6 @@ static int mpc512x_psc_spi_setup(struct spi_device *spi)  static void mpc512x_psc_spi_cleanup(struct spi_device *spi)  { -	if (gpio_is_valid(spi->cs_gpio)) -		gpio_free(spi->cs_gpio);  	kfree(spi->controller_state);  } @@ -476,11 +471,6 @@ static irqreturn_t mpc512x_psc_spi_isr(int irq, void *dev_id)  	return IRQ_NONE;  } -static void mpc512x_spi_cs_control(struct spi_device *spi, bool onoff) -{ -	gpio_set_value(spi->cs_gpio, onoff); -} -  static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,  					      u32 size, unsigned int irq)  { @@ -500,9 +490,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,  	mps->type = (int)of_device_get_match_data(dev);  	mps->irq = irq; -	if (pdata == NULL) { -		mps->cs_control = mpc512x_spi_cs_control; -	} else { +	if (pdata) {  		mps->cs_control = pdata->cs_control;  		master->bus_num = pdata->bus_num;  		master->num_chipselect = pdata->max_chipselect; @@ -513,6 +501,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,  	master->prepare_transfer_hardware = mpc512x_psc_spi_prep_xfer_hw;  	master->transfer_one_message = mpc512x_psc_spi_msg_xfer;  	master->unprepare_transfer_hardware = mpc512x_psc_spi_unprep_xfer_hw; +	master->use_gpio_descriptors = true;  	master->cleanup = mpc512x_psc_spi_cleanup;  	master->dev.of_node = dev->of_node; diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 753bd313e6fd..1a0b3208dfca 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -12,7 +12,7 @@  #include <linux/ioport.h>  #include <linux/module.h>  #include <linux/of.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/platform_device.h>  #include <linux/platform_data/spi-mt65xx.h>  #include <linux/pm_runtime.h> @@ -31,6 +31,7 @@  #define SPI_CFG2_REG                      0x0028  #define SPI_TX_SRC_REG_64                 0x002c  #define SPI_RX_DST_REG_64                 0x0030 +#define SPI_CFG3_IPM_REG                  0x0040  #define SPI_CFG0_SCK_HIGH_OFFSET          0  #define SPI_CFG0_SCK_LOW_OFFSET           8 @@ -43,11 +44,15 @@  #define SPI_CFG1_PACKET_LOOP_OFFSET       8  #define SPI_CFG1_PACKET_LENGTH_OFFSET     16  #define SPI_CFG1_GET_TICK_DLY_OFFSET      29 +#define SPI_CFG1_GET_TICK_DLY_OFFSET_V1   30  #define SPI_CFG1_GET_TICK_DLY_MASK        0xe0000000 +#define SPI_CFG1_GET_TICK_DLY_MASK_V1     0xc0000000 +  #define SPI_CFG1_CS_IDLE_MASK             0xff  #define SPI_CFG1_PACKET_LOOP_MASK         0xff00  #define SPI_CFG1_PACKET_LENGTH_MASK       0x3ff0000 +#define SPI_CFG1_IPM_PACKET_LENGTH_MASK   GENMASK(31, 16)  #define SPI_CFG2_SCK_HIGH_OFFSET          0  #define SPI_CFG2_SCK_LOW_OFFSET           16 @@ -68,7 +73,13 @@  #define SPI_CMD_TX_ENDIAN            BIT(15)  #define SPI_CMD_FINISH_IE            BIT(16)  #define SPI_CMD_PAUSE_IE             BIT(17) +#define SPI_CMD_IPM_NONIDLE_MODE     BIT(19) +#define SPI_CMD_IPM_SPIM_LOOP        BIT(21) +#define SPI_CMD_IPM_GET_TICKDLY_OFFSET    22 +#define SPI_CMD_IPM_GET_TICKDLY_MASK	GENMASK(24, 22) +#define SPI_CFG3_IPM_HALF_DUPLEX_DIR		BIT(2) +#define SPI_CFG3_IPM_HALF_DUPLEX_EN		BIT(3)  #define MT8173_SPI_MAX_PAD_SEL 3  #define MTK_SPI_PAUSE_INT_STATUS 0x2 @@ -78,6 +89,7 @@  #define MTK_SPI_MAX_FIFO_SIZE 32U  #define MTK_SPI_PACKET_SIZE 1024 +#define MTK_SPI_IPM_PACKET_SIZE SZ_64K  #define MTK_SPI_32BITS_MASK  (0xffffffff)  #define DMA_ADDR_EXT_BITS (36) @@ -93,6 +105,9 @@ struct mtk_spi_compatible {  	bool dma_ext;  	/* some IC no need unprepare SPI clk */  	bool no_need_unprepare; +	/* IPM design adjust and extend register to support more features */ +	bool ipm_design; +  };  struct mtk_spi { @@ -116,6 +131,12 @@ static const struct mtk_spi_compatible mt2712_compat = {  	.must_tx = true,  }; +static const struct mtk_spi_compatible mtk_ipm_compat = { +	.enhance_timing = true, +	.dma_ext = true, +	.ipm_design = true, +}; +  static const struct mtk_spi_compatible mt6765_compat = {  	.need_pad_sel = true,  	.must_tx = true, @@ -157,6 +178,9 @@ static const struct mtk_chip_config mtk_default_chip_info = {  };  static const struct of_device_id mtk_spi_of_match[] = { +	{ .compatible = "mediatek,spi-ipm", +		.data = (void *)&mtk_ipm_compat, +	},  	{ .compatible = "mediatek,mt2701-spi",  		.data = (void *)&mtk_common_compat,  	}, @@ -275,12 +299,11 @@ static int mtk_spi_set_hw_cs_timing(struct spi_device *spi)  	return 0;  } -static int mtk_spi_prepare_message(struct spi_master *master, -				   struct spi_message *msg) +static int mtk_spi_hw_init(struct spi_master *master, +			   struct spi_device *spi)  {  	u16 cpha, cpol;  	u32 reg_val; -	struct spi_device *spi = msg->spi;  	struct mtk_chip_config *chip_config = spi->controller_data;  	struct mtk_spi *mdata = spi_master_get_devdata(master); @@ -288,6 +311,15 @@ static int mtk_spi_prepare_message(struct spi_master *master,  	cpol = spi->mode & SPI_CPOL ? 1 : 0;  	reg_val = readl(mdata->base + SPI_CMD_REG); +	if (mdata->dev_comp->ipm_design) { +		/* SPI transfer without idle time until packet length done */ +		reg_val |= SPI_CMD_IPM_NONIDLE_MODE; +		if (spi->mode & SPI_LOOP) +			reg_val |= SPI_CMD_IPM_SPIM_LOOP; +		else +			reg_val &= ~SPI_CMD_IPM_SPIM_LOOP; +	} +  	if (cpha)  		reg_val |= SPI_CMD_CPHA;  	else @@ -345,17 +377,39 @@ static int mtk_spi_prepare_message(struct spi_master *master,  		       mdata->base + SPI_PAD_SEL_REG);  	/* tick delay */ -	reg_val = readl(mdata->base + SPI_CFG1_REG); -	reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; -	reg_val |= ((chip_config->tick_delay & 0x7) -		<< SPI_CFG1_GET_TICK_DLY_OFFSET); -	writel(reg_val, mdata->base + SPI_CFG1_REG); +	if (mdata->dev_comp->enhance_timing) { +		if (mdata->dev_comp->ipm_design) { +			reg_val = readl(mdata->base + SPI_CMD_REG); +			reg_val &= ~SPI_CMD_IPM_GET_TICKDLY_MASK; +			reg_val |= ((chip_config->tick_delay & 0x7) +				    << SPI_CMD_IPM_GET_TICKDLY_OFFSET); +			writel(reg_val, mdata->base + SPI_CMD_REG); +		} else { +			reg_val = readl(mdata->base + SPI_CFG1_REG); +			reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK; +			reg_val |= ((chip_config->tick_delay & 0x7) +				    << SPI_CFG1_GET_TICK_DLY_OFFSET); +			writel(reg_val, mdata->base + SPI_CFG1_REG); +		} +	} else { +		reg_val = readl(mdata->base + SPI_CFG1_REG); +		reg_val &= ~SPI_CFG1_GET_TICK_DLY_MASK_V1; +		reg_val |= ((chip_config->tick_delay & 0x3) +			    << SPI_CFG1_GET_TICK_DLY_OFFSET_V1); +		writel(reg_val, mdata->base + SPI_CFG1_REG); +	}  	/* set hw cs timing */  	mtk_spi_set_hw_cs_timing(spi);  	return 0;  } +static int mtk_spi_prepare_message(struct spi_master *master, +				   struct spi_message *msg) +{ +	return mtk_spi_hw_init(master, msg->spi); +} +  static void mtk_spi_set_cs(struct spi_device *spi, bool enable)  {  	u32 reg_val; @@ -377,13 +431,13 @@ static void mtk_spi_set_cs(struct spi_device *spi, bool enable)  }  static void mtk_spi_prepare_transfer(struct spi_master *master, -				     struct spi_transfer *xfer) +				     u32 speed_hz)  {  	u32 div, sck_time, reg_val;  	struct mtk_spi *mdata = spi_master_get_devdata(master); -	if (xfer->speed_hz < mdata->spi_clk_hz / 2) -		div = DIV_ROUND_UP(mdata->spi_clk_hz, xfer->speed_hz); +	if (speed_hz < mdata->spi_clk_hz / 2) +		div = DIV_ROUND_UP(mdata->spi_clk_hz, speed_hz);  	else  		div = 1; @@ -414,12 +468,24 @@ static void mtk_spi_setup_packet(struct spi_master *master)  	u32 packet_size, packet_loop, reg_val;  	struct mtk_spi *mdata = spi_master_get_devdata(master); -	packet_size = min_t(u32, mdata->xfer_len, MTK_SPI_PACKET_SIZE); +	if (mdata->dev_comp->ipm_design) +		packet_size = min_t(u32, +				    mdata->xfer_len, +				    MTK_SPI_IPM_PACKET_SIZE); +	else +		packet_size = min_t(u32, +				    mdata->xfer_len, +				    MTK_SPI_PACKET_SIZE); +  	packet_loop = mdata->xfer_len / packet_size;  	reg_val = readl(mdata->base + SPI_CFG1_REG); -	reg_val &= ~(SPI_CFG1_PACKET_LENGTH_MASK | SPI_CFG1_PACKET_LOOP_MASK); +	if (mdata->dev_comp->ipm_design) +		reg_val &= ~SPI_CFG1_IPM_PACKET_LENGTH_MASK; +	else +		reg_val &= ~SPI_CFG1_PACKET_LENGTH_MASK;  	reg_val |= (packet_size - 1) << SPI_CFG1_PACKET_LENGTH_OFFSET; +	reg_val &= ~SPI_CFG1_PACKET_LOOP_MASK;  	reg_val |= (packet_loop - 1) << SPI_CFG1_PACKET_LOOP_OFFSET;  	writel(reg_val, mdata->base + SPI_CFG1_REG);  } @@ -514,7 +580,7 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,  	mdata->cur_transfer = xfer;  	mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, xfer->len);  	mdata->num_xfered = 0; -	mtk_spi_prepare_transfer(master, xfer); +	mtk_spi_prepare_transfer(master, xfer->speed_hz);  	mtk_spi_setup_packet(master);  	if (xfer->tx_buf) { @@ -547,7 +613,7 @@ static int mtk_spi_dma_transfer(struct spi_master *master,  	mdata->cur_transfer = xfer;  	mdata->num_xfered = 0; -	mtk_spi_prepare_transfer(master, xfer); +	mtk_spi_prepare_transfer(master, xfer->speed_hz);  	cmd = readl(mdata->base + SPI_CMD_REG);  	if (xfer->tx_buf) @@ -582,6 +648,19 @@ static int mtk_spi_transfer_one(struct spi_master *master,  				struct spi_device *spi,  				struct spi_transfer *xfer)  { +	struct mtk_spi *mdata = spi_master_get_devdata(spi->master); +	u32 reg_val = 0; + +	/* prepare xfer direction and duplex mode */ +	if (mdata->dev_comp->ipm_design) { +		if (!xfer->tx_buf || !xfer->rx_buf) { +			reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_EN; +			if (xfer->rx_buf) +				reg_val |= SPI_CFG3_IPM_HALF_DUPLEX_DIR; +		} +		writel(reg_val, mdata->base + SPI_CFG3_IPM_REG); +	} +  	if (master->can_dma(master, spi, xfer))  		return mtk_spi_dma_transfer(master, spi, xfer);  	else @@ -605,8 +684,9 @@ static int mtk_spi_setup(struct spi_device *spi)  	if (!spi->controller_data)  		spi->controller_data = (void *)&mtk_default_chip_info; -	if (mdata->dev_comp->need_pad_sel && gpio_is_valid(spi->cs_gpio)) -		gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); +	if (mdata->dev_comp->need_pad_sel && spi->cs_gpiod) +		/* CS de-asserted, gpiolib will handle inversion */ +		gpiod_direction_output(spi->cs_gpiod, 0);  	return 0;  } @@ -730,6 +810,7 @@ static int mtk_spi_probe(struct platform_device *pdev)  	master->can_dma = mtk_spi_can_dma;  	master->setup = mtk_spi_setup;  	master->set_cs_timing = mtk_spi_set_hw_cs_timing; +	master->use_gpio_descriptors = true;  	of_id = of_match_node(mtk_spi_of_match, pdev->dev.of_node);  	if (!of_id) { @@ -746,6 +827,8 @@ static int mtk_spi_probe(struct platform_device *pdev)  	if (mdata->dev_comp->must_tx)  		master->flags = SPI_MASTER_MUST_TX; +	if (mdata->dev_comp->ipm_design) +		master->mode_bits |= SPI_LOOP;  	if (mdata->dev_comp->need_pad_sel) {  		mdata->pad_num = of_property_count_u32_elems( @@ -853,25 +936,12 @@ static int mtk_spi_probe(struct platform_device *pdev)  			goto err_disable_runtime_pm;  		} -		if (!master->cs_gpios && master->num_chipselect > 1) { +		if (!master->cs_gpiods && master->num_chipselect > 1) {  			dev_err(&pdev->dev,  				"cs_gpios not specified and num_chipselect > 1\n");  			ret = -EINVAL;  			goto err_disable_runtime_pm;  		} - -		if (master->cs_gpios) { -			for (i = 0; i < master->num_chipselect; i++) { -				ret = devm_gpio_request(&pdev->dev, -							master->cs_gpios[i], -							dev_name(&pdev->dev)); -				if (ret) { -					dev_err(&pdev->dev, -						"can't get CS GPIO %i\n", i); -					goto err_disable_runtime_pm; -				} -			} -		}  	}  	if (mdata->dev_comp->dma_ext) diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index 5c93730615f8..94fb09696677 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -95,6 +95,17 @@  #define CLK_TO_US(sp, clkcnt)		DIV_ROUND_UP(clkcnt, sp->spi_freq / 1000000) +struct mtk_nor_caps { +	u8 dma_bits; + +	/* extra_dummy_bit is adding for the IP of new SoCs. +	 * Some new SoCs modify the timing of fetching registers' values +	 * and IDs of nor flash, they need a extra_dummy_bit which can add +	 * more clock cycles for fetching data. +	 */ +	u8 extra_dummy_bit; +}; +  struct mtk_nor {  	struct spi_controller *ctlr;  	struct device *dev; @@ -104,11 +115,13 @@ struct mtk_nor {  	struct clk *spi_clk;  	struct clk *ctlr_clk;  	struct clk *axi_clk; +	struct clk *axi_s_clk;  	unsigned int spi_freq;  	bool wbuf_en;  	bool has_irq;  	bool high_dma;  	struct completion op_done; +	const struct mtk_nor_caps *caps;  };  static inline void mtk_nor_rmw(struct mtk_nor *sp, u32 reg, u32 set, u32 clr) @@ -554,7 +567,12 @@ static int mtk_nor_spi_mem_prg(struct mtk_nor *sp, const struct spi_mem_op *op)  	}  	// trigger op -	writel(prg_len * BITS_PER_BYTE, sp->base + MTK_NOR_REG_PRG_CNT); +	if (rx_len) +		writel(prg_len * BITS_PER_BYTE + sp->caps->extra_dummy_bit, +		       sp->base + MTK_NOR_REG_PRG_CNT); +	else +		writel(prg_len * BITS_PER_BYTE, sp->base + MTK_NOR_REG_PRG_CNT); +  	ret = mtk_nor_cmd_exec(sp, MTK_NOR_CMD_PROGRAM,  			       prg_len * BITS_PER_BYTE);  	if (ret) @@ -674,6 +692,7 @@ static void mtk_nor_disable_clk(struct mtk_nor *sp)  	clk_disable_unprepare(sp->spi_clk);  	clk_disable_unprepare(sp->ctlr_clk);  	clk_disable_unprepare(sp->axi_clk); +	clk_disable_unprepare(sp->axi_s_clk);  }  static int mtk_nor_enable_clk(struct mtk_nor *sp) @@ -697,6 +716,14 @@ static int mtk_nor_enable_clk(struct mtk_nor *sp)  		return ret;  	} +	ret = clk_prepare_enable(sp->axi_s_clk); +	if (ret) { +		clk_disable_unprepare(sp->spi_clk); +		clk_disable_unprepare(sp->ctlr_clk); +		clk_disable_unprepare(sp->axi_clk); +		return ret; +	} +  	return 0;  } @@ -743,9 +770,25 @@ static const struct spi_controller_mem_ops mtk_nor_mem_ops = {  	.exec_op = mtk_nor_exec_op  }; +static const struct mtk_nor_caps mtk_nor_caps_mt8173 = { +	.dma_bits = 32, +	.extra_dummy_bit = 0, +}; + +static const struct mtk_nor_caps mtk_nor_caps_mt8186 = { +	.dma_bits = 32, +	.extra_dummy_bit = 1, +}; + +static const struct mtk_nor_caps mtk_nor_caps_mt8192 = { +	.dma_bits = 36, +	.extra_dummy_bit = 0, +}; +  static const struct of_device_id mtk_nor_match[] = { -	{ .compatible = "mediatek,mt8192-nor", .data = (void *)36 }, -	{ .compatible = "mediatek,mt8173-nor", .data = (void *)32 }, +	{ .compatible = "mediatek,mt8173-nor", .data = &mtk_nor_caps_mt8173 }, +	{ .compatible = "mediatek,mt8186-nor", .data = &mtk_nor_caps_mt8186 }, +	{ .compatible = "mediatek,mt8192-nor", .data = &mtk_nor_caps_mt8192 },  	{ /* sentinel */ }  };  MODULE_DEVICE_TABLE(of, mtk_nor_match); @@ -754,10 +797,10 @@ static int mtk_nor_probe(struct platform_device *pdev)  {  	struct spi_controller *ctlr;  	struct mtk_nor *sp; +	struct mtk_nor_caps *caps;  	void __iomem *base; -	struct clk *spi_clk, *ctlr_clk, *axi_clk; +	struct clk *spi_clk, *ctlr_clk, *axi_clk, *axi_s_clk;  	int ret, irq; -	unsigned long dma_bits;  	base = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(base)) @@ -775,10 +818,16 @@ static int mtk_nor_probe(struct platform_device *pdev)  	if (IS_ERR(axi_clk))  		return PTR_ERR(axi_clk); -	dma_bits = (unsigned long)of_device_get_match_data(&pdev->dev); -	if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(dma_bits))) { -		dev_err(&pdev->dev, "failed to set dma mask(%lu)\n", dma_bits); -		return -EINVAL; +	axi_s_clk = devm_clk_get_optional(&pdev->dev, "axi_s"); +	if (IS_ERR(axi_s_clk)) +		return PTR_ERR(axi_s_clk); + +	caps = (struct mtk_nor_caps *)of_device_get_match_data(&pdev->dev); + +	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(caps->dma_bits)); +	if (ret) { +		dev_err(&pdev->dev, "failed to set dma mask(%u)\n", caps->dma_bits); +		return ret;  	}  	ctlr = devm_spi_alloc_master(&pdev->dev, sizeof(*sp)); @@ -808,7 +857,9 @@ static int mtk_nor_probe(struct platform_device *pdev)  	sp->spi_clk = spi_clk;  	sp->ctlr_clk = ctlr_clk;  	sp->axi_clk = axi_clk; -	sp->high_dma = (dma_bits > 32); +	sp->axi_s_clk = axi_s_clk; +	sp->caps = caps; +	sp->high_dma = caps->dma_bits > 32;  	sp->buffer = dmam_alloc_coherent(&pdev->dev,  				MTK_NOR_BOUNCE_BUF_SIZE + MTK_NOR_DMA_ALIGN,  				&sp->buffer_dma, GFP_KERNEL); diff --git a/drivers/spi/spi-npcm-fiu.c b/drivers/spi/spi-npcm-fiu.c index b62471ab6d7f..ba67dbed9fb8 100644 --- a/drivers/spi/spi-npcm-fiu.c +++ b/drivers/spi/spi-npcm-fiu.c @@ -201,7 +201,7 @@ struct fiu_data {  	int fiu_max;  }; -static const struct npcm_fiu_info npxm7xx_fiu_info[] = { +static const struct npcm_fiu_info npcm7xx_fiu_info[] = {  	{.name = "FIU0", .fiu_id = FIU0,  		.max_map_size = MAP_SIZE_128MB, .max_cs = 2},  	{.name = "FIU3", .fiu_id = FIU3, @@ -209,8 +209,8 @@ static const struct npcm_fiu_info npxm7xx_fiu_info[] = {  	{.name = "FIUX", .fiu_id = FIUX,  		.max_map_size = MAP_SIZE_16MB, .max_cs = 2} }; -static const struct fiu_data npxm7xx_fiu_data = { -	.npcm_fiu_data_info = npxm7xx_fiu_info, +static const struct fiu_data npcm7xx_fiu_data = { +	.npcm_fiu_data_info = npcm7xx_fiu_info,  	.fiu_max = 3,  }; @@ -664,14 +664,13 @@ static const struct spi_controller_mem_ops npcm_fiu_mem_ops = {  };  static const struct of_device_id npcm_fiu_dt_ids[] = { -	{ .compatible = "nuvoton,npcm750-fiu", .data = &npxm7xx_fiu_data  }, +	{ .compatible = "nuvoton,npcm750-fiu", .data = &npcm7xx_fiu_data  },  	{ /* sentinel */ }  };  static int npcm_fiu_probe(struct platform_device *pdev)  {  	const struct fiu_data *fiu_data_match; -	const struct of_device_id *match;  	struct device *dev = &pdev->dev;  	struct spi_controller *ctrl;  	struct npcm_fiu_spi *fiu; @@ -685,13 +684,12 @@ static int npcm_fiu_probe(struct platform_device *pdev)  	fiu = spi_controller_get_devdata(ctrl); -	match = of_match_device(npcm_fiu_dt_ids, dev); -	if (!match || !match->data) { +	fiu_data_match = of_device_get_match_data(dev); +	if (!fiu_data_match) {  		dev_err(dev, "No compatible OF match\n");  		return -ENODEV;  	} -	fiu_data_match = match->data;  	id = of_alias_get_id(dev->of_node, "fiu");  	if (id < 0 || id >= fiu_data_match->fiu_max) {  		dev_err(dev, "Invalid platform device id: %d\n", id); diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index f86433b29260..7e5c09a7d489 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -591,18 +591,16 @@ static int pic32_spi_setup(struct spi_device *spi)  	 * unreliable/erroneous SPI transactions.  	 * To avoid that we will always handle /CS by toggling GPIO.  	 */ -	if (!gpio_is_valid(spi->cs_gpio)) +	if (!spi->cs_gpiod)  		return -EINVAL; -	gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); -  	return 0;  }  static void pic32_spi_cleanup(struct spi_device *spi)  { -	/* de-activate cs-gpio */ -	gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); +	/* de-activate cs-gpio, gpiolib will handle inversion */ +	gpiod_direction_output(spi->cs_gpiod, 0);  }  static int pic32_spi_dma_prep(struct pic32_spi *pic32s, struct device *dev) @@ -784,6 +782,7 @@ static int pic32_spi_probe(struct platform_device *pdev)  	master->unprepare_message	= pic32_spi_unprepare_message;  	master->prepare_transfer_hardware	= pic32_spi_prepare_hardware;  	master->unprepare_transfer_hardware	= pic32_spi_unprepare_hardware; +	master->use_gpio_descriptors = true;  	/* optional DMA support */  	ret = pic32_spi_dma_prep(pic32s, &pdev->dev); diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 2e134eb4bd2c..861b21c63504 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -15,32 +15,20 @@  #include <linux/dmaengine.h>  #include <linux/platform_data/dma-dw.h> -enum { -	PORT_QUARK_X1000, -	PORT_BYT, -	PORT_MRFLD, -	PORT_BSW0, -	PORT_BSW1, -	PORT_BSW2, -	PORT_CE4100, -	PORT_LPT0, -	PORT_LPT1, -}; +#define PCI_DEVICE_ID_INTEL_QUARK_X1000		0x0935 +#define PCI_DEVICE_ID_INTEL_BYT			0x0f0e +#define PCI_DEVICE_ID_INTEL_MRFLD		0x1194 +#define PCI_DEVICE_ID_INTEL_BSW0		0x228e +#define PCI_DEVICE_ID_INTEL_BSW1		0x2290 +#define PCI_DEVICE_ID_INTEL_BSW2		0x22ac +#define PCI_DEVICE_ID_INTEL_CE4100		0x2e6a +#define PCI_DEVICE_ID_INTEL_LPT0_0		0x9c65 +#define PCI_DEVICE_ID_INTEL_LPT0_1		0x9c66 +#define PCI_DEVICE_ID_INTEL_LPT1_0		0x9ce5 +#define PCI_DEVICE_ID_INTEL_LPT1_1		0x9ce6  struct pxa_spi_info { -	enum pxa_ssp_type type; -	int port_id; -	int num_chipselect; -	unsigned long max_clk_rate; - -	/* DMA channel request parameters */ -	bool (*dma_filter)(struct dma_chan *chan, void *param); -	void *tx_param; -	void *rx_param; - -	int dma_burst_size; - -	int (*setup)(struct pci_dev *pdev, struct pxa_spi_info *c); +	int (*setup)(struct pci_dev *pdev, struct pxa2xx_spi_controller *c);  };  static struct dw_dma_slave byt_tx_param = { .dst_id = 0 }; @@ -65,6 +53,24 @@ static struct dw_dma_slave lpt1_rx_param = { .src_id = 1 };  static struct dw_dma_slave lpt0_tx_param = { .dst_id = 2 };  static struct dw_dma_slave lpt0_rx_param = { .src_id = 3 }; +static void pxa2xx_spi_pci_clk_unregister(void *clk) +{ +	clk_unregister(clk); +} + +static int pxa2xx_spi_pci_clk_register(struct pci_dev *dev, struct ssp_device *ssp, +				       unsigned long rate) +{ +	char buf[40]; + +	snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); +	ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0, rate); +	if (IS_ERR(ssp->clk)) +		return PTR_ERR(ssp->clk); + +	return devm_add_action_or_reset(&dev->dev, pxa2xx_spi_pci_clk_unregister, ssp->clk); +} +  static bool lpss_dma_filter(struct dma_chan *chan, void *param)  {  	struct dw_dma_slave *dws = param; @@ -76,55 +82,131 @@ static bool lpss_dma_filter(struct dma_chan *chan, void *param)  	return true;  } -static int lpss_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) +static void lpss_dma_put_device(void *dma_dev)  { +	pci_dev_put(dma_dev); +} + +static int lpss_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) +{ +	struct ssp_device *ssp = &c->ssp; +	struct dw_dma_slave *tx, *rx;  	struct pci_dev *dma_dev; +	int ret; -	c->num_chipselect = 1; -	c->max_clk_rate = 50000000; +	switch (dev->device) { +	case PCI_DEVICE_ID_INTEL_BYT: +		ssp->type = LPSS_BYT_SSP; +		ssp->port_id = 0; +		c->tx_param = &byt_tx_param; +		c->rx_param = &byt_rx_param; +		break; +	case PCI_DEVICE_ID_INTEL_BSW0: +		ssp->type = LPSS_BSW_SSP; +		ssp->port_id = 0; +		c->tx_param = &bsw0_tx_param; +		c->rx_param = &bsw0_rx_param; +		break; +	case PCI_DEVICE_ID_INTEL_BSW1: +		ssp->type = LPSS_BSW_SSP; +		ssp->port_id = 1; +		c->tx_param = &bsw1_tx_param; +		c->rx_param = &bsw1_rx_param; +		break; +	case PCI_DEVICE_ID_INTEL_BSW2: +		ssp->type = LPSS_BSW_SSP; +		ssp->port_id = 2; +		c->tx_param = &bsw2_tx_param; +		c->rx_param = &bsw2_rx_param; +		break; +	case PCI_DEVICE_ID_INTEL_LPT0_0: +	case PCI_DEVICE_ID_INTEL_LPT1_0: +		ssp->type = LPSS_LPT_SSP; +		ssp->port_id = 0; +		c->tx_param = &lpt0_tx_param; +		c->rx_param = &lpt0_rx_param; +		break; +	case PCI_DEVICE_ID_INTEL_LPT0_1: +	case PCI_DEVICE_ID_INTEL_LPT1_1: +		ssp->type = LPSS_LPT_SSP; +		ssp->port_id = 1; +		c->tx_param = &lpt1_tx_param; +		c->rx_param = &lpt1_rx_param; +		break; +	default: +		return -ENODEV; +	} -	dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); +	c->num_chipselect = 1; -	if (c->tx_param) { -		struct dw_dma_slave *slave = c->tx_param; +	ret = pxa2xx_spi_pci_clk_register(dev, ssp, 50000000); +	if (ret) +		return ret; -		slave->dma_dev = &dma_dev->dev; -		slave->m_master = 0; -		slave->p_master = 1; -	} +	dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); +	ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev); +	if (ret) +		return ret; -	if (c->rx_param) { -		struct dw_dma_slave *slave = c->rx_param; +	tx = c->tx_param; +	tx->dma_dev = &dma_dev->dev; +	tx->m_master = 0; +	tx->p_master = 1; -		slave->dma_dev = &dma_dev->dev; -		slave->m_master = 0; -		slave->p_master = 1; -	} +	rx = c->rx_param; +	rx->dma_dev = &dma_dev->dev; +	rx->m_master = 0; +	rx->p_master = 1;  	c->dma_filter = lpss_dma_filter; +	c->dma_burst_size = 1; +	c->enable_dma = 1;  	return 0;  } -static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c) +static const struct pxa_spi_info lpss_info_config = { +	.setup = lpss_spi_setup, +}; + +static int ce4100_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c)  { -	struct pci_dev *dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0)); +	struct ssp_device *ssp = &c->ssp; + +	ssp->type = PXA25x_SSP; +	ssp->port_id = dev->devfn; +	c->num_chipselect = dev->devfn; + +	return pxa2xx_spi_pci_clk_register(dev, ssp, 3686400); +} + +static const struct pxa_spi_info ce4100_info_config = { +	.setup = ce4100_spi_setup, +}; + +static int mrfld_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) +{ +	struct ssp_device *ssp = &c->ssp;  	struct dw_dma_slave *tx, *rx; +	struct pci_dev *dma_dev; +	int ret; + +	ssp->type = MRFLD_SSP;  	switch (PCI_FUNC(dev->devfn)) {  	case 0: -		c->port_id = 3; +		ssp->port_id = 3;  		c->num_chipselect = 1;  		c->tx_param = &mrfld3_tx_param;  		c->rx_param = &mrfld3_rx_param;  		break;  	case 1: -		c->port_id = 5; +		ssp->port_id = 5;  		c->num_chipselect = 4;  		c->tx_param = &mrfld5_tx_param;  		c->rx_param = &mrfld5_rx_param;  		break;  	case 2: -		c->port_id = 6; +		ssp->port_id = 6;  		c->num_chipselect = 1;  		c->tx_param = &mrfld6_tx_param;  		c->rx_param = &mrfld6_rx_param; @@ -133,6 +215,15 @@ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)  		return -ENODEV;  	} +	ret = pxa2xx_spi_pci_clk_register(dev, ssp, 25000000); +	if (ret) +		return ret; + +	dma_dev = pci_get_slot(dev->bus, PCI_DEVFN(21, 0)); +	ret = devm_add_action_or_reset(&dev->dev, lpss_dma_put_device, dma_dev); +	if (ret) +		return ret; +  	tx = c->tx_param;  	tx->dma_dev = &dma_dev->dev; @@ -141,81 +232,38 @@ static int mrfld_spi_setup(struct pci_dev *dev, struct pxa_spi_info *c)  	c->dma_filter = lpss_dma_filter;  	c->dma_burst_size = 8; +	c->enable_dma = 1;  	return 0;  } -static struct pxa_spi_info spi_info_configs[] = { -	[PORT_CE4100] = { -		.type = PXA25x_SSP, -		.port_id =  -1, -		.num_chipselect = -1, -		.max_clk_rate = 3686400, -	}, -	[PORT_BYT] = { -		.type = LPSS_BYT_SSP, -		.port_id = 0, -		.setup = lpss_spi_setup, -		.tx_param = &byt_tx_param, -		.rx_param = &byt_rx_param, -	}, -	[PORT_BSW0] = { -		.type = LPSS_BSW_SSP, -		.port_id = 0, -		.setup = lpss_spi_setup, -		.tx_param = &bsw0_tx_param, -		.rx_param = &bsw0_rx_param, -	}, -	[PORT_BSW1] = { -		.type = LPSS_BSW_SSP, -		.port_id = 1, -		.setup = lpss_spi_setup, -		.tx_param = &bsw1_tx_param, -		.rx_param = &bsw1_rx_param, -	}, -	[PORT_BSW2] = { -		.type = LPSS_BSW_SSP, -		.port_id = 2, -		.setup = lpss_spi_setup, -		.tx_param = &bsw2_tx_param, -		.rx_param = &bsw2_rx_param, -	}, -	[PORT_MRFLD] = { -		.type = MRFLD_SSP, -		.max_clk_rate = 25000000, -		.setup = mrfld_spi_setup, -	}, -	[PORT_QUARK_X1000] = { -		.type = QUARK_X1000_SSP, -		.port_id = -1, -		.num_chipselect = 1, -		.max_clk_rate = 50000000, -	}, -	[PORT_LPT0] = { -		.type = LPSS_LPT_SSP, -		.port_id = 0, -		.setup = lpss_spi_setup, -		.tx_param = &lpt0_tx_param, -		.rx_param = &lpt0_rx_param, -	}, -	[PORT_LPT1] = { -		.type = LPSS_LPT_SSP, -		.port_id = 1, -		.setup = lpss_spi_setup, -		.tx_param = &lpt1_tx_param, -		.rx_param = &lpt1_rx_param, -	}, +static const struct pxa_spi_info mrfld_info_config = { +	.setup = mrfld_spi_setup, +}; + +static int qrk_spi_setup(struct pci_dev *dev, struct pxa2xx_spi_controller *c) +{ +	struct ssp_device *ssp = &c->ssp; + +	ssp->type = QUARK_X1000_SSP; +	ssp->port_id = dev->devfn; +	c->num_chipselect = 1; + +	return pxa2xx_spi_pci_clk_register(dev, ssp, 50000000); +} + +static const struct pxa_spi_info qrk_info_config = { +	.setup = qrk_spi_setup,  };  static int pxa2xx_spi_pci_probe(struct pci_dev *dev,  		const struct pci_device_id *ent)  { +	const struct pxa_spi_info *info;  	struct platform_device_info pi;  	int ret;  	struct platform_device *pdev;  	struct pxa2xx_spi_controller spi_pdata;  	struct ssp_device *ssp; -	struct pxa_spi_info *c; -	char buf[40];  	ret = pcim_enable_device(dev);  	if (ret) @@ -225,27 +273,17 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,  	if (ret)  		return ret; -	c = &spi_info_configs[ent->driver_data]; -	if (c->setup) { -		ret = c->setup(dev, c); -		if (ret) -			return ret; -	} -  	memset(&spi_pdata, 0, sizeof(spi_pdata)); -	spi_pdata.num_chipselect = (c->num_chipselect > 0) ? c->num_chipselect : dev->devfn; -	spi_pdata.dma_filter = c->dma_filter; -	spi_pdata.tx_param = c->tx_param; -	spi_pdata.rx_param = c->rx_param; -	spi_pdata.enable_dma = c->rx_param && c->tx_param; -	spi_pdata.dma_burst_size = c->dma_burst_size ? c->dma_burst_size : 1;  	ssp = &spi_pdata.ssp;  	ssp->dev = &dev->dev;  	ssp->phys_base = pci_resource_start(dev, 0);  	ssp->mmio_base = pcim_iomap_table(dev)[0]; -	ssp->port_id = (c->port_id >= 0) ? c->port_id : dev->devfn; -	ssp->type = c->type; + +	info = (struct pxa_spi_info *)ent->driver_data; +	ret = info->setup(dev, &spi_pdata); +	if (ret) +		return ret;  	pci_set_master(dev); @@ -254,14 +292,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,  		return ret;  	ssp->irq = pci_irq_vector(dev, 0); -	snprintf(buf, sizeof(buf), "pxa2xx-spi.%d", ssp->port_id); -	ssp->clk = clk_register_fixed_rate(&dev->dev, buf, NULL, 0, -					   c->max_clk_rate); -	if (IS_ERR(ssp->clk)) -		return PTR_ERR(ssp->clk); -  	memset(&pi, 0, sizeof(pi)); -	pi.fwnode = dev->dev.fwnode; +	pi.fwnode = dev_fwnode(&dev->dev);  	pi.parent = &dev->dev;  	pi.name = "pxa2xx-spi";  	pi.id = ssp->port_id; @@ -269,10 +301,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,  	pi.size_data = sizeof(spi_pdata);  	pdev = platform_device_register_full(&pi); -	if (IS_ERR(pdev)) { -		clk_unregister(ssp->clk); +	if (IS_ERR(pdev))  		return PTR_ERR(pdev); -	}  	pci_set_drvdata(dev, pdev); @@ -282,26 +312,22 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,  static void pxa2xx_spi_pci_remove(struct pci_dev *dev)  {  	struct platform_device *pdev = pci_get_drvdata(dev); -	struct pxa2xx_spi_controller *spi_pdata; - -	spi_pdata = dev_get_platdata(&pdev->dev);  	platform_device_unregister(pdev); -	clk_unregister(spi_pdata->ssp.clk);  }  static const struct pci_device_id pxa2xx_spi_pci_devices[] = { -	{ PCI_VDEVICE(INTEL, 0x0935), PORT_QUARK_X1000 }, -	{ PCI_VDEVICE(INTEL, 0x0f0e), PORT_BYT }, -	{ PCI_VDEVICE(INTEL, 0x1194), PORT_MRFLD }, -	{ PCI_VDEVICE(INTEL, 0x228e), PORT_BSW0 }, -	{ PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, -	{ PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 }, -	{ PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, -	{ PCI_VDEVICE(INTEL, 0x9c65), PORT_LPT0 }, -	{ PCI_VDEVICE(INTEL, 0x9c66), PORT_LPT1 }, -	{ PCI_VDEVICE(INTEL, 0x9ce5), PORT_LPT0 }, -	{ PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT1 }, +	{ PCI_DEVICE_DATA(INTEL, QUARK_X1000, &qrk_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, BYT, &lpss_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, MRFLD, &mrfld_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, BSW0, &lpss_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, BSW1, &lpss_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, BSW2, &lpss_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, CE4100, &ce4100_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, LPT0_0, &lpss_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, LPT0_1, &lpss_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, LPT1_0, &lpss_info_config) }, +	{ PCI_DEVICE_DATA(INTEL, LPT1_1, &lpss_info_config) },  	{ }  };  MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index e88f86274eeb..edb42d08857d 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -13,7 +13,6 @@  #include <linux/err.h>  #include <linux/errno.h>  #include <linux/gpio/consumer.h> -#include <linux/gpio.h>  #include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/ioport.h> @@ -1163,57 +1162,6 @@ static int pxa2xx_spi_unprepare_transfer(struct spi_controller *controller)  	return 0;  } -static void cleanup_cs(struct spi_device *spi) -{ -	if (!gpio_is_valid(spi->cs_gpio)) -		return; - -	gpio_free(spi->cs_gpio); -	spi->cs_gpio = -ENOENT; -} - -static int setup_cs(struct spi_device *spi, struct chip_data *chip, -		    struct pxa2xx_spi_chip *chip_info) -{ -	struct driver_data *drv_data = spi_controller_get_devdata(spi->controller); - -	if (chip == NULL) -		return 0; - -	if (chip_info == NULL) -		return 0; - -	if (drv_data->ssp_type == CE4100_SSP) -		return 0; - -	/* -	 * NOTE: setup() can be called multiple times, possibly with -	 * different chip_info, release previously requested GPIO. -	 */ -	cleanup_cs(spi); - -	if (gpio_is_valid(chip_info->gpio_cs)) { -		int gpio = chip_info->gpio_cs; -		int err; - -		err = gpio_request(gpio, "SPI_CS"); -		if (err) { -			dev_err(&spi->dev, "failed to request chip select GPIO%d\n", gpio); -			return err; -		} - -		err = gpio_direction_output(gpio, !(spi->mode & SPI_CS_HIGH)); -		if (err) { -			gpio_free(gpio); -			return err; -		} - -		spi->cs_gpio = gpio; -	} - -	return 0; -} -  static int setup(struct spi_device *spi)  {  	struct pxa2xx_spi_chip *chip_info; @@ -1222,7 +1170,6 @@ static int setup(struct spi_device *spi)  	struct driver_data *drv_data =  		spi_controller_get_devdata(spi->controller);  	uint tx_thres, tx_hi_thres, rx_thres; -	int err;  	switch (drv_data->ssp_type) {  	case QUARK_X1000_SSP: @@ -1365,21 +1312,13 @@ static int setup(struct spi_device *spi)  	spi_set_ctldata(spi, chip); -	if (drv_data->ssp_type == CE4100_SSP) -		return 0; - -	err = setup_cs(spi, chip, chip_info); -	if (err) -		kfree(chip); - -	return err; +	return 0;  }  static void cleanup(struct spi_device *spi)  {  	struct chip_data *chip = spi_get_ctldata(spi); -	cleanup_cs(spi);  	kfree(chip);  } @@ -1455,6 +1394,11 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {  	{ PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },  	{ PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },  	{ PCI_VDEVICE(INTEL, 0x5ac6), LPSS_BXT_SSP }, +	/* RPL-S */ +	{ PCI_VDEVICE(INTEL, 0x7a2a), LPSS_CNL_SSP }, +	{ PCI_VDEVICE(INTEL, 0x7a2b), LPSS_CNL_SSP }, +	{ PCI_VDEVICE(INTEL, 0x7a79), LPSS_CNL_SSP }, +	{ PCI_VDEVICE(INTEL, 0x7a7b), LPSS_CNL_SSP },  	/* ADL-S */  	{ PCI_VDEVICE(INTEL, 0x7aaa), LPSS_CNL_SSP },  	{ PCI_VDEVICE(INTEL, 0x7aab), LPSS_CNL_SSP }, diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index d39dec6d1c91..00d6084306b4 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -593,7 +593,6 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)  {  	struct spi_qup *controller = dev_id;  	u32 opflags, qup_err, spi_err; -	unsigned long flags;  	int error = 0;  	qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS); @@ -625,10 +624,10 @@ static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id)  		error = -EIO;  	} -	spin_lock_irqsave(&controller->lock, flags); +	spin_lock(&controller->lock);  	if (!controller->error)  		controller->error = error; -	spin_unlock_irqrestore(&controller->lock, flags); +	spin_unlock(&controller->lock);  	if (spi_qup_is_dma_xfer(controller->mode)) {  		writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c index a46b38544027..bd87d3c92dd3 100644 --- a/drivers/spi/spi-rockchip-sfc.c +++ b/drivers/spi/spi-rockchip-sfc.c @@ -624,10 +624,8 @@ static int rockchip_sfc_probe(struct platform_device *pdev)  	/* Find the irq */  	ret = platform_get_irq(pdev, 0); -	if (ret < 0) { -		dev_err(dev, "Failed to get the irq\n"); +	if (ret < 0)  		goto err_irq; -	}  	ret = devm_request_irq(dev, ret, rockchip_sfc_irq_handler,  			       0, pdev->name, sfc); diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c index c6a1bb09be05..cdc16eecaf6b 100644 --- a/drivers/spi/spi-rockchip.c +++ b/drivers/spi/spi-rockchip.c @@ -133,7 +133,8 @@  #define INT_TF_OVERFLOW				(1 << 1)  #define INT_RF_UNDERFLOW			(1 << 2)  #define INT_RF_OVERFLOW				(1 << 3) -#define INT_RF_FULL					(1 << 4) +#define INT_RF_FULL				(1 << 4) +#define INT_CS_INACTIVE				(1 << 6)  /* Bit fields in ICR, 4bit */  #define ICR_MASK					0x0f @@ -194,6 +195,8 @@ struct rockchip_spi {  	bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];  	bool slave_abort; +	bool cs_inactive; /* spi slave tansmition stop when cs inactive */ +	struct spi_transfer *xfer; /* Store xfer temporarily */  };  static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable) @@ -275,8 +278,9 @@ static void rockchip_spi_handle_err(struct spi_controller *ctlr,  	 */  	spi_enable_chip(rs, false); -	/* make sure all interrupts are masked */ +	/* make sure all interrupts are masked and status cleared */  	writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); +	writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);  	if (atomic_read(&rs->state) & TXDMA)  		dmaengine_terminate_async(ctlr->dma_tx); @@ -343,6 +347,15 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)  	struct spi_controller *ctlr = dev_id;  	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); +	/* When int_cs_inactive comes, spi slave abort */ +	if (rs->cs_inactive && readl_relaxed(rs->regs + ROCKCHIP_SPI_IMR) & INT_CS_INACTIVE) { +		ctlr->slave_abort(ctlr); +		writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); +		writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR); + +		return IRQ_HANDLED; +	} +  	if (rs->tx_left)  		rockchip_spi_pio_writer(rs); @@ -350,6 +363,7 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)  	if (!rs->rx_left) {  		spi_enable_chip(rs, false);  		writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); +		writel_relaxed(0xffffffff, rs->regs + ROCKCHIP_SPI_ICR);  		spi_finalize_current_transfer(ctlr);  	} @@ -357,14 +371,18 @@ static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)  }  static int rockchip_spi_prepare_irq(struct rockchip_spi *rs, -		struct spi_transfer *xfer) +				    struct spi_controller *ctlr, +				    struct spi_transfer *xfer)  {  	rs->tx = xfer->tx_buf;  	rs->rx = xfer->rx_buf;  	rs->tx_left = rs->tx ? xfer->len / rs->n_bytes : 0;  	rs->rx_left = xfer->len / rs->n_bytes; -	writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR); +	if (rs->cs_inactive) +		writel_relaxed(INT_RF_FULL | INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR); +	else +		writel_relaxed(INT_RF_FULL, rs->regs + ROCKCHIP_SPI_IMR);  	spi_enable_chip(rs, true);  	if (rs->tx_left) @@ -383,6 +401,9 @@ static void rockchip_spi_dma_rxcb(void *data)  	if (state & TXDMA && !rs->slave_abort)  		return; +	if (rs->cs_inactive) +		writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR); +  	spi_enable_chip(rs, false);  	spi_finalize_current_transfer(ctlr);  } @@ -423,14 +444,16 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,  	atomic_set(&rs->state, 0); +	rs->tx = xfer->tx_buf; +	rs->rx = xfer->rx_buf; +  	rxdesc = NULL;  	if (xfer->rx_buf) {  		struct dma_slave_config rxconf = {  			.direction = DMA_DEV_TO_MEM,  			.src_addr = rs->dma_addr_rx,  			.src_addr_width = rs->n_bytes, -			.src_maxburst = rockchip_spi_calc_burst_size(xfer->len / -								     rs->n_bytes), +			.src_maxburst = rockchip_spi_calc_burst_size(xfer->len / rs->n_bytes),  		};  		dmaengine_slave_config(ctlr->dma_rx, &rxconf); @@ -474,10 +497,13 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,  	/* rx must be started before tx due to spi instinct */  	if (rxdesc) {  		atomic_or(RXDMA, &rs->state); -		dmaengine_submit(rxdesc); +		ctlr->dma_rx->cookie = dmaengine_submit(rxdesc);  		dma_async_issue_pending(ctlr->dma_rx);  	} +	if (rs->cs_inactive) +		writel_relaxed(INT_CS_INACTIVE, rs->regs + ROCKCHIP_SPI_IMR); +  	spi_enable_chip(rs, true);  	if (txdesc) { @@ -584,7 +610,42 @@ static size_t rockchip_spi_max_transfer_size(struct spi_device *spi)  static int rockchip_spi_slave_abort(struct spi_controller *ctlr)  {  	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr); +	u32 rx_fifo_left; +	struct dma_tx_state state; +	enum dma_status status; + +	/* Get current dma rx point */ +	if (atomic_read(&rs->state) & RXDMA) { +		dmaengine_pause(ctlr->dma_rx); +		status = dmaengine_tx_status(ctlr->dma_rx, ctlr->dma_rx->cookie, &state); +		if (status == DMA_ERROR) { +			rs->rx = rs->xfer->rx_buf; +			rs->xfer->len = 0; +			rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR); +			for (; rx_fifo_left; rx_fifo_left--) +				readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR); +			goto out; +		} else { +			rs->rx += rs->xfer->len - rs->n_bytes * state.residue; +		} +	} + +	/* Get the valid data left in rx fifo and set rs->xfer->len real rx size */ +	if (rs->rx) { +		rx_fifo_left = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR); +		for (; rx_fifo_left; rx_fifo_left--) { +			u32 rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR); + +			if (rs->n_bytes == 1) +				*(u8 *)rs->rx = (u8)rxw; +			else +				*(u16 *)rs->rx = (u16)rxw; +			rs->rx += rs->n_bytes; +		} +		rs->xfer->len = (unsigned int)(rs->rx - rs->xfer->rx_buf); +	} +out:  	if (atomic_read(&rs->state) & RXDMA)  		dmaengine_terminate_sync(ctlr->dma_rx);  	if (atomic_read(&rs->state) & TXDMA) @@ -626,7 +687,7 @@ static int rockchip_spi_transfer_one(  	}  	rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2; - +	rs->xfer = xfer;  	use_dma = ctlr->can_dma ? ctlr->can_dma(ctlr, spi, xfer) : false;  	ret = rockchip_spi_config(rs, spi, xfer, use_dma, ctlr->slave); @@ -636,7 +697,7 @@ static int rockchip_spi_transfer_one(  	if (use_dma)  		return rockchip_spi_prepare_dma(rs, ctlr, xfer); -	return rockchip_spi_prepare_irq(rs, xfer); +	return rockchip_spi_prepare_irq(rs, ctlr, xfer);  }  static bool rockchip_spi_can_dma(struct spi_controller *ctlr, @@ -653,6 +714,29 @@ static bool rockchip_spi_can_dma(struct spi_controller *ctlr,  	return xfer->len / bytes_per_word >= rs->fifo_len;  } +static int rockchip_spi_setup(struct spi_device *spi) +{ +	struct rockchip_spi *rs = spi_controller_get_devdata(spi->controller); +	u32 cr0; + +	pm_runtime_get_sync(rs->dev); + +	cr0 = readl_relaxed(rs->regs + ROCKCHIP_SPI_CTRLR0); + +	cr0 &= ~(0x3 << CR0_SCPH_OFFSET); +	cr0 |= ((spi->mode & 0x3) << CR0_SCPH_OFFSET); +	if (spi->mode & SPI_CS_HIGH && spi->chip_select <= 1) +		cr0 |= BIT(spi->chip_select) << CR0_SOI_OFFSET; +	else if (spi->chip_select <= 1) +		cr0 &= ~(BIT(spi->chip_select) << CR0_SOI_OFFSET); + +	writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0); + +	pm_runtime_put(rs->dev); + +	return 0; +} +  static int rockchip_spi_probe(struct platform_device *pdev)  {  	int ret; @@ -780,6 +864,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)  	ctlr->min_speed_hz = rs->freq / BAUDR_SCKDV_MAX;  	ctlr->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT); +	ctlr->setup = rockchip_spi_setup;  	ctlr->set_cs = rockchip_spi_set_cs;  	ctlr->transfer_one = rockchip_spi_transfer_one;  	ctlr->max_transfer_size = rockchip_spi_max_transfer_size; @@ -815,8 +900,13 @@ static int rockchip_spi_probe(struct platform_device *pdev)  	switch (readl_relaxed(rs->regs + ROCKCHIP_SPI_VERSION)) {  	case ROCKCHIP_SPI_VER2_TYPE2:  		ctlr->mode_bits |= SPI_CS_HIGH; +		if (ctlr->can_dma && slave_mode) +			rs->cs_inactive = true; +		else +			rs->cs_inactive = false;  		break;  	default: +		rs->cs_inactive = false;  		break;  	} @@ -875,14 +965,14 @@ static int rockchip_spi_suspend(struct device *dev)  {  	int ret;  	struct spi_controller *ctlr = dev_get_drvdata(dev); +	struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);  	ret = spi_controller_suspend(ctlr);  	if (ret < 0)  		return ret; -	ret = pm_runtime_force_suspend(dev); -	if (ret < 0) -		return ret; +	clk_disable_unprepare(rs->spiclk); +	clk_disable_unprepare(rs->apb_pclk);  	pinctrl_pm_select_sleep_state(dev); @@ -897,10 +987,14 @@ static int rockchip_spi_resume(struct device *dev)  	pinctrl_pm_select_default_state(dev); -	ret = pm_runtime_force_resume(dev); +	ret = clk_prepare_enable(rs->apb_pclk);  	if (ret < 0)  		return ret; +	ret = clk_prepare_enable(rs->spiclk); +	if (ret < 0) +		clk_disable_unprepare(rs->apb_pclk); +  	ret = spi_controller_resume(ctlr);  	if (ret < 0) {  		clk_disable_unprepare(rs->spiclk); @@ -942,7 +1036,7 @@ static int rockchip_spi_runtime_resume(struct device *dev)  #endif /* CONFIG_PM */  static const struct dev_pm_ops rockchip_spi_pm = { -	SET_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume) +	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_spi_suspend, rockchip_spi_resume)  	SET_RUNTIME_PM_OPS(rockchip_spi_runtime_suspend,  			   rockchip_spi_runtime_resume, NULL)  }; diff --git a/drivers/spi/spi-s3c24xx.c b/drivers/spi/spi-s3c24xx.c index d6f51695ca5b..660aa866af06 100644 --- a/drivers/spi/spi-s3c24xx.c +++ b/drivers/spi/spi-s3c24xx.c @@ -12,7 +12,6 @@  #include <linux/err.h>  #include <linux/clk.h>  #include <linux/platform_device.h> -#include <linux/gpio.h>  #include <linux/io.h>  #include <linux/slab.h> @@ -62,9 +61,6 @@ struct s3c24xx_spi {  	unsigned char		 fiq_inuse;  	unsigned char		 fiq_claimed; -	void			(*set_cs)(struct s3c2410_spi_info *spi, -					  int cs, int pol); -  	/* data buffers */  	const unsigned char	*tx;  	unsigned char		*rx; @@ -84,29 +80,21 @@ static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)  	return spi_master_get_devdata(sdev->master);  } -static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol) -{ -	gpio_set_value(spi->pin_cs, pol); -} -  static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)  {  	struct s3c24xx_spi_devstate *cs = spi->controller_state;  	struct s3c24xx_spi *hw = to_hw(spi); -	unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;  	/* change the chipselect state and the state of the spi engine clock */  	switch (value) {  	case BITBANG_CS_INACTIVE: -		hw->set_cs(hw->pdata, spi->chip_select, cspol^1);  		writeb(cs->spcon, hw->regs + S3C2410_SPCON);  		break;  	case BITBANG_CS_ACTIVE:  		writeb(cs->spcon | S3C2410_SPCON_ENSCK,  		       hw->regs + S3C2410_SPCON); -		hw->set_cs(hw->pdata, spi->chip_select, cspol);  		break;  	}  } @@ -452,14 +440,6 @@ static void s3c24xx_spi_initialsetup(struct s3c24xx_spi *hw)  	writeb(0xff, hw->regs + S3C2410_SPPRE);  	writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN);  	writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); - -	if (hw->pdata) { -		if (hw->set_cs == s3c24xx_spi_gpiocs) -			gpio_direction_output(hw->pdata->pin_cs, 1); - -		if (hw->pdata->gpio_setup) -			hw->pdata->gpio_setup(hw->pdata, 1); -	}  }  static int s3c24xx_spi_probe(struct platform_device *pdev) @@ -502,6 +482,9 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)  	master->num_chipselect = hw->pdata->num_cs;  	master->bus_num = pdata->bus_num;  	master->bits_per_word_mask = SPI_BPW_MASK(8); +	/* we need to call the local chipselect callback */ +	master->flags = SPI_MASTER_GPIO_SS; +	master->use_gpio_descriptors = true;  	/* setup the state for the bitbang driver */ @@ -541,27 +524,6 @@ static int s3c24xx_spi_probe(struct platform_device *pdev)  		goto err_no_pdata;  	} -	/* setup any gpio we can */ - -	if (!pdata->set_cs) { -		if (pdata->pin_cs < 0) { -			dev_err(&pdev->dev, "No chipselect pin\n"); -			err = -EINVAL; -			goto err_register; -		} - -		err = devm_gpio_request(&pdev->dev, pdata->pin_cs, -					dev_name(&pdev->dev)); -		if (err) { -			dev_err(&pdev->dev, "Failed to get gpio for cs\n"); -			goto err_register; -		} - -		hw->set_cs = s3c24xx_spi_gpiocs; -		gpio_direction_output(pdata->pin_cs, 1); -	} else -		hw->set_cs = pdata->set_cs; -  	s3c24xx_spi_initialsetup(hw);  	/* register our spi controller */ @@ -604,9 +566,6 @@ static int s3c24xx_spi_suspend(struct device *dev)  	if (ret)  		return ret; -	if (hw->pdata && hw->pdata->gpio_setup) -		hw->pdata->gpio_setup(hw->pdata, 0); -  	clk_disable(hw->clk);  	return 0;  } diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 8755cd85e83c..c26440e9058d 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -13,10 +13,8 @@  #include <linux/platform_device.h>  #include <linux/pm_runtime.h>  #include <linux/spi/spi.h> -#include <linux/gpio.h>  #include <linux/of.h>  #include <linux/of_device.h> -#include <linux/of_gpio.h>  #include <linux/platform_data/spi-s3c64xx.h> @@ -656,7 +654,11 @@ static int s3c64xx_spi_prepare_message(struct spi_master *master,  	struct s3c64xx_spi_csinfo *cs = spi->controller_data;  	/* Configure feedback delay */ -	writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); +	if (!cs) +		/* No delay if not defined */ +		writel(0, sdd->regs + S3C64XX_SPI_FB_CLK); +	else +		writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK);  	return 0;  } @@ -796,16 +798,14 @@ static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(  		return ERR_PTR(-EINVAL);  	} -	data_np = of_get_child_by_name(slave_np, "controller-data"); -	if (!data_np) { -		dev_err(&spi->dev, "child node 'controller-data' not found\n"); -		return ERR_PTR(-EINVAL); -	} -  	cs = kzalloc(sizeof(*cs), GFP_KERNEL); -	if (!cs) { -		of_node_put(data_np); +	if (!cs)  		return ERR_PTR(-ENOMEM); + +	data_np = of_get_child_by_name(slave_np, "controller-data"); +	if (!data_np) { +		dev_info(&spi->dev, "feedback delay set to default (0)\n"); +		return cs;  	}  	of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay); @@ -830,34 +830,16 @@ static int s3c64xx_spi_setup(struct spi_device *spi)  	if (spi->dev.of_node) {  		cs = s3c64xx_get_slave_ctrldata(spi);  		spi->controller_data = cs; -	} else if (cs) { -		/* On non-DT platforms the SPI core will set spi->cs_gpio -		 * to -ENOENT. The GPIO pin used to drive the chip select -		 * is defined by using platform data so spi->cs_gpio value -		 * has to be override to have the proper GPIO pin number. -		 */ -		spi->cs_gpio = cs->line;  	} -	if (IS_ERR_OR_NULL(cs)) { +	/* NULL is fine, we just avoid using the FB delay (=0) */ +	if (IS_ERR(cs)) {  		dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);  		return -ENODEV;  	} -	if (!spi_get_ctldata(spi)) { -		if (gpio_is_valid(spi->cs_gpio)) { -			err = gpio_request_one(spi->cs_gpio, GPIOF_OUT_INIT_HIGH, -					       dev_name(&spi->dev)); -			if (err) { -				dev_err(&spi->dev, -					"Failed to get /CS gpio [%d]: %d\n", -					spi->cs_gpio, err); -				goto err_gpio_req; -			} -		} - +	if (!spi_get_ctldata(spi))  		spi_set_ctldata(spi, cs); -	}  	pm_runtime_get_sync(&sdd->pdev->dev); @@ -909,11 +891,9 @@ setup_exit:  	/* setup() returns with device de-selected */  	s3c64xx_spi_set_cs(spi, false); -	if (gpio_is_valid(spi->cs_gpio)) -		gpio_free(spi->cs_gpio);  	spi_set_ctldata(spi, NULL); -err_gpio_req: +	/* This was dynamically allocated on the DT path */  	if (spi->dev.of_node)  		kfree(cs); @@ -924,19 +904,9 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi)  {  	struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); -	if (gpio_is_valid(spi->cs_gpio)) { -		gpio_free(spi->cs_gpio); -		if (spi->dev.of_node) -			kfree(cs); -		else { -			/* On non-DT platforms, the SPI core sets -			 * spi->cs_gpio to -ENOENT and .setup() -			 * overrides it with the GPIO pin value -			 * passed using platform data. -			 */ -			spi->cs_gpio = -ENOENT; -		} -	} +	/* This was dynamically allocated on the DT path */ +	if (spi->dev.of_node) +		kfree(cs);  	spi_set_ctldata(spi, NULL);  } @@ -1131,6 +1101,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)  	master->prepare_message = s3c64xx_spi_prepare_message;  	master->transfer_one = s3c64xx_spi_transfer_one;  	master->num_chipselect = sci->num_cs; +	master->use_gpio_descriptors = true;  	master->dma_alignment = 8;  	master->bits_per_word_mask = SPI_BPW_MASK(32) | SPI_BPW_MASK(16) |  					SPI_BPW_MASK(8); @@ -1442,6 +1413,16 @@ static const struct s3c64xx_spi_port_config exynos5433_spi_port_config = {  	.quirks		= S3C64XX_SPI_QUIRK_CS_AUTO,  }; +static struct s3c64xx_spi_port_config fsd_spi_port_config = { +	.fifo_lvl_mask	= { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f}, +	.rx_lvl_offset	= 15, +	.tx_st_done	= 25, +	.high_speed	= true, +	.clk_from_cmu	= true, +	.clk_ioclk	= false, +	.quirks		= S3C64XX_SPI_QUIRK_CS_AUTO, +}; +  static const struct platform_device_id s3c64xx_spi_driver_ids[] = {  	{  		.name		= "s3c2443-spi", @@ -1472,6 +1453,9 @@ static const struct of_device_id s3c64xx_spi_dt_match[] = {  	{ .compatible = "samsung,exynos5433-spi",  			.data = (void *)&exynos5433_spi_port_config,  	}, +	{ .compatible = "tesla,fsd-spi", +			.data = (void *)&fsd_spi_port_config, +	},  	{ },  };  MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match); diff --git a/drivers/spi/spi-slave-system-control.c b/drivers/spi/spi-slave-system-control.c index 169f3d595f60..d37cfe995a63 100644 --- a/drivers/spi/spi-slave-system-control.c +++ b/drivers/spi/spi-slave-system-control.c @@ -132,13 +132,12 @@ static int spi_slave_system_control_probe(struct spi_device *spi)  	return 0;  } -static int spi_slave_system_control_remove(struct spi_device *spi) +static void spi_slave_system_control_remove(struct spi_device *spi)  {  	struct spi_slave_system_control_priv *priv = spi_get_drvdata(spi);  	spi_slave_abort(spi);  	wait_for_completion(&priv->finished); -	return 0;  }  static struct spi_driver spi_slave_system_control_driver = { diff --git a/drivers/spi/spi-slave-time.c b/drivers/spi/spi-slave-time.c index f2e07a392d68..f56c1afb8534 100644 --- a/drivers/spi/spi-slave-time.c +++ b/drivers/spi/spi-slave-time.c @@ -106,13 +106,12 @@ static int spi_slave_time_probe(struct spi_device *spi)  	return 0;  } -static int spi_slave_time_remove(struct spi_device *spi) +static void spi_slave_time_remove(struct spi_device *spi)  {  	struct spi_slave_time_priv *priv = spi_get_drvdata(spi);  	spi_slave_abort(spi);  	wait_for_completion(&priv->finished); -	return 0;  }  static struct spi_driver spi_slave_time_driver = { diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index 6c44dda9ee8c..843be803696b 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -17,7 +17,6 @@  #include <linux/pinctrl/consumer.h>  #include <linux/platform_device.h>  #include <linux/of.h> -#include <linux/of_gpio.h>  #include <linux/of_irq.h>  #include <linux/pm_runtime.h>  #include <linux/spi/spi.h> @@ -171,11 +170,6 @@ static int spi_st_transfer_one(struct spi_master *master,  	return t->len;  } -static void spi_st_cleanup(struct spi_device *spi) -{ -	gpio_free(spi->cs_gpio); -} -  /* the spi->mode bits understood by this driver: */  #define MODEBITS  (SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | SPI_CS_HIGH)  static int spi_st_setup(struct spi_device *spi) @@ -183,29 +177,17 @@ static int spi_st_setup(struct spi_device *spi)  	struct spi_st *spi_st = spi_master_get_devdata(spi->master);  	u32 spi_st_clk, sscbrg, var;  	u32 hz = spi->max_speed_hz; -	int cs = spi->cs_gpio; -	int ret;  	if (!hz)  {  		dev_err(&spi->dev, "max_speed_hz unspecified\n");  		return -EINVAL;  	} -	if (!gpio_is_valid(cs)) { -		dev_err(&spi->dev, "%d is not a valid gpio\n", cs); +	if (!spi->cs_gpiod) { +		dev_err(&spi->dev, "no valid gpio assigned\n");  		return -EINVAL;  	} -	ret = gpio_request(cs, dev_name(&spi->dev)); -	if (ret) { -		dev_err(&spi->dev, "could not request gpio:%d\n", cs); -		return ret; -	} - -	ret = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); -	if (ret) -		goto out_free_gpio; -  	spi_st_clk = clk_get_rate(spi_st->clk);  	/* Set SSC_BRF */ @@ -213,8 +195,7 @@ static int spi_st_setup(struct spi_device *spi)  	if (sscbrg < 0x07 || sscbrg > BIT(16)) {  		dev_err(&spi->dev,  			"baudrate %d outside valid range %d\n", sscbrg, hz); -		ret = -EINVAL; -		goto out_free_gpio; +		return -EINVAL;  	}  	spi_st->baud = spi_st_clk / (2 * sscbrg); @@ -263,10 +244,6 @@ static int spi_st_setup(struct spi_device *spi)  	readl_relaxed(spi_st->base + SSC_RBUF);  	return 0; - -out_free_gpio: -	gpio_free(cs); -	return ret;  }  /* Interrupt fired when TX shift register becomes empty */ @@ -309,11 +286,11 @@ static int spi_st_probe(struct platform_device *pdev)  	master->dev.of_node		= np;  	master->mode_bits		= MODEBITS;  	master->setup			= spi_st_setup; -	master->cleanup			= spi_st_cleanup;  	master->transfer_one		= spi_st_transfer_one;  	master->bits_per_word_mask	= SPI_BPW_MASK(8) | SPI_BPW_MASK(16);  	master->auto_runtime_pm		= true;  	master->bus_num			= pdev->id; +	master->use_gpio_descriptors	= true;  	spi_st				= spi_master_get_devdata(master);  	spi_st->clk = devm_clk_get(&pdev->dev, "ssc"); diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 7fc24505a72c..a6adc20f6862 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -763,7 +763,7 @@ static irqreturn_t stm32f4_spi_irq_event(int irq, void *dev_id)  	if (!spi->cur_usedma && (spi->cur_comm == SPI_SIMPLEX_TX ||  				 spi->cur_comm == SPI_3WIRE_TX)) {  		/* OVR flag shouldn't be handled for TX only mode */ -		sr &= ~STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE; +		sr &= ~(STM32F4_SPI_SR_OVR | STM32F4_SPI_SR_RXNE);  		mask |= STM32F4_SPI_SR_TXE;  	} diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 1fdfc6e6691d..6000d0761206 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -280,7 +280,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master,  	 * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))  	 * Or we can use CDR2, which is calculated with the formula:  	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) -	 * Wether we use the former or the latter is set through the +	 * Whether we use the former or the latter is set through the  	 * DRS bit.  	 *  	 * First try CDR2, and if we can't reach the expected diff --git a/drivers/spi/spi-sunplus-sp7021.c b/drivers/spi/spi-sunplus-sp7021.c new file mode 100644 index 000000000000..f989f7b99296 --- /dev/null +++ b/drivers/spi/spi-sunplus-sp7021.c @@ -0,0 +1,584 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2021 Sunplus Inc. +// Author: Li-hao Kuo <lhjeff911@gmail.com> + +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> +#include <linux/spi/spi.h> + +#define SP7021_DATA_RDY_REG		0x0044 +#define SP7021_SLAVE_DMA_CTRL_REG	0x0048 +#define SP7021_SLAVE_DMA_LENGTH_REG	0x004c +#define SP7021_SLAVE_DMA_ADDR_REG	0x004c + +#define SP7021_SLAVE_DATA_RDY		BIT(0) +#define SP7021_SLAVE_SW_RST		BIT(1) +#define SP7021_SLA_DMA_W_INT		BIT(8) +#define SP7021_SLAVE_CLR_INT		BIT(8) +#define SP7021_SLAVE_DMA_EN		BIT(0) +#define SP7021_SLAVE_DMA_RW		BIT(6) +#define SP7021_SLAVE_DMA_CMD		GENMASK(3, 2) + +#define SP7021_FIFO_REG			0x0034 +#define SP7021_SPI_STATUS_REG		0x0038 +#define SP7021_SPI_CONFIG_REG		0x003c +#define SP7021_INT_BUSY_REG		0x004c +#define SP7021_DMA_CTRL_REG		0x0050 + +#define SP7021_SPI_START_FD		BIT(0) +#define SP7021_FD_SW_RST		BIT(1) +#define SP7021_TX_EMP_FLAG		BIT(2) +#define SP7021_RX_EMP_FLAG		BIT(4) +#define SP7021_RX_FULL_FLAG		BIT(5) +#define SP7021_FINISH_FLAG		BIT(6) + +#define SP7021_TX_CNT_MASK		GENMASK(11, 8) +#define SP7021_RX_CNT_MASK		GENMASK(15, 12) +#define SP7021_TX_LEN_MASK		GENMASK(23, 16) +#define SP7021_GET_LEN_MASK		GENMASK(31, 24) +#define SP7021_SET_TX_LEN		GENMASK(23, 16) +#define SP7021_SET_XFER_LEN		GENMASK(31, 24) + +#define SP7021_CPOL_FD			BIT(0) +#define SP7021_CPHA_R			BIT(1) +#define SP7021_CPHA_W			BIT(2) +#define SP7021_LSB_SEL			BIT(4) +#define SP7021_CS_POR			BIT(5) +#define SP7021_FD_SEL			BIT(6) + +#define SP7021_RX_UNIT			GENMASK(8, 7) +#define SP7021_TX_UNIT			GENMASK(10, 9) +#define SP7021_TX_EMP_FLAG_MASK		BIT(11) +#define SP7021_RX_FULL_FLAG_MASK	BIT(14) +#define SP7021_FINISH_FLAG_MASK		BIT(15) +#define SP7021_CLEAN_RW_BYTE		GENMASK(10, 7) +#define SP7021_CLEAN_FLUG_MASK		GENMASK(15, 11) +#define SP7021_CLK_MASK			GENMASK(31, 16) + +#define SP7021_INT_BYPASS		BIT(3) +#define SP7021_CLR_MASTER_INT		BIT(6) + +#define SP7021_SPI_DATA_SIZE		(255) +#define SP7021_FIFO_DATA_LEN		(16) + +enum { +	SP7021_MASTER_MODE = 0, +	SP7021_SLAVE_MODE = 1, +}; + +struct sp7021_spi_ctlr { +	struct device *dev; +	struct spi_controller *ctlr; +	void __iomem *m_base; +	void __iomem *s_base; +	u32 xfer_conf; +	int mode; +	int m_irq; +	int s_irq; +	struct clk *spi_clk; +	struct reset_control *rstc; +	// irq spin lock +	spinlock_t lock; +	// data xfer lock +	struct mutex buf_lock; +	struct completion isr_done; +	struct completion slave_isr; +	unsigned int  rx_cur_len; +	unsigned int  tx_cur_len; +	unsigned int  data_unit; +	const u8 *tx_buf; +	u8 *rx_buf; +}; + +static irqreturn_t sp7021_spi_slave_irq(int irq, void *dev) +{ +	struct sp7021_spi_ctlr *pspim = dev; +	unsigned int data_status; + +	data_status = readl(pspim->s_base + SP7021_DATA_RDY_REG); +	data_status |= SP7021_SLAVE_CLR_INT; +	writel(data_status , pspim->s_base + SP7021_DATA_RDY_REG); +	complete(&pspim->slave_isr); +	return IRQ_HANDLED; +} + +static int sp7021_spi_slave_abort(struct spi_controller *ctlr) +{ +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + +	complete(&pspim->slave_isr); +	complete(&pspim->isr_done); +	return 0; +} + +static int sp7021_spi_slave_tx(struct spi_device *spi, struct spi_transfer *xfer) +{ +	struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller); +	u32 value; + +	reinit_completion(&pspim->slave_isr); +	value = SP7021_SLAVE_DMA_EN | SP7021_SLAVE_DMA_RW | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3); +	writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); +	writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG); +	writel(xfer->tx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG); +	value = readl(pspim->s_base + SP7021_DATA_RDY_REG); +	value |= SP7021_SLAVE_DATA_RDY; +	writel(value, pspim->s_base + SP7021_DATA_RDY_REG); +	if (wait_for_completion_interruptible(&pspim->isr_done)) { +		dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__); +		return -EINTR; +	} +	return 0; +} + +static int sp7021_spi_slave_rx(struct spi_device *spi, struct spi_transfer *xfer) +{ +	struct sp7021_spi_ctlr *pspim = spi_controller_get_devdata(spi->controller); +	u32 value; + +	reinit_completion(&pspim->isr_done); +	value = SP7021_SLAVE_DMA_EN | FIELD_PREP(SP7021_SLAVE_DMA_CMD, 3); +	writel(value, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); +	writel(xfer->len, pspim->s_base + SP7021_SLAVE_DMA_LENGTH_REG); +	writel(xfer->rx_dma, pspim->s_base + SP7021_SLAVE_DMA_ADDR_REG); +	if (wait_for_completion_interruptible(&pspim->isr_done)) { +		dev_err(&spi->dev, "%s() wait_for_completion err\n", __func__); +		return -EINTR; +	} +	writel(SP7021_SLAVE_SW_RST, pspim->s_base + SP7021_SLAVE_DMA_CTRL_REG); +	return 0; +} + +static void sp7021_spi_master_rb(struct sp7021_spi_ctlr *pspim, unsigned int len) +{ +	int i; + +	for (i = 0; i < len; i++) { +		pspim->rx_buf[pspim->rx_cur_len] = +			readl(pspim->m_base + SP7021_FIFO_REG); +		pspim->rx_cur_len++; +	} +} + +static void sp7021_spi_master_wb(struct sp7021_spi_ctlr *pspim, unsigned int len) +{ +	int i; + +	for (i = 0; i < len; i++) { +		writel(pspim->tx_buf[pspim->tx_cur_len], +		       pspim->m_base + SP7021_FIFO_REG); +		pspim->tx_cur_len++; +	} +} + +static irqreturn_t sp7021_spi_master_irq(int irq, void *dev) +{ +	struct sp7021_spi_ctlr *pspim = dev; +	unsigned int tx_cnt, total_len; +	unsigned int tx_len, rx_cnt; +	unsigned int fd_status; +	bool isrdone = false; +	u32 value; + +	fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); +	tx_cnt = FIELD_GET(SP7021_TX_CNT_MASK, fd_status); +	tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status); +	total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); + +	if ((fd_status & SP7021_TX_EMP_FLAG) && (fd_status & SP7021_RX_EMP_FLAG) && total_len == 0) +		return IRQ_NONE; + +	if (tx_len == 0 && total_len == 0) +		return IRQ_NONE; + +	spin_lock_irq(&pspim->lock); + +	rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status); +	if (fd_status & SP7021_RX_FULL_FLAG) +		rx_cnt = pspim->data_unit; + +	tx_cnt = min(tx_len - pspim->tx_cur_len, pspim->data_unit - tx_cnt); +	dev_dbg(pspim->dev, "fd_st=0x%x rx_c:%d tx_c:%d tx_l:%d", +		fd_status, rx_cnt, tx_cnt, tx_len); + +	if (rx_cnt > 0) +		sp7021_spi_master_rb(pspim, rx_cnt); +	if (tx_cnt > 0) +		sp7021_spi_master_wb(pspim, tx_cnt); + +	fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); +	tx_len = FIELD_GET(SP7021_TX_LEN_MASK, fd_status); +	total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); + +	if (fd_status & SP7021_FINISH_FLAG || tx_len == pspim->tx_cur_len) { +		while (total_len != pspim->rx_cur_len) { +			fd_status = readl(pspim->m_base + SP7021_SPI_STATUS_REG); +			total_len = FIELD_GET(SP7021_GET_LEN_MASK, fd_status); +			if (fd_status & SP7021_RX_FULL_FLAG) +				rx_cnt = pspim->data_unit; +			else +				rx_cnt = FIELD_GET(SP7021_RX_CNT_MASK, fd_status); + +			if (rx_cnt > 0) +				sp7021_spi_master_rb(pspim, rx_cnt); +		} +		value = readl(pspim->m_base + SP7021_INT_BUSY_REG); +		value |= SP7021_CLR_MASTER_INT; +		writel(value, pspim->m_base + SP7021_INT_BUSY_REG); +		writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG); +		isrdone = true; +	} + +	if (isrdone) +		complete(&pspim->isr_done); +	spin_unlock_irq(&pspim->lock); +	return IRQ_HANDLED; +} + +static void sp7021_prep_transfer(struct spi_controller *ctlr, struct spi_device *spi) +{ +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + +	pspim->tx_cur_len = 0; +	pspim->rx_cur_len = 0; +	pspim->data_unit = SP7021_FIFO_DATA_LEN; +} + +// preliminary set CS, CPOL, CPHA and LSB +static int sp7021_spi_controller_prepare_message(struct spi_controller *ctlr, +						 struct spi_message *msg) +{ +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); +	struct spi_device *s = msg->spi; +	u32 valus, rs = 0; + +	valus = readl(pspim->m_base + SP7021_SPI_STATUS_REG); +	valus |= SP7021_FD_SW_RST; +	writel(valus, pspim->m_base + SP7021_SPI_STATUS_REG); +	rs |= SP7021_FD_SEL; +	if (s->mode & SPI_CPOL) +		rs |= SP7021_CPOL_FD; + +	if (s->mode & SPI_LSB_FIRST) +		rs |= SP7021_LSB_SEL; + +	if (s->mode & SPI_CS_HIGH) +		rs |= SP7021_CS_POR; + +	if (s->mode & SPI_CPHA) +		rs |=  SP7021_CPHA_R; +	else +		rs |=  SP7021_CPHA_W; + +	rs |=  FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0); +	pspim->xfer_conf = rs; +	if (pspim->xfer_conf & SP7021_CPOL_FD) +		writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); + +	return 0; +} + +static void sp7021_spi_setup_clk(struct spi_controller *ctlr, struct spi_transfer *xfer) +{ +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); +	u32 clk_rate, clk_sel, div; + +	clk_rate = clk_get_rate(pspim->spi_clk); +	div = max(2U, clk_rate / xfer->speed_hz); + +	clk_sel = (div / 2) - 1; +	pspim->xfer_conf &= ~SP7021_CLK_MASK; +	pspim->xfer_conf |= FIELD_PREP(SP7021_CLK_MASK, clk_sel); +	writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); +} + +static int sp7021_spi_master_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, +				       struct spi_transfer *xfer) +{ +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); +	unsigned long timeout = msecs_to_jiffies(1000); +	unsigned int xfer_cnt, xfer_len, last_len; +	unsigned int i, len_temp; +	u32 reg_temp; + +	xfer_cnt = xfer->len / SP7021_SPI_DATA_SIZE; +	last_len = xfer->len % SP7021_SPI_DATA_SIZE; + +	for (i = 0; i <= xfer_cnt; i++) { +		mutex_lock(&pspim->buf_lock); +		sp7021_prep_transfer(ctlr, spi); +		sp7021_spi_setup_clk(ctlr, xfer); +		reinit_completion(&pspim->isr_done); + +		if (i == xfer_cnt) +			xfer_len = last_len; +		else +			xfer_len = SP7021_SPI_DATA_SIZE; + +		pspim->tx_buf = xfer->tx_buf + i * SP7021_SPI_DATA_SIZE; +		pspim->rx_buf = xfer->rx_buf + i * SP7021_SPI_DATA_SIZE; + +		if (pspim->tx_cur_len < xfer_len) { +			len_temp = min(pspim->data_unit, xfer_len); +			sp7021_spi_master_wb(pspim, len_temp); +		} +		reg_temp = readl(pspim->m_base + SP7021_SPI_CONFIG_REG); +		reg_temp &= ~SP7021_CLEAN_RW_BYTE; +		reg_temp &= ~SP7021_CLEAN_FLUG_MASK; +		reg_temp |= SP7021_FD_SEL | SP7021_FINISH_FLAG_MASK | +			    SP7021_TX_EMP_FLAG_MASK | SP7021_RX_FULL_FLAG_MASK | +			    FIELD_PREP(SP7021_TX_UNIT, 0) | FIELD_PREP(SP7021_RX_UNIT, 0); +		writel(reg_temp, pspim->m_base + SP7021_SPI_CONFIG_REG); + +		reg_temp = FIELD_PREP(SP7021_SET_TX_LEN, xfer_len) | +				      FIELD_PREP(SP7021_SET_XFER_LEN, xfer_len) | +				      SP7021_SPI_START_FD; +		writel(reg_temp, pspim->m_base + SP7021_SPI_STATUS_REG); + +		if (!wait_for_completion_interruptible_timeout(&pspim->isr_done, timeout)) { +			dev_err(&spi->dev, "wait_for_completion err\n"); +			mutex_unlock(&pspim->buf_lock); +			return -ETIMEDOUT; +		} + +		reg_temp = readl(pspim->m_base + SP7021_SPI_STATUS_REG); +		if (reg_temp & SP7021_FINISH_FLAG) { +			writel(SP7021_FINISH_FLAG, pspim->m_base + SP7021_SPI_STATUS_REG); +			writel(readl(pspim->m_base + SP7021_SPI_CONFIG_REG) & +				SP7021_CLEAN_FLUG_MASK, pspim->m_base + SP7021_SPI_CONFIG_REG); +		} + +		if (pspim->xfer_conf & SP7021_CPOL_FD) +			writel(pspim->xfer_conf, pspim->m_base + SP7021_SPI_CONFIG_REG); + +		mutex_unlock(&pspim->buf_lock); +	} +	return 0; +} + +static int sp7021_spi_slave_transfer_one(struct spi_controller *ctlr, struct spi_device *spi, +				       struct spi_transfer *xfer) +{ +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); +	struct device *dev = pspim->dev; +	int ret; + +	if (xfer->tx_buf && !xfer->rx_buf) { +		xfer->tx_dma = dma_map_single(dev, (void *)xfer->tx_buf, +					      xfer->len, DMA_TO_DEVICE); +		if (dma_mapping_error(dev, xfer->tx_dma)) +			return -ENOMEM; +		ret = sp7021_spi_slave_tx(spi, xfer); +		dma_unmap_single(dev, xfer->tx_dma, xfer->len, DMA_TO_DEVICE); +	} else if (xfer->rx_buf && !xfer->tx_buf) { +		xfer->rx_dma = dma_map_single(dev, xfer->rx_buf, xfer->len, +					      DMA_FROM_DEVICE); +		if (dma_mapping_error(dev, xfer->rx_dma)) +			return -ENOMEM; +		ret = sp7021_spi_slave_rx(spi, xfer); +		dma_unmap_single(dev, xfer->rx_dma, xfer->len, DMA_FROM_DEVICE); +	} else { +		dev_dbg(&ctlr->dev, "%s() wrong command\n", __func__); +		return -EINVAL; +	} + +	spi_finalize_current_transfer(ctlr); +	return ret; +} + +static void sp7021_spi_disable_unprepare(void *data) +{ +	clk_disable_unprepare(data); +} + +static void sp7021_spi_reset_control_assert(void *data) +{ +	reset_control_assert(data); +} + +static int sp7021_spi_controller_probe(struct platform_device *pdev) +{ +	struct device *dev = &pdev->dev; +	struct sp7021_spi_ctlr *pspim; +	struct spi_controller *ctlr; +	int mode, ret; + +	pdev->id = of_alias_get_id(pdev->dev.of_node, "sp_spi"); + +	if (device_property_read_bool(dev, "spi-slave")) +		mode = SP7021_SLAVE_MODE; +	else +		mode = SP7021_MASTER_MODE; + +	if (mode == SP7021_SLAVE_MODE) +		ctlr = devm_spi_alloc_slave(dev, sizeof(*pspim)); +	else +		ctlr = devm_spi_alloc_master(dev, sizeof(*pspim)); +	if (!ctlr) +		return -ENOMEM; +	device_set_node(&ctlr->dev, dev_fwnode(dev)); +	ctlr->bus_num = pdev->id; +	ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; +	ctlr->auto_runtime_pm = true; +	ctlr->prepare_message = sp7021_spi_controller_prepare_message; +	if (mode == SP7021_SLAVE_MODE) { +		ctlr->transfer_one = sp7021_spi_slave_transfer_one; +		ctlr->slave_abort = sp7021_spi_slave_abort; +		ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX; +	} else { +		ctlr->bits_per_word_mask = SPI_BPW_MASK(8); +		ctlr->min_speed_hz = 40000; +		ctlr->max_speed_hz = 25000000; +		ctlr->use_gpio_descriptors = true; +		ctlr->flags = SPI_CONTROLLER_MUST_RX | SPI_CONTROLLER_MUST_TX; +		ctlr->transfer_one = sp7021_spi_master_transfer_one; +	} +	platform_set_drvdata(pdev, ctlr); +	pspim = spi_controller_get_devdata(ctlr); +	pspim->mode = mode; +	pspim->ctlr = ctlr; +	pspim->dev = dev; +	spin_lock_init(&pspim->lock); +	mutex_init(&pspim->buf_lock); +	init_completion(&pspim->isr_done); +	init_completion(&pspim->slave_isr); + +	pspim->m_base = devm_platform_ioremap_resource_byname(pdev, "master"); +	if (IS_ERR(pspim->m_base)) +		return dev_err_probe(dev, PTR_ERR(pspim->m_base), "m_base get fail\n"); + +	pspim->s_base = devm_platform_ioremap_resource_byname(pdev, "slave"); +	if (IS_ERR(pspim->s_base)) +		return dev_err_probe(dev, PTR_ERR(pspim->s_base), "s_base get fail\n"); + +	pspim->m_irq = platform_get_irq_byname(pdev, "master_risc"); +	if (pspim->m_irq < 0) +		return pspim->m_irq; + +	pspim->s_irq = platform_get_irq_byname(pdev, "slave_risc"); +	if (pspim->s_irq < 0) +		return pspim->s_irq; + +	pspim->spi_clk = devm_clk_get(dev, NULL); +	if (IS_ERR(pspim->spi_clk)) +		return dev_err_probe(dev, PTR_ERR(pspim->spi_clk), "clk get fail\n"); + +	pspim->rstc = devm_reset_control_get_exclusive(dev, NULL); +	if (IS_ERR(pspim->rstc)) +		return dev_err_probe(dev, PTR_ERR(pspim->rstc), "rst get fail\n"); + +	ret = clk_prepare_enable(pspim->spi_clk); +	if (ret) +		return dev_err_probe(dev, ret, "failed to enable clk\n"); + +	ret = devm_add_action_or_reset(dev, sp7021_spi_disable_unprepare, pspim->spi_clk); +	if (ret) +		return ret; + +	ret = reset_control_deassert(pspim->rstc); +	if (ret) +		return dev_err_probe(dev, ret, "failed to deassert reset\n"); + +	ret = devm_add_action_or_reset(dev, sp7021_spi_reset_control_assert, pspim->rstc); +	if (ret) +		return ret; + +	ret = devm_request_irq(dev, pspim->m_irq, sp7021_spi_master_irq, +			       IRQF_TRIGGER_RISING, pdev->name, pspim); +	if (ret) +		return ret; + +	ret = devm_request_irq(dev, pspim->s_irq, sp7021_spi_slave_irq, +			       IRQF_TRIGGER_RISING, pdev->name, pspim); +	if (ret) +		return ret; + +	pm_runtime_enable(dev); +	ret = spi_register_controller(ctlr); +	if (ret) { +		pm_runtime_disable(dev); +		return dev_err_probe(dev, ret, "spi_register_master fail\n"); +	} +	return 0; +} + +static int sp7021_spi_controller_remove(struct platform_device *pdev) +{ +	struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); + +	spi_unregister_controller(ctlr); +	pm_runtime_disable(&pdev->dev); +	pm_runtime_set_suspended(&pdev->dev); +	return 0; +} + +static int __maybe_unused sp7021_spi_controller_suspend(struct device *dev) +{ +	struct spi_controller *ctlr = dev_get_drvdata(dev); +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + +	return reset_control_assert(pspim->rstc); +} + +static int __maybe_unused sp7021_spi_controller_resume(struct device *dev) +{ +	struct spi_controller *ctlr = dev_get_drvdata(dev); +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + +	reset_control_deassert(pspim->rstc); +	return clk_prepare_enable(pspim->spi_clk); +} + +#ifdef CONFIG_PM +static int sp7021_spi_runtime_suspend(struct device *dev) +{ +	struct spi_controller *ctlr = dev_get_drvdata(dev); +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + +	return reset_control_assert(pspim->rstc); +} + +static int sp7021_spi_runtime_resume(struct device *dev) +{ +	struct spi_controller *ctlr = dev_get_drvdata(dev); +	struct sp7021_spi_ctlr *pspim = spi_master_get_devdata(ctlr); + +	return reset_control_deassert(pspim->rstc); +} +#endif + +static const struct dev_pm_ops sp7021_spi_pm_ops = { +	SET_RUNTIME_PM_OPS(sp7021_spi_runtime_suspend, +			   sp7021_spi_runtime_resume, NULL) +	SET_SYSTEM_SLEEP_PM_OPS(sp7021_spi_controller_suspend, +				sp7021_spi_controller_resume) +}; + +static const struct of_device_id sp7021_spi_controller_ids[] = { +	{ .compatible = "sunplus,sp7021-spi" }, +	{} +}; +MODULE_DEVICE_TABLE(of, sp7021_spi_controller_ids); + +static struct platform_driver sp7021_spi_controller_driver = { +	.probe = sp7021_spi_controller_probe, +	.remove = sp7021_spi_controller_remove, +	.driver = { +		.name = "sunplus,sp7021-spi-controller", +		.of_match_table = sp7021_spi_controller_ids, +		.pm     = &sp7021_spi_pm_ops, +	}, +}; +module_platform_driver(sp7021_spi_controller_driver); + +MODULE_AUTHOR("Li-hao Kuo <lhjeff911@gmail.com>"); +MODULE_DESCRIPTION("Sunplus SPI controller driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index e9de1d958bbd..8f345247a8c3 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1352,6 +1352,10 @@ static int tegra_spi_probe(struct platform_device *pdev)  	tspi->phys = r->start;  	spi_irq = platform_get_irq(pdev, 0); +	if (spi_irq < 0) { +		ret = spi_irq; +		goto exit_free_master; +	}  	tspi->irq = spi_irq;  	tspi->clk = devm_clk_get(&pdev->dev, "spi"); diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index 2a03739a0c60..80c3787deea9 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -1006,14 +1006,8 @@ static int tegra_slink_probe(struct platform_device *pdev)  	struct resource		*r;  	int ret, spi_irq;  	const struct tegra_slink_chip_data *cdata = NULL; -	const struct of_device_id *match; -	match = of_match_device(tegra_slink_of_match, &pdev->dev); -	if (!match) { -		dev_err(&pdev->dev, "Error: No device match found\n"); -		return -ENODEV; -	} -	cdata = match->data; +	cdata = of_device_get_match_data(&pdev->dev);  	master = spi_alloc_master(&pdev->dev, sizeof(*tspi));  	if (!master) { diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index ce1bdb4767ea..66f647f32876 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -21,6 +21,8 @@  #include <linux/of_device.h>  #include <linux/reset.h>  #include <linux/spi/spi.h> +#include <linux/acpi.h> +#include <linux/property.h>  #define QSPI_COMMAND1				0x000  #define QSPI_BIT_LENGTH(x)			(((x) & 0x1f) << 0) @@ -119,11 +121,40 @@  #define QSPI_NUM_DUMMY_CYCLE(x)			(((x) & 0xff) << 0)  #define QSPI_DUMMY_CYCLES_MAX			0xff +#define QSPI_CMB_SEQ_CMD			0x19c +#define QSPI_COMMAND_VALUE_SET(X)		(((x) & 0xFF) << 0) + +#define QSPI_CMB_SEQ_CMD_CFG			0x1a0 +#define QSPI_COMMAND_X1_X2_X4(x)		(((x) & 0x3) << 13) +#define QSPI_COMMAND_X1_X2_X4_MASK		(0x03 << 13) +#define QSPI_COMMAND_SDR_DDR			BIT(12) +#define QSPI_COMMAND_SIZE_SET(x)		(((x) & 0xFF) << 0) + +#define QSPI_GLOBAL_CONFIG			0X1a4 +#define QSPI_CMB_SEQ_EN				BIT(0) + +#define QSPI_CMB_SEQ_ADDR			0x1a8 +#define QSPI_ADDRESS_VALUE_SET(X)		(((x) & 0xFFFF) << 0) + +#define QSPI_CMB_SEQ_ADDR_CFG			0x1ac +#define QSPI_ADDRESS_X1_X2_X4(x)		(((x) & 0x3) << 13) +#define QSPI_ADDRESS_X1_X2_X4_MASK		(0x03 << 13) +#define QSPI_ADDRESS_SDR_DDR			BIT(12) +#define QSPI_ADDRESS_SIZE_SET(x)		(((x) & 0xFF) << 0) +  #define DATA_DIR_TX				BIT(0)  #define DATA_DIR_RX				BIT(1)  #define QSPI_DMA_TIMEOUT			(msecs_to_jiffies(1000))  #define DEFAULT_QSPI_DMA_BUF_LEN		(64 * 1024) +#define CMD_TRANSFER				0 +#define ADDR_TRANSFER				1 +#define DATA_TRANSFER				2 + +struct tegra_qspi_soc_data { +	bool has_dma; +	bool cmb_xfer_capable; +};  struct tegra_qspi_client_data {  	int tx_clk_tap_delay; @@ -137,7 +168,6 @@ struct tegra_qspi {  	spinlock_t				lock;  	struct clk				*clk; -	struct reset_control			*rst;  	void __iomem				*base;  	phys_addr_t				phys;  	unsigned int				irq; @@ -185,6 +215,7 @@ struct tegra_qspi {  	u32					*tx_dma_buf;  	dma_addr_t				tx_dma_phys;  	struct dma_async_tx_descriptor		*tx_dma_desc; +	const struct tegra_qspi_soc_data	*soc_data;  };  static inline u32 tegra_qspi_readl(struct tegra_qspi *tqspi, unsigned long offset) @@ -767,7 +798,7 @@ static u32 tegra_qspi_setup_transfer_one(struct spi_device *spi, struct spi_tran  	u32 tx_tap = 0, rx_tap = 0;  	int req_mode; -	if (speed != tqspi->cur_speed) { +	if (!has_acpi_companion(tqspi->dev) && speed != tqspi->cur_speed) {  		clk_set_rate(tqspi->clk, speed);  		tqspi->cur_speed = speed;  	} @@ -875,16 +906,16 @@ static int tegra_qspi_start_transfer_one(struct spi_device *spi,  static struct tegra_qspi_client_data *tegra_qspi_parse_cdata_dt(struct spi_device *spi)  {  	struct tegra_qspi_client_data *cdata; -	struct device_node *slave_np = spi->dev.of_node;  	cdata = devm_kzalloc(&spi->dev, sizeof(*cdata), GFP_KERNEL);  	if (!cdata)  		return NULL; -	of_property_read_u32(slave_np, "nvidia,tx-clk-tap-delay", -			     &cdata->tx_clk_tap_delay); -	of_property_read_u32(slave_np, "nvidia,rx-clk-tap-delay", -			     &cdata->rx_clk_tap_delay); +	device_property_read_u32(&spi->dev, "nvidia,tx-clk-tap-delay", +				 &cdata->tx_clk_tap_delay); +	device_property_read_u32(&spi->dev, "nvidia,rx-clk-tap-delay", +				 &cdata->rx_clk_tap_delay); +  	return cdata;  } @@ -906,7 +937,6 @@ static int tegra_qspi_setup(struct spi_device *spi)  		cdata = tegra_qspi_parse_cdata_dt(spi);  		spi->controller_data = cdata;  	} -  	spin_lock_irqsave(&tqspi->lock, flags);  	/* keep default cs state to inactive */ @@ -948,9 +978,8 @@ static void tegra_qspi_handle_error(struct tegra_qspi *tqspi)  	dev_err(tqspi->dev, "error in transfer, fifo status 0x%08x\n", tqspi->status_reg);  	tegra_qspi_dump_regs(tqspi);  	tegra_qspi_flush_fifos(tqspi, true); -	reset_control_assert(tqspi->rst); -	udelay(2); -	reset_control_deassert(tqspi->rst); +	if (device_reset(tqspi->dev) < 0) +		dev_warn_once(tqspi->dev, "device reset failed\n");  }  static void tegra_qspi_transfer_end(struct spi_device *spi) @@ -966,19 +995,179 @@ static void tegra_qspi_transfer_end(struct spi_device *spi)  	tegra_qspi_writel(tqspi, tqspi->def_command1_reg, QSPI_COMMAND1);  } -static int tegra_qspi_transfer_one_message(struct spi_master *master, struct spi_message *msg) +static u32 tegra_qspi_cmd_config(bool is_ddr, u8 bus_width, u8 len) +{ +	u32 cmd_config = 0; + +	/* Extract Command configuration and value */ +	if (is_ddr) +		cmd_config |= QSPI_COMMAND_SDR_DDR; +	else +		cmd_config &= ~QSPI_COMMAND_SDR_DDR; + +	cmd_config |= QSPI_COMMAND_X1_X2_X4(bus_width); +	cmd_config |= QSPI_COMMAND_SIZE_SET((len * 8) - 1); + +	return cmd_config; +} + +static u32 tegra_qspi_addr_config(bool is_ddr, u8 bus_width, u8 len) +{ +	u32 addr_config = 0; + +	/* Extract Address configuration and value */ +	is_ddr = 0; //Only SDR mode supported +	bus_width = 0; //X1 mode + +	if (is_ddr) +		addr_config |= QSPI_ADDRESS_SDR_DDR; +	else +		addr_config &= ~QSPI_ADDRESS_SDR_DDR; + +	addr_config |= QSPI_ADDRESS_X1_X2_X4(bus_width); +	addr_config |= QSPI_ADDRESS_SIZE_SET((len * 8) - 1); + +	return addr_config; +} + +static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, +					struct spi_message *msg) +{ +	bool is_first_msg = true; +	struct spi_transfer *xfer; +	struct spi_device *spi = msg->spi; +	u8 transfer_phase = 0; +	u32 cmd1 = 0, dma_ctl = 0; +	int ret = 0; +	u32 address_value = 0; +	u32 cmd_config = 0, addr_config = 0; +	u8 cmd_value = 0, val = 0; + +	/* Enable Combined sequence mode */ +	val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +	val |= QSPI_CMB_SEQ_EN; +	tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG); +	/* Process individual transfer list */ +	list_for_each_entry(xfer, &msg->transfers, transfer_list) { +		switch (transfer_phase) { +		case CMD_TRANSFER: +			/* X1 SDR mode */ +			cmd_config = tegra_qspi_cmd_config(false, 0, +							   xfer->len); +			cmd_value = *((const u8 *)(xfer->tx_buf)); +			break; +		case ADDR_TRANSFER: +			/* X1 SDR mode */ +			addr_config = tegra_qspi_addr_config(false, 0, +							     xfer->len); +			address_value = *((const u32 *)(xfer->tx_buf)); +			break; +		case DATA_TRANSFER: +			/* Program Command, Address value in register */ +			tegra_qspi_writel(tqspi, cmd_value, QSPI_CMB_SEQ_CMD); +			tegra_qspi_writel(tqspi, address_value, +					  QSPI_CMB_SEQ_ADDR); +			/* Program Command and Address config in register */ +			tegra_qspi_writel(tqspi, cmd_config, +					  QSPI_CMB_SEQ_CMD_CFG); +			tegra_qspi_writel(tqspi, addr_config, +					  QSPI_CMB_SEQ_ADDR_CFG); + +			reinit_completion(&tqspi->xfer_completion); +			cmd1 = tegra_qspi_setup_transfer_one(spi, xfer, +							     is_first_msg); +			ret = tegra_qspi_start_transfer_one(spi, xfer, +							    cmd1); + +			if (ret < 0) { +				dev_err(tqspi->dev, "Failed to start transfer-one: %d\n", +					ret); +				return ret; +			} + +			is_first_msg = false; +			ret = wait_for_completion_timeout +					(&tqspi->xfer_completion, +					QSPI_DMA_TIMEOUT); + +			if (WARN_ON(ret == 0)) { +				dev_err(tqspi->dev, "QSPI Transfer failed with timeout: %d\n", +					ret); +				if (tqspi->is_curr_dma_xfer && +				    (tqspi->cur_direction & DATA_DIR_TX)) +					dmaengine_terminate_all +						(tqspi->tx_dma_chan); + +				if (tqspi->is_curr_dma_xfer && +				    (tqspi->cur_direction & DATA_DIR_RX)) +					dmaengine_terminate_all +						(tqspi->rx_dma_chan); + +				/* Abort transfer by resetting pio/dma bit */ +				if (!tqspi->is_curr_dma_xfer) { +					cmd1 = tegra_qspi_readl +							(tqspi, +							 QSPI_COMMAND1); +					cmd1 &= ~QSPI_PIO; +					tegra_qspi_writel +							(tqspi, cmd1, +							 QSPI_COMMAND1); +				} else { +					dma_ctl = tegra_qspi_readl +							(tqspi, +							 QSPI_DMA_CTL); +					dma_ctl &= ~QSPI_DMA_EN; +					tegra_qspi_writel(tqspi, dma_ctl, +							  QSPI_DMA_CTL); +				} + +				/* Reset controller if timeout happens */ +				if (device_reset(tqspi->dev) < 0) +					dev_warn_once(tqspi->dev, +						      "device reset failed\n"); +				ret = -EIO; +				goto exit; +			} + +			if (tqspi->tx_status ||  tqspi->rx_status) { +				dev_err(tqspi->dev, "QSPI Transfer failed\n"); +				tqspi->tx_status = 0; +				tqspi->rx_status = 0; +				ret = -EIO; +				goto exit; +			} +			break; +		default: +			ret = -EINVAL; +			goto exit; +		} +		msg->actual_length += xfer->len; +		transfer_phase++; +	} + +exit: +	msg->status = ret; + +	return ret; +} + +static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, +					    struct spi_message *msg)  { -	struct tegra_qspi *tqspi = spi_master_get_devdata(master);  	struct spi_device *spi = msg->spi;  	struct spi_transfer *transfer;  	bool is_first_msg = true; -	int ret; +	int ret = 0, val = 0;  	msg->status = 0;  	msg->actual_length = 0;  	tqspi->tx_status = 0;  	tqspi->rx_status = 0; +	/* Disable Combined sequence mode */ +	val = tegra_qspi_readl(tqspi, QSPI_GLOBAL_CONFIG); +	val &= ~QSPI_CMB_SEQ_EN; +	tegra_qspi_writel(tqspi, val, QSPI_GLOBAL_CONFIG);  	list_for_each_entry(transfer, &msg->transfers, transfer_list) {  		struct spi_transfer *xfer = transfer;  		u8 dummy_bytes = 0; @@ -1016,7 +1205,6 @@ static int tegra_qspi_transfer_one_message(struct spi_master *master, struct spi  			goto complete_xfer;  		} -		is_first_msg = false;  		ret = wait_for_completion_timeout(&tqspi->xfer_completion,  						  QSPI_DMA_TIMEOUT);  		if (WARN_ON(ret == 0)) { @@ -1061,7 +1249,48 @@ complete_xfer:  	ret = 0;  exit:  	msg->status = ret; + +	return ret; +} + +static bool tegra_qspi_validate_cmb_seq(struct tegra_qspi *tqspi, +					struct spi_message *msg) +{ +	int transfer_count = 0; +	struct spi_transfer *xfer; + +	list_for_each_entry(xfer, &msg->transfers, transfer_list) { +		transfer_count++; +	} +	if (!tqspi->soc_data->cmb_xfer_capable || transfer_count != 3) +		return false; +	xfer = list_first_entry(&msg->transfers, typeof(*xfer), +				transfer_list); +	if (xfer->len > 2) +		return false; +	xfer = list_next_entry(xfer, transfer_list); +	if (xfer->len > 4 || xfer->len < 3) +		return false; +	xfer = list_next_entry(xfer, transfer_list); +	if (!tqspi->soc_data->has_dma || xfer->len > (QSPI_FIFO_DEPTH << 2)) +		return false; + +	return true; +} + +static int tegra_qspi_transfer_one_message(struct spi_master *master, +					   struct spi_message *msg) +{ +	struct tegra_qspi *tqspi = spi_master_get_devdata(master); +	int ret; + +	if (tegra_qspi_validate_cmb_seq(tqspi, msg)) +		ret = tegra_qspi_combined_seq_xfer(tqspi, msg); +	else +		ret = tegra_qspi_non_combined_seq_xfer(tqspi, msg); +  	spi_finalize_current_message(master); +  	return ret;  } @@ -1193,15 +1422,58 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data)  	return handle_dma_based_xfer(tqspi);  } +static struct tegra_qspi_soc_data tegra210_qspi_soc_data = { +	.has_dma = true, +	.cmb_xfer_capable = false, +}; + +static struct tegra_qspi_soc_data tegra186_qspi_soc_data = { +	.has_dma = true, +	.cmb_xfer_capable = true, +}; + +static struct tegra_qspi_soc_data tegra234_qspi_soc_data = { +	.has_dma = false, +	.cmb_xfer_capable = true, +}; +  static const struct of_device_id tegra_qspi_of_match[] = { -	{ .compatible = "nvidia,tegra210-qspi", }, -	{ .compatible = "nvidia,tegra186-qspi", }, -	{ .compatible = "nvidia,tegra194-qspi", }, +	{ +		.compatible = "nvidia,tegra210-qspi", +		.data	    = &tegra210_qspi_soc_data, +	}, { +		.compatible = "nvidia,tegra186-qspi", +		.data	    = &tegra186_qspi_soc_data, +	}, { +		.compatible = "nvidia,tegra194-qspi", +		.data	    = &tegra186_qspi_soc_data, +	}, { +		.compatible = "nvidia,tegra234-qspi", +		.data	    = &tegra234_qspi_soc_data, +	},  	{}  };  MODULE_DEVICE_TABLE(of, tegra_qspi_of_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id tegra_qspi_acpi_match[] = { +	{ +		.id = "NVDA1213", +		.driver_data = (kernel_ulong_t)&tegra210_qspi_soc_data, +	}, { +		.id = "NVDA1313", +		.driver_data = (kernel_ulong_t)&tegra186_qspi_soc_data, +	}, { +		.id = "NVDA1413", +		.driver_data = (kernel_ulong_t)&tegra234_qspi_soc_data, +	}, +	{} +}; + +MODULE_DEVICE_TABLE(acpi, tegra_qspi_acpi_match); +#endif +  static int tegra_qspi_probe(struct platform_device *pdev)  {  	struct spi_master	*master; @@ -1233,6 +1505,7 @@ static int tegra_qspi_probe(struct platform_device *pdev)  	tqspi->dev = &pdev->dev;  	spin_lock_init(&tqspi->lock); +	tqspi->soc_data = device_get_match_data(&pdev->dev);  	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	tqspi->base = devm_ioremap_resource(&pdev->dev, r);  	if (IS_ERR(tqspi->base)) @@ -1240,20 +1513,18 @@ static int tegra_qspi_probe(struct platform_device *pdev)  	tqspi->phys = r->start;  	qspi_irq = platform_get_irq(pdev, 0); +	if (qspi_irq < 0) +		return qspi_irq;  	tqspi->irq = qspi_irq; -	tqspi->clk = devm_clk_get(&pdev->dev, "qspi"); -	if (IS_ERR(tqspi->clk)) { -		ret = PTR_ERR(tqspi->clk); -		dev_err(&pdev->dev, "failed to get clock: %d\n", ret); -		return ret; -	} +	if (!has_acpi_companion(tqspi->dev)) { +		tqspi->clk = devm_clk_get(&pdev->dev, "qspi"); +		if (IS_ERR(tqspi->clk)) { +			ret = PTR_ERR(tqspi->clk); +			dev_err(&pdev->dev, "failed to get clock: %d\n", ret); +			return ret; +		} -	tqspi->rst = devm_reset_control_get_exclusive(&pdev->dev, NULL); -	if (IS_ERR(tqspi->rst)) { -		ret = PTR_ERR(tqspi->rst); -		dev_err(&pdev->dev, "failed to get reset control: %d\n", ret); -		return ret;  	}  	tqspi->max_buf_size = QSPI_FIFO_DEPTH << 2; @@ -1277,9 +1548,8 @@ static int tegra_qspi_probe(struct platform_device *pdev)  		goto exit_pm_disable;  	} -	reset_control_assert(tqspi->rst); -	udelay(2); -	reset_control_deassert(tqspi->rst); +	if (device_reset(tqspi->dev) < 0) +		dev_warn_once(tqspi->dev, "device reset failed\n");  	tqspi->def_command1_reg = QSPI_M_S | QSPI_CS_SW_HW |  QSPI_CS_SW_VAL;  	tegra_qspi_writel(tqspi, tqspi->def_command1_reg, QSPI_COMMAND1); @@ -1358,6 +1628,9 @@ static int __maybe_unused tegra_qspi_runtime_suspend(struct device *dev)  	struct spi_master *master = dev_get_drvdata(dev);  	struct tegra_qspi *tqspi = spi_master_get_devdata(master); +	/* Runtime pm disabled with ACPI */ +	if (has_acpi_companion(tqspi->dev)) +		return 0;  	/* flush all write which are in PPSB queue by reading back */  	tegra_qspi_readl(tqspi, QSPI_COMMAND1); @@ -1372,6 +1645,9 @@ static int __maybe_unused tegra_qspi_runtime_resume(struct device *dev)  	struct tegra_qspi *tqspi = spi_master_get_devdata(master);  	int ret; +	/* Runtime pm disabled with ACPI */ +	if (has_acpi_companion(tqspi->dev)) +		return 0;  	ret = clk_prepare_enable(tqspi->clk);  	if (ret < 0)  		dev_err(tqspi->dev, "failed to enable clock: %d\n", ret); @@ -1389,6 +1665,7 @@ static struct platform_driver tegra_qspi_driver = {  		.name		= "tegra-qspi",  		.pm		= &tegra_qspi_pm_ops,  		.of_match_table	= tegra_qspi_of_match, +		.acpi_match_table = ACPI_PTR(tegra_qspi_acpi_match),  	},  	.probe =	tegra_qspi_probe,  	.remove =	tegra_qspi_remove, diff --git a/drivers/spi/spi-tle62x0.c b/drivers/spi/spi-tle62x0.c index f8ad0709d015..a565352f6381 100644 --- a/drivers/spi/spi-tle62x0.c +++ b/drivers/spi/spi-tle62x0.c @@ -288,7 +288,7 @@ static int tle62x0_probe(struct spi_device *spi)  	return ret;  } -static int tle62x0_remove(struct spi_device *spi) +static void tle62x0_remove(struct spi_device *spi)  {  	struct tle62x0_state *st = spi_get_drvdata(spi);  	int ptr; @@ -298,7 +298,6 @@ static int tle62x0_remove(struct spi_device *spi)  	device_remove_file(&spi->dev, &dev_attr_status_show);  	kfree(st); -	return 0;  }  static struct spi_driver tle62x0_driver = { diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index 8c4615b76339..dfaa1d79a78b 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -103,6 +103,7 @@  static int use_dma = 1;  struct pch_spi_dma_ctrl { +	struct pci_dev		*dma_dev;  	struct dma_async_tx_descriptor	*desc_tx;  	struct dma_async_tx_descriptor	*desc_rx;  	struct pch_dma_slave		param_tx; @@ -876,8 +877,7 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)  	if (!chan) {  		dev_err(&data->master->dev,  			"ERROR: dma_request_channel FAILS(Tx)\n"); -		data->use_dma = 0; -		return; +		goto out;  	}  	dma->chan_tx = chan; @@ -893,10 +893,15 @@ static void pch_spi_request_dma(struct pch_spi_data *data, int bpw)  			"ERROR: dma_request_channel FAILS(Rx)\n");  		dma_release_channel(dma->chan_tx);  		dma->chan_tx = NULL; -		data->use_dma = 0; -		return; +		goto out;  	}  	dma->chan_rx = chan; + +	dma->dma_dev = dma_dev; +	return; +out: +	pci_dev_put(dma_dev); +	data->use_dma = 0;  }  static void pch_spi_release_dma(struct pch_spi_data *data) @@ -912,6 +917,8 @@ static void pch_spi_release_dma(struct pch_spi_data *data)  		dma_release_channel(dma->chan_rx);  		dma->chan_rx = NULL;  	} + +	pci_dev_put(dma->dma_dev);  }  static void pch_spi_handle_dma(struct pch_spi_data *data, int *bpw) diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c index 328b6559bb19..2b5afae8ff7f 100644 --- a/drivers/spi/spi-zynqmp-gqspi.c +++ b/drivers/spi/spi-zynqmp-gqspi.c @@ -1172,7 +1172,10 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)  		goto clk_dis_all;  	} -	dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); +	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(44)); +	if (ret) +		goto clk_dis_all; +  	ctlr->bits_per_word_mask = SPI_BPW_MASK(8);  	ctlr->num_chipselect = GQSPI_DEFAULT_NUM_CS;  	ctlr->mem_ops = &zynqmp_qspi_mem_ops; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d96082dc3340..c4dd1200fe99 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -18,7 +18,6 @@  #include <linux/mod_devicetable.h>  #include <linux/spi/spi.h>  #include <linux/spi/spi-mem.h> -#include <linux/of_gpio.h>  #include <linux/gpio/consumer.h>  #include <linux/pm_runtime.h>  #include <linux/pm_domain.h> @@ -144,7 +143,7 @@ static ssize_t spi_statistics_##name##_show(struct spi_statistics *stat, \  	unsigned long flags;						\  	ssize_t len;							\  	spin_lock_irqsave(&stat->lock, flags);				\ -	len = sprintf(buf, format_string, stat->field);			\ +	len = sysfs_emit(buf, format_string "\n", stat->field);		\  	spin_unlock_irqrestore(&stat->lock, flags);			\  	return len;							\  }									\ @@ -404,15 +403,8 @@ static void spi_remove(struct device *dev)  {  	const struct spi_driver		*sdrv = to_spi_driver(dev->driver); -	if (sdrv->remove) { -		int ret; - -		ret = sdrv->remove(to_spi_device(dev)); -		if (ret) -			dev_warn(dev, -				 "Failed to unbind driver (%pe), ignoring\n", -				 ERR_PTR(ret)); -	} +	if (sdrv->remove) +		sdrv->remove(to_spi_device(dev));  	dev_pm_domain_detach(dev, true);  } @@ -532,7 +524,7 @@ static DEFINE_MUTEX(board_lock);   *   * Return: a pointer to the new device, or NULL.   */ -static struct spi_device *spi_alloc_device(struct spi_controller *ctlr) +struct spi_device *spi_alloc_device(struct spi_controller *ctlr)  {  	struct spi_device	*spi; @@ -549,7 +541,6 @@ static struct spi_device *spi_alloc_device(struct spi_controller *ctlr)  	spi->dev.parent = &ctlr->dev;  	spi->dev.bus = &spi_bus_type;  	spi->dev.release = spidev_release; -	spi->cs_gpio = -ENOENT;  	spi->mode = ctlr->buswidth_override_bits;  	spin_lock_init(&spi->statistics.lock); @@ -557,6 +548,7 @@ static struct spi_device *spi_alloc_device(struct spi_controller *ctlr)  	device_initialize(&spi->dev);  	return spi;  } +EXPORT_SYMBOL_GPL(spi_alloc_device);  static void spi_dev_set_name(struct spi_device *spi)  { @@ -612,11 +604,8 @@ static int __spi_add_device(struct spi_device *spi)  		return -ENODEV;  	} -	/* Descriptors take precedence */  	if (ctlr->cs_gpiods)  		spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select]; -	else if (ctlr->cs_gpios) -		spi->cs_gpio = ctlr->cs_gpios[spi->chip_select];  	/*  	 * Drivers may modify this initial i/o setup, but will @@ -652,7 +641,7 @@ static int __spi_add_device(struct spi_device *spi)   *   * Return: 0 on success; negative errno on failure   */ -static int spi_add_device(struct spi_device *spi) +int spi_add_device(struct spi_device *spi)  {  	struct spi_controller *ctlr = spi->controller;  	struct device *dev = ctlr->dev.parent; @@ -673,6 +662,7 @@ static int spi_add_device(struct spi_device *spi)  	mutex_unlock(&ctlr->add_lock);  	return status;  } +EXPORT_SYMBOL_GPL(spi_add_device);  static int spi_add_device_locked(struct spi_device *spi)  { @@ -936,48 +926,40 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)  	 * Avoid calling into the driver (or doing delays) if the chip select  	 * isn't actually changing from the last time this was called.  	 */ -	if (!force && (spi->controller->last_cs_enable == enable) && +	if (!force && ((enable && spi->controller->last_cs == spi->chip_select) || +				(!enable && spi->controller->last_cs != spi->chip_select)) &&  	    (spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH)))  		return;  	trace_spi_set_cs(spi, activate); -	spi->controller->last_cs_enable = enable; +	spi->controller->last_cs = enable ? spi->chip_select : -1;  	spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH; -	if ((spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || -	    !spi->controller->set_cs_timing) && !activate) { +	if ((spi->cs_gpiod || !spi->controller->set_cs_timing) && !activate) {  		spi_delay_exec(&spi->cs_hold, NULL);  	}  	if (spi->mode & SPI_CS_HIGH)  		enable = !enable; -	if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) { +	if (spi->cs_gpiod) {  		if (!(spi->mode & SPI_NO_CS)) { -			if (spi->cs_gpiod) { -				/* -				 * Historically ACPI has no means of the GPIO polarity and -				 * thus the SPISerialBus() resource defines it on the per-chip -				 * basis. In order to avoid a chain of negations, the GPIO -				 * polarity is considered being Active High. Even for the cases -				 * when _DSD() is involved (in the updated versions of ACPI) -				 * the GPIO CS polarity must be defined Active High to avoid -				 * ambiguity. That's why we use enable, that takes SPI_CS_HIGH -				 * into account. -				 */ -				if (has_acpi_companion(&spi->dev)) -					gpiod_set_value_cansleep(spi->cs_gpiod, !enable); -				else -					/* Polarity handled by GPIO library */ -					gpiod_set_value_cansleep(spi->cs_gpiod, activate); -			} else { -				/* -				 * Invert the enable line, as active low is -				 * default for SPI. -				 */ -				gpio_set_value_cansleep(spi->cs_gpio, !enable); -			} +			/* +			 * Historically ACPI has no means of the GPIO polarity and +			 * thus the SPISerialBus() resource defines it on the per-chip +			 * basis. In order to avoid a chain of negations, the GPIO +			 * polarity is considered being Active High. Even for the cases +			 * when _DSD() is involved (in the updated versions of ACPI) +			 * the GPIO CS polarity must be defined Active High to avoid +			 * ambiguity. That's why we use enable, that takes SPI_CS_HIGH +			 * into account. +			 */ +			if (has_acpi_companion(&spi->dev)) +				gpiod_set_value_cansleep(spi->cs_gpiod, !enable); +			else +				/* Polarity handled by GPIO library */ +				gpiod_set_value_cansleep(spi->cs_gpiod, activate);  		}  		/* Some SPI masters need both GPIO CS & slave_select */  		if ((spi->controller->flags & SPI_MASTER_GPIO_SS) && @@ -987,8 +969,7 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)  		spi->controller->set_cs(spi, !enable);  	} -	if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || -	    !spi->controller->set_cs_timing) { +	if (spi->cs_gpiod || !spi->controller->set_cs_timing) {  		if (activate)  			spi_delay_exec(&spi->cs_setup, NULL);  		else @@ -1019,10 +1000,10 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev,  	int i, ret;  	if (vmalloced_buf || kmap_buf) { -		desc_len = min_t(unsigned int, max_seg_size, PAGE_SIZE); +		desc_len = min_t(unsigned long, max_seg_size, PAGE_SIZE);  		sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);  	} else if (virt_addr_valid(buf)) { -		desc_len = min_t(unsigned int, max_seg_size, ctlr->max_dma_len); +		desc_len = min_t(size_t, max_seg_size, ctlr->max_dma_len);  		sgs = DIV_ROUND_UP(len, desc_len);  	} else {  		return -EINVAL; @@ -2318,8 +2299,50 @@ struct acpi_spi_lookup {  	int			irq;  	u8			bits_per_word;  	u8			chip_select; +	int			n; +	int			index;  }; +static int acpi_spi_count(struct acpi_resource *ares, void *data) +{ +	struct acpi_resource_spi_serialbus *sb; +	int *count = data; + +	if (ares->type != ACPI_RESOURCE_TYPE_SERIAL_BUS) +		return 1; + +	sb = &ares->data.spi_serial_bus; +	if (sb->type != ACPI_RESOURCE_SERIAL_TYPE_SPI) +		return 1; + +	*count = *count + 1; + +	return 1; +} + +/** + * acpi_spi_count_resources - Count the number of SpiSerialBus resources + * @adev:	ACPI device + * + * Returns the number of SpiSerialBus resources in the ACPI-device's + * resource-list; or a negative error code. + */ +int acpi_spi_count_resources(struct acpi_device *adev) +{ +	LIST_HEAD(r); +	int count = 0; +	int ret; + +	ret = acpi_dev_get_resources(adev, &r, acpi_spi_count, &count); +	if (ret < 0) +		return ret; + +	acpi_dev_free_resource_list(&r); + +	return count; +} +EXPORT_SYMBOL_GPL(acpi_spi_count_resources); +  static void acpi_spi_parse_apple_properties(struct acpi_device *dev,  					    struct acpi_spi_lookup *lookup)  { @@ -2349,6 +2372,8 @@ static void acpi_spi_parse_apple_properties(struct acpi_device *dev,  		lookup->mode |= SPI_CPHA;  } +static struct spi_controller *acpi_spi_find_controller_by_adev(struct acpi_device *adev); +  static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)  {  	struct acpi_spi_lookup *lookup = data; @@ -2362,14 +2387,35 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)  		sb = &ares->data.spi_serial_bus;  		if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) { +			if (lookup->index != -1 && lookup->n++ != lookup->index) +				return 1; + +			if (lookup->index == -1 && !ctlr) +				return -ENODEV; +  			status = acpi_get_handle(NULL,  						 sb->resource_source.string_ptr,  						 &parent_handle); -			if (ACPI_FAILURE(status) || -			    ACPI_HANDLE(ctlr->dev.parent) != parent_handle) +			if (ACPI_FAILURE(status))  				return -ENODEV; +			if (ctlr) { +				if (ACPI_HANDLE(ctlr->dev.parent) != parent_handle) +					return -ENODEV; +			} else { +				struct acpi_device *adev; + +				if (acpi_bus_get_device(parent_handle, &adev)) +					return -ENODEV; + +				ctlr = acpi_spi_find_controller_by_adev(adev); +				if (!ctlr) +					return -ENODEV; + +				lookup->ctlr = ctlr; +			} +  			/*  			 * ACPI DeviceSelection numbering is handled by the  			 * host controller driver in Windows and can vary @@ -2408,8 +2454,25 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)  	return 1;  } -static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, -					    struct acpi_device *adev) +/** + * acpi_spi_device_alloc - Allocate a spi device, and fill it in with ACPI information + * @ctlr: controller to which the spi device belongs + * @adev: ACPI Device for the spi device + * @index: Index of the spi resource inside the ACPI Node + * + * This should be used to allocate a new spi device from and ACPI Node. + * The caller is responsible for calling spi_add_device to register the spi device. + * + * If ctlr is set to NULL, the Controller for the spi device will be looked up + * using the resource. + * If index is set to -1, index is not used. + * Note: If index is -1, ctlr must be set. + * + * Return: a pointer to the new device, or ERR_PTR on error. + */ +struct spi_device *acpi_spi_device_alloc(struct spi_controller *ctlr, +					 struct acpi_device *adev, +					 int index)  {  	acpi_handle parent_handle = NULL;  	struct list_head resource_list; @@ -2417,12 +2480,13 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,  	struct spi_device *spi;  	int ret; -	if (acpi_bus_get_status(adev) || !adev->status.present || -	    acpi_device_enumerated(adev)) -		return AE_OK; +	if (!ctlr && index == -1) +		return ERR_PTR(-EINVAL);  	lookup.ctlr		= ctlr;  	lookup.irq		= -1; +	lookup.index		= index; +	lookup.n		= 0;  	INIT_LIST_HEAD(&resource_list);  	ret = acpi_dev_get_resources(adev, &resource_list, @@ -2431,26 +2495,25 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,  	if (ret < 0)  		/* found SPI in _CRS but it points to another controller */ -		return AE_OK; +		return ERR_PTR(-ENODEV);  	if (!lookup.max_speed_hz &&  	    ACPI_SUCCESS(acpi_get_parent(adev->handle, &parent_handle)) && -	    ACPI_HANDLE(ctlr->dev.parent) == parent_handle) { +	    ACPI_HANDLE(lookup.ctlr->dev.parent) == parent_handle) {  		/* Apple does not use _CRS but nested devices for SPI slaves */  		acpi_spi_parse_apple_properties(adev, &lookup);  	}  	if (!lookup.max_speed_hz) -		return AE_OK; +		return ERR_PTR(-ENODEV); -	spi = spi_alloc_device(ctlr); +	spi = spi_alloc_device(lookup.ctlr);  	if (!spi) { -		dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n", +		dev_err(&lookup.ctlr->dev, "failed to allocate SPI device for %s\n",  			dev_name(&adev->dev)); -		return AE_NO_MEMORY; +		return ERR_PTR(-ENOMEM);  	} -  	ACPI_COMPANION_SET(&spi->dev, adev);  	spi->max_speed_hz	= lookup.max_speed_hz;  	spi->mode		|= lookup.mode; @@ -2458,6 +2521,27 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,  	spi->bits_per_word	= lookup.bits_per_word;  	spi->chip_select	= lookup.chip_select; +	return spi; +} +EXPORT_SYMBOL_GPL(acpi_spi_device_alloc); + +static acpi_status acpi_register_spi_device(struct spi_controller *ctlr, +					    struct acpi_device *adev) +{ +	struct spi_device *spi; + +	if (acpi_bus_get_status(adev) || !adev->status.present || +	    acpi_device_enumerated(adev)) +		return AE_OK; + +	spi = acpi_spi_device_alloc(ctlr, adev, -1); +	if (IS_ERR(spi)) { +		if (PTR_ERR(spi) == -ENOMEM) +			return AE_NO_MEMORY; +		else +			return AE_OK; +	} +  	acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias,  			  sizeof(spi->modalias)); @@ -2480,10 +2564,10 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,  static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,  				       void *data, void **return_value)  { +	struct acpi_device *adev = acpi_fetch_acpi_dev(handle);  	struct spi_controller *ctlr = data; -	struct acpi_device *adev; -	if (acpi_bus_get_device(handle, &adev)) +	if (!adev)  		return AE_OK;  	return acpi_register_spi_device(ctlr, adev); @@ -2729,46 +2813,6 @@ struct spi_controller *__devm_spi_alloc_controller(struct device *dev,  }  EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller); -#ifdef CONFIG_OF -static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) -{ -	int nb, i, *cs; -	struct device_node *np = ctlr->dev.of_node; - -	if (!np) -		return 0; - -	nb = of_gpio_named_count(np, "cs-gpios"); -	ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect); - -	/* Return error only for an incorrectly formed cs-gpios property */ -	if (nb == 0 || nb == -ENOENT) -		return 0; -	else if (nb < 0) -		return nb; - -	cs = devm_kcalloc(&ctlr->dev, ctlr->num_chipselect, sizeof(int), -			  GFP_KERNEL); -	ctlr->cs_gpios = cs; - -	if (!ctlr->cs_gpios) -		return -ENOMEM; - -	for (i = 0; i < ctlr->num_chipselect; i++) -		cs[i] = -ENOENT; - -	for (i = 0; i < nb; i++) -		cs[i] = of_get_named_gpio(np, "cs-gpios", i); - -	return 0; -} -#else -static int of_spi_get_gpio_numbers(struct spi_controller *ctlr) -{ -	return 0; -} -#endif -  /**   * spi_get_gpio_descs() - grab chip select GPIOs for the master   * @ctlr: The SPI master to grab GPIO descriptors for @@ -2953,22 +2997,15 @@ int spi_register_controller(struct spi_controller *ctlr)  	 */  	dev_set_name(&ctlr->dev, "spi%u", ctlr->bus_num); -	if (!spi_controller_is_slave(ctlr)) { -		if (ctlr->use_gpio_descriptors) { -			status = spi_get_gpio_descs(ctlr); -			if (status) -				goto free_bus_id; -			/* -			 * A controller using GPIO descriptors always -			 * supports SPI_CS_HIGH if need be. -			 */ -			ctlr->mode_bits |= SPI_CS_HIGH; -		} else { -			/* Legacy code path for GPIOs from DT */ -			status = of_spi_get_gpio_numbers(ctlr); -			if (status) -				goto free_bus_id; -		} +	if (!spi_controller_is_slave(ctlr) && ctlr->use_gpio_descriptors) { +		status = spi_get_gpio_descs(ctlr); +		if (status) +			goto free_bus_id; +		/* +		 * A controller using GPIO descriptors always +		 * supports SPI_CS_HIGH if need be. +		 */ +		ctlr->mode_bits |= SPI_CS_HIGH;  	}  	/* @@ -2980,6 +3017,9 @@ int spi_register_controller(struct spi_controller *ctlr)  		goto free_bus_id;  	} +	/* setting last_cs to -1 means no chip selected */ +	ctlr->last_cs = -1; +  	status = device_add(&ctlr->dev);  	if (status < 0)  		goto free_bus_id; @@ -3457,12 +3497,6 @@ int spi_setup(struct spi_device *spi)  	 */  	bad_bits = spi->mode & ~(spi->controller->mode_bits | SPI_CS_WORD |  				 SPI_NO_TX | SPI_NO_RX); -	/* -	 * Nothing prevents from working with active-high CS in case if it -	 * is driven by GPIO. -	 */ -	if (gpio_is_valid(spi->cs_gpio)) -		bad_bits &= ~SPI_CS_HIGH;  	ugly_bits = bad_bits &  		    (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL |  		     SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL); @@ -3588,8 +3622,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)  	 * cs_change is set for each transfer.  	 */  	if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) || -					  spi->cs_gpiod || -					  gpio_is_valid(spi->cs_gpio))) { +					  spi->cs_gpiod)) {  		size_t maxsize;  		int ret; diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index a5cceca8b82b..53a551714265 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -453,22 +453,29 @@ spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  				dev_dbg(&spi->dev, "%d bits per word\n", tmp);  		}  		break; -	case SPI_IOC_WR_MAX_SPEED_HZ: +	case SPI_IOC_WR_MAX_SPEED_HZ: { +		u32 save; +  		retval = get_user(tmp, (__u32 __user *)arg); -		if (retval == 0) { -			u32	save = spi->max_speed_hz; +		if (retval) +			break; +		if (tmp == 0) { +			retval = -EINVAL; +			break; +		} -			spi->max_speed_hz = tmp; -			retval = spi_setup(spi); -			if (retval == 0) { -				spidev->speed_hz = tmp; -				dev_dbg(&spi->dev, "%d Hz (max)\n", -					spidev->speed_hz); -			} -			spi->max_speed_hz = save; +		save = spi->max_speed_hz; + +		spi->max_speed_hz = tmp; +		retval = spi_setup(spi); +		if (retval == 0) { +			spidev->speed_hz = tmp; +			dev_dbg(&spi->dev, "%d Hz (max)\n", spidev->speed_hz);  		} -		break; +		spi->max_speed_hz = save; +		break; +	}  	default:  		/* segmented and/or full-duplex I/O request */  		/* Check message and copy into scratch area */ @@ -803,7 +810,7 @@ static int spidev_probe(struct spi_device *spi)  	return status;  } -static int spidev_remove(struct spi_device *spi) +static void spidev_remove(struct spi_device *spi)  {  	struct spidev_data	*spidev = spi_get_drvdata(spi); @@ -820,8 +827,6 @@ static int spidev_remove(struct spi_device *spi)  	if (spidev->users == 0)  		kfree(spidev);  	mutex_unlock(&device_list_lock); - -	return 0;  }  static struct spi_driver spidev_spi_driver = { diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h index 55677efc0138..b68f5f9b7c78 100644 --- a/drivers/staging/fbtft/fbtft.h +++ b/drivers/staging/fbtft/fbtft.h @@ -272,21 +272,39 @@ void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);  void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);  void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...); +#define FBTFT_DT_TABLE(_compatible)						\ +static const struct of_device_id dt_ids[] = {					\ +	{ .compatible = _compatible },						\ +	{},									\ +};										\ +MODULE_DEVICE_TABLE(of, dt_ids); + +#define FBTFT_SPI_DRIVER(_name, _compatible, _display, _spi_ids)		\ +										\ +static int fbtft_driver_probe_spi(struct spi_device *spi)			\ +{										\ +	return fbtft_probe_common(_display, spi, NULL);				\ +}										\ +										\ +static void fbtft_driver_remove_spi(struct spi_device *spi)			\ +{										\ +	struct fb_info *info = spi_get_drvdata(spi);				\ +										\ +	fbtft_remove_common(&spi->dev, info);					\ +}										\ +										\ +static struct spi_driver fbtft_driver_spi_driver = {				\ +	.driver = {								\ +		.name = _name,							\ +		.of_match_table = dt_ids,					\ +	},									\ +	.id_table = _spi_ids,							\ +	.probe = fbtft_driver_probe_spi,					\ +	.remove = fbtft_driver_remove_spi,					\ +}; +  #define FBTFT_REGISTER_DRIVER(_name, _compatible, _display)                \  									   \ -static int fbtft_driver_probe_spi(struct spi_device *spi)                  \ -{                                                                          \ -	return fbtft_probe_common(_display, spi, NULL);                    \ -}                                                                          \ -									   \ -static int fbtft_driver_remove_spi(struct spi_device *spi)                 \ -{                                                                          \ -	struct fb_info *info = spi_get_drvdata(spi);                       \ -									   \ -	fbtft_remove_common(&spi->dev, info);                              \ -	return 0;                                                          \ -}                                                                          \ -									   \  static int fbtft_driver_probe_pdev(struct platform_device *pdev)           \  {                                                                          \  	return fbtft_probe_common(_display, NULL, pdev);                   \ @@ -300,22 +318,9 @@ static int fbtft_driver_remove_pdev(struct platform_device *pdev)          \  	return 0;                                                          \  }                                                                          \  									   \ -static const struct of_device_id dt_ids[] = {                              \ -	{ .compatible = _compatible },                                     \ -	{},                                                                \ -};                                                                         \ -									   \ -MODULE_DEVICE_TABLE(of, dt_ids);                                           \ +FBTFT_DT_TABLE(_compatible)						   \  									   \ -									   \ -static struct spi_driver fbtft_driver_spi_driver = {                       \ -	.driver = {                                                        \ -		.name   = _name,                                           \ -		.of_match_table = dt_ids,                                  \ -	},                                                                 \ -	.probe  = fbtft_driver_probe_spi,                                  \ -	.remove = fbtft_driver_remove_spi,                                 \ -};                                                                         \ +FBTFT_SPI_DRIVER(_name, _compatible, _display, NULL)			   \  									   \  static struct platform_driver fbtft_driver_platform_driver = {             \  	.driver = {                                                        \ @@ -351,42 +356,15 @@ module_exit(fbtft_driver_module_exit);  #define FBTFT_REGISTER_SPI_DRIVER(_name, _comp_vend, _comp_dev, _display)	\  										\ -static int fbtft_driver_probe_spi(struct spi_device *spi)			\ -{										\ -	return fbtft_probe_common(_display, spi, NULL);				\ -}										\ -										\ -static int fbtft_driver_remove_spi(struct spi_device *spi)			\ -{										\ -	struct fb_info *info = spi_get_drvdata(spi);				\ -										\ -	fbtft_remove_common(&spi->dev, info);					\ -	return 0;								\ -}										\ -										\ -static const struct of_device_id dt_ids[] = {					\ -	{ .compatible = _comp_vend "," _comp_dev },				\ -	{},									\ -};										\ -										\ -MODULE_DEVICE_TABLE(of, dt_ids);						\ +FBTFT_DT_TABLE(_comp_vend "," _comp_dev)					\  										\  static const struct spi_device_id spi_ids[] = {					\  	{ .name = _comp_dev },							\  	{},									\  };										\ -										\  MODULE_DEVICE_TABLE(spi, spi_ids);						\  										\ -static struct spi_driver fbtft_driver_spi_driver = {				\ -	.driver = {								\ -		.name  = _name,							\ -		.of_match_table = dt_ids,					\ -	},									\ -	.id_table = spi_ids,							\ -	.probe  = fbtft_driver_probe_spi,					\ -	.remove = fbtft_driver_remove_spi,					\ -};										\ +FBTFT_SPI_DRIVER(_name, _comp_vend "," _comp_dev, _display, spi_ids)		\  										\  module_spi_driver(fbtft_driver_spi_driver); diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index 68c09fa016ed..1d31c35875e3 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c @@ -1264,7 +1264,7 @@ RX_failed:  	return retval;  } -static int pi433_remove(struct spi_device *spi) +static void pi433_remove(struct spi_device *spi)  {  	struct pi433_device	*device = spi_get_drvdata(spi); @@ -1284,8 +1284,6 @@ static int pi433_remove(struct spi_device *spi)  	kfree(device->rx_buffer);  	kfree(device); - -	return 0;  }  static const struct of_device_id pi433_dt_ids[] = { diff --git a/drivers/staging/wfx/bus_spi.c b/drivers/staging/wfx/bus_spi.c index 55ffcd7c42e2..fa0ff66a457d 100644 --- a/drivers/staging/wfx/bus_spi.c +++ b/drivers/staging/wfx/bus_spi.c @@ -232,12 +232,11 @@ static int wfx_spi_probe(struct spi_device *func)  	return wfx_probe(bus->core);  } -static int wfx_spi_remove(struct spi_device *func) +static void wfx_spi_remove(struct spi_device *func)  {  	struct wfx_spi_priv *bus = spi_get_drvdata(func);  	wfx_release(bus->core); -	return 0;  }  /* For dynamic driver binding, kernel does not use OF to match driver. It only diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 3c92d4e01488..516cff362434 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c @@ -805,7 +805,7 @@ static int max3100_probe(struct spi_device *spi)  	return 0;  } -static int max3100_remove(struct spi_device *spi) +static void max3100_remove(struct spi_device *spi)  {  	struct max3100_port *s = spi_get_drvdata(spi);  	int i; @@ -828,13 +828,12 @@ static int max3100_remove(struct spi_device *spi)  	for (i = 0; i < MAX_MAX3100; i++)  		if (max3100s[i]) {  			mutex_unlock(&max3100s_lock); -			return 0; +			return;  		}  	pr_debug("removing max3100 driver\n");  	uart_unregister_driver(&max3100_uart_driver);  	mutex_unlock(&max3100s_lock); -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index dde0824b2fa5..3112b4a05448 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1487,10 +1487,9 @@ static int max310x_spi_probe(struct spi_device *spi)  	return max310x_probe(&spi->dev, devtype, regmap, spi->irq);  } -static int max310x_spi_remove(struct spi_device *spi) +static void max310x_spi_remove(struct spi_device *spi)  {  	max310x_remove(&spi->dev); -	return 0;  }  static const struct spi_device_id max310x_id_table[] = { diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 38d1c0748533..3a6c68e19c80 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1443,11 +1443,9 @@ static int sc16is7xx_spi_probe(struct spi_device *spi)  	return sc16is7xx_probe(&spi->dev, devtype, regmap, spi->irq);  } -static int sc16is7xx_spi_remove(struct spi_device *spi) +static void sc16is7xx_spi_remove(struct spi_device *spi)  {  	sc16is7xx_remove(&spi->dev); - -	return 0;  }  static const struct spi_device_id sc16is7xx_spi_id_table[] = { diff --git a/drivers/usb/gadget/udc/max3420_udc.c b/drivers/usb/gadget/udc/max3420_udc.c index d2a2b20cc1ad..7d9bd16190c0 100644 --- a/drivers/usb/gadget/udc/max3420_udc.c +++ b/drivers/usb/gadget/udc/max3420_udc.c @@ -1292,7 +1292,7 @@ del_gadget:  	return err;  } -static int max3420_remove(struct spi_device *spi) +static void max3420_remove(struct spi_device *spi)  {  	struct max3420_udc *udc = spi_get_drvdata(spi);  	unsigned long flags; @@ -1304,8 +1304,6 @@ static int max3420_remove(struct spi_device *spi)  	kthread_stop(udc->thread_task);  	spin_unlock_irqrestore(&udc->lock, flags); - -	return 0;  }  static const struct of_device_id max3420_udc_of_match[] = { diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index 30de85a707fe..99a5523a79fb 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1926,7 +1926,7 @@ error:  	return retval;  } -static int +static void  max3421_remove(struct spi_device *spi)  {  	struct max3421_hcd *max3421_hcd; @@ -1947,7 +1947,6 @@ max3421_remove(struct spi_device *spi)  	free_irq(spi->irq, hcd);  	usb_put_hcd(hcd); -	return 0;  }  static const struct of_device_id max3421_of_match_table[] = { diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index 8a4361e95a11..522dd81110b8 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c @@ -506,12 +506,11 @@ static int ams369fg06_probe(struct spi_device *spi)  	return 0;  } -static int ams369fg06_remove(struct spi_device *spi) +static void ams369fg06_remove(struct spi_device *spi)  {  	struct ams369fg06 *lcd = spi_get_drvdata(spi);  	ams369fg06_power(lcd, FB_BLANK_POWERDOWN); -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index 33f5d80495e6..0a57033ae31d 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -542,7 +542,7 @@ static int corgi_lcd_probe(struct spi_device *spi)  	return 0;  } -static int corgi_lcd_remove(struct spi_device *spi) +static void corgi_lcd_remove(struct spi_device *spi)  {  	struct corgi_lcd *lcd = spi_get_drvdata(spi); @@ -550,7 +550,6 @@ static int corgi_lcd_remove(struct spi_device *spi)  	lcd->bl_dev->props.brightness = 0;  	backlight_update_status(lcd->bl_dev);  	corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); -	return 0;  }  static struct spi_driver corgi_lcd_driver = { diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index 328aba9cddad..e7b6bd827986 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -526,10 +526,9 @@ static int ili922x_probe(struct spi_device *spi)  	return 0;  } -static int ili922x_remove(struct spi_device *spi) +static void ili922x_remove(struct spi_device *spi)  {  	ili922x_poweroff(spi); -	return 0;  }  static struct spi_driver ili922x_driver = { diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index 46f97d1c3d21..cc763cf15f53 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c @@ -223,12 +223,11 @@ static int l4f00242t03_probe(struct spi_device *spi)  	return 0;  } -static int l4f00242t03_remove(struct spi_device *spi) +static void l4f00242t03_remove(struct spi_device *spi)  {  	struct l4f00242t03_priv *priv = spi_get_drvdata(spi);  	l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); -	return 0;  }  static void l4f00242t03_shutdown(struct spi_device *spi) diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index f949b66dce1b..5c46df8022bf 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -364,12 +364,11 @@ static int lms501kf03_probe(struct spi_device *spi)  	return 0;  } -static int lms501kf03_remove(struct spi_device *spi) +static void lms501kf03_remove(struct spi_device *spi)  {  	struct lms501kf03 *lcd = spi_get_drvdata(spi);  	lms501kf03_power(lcd, FB_BLANK_POWERDOWN); -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index 5cbf621e48bd..b6d373af6e3f 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c @@ -255,12 +255,11 @@ static int ltv350qv_probe(struct spi_device *spi)  	return 0;  } -static int ltv350qv_remove(struct spi_device *spi) +static void ltv350qv_remove(struct spi_device *spi)  {  	struct ltv350qv *lcd = spi_get_drvdata(spi);  	ltv350qv_power(lcd, FB_BLANK_POWERDOWN); -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index 0de044dcafd5..fc6fbaf85594 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -397,12 +397,11 @@ static int tdo24m_probe(struct spi_device *spi)  	return 0;  } -static int tdo24m_remove(struct spi_device *spi) +static void tdo24m_remove(struct spi_device *spi)  {  	struct tdo24m *lcd = spi_get_drvdata(spi);  	tdo24m_power(lcd, FB_BLANK_POWERDOWN); -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 38765544345b..23d6c6bf0f54 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -232,15 +232,13 @@ err_register:  	return ret;  } -static int tosa_lcd_remove(struct spi_device *spi) +static void tosa_lcd_remove(struct spi_device *spi)  {  	struct tosa_lcd_data *data = spi_get_drvdata(spi);  	i2c_unregister_device(data->i2c);  	tosa_lcd_tg_off(data); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index 3567b45f9ba9..bfc1913e8b55 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c @@ -233,11 +233,9 @@ static int vgg2432a4_probe(struct spi_device *spi)  	return 0;  } -static int vgg2432a4_remove(struct spi_device *spi) +static void vgg2432a4_remove(struct spi_device *spi)  {  	ili9320_remove(spi_get_drvdata(spi)); - -	return 0;  }  static void vgg2432a4_shutdown(struct spi_device *spi) diff --git a/drivers/video/fbdev/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c index a75ae0c9b14c..03cff39d392d 100644 --- a/drivers/video/fbdev/omap/lcd_mipid.c +++ b/drivers/video/fbdev/omap/lcd_mipid.c @@ -570,14 +570,12 @@ static int mipid_spi_probe(struct spi_device *spi)  	return 0;  } -static int mipid_spi_remove(struct spi_device *spi) +static void mipid_spi_remove(struct spi_device *spi)  {  	struct mipid_device *md = dev_get_drvdata(&spi->dev);  	mipid_disable(&md->panel);  	kfree(md); - -	return 0;  }  static struct spi_driver mipid_spi_driver = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c index 1bec7a4422e8..aab67721263d 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-lgphilips-lb035q02.c @@ -316,7 +316,7 @@ err_gpio:  	return r;  } -static int lb035q02_panel_spi_remove(struct spi_device *spi) +static void lb035q02_panel_spi_remove(struct spi_device *spi)  {  	struct panel_drv_data *ddata = spi_get_drvdata(spi);  	struct omap_dss_device *dssdev = &ddata->dssdev; @@ -328,8 +328,6 @@ static int lb035q02_panel_spi_remove(struct spi_device *spi)  	lb035q02_disconnect(dssdev);  	omap_dss_put_device(in); - -	return 0;  }  static const struct of_device_id lb035q02_of_match[] = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c index dff9ebbadfc0..be9910ff6e62 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-nec-nl8048hl11.c @@ -327,7 +327,7 @@ err_gpio:  	return r;  } -static int nec_8048_remove(struct spi_device *spi) +static void nec_8048_remove(struct spi_device *spi)  {  	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);  	struct omap_dss_device *dssdev = &ddata->dssdev; @@ -341,8 +341,6 @@ static int nec_8048_remove(struct spi_device *spi)  	nec_8048_disconnect(dssdev);  	omap_dss_put_device(in); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c index 8d8b5ff7d43c..a909b5385ca5 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c @@ -857,7 +857,7 @@ err_gpio:  	return r;  } -static int acx565akm_remove(struct spi_device *spi) +static void acx565akm_remove(struct spi_device *spi)  {  	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);  	struct omap_dss_device *dssdev = &ddata->dssdev; @@ -874,8 +874,6 @@ static int acx565akm_remove(struct spi_device *spi)  	acx565akm_disconnect(dssdev);  	omap_dss_put_device(in); - -	return 0;  }  static const struct of_device_id acx565akm_of_match[] = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c index 595ebd8bd5dc..3c0f887d3092 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td028ttec1.c @@ -425,7 +425,7 @@ err_reg:  	return r;  } -static int td028ttec1_panel_remove(struct spi_device *spi) +static void td028ttec1_panel_remove(struct spi_device *spi)  {  	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);  	struct omap_dss_device *dssdev = &ddata->dssdev; @@ -439,8 +439,6 @@ static int td028ttec1_panel_remove(struct spi_device *spi)  	td028ttec1_panel_disconnect(dssdev);  	omap_dss_put_device(in); - -	return 0;  }  static const struct of_device_id td028ttec1_of_match[] = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c index afac1d9445aa..58bbba7c037f 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c @@ -564,7 +564,7 @@ err_regulator:  	return r;  } -static int tpo_td043_remove(struct spi_device *spi) +static void tpo_td043_remove(struct spi_device *spi)  {  	struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);  	struct omap_dss_device *dssdev = &ddata->dssdev; @@ -580,8 +580,6 @@ static int tpo_td043_remove(struct spi_device *spi)  	omap_dss_put_device(in);  	sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group); - -	return 0;  }  #ifdef CONFIG_PM_SLEEP |