162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Broadcom BCM63xx flash registration
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
562306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
662306a36Sopenharmony_ci * for more details.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
962306a36Sopenharmony_ci * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
1062306a36Sopenharmony_ci * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/platform_device.h>
1662306a36Sopenharmony_ci#include <linux/mtd/mtd.h>
1762306a36Sopenharmony_ci#include <linux/mtd/partitions.h>
1862306a36Sopenharmony_ci#include <linux/mtd/physmap.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <bcm63xx_cpu.h>
2162306a36Sopenharmony_ci#include <bcm63xx_dev_flash.h>
2262306a36Sopenharmony_ci#include <bcm63xx_regs.h>
2362306a36Sopenharmony_ci#include <bcm63xx_io.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic struct mtd_partition mtd_partitions[] = {
2662306a36Sopenharmony_ci	{
2762306a36Sopenharmony_ci		.name		= "cfe",
2862306a36Sopenharmony_ci		.offset		= 0x0,
2962306a36Sopenharmony_ci		.size		= 0x40000,
3062306a36Sopenharmony_ci	}
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic struct physmap_flash_data flash_data = {
3662306a36Sopenharmony_ci	.width			= 2,
3762306a36Sopenharmony_ci	.parts			= mtd_partitions,
3862306a36Sopenharmony_ci	.part_probe_types	= bcm63xx_part_types,
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic struct resource mtd_resources[] = {
4262306a36Sopenharmony_ci	{
4362306a36Sopenharmony_ci		.start		= 0,	/* filled at runtime */
4462306a36Sopenharmony_ci		.end		= 0,	/* filled at runtime */
4562306a36Sopenharmony_ci		.flags		= IORESOURCE_MEM,
4662306a36Sopenharmony_ci	}
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic struct platform_device mtd_dev = {
5062306a36Sopenharmony_ci	.name			= "physmap-flash",
5162306a36Sopenharmony_ci	.resource		= mtd_resources,
5262306a36Sopenharmony_ci	.num_resources		= ARRAY_SIZE(mtd_resources),
5362306a36Sopenharmony_ci	.dev			= {
5462306a36Sopenharmony_ci		.platform_data	= &flash_data,
5562306a36Sopenharmony_ci	},
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic int __init bcm63xx_detect_flash_type(void)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	u32 val;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	switch (bcm63xx_get_cpu_id()) {
6362306a36Sopenharmony_ci	case BCM6328_CPU_ID:
6462306a36Sopenharmony_ci		val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
6562306a36Sopenharmony_ci		if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
6662306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
6762306a36Sopenharmony_ci		else
6862306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_NAND;
6962306a36Sopenharmony_ci	case BCM6338_CPU_ID:
7062306a36Sopenharmony_ci	case BCM6345_CPU_ID:
7162306a36Sopenharmony_ci	case BCM6348_CPU_ID:
7262306a36Sopenharmony_ci		/* no way to auto detect so assume parallel */
7362306a36Sopenharmony_ci		return BCM63XX_FLASH_TYPE_PARALLEL;
7462306a36Sopenharmony_ci	case BCM3368_CPU_ID:
7562306a36Sopenharmony_ci	case BCM6358_CPU_ID:
7662306a36Sopenharmony_ci		val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
7762306a36Sopenharmony_ci		if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
7862306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_PARALLEL;
7962306a36Sopenharmony_ci		else
8062306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
8162306a36Sopenharmony_ci	case BCM6362_CPU_ID:
8262306a36Sopenharmony_ci		val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
8362306a36Sopenharmony_ci		if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
8462306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
8562306a36Sopenharmony_ci		else
8662306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_NAND;
8762306a36Sopenharmony_ci	case BCM6368_CPU_ID:
8862306a36Sopenharmony_ci		val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
8962306a36Sopenharmony_ci		switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
9062306a36Sopenharmony_ci		case STRAPBUS_6368_BOOT_SEL_NAND:
9162306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_NAND;
9262306a36Sopenharmony_ci		case STRAPBUS_6368_BOOT_SEL_SERIAL:
9362306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
9462306a36Sopenharmony_ci		case STRAPBUS_6368_BOOT_SEL_PARALLEL:
9562306a36Sopenharmony_ci			return BCM63XX_FLASH_TYPE_PARALLEL;
9662306a36Sopenharmony_ci		}
9762306a36Sopenharmony_ci		fallthrough;
9862306a36Sopenharmony_ci	default:
9962306a36Sopenharmony_ci		return -EINVAL;
10062306a36Sopenharmony_ci	}
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ciint __init bcm63xx_flash_register(void)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	int flash_type;
10662306a36Sopenharmony_ci	u32 val;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	flash_type = bcm63xx_detect_flash_type();
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	switch (flash_type) {
11162306a36Sopenharmony_ci	case BCM63XX_FLASH_TYPE_PARALLEL:
11262306a36Sopenharmony_ci		/* read base address of boot chip select (0) */
11362306a36Sopenharmony_ci		val = bcm_mpi_readl(MPI_CSBASE_REG(0));
11462306a36Sopenharmony_ci		val &= MPI_CSBASE_BASE_MASK;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci		mtd_resources[0].start = val;
11762306a36Sopenharmony_ci		mtd_resources[0].end = 0x1FFFFFFF;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci		return platform_device_register(&mtd_dev);
12062306a36Sopenharmony_ci	case BCM63XX_FLASH_TYPE_SERIAL:
12162306a36Sopenharmony_ci		pr_warn("unsupported serial flash detected\n");
12262306a36Sopenharmony_ci		return -ENODEV;
12362306a36Sopenharmony_ci	case BCM63XX_FLASH_TYPE_NAND:
12462306a36Sopenharmony_ci		pr_warn("unsupported NAND flash detected\n");
12562306a36Sopenharmony_ci		return -ENODEV;
12662306a36Sopenharmony_ci	default:
12762306a36Sopenharmony_ci		pr_err("flash detection failed for BCM%x: %d\n",
12862306a36Sopenharmony_ci		       bcm63xx_get_cpu_id(), flash_type);
12962306a36Sopenharmony_ci		return -ENODEV;
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci}
132