linux/drivers/acpi/acpi_amba.c
<<
>>
Prefs
   1
   2/*
   3 * ACPI support for platform bus type.
   4 *
   5 * Copyright (C) 2015, Linaro Ltd
   6 * Author: Graeme Gregory <graeme.gregory@linaro.org>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/acpi.h>
  14#include <linux/amba/bus.h>
  15#include <linux/clkdev.h>
  16#include <linux/clk-provider.h>
  17#include <linux/device.h>
  18#include <linux/err.h>
  19#include <linux/ioport.h>
  20#include <linux/kernel.h>
  21#include <linux/module.h>
  22
  23#include "internal.h"
  24
  25static const struct acpi_device_id amba_id_list[] = {
  26        {"ARMH0061", 0}, /* PL061 GPIO Device */
  27        {"", 0},
  28};
  29
  30static void amba_register_dummy_clk(void)
  31{
  32        static struct clk *amba_dummy_clk;
  33
  34        /* If clock already registered */
  35        if (amba_dummy_clk)
  36                return;
  37
  38        amba_dummy_clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, 0, 0);
  39        clk_register_clkdev(amba_dummy_clk, "apb_pclk", NULL);
  40}
  41
  42static int amba_handler_attach(struct acpi_device *adev,
  43                                const struct acpi_device_id *id)
  44{
  45        struct amba_device *dev;
  46        struct resource_entry *rentry;
  47        struct list_head resource_list;
  48        bool address_found = false;
  49        int irq_no = 0;
  50        int ret;
  51
  52        /* If the ACPI node already has a physical device attached, skip it. */
  53        if (adev->physical_node_count)
  54                return 0;
  55
  56        dev = amba_device_alloc(dev_name(&adev->dev), 0, 0);
  57        if (!dev) {
  58                dev_err(&adev->dev, "%s(): amba_device_alloc() failed\n",
  59                        __func__);
  60                return -ENOMEM;
  61        }
  62
  63        INIT_LIST_HEAD(&resource_list);
  64        ret = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
  65        if (ret < 0)
  66                goto err_free;
  67
  68        list_for_each_entry(rentry, &resource_list, node) {
  69                switch (resource_type(rentry->res)) {
  70                case IORESOURCE_MEM:
  71                        if (!address_found) {
  72                                dev->res = *rentry->res;
  73                                address_found = true;
  74                        }
  75                        break;
  76                case IORESOURCE_IRQ:
  77                        if (irq_no < AMBA_NR_IRQS)
  78                                dev->irq[irq_no++] = rentry->res->start;
  79                        break;
  80                default:
  81                        dev_warn(&adev->dev, "Invalid resource\n");
  82                        break;
  83                }
  84        }
  85
  86        acpi_dev_free_resource_list(&resource_list);
  87
  88        /*
  89         * If the ACPI node has a parent and that parent has a physical device
  90         * attached to it, that physical device should be the parent of
  91         * the amba device we are about to create.
  92         */
  93        if (adev->parent)
  94                dev->dev.parent = acpi_get_first_physical_node(adev->parent);
  95
  96        ACPI_COMPANION_SET(&dev->dev, adev);
  97
  98        ret = amba_device_add(dev, &iomem_resource);
  99        if (ret) {
 100                dev_err(&adev->dev, "%s(): amba_device_add() failed (%d)\n",
 101                       __func__, ret);
 102                goto err_free;
 103        }
 104
 105        return 1;
 106
 107err_free:
 108        amba_device_put(dev);
 109        return ret;
 110}
 111
 112static struct acpi_scan_handler amba_handler = {
 113        .ids = amba_id_list,
 114        .attach = amba_handler_attach,
 115};
 116
 117void __init acpi_amba_init(void)
 118{
 119        amba_register_dummy_clk();
 120        acpi_scan_add_handler(&amba_handler);
 121}
 122