Loading asoc/codecs/wcd-spi.c +92 −0 Original line number Diff line number Diff line Loading @@ -14,8 +14,10 @@ #include <linux/regmap.h> #include <linux/component.h> #include <linux/ratelimit.h> #include <linux/platform_device.h> #include <sound/wcd-dsp-mgr.h> #include <sound/wcd-spi.h> #include <soc/wcd-spi-ac.h> #include "wcd-spi-registers.h" /* Byte manipulations */ Loading Loading @@ -157,6 +159,8 @@ struct wcd_spi_priv { /* DMA handles for transfer buffers */ dma_addr_t tx_dma; dma_addr_t rx_dma; /* Handle to child (qmi client) device */ struct device *ac_dev; }; enum xfer_request { Loading Loading @@ -567,6 +571,19 @@ static int wcd_spi_clk_enable(struct spi_device *spi) int ret; u32 rd_status = 0; /* Get the SPI access first */ if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_REQUEST, WCD_SPI_AC_DATA_TRANSFER); if (ret) { dev_err(&spi->dev, "%s: Can't get spi access, err = %d\n", __func__, ret); return ret; } } ret = wcd_spi_cmd_nop(spi); if (ret < 0) { dev_err(&spi->dev, "%s: NOP1 failed, err = %d\n", Loading Loading @@ -620,6 +637,17 @@ static int wcd_spi_clk_disable(struct spi_device *spi) */ clear_bit(WCD_SPI_CLK_STATE_ENABLED, &wcd_spi->status_mask); /* once the clock is released, SPI access can be released as well */ if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_RELEASE, WCD_SPI_AC_DATA_TRANSFER); if (ret) dev_err(&spi->dev, "%s: SPI access release failed, err = %d\n", __func__, ret); } return ret; } Loading Loading @@ -944,6 +972,18 @@ static int wdsp_spi_event_handler(struct device *dev, void *priv_data, __func__, event); switch (event) { case WDSP_EVENT_PRE_SHUTDOWN: if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_REQUEST, WCD_SPI_AC_REMOTE_DOWN); if (ret) dev_err(&spi->dev, "%s: request access failed %d\n", __func__, ret); } break; case WDSP_EVENT_POST_SHUTDOWN: cancel_delayed_work_sync(&wcd_spi->clk_dwork); WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); Loading @@ -953,6 +993,18 @@ static int wdsp_spi_event_handler(struct device *dev, void *priv_data, WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); break; case WDSP_EVENT_POST_BOOTUP: if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_RELEASE, WCD_SPI_AC_REMOTE_DOWN); if (ret) dev_err(&spi->dev, "%s: release access failed %d\n", __func__, ret); } break; case WDSP_EVENT_PRE_DLOAD_CODE: case WDSP_EVENT_PRE_DLOAD_DATA: ret = wcd_spi_clk_ctrl(spi, WCD_SPI_CLK_ENABLE, Loading Loading @@ -1299,10 +1351,50 @@ static struct regmap_config wcd_spi_regmap_cfg = { .readable_reg = wcd_spi_is_readable_reg, }; static int wcd_spi_add_ac_dev(struct device *dev, struct device_node *node) { struct spi_device *spi = to_spi_device(dev); struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi); struct platform_device *pdev; int ret = 0; pdev = platform_device_alloc("wcd-spi-ac", -1); if (IS_ERR_OR_NULL(pdev)) { ret = PTR_ERR(pdev); dev_err(dev, "%s: pdev alloc failed, ret = %d\n", __func__, ret); return ret; } pdev->dev.parent = dev; pdev->dev.of_node = node; ret = platform_device_add(pdev); if (ret) { dev_err(dev, "%s: pdev add failed, ret = %d\n", __func__, ret); goto dealloc_pdev; } wcd_spi->ac_dev = &pdev->dev; return 0; dealloc_pdev: platform_device_put(pdev); return ret; } static int wdsp_spi_init(struct device *dev, void *priv_data) { struct spi_device *spi = to_spi_device(dev); int ret; struct device_node *node; for_each_child_of_node(dev->of_node, node) { if (!strcmp(node->name, "wcd_spi_ac")) wcd_spi_add_ac_dev(dev, node); } ret = wcd_spi_init(spi); if (ret < 0) Loading Loading
asoc/codecs/wcd-spi.c +92 −0 Original line number Diff line number Diff line Loading @@ -14,8 +14,10 @@ #include <linux/regmap.h> #include <linux/component.h> #include <linux/ratelimit.h> #include <linux/platform_device.h> #include <sound/wcd-dsp-mgr.h> #include <sound/wcd-spi.h> #include <soc/wcd-spi-ac.h> #include "wcd-spi-registers.h" /* Byte manipulations */ Loading Loading @@ -157,6 +159,8 @@ struct wcd_spi_priv { /* DMA handles for transfer buffers */ dma_addr_t tx_dma; dma_addr_t rx_dma; /* Handle to child (qmi client) device */ struct device *ac_dev; }; enum xfer_request { Loading Loading @@ -567,6 +571,19 @@ static int wcd_spi_clk_enable(struct spi_device *spi) int ret; u32 rd_status = 0; /* Get the SPI access first */ if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_REQUEST, WCD_SPI_AC_DATA_TRANSFER); if (ret) { dev_err(&spi->dev, "%s: Can't get spi access, err = %d\n", __func__, ret); return ret; } } ret = wcd_spi_cmd_nop(spi); if (ret < 0) { dev_err(&spi->dev, "%s: NOP1 failed, err = %d\n", Loading Loading @@ -620,6 +637,17 @@ static int wcd_spi_clk_disable(struct spi_device *spi) */ clear_bit(WCD_SPI_CLK_STATE_ENABLED, &wcd_spi->status_mask); /* once the clock is released, SPI access can be released as well */ if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_RELEASE, WCD_SPI_AC_DATA_TRANSFER); if (ret) dev_err(&spi->dev, "%s: SPI access release failed, err = %d\n", __func__, ret); } return ret; } Loading Loading @@ -944,6 +972,18 @@ static int wdsp_spi_event_handler(struct device *dev, void *priv_data, __func__, event); switch (event) { case WDSP_EVENT_PRE_SHUTDOWN: if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_REQUEST, WCD_SPI_AC_REMOTE_DOWN); if (ret) dev_err(&spi->dev, "%s: request access failed %d\n", __func__, ret); } break; case WDSP_EVENT_POST_SHUTDOWN: cancel_delayed_work_sync(&wcd_spi->clk_dwork); WCD_SPI_MUTEX_LOCK(spi, wcd_spi->clk_mutex); Loading @@ -953,6 +993,18 @@ static int wdsp_spi_event_handler(struct device *dev, void *priv_data, WCD_SPI_MUTEX_UNLOCK(spi, wcd_spi->clk_mutex); break; case WDSP_EVENT_POST_BOOTUP: if (wcd_spi->ac_dev) { ret = wcd_spi_access_ctl(wcd_spi->ac_dev, WCD_SPI_ACCESS_RELEASE, WCD_SPI_AC_REMOTE_DOWN); if (ret) dev_err(&spi->dev, "%s: release access failed %d\n", __func__, ret); } break; case WDSP_EVENT_PRE_DLOAD_CODE: case WDSP_EVENT_PRE_DLOAD_DATA: ret = wcd_spi_clk_ctrl(spi, WCD_SPI_CLK_ENABLE, Loading Loading @@ -1299,10 +1351,50 @@ static struct regmap_config wcd_spi_regmap_cfg = { .readable_reg = wcd_spi_is_readable_reg, }; static int wcd_spi_add_ac_dev(struct device *dev, struct device_node *node) { struct spi_device *spi = to_spi_device(dev); struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi); struct platform_device *pdev; int ret = 0; pdev = platform_device_alloc("wcd-spi-ac", -1); if (IS_ERR_OR_NULL(pdev)) { ret = PTR_ERR(pdev); dev_err(dev, "%s: pdev alloc failed, ret = %d\n", __func__, ret); return ret; } pdev->dev.parent = dev; pdev->dev.of_node = node; ret = platform_device_add(pdev); if (ret) { dev_err(dev, "%s: pdev add failed, ret = %d\n", __func__, ret); goto dealloc_pdev; } wcd_spi->ac_dev = &pdev->dev; return 0; dealloc_pdev: platform_device_put(pdev); return ret; } static int wdsp_spi_init(struct device *dev, void *priv_data) { struct spi_device *spi = to_spi_device(dev); int ret; struct device_node *node; for_each_child_of_node(dev->of_node, node) { if (!strcmp(node->name, "wcd_spi_ac")) wcd_spi_add_ac_dev(dev, node); } ret = wcd_spi_init(spi); if (ret < 0) Loading