0001
0002
0003
0004
0005
0006 #include <linux/platform_device.h>
0007 #include <linux/dma-mapping.h>
0008 #include <linux/firmware.h>
0009 #include <linux/pci_ids.h>
0010 #include <linux/iopoll.h>
0011
0012 #include "falcon.h"
0013 #include "drm.h"
0014
0015 enum falcon_memory {
0016 FALCON_MEMORY_IMEM,
0017 FALCON_MEMORY_DATA,
0018 };
0019
0020 static void falcon_writel(struct falcon *falcon, u32 value, u32 offset)
0021 {
0022 writel(value, falcon->regs + offset);
0023 }
0024
0025 int falcon_wait_idle(struct falcon *falcon)
0026 {
0027 u32 value;
0028
0029 return readl_poll_timeout(falcon->regs + FALCON_IDLESTATE, value,
0030 (value == 0), 10, 100000);
0031 }
0032
0033 static int falcon_dma_wait_idle(struct falcon *falcon)
0034 {
0035 u32 value;
0036
0037 return readl_poll_timeout(falcon->regs + FALCON_DMATRFCMD, value,
0038 (value & FALCON_DMATRFCMD_IDLE), 10, 100000);
0039 }
0040
0041 static int falcon_copy_chunk(struct falcon *falcon,
0042 phys_addr_t base,
0043 unsigned long offset,
0044 enum falcon_memory target)
0045 {
0046 u32 cmd = FALCON_DMATRFCMD_SIZE_256B;
0047
0048 if (target == FALCON_MEMORY_IMEM)
0049 cmd |= FALCON_DMATRFCMD_IMEM;
0050
0051
0052
0053
0054
0055
0056
0057 cmd |= FALCON_DMATRFCMD_DMACTX(1);
0058
0059 falcon_writel(falcon, offset, FALCON_DMATRFMOFFS);
0060 falcon_writel(falcon, base, FALCON_DMATRFFBOFFS);
0061 falcon_writel(falcon, cmd, FALCON_DMATRFCMD);
0062
0063 return falcon_dma_wait_idle(falcon);
0064 }
0065
0066 static void falcon_copy_firmware_image(struct falcon *falcon,
0067 const struct firmware *firmware)
0068 {
0069 u32 *virt = falcon->firmware.virt;
0070 size_t i;
0071
0072
0073 for (i = 0; i < firmware->size / sizeof(u32); i++)
0074 virt[i] = le32_to_cpu(((__le32 *)firmware->data)[i]);
0075 }
0076
0077 static int falcon_parse_firmware_image(struct falcon *falcon)
0078 {
0079 struct falcon_fw_bin_header_v1 *bin = (void *)falcon->firmware.virt;
0080 struct falcon_fw_os_header_v1 *os;
0081
0082
0083 if (bin->magic != PCI_VENDOR_ID_NVIDIA && bin->magic != 0x10fe) {
0084 dev_err(falcon->dev, "incorrect firmware magic\n");
0085 return -EINVAL;
0086 }
0087
0088
0089 if (bin->version != 1) {
0090 dev_err(falcon->dev, "unsupported firmware version\n");
0091 return -EINVAL;
0092 }
0093
0094
0095 if (bin->size > falcon->firmware.size) {
0096 dev_err(falcon->dev, "firmware image size inconsistency\n");
0097 return -EINVAL;
0098 }
0099
0100 os = falcon->firmware.virt + bin->os_header_offset;
0101
0102 falcon->firmware.bin_data.size = bin->os_size;
0103 falcon->firmware.bin_data.offset = bin->os_data_offset;
0104 falcon->firmware.code.offset = os->code_offset;
0105 falcon->firmware.code.size = os->code_size;
0106 falcon->firmware.data.offset = os->data_offset;
0107 falcon->firmware.data.size = os->data_size;
0108
0109 return 0;
0110 }
0111
0112 int falcon_read_firmware(struct falcon *falcon, const char *name)
0113 {
0114 int err;
0115
0116
0117 err = request_firmware(&falcon->firmware.firmware, name, falcon->dev);
0118 if (err < 0)
0119 return err;
0120
0121 falcon->firmware.size = falcon->firmware.firmware->size;
0122
0123 return 0;
0124 }
0125
0126 int falcon_load_firmware(struct falcon *falcon)
0127 {
0128 const struct firmware *firmware = falcon->firmware.firmware;
0129 int err;
0130
0131
0132 falcon_copy_firmware_image(falcon, firmware);
0133
0134
0135 err = falcon_parse_firmware_image(falcon);
0136 if (err < 0) {
0137 dev_err(falcon->dev, "failed to parse firmware image\n");
0138 return err;
0139 }
0140
0141 release_firmware(firmware);
0142 falcon->firmware.firmware = NULL;
0143
0144 return 0;
0145 }
0146
0147 int falcon_init(struct falcon *falcon)
0148 {
0149 falcon->firmware.virt = NULL;
0150
0151 return 0;
0152 }
0153
0154 void falcon_exit(struct falcon *falcon)
0155 {
0156 if (falcon->firmware.firmware)
0157 release_firmware(falcon->firmware.firmware);
0158 }
0159
0160 int falcon_boot(struct falcon *falcon)
0161 {
0162 unsigned long offset;
0163 u32 value;
0164 int err;
0165
0166 if (!falcon->firmware.virt)
0167 return -EINVAL;
0168
0169 err = readl_poll_timeout(falcon->regs + FALCON_DMACTL, value,
0170 (value & (FALCON_DMACTL_IMEM_SCRUBBING |
0171 FALCON_DMACTL_DMEM_SCRUBBING)) == 0,
0172 10, 10000);
0173 if (err < 0)
0174 return err;
0175
0176 falcon_writel(falcon, 0, FALCON_DMACTL);
0177
0178
0179 falcon_writel(falcon, (falcon->firmware.iova +
0180 falcon->firmware.bin_data.offset) >> 8,
0181 FALCON_DMATRFBASE);
0182
0183
0184 for (offset = 0; offset < falcon->firmware.data.size; offset += 256)
0185 falcon_copy_chunk(falcon,
0186 falcon->firmware.data.offset + offset,
0187 offset, FALCON_MEMORY_DATA);
0188
0189
0190 for (offset = 0; offset < falcon->firmware.code.size; offset += 256)
0191 falcon_copy_chunk(falcon, falcon->firmware.code.offset + offset,
0192 offset, FALCON_MEMORY_IMEM);
0193
0194
0195 falcon_writel(falcon, FALCON_IRQMSET_EXT(0xff) |
0196 FALCON_IRQMSET_SWGEN1 |
0197 FALCON_IRQMSET_SWGEN0 |
0198 FALCON_IRQMSET_EXTERR |
0199 FALCON_IRQMSET_HALT |
0200 FALCON_IRQMSET_WDTMR,
0201 FALCON_IRQMSET);
0202 falcon_writel(falcon, FALCON_IRQDEST_EXT(0xff) |
0203 FALCON_IRQDEST_SWGEN1 |
0204 FALCON_IRQDEST_SWGEN0 |
0205 FALCON_IRQDEST_EXTERR |
0206 FALCON_IRQDEST_HALT,
0207 FALCON_IRQDEST);
0208
0209
0210 falcon_writel(falcon, FALCON_ITFEN_MTHDEN |
0211 FALCON_ITFEN_CTXEN,
0212 FALCON_ITFEN);
0213
0214
0215 falcon_writel(falcon, 0x00000000, FALCON_BOOTVEC);
0216 falcon_writel(falcon, FALCON_CPUCTL_STARTCPU, FALCON_CPUCTL);
0217
0218 err = falcon_wait_idle(falcon);
0219 if (err < 0) {
0220 dev_err(falcon->dev, "Falcon boot failed due to timeout\n");
0221 return err;
0222 }
0223
0224 return 0;
0225 }
0226
0227 void falcon_execute_method(struct falcon *falcon, u32 method, u32 data)
0228 {
0229 falcon_writel(falcon, method >> 2, FALCON_UCLASS_METHOD_OFFSET);
0230 falcon_writel(falcon, data, FALCON_UCLASS_METHOD_DATA);
0231 }