Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: vexpress: Define the device as MFD cells

This patch - finally, after over 6 months! :-( - addresses
Samuel's request to split the vexpress-sysreg driver into
smaller portions and define the device in a form of MFD
cells:

* LEDs code has been completely removed and replaced with
"gpio-leds" nodes in the tree (referencing dedicated
GPIO subnodes in sysreg - bindings documentation updated);
this also better fits the reality as some variants of the
motherboard don't have all the LEDs populated

* syscfg bridge code has been extracted into a separate
driver (placed in drivers/misc for no better place)

* all the ID & MISC registers are defined as sysconf
making them available for other drivers should they need
to use them (and also to the user via /sys/kernel/debug/regmap
which can be helpful in platform debugging)

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
Acked-by: Lee Jones <lee.jones@linaro.org>

+674 -445
+34 -2
Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
··· 8 8 Required node properties: 9 9 - compatible value : = "arm,vexpress,sysreg"; 10 10 - reg : physical base address and the size of the registers window 11 + 12 + Deprecated properties, replaced by GPIO subnodes (see below): 11 13 - gpio-controller : specifies that the node is a GPIO controller 12 14 - #gpio-cells : size of the GPIO specifier, should be 2: 13 15 - first cell is the pseudo-GPIO line number: ··· 18 16 2 - NOR FLASH WPn 19 17 - second cell can take standard GPIO flags (currently ignored). 20 18 19 + Control registers providing pseudo-GPIO lines must be represented 20 + by subnodes, each of them requiring the following properties: 21 + - compatible value : one of 22 + "arm,vexpress-sysreg,sys_led" 23 + "arm,vexpress-sysreg,sys_mci" 24 + "arm,vexpress-sysreg,sys_flash" 25 + - gpio-controller : makes the node a GPIO controller 26 + - #gpio-cells : size of the GPIO specifier, must be 2: 27 + - first cell is the function number: 28 + - for sys_led : 0..7 = LED 0..7 29 + - for sys_mci : 0 = MMC CARDIN, 1 = MMC WPROT 30 + - for sys_flash : 0 = NOR FLASH WPn 31 + - second cell can take standard GPIO flags (currently ignored). 32 + 21 33 Example: 22 34 v2m_sysreg: sysreg@10000000 { 23 35 compatible = "arm,vexpress-sysreg"; 24 36 reg = <0x10000000 0x1000>; 25 - gpio-controller; 26 - #gpio-cells = <2>; 37 + 38 + v2m_led_gpios: sys_led@08 { 39 + compatible = "arm,vexpress-sysreg,sys_led"; 40 + gpio-controller; 41 + #gpio-cells = <2>; 42 + }; 43 + 44 + v2m_mmc_gpios: sys_mci@48 { 45 + compatible = "arm,vexpress-sysreg,sys_mci"; 46 + gpio-controller; 47 + #gpio-cells = <2>; 48 + }; 49 + 50 + v2m_flash_gpios: sys_flash@4c { 51 + compatible = "arm,vexpress-sysreg,sys_flash"; 52 + gpio-controller; 53 + #gpio-cells = <2>; 54 + }; 27 55 }; 28 56 29 57 This block also can also act a bridge to the platform's configuration
+72 -4
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
··· 74 74 v2m_sysreg: sysreg@010000 { 75 75 compatible = "arm,vexpress-sysreg"; 76 76 reg = <0x010000 0x1000>; 77 - gpio-controller; 78 - #gpio-cells = <2>; 77 + 78 + v2m_led_gpios: sys_led@08 { 79 + compatible = "arm,vexpress-sysreg,sys_led"; 80 + gpio-controller; 81 + #gpio-cells = <2>; 82 + }; 83 + 84 + v2m_mmc_gpios: sys_mci@48 { 85 + compatible = "arm,vexpress-sysreg,sys_mci"; 86 + gpio-controller; 87 + #gpio-cells = <2>; 88 + }; 89 + 90 + v2m_flash_gpios: sys_flash@4c { 91 + compatible = "arm,vexpress-sysreg,sys_flash"; 92 + gpio-controller; 93 + #gpio-cells = <2>; 94 + }; 79 95 }; 80 96 81 97 v2m_sysctl: sysctl@020000 { ··· 129 113 compatible = "arm,pl180", "arm,primecell"; 130 114 reg = <0x050000 0x1000>; 131 115 interrupts = <9 10>; 132 - cd-gpios = <&v2m_sysreg 0 0>; 133 - wp-gpios = <&v2m_sysreg 1 0>; 116 + cd-gpios = <&v2m_mmc_gpios 0 0>; 117 + wp-gpios = <&v2m_mmc_gpios 1 0>; 134 118 max-frequency = <12000000>; 135 119 vmmc-supply = <&v2m_fixed_3v3>; 136 120 clocks = <&v2m_clk24mhz>, <&smbclk>; ··· 279 263 #clock-cells = <0>; 280 264 clock-frequency = <32768>; 281 265 clock-output-names = "v2m:refclk32khz"; 266 + }; 267 + 268 + leds { 269 + compatible = "gpio-leds"; 270 + 271 + user@1 { 272 + label = "v2m:green:user1"; 273 + gpios = <&v2m_led_gpios 0 0>; 274 + linux,default-trigger = "heartbeat"; 275 + }; 276 + 277 + user@2 { 278 + label = "v2m:green:user2"; 279 + gpios = <&v2m_led_gpios 1 0>; 280 + linux,default-trigger = "mmc0"; 281 + }; 282 + 283 + user@3 { 284 + label = "v2m:green:user3"; 285 + gpios = <&v2m_led_gpios 2 0>; 286 + linux,default-trigger = "cpu0"; 287 + }; 288 + 289 + user@4 { 290 + label = "v2m:green:user4"; 291 + gpios = <&v2m_led_gpios 3 0>; 292 + linux,default-trigger = "cpu1"; 293 + }; 294 + 295 + user@5 { 296 + label = "v2m:green:user5"; 297 + gpios = <&v2m_led_gpios 4 0>; 298 + linux,default-trigger = "cpu2"; 299 + }; 300 + 301 + user@6 { 302 + label = "v2m:green:user6"; 303 + gpios = <&v2m_led_gpios 5 0>; 304 + linux,default-trigger = "cpu3"; 305 + }; 306 + 307 + user@7 { 308 + label = "v2m:green:user7"; 309 + gpios = <&v2m_led_gpios 6 0>; 310 + linux,default-trigger = "cpu4"; 311 + }; 312 + 313 + user@8 { 314 + label = "v2m:green:user8"; 315 + gpios = <&v2m_led_gpios 7 0>; 316 + linux,default-trigger = "cpu5"; 317 + }; 282 318 }; 283 319 284 320 mcc {
+72 -4
arch/arm/boot/dts/vexpress-v2m.dtsi
··· 73 73 v2m_sysreg: sysreg@00000 { 74 74 compatible = "arm,vexpress-sysreg"; 75 75 reg = <0x00000 0x1000>; 76 - gpio-controller; 77 - #gpio-cells = <2>; 76 + 77 + v2m_led_gpios: sys_led@08 { 78 + compatible = "arm,vexpress-sysreg,sys_led"; 79 + gpio-controller; 80 + #gpio-cells = <2>; 81 + }; 82 + 83 + v2m_mmc_gpios: sys_mci@48 { 84 + compatible = "arm,vexpress-sysreg,sys_mci"; 85 + gpio-controller; 86 + #gpio-cells = <2>; 87 + }; 88 + 89 + v2m_flash_gpios: sys_flash@4c { 90 + compatible = "arm,vexpress-sysreg,sys_flash"; 91 + gpio-controller; 92 + #gpio-cells = <2>; 93 + }; 78 94 }; 79 95 80 96 v2m_sysctl: sysctl@01000 { ··· 128 112 compatible = "arm,pl180", "arm,primecell"; 129 113 reg = <0x05000 0x1000>; 130 114 interrupts = <9 10>; 131 - cd-gpios = <&v2m_sysreg 0 0>; 132 - wp-gpios = <&v2m_sysreg 1 0>; 115 + cd-gpios = <&v2m_mmc_gpios 0 0>; 116 + wp-gpios = <&v2m_mmc_gpios 1 0>; 133 117 max-frequency = <12000000>; 134 118 vmmc-supply = <&v2m_fixed_3v3>; 135 119 clocks = <&v2m_clk24mhz>, <&smbclk>; ··· 278 262 #clock-cells = <0>; 279 263 clock-frequency = <32768>; 280 264 clock-output-names = "v2m:refclk32khz"; 265 + }; 266 + 267 + leds { 268 + compatible = "gpio-leds"; 269 + 270 + user@1 { 271 + label = "v2m:green:user1"; 272 + gpios = <&v2m_led_gpios 0 0>; 273 + linux,default-trigger = "heartbeat"; 274 + }; 275 + 276 + user@2 { 277 + label = "v2m:green:user2"; 278 + gpios = <&v2m_led_gpios 1 0>; 279 + linux,default-trigger = "mmc0"; 280 + }; 281 + 282 + user@3 { 283 + label = "v2m:green:user3"; 284 + gpios = <&v2m_led_gpios 2 0>; 285 + linux,default-trigger = "cpu0"; 286 + }; 287 + 288 + user@4 { 289 + label = "v2m:green:user4"; 290 + gpios = <&v2m_led_gpios 3 0>; 291 + linux,default-trigger = "cpu1"; 292 + }; 293 + 294 + user@5 { 295 + label = "v2m:green:user5"; 296 + gpios = <&v2m_led_gpios 4 0>; 297 + linux,default-trigger = "cpu2"; 298 + }; 299 + 300 + user@6 { 301 + label = "v2m:green:user6"; 302 + gpios = <&v2m_led_gpios 5 0>; 303 + linux,default-trigger = "cpu3"; 304 + }; 305 + 306 + user@7 { 307 + label = "v2m:green:user7"; 308 + gpios = <&v2m_led_gpios 6 0>; 309 + linux,default-trigger = "cpu4"; 310 + }; 311 + 312 + user@8 { 313 + label = "v2m:green:user8"; 314 + gpios = <&v2m_led_gpios 7 0>; 315 + linux,default-trigger = "cpu5"; 316 + }; 281 317 }; 282 318 283 319 mcc {
+1 -1
arch/arm/mach-vexpress/ct-ca9x4.c
··· 160 160 amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource); 161 161 162 162 platform_device_register(&pmu_device); 163 - vexpress_sysreg_config_device_register(&osc1_device); 163 + vexpress_syscfg_device_register(&osc1_device); 164 164 } 165 165 166 166 #ifdef CONFIG_SMP
+7 -8
arch/arm/mach-vexpress/v2m.c
··· 201 201 202 202 static struct mmci_platform_data v2m_mmci_data = { 203 203 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 204 - .gpio_wp = VEXPRESS_GPIO_MMC_WPROT, 205 - .gpio_cd = VEXPRESS_GPIO_MMC_CARDIN, 204 + .status = vexpress_get_mci_cardin, 205 + .gpio_cd = -1, 206 + .gpio_wp = -1, 206 207 }; 207 208 208 209 static struct resource v2m_sysreg_resources[] = { ··· 352 351 for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++) 353 352 amba_device_register(v2m_amba_devs[i], &iomem_resource); 354 353 355 - vexpress_sysreg_config_device_register(&v2m_muxfpga_device); 356 - vexpress_sysreg_config_device_register(&v2m_shutdown_device); 357 - vexpress_sysreg_config_device_register(&v2m_reboot_device); 358 - vexpress_sysreg_config_device_register(&v2m_dvimode_device); 354 + vexpress_syscfg_device_register(&v2m_muxfpga_device); 355 + vexpress_syscfg_device_register(&v2m_shutdown_device); 356 + vexpress_syscfg_device_register(&v2m_reboot_device); 357 + vexpress_syscfg_device_register(&v2m_dvimode_device); 359 358 360 359 ct_desc->init_tile(); 361 360 } ··· 409 408 void __init v2m_dt_init_early(void) 410 409 { 411 410 u32 dt_hbi; 412 - 413 - vexpress_sysreg_of_early_init(); 414 411 415 412 /* Confirm board type against DT property, if available */ 416 413 if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) {
+10 -5
drivers/mfd/Kconfig
··· 1227 1227 1228 1228 endmenu 1229 1229 1230 - config VEXPRESS_CONFIG 1231 - bool "ARM Versatile Express platform infrastructure" 1232 - depends on ARM || ARM64 1230 + config MFD_VEXPRESS_SYSREG 1231 + bool "Versatile Express System Registers" 1232 + depends on VEXPRESS_CONFIG 1233 + default y 1234 + select CLKSRC_MMIO 1235 + select GPIO_GENERIC_PLATFORM 1236 + select MFD_CORE 1237 + select MFD_SYSCON 1233 1238 help 1234 - Platform configuration infrastructure for the ARM Ltd. 1235 - Versatile Express. 1239 + System Registers are the platform configuration block 1240 + on the ARM Ltd. Versatile Express board. 1236 1241 1237 1242 endmenu 1238 1243 endif
+1 -1
drivers/mfd/Makefile
··· 161 161 obj-$(CONFIG_MFD_SEC_CORE) += sec-core.o sec-irq.o 162 162 obj-$(CONFIG_MFD_SYSCON) += syscon.o 163 163 obj-$(CONFIG_MFD_LM3533) += lm3533-core.o lm3533-ctrlbank.o 164 - obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-sysreg.o 164 + obj-$(CONFIG_MFD_VEXPRESS_SYSREG) += vexpress-sysreg.o 165 165 obj-$(CONFIG_MFD_RETU) += retu-mfd.o 166 166 obj-$(CONFIG_MFD_AS3711) += as3711.o 167 167 obj-$(CONFIG_MFD_AS3722) += as3722.o
+141 -406
drivers/mfd/vexpress-sysreg.c
··· 11 11 * Copyright (C) 2012 ARM Limited 12 12 */ 13 13 14 + #include <linux/basic_mmio_gpio.h> 14 15 #include <linux/err.h> 15 - #include <linux/gpio.h> 16 16 #include <linux/io.h> 17 - #include <linux/leds.h> 17 + #include <linux/mfd/core.h> 18 18 #include <linux/of_address.h> 19 19 #include <linux/of_platform.h> 20 + #include <linux/platform_data/syscon.h> 20 21 #include <linux/platform_device.h> 21 - #include <linux/regulator/driver.h> 22 - #include <linux/sched.h> 23 22 #include <linux/slab.h> 24 23 #include <linux/stat.h> 25 - #include <linux/timer.h> 26 24 #include <linux/vexpress.h> 27 25 28 26 #define SYS_ID 0x000 29 27 #define SYS_SW 0x004 30 28 #define SYS_LED 0x008 31 29 #define SYS_100HZ 0x024 32 - #define SYS_FLAGS 0x030 33 30 #define SYS_FLAGSSET 0x030 34 31 #define SYS_FLAGSCLR 0x034 35 32 #define SYS_NVFLAGS 0x038 ··· 48 51 #define SYS_ID_HBI_SHIFT 16 49 52 #define SYS_PROCIDx_HBI_SHIFT 0 50 53 51 - #define SYS_LED_LED(n) (1 << (n)) 52 - 53 54 #define SYS_MCI_CARDIN (1 << 0) 54 55 #define SYS_MCI_WPROT (1 << 1) 55 56 56 - #define SYS_FLASH_WPn (1 << 0) 57 - 58 57 #define SYS_MISC_MASTERSITE (1 << 14) 59 58 60 - #define SYS_CFGCTRL_START (1 << 31) 61 - #define SYS_CFGCTRL_WRITE (1 << 30) 62 - #define SYS_CFGCTRL_DCC(n) (((n) & 0xf) << 26) 63 - #define SYS_CFGCTRL_FUNC(n) (((n) & 0x3f) << 20) 64 - #define SYS_CFGCTRL_SITE(n) (((n) & 0x3) << 16) 65 - #define SYS_CFGCTRL_POSITION(n) (((n) & 0xf) << 12) 66 - #define SYS_CFGCTRL_DEVICE(n) (((n) & 0xfff) << 0) 67 59 68 - #define SYS_CFGSTAT_ERR (1 << 1) 69 - #define SYS_CFGSTAT_COMPLETE (1 << 0) 60 + static void __iomem *__vexpress_sysreg_base; 70 61 62 + static void __iomem *vexpress_sysreg_base(void) 63 + { 64 + if (!__vexpress_sysreg_base) { 65 + struct device_node *node = of_find_compatible_node(NULL, NULL, 66 + "arm,vexpress-sysreg"); 71 67 72 - static void __iomem *vexpress_sysreg_base; 73 - static struct device *vexpress_sysreg_dev; 74 - static LIST_HEAD(vexpress_sysreg_config_funcs); 75 - static struct device *vexpress_sysreg_config_bridge; 68 + __vexpress_sysreg_base = of_iomap(node, 0); 69 + } 70 + 71 + WARN_ON(!__vexpress_sysreg_base); 72 + 73 + return __vexpress_sysreg_base; 74 + } 76 75 77 76 78 77 static int vexpress_sysreg_get_master(void) 79 78 { 80 - if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) 79 + if (readl(vexpress_sysreg_base() + SYS_MISC) & SYS_MISC_MASTERSITE) 81 80 return VEXPRESS_SITE_DB2; 82 81 83 82 return VEXPRESS_SITE_DB1; ··· 81 88 82 89 void vexpress_flags_set(u32 data) 83 90 { 84 - writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR); 85 - writel(data, vexpress_sysreg_base + SYS_FLAGSSET); 91 + writel(~0, vexpress_sysreg_base() + SYS_FLAGSCLR); 92 + writel(data, vexpress_sysreg_base() + SYS_FLAGSSET); 93 + } 94 + 95 + unsigned int vexpress_get_mci_cardin(struct device *dev) 96 + { 97 + return readl(vexpress_sysreg_base() + SYS_MCI) & SYS_MCI_CARDIN; 86 98 } 87 99 88 100 u32 vexpress_get_procid(int site) ··· 95 97 if (site == VEXPRESS_SITE_MASTER) 96 98 site = vexpress_sysreg_get_master(); 97 99 98 - return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ? 100 + return readl(vexpress_sysreg_base() + (site == VEXPRESS_SITE_DB1 ? 99 101 SYS_PROCID0 : SYS_PROCID1)); 100 102 } 101 103 ··· 105 107 106 108 switch (site) { 107 109 case VEXPRESS_SITE_MB: 108 - id = readl(vexpress_sysreg_base + SYS_ID); 110 + id = readl(vexpress_sysreg_base() + SYS_ID); 109 111 return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK; 110 112 case VEXPRESS_SITE_MASTER: 111 113 case VEXPRESS_SITE_DB1: ··· 119 121 120 122 void __iomem *vexpress_get_24mhz_clock_base(void) 121 123 { 122 - return vexpress_sysreg_base + SYS_24MHZ; 123 - } 124 - 125 - 126 - struct vexpress_sysreg_config_func { 127 - struct list_head list; 128 - struct regmap *regmap; 129 - int num_templates; 130 - u32 template[0]; /* Keep this last */ 131 - }; 132 - 133 - static int vexpress_sysreg_config_exec(struct vexpress_sysreg_config_func *func, 134 - int index, bool write, u32 *data) 135 - { 136 - u32 command, status; 137 - int tries; 138 - long timeout; 139 - 140 - if (WARN_ON(!vexpress_sysreg_base)) 141 - return -ENOENT; 142 - 143 - if (WARN_ON(index > func->num_templates)) 144 - return -EINVAL; 145 - 146 - command = readl(vexpress_sysreg_base + SYS_CFGCTRL); 147 - if (WARN_ON(command & SYS_CFGCTRL_START)) 148 - return -EBUSY; 149 - 150 - command = func->template[index]; 151 - command |= SYS_CFGCTRL_START; 152 - command |= write ? SYS_CFGCTRL_WRITE : 0; 153 - 154 - /* Use a canary for reads */ 155 - if (!write) 156 - *data = 0xdeadbeef; 157 - 158 - dev_dbg(vexpress_sysreg_dev, "command %x, data %x\n", 159 - command, *data); 160 - writel(*data, vexpress_sysreg_base + SYS_CFGDATA); 161 - writel(0, vexpress_sysreg_base + SYS_CFGSTAT); 162 - writel(command, vexpress_sysreg_base + SYS_CFGCTRL); 163 - mb(); 164 - 165 - /* The operation can take ages... Go to sleep, 100us initially */ 166 - tries = 100; 167 - timeout = 100; 168 - do { 169 - set_current_state(TASK_INTERRUPTIBLE); 170 - schedule_timeout(usecs_to_jiffies(timeout)); 171 - if (signal_pending(current)) 172 - return -EINTR; 173 - 174 - status = readl(vexpress_sysreg_base + SYS_CFGSTAT); 175 - if (status & SYS_CFGSTAT_ERR) 176 - return -EFAULT; 177 - 178 - if (timeout > 20) 179 - timeout -= 20; 180 - } while (--tries && !(status & SYS_CFGSTAT_COMPLETE)); 181 - if (WARN_ON_ONCE(!tries)) 182 - return -ETIMEDOUT; 183 - 184 - if (!write) { 185 - *data = readl(vexpress_sysreg_base + SYS_CFGDATA); 186 - dev_dbg(vexpress_sysreg_dev, "func %p, read data %x\n", 187 - func, *data); 188 - } 189 - 190 - return 0; 191 - } 192 - 193 - static int vexpress_sysreg_config_read(void *context, unsigned int index, 194 - unsigned int *val) 195 - { 196 - struct vexpress_sysreg_config_func *func = context; 197 - 198 - return vexpress_sysreg_config_exec(func, index, false, val); 199 - } 200 - 201 - static int vexpress_sysreg_config_write(void *context, unsigned int index, 202 - unsigned int val) 203 - { 204 - struct vexpress_sysreg_config_func *func = context; 205 - 206 - return vexpress_sysreg_config_exec(func, index, true, &val); 207 - } 208 - 209 - struct regmap_config vexpress_sysreg_regmap_config = { 210 - .lock = vexpress_config_lock, 211 - .unlock = vexpress_config_unlock, 212 - .reg_bits = 32, 213 - .val_bits = 32, 214 - .reg_read = vexpress_sysreg_config_read, 215 - .reg_write = vexpress_sysreg_config_write, 216 - .reg_format_endian = REGMAP_ENDIAN_LITTLE, 217 - .val_format_endian = REGMAP_ENDIAN_LITTLE, 218 - }; 219 - 220 - static struct regmap *vexpress_sysreg_config_regmap_init(struct device *dev, 221 - void *context) 222 - { 223 - struct platform_device *pdev = to_platform_device(dev); 224 - struct vexpress_sysreg_config_func *func; 225 - struct property *prop; 226 - const __be32 *val = NULL; 227 - __be32 energy_quirk[4]; 228 - int num; 229 - u32 site, position, dcc; 230 - int err; 231 - int i; 232 - 233 - if (dev->of_node) { 234 - err = vexpress_config_get_topo(dev->of_node, &site, &position, 235 - &dcc); 236 - if (err) 237 - return ERR_PTR(err); 238 - 239 - prop = of_find_property(dev->of_node, 240 - "arm,vexpress-sysreg,func", NULL); 241 - if (!prop) 242 - return ERR_PTR(-EINVAL); 243 - 244 - num = prop->length / sizeof(u32) / 2; 245 - val = prop->value; 246 - } else { 247 - if (pdev->num_resources != 1 || 248 - pdev->resource[0].flags != IORESOURCE_BUS) 249 - return ERR_PTR(-EFAULT); 250 - 251 - site = pdev->resource[0].start; 252 - if (site == VEXPRESS_SITE_MASTER) 253 - site = vexpress_sysreg_get_master(); 254 - position = 0; 255 - dcc = 0; 256 - num = 1; 257 - } 258 - 259 - /* 260 - * "arm,vexpress-energy" function used to be described 261 - * by its first device only, now it requires both 262 - */ 263 - if (num == 1 && of_device_is_compatible(dev->of_node, 264 - "arm,vexpress-energy")) { 265 - num = 2; 266 - energy_quirk[0] = *val; 267 - energy_quirk[2] = *val++; 268 - energy_quirk[1] = *val; 269 - energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1); 270 - val = energy_quirk; 271 - } 272 - 273 - func = kzalloc(sizeof(*func) + sizeof(*func->template) * num, 274 - GFP_KERNEL); 275 - if (!func) 276 - return NULL; 277 - 278 - func->num_templates = num; 279 - 280 - for (i = 0; i < num; i++) { 281 - u32 function, device; 282 - 283 - if (dev->of_node) { 284 - function = be32_to_cpup(val++); 285 - device = be32_to_cpup(val++); 286 - } else { 287 - function = pdev->resource[0].end; 288 - device = pdev->id; 289 - } 290 - 291 - dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n", 292 - func, site, position, dcc, 293 - function, device); 294 - 295 - func->template[i] = SYS_CFGCTRL_DCC(dcc); 296 - func->template[i] |= SYS_CFGCTRL_SITE(site); 297 - func->template[i] |= SYS_CFGCTRL_POSITION(position); 298 - func->template[i] |= SYS_CFGCTRL_FUNC(function); 299 - func->template[i] |= SYS_CFGCTRL_DEVICE(device); 300 - } 301 - 302 - vexpress_sysreg_regmap_config.max_register = num - 1; 303 - 304 - func->regmap = regmap_init(dev, NULL, func, 305 - &vexpress_sysreg_regmap_config); 306 - 307 - if (IS_ERR(func->regmap)) 308 - kfree(func); 309 - else 310 - list_add(&func->list, &vexpress_sysreg_config_funcs); 311 - 312 - return func->regmap; 313 - } 314 - 315 - static void vexpress_sysreg_config_regmap_exit(struct regmap *regmap, 316 - void *context) 317 - { 318 - struct vexpress_sysreg_config_func *func, *tmp; 319 - 320 - regmap_exit(regmap); 321 - 322 - list_for_each_entry_safe(func, tmp, &vexpress_sysreg_config_funcs, 323 - list) { 324 - if (func->regmap == regmap) { 325 - list_del(&vexpress_sysreg_config_funcs); 326 - kfree(func); 327 - break; 328 - } 329 - } 330 - } 331 - 332 - static struct vexpress_config_bridge_ops vexpress_sysreg_config_bridge_ops = { 333 - .regmap_init = vexpress_sysreg_config_regmap_init, 334 - .regmap_exit = vexpress_sysreg_config_regmap_exit, 335 - }; 336 - 337 - int vexpress_sysreg_config_device_register(struct platform_device *pdev) 338 - { 339 - pdev->dev.parent = vexpress_sysreg_config_bridge; 340 - 341 - return platform_device_register(pdev); 124 + return vexpress_sysreg_base() + SYS_24MHZ; 342 125 } 343 126 344 127 345 128 void __init vexpress_sysreg_early_init(void __iomem *base) 346 129 { 347 - vexpress_sysreg_base = base; 348 - vexpress_config_set_master(vexpress_sysreg_get_master()); 349 - } 350 - 351 - void __init vexpress_sysreg_of_early_init(void) 352 - { 353 - struct device_node *node; 354 - 355 - if (vexpress_sysreg_base) 356 - return; 357 - 358 - node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg"); 359 - if (WARN_ON(!node)) 360 - return; 361 - 362 - vexpress_sysreg_base = of_iomap(node, 0); 363 - if (WARN_ON(!vexpress_sysreg_base)) 364 - return; 130 + __vexpress_sysreg_base = base; 365 131 366 132 vexpress_config_set_master(vexpress_sysreg_get_master()); 367 133 } 368 134 369 135 370 - #ifdef CONFIG_GPIOLIB 136 + /* The sysreg block is just a random collection of various functions... */ 371 137 372 - #define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \ 373 - [VEXPRESS_GPIO_##_name] = { \ 374 - .reg = _reg, \ 375 - .value = _reg##_##_value, \ 138 + static struct syscon_platform_data vexpress_sysreg_sys_id_pdata = { 139 + .label = "sys_id", 140 + }; 141 + 142 + static struct bgpio_pdata vexpress_sysreg_sys_led_pdata = { 143 + .label = "sys_led", 144 + .base = -1, 145 + .ngpio = 8, 146 + }; 147 + 148 + static struct bgpio_pdata vexpress_sysreg_sys_mci_pdata = { 149 + .label = "sys_mci", 150 + .base = -1, 151 + .ngpio = 2, 152 + }; 153 + 154 + static struct bgpio_pdata vexpress_sysreg_sys_flash_pdata = { 155 + .label = "sys_flash", 156 + .base = -1, 157 + .ngpio = 1, 158 + }; 159 + 160 + static struct syscon_platform_data vexpress_sysreg_sys_misc_pdata = { 161 + .label = "sys_misc", 162 + }; 163 + 164 + static struct syscon_platform_data vexpress_sysreg_sys_procid_pdata = { 165 + .label = "sys_procid", 166 + }; 167 + 168 + static struct mfd_cell vexpress_sysreg_cells[] = { 169 + { 170 + .name = "syscon", 171 + .num_resources = 1, 172 + .resources = (struct resource []) { 173 + DEFINE_RES_MEM(SYS_ID, 0x4), 174 + }, 175 + .platform_data = &vexpress_sysreg_sys_id_pdata, 176 + .pdata_size = sizeof(vexpress_sysreg_sys_id_pdata), 177 + }, { 178 + .name = "basic-mmio-gpio", 179 + .of_compatible = "arm,vexpress-sysreg,sys_led", 180 + .num_resources = 1, 181 + .resources = (struct resource []) { 182 + DEFINE_RES_MEM_NAMED(SYS_LED, 0x4, "dat"), 183 + }, 184 + .platform_data = &vexpress_sysreg_sys_led_pdata, 185 + .pdata_size = sizeof(vexpress_sysreg_sys_led_pdata), 186 + }, { 187 + .name = "basic-mmio-gpio", 188 + .of_compatible = "arm,vexpress-sysreg,sys_mci", 189 + .num_resources = 1, 190 + .resources = (struct resource []) { 191 + DEFINE_RES_MEM_NAMED(SYS_MCI, 0x4, "dat"), 192 + }, 193 + .platform_data = &vexpress_sysreg_sys_mci_pdata, 194 + .pdata_size = sizeof(vexpress_sysreg_sys_mci_pdata), 195 + }, { 196 + .name = "basic-mmio-gpio", 197 + .of_compatible = "arm,vexpress-sysreg,sys_flash", 198 + .num_resources = 1, 199 + .resources = (struct resource []) { 200 + DEFINE_RES_MEM_NAMED(SYS_FLASH, 0x4, "dat"), 201 + }, 202 + .platform_data = &vexpress_sysreg_sys_flash_pdata, 203 + .pdata_size = sizeof(vexpress_sysreg_sys_flash_pdata), 204 + }, { 205 + .name = "syscon", 206 + .num_resources = 1, 207 + .resources = (struct resource []) { 208 + DEFINE_RES_MEM(SYS_MISC, 0x4), 209 + }, 210 + .platform_data = &vexpress_sysreg_sys_misc_pdata, 211 + .pdata_size = sizeof(vexpress_sysreg_sys_misc_pdata), 212 + }, { 213 + .name = "syscon", 214 + .num_resources = 1, 215 + .resources = (struct resource []) { 216 + DEFINE_RES_MEM(SYS_PROCID0, 0x8), 217 + }, 218 + .platform_data = &vexpress_sysreg_sys_procid_pdata, 219 + .pdata_size = sizeof(vexpress_sysreg_sys_procid_pdata), 220 + }, { 221 + .name = "vexpress-syscfg", 222 + .num_resources = 1, 223 + .resources = (struct resource []) { 224 + DEFINE_RES_MEM(SYS_CFGDATA, 0xc), 225 + }, 376 226 } 377 - 378 - static struct vexpress_sysreg_gpio { 379 - unsigned long reg; 380 - u32 value; 381 - } vexpress_sysreg_gpios[] = { 382 - VEXPRESS_SYSREG_GPIO(MMC_CARDIN, SYS_MCI, CARDIN), 383 - VEXPRESS_SYSREG_GPIO(MMC_WPROT, SYS_MCI, WPROT), 384 - VEXPRESS_SYSREG_GPIO(FLASH_WPn, SYS_FLASH, WPn), 385 - VEXPRESS_SYSREG_GPIO(LED0, SYS_LED, LED(0)), 386 - VEXPRESS_SYSREG_GPIO(LED1, SYS_LED, LED(1)), 387 - VEXPRESS_SYSREG_GPIO(LED2, SYS_LED, LED(2)), 388 - VEXPRESS_SYSREG_GPIO(LED3, SYS_LED, LED(3)), 389 - VEXPRESS_SYSREG_GPIO(LED4, SYS_LED, LED(4)), 390 - VEXPRESS_SYSREG_GPIO(LED5, SYS_LED, LED(5)), 391 - VEXPRESS_SYSREG_GPIO(LED6, SYS_LED, LED(6)), 392 - VEXPRESS_SYSREG_GPIO(LED7, SYS_LED, LED(7)), 393 227 }; 394 - 395 - static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip, 396 - unsigned offset) 397 - { 398 - return 0; 399 - } 400 - 401 - static int vexpress_sysreg_gpio_get(struct gpio_chip *chip, 402 - unsigned offset) 403 - { 404 - struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset]; 405 - u32 reg_value = readl(vexpress_sysreg_base + gpio->reg); 406 - 407 - return !!(reg_value & gpio->value); 408 - } 409 - 410 - static void vexpress_sysreg_gpio_set(struct gpio_chip *chip, 411 - unsigned offset, int value) 412 - { 413 - struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset]; 414 - u32 reg_value = readl(vexpress_sysreg_base + gpio->reg); 415 - 416 - if (value) 417 - reg_value |= gpio->value; 418 - else 419 - reg_value &= ~gpio->value; 420 - 421 - writel(reg_value, vexpress_sysreg_base + gpio->reg); 422 - } 423 - 424 - static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip, 425 - unsigned offset, int value) 426 - { 427 - vexpress_sysreg_gpio_set(chip, offset, value); 428 - 429 - return 0; 430 - } 431 - 432 - static struct gpio_chip vexpress_sysreg_gpio_chip = { 433 - .label = "vexpress-sysreg", 434 - .direction_input = vexpress_sysreg_gpio_direction_input, 435 - .direction_output = vexpress_sysreg_gpio_direction_output, 436 - .get = vexpress_sysreg_gpio_get, 437 - .set = vexpress_sysreg_gpio_set, 438 - .ngpio = ARRAY_SIZE(vexpress_sysreg_gpios), 439 - .base = 0, 440 - }; 441 - 442 - 443 - #define VEXPRESS_SYSREG_GREEN_LED(_name, _default_trigger, _gpio) \ 444 - { \ 445 - .name = "v2m:green:"_name, \ 446 - .default_trigger = _default_trigger, \ 447 - .gpio = VEXPRESS_GPIO_##_gpio, \ 448 - } 449 - 450 - struct gpio_led vexpress_sysreg_leds[] = { 451 - VEXPRESS_SYSREG_GREEN_LED("user1", "heartbeat", LED0), 452 - VEXPRESS_SYSREG_GREEN_LED("user2", "mmc0", LED1), 453 - VEXPRESS_SYSREG_GREEN_LED("user3", "cpu0", LED2), 454 - VEXPRESS_SYSREG_GREEN_LED("user4", "cpu1", LED3), 455 - VEXPRESS_SYSREG_GREEN_LED("user5", "cpu2", LED4), 456 - VEXPRESS_SYSREG_GREEN_LED("user6", "cpu3", LED5), 457 - VEXPRESS_SYSREG_GREEN_LED("user7", "cpu4", LED6), 458 - VEXPRESS_SYSREG_GREEN_LED("user8", "cpu5", LED7), 459 - }; 460 - 461 - struct gpio_led_platform_data vexpress_sysreg_leds_pdata = { 462 - .num_leds = ARRAY_SIZE(vexpress_sysreg_leds), 463 - .leds = vexpress_sysreg_leds, 464 - }; 465 - 466 - #endif 467 - 468 - 469 - static ssize_t vexpress_sysreg_sys_id_show(struct device *dev, 470 - struct device_attribute *attr, char *buf) 471 - { 472 - return sprintf(buf, "0x%08x\n", readl(vexpress_sysreg_base + SYS_ID)); 473 - } 474 - 475 - DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL); 476 228 477 229 static int vexpress_sysreg_probe(struct platform_device *pdev) 478 230 { 479 - int err; 480 - struct resource *res = platform_get_resource(pdev, 481 - IORESOURCE_MEM, 0); 231 + struct resource *mem; 232 + void __iomem *base; 233 + struct bgpio_chip *mmc_gpio_chip; 482 234 483 - if (!devm_request_mem_region(&pdev->dev, res->start, 484 - resource_size(res), pdev->name)) { 485 - dev_err(&pdev->dev, "Failed to request memory region!\n"); 486 - return -EBUSY; 487 - } 235 + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 236 + if (!mem) 237 + return -EINVAL; 488 238 489 - if (!vexpress_sysreg_base) 490 - vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, 491 - resource_size(res)); 492 - 493 - if (!vexpress_sysreg_base) { 494 - dev_err(&pdev->dev, "Failed to obtain base address!\n"); 495 - return -EFAULT; 496 - } 239 + base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); 240 + if (!base) 241 + return -ENOMEM; 497 242 498 243 vexpress_config_set_master(vexpress_sysreg_get_master()); 499 - vexpress_sysreg_dev = &pdev->dev; 500 244 501 - #ifdef CONFIG_GPIOLIB 502 - vexpress_sysreg_gpio_chip.dev = &pdev->dev; 503 - err = gpiochip_add(&vexpress_sysreg_gpio_chip); 504 - if (err) { 505 - dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n", 506 - err); 507 - return err; 508 - } 245 + /* 246 + * Duplicated SYS_MCI pseudo-GPIO controller for compatibility with 247 + * older trees using sysreg node for MMC control lines. 248 + */ 249 + mmc_gpio_chip = devm_kzalloc(&pdev->dev, sizeof(*mmc_gpio_chip), 250 + GFP_KERNEL); 251 + if (!mmc_gpio_chip) 252 + return -ENOMEM; 253 + bgpio_init(mmc_gpio_chip, &pdev->dev, 0x4, base + SYS_MCI, 254 + NULL, NULL, NULL, NULL, 0); 255 + mmc_gpio_chip->gc.ngpio = 2; 256 + gpiochip_add(&mmc_gpio_chip->gc); 509 257 510 - platform_device_register_data(vexpress_sysreg_dev, "leds-gpio", 511 - PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata, 512 - sizeof(vexpress_sysreg_leds_pdata)); 513 - #endif 514 - 515 - vexpress_sysreg_config_bridge = vexpress_config_bridge_register( 516 - &pdev->dev, &vexpress_sysreg_config_bridge_ops, NULL); 517 - WARN_ON(!vexpress_sysreg_config_bridge); 518 - 519 - device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id); 520 - 521 - return 0; 258 + return mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO, 259 + vexpress_sysreg_cells, 260 + ARRAY_SIZE(vexpress_sysreg_cells), mem, 0, NULL); 522 261 } 523 262 524 263 static const struct of_device_id vexpress_sysreg_match[] = {
+9
drivers/misc/Kconfig
··· 515 515 the genalloc API. It is supposed to be used for small on-chip SRAM 516 516 areas found on many SoCs. 517 517 518 + config VEXPRESS_SYSCFG 519 + bool "Versatile Express System Configuration driver" 520 + depends on VEXPRESS_CONFIG 521 + default y 522 + help 523 + ARM Ltd. Versatile Express uses specialised platform configuration 524 + bus. System Configuration interface is one of the possible means 525 + of generating transactions on this bus. 526 + 518 527 source "drivers/misc/c2port/Kconfig" 519 528 source "drivers/misc/eeprom/Kconfig" 520 529 source "drivers/misc/cb710/Kconfig"
+1
drivers/misc/Makefile
··· 55 55 obj-y += mic/ 56 56 obj-$(CONFIG_GENWQE) += genwqe/ 57 57 obj-$(CONFIG_ECHO) += echo/ 58 + obj-$(CONFIG_VEXPRESS_SYSCFG) += vexpress-syscfg.o
+324
drivers/misc/vexpress-syscfg.c
··· 1 + /* 2 + * This program is free software; you can redistribute it and/or modify 3 + * it under the terms of the GNU General Public License version 2 as 4 + * published by the Free Software Foundation. 5 + * 6 + * This program is distributed in the hope that it will be useful, 7 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 + * GNU General Public License for more details. 10 + * 11 + * Copyright (C) 2014 ARM Limited 12 + */ 13 + 14 + #include <linux/delay.h> 15 + #include <linux/err.h> 16 + #include <linux/io.h> 17 + #include <linux/of.h> 18 + #include <linux/platform_device.h> 19 + #include <linux/sched.h> 20 + #include <linux/slab.h> 21 + #include <linux/syscore_ops.h> 22 + #include <linux/vexpress.h> 23 + 24 + 25 + #define SYS_CFGDATA 0x0 26 + 27 + #define SYS_CFGCTRL 0x4 28 + #define SYS_CFGCTRL_START (1 << 31) 29 + #define SYS_CFGCTRL_WRITE (1 << 30) 30 + #define SYS_CFGCTRL_DCC(n) (((n) & 0xf) << 26) 31 + #define SYS_CFGCTRL_FUNC(n) (((n) & 0x3f) << 20) 32 + #define SYS_CFGCTRL_SITE(n) (((n) & 0x3) << 16) 33 + #define SYS_CFGCTRL_POSITION(n) (((n) & 0xf) << 12) 34 + #define SYS_CFGCTRL_DEVICE(n) (((n) & 0xfff) << 0) 35 + 36 + #define SYS_CFGSTAT 0x8 37 + #define SYS_CFGSTAT_ERR (1 << 1) 38 + #define SYS_CFGSTAT_COMPLETE (1 << 0) 39 + 40 + 41 + struct vexpress_syscfg { 42 + struct device *dev; 43 + void __iomem *base; 44 + struct list_head funcs; 45 + }; 46 + 47 + struct vexpress_syscfg_func { 48 + struct list_head list; 49 + struct vexpress_syscfg *syscfg; 50 + struct regmap *regmap; 51 + int num_templates; 52 + u32 template[0]; /* Keep it last! */ 53 + }; 54 + 55 + 56 + static int vexpress_syscfg_exec(struct vexpress_syscfg_func *func, 57 + int index, bool write, u32 *data) 58 + { 59 + struct vexpress_syscfg *syscfg = func->syscfg; 60 + u32 command, status; 61 + int tries; 62 + long timeout; 63 + 64 + if (WARN_ON(index > func->num_templates)) 65 + return -EINVAL; 66 + 67 + command = readl(syscfg->base + SYS_CFGCTRL); 68 + if (WARN_ON(command & SYS_CFGCTRL_START)) 69 + return -EBUSY; 70 + 71 + command = func->template[index]; 72 + command |= SYS_CFGCTRL_START; 73 + command |= write ? SYS_CFGCTRL_WRITE : 0; 74 + 75 + /* Use a canary for reads */ 76 + if (!write) 77 + *data = 0xdeadbeef; 78 + 79 + dev_dbg(syscfg->dev, "func %p, command %x, data %x\n", 80 + func, command, *data); 81 + writel(*data, syscfg->base + SYS_CFGDATA); 82 + writel(0, syscfg->base + SYS_CFGSTAT); 83 + writel(command, syscfg->base + SYS_CFGCTRL); 84 + mb(); 85 + 86 + /* The operation can take ages... Go to sleep, 100us initially */ 87 + tries = 100; 88 + timeout = 100; 89 + do { 90 + if (!irqs_disabled()) { 91 + set_current_state(TASK_INTERRUPTIBLE); 92 + schedule_timeout(usecs_to_jiffies(timeout)); 93 + if (signal_pending(current)) 94 + return -EINTR; 95 + } else { 96 + udelay(timeout); 97 + } 98 + 99 + status = readl(syscfg->base + SYS_CFGSTAT); 100 + if (status & SYS_CFGSTAT_ERR) 101 + return -EFAULT; 102 + 103 + if (timeout > 20) 104 + timeout -= 20; 105 + } while (--tries && !(status & SYS_CFGSTAT_COMPLETE)); 106 + if (WARN_ON_ONCE(!tries)) 107 + return -ETIMEDOUT; 108 + 109 + if (!write) { 110 + *data = readl(syscfg->base + SYS_CFGDATA); 111 + dev_dbg(syscfg->dev, "func %p, read data %x\n", func, *data); 112 + } 113 + 114 + return 0; 115 + } 116 + 117 + static int vexpress_syscfg_read(void *context, unsigned int index, 118 + unsigned int *val) 119 + { 120 + struct vexpress_syscfg_func *func = context; 121 + 122 + return vexpress_syscfg_exec(func, index, false, val); 123 + } 124 + 125 + static int vexpress_syscfg_write(void *context, unsigned int index, 126 + unsigned int val) 127 + { 128 + struct vexpress_syscfg_func *func = context; 129 + 130 + return vexpress_syscfg_exec(func, index, true, &val); 131 + } 132 + 133 + struct regmap_config vexpress_syscfg_regmap_config = { 134 + .lock = vexpress_config_lock, 135 + .unlock = vexpress_config_unlock, 136 + .reg_bits = 32, 137 + .val_bits = 32, 138 + .reg_read = vexpress_syscfg_read, 139 + .reg_write = vexpress_syscfg_write, 140 + .reg_format_endian = REGMAP_ENDIAN_LITTLE, 141 + .val_format_endian = REGMAP_ENDIAN_LITTLE, 142 + }; 143 + 144 + 145 + static struct regmap *vexpress_syscfg_regmap_init(struct device *dev, 146 + void *context) 147 + { 148 + struct platform_device *pdev = to_platform_device(dev); 149 + struct vexpress_syscfg *syscfg = context; 150 + struct vexpress_syscfg_func *func; 151 + struct property *prop; 152 + const __be32 *val = NULL; 153 + __be32 energy_quirk[4]; 154 + int num; 155 + u32 site, position, dcc; 156 + int i; 157 + 158 + if (dev->of_node) { 159 + int err = vexpress_config_get_topo(dev->of_node, &site, 160 + &position, &dcc); 161 + 162 + if (err) 163 + return ERR_PTR(err); 164 + 165 + prop = of_find_property(dev->of_node, 166 + "arm,vexpress-sysreg,func", NULL); 167 + if (!prop) 168 + return ERR_PTR(-EINVAL); 169 + 170 + num = prop->length / sizeof(u32) / 2; 171 + val = prop->value; 172 + } else { 173 + if (pdev->num_resources != 1 || 174 + pdev->resource[0].flags != IORESOURCE_BUS) 175 + return ERR_PTR(-EFAULT); 176 + 177 + site = pdev->resource[0].start; 178 + if (site == VEXPRESS_SITE_MASTER) 179 + site = vexpress_config_get_master(); 180 + position = 0; 181 + dcc = 0; 182 + num = 1; 183 + } 184 + 185 + /* 186 + * "arm,vexpress-energy" function used to be described 187 + * by its first device only, now it requires both 188 + */ 189 + if (num == 1 && of_device_is_compatible(dev->of_node, 190 + "arm,vexpress-energy")) { 191 + num = 2; 192 + energy_quirk[0] = *val; 193 + energy_quirk[2] = *val++; 194 + energy_quirk[1] = *val; 195 + energy_quirk[3] = cpu_to_be32(be32_to_cpup(val) + 1); 196 + val = energy_quirk; 197 + } 198 + 199 + func = kzalloc(sizeof(*func) + sizeof(*func->template) * num, 200 + GFP_KERNEL); 201 + if (!func) 202 + return NULL; 203 + 204 + func->syscfg = syscfg; 205 + func->num_templates = num; 206 + 207 + for (i = 0; i < num; i++) { 208 + u32 function, device; 209 + 210 + if (dev->of_node) { 211 + function = be32_to_cpup(val++); 212 + device = be32_to_cpup(val++); 213 + } else { 214 + function = pdev->resource[0].end; 215 + device = pdev->id; 216 + } 217 + 218 + dev_dbg(dev, "func %p: %u/%u/%u/%u/%u\n", 219 + func, site, position, dcc, 220 + function, device); 221 + 222 + func->template[i] = SYS_CFGCTRL_DCC(dcc); 223 + func->template[i] |= SYS_CFGCTRL_SITE(site); 224 + func->template[i] |= SYS_CFGCTRL_POSITION(position); 225 + func->template[i] |= SYS_CFGCTRL_FUNC(function); 226 + func->template[i] |= SYS_CFGCTRL_DEVICE(device); 227 + } 228 + 229 + vexpress_syscfg_regmap_config.max_register = num - 1; 230 + 231 + func->regmap = regmap_init(dev, NULL, func, 232 + &vexpress_syscfg_regmap_config); 233 + 234 + if (IS_ERR(func->regmap)) 235 + kfree(func); 236 + else 237 + list_add(&func->list, &syscfg->funcs); 238 + 239 + return func->regmap; 240 + } 241 + 242 + static void vexpress_syscfg_regmap_exit(struct regmap *regmap, void *context) 243 + { 244 + struct vexpress_syscfg *syscfg = context; 245 + struct vexpress_syscfg_func *func, *tmp; 246 + 247 + regmap_exit(regmap); 248 + 249 + list_for_each_entry_safe(func, tmp, &syscfg->funcs, list) { 250 + if (func->regmap == regmap) { 251 + list_del(&syscfg->funcs); 252 + kfree(func); 253 + break; 254 + } 255 + } 256 + } 257 + 258 + static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops = { 259 + .regmap_init = vexpress_syscfg_regmap_init, 260 + .regmap_exit = vexpress_syscfg_regmap_exit, 261 + }; 262 + 263 + 264 + /* Non-DT hack, to be gone... */ 265 + static struct device *vexpress_syscfg_bridge; 266 + 267 + int vexpress_syscfg_device_register(struct platform_device *pdev) 268 + { 269 + pdev->dev.parent = vexpress_syscfg_bridge; 270 + 271 + return platform_device_register(pdev); 272 + } 273 + 274 + 275 + int vexpress_syscfg_probe(struct platform_device *pdev) 276 + { 277 + struct vexpress_syscfg *syscfg; 278 + struct resource *res; 279 + struct device *bridge; 280 + 281 + syscfg = devm_kzalloc(&pdev->dev, sizeof(*syscfg), GFP_KERNEL); 282 + if (!syscfg) 283 + return -ENOMEM; 284 + syscfg->dev = &pdev->dev; 285 + INIT_LIST_HEAD(&syscfg->funcs); 286 + 287 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 288 + if (!devm_request_mem_region(&pdev->dev, res->start, 289 + resource_size(res), pdev->name)) 290 + return -EBUSY; 291 + 292 + syscfg->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 293 + if (!syscfg->base) 294 + return -EFAULT; 295 + 296 + /* Must use dev.parent (MFD), as that's where DT phandle points at... */ 297 + bridge = vexpress_config_bridge_register(pdev->dev.parent, 298 + &vexpress_syscfg_bridge_ops, syscfg); 299 + if (IS_ERR(bridge)) 300 + return PTR_ERR(bridge); 301 + 302 + /* Non-DT case */ 303 + if (!pdev->dev.of_node) 304 + vexpress_syscfg_bridge = bridge; 305 + 306 + return 0; 307 + } 308 + 309 + static const struct platform_device_id vexpress_syscfg_id_table[] = { 310 + { "vexpress-syscfg", }, 311 + {}, 312 + }; 313 + 314 + static struct platform_driver vexpress_syscfg_driver = { 315 + .driver.name = "vexpress-syscfg", 316 + .id_table = vexpress_syscfg_id_table, 317 + .probe = vexpress_syscfg_probe, 318 + }; 319 + 320 + static int __init vexpress_syscfg_init(void) 321 + { 322 + return platform_driver_register(&vexpress_syscfg_driver); 323 + } 324 + core_initcall(vexpress_syscfg_init);
+2 -14
include/linux/vexpress.h
··· 24 24 #define VEXPRESS_SITE_DB2 2 25 25 #define VEXPRESS_SITE_MASTER 0xf 26 26 27 - #define VEXPRESS_GPIO_MMC_CARDIN 0 28 - #define VEXPRESS_GPIO_MMC_WPROT 1 29 - #define VEXPRESS_GPIO_FLASH_WPn 2 30 - #define VEXPRESS_GPIO_LED0 3 31 - #define VEXPRESS_GPIO_LED1 4 32 - #define VEXPRESS_GPIO_LED2 5 33 - #define VEXPRESS_GPIO_LED3 6 34 - #define VEXPRESS_GPIO_LED4 7 35 - #define VEXPRESS_GPIO_LED5 8 36 - #define VEXPRESS_GPIO_LED6 9 37 - #define VEXPRESS_GPIO_LED7 10 38 - 39 27 #define VEXPRESS_RES_FUNC(_site, _func) \ 40 28 { \ 41 29 .start = (_site), \ ··· 58 70 59 71 /* Platform control */ 60 72 73 + unsigned int vexpress_get_mci_cardin(struct device *dev); 61 74 u32 vexpress_get_procid(int site); 62 75 u32 vexpress_get_hbi(int site); 63 76 void *vexpress_get_24mhz_clock_base(void); 64 77 void vexpress_flags_set(u32 data); 65 78 66 79 void vexpress_sysreg_early_init(void __iomem *base); 67 - void vexpress_sysreg_of_early_init(void); 68 - int vexpress_sysreg_config_device_register(struct platform_device *pdev); 80 + int vexpress_syscfg_device_register(struct platform_device *pdev); 69 81 70 82 /* Clocks */ 71 83