xref: /kernel/linux/linux-6.6/arch/mips/ar7/platform.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org>
462306a36Sopenharmony_ci * Copyright (C) 2006,2007 Eugene Konev <ejka@openwrt.org>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/init.h>
862306a36Sopenharmony_ci#include <linux/types.h>
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1162306a36Sopenharmony_ci#include <linux/platform_device.h>
1262306a36Sopenharmony_ci#include <linux/mtd/physmap.h>
1362306a36Sopenharmony_ci#include <linux/serial.h>
1462306a36Sopenharmony_ci#include <linux/serial_8250.h>
1562306a36Sopenharmony_ci#include <linux/ioport.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <linux/vlynq.h>
1862306a36Sopenharmony_ci#include <linux/leds.h>
1962306a36Sopenharmony_ci#include <linux/string.h>
2062306a36Sopenharmony_ci#include <linux/etherdevice.h>
2162306a36Sopenharmony_ci#include <linux/phy.h>
2262306a36Sopenharmony_ci#include <linux/phy_fixed.h>
2362306a36Sopenharmony_ci#include <linux/gpio.h>
2462306a36Sopenharmony_ci#include <linux/clk.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include <asm/addrspace.h>
2762306a36Sopenharmony_ci#include <asm/mach-ar7/ar7.h>
2862306a36Sopenharmony_ci#include <asm/mach-ar7/prom.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/*****************************************************************************
3162306a36Sopenharmony_ci * VLYNQ Bus
3262306a36Sopenharmony_ci ****************************************************************************/
3362306a36Sopenharmony_cistruct plat_vlynq_data {
3462306a36Sopenharmony_ci	struct plat_vlynq_ops ops;
3562306a36Sopenharmony_ci	int gpio_bit;
3662306a36Sopenharmony_ci	int reset_bit;
3762306a36Sopenharmony_ci};
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic int vlynq_on(struct vlynq_device *dev)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	int ret;
4262306a36Sopenharmony_ci	struct plat_vlynq_data *pdata = dev->dev.platform_data;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	ret = gpio_request(pdata->gpio_bit, "vlynq");
4562306a36Sopenharmony_ci	if (ret)
4662306a36Sopenharmony_ci		goto out;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	ar7_device_reset(pdata->reset_bit);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	ret = ar7_gpio_disable(pdata->gpio_bit);
5162306a36Sopenharmony_ci	if (ret)
5262306a36Sopenharmony_ci		goto out_enabled;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	ret = ar7_gpio_enable(pdata->gpio_bit);
5562306a36Sopenharmony_ci	if (ret)
5662306a36Sopenharmony_ci		goto out_enabled;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	ret = gpio_direction_output(pdata->gpio_bit, 0);
5962306a36Sopenharmony_ci	if (ret)
6062306a36Sopenharmony_ci		goto out_gpio_enabled;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	msleep(50);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	gpio_set_value(pdata->gpio_bit, 1);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	msleep(50);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	return 0;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ciout_gpio_enabled:
7162306a36Sopenharmony_ci	ar7_gpio_disable(pdata->gpio_bit);
7262306a36Sopenharmony_ciout_enabled:
7362306a36Sopenharmony_ci	ar7_device_disable(pdata->reset_bit);
7462306a36Sopenharmony_ci	gpio_free(pdata->gpio_bit);
7562306a36Sopenharmony_ciout:
7662306a36Sopenharmony_ci	return ret;
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic void vlynq_off(struct vlynq_device *dev)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	struct plat_vlynq_data *pdata = dev->dev.platform_data;
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	ar7_gpio_disable(pdata->gpio_bit);
8462306a36Sopenharmony_ci	gpio_free(pdata->gpio_bit);
8562306a36Sopenharmony_ci	ar7_device_disable(pdata->reset_bit);
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cistatic struct resource vlynq_low_res[] = {
8962306a36Sopenharmony_ci	{
9062306a36Sopenharmony_ci		.name	= "regs",
9162306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
9262306a36Sopenharmony_ci		.start	= AR7_REGS_VLYNQ0,
9362306a36Sopenharmony_ci		.end	= AR7_REGS_VLYNQ0 + 0xff,
9462306a36Sopenharmony_ci	},
9562306a36Sopenharmony_ci	{
9662306a36Sopenharmony_ci		.name	= "irq",
9762306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
9862306a36Sopenharmony_ci		.start	= 29,
9962306a36Sopenharmony_ci		.end	= 29,
10062306a36Sopenharmony_ci	},
10162306a36Sopenharmony_ci	{
10262306a36Sopenharmony_ci		.name	= "mem",
10362306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
10462306a36Sopenharmony_ci		.start	= 0x04000000,
10562306a36Sopenharmony_ci		.end	= 0x04ffffff,
10662306a36Sopenharmony_ci	},
10762306a36Sopenharmony_ci	{
10862306a36Sopenharmony_ci		.name	= "devirq",
10962306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
11062306a36Sopenharmony_ci		.start	= 80,
11162306a36Sopenharmony_ci		.end	= 111,
11262306a36Sopenharmony_ci	},
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic struct resource vlynq_high_res[] = {
11662306a36Sopenharmony_ci	{
11762306a36Sopenharmony_ci		.name	= "regs",
11862306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
11962306a36Sopenharmony_ci		.start	= AR7_REGS_VLYNQ1,
12062306a36Sopenharmony_ci		.end	= AR7_REGS_VLYNQ1 + 0xff,
12162306a36Sopenharmony_ci	},
12262306a36Sopenharmony_ci	{
12362306a36Sopenharmony_ci		.name	= "irq",
12462306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
12562306a36Sopenharmony_ci		.start	= 33,
12662306a36Sopenharmony_ci		.end	= 33,
12762306a36Sopenharmony_ci	},
12862306a36Sopenharmony_ci	{
12962306a36Sopenharmony_ci		.name	= "mem",
13062306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
13162306a36Sopenharmony_ci		.start	= 0x0c000000,
13262306a36Sopenharmony_ci		.end	= 0x0cffffff,
13362306a36Sopenharmony_ci	},
13462306a36Sopenharmony_ci	{
13562306a36Sopenharmony_ci		.name	= "devirq",
13662306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
13762306a36Sopenharmony_ci		.start	= 112,
13862306a36Sopenharmony_ci		.end	= 143,
13962306a36Sopenharmony_ci	},
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic struct plat_vlynq_data vlynq_low_data = {
14362306a36Sopenharmony_ci	.ops = {
14462306a36Sopenharmony_ci		.on	= vlynq_on,
14562306a36Sopenharmony_ci		.off	= vlynq_off,
14662306a36Sopenharmony_ci	},
14762306a36Sopenharmony_ci	.reset_bit	= 20,
14862306a36Sopenharmony_ci	.gpio_bit	= 18,
14962306a36Sopenharmony_ci};
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic struct plat_vlynq_data vlynq_high_data = {
15262306a36Sopenharmony_ci	.ops = {
15362306a36Sopenharmony_ci		.on	= vlynq_on,
15462306a36Sopenharmony_ci		.off	= vlynq_off,
15562306a36Sopenharmony_ci	},
15662306a36Sopenharmony_ci	.reset_bit	= 16,
15762306a36Sopenharmony_ci	.gpio_bit	= 19,
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistatic struct platform_device vlynq_low = {
16162306a36Sopenharmony_ci	.id		= 0,
16262306a36Sopenharmony_ci	.name		= "vlynq",
16362306a36Sopenharmony_ci	.dev = {
16462306a36Sopenharmony_ci		.platform_data	= &vlynq_low_data,
16562306a36Sopenharmony_ci	},
16662306a36Sopenharmony_ci	.resource	= vlynq_low_res,
16762306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(vlynq_low_res),
16862306a36Sopenharmony_ci};
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic struct platform_device vlynq_high = {
17162306a36Sopenharmony_ci	.id		= 1,
17262306a36Sopenharmony_ci	.name		= "vlynq",
17362306a36Sopenharmony_ci	.dev = {
17462306a36Sopenharmony_ci		.platform_data	= &vlynq_high_data,
17562306a36Sopenharmony_ci	},
17662306a36Sopenharmony_ci	.resource	= vlynq_high_res,
17762306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(vlynq_high_res),
17862306a36Sopenharmony_ci};
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci/*****************************************************************************
18162306a36Sopenharmony_ci * Flash
18262306a36Sopenharmony_ci ****************************************************************************/
18362306a36Sopenharmony_cistatic struct resource physmap_flash_resource = {
18462306a36Sopenharmony_ci	.name	= "mem",
18562306a36Sopenharmony_ci	.flags	= IORESOURCE_MEM,
18662306a36Sopenharmony_ci	.start	= 0x10000000,
18762306a36Sopenharmony_ci	.end	= 0x107fffff,
18862306a36Sopenharmony_ci};
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic const char *ar7_probe_types[] = { "ar7part", NULL };
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic struct physmap_flash_data physmap_flash_data = {
19362306a36Sopenharmony_ci	.width	= 2,
19462306a36Sopenharmony_ci	.part_probe_types = ar7_probe_types,
19562306a36Sopenharmony_ci};
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic struct platform_device physmap_flash = {
19862306a36Sopenharmony_ci	.name		= "physmap-flash",
19962306a36Sopenharmony_ci	.dev = {
20062306a36Sopenharmony_ci		.platform_data	= &physmap_flash_data,
20162306a36Sopenharmony_ci	},
20262306a36Sopenharmony_ci	.resource	= &physmap_flash_resource,
20362306a36Sopenharmony_ci	.num_resources	= 1,
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/*****************************************************************************
20762306a36Sopenharmony_ci * Ethernet
20862306a36Sopenharmony_ci ****************************************************************************/
20962306a36Sopenharmony_cistatic struct resource cpmac_low_res[] = {
21062306a36Sopenharmony_ci	{
21162306a36Sopenharmony_ci		.name	= "regs",
21262306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
21362306a36Sopenharmony_ci		.start	= AR7_REGS_MAC0,
21462306a36Sopenharmony_ci		.end	= AR7_REGS_MAC0 + 0x7ff,
21562306a36Sopenharmony_ci	},
21662306a36Sopenharmony_ci	{
21762306a36Sopenharmony_ci		.name	= "irq",
21862306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
21962306a36Sopenharmony_ci		.start	= 27,
22062306a36Sopenharmony_ci		.end	= 27,
22162306a36Sopenharmony_ci	},
22262306a36Sopenharmony_ci};
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic struct resource cpmac_high_res[] = {
22562306a36Sopenharmony_ci	{
22662306a36Sopenharmony_ci		.name	= "regs",
22762306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
22862306a36Sopenharmony_ci		.start	= AR7_REGS_MAC1,
22962306a36Sopenharmony_ci		.end	= AR7_REGS_MAC1 + 0x7ff,
23062306a36Sopenharmony_ci	},
23162306a36Sopenharmony_ci	{
23262306a36Sopenharmony_ci		.name	= "irq",
23362306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
23462306a36Sopenharmony_ci		.start	= 41,
23562306a36Sopenharmony_ci		.end	= 41,
23662306a36Sopenharmony_ci	},
23762306a36Sopenharmony_ci};
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic struct fixed_phy_status fixed_phy_status __initdata = {
24062306a36Sopenharmony_ci	.link		= 1,
24162306a36Sopenharmony_ci	.speed		= 100,
24262306a36Sopenharmony_ci	.duplex		= 1,
24362306a36Sopenharmony_ci};
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_cistatic struct plat_cpmac_data cpmac_low_data = {
24662306a36Sopenharmony_ci	.reset_bit	= 17,
24762306a36Sopenharmony_ci	.power_bit	= 20,
24862306a36Sopenharmony_ci	.phy_mask	= 0x80000000,
24962306a36Sopenharmony_ci};
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic struct plat_cpmac_data cpmac_high_data = {
25262306a36Sopenharmony_ci	.reset_bit	= 21,
25362306a36Sopenharmony_ci	.power_bit	= 22,
25462306a36Sopenharmony_ci	.phy_mask	= 0x7fffffff,
25562306a36Sopenharmony_ci};
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic u64 cpmac_dma_mask = DMA_BIT_MASK(32);
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_cistatic struct platform_device cpmac_low = {
26062306a36Sopenharmony_ci	.id		= 0,
26162306a36Sopenharmony_ci	.name		= "cpmac",
26262306a36Sopenharmony_ci	.dev = {
26362306a36Sopenharmony_ci		.dma_mask		= &cpmac_dma_mask,
26462306a36Sopenharmony_ci		.coherent_dma_mask	= DMA_BIT_MASK(32),
26562306a36Sopenharmony_ci		.platform_data		= &cpmac_low_data,
26662306a36Sopenharmony_ci	},
26762306a36Sopenharmony_ci	.resource	= cpmac_low_res,
26862306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(cpmac_low_res),
26962306a36Sopenharmony_ci};
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic struct platform_device cpmac_high = {
27262306a36Sopenharmony_ci	.id		= 1,
27362306a36Sopenharmony_ci	.name		= "cpmac",
27462306a36Sopenharmony_ci	.dev = {
27562306a36Sopenharmony_ci		.dma_mask		= &cpmac_dma_mask,
27662306a36Sopenharmony_ci		.coherent_dma_mask	= DMA_BIT_MASK(32),
27762306a36Sopenharmony_ci		.platform_data		= &cpmac_high_data,
27862306a36Sopenharmony_ci	},
27962306a36Sopenharmony_ci	.resource	= cpmac_high_res,
28062306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(cpmac_high_res),
28162306a36Sopenharmony_ci};
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic void __init cpmac_get_mac(int instance, unsigned char *dev_addr)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	char name[5], *mac;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	sprintf(name, "mac%c", 'a' + instance);
28862306a36Sopenharmony_ci	mac = prom_getenv(name);
28962306a36Sopenharmony_ci	if (!mac && instance) {
29062306a36Sopenharmony_ci		sprintf(name, "mac%c", 'a');
29162306a36Sopenharmony_ci		mac = prom_getenv(name);
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	if (mac) {
29562306a36Sopenharmony_ci		if (!mac_pton(mac, dev_addr)) {
29662306a36Sopenharmony_ci			pr_warn("cannot parse mac address, using random address\n");
29762306a36Sopenharmony_ci			eth_random_addr(dev_addr);
29862306a36Sopenharmony_ci		}
29962306a36Sopenharmony_ci	} else
30062306a36Sopenharmony_ci		eth_random_addr(dev_addr);
30162306a36Sopenharmony_ci}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci/*****************************************************************************
30462306a36Sopenharmony_ci * USB
30562306a36Sopenharmony_ci ****************************************************************************/
30662306a36Sopenharmony_cistatic struct resource usb_res[] = {
30762306a36Sopenharmony_ci	{
30862306a36Sopenharmony_ci		.name	= "regs",
30962306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
31062306a36Sopenharmony_ci		.start	= AR7_REGS_USB,
31162306a36Sopenharmony_ci		.end	= AR7_REGS_USB + 0xff,
31262306a36Sopenharmony_ci	},
31362306a36Sopenharmony_ci	{
31462306a36Sopenharmony_ci		.name	= "irq",
31562306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
31662306a36Sopenharmony_ci		.start	= 32,
31762306a36Sopenharmony_ci		.end	= 32,
31862306a36Sopenharmony_ci	},
31962306a36Sopenharmony_ci	{
32062306a36Sopenharmony_ci		.name	= "mem",
32162306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
32262306a36Sopenharmony_ci		.start	= 0x03400000,
32362306a36Sopenharmony_ci		.end	= 0x03401fff,
32462306a36Sopenharmony_ci	},
32562306a36Sopenharmony_ci};
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic struct platform_device ar7_udc = {
32862306a36Sopenharmony_ci	.name		= "ar7_udc",
32962306a36Sopenharmony_ci	.resource	= usb_res,
33062306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(usb_res),
33162306a36Sopenharmony_ci};
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci/*****************************************************************************
33462306a36Sopenharmony_ci * LEDs
33562306a36Sopenharmony_ci ****************************************************************************/
33662306a36Sopenharmony_cistatic const struct gpio_led default_leds[] = {
33762306a36Sopenharmony_ci	{
33862306a36Sopenharmony_ci		.name			= "status",
33962306a36Sopenharmony_ci		.gpio			= 8,
34062306a36Sopenharmony_ci		.active_low		= 1,
34162306a36Sopenharmony_ci	},
34262306a36Sopenharmony_ci};
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_cistatic const struct gpio_led titan_leds[] = {
34562306a36Sopenharmony_ci	{ .name = "status", .gpio = 8, .active_low = 1, },
34662306a36Sopenharmony_ci	{ .name = "wifi", .gpio = 13, .active_low = 1, },
34762306a36Sopenharmony_ci};
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic const struct gpio_led dsl502t_leds[] = {
35062306a36Sopenharmony_ci	{
35162306a36Sopenharmony_ci		.name			= "status",
35262306a36Sopenharmony_ci		.gpio			= 9,
35362306a36Sopenharmony_ci		.active_low		= 1,
35462306a36Sopenharmony_ci	},
35562306a36Sopenharmony_ci	{
35662306a36Sopenharmony_ci		.name			= "ethernet",
35762306a36Sopenharmony_ci		.gpio			= 7,
35862306a36Sopenharmony_ci		.active_low		= 1,
35962306a36Sopenharmony_ci	},
36062306a36Sopenharmony_ci	{
36162306a36Sopenharmony_ci		.name			= "usb",
36262306a36Sopenharmony_ci		.gpio			= 12,
36362306a36Sopenharmony_ci		.active_low		= 1,
36462306a36Sopenharmony_ci	},
36562306a36Sopenharmony_ci};
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic const struct gpio_led dg834g_leds[] = {
36862306a36Sopenharmony_ci	{
36962306a36Sopenharmony_ci		.name			= "ppp",
37062306a36Sopenharmony_ci		.gpio			= 6,
37162306a36Sopenharmony_ci		.active_low		= 1,
37262306a36Sopenharmony_ci	},
37362306a36Sopenharmony_ci	{
37462306a36Sopenharmony_ci		.name			= "status",
37562306a36Sopenharmony_ci		.gpio			= 7,
37662306a36Sopenharmony_ci		.active_low		= 1,
37762306a36Sopenharmony_ci	},
37862306a36Sopenharmony_ci	{
37962306a36Sopenharmony_ci		.name			= "adsl",
38062306a36Sopenharmony_ci		.gpio			= 8,
38162306a36Sopenharmony_ci		.active_low		= 1,
38262306a36Sopenharmony_ci	},
38362306a36Sopenharmony_ci	{
38462306a36Sopenharmony_ci		.name			= "wifi",
38562306a36Sopenharmony_ci		.gpio			= 12,
38662306a36Sopenharmony_ci		.active_low		= 1,
38762306a36Sopenharmony_ci	},
38862306a36Sopenharmony_ci	{
38962306a36Sopenharmony_ci		.name			= "power",
39062306a36Sopenharmony_ci		.gpio			= 14,
39162306a36Sopenharmony_ci		.active_low		= 1,
39262306a36Sopenharmony_ci		.default_trigger	= "default-on",
39362306a36Sopenharmony_ci	},
39462306a36Sopenharmony_ci};
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_cistatic const struct gpio_led fb_sl_leds[] = {
39762306a36Sopenharmony_ci	{
39862306a36Sopenharmony_ci		.name			= "1",
39962306a36Sopenharmony_ci		.gpio			= 7,
40062306a36Sopenharmony_ci	},
40162306a36Sopenharmony_ci	{
40262306a36Sopenharmony_ci		.name			= "2",
40362306a36Sopenharmony_ci		.gpio			= 13,
40462306a36Sopenharmony_ci		.active_low		= 1,
40562306a36Sopenharmony_ci	},
40662306a36Sopenharmony_ci	{
40762306a36Sopenharmony_ci		.name			= "3",
40862306a36Sopenharmony_ci		.gpio			= 10,
40962306a36Sopenharmony_ci		.active_low		= 1,
41062306a36Sopenharmony_ci	},
41162306a36Sopenharmony_ci	{
41262306a36Sopenharmony_ci		.name			= "4",
41362306a36Sopenharmony_ci		.gpio			= 12,
41462306a36Sopenharmony_ci		.active_low		= 1,
41562306a36Sopenharmony_ci	},
41662306a36Sopenharmony_ci	{
41762306a36Sopenharmony_ci		.name			= "5",
41862306a36Sopenharmony_ci		.gpio			= 9,
41962306a36Sopenharmony_ci		.active_low		= 1,
42062306a36Sopenharmony_ci	},
42162306a36Sopenharmony_ci};
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic const struct gpio_led fb_fon_leds[] = {
42462306a36Sopenharmony_ci	{
42562306a36Sopenharmony_ci		.name			= "1",
42662306a36Sopenharmony_ci		.gpio			= 8,
42762306a36Sopenharmony_ci	},
42862306a36Sopenharmony_ci	{
42962306a36Sopenharmony_ci		.name			= "2",
43062306a36Sopenharmony_ci		.gpio			= 3,
43162306a36Sopenharmony_ci		.active_low		= 1,
43262306a36Sopenharmony_ci	},
43362306a36Sopenharmony_ci	{
43462306a36Sopenharmony_ci		.name			= "3",
43562306a36Sopenharmony_ci		.gpio			= 5,
43662306a36Sopenharmony_ci	},
43762306a36Sopenharmony_ci	{
43862306a36Sopenharmony_ci		.name			= "4",
43962306a36Sopenharmony_ci		.gpio			= 4,
44062306a36Sopenharmony_ci		.active_low		= 1,
44162306a36Sopenharmony_ci	},
44262306a36Sopenharmony_ci	{
44362306a36Sopenharmony_ci		.name			= "5",
44462306a36Sopenharmony_ci		.gpio			= 11,
44562306a36Sopenharmony_ci		.active_low		= 1,
44662306a36Sopenharmony_ci	},
44762306a36Sopenharmony_ci};
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_cistatic const struct gpio_led gt701_leds[] = {
45062306a36Sopenharmony_ci	{
45162306a36Sopenharmony_ci		.name			= "inet:green",
45262306a36Sopenharmony_ci		.gpio			= 13,
45362306a36Sopenharmony_ci		.active_low		= 1,
45462306a36Sopenharmony_ci	},
45562306a36Sopenharmony_ci	{
45662306a36Sopenharmony_ci		.name			= "usb",
45762306a36Sopenharmony_ci		.gpio			= 12,
45862306a36Sopenharmony_ci		.active_low		= 1,
45962306a36Sopenharmony_ci	},
46062306a36Sopenharmony_ci	{
46162306a36Sopenharmony_ci		.name			= "inet:red",
46262306a36Sopenharmony_ci		.gpio			= 9,
46362306a36Sopenharmony_ci		.active_low		= 1,
46462306a36Sopenharmony_ci	},
46562306a36Sopenharmony_ci	{
46662306a36Sopenharmony_ci		.name			= "power:red",
46762306a36Sopenharmony_ci		.gpio			= 7,
46862306a36Sopenharmony_ci		.active_low		= 1,
46962306a36Sopenharmony_ci	},
47062306a36Sopenharmony_ci	{
47162306a36Sopenharmony_ci		.name			= "power:green",
47262306a36Sopenharmony_ci		.gpio			= 8,
47362306a36Sopenharmony_ci		.active_low		= 1,
47462306a36Sopenharmony_ci		.default_trigger	= "default-on",
47562306a36Sopenharmony_ci	},
47662306a36Sopenharmony_ci	{
47762306a36Sopenharmony_ci		.name			= "ethernet",
47862306a36Sopenharmony_ci		.gpio			= 10,
47962306a36Sopenharmony_ci		.active_low		= 1,
48062306a36Sopenharmony_ci	},
48162306a36Sopenharmony_ci};
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic struct gpio_led_platform_data ar7_led_data;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic struct platform_device ar7_gpio_leds = {
48662306a36Sopenharmony_ci	.name = "leds-gpio",
48762306a36Sopenharmony_ci	.dev = {
48862306a36Sopenharmony_ci		.platform_data = &ar7_led_data,
48962306a36Sopenharmony_ci	}
49062306a36Sopenharmony_ci};
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_cistatic void __init detect_leds(void)
49362306a36Sopenharmony_ci{
49462306a36Sopenharmony_ci	char *prid, *usb_prod;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	/* Default LEDs */
49762306a36Sopenharmony_ci	ar7_led_data.num_leds = ARRAY_SIZE(default_leds);
49862306a36Sopenharmony_ci	ar7_led_data.leds = default_leds;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	/* FIXME: the whole thing is unreliable */
50162306a36Sopenharmony_ci	prid = prom_getenv("ProductID");
50262306a36Sopenharmony_ci	usb_prod = prom_getenv("usb_prod");
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/* If we can't get the product id from PROM, use the default LEDs */
50562306a36Sopenharmony_ci	if (!prid)
50662306a36Sopenharmony_ci		return;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	if (strstr(prid, "Fritz_Box_FON")) {
50962306a36Sopenharmony_ci		ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds);
51062306a36Sopenharmony_ci		ar7_led_data.leds = fb_fon_leds;
51162306a36Sopenharmony_ci	} else if (strstr(prid, "Fritz_Box_")) {
51262306a36Sopenharmony_ci		ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds);
51362306a36Sopenharmony_ci		ar7_led_data.leds = fb_sl_leds;
51462306a36Sopenharmony_ci	} else if ((!strcmp(prid, "AR7RD") || !strcmp(prid, "AR7DB"))
51562306a36Sopenharmony_ci		&& usb_prod != NULL && strstr(usb_prod, "DSL-502T")) {
51662306a36Sopenharmony_ci		ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds);
51762306a36Sopenharmony_ci		ar7_led_data.leds = dsl502t_leds;
51862306a36Sopenharmony_ci	} else if (strstr(prid, "DG834")) {
51962306a36Sopenharmony_ci		ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds);
52062306a36Sopenharmony_ci		ar7_led_data.leds = dg834g_leds;
52162306a36Sopenharmony_ci	} else if (strstr(prid, "CYWM") || strstr(prid, "CYWL")) {
52262306a36Sopenharmony_ci		ar7_led_data.num_leds = ARRAY_SIZE(titan_leds);
52362306a36Sopenharmony_ci		ar7_led_data.leds = titan_leds;
52462306a36Sopenharmony_ci	} else if (strstr(prid, "GT701")) {
52562306a36Sopenharmony_ci		ar7_led_data.num_leds = ARRAY_SIZE(gt701_leds);
52662306a36Sopenharmony_ci		ar7_led_data.leds = gt701_leds;
52762306a36Sopenharmony_ci	}
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci/*****************************************************************************
53162306a36Sopenharmony_ci * Watchdog
53262306a36Sopenharmony_ci ****************************************************************************/
53362306a36Sopenharmony_cistatic struct resource ar7_wdt_res = {
53462306a36Sopenharmony_ci	.name		= "regs",
53562306a36Sopenharmony_ci	.flags		= IORESOURCE_MEM,
53662306a36Sopenharmony_ci	.start		= -1,	/* Filled at runtime */
53762306a36Sopenharmony_ci	.end		= -1,	/* Filled at runtime */
53862306a36Sopenharmony_ci};
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_cistatic struct platform_device ar7_wdt = {
54162306a36Sopenharmony_ci	.name		= "ar7_wdt",
54262306a36Sopenharmony_ci	.resource	= &ar7_wdt_res,
54362306a36Sopenharmony_ci	.num_resources	= 1,
54462306a36Sopenharmony_ci};
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci/*****************************************************************************
54762306a36Sopenharmony_ci * Init
54862306a36Sopenharmony_ci ****************************************************************************/
54962306a36Sopenharmony_cistatic int __init ar7_register_uarts(void)
55062306a36Sopenharmony_ci{
55162306a36Sopenharmony_ci#ifdef CONFIG_SERIAL_8250
55262306a36Sopenharmony_ci	static struct uart_port uart_port __initdata;
55362306a36Sopenharmony_ci	struct clk *bus_clk;
55462306a36Sopenharmony_ci	int res;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	memset(&uart_port, 0, sizeof(struct uart_port));
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	bus_clk = clk_get(NULL, "bus");
55962306a36Sopenharmony_ci	if (IS_ERR(bus_clk))
56062306a36Sopenharmony_ci		panic("unable to get bus clk");
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	uart_port.type		= PORT_AR7;
56362306a36Sopenharmony_ci	uart_port.uartclk	= clk_get_rate(bus_clk) / 2;
56462306a36Sopenharmony_ci	uart_port.iotype	= UPIO_MEM32;
56562306a36Sopenharmony_ci	uart_port.flags		= UPF_FIXED_TYPE | UPF_BOOT_AUTOCONF;
56662306a36Sopenharmony_ci	uart_port.regshift	= 2;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	uart_port.line		= 0;
56962306a36Sopenharmony_ci	uart_port.irq		= AR7_IRQ_UART0;
57062306a36Sopenharmony_ci	uart_port.mapbase	= AR7_REGS_UART0;
57162306a36Sopenharmony_ci	uart_port.membase	= ioremap(uart_port.mapbase, 256);
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	res = early_serial_setup(&uart_port);
57462306a36Sopenharmony_ci	if (res)
57562306a36Sopenharmony_ci		return res;
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	/* Only TNETD73xx have a second serial port */
57862306a36Sopenharmony_ci	if (ar7_has_second_uart()) {
57962306a36Sopenharmony_ci		uart_port.line		= 1;
58062306a36Sopenharmony_ci		uart_port.irq		= AR7_IRQ_UART1;
58162306a36Sopenharmony_ci		uart_port.mapbase	= UR8_REGS_UART1;
58262306a36Sopenharmony_ci		uart_port.membase	= ioremap(uart_port.mapbase, 256);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci		res = early_serial_setup(&uart_port);
58562306a36Sopenharmony_ci		if (res)
58662306a36Sopenharmony_ci			return res;
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci#endif
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	return 0;
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cistatic void __init titan_fixup_devices(void)
59462306a36Sopenharmony_ci{
59562306a36Sopenharmony_ci	/* Set vlynq0 data */
59662306a36Sopenharmony_ci	vlynq_low_data.reset_bit = 15;
59762306a36Sopenharmony_ci	vlynq_low_data.gpio_bit = 14;
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/* Set vlynq1 data */
60062306a36Sopenharmony_ci	vlynq_high_data.reset_bit = 16;
60162306a36Sopenharmony_ci	vlynq_high_data.gpio_bit = 7;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	/* Set vlynq0 resources */
60462306a36Sopenharmony_ci	vlynq_low_res[0].start = TITAN_REGS_VLYNQ0;
60562306a36Sopenharmony_ci	vlynq_low_res[0].end = TITAN_REGS_VLYNQ0 + 0xff;
60662306a36Sopenharmony_ci	vlynq_low_res[1].start = 33;
60762306a36Sopenharmony_ci	vlynq_low_res[1].end = 33;
60862306a36Sopenharmony_ci	vlynq_low_res[2].start = 0x0c000000;
60962306a36Sopenharmony_ci	vlynq_low_res[2].end = 0x0fffffff;
61062306a36Sopenharmony_ci	vlynq_low_res[3].start = 80;
61162306a36Sopenharmony_ci	vlynq_low_res[3].end = 111;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	/* Set vlynq1 resources */
61462306a36Sopenharmony_ci	vlynq_high_res[0].start = TITAN_REGS_VLYNQ1;
61562306a36Sopenharmony_ci	vlynq_high_res[0].end = TITAN_REGS_VLYNQ1 + 0xff;
61662306a36Sopenharmony_ci	vlynq_high_res[1].start = 34;
61762306a36Sopenharmony_ci	vlynq_high_res[1].end = 34;
61862306a36Sopenharmony_ci	vlynq_high_res[2].start = 0x40000000;
61962306a36Sopenharmony_ci	vlynq_high_res[2].end = 0x43ffffff;
62062306a36Sopenharmony_ci	vlynq_high_res[3].start = 112;
62162306a36Sopenharmony_ci	vlynq_high_res[3].end = 143;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	/* Set cpmac0 data */
62462306a36Sopenharmony_ci	cpmac_low_data.phy_mask = 0x40000000;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	/* Set cpmac1 data */
62762306a36Sopenharmony_ci	cpmac_high_data.phy_mask = 0x80000000;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	/* Set cpmac0 resources */
63062306a36Sopenharmony_ci	cpmac_low_res[0].start = TITAN_REGS_MAC0;
63162306a36Sopenharmony_ci	cpmac_low_res[0].end = TITAN_REGS_MAC0 + 0x7ff;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	/* Set cpmac1 resources */
63462306a36Sopenharmony_ci	cpmac_high_res[0].start = TITAN_REGS_MAC1;
63562306a36Sopenharmony_ci	cpmac_high_res[0].end = TITAN_REGS_MAC1 + 0x7ff;
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistatic int __init ar7_register_devices(void)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	void __iomem *bootcr;
64162306a36Sopenharmony_ci	u32 val;
64262306a36Sopenharmony_ci	int res;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	res = ar7_gpio_init();
64562306a36Sopenharmony_ci	if (res)
64662306a36Sopenharmony_ci		pr_warn("unable to register gpios: %d\n", res);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	res = ar7_register_uarts();
64962306a36Sopenharmony_ci	if (res)
65062306a36Sopenharmony_ci		pr_err("unable to setup uart(s): %d\n", res);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	res = platform_device_register(&physmap_flash);
65362306a36Sopenharmony_ci	if (res)
65462306a36Sopenharmony_ci		pr_warn("unable to register physmap-flash: %d\n", res);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	if (ar7_is_titan())
65762306a36Sopenharmony_ci		titan_fixup_devices();
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci	ar7_device_disable(vlynq_low_data.reset_bit);
66062306a36Sopenharmony_ci	res = platform_device_register(&vlynq_low);
66162306a36Sopenharmony_ci	if (res)
66262306a36Sopenharmony_ci		pr_warn("unable to register vlynq-low: %d\n", res);
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	if (ar7_has_high_vlynq()) {
66562306a36Sopenharmony_ci		ar7_device_disable(vlynq_high_data.reset_bit);
66662306a36Sopenharmony_ci		res = platform_device_register(&vlynq_high);
66762306a36Sopenharmony_ci		if (res)
66862306a36Sopenharmony_ci			pr_warn("unable to register vlynq-high: %d\n", res);
66962306a36Sopenharmony_ci	}
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	if (ar7_has_high_cpmac()) {
67262306a36Sopenharmony_ci		res = fixed_phy_add(PHY_POLL, cpmac_high.id,
67362306a36Sopenharmony_ci				    &fixed_phy_status);
67462306a36Sopenharmony_ci		if (!res) {
67562306a36Sopenharmony_ci			cpmac_get_mac(1, cpmac_high_data.dev_addr);
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci			res = platform_device_register(&cpmac_high);
67862306a36Sopenharmony_ci			if (res)
67962306a36Sopenharmony_ci				pr_warn("unable to register cpmac-high: %d\n",
68062306a36Sopenharmony_ci					res);
68162306a36Sopenharmony_ci		} else
68262306a36Sopenharmony_ci			pr_warn("unable to add cpmac-high phy: %d\n", res);
68362306a36Sopenharmony_ci	} else
68462306a36Sopenharmony_ci		cpmac_low_data.phy_mask = 0xffffffff;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	res = fixed_phy_add(PHY_POLL, cpmac_low.id, &fixed_phy_status);
68762306a36Sopenharmony_ci	if (!res) {
68862306a36Sopenharmony_ci		cpmac_get_mac(0, cpmac_low_data.dev_addr);
68962306a36Sopenharmony_ci		res = platform_device_register(&cpmac_low);
69062306a36Sopenharmony_ci		if (res)
69162306a36Sopenharmony_ci			pr_warn("unable to register cpmac-low: %d\n", res);
69262306a36Sopenharmony_ci	} else
69362306a36Sopenharmony_ci		pr_warn("unable to add cpmac-low phy: %d\n", res);
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	detect_leds();
69662306a36Sopenharmony_ci	res = platform_device_register(&ar7_gpio_leds);
69762306a36Sopenharmony_ci	if (res)
69862306a36Sopenharmony_ci		pr_warn("unable to register leds: %d\n", res);
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	res = platform_device_register(&ar7_udc);
70162306a36Sopenharmony_ci	if (res)
70262306a36Sopenharmony_ci		pr_warn("unable to register usb slave: %d\n", res);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	/* Register watchdog only if enabled in hardware */
70562306a36Sopenharmony_ci	bootcr = ioremap(AR7_REGS_DCL, 4);
70662306a36Sopenharmony_ci	val = readl(bootcr);
70762306a36Sopenharmony_ci	iounmap(bootcr);
70862306a36Sopenharmony_ci	if (val & AR7_WDT_HW_ENA) {
70962306a36Sopenharmony_ci		if (ar7_has_high_vlynq())
71062306a36Sopenharmony_ci			ar7_wdt_res.start = UR8_REGS_WDT;
71162306a36Sopenharmony_ci		else
71262306a36Sopenharmony_ci			ar7_wdt_res.start = AR7_REGS_WDT;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci		ar7_wdt_res.end = ar7_wdt_res.start + 0x20;
71562306a36Sopenharmony_ci		res = platform_device_register(&ar7_wdt);
71662306a36Sopenharmony_ci		if (res)
71762306a36Sopenharmony_ci			pr_warn("unable to register watchdog: %d\n", res);
71862306a36Sopenharmony_ci	}
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci	return 0;
72162306a36Sopenharmony_ci}
72262306a36Sopenharmony_cidevice_initcall(ar7_register_devices);
723