Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * DDR PHY Front End (DPFE) driver for Broadcom set top box SoCs
0004  *
0005  * Copyright (c) 2017 Broadcom
0006  */
0007 
0008 /*
0009  * This driver provides access to the DPFE interface of Broadcom STB SoCs.
0010  * The firmware running on the DCPU inside the DDR PHY can provide current
0011  * information about the system's RAM, for instance the DRAM refresh rate.
0012  * This can be used as an indirect indicator for the DRAM's temperature.
0013  * Slower refresh rate means cooler RAM, higher refresh rate means hotter
0014  * RAM.
0015  *
0016  * Throughout the driver, we use readl_relaxed() and writel_relaxed(), which
0017  * already contain the appropriate le32_to_cpu()/cpu_to_le32() calls.
0018  *
0019  * Note regarding the loading of the firmware image: we use be32_to_cpu()
0020  * and le_32_to_cpu(), so we can support the following four cases:
0021  *     - LE kernel + LE firmware image (the most common case)
0022  *     - LE kernel + BE firmware image
0023  *     - BE kernel + LE firmware image
0024  *     - BE kernel + BE firmware image
0025  *
0026  * The DPCU always runs in big endian mode. The firmware image, however, can
0027  * be in either format. Also, communication between host CPU and DCPU is
0028  * always in little endian.
0029  */
0030 
0031 #include <linux/delay.h>
0032 #include <linux/firmware.h>
0033 #include <linux/io.h>
0034 #include <linux/module.h>
0035 #include <linux/of_address.h>
0036 #include <linux/of_device.h>
0037 #include <linux/platform_device.h>
0038 
0039 #define DRVNAME         "brcmstb-dpfe"
0040 
0041 /* DCPU register offsets */
0042 #define REG_DCPU_RESET      0x0
0043 #define REG_TO_DCPU_MBOX    0x10
0044 #define REG_TO_HOST_MBOX    0x14
0045 
0046 /* Macros to process offsets returned by the DCPU */
0047 #define DRAM_MSG_ADDR_OFFSET    0x0
0048 #define DRAM_MSG_TYPE_OFFSET    0x1c
0049 #define DRAM_MSG_ADDR_MASK  ((1UL << DRAM_MSG_TYPE_OFFSET) - 1)
0050 #define DRAM_MSG_TYPE_MASK  ((1UL << \
0051                  (BITS_PER_LONG - DRAM_MSG_TYPE_OFFSET)) - 1)
0052 
0053 /* Message RAM */
0054 #define DCPU_MSG_RAM_START  0x100
0055 #define DCPU_MSG_RAM(x)     (DCPU_MSG_RAM_START + (x) * sizeof(u32))
0056 
0057 /* DRAM Info Offsets & Masks */
0058 #define DRAM_INFO_INTERVAL  0x0
0059 #define DRAM_INFO_MR4       0x4
0060 #define DRAM_INFO_ERROR     0x8
0061 #define DRAM_INFO_MR4_MASK  0xff
0062 #define DRAM_INFO_MR4_SHIFT 24  /* We need to look at byte 3 */
0063 
0064 /* DRAM MR4 Offsets & Masks */
0065 #define DRAM_MR4_REFRESH    0x0 /* Refresh rate */
0066 #define DRAM_MR4_SR_ABORT   0x3 /* Self Refresh Abort */
0067 #define DRAM_MR4_PPRE       0x4 /* Post-package repair entry/exit */
0068 #define DRAM_MR4_TH_OFFS    0x5 /* Thermal Offset; vendor specific */
0069 #define DRAM_MR4_TUF        0x7 /* Temperature Update Flag */
0070 
0071 #define DRAM_MR4_REFRESH_MASK   0x7
0072 #define DRAM_MR4_SR_ABORT_MASK  0x1
0073 #define DRAM_MR4_PPRE_MASK  0x1
0074 #define DRAM_MR4_TH_OFFS_MASK   0x3
0075 #define DRAM_MR4_TUF_MASK   0x1
0076 
0077 /* DRAM Vendor Offsets & Masks (API v2) */
0078 #define DRAM_VENDOR_MR5     0x0
0079 #define DRAM_VENDOR_MR6     0x4
0080 #define DRAM_VENDOR_MR7     0x8
0081 #define DRAM_VENDOR_MR8     0xc
0082 #define DRAM_VENDOR_ERROR   0x10
0083 #define DRAM_VENDOR_MASK    0xff
0084 #define DRAM_VENDOR_SHIFT   24  /* We need to look at byte 3 */
0085 
0086 /* DRAM Information Offsets & Masks (API v3) */
0087 #define DRAM_DDR_INFO_MR4   0x0
0088 #define DRAM_DDR_INFO_MR5   0x4
0089 #define DRAM_DDR_INFO_MR6   0x8
0090 #define DRAM_DDR_INFO_MR7   0xc
0091 #define DRAM_DDR_INFO_MR8   0x10
0092 #define DRAM_DDR_INFO_ERROR 0x14
0093 #define DRAM_DDR_INFO_MASK  0xff
0094 
0095 /* Reset register bits & masks */
0096 #define DCPU_RESET_SHIFT    0x0
0097 #define DCPU_RESET_MASK     0x1
0098 #define DCPU_CLK_DISABLE_SHIFT  0x2
0099 
0100 /* DCPU return codes */
0101 #define DCPU_RET_ERROR_BIT  BIT(31)
0102 #define DCPU_RET_SUCCESS    0x1
0103 #define DCPU_RET_ERR_HEADER (DCPU_RET_ERROR_BIT | BIT(0))
0104 #define DCPU_RET_ERR_INVAL  (DCPU_RET_ERROR_BIT | BIT(1))
0105 #define DCPU_RET_ERR_CHKSUM (DCPU_RET_ERROR_BIT | BIT(2))
0106 #define DCPU_RET_ERR_COMMAND    (DCPU_RET_ERROR_BIT | BIT(3))
0107 /* This error code is not firmware defined and only used in the driver. */
0108 #define DCPU_RET_ERR_TIMEDOUT   (DCPU_RET_ERROR_BIT | BIT(4))
0109 
0110 /* Firmware magic */
0111 #define DPFE_BE_MAGIC       0xfe1010fe
0112 #define DPFE_LE_MAGIC       0xfe0101fe
0113 
0114 /* Error codes */
0115 #define ERR_INVALID_MAGIC   -1
0116 #define ERR_INVALID_SIZE    -2
0117 #define ERR_INVALID_CHKSUM  -3
0118 
0119 /* Message types */
0120 #define DPFE_MSG_TYPE_COMMAND   1
0121 #define DPFE_MSG_TYPE_RESPONSE  2
0122 
0123 #define DELAY_LOOP_MAX      1000
0124 
0125 enum dpfe_msg_fields {
0126     MSG_HEADER,
0127     MSG_COMMAND,
0128     MSG_ARG_COUNT,
0129     MSG_ARG0,
0130     MSG_FIELD_MAX   = 16 /* Max number of arguments */
0131 };
0132 
0133 enum dpfe_commands {
0134     DPFE_CMD_GET_INFO,
0135     DPFE_CMD_GET_REFRESH,
0136     DPFE_CMD_GET_VENDOR,
0137     DPFE_CMD_MAX /* Last entry */
0138 };
0139 
0140 /*
0141  * Format of the binary firmware file:
0142  *
0143  *   entry
0144  *      0    header
0145  *              value:  0xfe0101fe  <== little endian
0146  *                      0xfe1010fe  <== big endian
0147  *      1    sequence:
0148  *              [31:16] total segments on this build
0149  *              [15:0]  this segment sequence.
0150  *      2    FW version
0151  *      3    IMEM byte size
0152  *      4    DMEM byte size
0153  *           IMEM
0154  *           DMEM
0155  *      last checksum ==> sum of everything
0156  */
0157 struct dpfe_firmware_header {
0158     u32 magic;
0159     u32 sequence;
0160     u32 version;
0161     u32 imem_size;
0162     u32 dmem_size;
0163 };
0164 
0165 /* Things we only need during initialization. */
0166 struct init_data {
0167     unsigned int dmem_len;
0168     unsigned int imem_len;
0169     unsigned int chksum;
0170     bool is_big_endian;
0171 };
0172 
0173 /* API version and corresponding commands */
0174 struct dpfe_api {
0175     int version;
0176     const char *fw_name;
0177     const struct attribute_group **sysfs_attrs;
0178     u32 command[DPFE_CMD_MAX][MSG_FIELD_MAX];
0179 };
0180 
0181 /* Things we need for as long as we are active. */
0182 struct brcmstb_dpfe_priv {
0183     void __iomem *regs;
0184     void __iomem *dmem;
0185     void __iomem *imem;
0186     struct device *dev;
0187     const struct dpfe_api *dpfe_api;
0188     struct mutex lock;
0189 };
0190 
0191 /*
0192  * Forward declaration of our sysfs attribute functions, so we can declare the
0193  * attribute data structures early.
0194  */
0195 static ssize_t show_info(struct device *, struct device_attribute *, char *);
0196 static ssize_t show_refresh(struct device *, struct device_attribute *, char *);
0197 static ssize_t store_refresh(struct device *, struct device_attribute *,
0198               const char *, size_t);
0199 static ssize_t show_vendor(struct device *, struct device_attribute *, char *);
0200 static ssize_t show_dram(struct device *, struct device_attribute *, char *);
0201 
0202 /*
0203  * Declare our attributes early, so they can be referenced in the API data
0204  * structure. We need to do this, because the attributes depend on the API
0205  * version.
0206  */
0207 static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL);
0208 static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh);
0209 static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL);
0210 static DEVICE_ATTR(dpfe_dram, 0444, show_dram, NULL);
0211 
0212 /* API v2 sysfs attributes */
0213 static struct attribute *dpfe_v2_attrs[] = {
0214     &dev_attr_dpfe_info.attr,
0215     &dev_attr_dpfe_refresh.attr,
0216     &dev_attr_dpfe_vendor.attr,
0217     NULL
0218 };
0219 ATTRIBUTE_GROUPS(dpfe_v2);
0220 
0221 /* API v3 sysfs attributes */
0222 static struct attribute *dpfe_v3_attrs[] = {
0223     &dev_attr_dpfe_info.attr,
0224     &dev_attr_dpfe_dram.attr,
0225     NULL
0226 };
0227 ATTRIBUTE_GROUPS(dpfe_v3);
0228 
0229 /*
0230  * Old API v2 firmware commands, as defined in the rev 0.61 specification, we
0231  * use a version set to 1 to denote that it is not compatible with the new API
0232  * v2 and onwards.
0233  */
0234 static const struct dpfe_api dpfe_api_old_v2 = {
0235     .version = 1,
0236     .fw_name = "dpfe.bin",
0237     .sysfs_attrs = dpfe_v2_groups,
0238     .command = {
0239         [DPFE_CMD_GET_INFO] = {
0240             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0241             [MSG_COMMAND] = 1,
0242             [MSG_ARG_COUNT] = 1,
0243             [MSG_ARG0] = 1,
0244         },
0245         [DPFE_CMD_GET_REFRESH] = {
0246             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0247             [MSG_COMMAND] = 2,
0248             [MSG_ARG_COUNT] = 1,
0249             [MSG_ARG0] = 1,
0250         },
0251         [DPFE_CMD_GET_VENDOR] = {
0252             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0253             [MSG_COMMAND] = 2,
0254             [MSG_ARG_COUNT] = 1,
0255             [MSG_ARG0] = 2,
0256         },
0257     }
0258 };
0259 
0260 /*
0261  * API v2 firmware commands, as defined in the rev 0.8 specification, named new
0262  * v2 here
0263  */
0264 static const struct dpfe_api dpfe_api_new_v2 = {
0265     .version = 2,
0266     .fw_name = NULL, /* We expect the firmware to have been downloaded! */
0267     .sysfs_attrs = dpfe_v2_groups,
0268     .command = {
0269         [DPFE_CMD_GET_INFO] = {
0270             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0271             [MSG_COMMAND] = 0x101,
0272         },
0273         [DPFE_CMD_GET_REFRESH] = {
0274             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0275             [MSG_COMMAND] = 0x201,
0276         },
0277         [DPFE_CMD_GET_VENDOR] = {
0278             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0279             [MSG_COMMAND] = 0x202,
0280         },
0281     }
0282 };
0283 
0284 /* API v3 firmware commands */
0285 static const struct dpfe_api dpfe_api_v3 = {
0286     .version = 3,
0287     .fw_name = NULL, /* We expect the firmware to have been downloaded! */
0288     .sysfs_attrs = dpfe_v3_groups,
0289     .command = {
0290         [DPFE_CMD_GET_INFO] = {
0291             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0292             [MSG_COMMAND] = 0x0101,
0293             [MSG_ARG_COUNT] = 1,
0294             [MSG_ARG0] = 1,
0295         },
0296         [DPFE_CMD_GET_REFRESH] = {
0297             [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
0298             [MSG_COMMAND] = 0x0202,
0299             [MSG_ARG_COUNT] = 0,
0300         },
0301         /* There's no GET_VENDOR command in API v3. */
0302     },
0303 };
0304 
0305 static const char *get_error_text(unsigned int i)
0306 {
0307     static const char * const error_text[] = {
0308         "Success", "Header code incorrect",
0309         "Unknown command or argument", "Incorrect checksum",
0310         "Malformed command", "Timed out", "Unknown error",
0311     };
0312 
0313     if (unlikely(i >= ARRAY_SIZE(error_text)))
0314         i = ARRAY_SIZE(error_text) - 1;
0315 
0316     return error_text[i];
0317 }
0318 
0319 static bool is_dcpu_enabled(struct brcmstb_dpfe_priv *priv)
0320 {
0321     u32 val;
0322 
0323     mutex_lock(&priv->lock);
0324     val = readl_relaxed(priv->regs + REG_DCPU_RESET);
0325     mutex_unlock(&priv->lock);
0326 
0327     return !(val & DCPU_RESET_MASK);
0328 }
0329 
0330 static void __disable_dcpu(struct brcmstb_dpfe_priv *priv)
0331 {
0332     u32 val;
0333 
0334     if (!is_dcpu_enabled(priv))
0335         return;
0336 
0337     mutex_lock(&priv->lock);
0338 
0339     /* Put DCPU in reset if it's running. */
0340     val = readl_relaxed(priv->regs + REG_DCPU_RESET);
0341     val |= (1 << DCPU_RESET_SHIFT);
0342     writel_relaxed(val, priv->regs + REG_DCPU_RESET);
0343 
0344     mutex_unlock(&priv->lock);
0345 }
0346 
0347 static void __enable_dcpu(struct brcmstb_dpfe_priv *priv)
0348 {
0349     void __iomem *regs = priv->regs;
0350     u32 val;
0351 
0352     mutex_lock(&priv->lock);
0353 
0354     /* Clear mailbox registers. */
0355     writel_relaxed(0, regs + REG_TO_DCPU_MBOX);
0356     writel_relaxed(0, regs + REG_TO_HOST_MBOX);
0357 
0358     /* Disable DCPU clock gating */
0359     val = readl_relaxed(regs + REG_DCPU_RESET);
0360     val &= ~(1 << DCPU_CLK_DISABLE_SHIFT);
0361     writel_relaxed(val, regs + REG_DCPU_RESET);
0362 
0363     /* Take DCPU out of reset */
0364     val = readl_relaxed(regs + REG_DCPU_RESET);
0365     val &= ~(1 << DCPU_RESET_SHIFT);
0366     writel_relaxed(val, regs + REG_DCPU_RESET);
0367 
0368     mutex_unlock(&priv->lock);
0369 }
0370 
0371 static unsigned int get_msg_chksum(const u32 msg[], unsigned int max)
0372 {
0373     unsigned int sum = 0;
0374     unsigned int i;
0375 
0376     /* Don't include the last field in the checksum. */
0377     for (i = 0; i < max; i++)
0378         sum += msg[i];
0379 
0380     return sum;
0381 }
0382 
0383 static void __iomem *get_msg_ptr(struct brcmstb_dpfe_priv *priv, u32 response,
0384                  char *buf, ssize_t *size)
0385 {
0386     unsigned int msg_type;
0387     unsigned int offset;
0388     void __iomem *ptr = NULL;
0389 
0390     /* There is no need to use this function for API v3 or later. */
0391     if (unlikely(priv->dpfe_api->version >= 3))
0392         return NULL;
0393 
0394     msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
0395     offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
0396 
0397     /*
0398      * msg_type == 1: the offset is relative to the message RAM
0399      * msg_type == 0: the offset is relative to the data RAM (this is the
0400      *                previous way of passing data)
0401      * msg_type is anything else: there's critical hardware problem
0402      */
0403     switch (msg_type) {
0404     case 1:
0405         ptr = priv->regs + DCPU_MSG_RAM_START + offset;
0406         break;
0407     case 0:
0408         ptr = priv->dmem + offset;
0409         break;
0410     default:
0411         dev_emerg(priv->dev, "invalid message reply from DCPU: %#x\n",
0412             response);
0413         if (buf && size)
0414             *size = sprintf(buf,
0415                 "FATAL: communication error with DCPU\n");
0416     }
0417 
0418     return ptr;
0419 }
0420 
0421 static void __finalize_command(struct brcmstb_dpfe_priv *priv)
0422 {
0423     unsigned int release_mbox;
0424 
0425     /*
0426      * It depends on the API version which MBOX register we have to write to
0427      * signal we are done.
0428      */
0429     release_mbox = (priv->dpfe_api->version < 2)
0430             ? REG_TO_HOST_MBOX : REG_TO_DCPU_MBOX;
0431     writel_relaxed(0, priv->regs + release_mbox);
0432 }
0433 
0434 static int __send_command(struct brcmstb_dpfe_priv *priv, unsigned int cmd,
0435               u32 result[])
0436 {
0437     const u32 *msg = priv->dpfe_api->command[cmd];
0438     void __iomem *regs = priv->regs;
0439     unsigned int i, chksum, chksum_idx;
0440     int ret = 0;
0441     u32 resp;
0442 
0443     if (cmd >= DPFE_CMD_MAX)
0444         return -1;
0445 
0446     mutex_lock(&priv->lock);
0447 
0448     /* Wait for DCPU to become ready */
0449     for (i = 0; i < DELAY_LOOP_MAX; i++) {
0450         resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
0451         if (resp == 0)
0452             break;
0453         msleep(1);
0454     }
0455     if (resp != 0) {
0456         mutex_unlock(&priv->lock);
0457         return -ffs(DCPU_RET_ERR_TIMEDOUT);
0458     }
0459 
0460     /* Compute checksum over the message */
0461     chksum_idx = msg[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
0462     chksum = get_msg_chksum(msg, chksum_idx);
0463 
0464     /* Write command and arguments to message area */
0465     for (i = 0; i < MSG_FIELD_MAX; i++) {
0466         if (i == chksum_idx)
0467             writel_relaxed(chksum, regs + DCPU_MSG_RAM(i));
0468         else
0469             writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i));
0470     }
0471 
0472     /* Tell DCPU there is a command waiting */
0473     writel_relaxed(1, regs + REG_TO_DCPU_MBOX);
0474 
0475     /* Wait for DCPU to process the command */
0476     for (i = 0; i < DELAY_LOOP_MAX; i++) {
0477         /* Read response code */
0478         resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
0479         if (resp > 0)
0480             break;
0481         msleep(1);
0482     }
0483 
0484     if (i == DELAY_LOOP_MAX) {
0485         resp = (DCPU_RET_ERR_TIMEDOUT & ~DCPU_RET_ERROR_BIT);
0486         ret = -ffs(resp);
0487     } else {
0488         /* Read response data */
0489         for (i = 0; i < MSG_FIELD_MAX; i++)
0490             result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i));
0491         chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1;
0492     }
0493 
0494     /* Tell DCPU we are done */
0495     __finalize_command(priv);
0496 
0497     mutex_unlock(&priv->lock);
0498 
0499     if (ret)
0500         return ret;
0501 
0502     /* Verify response */
0503     chksum = get_msg_chksum(result, chksum_idx);
0504     if (chksum != result[chksum_idx])
0505         resp = DCPU_RET_ERR_CHKSUM;
0506 
0507     if (resp != DCPU_RET_SUCCESS) {
0508         resp &= ~DCPU_RET_ERROR_BIT;
0509         ret = -ffs(resp);
0510     }
0511 
0512     return ret;
0513 }
0514 
0515 /* Ensure that the firmware file loaded meets all the requirements. */
0516 static int __verify_firmware(struct init_data *init,
0517                  const struct firmware *fw)
0518 {
0519     const struct dpfe_firmware_header *header = (void *)fw->data;
0520     unsigned int dmem_size, imem_size, total_size;
0521     bool is_big_endian = false;
0522     const u32 *chksum_ptr;
0523 
0524     if (header->magic == DPFE_BE_MAGIC)
0525         is_big_endian = true;
0526     else if (header->magic != DPFE_LE_MAGIC)
0527         return ERR_INVALID_MAGIC;
0528 
0529     if (is_big_endian) {
0530         dmem_size = be32_to_cpu(header->dmem_size);
0531         imem_size = be32_to_cpu(header->imem_size);
0532     } else {
0533         dmem_size = le32_to_cpu(header->dmem_size);
0534         imem_size = le32_to_cpu(header->imem_size);
0535     }
0536 
0537     /* Data and instruction sections are 32 bit words. */
0538     if ((dmem_size % sizeof(u32)) != 0 || (imem_size % sizeof(u32)) != 0)
0539         return ERR_INVALID_SIZE;
0540 
0541     /*
0542      * The header + the data section + the instruction section + the
0543      * checksum must be equal to the total firmware size.
0544      */
0545     total_size = dmem_size + imem_size + sizeof(*header) +
0546         sizeof(*chksum_ptr);
0547     if (total_size != fw->size)
0548         return ERR_INVALID_SIZE;
0549 
0550     /* The checksum comes at the very end. */
0551     chksum_ptr = (void *)fw->data + sizeof(*header) + dmem_size + imem_size;
0552 
0553     init->is_big_endian = is_big_endian;
0554     init->dmem_len = dmem_size;
0555     init->imem_len = imem_size;
0556     init->chksum = (is_big_endian)
0557         ? be32_to_cpu(*chksum_ptr) : le32_to_cpu(*chksum_ptr);
0558 
0559     return 0;
0560 }
0561 
0562 /* Verify checksum by reading back the firmware from co-processor RAM. */
0563 static int __verify_fw_checksum(struct init_data *init,
0564                 struct brcmstb_dpfe_priv *priv,
0565                 const struct dpfe_firmware_header *header,
0566                 u32 checksum)
0567 {
0568     u32 magic, sequence, version, sum;
0569     u32 __iomem *dmem = priv->dmem;
0570     u32 __iomem *imem = priv->imem;
0571     unsigned int i;
0572 
0573     if (init->is_big_endian) {
0574         magic = be32_to_cpu(header->magic);
0575         sequence = be32_to_cpu(header->sequence);
0576         version = be32_to_cpu(header->version);
0577     } else {
0578         magic = le32_to_cpu(header->magic);
0579         sequence = le32_to_cpu(header->sequence);
0580         version = le32_to_cpu(header->version);
0581     }
0582 
0583     sum = magic + sequence + version + init->dmem_len + init->imem_len;
0584 
0585     for (i = 0; i < init->dmem_len / sizeof(u32); i++)
0586         sum += readl_relaxed(dmem + i);
0587 
0588     for (i = 0; i < init->imem_len / sizeof(u32); i++)
0589         sum += readl_relaxed(imem + i);
0590 
0591     return (sum == checksum) ? 0 : -1;
0592 }
0593 
0594 static int __write_firmware(u32 __iomem *mem, const u32 *fw,
0595                 unsigned int size, bool is_big_endian)
0596 {
0597     unsigned int i;
0598 
0599     /* Convert size to 32-bit words. */
0600     size /= sizeof(u32);
0601 
0602     /* It is recommended to clear the firmware area first. */
0603     for (i = 0; i < size; i++)
0604         writel_relaxed(0, mem + i);
0605 
0606     /* Now copy it. */
0607     if (is_big_endian) {
0608         for (i = 0; i < size; i++)
0609             writel_relaxed(be32_to_cpu(fw[i]), mem + i);
0610     } else {
0611         for (i = 0; i < size; i++)
0612             writel_relaxed(le32_to_cpu(fw[i]), mem + i);
0613     }
0614 
0615     return 0;
0616 }
0617 
0618 static int brcmstb_dpfe_download_firmware(struct brcmstb_dpfe_priv *priv)
0619 {
0620     const struct dpfe_firmware_header *header;
0621     unsigned int dmem_size, imem_size;
0622     struct device *dev = priv->dev;
0623     bool is_big_endian = false;
0624     const struct firmware *fw;
0625     const u32 *dmem, *imem;
0626     struct init_data init;
0627     const void *fw_blob;
0628     int ret;
0629 
0630     /*
0631      * Skip downloading the firmware if the DCPU is already running and
0632      * responding to commands.
0633      */
0634     if (is_dcpu_enabled(priv)) {
0635         u32 response[MSG_FIELD_MAX];
0636 
0637         ret = __send_command(priv, DPFE_CMD_GET_INFO, response);
0638         if (!ret)
0639             return 0;
0640     }
0641 
0642     /*
0643      * If the firmware filename is NULL it means the boot firmware has to
0644      * download the DCPU firmware for us. If that didn't work, we have to
0645      * bail, since downloading it ourselves wouldn't work either.
0646      */
0647     if (!priv->dpfe_api->fw_name)
0648         return -ENODEV;
0649 
0650     ret = firmware_request_nowarn(&fw, priv->dpfe_api->fw_name, dev);
0651     /*
0652      * Defer the firmware download if the firmware file couldn't be found.
0653      * The root file system may not be available yet.
0654      */
0655     if (ret)
0656         return (ret == -ENOENT) ? -EPROBE_DEFER : ret;
0657 
0658     ret = __verify_firmware(&init, fw);
0659     if (ret) {
0660         ret = -EFAULT;
0661         goto release_fw;
0662     }
0663 
0664     __disable_dcpu(priv);
0665 
0666     is_big_endian = init.is_big_endian;
0667     dmem_size = init.dmem_len;
0668     imem_size = init.imem_len;
0669 
0670     /* At the beginning of the firmware blob is a header. */
0671     header = (struct dpfe_firmware_header *)fw->data;
0672     /* Void pointer to the beginning of the actual firmware. */
0673     fw_blob = fw->data + sizeof(*header);
0674     /* IMEM comes right after the header. */
0675     imem = fw_blob;
0676     /* DMEM follows after IMEM. */
0677     dmem = fw_blob + imem_size;
0678 
0679     ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian);
0680     if (ret)
0681         goto release_fw;
0682     ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian);
0683     if (ret)
0684         goto release_fw;
0685 
0686     ret = __verify_fw_checksum(&init, priv, header, init.chksum);
0687     if (ret)
0688         goto release_fw;
0689 
0690     __enable_dcpu(priv);
0691 
0692 release_fw:
0693     release_firmware(fw);
0694     return ret;
0695 }
0696 
0697 static ssize_t generic_show(unsigned int command, u32 response[],
0698                 struct brcmstb_dpfe_priv *priv, char *buf)
0699 {
0700     int ret;
0701 
0702     if (!priv)
0703         return sprintf(buf, "ERROR: driver private data not set\n");
0704 
0705     ret = __send_command(priv, command, response);
0706     if (ret < 0)
0707         return sprintf(buf, "ERROR: %s\n", get_error_text(-ret));
0708 
0709     return 0;
0710 }
0711 
0712 static ssize_t show_info(struct device *dev, struct device_attribute *devattr,
0713              char *buf)
0714 {
0715     u32 response[MSG_FIELD_MAX];
0716     struct brcmstb_dpfe_priv *priv;
0717     unsigned int info;
0718     ssize_t ret;
0719 
0720     priv = dev_get_drvdata(dev);
0721     ret = generic_show(DPFE_CMD_GET_INFO, response, priv, buf);
0722     if (ret)
0723         return ret;
0724 
0725     info = response[MSG_ARG0];
0726 
0727     return sprintf(buf, "%u.%u.%u.%u\n",
0728                (info >> 24) & 0xff,
0729                (info >> 16) & 0xff,
0730                (info >> 8) & 0xff,
0731                info & 0xff);
0732 }
0733 
0734 static ssize_t show_refresh(struct device *dev,
0735                 struct device_attribute *devattr, char *buf)
0736 {
0737     u32 response[MSG_FIELD_MAX];
0738     void __iomem *info;
0739     struct brcmstb_dpfe_priv *priv;
0740     u8 refresh, sr_abort, ppre, thermal_offs, tuf;
0741     u32 mr4;
0742     ssize_t ret;
0743 
0744     priv = dev_get_drvdata(dev);
0745     ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
0746     if (ret)
0747         return ret;
0748 
0749     info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
0750     if (!info)
0751         return ret;
0752 
0753     mr4 = (readl_relaxed(info + DRAM_INFO_MR4) >> DRAM_INFO_MR4_SHIFT) &
0754            DRAM_INFO_MR4_MASK;
0755 
0756     refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK;
0757     sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK;
0758     ppre = (mr4 >> DRAM_MR4_PPRE) & DRAM_MR4_PPRE_MASK;
0759     thermal_offs = (mr4 >> DRAM_MR4_TH_OFFS) & DRAM_MR4_TH_OFFS_MASK;
0760     tuf = (mr4 >> DRAM_MR4_TUF) & DRAM_MR4_TUF_MASK;
0761 
0762     return sprintf(buf, "%#x %#x %#x %#x %#x %#x %#x\n",
0763                readl_relaxed(info + DRAM_INFO_INTERVAL),
0764                refresh, sr_abort, ppre, thermal_offs, tuf,
0765                readl_relaxed(info + DRAM_INFO_ERROR));
0766 }
0767 
0768 static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
0769               const char *buf, size_t count)
0770 {
0771     u32 response[MSG_FIELD_MAX];
0772     struct brcmstb_dpfe_priv *priv;
0773     void __iomem *info;
0774     unsigned long val;
0775     int ret;
0776 
0777     if (kstrtoul(buf, 0, &val) < 0)
0778         return -EINVAL;
0779 
0780     priv = dev_get_drvdata(dev);
0781     ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response);
0782     if (ret)
0783         return ret;
0784 
0785     info = get_msg_ptr(priv, response[MSG_ARG0], NULL, NULL);
0786     if (!info)
0787         return -EIO;
0788 
0789     writel_relaxed(val, info + DRAM_INFO_INTERVAL);
0790 
0791     return count;
0792 }
0793 
0794 static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr,
0795                char *buf)
0796 {
0797     u32 response[MSG_FIELD_MAX];
0798     struct brcmstb_dpfe_priv *priv;
0799     void __iomem *info;
0800     ssize_t ret;
0801     u32 mr5, mr6, mr7, mr8, err;
0802 
0803     priv = dev_get_drvdata(dev);
0804     ret = generic_show(DPFE_CMD_GET_VENDOR, response, priv, buf);
0805     if (ret)
0806         return ret;
0807 
0808     info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
0809     if (!info)
0810         return ret;
0811 
0812     mr5 = (readl_relaxed(info + DRAM_VENDOR_MR5) >> DRAM_VENDOR_SHIFT) &
0813         DRAM_VENDOR_MASK;
0814     mr6 = (readl_relaxed(info + DRAM_VENDOR_MR6) >> DRAM_VENDOR_SHIFT) &
0815         DRAM_VENDOR_MASK;
0816     mr7 = (readl_relaxed(info + DRAM_VENDOR_MR7) >> DRAM_VENDOR_SHIFT) &
0817         DRAM_VENDOR_MASK;
0818     mr8 = (readl_relaxed(info + DRAM_VENDOR_MR8) >> DRAM_VENDOR_SHIFT) &
0819         DRAM_VENDOR_MASK;
0820     err = readl_relaxed(info + DRAM_VENDOR_ERROR) & DRAM_VENDOR_MASK;
0821 
0822     return sprintf(buf, "%#x %#x %#x %#x %#x\n", mr5, mr6, mr7, mr8, err);
0823 }
0824 
0825 static ssize_t show_dram(struct device *dev, struct device_attribute *devattr,
0826              char *buf)
0827 {
0828     u32 response[MSG_FIELD_MAX];
0829     struct brcmstb_dpfe_priv *priv;
0830     ssize_t ret;
0831     u32 mr4, mr5, mr6, mr7, mr8, err;
0832 
0833     priv = dev_get_drvdata(dev);
0834     ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf);
0835     if (ret)
0836         return ret;
0837 
0838     mr4 = response[MSG_ARG0 + 0] & DRAM_INFO_MR4_MASK;
0839     mr5 = response[MSG_ARG0 + 1] & DRAM_DDR_INFO_MASK;
0840     mr6 = response[MSG_ARG0 + 2] & DRAM_DDR_INFO_MASK;
0841     mr7 = response[MSG_ARG0 + 3] & DRAM_DDR_INFO_MASK;
0842     mr8 = response[MSG_ARG0 + 4] & DRAM_DDR_INFO_MASK;
0843     err = response[MSG_ARG0 + 5] & DRAM_DDR_INFO_MASK;
0844 
0845     return sprintf(buf, "%#x %#x %#x %#x %#x %#x\n", mr4, mr5, mr6, mr7,
0846             mr8, err);
0847 }
0848 
0849 static int brcmstb_dpfe_resume(struct platform_device *pdev)
0850 {
0851     struct brcmstb_dpfe_priv *priv = platform_get_drvdata(pdev);
0852 
0853     return brcmstb_dpfe_download_firmware(priv);
0854 }
0855 
0856 static int brcmstb_dpfe_probe(struct platform_device *pdev)
0857 {
0858     struct device *dev = &pdev->dev;
0859     struct brcmstb_dpfe_priv *priv;
0860     int ret;
0861 
0862     priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0863     if (!priv)
0864         return -ENOMEM;
0865 
0866     priv->dev = dev;
0867 
0868     mutex_init(&priv->lock);
0869     platform_set_drvdata(pdev, priv);
0870 
0871     priv->regs = devm_platform_ioremap_resource_byname(pdev, "dpfe-cpu");
0872     if (IS_ERR(priv->regs)) {
0873         dev_err(dev, "couldn't map DCPU registers\n");
0874         return -ENODEV;
0875     }
0876 
0877     priv->dmem = devm_platform_ioremap_resource_byname(pdev, "dpfe-dmem");
0878     if (IS_ERR(priv->dmem)) {
0879         dev_err(dev, "Couldn't map DCPU data memory\n");
0880         return -ENOENT;
0881     }
0882 
0883     priv->imem = devm_platform_ioremap_resource_byname(pdev, "dpfe-imem");
0884     if (IS_ERR(priv->imem)) {
0885         dev_err(dev, "Couldn't map DCPU instruction memory\n");
0886         return -ENOENT;
0887     }
0888 
0889     priv->dpfe_api = of_device_get_match_data(dev);
0890     if (unlikely(!priv->dpfe_api)) {
0891         /*
0892          * It should be impossible to end up here, but to be safe we
0893          * check anyway.
0894          */
0895         dev_err(dev, "Couldn't determine API\n");
0896         return -ENOENT;
0897     }
0898 
0899     ret = brcmstb_dpfe_download_firmware(priv);
0900     if (ret)
0901         return dev_err_probe(dev, ret, "Couldn't download firmware\n");
0902 
0903     ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
0904     if (!ret)
0905         dev_info(dev, "registered with API v%d.\n",
0906              priv->dpfe_api->version);
0907 
0908     return ret;
0909 }
0910 
0911 static int brcmstb_dpfe_remove(struct platform_device *pdev)
0912 {
0913     struct brcmstb_dpfe_priv *priv = dev_get_drvdata(&pdev->dev);
0914 
0915     sysfs_remove_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs);
0916 
0917     return 0;
0918 }
0919 
0920 static const struct of_device_id brcmstb_dpfe_of_match[] = {
0921     /* Use legacy API v2 for a select number of chips */
0922     { .compatible = "brcm,bcm7268-dpfe-cpu", .data = &dpfe_api_old_v2 },
0923     { .compatible = "brcm,bcm7271-dpfe-cpu", .data = &dpfe_api_old_v2 },
0924     { .compatible = "brcm,bcm7278-dpfe-cpu", .data = &dpfe_api_old_v2 },
0925     { .compatible = "brcm,bcm7211-dpfe-cpu", .data = &dpfe_api_new_v2 },
0926     /* API v3 is the default going forward */
0927     { .compatible = "brcm,dpfe-cpu", .data = &dpfe_api_v3 },
0928     {}
0929 };
0930 MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match);
0931 
0932 static struct platform_driver brcmstb_dpfe_driver = {
0933     .driver = {
0934         .name = DRVNAME,
0935         .of_match_table = brcmstb_dpfe_of_match,
0936     },
0937     .probe = brcmstb_dpfe_probe,
0938     .remove = brcmstb_dpfe_remove,
0939     .resume = brcmstb_dpfe_resume,
0940 };
0941 
0942 module_platform_driver(brcmstb_dpfe_driver);
0943 
0944 MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
0945 MODULE_DESCRIPTION("BRCMSTB DDR PHY Front End Driver");
0946 MODULE_LICENSE("GPL");