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/acpi.h>
2020-09-07 15:57:33 +03:00
# include <linux/clkdev.h>
# include <linux/clk-provider.h>
2015-02-06 03:27:51 +03:00
# include <linux/err.h>
2019-04-19 01:20:22 +03:00
# include <linux/io.h>
2020-09-07 15:57:33 +03:00
# include <linux/platform_data/clk-fch.h>
# include <linux/platform_device.h>
2015-02-06 03:27:51 +03:00
# include "internal.h"
struct apd_private_data ;
/**
* struct apd_device_desc - a descriptor for apd device
* @ fixed_clk_rate : fixed rate input clock source for acpi device ;
* 0 means no fixed rate input clock source
2020-09-07 15:57:29 +03:00
* @ properties : build - in properties of the device such as UART
2015-02-06 03:27:51 +03:00
* @ 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 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 ) ;
}
2020-07-31 16:36:01 +03:00
static int fch_misc_setup ( struct apd_private_data * pdata )
2018-05-09 12:59:01 +03:00
{
struct acpi_device * adev = pdata - > adev ;
2020-07-31 16:36:03 +03:00
const union acpi_object * obj ;
2018-05-09 12:59:01 +03:00
struct platform_device * clkdev ;
2020-07-31 16:36:01 +03:00
struct fch_clk_data * clk_data ;
2018-05-09 12:59:01 +03:00
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 ;
2021-12-12 21:05:25 +03:00
if ( ! acpi_dev_get_property ( adev , " clk-name " , ACPI_TYPE_STRING , & obj ) ) {
clk_data - > name = devm_kzalloc ( & adev - > dev , obj - > string . length ,
GFP_KERNEL ) ;
strcpy ( clk_data - > name , obj - > string . pointer ) ;
} else {
/* Set default name to mclk if entry missing in firmware */
clk_data - > name = " mclk " ;
}
2018-05-09 12:59:01 +03:00
list_for_each_entry ( rentry , & resource_list , node ) {
clk_data - > base = devm_ioremap ( & adev - > dev , rentry - > res - > start ,
resource_size ( rentry - > res ) ) ;
break ;
}
2022-01-07 06:35:16 +03:00
if ( ! clk_data - > base )
return - ENOMEM ;
2018-05-09 12:59:01 +03:00
acpi_dev_free_resource_list ( & resource_list ) ;
2020-07-31 16:36:01 +03:00
clkdev = platform_device_register_data ( & adev - > dev , " clk-fch " ,
2018-05-09 12:59:01 +03:00
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
2020-07-31 16:36:01 +03:00
static const struct apd_device_desc fch_misc_desc = {
. setup = fch_misc_setup ,
2018-05-09 12:59:01 +03:00
} ;
2020-09-07 15:57:32 +03:00
# endif /* CONFIG_X86_AMD_PLATFORM_DEVICE */
2015-12-11 00:19:16 +03:00
# 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
2020-02-03 04:36:06 +03:00
static const struct apd_device_desc hip08_lite_i2c_desc = {
. setup = acpi_apd_setup ,
. fixed_clk_rate = 125000000 ,
} ;
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 ,
} ;
2020-09-07 15:57:32 +03:00
# endif /* CONFIG_ARM64 */
2015-02-06 03:27:51 +03:00
2020-09-07 15:57:32 +03:00
# endif
2015-02-06 03:27:51 +03:00
2021-03-27 15:08:13 +03:00
/*
* Create platform device during acpi scan attach handle .
* Return value > 0 on success of creating device .
*/
2015-02-06 03:27:51 +03:00
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 ) } ,
{ " AMD0020 " , APD_ADDR ( cz_uart_desc ) } ,
{ " AMD0030 " , } ,
2020-07-31 16:36:01 +03:00
{ " AMD0040 " , APD_ADDR ( fch_misc_desc ) } ,
2022-02-08 17:12:18 +03:00
{ " AMDI0010 " , APD_ADDR ( wt_i2c_desc ) } ,
{ " AMDI0019 " , APD_ADDR ( wt_i2c_desc ) } ,
{ " AMDI0020 " , APD_ADDR ( cz_uart_desc ) } ,
{ " AMDI0022 " , APD_ADDR ( cz_uart_desc ) } ,
2020-08-07 12:35:29 +03:00
{ " HYGO0010 " , APD_ADDR ( wt_i2c_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 ) } ,
2020-02-03 04:36:06 +03:00
{ " HISI02A3 " , APD_ADDR ( hip08_lite_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 ) ;
}