Thomas Gleixner | 1802d0b | 2019-05-27 08:55:21 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 2 | /* |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 3 | * |
| 4 | * Copyright (C) 2012 ARM Limited |
| 5 | */ |
| 6 | |
Linus Walleij | 0f4630f | 2015-12-04 14:02:58 +0100 | [diff] [blame] | 7 | #include <linux/gpio/driver.h> |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 8 | #include <linux/err.h> |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 9 | #include <linux/io.h> |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 10 | #include <linux/mfd/core.h> |
Rob Herring | 7b9d428 | 2020-04-29 15:58:20 -0500 | [diff] [blame] | 11 | #include <linux/module.h> |
Pawel Moll | 3b9334a | 2014-04-30 16:46:29 +0100 | [diff] [blame] | 12 | #include <linux/of_platform.h> |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 13 | #include <linux/platform_data/syscon.h> |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 14 | #include <linux/platform_device.h> |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 15 | #include <linux/slab.h> |
| 16 | #include <linux/stat.h> |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 17 | |
| 18 | #define SYS_ID 0x000 |
| 19 | #define SYS_SW 0x004 |
| 20 | #define SYS_LED 0x008 |
| 21 | #define SYS_100HZ 0x024 |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 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 | |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 39 | /* The sysreg block is just a random collection of various functions... */ |
Pawel Moll | 8eb12b9 | 2013-06-11 11:56:02 +0100 | [diff] [blame] | 40 | |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 41 | static struct bgpio_pdata vexpress_sysreg_sys_led_pdata = { |
| 42 | .label = "sys_led", |
| 43 | .base = -1, |
| 44 | .ngpio = 8, |
| 45 | }; |
| 46 | |
| 47 | static struct bgpio_pdata vexpress_sysreg_sys_mci_pdata = { |
| 48 | .label = "sys_mci", |
| 49 | .base = -1, |
| 50 | .ngpio = 2, |
| 51 | }; |
| 52 | |
| 53 | static struct bgpio_pdata vexpress_sysreg_sys_flash_pdata = { |
| 54 | .label = "sys_flash", |
| 55 | .base = -1, |
| 56 | .ngpio = 1, |
| 57 | }; |
| 58 | |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 59 | static struct mfd_cell vexpress_sysreg_cells[] = { |
| 60 | { |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 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 | }, { |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 88 | .name = "vexpress-syscfg", |
| 89 | .num_resources = 1, |
| 90 | .resources = (struct resource []) { |
Rob Herring | 310f80d | 2020-04-29 15:58:23 -0500 | [diff] [blame] | 91 | DEFINE_RES_MEM(SYS_MISC, 0x4c), |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 92 | }, |
Pawel Moll | 8ea402f | 2013-01-30 10:33:16 +0000 | [diff] [blame] | 93 | } |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 94 | }; |
| 95 | |
Greg Kroah-Hartman | 612b95c | 2012-12-21 15:03:15 -0800 | [diff] [blame] | 96 | static int vexpress_sysreg_probe(struct platform_device *pdev) |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 97 | { |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 98 | struct resource *mem; |
| 99 | void __iomem *base; |
Linus Walleij | 0f4630f | 2015-12-04 14:02:58 +0100 | [diff] [blame] | 100 | struct gpio_chip *mmc_gpio_chip; |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 101 | |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 102 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 103 | if (!mem) |
| 104 | return -EINVAL; |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 105 | |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 106 | base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); |
| 107 | if (!base) |
| 108 | return -ENOMEM; |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 109 | |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 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); |
Linus Walleij | 0f4630f | 2015-12-04 14:02:58 +0100 | [diff] [blame] | 120 | mmc_gpio_chip->ngpio = 2; |
Rob Herring | 0ea355e | 2020-04-29 15:58:19 -0500 | [diff] [blame] | 121 | devm_gpiochip_add_data(&pdev->dev, mmc_gpio_chip, NULL); |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 122 | |
Rob Herring | 0ea355e | 2020-04-29 15:58:19 -0500 | [diff] [blame] | 123 | return devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, |
Pawel Moll | 974cc7b | 2014-04-23 10:49:31 +0100 | [diff] [blame] | 124 | vexpress_sysreg_cells, |
| 125 | ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, NULL); |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 126 | } |
| 127 | |
| 128 | static const struct of_device_id vexpress_sysreg_match[] = { |
| 129 | { .compatible = "arm,vexpress-sysreg", }, |
| 130 | {}, |
| 131 | }; |
Rob Herring | 7b9d428 | 2020-04-29 15:58:20 -0500 | [diff] [blame] | 132 | MODULE_DEVICE_TABLE(of, vexpress_sysreg_match); |
Pawel Moll | 88e0abc | 2012-09-18 12:24:57 +0100 | [diff] [blame] | 133 | |
| 134 | static 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 | |
Rob Herring | 7b9d428 | 2020-04-29 15:58:20 -0500 | [diff] [blame] | 142 | module_platform_driver(vexpress_sysreg_driver); |
| 143 | MODULE_LICENSE("GPL v2"); |