Merge tag 'soundwire-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Sep 2019 17:52:23 +0000 (10:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Sep 2019 17:52:23 +0000 (10:52 -0700)
Pull soundwire updates from Vinod Koul:
 "This includes DT support thanks to Srini and more work done by Intel
  (Pierre) on improving cadence and intel support.

  Summary:

   - Add DT bindings and DT support in core

   - Add debugfs support for soundwire properties

   - Improvements on streaming handling to core

   - Improved handling of Cadence module

   - More updates and improvements to Intel driver"

* tag 'soundwire-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: (30 commits)
  soundwire: stream: make stream name a const pointer
  soundwire: Add compute_params callback
  soundwire: core: add device tree support for slave devices
  dt-bindings: soundwire: add slave bindings
  soundwire: bus: set initial value to port_status
  soundwire: intel: handle disabled links
  soundwire: intel: add debugfs register dump
  soundwire: cadence_master: add debugfs register dump
  soundwire: add debugfs support
  soundwire: intel: remove unused variables
  soundwire: intel: move shutdown() callback and don't export symbol
  soundwire: cadence_master: add kernel parameter to override interrupt mask
  soundwire: intel_init: add kernel module parameter to filter out links
  soundwire: cadence_master: fix divider setting in clock register
  soundwire: cadence_master: make use of mclk_freq property
  soundwire: intel: read mclk_freq property from firmware
  soundwire: add new mclk_freq field for properties
  soundwire: stream: remove unnecessary variable initializations
  soundwire: stream: fix disable sequence
  soundwire: include mod_devicetable.h to avoid compiling warnings
  ...

1  2 
drivers/soundwire/Makefile
drivers/soundwire/cadence_master.c

index 45b7e50016539aaad4242a14a7292ff5c4d7b3a6,34bbd36a9851f51d245eb21902afd17631b261e6..563894e5ecaf5098986f992a2bb748f41ff8f51b
@@@ -5,8 -5,12 +5,12 @@@
  
  #Bus Objs
  soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o
 -obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
 +obj-$(CONFIG_SOUNDWIRE) += soundwire-bus.o
  
+ ifdef CONFIG_DEBUG_FS
+ soundwire-bus-objs += debugfs.o
+ endif
  #Cadence Objs
  soundwire-cadence-objs := cadence_master.o
  obj-$(CONFIG_SOUNDWIRE_CADENCE) += soundwire-cadence.o
index 60e8bdee5c754b83f2170bad9757d5cc5c63aa9d,dcb698e43c48ba3af9fb189118ca37e9376caadc..502ed4ec8f070a7c398f2b5fa959408608e8ac02
@@@ -8,6 -8,7 +8,7 @@@
  
  #include <linux/delay.h>
  #include <linux/device.h>
+ #include <linux/debugfs.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
  #include <linux/module.h>
  #include "bus.h"
  #include "cadence_master.h"
  
+ static int interrupt_mask;
+ module_param_named(cnds_mcp_int_mask, interrupt_mask, int, 0444);
+ MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask");
  #define CDNS_MCP_CONFIG                               0x0
  
  #define CDNS_MCP_CONFIG_MCMD_RETRY            GENMASK(27, 24)
@@@ -47,6 -52,8 +52,8 @@@
  #define CDNS_MCP_SSPSTAT                      0xC
  #define CDNS_MCP_FRAME_SHAPE                  0x10
  #define CDNS_MCP_FRAME_SHAPE_INIT             0x14
+ #define CDNS_MCP_FRAME_SHAPE_COL_MASK         GENMASK(2, 0)
+ #define CDNS_MCP_FRAME_SHAPE_ROW_OFFSET               3
  
  #define CDNS_MCP_CONFIG_UPDATE                        0x18
  #define CDNS_MCP_CONFIG_UPDATE_BIT            BIT(0)
@@@ -56,6 -63,7 +63,7 @@@
  #define CDNS_MCP_SSP_CTRL1                    0x28
  #define CDNS_MCP_CLK_CTRL0                    0x30
  #define CDNS_MCP_CLK_CTRL1                    0x38
