forked from mirrors/linux
		
	bcma: detect and register serial flash device
Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
		
							parent
							
								
									01e17dacd4
								
							
						
					
					
						commit
						d57ef3a6a2
					
				
					 6 changed files with 146 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -48,7 +48,7 @@ config BCMA_DRIVER_MIPS
 | 
			
		|||
 | 
			
		||||
config BCMA_SFLASH
 | 
			
		||||
	bool
 | 
			
		||||
	depends on BCMA_DRIVER_MIPS && BROKEN
 | 
			
		||||
	depends on BCMA_DRIVER_MIPS
 | 
			
		||||
	default y
 | 
			
		||||
 | 
			
		||||
config BCMA_NFLASH
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,7 @@ u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
 | 
			
		|||
#ifdef CONFIG_BCMA_SFLASH
 | 
			
		||||
/* driver_chipcommon_sflash.c */
 | 
			
		||||
int bcma_sflash_init(struct bcma_drv_cc *cc);
 | 
			
		||||
extern struct platform_device bcma_sflash_dev;
 | 
			
		||||
#else
 | 
			
		||||
static inline int bcma_sflash_init(struct bcma_drv_cc *cc)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,15 +5,132 @@
 | 
			
		|||
 * Licensed under the GNU/GPL. See COPYING for details.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
#include <linux/bcma/bcma.h>
 | 
			
		||||
#include <linux/bcma/bcma_driver_chipcommon.h>
 | 
			
		||||
#include <linux/delay.h>
 | 
			
		||||
 | 
			
		||||
#include "bcma_private.h"
 | 
			
		||||
 | 
			
		||||
static struct resource bcma_sflash_resource = {
 | 
			
		||||
	.name	= "bcma_sflash",
 | 
			
		||||
	.start	= BCMA_SFLASH,
 | 
			
		||||
	.end	= 0,
 | 
			
