18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci/* 48c2ecf20Sopenharmony_ci * ACPI support for platform bus type. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2015, Linaro Ltd 78c2ecf20Sopenharmony_ci * Author: Graeme Gregory <graeme.gregory@linaro.org> 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/acpi.h> 118c2ecf20Sopenharmony_ci#include <linux/amba/bus.h> 128c2ecf20Sopenharmony_ci#include <linux/clkdev.h> 138c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 148c2ecf20Sopenharmony_ci#include <linux/device.h> 158c2ecf20Sopenharmony_ci#include <linux/err.h> 168c2ecf20Sopenharmony_ci#include <linux/ioport.h> 178c2ecf20Sopenharmony_ci#include <linux/kernel.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "internal.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistatic const struct acpi_device_id amba_id_list[] = { 238c2ecf20Sopenharmony_ci {"ARMH0061", 0}, /* PL061 GPIO Device */ 248c2ecf20Sopenharmony_ci {"ARMHC500", 0}, /* ARM CoreSight ETM4x */ 258c2ecf20Sopenharmony_ci {"ARMHC501", 0}, /* ARM CoreSight ETR */ 268c2ecf20Sopenharmony_ci {"ARMHC502", 0}, /* ARM CoreSight STM */ 278c2ecf20Sopenharmony_ci {"ARMHC503", 0}, /* ARM CoreSight Debug */ 288c2ecf20Sopenharmony_ci {"ARMHC979", 0}, /* ARM CoreSight TPIU */ 298c2ecf20Sopenharmony_ci {"ARMHC97C", 0}, /* ARM CoreSight SoC-400 TMC, SoC-600 ETF/ETB */ 308c2ecf20Sopenharmony_ci {"ARMHC98D", 0}, /* ARM CoreSight Dynamic Replicator */ 318c2ecf20Sopenharmony_ci {"ARMHC9CA", 0}, /* ARM CoreSight CATU */ 328c2ecf20Sopenharmony_ci {"ARMHC9FF", 0}, /* ARM CoreSight Dynamic Funnel */ 338c2ecf20Sopenharmony_ci {"", 0}, 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic void amba_register_dummy_clk(void) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci static struct clk *amba_dummy_clk; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* If clock already registered */ 418c2ecf20Sopenharmony_ci if (amba_dummy_clk) 428c2ecf20Sopenharmony_ci return; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 0); 458c2ecf20Sopenharmony_ci clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic int amba_handler_attach(struct acpi_device *adev, 498c2ecf20Sopenharmony_ci const struct acpi_device_id *id) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci struct amba_device *dev; 528c2ecf20Sopenharmony_ci struct resource_entry *rentry; 538c2ecf20Sopenharmony_ci struct list_head resource_list; 548c2ecf20Sopenharmony_ci bool address_found = false; 558c2ecf20Sopenharmony_ci int irq_no = 0; 568c2ecf20Sopenharmony_ci int ret; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* If the ACPI node already has a physical device attached, skip it. */ 598c2ecf20Sopenharmony_ci if (adev->physical_node_count) 608c2ecf20Sopenharmony_ci return 0; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci dev = amba_device_alloc(dev_name(&adev->dev), 0, 0); 638c2ecf20Sopenharmony_ci if (!dev) { 648c2ecf20Sopenharmony_ci dev_err(&adev->dev, "%s(): amba_device_alloc() failed\n", 658c2ecf20Sopenharmony_ci __func__); 668c2ecf20Sopenharmony_ci return -ENOMEM; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&resource_list); 708c2ecf20Sopenharmony_ci ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL); 718c2ecf20Sopenharmony_ci if (ret < 0) 728c2ecf20Sopenharmony_ci goto err_free; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci list_for_each_entry(rentry, &resource_list, node) { 758c2ecf20Sopenharmony_ci switch (resource_type(rentry->res)) { 768c2ecf20Sopenharmony_ci case IORESOURCE_MEM: 778c2ecf20Sopenharmony_ci if (!address_found) { 788c2ecf20Sopenharmony_ci dev->res = *rentry->res; 798c2ecf20Sopenharmony_ci dev->res.name = dev_name(&dev->dev); 808c2ecf20Sopenharmony_ci address_found = true; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci break; 838c2ecf20Sopenharmony_ci case IORESOURCE_IRQ: 848c2ecf20Sopenharmony_ci if (irq_no < AMBA_NR_IRQS) 858c2ecf20Sopenharmony_ci dev->irq[irq_no++] = rentry->res->start; 868c2ecf20Sopenharmony_ci break; 878c2ecf20Sopenharmony_ci default: 888c2ecf20Sopenharmony_ci dev_warn(&adev->dev, "Invalid resource\n"); 898c2ecf20Sopenharmony_ci break; 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci acpi_dev_free_resource_list(&resource_list); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* 968c2ecf20Sopenharmony_ci * If the ACPI node has a parent and that parent has a physical device 978c2ecf20Sopenharmony_ci * attached to it, that physical device should be the parent of 988c2ecf20Sopenharmony_ci * the amba device we are about to create. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ci if (adev->parent) 1018c2ecf20Sopenharmony_ci dev->dev.parent = acpi_get_first_physical_node(adev->parent); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci ACPI_COMPANION_SET(&dev->dev, adev); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci ret = amba_device_add(dev, &iomem_resource); 1068c2ecf20Sopenharmony_ci if (ret) { 1078c2ecf20Sopenharmony_ci dev_err(&adev->dev, "%s(): amba_device_add() failed (%d)\n", 1088c2ecf20Sopenharmony_ci __func__, ret); 1098c2ecf20Sopenharmony_ci goto err_free; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return 1; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cierr_free: 1158c2ecf20Sopenharmony_ci amba_device_put(dev); 1168c2ecf20Sopenharmony_ci return ret; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic struct acpi_scan_handler amba_handler = { 1208c2ecf20Sopenharmony_ci .ids = amba_id_list, 1218c2ecf20Sopenharmony_ci .attach = amba_handler_attach, 1228c2ecf20Sopenharmony_ci}; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_civoid __init acpi_amba_init(void) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci amba_register_dummy_clk(); 1278c2ecf20Sopenharmony_ci acpi_scan_add_handler(&amba_handler); 1288c2ecf20Sopenharmony_ci} 129