+ #define CDNS_MCP_CLK_MCLKD_MASK               GENMASK(7, 0)
  
  #define CDNS_MCP_STAT                         0x40
  
  #define CDNS_MCP_INT_DPINT                    BIT(11)
  #define CDNS_MCP_INT_CTRL_CLASH                       BIT(10)
  #define CDNS_MCP_INT_DATA_CLASH                       BIT(9)
+ #define CDNS_MCP_INT_PARITY                   BIT(8)
  #define CDNS_MCP_INT_CMD_ERR                  BIT(7)
+ #define CDNS_MCP_INT_RX_NE                    BIT(3)
  #define CDNS_MCP_INT_RX_WL                    BIT(2)
  #define CDNS_MCP_INT_TXE                      BIT(1)
+ #define CDNS_MCP_INT_TXF                      BIT(0)
  
  #define CDNS_MCP_INTSET                               0x4C
  
 -#define CDNS_SDW_SLAVE_STAT                   0x50
 -#define CDNS_MCP_SLAVE_STAT_MASK              BIT(1, 0)
 +#define CDNS_MCP_SLAVE_STAT                   0x50
 +#define CDNS_MCP_SLAVE_STAT_MASK              GENMASK(1, 0)
  
  #define CDNS_MCP_SLAVE_INTSTAT0                       0x54
  #define CDNS_MCP_SLAVE_INTSTAT1                       0x58
  #define CDNS_MCP_SLAVE_INTMASK0                       0x5C
  #define CDNS_MCP_SLAVE_INTMASK1                       0x60
  
 -#define CDNS_MCP_SLAVE_INTMASK0_MASK          GENMASK(30, 0)
 -#define CDNS_MCP_SLAVE_INTMASK1_MASK          GENMASK(16, 0)
 +#define CDNS_MCP_SLAVE_INTMASK0_MASK          GENMASK(31, 0)
 +#define CDNS_MCP_SLAVE_INTMASK1_MASK          GENMASK(15, 0)
  
  #define CDNS_MCP_PORT_INTSTAT                 0x64
  #define CDNS_MCP_PDI_STAT                     0x6C
  #define CDNS_PDI_CONFIG_PORT                  GENMASK(4, 0)
  
  /* Driver defaults */
- #define CDNS_DEFAULT_CLK_DIVIDER              0
- #define CDNS_DEFAULT_FRAME_SHAPE              0x30
  #define CDNS_DEFAULT_SSP_INTERVAL             0x18
  #define CDNS_TX_TIMEOUT                               2000
  
@@@ -223,6 -231,112 +231,112 @@@ static int cdns_clear_bit(struct sdw_cd
        return -EAGAIN;
  }
  
