Loading...
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 171 | /*
* Altera Arria10 DevKit System Resource MFD Driver
*
* Author: Thor Thayer <tthayer@opensource.altera.com>
*
* Copyright Intel Corporation (C) 2014-2016. All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* 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/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_rw = 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" },
{ },
};
static struct spi_driver altr_a10sr_spi_driver = {
.probe = altr_a10sr_spi_probe,
.driver = {
.name = "altr_a10sr",
.of_match_table = of_match_ptr(altr_a10sr_spi_of_match),
},
};
builtin_driver(altr_a10sr_spi_driver, spi_register_driver)
|