1 // SPDX-License-Identifier: GPL-2.0+ 2 // 3 // AMD Renoir ACP PCI Driver 4 // 5 //Copyright 2020 Advanced Micro Devices, Inc. 6 7 #include <linux/pci.h> 8 #include <linux/module.h> 9 #include <linux/io.h> 10 #include <linux/delay.h> 11 #include <linux/platform_device.h> 12 #include <linux/interrupt.h> 13 #include <linux/pm_runtime.h> 14 15 #include "rn_acp3x.h" 16 17 static int acp_power_gating; 18 module_param(acp_power_gating, int, 0644); 19 MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); 20 21 struct acp_dev_data { 22 void __iomem *acp_base; 23 struct resource *res; 24 struct platform_device *pdev[ACP_DEVS]; 25 }; 26 27 static int rn_acp_power_on(void __iomem *acp_base) 28 { 29 u32 val; 30 int timeout; 31 32 val = rn_readl(acp_base + ACP_PGFSM_STATUS); 33 34 if (val == 0) 35 return val; 36 37 if ((val & ACP_PGFSM_STATUS_MASK) != 38 ACP_POWER_ON_IN_PROGRESS) 39 rn_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, 40 acp_base + ACP_PGFSM_CONTROL); 41 timeout = 0; 42 while (++timeout < 500) { 43 val = rn_readl(acp_base + ACP_PGFSM_STATUS); 44 if (!val) 45 return 0; 46 udelay(1); 47 } 48 return -ETIMEDOUT; 49 } 50 51 static int rn_acp_power_off(void __iomem *acp_base) 52 { 53 u32 val; 54 int timeout; 55 56 rn_writel(ACP_PGFSM_CNTL_POWER_OFF_MASK, 57 acp_base + ACP_PGFSM_CONTROL); 58 timeout = 0; 59 while (++timeout < 500) { 60 val = rn_readl(acp_base + ACP_PGFSM_STATUS); 61 if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF) 62 return 0; 63 udelay(1); 64 } 65 return -ETIMEDOUT; 66 } 67 68 static int rn_acp_reset(void __iomem *acp_base) 69 { 70 u32 val; 71 int timeout; 72 73 rn_writel(1, acp_base + ACP_SOFT_RESET); 74 timeout = 0; 75 while (++timeout < 500) { 76 val = rn_readl(acp_base + ACP_SOFT_RESET); 77 if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) 78 break; 79 cpu_relax(); 80 } 81 rn_writel(0, acp_base + ACP_SOFT_RESET); 82 timeout = 0; 83 while (++timeout < 500) { 84 val = rn_readl(acp_base + ACP_SOFT_RESET); 85 if (!val) 86 return 0; 87 cpu_relax(); 88 } 89 return -ETIMEDOUT; 90 } 91 92 static void rn_acp_enable_interrupts(void __iomem *acp_base) 93 { 94 u32 ext_intr_ctrl; 95 96 rn_writel(0x01, acp_base + ACP_EXTERNAL_INTR_ENB); 97 ext_intr_ctrl = rn_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); 98 ext_intr_ctrl |= ACP_ERROR_MASK; 99 rn_writel(ext_intr_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); 100 } 101 102 static void rn_acp_disable_interrupts(void __iomem *acp_base) 103 { 104 rn_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + 105 ACP_EXTERNAL_INTR_STAT); 106 rn_writel(0x00, acp_base + ACP_EXTERNAL_INTR_ENB); 107 } 108 109 static int rn_acp_init(void __iomem *acp_base) 110 { 111 int ret; 112 113 /* power on */ 114 ret = rn_acp_power_on(acp_base); 115 if (ret) { 116 pr_err("ACP power on failed\n"); 117 return ret; 118 } 119 rn_writel(0x01, acp_base + ACP_CONTROL); 120 /* Reset */ 121 ret = rn_acp_reset(acp_base); 122 if (ret) { 123 pr_err("ACP reset failed\n"); 124 return ret; 125 } 126 rn_writel(0x03, acp_base + ACP_CLKMUX_SEL); 127 rn_acp_enable_interrupts(acp_base); 128 return 0; 129 } 130 131 static int rn_acp_deinit(void __iomem *acp_base) 132 { 133 int ret; 134 135 rn_acp_disable_interrupts(acp_base); 136 /* Reset */ 137 ret = rn_acp_reset(acp_base); 138 if (ret) { 139 pr_err("ACP reset failed\n"); 140 return ret; 141 } 142 rn_writel(0x00, acp_base + ACP_CLKMUX_SEL); 143 rn_writel(0x00, acp_base + ACP_CONTROL); 144 /* power off */ 145 if (acp_power_gating) { 146 ret = rn_acp_power_off(acp_base); 147 if (ret) { 148 pr_err("ACP power off failed\n"); 149 return ret; 150 } 151 } 152 return 0; 153 } 154 155 static int snd_rn_acp_probe(struct pci_dev *pci, 156 const struct pci_device_id *pci_id) 157 { 158 struct acp_dev_data *adata; 159 struct platform_device_info pdevinfo[ACP_DEVS]; 160 unsigned int irqflags; 161 int ret, index; 162 u32 addr; 163 164 if (pci_enable_device(pci)) { 165 dev_err(&pci->dev, "pci_enable_device failed\n"); 166 return -ENODEV; 167 } 168 169 ret = pci_request_regions(pci, "AMD ACP3x audio"); 170 if (ret < 0) { 171 dev_err(&pci->dev, "pci_request_regions failed\n"); 172 goto disable_pci; 173 } 174 175 adata = devm_kzalloc(&pci->dev, sizeof(struct acp_dev_data), 176 GFP_KERNEL); 177 if (!adata) { 178 ret = -ENOMEM; 179 goto release_regions; 180 } 181 182 /* check for msi interrupt support */ 183 ret = pci_enable_msi(pci); 184 if (ret) 185 /* msi is not enabled */ 186 irqflags = IRQF_SHARED; 187 else 188 /* msi is enabled */ 189 irqflags = 0; 190 191 addr = pci_resource_start(pci, 0); 192 adata->acp_base = devm_ioremap(&pci->dev, addr, 193 pci_resource_len(pci, 0)); 194 if (!adata->acp_base) { 195 ret = -ENOMEM; 196 goto disable_msi; 197 } 198 pci_set_master(pci); 199 pci_set_drvdata(pci, adata); 200 ret = rn_acp_init(adata->acp_base); 201 if (ret) 202 goto disable_msi; 203 204 adata->res = devm_kzalloc(&pci->dev, 205 sizeof(struct resource) * 2, 206 GFP_KERNEL); 207 if (!adata->res) { 208 ret = -ENOMEM; 209 goto de_init; 210 } 211 212 adata->res[0].name = "acp_pdm_iomem"; 213 adata->res[0].flags = IORESOURCE_MEM; 214 adata->res[0].start = addr; 215 adata->res[0].end = addr + (ACP_REG_END - ACP_REG_START); 216 adata->res[1].name = "acp_pdm_irq"; 217 adata->res[1].flags = IORESOURCE_IRQ; 218 adata->res[1].start = pci->irq; 219 adata->res[1].end = pci->irq; 220 221 memset(&pdevinfo, 0, sizeof(pdevinfo)); 222 pdevinfo[0].name = "acp_rn_pdm_dma"; 223 pdevinfo[0].id = 0; 224 pdevinfo[0].parent = &pci->dev; 225 pdevinfo[0].num_res = 2; 226 pdevinfo[0].res = adata->res; 227 pdevinfo[0].data = &irqflags; 228 pdevinfo[0].size_data = sizeof(irqflags); 229 230 pdevinfo[1].name = "dmic-codec"; 231 pdevinfo[1].id = 0; 232 pdevinfo[1].parent = &pci->dev; 233 pdevinfo[2].name = "acp_pdm_mach"; 234 pdevinfo[2].id = 0; 235 pdevinfo[2].parent = &pci->dev; 236 for (index = 0; index < ACP_DEVS; index++) { 237 adata->pdev[index] = 238 platform_device_register_full(&pdevinfo[index]); 239 if (IS_ERR(adata->pdev[index])) { 240 dev_err(&pci->dev, "cannot register %s device\n", 241 pdevinfo[index].name); 242 ret = PTR_ERR(adata->pdev[index]); 243 goto unregister_devs; 244 } 245 } 246 pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); 247 pm_runtime_use_autosuspend(&pci->dev); 248 pm_runtime_put_noidle(&pci->dev); 249 pm_runtime_allow(&pci->dev); 250 return 0; 251 252 unregister_devs: 253 for (index = 0; index < ACP_DEVS; index++) 254 platform_device_unregister(adata->pdev[index]); 255 de_init: 256 if (rn_acp_deinit(adata->acp_base)) 257 dev_err(&pci->dev, "ACP de-init failed\n"); 258 disable_msi: 259 pci_disable_msi(pci); 260 release_regions: 261 pci_release_regions(pci); 262 disable_pci: 263 pci_disable_device(pci); 264 265 return ret; 266 } 267 268 static int snd_rn_acp_suspend(struct device *dev) 269 { 270 int ret; 271 struct acp_dev_data *adata; 272 273 adata = dev_get_drvdata(dev); 274 ret = rn_acp_deinit(adata->acp_base); 275 if (ret) 276 dev_err(dev, "ACP de-init failed\n"); 277 else 278 dev_dbg(dev, "ACP de-initialized\n"); 279 280 return ret; 281 } 282 283 static int snd_rn_acp_resume(struct device *dev) 284 { 285 int ret; 286 struct acp_dev_data *adata; 287 288 adata = dev_get_drvdata(dev); 289 ret = rn_acp_init(adata->acp_base); 290 if (ret) { 291 dev_err(dev, "ACP init failed\n"); 292 return ret; 293 } 294 return 0; 295 } 296 297 static const struct dev_pm_ops rn_acp_pm = { 298 .runtime_suspend = snd_rn_acp_suspend, 299 .runtime_resume = snd_rn_acp_resume, 300 .suspend = snd_rn_acp_suspend, 301 .resume = snd_rn_acp_resume, 302 }; 303 304 static void snd_rn_acp_remove(struct pci_dev *pci) 305 { 306 struct acp_dev_data *adata; 307 int ret, index; 308 309 adata = pci_get_drvdata(pci); 310 for (index = 0; index < ACP_DEVS; index++) 311 platform_device_unregister(adata->pdev[index]); 312 ret = rn_acp_deinit(adata->acp_base); 313 if (ret) 314 dev_err(&pci->dev, "ACP de-init failed\n"); 315 pm_runtime_forbid(&pci->dev); 316 pm_runtime_get_noresume(&pci->dev); 317 pci_disable_msi(pci); 318 pci_release_regions(pci); 319 pci_disable_device(pci); 320 } 321 322 static const struct pci_device_id snd_rn_acp_ids[] = { 323 { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), 324 .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, 325 .class_mask = 0xffffff }, 326 { 0, }, 327 }; 328 MODULE_DEVICE_TABLE(pci, snd_rn_acp_ids); 329 330 static struct pci_driver rn_acp_driver = { 331 .name = KBUILD_MODNAME, 332 .id_table = snd_rn_acp_ids, 333 .probe = snd_rn_acp_probe, 334 .remove = snd_rn_acp_remove, 335 .driver = { 336 .pm = &rn_acp_pm, 337 } 338 }; 339 340 module_pci_driver(rn_acp_driver); 341 342 MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); 343 MODULE_DESCRIPTION("AMD ACP Renoir PCI driver"); 344 MODULE_LICENSE("GPL v2"); 345