aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bcma/sprom.c
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2011-06-01 20:08:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-06-03 15:01:07 -0400
commit27f18dc2dafe66a93c7101fc94201b8c83903597 (patch)
tree4600db64c653cfc74d427fc26b7f94ef8fb5db28 /drivers/bcma/sprom.c
parent4da909e7b572b561d8150f9d41b04bcfff386222 (diff)
bcma: read SPROM and extract MAC from it
In case of BCMA cards SPROM is located in the ChipCommon core, it is not mapped as separated host window. So far we have met only SPROMs rev 8. SPROM layout seems to be the same as for SSB buses, so we decided to share SPROM struct and some defines. For now we extract MAC address only, this can be improved of course. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/bcma/sprom.c')
-rw-r--r--drivers/bcma/sprom.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c
new file mode 100644
index 000000000000..ffbb0e32e921
--- /dev/null
+++ b/drivers/bcma/sprom.c
@@ -0,0 +1,162 @@
1/*
2 * Broadcom specific AMBA
3 * SPROM reading
4 *
5 * Licensed under the GNU/GPL. See COPYING for details.
6 */
7
8#include "bcma_private.h"
9
10#include <linux/bcma/bcma.h>
11#include <linux/bcma/bcma_regs.h>
12#include <linux/pci.h>
13#include <linux/io.h>
14#include <linux/dma-mapping.h>
15#include <linux/slab.h>
16
17#define SPOFF(offset) ((offset) / sizeof(u16))
18
19/**************************************************
20 * R/W ops.
21 **************************************************/
22
23static void bcma_sprom_read(struct bcma_bus *bus, u16 *sprom)
24{
25 int i;
26 for (i = 0; i < SSB_SPROMSIZE_WORDS_R4; i++)
27 sprom[i] = bcma_read16(bus->drv_cc.core,
28 BCMA_CC_SPROM + (i * 2));
29}
30
31/**************************************************
32 * Validation.
33 **************************************************/
34
35static inline u8 bcma_crc8(u8 crc, u8 data)
36{
37 /* Polynomial: x^8 + x^7 + x^6 + x^4 + x^2 + 1 */
38 static const u8 t[] = {
39 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
40 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
41 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
42 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
43 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
44 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
45 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
46 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
47 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
48 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
49 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
50 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
51 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
52 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
53 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
54 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
55 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
56 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
57 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
58 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
59 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
60 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
61 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
62 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
63 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
64 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
65 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
66 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
67 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
68 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
69 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
70 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F,
71 };
72 return t[crc ^ data];
73}
74
75static u8 bcma_sprom_crc(const u16 *sprom)
76{
77 int word;
78 u8 crc = 0xFF;
79
80 for (word = 0; word < SSB_SPROMSIZE_WORDS_R4 - 1; word++) {
81 crc = bcma_crc8(crc, sprom[word] & 0x00FF);
82 crc = bcma_crc8(crc, (sprom[word] & 0xFF00) >> 8);
83 }
84 crc = bcma_crc8(crc, sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & 0x00FF);
85 crc ^= 0xFF;
86
87 return crc;
88}
89
90static int bcma_sprom_check_crc(const u16 *sprom)
91{
92 u8 crc;
93 u8 expected_crc;
94 u16 tmp;
95
96 crc = bcma_sprom_crc(sprom);
97 tmp = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_CRC;
98 expected_crc = tmp >> SSB_SPROM_REVISION_CRC_SHIFT;
99 if (crc != expected_crc)
100 return -EPROTO;
101
102 return 0;
103}
104
105static int bcma_sprom_valid(const u16 *sprom)
106{
107 u16 revision;
108 int err;
109
110 err = bcma_sprom_check_crc(sprom);
111 if (err)
112 return err;
113
114 revision = sprom[SSB_SPROMSIZE_WORDS_R4 - 1] & SSB_SPROM_REVISION_REV;
115 if (revision != 8) {
116 pr_err("Unsupported SPROM revision: %d\n", revision);
117 return -ENOENT;
118 }
119
120 return 0;
121}
122
123/**************************************************
124 * SPROM extraction.
125 **************************************************/
126
127static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
128{
129 u16 v;
130 int i;
131
132 for (i = 0; i < 3; i++) {
133 v = sprom[SPOFF(SSB_SPROM8_IL0MAC) + i];
134 *(((__be16 *)bus->sprom.il0mac) + i) = cpu_to_be16(v);
135 }
136}
137
138int bcma_sprom_get(struct bcma_bus *bus)
139{
140 u16 *sprom;
141 int err = 0;
142
143 if (!bus->drv_cc.core)
144 return -EOPNOTSUPP;
145
146 sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
147 GFP_KERNEL);
148 if (!sprom)
149 return -ENOMEM;
150
151 bcma_sprom_read(bus, sprom);
152
153 err = bcma_sprom_valid(sprom);
154 if (err)
155 goto out;
156
157 bcma_sprom_extract_r8(bus, sprom);
158
159out:
160 kfree(sprom);
161 return err;
162}