162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de>
462306a36Sopenharmony_ci *  Thanks to :
562306a36Sopenharmony_ci *	Dale Farnsworth <dale@farnsworth.org>
662306a36Sopenharmony_ci *	Mark A. Greer <mgreer@mvista.com>
762306a36Sopenharmony_ci *	Nicolas DET <nd@bplan-gmbh.de>
862306a36Sopenharmony_ci *	Benjamin Herrenschmidt <benh@kernel.crashing.org>
962306a36Sopenharmony_ci *  And anyone else who helped me on this.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/types.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/ioport.h>
1562306a36Sopenharmony_ci#include <linux/device.h>
1662306a36Sopenharmony_ci#include <linux/platform_device.h>
1762306a36Sopenharmony_ci#include <linux/mv643xx.h>
1862306a36Sopenharmony_ci#include <linux/pci.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define PEGASOS2_MARVELL_REGBASE 		(0xf1000000)
2162306a36Sopenharmony_ci#define PEGASOS2_MARVELL_REGSIZE 		(0x00004000)
2262306a36Sopenharmony_ci#define PEGASOS2_SRAM_BASE 			(0xf2000000)
2362306a36Sopenharmony_ci#define PEGASOS2_SRAM_SIZE			(256*1024)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define PEGASOS2_SRAM_BASE_ETH_PORT0			(PEGASOS2_SRAM_BASE)
2662306a36Sopenharmony_ci#define PEGASOS2_SRAM_BASE_ETH_PORT1			(PEGASOS2_SRAM_BASE_ETH_PORT0 + (PEGASOS2_SRAM_SIZE / 2) )
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#define PEGASOS2_SRAM_RXRING_SIZE		(PEGASOS2_SRAM_SIZE/4)
3062306a36Sopenharmony_ci#define PEGASOS2_SRAM_TXRING_SIZE		(PEGASOS2_SRAM_SIZE/4)
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#undef BE_VERBOSE
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic struct resource mv643xx_eth_shared_resources[] = {
3562306a36Sopenharmony_ci	[0] = {
3662306a36Sopenharmony_ci		.name	= "ethernet shared base",
3762306a36Sopenharmony_ci		.start	= 0xf1000000 + MV643XX_ETH_SHARED_REGS,
3862306a36Sopenharmony_ci		.end	= 0xf1000000 + MV643XX_ETH_SHARED_REGS +
3962306a36Sopenharmony_ci					MV643XX_ETH_SHARED_REGS_SIZE - 1,
4062306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
4162306a36Sopenharmony_ci	},
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic struct platform_device mv643xx_eth_shared_device = {
4562306a36Sopenharmony_ci	.name		= MV643XX_ETH_SHARED_NAME,
4662306a36Sopenharmony_ci	.id		= 0,
4762306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
4862306a36Sopenharmony_ci	.resource	= mv643xx_eth_shared_resources,
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * The orion mdio driver only covers shared + 0x4 up to shared + 0x84 - 1
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_cistatic struct resource mv643xx_eth_mvmdio_resources[] = {
5562306a36Sopenharmony_ci	[0] = {
5662306a36Sopenharmony_ci		.name	= "ethernet mdio base",
5762306a36Sopenharmony_ci		.start	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x4,
5862306a36Sopenharmony_ci		.end	= 0xf1000000 + MV643XX_ETH_SHARED_REGS + 0x83,
5962306a36Sopenharmony_ci		.flags	= IORESOURCE_MEM,
6062306a36Sopenharmony_ci	},
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistatic struct platform_device mv643xx_eth_mvmdio_device = {
6462306a36Sopenharmony_ci	.name		= "orion-mdio",
6562306a36Sopenharmony_ci	.id		= -1,
6662306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(mv643xx_eth_mvmdio_resources),
6762306a36Sopenharmony_ci	.resource	= mv643xx_eth_mvmdio_resources,
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic struct resource mv643xx_eth_port1_resources[] = {
7162306a36Sopenharmony_ci	[0] = {
7262306a36Sopenharmony_ci		.name	= "eth port1 irq",
7362306a36Sopenharmony_ci		.start	= 9,
7462306a36Sopenharmony_ci		.end	= 9,
7562306a36Sopenharmony_ci		.flags	= IORESOURCE_IRQ,
7662306a36Sopenharmony_ci	},
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic struct mv643xx_eth_platform_data eth_port1_pd = {
8062306a36Sopenharmony_ci	.shared		= &mv643xx_eth_shared_device,
8162306a36Sopenharmony_ci	.port_number	= 1,
8262306a36Sopenharmony_ci	.phy_addr	= MV643XX_ETH_PHY_ADDR(7),
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	.tx_sram_addr = PEGASOS2_SRAM_BASE_ETH_PORT1,
8562306a36Sopenharmony_ci	.tx_sram_size = PEGASOS2_SRAM_TXRING_SIZE,
8662306a36Sopenharmony_ci	.tx_queue_size = PEGASOS2_SRAM_TXRING_SIZE/16,
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	.rx_sram_addr = PEGASOS2_SRAM_BASE_ETH_PORT1 + PEGASOS2_SRAM_TXRING_SIZE,
8962306a36Sopenharmony_ci	.rx_sram_size = PEGASOS2_SRAM_RXRING_SIZE,
9062306a36Sopenharmony_ci	.rx_queue_size = PEGASOS2_SRAM_RXRING_SIZE/16,
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic struct platform_device eth_port1_device = {
9462306a36Sopenharmony_ci	.name		= MV643XX_ETH_NAME,
9562306a36Sopenharmony_ci	.id		= 1,
9662306a36Sopenharmony_ci	.num_resources	= ARRAY_SIZE(mv643xx_eth_port1_resources),
9762306a36Sopenharmony_ci	.resource	= mv643xx_eth_port1_resources,
9862306a36Sopenharmony_ci	.dev = {
9962306a36Sopenharmony_ci		.platform_data = &eth_port1_pd,
10062306a36Sopenharmony_ci	},
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
10462306a36Sopenharmony_ci	&mv643xx_eth_shared_device,
10562306a36Sopenharmony_ci	&mv643xx_eth_mvmdio_device,
10662306a36Sopenharmony_ci	&eth_port1_device,
10762306a36Sopenharmony_ci};
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci/***********/
11062306a36Sopenharmony_ci/***********/
11162306a36Sopenharmony_ci#define MV_READ(offset,val) 	{ val = readl(mv643xx_reg_base + offset); }
11262306a36Sopenharmony_ci#define MV_WRITE(offset,data) writel(data, mv643xx_reg_base + offset)
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_cistatic void __iomem *mv643xx_reg_base;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic int __init Enable_SRAM(void)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	u32 ALong;
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	if (mv643xx_reg_base == NULL)
12162306a36Sopenharmony_ci		mv643xx_reg_base = ioremap(PEGASOS2_MARVELL_REGBASE,
12262306a36Sopenharmony_ci					PEGASOS2_MARVELL_REGSIZE);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (mv643xx_reg_base == NULL)
12562306a36Sopenharmony_ci		return -ENOMEM;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci#ifdef BE_VERBOSE
12862306a36Sopenharmony_ci	printk("Pegasos II/Marvell MV64361: register remapped from %p to %p\n",
12962306a36Sopenharmony_ci		(void *)PEGASOS2_MARVELL_REGBASE, (void *)mv643xx_reg_base);
13062306a36Sopenharmony_ci#endif
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	MV_WRITE(MV64340_SRAM_CONFIG, 0);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	MV_WRITE(MV64340_INTEGRATED_SRAM_BASE_ADDR, PEGASOS2_SRAM_BASE >> 16);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	MV_READ(MV64340_BASE_ADDR_ENABLE, ALong);
13762306a36Sopenharmony_ci	ALong &= ~(1 << 19);
13862306a36Sopenharmony_ci	MV_WRITE(MV64340_BASE_ADDR_ENABLE, ALong);
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	ALong = 0x02;
14162306a36Sopenharmony_ci	ALong |= PEGASOS2_SRAM_BASE & 0xffff0000;
14262306a36Sopenharmony_ci	MV_WRITE(MV643XX_ETH_BAR_4, ALong);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	MV_WRITE(MV643XX_ETH_SIZE_REG_4, (PEGASOS2_SRAM_SIZE-1) & 0xffff0000);
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	MV_READ(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
14762306a36Sopenharmony_ci	ALong &= ~(1 << 4);
14862306a36Sopenharmony_ci	MV_WRITE(MV643XX_ETH_BASE_ADDR_ENABLE_REG, ALong);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci#ifdef BE_VERBOSE
15162306a36Sopenharmony_ci	printk("Pegasos II/Marvell MV64361: register unmapped\n");
15262306a36Sopenharmony_ci	printk("Pegasos II/Marvell MV64361: SRAM at %p, size=%x\n", (void*) PEGASOS2_SRAM_BASE, PEGASOS2_SRAM_SIZE);
15362306a36Sopenharmony_ci#endif
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	iounmap(mv643xx_reg_base);
15662306a36Sopenharmony_ci	mv643xx_reg_base = NULL;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	return 1;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci/***********/
16362306a36Sopenharmony_ci/***********/
16462306a36Sopenharmony_cistatic int __init mv643xx_eth_add_pds(void)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	int ret = 0;
16762306a36Sopenharmony_ci	static struct pci_device_id pci_marvell_mv64360[] = {
16862306a36Sopenharmony_ci		{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) },
16962306a36Sopenharmony_ci		{ }
17062306a36Sopenharmony_ci	};
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#ifdef BE_VERBOSE
17362306a36Sopenharmony_ci	printk("Pegasos II/Marvell MV64361: init\n");
17462306a36Sopenharmony_ci#endif
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (pci_dev_present(pci_marvell_mv64360)) {
17762306a36Sopenharmony_ci		ret = platform_add_devices(mv643xx_eth_pd_devs,
17862306a36Sopenharmony_ci				ARRAY_SIZE(mv643xx_eth_pd_devs));
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci		if ( Enable_SRAM() < 0)
18162306a36Sopenharmony_ci		{
18262306a36Sopenharmony_ci			eth_port1_pd.tx_sram_addr = 0;
18362306a36Sopenharmony_ci			eth_port1_pd.tx_sram_size = 0;
18462306a36Sopenharmony_ci			eth_port1_pd.rx_sram_addr = 0;
18562306a36Sopenharmony_ci			eth_port1_pd.rx_sram_size = 0;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci#ifdef BE_VERBOSE
18862306a36Sopenharmony_ci			printk("Pegasos II/Marvell MV64361: Can't enable the "
18962306a36Sopenharmony_ci				"SRAM\n");
19062306a36Sopenharmony_ci#endif
19162306a36Sopenharmony_ci		}
19262306a36Sopenharmony_ci	}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci#ifdef BE_VERBOSE
19562306a36Sopenharmony_ci	printk("Pegasos II/Marvell MV64361: init is over\n");
19662306a36Sopenharmony_ci#endif
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	return ret;
19962306a36Sopenharmony_ci}
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_cidevice_initcall(mv643xx_eth_add_pds);
202