diff options
Diffstat (limited to 'drivers/firmware/raspberrypi.c')
-rw-r--r-- | drivers/firmware/raspberrypi.c | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c index 6692888f04cf..a200a2174611 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c | |||
@@ -21,6 +21,10 @@ | |||
21 | #define MBOX_DATA28(msg) ((msg) & ~0xf) | 21 | #define MBOX_DATA28(msg) ((msg) & ~0xf) |
22 | #define MBOX_CHAN_PROPERTY 8 | 22 | #define MBOX_CHAN_PROPERTY 8 |
23 | 23 | ||
24 | #define MAX_RPI_FW_PROP_BUF_SIZE 32 | ||
25 | |||
26 | static struct platform_device *rpi_hwmon; | ||
27 | |||
24 | struct rpi_firmware { | 28 | struct rpi_firmware { |
25 | struct mbox_client cl; | 29 | struct mbox_client cl; |
26 | struct mbox_chan *chan; /* The property channel. */ | 30 | struct mbox_chan *chan; /* The property channel. */ |
@@ -143,18 +147,22 @@ int rpi_firmware_property(struct rpi_firmware *fw, | |||
143 | /* Single tags are very small (generally 8 bytes), so the | 147 | /* Single tags are very small (generally 8 bytes), so the |
144 | * stack should be safe. | 148 | * stack should be safe. |
145 | */ | 149 | */ |
146 | u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)]; | 150 | u8 data[sizeof(struct rpi_firmware_property_tag_header) + |
151 | MAX_RPI_FW_PROP_BUF_SIZE]; | ||
147 | struct rpi_firmware_property_tag_header *header = | 152 | struct rpi_firmware_property_tag_header *header = |
148 | (struct rpi_firmware_property_tag_header *)data; | 153 | (struct rpi_firmware_property_tag_header *)data; |
149 | int ret; | 154 | int ret; |
150 | 155 | ||
156 | if (WARN_ON(buf_size > sizeof(data) - sizeof(*header))) | ||
157 | return -EINVAL; | ||
158 | |||
151 | header->tag = tag; | 159 | header->tag = tag; |
152 | header->buf_size = buf_size; | 160 | header->buf_size = buf_size; |
153 | header->req_resp_size = 0; | 161 | header->req_resp_size = 0; |
154 | memcpy(data + sizeof(struct rpi_firmware_property_tag_header), | 162 | memcpy(data + sizeof(struct rpi_firmware_property_tag_header), |
155 | tag_data, buf_size); | 163 | tag_data, buf_size); |
156 | 164 | ||
157 | ret = rpi_firmware_property_list(fw, &data, sizeof(data)); | 165 | ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header)); |
158 | memcpy(tag_data, | 166 | memcpy(tag_data, |
159 | data + sizeof(struct rpi_firmware_property_tag_header), | 167 | data + sizeof(struct rpi_firmware_property_tag_header), |
160 | buf_size); | 168 | buf_size); |
@@ -183,6 +191,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw) | |||
183 | } | 191 | } |
184 | } | 192 | } |
185 | 193 | ||
194 | static void | ||
195 | rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw) | ||
196 | { | ||
197 | u32 packet; | ||
198 | int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED, | ||
199 | &packet, sizeof(packet)); | ||
200 | |||
201 | if (ret) | ||
202 | return; | ||
203 | |||
204 | rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon", | ||
205 | -1, NULL, 0); | ||
206 | } | ||
207 | |||
186 | static int rpi_firmware_probe(struct platform_device *pdev) | 208 | static int rpi_firmware_probe(struct platform_device *pdev) |
187 | { | 209 | { |
188 | struct device *dev = &pdev->dev; | 210 | struct device *dev = &pdev->dev; |
@@ -209,6 +231,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) | |||
209 | platform_set_drvdata(pdev, fw); | 231 | platform_set_drvdata(pdev, fw); |
210 | 232 | ||
211 | rpi_firmware_print_firmware_revision(fw); | 233 | rpi_firmware_print_firmware_revision(fw); |
234 | rpi_register_hwmon_driver(dev, fw); | ||
212 | 235 | ||
213 | return 0; | 236 | return 0; |
214 | } | 237 | } |
@@ -217,6 +240,8 @@ static int rpi_firmware_remove(struct platform_device *pdev) | |||
217 | { | 240 | { |
218 | struct rpi_firmware *fw = platform_get_drvdata(pdev); | 241 | struct rpi_firmware *fw = platform_get_drvdata(pdev); |
219 | 242 | ||
243 | platform_device_unregister(rpi_hwmon); | ||
244 | rpi_hwmon = NULL; | ||
220 | mbox_free_channel(fw->chan); | 245 | mbox_free_channel(fw->chan); |
221 | 246 | ||
222 | return 0; | 247 | return 0; |