xref: /openbmc/linux/drivers/mfd/sta2x11-mfd.c (revision 6ceb5f17)
145051539SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
235bdd290SAlessandro Rubini /*
3cf090914SPaul Gortmaker  * STA2x11 mfd for GPIO, SCTL and APBREG
4cf090914SPaul Gortmaker  *
535bdd290SAlessandro Rubini  * Copyright (c) 2009-2011 Wind River Systems, Inc.
6b73df698SDavide Ciminaghi  * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
735bdd290SAlessandro Rubini  */
835bdd290SAlessandro Rubini 
935bdd290SAlessandro Rubini #include <linux/kernel.h>
10cf090914SPaul Gortmaker #include <linux/init.h>
11cf090914SPaul Gortmaker #include <linux/export.h>
1235bdd290SAlessandro Rubini #include <linux/spinlock.h>
1335bdd290SAlessandro Rubini #include <linux/errno.h>
1435bdd290SAlessandro Rubini #include <linux/device.h>
1535bdd290SAlessandro Rubini #include <linux/slab.h>
1635bdd290SAlessandro Rubini #include <linux/list.h>
1735bdd290SAlessandro Rubini #include <linux/io.h>
1835bdd290SAlessandro Rubini #include <linux/ioport.h>
1935bdd290SAlessandro Rubini #include <linux/pci.h>
2035bdd290SAlessandro Rubini #include <linux/seq_file.h>
2135bdd290SAlessandro Rubini #include <linux/platform_device.h>
2235bdd290SAlessandro Rubini #include <linux/mfd/core.h>
2335bdd290SAlessandro Rubini #include <linux/mfd/sta2x11-mfd.h>
24d94e2553SDavide Ciminaghi #include <linux/regmap.h>
2535bdd290SAlessandro Rubini 
2635bdd290SAlessandro Rubini #include <asm/sta2x11.h>
2735bdd290SAlessandro Rubini 
__reg_within_range(unsigned int r,unsigned int start,unsigned int end)28d94e2553SDavide Ciminaghi static inline int __reg_within_range(unsigned int r,
29d94e2553SDavide Ciminaghi 				     unsigned int start,
30d94e2553SDavide Ciminaghi 				     unsigned int end)
31d94e2553SDavide Ciminaghi {
32d94e2553SDavide Ciminaghi 	return ((r >= start) && (r <= end));
33d94e2553SDavide Ciminaghi }
34d94e2553SDavide Ciminaghi 
3535bdd290SAlessandro Rubini /* This describes STA2X11 MFD chip for us, we may have several */
3635bdd290SAlessandro Rubini struct sta2x11_mfd {
3735bdd290SAlessandro Rubini 	struct sta2x11_instance *instance;
38d94e2553SDavide Ciminaghi 	struct regmap *regmap[sta2x11_n_mfd_plat_devs];
39e885ba29SDavide Ciminaghi 	spinlock_t lock[sta2x11_n_mfd_plat_devs];
4035bdd290SAlessandro Rubini 	struct list_head list;
411950c716SDavide Ciminaghi 	void __iomem *regs[sta2x11_n_mfd_plat_devs];
4235bdd290SAlessandro Rubini };
4335bdd290SAlessandro Rubini 
4435bdd290SAlessandro Rubini static LIST_HEAD(sta2x11_mfd_list);
4535bdd290SAlessandro Rubini 
4635bdd290SAlessandro Rubini /* Three functions to act on the list */
sta2x11_mfd_find(struct pci_dev * pdev)4735bdd290SAlessandro Rubini static struct sta2x11_mfd *sta2x11_mfd_find(struct pci_dev *pdev)
4835bdd290SAlessandro Rubini {
4935bdd290SAlessandro Rubini 	struct sta2x11_instance *instance;
5035bdd290SAlessandro Rubini 	struct sta2x11_mfd *mfd;
5135bdd290SAlessandro Rubini 
5235bdd290SAlessandro Rubini 	if (!pdev && !list_empty(&sta2x11_mfd_list)) {
5381d30edaSJoe Perches 		pr_warn("%s: Unspecified device, using first instance\n",
5481d30edaSJoe Perches 			__func__);
5535bdd290SAlessandro Rubini 		return list_entry(sta2x11_mfd_list.next,
5635bdd290SAlessandro Rubini 				  struct sta2x11_mfd, list);
5735bdd290SAlessandro Rubini 	}
5835bdd290SAlessandro Rubini 
5935bdd290SAlessandro Rubini 	instance = sta2x11_get_instance(pdev);
6035bdd290SAlessandro Rubini 	if (!instance)
6135bdd290SAlessandro Rubini 		return NULL;
6235bdd290SAlessandro Rubini 	list_for_each_entry(mfd, &sta2x11_mfd_list, list) {
6335bdd290SAlessandro Rubini 		if (mfd->instance == instance)
6435bdd290SAlessandro Rubini 			return mfd;
6535bdd290SAlessandro Rubini 	}
6635bdd290SAlessandro Rubini 	return NULL;
6735bdd290SAlessandro Rubini }
6835bdd290SAlessandro Rubini 
sta2x11_mfd_add(struct pci_dev * pdev,gfp_t flags)69f791be49SBill Pemberton static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
7035bdd290SAlessandro Rubini {
71e885ba29SDavide Ciminaghi 	int i;
7235bdd290SAlessandro Rubini 	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
7335bdd290SAlessandro Rubini 	struct sta2x11_instance *instance;
7435bdd290SAlessandro Rubini 
7535bdd290SAlessandro Rubini 	if (mfd)
7635bdd290SAlessandro Rubini 		return -EBUSY;
7735bdd290SAlessandro Rubini 	instance = sta2x11_get_instance(pdev);
7835bdd290SAlessandro Rubini 	if (!instance)
7935bdd290SAlessandro Rubini 		return -EINVAL;
8035bdd290SAlessandro Rubini 	mfd = kzalloc(sizeof(*mfd), flags);
8135bdd290SAlessandro Rubini 	if (!mfd)
8235bdd290SAlessandro Rubini 		return -ENOMEM;
8335bdd290SAlessandro Rubini 	INIT_LIST_HEAD(&mfd->list);
84e885ba29SDavide Ciminaghi 	for (i = 0; i < ARRAY_SIZE(mfd->lock); i++)
85e885ba29SDavide Ciminaghi 		spin_lock_init(&mfd->lock[i]);
8635bdd290SAlessandro Rubini 	mfd->instance = instance;
8735bdd290SAlessandro Rubini 	list_add(&mfd->list, &sta2x11_mfd_list);
8835bdd290SAlessandro Rubini 	return 0;
8935bdd290SAlessandro Rubini }
9035bdd290SAlessandro Rubini 
911950c716SDavide Ciminaghi /* This function is exported and is not expected to fail */
__sta2x11_mfd_mask(struct pci_dev * pdev,u32 reg,u32 mask,u32 val,enum sta2x11_mfd_plat_dev index)921950c716SDavide Ciminaghi u32 __sta2x11_mfd_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val,
931950c716SDavide Ciminaghi 		       enum sta2x11_mfd_plat_dev index)
9435bdd290SAlessandro Rubini {
9535bdd290SAlessandro Rubini 	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
9635bdd290SAlessandro Rubini 	u32 r;
9735bdd290SAlessandro Rubini 	unsigned long flags;
98709edecdSWei Yongjun 	void __iomem *regs;
9935bdd290SAlessandro Rubini 
10035bdd290SAlessandro Rubini 	if (!mfd) {
10135bdd290SAlessandro Rubini 		dev_warn(&pdev->dev, ": can't access sctl regs\n");
10235bdd290SAlessandro Rubini 		return 0;
10335bdd290SAlessandro Rubini 	}
104709edecdSWei Yongjun 
105709edecdSWei Yongjun 	regs = mfd->regs[index];
1061950c716SDavide Ciminaghi 	if (!regs) {
10735bdd290SAlessandro Rubini 		dev_warn(&pdev->dev, ": system ctl not initialized\n");
10835bdd290SAlessandro Rubini 		return 0;
10935bdd290SAlessandro Rubini 	}
110e885ba29SDavide Ciminaghi 	spin_lock_irqsave(&mfd->lock[index], flags);
1111950c716SDavide Ciminaghi 	r = readl(regs + reg);
11235bdd290SAlessandro Rubini 	r &= ~mask;
11335bdd290SAlessandro Rubini 	r |= val;
11435bdd290SAlessandro Rubini 	if (mask)
1151950c716SDavide Ciminaghi 		writel(r, regs + reg);
116e885ba29SDavide Ciminaghi 	spin_unlock_irqrestore(&mfd->lock[index], flags);
11735bdd290SAlessandro Rubini 	return r;
11835bdd290SAlessandro Rubini }
1191950c716SDavide Ciminaghi EXPORT_SYMBOL(__sta2x11_mfd_mask);
12035bdd290SAlessandro Rubini 
sta2x11_mfd_get_regs_data(struct platform_device * dev,enum sta2x11_mfd_plat_dev index,void __iomem ** regs,spinlock_t ** lock)12129f5b5a3SDavide Ciminaghi int sta2x11_mfd_get_regs_data(struct platform_device *dev,
12229f5b5a3SDavide Ciminaghi 			      enum sta2x11_mfd_plat_dev index,
12329f5b5a3SDavide Ciminaghi 			      void __iomem **regs,
12429f5b5a3SDavide Ciminaghi 			      spinlock_t **lock)
12535bdd290SAlessandro Rubini {
126334a41ceSJingoo Han 	struct pci_dev *pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev);
12729f5b5a3SDavide Ciminaghi 	struct sta2x11_mfd *mfd;
12835bdd290SAlessandro Rubini 
12929f5b5a3SDavide Ciminaghi 	if (!pdev)
13029f5b5a3SDavide Ciminaghi 		return -ENODEV;
13129f5b5a3SDavide Ciminaghi 	mfd = sta2x11_mfd_find(pdev);
13229f5b5a3SDavide Ciminaghi 	if (!mfd)
13329f5b5a3SDavide Ciminaghi 		return -ENODEV;
13429f5b5a3SDavide Ciminaghi 	if (index >= sta2x11_n_mfd_plat_devs)
13529f5b5a3SDavide Ciminaghi 		return -ENODEV;
13629f5b5a3SDavide Ciminaghi 	*regs = mfd->regs[index];
13729f5b5a3SDavide Ciminaghi 	*lock = &mfd->lock[index];
13829f5b5a3SDavide Ciminaghi 	pr_debug("%s %d *regs = %p\n", __func__, __LINE__, *regs);
13929f5b5a3SDavide Ciminaghi 	return *regs ? 0 : -ENODEV;
14035bdd290SAlessandro Rubini }
14129f5b5a3SDavide Ciminaghi EXPORT_SYMBOL(sta2x11_mfd_get_regs_data);
14229f5b5a3SDavide Ciminaghi 
143d94e2553SDavide Ciminaghi /*
144d94e2553SDavide Ciminaghi  * Special sta2x11-mfd regmap lock/unlock functions
145d94e2553SDavide Ciminaghi  */
14635bdd290SAlessandro Rubini 
sta2x11_regmap_lock(void * __lock)147d94e2553SDavide Ciminaghi static void sta2x11_regmap_lock(void *__lock)
148d94e2553SDavide Ciminaghi {
149d94e2553SDavide Ciminaghi 	spinlock_t *lock = __lock;
150d94e2553SDavide Ciminaghi 	spin_lock(lock);
15135bdd290SAlessandro Rubini }
15235bdd290SAlessandro Rubini 
sta2x11_regmap_unlock(void * __lock)153d94e2553SDavide Ciminaghi static void sta2x11_regmap_unlock(void *__lock)
154d94e2553SDavide Ciminaghi {
155d94e2553SDavide Ciminaghi 	spinlock_t *lock = __lock;
156d94e2553SDavide Ciminaghi 	spin_unlock(lock);
15735bdd290SAlessandro Rubini }
15835bdd290SAlessandro Rubini 
159dba6c1aeSDavide Ciminaghi /* OTP (one time programmable registers do not require locking */
sta2x11_regmap_nolock(void * __lock)160dba6c1aeSDavide Ciminaghi static void sta2x11_regmap_nolock(void *__lock)
161dba6c1aeSDavide Ciminaghi {
162dba6c1aeSDavide Ciminaghi }
16335bdd290SAlessandro Rubini 
1641950c716SDavide Ciminaghi static const char *sta2x11_mfd_names[sta2x11_n_mfd_plat_devs] = {
165b18adafcSDavide Ciminaghi 	[sta2x11_sctl] = STA2X11_MFD_SCTL_NAME,
166b18adafcSDavide Ciminaghi 	[sta2x11_apbreg] = STA2X11_MFD_APBREG_NAME,
167b18adafcSDavide Ciminaghi 	[sta2x11_apb_soc_regs] = STA2X11_MFD_APB_SOC_REGS_NAME,
168dba6c1aeSDavide Ciminaghi 	[sta2x11_scr] = STA2X11_MFD_SCR_NAME,
16935bdd290SAlessandro Rubini };
17035bdd290SAlessandro Rubini 
sta2x11_sctl_writeable_reg(struct device * dev,unsigned int reg)171d94e2553SDavide Ciminaghi static bool sta2x11_sctl_writeable_reg(struct device *dev, unsigned int reg)
172d94e2553SDavide Ciminaghi {
173d94e2553SDavide Ciminaghi 	return !__reg_within_range(reg, SCTL_SCPCIECSBRST, SCTL_SCRSTSTA);
174d94e2553SDavide Ciminaghi }
17535bdd290SAlessandro Rubini 
176d94e2553SDavide Ciminaghi static struct regmap_config sta2x11_sctl_regmap_config = {
177d94e2553SDavide Ciminaghi 	.reg_bits = 32,
178d94e2553SDavide Ciminaghi 	.reg_stride = 4,
179d94e2553SDavide Ciminaghi 	.val_bits = 32,
180d94e2553SDavide Ciminaghi 	.lock = sta2x11_regmap_lock,
181d94e2553SDavide Ciminaghi 	.unlock = sta2x11_regmap_unlock,
182d94e2553SDavide Ciminaghi 	.max_register = SCTL_SCRSTSTA,
183d94e2553SDavide Ciminaghi 	.writeable_reg = sta2x11_sctl_writeable_reg,
18435bdd290SAlessandro Rubini };
18535bdd290SAlessandro Rubini 
sta2x11_scr_readable_reg(struct device * dev,unsigned int reg)186dba6c1aeSDavide Ciminaghi static bool sta2x11_scr_readable_reg(struct device *dev, unsigned int reg)
187dba6c1aeSDavide Ciminaghi {
188dba6c1aeSDavide Ciminaghi 	return (reg == STA2X11_SECR_CR) ||
189dba6c1aeSDavide Ciminaghi 		__reg_within_range(reg, STA2X11_SECR_FVR0, STA2X11_SECR_FVR1);
190dba6c1aeSDavide Ciminaghi }
19135bdd290SAlessandro Rubini 
sta2x11_scr_writeable_reg(struct device * dev,unsigned int reg)192dba6c1aeSDavide Ciminaghi static bool sta2x11_scr_writeable_reg(struct device *dev, unsigned int reg)
193dba6c1aeSDavide Ciminaghi {
194dba6c1aeSDavide Ciminaghi 	return false;
195dba6c1aeSDavide Ciminaghi }
196dba6c1aeSDavide Ciminaghi 
197dba6c1aeSDavide Ciminaghi static struct regmap_config sta2x11_scr_regmap_config = {
198dba6c1aeSDavide Ciminaghi 	.reg_bits = 32,
199dba6c1aeSDavide Ciminaghi 	.reg_stride = 4,
200dba6c1aeSDavide Ciminaghi 	.val_bits = 32,
201dba6c1aeSDavide Ciminaghi 	.lock = sta2x11_regmap_nolock,
202dba6c1aeSDavide Ciminaghi 	.unlock = sta2x11_regmap_nolock,
203dba6c1aeSDavide Ciminaghi 	.max_register = STA2X11_SECR_FVR1,
204dba6c1aeSDavide Ciminaghi 	.readable_reg = sta2x11_scr_readable_reg,
205dba6c1aeSDavide Ciminaghi 	.writeable_reg = sta2x11_scr_writeable_reg,
206dba6c1aeSDavide Ciminaghi };
207dba6c1aeSDavide Ciminaghi 
sta2x11_apbreg_readable_reg(struct device * dev,unsigned int reg)208d94e2553SDavide Ciminaghi static bool sta2x11_apbreg_readable_reg(struct device *dev, unsigned int reg)
209d94e2553SDavide Ciminaghi {
210d94e2553SDavide Ciminaghi 	/* Two blocks (CAN and MLB, SARAC) 0x100 bytes apart */
211d94e2553SDavide Ciminaghi 	if (reg >= APBREG_BSR_SARAC)
212d94e2553SDavide Ciminaghi 		reg -= APBREG_BSR_SARAC;
213d94e2553SDavide Ciminaghi 	switch (reg) {
214d94e2553SDavide Ciminaghi 	case APBREG_BSR:
215d94e2553SDavide Ciminaghi 	case APBREG_PAER:
216d94e2553SDavide Ciminaghi 	case APBREG_PWAC:
217d94e2553SDavide Ciminaghi 	case APBREG_PRAC:
218d94e2553SDavide Ciminaghi 	case APBREG_PCG:
219d94e2553SDavide Ciminaghi 	case APBREG_PUR:
220d94e2553SDavide Ciminaghi 	case APBREG_EMU_PCG:
221d94e2553SDavide Ciminaghi 		return true;
222d94e2553SDavide Ciminaghi 	default:
223d94e2553SDavide Ciminaghi 		return false;
224d94e2553SDavide Ciminaghi 	}
225d94e2553SDavide Ciminaghi }
226d94e2553SDavide Ciminaghi 
sta2x11_apbreg_writeable_reg(struct device * dev,unsigned int reg)227d94e2553SDavide Ciminaghi static bool sta2x11_apbreg_writeable_reg(struct device *dev, unsigned int reg)
228d94e2553SDavide Ciminaghi {
229d94e2553SDavide Ciminaghi 	if (reg >= APBREG_BSR_SARAC)
230d94e2553SDavide Ciminaghi 		reg -= APBREG_BSR_SARAC;
231d94e2553SDavide Ciminaghi 	if (!sta2x11_apbreg_readable_reg(dev, reg))
232d94e2553SDavide Ciminaghi 		return false;
233d94e2553SDavide Ciminaghi 	return reg != APBREG_PAER;
234d94e2553SDavide Ciminaghi }
235d94e2553SDavide Ciminaghi 
236d94e2553SDavide Ciminaghi static struct regmap_config sta2x11_apbreg_regmap_config = {
237d94e2553SDavide Ciminaghi 	.reg_bits = 32,
238d94e2553SDavide Ciminaghi 	.reg_stride = 4,
239d94e2553SDavide Ciminaghi 	.val_bits = 32,
240d94e2553SDavide Ciminaghi 	.lock = sta2x11_regmap_lock,
241d94e2553SDavide Ciminaghi 	.unlock = sta2x11_regmap_unlock,
242d94e2553SDavide Ciminaghi 	.max_register = APBREG_EMU_PCG_SARAC,
243d94e2553SDavide Ciminaghi 	.readable_reg = sta2x11_apbreg_readable_reg,
244d94e2553SDavide Ciminaghi 	.writeable_reg = sta2x11_apbreg_writeable_reg,
245d94e2553SDavide Ciminaghi };
246d94e2553SDavide Ciminaghi 
sta2x11_apb_soc_regs_readable_reg(struct device * dev,unsigned int reg)247d94e2553SDavide Ciminaghi static bool sta2x11_apb_soc_regs_readable_reg(struct device *dev,
248d94e2553SDavide Ciminaghi 					      unsigned int reg)
249d94e2553SDavide Ciminaghi {
250d94e2553SDavide Ciminaghi 	return reg <= PCIE_SoC_INT_ROUTER_STATUS3_REG ||
251d94e2553SDavide Ciminaghi 		__reg_within_range(reg, DMA_IP_CTRL_REG, SPARE3_RESERVED) ||
252d94e2553SDavide Ciminaghi 		__reg_within_range(reg, MASTER_LOCK_REG,
253d94e2553SDavide Ciminaghi 				   SYSTEM_CONFIG_STATUS_REG) ||
254d94e2553SDavide Ciminaghi 		reg == MSP_CLK_CTRL_REG ||
255d94e2553SDavide Ciminaghi 		__reg_within_range(reg, COMPENSATION_REG1, TEST_CTL_REG);
256d94e2553SDavide Ciminaghi }
257d94e2553SDavide Ciminaghi 
sta2x11_apb_soc_regs_writeable_reg(struct device * dev,unsigned int reg)258d94e2553SDavide Ciminaghi static bool sta2x11_apb_soc_regs_writeable_reg(struct device *dev,
259d94e2553SDavide Ciminaghi 					       unsigned int reg)
260d94e2553SDavide Ciminaghi {
261d94e2553SDavide Ciminaghi 	if (!sta2x11_apb_soc_regs_readable_reg(dev, reg))
262d94e2553SDavide Ciminaghi 		return false;
263d94e2553SDavide Ciminaghi 	switch (reg) {
264d94e2553SDavide Ciminaghi 	case PCIE_COMMON_CLOCK_CONFIG_0_4_0:
265d94e2553SDavide Ciminaghi 	case SYSTEM_CONFIG_STATUS_REG:
266d94e2553SDavide Ciminaghi 	case COMPENSATION_REG1:
267d94e2553SDavide Ciminaghi 	case PCIE_SoC_INT_ROUTER_STATUS0_REG...PCIE_SoC_INT_ROUTER_STATUS3_REG:
268d94e2553SDavide Ciminaghi 	case PCIE_PM_STATUS_0_PORT_0_4...PCIE_PM_STATUS_7_0_EP4:
269d94e2553SDavide Ciminaghi 		return false;
270d94e2553SDavide Ciminaghi 	default:
271d94e2553SDavide Ciminaghi 		return true;
272d94e2553SDavide Ciminaghi 	}
273d94e2553SDavide Ciminaghi }
274d94e2553SDavide Ciminaghi 
275d94e2553SDavide Ciminaghi static struct regmap_config sta2x11_apb_soc_regs_regmap_config = {
276d94e2553SDavide Ciminaghi 	.reg_bits = 32,
277d94e2553SDavide Ciminaghi 	.reg_stride = 4,
278d94e2553SDavide Ciminaghi 	.val_bits = 32,
279d94e2553SDavide Ciminaghi 	.lock = sta2x11_regmap_lock,
280d94e2553SDavide Ciminaghi 	.unlock = sta2x11_regmap_unlock,
281d94e2553SDavide Ciminaghi 	.max_register = TEST_CTL_REG,
282d94e2553SDavide Ciminaghi 	.readable_reg = sta2x11_apb_soc_regs_readable_reg,
283d94e2553SDavide Ciminaghi 	.writeable_reg = sta2x11_apb_soc_regs_writeable_reg,
284d94e2553SDavide Ciminaghi };
285d94e2553SDavide Ciminaghi 
286d94e2553SDavide Ciminaghi static struct regmap_config *
287d94e2553SDavide Ciminaghi sta2x11_mfd_regmap_configs[sta2x11_n_mfd_plat_devs] = {
288d94e2553SDavide Ciminaghi 	[sta2x11_sctl] = &sta2x11_sctl_regmap_config,
289d94e2553SDavide Ciminaghi 	[sta2x11_apbreg] = &sta2x11_apbreg_regmap_config,
290d94e2553SDavide Ciminaghi 	[sta2x11_apb_soc_regs] = &sta2x11_apb_soc_regs_regmap_config,
291dba6c1aeSDavide Ciminaghi 	[sta2x11_scr] = &sta2x11_scr_regmap_config,
292d94e2553SDavide Ciminaghi };
293d94e2553SDavide Ciminaghi 
294dba6c1aeSDavide Ciminaghi /* Probe for the four platform devices */
2951950c716SDavide Ciminaghi 
sta2x11_mfd_platform_probe(struct platform_device * dev,enum sta2x11_mfd_plat_dev index)2961950c716SDavide Ciminaghi static int sta2x11_mfd_platform_probe(struct platform_device *dev,
2971950c716SDavide Ciminaghi 				      enum sta2x11_mfd_plat_dev index)
29835bdd290SAlessandro Rubini {
29935bdd290SAlessandro Rubini 	struct pci_dev **pdev;
30035bdd290SAlessandro Rubini 	struct sta2x11_mfd *mfd;
30135bdd290SAlessandro Rubini 	struct resource *res;
3021950c716SDavide Ciminaghi 	const char *name = sta2x11_mfd_names[index];
303d94e2553SDavide Ciminaghi 	struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
30435bdd290SAlessandro Rubini 
305334a41ceSJingoo Han 	pdev = dev_get_platdata(&dev->dev);
30635bdd290SAlessandro Rubini 	mfd = sta2x11_mfd_find(*pdev);
30735bdd290SAlessandro Rubini 	if (!mfd)
30835bdd290SAlessandro Rubini 		return -ENODEV;
309d94e2553SDavide Ciminaghi 	if (!regmap_config)
310d94e2553SDavide Ciminaghi 		return -ENODEV;
31135bdd290SAlessandro Rubini 
31235bdd290SAlessandro Rubini 	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
31335bdd290SAlessandro Rubini 	if (!res)
31435bdd290SAlessandro Rubini 		return -ENOMEM;
31535bdd290SAlessandro Rubini 
3161950c716SDavide Ciminaghi 	if (!request_mem_region(res->start, resource_size(res), name))
31735bdd290SAlessandro Rubini 		return -EBUSY;
31835bdd290SAlessandro Rubini 
3191950c716SDavide Ciminaghi 	mfd->regs[index] = ioremap(res->start, resource_size(res));
3201950c716SDavide Ciminaghi 	if (!mfd->regs[index]) {
32135bdd290SAlessandro Rubini 		release_mem_region(res->start, resource_size(res));
32235bdd290SAlessandro Rubini 		return -ENOMEM;
32335bdd290SAlessandro Rubini 	}
324d94e2553SDavide Ciminaghi 	regmap_config->lock_arg = &mfd->lock;
325d94e2553SDavide Ciminaghi 	/*
326d94e2553SDavide Ciminaghi 	   No caching, registers could be reached both via regmap and via
327d94e2553SDavide Ciminaghi 	   void __iomem *
328d94e2553SDavide Ciminaghi 	*/
329d94e2553SDavide Ciminaghi 	regmap_config->cache_type = REGCACHE_NONE;
330d94e2553SDavide Ciminaghi 	mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
331d94e2553SDavide Ciminaghi 						   regmap_config);
332ec9e4ba6SWei Yongjun 	WARN_ON(IS_ERR(mfd->regmap[index]));
333d94e2553SDavide Ciminaghi 
33435bdd290SAlessandro Rubini 	return 0;
33535bdd290SAlessandro Rubini }
33635bdd290SAlessandro Rubini 
sta2x11_sctl_probe(struct platform_device * dev)3371950c716SDavide Ciminaghi static int sta2x11_sctl_probe(struct platform_device *dev)
3381950c716SDavide Ciminaghi {
3391950c716SDavide Ciminaghi 	return sta2x11_mfd_platform_probe(dev, sta2x11_sctl);
3401950c716SDavide Ciminaghi }
3411950c716SDavide Ciminaghi 
sta2x11_apbreg_probe(struct platform_device * dev)34235bdd290SAlessandro Rubini static int sta2x11_apbreg_probe(struct platform_device *dev)
34335bdd290SAlessandro Rubini {
3441950c716SDavide Ciminaghi 	return sta2x11_mfd_platform_probe(dev, sta2x11_apbreg);
34535bdd290SAlessandro Rubini }
34635bdd290SAlessandro Rubini 
sta2x11_apb_soc_regs_probe(struct platform_device * dev)3471950c716SDavide Ciminaghi static int sta2x11_apb_soc_regs_probe(struct platform_device *dev)
3481950c716SDavide Ciminaghi {
3491950c716SDavide Ciminaghi 	return sta2x11_mfd_platform_probe(dev, sta2x11_apb_soc_regs);
3501950c716SDavide Ciminaghi }
3511950c716SDavide Ciminaghi 
sta2x11_scr_probe(struct platform_device * dev)352dba6c1aeSDavide Ciminaghi static int sta2x11_scr_probe(struct platform_device *dev)
353dba6c1aeSDavide Ciminaghi {
354dba6c1aeSDavide Ciminaghi 	return sta2x11_mfd_platform_probe(dev, sta2x11_scr);
355dba6c1aeSDavide Ciminaghi }
356dba6c1aeSDavide Ciminaghi 
3571950c716SDavide Ciminaghi /* The three platform drivers */
35835bdd290SAlessandro Rubini static struct platform_driver sta2x11_sctl_platform_driver = {
35935bdd290SAlessandro Rubini 	.driver = {
360b18adafcSDavide Ciminaghi 		.name	= STA2X11_MFD_SCTL_NAME,
36135bdd290SAlessandro Rubini 	},
36235bdd290SAlessandro Rubini 	.probe		= sta2x11_sctl_probe,
36335bdd290SAlessandro Rubini };
36435bdd290SAlessandro Rubini 
36535bdd290SAlessandro Rubini static struct platform_driver sta2x11_platform_driver = {
36635bdd290SAlessandro Rubini 	.driver = {
367b18adafcSDavide Ciminaghi 		.name	= STA2X11_MFD_APBREG_NAME,
36835bdd290SAlessandro Rubini 	},
36935bdd290SAlessandro Rubini 	.probe		= sta2x11_apbreg_probe,
37035bdd290SAlessandro Rubini };
37135bdd290SAlessandro Rubini 
3721950c716SDavide Ciminaghi static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
3731950c716SDavide Ciminaghi 	.driver = {
374b18adafcSDavide Ciminaghi 		.name	= STA2X11_MFD_APB_SOC_REGS_NAME,
3751950c716SDavide Ciminaghi 	},
3761950c716SDavide Ciminaghi 	.probe		= sta2x11_apb_soc_regs_probe,
3771950c716SDavide Ciminaghi };
3781950c716SDavide Ciminaghi 
379dba6c1aeSDavide Ciminaghi static struct platform_driver sta2x11_scr_platform_driver = {
380dba6c1aeSDavide Ciminaghi 	.driver = {
381dba6c1aeSDavide Ciminaghi 		.name = STA2X11_MFD_SCR_NAME,
382dba6c1aeSDavide Ciminaghi 	},
383dba6c1aeSDavide Ciminaghi 	.probe = sta2x11_scr_probe,
384dba6c1aeSDavide Ciminaghi };
385dba6c1aeSDavide Ciminaghi 
386d91d76d8SThierry Reding static struct platform_driver * const drivers[] = {
387d91d76d8SThierry Reding 	&sta2x11_platform_driver,
388d91d76d8SThierry Reding 	&sta2x11_sctl_platform_driver,
389d91d76d8SThierry Reding 	&sta2x11_apb_soc_regs_platform_driver,
390d91d76d8SThierry Reding 	&sta2x11_scr_platform_driver,
391d91d76d8SThierry Reding };
392dba6c1aeSDavide Ciminaghi 
sta2x11_drivers_init(void)393d91d76d8SThierry Reding static int __init sta2x11_drivers_init(void)
394d91d76d8SThierry Reding {
395d91d76d8SThierry Reding 	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
396d91d76d8SThierry Reding }
397dba6c1aeSDavide Ciminaghi 
39835bdd290SAlessandro Rubini /*
3991950c716SDavide Ciminaghi  * What follows are the PCI devices that host the above pdevs.
40035bdd290SAlessandro Rubini  * Each logic block is 4kB and they are all consecutive: we use this info.
40135bdd290SAlessandro Rubini  */
40235bdd290SAlessandro Rubini 
4031950c716SDavide Ciminaghi /* Mfd 0 device */
4041950c716SDavide Ciminaghi 
4051950c716SDavide Ciminaghi /* Mfd 0, Bar 0 */
4061950c716SDavide Ciminaghi enum mfd0_bar0_cells {
40735bdd290SAlessandro Rubini 	STA2X11_GPIO_0 = 0,
40835bdd290SAlessandro Rubini 	STA2X11_GPIO_1,
40935bdd290SAlessandro Rubini 	STA2X11_GPIO_2,
41035bdd290SAlessandro Rubini 	STA2X11_GPIO_3,
41135bdd290SAlessandro Rubini 	STA2X11_SCTL,
41235bdd290SAlessandro Rubini 	STA2X11_SCR,
41335bdd290SAlessandro Rubini 	STA2X11_TIME,
41435bdd290SAlessandro Rubini };
4151950c716SDavide Ciminaghi /* Mfd 0 , Bar 1 */
4161950c716SDavide Ciminaghi enum mfd0_bar1_cells {
41735bdd290SAlessandro Rubini 	STA2X11_APBREG = 0,
41835bdd290SAlessandro Rubini };
41935bdd290SAlessandro Rubini #define CELL_4K(_name, _cell) { \
42035bdd290SAlessandro Rubini 		.name = _name, \
42135bdd290SAlessandro Rubini 		.start = _cell * 4096, .end = _cell * 4096 + 4095, \
42235bdd290SAlessandro Rubini 		.flags = IORESOURCE_MEM, \
42335bdd290SAlessandro Rubini 		}
42435bdd290SAlessandro Rubini 
425a73e5df1SBill Pemberton static const struct resource gpio_resources[] = {
42635bdd290SAlessandro Rubini 	{
427b18adafcSDavide Ciminaghi 		/* 4 consecutive cells, 1 driver */
428b18adafcSDavide Ciminaghi 		.name = STA2X11_MFD_GPIO_NAME,
42935bdd290SAlessandro Rubini 		.start = 0,
43035bdd290SAlessandro Rubini 		.end = (4 * 4096) - 1,
43135bdd290SAlessandro Rubini 		.flags = IORESOURCE_MEM,
43235bdd290SAlessandro Rubini 	}
43335bdd290SAlessandro Rubini };
434a73e5df1SBill Pemberton static const struct resource sctl_resources[] = {
435b18adafcSDavide Ciminaghi 	CELL_4K(STA2X11_MFD_SCTL_NAME, STA2X11_SCTL),
43635bdd290SAlessandro Rubini };
437a73e5df1SBill Pemberton static const struct resource scr_resources[] = {
438b18adafcSDavide Ciminaghi 	CELL_4K(STA2X11_MFD_SCR_NAME, STA2X11_SCR),
43935bdd290SAlessandro Rubini };
440a73e5df1SBill Pemberton static const struct resource time_resources[] = {
441b18adafcSDavide Ciminaghi 	CELL_4K(STA2X11_MFD_TIME_NAME, STA2X11_TIME),
44235bdd290SAlessandro Rubini };
44335bdd290SAlessandro Rubini 
444a73e5df1SBill Pemberton static const struct resource apbreg_resources[] = {
445b18adafcSDavide Ciminaghi 	CELL_4K(STA2X11_MFD_APBREG_NAME, STA2X11_APBREG),
44635bdd290SAlessandro Rubini };
44735bdd290SAlessandro Rubini 
44835bdd290SAlessandro Rubini #define DEV(_name, _r) \
44935bdd290SAlessandro Rubini 	{ .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, }
45035bdd290SAlessandro Rubini 
4512dfea380SLinus Torvalds static struct mfd_cell sta2x11_mfd0_bar0[] = {
452b18adafcSDavide Ciminaghi 	/* offset 0: we add pdata later */
453b18adafcSDavide Ciminaghi 	DEV(STA2X11_MFD_GPIO_NAME, gpio_resources),
454b18adafcSDavide Ciminaghi 	DEV(STA2X11_MFD_SCTL_NAME, sctl_resources),
455b18adafcSDavide Ciminaghi 	DEV(STA2X11_MFD_SCR_NAME,  scr_resources),
456b18adafcSDavide Ciminaghi 	DEV(STA2X11_MFD_TIME_NAME, time_resources),
45735bdd290SAlessandro Rubini };
45835bdd290SAlessandro Rubini 
4592dfea380SLinus Torvalds static struct mfd_cell sta2x11_mfd0_bar1[] = {
460b18adafcSDavide Ciminaghi 	DEV(STA2X11_MFD_APBREG_NAME, apbreg_resources),
46135bdd290SAlessandro Rubini };
46235bdd290SAlessandro Rubini 
4631950c716SDavide Ciminaghi /* Mfd 1 devices */
4641950c716SDavide Ciminaghi 
4651950c716SDavide Ciminaghi /* Mfd 1, Bar 0 */
4661950c716SDavide Ciminaghi enum mfd1_bar0_cells {
4671950c716SDavide Ciminaghi 	STA2X11_VIC = 0,
4681950c716SDavide Ciminaghi };
4691950c716SDavide Ciminaghi 
4701950c716SDavide Ciminaghi /* Mfd 1, Bar 1 */
4711950c716SDavide Ciminaghi enum mfd1_bar1_cells {
4721950c716SDavide Ciminaghi 	STA2X11_APB_SOC_REGS = 0,
4731950c716SDavide Ciminaghi };
4741950c716SDavide Ciminaghi 
475612b95cdSGreg Kroah-Hartman static const struct resource vic_resources[] = {
476b18adafcSDavide Ciminaghi 	CELL_4K(STA2X11_MFD_VIC_NAME, STA2X11_VIC),
4771950c716SDavide Ciminaghi };
4781950c716SDavide Ciminaghi 
479612b95cdSGreg Kroah-Hartman static const struct resource apb_soc_regs_resources[] = {
480b18adafcSDavide Ciminaghi 	CELL_4K(STA2X11_MFD_APB_SOC_REGS_NAME, STA2X11_APB_SOC_REGS),
4811950c716SDavide Ciminaghi };
4821950c716SDavide Ciminaghi 
483612b95cdSGreg Kroah-Hartman static struct mfd_cell sta2x11_mfd1_bar0[] = {
484b18adafcSDavide Ciminaghi 	DEV(STA2X11_MFD_VIC_NAME, vic_resources),
4851950c716SDavide Ciminaghi };
4861950c716SDavide Ciminaghi 
487612b95cdSGreg Kroah-Hartman static struct mfd_cell sta2x11_mfd1_bar1[] = {
488b18adafcSDavide Ciminaghi 	DEV(STA2X11_MFD_APB_SOC_REGS_NAME, apb_soc_regs_resources),
4891950c716SDavide Ciminaghi };
4901950c716SDavide Ciminaghi 
4911950c716SDavide Ciminaghi 
sta2x11_mfd_suspend(struct pci_dev * pdev,pm_message_t state)49235bdd290SAlessandro Rubini static int sta2x11_mfd_suspend(struct pci_dev *pdev, pm_message_t state)
49335bdd290SAlessandro Rubini {
49435bdd290SAlessandro Rubini 	pci_save_state(pdev);
49535bdd290SAlessandro Rubini 	pci_disable_device(pdev);
49635bdd290SAlessandro Rubini 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
49735bdd290SAlessandro Rubini 
49835bdd290SAlessandro Rubini 	return 0;
49935bdd290SAlessandro Rubini }
50035bdd290SAlessandro Rubini 
sta2x11_mfd_resume(struct pci_dev * pdev)50135bdd290SAlessandro Rubini static int sta2x11_mfd_resume(struct pci_dev *pdev)
50235bdd290SAlessandro Rubini {
50335bdd290SAlessandro Rubini 	int err;
50435bdd290SAlessandro Rubini 
5054d1d9980SJulia Lawall 	pci_set_power_state(pdev, PCI_D0);
50635bdd290SAlessandro Rubini 	err = pci_enable_device(pdev);
50735bdd290SAlessandro Rubini 	if (err)
50835bdd290SAlessandro Rubini 		return err;
50935bdd290SAlessandro Rubini 	pci_restore_state(pdev);
51035bdd290SAlessandro Rubini 
51135bdd290SAlessandro Rubini 	return 0;
51235bdd290SAlessandro Rubini }
51335bdd290SAlessandro Rubini 
5141950c716SDavide Ciminaghi struct sta2x11_mfd_bar_setup_data {
5151950c716SDavide Ciminaghi 	struct mfd_cell *cells;
5161950c716SDavide Ciminaghi 	int ncells;
5171950c716SDavide Ciminaghi };
5181950c716SDavide Ciminaghi 
5191950c716SDavide Ciminaghi struct sta2x11_mfd_setup_data {
5201950c716SDavide Ciminaghi 	struct sta2x11_mfd_bar_setup_data bars[2];
5211950c716SDavide Ciminaghi };
5221950c716SDavide Ciminaghi 
5231950c716SDavide Ciminaghi #define STA2X11_MFD0 0
5241950c716SDavide Ciminaghi #define STA2X11_MFD1 1
5251950c716SDavide Ciminaghi 
5261950c716SDavide Ciminaghi static struct sta2x11_mfd_setup_data mfd_setup_data[] = {
5271950c716SDavide Ciminaghi 	/* Mfd 0: gpio, sctl, scr, timers / apbregs */
5281950c716SDavide Ciminaghi 	[STA2X11_MFD0] = {
5291950c716SDavide Ciminaghi 		.bars = {
5301950c716SDavide Ciminaghi 			[0] = {
5311950c716SDavide Ciminaghi 				.cells = sta2x11_mfd0_bar0,
5321950c716SDavide Ciminaghi 				.ncells = ARRAY_SIZE(sta2x11_mfd0_bar0),
5331950c716SDavide Ciminaghi 			},
5341950c716SDavide Ciminaghi 			[1] = {
5351950c716SDavide Ciminaghi 				.cells = sta2x11_mfd0_bar1,
5361950c716SDavide Ciminaghi 				.ncells = ARRAY_SIZE(sta2x11_mfd0_bar1),
5371950c716SDavide Ciminaghi 			},
5381950c716SDavide Ciminaghi 		},
5391950c716SDavide Ciminaghi 	},
5401950c716SDavide Ciminaghi 	/* Mfd 1: vic / apb-soc-regs */
5411950c716SDavide Ciminaghi 	[STA2X11_MFD1] = {
5421950c716SDavide Ciminaghi 		.bars = {
5431950c716SDavide Ciminaghi 			[0] = {
5441950c716SDavide Ciminaghi 				.cells = sta2x11_mfd1_bar0,
5451950c716SDavide Ciminaghi 				.ncells = ARRAY_SIZE(sta2x11_mfd1_bar0),
5461950c716SDavide Ciminaghi 			},
5471950c716SDavide Ciminaghi 			[1] = {
5481950c716SDavide Ciminaghi 				.cells = sta2x11_mfd1_bar1,
5491950c716SDavide Ciminaghi 				.ncells = ARRAY_SIZE(sta2x11_mfd1_bar1),
5501950c716SDavide Ciminaghi 			},
5511950c716SDavide Ciminaghi 		},
5521950c716SDavide Ciminaghi 	},
5531950c716SDavide Ciminaghi };
5541950c716SDavide Ciminaghi 
sta2x11_mfd_setup(struct pci_dev * pdev,struct sta2x11_mfd_setup_data * sd)5552dfea380SLinus Torvalds static void sta2x11_mfd_setup(struct pci_dev *pdev,
5561950c716SDavide Ciminaghi 			      struct sta2x11_mfd_setup_data *sd)
5571950c716SDavide Ciminaghi {
5581950c716SDavide Ciminaghi 	int i, j;
5591950c716SDavide Ciminaghi 	for (i = 0; i < ARRAY_SIZE(sd->bars); i++)
5601950c716SDavide Ciminaghi 		for (j = 0; j < sd->bars[i].ncells; j++) {
5611950c716SDavide Ciminaghi 			sd->bars[i].cells[j].pdata_size = sizeof(pdev);
5621950c716SDavide Ciminaghi 			sd->bars[i].cells[j].platform_data = &pdev;
5631950c716SDavide Ciminaghi 		}
5641950c716SDavide Ciminaghi }
5651950c716SDavide Ciminaghi 
sta2x11_mfd_probe(struct pci_dev * pdev,const struct pci_device_id * pci_id)566f791be49SBill Pemberton static int sta2x11_mfd_probe(struct pci_dev *pdev,
56735bdd290SAlessandro Rubini 			     const struct pci_device_id *pci_id)
56835bdd290SAlessandro Rubini {
56935bdd290SAlessandro Rubini 	int err, i;
5701950c716SDavide Ciminaghi 	struct sta2x11_mfd_setup_data *setup_data;
57135bdd290SAlessandro Rubini 
57235bdd290SAlessandro Rubini 	dev_info(&pdev->dev, "%s\n", __func__);
57335bdd290SAlessandro Rubini 
57435bdd290SAlessandro Rubini 	err = pci_enable_device(pdev);
57535bdd290SAlessandro Rubini 	if (err) {
57635bdd290SAlessandro Rubini 		dev_err(&pdev->dev, "Can't enable device.\n");
57735bdd290SAlessandro Rubini 		return err;
57835bdd290SAlessandro Rubini 	}
57935bdd290SAlessandro Rubini 
58035bdd290SAlessandro Rubini 	err = pci_enable_msi(pdev);
58135bdd290SAlessandro Rubini 	if (err)
58235bdd290SAlessandro Rubini 		dev_info(&pdev->dev, "Enable msi failed\n");
58335bdd290SAlessandro Rubini 
5841950c716SDavide Ciminaghi 	setup_data = pci_id->device == PCI_DEVICE_ID_STMICRO_GPIO ?
5851950c716SDavide Ciminaghi 		&mfd_setup_data[STA2X11_MFD0] :
5861950c716SDavide Ciminaghi 		&mfd_setup_data[STA2X11_MFD1];
58735bdd290SAlessandro Rubini 
58835bdd290SAlessandro Rubini 	/* platform data is the pci device for all of them */
5891950c716SDavide Ciminaghi 	sta2x11_mfd_setup(pdev, setup_data);
59035bdd290SAlessandro Rubini 
59135bdd290SAlessandro Rubini 	/* Record this pdev before mfd_add_devices: their probe looks for it */
5928ec86a30SDavide Ciminaghi 	if (!sta2x11_mfd_find(pdev))
593*6ceb5f17SJulia Lawall 		sta2x11_mfd_add(pdev, GFP_KERNEL);
59435bdd290SAlessandro Rubini 
5951950c716SDavide Ciminaghi 	/* Just 2 bars for all mfd's at present */
5961950c716SDavide Ciminaghi 	for (i = 0; i < 2; i++) {
59735bdd290SAlessandro Rubini 		err = mfd_add_devices(&pdev->dev, -1,
5981950c716SDavide Ciminaghi 				      setup_data->bars[i].cells,
5991950c716SDavide Ciminaghi 				      setup_data->bars[i].ncells,
6001950c716SDavide Ciminaghi 				      &pdev->resource[i],
6010848c94fSMark Brown 				      0, NULL);
60235bdd290SAlessandro Rubini 		if (err) {
6031950c716SDavide Ciminaghi 			dev_err(&pdev->dev,
6041950c716SDavide Ciminaghi 				"mfd_add_devices[%d] failed: %d\n", i, err);
60535bdd290SAlessandro Rubini 			goto err_disable;
60635bdd290SAlessandro Rubini 		}
60735bdd290SAlessandro Rubini 	}
60835bdd290SAlessandro Rubini 
60935bdd290SAlessandro Rubini 	return 0;
61035bdd290SAlessandro Rubini 
61135bdd290SAlessandro Rubini err_disable:
61235bdd290SAlessandro Rubini 	mfd_remove_devices(&pdev->dev);
61335bdd290SAlessandro Rubini 	pci_disable_device(pdev);
61435bdd290SAlessandro Rubini 	pci_disable_msi(pdev);
61535bdd290SAlessandro Rubini 	return err;
61635bdd290SAlessandro Rubini }
61735bdd290SAlessandro Rubini 
61836fcd06cSJingoo Han static const struct pci_device_id sta2x11_mfd_tbl[] = {
61935bdd290SAlessandro Rubini 	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
6201950c716SDavide Ciminaghi 	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
62135bdd290SAlessandro Rubini 	{0,},
62235bdd290SAlessandro Rubini };
62335bdd290SAlessandro Rubini 
62435bdd290SAlessandro Rubini static struct pci_driver sta2x11_mfd_driver = {
62535bdd290SAlessandro Rubini 	.name =		"sta2x11-mfd",
62635bdd290SAlessandro Rubini 	.id_table =	sta2x11_mfd_tbl,
62735bdd290SAlessandro Rubini 	.probe =	sta2x11_mfd_probe,
62835bdd290SAlessandro Rubini 	.suspend =	sta2x11_mfd_suspend,
62935bdd290SAlessandro Rubini 	.resume =	sta2x11_mfd_resume,
63035bdd290SAlessandro Rubini };
63135bdd290SAlessandro Rubini 
sta2x11_mfd_init(void)63235bdd290SAlessandro Rubini static int __init sta2x11_mfd_init(void)
63335bdd290SAlessandro Rubini {
63435bdd290SAlessandro Rubini 	pr_info("%s\n", __func__);
63535bdd290SAlessandro Rubini 	return pci_register_driver(&sta2x11_mfd_driver);
63635bdd290SAlessandro Rubini }
63735bdd290SAlessandro Rubini 
63835bdd290SAlessandro Rubini /*
63935bdd290SAlessandro Rubini  * All of this must be ready before "normal" devices like MMCI appear.
64035bdd290SAlessandro Rubini  * But MFD (the pci device) can't be too early. The following choice
64135bdd290SAlessandro Rubini  * prepares platform drivers very early and probe the PCI device later,
64235bdd290SAlessandro Rubini  * but before other PCI devices.
64335bdd290SAlessandro Rubini  */
644d91d76d8SThierry Reding subsys_initcall(sta2x11_drivers_init);
64535bdd290SAlessandro Rubini rootfs_initcall(sta2x11_mfd_init);
646