		||||
	.flags  = IORESOURCE_MEM | IORESOURCE_READONLY,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct platform_device bcma_sflash_dev = {
 | 
			
		||||
	.name		= "bcma_sflash",
 | 
			
		||||
	.resource	= &bcma_sflash_resource,
 | 
			
		||||
	.num_resources	= 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct bcma_sflash_tbl_e {
 | 
			
		||||
	char *name;
 | 
			
		||||
	u32 id;
 | 
			
		||||
	u32 blocksize;
 | 
			
		||||
	u16 numblocks;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
 | 
			
		||||
	{ "", 0x14, 0x10000, 32, },
 | 
			
		||||
	{ 0 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
 | 
			
		||||
	{ 0 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
 | 
			
		||||
	{ 0 },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	bcma_cc_write32(cc, BCMA_CC_FLASHCTL,
 | 
			
		||||
			BCMA_CC_FLASHCTL_START | opcode);
 | 
			
		||||
	for (i = 0; i < 1000; i++) {
 | 
			
		||||
		if (!(bcma_cc_read32(cc, BCMA_CC_FLASHCTL) &
 | 
			
		||||
		      BCMA_CC_FLASHCTL_BUSY))
 | 
			
		||||
			return;
 | 
			
		||||
		cpu_relax();
 | 
			
		||||
	}
 | 
			
		||||
	bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Initialize serial flash access */
 | 
			
		||||
int bcma_sflash_init(struct bcma_drv_cc *cc)
 | 
			
		||||
{
 | 
			
		||||
	bcma_err(cc->core->bus, "Serial flash support is broken\n");
 | 
			
		||||
	struct bcma_bus *bus = cc->core->bus;
 | 
			
		||||
	struct bcma_sflash *sflash = &cc->sflash;
 | 
			
		||||
	struct bcma_sflash_tbl_e *e;
 | 
			
		||||
	u32 id, id2;
 | 
			
		||||
 | 
			
		||||
	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
 | 
			
		||||
	case BCMA_CC_FLASHT_STSER:
 | 
			
		||||
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP);
 | 
			
		||||
 | 
			
		||||
		bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0);
 | 
			
		||||
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
 | 
			
		||||
		id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
 | 
			
		||||
 | 
			
		||||
		bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1);
 | 
			
		||||
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
 | 
			
		||||
		id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);
 | 
			
		||||
 | 
			
		||||
		switch (id) {
 | 
			
		||||
		case 0xbf:
 | 
			
		||||
			for (e = bcma_sflash_sst_tbl; e->name; e++) {
 | 
			
		||||
				if (e->id == id2)
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			for (e = bcma_sflash_st_tbl; e->name; e++) {
 | 
			
		||||
				if (e->id == id)
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (!e->name) {
 | 
			
		||||
			bcma_err(bus, "Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2);
 | 
			
		||||
			return -ENOTSUPP;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	case BCMA_CC_FLASHT_ATSER:
 | 
			
		||||
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
 | 
			
		||||
		id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c;
 | 
			
		||||
 | 
			
		||||
		for (e = bcma_sflash_at_tbl; e->name; e++) {
 | 
			
		||||
			if (e->id == id)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
		if (!e->name) {
 | 
			
		||||
			bcma_err(bus, "Unsupported Atmel serial flash (id: 0x%X)\n", id);
 | 
			
		||||
			return -ENOTSUPP;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		bcma_err(bus, "Unsupported flash type\n");
 | 
			
		||||
		return -ENOTSUPP;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sflash->window = BCMA_SFLASH;
 | 
			
		||||
	sflash->blocksize = e->blocksize;
 | 
			
		||||
	sflash->numblocks = e->numblocks;
 | 
			
		||||
	sflash->size = sflash->blocksize * sflash->numblocks;
 | 
			
		||||
	sflash->present = true;
 | 
			
		||||
 | 
			
		||||
	bcma_info(bus, "Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
 | 
			
		||||
		  e->name, sflash->size / 1024, sflash->blocksize,
 | 
			
		||||
		  sflash->numblocks);
 | 
			
		||||
 | 
			
		||||
	/* Prepare platform device, but don't register it yet. It's too early,
 | 
			
		||||
	 * malloc (required by device_private_init) is not available yet. */
 | 
			
		||||
	bcma_sflash_dev.resource[0].end = bcma_sflash_dev.resource[0].start +
 | 
			
		||||
					  sflash->size;
 | 
			
		||||
	bcma_sflash_dev.dev.platform_data = sflash;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@
 | 
			
		|||
 | 
			
		||||
#include "bcma_private.h"
 | 
			
		||||
#include <linux/module.h>
 | 
			
		||||
#include <linux/platform_device.h>
 | 
			
		||||
#include <linux/bcma/bcma.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -136,6 +137,14 @@ static int bcma_register_cores(struct bcma_bus *bus)
 | 
			
		|||
		dev_id++;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_BCMA_SFLASH
 | 
			
		||||
	if (bus->drv_cc.sflash.present) {
 | 
			
		||||
		err = platform_device_register(&bcma_sflash_dev);
 | 
			
		||||
		if (err)
 | 
			
		||||
			bcma_err(bus, "Error registering serial flash\n");
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -509,6 +509,16 @@ struct bcma_pflash {
 | 
			
		|||
	u32 window_size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_BCMA_SFLASH
 | 
			
		||||
struct bcma_sflash {
 | 
			
		||||
	bool present;
 | 
			
		||||
	u32 window;
 | 
			
		||||
	u32 blocksize;
 | 
			
		||||
	u16 numblocks;
 | 
			
		||||
	u32 size;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
struct bcma_serial_port {
 | 
			
		||||
	void *regs;
 | 
			
		||||
	unsigned long clockspeed;
 | 
			
		||||
| 
						 | 
				
			
			@ -529,6 +539,9 @@ struct bcma_drv_cc {
 | 
			
		|||
	struct bcma_chipcommon_pmu pmu;
 | 
			
		||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
 | 
			
		||||
	struct bcma_pflash pflash;
 | 
			
		||||
#ifdef CONFIG_BCMA_SFLASH
 | 
			
		||||
	struct bcma_sflash sflash;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	int nr_serial_ports;
 | 
			
		||||
	struct bcma_serial_port serial_ports[4];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,4 +85,6 @@
 | 
			
		|||
							 * (2 ZettaBytes), high 32 bits
 | 
			
		||||
							 */
 | 
			
		||||
 | 
			
		||||
#define BCMA_SFLASH			0x1c000000
 | 
			
		||||
 | 
			
		||||
#endif /* LINUX_BCMA_REGS_H_ */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue