cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

acpi_apd.c (6751B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * AMD ACPI support for ACPI2platform device.
      4 *
      5 * Copyright (c) 2014,2015 AMD Corporation.
      6 * Authors: Ken Xue <Ken.Xue@amd.com>
      7 *	Wu, Jeff <Jeff.Wu@amd.com>
      8 */
      9
     10#include <linux/acpi.h>
     11#include <linux/clkdev.h>
     12#include <linux/clk-provider.h>
     13#include <linux/err.h>
     14#include <linux/io.h>
     15#include <linux/platform_data/clk-fch.h>
     16#include <linux/platform_device.h>
     17
     18#include "internal.h"
     19
     20struct apd_private_data;
     21
     22/**
     23 * struct apd_device_desc - a descriptor for apd device
     24 * @fixed_clk_rate: fixed rate input clock source for acpi device;
     25 *			0 means no fixed rate input clock source
     26 * @properties: build-in properties of the device such as UART
     27 * @setup: a hook routine to set device resource during create platform device
     28 *
     29 * Device description defined as acpi_device_id.driver_data
     30 */
     31struct apd_device_desc {
     32	unsigned int fixed_clk_rate;
     33	struct property_entry *properties;
     34	int (*setup)(struct apd_private_data *pdata);
     35};
     36
     37struct apd_private_data {
     38	struct clk *clk;
     39	struct acpi_device *adev;
     40	const struct apd_device_desc *dev_desc;
     41};
     42
     43#if defined(CONFIG_X86_AMD_PLATFORM_DEVICE) || defined(CONFIG_ARM64)
     44#define APD_ADDR(desc)	((unsigned long)&desc)
     45
     46static int acpi_apd_setup(struct apd_private_data *pdata)
     47{
     48	const struct apd_device_desc *dev_desc = pdata->dev_desc;
     49	struct clk *clk;
     50
     51	if (dev_desc->fixed_clk_rate) {
     52		clk = clk_register_fixed_rate(&pdata->adev->dev,
     53					dev_name(&pdata->adev->dev),
     54					NULL, 0, dev_desc->fixed_clk_rate);
     55		clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev));
     56		pdata->clk = clk;
     57	}
     58
     59	return 0;
     60}
     61
     62#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
     63static int misc_check_res(struct acpi_resource *ares, void *data)
     64{
     65	struct resource res;
     66
     67	return !acpi_dev_resource_memory(ares, &res);
     68}
     69
     70static int fch_misc_setup(struct apd_private_data *pdata)
     71{
     72	struct acpi_device *adev = pdata->adev;
     73	const union acpi_object *obj;
     74	struct platform_device *clkdev;
     75	struct fch_clk_data *clk_data;
     76	struct resource_entry *rentry;
     77	struct list_head resource_list;
     78	int ret;
     79
     80	clk_data = devm_kzalloc(&adev->dev, sizeof(*clk_data), GFP_KERNEL);
     81	if (!clk_data)
     82		return -ENOMEM;
     83
     84	INIT_LIST_HEAD(&resource_list);
     85	ret = acpi_dev_get_resources(adev, &resource_list, misc_check_res,
     86				     NULL);
     87	if (ret < 0)
     88		return -ENOENT;
     89
     90	if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) {
     91		clk_data->name = devm_kzalloc(&adev->dev, obj->string.length,
     92					      GFP_KERNEL);
     93
     94		strcpy(clk_data->name, obj->string.pointer);
     95	} else {
     96		/* Set default name to mclk if entry missing in firmware */
     97		clk_data->name = "mclk";
     98	}
     99
    100	list_for_each_entry(rentry, &resource_list, node) {
    101		clk_data->base = devm_ioremap(&adev->dev, rentry->res->start,
    102					      resource_size(rentry->res));
    103		break;
    104	}
    105	if (!clk_data->base)
    106		return -ENOMEM;
    107
    108	acpi_dev_free_resource_list(&resource_list);
    109
    110	clkdev = platform_device_register_data(&adev->dev, "clk-fch",
    111					       PLATFORM_DEVID_NONE, clk_data,
    112					       sizeof(*clk_data));
    113	return PTR_ERR_OR_ZERO(clkdev);
    114}
    115
    116static const struct apd_device_desc cz_i2c_desc = {
    117	.setup = acpi_apd_setup,
    118	.fixed_clk_rate = 133000000,
    119};
    120
    121static const struct apd_device_desc wt_i2c_desc = {
    122	.setup = acpi_apd_setup,
    123	.fixed_clk_rate = 150000000,
    124};
    125
    126static struct property_entry uart_properties[] = {
    127	PROPERTY_ENTRY_U32("reg-io-width", 4),
    128	PROPERTY_ENTRY_U32("reg-shift", 2),
    129	PROPERTY_ENTRY_BOOL("snps,uart-16550-compatible"),
    130	{ },
    131};
    132
    133static const struct apd_device_desc cz_uart_desc = {
    134	.setup = acpi_apd_setup,
    135	.fixed_clk_rate = 48000000,
    136	.properties = uart_properties,
    137};
    138
    139static const struct apd_device_desc fch_misc_desc = {
    140	.setup = fch_misc_setup,
    141};
    142#endif /* CONFIG_X86_AMD_PLATFORM_DEVICE */
    143
    144#ifdef CONFIG_ARM64
    145static const struct apd_device_desc xgene_i2c_desc = {
    146	.setup = acpi_apd_setup,
    147	.fixed_clk_rate = 100000000,
    148};
    149
    150static const struct apd_device_desc vulcan_spi_desc = {
    151	.setup = acpi_apd_setup,
    152	.fixed_clk_rate = 133000000,
    153};
    154
    155static const struct apd_device_desc hip07_i2c_desc = {
    156	.setup = acpi_apd_setup,
    157	.fixed_clk_rate = 200000000,
    158};
    159
    160static const struct apd_device_desc hip08_i2c_desc = {
    161	.setup = acpi_apd_setup,
    162	.fixed_clk_rate = 250000000,
    163};
    164
    165static const struct apd_device_desc hip08_lite_i2c_desc = {
    166	.setup = acpi_apd_setup,
    167	.fixed_clk_rate = 125000000,
    168};
    169
    170static const struct apd_device_desc thunderx2_i2c_desc = {
    171	.setup = acpi_apd_setup,
    172	.fixed_clk_rate = 125000000,
    173};
    174
    175static const struct apd_device_desc nxp_i2c_desc = {
    176	.setup = acpi_apd_setup,
    177	.fixed_clk_rate = 350000000,
    178};
    179
    180static const struct apd_device_desc hip08_spi_desc = {
    181	.setup = acpi_apd_setup,
    182	.fixed_clk_rate = 250000000,
    183};
    184#endif /* CONFIG_ARM64 */
    185
    186#endif
    187
    188/*
    189 * Create platform device during acpi scan attach handle.
    190 * Return value > 0 on success of creating device.
    191 */
    192static int acpi_apd_create_device(struct acpi_device *adev,
    193				   const struct acpi_device_id *id)
    194{
    195	const struct apd_device_desc *dev_desc = (void *)id->driver_data;
    196	struct apd_private_data *pdata;
    197	struct platform_device *pdev;
    198	int ret;
    199
    200	if (!dev_desc) {
    201		pdev = acpi_create_platform_device(adev, NULL);
    202		return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1;
    203	}
    204
    205	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
    206	if (!pdata)
    207		return -ENOMEM;
    208
    209	pdata->adev = adev;
    210	pdata->dev_desc = dev_desc;
    211
    212	if (dev_desc->setup) {
    213		ret = dev_desc->setup(pdata);
    214		if (ret)
    215			goto err_out;
    216	}
    217
    218	adev->driver_data = pdata;
    219	pdev = acpi_create_platform_device(adev, dev_desc->properties);
    220	if (!IS_ERR_OR_NULL(pdev))
    221		return 1;
    222
    223	ret = PTR_ERR(pdev);
    224	adev->driver_data = NULL;
    225
    226 err_out:
    227	kfree(pdata);
    228	return ret;
    229}
    230
    231static const struct acpi_device_id acpi_apd_device_ids[] = {
    232	/* Generic apd devices */
    233#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
    234	{ "AMD0010", APD_ADDR(cz_i2c_desc) },
    235	{ "AMD0020", APD_ADDR(cz_uart_desc) },
    236	{ "AMD0030", },
    237	{ "AMD0040", APD_ADDR(fch_misc_desc)},
    238	{ "AMDI0010", APD_ADDR(wt_i2c_desc) },
    239	{ "AMDI0019", APD_ADDR(wt_i2c_desc) },
    240	{ "AMDI0020", APD_ADDR(cz_uart_desc) },
    241	{ "AMDI0022", APD_ADDR(cz_uart_desc) },
    242	{ "HYGO0010", APD_ADDR(wt_i2c_desc) },
    243#endif
    244#ifdef CONFIG_ARM64
    245	{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
    246	{ "BRCM900D", APD_ADDR(vulcan_spi_desc) },
    247	{ "CAV900D",  APD_ADDR(vulcan_spi_desc) },
    248	{ "CAV9007",  APD_ADDR(thunderx2_i2c_desc) },
    249	{ "HISI02A1", APD_ADDR(hip07_i2c_desc) },
    250	{ "HISI02A2", APD_ADDR(hip08_i2c_desc) },
    251	{ "HISI02A3", APD_ADDR(hip08_lite_i2c_desc) },
    252	{ "HISI0173", APD_ADDR(hip08_spi_desc) },
    253	{ "NXP0001", APD_ADDR(nxp_i2c_desc) },
    254#endif
    255	{ }
    256};
    257
    258static struct acpi_scan_handler apd_handler = {
    259	.ids = acpi_apd_device_ids,
    260	.attach = acpi_apd_create_device,
    261};
    262
    263void __init acpi_apd_init(void)
    264{
    265	acpi_scan_add_handler(&apd_handler);
    266}