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 |