qfw_pio.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * PIO interface for QFW
  4. *
  5. * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
  6. * (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
  7. */
  8. #define LOG_CATEGORY UCLASS_QFW
  9. #include <asm/io.h>
  10. #include <dm/device.h>
  11. #include <qfw.h>
  12. /*
  13. * PIO ports are correct for x86, which appears to be the only arch that uses
  14. * PIO.
  15. */
  16. #define FW_CONTROL_PORT 0x510
  17. #define FW_DATA_PORT 0x511
  18. #define FW_DMA_PORT_LOW 0x514
  19. #define FW_DMA_PORT_HIGH 0x518
  20. static void qfw_pio_read_entry_io(struct udevice *dev, u16 entry, u32 size,
  21. void *address)
  22. {
  23. /*
  24. * writing FW_CFG_INVALID will cause read operation to resume at last
  25. * offset, otherwise read will start at offset 0
  26. *
  27. * Note: on platform where the control register is IO port, the
  28. * endianness is little endian.
  29. */
  30. if (entry != FW_CFG_INVALID)
  31. outw(cpu_to_le16(entry), FW_CONTROL_PORT);
  32. /* the endianness of data register is string-preserving */
  33. u32 i = 0;
  34. u8 *data = address;
  35. while (size--)
  36. data[i++] = inb(FW_DATA_PORT);
  37. }
  38. /* Read configuration item using fw_cfg DMA interface */
  39. static void qfw_pio_read_entry_dma(struct udevice *dev, struct qfw_dma *dma)
  40. {
  41. /* the DMA address register is big-endian */
  42. outl(cpu_to_be32((uintptr_t)dma), FW_DMA_PORT_HIGH);
  43. while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR);
  44. }
  45. static int qfw_pio_probe(struct udevice *dev)
  46. {
  47. return qfw_register(dev);
  48. }
  49. static struct dm_qfw_ops qfw_pio_ops = {
  50. .read_entry_io = qfw_pio_read_entry_io,
  51. .read_entry_dma = qfw_pio_read_entry_dma,
  52. };
  53. U_BOOT_DRIVER(qfw_pio) = {
  54. .name = "qfw_pio",
  55. .id = UCLASS_QFW,
  56. .probe = qfw_pio_probe,
  57. .ops = &qfw_pio_ops,
  58. };