diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-20 08:15:23 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-09-20 08:15:23 -0700 |
| commit | bdab18633a302c82b5e5d5dbc4e38b0baf9c0837 (patch) | |
| tree | 0446500af9a76d4e8b2a72a0a41391ceede73a10 /drivers/mfd/altera-a10sr.c | |
| download | linux-stable-bdab18633a302c82b5e5d5dbc4e38b0baf9c0837.tar.gz linux-stable-bdab18633a302c82b5e5d5dbc4e38b0baf9c0837.zip | |
Merge tag 'locking-urgent-2026-09-20' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tipgrafted
Pull futex fix from Ingo Molnar:
- Also allocate a default private futex hash on vfork() as well, to
avoid races with (private) futex waiters (Peter Zijlstra)
* tag 'locking-urgent-2026-09-20' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
futex: Also allocate private hash on vfork()
Diffstat (limited to 'drivers/mfd/altera-a10sr.c')
| -rw-r--r-- | drivers/mfd/altera-a10sr.c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/drivers/mfd/altera-a10sr.c b/drivers/mfd/altera-a10sr.c new file mode 100644 index 000000000..9c0262228 --- /dev/null +++ b/drivers/mfd/altera-a10sr.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Altera Arria10 DevKit System Resource MFD Driver + * + * Author: Thor Thayer <tthayer@opensource.altera.com> + * + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved + * + * SPI access for Altera Arria10 MAX5 System Resource Chip + * + * Adapted from DA9052 + */ + +#include <linux/mfd/altera-a10sr.h> +#include <linux/mfd/core.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/spi/spi.h> + +static const struct mfd_cell altr_a10sr_subdev_info[] = { + { + .name = "altr_a10sr_gpio", + .of_compatible = "altr,a10sr-gpio", + }, + { + .name = "altr_a10sr_reset", + .of_compatible = "altr,a10sr-reset", + }, +}; + +static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_VERSION_READ: + case ALTR_A10SR_LED_REG: + case ALTR_A10SR_PBDSW_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_PWR_GOOD1_REG: + case ALTR_A10SR_PWR_GOOD2_REG: + case ALTR_A10SR_PWR_GOOD3_REG: + case ALTR_A10SR_FMCAB_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_USB_QSPI_REG: + case ALTR_A10SR_SFPA_REG: + case ALTR_A10SR_SFPB_REG: + case ALTR_A10SR_I2C_M_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +static bool altr_a10sr_reg_writeable(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_LED_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_FMCAB_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_USB_QSPI_REG: + case ALTR_A10SR_SFPA_REG: + case ALTR_A10SR_SFPB_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg) +{ + switch (reg) { + case ALTR_A10SR_PBDSW_REG: + case ALTR_A10SR_PBDSW_IRQ_REG: + case ALTR_A10SR_PWR_GOOD1_REG: + case ALTR_A10SR_PWR_GOOD2_REG: + case ALTR_A10SR_PWR_GOOD3_REG: + case ALTR_A10SR_HPS_RST_REG: + case ALTR_A10SR_I2C_M_REG: + case ALTR_A10SR_WARM_RST_REG: + case ALTR_A10SR_WR_KEY_REG: + case ALTR_A10SR_PMBUS_REG: + return true; + default: + return false; + } +} + +static const struct regmap_config altr_a10sr_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .cache_type = REGCACHE_NONE, + + .use_single_read = true, + .use_single_write = true, + .read_flag_mask = 1, + .write_flag_mask = 0, + + .max_register = ALTR_A10SR_WR_KEY_REG, + .readable_reg = altr_a10sr_reg_readable, + .writeable_reg = altr_a10sr_reg_writeable, + .volatile_reg = altr_a10sr_reg_volatile, + +}; + +static int altr_a10sr_spi_probe(struct spi_device *spi) +{ + int ret; + struct altr_a10sr *a10sr; + + a10sr = devm_kzalloc(&spi->dev, sizeof(*a10sr), + GFP_KERNEL); + if (!a10sr) + return -ENOMEM; + + spi->mode = SPI_MODE_3; + spi->bits_per_word = 8; + spi_setup(spi); + + a10sr->dev = &spi->dev; + + spi_set_drvdata(spi, a10sr); + + a10sr->regmap = devm_regmap_init_spi(spi, &altr_a10sr_regmap_config); + if (IS_ERR(a10sr->regmap)) { + ret = PTR_ERR(a10sr->regmap); + dev_err(&spi->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + ret = devm_mfd_add_devices(a10sr->dev, PLATFORM_DEVID_AUTO, + altr_a10sr_subdev_info, + ARRAY_SIZE(altr_a10sr_subdev_info), + NULL, 0, NULL); + if (ret) + dev_err(a10sr->dev, "Failed to register sub-devices: %d\n", + ret); + + return ret; +} + +static const struct of_device_id altr_a10sr_spi_of_match[] = { + { .compatible = "altr,a10sr" }, + { }, +}; +MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match); + +static const struct spi_device_id altr_a10sr_spi_ids[] = { + { .name = "a10sr" }, + { } +}; +MODULE_DEVICE_TABLE(spi, altr_a10sr_spi_ids); + +static struct spi_driver altr_a10sr_spi_driver = { + .probe = altr_a10sr_spi_probe, + .driver = { + .name = "altr_a10sr", + .of_match_table = altr_a10sr_spi_of_match, + }, + .id_table = altr_a10sr_spi_ids, +}; +builtin_driver(altr_a10sr_spi_driver, spi_register_driver) |