+ /*
+  * debugfs
+  */
+ #ifdef CONFIG_DEBUG_FS
+ #define RD_BUF (2 * PAGE_SIZE)
+ static ssize_t cdns_sprintf(struct sdw_cdns *cdns,
+                           char *buf, size_t pos, unsigned int reg)
+ {
+       return scnprintf(buf + pos, RD_BUF - pos,
+                        "%4x\t%8x\n", reg, cdns_readl(cdns, reg));
+ }
+ static int cdns_reg_show(struct seq_file *s, void *data)
+ {
+       struct sdw_cdns *cdns = s->private;
+       char *buf;
+       ssize_t ret;
+       int num_ports;
+       int i, j;
+       buf = kzalloc(RD_BUF, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       ret = scnprintf(buf, RD_BUF, "Register  Value\n");
+       ret += scnprintf(buf + ret, RD_BUF - ret, "\nMCP Registers\n");
+       /* 8 MCP registers */
+       for (i = CDNS_MCP_CONFIG; i <= CDNS_MCP_PHYCTRL; i += sizeof(u32))
+               ret += cdns_sprintf(cdns, buf, ret, i);
+       ret += scnprintf(buf + ret, RD_BUF - ret,
+                        "\nStatus & Intr Registers\n");
+       /* 13 Status & Intr registers (offsets 0x70 and 0x74 not defined) */
+       for (i = CDNS_MCP_STAT; i <=  CDNS_MCP_FIFOSTAT; i += sizeof(u32))
+               ret += cdns_sprintf(cdns, buf, ret, i);
+       ret += scnprintf(buf + ret, RD_BUF - ret,
+                        "\nSSP & Clk ctrl Registers\n");
+       ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL0);
+       ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL1);
+       ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL0);
+       ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL1);
+       ret += scnprintf(buf + ret, RD_BUF - ret,
+                        "\nDPn B0 Registers\n");
+       /*
+        * in sdw_cdns_pdi_init() we filter out the Bulk PDIs,
+        * so the indices need to be corrected again
+        */
+       num_ports = cdns->num_ports + CDNS_PCM_PDI_OFFSET;
+       for (i = 0; i < num_ports; i++) {
+               ret += scnprintf(buf + ret, RD_BUF - ret,
+                                "\nDP-%d\n", i);
+               for (j = CDNS_DPN_B0_CONFIG(i);
+                    j < CDNS_DPN_B0_ASYNC_CTRL(i); j += sizeof(u32))
+                       ret += cdns_sprintf(cdns, buf, ret, j);
+       }
+       ret += scnprintf(buf + ret, RD_BUF - ret,
+                        "\nDPn B1 Registers\n");
+       for (i = 0; i < num_ports; i++) {
+               ret += scnprintf(buf + ret, RD_BUF - ret,
+                                "\nDP-%d\n", i);
+               for (j = CDNS_DPN_B1_CONFIG(i);
+                    j < CDNS_DPN_B1_ASYNC_CTRL(i); j += sizeof(u32))
+                       ret += cdns_sprintf(cdns, buf, ret, j);
+       }
+       ret += scnprintf(buf + ret, RD_BUF - ret,
+                        "\nDPn Control Registers\n");
+       for (i = 0; i < num_ports; i++)
+               ret += cdns_sprintf(cdns, buf, ret,
+                               CDNS_PORTCTRL + i * CDNS_PORT_OFFSET);
+       ret += scnprintf(buf + ret, RD_BUF - ret,
+                        "\nPDIn Config Registers\n");
+       /* number of PDI and ports is interchangeable */
+       for (i = 0; i < num_ports; i++)
+               ret += cdns_sprintf(cdns, buf, ret, CDNS_PDI_CONFIG(i));
+       seq_printf(s, "%s", buf);
+       kfree(buf);
+       return 0;
+ }
+ DEFINE_SHOW_ATTRIBUTE(cdns_reg);
+ /**
+  * sdw_cdns_debugfs_init() - Cadence debugfs init
+  * @cdns: Cadence instance
+  * @root: debugfs root
+  */
+ void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
+ {
+       debugfs_create_file("cdns-registers", 0400, root, cdns, &cdns_reg_fops);
+ }
+ EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init);
+ #endif /* CONFIG_DEBUG_FS */
  /*
   * IO Calls
   */
@@@ -575,10 -689,14 +689,14 @@@ irqreturn_t sdw_cdns_irq(int irq, void 
                }
        }
  
