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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
From d135d94b3d1fe599d13e7198d5f502912d694c13 Mon Sep 17 00:00:00 2001
From: Jonas Gorski <jonas.gorski@gmail.com>
Date: Sun, 3 Jul 2011 15:00:38 +0200
Subject: [PATCH 29/60] MIPS: BCM63XX: Register SPI flash if present
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
---
arch/mips/bcm63xx/dev-flash.c | 35 +++++++++++++++++++-
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 2 +
2 files changed, 33 insertions(+), 2 deletions(-)
--- a/arch/mips/bcm63xx/dev-flash.c
+++ b/arch/mips/bcm63xx/dev-flash.c
@@ -17,9 +17,13 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/spi-nor.h>
+#include <linux/of.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_flash.h>
+#include <bcm63xx_dev_hsspi.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
@@ -66,6 +70,46 @@ void __init bcm63xx_flash_force_phys_bas
mtd_resources[0].end = end;
}
+static struct flash_platform_data bcm63xx_flash_data = {
+ .part_probe_types = bcm63xx_part_types,
+};
+
+static struct spi_board_info bcm63xx_spi_flash_info[] = {
+ {
+ .bus_num = 0,
+ .chip_select = 0,
+ .mode = 0,
+ .max_speed_hz = 781000,
+ .modalias = "m25p80",
+ .platform_data = &bcm63xx_flash_data,
+ },
+};
+
+static void bcm63xx_of_update_spi_flash_speed(struct device_node *np,
+ unsigned int new_hz)
+{
+ struct property *max_hz;
+ __be32 *hz;
+
+ max_hz = kzalloc(sizeof(*max_hz) + sizeof(*hz), GFP_KERNEL);
+ if (!max_hz)
+ return;
+
+ max_hz->name = kstrdup("spi-max-frequency", GFP_KERNEL);
+ if (!max_hz->name) {
+ kfree(max_hz);
+ return;
+ }
+
+ max_hz->value = max_hz + 1;
+ max_hz->length = sizeof(*hz);
+
+ hz = max_hz->value;
+ *hz = cpu_to_be32(new_hz);
+
+ of_update_property(np, max_hz);
+}
+
static int __init bcm63xx_detect_flash_type(void)
{
u32 val;
@@ -73,9 +117,15 @@ static int __init bcm63xx_detect_flash_t
switch (bcm63xx_get_cpu_id()) {
case BCM6318_CPU_ID:
/* only support serial flash */
+ bcm63xx_spi_flash_info[0].max_speed_hz = 62500000;
return BCM63XX_FLASH_TYPE_SERIAL;
case BCM6328_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
+ if (val & STRAPBUS_6328_HSSPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 33333334;
+ else
+ bcm63xx_spi_flash_info[0].max_speed_hz = 16666667;
+
if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
@@ -94,12 +144,20 @@ static int __init bcm63xx_detect_flash_t
return BCM63XX_FLASH_TYPE_SERIAL;
case BCM6362_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6362_REG);
+ if (val & STRAPBUS_6362_HSSPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 50000000;
+ else
+ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
+
if (val & STRAPBUS_6362_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
return BCM63XX_FLASH_TYPE_NAND;
case BCM6368_CPU_ID:
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
+ if (val & STRAPBUS_6368_SPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
+
switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
case STRAPBUS_6368_BOOT_SEL_NAND:
return BCM63XX_FLASH_TYPE_NAND;
@@ -110,6 +168,11 @@ static int __init bcm63xx_detect_flash_t
}
case BCM63268_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_63268_REG);
+ if (val & STRAPBUS_63268_HSSPI_CLK_FAST)
+ bcm63xx_spi_flash_info[0].max_speed_hz = 50000000;
+ else
+ bcm63xx_spi_flash_info[0].max_speed_hz = 20000000;
+
if (val & STRAPBUS_63268_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
@@ -176,6 +239,7 @@ void __init bcm63xx_flash_detect(void)
int __init bcm63xx_flash_register(void)
{
+ struct device_node *np;
u32 val;
switch (flash_type) {
@@ -195,8 +259,21 @@ int __init bcm63xx_flash_register(void)
return platform_device_register(&mtd_dev);
case BCM63XX_FLASH_TYPE_SERIAL:
- pr_warn("unsupported serial flash detected\n");
- return -ENODEV;
+ np = of_find_compatible_node(NULL, NULL, "jedec,spi-nor");
+ if (np) {
+ bcm63xx_of_update_spi_flash_speed(np, bcm63xx_spi_flash_info[0].max_speed_hz);
+ of_node_put(np);
+ return 0;
+ } else {
+ if (BCMCPU_IS_6318() || BCMCPU_IS_6328() ||
+ BCMCPU_IS_6362() || BCMCPU_IS_63268()) {
+ bcm63xx_spi_flash_info[0].bus_num = 1;
+ bcm63xx_spi_flash_info[0].mode = SPI_RX_DUAL;
+ }
+
+ return spi_register_board_info(bcm63xx_spi_flash_info,
+ ARRAY_SIZE(bcm63xx_spi_flash_info));
+ }
case BCM63XX_FLASH_TYPE_NAND:
pr_warn("unsupported NAND flash detected\n");
return -ENODEV;
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -708,6 +708,7 @@
#define GPIO_STRAPBUS_REG 0x40
#define STRAPBUS_6358_BOOT_SEL_PARALLEL (1 << 1)
#define STRAPBUS_6358_BOOT_SEL_SERIAL (0 << 1)
+#define STRAPBUS_6368_SPI_CLK_FAST (1 << 6)
#define STRAPBUS_6368_BOOT_SEL_MASK 0x3
#define STRAPBUS_6368_BOOT_SEL_NAND 0
#define STRAPBUS_6368_BOOT_SEL_SERIAL 1
@@ -1564,6 +1565,7 @@
#define IDDQ_CTRL_63268_USBH (1 << 4)
#define MISC_STRAPBUS_6328_REG 0x240
+#define STRAPBUS_6328_HSSPI_CLK_FAST (1 << 4)
#define STRAPBUS_6328_FCVO_SHIFT 7
#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
#define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
|