xref: /linux/drivers/mfd/altera-a10sr.c (revision 9952f6918daa4ab5fc81307a9f90e31a4df3b200)
1*9952f691SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29787f5e2SThor Thayer /*
30a589167SPaul Gortmaker  * Altera Arria10 DevKit System Resource MFD Driver
40a589167SPaul Gortmaker  *
50a589167SPaul Gortmaker  * Author: Thor Thayer <tthayer@opensource.altera.com>
60a589167SPaul Gortmaker  *
79787f5e2SThor Thayer  * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved
89787f5e2SThor Thayer  *
99787f5e2SThor Thayer  * SPI access for Altera Arria10 MAX5 System Resource Chip
109787f5e2SThor Thayer  *
119787f5e2SThor Thayer  * Adapted from DA9052
129787f5e2SThor Thayer  */
139787f5e2SThor Thayer 
149787f5e2SThor Thayer #include <linux/mfd/altera-a10sr.h>
159787f5e2SThor Thayer #include <linux/mfd/core.h>
160a589167SPaul Gortmaker #include <linux/init.h>
179787f5e2SThor Thayer #include <linux/of.h>
189787f5e2SThor Thayer #include <linux/spi/spi.h>
199787f5e2SThor Thayer 
209787f5e2SThor Thayer static const struct mfd_cell altr_a10sr_subdev_info[] = {
219787f5e2SThor Thayer 	{
229787f5e2SThor Thayer 		.name = "altr_a10sr_gpio",
239787f5e2SThor Thayer 		.of_compatible = "altr,a10sr-gpio",
249787f5e2SThor Thayer 	},
25dd47e972SThor Thayer 	{
26dd47e972SThor Thayer 		.name = "altr_a10sr_reset",
27dd47e972SThor Thayer 		.of_compatible = "altr,a10sr-reset",
28dd47e972SThor Thayer 	},
299787f5e2SThor Thayer };
309787f5e2SThor Thayer 
319787f5e2SThor Thayer static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg)
329787f5e2SThor Thayer {
339787f5e2SThor Thayer 	switch (reg) {
349787f5e2SThor Thayer 	case ALTR_A10SR_VERSION_READ:
359787f5e2SThor Thayer 	case ALTR_A10SR_LED_REG:
369787f5e2SThor Thayer 	case ALTR_A10SR_PBDSW_REG:
379787f5e2SThor Thayer 	case ALTR_A10SR_PBDSW_IRQ_REG:
389787f5e2SThor Thayer 	case ALTR_A10SR_PWR_GOOD1_REG:
399787f5e2SThor Thayer 	case ALTR_A10SR_PWR_GOOD2_REG:
409787f5e2SThor Thayer 	case ALTR_A10SR_PWR_GOOD3_REG:
419787f5e2SThor Thayer 	case ALTR_A10SR_FMCAB_REG:
429787f5e2SThor Thayer 	case ALTR_A10SR_HPS_RST_REG:
439787f5e2SThor Thayer 	case ALTR_A10SR_USB_QSPI_REG:
449787f5e2SThor Thayer 	case ALTR_A10SR_SFPA_REG:
459787f5e2SThor Thayer 	case ALTR_A10SR_SFPB_REG:
469787f5e2SThor Thayer 	case ALTR_A10SR_I2C_M_REG:
479787f5e2SThor Thayer 	case ALTR_A10SR_WARM_RST_REG:
489787f5e2SThor Thayer 	case ALTR_A10SR_WR_KEY_REG:
499787f5e2SThor Thayer 	case ALTR_A10SR_PMBUS_REG:
509787f5e2SThor Thayer 		return true;
519787f5e2SThor Thayer 	default:
529787f5e2SThor Thayer 		return false;
539787f5e2SThor Thayer 	}
549787f5e2SThor Thayer }
559787f5e2SThor Thayer 
569787f5e2SThor Thayer static bool altr_a10sr_reg_writeable(struct device *dev, unsigned int reg)
579787f5e2SThor Thayer {
589787f5e2SThor Thayer 	switch (reg) {
599787f5e2SThor Thayer 	case ALTR_A10SR_LED_REG:
609787f5e2SThor Thayer 	case ALTR_A10SR_PBDSW_IRQ_REG:
619787f5e2SThor Thayer 	case ALTR_A10SR_FMCAB_REG:
629787f5e2SThor Thayer 	case ALTR_A10SR_HPS_RST_REG:
639787f5e2SThor Thayer 	case ALTR_A10SR_USB_QSPI_REG:
649787f5e2SThor Thayer 	case ALTR_A10SR_SFPA_REG:
659787f5e2SThor Thayer 	case ALTR_A10SR_SFPB_REG:
669787f5e2SThor Thayer 	case ALTR_A10SR_WARM_RST_REG:
679787f5e2SThor Thayer 	case ALTR_A10SR_WR_KEY_REG:
689787f5e2SThor Thayer 	case ALTR_A10SR_PMBUS_REG:
699787f5e2SThor Thayer 		return true;
709787f5e2SThor Thayer 	default:
719787f5e2SThor Thayer 		return false;
729787f5e2SThor Thayer 	}
739787f5e2SThor Thayer }
749787f5e2SThor Thayer 
759787f5e2SThor Thayer static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg)
769787f5e2SThor Thayer {
779787f5e2SThor Thayer 	switch (reg) {
789787f5e2SThor Thayer 	case ALTR_A10SR_PBDSW_REG:
799787f5e2SThor Thayer 	case ALTR_A10SR_PBDSW_IRQ_REG:
809787f5e2SThor Thayer 	case ALTR_A10SR_PWR_GOOD1_REG:
819787f5e2SThor Thayer 	case ALTR_A10SR_PWR_GOOD2_REG:
829787f5e2SThor Thayer 	case ALTR_A10SR_PWR_GOOD3_REG:
839787f5e2SThor Thayer 	case ALTR_A10SR_HPS_RST_REG:
849787f5e2SThor Thayer 	case ALTR_A10SR_I2C_M_REG:
859787f5e2SThor Thayer 	case ALTR_A10SR_WARM_RST_REG:
869787f5e2SThor Thayer 	case ALTR_A10SR_WR_KEY_REG:
879787f5e2SThor Thayer 	case ALTR_A10SR_PMBUS_REG:
889787f5e2SThor Thayer 		return true;
899787f5e2SThor Thayer 	default:
909787f5e2SThor Thayer 		return false;
919787f5e2SThor Thayer 	}
929787f5e2SThor Thayer }
939787f5e2SThor Thayer 
947f70495aSAxel Lin static const struct regmap_config altr_a10sr_regmap_config = {
959787f5e2SThor Thayer 	.reg_bits = 8,
969787f5e2SThor Thayer 	.val_bits = 8,
979787f5e2SThor Thayer 
989787f5e2SThor Thayer 	.cache_type = REGCACHE_NONE,
999787f5e2SThor Thayer 
1001c96a2f6SDavid Frey 	.use_single_read = true,
1011c96a2f6SDavid Frey 	.use_single_write = true,
1029787f5e2SThor Thayer 	.read_flag_mask = 1,
1039787f5e2SThor Thayer 	.write_flag_mask = 0,
1049787f5e2SThor Thayer 
1059787f5e2SThor Thayer 	.max_register = ALTR_A10SR_WR_KEY_REG,
1069787f5e2SThor Thayer 	.readable_reg = altr_a10sr_reg_readable,
1079787f5e2SThor Thayer 	.writeable_reg = altr_a10sr_reg_writeable,
1089787f5e2SThor Thayer 	.volatile_reg = altr_a10sr_reg_volatile,
1099787f5e2SThor Thayer 
1109787f5e2SThor Thayer };
1119787f5e2SThor Thayer 
1129787f5e2SThor Thayer static int altr_a10sr_spi_probe(struct spi_device *spi)
1139787f5e2SThor Thayer {
1149787f5e2SThor Thayer 	int ret;
1159787f5e2SThor Thayer 	struct altr_a10sr *a10sr;
1169787f5e2SThor Thayer 
1179787f5e2SThor Thayer 	a10sr = devm_kzalloc(&spi->dev, sizeof(*a10sr),
1189787f5e2SThor Thayer 			     GFP_KERNEL);
1199787f5e2SThor Thayer 	if (!a10sr)
1209787f5e2SThor Thayer 		return -ENOMEM;
1219787f5e2SThor Thayer 
1229787f5e2SThor Thayer 	spi->mode = SPI_MODE_3;
1239787f5e2SThor Thayer 	spi->bits_per_word = 8;
1249787f5e2SThor Thayer 	spi_setup(spi);
1259787f5e2SThor Thayer 
1269787f5e2SThor Thayer 	a10sr->dev = &spi->dev;
1279787f5e2SThor Thayer 
1289787f5e2SThor Thayer 	spi_set_drvdata(spi, a10sr);
1299787f5e2SThor Thayer 
1309787f5e2SThor Thayer 	a10sr->regmap = devm_regmap_init_spi(spi, &altr_a10sr_regmap_config);
1319787f5e2SThor Thayer 	if (IS_ERR(a10sr->regmap)) {
1329787f5e2SThor Thayer 		ret = PTR_ERR(a10sr->regmap);
1339787f5e2SThor Thayer 		dev_err(&spi->dev, "Failed to allocate register map: %d\n",
1349787f5e2SThor Thayer 			ret);
1359787f5e2SThor Thayer 		return ret;
1369787f5e2SThor Thayer 	}
1379787f5e2SThor Thayer 
1389787f5e2SThor Thayer 	ret = devm_mfd_add_devices(a10sr->dev, PLATFORM_DEVID_AUTO,
1399787f5e2SThor Thayer 				   altr_a10sr_subdev_info,
1409787f5e2SThor Thayer 				   ARRAY_SIZE(altr_a10sr_subdev_info),
1419787f5e2SThor Thayer 				   NULL, 0, NULL);
1429787f5e2SThor Thayer 	if (ret)
1439787f5e2SThor Thayer 		dev_err(a10sr->dev, "Failed to register sub-devices: %d\n",
1449787f5e2SThor Thayer 			ret);
1459787f5e2SThor Thayer 
1469787f5e2SThor Thayer 	return ret;
1479787f5e2SThor Thayer }
1489787f5e2SThor Thayer 
1499787f5e2SThor Thayer static const struct of_device_id altr_a10sr_spi_of_match[] = {
1509787f5e2SThor Thayer 	{ .compatible = "altr,a10sr" },
1519787f5e2SThor Thayer 	{ },
1529787f5e2SThor Thayer };
1539787f5e2SThor Thayer 
1549787f5e2SThor Thayer static struct spi_driver altr_a10sr_spi_driver = {
1559787f5e2SThor Thayer 	.probe = altr_a10sr_spi_probe,
1569787f5e2SThor Thayer 	.driver = {
1579787f5e2SThor Thayer 		.name = "altr_a10sr",
1589787f5e2SThor Thayer 		.of_match_table = of_match_ptr(altr_a10sr_spi_of_match),
1599787f5e2SThor Thayer 	},
1609787f5e2SThor Thayer };
1610a589167SPaul Gortmaker builtin_driver(altr_a10sr_spi_driver, spi_register_driver)
162