162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2015 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1262306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1362306a36Sopenharmony_ci *
1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Authors: AMD
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include <linux/irqdomain.h>
2762306a36Sopenharmony_ci#include <linux/pci.h>
2862306a36Sopenharmony_ci#include <linux/pm_domain.h>
2962306a36Sopenharmony_ci#include <linux/platform_device.h>
3062306a36Sopenharmony_ci#include <sound/designware_i2s.h>
3162306a36Sopenharmony_ci#include <sound/pcm.h>
3262306a36Sopenharmony_ci#include <linux/acpi.h>
3362306a36Sopenharmony_ci#include <linux/dmi.h>
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include "amdgpu.h"
3662306a36Sopenharmony_ci#include "atom.h"
3762306a36Sopenharmony_ci#include "amdgpu_acp.h"
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include "acp_gfx_if.h"
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define ST_JADEITE 1
4262306a36Sopenharmony_ci#define ACP_TILE_ON_MASK			0x03
4362306a36Sopenharmony_ci#define ACP_TILE_OFF_MASK			0x02
4462306a36Sopenharmony_ci#define ACP_TILE_ON_RETAIN_REG_MASK		0x1f
4562306a36Sopenharmony_ci#define ACP_TILE_OFF_RETAIN_REG_MASK		0x20
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci#define ACP_TILE_P1_MASK			0x3e
4862306a36Sopenharmony_ci#define ACP_TILE_P2_MASK			0x3d
4962306a36Sopenharmony_ci#define ACP_TILE_DSP0_MASK			0x3b
5062306a36Sopenharmony_ci#define ACP_TILE_DSP1_MASK			0x37
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define ACP_TILE_DSP2_MASK			0x2f
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#define ACP_DMA_REGS_END			0x146c0
5562306a36Sopenharmony_ci#define ACP_I2S_PLAY_REGS_START			0x14840
5662306a36Sopenharmony_ci#define ACP_I2S_PLAY_REGS_END			0x148b4
5762306a36Sopenharmony_ci#define ACP_I2S_CAP_REGS_START			0x148b8
5862306a36Sopenharmony_ci#define ACP_I2S_CAP_REGS_END			0x1496c
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci#define ACP_I2S_COMP1_CAP_REG_OFFSET		0xac
6162306a36Sopenharmony_ci#define ACP_I2S_COMP2_CAP_REG_OFFSET		0xa8
6262306a36Sopenharmony_ci#define ACP_I2S_COMP1_PLAY_REG_OFFSET		0x6c
6362306a36Sopenharmony_ci#define ACP_I2S_COMP2_PLAY_REG_OFFSET		0x68
6462306a36Sopenharmony_ci#define ACP_BT_PLAY_REGS_START			0x14970
6562306a36Sopenharmony_ci#define ACP_BT_PLAY_REGS_END			0x14a24
6662306a36Sopenharmony_ci#define ACP_BT_COMP1_REG_OFFSET			0xac
6762306a36Sopenharmony_ci#define ACP_BT_COMP2_REG_OFFSET			0xa8
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#define mmACP_PGFSM_RETAIN_REG			0x51c9
7062306a36Sopenharmony_ci#define mmACP_PGFSM_CONFIG_REG			0x51ca
7162306a36Sopenharmony_ci#define mmACP_PGFSM_READ_REG_0			0x51cc
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define mmACP_MEM_SHUT_DOWN_REQ_LO		0x51f8
7462306a36Sopenharmony_ci#define mmACP_MEM_SHUT_DOWN_REQ_HI		0x51f9
7562306a36Sopenharmony_ci#define mmACP_MEM_SHUT_DOWN_STS_LO		0x51fa
7662306a36Sopenharmony_ci#define mmACP_MEM_SHUT_DOWN_STS_HI		0x51fb
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define mmACP_CONTROL				0x5131
7962306a36Sopenharmony_ci#define mmACP_STATUS				0x5133
8062306a36Sopenharmony_ci#define mmACP_SOFT_RESET			0x5134
8162306a36Sopenharmony_ci#define ACP_CONTROL__ClkEn_MASK			0x1
8262306a36Sopenharmony_ci#define ACP_SOFT_RESET__SoftResetAud_MASK	0x100
8362306a36Sopenharmony_ci#define ACP_SOFT_RESET__SoftResetAudDone_MASK	0x1000000
8462306a36Sopenharmony_ci#define ACP_CLOCK_EN_TIME_OUT_VALUE		0x000000FF
8562306a36Sopenharmony_ci#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE	0x000000FF
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#define ACP_TIMEOUT_LOOP			0x000000FF
8862306a36Sopenharmony_ci#define ACP_DEVS				4
8962306a36Sopenharmony_ci#define ACP_SRC_ID				162
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic unsigned long acp_machine_id;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cienum {
9462306a36Sopenharmony_ci	ACP_TILE_P1 = 0,
9562306a36Sopenharmony_ci	ACP_TILE_P2,
9662306a36Sopenharmony_ci	ACP_TILE_DSP0,
9762306a36Sopenharmony_ci	ACP_TILE_DSP1,
9862306a36Sopenharmony_ci	ACP_TILE_DSP2,
9962306a36Sopenharmony_ci};
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_cistatic int acp_sw_init(void *handle)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	adev->acp.parent = adev->dev;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	adev->acp.cgs_device =
10862306a36Sopenharmony_ci		amdgpu_cgs_create_device(adev);
10962306a36Sopenharmony_ci	if (!adev->acp.cgs_device)
11062306a36Sopenharmony_ci		return -EINVAL;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	return 0;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic int acp_sw_fini(void *handle)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	if (adev->acp.cgs_device)
12062306a36Sopenharmony_ci		amdgpu_cgs_destroy_device(adev->acp.cgs_device);
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	return 0;
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistruct acp_pm_domain {
12662306a36Sopenharmony_ci	void *adev;
12762306a36Sopenharmony_ci	struct generic_pm_domain gpd;
12862306a36Sopenharmony_ci};
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic int acp_poweroff(struct generic_pm_domain *genpd)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct acp_pm_domain *apd;
13362306a36Sopenharmony_ci	struct amdgpu_device *adev;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	apd = container_of(genpd, struct acp_pm_domain, gpd);
13662306a36Sopenharmony_ci	adev = apd->adev;
13762306a36Sopenharmony_ci	/* call smu to POWER GATE ACP block
13862306a36Sopenharmony_ci	 * smu will
13962306a36Sopenharmony_ci	 * 1. turn off the acp clock
14062306a36Sopenharmony_ci	 * 2. power off the acp tiles
14162306a36Sopenharmony_ci	 * 3. check and enter ulv state
14262306a36Sopenharmony_ci	 */
14362306a36Sopenharmony_ci	amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
14462306a36Sopenharmony_ci	return 0;
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic int acp_poweron(struct generic_pm_domain *genpd)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	struct acp_pm_domain *apd;
15062306a36Sopenharmony_ci	struct amdgpu_device *adev;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	apd = container_of(genpd, struct acp_pm_domain, gpd);
15362306a36Sopenharmony_ci	adev = apd->adev;
15462306a36Sopenharmony_ci	/* call smu to UNGATE ACP block
15562306a36Sopenharmony_ci	 * smu will
15662306a36Sopenharmony_ci	 * 1. exit ulv
15762306a36Sopenharmony_ci	 * 2. turn on acp clock
15862306a36Sopenharmony_ci	 * 3. power on acp tiles
15962306a36Sopenharmony_ci	 */
16062306a36Sopenharmony_ci	amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
16162306a36Sopenharmony_ci	return 0;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic int acp_genpd_add_device(struct device *dev, void *data)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct generic_pm_domain *gpd = data;
16762306a36Sopenharmony_ci	int ret;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	ret = pm_genpd_add_device(gpd, dev);
17062306a36Sopenharmony_ci	if (ret)
17162306a36Sopenharmony_ci		dev_err(dev, "Failed to add dev to genpd %d\n", ret);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	return ret;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistatic int acp_genpd_remove_device(struct device *dev, void *data)
17762306a36Sopenharmony_ci{
17862306a36Sopenharmony_ci	int ret;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	ret = pm_genpd_remove_device(dev);
18162306a36Sopenharmony_ci	if (ret)
18262306a36Sopenharmony_ci		dev_err(dev, "Failed to remove dev from genpd %d\n", ret);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	/* Continue to remove */
18562306a36Sopenharmony_ci	return 0;
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_cistatic int acp_quirk_cb(const struct dmi_system_id *id)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	acp_machine_id = ST_JADEITE;
19162306a36Sopenharmony_ci	return 1;
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic const struct dmi_system_id acp_quirk_table[] = {
19562306a36Sopenharmony_ci	{
19662306a36Sopenharmony_ci		.callback = acp_quirk_cb,
19762306a36Sopenharmony_ci		.matches = {
19862306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "AMD"),
19962306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jadeite"),
20062306a36Sopenharmony_ci		}
20162306a36Sopenharmony_ci	},
20262306a36Sopenharmony_ci	{
20362306a36Sopenharmony_ci		.callback = acp_quirk_cb,
20462306a36Sopenharmony_ci		.matches = {
20562306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "IP3 Technology CO.,Ltd."),
20662306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN1D"),
20762306a36Sopenharmony_ci		},
20862306a36Sopenharmony_ci	},
20962306a36Sopenharmony_ci	{
21062306a36Sopenharmony_ci		.callback = acp_quirk_cb,
21162306a36Sopenharmony_ci		.matches = {
21262306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Standard"),
21362306a36Sopenharmony_ci			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ASN10"),
21462306a36Sopenharmony_ci		},
21562306a36Sopenharmony_ci	},
21662306a36Sopenharmony_ci	{}
21762306a36Sopenharmony_ci};
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci/**
22062306a36Sopenharmony_ci * acp_hw_init - start and test ACP block
22162306a36Sopenharmony_ci *
22262306a36Sopenharmony_ci * @handle: handle used to pass amdgpu_device pointer
22362306a36Sopenharmony_ci *
22462306a36Sopenharmony_ci */
22562306a36Sopenharmony_cistatic int acp_hw_init(void *handle)
22662306a36Sopenharmony_ci{
22762306a36Sopenharmony_ci	int r;
22862306a36Sopenharmony_ci	u64 acp_base;
22962306a36Sopenharmony_ci	u32 val = 0;
23062306a36Sopenharmony_ci	u32 count = 0;
23162306a36Sopenharmony_ci	struct i2s_platform_data *i2s_pdata = NULL;
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	const struct amdgpu_ip_block *ip_block =
23662306a36Sopenharmony_ci		amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_ACP);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	if (!ip_block)
23962306a36Sopenharmony_ci		return -EINVAL;
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	r = amd_acp_hw_init(adev->acp.cgs_device,
24262306a36Sopenharmony_ci			    ip_block->version->major, ip_block->version->minor);
24362306a36Sopenharmony_ci	/* -ENODEV means board uses AZ rather than ACP */
24462306a36Sopenharmony_ci	if (r == -ENODEV) {
24562306a36Sopenharmony_ci		amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
24662306a36Sopenharmony_ci		return 0;
24762306a36Sopenharmony_ci	} else if (r) {
24862306a36Sopenharmony_ci		return r;
24962306a36Sopenharmony_ci	}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci	if (adev->rmmio_size == 0 || adev->rmmio_size < 0x5289)
25262306a36Sopenharmony_ci		return -EINVAL;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	acp_base = adev->rmmio_base;
25562306a36Sopenharmony_ci	adev->acp.acp_genpd = kzalloc(sizeof(struct acp_pm_domain), GFP_KERNEL);
25662306a36Sopenharmony_ci	if (!adev->acp.acp_genpd)
25762306a36Sopenharmony_ci		return -ENOMEM;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	adev->acp.acp_genpd->gpd.name = "ACP_AUDIO";
26062306a36Sopenharmony_ci	adev->acp.acp_genpd->gpd.power_off = acp_poweroff;
26162306a36Sopenharmony_ci	adev->acp.acp_genpd->gpd.power_on = acp_poweron;
26262306a36Sopenharmony_ci	adev->acp.acp_genpd->adev = adev;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false);
26562306a36Sopenharmony_ci	dmi_check_system(acp_quirk_table);
26662306a36Sopenharmony_ci	switch (acp_machine_id) {
26762306a36Sopenharmony_ci	case ST_JADEITE:
26862306a36Sopenharmony_ci	{
26962306a36Sopenharmony_ci		adev->acp.acp_cell = kcalloc(2, sizeof(struct mfd_cell),
27062306a36Sopenharmony_ci					     GFP_KERNEL);
27162306a36Sopenharmony_ci		if (!adev->acp.acp_cell) {
27262306a36Sopenharmony_ci			r = -ENOMEM;
27362306a36Sopenharmony_ci			goto failure;
27462306a36Sopenharmony_ci		}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci		adev->acp.acp_res = kcalloc(3, sizeof(struct resource), GFP_KERNEL);
27762306a36Sopenharmony_ci		if (!adev->acp.acp_res) {
27862306a36Sopenharmony_ci			r = -ENOMEM;
27962306a36Sopenharmony_ci			goto failure;
28062306a36Sopenharmony_ci		}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci		i2s_pdata = kcalloc(1, sizeof(struct i2s_platform_data), GFP_KERNEL);
28362306a36Sopenharmony_ci		if (!i2s_pdata) {
28462306a36Sopenharmony_ci			r = -ENOMEM;
28562306a36Sopenharmony_ci			goto failure;
28662306a36Sopenharmony_ci		}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci		i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
28962306a36Sopenharmony_ci				      DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
29062306a36Sopenharmony_ci		i2s_pdata[0].cap = DWC_I2S_PLAY | DWC_I2S_RECORD;
29162306a36Sopenharmony_ci		i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000;
29262306a36Sopenharmony_ci		i2s_pdata[0].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
29362306a36Sopenharmony_ci		i2s_pdata[0].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci		adev->acp.acp_res[0].name = "acp2x_dma";
29662306a36Sopenharmony_ci		adev->acp.acp_res[0].flags = IORESOURCE_MEM;
29762306a36Sopenharmony_ci		adev->acp.acp_res[0].start = acp_base;
29862306a36Sopenharmony_ci		adev->acp.acp_res[0].end = acp_base + ACP_DMA_REGS_END;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci		adev->acp.acp_res[1].name = "acp2x_dw_i2s_play_cap";
30162306a36Sopenharmony_ci		adev->acp.acp_res[1].flags = IORESOURCE_MEM;
30262306a36Sopenharmony_ci		adev->acp.acp_res[1].start = acp_base + ACP_I2S_CAP_REGS_START;
30362306a36Sopenharmony_ci		adev->acp.acp_res[1].end = acp_base + ACP_I2S_CAP_REGS_END;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci		adev->acp.acp_res[2].name = "acp2x_dma_irq";
30662306a36Sopenharmony_ci		adev->acp.acp_res[2].flags = IORESOURCE_IRQ;
30762306a36Sopenharmony_ci		adev->acp.acp_res[2].start = amdgpu_irq_create_mapping(adev, 162);
30862306a36Sopenharmony_ci		adev->acp.acp_res[2].end = adev->acp.acp_res[2].start;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci		adev->acp.acp_cell[0].name = "acp_audio_dma";
31162306a36Sopenharmony_ci		adev->acp.acp_cell[0].num_resources = 3;
31262306a36Sopenharmony_ci		adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
31362306a36Sopenharmony_ci		adev->acp.acp_cell[0].platform_data = &adev->asic_type;
31462306a36Sopenharmony_ci		adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci		adev->acp.acp_cell[1].name = "designware-i2s";
31762306a36Sopenharmony_ci		adev->acp.acp_cell[1].num_resources = 1;
31862306a36Sopenharmony_ci		adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1];
31962306a36Sopenharmony_ci		adev->acp.acp_cell[1].platform_data = &i2s_pdata[0];
32062306a36Sopenharmony_ci		adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data);
32162306a36Sopenharmony_ci		r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, 2);
32262306a36Sopenharmony_ci		if (r)
32362306a36Sopenharmony_ci			goto failure;
32462306a36Sopenharmony_ci		r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
32562306a36Sopenharmony_ci					  acp_genpd_add_device);
32662306a36Sopenharmony_ci		if (r)
32762306a36Sopenharmony_ci			goto failure;
32862306a36Sopenharmony_ci		break;
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci	default:
33162306a36Sopenharmony_ci		adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell),
33262306a36Sopenharmony_ci					     GFP_KERNEL);
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci		if (!adev->acp.acp_cell) {
33562306a36Sopenharmony_ci			r = -ENOMEM;
33662306a36Sopenharmony_ci			goto failure;
33762306a36Sopenharmony_ci		}
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci		adev->acp.acp_res = kcalloc(5, sizeof(struct resource), GFP_KERNEL);
34062306a36Sopenharmony_ci		if (!adev->acp.acp_res) {
34162306a36Sopenharmony_ci			r = -ENOMEM;
34262306a36Sopenharmony_ci			goto failure;
34362306a36Sopenharmony_ci		}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		i2s_pdata = kcalloc(3, sizeof(struct i2s_platform_data), GFP_KERNEL);
34662306a36Sopenharmony_ci		if (!i2s_pdata) {
34762306a36Sopenharmony_ci			r = -ENOMEM;
34862306a36Sopenharmony_ci			goto failure;
34962306a36Sopenharmony_ci		}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci		switch (adev->asic_type) {
35262306a36Sopenharmony_ci		case CHIP_STONEY:
35362306a36Sopenharmony_ci			i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
35462306a36Sopenharmony_ci				DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
35562306a36Sopenharmony_ci			break;
35662306a36Sopenharmony_ci		default:
35762306a36Sopenharmony_ci			i2s_pdata[0].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
35862306a36Sopenharmony_ci		}
35962306a36Sopenharmony_ci		i2s_pdata[0].cap = DWC_I2S_PLAY;
36062306a36Sopenharmony_ci		i2s_pdata[0].snd_rates = SNDRV_PCM_RATE_8000_96000;
36162306a36Sopenharmony_ci		i2s_pdata[0].i2s_reg_comp1 = ACP_I2S_COMP1_PLAY_REG_OFFSET;
36262306a36Sopenharmony_ci		i2s_pdata[0].i2s_reg_comp2 = ACP_I2S_COMP2_PLAY_REG_OFFSET;
36362306a36Sopenharmony_ci		switch (adev->asic_type) {
36462306a36Sopenharmony_ci		case CHIP_STONEY:
36562306a36Sopenharmony_ci			i2s_pdata[1].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
36662306a36Sopenharmony_ci				DW_I2S_QUIRK_COMP_PARAM1 |
36762306a36Sopenharmony_ci				DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
36862306a36Sopenharmony_ci			break;
36962306a36Sopenharmony_ci		default:
37062306a36Sopenharmony_ci			i2s_pdata[1].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET |
37162306a36Sopenharmony_ci				DW_I2S_QUIRK_COMP_PARAM1;
37262306a36Sopenharmony_ci		}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci		i2s_pdata[1].cap = DWC_I2S_RECORD;
37562306a36Sopenharmony_ci		i2s_pdata[1].snd_rates = SNDRV_PCM_RATE_8000_96000;
37662306a36Sopenharmony_ci		i2s_pdata[1].i2s_reg_comp1 = ACP_I2S_COMP1_CAP_REG_OFFSET;
37762306a36Sopenharmony_ci		i2s_pdata[1].i2s_reg_comp2 = ACP_I2S_COMP2_CAP_REG_OFFSET;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci		i2s_pdata[2].quirks = DW_I2S_QUIRK_COMP_REG_OFFSET;
38062306a36Sopenharmony_ci		switch (adev->asic_type) {
38162306a36Sopenharmony_ci		case CHIP_STONEY:
38262306a36Sopenharmony_ci			i2s_pdata[2].quirks |= DW_I2S_QUIRK_16BIT_IDX_OVERRIDE;
38362306a36Sopenharmony_ci			break;
38462306a36Sopenharmony_ci		default:
38562306a36Sopenharmony_ci			break;
38662306a36Sopenharmony_ci		}
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci		i2s_pdata[2].cap = DWC_I2S_PLAY | DWC_I2S_RECORD;
38962306a36Sopenharmony_ci		i2s_pdata[2].snd_rates = SNDRV_PCM_RATE_8000_96000;
39062306a36Sopenharmony_ci		i2s_pdata[2].i2s_reg_comp1 = ACP_BT_COMP1_REG_OFFSET;
39162306a36Sopenharmony_ci		i2s_pdata[2].i2s_reg_comp2 = ACP_BT_COMP2_REG_OFFSET;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci		adev->acp.acp_res[0].name = "acp2x_dma";
39462306a36Sopenharmony_ci		adev->acp.acp_res[0].flags = IORESOURCE_MEM;
39562306a36Sopenharmony_ci		adev->acp.acp_res[0].start = acp_base;
39662306a36Sopenharmony_ci		adev->acp.acp_res[0].end = acp_base + ACP_DMA_REGS_END;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci		adev->acp.acp_res[1].name = "acp2x_dw_i2s_play";
39962306a36Sopenharmony_ci		adev->acp.acp_res[1].flags = IORESOURCE_MEM;
40062306a36Sopenharmony_ci		adev->acp.acp_res[1].start = acp_base + ACP_I2S_PLAY_REGS_START;
40162306a36Sopenharmony_ci		adev->acp.acp_res[1].end = acp_base + ACP_I2S_PLAY_REGS_END;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci		adev->acp.acp_res[2].name = "acp2x_dw_i2s_cap";
40462306a36Sopenharmony_ci		adev->acp.acp_res[2].flags = IORESOURCE_MEM;
40562306a36Sopenharmony_ci		adev->acp.acp_res[2].start = acp_base + ACP_I2S_CAP_REGS_START;
40662306a36Sopenharmony_ci		adev->acp.acp_res[2].end = acp_base + ACP_I2S_CAP_REGS_END;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci		adev->acp.acp_res[3].name = "acp2x_dw_bt_i2s_play_cap";
40962306a36Sopenharmony_ci		adev->acp.acp_res[3].flags = IORESOURCE_MEM;
41062306a36Sopenharmony_ci		adev->acp.acp_res[3].start = acp_base + ACP_BT_PLAY_REGS_START;
41162306a36Sopenharmony_ci		adev->acp.acp_res[3].end = acp_base + ACP_BT_PLAY_REGS_END;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci		adev->acp.acp_res[4].name = "acp2x_dma_irq";
41462306a36Sopenharmony_ci		adev->acp.acp_res[4].flags = IORESOURCE_IRQ;
41562306a36Sopenharmony_ci		adev->acp.acp_res[4].start = amdgpu_irq_create_mapping(adev, 162);
41662306a36Sopenharmony_ci		adev->acp.acp_res[4].end = adev->acp.acp_res[4].start;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		adev->acp.acp_cell[0].name = "acp_audio_dma";
41962306a36Sopenharmony_ci		adev->acp.acp_cell[0].num_resources = 5;
42062306a36Sopenharmony_ci		adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0];
42162306a36Sopenharmony_ci		adev->acp.acp_cell[0].platform_data = &adev->asic_type;
42262306a36Sopenharmony_ci		adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci		adev->acp.acp_cell[1].name = "designware-i2s";
42562306a36Sopenharmony_ci		adev->acp.acp_cell[1].num_resources = 1;
42662306a36Sopenharmony_ci		adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1];
42762306a36Sopenharmony_ci		adev->acp.acp_cell[1].platform_data = &i2s_pdata[0];
42862306a36Sopenharmony_ci		adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data);
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci		adev->acp.acp_cell[2].name = "designware-i2s";
43162306a36Sopenharmony_ci		adev->acp.acp_cell[2].num_resources = 1;
43262306a36Sopenharmony_ci		adev->acp.acp_cell[2].resources = &adev->acp.acp_res[2];
43362306a36Sopenharmony_ci		adev->acp.acp_cell[2].platform_data = &i2s_pdata[1];
43462306a36Sopenharmony_ci		adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci		adev->acp.acp_cell[3].name = "designware-i2s";
43762306a36Sopenharmony_ci		adev->acp.acp_cell[3].num_resources = 1;
43862306a36Sopenharmony_ci		adev->acp.acp_cell[3].resources = &adev->acp.acp_res[3];
43962306a36Sopenharmony_ci		adev->acp.acp_cell[3].platform_data = &i2s_pdata[2];
44062306a36Sopenharmony_ci		adev->acp.acp_cell[3].pdata_size = sizeof(struct i2s_platform_data);
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_ci		r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, ACP_DEVS);
44362306a36Sopenharmony_ci		if (r)
44462306a36Sopenharmony_ci			goto failure;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci		r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd,
44762306a36Sopenharmony_ci					  acp_genpd_add_device);
44862306a36Sopenharmony_ci		if (r)
44962306a36Sopenharmony_ci			goto failure;
45062306a36Sopenharmony_ci	}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	/* Assert Soft reset of ACP */
45362306a36Sopenharmony_ci	val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	val |= ACP_SOFT_RESET__SoftResetAud_MASK;
45662306a36Sopenharmony_ci	cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE;
45962306a36Sopenharmony_ci	while (true) {
46062306a36Sopenharmony_ci		val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
46162306a36Sopenharmony_ci		if (ACP_SOFT_RESET__SoftResetAudDone_MASK ==
46262306a36Sopenharmony_ci		    (val & ACP_SOFT_RESET__SoftResetAudDone_MASK))
46362306a36Sopenharmony_ci			break;
46462306a36Sopenharmony_ci		if (--count == 0) {
46562306a36Sopenharmony_ci			dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
46662306a36Sopenharmony_ci			r = -ETIMEDOUT;
46762306a36Sopenharmony_ci			goto failure;
46862306a36Sopenharmony_ci		}
46962306a36Sopenharmony_ci		udelay(100);
47062306a36Sopenharmony_ci	}
47162306a36Sopenharmony_ci	/* Enable clock to ACP and wait until the clock is enabled */
47262306a36Sopenharmony_ci	val = cgs_read_register(adev->acp.cgs_device, mmACP_CONTROL);
47362306a36Sopenharmony_ci	val = val | ACP_CONTROL__ClkEn_MASK;
47462306a36Sopenharmony_ci	cgs_write_register(adev->acp.cgs_device, mmACP_CONTROL, val);
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	count = ACP_CLOCK_EN_TIME_OUT_VALUE;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	while (true) {
47962306a36Sopenharmony_ci		val = cgs_read_register(adev->acp.cgs_device, mmACP_STATUS);
48062306a36Sopenharmony_ci		if (val & (u32) 0x1)
48162306a36Sopenharmony_ci			break;
48262306a36Sopenharmony_ci		if (--count == 0) {
48362306a36Sopenharmony_ci			dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
48462306a36Sopenharmony_ci			r = -ETIMEDOUT;
48562306a36Sopenharmony_ci			goto failure;
48662306a36Sopenharmony_ci		}
48762306a36Sopenharmony_ci		udelay(100);
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci	/* Deassert the SOFT RESET flags */
49062306a36Sopenharmony_ci	val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
49162306a36Sopenharmony_ci	val &= ~ACP_SOFT_RESET__SoftResetAud_MASK;
49262306a36Sopenharmony_ci	cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
49362306a36Sopenharmony_ci	return 0;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_cifailure:
49662306a36Sopenharmony_ci	kfree(i2s_pdata);
49762306a36Sopenharmony_ci	kfree(adev->acp.acp_res);
49862306a36Sopenharmony_ci	kfree(adev->acp.acp_cell);
49962306a36Sopenharmony_ci	kfree(adev->acp.acp_genpd);
50062306a36Sopenharmony_ci	return r;
50162306a36Sopenharmony_ci}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci/**
50462306a36Sopenharmony_ci * acp_hw_fini - stop the hardware block
50562306a36Sopenharmony_ci *
50662306a36Sopenharmony_ci * @handle: handle used to pass amdgpu_device pointer
50762306a36Sopenharmony_ci *
50862306a36Sopenharmony_ci */
50962306a36Sopenharmony_cistatic int acp_hw_fini(void *handle)
51062306a36Sopenharmony_ci{
51162306a36Sopenharmony_ci	u32 val = 0;
51262306a36Sopenharmony_ci	u32 count = 0;
51362306a36Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	/* return early if no ACP */
51662306a36Sopenharmony_ci	if (!adev->acp.acp_genpd) {
51762306a36Sopenharmony_ci		amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
51862306a36Sopenharmony_ci		return 0;
51962306a36Sopenharmony_ci	}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	/* Assert Soft reset of ACP */
52262306a36Sopenharmony_ci	val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	val |= ACP_SOFT_RESET__SoftResetAud_MASK;
52562306a36Sopenharmony_ci	cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val);
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE;
52862306a36Sopenharmony_ci	while (true) {
52962306a36Sopenharmony_ci		val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET);
53062306a36Sopenharmony_ci		if (ACP_SOFT_RESET__SoftResetAudDone_MASK ==
53162306a36Sopenharmony_ci		    (val & ACP_SOFT_RESET__SoftResetAudDone_MASK))
53262306a36Sopenharmony_ci			break;
53362306a36Sopenharmony_ci		if (--count == 0) {
53462306a36Sopenharmony_ci			dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
53562306a36Sopenharmony_ci			return -ETIMEDOUT;
53662306a36Sopenharmony_ci		}
53762306a36Sopenharmony_ci		udelay(100);
53862306a36Sopenharmony_ci	}
53962306a36Sopenharmony_ci	/* Disable ACP clock */
54062306a36Sopenharmony_ci	val = cgs_read_register(adev->acp.cgs_device, mmACP_CONTROL);
54162306a36Sopenharmony_ci	val &= ~ACP_CONTROL__ClkEn_MASK;
54262306a36Sopenharmony_ci	cgs_write_register(adev->acp.cgs_device, mmACP_CONTROL, val);
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	count = ACP_CLOCK_EN_TIME_OUT_VALUE;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	while (true) {
54762306a36Sopenharmony_ci		val = cgs_read_register(adev->acp.cgs_device, mmACP_STATUS);
54862306a36Sopenharmony_ci		if (val & (u32) 0x1)
54962306a36Sopenharmony_ci			break;
55062306a36Sopenharmony_ci		if (--count == 0) {
55162306a36Sopenharmony_ci			dev_err(&adev->pdev->dev, "Failed to reset ACP\n");
55262306a36Sopenharmony_ci			return -ETIMEDOUT;
55362306a36Sopenharmony_ci		}
55462306a36Sopenharmony_ci		udelay(100);
55562306a36Sopenharmony_ci	}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci	device_for_each_child(adev->acp.parent, NULL,
55862306a36Sopenharmony_ci			      acp_genpd_remove_device);
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	mfd_remove_devices(adev->acp.parent);
56162306a36Sopenharmony_ci	kfree(adev->acp.acp_res);
56262306a36Sopenharmony_ci	kfree(adev->acp.acp_genpd);
56362306a36Sopenharmony_ci	kfree(adev->acp.acp_cell);
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	return 0;
56662306a36Sopenharmony_ci}
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_cistatic int acp_suspend(void *handle)
56962306a36Sopenharmony_ci{
57062306a36Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	/* power up on suspend */
57362306a36Sopenharmony_ci	if (!adev->acp.acp_cell)
57462306a36Sopenharmony_ci		amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false);
57562306a36Sopenharmony_ci	return 0;
57662306a36Sopenharmony_ci}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_cistatic int acp_resume(void *handle)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	/* power down again on resume */
58362306a36Sopenharmony_ci	if (!adev->acp.acp_cell)
58462306a36Sopenharmony_ci		amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true);
58562306a36Sopenharmony_ci	return 0;
58662306a36Sopenharmony_ci}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_cistatic int acp_early_init(void *handle)
58962306a36Sopenharmony_ci{
59062306a36Sopenharmony_ci	return 0;
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cistatic bool acp_is_idle(void *handle)
59462306a36Sopenharmony_ci{
59562306a36Sopenharmony_ci	return true;
59662306a36Sopenharmony_ci}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_cistatic int acp_wait_for_idle(void *handle)
59962306a36Sopenharmony_ci{
60062306a36Sopenharmony_ci	return 0;
60162306a36Sopenharmony_ci}
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_cistatic int acp_soft_reset(void *handle)
60462306a36Sopenharmony_ci{
60562306a36Sopenharmony_ci	return 0;
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_cistatic int acp_set_clockgating_state(void *handle,
60962306a36Sopenharmony_ci				     enum amd_clockgating_state state)
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	return 0;
61262306a36Sopenharmony_ci}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_cistatic int acp_set_powergating_state(void *handle,
61562306a36Sopenharmony_ci				     enum amd_powergating_state state)
61662306a36Sopenharmony_ci{
61762306a36Sopenharmony_ci	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
61862306a36Sopenharmony_ci	bool enable = (state == AMD_PG_STATE_GATE);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable);
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	return 0;
62362306a36Sopenharmony_ci}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_cistatic const struct amd_ip_funcs acp_ip_funcs = {
62662306a36Sopenharmony_ci	.name = "acp_ip",
62762306a36Sopenharmony_ci	.early_init = acp_early_init,
62862306a36Sopenharmony_ci	.late_init = NULL,
62962306a36Sopenharmony_ci	.sw_init = acp_sw_init,
63062306a36Sopenharmony_ci	.sw_fini = acp_sw_fini,
63162306a36Sopenharmony_ci	.hw_init = acp_hw_init,
63262306a36Sopenharmony_ci	.hw_fini = acp_hw_fini,
63362306a36Sopenharmony_ci	.suspend = acp_suspend,
63462306a36Sopenharmony_ci	.resume = acp_resume,
63562306a36Sopenharmony_ci	.is_idle = acp_is_idle,
63662306a36Sopenharmony_ci	.wait_for_idle = acp_wait_for_idle,
63762306a36Sopenharmony_ci	.soft_reset = acp_soft_reset,
63862306a36Sopenharmony_ci	.set_clockgating_state = acp_set_clockgating_state,
63962306a36Sopenharmony_ci	.set_powergating_state = acp_set_powergating_state,
64062306a36Sopenharmony_ci};
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ciconst struct amdgpu_ip_block_version acp_ip_block = {
64362306a36Sopenharmony_ci	.type = AMD_IP_BLOCK_TYPE_ACP,
64462306a36Sopenharmony_ci	.major = 2,
64562306a36Sopenharmony_ci	.minor = 2,
64662306a36Sopenharmony_ci	.rev = 0,
64762306a36Sopenharmony_ci	.funcs = &acp_ip_funcs,
64862306a36Sopenharmony_ci};
649