hc
2024-05-10 748e4f3d702def1a4bff191e0cf93b6a05340f01
kernel/drivers/memory/brcmstb_dpfe.c
....@@ -1,10 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * DDR PHY Front End (DPFE) driver for Broadcom set top box SoCs
34 *
45 * Copyright (c) 2017 Broadcom
5
- *
6
- * Released under the GPLv2 only.
7
- * SPDX-License-Identifier: GPL-2.0
86 */
97
108 /*
....@@ -25,7 +23,7 @@
2523 * - BE kernel + LE firmware image
2624 * - BE kernel + BE firmware image
2725 *
28
- * The DPCU always runs in big endian mode. The firwmare image, however, can
26
+ * The DPCU always runs in big endian mode. The firmware image, however, can
2927 * be in either format. Also, communication between host CPU and DCPU is
3028 * always in little endian.
3129 */
....@@ -35,10 +33,10 @@
3533 #include <linux/io.h>
3634 #include <linux/module.h>
3735 #include <linux/of_address.h>
36
+#include <linux/of_device.h>
3837 #include <linux/platform_device.h>
3938
4039 #define DRVNAME "brcmstb-dpfe"
41
-#define FIRMWARE_NAME "dpfe.bin"
4240
4341 /* DCPU register offsets */
4442 #define REG_DCPU_RESET 0x0
....@@ -61,6 +59,7 @@
6159 #define DRAM_INFO_MR4 0x4
6260 #define DRAM_INFO_ERROR 0x8
6361 #define DRAM_INFO_MR4_MASK 0xff
62
+#define DRAM_INFO_MR4_SHIFT 24 /* We need to look at byte 3 */
6463
6564 /* DRAM MR4 Offsets & Masks */
6665 #define DRAM_MR4_REFRESH 0x0 /* Refresh rate */
....@@ -75,13 +74,23 @@
7574 #define DRAM_MR4_TH_OFFS_MASK 0x3
7675 #define DRAM_MR4_TUF_MASK 0x1
7776
78
-/* DRAM Vendor Offsets & Masks */
77
+/* DRAM Vendor Offsets & Masks (API v2) */
7978 #define DRAM_VENDOR_MR5 0x0
8079 #define DRAM_VENDOR_MR6 0x4
8180 #define DRAM_VENDOR_MR7 0x8
8281 #define DRAM_VENDOR_MR8 0xc
8382 #define DRAM_VENDOR_ERROR 0x10
8483 #define DRAM_VENDOR_MASK 0xff
84
+#define DRAM_VENDOR_SHIFT 24 /* We need to look at byte 3 */
85
+
86
+/* DRAM Information Offsets & Masks (API v3) */
87
+#define DRAM_DDR_INFO_MR4 0x0
88
+#define DRAM_DDR_INFO_MR5 0x4
89
+#define DRAM_DDR_INFO_MR6 0x8
90
+#define DRAM_DDR_INFO_MR7 0xc
91
+#define DRAM_DDR_INFO_MR8 0x10
92
+#define DRAM_DDR_INFO_ERROR 0x14
93
+#define DRAM_DDR_INFO_MASK 0xff
8594
8695 /* Reset register bits & masks */
8796 #define DCPU_RESET_SHIFT 0x0
....@@ -111,15 +120,14 @@
111120 #define DPFE_MSG_TYPE_COMMAND 1
112121 #define DPFE_MSG_TYPE_RESPONSE 2
113122
114
-#define DELAY_LOOP_MAX 200000
123
+#define DELAY_LOOP_MAX 1000
115124
116125 enum dpfe_msg_fields {
117126 MSG_HEADER,
118127 MSG_COMMAND,
119128 MSG_ARG_COUNT,
120129 MSG_ARG0,
121
- MSG_CHKSUM,
122
- MSG_FIELD_MAX /* Last entry */
130
+ MSG_FIELD_MAX = 16 /* Max number of arguments */
123131 };
124132
125133 enum dpfe_commands {
....@@ -127,14 +135,6 @@
127135 DPFE_CMD_GET_REFRESH,
128136 DPFE_CMD_GET_VENDOR,
129137 DPFE_CMD_MAX /* Last entry */
130
-};
131
-
132
-struct dpfe_msg {
133
- u32 header;
134
- u32 command;
135
- u32 arg_count;
136
- u32 arg0;
137
- u32 chksum; /* This is the sum of all other entries. */
138138 };
139139
140140 /*
....@@ -170,70 +170,186 @@
170170 bool is_big_endian;
171171 };
172172
173
+/* API version and corresponding commands */
174
+struct dpfe_api {
175
+ int version;
176
+ const char *fw_name;
177
+ const struct attribute_group **sysfs_attrs;
178
+ u32 command[DPFE_CMD_MAX][MSG_FIELD_MAX];
179
+};
180
+
173181 /* Things we need for as long as we are active. */
174
-struct private_data {
182
+struct brcmstb_dpfe_priv {
175183 void __iomem *regs;
176184 void __iomem *dmem;
177185 void __iomem *imem;
178186 struct device *dev;
187
+ const struct dpfe_api *dpfe_api;
179188 struct mutex lock;
180189 };
181190
182
-static const char *error_text[] = {
183
- "Success", "Header code incorrect", "Unknown command or argument",
184
- "Incorrect checksum", "Malformed command", "Timed out",
191
+/*
192
+ * Forward declaration of our sysfs attribute functions, so we can declare the
193
+ * attribute data structures early.
194
+ */
195
+static ssize_t show_info(struct device *, struct device_attribute *, char *);
196
+static ssize_t show_refresh(struct device *, struct device_attribute *, char *);
197
+static ssize_t store_refresh(struct device *, struct device_attribute *,
198
+ const char *, size_t);
199
+static ssize_t show_vendor(struct device *, struct device_attribute *, char *);
200
+static ssize_t show_dram(struct device *, struct device_attribute *, char *);
201
+
202
+/*
203
+ * Declare our attributes early, so they can be referenced in the API data
204
+ * structure. We need to do this, because the attributes depend on the API
205
+ * version.
206
+ */
207
+static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL);
208
+static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh);
209
+static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL);
210
+static DEVICE_ATTR(dpfe_dram, 0444, show_dram, NULL);
211
+
212
+/* API v2 sysfs attributes */
213
+static struct attribute *dpfe_v2_attrs[] = {
214
+ &dev_attr_dpfe_info.attr,
215
+ &dev_attr_dpfe_refresh.attr,
216
+ &dev_attr_dpfe_vendor.attr,
217
+ NULL
218
+};
219
+ATTRIBUTE_GROUPS(dpfe_v2);
220
+
221
+/* API v3 sysfs attributes */
222
+static struct attribute *dpfe_v3_attrs[] = {
223
+ &dev_attr_dpfe_info.attr,
224
+ &dev_attr_dpfe_dram.attr,
225
+ NULL
226
+};
227
+ATTRIBUTE_GROUPS(dpfe_v3);
228
+
229
+/*
230
+ * Old API v2 firmware commands, as defined in the rev 0.61 specification, we
231
+ * use a version set to 1 to denote that it is not compatible with the new API
232
+ * v2 and onwards.
233
+ */
234
+static const struct dpfe_api dpfe_api_old_v2 = {
235
+ .version = 1,
236
+ .fw_name = "dpfe.bin",
237
+ .sysfs_attrs = dpfe_v2_groups,
238
+ .command = {
239
+ [DPFE_CMD_GET_INFO] = {
240
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
241
+ [MSG_COMMAND] = 1,
242
+ [MSG_ARG_COUNT] = 1,
243
+ [MSG_ARG0] = 1,
244
+ },
245
+ [DPFE_CMD_GET_REFRESH] = {
246
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
247
+ [MSG_COMMAND] = 2,
248
+ [MSG_ARG_COUNT] = 1,
249
+ [MSG_ARG0] = 1,
250
+ },
251
+ [DPFE_CMD_GET_VENDOR] = {
252
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
253
+ [MSG_COMMAND] = 2,
254
+ [MSG_ARG_COUNT] = 1,
255
+ [MSG_ARG0] = 2,
256
+ },
257
+ }
185258 };
186259
187
-/* List of supported firmware commands */
188
-static const u32 dpfe_commands[DPFE_CMD_MAX][MSG_FIELD_MAX] = {
189
- [DPFE_CMD_GET_INFO] = {
190
- [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
191
- [MSG_COMMAND] = 1,
192
- [MSG_ARG_COUNT] = 1,
193
- [MSG_ARG0] = 1,
194
- [MSG_CHKSUM] = 4,
195
- },
196
- [DPFE_CMD_GET_REFRESH] = {
197
- [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
198
- [MSG_COMMAND] = 2,
199
- [MSG_ARG_COUNT] = 1,
200
- [MSG_ARG0] = 1,
201
- [MSG_CHKSUM] = 5,
202
- },
203
- [DPFE_CMD_GET_VENDOR] = {
204
- [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
205
- [MSG_COMMAND] = 2,
206
- [MSG_ARG_COUNT] = 1,
207
- [MSG_ARG0] = 2,
208
- [MSG_CHKSUM] = 6,
260
+/*
261
+ * API v2 firmware commands, as defined in the rev 0.8 specification, named new
262
+ * v2 here
263
+ */
264
+static const struct dpfe_api dpfe_api_new_v2 = {
265
+ .version = 2,
266
+ .fw_name = NULL, /* We expect the firmware to have been downloaded! */
267
+ .sysfs_attrs = dpfe_v2_groups,
268
+ .command = {
269
+ [DPFE_CMD_GET_INFO] = {
270
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
271
+ [MSG_COMMAND] = 0x101,
272
+ },
273
+ [DPFE_CMD_GET_REFRESH] = {
274
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
275
+ [MSG_COMMAND] = 0x201,
276
+ },
277
+ [DPFE_CMD_GET_VENDOR] = {
278
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
279
+ [MSG_COMMAND] = 0x202,
280
+ },
281
+ }
282
+};
283
+
284
+/* API v3 firmware commands */
285
+static const struct dpfe_api dpfe_api_v3 = {
286
+ .version = 3,
287
+ .fw_name = NULL, /* We expect the firmware to have been downloaded! */
288
+ .sysfs_attrs = dpfe_v3_groups,
289
+ .command = {
290
+ [DPFE_CMD_GET_INFO] = {
291
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
292
+ [MSG_COMMAND] = 0x0101,
293
+ [MSG_ARG_COUNT] = 1,
294
+ [MSG_ARG0] = 1,
295
+ },
296
+ [DPFE_CMD_GET_REFRESH] = {
297
+ [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
298
+ [MSG_COMMAND] = 0x0202,
299
+ [MSG_ARG_COUNT] = 0,
300
+ },
301
+ /* There's no GET_VENDOR command in API v3. */
209302 },
210303 };
211304
212
-static bool is_dcpu_enabled(void __iomem *regs)
305
+static const char *get_error_text(unsigned int i)
306
+{
307
+ static const char * const error_text[] = {
308
+ "Success", "Header code incorrect",
309
+ "Unknown command or argument", "Incorrect checksum",
310
+ "Malformed command", "Timed out", "Unknown error",
311
+ };
312
+
313
+ if (unlikely(i >= ARRAY_SIZE(error_text)))
314
+ i = ARRAY_SIZE(error_text) - 1;
315
+
316
+ return error_text[i];
317
+}
318
+
319
+static bool is_dcpu_enabled(struct brcmstb_dpfe_priv *priv)
213320 {
214321 u32 val;
215322
216
- val = readl_relaxed(regs + REG_DCPU_RESET);
323
+ mutex_lock(&priv->lock);
324
+ val = readl_relaxed(priv->regs + REG_DCPU_RESET);
325
+ mutex_unlock(&priv->lock);
217326
218327 return !(val & DCPU_RESET_MASK);
219328 }
220329
221
-static void __disable_dcpu(void __iomem *regs)
330
+static void __disable_dcpu(struct brcmstb_dpfe_priv *priv)
222331 {
223332 u32 val;
224333
225
- if (!is_dcpu_enabled(regs))
334
+ if (!is_dcpu_enabled(priv))
226335 return;
227336
337
+ mutex_lock(&priv->lock);
338
+
228339 /* Put DCPU in reset if it's running. */
229
- val = readl_relaxed(regs + REG_DCPU_RESET);
340
+ val = readl_relaxed(priv->regs + REG_DCPU_RESET);
230341 val |= (1 << DCPU_RESET_SHIFT);
231
- writel_relaxed(val, regs + REG_DCPU_RESET);
342
+ writel_relaxed(val, priv->regs + REG_DCPU_RESET);
343
+
344
+ mutex_unlock(&priv->lock);
232345 }
233346
234
-static void __enable_dcpu(void __iomem *regs)
347
+static void __enable_dcpu(struct brcmstb_dpfe_priv *priv)
235348 {
349
+ void __iomem *regs = priv->regs;
236350 u32 val;
351
+
352
+ mutex_lock(&priv->lock);
237353
238354 /* Clear mailbox registers. */
239355 writel_relaxed(0, regs + REG_TO_DCPU_MBOX);
....@@ -248,26 +364,32 @@
248364 val = readl_relaxed(regs + REG_DCPU_RESET);
249365 val &= ~(1 << DCPU_RESET_SHIFT);
250366 writel_relaxed(val, regs + REG_DCPU_RESET);
367
+
368
+ mutex_unlock(&priv->lock);
251369 }
252370
253
-static unsigned int get_msg_chksum(const u32 msg[])
371
+static unsigned int get_msg_chksum(const u32 msg[], unsigned int max)
254372 {
255373 unsigned int sum = 0;
256374 unsigned int i;
257375
258376 /* Don't include the last field in the checksum. */
259
- for (i = 0; i < MSG_FIELD_MAX - 1; i++)
377
+ for (i = 0; i < max; i++)
260378 sum += msg[i];
261379
262380 return sum;
263381 }
264382
265
-static void __iomem *get_msg_ptr(struct private_data *priv, u32 response,
383
+static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
266384 char *buf, ssize_t *size)
267385 {
268386 unsigned int msg_type;
269387 unsigned int offset;
270388 void __iomem *ptr = NULL;
389
+
390
+ /* There is no need to use this function for API v3 or later. */
391
+ if (unlikely(priv->dpfe_api->version >= 3))
392
+ return NULL;
271393
272394 msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
273395 offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
....@@ -296,23 +418,58 @@
296418 return ptr;
297419 }
298420
299
-static int __send_command(struct private_data *priv, unsigned int cmd,
421
+static void __finalize_command(struct brcmstb_dpfe_priv *priv)
422
+{
423
+ unsigned int release_mbox;
424
+
425
+ /*
426
+ * It depends on the API version which MBOX register we have to write to
427
+ * to signal we are done.
428
+ */
429
+ release_mbox = (priv->dpfe_api->version < 2)
430
+ ? REG_TO_HOST_MBOX : REG_TO_DCPU_MBOX;
431
+ writel_relaxed(0, priv->regs + release_mbox);
432
+}
433
+
434
+static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
300435 u32 result[])
301436 {
302
- const u32 *msg = dpfe_commands[cmd];
303437 void __iomem *regs = priv->regs;
304
- unsigned int i, chksum;
438
+ unsigned int i, chksum, chksum_idx;
439
+ const u32 *msg;
305440 int ret = 0;
306441 u32 resp;
307442
308443 if (cmd >= DPFE_CMD_MAX)
309444 return -1;
310445
446
+ msg = priv->dpfe_api->command[cmd];
447
+
311448 mutex_lock(&priv->lock);
312449
450
+ /* Wait for DCPU to become ready */
451
+ for (i = 0; i < DELAY_LOOP_MAX; i++) {
452
+ resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
453
+ if (resp == 0)
454
+ break;
455
+ msleep(1);
456
+ }
457
+ if (resp != 0) {
458
+ mutex_unlock(&priv->lock);
459
+ return -ffs(DCPU_RET_ERR_TIMEDOUT);
460
+ }
461
+
462
+ /* Compute checksum over the message */
463
+ chksum_idx = msg[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
464
+ chksum = get_msg_chksum(msg, chksum_idx);
465
+
313466 /* Write command and arguments to message area */
314
- for (i = 0; i < MSG_FIELD_MAX; i++)
315
- writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i));
467
+ for (i = 0; i < MSG_FIELD_MAX; i++) {
468
+ if (i == chksum_idx)
469
+ writel_relaxed(chksum, regs + DCPU_MSG_RAM(i));
470
+ else
471
+ writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i));
472
+ }
316473
317474 /* Tell DCPU there is a command waiting */
318475 writel_relaxed(1, regs + REG_TO_DCPU_MBOX);
....@@ -323,7 +480,7 @@
323480 resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
324481 if (resp > 0)
325482 break;
326
- udelay(5);
483
+ msleep(1);
327484 }
328485
329486 if (i == DELAY_LOOP_MAX) {
....@@ -333,10 +490,11 @@
333490 /* Read response data */
334491 for (i = 0; i < MSG_FIELD_MAX; i++)
335492 result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i));
493
+ chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
336494 }
337495
338496 /* Tell DCPU we are done */
339
- writel_relaxed(0, regs + REG_TO_HOST_MBOX);
497
+ __finalize_command(priv);
340498
341499 mutex_unlock(&priv->lock);
342500
....@@ -344,8 +502,8 @@
344502 return ret;
345503
346504 /* Verify response */
347
- chksum = get_msg_chksum(result);
348
- if (chksum != result[MSG_CHKSUM])
505
+ chksum = get_msg_chksum(result, chksum_idx);
506
+ if (chksum != result[chksum_idx])
349507 resp = DCPU_RET_ERR_CHKSUM;
350508
351509 if (resp != DCPU_RET_SUCCESS) {
....@@ -405,7 +563,7 @@
405563
406564 /* Verify checksum by reading back the firmware from co-processor RAM. */
407565 static int __verify_fw_checksum(struct init_data *init,
408
- struct private_data *priv,
566
+ struct brcmstb_dpfe_priv *priv,
409567 const struct dpfe_firmware_header *header,
410568 u32 checksum)
411569 {
....@@ -459,26 +617,23 @@
459617 return 0;
460618 }
461619
462
-static int brcmstb_dpfe_download_firmware(struct platform_device *pdev,
463
- struct init_data *init)
620
+static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv)
464621 {
465622 const struct dpfe_firmware_header *header;
466623 unsigned int dmem_size, imem_size;
467
- struct device *dev = &pdev->dev;
624
+ struct device *dev = priv->dev;
468625 bool is_big_endian = false;
469
- struct private_data *priv;
470626 const struct firmware *fw;
471627 const u32 *dmem, *imem;
628
+ struct init_data init;
472629 const void *fw_blob;
473630 int ret;
474
-
475
- priv = platform_get_drvdata(pdev);
476631
477632 /*
478633 * Skip downloading the firmware if the DCPU is already running and
479634 * responding to commands.
480635 */
481
- if (is_dcpu_enabled(priv->regs)) {
636
+ if (is_dcpu_enabled(priv)) {
482637 u32 response[MSG_FIELD_MAX];
483638
484639 ret = __send_command(priv, DPFE_CMD_GET_INFO, response);
....@@ -486,20 +641,33 @@
486641 return 0;
487642 }
488643
489
- ret = request_firmware(&fw, FIRMWARE_NAME, dev);
490
- /* request_firmware() prints its own error messages. */
644
+ /*
645
+ * If the firmware filename is NULL it means the boot firmware has to
646
+ * download the DCPU firmware for us. If that didn't work, we have to
647
+ * bail, since downloading it ourselves wouldn't work either.
648
+ */
649
+ if (!priv->dpfe_api->fw_name)
650
+ return -ENODEV;
651
+
652
+ ret = firmware_request_nowarn(&fw, priv->dpfe_api->fw_name, dev);
653
+ /*
654
+ * Defer the firmware download if the firmware file couldn't be found.
655
+ * The root file system may not be available yet.
656
+ */
491657 if (ret)
492
- return ret;
658
+ return (ret == -ENOENT) ? -EPROBE_DEFER : ret;
493659
494
- ret = __verify_firmware(init, fw);
495
- if (ret)
496
- return -EFAULT;
660
+ ret = __verify_firmware(&init, fw);
661
+ if (ret) {
662
+ ret = -EFAULT;
663
+ goto release_fw;
664
+ }
497665
498
- __disable_dcpu(priv->regs);
666
+ __disable_dcpu(priv);
499667
500
- is_big_endian = init->is_big_endian;
501
- dmem_size = init->dmem_len;
502
- imem_size = init->imem_len;
668
+ is_big_endian = init.is_big_endian;
669
+ dmem_size = init.dmem_len;
670
+ imem_size = init.imem_len;
503671
504672 /* At the beginning of the firmware blob is a header. */
505673 header = (struct dpfe_firmware_header *)fw->data;
....@@ -512,33 +680,33 @@
512680
513681 ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian);
514682 if (ret)
515
- return ret;
683
+ goto release_fw;
516684 ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian);
517685 if (ret)
518
- return ret;
686
+ goto release_fw;
519687
520
- ret = __verify_fw_checksum(init, priv, header, init->chksum);
688
+ ret = __verify_fw_checksum(&init, priv, header, init.chksum);
521689 if (ret)
522
- return ret;
690
+ goto release_fw;
523691
524
- __enable_dcpu(priv->regs);
692
+ __enable_dcpu(priv);
525693
526
- return 0;
694
+release_fw:
695
+ release_firmware(fw);
696
+ return ret;
527697 }
528698
529699 static ssize_t generic_show(unsigned int command, u32 response[],
530
- struct device *dev, char *buf)
700
+ struct brcmstb_dpfe_priv *priv, char *buf)
531701 {
532
- struct private_data *priv;
533702 int ret;
534703
535
- priv = dev_get_drvdata(dev);
536704 if (!priv)
537705 return sprintf(buf, "ERROR: driver private data not set\n");
538706
539707 ret = __send_command(priv, command, response);
540708 if (ret < 0)
541
- return sprintf(buf, "ERROR: %s\n", error_text[-ret]);
709
+ return sprintf(buf, "ERROR: %s\n", get_error_text(-ret));
542710
543711 return 0;
544712 }
....@@ -547,10 +715,12 @@
547715 char *buf)
548716 {
549717 u32 response[MSG_FIELD_MAX];
718
+ struct brcmstb_dpfe_priv *priv;
550719 unsigned int info;
551720 ssize_t ret;
552721
553
- ret = generic_show(DPFE_CMD_GET_INFO, response, dev, buf);
722
+ priv = dev_get_drvdata(dev);
723
+ ret = generic_show(DPFE_CMD_GET_INFO, response, priv, buf);
554724 if (ret)
555725 return ret;
556726
....@@ -568,22 +738,22 @@
568738 {
569739 u32 response[MSG_FIELD_MAX];
570740 void __iomem *info;
571
- struct private_data *priv;
741
+ struct brcmstb_dpfe_priv *priv;
572742 u8 refresh, sr_abort, ppre, thermal_offs, tuf;
573743 u32 mr4;
574744 ssize_t ret;
575745
576
- ret = generic_show(DPFE_CMD_GET_REFRESH, response, dev, buf);
746
+ priv = dev_get_drvdata(dev);
747
+ ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
577748 if (ret)
578749 return ret;
579
-
580
- priv = dev_get_drvdata(dev);
581750
582751 info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
583752 if (!info)
584753 return ret;
585754
586
- mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK;
755
+ mr4 = (readl_relaxed(info + DRAM_INFO_MR4) >> DRAM_INFO_MR4_SHIFT) &
756
+ DRAM_INFO_MR4_MASK;
587757
588758 refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK;
589759 sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK;
....@@ -601,7 +771,7 @@
601771 const char *buf, size_t count)
602772 {
603773 u32 response[MSG_FIELD_MAX];
604
- struct private_data *priv;
774
+ struct brcmstb_dpfe_priv *priv;
605775 void __iomem *info;
606776 unsigned long val;
607777 int ret;
....@@ -610,7 +780,6 @@
610780 return -EINVAL;
611781
612782 priv = dev_get_drvdata(dev);
613
-
614783 ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response);
615784 if (ret)
616785 return ret;
....@@ -625,61 +794,79 @@
625794 }
626795
627796 static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr,
628
- char *buf)
797
+ char *buf)
629798 {
630799 u32 response[MSG_FIELD_MAX];
631
- struct private_data *priv;
800
+ struct brcmstb_dpfe_priv *priv;
632801 void __iomem *info;
633802 ssize_t ret;
634
-
635
- ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf);
636
- if (ret)
637
- return ret;
803
+ u32 mr5, mr6, mr7, mr8, err;
638804
639805 priv = dev_get_drvdata(dev);
806
+ ret = generic_show(DPFE_CMD_GET_VENDOR, response, priv, buf);
807
+ if (ret)
808
+ return ret;
640809
641810 info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
642811 if (!info)
643812 return ret;
644813
645
- return sprintf(buf, "%#x %#x %#x %#x %#x\n",
646
- readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK,
647
- readl_relaxed(info + DRAM_VENDOR_MR6) & DRAM_VENDOR_MASK,
648
- readl_relaxed(info + DRAM_VENDOR_MR7) & DRAM_VENDOR_MASK,
649
- readl_relaxed(info + DRAM_VENDOR_MR8) & DRAM_VENDOR_MASK,
650
- readl_relaxed(info + DRAM_VENDOR_ERROR) &
651
- DRAM_VENDOR_MASK);
814
+ mr5 = (readl_relaxed(info + DRAM_VENDOR_MR5) >> DRAM_VENDOR_SHIFT) &
815
+ DRAM_VENDOR_MASK;
816
+ mr6 = (readl_relaxed(info + DRAM_VENDOR_MR6) >> DRAM_VENDOR_SHIFT) &
817
+ DRAM_VENDOR_MASK;
818
+ mr7 = (readl_relaxed(info + DRAM_VENDOR_MR7) >> DRAM_VENDOR_SHIFT) &
819
+ DRAM_VENDOR_MASK;
820
+ mr8 = (readl_relaxed(info + DRAM_VENDOR_MR8) >> DRAM_VENDOR_SHIFT) &
821
+ DRAM_VENDOR_MASK;
822
+ err = readl_relaxed(info + DRAM_VENDOR_ERROR) & DRAM_VENDOR_MASK;
823
+
824
+ return sprintf(buf, "%#x %#x %#x %#x %#x\n", mr5, mr6, mr7, mr8, err);
825
+}
826
+
827
+static ssize_t show_dram(struct device *dev, struct device_attribute *devattr,
828
+ char *buf)
829
+{
830
+ u32 response[MSG_FIELD_MAX];
831
+ struct brcmstb_dpfe_priv *priv;
832
+ ssize_t ret;
833
+ u32 mr4, mr5, mr6, mr7, mr8, err;
834
+
835
+ priv = dev_get_drvdata(dev);
836
+ ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
837
+ if (ret)
838
+ return ret;
839
+
840
+ mr4 = response[MSG_ARG0 + 0] & DRAM_INFO_MR4_MASK;
841
+ mr5 = response[MSG_ARG0 + 1] & DRAM_DDR_INFO_MASK;
842
+ mr6 = response[MSG_ARG0 + 2] & DRAM_DDR_INFO_MASK;
843
+ mr7 = response[MSG_ARG0 + 3] & DRAM_DDR_INFO_MASK;
844
+ mr8 = response[MSG_ARG0 + 4] & DRAM_DDR_INFO_MASK;
845
+ err = response[MSG_ARG0 + 5] & DRAM_DDR_INFO_MASK;
846
+
847
+ return sprintf(buf, "%#x %#x %#x %#x %#x %#x\n", mr4, mr5, mr6, mr7,
848
+ mr8, err);
652849 }
653850
654851 static int brcmstb_dpfe_resume(struct platform_device *pdev)
655852 {
656
- struct init_data init;
853
+ struct brcmstb_dpfe_priv *priv = platform_get_drvdata(pdev);
657854
658
- return brcmstb_dpfe_download_firmware(pdev, &init);
855
+ return brcmstb_dpfe_download_firmware(priv);
659856 }
660
-
661
-static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL);
662
-static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh);
663
-static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL);
664
-static struct attribute *dpfe_attrs[] = {
665
- &dev_attr_dpfe_info.attr,
666
- &dev_attr_dpfe_refresh.attr,
667
- &dev_attr_dpfe_vendor.attr,
668
- NULL
669
-};
670
-ATTRIBUTE_GROUPS(dpfe);
671857
672858 static int brcmstb_dpfe_probe(struct platform_device *pdev)
673859 {
674860 struct device *dev = &pdev->dev;
675
- struct private_data *priv;
676
- struct init_data init;
861
+ struct brcmstb_dpfe_priv *priv;
677862 struct resource *res;
678863 int ret;
679864
680865 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
681866 if (!priv)
682867 return -ENOMEM;
868
+
869
+ priv->dev = dev;
683870
684871 mutex_init(&priv->lock);
685872 platform_set_drvdata(pdev, priv);
....@@ -705,26 +892,45 @@
705892 return -ENOENT;
706893 }
707894
708
- ret = brcmstb_dpfe_download_firmware(pdev, &init);
709
- if (ret)
710
- return ret;
895
+ priv->dpfe_api = of_device_get_match_data(dev);
896
+ if (unlikely(!priv->dpfe_api)) {
897
+ /*
898
+ * It should be impossible to end up here, but to be safe we
899
+ * check anyway.
900
+ */
901
+ dev_err(dev, "Couldn't determine API\n");
902
+ return -ENOENT;
903
+ }
711904
712
- ret = sysfs_create_groups(&pdev->dev.kobj, dpfe_groups);
905
+ ret = brcmstb_dpfe_download_firmware(priv);
906
+ if (ret)
907
+ return dev_err_probe(dev, ret, "Couldn't download firmware\n");
908
+
909
+ ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
713910 if (!ret)
714
- dev_info(dev, "registered.\n");
911
+ dev_info(dev, "registered with API v%d.\n",
912
+ priv->dpfe_api->version);
715913
716914 return ret;
717915 }
718916
719917 static int brcmstb_dpfe_remove(struct platform_device *pdev)
720918 {
721
- sysfs_remove_groups(&pdev->dev.kobj, dpfe_groups);
919
+ struct brcmstb_dpfe_priv *priv = dev_get_drvdata(&pdev->dev);
920
+
921
+ sysfs_remove_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
722922
723923 return 0;
724924 }
725925
726926 static const struct of_device_id brcmstb_dpfe_of_match[] = {
727
- { .compatible = "brcm,dpfe-cpu", },
927
+ /* Use legacy API v2 for a select number of chips */
928
+ { .compatible = "brcm,bcm7268-dpfe-cpu", .data = &dpfe_api_old_v2 },
929
+ { .compatible = "brcm,bcm7271-dpfe-cpu", .data = &dpfe_api_old_v2 },
930
+ { .compatible = "brcm,bcm7278-dpfe-cpu", .data = &dpfe_api_old_v2 },
931
+ { .compatible = "brcm,bcm7211-dpfe-cpu", .data = &dpfe_api_new_v2 },
932
+ /* API v3 is the default going forward */
933
+ { .compatible = "brcm,dpfe-cpu", .data = &dpfe_api_v3 },
728934 {}
729935 };
730936 MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match);