2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-02-06 03:27:51 +03:00
/*
* AMD ACPI support for ACPI2platform device .
*
* Copyright ( c ) 2014 , 2015 AMD Corporation .
* Authors : Ken Xue < Ken . Xue @ amd . com >
* Wu , Jeff < Jeff . Wu @ amd . com >
*/
# include <linux/clk-provider.h>
2018-05-09 12:59:01 +03:00
# include <linux/platform_data/clk-st.h>
2015-02-06 03:27:51 +03:00
# include <linux/platform_device.h>
# include <linux/pm_domain.h>
# include <linux/clkdev.h>
# include <linux/acpi.h>
# include <linux/err.h>
2019-04-19 01:20:22 +03:00
# include <linux/io.h>
2015-02-06 03:27:51 +03:00
# include <linux/pm.h>
# include "internal.h"
ACPI_MODULE_NAME ( " acpi_apd " ) ;
struct apd_private_data ;
/**
* ACPI_APD_SYSFS : add device attributes in sysfs
* ACPI_APD_PM : attach power domain to device
*/
# define ACPI_APD_SYSFS BIT(0)
# define ACPI_APD_PM BIT(1)
/**
* struct apd_device_desc - a descriptor for apd device
* @ flags : device flags like % ACPI_APD_SYSFS , % ACPI_APD_PM
* @ fixed_clk_rate : fixed rate input clock source for acpi device ;
* 0 means no fixed rate input clock source
* @ setup : a hook routine to set device resource during create platform device
*
* Device description defined as acpi_device_id . driver_data
*/
struct apd_device_desc {
unsigned int flags ;
unsigned int fixed_clk_rate ;
2016-08-23 11:33:26 +03:00
struct property_entry * properties ;
2015-02-06 03:27:51 +03:00
int ( * setup ) ( struct apd_private_data * pdata ) ;
} ;
struct apd_private_data {
struct clk * clk ;
struct acpi_device * adev ;
const struct apd_device_desc * dev_desc ;
} ;
2015-12-11 00:19:16 +03:00
# if defined(CONFIG_X86_AMD_PLATFORM_DEVICE) || defined(CONFIG_ARM64)
2015-02-06 03:27:51 +03:00
# define APD_ADDR(desc) ((unsigned long)&desc)
static int acpi_apd_setup ( struct apd_private_data * pdata )
{
const struct apd_device_desc * dev_desc = pdata - > dev_desc ;
2019-07-02 16:10:29 +03:00
struct clk * clk ;
2015-02-06 03:27:51 +03:00
if ( dev_desc - > fixed_clk_rate ) {
clk = clk_register_fixed_rate ( & pdata - > adev - > dev ,
dev_name ( & pdata - > adev - > dev ) ,
2016-04-20 04:27:46 +03:00
NULL , 0 , dev_desc - > fixed_clk_rate ) ;
2015-02-06 03:27:51 +03:00
clk_register_clkdev ( clk , NULL , dev_name ( & pdata - > adev - > dev ) ) ;
pdata - > clk = clk ;
}
return 0 ;
}
2015-12-11 00:19:16 +03:00
# ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
2018-05-09 12:59:01 +03:00
static int misc_check_res ( struct acpi_resource * ares , void * data )
{
struct resource res ;
return ! acpi_dev_resource_memory ( ares , & res ) ;
}
static int st_misc_setup ( struct apd_private_data * pdata )
{
struct acpi_device * adev = pdata - > adev ;
struct platform_device * clkdev ;
struct st_clk_data * clk_data ;
struct resource_entry * rentry ;
struct list_head resource_list ;
int ret ;
clk_data = devm_kzalloc ( & adev - > dev , sizeof ( * clk_data ) , GFP_KERNEL ) ;
if ( ! clk_data )
return - ENOMEM ;
INIT_LIST_HEAD ( & resource_list ) ;
ret = acpi_dev_get_resources ( adev , & resource_list , misc_check_res ,
NULL ) ;
if ( ret < 0 )
return - ENOENT ;
list_for_each_entry ( rentry , & resource_list , node ) {
clk_data - > base = devm_ioremap ( & adev - > dev , rentry - > res - > start ,
resource_size ( rentry - > res ) ) ;
break ;
}
acpi_dev_free_resource_list ( & resource_list ) ;
clkdev = platform_device_register_data ( & adev - > dev , " clk-st " ,
PLATFORM_DEVID_NONE , clk_data ,
sizeof ( * clk_data ) ) ;
return PTR_ERR_OR_ZERO ( clkdev ) ;
}
2016-09-11 16:06:06 +03:00
static const struct apd_device_desc cz_i2c_desc = {
2015-02-06 03:27:51 +03:00
. setup = acpi_apd_setup ,
. fixed_clk_rate = 133000000 ,
} ;
2016-10-19 12:00:32 +03:00
static const struct apd_device_desc wt_i2c_desc = {
. setup = acpi_apd_setup ,
. fixed_clk_rate = 150000000 ,
} ;
2016-08-23 11:33:26 +03:00
static struct property_entry uart_properties [ ] = {
PROPERTY_ENTRY_U32 ( " reg-io-width " , 4 ) ,
PROPERTY_ENTRY_U32 ( " reg-shift " , 2 ) ,
PROPERTY_ENTRY_BOOL ( " snps,uart-16550-compatible " ) ,
{ } ,
} ;
2016-09-11 16:06:06 +03:00
static const struct apd_device_desc cz_uart_desc = {
2015-02-06 03:27:51 +03:00
. setup = acpi_apd_setup ,
. fixed_clk_rate = 48000000 ,
2016-08-23 11:33:26 +03:00
. properties = uart_properties ,
2015-02-06 03:27:51 +03:00
} ;
2018-05-09 12:59:01 +03:00
static const struct apd_device_desc st_misc_desc = {
. setup = st_misc_setup ,
} ;
2015-12-11 00:19:16 +03:00
# endif
# ifdef CONFIG_ARM64
2016-09-11 16:06:06 +03:00
static const struct apd_device_desc xgene_i2c_desc = {
2015-12-11 00:19:16 +03:00
. setup = acpi_apd_setup ,
. fixed_clk_rate = 100000000 ,
} ;
2016-08-09 17:05:21 +03:00
2016-09-11 16:06:06 +03:00
static const struct apd_device_desc vulcan_spi_desc = {
2016-08-09 17:05:21 +03:00
. setup = acpi_apd_setup ,
. fixed_clk_rate = 133000000 ,
} ;
2017-04-22 06:23:43 +03:00
static const struct apd_device_desc hip07_i2c_desc = {
. setup = acpi_apd_setup ,
. fixed_clk_rate = 200000000 ,
} ;
static const struct apd_device_desc hip08_i2c_desc = {
. setup = acpi_apd_setup ,
. fixed_clk_rate = 250000000 ,
} ;
2019-09-06 10:53:19 +03:00
2017-10-10 09:27:54 +03:00
static const struct apd_device_desc thunderx2_i2c_desc = {
. setup = acpi_apd_setup ,
. fixed_clk_rate = 125000000 ,
} ;
2018-12-03 06:15:49 +03:00
2019-09-06 10:53:19 +03:00
static const struct apd_device_desc nxp_i2c_desc = {
. setup = acpi_apd_setup ,
. fixed_clk_rate = 350000000 ,
} ;
2018-12-03 06:15:49 +03:00
static const struct apd_device_desc hip08_spi_desc = {
. setup = acpi_apd_setup ,
. fixed_clk_rate = 250000000 ,
} ;
2015-12-11 00:19:16 +03:00
# endif
2015-02-06 03:27:51 +03:00
# else
# define APD_ADDR(desc) (0UL)
# endif /* CONFIG_X86_AMD_PLATFORM_DEVICE */
/**
* Create platform device during acpi scan attach handle .
* Return value > 0 on success of creating device .
*/
static int acpi_apd_create_device ( struct acpi_device * adev ,
const struct acpi_device_id * id )
{
const struct apd_device_desc * dev_desc = ( void * ) id - > driver_data ;
struct apd_private_data * pdata ;
struct platform_device * pdev ;
int ret ;
if ( ! dev_desc ) {
2016-11-03 17:21:26 +03:00
pdev = acpi_create_platform_device ( adev , NULL ) ;
2015-02-06 03:27:51 +03:00
return IS_ERR_OR_NULL ( pdev ) ? PTR_ERR ( pdev ) : 1 ;
}
pdata = kzalloc ( sizeof ( * pdata ) , GFP_KERNEL ) ;
if ( ! pdata )
return - ENOMEM ;
pdata - > adev = adev ;
pdata - > dev_desc = dev_desc ;
if ( dev_desc - > setup ) {
ret = dev_desc - > setup ( pdata ) ;
if ( ret )
goto err_out ;
}
adev - > driver_data = pdata ;
2016-11-03 17:21:26 +03:00
pdev = acpi_create_platform_device ( adev , dev_desc - > properties ) ;
2015-02-06 03:27:51 +03:00
if ( ! IS_ERR_OR_NULL ( pdev ) )
return 1 ;
ret = PTR_ERR ( pdev ) ;
adev - > driver_data = NULL ;
err_out :
kfree ( pdata ) ;
return ret ;
}
static const struct acpi_device_id acpi_apd_device_ids [ ] = {
/* Generic apd devices */
2015-12-11 00:19:16 +03:00
# ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
2015-02-06 03:27:51 +03:00
{ " AMD0010 " , APD_ADDR ( cz_i2c_desc ) } ,
2016-10-19 12:00:32 +03:00
{ " AMDI0010 " , APD_ADDR ( wt_i2c_desc ) } ,
2015-02-06 03:27:51 +03:00
{ " AMD0020 " , APD_ADDR ( cz_uart_desc ) } ,
2016-03-11 12:28:23 +03:00
{ " AMDI0020 " , APD_ADDR ( cz_uart_desc ) } ,
2015-02-06 03:27:51 +03:00
{ " AMD0030 " , } ,
2018-05-09 12:59:01 +03:00
{ " AMD0040 " , APD_ADDR ( st_misc_desc ) } ,
2015-12-11 00:19:16 +03:00
# endif
# ifdef CONFIG_ARM64
{ " APMC0D0F " , APD_ADDR ( xgene_i2c_desc ) } ,
2016-08-09 17:05:21 +03:00
{ " BRCM900D " , APD_ADDR ( vulcan_spi_desc ) } ,
2017-03-12 14:11:43 +03:00
{ " CAV900D " , APD_ADDR ( vulcan_spi_desc ) } ,
2017-10-10 09:27:54 +03:00
{ " CAV9007 " , APD_ADDR ( thunderx2_i2c_desc ) } ,
2017-07-28 12:42:35 +03:00
{ " HISI02A1 " , APD_ADDR ( hip07_i2c_desc ) } ,
{ " HISI02A2 " , APD_ADDR ( hip08_i2c_desc ) } ,
2018-12-03 06:15:49 +03:00
{ " HISI0173 " , APD_ADDR ( hip08_spi_desc ) } ,
2019-09-06 10:53:19 +03:00
{ " NXP0001 " , APD_ADDR ( nxp_i2c_desc ) } ,
2015-12-11 00:19:16 +03:00
# endif
2015-02-06 03:27:51 +03:00
{ }
} ;
static struct acpi_scan_handler apd_handler = {
. ids = acpi_apd_device_ids ,
. attach = acpi_apd_create_device ,
} ;
void __init acpi_apd_init ( void )
{
acpi_scan_add_handler ( & apd_handler ) ;
}