18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Broadcom BCM63xx flash registration
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
58c2ecf20Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
68c2ecf20Sopenharmony_ci * for more details.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
98c2ecf20Sopenharmony_ci * Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
108c2ecf20Sopenharmony_ci * Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/init.h>
148c2ecf20Sopenharmony_ci#include <linux/kernel.h>
158c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
168c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h>
178c2ecf20Sopenharmony_ci#include <linux/mtd/partitions.h>
188c2ecf20Sopenharmony_ci#include <linux/mtd/physmap.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#include <bcm63xx_cpu.h>
218c2ecf20Sopenharmony_ci#include <bcm63xx_dev_flash.h>
228c2ecf20Sopenharmony_ci#include <bcm63xx_regs.h>
238c2ecf20Sopenharmony_ci#include <bcm63xx_io.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic struct mtd_partition mtd_partitions[] = {
268c2ecf20Sopenharmony_ci	{
278c2ecf20Sopenharmony_ci		.name		= "cfe",
288c2ecf20Sopenharmony_ci		.offset		= 0x0,
298c2ecf20Sopenharmony_ci		.size		= 0x40000,
308c2ecf20Sopenharmony_ci	}
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic struct physmap_flash_data flash_data = {
368c2ecf20Sopenharmony_ci	.width			= 2,
378c2ecf20Sopenharmony_ci	.parts			= mtd_partitions,
388c2ecf20Sopenharmony_ci	.part_probe_types	= bcm63xx_part_types,
398c2ecf20Sopenharmony_ci};
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic struct resource mtd_resources[] = {
428c2ecf20Sopenharmony_ci	{
438c2ecf20Sopenharmony_ci		.start		= 0,	/* filled at runtime */
448c2ecf20Sopenharmony_ci		.end		= 0,	/* filled at runtime */
458c2ecf20Sopenharmony_ci		.flags		= IORESOURCE_MEM,
468c2ecf20Sopenharmony_ci	}
478c2ecf20Sopenharmony_ci};
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_cistatic struct platform_device mtd_dev = {
508c2ecf20Sopenharmony_ci	.name			= "physmap-flash",
518c2ecf20Sopenharmony_ci	.resource		= mtd_resources,
528c2ecf20Sopenharmony_ci	.num_resources		= ARRAY_SIZE(mtd_resources),
538c2ecf20Sopenharmony_ci	.dev			= {
548c2ecf20Sopenharmony_ci		.platform_data	= &flash_data,
558c2ecf20Sopenharmony_ci	},
568c2ecf20Sopenharmony_ci};
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic int __init bcm63xx_detect_flash_type(void)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	u32 val;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	switch (bcm63xx_get_cpu_id()) {
638c2ecf20Sopenharmony_ci	case BCM6328_CPU_ID:
648c2ecf20Sopenharmony_ci		val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
658c2ecf20Sopenharmony_ci		if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
668c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
678c2ecf20Sopenharmony_ci		else
688c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_NAND;
698c2ecf20Sopenharmony_ci	case BCM6338_CPU_ID:
708c2ecf20Sopenharmony_ci	case BCM6345_CPU_ID:
718c2ecf20Sopenharmony_ci	case BCM6348_CPU_ID:
728c2ecf20Sopenharmony_ci		/* no way to auto detect so assume parallel */
738c2ecf20Sopenharmony_ci		return BCM63XX_FLASH_TYPE_PARALLEL;
748c2ecf20Sopenharmony_ci	case BCM3368_CPU_ID:
758c2ecf20Sopenharmony_ci	case BCM6358_CPU_ID:
768c2ecf20Sopenharmony_ci		val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
778c2ecf20Sopenharmony_ci		if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
788c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_PARALLEL;
798c2ecf20Sopenharmony_ci		else
808c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
818c2ecf20Sopenharmony_ci	case BCM6362_CPU_ID:
828c2ecf20Sopenharmony_ci		val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
838c2ecf20Sopenharmony_ci		if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
848c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
858c2ecf20Sopenharmony_ci		else
868c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_NAND;
878c2ecf20Sopenharmony_ci	case BCM6368_CPU_ID:
888c2ecf20Sopenharmony_ci		val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
898c2ecf20Sopenharmony_ci		switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
908c2ecf20Sopenharmony_ci		case STRAPBUS_6368_BOOT_SEL_NAND:
918c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_NAND;
928c2ecf20Sopenharmony_ci		case STRAPBUS_6368_BOOT_SEL_SERIAL:
938c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_SERIAL;
948c2ecf20Sopenharmony_ci		case STRAPBUS_6368_BOOT_SEL_PARALLEL:
958c2ecf20Sopenharmony_ci			return BCM63XX_FLASH_TYPE_PARALLEL;
968c2ecf20Sopenharmony_ci		}
978c2ecf20Sopenharmony_ci		fallthrough;
988c2ecf20Sopenharmony_ci	default:
998c2ecf20Sopenharmony_ci		return -EINVAL;
1008c2ecf20Sopenharmony_ci	}
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ciint __init bcm63xx_flash_register(void)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	int flash_type;
1068c2ecf20Sopenharmony_ci	u32 val;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	flash_type = bcm63xx_detect_flash_type();
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	switch (flash_type) {
1118c2ecf20Sopenharmony_ci	case BCM63XX_FLASH_TYPE_PARALLEL:
1128c2ecf20Sopenharmony_ci		/* read base address of boot chip select (0) */
1138c2ecf20Sopenharmony_ci		val = bcm_mpi_readl(MPI_CSBASE_REG(0));
1148c2ecf20Sopenharmony_ci		val &= MPI_CSBASE_BASE_MASK;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci		mtd_resources[0].start = val;
1178c2ecf20Sopenharmony_ci		mtd_resources[0].end = 0x1FFFFFFF;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci		return platform_device_register(&mtd_dev);
1208c2ecf20Sopenharmony_ci	case BCM63XX_FLASH_TYPE_SERIAL:
1218c2ecf20Sopenharmony_ci		pr_warn("unsupported serial flash detected\n");
1228c2ecf20Sopenharmony_ci		return -ENODEV;
1238c2ecf20Sopenharmony_ci	case BCM63XX_FLASH_TYPE_NAND:
1248c2ecf20Sopenharmony_ci		pr_warn("unsupported NAND flash detected\n");
1258c2ecf20Sopenharmony_ci		return -ENODEV;
1268c2ecf20Sopenharmony_ci	default:
1278c2ecf20Sopenharmony_ci		pr_err("flash detection failed for BCM%x: %d\n",
1288c2ecf20Sopenharmony_ci		       bcm63xx_get_cpu_id(), flash_type);
1298c2ecf20Sopenharmony_ci		return -ENODEV;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci}
132