Linux Audio

Check our new training course

Loading...
v5.9
  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");
 
 
 
 
v3.15
 
  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) 2012 ARM Limited
 12 */
 13
 
 14#include <linux/err.h>
 15#include <linux/gpio.h>
 16#include <linux/io.h>
 17#include <linux/leds.h>
 18#include <linux/of_address.h>
 
 
 19#include <linux/platform_device.h>
 20#include <linux/regulator/driver.h>
 21#include <linux/slab.h>
 22#include <linux/stat.h>
 23#include <linux/timer.h>
 24#include <linux/vexpress.h>
 25
 26#define SYS_ID			0x000
 27#define SYS_SW			0x004
 28#define SYS_LED			0x008
 29#define SYS_100HZ		0x024
 30#define SYS_FLAGS		0x030
 31#define SYS_FLAGSSET		0x030
 32#define SYS_FLAGSCLR		0x034
 33#define SYS_NVFLAGS		0x038
 34#define SYS_NVFLAGSSET		0x038
 35#define SYS_NVFLAGSCLR		0x03c
 36#define SYS_MCI			0x048
 37#define SYS_FLASH		0x04c
 38#define SYS_CFGSW		0x058
 39#define SYS_24MHZ		0x05c
 40#define SYS_MISC		0x060
 41#define SYS_DMA			0x064
 42#define SYS_PROCID0		0x084
 43#define SYS_PROCID1		0x088
 44#define SYS_CFGDATA		0x0a0
 45#define SYS_CFGCTRL		0x0a4
 46#define SYS_CFGSTAT		0x0a8
 47
 48#define SYS_HBI_MASK		0xfff
 49#define SYS_ID_HBI_SHIFT	16
 50#define SYS_PROCIDx_HBI_SHIFT	0
 51
 52#define SYS_LED_LED(n)		(1 << (n))
 53
 54#define SYS_MCI_CARDIN		(1 << 0)
 55#define SYS_MCI_WPROT		(1 << 1)
 56
 57#define SYS_FLASH_WPn		(1 << 0)
 58
 59#define SYS_MISC_MASTERSITE	(1 << 14)
 60
 61#define SYS_CFGCTRL_START	(1 << 31)
 62#define SYS_CFGCTRL_WRITE	(1 << 30)
 63#define SYS_CFGCTRL_DCC(n)	(((n) & 0xf) << 26)
 64#define SYS_CFGCTRL_FUNC(n)	(((n) & 0x3f) << 20)
 65#define SYS_CFGCTRL_SITE(n)	(((n) & 0x3) << 16)
 66#define SYS_CFGCTRL_POSITION(n)	(((n) & 0xf) << 12)
 67#define SYS_CFGCTRL_DEVICE(n)	(((n) & 0xfff) << 0)
 68
 69#define SYS_CFGSTAT_ERR		(1 << 1)
 70#define SYS_CFGSTAT_COMPLETE	(1 << 0)
 71
 72
 73static void __iomem *vexpress_sysreg_base;
 74static struct device *vexpress_sysreg_dev;
 75static int vexpress_master_site;
 76
 77
 78void vexpress_flags_set(u32 data)
 79{
 80	writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR);
 81	writel(data, vexpress_sysreg_base + SYS_FLAGSSET);
 82}
 83
 84u32 vexpress_get_procid(int site)
 85{
 86	if (site == VEXPRESS_SITE_MASTER)
 87		site = vexpress_master_site;
 88
 89	return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
 90			SYS_PROCID0 : SYS_PROCID1));
 91}
 92
 93u32 vexpress_get_hbi(int site)
 94{
 95	u32 id;
 96
 97	switch (site) {
 98	case VEXPRESS_SITE_MB:
 99		id = readl(vexpress_sysreg_base + SYS_ID);
100		return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK;
101	case VEXPRESS_SITE_MASTER:
102	case VEXPRESS_SITE_DB1:
103	case VEXPRESS_SITE_DB2:
104		id = vexpress_get_procid(site);
105		return (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK;
106	}
107
108	return ~0;
109}
110
111void __iomem *vexpress_get_24mhz_clock_base(void)
112{
113	return vexpress_sysreg_base + SYS_24MHZ;
114}
115
116
117static void vexpress_sysreg_find_prop(struct device_node *node,
118		const char *name, u32 *val)
119{
120	of_node_get(node);
121	while (node) {
122		if (of_property_read_u32(node, name, val) == 0) {
123			of_node_put(node);
124			return;
125		}
126		node = of_get_next_parent(node);
127	}
128}
129
130unsigned __vexpress_get_site(struct device *dev, struct device_node *node)
131{
132	u32 site = 0;
133
134	WARN_ON(dev && node && dev->of_node != node);
135	if (dev && !node)
136		node = dev->of_node;
137
138	if (node) {
139		vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
140	} else if (dev && dev->bus == &platform_bus_type) {
141		struct platform_device *pdev = to_platform_device(dev);
142
143		if (pdev->num_resources == 1 &&
144				pdev->resource[0].flags == IORESOURCE_BUS)
145			site = pdev->resource[0].start;
146	} else if (dev && strncmp(dev_name(dev), "ct:", 3) == 0) {
147		site = VEXPRESS_SITE_MASTER;
148	}
149
150	if (site == VEXPRESS_SITE_MASTER)
151		site = vexpress_master_site;
152
153	return site;
154}
155
156
157struct vexpress_sysreg_config_func {
158	u32 template;
159	u32 device;
160};
161
162static struct vexpress_config_bridge *vexpress_sysreg_config_bridge;
163static struct timer_list vexpress_sysreg_config_timer;
164static u32 *vexpress_sysreg_config_data;
165static int vexpress_sysreg_config_tries;
166
167static void *vexpress_sysreg_config_func_get(struct device *dev,
168		struct device_node *node)
169{
170	struct vexpress_sysreg_config_func *config_func;
171	u32 site = 0;
172	u32 position = 0;
173	u32 dcc = 0;
174	u32 func_device[2];
175	int err = -EFAULT;
176
177	if (node) {
178		of_node_get(node);
179		vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
180		vexpress_sysreg_find_prop(node, "arm,vexpress,position",
181				&position);
182		vexpress_sysreg_find_prop(node, "arm,vexpress,dcc", &dcc);
183		err = of_property_read_u32_array(node,
184				"arm,vexpress-sysreg,func", func_device,
185				ARRAY_SIZE(func_device));
186		of_node_put(node);
187	} else if (dev && dev->bus == &platform_bus_type) {
188		struct platform_device *pdev = to_platform_device(dev);
189
190		if (pdev->num_resources == 1 &&
191				pdev->resource[0].flags == IORESOURCE_BUS) {
192			site = pdev->resource[0].start;
193			func_device[0] = pdev->resource[0].end;
194			func_device[1] = pdev->id;
195			err = 0;
196		}
197	}
198	if (err)
199		return NULL;
200
201	config_func = kzalloc(sizeof(*config_func), GFP_KERNEL);
202	if (!config_func)
203		return NULL;
204
205	config_func->template = SYS_CFGCTRL_DCC(dcc);
206	config_func->template |= SYS_CFGCTRL_FUNC(func_device[0]);
207	config_func->template |= SYS_CFGCTRL_SITE(site == VEXPRESS_SITE_MASTER ?
208			vexpress_master_site : site);
209	config_func->template |= SYS_CFGCTRL_POSITION(position);
210	config_func->device |= func_device[1];
211
212	dev_dbg(vexpress_sysreg_dev, "func 0x%p = 0x%x, %d\n", config_func,
213			config_func->template, config_func->device);
214
215	return config_func;
216}
217
218static void vexpress_sysreg_config_func_put(void *func)
219{
220	kfree(func);
221}
222
223static int vexpress_sysreg_config_func_exec(void *func, int offset,
224		bool write, u32 *data)
225{
226	int status;
227	struct vexpress_sysreg_config_func *config_func = func;
228	u32 command;
229
230	if (WARN_ON(!vexpress_sysreg_base))
231		return -ENOENT;
232
233	command = readl(vexpress_sysreg_base + SYS_CFGCTRL);
234	if (WARN_ON(command & SYS_CFGCTRL_START))
235		return -EBUSY;
236
237	command = SYS_CFGCTRL_START;
238	command |= write ? SYS_CFGCTRL_WRITE : 0;
239	command |= config_func->template;
240	command |= SYS_CFGCTRL_DEVICE(config_func->device + offset);
241
242	/* Use a canary for reads */
243	if (!write)
244		*data = 0xdeadbeef;
245
246	dev_dbg(vexpress_sysreg_dev, "command %x, data %x\n",
247			command, *data);
248	writel(*data, vexpress_sysreg_base + SYS_CFGDATA);
249	writel(0, vexpress_sysreg_base + SYS_CFGSTAT);
250	writel(command, vexpress_sysreg_base + SYS_CFGCTRL);
251	mb();
252
253	if (vexpress_sysreg_dev) {
254		/* Schedule completion check */
255		if (!write)
256			vexpress_sysreg_config_data = data;
257		vexpress_sysreg_config_tries = 100;
258		mod_timer(&vexpress_sysreg_config_timer,
259				jiffies + usecs_to_jiffies(100));
260		status = VEXPRESS_CONFIG_STATUS_WAIT;
261	} else {
262		/* Early execution, no timer available, have to spin */
263		u32 cfgstat;
264
265		do {
266			cpu_relax();
267			cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
268		} while (!cfgstat);
269
270		if (!write && (cfgstat & SYS_CFGSTAT_COMPLETE))
271			*data = readl(vexpress_sysreg_base + SYS_CFGDATA);
272		status = VEXPRESS_CONFIG_STATUS_DONE;
273
274		if (cfgstat & SYS_CFGSTAT_ERR)
275			status = -EINVAL;
276	}
277
278	return status;
279}
280
281struct vexpress_config_bridge_info vexpress_sysreg_config_bridge_info = {
282	.name = "vexpress-sysreg",
283	.func_get = vexpress_sysreg_config_func_get,
284	.func_put = vexpress_sysreg_config_func_put,
285	.func_exec = vexpress_sysreg_config_func_exec,
286};
287
288static void vexpress_sysreg_config_complete(unsigned long data)
289{
290	int status = VEXPRESS_CONFIG_STATUS_DONE;
291	u32 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
292
293	if (cfgstat & SYS_CFGSTAT_ERR)
294		status = -EINVAL;
295	if (!vexpress_sysreg_config_tries--)
296		status = -ETIMEDOUT;
297
298	if (status < 0) {
299		dev_err(vexpress_sysreg_dev, "error %d\n", status);
300	} else if (!(cfgstat & SYS_CFGSTAT_COMPLETE)) {
301		mod_timer(&vexpress_sysreg_config_timer,
302				jiffies + usecs_to_jiffies(50));
303		return;
304	}
305
306	if (vexpress_sysreg_config_data) {
307		*vexpress_sysreg_config_data = readl(vexpress_sysreg_base +
308				SYS_CFGDATA);
309		dev_dbg(vexpress_sysreg_dev, "read data %x\n",
310				*vexpress_sysreg_config_data);
311		vexpress_sysreg_config_data = NULL;
312	}
313
314	vexpress_config_complete(vexpress_sysreg_config_bridge, status);
315}
316
317
318void vexpress_sysreg_setup(struct device_node *node)
319{
320	if (WARN_ON(!vexpress_sysreg_base))
321		return;
322
323	if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
324		vexpress_master_site = VEXPRESS_SITE_DB2;
325	else
326		vexpress_master_site = VEXPRESS_SITE_DB1;
327
328	vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
329			node, &vexpress_sysreg_config_bridge_info);
330	WARN_ON(!vexpress_sysreg_config_bridge);
331}
332
333void __init vexpress_sysreg_early_init(void __iomem *base)
334{
335	vexpress_sysreg_base = base;
336	vexpress_sysreg_setup(NULL);
337}
338
339void __init vexpress_sysreg_of_early_init(void)
340{
341	struct device_node *node;
342
343	if (vexpress_sysreg_base)
344		return;
345
346	node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
347	if (node) {
348		vexpress_sysreg_base = of_iomap(node, 0);
349		vexpress_sysreg_setup(node);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350	}
351}
352
353
354#ifdef CONFIG_GPIOLIB
355
356#define VEXPRESS_SYSREG_GPIO(_name, _reg, _value) \
357	[VEXPRESS_GPIO_##_name] = { \
358		.reg = _reg, \
359		.value = _reg##_##_value, \
360	}
361
362static struct vexpress_sysreg_gpio {
363	unsigned long reg;
364	u32 value;
365} vexpress_sysreg_gpios[] = {
366	VEXPRESS_SYSREG_GPIO(MMC_CARDIN,	SYS_MCI,	CARDIN),
367	VEXPRESS_SYSREG_GPIO(MMC_WPROT,		SYS_MCI,	WPROT),
368	VEXPRESS_SYSREG_GPIO(FLASH_WPn,		SYS_FLASH,	WPn),
369	VEXPRESS_SYSREG_GPIO(LED0,		SYS_LED,	LED(0)),
370	VEXPRESS_SYSREG_GPIO(LED1,		SYS_LED,	LED(1)),
371	VEXPRESS_SYSREG_GPIO(LED2,		SYS_LED,	LED(2)),
372	VEXPRESS_SYSREG_GPIO(LED3,		SYS_LED,	LED(3)),
373	VEXPRESS_SYSREG_GPIO(LED4,		SYS_LED,	LED(4)),
374	VEXPRESS_SYSREG_GPIO(LED5,		SYS_LED,	LED(5)),
375	VEXPRESS_SYSREG_GPIO(LED6,		SYS_LED,	LED(6)),
376	VEXPRESS_SYSREG_GPIO(LED7,		SYS_LED,	LED(7)),
377};
378
379static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip,
380				       unsigned offset)
381{
382	return 0;
383}
384
385static int vexpress_sysreg_gpio_get(struct gpio_chip *chip,
386				       unsigned offset)
387{
388	struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
389	u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
390
391	return !!(reg_value & gpio->value);
392}
393
394static void vexpress_sysreg_gpio_set(struct gpio_chip *chip,
395				       unsigned offset, int value)
396{
397	struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
398	u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
399
400	if (value)
401		reg_value |= gpio->value;
402	else
403		reg_value &= ~gpio->value;
404
405	writel(reg_value, vexpress_sysreg_base + gpio->reg);
406}
407
408static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip,
409						unsigned offset, int value)
410{
411	vexpress_sysreg_gpio_set(chip, offset, value);
412
413	return 0;
414}
415
416static struct gpio_chip vexpress_sysreg_gpio_chip = {
417	.label = "vexpress-sysreg",
418	.direction_input = vexpress_sysreg_gpio_direction_input,
419	.direction_output = vexpress_sysreg_gpio_direction_output,
420	.get = vexpress_sysreg_gpio_get,
421	.set = vexpress_sysreg_gpio_set,
422	.ngpio = ARRAY_SIZE(vexpress_sysreg_gpios),
423	.base = 0,
424};
425
426
427#define VEXPRESS_SYSREG_GREEN_LED(_name, _default_trigger, _gpio) \
428	{ \
429		.name = "v2m:green:"_name, \
430		.default_trigger = _default_trigger, \
431		.gpio = VEXPRESS_GPIO_##_gpio, \
432	}
433
434struct gpio_led vexpress_sysreg_leds[] = {
435	VEXPRESS_SYSREG_GREEN_LED("user1",	"heartbeat",	LED0),
436	VEXPRESS_SYSREG_GREEN_LED("user2",	"mmc0",		LED1),
437	VEXPRESS_SYSREG_GREEN_LED("user3",	"cpu0",		LED2),
438	VEXPRESS_SYSREG_GREEN_LED("user4",	"cpu1",		LED3),
439	VEXPRESS_SYSREG_GREEN_LED("user5",	"cpu2",		LED4),
440	VEXPRESS_SYSREG_GREEN_LED("user6",	"cpu3",		LED5),
441	VEXPRESS_SYSREG_GREEN_LED("user7",	"cpu4",		LED6),
442	VEXPRESS_SYSREG_GREEN_LED("user8",	"cpu5",		LED7),
443};
444
445struct gpio_led_platform_data vexpress_sysreg_leds_pdata = {
446	.num_leds = ARRAY_SIZE(vexpress_sysreg_leds),
447	.leds = vexpress_sysreg_leds,
448};
449
450#endif
451
452
453static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
454		struct device_attribute *attr, char *buf)
455{
456	return sprintf(buf, "0x%08x\n", readl(vexpress_sysreg_base + SYS_ID));
457}
458
459DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL);
460
461static int vexpress_sysreg_probe(struct platform_device *pdev)
462{
463	int err;
464	struct resource *res = platform_get_resource(pdev,
465			IORESOURCE_MEM, 0);
466
467	if (!devm_request_mem_region(&pdev->dev, res->start,
468			resource_size(res), pdev->name)) {
469		dev_err(&pdev->dev, "Failed to request memory region!\n");
470		return -EBUSY;
471	}
472
473	if (!vexpress_sysreg_base) {
474		vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
475				resource_size(res));
476		vexpress_sysreg_setup(pdev->dev.of_node);
477	}
478
479	if (!vexpress_sysreg_base) {
480		dev_err(&pdev->dev, "Failed to obtain base address!\n");
481		return -EFAULT;
482	}
483
484	setup_timer(&vexpress_sysreg_config_timer,
485			vexpress_sysreg_config_complete, 0);
486
487	vexpress_sysreg_dev = &pdev->dev;
488
489#ifdef CONFIG_GPIOLIB
490	vexpress_sysreg_gpio_chip.dev = &pdev->dev;
491	err = gpiochip_add(&vexpress_sysreg_gpio_chip);
492	if (err) {
493		vexpress_config_bridge_unregister(
494				vexpress_sysreg_config_bridge);
495		dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n",
496				err);
497		return err;
498	}
499
500	platform_device_register_data(vexpress_sysreg_dev, "leds-gpio",
501			PLATFORM_DEVID_AUTO, &vexpress_sysreg_leds_pdata,
502			sizeof(vexpress_sysreg_leds_pdata));
503#endif
504
505	device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
506
507	return 0;
508}
509
510static const struct of_device_id vexpress_sysreg_match[] = {
511	{ .compatible = "arm,vexpress-sysreg", },
512	{},
513};
 
514
515static struct platform_driver vexpress_sysreg_driver = {
516	.driver = {
517		.name = "vexpress-sysreg",
518		.of_match_table = vexpress_sysreg_match,
519	},
520	.probe = vexpress_sysreg_probe,
521};
522
523static int __init vexpress_sysreg_init(void)
524{
525	vexpress_sysreg_of_early_init();
526	return platform_driver_register(&vexpress_sysreg_driver);
527}
528core_initcall(vexpress_sysreg_init);