linux/drivers/mfd/vexpress-sysreg.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *
   4 * Copyright (C) 2012 ARM Limited
   5 */
   6
   7#include <linux/gpio/driver.h>
   8#include <linux/err.h>
   9#include <linux/io.h>
  10#include <linux/mfd/core.h>
  11#include <linux/module.h>
  12#include <linux/of_platform.h>
  13#include <linux/platform_data/syscon.h>
  14#include <linux/platform_device.h>
  15#include <linux/slab.h>
  16#include <linux/stat.h>
  17
  18#define SYS_ID                  0x000
  19#define SYS_SW                  0x004
  20#define SYS_LED                 0x008
  21#define SYS_100HZ               0x024
  22#define SYS_FLAGSSET            0x030
  23#define SYS_FLAGSCLR            0x034
  24#define SYS_NVFLAGS             0x038
  25#define SYS_NVFLAGSSET          0x038
  26#define SYS_NVFLAGSCLR          0x03c
  27#define SYS_MCI                 0x048
  28#define SYS_FLASH               0x04c
  29#define SYS_CFGSW               0x058
  30#define SYS_24MHZ               0x05c
  31#define SYS_MISC                0x060
  32#define SYS_DMA                 0x064
  33#define SYS_PROCID0             0x084
  34#define SYS_PROCID1             0x088
  35#define SYS_CFGDATA             0x0a0
  36#define SYS_CFGCTRL             0x0a4
  37#define SYS_CFGSTAT             0x0a8
  38
  39/* The sysreg block is just a random collection of various functions... */
  40
  41static struct bgpio_pdata vexpress_sysreg_sys_led_pdata = {
  42        .label = "sys_led",
  43        .base = -1,
  44        .ngpio = 8,
  45};
  46
  47static struct bgpio_pdata vexpress_sysreg_sys_mci_pdata = {
  48        .label = "sys_mci",
  49        .base = -1,
  50        .ngpio = 2,
  51};
  52
  53static struct bgpio_pdata vexpress_sysreg_sys_flash_pdata = {
  54        .label = "sys_flash",
  55        .base = -1,
  56        .ngpio = 1,
  57};
  58
  59static struct mfd_cell vexpress_sysreg_cells[] = {
  60        {
  61                .name = "basic-mmio-gpio",
  62                .of_compatible = "arm,vexpress-sysreg,sys_led",
  63                .num_resources = 1,
  64                .resources = (struct resource []) {
  65                        DEFINE_RES_MEM_NAMED(SYS_LED, 0x4, "dat"),
  66                },
  67                .platform_data = &vexpress_sysreg_sys_led_pdata,
  68                .pdata_size = sizeof(vexpress_sysreg_sys_led_pdata),
  69        }, {
  70                .name = "basic-mmio-gpio",
  71                .of_compatible = "arm,vexpress-sysreg,sys_mci",
  72                .num_resources = 1,
  73                .resources = (struct resource []) {
  74                        DEFINE_RES_MEM_NAMED(SYS_MCI, 0x4, "dat"),
  75                },
  76                .platform_data = &vexpress_sysreg_sys_mci_pdata,
  77                .pdata_size = sizeof(vexpress_sysreg_sys_mci_pdata),
  78        }, {
  79                .name = "basic-mmio-gpio",
  80                .of_compatible = "arm,vexpress-sysreg,sys_flash",
  81                .num_resources = 1,
  82                .resources = (struct resource []) {
  83                        DEFINE_RES_MEM_NAMED(SYS_FLASH, 0x4, "dat"),
  84                },
  85                .platform_data = &vexpress_sysreg_sys_flash_pdata,
  86                .pdata_size = sizeof(vexpress_sysreg_sys_flash_pdata),
  87        }, {
  88                .name = "vexpress-syscfg",
  89                .num_resources = 1,
  90                .resources = (struct resource []) {
  91                        DEFINE_RES_MEM(SYS_MISC, 0x4c),
  92                },
  93        }
  94};
  95
  96static int vexpress_sysreg_probe(struct platform_device *pdev)
  97{
  98        struct resource *mem;
  99        void __iomem *base;
 100        struct gpio_chip *mmc_gpio_chip;
 101
 102        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 103        if (!mem)
 104                return -EINVAL;
 105
 106        base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
 107        if (!base)
 108                return -ENOMEM;
 109
 110        /*
 111         * Duplicated SYS_MCI pseudo-GPIO controller for compatibility with
 112         * older trees using sysreg node for MMC control lines.
 113         */
 114        mmc_gpio_chip = devm_kzalloc(&pdev->dev, sizeof(*mmc_gpio_chip),
 115                        GFP_KERNEL);
 116        if (!mmc_gpio_chip)
 117                return -ENOMEM;
 118        bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI,
 119                        NULL, NULL, NULL, NULL, 0);
 120        mmc_gpio_chip->ngpio = 2;
 121        devm_gpiochip_add_data(&pdev->dev, mmc_gpio_chip, NULL);
 122
 123        return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
 124                        vexpress_sysreg_cells,
 125                        ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, NULL);
 126}
 127
 128static const struct of_device_id vexpress_sysreg_match[] = {
 129        { .compatible = "arm,vexpress-sysreg", },
 130        {},
 131};
 132MODULE_DEVICE_TABLE(of, vexpress_sysreg_match);
 133
 134static struct platform_driver vexpress_sysreg_driver = {
 135        .driver = {
 136                .name = "vexpress-sysreg",
 137                .of_match_table = vexpress_sysreg_match,
 138        },
 139        .probe = vexpress_sysreg_probe,
 140};
 141
 142module_platform_driver(vexpress_sysreg_driver);
 143MODULE_LICENSE("GPL v2");
 144