brintos

brintos / linux-shallow public Read only

0
0
Text · 6.6 KiB · 800f978 Raw
268 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 device24 * @fixed_clk_rate: fixed rate input clock source for acpi device;25 *			0 means no fixed rate input clock source26 * @properties: build-in properties of the device such as UART27 * @setup: a hook routine to set device resource during create platform device28 *29 * Device description defined as acpi_device_id.driver_data30 */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_DEVICE63 64static int fch_misc_setup(struct apd_private_data *pdata)65{66	struct acpi_device *adev = pdata->adev;67	const union acpi_object *obj;68	struct platform_device *clkdev;69	struct fch_clk_data *clk_data;70	struct resource_entry *rentry;71	struct list_head resource_list;72	int ret;73 74	clk_data = devm_kzalloc(&adev->dev, sizeof(*clk_data), GFP_KERNEL);75	if (!clk_data)76		return -ENOMEM;77 78	INIT_LIST_HEAD(&resource_list);79	ret = acpi_dev_get_memory_resources(adev, &resource_list);80	if (ret < 0)81		return -ENOENT;82 83	if (!acpi_dev_get_property(adev, "clk-name", ACPI_TYPE_STRING, &obj)) {84		clk_data->name = devm_kzalloc(&adev->dev, obj->string.length,85					      GFP_KERNEL);86		if (!clk_data->name)87			return -ENOMEM;88 89		strcpy(clk_data->name, obj->string.pointer);90	} else {91		/* Set default name to mclk if entry missing in firmware */92		clk_data->name = "mclk";93	}94 95	list_for_each_entry(rentry, &resource_list, node) {96		clk_data->base = devm_ioremap(&adev->dev, rentry->res->start,97					      resource_size(rentry->res));98		break;99	}100	if (!clk_data->base)101		return -ENOMEM;102 103	acpi_dev_free_resource_list(&resource_list);104 105	clkdev = platform_device_register_data(&adev->dev, "clk-fch",106					       PLATFORM_DEVID_NONE, clk_data,107					       sizeof(*clk_data));108	return PTR_ERR_OR_ZERO(clkdev);109}110 111static const struct apd_device_desc cz_i2c_desc = {112	.setup = acpi_apd_setup,113	.fixed_clk_rate = 133000000,114};115 116static const struct apd_device_desc wt_i2c_desc = {117	.setup = acpi_apd_setup,118	.fixed_clk_rate = 150000000,119};120 121static const struct apd_device_desc wt_i3c_desc = {122	.setup = acpi_apd_setup,123	.fixed_clk_rate = 125000000,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_ARM64145static 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#endif187 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_DEVICE234	{ "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	{ "AMDI0015", APD_ADDR(wt_i3c_desc) },240	{ "AMDI0019", APD_ADDR(wt_i2c_desc) },241	{ "AMDI0020", APD_ADDR(cz_uart_desc) },242	{ "AMDI0022", APD_ADDR(cz_uart_desc) },243	{ "HYGO0010", APD_ADDR(wt_i2c_desc) },244#endif245#ifdef CONFIG_ARM64246	{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },247	{ "BRCM900D", APD_ADDR(vulcan_spi_desc) },248	{ "CAV900D",  APD_ADDR(vulcan_spi_desc) },249	{ "CAV9007",  APD_ADDR(thunderx2_i2c_desc) },250	{ "HISI02A1", APD_ADDR(hip07_i2c_desc) },251	{ "HISI02A2", APD_ADDR(hip08_i2c_desc) },252	{ "HISI02A3", APD_ADDR(hip08_lite_i2c_desc) },253	{ "HISI0173", APD_ADDR(hip08_spi_desc) },254	{ "NXP0001", APD_ADDR(nxp_i2c_desc) },255#endif256	{ }257};258 259static struct acpi_scan_handler apd_handler = {260	.ids = acpi_apd_device_ids,261	.attach = acpi_apd_create_device,262};263 264void __init acpi_apd_init(void)265{266	acpi_scan_add_handler(&apd_handler);267}268