[PATCH v14 7/9] fw_cfg: add DMA register

2018-02-14 Thread Marc-André Lureau
Add an optional  kernel module (or command line) parameter
using the following syntax:

  [qemu_fw_cfg.]ioport=@[::[:]]
 or
  [qemu_fw_cfg.]mmio=@[::[:]]

and initializes the register address using given or default offset.

Signed-off-by: Marc-André Lureau 
Reviewed-by: Gabriel Somlo 
---
 drivers/firmware/qemu_fw_cfg.c | 53 --
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index c4c726841ba7..37638b95cb45 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -10,20 +10,21 @@
  * and select subsets of aarch64), a Device Tree node (on arm), or using
  * a kernel module (or command line) parameter with the following syntax:
  *
- *  [qemu_fw_cfg.]ioport=@[::]
+ *  [qemu_fw_cfg.]ioport=@[::[:]]
  * or
- *  [qemu_fw_cfg.]mmio=@[::]
+ *  [qemu_fw_cfg.]mmio=@[::[:]]
  *
  * where:
  *   := size of ioport or mmio range
  *   := physical base address of ioport or mmio range
  *   := (optional) offset of control register
  *   := (optional) offset of data register
+ *   := (optional) offset of dma register
  *
  * e.g.:
- *  qemu_fw_cfg.ioport=2@0x510:0:1 (the default on x86)
+ *  qemu_fw_cfg.ioport=12@0x510:0:1:4  (the default on x86)
  * or
- *  qemu_fw_cfg.mmio=0xA@0x902:8:0 (the default on arm)
+ *  qemu_fw_cfg.mmio=16@0x902:8:0:16   (the default on arm)
  */
 
 #include 
@@ -45,6 +46,7 @@ static resource_size_t fw_cfg_p_size;
 static void __iomem *fw_cfg_dev_base;
 static void __iomem *fw_cfg_reg_ctrl;
 static void __iomem *fw_cfg_reg_data;
+static void __iomem *fw_cfg_reg_dma;
 
 /* atomic access to fw_cfg device (potentially slow i/o, so using mutex) */
 static DEFINE_MUTEX(fw_cfg_dev_lock);
@@ -102,12 +104,14 @@ static void fw_cfg_io_cleanup(void)
 # if (defined(CONFIG_ARM) || defined(CONFIG_ARM64))
 #  define FW_CFG_CTRL_OFF 0x08
 #  define FW_CFG_DATA_OFF 0x00
+#  define FW_CFG_DMA_OFF 0x10
 # elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m 
*/
 #  define FW_CFG_CTRL_OFF 0x00
 #  define FW_CFG_DATA_OFF 0x02
 # elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64)) /* x86, sun4u */
 #  define FW_CFG_CTRL_OFF 0x00
 #  define FW_CFG_DATA_OFF 0x01
+#  define FW_CFG_DMA_OFF 0x04
 # else
 #  error "QEMU FW_CFG not available on this architecture!"
 # endif
