cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

acp-pci.c (3843B)


      1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
      2//
      3// This file is provided under a dual BSD/GPLv2 license. When using or
      4// redistributing this file, you may do so under either license.
      5//
      6// Copyright(c) 2022 Advanced Micro Devices, Inc. All rights reserved.
      7//
      8// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
      9
     10/*
     11 * Generic PCI interface for ACP device
     12 */
     13
     14#include <linux/delay.h>
     15#include <linux/interrupt.h>
     16#include <linux/pci.h>
     17#include <linux/platform_device.h>
     18#include <linux/pm_runtime.h>
     19#include <linux/module.h>
     20
     21#include "amd.h"
     22#include "../mach-config.h"
     23
     24#define DRV_NAME "acp_pci"
     25
     26#define ACP3x_REG_START	0x1240000
     27#define ACP3x_REG_END	0x125C000
     28
     29static struct platform_device *dmic_dev;
     30static struct platform_device *pdev;
     31
     32static const struct resource acp3x_res[] = {
     33	{
     34		.start = 0,
     35		.end = ACP3x_REG_END - ACP3x_REG_START,
     36		.name = "acp_mem",
     37		.flags = IORESOURCE_MEM,
     38	},
     39	{
     40		.start = 0,
     41		.end = 0,
     42		.name = "acp_dai_irq",
     43		.flags = IORESOURCE_IRQ,
     44	},
     45};
     46
     47static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
     48{
     49	struct platform_device_info pdevinfo;
     50	struct device *dev = &pci->dev;
     51	const struct resource *res_acp;
     52	struct acp_chip_info *chip;
     53	struct resource *res;
     54	unsigned int flag, addr, num_res, i;
     55	int ret;
     56
     57	flag = snd_amd_acp_find_config(pci);
     58	if (flag != FLAG_AMD_LEGACY)
     59		return -ENODEV;
     60
     61	chip = devm_kzalloc(&pci->dev, sizeof(*chip), GFP_KERNEL);
     62	if (!chip)
     63		return -ENOMEM;
     64
     65	if (pci_enable_device(pci)) {
     66		dev_err(&pci->dev, "pci_enable_device failed\n");
     67		return -ENODEV;
     68	}
     69
     70	ret = pci_request_regions(pci, "AMD ACP3x audio");
     71	if (ret < 0) {
     72		dev_err(&pci->dev, "pci_request_regions failed\n");
     73		return -ENOMEM;
     74	}
     75
     76	pci_set_master(pci);
     77
     78	switch (pci->revision) {
     79	case 0x01:
     80		res_acp = acp3x_res;
     81		num_res = ARRAY_SIZE(acp3x_res);
     82		chip->name = "acp_asoc_renoir";
     83		chip->acp_rev = ACP3X_DEV;
     84		break;
     85	default:
     86		dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
     87		return -EINVAL;
     88	}
     89
     90	dmic_dev = platform_device_register_data(dev, "dmic-codec", PLATFORM_DEVID_NONE, NULL, 0);
     91	if (IS_ERR(dmic_dev)) {
     92		dev_err(dev, "failed to create DMIC device\n");
     93		return PTR_ERR(dmic_dev);
     94	}
     95
     96	addr = pci_resource_start(pci, 0);
     97	chip->base = devm_ioremap(&pci->dev, addr, pci_resource_len(pci, 0));
     98
     99	res = devm_kzalloc(&pci->dev, sizeof(struct resource) * num_res, GFP_KERNEL);
    100	if (!res) {
    101		platform_device_unregister(dmic_dev);
    102		return -ENOMEM;
    103	}
    104
    105	for (i = 0; i < num_res; i++, res_acp++) {
    106		res[i].name = res_acp->name;
    107		res[i].flags = res_acp->flags;
    108		res[i].start = addr + res_acp->start;
    109		res[i].end = addr + res_acp->end;
    110		if (res_acp->flags == IORESOURCE_IRQ) {
    111			res[i].start = pci->irq;
    112			res[i].end = res[i].start;
    113		}
    114	}
    115
    116	memset(&pdevinfo, 0, sizeof(pdevinfo));
    117
    118	pdevinfo.name = chip->name;
    119	pdevinfo.id = 0;
    120	pdevinfo.parent = &pci->dev;
    121	pdevinfo.num_res = num_res;
    122	pdevinfo.res = &res[0];
    123	pdevinfo.data = chip;
    124	pdevinfo.size_data = sizeof(*chip);
    125
    126	pdev = platform_device_register_full(&pdevinfo);
    127	if (IS_ERR(pdev)) {
    128		dev_err(&pci->dev, "cannot register %s device\n", pdevinfo.name);
    129		platform_device_unregister(dmic_dev);
    130		ret = PTR_ERR(pdev);
    131	}
    132
    133	return ret;
    134};
    135
    136static void acp_pci_remove(struct pci_dev *pci)
    137{
    138	if (dmic_dev)
    139		platform_device_unregister(dmic_dev);
    140	if (pdev)
    141		platform_device_unregister(pdev);
    142}
    143
    144/* PCI IDs */
    145static const struct pci_device_id acp_pci_ids[] = {
    146	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_PCI_DEV_ID)},
    147	{ 0, }
    148};
    149MODULE_DEVICE_TABLE(pci, acp_pci_ids);
    150
    151/* pci_driver definition */
    152static struct pci_driver snd_amd_acp_pci_driver = {
    153	.name = KBUILD_MODNAME,
    154	.id_table = acp_pci_ids,
    155	.probe = acp_pci_probe,
    156	.remove = acp_pci_remove,
    157};
    158module_pci_driver(snd_amd_acp_pci_driver);
    159
    160MODULE_LICENSE("Dual BSD/GPL");
    161MODULE_ALIAS(DRV_NAME);