Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Altera Arria10 DevKit System Resource MFD Driver
0004  *
0005  * Author: Thor Thayer <tthayer@opensource.altera.com>
0006  *
0007  * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved
0008  *
0009  * SPI access for Altera Arria10 MAX5 System Resource Chip
0010  *
0011  * Adapted from DA9052
0012  */
0013 
0014 #include <linux/mfd/altera-a10sr.h>
0015 #include <linux/mfd/core.h>
0016 #include <linux/init.h>
0017 #include <linux/module.h>
0018 #include <linux/of.h>
0019 #include <linux/spi/spi.h>
0020 
0021 static const struct mfd_cell altr_a10sr_subdev_info[] = {
0022     {
0023         .name = "altr_a10sr_gpio",
0024         .of_compatible = "altr,a10sr-gpio",
0025     },
0026     {
0027         .name = "altr_a10sr_reset",
0028         .of_compatible = "altr,a10sr-reset",
0029     },
0030 };
0031 
0032 static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg)
0033 {
0034     switch (reg) {
0035     case ALTR_A10SR_VERSION_READ:
0036     case ALTR_A10SR_LED_REG:
0037     case ALTR_A10SR_PBDSW_REG:
0038     case ALTR_A10SR_PBDSW_IRQ_REG:
0039     case ALTR_A10SR_PWR_GOOD1_REG:
0040     case ALTR_A10SR_PWR_GOOD2_REG:
0041     case ALTR_A10SR_PWR_GOOD3_REG:
0042     case ALTR_A10SR_FMCAB_REG:
0043     case ALTR_A10SR_HPS_RST_REG:
0044     case ALTR_A10SR_USB_QSPI_REG:
0045     case ALTR_A10SR_SFPA_REG:
0046     case ALTR_A10SR_SFPB_REG:
0047     case ALTR_A10SR_I2C_M_REG:
0048     case ALTR_A10SR_WARM_RST_REG:
0049     case ALTR_A10SR_WR_KEY_REG:
0050     case ALTR_A10SR_PMBUS_REG:
0051         return true;
0052     default:
0053         return false;
0054     }
0055 }
0056 
0057 static bool altr_a10sr_reg_writeable(struct device *dev, unsigned int reg)
0058 {
0059     switch (reg) {
0060     case ALTR_A10SR_LED_REG:
0061     case ALTR_A10SR_PBDSW_IRQ_REG:
0062     case ALTR_A10SR_FMCAB_REG:
0063     case ALTR_A10SR_HPS_RST_REG:
0064     case ALTR_A10SR_USB_QSPI_REG:
0065     case ALTR_A10SR_SFPA_REG:
0066     case ALTR_A10SR_SFPB_REG:
0067     case ALTR_A10SR_WARM_RST_REG:
0068     case ALTR_A10SR_WR_KEY_REG:
0069     case ALTR_A10SR_PMBUS_REG:
0070         return true;
0071     default:
0072         return false;
0073     }
0074 }
0075 
0076 static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg)
0077 {
0078     switch (reg) {
0079     case ALTR_A10SR_PBDSW_REG:
0080     case ALTR_A10SR_PBDSW_IRQ_REG:
0081     case ALTR_A10SR_PWR_GOOD1_REG:
0082     case ALTR_A10SR_PWR_GOOD2_REG:
0083     case ALTR_A10SR_PWR_GOOD3_REG:
0084     case ALTR_A10SR_HPS_RST_REG:
0085     case ALTR_A10SR_I2C_M_REG:
0086     case ALTR_A10SR_WARM_RST_REG:
0087     case ALTR_A10SR_WR_KEY_REG:
0088     case ALTR_A10SR_PMBUS_REG:
0089         return true;
0090     default:
0091         return false;
0092     }
0093 }
0094 
0095 static const struct regmap_config altr_a10sr_regmap_config = {
0096     .reg_bits = 8,
0097     .val_bits = 8,
0098 
0099     .cache_type = REGCACHE_NONE,
0100 
0101     .use_single_read = true,
0102     .use_single_write = true,
0103     .read_flag_mask = 1,
0104     .write_flag_mask = 0,
0105 
0106     .max_register = ALTR_A10SR_WR_KEY_REG,
0107     .readable_reg = altr_a10sr_reg_readable,
0108     .writeable_reg = altr_a10sr_reg_writeable,
0109     .volatile_reg = altr_a10sr_reg_volatile,
0110 
0111 };
0112 
0113 static int altr_a10sr_spi_probe(struct spi_device *spi)
0114 {
0115     int ret;
0116     struct altr_a10sr *a10sr;
0117 
0118     a10sr = devm_kzalloc(&spi->dev, sizeof(*a10sr),
0119                  GFP_KERNEL);
0120     if (!a10sr)
0121         return -ENOMEM;
0122 
0123     spi->mode = SPI_MODE_3;
0124     spi->bits_per_word = 8;
0125     spi_setup(spi);
0126 
0127     a10sr->dev = &spi->dev;
0128 
0129     spi_set_drvdata(spi, a10sr);
0130 
0131     a10sr->regmap = devm_regmap_init_spi(spi, &altr_a10sr_regmap_config);
0132     if (IS_ERR(a10sr->regmap)) {
0133         ret = PTR_ERR(a10sr->regmap);
0134         dev_err(&spi->dev, "Failed to allocate register map: %d\n",
0135             ret);
0136         return ret;
0137     }
0138 
0139     ret = devm_mfd_add_devices(a10sr->dev, PLATFORM_DEVID_AUTO,
0140                    altr_a10sr_subdev_info,
0141                    ARRAY_SIZE(altr_a10sr_subdev_info),
0142                    NULL, 0, NULL);
0143     if (ret)
0144         dev_err(a10sr->dev, "Failed to register sub-devices: %d\n",
0145             ret);
0146 
0147     return ret;
0148 }
0149 
0150 static const struct of_device_id altr_a10sr_spi_of_match[] = {
0151     { .compatible = "altr,a10sr" },
0152     { },
0153 };
0154 MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match);
0155 
0156 static const struct spi_device_id altr_a10sr_spi_ids[] = {
0157     { .name = "a10sr" },
0158     { },
0159 };
0160 MODULE_DEVICE_TABLE(spi, altr_a10sr_spi_ids);
0161 
0162 static struct spi_driver altr_a10sr_spi_driver = {
0163     .probe = altr_a10sr_spi_probe,
0164     .driver = {
0165         .name = "altr_a10sr",
0166         .of_match_table = of_match_ptr(altr_a10sr_spi_of_match),
0167     },
0168     .id_table = altr_a10sr_spi_ids,
0169 };
0170 builtin_driver(altr_a10sr_spi_driver, spi_register_driver)