@@ -117,7 +121,7 @@ static void fw_cfg_io_cleanup(void)
 static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 {
char sig[FW_CFG_SIG_SIZE];
-   struct resource *range, *ctrl, *data;
+   struct resource *range, *ctrl, *data, *dma;
 
/* acquire i/o range details */
fw_cfg_is_mmio = false;
@@ -154,6 +158,7 @@ static int fw_cfg_do_platform_probe(struct platform_device 
*pdev)
/* were custom register offsets provided (e.g. on the command line)? */
ctrl = platform_get_resource_byname(pdev, IORESOURCE_REG, "ctrl");
data = platform_get_resource_byname(pdev, IORESOURCE_REG, "data");
+   dma = platform_get_resource_byname(pdev, IORESOURCE_REG, "dma");
if (ctrl && data) {
fw_cfg_reg_ctrl = fw_cfg_dev_base + ctrl->start;
fw_cfg_reg_data = fw_cfg_dev_base + data->start;
@@ -163,6 +168,13 @@ static int fw_cfg_do_platform_probe(struct platform_device 
*pdev)
fw_cfg_reg_data = fw_cfg_dev_base + FW_CFG_DATA_OFF;
}
 
+   if (dma)
+   fw_cfg_reg_dma = fw_cfg_dev_base + dma->start;
+#ifdef FW_CFG_DMA_OFF
+   else
+   fw_cfg_reg_dma = fw_cfg_dev_base + FW_CFG_DMA_OFF;
+#endif
+
/* verify fw_cfg device signature */
fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE);
if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {
@@ -617,6 +629,7 @@ static struct platform_device *fw_cfg_cmdline_dev;
 /* use special scanf/printf modifier for phys_addr_t, resource_size_t */
 #define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \
 ":%" __PHYS_ADDR_PREFIX "i" \
+":%" __PHYS_ADDR_PREFIX "i%n" \
 ":%" __PHYS_ADDR_PREFIX "i%n"
 
 #define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \
@@ -626,12 +639,15 @@ static struct platform_device *fw_cfg_cmdline_dev;
 ":%" __PHYS_ADDR_PREFIX "u" \
 ":%" __PHYS_ADDR_PREFIX "u"
 
+#define PH_ADDR_PR_4_FMT PH_ADDR_PR_3_FMT \
+":%" __PHYS_ADDR_PREFIX "u"
+
 static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
 {
-   struct resource res[3] = {};
+   struct resource res[4] = {};
char *str;
phys_addr_t base;
-   resource_size_t size, ctrl_off, data_off;
+   resource_size_t size, ctrl_off, data_off, dma_off;
int processed, consumed = 0;
 
/* only 

[PATCH v14 7/9] fw_cfg: add DMA register

2018-02-14 Thread Marc-André Lureau
Add an optional  kernel module (or command line) parameter
using the following syntax:

  [qemu_fw_cfg.]ioport=@[::[:]]
 or
  [qemu_fw_cfg.]mmio=@[::[:]]

and initializes the register address using given or default offset.

Signed-off-by: Marc-André Lureau 
Reviewed-by: Gabriel Somlo 
---
 drivers/firmware/qemu_fw_cfg.c | 53 --
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index c4c726841ba7..37638b95cb45 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -10,20 +10,21 @@
  * and select subsets of aarch64), a Device Tree node (on arm), or using
  * a kernel module (or command line) parameter with the following syntax:
  *
- *  [qemu_fw_cfg.]ioport=@[::]
+ *  [qemu_fw_cfg.]ioport=@[::[:]]
  * or
- *  [qemu_fw_cfg.]mmio=@[::]
+ *  [qemu_fw_cfg.]mmio=@[::[:]]
  *
  * where:
  *   := size of ioport or mmio range
  *   := physical base address of ioport or mmio range
  *   := (optional) offset of control register
  *   := (optional) offset of data register
+ *   := (optional) offset of dma register
  *
  * e.g.:
- *  qemu_fw_cfg.ioport=2@0x510:0:1 (the default on x86)
+ *  qemu_fw_cfg.ioport=12@0x510:0:1:4  (the default on x86)
  * or
- *  qemu_fw_cfg.mmio=0xA@0x902:8:0 (the default on arm)
+ *  qemu_fw_cfg.mmio=16@0x902:8:0:16   (the default on arm)
  */
 
 #include 
@@ -45,6 +46,7 @@ static resource_size_t fw_cfg_p_size;
 static void __iomem *fw_cfg_dev_base;
 static void __iomem *fw_cfg_reg_ctrl;
 static void __iomem *fw_cfg_reg_data;
+static void __iomem *fw_cfg_reg_dma;
 
 /* atomic access to fw_cfg device (potentially slow i/o, so using mutex) */
 static DEFINE_MUTEX(fw_cfg_dev_lock);
@@ -102,12 +104,14 @@ static void fw_cfg_io_cleanup(void)
 # if (defined(CONFIG_ARM) || defined(CONFIG_ARM64))
 #  define FW_CFG_CTRL_OFF 0x08
 #  define FW_CFG_DATA_OFF 0x00
+#  define FW_CFG_DMA_OFF 0x10
 # elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m 
*/
 #  define FW_CFG_CTRL_OFF 0x00
 #  define FW_CFG_DATA_OFF 0x02
 # elif (defined(CONFIG_X86) || defined(CONFIG_SPARC64)) /* x86, sun4u */
 #  define FW_CFG_CTRL_OFF 0x00
 #  define FW_CFG_DATA_OFF 0x01
+#  define FW_CFG_DMA_OFF 0x04
 # else
 #  error "QEMU FW_CFG not available on this architecture!"
 # endif
@@ -117,7 +121,7 @@ static void fw_cfg_io_cleanup(void)
 static int fw_cfg_do_platform_probe(struct platform_device *pdev)
 {
char sig[FW_CFG_SIG_SIZE];
-   struct resource *range, *ctrl, *data;
+   struct resource *range, *ctrl, *data, *dma;
 
/* acquire i/o range details */
fw_cfg_is_mmio = false;
@@ -154,6 +158,7 @@ static int fw_cfg_do_platform_probe(struct platform_device 
*pdev)
/* were custom register offsets provided (e.g. on the command line)? */
ctrl = platform_get_resource_byname(pdev, IORESOURCE_REG, "ctrl");
data = platform_get_resource_byname(pdev, IORESOURCE_REG, "data");
+   dma = platform_get_resource_byname(pdev, IORESOURCE_REG, "dma");
if (ctrl && data) {
fw_cfg_reg_ctrl = fw_cfg_dev_base + ctrl->start;
fw_cfg_reg_data = fw_cfg_dev_base + data->start;
@@ -163,6 +168,13 @@ static int fw_cfg_do_platform_probe(struct platform_device 
*pdev)
fw_cfg_reg_data = fw_cfg_dev_base + FW_CFG_DATA_OFF;
}
 
+   if (dma)
+   fw_cfg_reg_dma = fw_cfg_dev_base + dma->start;
+#ifdef FW_CFG_DMA_OFF
+   else
+   fw_cfg_reg_dma = fw_cfg_dev_base + FW_CFG_DMA_OFF;
+#endif
+
/* verify fw_cfg device signature */
fw_cfg_read_blob(FW_CFG_SIGNATURE, sig, 0, FW_CFG_SIG_SIZE);
if (memcmp(sig, "QEMU", FW_CFG_SIG_SIZE) != 0) {
@@ -617,6 +629,7 @@ static struct platform_device *fw_cfg_cmdline_dev;
 /* use special scanf/printf modifier for phys_addr_t, resource_size_t */
 #define PH_ADDR_SCAN_FMT "@%" __PHYS_ADDR_PREFIX "i%n" \
 ":%" __PHYS_ADDR_PREFIX "i" \
+":%" __PHYS_ADDR_PREFIX "i%n" \
 ":%" __PHYS_ADDR_PREFIX "i%n"
 
 #define PH_ADDR_PR_1_FMT "0x%" __PHYS_ADDR_PREFIX "x@" \
@@ -626,12 +639,15 @@ static struct platform_device *fw_cfg_cmdline_dev;
 ":%" __PHYS_ADDR_PREFIX "u" \
 ":%" __PHYS_ADDR_PREFIX "u"
 
+#define PH_ADDR_PR_4_FMT PH_ADDR_PR_3_FMT \
+":%" __PHYS_ADDR_PREFIX "u"
+
 static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
 {
-   struct resource res[3] = {};
+   struct resource res[4] = {};
char *str;
phys_addr_t base;
-   resource_size_t size, ctrl_off, data_off;
+   resource_size_t size, ctrl_off, data_off, dma_off;
int processed, consumed = 0;
 
/* only one fw_cfg device can exist system-wide, so if