Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: altr_a10sr: Add Altera Arria10 DevKit System Resource Chip

Add support for the Altera Arria10 Development Kit System Resource
chip which is implemented using a MAX5 as a external gpio extender
with the regmap framework over a SPI bus.

Signed-off-by: Thor Thayer <tthayer@opensource.altera.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Thor Thayer and committed by
Lee Jones
9787f5e2 8ce064bf

+267
+11
drivers/mfd/Kconfig
··· 18 18 This is the core driver for CS5535/CS5536 MFD functions. This is 19 19 necessary for using the board's GPIO and MFGPT functionality. 20 20 21 + config MFD_ALTERA_A10SR 22 + bool "Altera Arria10 DevKit System Resource chip" 23 + depends on ARCH_SOCFPGA && SPI_MASTER=y && OF 24 + select REGMAP_SPI 25 + select MFD_CORE 26 + help 27 + Support for the Altera Arria10 DevKit MAX5 System Resource chip 28 + using the SPI interface. This driver provides common support for 29 + accessing the external gpio extender (LEDs & buttons) and 30 + power supply alarms (hwmon). 31 + 21 32 config MFD_ACT8945A 22 33 tristate "Active-semi ACT8945A" 23 34 select MFD_CORE
+2
drivers/mfd/Makefile
··· 205 205 intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o 206 206 obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o 207 207 obj-$(CONFIG_MFD_MT6397) += mt6397-core.o 208 + 209 + obj-$(CONFIG_MFD_ALTERA_A10SR) += altera-a10sr.o
+169
drivers/mfd/altera-a10sr.c
··· 1 + /* 2 + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program. If not, see <http://www.gnu.org/licenses/>. 15 + * 16 + * SPI access for Altera Arria10 MAX5 System Resource Chip 17 + * 18 + * Adapted from DA9052 19 + */ 20 + 21 + #include <linux/mfd/altera-a10sr.h> 22 + #include <linux/mfd/core.h> 23 + #include <linux/module.h> 24 + #include <linux/of.h> 25 + #include <linux/spi/spi.h> 26 + 27 + static const struct mfd_cell altr_a10sr_subdev_info[] = { 28 + { 29 + .name = "altr_a10sr_gpio", 30 + .of_compatible = "altr,a10sr-gpio", 31 + }, 32 + }; 33 + 34 + static bool altr_a10sr_reg_readable(struct device *dev, unsigned int reg) 35 + { 36 + switch (reg) { 37 + case ALTR_A10SR_VERSION_READ: 38 + case ALTR_A10SR_LED_REG: 39 + case ALTR_A10SR_PBDSW_REG: 40 + case ALTR_A10SR_PBDSW_IRQ_REG: 41 + case ALTR_A10SR_PWR_GOOD1_REG: 42 + case ALTR_A10SR_PWR_GOOD2_REG: 43 + case ALTR_A10SR_PWR_GOOD3_REG: 44 + case ALTR_A10SR_FMCAB_REG: 45 + case ALTR_A10SR_HPS_RST_REG: 46 + case ALTR_A10SR_USB_QSPI_REG: 47 + case ALTR_A10SR_SFPA_REG: 48 + case ALTR_A10SR_SFPB_REG: 49 + case ALTR_A10SR_I2C_M_REG: 50 + case ALTR_A10SR_WARM_RST_REG: 51 + case ALTR_A10SR_WR_KEY_REG: 52 + case ALTR_A10SR_PMBUS_REG: 53 + return true; 54 + default: 55 + return false; 56 + } 57 + } 58 + 59 + static bool altr_a10sr_reg_writeable(struct device *dev, unsigned int reg) 60 + { 61 + switch (reg) { 62 + case ALTR_A10SR_LED_REG: 63 + case ALTR_A10SR_PBDSW_IRQ_REG: 64 + case ALTR_A10SR_FMCAB_REG: 65 + case ALTR_A10SR_HPS_RST_REG: 66 + case ALTR_A10SR_USB_QSPI_REG: 67 + case ALTR_A10SR_SFPA_REG: 68 + case ALTR_A10SR_SFPB_REG: 69 + case ALTR_A10SR_WARM_RST_REG: 70 + case ALTR_A10SR_WR_KEY_REG: 71 + case ALTR_A10SR_PMBUS_REG: 72 + return true; 73 + default: 74 + return false; 75 + } 76 + } 77 + 78 + static bool altr_a10sr_reg_volatile(struct device *dev, unsigned int reg) 79 + { 80 + switch (reg) { 81 + case ALTR_A10SR_PBDSW_REG: 82 + case ALTR_A10SR_PBDSW_IRQ_REG: 83 + case ALTR_A10SR_PWR_GOOD1_REG: 84 + case ALTR_A10SR_PWR_GOOD2_REG: 85 + case ALTR_A10SR_PWR_GOOD3_REG: 86 + case ALTR_A10SR_HPS_RST_REG: 87 + case ALTR_A10SR_I2C_M_REG: 88 + case ALTR_A10SR_WARM_RST_REG: 89 + case ALTR_A10SR_WR_KEY_REG: 90 + case ALTR_A10SR_PMBUS_REG: 91 + return true; 92 + default: 93 + return false; 94 + } 95 + } 96 + 97 + const struct regmap_config altr_a10sr_regmap_config = { 98 + .reg_bits = 8, 99 + .val_bits = 8, 100 + 101 + .cache_type = REGCACHE_NONE, 102 + 103 + .use_single_rw = true, 104 + .read_flag_mask = 1, 105 + .write_flag_mask = 0, 106 + 107 + .max_register = ALTR_A10SR_WR_KEY_REG, 108 + .readable_reg = altr_a10sr_reg_readable, 109 + .writeable_reg = altr_a10sr_reg_writeable, 110 + .volatile_reg = altr_a10sr_reg_volatile, 111 + 112 + }; 113 + 114 + static int altr_a10sr_spi_probe(struct spi_device *spi) 115 + { 116 + int ret; 117 + struct altr_a10sr *a10sr; 118 + 119 + a10sr = devm_kzalloc(&spi->dev, sizeof(*a10sr), 120 + GFP_KERNEL); 121 + if (!a10sr) 122 + return -ENOMEM; 123 + 124 + spi->mode = SPI_MODE_3; 125 + spi->bits_per_word = 8; 126 + spi_setup(spi); 127 + 128 + a10sr->dev = &spi->dev; 129 + 130 + spi_set_drvdata(spi, a10sr); 131 + 132 + a10sr->regmap = devm_regmap_init_spi(spi, &altr_a10sr_regmap_config); 133 + if (IS_ERR(a10sr->regmap)) { 134 + ret = PTR_ERR(a10sr->regmap); 135 + dev_err(&spi->dev, "Failed to allocate register map: %d\n", 136 + ret); 137 + return ret; 138 + } 139 + 140 + ret = devm_mfd_add_devices(a10sr->dev, PLATFORM_DEVID_AUTO, 141 + altr_a10sr_subdev_info, 142 + ARRAY_SIZE(altr_a10sr_subdev_info), 143 + NULL, 0, NULL); 144 + if (ret) 145 + dev_err(a10sr->dev, "Failed to register sub-devices: %d\n", 146 + ret); 147 + 148 + return ret; 149 + } 150 + 151 + static const struct of_device_id altr_a10sr_spi_of_match[] = { 152 + { .compatible = "altr,a10sr" }, 153 + { }, 154 + }; 155 + MODULE_DEVICE_TABLE(of, altr_a10sr_spi_of_match); 156 + 157 + static struct spi_driver altr_a10sr_spi_driver = { 158 + .probe = altr_a10sr_spi_probe, 159 + .driver = { 160 + .name = "altr_a10sr", 161 + .of_match_table = of_match_ptr(altr_a10sr_spi_of_match), 162 + }, 163 + }; 164 + 165 + module_spi_driver(altr_a10sr_spi_driver); 166 + 167 + MODULE_LICENSE("GPL v2"); 168 + MODULE_AUTHOR("Thor Thayer <tthayer@opensource.altera.com>"); 169 + MODULE_DESCRIPTION("Altera Arria10 DevKit System Resource MFD Driver");
+85
include/linux/mfd/altera-a10sr.h
··· 1 + /* 2 + * Copyright Intel Corporation (C) 2014-2016. All Rights Reserved 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program. If not, see <http://www.gnu.org/licenses/>. 15 + * 16 + * Declarations for Altera Arria10 MAX5 System Resource Chip 17 + * 18 + * Adapted from DA9052 19 + */ 20 + 21 + #ifndef __MFD_ALTERA_A10SR_H 22 + #define __MFD_ALTERA_A10SR_H 23 + 24 + #include <linux/completion.h> 25 + #include <linux/list.h> 26 + #include <linux/mfd/core.h> 27 + #include <linux/regmap.h> 28 + #include <linux/slab.h> 29 + 30 + /* Write registers are always on even addresses */ 31 + #define WRITE_REG_MASK 0xFE 32 + /* Odd registers are always on odd addresses */ 33 + #define READ_REG_MASK 0x01 34 + 35 + #define ALTR_A10SR_BITS_PER_REGISTER 8 36 + /* 37 + * To find the correct register, we divide the input GPIO by 38 + * the number of GPIO in each register. We then need to multiply 39 + * by 2 because the reads are at odd addresses. 40 + */ 41 + #define ALTR_A10SR_REG_OFFSET(X) (((X) / ALTR_A10SR_BITS_PER_REGISTER) << 1) 42 + #define ALTR_A10SR_REG_BIT(X) ((X) % ALTR_A10SR_BITS_PER_REGISTER) 43 + #define ALTR_A10SR_REG_BIT_CHG(X, Y) ((X) << ALTR_A10SR_REG_BIT(Y)) 44 + #define ALTR_A10SR_REG_BIT_MASK(X) (1 << ALTR_A10SR_REG_BIT(X)) 45 + 46 + /* Arria10 System Controller Register Defines */ 47 + #define ALTR_A10SR_NOP 0x00 /* No Change */ 48 + #define ALTR_A10SR_VERSION_READ 0x00 /* MAX5 Version Read */ 49 + 50 + #define ALTR_A10SR_LED_REG 0x02 /* LED - Upper 4 bits */ 51 + /* LED register Bit Definitions */ 52 + #define ALTR_A10SR_LED_VALID_SHIFT 4 /* LED - Upper 4 bits valid */ 53 + #define ALTR_A10SR_OUT_VALID_RANGE_LO ALTR_A10SR_LED_VALID_SHIFT 54 + #define ALTR_A10SR_OUT_VALID_RANGE_HI 7 55 + 56 + #define ALTR_A10SR_PBDSW_REG 0x04 /* PB & DIP SW - Input only */ 57 + #define ALTR_A10SR_PBDSW_IRQ_REG 0x06 /* PB & DIP SW Flag Clear */ 58 + /* Pushbutton & DIP Switch Bit Definitions */ 59 + #define ALTR_A10SR_IN_VALID_RANGE_LO 8 60 + #define ALTR_A10SR_IN_VALID_RANGE_HI 15 61 + 62 + #define ALTR_A10SR_PWR_GOOD1_REG 0x08 /* Power Good1 Read */ 63 + #define ALTR_A10SR_PWR_GOOD2_REG 0x0A /* Power Good2 Read */ 64 + #define ALTR_A10SR_PWR_GOOD3_REG 0x0C /* Power Good3 Read */ 65 + #define ALTR_A10SR_FMCAB_REG 0x0E /* FMCA/B & PCIe Pwr Enable */ 66 + #define ALTR_A10SR_HPS_RST_REG 0x10 /* HPS Reset */ 67 + #define ALTR_A10SR_USB_QSPI_REG 0x12 /* USB, BQSPI, FILE Reset */ 68 + #define ALTR_A10SR_SFPA_REG 0x14 /* SFPA Control Reg */ 69 + #define ALTR_A10SR_SFPB_REG 0x16 /* SFPB Control Reg */ 70 + #define ALTR_A10SR_I2C_M_REG 0x18 /* I2C Master Select */ 71 + #define ALTR_A10SR_WARM_RST_REG 0x1A /* HPS Warm Reset */ 72 + #define ALTR_A10SR_WR_KEY_REG 0x1C /* HPS Warm Reset Key */ 73 + #define ALTR_A10SR_PMBUS_REG 0x1E /* HPS PM Bus */ 74 + 75 + /** 76 + * struct altr_a10sr - Altera Max5 MFD device private data structure 77 + * @dev: : this device 78 + * @regmap: the regmap assigned to the parent device. 79 + */ 80 + struct altr_a10sr { 81 + struct device *dev; 82 + struct regmap *regmap; 83 + }; 84 + 85 + #endif /* __MFD_ALTERA_A10SR_H */