1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 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)
|