aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd/sta2x11-mfd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-16 21:55:20 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-16 21:55:20 -0500
commit2dfea3803dcf70983d14ce1dcbb3e97a7459a28b (patch)
tree59bffc7389ff554585f79d7cc06021790dc2b317 /drivers/mfd/sta2x11-mfd.c
parentaed606e3bc1f10753254db308d3fd8c053c41328 (diff)
parent1881b68b8961a86d40c3c5c205e533515a2dc9c6 (diff)
Merge tag 'mfd-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6
Pull MFS update from Samuel Ortiz: "This is the MFD patch set for the 3.8 merge window. We have several new drivers, most of the time coming with their sub devices drivers: - Austria Microsystem's AS3711 - Nano River's viperboard - TI's TPS80031, AM335x TS/ADC, - Realtek's MMC/memstick card reader - Nokia's retu We also got some notable cleanups and improvements: - tps6586x got converted to IRQ domains. - tps65910 and tps65090 moved to the regmap IRQ API. - STMPE is now Device Tree aware. - A general twl6040 and twl-core cleanup, with moves to the regmap I/O and IRQ APIs and a conversion to the recently added PWM framework. - sta2x11 gained regmap support. Then the rest is mostly tiny cleanups and fixes, among which we have Mark's wm5xxx and wm8xxx patchset." Far amount of annoying but largely trivial conflicts. Many due to __devinit/exit removal, others due to one or two of the new drivers also having come in through another tree. * tag 'mfd-3.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6: (119 commits) mfd: tps6507x: Convert to devm_kzalloc mfd: stmpe: Update DT support for stmpe driver mfd: wm5102: Add readback of DSP status 3 register mfd: arizona: Log if we fail to create the primary IRQ domain mfd: tps80031: MFD_TPS80031 needs to select REGMAP_IRQ mfd: tps80031: Add terminating entry for tps80031_id_table mfd: sta2x11: Fix potential NULL pointer dereference in __sta2x11_mfd_mask() mfd: wm5102: Add tuning for revision B mfd: arizona: Defer patch initialistation until after first device boot mfd: tps65910: Fix wrong ack_base register mfd: tps65910: Remove unused data mfd: stmpe: Get rid of irq_invert_polarity mfd: ab8500-core: Fix invalid free of devm_ allocated data mfd: wm5102: Mark DSP memory regions as volatile mfd: wm5102: Correct default for LDO1_CONTROL_2 mfd: arizona: Register haptics devices mfd: wm8994: Make current device behaviour the default mfd: tps65090: MFD_TPS65090 needs to select REGMAP_IRQ mfd: Fix stmpe.c build when OF is not enabled mfd: jz4740-adc: Use devm_kzalloc ...
Diffstat (limited to 'drivers/mfd/sta2x11-mfd.c')
-rw-r--r--drivers/mfd/sta2x11-mfd.c536
1 files changed, 380 insertions, 156 deletions
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
index d6284cacd27a..1225dcbcfcfc 100644
--- a/drivers/mfd/sta2x11-mfd.c
+++ b/drivers/mfd/sta2x11-mfd.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) 2009-2011 Wind River Systems, Inc. 2 * Copyright (c) 2009-2011 Wind River Systems, Inc.
3 * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini) 3 * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
@@ -27,21 +27,28 @@
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;
41 spinlock_t lock; 48 struct regmap *regmap[sta2x11_n_mfd_plat_devs];
49 spinlock_t lock[sta2x11_n_mfd_plat_devs];
42 struct list_head list; 50 struct list_head list;
43 void __iomem *sctl_regs; 51 void __iomem *regs[sta2x11_n_mfd_plat_devs];
44 void __iomem *apbreg_regs;
45}; 52};
46 53
47static LIST_HEAD(sta2x11_mfd_list); 54static LIST_HEAD(sta2x11_mfd_list);
@@ -71,6 +78,7 @@ static struct sta2x11_mfd *sta2x11_mfd_find(struct pci_dev *pdev)
71 78
72static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags) 79static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
73{ 80{
81 int i;
74 struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev); 82 struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
75 struct sta2x11_instance *instance; 83 struct sta2x11_instance *instance;
76 84
@@ -83,7 +91,8 @@ static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
83 if (!mfd) 91 if (!mfd)
84 return -ENOMEM; 92 return -ENOMEM;
85 INIT_LIST_HEAD(&mfd->list); 93 INIT_LIST_HEAD(&mfd->list);
86 spin_lock_init(&mfd->lock); 94 for (i = 0; i < ARRAY_SIZE(mfd->lock); i++)
95 spin_lock_init(&mfd->lock[i]);
87 mfd->instance = instance; 96 mfd->instance = instance;
88 list_add(&mfd->list, &sta2x11_mfd_list); 97 list_add(&mfd->list, &sta2x11_mfd_list);
89 return 0; 98 return 0;
@@ -100,161 +109,276 @@ static int mfd_remove(struct pci_dev *pdev)
100 return 0; 109 return 0;
101} 110}
102 111
103/* These two functions are exported and are not expected to fail */ 112/* This function is exported and is not expected to fail */
104u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val) 113u32 __sta2x11_mfd_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val,
114 enum sta2x11_mfd_plat_dev index)
105{ 115{
106 struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev); 116 struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
107 u32 r; 117 u32 r;
108 unsigned long flags; 118 unsigned long flags;
119 void __iomem *regs;
109 120
110 if (!mfd) { 121 if (!mfd) {
111 dev_warn(&pdev->dev, ": can't access sctl regs\n"); 122 dev_warn(&pdev->dev, ": can't access sctl regs\n");
112 return 0; 123 return 0;
113 } 124 }
114 if (!mfd->sctl_regs) { 125
126 regs = mfd->regs[index];
127 if (!regs) {
115 dev_warn(&pdev->dev, ": system ctl not initialized\n"); 128 dev_warn(&pdev->dev, ": system ctl not initialized\n");
116 return 0; 129 return 0;
117 } 130 }
118 spin_lock_irqsave(&mfd->lock, flags); 131 spin_lock_irqsave(&mfd->lock[index], flags);
119 r = readl(mfd->sctl_regs + reg); 132 r = readl(regs + reg);
120 r &= ~mask; 133 r &= ~mask;
121 r |= val; 134 r |= val;
122 if (mask) 135 if (mask)
123 writel(r, mfd->sctl_regs + reg); 136 writel(r, regs + reg);
124 spin_unlock_irqrestore(&mfd->lock, flags); 137 spin_unlock_irqrestore(&mfd->lock[index], flags);
125 return r; 138 return r;
126} 139}
127EXPORT_SYMBOL(sta2x11_sctl_mask); 140EXPORT_SYMBOL(__sta2x11_mfd_mask);
128 141
129u32 sta2x11_apbreg_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val) 142int sta2x11_mfd_get_regs_data(struct platform_device *dev,
143 enum sta2x11_mfd_plat_dev index,
144 void __iomem **regs,
145 spinlock_t **lock)
130{ 146{
131 struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev); 147 struct pci_dev *pdev = *(struct pci_dev **)(dev->dev.platform_data);
132 u32 r; 148 struct sta2x11_mfd *mfd;
133 unsigned long flags;
134 149
135 if (!mfd) { 150 if (!pdev)
136 dev_warn(&pdev->dev, ": can't access apb regs\n"); 151 return -ENODEV;
137 return 0; 152 mfd = sta2x11_mfd_find(pdev);
138 } 153 if (!mfd)
139 if (!mfd->apbreg_regs) { 154 return -ENODEV;
140 dev_warn(&pdev->dev, ": apb bridge not initialized\n"); 155 if (index >= sta2x11_n_mfd_plat_devs)
141 return 0; 156 return -ENODEV;
142 } 157 *regs = mfd->regs[index];
143 spin_lock_irqsave(&mfd->lock, flags); 158 *lock = &mfd->lock[index];
144 r = readl(mfd->apbreg_regs + reg); 159 pr_debug("%s %d *regs = %p\n", __func__, __LINE__, *regs);
145 r &= ~mask; 160 return *regs ? 0 : -ENODEV;
146 r |= val;
147 if (mask)
148 writel(r, mfd->apbreg_regs + reg);
149 spin_unlock_irqrestore(&mfd->lock, flags);
150 return r;
151} 161}
152EXPORT_SYMBOL(sta2x11_apbreg_mask); 162EXPORT_SYMBOL(sta2x11_mfd_get_regs_data);
153
154/* Two debugfs files, for our registers (FIXME: one instance only) */
155#define REG(regname) {.name = #regname, .offset = SCTL_ ## regname}
156static struct debugfs_reg32 sta2x11_sctl_regs[] = {
157 REG(SCCTL), REG(ARMCFG), REG(SCPLLCTL), REG(SCPLLFCTRL),
158 REG(SCRESFRACT), REG(SCRESCTRL1), REG(SCRESXTRL2), REG(SCPEREN0),
159 REG(SCPEREN1), REG(SCPEREN2), REG(SCGRST), REG(SCPCIPMCR1),
160 REG(SCPCIPMCR2), REG(SCPCIPMSR1), REG(SCPCIPMSR2), REG(SCPCIPMSR3),
161 REG(SCINTREN), REG(SCRISR), REG(SCCLKSTAT0), REG(SCCLKSTAT1),
162 REG(SCCLKSTAT2), REG(SCRSTSTA),
163};
164#undef REG
165 163
166static struct debugfs_regset32 sctl_regset = { 164/*
167 .regs = sta2x11_sctl_regs, 165 * Special sta2x11-mfd regmap lock/unlock functions
168 .nregs = ARRAY_SIZE(sta2x11_sctl_regs), 166 */
169}; 167
168static void sta2x11_regmap_lock(void *__lock)
169{
170 spinlock_t *lock = __lock;
171 spin_lock(lock);
172}
170 173
171#define REG(regname) {.name = #regname, .offset = regname} 174static void sta2x11_regmap_unlock(void *__lock)
172static struct debugfs_reg32 sta2x11_apbreg_regs[] = { 175{
173 REG(APBREG_BSR), REG(APBREG_PAER), REG(APBREG_PWAC), REG(APBREG_PRAC), 176 spinlock_t *lock = __lock;
174 REG(APBREG_PCG), REG(APBREG_PUR), REG(APBREG_EMU_PCG), 177 spin_unlock(lock);
178}
179
180/* OTP (one time programmable registers do not require locking */
181static void sta2x11_regmap_nolock(void *__lock)
182{
183}
184
185static const char *sta2x11_mfd_names[sta2x11_n_mfd_plat_devs] = {
186 [sta2x11_sctl] = STA2X11_MFD_SCTL_NAME,
187 [sta2x11_apbreg] = STA2X11_MFD_APBREG_NAME,
188 [sta2x11_apb_soc_regs] = STA2X11_MFD_APB_SOC_REGS_NAME,
189 [sta2x11_scr] = STA2X11_MFD_SCR_NAME,
175}; 190};
176#undef REG
177 191
178static struct debugfs_regset32 apbreg_regset = { 192static bool sta2x11_sctl_writeable_reg(struct device *dev, unsigned int reg)
179 .regs = sta2x11_apbreg_regs, 193{
180 .nregs = ARRAY_SIZE(sta2x11_apbreg_regs), 194 return !__reg_within_range(reg, SCTL_SCPCIECSBRST, SCTL_SCRSTSTA);
195}
196
197static struct regmap_config sta2x11_sctl_regmap_config = {
198 .reg_bits = 32,
199 .reg_stride = 4,
200 .val_bits = 32,
201 .lock = sta2x11_regmap_lock,
202 .unlock = sta2x11_regmap_unlock,
203 .max_register = SCTL_SCRSTSTA,
204 .writeable_reg = sta2x11_sctl_writeable_reg,
181}; 205};
182 206
183static struct dentry *sta2x11_sctl_debugfs; 207static bool sta2x11_scr_readable_reg(struct device *dev, unsigned int reg)
184static struct dentry *sta2x11_apbreg_debugfs; 208{
209 return (reg == STA2X11_SECR_CR) ||
210 __reg_within_range(reg, STA2X11_SECR_FVR0, STA2X11_SECR_FVR1);
211}
185 212
186/* Probe for the two platform devices */ 213static bool sta2x11_scr_writeable_reg(struct device *dev, unsigned int reg)
187static int sta2x11_sctl_probe(struct platform_device *dev)
188{ 214{
189 struct pci_dev **pdev; 215 return false;
190 struct sta2x11_mfd *mfd; 216}
191 struct resource *res;
192 217
193 pdev = dev->dev.platform_data; 218static struct regmap_config sta2x11_scr_regmap_config = {
194 mfd = sta2x11_mfd_find(*pdev); 219 .reg_bits = 32,
195 if (!mfd) 220 .reg_stride = 4,
196 return -ENODEV; 221 .val_bits = 32,
222 .lock = sta2x11_regmap_nolock,
223 .unlock = sta2x11_regmap_nolock,
224 .max_register = STA2X11_SECR_FVR1,
225 .readable_reg = sta2x11_scr_readable_reg,
226 .writeable_reg = sta2x11_scr_writeable_reg,
227};
197 228
198 res = platform_get_resource(dev, IORESOURCE_MEM, 0); 229static bool sta2x11_apbreg_readable_reg(struct device *dev, unsigned int reg)
199 if (!res) 230{
200 return -ENOMEM; 231 /* Two blocks (CAN and MLB, SARAC) 0x100 bytes apart */
232 if (reg >= APBREG_BSR_SARAC)
233 reg -= APBREG_BSR_SARAC;
234 switch (reg) {
235 case APBREG_BSR:
236 case APBREG_PAER:
237 case APBREG_PWAC:
238 case APBREG_PRAC:
239 case APBREG_PCG:
240 case APBREG_PUR:
241 case APBREG_EMU_PCG:
242 return true;
243 default:
244 return false;
245 }
246}
201 247
202 if (!request_mem_region(res->start, resource_size(res), 248static bool sta2x11_apbreg_writeable_reg(struct device *dev, unsigned int reg)
203 "sta2x11-sctl")) 249{
204 return -EBUSY; 250 if (reg >= APBREG_BSR_SARAC)
251 reg -= APBREG_BSR_SARAC;
252 if (!sta2x11_apbreg_readable_reg(dev, reg))
253 return false;
254 return reg != APBREG_PAER;
255}
205 256
206 mfd->sctl_regs = ioremap(res->start, resource_size(res)); 257static struct regmap_config sta2x11_apbreg_regmap_config = {
207 if (!mfd->sctl_regs) { 258 .reg_bits = 32,
208 release_mem_region(res->start, resource_size(res)); 259 .reg_stride = 4,
209 return -ENOMEM; 260 .val_bits = 32,
261 .lock = sta2x11_regmap_lock,
262 .unlock = sta2x11_regmap_unlock,
263 .max_register = APBREG_EMU_PCG_SARAC,
264 .readable_reg = sta2x11_apbreg_readable_reg,
265 .writeable_reg = sta2x11_apbreg_writeable_reg,
266};
267
268static bool sta2x11_apb_soc_regs_readable_reg(struct device *dev,
269 unsigned int reg)
270{
271 return reg <= PCIE_SoC_INT_ROUTER_STATUS3_REG ||
272 __reg_within_range(reg, DMA_IP_CTRL_REG, SPARE3_RESERVED) ||
273 __reg_within_range(reg, MASTER_LOCK_REG,
274 SYSTEM_CONFIG_STATUS_REG) ||
275 reg == MSP_CLK_CTRL_REG ||
276 __reg_within_range(reg, COMPENSATION_REG1, TEST_CTL_REG);
277}
278
279static bool sta2x11_apb_soc_regs_writeable_reg(struct device *dev,
280 unsigned int reg)
281{
282 if (!sta2x11_apb_soc_regs_readable_reg(dev, reg))
283 return false;
284 switch (reg) {
285 case PCIE_COMMON_CLOCK_CONFIG_0_4_0:
286 case SYSTEM_CONFIG_STATUS_REG:
287 case COMPENSATION_REG1:
288 case PCIE_SoC_INT_ROUTER_STATUS0_REG...PCIE_SoC_INT_ROUTER_STATUS3_REG:
289 case PCIE_PM_STATUS_0_PORT_0_4...PCIE_PM_STATUS_7_0_EP4:
290 return false;
291 default:
292 return true;
210 } 293 }
211 sctl_regset.base = mfd->sctl_regs;
212 sta2x11_sctl_debugfs = debugfs_create_regset32("sta2x11-sctl",
213 S_IFREG | S_IRUGO,
214 NULL, &sctl_regset);
215 return 0;
216} 294}
217 295
218static int sta2x11_apbreg_probe(struct platform_device *dev) 296static struct regmap_config sta2x11_apb_soc_regs_regmap_config = {
297 .reg_bits = 32,
298 .reg_stride = 4,
299 .val_bits = 32,
300 .lock = sta2x11_regmap_lock,
301 .unlock = sta2x11_regmap_unlock,
302 .max_register = TEST_CTL_REG,
303 .readable_reg = sta2x11_apb_soc_regs_readable_reg,
304 .writeable_reg = sta2x11_apb_soc_regs_writeable_reg,
305};
306
307static struct regmap_config *
308sta2x11_mfd_regmap_configs[sta2x11_n_mfd_plat_devs] = {
309 [sta2x11_sctl] = &sta2x11_sctl_regmap_config,
310 [sta2x11_apbreg] = &sta2x11_apbreg_regmap_config,
311 [sta2x11_apb_soc_regs] = &sta2x11_apb_soc_regs_regmap_config,
312 [sta2x11_scr] = &sta2x11_scr_regmap_config,
313};
314
315/* Probe for the four platform devices */
316
317static int sta2x11_mfd_platform_probe(struct platform_device *dev,
318 enum sta2x11_mfd_plat_dev index)
219{ 319{
220 struct pci_dev **pdev; 320 struct pci_dev **pdev;
221 struct sta2x11_mfd *mfd; 321 struct sta2x11_mfd *mfd;
222 struct resource *res; 322 struct resource *res;
323 const char *name = sta2x11_mfd_names[index];
324 struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
223 325
224 pdev = dev->dev.platform_data; 326 pdev = dev->dev.platform_data;
225 dev_dbg(&dev->dev, "%s: pdata is %p\n", __func__, pdev);
226 dev_dbg(&dev->dev, "%s: *pdata is %p\n", __func__, *pdev);
227
228 mfd = sta2x11_mfd_find(*pdev); 327 mfd = sta2x11_mfd_find(*pdev);
229 if (!mfd) 328 if (!mfd)
230 return -ENODEV; 329 return -ENODEV;
330 if (!regmap_config)
331 return -ENODEV;
231 332
232 res = platform_get_resource(dev, IORESOURCE_MEM, 0); 333 res = platform_get_resource(dev, IORESOURCE_MEM, 0);
233 if (!res) 334 if (!res)
234 return -ENOMEM; 335 return -ENOMEM;
235 336
236 if (!request_mem_region(res->start, resource_size(res), 337 if (!request_mem_region(res->start, resource_size(res), name))
237 "sta2x11-apbreg"))
238 return -EBUSY; 338 return -EBUSY;
239 339
240 mfd->apbreg_regs = ioremap(res->start, resource_size(res)); 340 mfd->regs[index] = ioremap(res->start, resource_size(res));
241 if (!mfd->apbreg_regs) { 341 if (!mfd->regs[index]) {
242 release_mem_region(res->start, resource_size(res)); 342 release_mem_region(res->start, resource_size(res));
243 return -ENOMEM; 343 return -ENOMEM;
244 } 344 }
245 dev_dbg(&dev->dev, "%s: regbase %p\n", __func__, mfd->apbreg_regs); 345 regmap_config->lock_arg = &mfd->lock;
346 /*
347 No caching, registers could be reached both via regmap and via
348 void __iomem *
349 */
350 regmap_config->cache_type = REGCACHE_NONE;
351 mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
352 regmap_config);
353 WARN_ON(!mfd->regmap[index]);
246 354
247 apbreg_regset.base = mfd->apbreg_regs;
248 sta2x11_apbreg_debugfs = debugfs_create_regset32("sta2x11-apbreg",
249 S_IFREG | S_IRUGO,
250 NULL, &apbreg_regset);
251 return 0; 355 return 0;
252} 356}
253 357
254/* The two platform drivers */ 358static int sta2x11_sctl_probe(struct platform_device *dev)
359{
360 return sta2x11_mfd_platform_probe(dev, sta2x11_sctl);
361}
362
363static int sta2x11_apbreg_probe(struct platform_device *dev)
364{
365 return sta2x11_mfd_platform_probe(dev, sta2x11_apbreg);
366}
367
368static int sta2x11_apb_soc_regs_probe(struct platform_device *dev)
369{
370 return sta2x11_mfd_platform_probe(dev, sta2x11_apb_soc_regs);
371}
372
373static int sta2x11_scr_probe(struct platform_device *dev)
374{
375 return sta2x11_mfd_platform_probe(dev, sta2x11_scr);
376}
377
378/* The three platform drivers */
255static struct platform_driver sta2x11_sctl_platform_driver = { 379static struct platform_driver sta2x11_sctl_platform_driver = {
256 .driver = { 380 .driver = {
257 .name = "sta2x11-sctl", 381 .name = STA2X11_MFD_SCTL_NAME,
258 .owner = THIS_MODULE, 382 .owner = THIS_MODULE,
259 }, 383 },
260 .probe = sta2x11_sctl_probe, 384 .probe = sta2x11_sctl_probe,
@@ -268,7 +392,7 @@ static int __init sta2x11_sctl_init(void)
268 392
269static struct platform_driver sta2x11_platform_driver = { 393static struct platform_driver sta2x11_platform_driver = {
270 .driver = { 394 .driver = {
271 .name = "sta2x11-apbreg", 395 .name = STA2X11_MFD_APBREG_NAME,
272 .owner = THIS_MODULE, 396 .owner = THIS_MODULE,
273 }, 397 },
274 .probe = sta2x11_apbreg_probe, 398 .probe = sta2x11_apbreg_probe,
@@ -280,13 +404,44 @@ static int __init sta2x11_apbreg_init(void)
280 return platform_driver_register(&sta2x11_platform_driver); 404 return platform_driver_register(&sta2x11_platform_driver);
281} 405}
282 406
407static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
408 .driver = {
409 .name = STA2X11_MFD_APB_SOC_REGS_NAME,
410 .owner = THIS_MODULE,
411 },
412 .probe = sta2x11_apb_soc_regs_probe,
413};
414
415static int __init sta2x11_apb_soc_regs_init(void)
416{
417 pr_info("%s\n", __func__);
418 return platform_driver_register(&sta2x11_apb_soc_regs_platform_driver);
419}
420
421static struct platform_driver sta2x11_scr_platform_driver = {
422 .driver = {
423 .name = STA2X11_MFD_SCR_NAME,
424 .owner = THIS_MODULE,
425 },
426 .probe = sta2x11_scr_probe,
427};
428
429static int __init sta2x11_scr_init(void)
430{
431 pr_info("%s\n", __func__);
432 return platform_driver_register(&sta2x11_scr_platform_driver);
433}
434
435
283/* 436/*
284 * What follows is the PCI device that hosts the above two pdevs. 437 * What follows are the PCI devices that host the above pdevs.
285 * Each logic block is 4kB and they are all consecutive: we use this info. 438 * Each logic block is 4kB and they are all consecutive: we use this info.
286 */ 439 */
287 440
288/* Bar 0 */ 441/* Mfd 0 device */
289enum bar0_cells { 442
443/* Mfd 0, Bar 0 */
444enum mfd0_bar0_cells {
290 STA2X11_GPIO_0 = 0, 445 STA2X11_GPIO_0 = 0,
291 STA2X11_GPIO_1, 446 STA2X11_GPIO_1,
292 STA2X11_GPIO_2, 447 STA2X11_GPIO_2,
@@ -295,8 +450,8 @@ enum bar0_cells {
295 STA2X11_SCR, 450 STA2X11_SCR,
296 STA2X11_TIME, 451 STA2X11_TIME,
297}; 452};
298/* Bar 1 */ 453/* Mfd 0 , Bar 1 */
299enum bar1_cells { 454enum mfd0_bar1_cells {
300 STA2X11_APBREG = 0, 455 STA2X11_APBREG = 0,
301}; 456};
302#define CELL_4K(_name, _cell) { \ 457#define CELL_4K(_name, _cell) { \
@@ -307,40 +462,71 @@ enum bar1_cells {
307 462
308static const struct resource gpio_resources[] = { 463static const struct resource gpio_resources[] = {
309 { 464 {
310 .name = "sta2x11_gpio", /* 4 consecutive cells, 1 driver */ 465 /* 4 consecutive cells, 1 driver */
466 .name = STA2X11_MFD_GPIO_NAME,
311 .start = 0, 467 .start = 0,
312 .end = (4 * 4096) - 1, 468 .end = (4 * 4096) - 1,
313 .flags = IORESOURCE_MEM, 469 .flags = IORESOURCE_MEM,
314 } 470 }
315}; 471};
316static const struct resource sctl_resources[] = { 472static const struct resource sctl_resources[] = {
317 CELL_4K("sta2x11-sctl", STA2X11_SCTL), 473 CELL_4K(STA2X11_MFD_SCTL_NAME, STA2X11_SCTL),
318}; 474};
319static const struct resource scr_resources[] = { 475static const struct resource scr_resources[] = {
320 CELL_4K("sta2x11-scr", STA2X11_SCR), 476 CELL_4K(STA2X11_MFD_SCR_NAME, STA2X11_SCR),
321}; 477};
322static const struct resource time_resources[] = { 478static const struct resource time_resources[] = {
323 CELL_4K("sta2x11-time", STA2X11_TIME), 479 CELL_4K(STA2X11_MFD_TIME_NAME, STA2X11_TIME),
324}; 480};
325 481
326static const struct resource apbreg_resources[] = { 482static const struct resource apbreg_resources[] = {
327 CELL_4K("sta2x11-apbreg", STA2X11_APBREG), 483 CELL_4K(STA2X11_MFD_APBREG_NAME, STA2X11_APBREG),
328}; 484};
329 485
330#define DEV(_name, _r) \ 486#define DEV(_name, _r) \
331 { .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, } 487 { .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, }
332 488
333static struct mfd_cell sta2x11_mfd_bar0[] = { 489static struct mfd_cell sta2x11_mfd0_bar0[] = {
334 DEV("sta2x11-gpio", gpio_resources), /* offset 0: we add pdata later */ 490 /* offset 0: we add pdata later */
335 DEV("sta2x11-sctl", sctl_resources), 491 DEV(STA2X11_MFD_GPIO_NAME, gpio_resources),
336 DEV("sta2x11-scr", scr_resources), 492 DEV(STA2X11_MFD_SCTL_NAME, sctl_resources),
337 DEV("sta2x11-time", time_resources), 493 DEV(STA2X11_MFD_SCR_NAME, scr_resources),
494 DEV(STA2X11_MFD_TIME_NAME, time_resources),
338}; 495};
339 496
340static struct mfd_cell sta2x11_mfd_bar1[] = { 497static struct mfd_cell sta2x11_mfd0_bar1[] = {
341 DEV("sta2x11-apbreg", apbreg_resources), 498 DEV(STA2X11_MFD_APBREG_NAME, apbreg_resources),
342}; 499};
343 500
501/* Mfd 1 devices */
502
503/* Mfd 1, Bar 0 */
504enum mfd1_bar0_cells {
505 STA2X11_VIC = 0,
506};
507
508/* Mfd 1, Bar 1 */
509enum mfd1_bar1_cells {
510 STA2X11_APB_SOC_REGS = 0,
511};
512
513static const __devinitconst struct resource vic_resources[] = {
514 CELL_4K(STA2X11_MFD_VIC_NAME, STA2X11_VIC),
515};
516
517static const __devinitconst struct resource apb_soc_regs_resources[] = {
518 CELL_4K(STA2X11_MFD_APB_SOC_REGS_NAME, STA2X11_APB_SOC_REGS),
519};
520
521static __devinitdata struct mfd_cell sta2x11_mfd1_bar0[] = {
522 DEV(STA2X11_MFD_VIC_NAME, vic_resources),
523};
524
525static __devinitdata struct mfd_cell sta2x11_mfd1_bar1[] = {
526 DEV(STA2X11_MFD_APB_SOC_REGS_NAME, apb_soc_regs_resources),
527};
528
529
344static int sta2x11_mfd_suspend(struct pci_dev *pdev, pm_message_t state) 530static int sta2x11_mfd_suspend(struct pci_dev *pdev, pm_message_t state)
345{ 531{
346 pci_save_state(pdev); 532 pci_save_state(pdev);
@@ -363,11 +549,63 @@ static int sta2x11_mfd_resume(struct pci_dev *pdev)
363 return 0; 549 return 0;
364} 550}
365 551
552struct sta2x11_mfd_bar_setup_data {
553 struct mfd_cell *cells;
554 int ncells;
555};
556
557struct sta2x11_mfd_setup_data {
558 struct sta2x11_mfd_bar_setup_data bars[2];
559};
560
561#define STA2X11_MFD0 0
562#define STA2X11_MFD1 1
563
564static struct sta2x11_mfd_setup_data mfd_setup_data[] = {
565 /* Mfd 0: gpio, sctl, scr, timers / apbregs */
566 [STA2X11_MFD0] = {
567 .bars = {
568 [0] = {
569 .cells = sta2x11_mfd0_bar0,
570 .ncells = ARRAY_SIZE(sta2x11_mfd0_bar0),
571 },
572 [1] = {
573 .cells = sta2x11_mfd0_bar1,
574 .ncells = ARRAY_SIZE(sta2x11_mfd0_bar1),
575 },
576 },
577 },
578 /* Mfd 1: vic / apb-soc-regs */
579 [STA2X11_MFD1] = {
580 .bars = {
581 [0] = {
582 .cells = sta2x11_mfd1_bar0,
583 .ncells = ARRAY_SIZE(sta2x11_mfd1_bar0),
584 },
585 [1] = {
586 .cells = sta2x11_mfd1_bar1,
587 .ncells = ARRAY_SIZE(sta2x11_mfd1_bar1),
588 },
589 },
590 },
591};
592
593static void sta2x11_mfd_setup(struct pci_dev *pdev,
594 struct sta2x11_mfd_setup_data *sd)
595{
596 int i, j;
597 for (i = 0; i < ARRAY_SIZE(sd->bars); i++)
598 for (j = 0; j < sd->bars[i].ncells; j++) {
599 sd->bars[i].cells[j].pdata_size = sizeof(pdev);
600 sd->bars[i].cells[j].platform_data = &pdev;
601 }
602}
603
366static int sta2x11_mfd_probe(struct pci_dev *pdev, 604static int sta2x11_mfd_probe(struct pci_dev *pdev,
367 const struct pci_device_id *pci_id) 605 const struct pci_device_id *pci_id)
368{ 606{
369 int err, i; 607 int err, i;
370 struct sta2x11_gpio_pdata *gpio_data; 608 struct sta2x11_mfd_setup_data *setup_data;
371 609
372 dev_info(&pdev->dev, "%s\n", __func__); 610 dev_info(&pdev->dev, "%s\n", __func__);
373 611
@@ -381,46 +619,29 @@ static int sta2x11_mfd_probe(struct pci_dev *pdev,
381 if (err) 619 if (err)
382 dev_info(&pdev->dev, "Enable msi failed\n"); 620 dev_info(&pdev->dev, "Enable msi failed\n");
383 621
384 /* Read gpio config data as pci device's platform data */ 622 setup_data = pci_id->device == PCI_DEVICE_ID_STMICRO_GPIO ?
385 gpio_data = dev_get_platdata(&pdev->dev); 623 &mfd_setup_data[STA2X11_MFD0] :
386 if (!gpio_data) 624 &mfd_setup_data[STA2X11_MFD1];
387 dev_warn(&pdev->dev, "no gpio configuration\n");
388
389 dev_dbg(&pdev->dev, "%s, gpio_data = %p (%p)\n", __func__,
390 gpio_data, &gpio_data);
391 dev_dbg(&pdev->dev, "%s, pdev = %p (%p)\n", __func__,
392 pdev, &pdev);
393 625
394 /* platform data is the pci device for all of them */ 626 /* platform data is the pci device for all of them */
395 for (i = 0; i < ARRAY_SIZE(sta2x11_mfd_bar0); i++) { 627 sta2x11_mfd_setup(pdev, setup_data);
396 sta2x11_mfd_bar0[i].pdata_size = sizeof(pdev);
397 sta2x11_mfd_bar0[i].platform_data = &pdev;
398 }
399 sta2x11_mfd_bar1[0].pdata_size = sizeof(pdev);
400 sta2x11_mfd_bar1[0].platform_data = &pdev;
401 628
402 /* Record this pdev before mfd_add_devices: their probe looks for it */ 629 /* Record this pdev before mfd_add_devices: their probe looks for it */
403 sta2x11_mfd_add(pdev, GFP_ATOMIC); 630 if (!sta2x11_mfd_find(pdev))
404 631 sta2x11_mfd_add(pdev, GFP_ATOMIC);
405 632
406 err = mfd_add_devices(&pdev->dev, -1, 633 /* Just 2 bars for all mfd's at present */
407 sta2x11_mfd_bar0, 634 for (i = 0; i < 2; i++) {
408 ARRAY_SIZE(sta2x11_mfd_bar0), 635 err = mfd_add_devices(&pdev->dev, -1,
409 &pdev->resource[0], 636 setup_data->bars[i].cells,
410 0, NULL); 637 setup_data->bars[i].ncells,
411 if (err) { 638 &pdev->resource[i],
412 dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err); 639 0, NULL);
413 goto err_disable; 640 if (err) {
414 } 641 dev_err(&pdev->dev,
415 642 "mfd_add_devices[%d] failed: %d\n", i, err);
416 err = mfd_add_devices(&pdev->dev, -1, 643 goto err_disable;
417 sta2x11_mfd_bar1, 644 }
418 ARRAY_SIZE(sta2x11_mfd_bar1),
419 &pdev->resource[1],
420 0, NULL);
421 if (err) {
422 dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err);
423 goto err_disable;
424 } 645 }
425 646
426 return 0; 647 return 0;
@@ -434,6 +655,7 @@ err_disable:
434 655
435static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = { 656static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = {
436 {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)}, 657 {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
658 {PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
437 {0,}, 659 {0,},
438}; 660};
439 661
@@ -459,6 +681,8 @@ static int __init sta2x11_mfd_init(void)
459 */ 681 */
460subsys_initcall(sta2x11_apbreg_init); 682subsys_initcall(sta2x11_apbreg_init);
461subsys_initcall(sta2x11_sctl_init); 683subsys_initcall(sta2x11_sctl_init);
684subsys_initcall(sta2x11_apb_soc_regs_init);
685subsys_initcall(sta2x11_scr_init);
462rootfs_initcall(sta2x11_mfd_init); 686rootfs_initcall(sta2x11_mfd_init);
463 687
464MODULE_LICENSE("GPL v2"); 688MODULE_LICENSE("GPL v2");