aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/Kconfig12
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/sigma.c153
3 files changed, 0 insertions, 166 deletions
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index efba163595db..9b00072a020f 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -145,18 +145,6 @@ config ISCSI_IBFT
145 detect iSCSI boot parameters dynamically during system boot, say Y. 145 detect iSCSI boot parameters dynamically during system boot, say Y.
146 Otherwise, say N. 146 Otherwise, say N.
147 147
148config SIGMA
149 tristate "SigmaStudio firmware loader"
150 depends on I2C
151 select CRC32
152 default n
153 help
154 Enable helper functions for working with Analog Devices SigmaDSP
155 parts and binary firmwares produced by Analog Devices SigmaStudio.
156
157 If unsure, say N here. Drivers that need these helpers will select
158 this option automatically.
159
160source "drivers/firmware/google/Kconfig" 148source "drivers/firmware/google/Kconfig"
161 149
162endmenu 150endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 47338c979126..5a7e27399729 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -12,6 +12,5 @@ obj-$(CONFIG_DMIID) += dmi-id.o
12obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o 12obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
13obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o 13obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
14obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o 14obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
15obj-$(CONFIG_SIGMA) += sigma.o
16 15
17obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ 16obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
deleted file mode 100644
index 1eedb6f7fdab..000000000000
--- a/drivers/firmware/sigma.c
+++ /dev/null
@@ -1,153 +0,0 @@
1/*
2 * Load Analog Devices SigmaStudio firmware files
3 *
4 * Copyright 2009-2011 Analog Devices Inc.
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/crc32.h>
10#include <linux/delay.h>
11#include <linux/firmware.h>
12#include <linux/kernel.h>
13#include <linux/i2c.h>
14#include <linux/module.h>
15#include <linux/sigma.h>
16
17static size_t sigma_action_size(struct sigma_action *sa)
18{
19 size_t payload = 0;
20
21 switch (sa->instr) {
22 case SIGMA_ACTION_WRITEXBYTES:
23 case SIGMA_ACTION_WRITESINGLE:
24 case SIGMA_ACTION_WRITESAFELOAD:
25 payload = sigma_action_len(sa);
26 break;
27 default:
28 break;
29 }
30
31 payload = ALIGN(payload, 2);
32
33 return payload + sizeof(struct sigma_action);
34}
35
36/*
37 * Returns a negative error value in case of an error, 0 if processing of
38 * the firmware should be stopped after this action, 1 otherwise.
39 */
40static int
41process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
42{
43 size_t len = sigma_action_len(sa);
44 int ret;
45
46 pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
47 sa->instr, sa->addr, len);
48
49 switch (sa->instr) {
50 case SIGMA_ACTION_WRITEXBYTES:
51 case SIGMA_ACTION_WRITESINGLE:
52 case SIGMA_ACTION_WRITESAFELOAD:
53 ret = i2c_master_send(client, (void *)&sa->addr, len);
54 if (ret < 0)
55 return -EINVAL;
56 break;
57 case SIGMA_ACTION_DELAY:
58 udelay(len);
59 len = 0;
60 break;
61 case SIGMA_ACTION_END:
62 return 0;
63 default:
64 return -EINVAL;
65 }
66
67 return 1;
68}
69
70static int
71process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
72{
73 struct sigma_action *sa;
74 size_t size;
75 int ret;
76
77 while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
78 sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
79
80 size = sigma_action_size(sa);
81 ssfw->pos += size;
82 if (ssfw->pos > ssfw->fw->size || size == 0)
83 break;
84
85 ret = process_sigma_action(client, sa);
86
87 pr_debug("%s: action returned %i\n", __func__, ret);
88
89 if (ret <= 0)
90 return ret;
91 }
92
93 if (ssfw->pos != ssfw->fw->size)
94 return -EINVAL;
95
96 return 0;
97}
98
99int process_sigma_firmware(struct i2c_client *client, const char *name)
100{
101 int ret;
102 struct sigma_firmware_header *ssfw_head;
103 struct sigma_firmware ssfw;
104 const struct firmware *fw;
105 u32 crc;
106
107 pr_debug("%s: loading firmware %s\n", __func__, name);
108
109 /* first load the blob */
110 ret = request_firmware(&fw, name, &client->dev);
111 if (ret) {
112 pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
113 return ret;
114 }
115 ssfw.fw = fw;
116
117 /* then verify the header */
118 ret = -EINVAL;
119
120 /*
121 * Reject too small or unreasonable large files. The upper limit has been
122 * chosen a bit arbitrarily, but it should be enough for all practical
123 * purposes and having the limit makes it easier to avoid integer
124 * overflows later in the loading process.
125 */
126 if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
127 goto done;
128
129 ssfw_head = (void *)fw->data;
130 if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
131 goto done;
132
133 crc = crc32(0, fw->data + sizeof(*ssfw_head),
134 fw->size - sizeof(*ssfw_head));
135 pr_debug("%s: crc=%x\n", __func__, crc);
136 if (crc != le32_to_cpu(ssfw_head->crc))
137 goto done;
138
139 ssfw.pos = sizeof(*ssfw_head);
140
141 /* finally process all of the actions */
142 ret = process_sigma_actions(client, &ssfw);
143
144 done:
145 release_firmware(fw);
146
147 pr_debug("%s: loaded %s\n", __func__, name);
148
149 return ret;
150}
151EXPORT_SYMBOL(process_sigma_firmware);
152
153MODULE_LICENSE("GPL");