aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/sta2x11-mfd.c234
-rw-r--r--include/linux/mfd/sta2x11-mfd.h1
3 files changed, 131 insertions, 105 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b280639a7634..59359a7a2493 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1046,6 +1046,7 @@ config MFD_STA2X11
1046 bool "STA2X11 multi function device support" 1046 bool "STA2X11 multi function device support"
1047 depends on STA2X11 1047 depends on STA2X11
1048 select MFD_CORE 1048 select MFD_CORE
1049 select REGMAP_MMIO
1049 1050
1050config MFD_SYSCON 1051config MFD_SYSCON
1051 bool "System Controller Register R/W Based on Regmap" 1052 bool "System Controller Register R/W Based on Regmap"
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index 9e01b84aa8bc..0cac2013bbf6 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -27,17 +27,25 @@
27#include <linux/io.h> 27#include <linux/io.h>
28#include <linux/ioport.h> 28#include <linux/ioport.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <linux/debugfs.h>
31#include <linux/seq_file.h> 30#include <linux/seq_file.h>
32#include <linux/platform_device.h> 31#include <linux/platform_device.h>
33#include <linux/mfd/core.h> 32#include <linux/mfd/core.h>
34#include <linux/mfd/sta2x11-mfd.h> 33#include <linux/mfd/sta2x11-mfd.h>
34#include <linux/regmap.h>
35 35
36#include <asm/sta2x11.h> 36#include <asm/sta2x11.h>
37 37
38static inline int __reg_within_range(unsigned int r,
39 unsigned int start,
40 unsigned int end)
41{
42 return ((r >= start) && (r <= end));
43}
44
38/* This describes STA2X11 MFD chip for us, we may have several */ 45/* This describes STA2X11 MFD chip for us, we may have several */
39struct sta2x11_mfd { 46struct sta2x11_mfd {
40 struct sta2x11_instance *instance; 47 struct sta2x11_instance *instance;
48 struct regmap *regmap[sta2x11_n_mfd_plat_devs];
41 spinlock_t lock; 49 spinlock_t lock;
42 struct list_head list; 50 struct list_head list;
43 void __iomem *regs[sta2x11_n_mfd_plat_devs]; 51 void __iomem *regs[sta2x11_n_mfd_plat_devs];
@@ -127,118 +135,126 @@ u32 __sta2x11_mfd_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val,
127} 135}
128EXPORT_SYMBOL(__sta2x11_mfd_mask); 136EXPORT_SYMBOL(__sta2x11_mfd_mask);
129 137
130/* Two debugfs files, for our registers (FIXME: one instance only) */ 138/*
131#define REG(regname) {.name = #regname, .offset = SCTL_ ## regname} 139 * Special sta2x11-mfd regmap lock/unlock functions
132static struct debugfs_reg32 sta2x11_sctl_regs[] = { 140 */
133 REG(SCCTL), REG(ARMCFG), REG(SCPLLCTL), REG(SCPLLFCTRL),
134 REG(SCRESFRACT), REG(SCRESCTRL1), REG(SCRESXTRL2), REG(SCPEREN0),
135 REG(SCPEREN1), REG(SCPEREN2), REG(SCGRST), REG(SCPCIPMCR1),
136 REG(SCPCIPMCR2), REG(SCPCIPMSR1), REG(SCPCIPMSR2), REG(SCPCIPMSR3),
137 REG(SCINTREN), REG(SCRISR), REG(SCCLKSTAT0), REG(SCCLKSTAT1),
138 REG(SCCLKSTAT2), REG(SCRSTSTA),
139};
140#undef REG
141 141
142static struct debugfs_regset32 sctl_regset = { 142static void sta2x11_regmap_lock(void *__lock)
143 .regs = sta2x11_sctl_regs, 143{
144 .nregs = ARRAY_SIZE(sta2x11_sctl_regs), 144 spinlock_t *lock = __lock;
145}; 145 spin_lock(lock);
146}
146 147
147#define REG(regname) {.name = #regname, .offset = regname} 148static void sta2x11_regmap_unlock(void *__lock)
148static struct debugfs_reg32 sta2x11_apbreg_regs[] = { 149{
149 REG(APBREG_BSR), REG(APBREG_PAER), REG(APBREG_PWAC), REG(APBREG_PRAC), 150 spinlock_t *lock = __lock;
150 REG(APBREG_PCG), REG(APBREG_PUR), REG(APBREG_EMU_PCG), 151 spin_unlock(lock);
151}; 152}
152#undef REG
153 153
154static struct debugfs_regset32 apbreg_regset = { 154static const char *sta2x11_mfd_names[sta2x11_n_mfd_plat_devs] = {
155 .regs = sta2x11_apbreg_regs, 155 [sta2x11_sctl] = "sta2x11-sctl",
156 .nregs = ARRAY_SIZE(sta2x11_apbreg_regs), 156 [sta2x11_apbreg] = "sta2x11-apbreg",
157 [sta2x11_apb_soc_regs] = "sta2x11-apb-soc-regs",
157}; 158};
158 159
159#define REG(regname) {.name = #regname, .offset = regname} 160static bool sta2x11_sctl_writeable_reg(struct device *dev, unsigned int reg)
160static struct debugfs_reg32 sta2x11_apb_soc_regs_regs[] = { 161{
161 REG(PCIE_EP1_FUNC3_0_INTR_REG), REG(PCIE_EP1_FUNC7_4_INTR_REG), 162 return !__reg_within_range(reg, SCTL_SCPCIECSBRST, SCTL_SCRSTSTA);
162 REG(PCIE_EP2_FUNC3_0_INTR_REG), REG(PCIE_EP2_FUNC7_4_INTR_REG), 163}
163 REG(PCIE_EP3_FUNC3_0_INTR_REG), REG(PCIE_EP3_FUNC7_4_INTR_REG), 164
164 REG(PCIE_EP4_FUNC3_0_INTR_REG), REG(PCIE_EP4_FUNC7_4_INTR_REG), 165static struct regmap_config sta2x11_sctl_regmap_config = {
165 REG(PCIE_INTR_ENABLE0_REG), REG(PCIE_INTR_ENABLE1_REG), 166 .reg_bits = 32,
166 REG(PCIE_EP1_FUNC_TC_REG), REG(PCIE_EP2_FUNC_TC_REG), 167 .reg_stride = 4,
167 REG(PCIE_EP3_FUNC_TC_REG), REG(PCIE_EP4_FUNC_TC_REG), 168 .val_bits = 32,
168 REG(PCIE_EP1_FUNC_F_REG), REG(PCIE_EP2_FUNC_F_REG), 169 .lock = sta2x11_regmap_lock,
169 REG(PCIE_EP3_FUNC_F_REG), REG(PCIE_EP4_FUNC_F_REG), 170 .unlock = sta2x11_regmap_unlock,
170 REG(PCIE_PAB_AMBA_SW_RST_REG), REG(PCIE_PM_STATUS_0_PORT_0_4), 171 .max_register = SCTL_SCRSTSTA,
171 REG(PCIE_PM_STATUS_7_0_EP1), REG(PCIE_PM_STATUS_7_0_EP2), 172 .writeable_reg = sta2x11_sctl_writeable_reg,
172 REG(PCIE_PM_STATUS_7_0_EP3), REG(PCIE_PM_STATUS_7_0_EP4),
173 REG(PCIE_DEV_ID_0_EP1_REG), REG(PCIE_CC_REV_ID_0_EP1_REG),
174 REG(PCIE_DEV_ID_1_EP1_REG), REG(PCIE_CC_REV_ID_1_EP1_REG),
175 REG(PCIE_DEV_ID_2_EP1_REG), REG(PCIE_CC_REV_ID_2_EP1_REG),
176 REG(PCIE_DEV_ID_3_EP1_REG), REG(PCIE_CC_REV_ID_3_EP1_REG),
177 REG(PCIE_DEV_ID_4_EP1_REG), REG(PCIE_CC_REV_ID_4_EP1_REG),
178 REG(PCIE_DEV_ID_5_EP1_REG), REG(PCIE_CC_REV_ID_5_EP1_REG),
179 REG(PCIE_DEV_ID_6_EP1_REG), REG(PCIE_CC_REV_ID_6_EP1_REG),
180 REG(PCIE_DEV_ID_7_EP1_REG), REG(PCIE_CC_REV_ID_7_EP1_REG),
181 REG(PCIE_DEV_ID_0_EP2_REG), REG(PCIE_CC_REV_ID_0_EP2_REG),
182 REG(PCIE_DEV_ID_1_EP2_REG), REG(PCIE_CC_REV_ID_1_EP2_REG),
183 REG(PCIE_DEV_ID_2_EP2_REG), REG(PCIE_CC_REV_ID_2_EP2_REG),
184 REG(PCIE_DEV_ID_3_EP2_REG), REG(PCIE_CC_REV_ID_3_EP2_REG),
185 REG(PCIE_DEV_ID_4_EP2_REG), REG(PCIE_CC_REV_ID_4_EP2_REG),
186 REG(PCIE_DEV_ID_5_EP2_REG), REG(PCIE_CC_REV_ID_5_EP2_REG),
187 REG(PCIE_DEV_ID_6_EP2_REG), REG(PCIE_CC_REV_ID_6_EP2_REG),
188 REG(PCIE_DEV_ID_7_EP2_REG), REG(PCIE_CC_REV_ID_7_EP2_REG),
189 REG(PCIE_DEV_ID_0_EP3_REG), REG(PCIE_CC_REV_ID_0_EP3_REG),
190 REG(PCIE_DEV_ID_1_EP3_REG), REG(PCIE_CC_REV_ID_1_EP3_REG),
191 REG(PCIE_DEV_ID_2_EP3_REG), REG(PCIE_CC_REV_ID_2_EP3_REG),
192 REG(PCIE_DEV_ID_3_EP3_REG), REG(PCIE_CC_REV_ID_3_EP3_REG),
193 REG(PCIE_DEV_ID_4_EP3_REG), REG(PCIE_CC_REV_ID_4_EP3_REG),
194 REG(PCIE_DEV_ID_5_EP3_REG), REG(PCIE_CC_REV_ID_5_EP3_REG),
195 REG(PCIE_DEV_ID_6_EP3_REG), REG(PCIE_CC_REV_ID_6_EP3_REG),
196 REG(PCIE_DEV_ID_7_EP3_REG), REG(PCIE_CC_REV_ID_7_EP3_REG),
197 REG(PCIE_DEV_ID_0_EP4_REG), REG(PCIE_CC_REV_ID_0_EP4_REG),
198 REG(PCIE_DEV_ID_1_EP4_REG), REG(PCIE_CC_REV_ID_1_EP4_REG),
199 REG(PCIE_DEV_ID_2_EP4_REG), REG(PCIE_CC_REV_ID_2_EP4_REG),
200 REG(PCIE_DEV_ID_3_EP4_REG), REG(PCIE_CC_REV_ID_3_EP4_REG),
201 REG(PCIE_DEV_ID_4_EP4_REG), REG(PCIE_CC_REV_ID_4_EP4_REG),
202 REG(PCIE_DEV_ID_5_EP4_REG), REG(PCIE_CC_REV_ID_5_EP4_REG),
203 REG(PCIE_DEV_ID_6_EP4_REG), REG(PCIE_CC_REV_ID_6_EP4_REG),
204 REG(PCIE_DEV_ID_7_EP4_REG), REG(PCIE_CC_REV_ID_7_EP4_REG),
205 REG(PCIE_SUBSYS_VEN_ID_REG), REG(PCIE_COMMON_CLOCK_CONFIG_0_4_0),
206 REG(PCIE_MIPHYP_SSC_EN_REG), REG(PCIE_MIPHYP_ADDR_REG),
207 REG(PCIE_L1_ASPM_READY_REG), REG(PCIE_EXT_CFG_RDY_REG),
208 REG(PCIE_SoC_INT_ROUTER_STATUS0_REG),
209 REG(PCIE_SoC_INT_ROUTER_STATUS1_REG),
210 REG(PCIE_SoC_INT_ROUTER_STATUS2_REG),
211 REG(PCIE_SoC_INT_ROUTER_STATUS3_REG),
212 REG(DMA_IP_CTRL_REG), REG(DISP_BRIDGE_PU_PD_CTRL_REG),
213 REG(VIP_PU_PD_CTRL_REG), REG(USB_MLB_PU_PD_CTRL_REG),
214 REG(SDIO_PU_PD_MISCFUNC_CTRL_REG1), REG(SDIO_PU_PD_MISCFUNC_CTRL_REG2),
215 REG(UART_PU_PD_CTRL_REG), REG(ARM_Lock), REG(SYS_IO_CHAR_REG1),
216 REG(SYS_IO_CHAR_REG2), REG(SATA_CORE_ID_REG), REG(SATA_CTRL_REG),
217 REG(I2C_HSFIX_MISC_REG), REG(SPARE2_RESERVED), REG(SPARE3_RESERVED),
218 REG(MASTER_LOCK_REG), REG(SYSTEM_CONFIG_STATUS_REG),
219 REG(MSP_CLK_CTRL_REG), REG(COMPENSATION_REG1), REG(COMPENSATION_REG2),
220 REG(COMPENSATION_REG3), REG(TEST_CTL_REG),
221}; 173};
222#undef REG
223 174
224static struct debugfs_regset32 apb_soc_regs_regset = { 175static bool sta2x11_apbreg_readable_reg(struct device *dev, unsigned int reg)
225 .regs = sta2x11_apb_soc_regs_regs, 176{
226 .nregs = ARRAY_SIZE(sta2x11_apb_soc_regs_regs), 177 /* Two blocks (CAN and MLB, SARAC) 0x100 bytes apart */
178 if (reg >= APBREG_BSR_SARAC)
179 reg -= APBREG_BSR_SARAC;
180 switch (reg) {
181 case APBREG_BSR:
182 case APBREG_PAER:
183 case APBREG_PWAC:
184 case APBREG_PRAC:
185 case APBREG_PCG:
186 case APBREG_PUR:
187 case APBREG_EMU_PCG:
188 return true;
189 default:
190 return false;
191 }
192}
193
194static bool sta2x11_apbreg_writeable_reg(struct device *dev, unsigned int reg)
195{
196 if (reg >= APBREG_BSR_SARAC)
197 reg -= APBREG_BSR_SARAC;
198 if (!sta2x11_apbreg_readable_reg(dev, reg))
199 return false;
200 return reg != APBREG_PAER;
201}
202
203static struct regmap_config sta2x11_apbreg_regmap_config = {
204 .reg_bits = 32,
205 .reg_stride = 4,
206 .val_bits = 32,
207 .lock = sta2x11_regmap_lock,
208 .unlock = sta2x11_regmap_unlock,
209 .max_register = APBREG_EMU_PCG_SARAC,
210 .readable_reg = sta2x11_apbreg_readable_reg,
211 .writeable_reg = sta2x11_apbreg_writeable_reg,
227}; 212};
228 213
214static bool sta2x11_apb_soc_regs_readable_reg(struct device *dev,
215 unsigned int reg)
216{
217 return reg <= PCIE_SoC_INT_ROUTER_STATUS3_REG ||
218 __reg_within_range(reg, DMA_IP_CTRL_REG, SPARE3_RESERVED) ||
219 __reg_within_range(reg, MASTER_LOCK_REG,
220 SYSTEM_CONFIG_STATUS_REG) ||
221 reg == MSP_CLK_CTRL_REG ||
222 __reg_within_range(reg, COMPENSATION_REG1, TEST_CTL_REG);
223}
229 224
230static struct dentry *sta2x11_mfd_debugfs[sta2x11_n_mfd_plat_devs]; 225static bool sta2x11_apb_soc_regs_writeable_reg(struct device *dev,
226 unsigned int reg)
227{
228 if (!sta2x11_apb_soc_regs_readable_reg(dev, reg))
229 return false;
230 switch (reg) {
231 case PCIE_COMMON_CLOCK_CONFIG_0_4_0:
232 case SYSTEM_CONFIG_STATUS_REG:
233 case COMPENSATION_REG1:
234 case PCIE_SoC_INT_ROUTER_STATUS0_REG...PCIE_SoC_INT_ROUTER_STATUS3_REG:
235 case PCIE_PM_STATUS_0_PORT_0_4...PCIE_PM_STATUS_7_0_EP4:
236 return false;
237 default:
238 return true;
239 }
240}
231 241
232static struct debugfs_regset32 *sta2x11_mfd_regset[sta2x11_n_mfd_plat_devs] = { 242static struct regmap_config sta2x11_apb_soc_regs_regmap_config = {
233 [sta2x11_sctl] = &sctl_regset, 243 .reg_bits = 32,
234 [sta2x11_apbreg] = &apbreg_regset, 244 .reg_stride = 4,
235 [sta2x11_apb_soc_regs] = &apb_soc_regs_regset, 245 .val_bits = 32,
246 .lock = sta2x11_regmap_lock,
247 .unlock = sta2x11_regmap_unlock,
248 .max_register = TEST_CTL_REG,
249 .readable_reg = sta2x11_apb_soc_regs_readable_reg,
250 .writeable_reg = sta2x11_apb_soc_regs_writeable_reg,
236}; 251};
237 252
238static const char *sta2x11_mfd_names[sta2x11_n_mfd_plat_devs] = { 253static struct regmap_config *
239 [sta2x11_sctl] = "sta2x11-sctl", 254sta2x11_mfd_regmap_configs[sta2x11_n_mfd_plat_devs] = {
240 [sta2x11_apbreg] = "sta2x11-apbreg", 255 [sta2x11_sctl] = &sta2x11_sctl_regmap_config,
241 [sta2x11_apb_soc_regs] = "sta2x11-apb-soc-regs", 256 [sta2x11_apbreg] = &sta2x11_apbreg_regmap_config,
257 [sta2x11_apb_soc_regs] = &sta2x11_apb_soc_regs_regmap_config,
242}; 258};
243 259
244/* Probe for the three platform devices */ 260/* Probe for the three platform devices */
@@ -250,12 +266,14 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev,
250 struct sta2x11_mfd *mfd; 266 struct sta2x11_mfd *mfd;
251 struct resource *res; 267 struct resource *res;
252 const char *name = sta2x11_mfd_names[index]; 268 const char *name = sta2x11_mfd_names[index];
253 struct debugfs_regset32 *regset = sta2x11_mfd_regset[index]; 269 struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
254 270
255 pdev = dev->dev.platform_data; 271 pdev = dev->dev.platform_data;
256 mfd = sta2x11_mfd_find(*pdev); 272 mfd = sta2x11_mfd_find(*pdev);
257 if (!mfd) 273 if (!mfd)
258 return -ENODEV; 274 return -ENODEV;
275 if (!regmap_config)
276 return -ENODEV;
259 277
260 res = platform_get_resource(dev, IORESOURCE_MEM, 0); 278 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
261 if (!res) 279 if (!res)
@@ -269,10 +287,16 @@ static int sta2x11_mfd_platform_probe(struct platform_device *dev,
269 release_mem_region(res->start, resource_size(res)); 287 release_mem_region(res->start, resource_size(res));
270 return -ENOMEM; 288 return -ENOMEM;
271 } 289 }
272 regset->base = mfd->regs[index]; 290 regmap_config->lock_arg = &mfd->lock;
273 sta2x11_mfd_debugfs[index] = debugfs_create_regset32(name, 291 /*
274 S_IFREG | S_IRUGO, 292 No caching, registers could be reached both via regmap and via
275 NULL, regset); 293 void __iomem *
294 */
295 regmap_config->cache_type = REGCACHE_NONE;
296 mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
297 regmap_config);
298 WARN_ON(!mfd->regmap[index]);
299
276 return 0; 300 return 0;
277} 301}
278 302
diff --git a/include/linux/mfd/sta2x11-mfd.h b/include/linux/mfd/sta2x11-mfd.h
index 4d858797d7e2..83344304f2cf 100644
--- a/include/linux/mfd/sta2x11-mfd.h
+++ b/include/linux/mfd/sta2x11-mfd.h
@@ -246,6 +246,7 @@ u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
246#define SCTL_SCPEREN1 0x20 /* Peripheral clock enable register 1 */ 246#define SCTL_SCPEREN1 0x20 /* Peripheral clock enable register 1 */
247#define SCTL_SCPEREN2 0x24 /* Peripheral clock enable register 2 */ 247#define SCTL_SCPEREN2 0x24 /* Peripheral clock enable register 2 */
248#define SCTL_SCGRST 0x28 /* Peripheral global reset */ 248#define SCTL_SCGRST 0x28 /* Peripheral global reset */
249#define SCTL_SCPCIECSBRST 0x2c /* PCIe PAB CSB reset status register */
249#define SCTL_SCPCIPMCR1 0x30 /* PCI power management control 1 */ 250#define SCTL_SCPCIPMCR1 0x30 /* PCI power management control 1 */
250#define SCTL_SCPCIPMCR2 0x34 /* PCI power management control 2 */ 251#define SCTL_SCPCIPMCR2 0x34 /* PCI power management control 2 */
251#define SCTL_SCPCIPMSR1 0x38 /* PCI power management status 1 */ 252#define SCTL_SCPCIPMSR1 0x38 /* PCI power management status 1 */