ptp_ocp.c (b88fdbba931e9c79772120cb60a6ea8adaf0b451) ptp_ocp.c (3c3673bde50c31d1f5ab0b39e9eeb555285786bb)
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2020 Facebook */
3
4#include <linux/err.h>
5#include <linux/kernel.h>
6#include <linux/module.h>
7#include <linux/debugfs.h>
8#include <linux/init.h>

--- 5 unchanged lines hidden (view full) ---

14#include <linux/platform_data/i2c-xiic.h>
15#include <linux/ptp_clock_kernel.h>
16#include <linux/spi/spi.h>
17#include <linux/spi/xilinx_spi.h>
18#include <net/devlink.h>
19#include <linux/i2c.h>
20#include <linux/mtd/mtd.h>
21#include <linux/nvmem-consumer.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/* Copyright (c) 2020 Facebook */
3
4#include <linux/err.h>
5#include <linux/kernel.h>
6#include <linux/module.h>
7#include <linux/debugfs.h>
8#include <linux/init.h>

--- 5 unchanged lines hidden (view full) ---

14#include <linux/platform_data/i2c-xiic.h>
15#include <linux/ptp_clock_kernel.h>
16#include <linux/spi/spi.h>
17#include <linux/spi/xilinx_spi.h>
18#include <net/devlink.h>
19#include <linux/i2c.h>
20#include <linux/mtd/mtd.h>
21#include <linux/nvmem-consumer.h>
22#include <linux/crc16.h>
22
23#define PCI_VENDOR_ID_FACEBOOK 0x1d9b
24#define PCI_DEVICE_ID_FACEBOOK_TIMECARD 0x0400
25
26#define PCI_VENDOR_ID_CELESTICA 0x18d4
27#define PCI_DEVICE_ID_CELESTICA_TIMECARD 0x1008
28
29static struct class timecard_class = {

--- 178 unchanged lines hidden (view full) ---

208
209struct ptp_ocp_flash_info {
210 const char *name;
211 int pci_offset;
212 int data_size;
213 void *data;
214};
215
23
24#define PCI_VENDOR_ID_FACEBOOK 0x1d9b
25#define PCI_DEVICE_ID_FACEBOOK_TIMECARD 0x0400
26
27#define PCI_VENDOR_ID_CELESTICA 0x18d4
28#define PCI_DEVICE_ID_CELESTICA_TIMECARD 0x1008
29
30static struct class timecard_class = {

--- 178 unchanged lines hidden (view full) ---

209
210struct ptp_ocp_flash_info {
211 const char *name;
212 int pci_offset;
213 int data_size;
214 void *data;
215};
216
217struct ptp_ocp_firmware_header {
218 char magic[4];
219 __be16 pci_vendor_id;
220 __be16 pci_device_id;
221 __be32 image_size;
222 __be16 hw_revision;
223 __be16 crc;
224};
225
226#define OCP_FIRMWARE_MAGIC_HEADER "OCPC"
227
216struct ptp_ocp_i2c_info {
217 const char *name;
218 unsigned long fixed_rate;
219 size_t data_size;
220 void *data;
221};
222
223struct ptp_ocp_ext_info {

--- 1095 unchanged lines hidden (view full) ---

1319 last = dev;
1320 }
1321 put_device(last);
1322
1323 return dev;
1324}
1325
1326static int
228struct ptp_ocp_i2c_info {
229 const char *name;
230 unsigned long fixed_rate;
231 size_t data_size;
232 void *data;
233};
234
235struct ptp_ocp_ext_info {

--- 1095 unchanged lines hidden (view full) ---

1331 last = dev;
1332 }
1333 put_device(last);
1334
1335 return dev;
1336}
1337
1338static int
1339ptp_ocp_devlink_fw_image(struct devlink *devlink, const struct firmware *fw,
1340 const u8 **data, size_t *size)
1341{
1342 struct ptp_ocp *bp = devlink_priv(devlink);
1343 const struct ptp_ocp_firmware_header *hdr;
1344 size_t offset, length;
1345 u16 crc;
1346
1347 hdr = (const struct ptp_ocp_firmware_header *)fw->data;
1348 if (memcmp(hdr->magic, OCP_FIRMWARE_MAGIC_HEADER, 4)) {
1349 devlink_flash_update_status_notify(devlink,
1350 "No firmware header found, flashing raw image",
1351 NULL, 0, 0);
1352 offset = 0;
1353 length = fw->size;
1354 goto out;
1355 }
1356
1357 if (be16_to_cpu(hdr->pci_vendor_id) != bp->pdev->vendor ||
1358 be16_to_cpu(hdr->pci_device_id) != bp->pdev->device) {
1359 devlink_flash_update_status_notify(devlink,
1360 "Firmware image compatibility check failed",
1361 NULL, 0, 0);
1362 return -EINVAL;
1363 }
1364
1365 offset = sizeof(*hdr);
1366 length = be32_to_cpu(hdr->image_size);
1367 if (length != (fw->size - offset)) {
1368 devlink_flash_update_status_notify(devlink,
1369 "Firmware image size check failed",
1370 NULL, 0, 0);
1371 return -EINVAL;
1372 }
1373
1374 crc = crc16(0xffff, &fw->data[offset], length);
1375 if (be16_to_cpu(hdr->crc) != crc) {
1376 devlink_flash_update_status_notify(devlink,
1377 "Firmware image CRC check failed",
1378 NULL, 0, 0);
1379 return -EINVAL;
1380 }
1381
1382out:
1383 *data = &fw->data[offset];
1384 *size = length;
1385
1386 return 0;
1387}
1388
1389static int
1327ptp_ocp_devlink_flash(struct devlink *devlink, struct device *dev,
1328 const struct firmware *fw)
1329{
1330 struct mtd_info *mtd = dev_get_drvdata(dev);
1331 struct ptp_ocp *bp = devlink_priv(devlink);
1390ptp_ocp_devlink_flash(struct devlink *devlink, struct device *dev,
1391 const struct firmware *fw)
1392{
1393 struct mtd_info *mtd = dev_get_drvdata(dev);
1394 struct ptp_ocp *bp = devlink_priv(devlink);
1332 size_t off, len, resid, wrote;
1395 size_t off, len, size, resid, wrote;
1333 struct erase_info erase;
1334 size_t base, blksz;
1396 struct erase_info erase;
1397 size_t base, blksz;
1335 int err = 0;
1398 const u8 *data;
1399 int err;
1336
1400
1401 err = ptp_ocp_devlink_fw_image(devlink, fw, &data, &size);
1402 if (err)
1403 goto out;
1404
1337 off = 0;
1338 base = bp->flash_start;
1339 blksz = 4096;
1405 off = 0;
1406 base = bp->flash_start;
1407 blksz = 4096;
1340 resid = fw->size;
1408 resid = size;
1341
1342 while (resid) {
1343 devlink_flash_update_status_notify(devlink, "Flashing",
1409
1410 while (resid) {
1411 devlink_flash_update_status_notify(devlink, "Flashing",
1344 NULL, off, fw->size);
1412 NULL, off, size);
1345
1346 len = min_t(size_t, resid, blksz);
1347 erase.addr = base + off;
1348 erase.len = blksz;
1349
1350 err = mtd_erase(mtd, &erase);
1351 if (err)
1352 goto out;
1353
1413
1414 len = min_t(size_t, resid, blksz);
1415 erase.addr = base + off;
1416 erase.len = blksz;
1417
1418 err = mtd_erase(mtd, &erase);
1419 if (err)
1420 goto out;
1421
1354 err = mtd_write(mtd, base + off, len, &wrote, &fw->data[off]);
1422 err = mtd_write(mtd, base + off, len, &wrote, data + off);
1355 if (err)
1356 goto out;
1357
1358 off += blksz;
1359 resid -= len;
1360 }
1361out:
1362 return err;

--- 2463 unchanged lines hidden ---
1423 if (err)
1424 goto out;
1425
1426 off += blksz;
1427 resid -= len;
1428 }
1429out:
1430 return err;

--- 2463 unchanged lines hidden ---