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 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 */ 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 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 */ 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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)) 59335bdd290SAlessandro Rubini sta2x11_mfd_add(pdev, GFP_ATOMIC); 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 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