// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
/*
* SoundWire AMD Manager driver
*
* Copyright 2023-24 Advanced Micro Devices, Inc.
*/
#include <linux/completion.h>
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/pm_runtime.h>
#include <linux/wait.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "bus.h"
#include "amd_init.h"
#include "amd_manager.h"
#define DRV_NAME "amd_sdw_manager"
#define to_amd_sdw(b) container_of(b, struct amd_sdw_manager, bus)
static int amd_init_sdw_manager(struct amd_sdw_manager *amd_manager)
{
u32 val;
int ret;
writel(AMD_SDW_ENABLE, amd_manager->mmio + ACP_SW_EN);
ret = readl_poll_timeout(amd_manager->mmio + ACP_SW_EN_STATUS, val, val, ACP_DELAY_US,
AMD_SDW_TIMEOUT);
if (ret)
return ret;
/* SoundWire manager bus reset */
writel(AMD_SDW_BUS_RESET_REQ, amd_manager->mmio + ACP_SW_BUS_RESET_CTRL);
ret = readl_poll_timeout(amd_manager->mmio + ACP_SW_BUS_RESET_CTRL, val,
(val & AMD_SDW_BUS_RESET_DONE), ACP_DELAY_US, AMD_SDW_TIMEOUT);
if (ret)
return ret;
writel(AMD_SDW_BUS_RESET_CLEAR_REQ, amd_manager->mmio + ACP_SW_BUS_RESET_CTRL);
ret = readl_poll_timeout(amd_manager->mmio + ACP_SW_BUS_RESET_CTRL, val, !val,
ACP_DELAY_US, AMD_SDW_TIMEOUT);
if (ret) {
dev_err(amd_manager->dev, "Failed to reset SoundWire manager instance%d\n",
amd_manager->instance);
return ret;
}
writel(AMD_SDW_DISABLE, amd_manager->mmio + ACP_SW_EN);
return readl_poll_timeout(amd_manager->mmio + ACP_SW_EN_STATUS, val, !val, ACP_DELAY_US,
AMD_SDW_TIMEOUT);
}
static int amd_enable_sdw_manager(struct amd_sdw_manager *amd_manager)
{
u32 val;
writel(AMD_SDW_ENABLE, amd_manager->mmio + ACP_SW_EN);
return readl_poll_timeout(amd_manager->mmio + ACP_SW_EN_STATUS, val, val, ACP_DELAY_US,
AMD_SDW_TIMEOUT);
}
static int amd_disable_sdw_manager(struct amd_sdw_manager *amd_manager)
{
u32 val;
writel(