19952f691SThomas 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>
1737f127cfSArnd Bergmann #include <linux/module.h>
189787f5e2SThor Thayer #include <linux/of.h>
199787f5e2SThor Thayer #include <linux/spi/spi.h>
209787f5e2SThor Thayer
219787f5e2SThor Thayer static const struct mfd_cell altr_a10sr_subdev_info[] = {
229787f5e2SThor Thayer {
239787f5e2SThor Thayer .name = "altr_a10sr_gpio",
249787f5e2SThor Thayer .of_compatible = "altr,a10sr-gpio",
259787f5e2SThor Thayer },
26dd47e972SThor Thayer {
27dd47e972SThor Thayer .name = "altr_a10sr_reset",
28dd47e972SThor Thayer .of_compatible = "altr,a10sr-reset",
29dd47e972SThor Thayer },
309787f5e2SThor Thayer };
319787f5e2SThor Thayer
altr_a10sr_reg_readable(struct device * dev,unsigned int reg)329787f5e2SThor Thayer static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg)
339787f5e2SThor Thayer {
349787f5e2SThor Thayer switch (reg) {
359787f5e2SThor Thayer case ALTR_A10SR_VERSION_READ:
369787f5e2SThor Thayer case ALTR_A10SR_LED_REG:
379787f5e2SThor Thayer case ALTR_A10SR_PBDSW_REG:
389787f5e2SThor Thayer case ALTR_A10SR_PBDSW_IRQ_REG:
399787f5e2SThor Thayer case ALTR_A10SR_PWR_GOOD1_REG:
409787f5e2SThor Thayer case ALTR_A10SR_PWR_GOOD2_REG:
419787f5e2SThor Thayer case ALTR_A10SR_PWR_GOOD3_REG:
429787f5e2SThor Thayer case ALTR_A10SR_FMCAB_REG:
439787f5e2SThor Thayer case ALTR_A10SR_HPS_RST_REG:
449787f5e2SThor Thayer case ALTR_A10SR_USB_QSPI_REG:
459787f5e2SThor Thayer case ALTR_A10SR_SFPA_REG:
469787f5e2SThor Thayer case ALTR_A10SR_SFPB_REG:
479787f5e2SThor Thayer case ALTR_A10SR_I2C_M_REG:
489787f5e2SThor Thayer case ALTR_A10SR_WARM_RST_REG:
499787f5e2SThor Thayer case ALTR_A10SR_WR_KEY_REG:
509787f5e2SThor Thayer case ALTR_A10SR_PMBUS_REG:
519787f5e2SThor Thayer return true;
529787f5e2SThor Thayer default:
539787f5e2SThor Thayer return false;
549787f5e2SThor Thayer }
559787f5e2SThor Thayer }
569787f5e2SThor Thayer
altr_a10sr_reg_writeable(struct device * dev,unsigned int reg)579787f5e2SThor Thayer static bool altr_a10sr_reg_writeable(struct device *dev, unsigned int reg)
589787f5e2SThor Thayer {
599787f5e2SThor Thayer switch (reg) {
609787f5e2SThor Thayer case ALTR_A10SR_LED_REG:
619787f5e2SThor Thayer case ALTR_A10SR_PBDSW_IRQ_REG:
629787f5e2SThor Thayer case ALTR_A10SR_FMCAB_REG:
639787f5e2SThor Thayer case ALTR_A10SR_HPS_RST_REG:
649787f5e2SThor Thayer case ALTR_A10SR_USB_QSPI_REG:
659787f5e2SThor Thayer case ALTR_A10SR_SFPA_REG:
669787f5e2SThor Thayer case ALTR_A10SR_SFPB_REG:
679787f5e2SThor Thayer case ALTR_A10SR_WARM_RST_REG:
689787f5e2SThor Thayer case ALTR_A10SR_WR_KEY_REG:
699787f5e2SThor Thayer case ALTR_A10SR_PMBUS_REG:
709787f5e2SThor Thayer return true;
719787f5e2SThor Thayer default:
729787f5e2SThor Thayer return false;
739787f5e2SThor Thayer }
749787f5e2SThor Thayer }
759787f5e2SThor Thayer
altr_a10sr_reg_volatile(struct device * dev,unsigned int reg)769787f5e2SThor Thayer static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg)
779787f5e2SThor Thayer {
789787f5e2SThor Thayer switch (reg) {
799787f5e2SThor Thayer case ALTR_A10SR_PBDSW_REG:
809787f5e2SThor Thayer case ALTR_A10SR_PBDSW_IRQ_REG:
819787f5e2SThor Thayer case ALTR_A10SR_PWR_GOOD1_REG:
829787f5e2SThor Thayer case ALTR_A10SR_PWR_GOOD2_REG:
839787f5e2SThor Thayer case ALTR_A10SR_PWR_GOOD3_REG:
849787f5e2SThor Thayer case ALTR_A10SR_HPS_RST_REG:
859787f5e2SThor Thayer case ALTR_A10SR_I2C_M_REG:
869787f5e2SThor Thayer case ALTR_A10SR_WARM_RST_REG:
879787f5e2SThor Thayer case ALTR_A10SR_WR_KEY_REG:
889787f5e2SThor Thayer case ALTR_A10SR_PMBUS_REG:
899787f5e2SThor Thayer return true;
909787f5e2SThor Thayer default:
919787f5e2SThor Thayer return false;
929787f5e2SThor Thayer }
939787f5e2SThor Thayer }
949787f5e2SThor Thayer
957f70495aSAxel Lin static const struct regmap_config altr_a10sr_regmap_config = {
969787f5e2SThor Thayer .reg_bits = 8,
979787f5e2SThor Thayer .val_bits = 8,
989787f5e2SThor Thayer
999787f5e2SThor Thayer .cache_type = REGCACHE_NONE,
1009787f5e2SThor Thayer
1011c96a2f6SDavid Frey .use_single_read = true,
1021c96a2f6SDavid Frey .use_single_write = true,
1039787f5e2SThor Thayer .read_flag_mask = 1,
1049787f5e2SThor Thayer .write_flag_mask = 0,
1059787f5e2SThor Thayer
1069787f5e2SThor Thayer .max_register = ALTR_A10SR_WR_KEY_REG,
1079787f5e2SThor Thayer .readable_reg = altr_a10sr_reg_readable,
1089787f5e2SThor Thayer .writeable_reg = altr_a10sr_reg_writeable,
1099787f5e2SThor Thayer .volatile_reg = altr_a10sr_reg_volatile,
1109787f5e2SThor Thayer
1119787f5e2SThor Thayer };
1129787f5e2SThor Thayer
altr_a10sr_spi_probe(struct spi_device * spi)1139787f5e2SThor Thayer static int altr_a10sr_spi_probe(struct spi_device *spi)
1149787f5e2SThor Thayer {
1159787f5e2SThor Thayer int ret;
1169787f5e2SThor Thayer struct altr_a10sr *a10sr;
1179787f5e2SThor Thayer
1189787f5e2SThor Thayer a10sr = devm_kzalloc(&spi->dev, sizeof(*a10sr),
1199787f5e2SThor Thayer GFP_KERNEL);
1209787f5e2SThor Thayer if (!a10sr)
1219787f5e2SThor Thayer return -ENOMEM;
1229787f5e2SThor Thayer
1239787f5e2SThor Thayer spi->mode = SPI_MODE_3;
1249787f5e2SThor Thayer spi->bits_per_word = 8;
1259787f5e2SThor Thayer spi_setup(spi);
1269787f5e2SThor Thayer
1279787f5e2SThor Thayer a10sr->dev = &spi->dev;
1289787f5e2SThor Thayer
1299787f5e2SThor Thayer spi_set_drvdata(spi, a10sr);
1309787f5e2SThor Thayer
1319787f5e2SThor Thayer a10sr->regmap = devm_regmap_init_spi(spi, &altr_a10sr_regmap_config);
1329787f5e2SThor Thayer if (IS_ERR(a10sr->regmap)) {
1339787f5e2SThor Thayer ret = PTR_ERR(a10sr->regmap);
1349787f5e2SThor Thayer dev_err(&spi->dev, "Failed to allocate register map: %d\n",
1359787f5e2SThor Thayer ret);
1369787f5e2SThor Thayer return ret;
1379787f5e2SThor Thayer }
1389787f5e2SThor Thayer
1399787f5e2SThor Thayer ret = devm_mfd_add_devices(a10sr->dev, PLATFORM_DEVID_AUTO,
1409787f5e2SThor Thayer altr_a10sr_subdev_info,
1419787f5e2SThor Thayer ARRAY_SIZE(altr_a10sr_subdev_info),
1429787f5e2SThor Thayer NULL, 0, NULL);
1439787f5e2SThor Thayer if (ret)
1449787f5e2SThor Thayer dev_err(a10sr->dev, "Failed to register sub-devices: %d\n",
1459787f5e2SThor Thayer ret);
1469787f5e2SThor Thayer
1479787f5e2SThor Thayer return ret;
1489787f5e2SThor Thayer }
1499787f5e2SThor Thayer
1509787f5e2SThor Thayer static const struct of_device_id altr_a10sr_spi_of_match[] = {
1519787f5e2SThor Thayer { .compatible = "altr,a10sr" },
1529787f5e2SThor Thayer { },
1539787f5e2SThor Thayer };
1544ea673e8SMark Brown MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match);
1554ea673e8SMark Brown
1564ea673e8SMark Brown static const struct spi_device_id altr_a10sr_spi_ids[] = {
1574ea673e8SMark Brown { .name = "a10sr" },
1584ea673e8SMark Brown { },
1594ea673e8SMark Brown };
1604ea673e8SMark Brown MODULE_DEVICE_TABLE(spi, altr_a10sr_spi_ids);
1619787f5e2SThor Thayer
1629787f5e2SThor Thayer static struct spi_driver altr_a10sr_spi_driver = {
1639787f5e2SThor Thayer .probe = altr_a10sr_spi_probe,
1649787f5e2SThor Thayer .driver = {
1659787f5e2SThor Thayer .name = "altr_a10sr",
166*23fa9421SZhu Wang .of_match_table = altr_a10sr_spi_of_match,
1679787f5e2SThor Thayer },
1684ea673e8SMark Brown .id_table = altr_a10sr_spi_ids,
1699787f5e2SThor Thayer };
1700a589167SPaul Gortmaker builtin_driver(altr_a10sr_spi_driver, spi_register_driver)
171