+       if (int_status & CDNS_MCP_INT_PARITY) {
+               /* Parity error detected by Master */
+               dev_err_ratelimited(cdns->dev, "Parity error\n");
+       }
        if (int_status & CDNS_MCP_INT_CTRL_CLASH) {
                /* Slave is driving bit slot during control word */
                dev_err_ratelimited(cdns->dev, "Bus clash for control word\n");
-               int_status |= CDNS_MCP_INT_CTRL_CLASH;
        }
  
        if (int_status & CDNS_MCP_INT_DATA_CLASH) {
                 * ownership of data bits or Slave gone bonkers
                 */
                dev_err_ratelimited(cdns->dev, "Bus clash for data word\n");
-               int_status |= CDNS_MCP_INT_DATA_CLASH;
        }
  
        if (int_status & CDNS_MCP_INT_SLAVE_MASK) {
@@@ -644,10 -761,26 +761,26 @@@ static int _cdns_enable_interrupt(struc
        cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
                    CDNS_MCP_SLAVE_INTMASK1_MASK);
  
-       mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
-               CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH |
-               CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
-               CDNS_MCP_INT_RX_WL | CDNS_MCP_INT_IRQ | CDNS_MCP_INT_DPINT;
+       /* enable detection of all slave state changes */
+       mask = CDNS_MCP_INT_SLAVE_MASK;
+       /* enable detection of bus issues */
+       mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
+               CDNS_MCP_INT_PARITY;
+       /* no detection of port interrupts for now */
+       /* enable detection of RX fifo level */
+       mask |= CDNS_MCP_INT_RX_WL;
+       /*
+        * CDNS_MCP_INT_IRQ needs to be set otherwise all previous
+        * settings are irrelevant
+        */
+       mask |= CDNS_MCP_INT_IRQ;
+       if (interrupt_mask) /* parameter override */
+               mask = interrupt_mask;
  
        cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
  
@@@ -788,13 -921,30 +921,30 @@@ int sdw_cdns_pdi_init(struct sdw_cdns *
  }
  EXPORT_SYMBOL(sdw_cdns_pdi_init);
  
+ static u32 cdns_set_initial_frame_shape(int n_rows, int n_cols)
+ {
+       u32 val;
+       int c;
+       int r;
+       r = sdw_find_row_index(n_rows);
+       c = sdw_find_col_index(n_cols) & CDNS_MCP_FRAME_SHAPE_COL_MASK;
+       val = (r << CDNS_MCP_FRAME_SHAPE_ROW_OFFSET) | c;
+       return val;
+ }
  /**
   * sdw_cdns_init() - Cadence initialization
   * @cdns: Cadence instance
   */
  int sdw_cdns_init(struct sdw_cdns *cdns)
  {
+       struct sdw_bus *bus = &cdns->bus;
+       struct sdw_master_prop *prop = &bus->prop;
        u32 val;
+       int divider;
        int ret;
  
        /* Exit clock stop */
        }
  
        /* Set clock divider */
-       val = cdns_readl(cdns, CDNS_MCP_CLK_CTRL0);
-       val |= CDNS_DEFAULT_CLK_DIVIDER;
-       cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
+       divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
  
-       /* Set the default frame shape */
-       cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, CDNS_DEFAULT_FRAME_SHAPE);
+       cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0,
+                    CDNS_MCP_CLK_MCLKD_MASK, divider);
+       cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1,
+                    CDNS_MCP_CLK_MCLKD_MASK, divider);
+       /*
+        * Frame shape changes after initialization have to be done
+        * with the bank switch mechanism
+        */
+       val = cdns_set_initial_frame_shape(prop->default_row,
+                                          prop->default_col);
+       cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, val);
  
        /* Set SSP interval to default value */
        cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL);
@@@ -851,8 -1009,9 +1009,9 @@@ EXPORT_SYMBOL(sdw_cdns_init)
  
  int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params)
  {
+       struct sdw_master_prop *prop = &bus->prop;
        struct sdw_cdns *cdns = bus_to_cdns(bus);
-       int mcp_clkctrl_off, mcp_clkctrl;
+       int mcp_clkctrl_off;
        int divider;
  
        if (!params->curr_dr_freq) {
                return -EINVAL;
        }
  
-       divider = (params->max_dr_freq / params->curr_dr_freq) - 1;
+       divider = prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR /
+               params->curr_dr_freq;
+       divider--; /* divider is 1/(N+1) */
  
        if (params->next_bank)
                mcp_clkctrl_off = CDNS_MCP_CLK_CTRL1;
        else
                mcp_clkctrl_off = CDNS_MCP_CLK_CTRL0;
  
-       mcp_clkctrl = cdns_readl(cdns, mcp_clkctrl_off);
-       mcp_clkctrl |= divider;
-       cdns_writel(cdns, mcp_clkctrl_off, mcp_clkctrl);
+       cdns_updatel(cdns, mcp_clkctrl_off, CDNS_MCP_CLK_MCLKD_MASK, divider);
  
        return 0;
  }
@@@ -1170,19 -1329,5 +1329,5 @@@ int sdw_cdns_alloc_stream(struct sdw_cd
  }
  EXPORT_SYMBOL(sdw_cdns_alloc_stream);
  
- void sdw_cdns_shutdown(struct snd_pcm_substream *substream,
-                      struct snd_soc_dai *dai)
- {
-       struct sdw_cdns_dma_data *dma;
-       dma = snd_soc_dai_get_dma_data(dai, substream);
-       if (!dma)
-               return;
-       snd_soc_dai_set_dma_data(dai, substream, NULL);
-       kfree(dma);
- }
- EXPORT_SYMBOL(sdw_cdns_shutdown);
  MODULE_LICENSE("Dual BSD/GPL");
  MODULE_DESCRIPTION("Cadence Soundwire Library");