summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/mtd/chips/rtl819x/spi_flash.c
blob: 6f21f791ccedd8c3b7581c1f4dad8212090ce7a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <linux/config.h>
#include <linux/mtd/map.h>
#include <linux/mtd/gen_probe.h>
#include <linux/spinlock.h>

#include "spi_flash.h"
#include "spi_common.h"

#define MTD_SPI_DEBUG 0
#if (MTD_SPI_DEBUG)
#define KDEBUG(args...) printk(args)
#else
#define KDEBUG(args...)
#endif

struct spi_chip_mtd spi_probe_mtd;
extern struct spi_flash_type spi_flash_info[2];

// uiAddr = from; pucBuffer = to; uiLen = size
static unsigned int do_spi_read(unsigned int from, unsigned int to, unsigned int size, unsigned int uiChip)
{
	unsigned int uiRet;
	uiRet = spi_flash_info[uiChip].pfRead(uiChip, from, size, (unsigned char*)to);
	KDEBUG("do_spi_read: from=%x; to=%x; size=%x; uiRet=%x\n", from, to, size, uiRet);
	return 0;
}
/*
// uiAddr = to; pucBuffer = from; uiLen = size
static unsigned int do_spi_write(unsigned int  from, unsigned int  to, unsigned int  size)
{
	unsigned int uiRet;
	uiRet = spi_flash_info[0].pfWrite(0, to, size, (unsigned char*)from);
	KDEBUG("do_spi_write: from=%x; to=%x; size=%x; uiRet=%x\n", from, to, size, uiRet);
	return 0;
}
*/
// uiAddr = to; pucBuffer = from; uiLen = size (stupid!!!)
static unsigned int do_spi_write(unsigned int from, unsigned int to, unsigned int size, unsigned int uiChip)
{
	unsigned int uiStartAddr, uiStartLen, uiPageAddr, uiPageCount, uiEndAddr, uiEndLen, i, uiRet;
	unsigned char* puc = (unsigned char*)from;
	KDEBUG("do_spi_write:from=%x; to=%x; size=%x;\n", from, to, size);
	calAddr(to, size, spi_flash_info[uiChip].page_size, &uiStartAddr, &uiStartLen, &uiPageAddr, &uiPageCount, &uiEndAddr, &uiEndLen);
	if((uiPageCount == 0x00) && (uiEndLen == 0x00))	// all data in the same page
	{
		uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiStartAddr, uiStartLen, puc);
	}
	else
	{
		if(uiStartLen > 0)
		{
			uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiStartAddr, uiStartLen, puc);
			puc += uiStartLen;
		}
		for(i = 0; i < uiPageCount; i++)
		{
			uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiPageAddr, spi_flash_info[uiChip].page_size, puc);
			puc += spi_flash_info[uiChip].page_size;
			uiPageAddr += spi_flash_info[uiChip].page_size;
		}
		if(uiEndLen > 0)
		{
			uiRet = spi_flash_info[uiChip].pfPageWrite(uiChip, uiEndAddr, uiEndLen, puc);
		}
	}
	//ComSrlCmd_WRDI(0);
	return 0;
}
// uiAddr = addr
static int do_spi_erase(unsigned int  addr, unsigned int uiChip)
{
	unsigned int uiRet;
	uiRet = spi_flash_info[uiChip].pfErase(uiChip, addr);
	KDEBUG("do_spi_erase: addr=%x;\n", addr);
	return 0;
}
// SPI flash destroy
static void spi_suzaku_destroy(struct spi_chip_info *chip_info)
{
	KDEBUG("spi_suzaku_destroy:\n");
	return;
}

// SPI flash probe
int spi_cp_probe(unsigned int uiChip)
{
	spi_regist(uiChip);
	
	spi_probe_mtd.chip_id = spi_flash_info[uiChip].chip_id;
	spi_probe_mtd.extra_id = spi_flash_info[uiChip].dev_id;
	spi_probe_mtd.sectorSize = spi_flash_info[uiChip].sector_size;
	spi_probe_mtd.deviceSize = spi_flash_info[uiChip].chip_size;
	spi_probe_mtd.uiClkMhz = 0;
	spi_probe_mtd.name = spi_flash_info[uiChip].chip_name;

	KDEBUG("spi_cp_probe:uiChip=%x\n", uiChip);
	return 0;
}

// malloc mtd
static struct spi_chip_info *spi_suzaku_setup(struct map_info *map)
{
	struct spi_chip_info *chip_info;
	chip_info = kmalloc(sizeof(*chip_info), GFP_KERNEL);
	if (!chip_info)
	{
		printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
		return NULL;
	}
	memset(chip_info, 0, sizeof(struct spi_chip_info));
	KDEBUG("spi_suzaku_setup\n");
	return chip_info;
}


struct spi_chip_info *spi_probe_flash_chip(struct map_info *map, struct chip_probe *cp)
{
	struct spi_chip_info *chip_info = NULL;
	unsigned int chip_select=0; // 0 or 1

	if (!strcmp(cp->name,"SPI2"))
		chip_select=1;
	
	spi_cp_probe(chip_select);
	chip_info = spi_suzaku_setup(map);
	KDEBUG("spi_probe_flash_chip\n");
	if (chip_info) 
	{
		chip_info->name = cp->name;
		chip_info->chip_select = chip_select;
		chip_info->flash	= &spi_probe_mtd;
		chip_info->destroy	= spi_suzaku_destroy; 
	 	chip_info->read		= do_spi_read;
		chip_info->write	= do_spi_write;
		chip_info->erase	= do_spi_erase;
		return chip_info;
	}
	else
	{
		return NULL;
	}
}

EXPORT_SYMBOL(spi_probe_flash_chip);