162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Broadcom specific AMBA 362306a36Sopenharmony_ci * ChipCommon NAND flash interface 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Licensed under the GNU/GPL. See COPYING for details. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "bcma_private.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/bitops.h> 1162306a36Sopenharmony_ci#include <linux/platform_device.h> 1262306a36Sopenharmony_ci#include <linux/platform_data/brcmnand.h> 1362306a36Sopenharmony_ci#include <linux/bcma/bcma.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* Alternate NAND controller driver name in order to allow both bcm47xxnflash 1662306a36Sopenharmony_ci * and bcma_brcmnand to be built into the same kernel image. 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_cistatic const char *bcma_nflash_alt_name = "bcma_brcmnand"; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistruct platform_device bcma_nflash_dev = { 2162306a36Sopenharmony_ci .name = "bcma_nflash", 2262306a36Sopenharmony_ci .num_resources = 0, 2362306a36Sopenharmony_ci}; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic const char *probes[] = { "bcm47xxpart", NULL }; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci/* Initialize NAND flash access */ 2862306a36Sopenharmony_ciint bcma_nflash_init(struct bcma_drv_cc *cc) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci struct bcma_bus *bus = cc->core->bus; 3162306a36Sopenharmony_ci u32 reg; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && 3462306a36Sopenharmony_ci cc->core->id.rev != 38) { 3562306a36Sopenharmony_ci bcma_err(bus, "NAND flash on unsupported board!\n"); 3662306a36Sopenharmony_ci return -ENOTSUPP; 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci if (!(cc->capabilities & BCMA_CC_CAP_NFLASH)) { 4062306a36Sopenharmony_ci bcma_err(bus, "NAND flash not present according to ChipCommon\n"); 4162306a36Sopenharmony_ci return -ENODEV; 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci cc->nflash.present = true; 4562306a36Sopenharmony_ci if (cc->core->id.rev == 38 && 4662306a36Sopenharmony_ci (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)) { 4762306a36Sopenharmony_ci cc->nflash.boot = true; 4862306a36Sopenharmony_ci /* Determine the chip select that is being used */ 4962306a36Sopenharmony_ci reg = bcma_cc_read32(cc, BCMA_CC_NAND_CS_NAND_SELECT) & 0xff; 5062306a36Sopenharmony_ci cc->nflash.brcmnand_info.chip_select = ffs(reg) - 1; 5162306a36Sopenharmony_ci cc->nflash.brcmnand_info.part_probe_types = probes; 5262306a36Sopenharmony_ci cc->nflash.brcmnand_info.ecc_stepsize = 512; 5362306a36Sopenharmony_ci cc->nflash.brcmnand_info.ecc_strength = 1; 5462306a36Sopenharmony_ci bcma_nflash_dev.name = bcma_nflash_alt_name; 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci /* Prepare platform device, but don't register it yet. It's too early, 5862306a36Sopenharmony_ci * malloc (required by device_private_init) is not available yet. */ 5962306a36Sopenharmony_ci bcma_nflash_dev.dev.platform_data = &cc->nflash; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 63