2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-01-20 17:29:27 +03:00
/*
* ACPI support for platform bus type .
*
* Copyright ( C ) 2015 , Linaro Ltd
* Author : Graeme Gregory < graeme . gregory @ linaro . org >
*/
# include <linux/acpi.h>
# include <linux/amba/bus.h>
# include <linux/clkdev.h>
# include <linux/clk-provider.h>
# include <linux/device.h>
# include <linux/err.h>
# include <linux/ioport.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include "internal.h"
static const struct acpi_device_id amba_id_list [ ] = {
{ " ARMH0061 " , 0 } , /* PL061 GPIO Device */
2019-06-19 22:53:07 +03:00
{ " ARMHC500 " , 0 } , /* ARM CoreSight ETM4x */
{ " ARMHC501 " , 0 } , /* ARM CoreSight ETR */
{ " ARMHC502 " , 0 } , /* ARM CoreSight STM */
{ " ARMHC503 " , 0 } , /* ARM CoreSight Debug */
{ " ARMHC979 " , 0 } , /* ARM CoreSight TPIU */
{ " ARMHC97C " , 0 } , /* ARM CoreSight SoC-400 TMC, SoC-600 ETF/ETB */
{ " ARMHC98D " , 0 } , /* ARM CoreSight Dynamic Replicator */
{ " ARMHC9CA " , 0 } , /* ARM CoreSight CATU */
{ " ARMHC9FF " , 0 } , /* ARM CoreSight Dynamic Funnel */
2016-01-20 17:29:27 +03:00
{ " " , 0 } ,
} ;
static void amba_register_dummy_clk ( void )
{
static struct clk * amba_dummy_clk ;
/* If clock already registered */
if ( amba_dummy_clk )
return ;
2016-04-20 04:28:38 +03:00
amba_dummy_clk = clk_register_fixed_rate ( NULL , " apb_pclk " , NULL , 0 , 0 ) ;
2016-01-20 17:29:27 +03:00
clk_register_clkdev ( amba_dummy_clk , " apb_pclk " , NULL ) ;
}
static int amba_handler_attach ( struct acpi_device * adev ,
const struct acpi_device_id * id )
{
struct amba_device * dev ;
struct resource_entry * rentry ;
struct list_head resource_list ;
bool address_found = false ;
int irq_no = 0 ;
int ret ;
/* If the ACPI node already has a physical device attached, skip it. */
if ( adev - > physical_node_count )
return 0 ;
dev = amba_device_alloc ( dev_name ( & adev - > dev ) , 0 , 0 ) ;
if ( ! dev ) {
dev_err ( & adev - > dev , " %s(): amba_device_alloc() failed \n " ,
__func__ ) ;
return - ENOMEM ;
}
INIT_LIST_HEAD ( & resource_list ) ;
ret = acpi_dev_get_resources ( adev , & resource_list , NULL , NULL ) ;
if ( ret < 0 )
goto err_free ;
list_for_each_entry ( rentry , & resource_list , node ) {
switch ( resource_type ( rentry - > res ) ) {
case IORESOURCE_MEM :
if ( ! address_found ) {
dev - > res = * rentry - > res ;
address_found = true ;
}
break ;
case IORESOURCE_IRQ :
if ( irq_no < AMBA_NR_IRQS )
dev - > irq [ irq_no + + ] = rentry - > res - > start ;
break ;
default :
dev_warn ( & adev - > dev , " Invalid resource \n " ) ;
break ;
}
}
acpi_dev_free_resource_list ( & resource_list ) ;
/*
* If the ACPI node has a parent and that parent has a physical device
* attached to it , that physical device should be the parent of
* the amba device we are about to create .
*/
if ( adev - > parent )
dev - > dev . parent = acpi_get_first_physical_node ( adev - > parent ) ;
ACPI_COMPANION_SET ( & dev - > dev , adev ) ;
ret = amba_device_add ( dev , & iomem_resource ) ;
if ( ret ) {
dev_err ( & adev - > dev , " %s(): amba_device_add() failed (%d) \n " ,
__func__ , ret ) ;
goto err_free ;
}
return 1 ;
err_free :
amba_device_put ( dev ) ;
return ret ;
}
static struct acpi_scan_handler amba_handler = {
. ids = amba_id_list ,
. attach = amba_handler_attach ,
} ;
void __init acpi_amba_init ( void )
{
amba_register_dummy_clk ( ) ;
acpi_scan_add_handler ( & amba_handler ) ;
}