pci-acp5x.c (4a7151c9688cc166ff6bf5a1a00e3cee429a2f11) | pci-acp5x.c (5d9ee88a10e854c5c43e0ae6b1bb0ff454cd45d1) |
---|---|
1// SPDX-License-Identifier: GPL-2.0+ 2// 3// AMD Vangogh ACP PCI Driver 4// 5// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. 6 7#include <linux/pci.h> 8#include <linux/module.h> 9#include <linux/io.h> | 1// SPDX-License-Identifier: GPL-2.0+ 2// 3// AMD Vangogh ACP PCI Driver 4// 5// Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. 6 7#include <linux/pci.h> 8#include <linux/module.h> 9#include <linux/io.h> |
10#include <linux/delay.h> |
|
10 11#include "acp5x.h" 12 13struct acp5x_dev_data { 14 void __iomem *acp5x_base; 15}; 16 | 11 12#include "acp5x.h" 13 14struct acp5x_dev_data { 15 void __iomem *acp5x_base; 16}; 17 |
18static int acp5x_power_on(void __iomem *acp5x_base) 19{ 20 u32 val; 21 int timeout; 22 23 val = acp_readl(acp5x_base + ACP_PGFSM_STATUS); 24 25 if (val == 0) 26 return val; 27 28 if ((val & ACP_PGFSM_STATUS_MASK) != 29 ACP_POWER_ON_IN_PROGRESS) 30 acp_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, 31 acp5x_base + ACP_PGFSM_CONTROL); 32 timeout = 0; 33 while (++timeout < 500) { 34 val = acp_readl(acp5x_base + ACP_PGFSM_STATUS); 35 if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_ON) 36 return 0; 37 udelay(1); 38 } 39 return -ETIMEDOUT; 40} 41 42static int acp5x_reset(void __iomem *acp5x_base) 43{ 44 u32 val; 45 int timeout; 46 47 acp_writel(1, acp5x_base + ACP_SOFT_RESET); 48 timeout = 0; 49 while (++timeout < 500) { 50 val = acp_readl(acp5x_base + ACP_SOFT_RESET); 51 if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) 52 break; 53 cpu_relax(); 54 } 55 acp_writel(0, acp5x_base + ACP_SOFT_RESET); 56 timeout = 0; 57 while (++timeout < 500) { 58 val = acp_readl(acp5x_base + ACP_SOFT_RESET); 59 if (!val) 60 return 0; 61 cpu_relax(); 62 } 63 return -ETIMEDOUT; 64} 65 66static void acp5x_enable_interrupts(void __iomem *acp5x_base) 67{ 68 acp_writel(0x01, acp5x_base + ACP_EXTERNAL_INTR_ENB); 69} 70 71static void acp5x_disable_interrupts(void __iomem *acp5x_base) 72{ 73 acp_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp5x_base + 74 ACP_EXTERNAL_INTR_STAT); 75 acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_CNTL); 76 acp_writel(0x00, acp5x_base + ACP_EXTERNAL_INTR_ENB); 77} 78 79static int acp5x_init(void __iomem *acp5x_base) 80{ 81 int ret; 82 83 /* power on */ 84 ret = acp5x_power_on(acp5x_base); 85 if (ret) { 86 pr_err("ACP5x power on failed\n"); 87 return ret; 88 } 89 /* Reset */ 90 ret = acp5x_reset(acp5x_base); 91 if (ret) { 92 pr_err("ACP5x reset failed\n"); 93 return ret; 94 } 95 acp5x_enable_interrupts(acp5x_base); 96 return 0; 97} 98 99static int acp5x_deinit(void __iomem *acp5x_base) 100{ 101 int ret; 102 103 acp5x_disable_interrupts(acp5x_base); 104 /* Reset */ 105 ret = acp5x_reset(acp5x_base); 106 if (ret) { 107 pr_err("ACP5x reset failed\n"); 108 return ret; 109 } 110 return 0; 111} 112 |
|
17static int snd_acp5x_probe(struct pci_dev *pci, 18 const struct pci_device_id *pci_id) 19{ 20 struct acp5x_dev_data *adata; 21 int ret; 22 u32 addr; 23 24 if (pci->revision != 0x50) --- 20 unchanged lines hidden (view full) --- 45 adata->acp5x_base = devm_ioremap(&pci->dev, addr, 46 pci_resource_len(pci, 0)); 47 if (!adata->acp5x_base) { 48 ret = -ENOMEM; 49 goto release_regions; 50 } 51 pci_set_master(pci); 52 pci_set_drvdata(pci, adata); | 113static int snd_acp5x_probe(struct pci_dev *pci, 114 const struct pci_device_id *pci_id) 115{ 116 struct acp5x_dev_data *adata; 117 int ret; 118 u32 addr; 119 120 if (pci->revision != 0x50) --- 20 unchanged lines hidden (view full) --- 141 adata->acp5x_base = devm_ioremap(&pci->dev, addr, 142 pci_resource_len(pci, 0)); 143 if (!adata->acp5x_base) { 144 ret = -ENOMEM; 145 goto release_regions; 146 } 147 pci_set_master(pci); 148 pci_set_drvdata(pci, adata); |
149 ret = acp5x_init(adata->acp5x_base); 150 if (ret) 151 goto release_regions; |
|
53 54release_regions: 55 pci_release_regions(pci); 56disable_pci: 57 pci_disable_device(pci); 58 59 return ret; 60} 61 62static void snd_acp5x_remove(struct pci_dev *pci) 63{ | 152 153release_regions: 154 pci_release_regions(pci); 155disable_pci: 156 pci_disable_device(pci); 157 158 return ret; 159} 160 161static void snd_acp5x_remove(struct pci_dev *pci) 162{ |
163 struct acp5x_dev_data *adata; 164 int ret; 165 166 adata = pci_get_drvdata(pci); 167 ret = acp5x_deinit(adata->acp5x_base); 168 if (ret) 169 dev_err(&pci->dev, "ACP de-init failed\n"); |
|
64 pci_release_regions(pci); 65 pci_disable_device(pci); 66} 67 68static const struct pci_device_id snd_acp5x_ids[] = { 69 { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), 70 .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, 71 .class_mask = 0xffffff }, --- 16 unchanged lines hidden --- | 170 pci_release_regions(pci); 171 pci_disable_device(pci); 172} 173 174static const struct pci_device_id snd_acp5x_ids[] = { 175 { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), 176 .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, 177 .class_mask = 0xffffff }, --- 16 unchanged lines hidden --- |