Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.17-rc6 202 lines 5.0 kB view raw
1/* 2 * AMD ACPI support for ACPI2platform device. 3 * 4 * Copyright (c) 2014,2015 AMD Corporation. 5 * Authors: Ken Xue <Ken.Xue@amd.com> 6 * Wu, Jeff <Jeff.Wu@amd.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 */ 12 13#include <linux/clk-provider.h> 14#include <linux/platform_device.h> 15#include <linux/pm_domain.h> 16#include <linux/clkdev.h> 17#include <linux/acpi.h> 18#include <linux/err.h> 19#include <linux/pm.h> 20 21#include "internal.h" 22 23ACPI_MODULE_NAME("acpi_apd"); 24struct apd_private_data; 25 26/** 27 * ACPI_APD_SYSFS : add device attributes in sysfs 28 * ACPI_APD_PM : attach power domain to device 29 */ 30#define ACPI_APD_SYSFS BIT(0) 31#define ACPI_APD_PM BIT(1) 32 33/** 34 * struct apd_device_desc - a descriptor for apd device 35 * @flags: device flags like %ACPI_APD_SYSFS, %ACPI_APD_PM 36 * @fixed_clk_rate: fixed rate input clock source for acpi device; 37 * 0 means no fixed rate input clock source 38 * @setup: a hook routine to set device resource during create platform device 39 * 40 * Device description defined as acpi_device_id.driver_data 41 */ 42struct apd_device_desc { 43 unsigned int flags; 44 unsigned int fixed_clk_rate; 45 struct property_entry *properties; 46 int (*setup)(struct apd_private_data *pdata); 47}; 48 49struct apd_private_data { 50 struct clk *clk; 51 struct acpi_device *adev; 52 const struct apd_device_desc *dev_desc; 53}; 54 55#if defined(CONFIG_X86_AMD_PLATFORM_DEVICE) || defined(CONFIG_ARM64) 56#define APD_ADDR(desc) ((unsigned long)&desc) 57 58static int acpi_apd_setup(struct apd_private_data *pdata) 59{ 60 const struct apd_device_desc *dev_desc = pdata->dev_desc; 61 struct clk *clk = ERR_PTR(-ENODEV); 62 63 if (dev_desc->fixed_clk_rate) { 64 clk = clk_register_fixed_rate(&pdata->adev->dev, 65 dev_name(&pdata->adev->dev), 66 NULL, 0, dev_desc->fixed_clk_rate); 67 clk_register_clkdev(clk, NULL, dev_name(&pdata->adev->dev)); 68 pdata->clk = clk; 69 } 70 71 return 0; 72} 73 74#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE 75static const struct apd_device_desc cz_i2c_desc = { 76 .setup = acpi_apd_setup, 77 .fixed_clk_rate = 133000000, 78}; 79 80static const struct apd_device_desc wt_i2c_desc = { 81 .setup = acpi_apd_setup, 82 .fixed_clk_rate = 150000000, 83}; 84 85static struct property_entry uart_properties[] = { 86 PROPERTY_ENTRY_U32("reg-io-width", 4), 87 PROPERTY_ENTRY_U32("reg-shift", 2), 88 PROPERTY_ENTRY_BOOL("snps,uart-16550-compatible"), 89 { }, 90}; 91 92static const struct apd_device_desc cz_uart_desc = { 93 .setup = acpi_apd_setup, 94 .fixed_clk_rate = 48000000, 95 .properties = uart_properties, 96}; 97#endif 98 99#ifdef CONFIG_ARM64 100static const struct apd_device_desc xgene_i2c_desc = { 101 .setup = acpi_apd_setup, 102 .fixed_clk_rate = 100000000, 103}; 104 105static const struct apd_device_desc vulcan_spi_desc = { 106 .setup = acpi_apd_setup, 107 .fixed_clk_rate = 133000000, 108}; 109 110static const struct apd_device_desc hip07_i2c_desc = { 111 .setup = acpi_apd_setup, 112 .fixed_clk_rate = 200000000, 113}; 114 115static const struct apd_device_desc hip08_i2c_desc = { 116 .setup = acpi_apd_setup, 117 .fixed_clk_rate = 250000000, 118}; 119static const struct apd_device_desc thunderx2_i2c_desc = { 120 .setup = acpi_apd_setup, 121 .fixed_clk_rate = 125000000, 122}; 123#endif 124 125#else 126 127#define APD_ADDR(desc) (0UL) 128 129#endif /* CONFIG_X86_AMD_PLATFORM_DEVICE */ 130 131/** 132* Create platform device during acpi scan attach handle. 133* Return value > 0 on success of creating device. 134*/ 135static int acpi_apd_create_device(struct acpi_device *adev, 136 const struct acpi_device_id *id) 137{ 138 const struct apd_device_desc *dev_desc = (void *)id->driver_data; 139 struct apd_private_data *pdata; 140 struct platform_device *pdev; 141 int ret; 142 143 if (!dev_desc) { 144 pdev = acpi_create_platform_device(adev, NULL); 145 return IS_ERR_OR_NULL(pdev) ? PTR_ERR(pdev) : 1; 146 } 147 148 pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); 149 if (!pdata) 150 return -ENOMEM; 151 152 pdata->adev = adev; 153 pdata->dev_desc = dev_desc; 154 155 if (dev_desc->setup) { 156 ret = dev_desc->setup(pdata); 157 if (ret) 158 goto err_out; 159 } 160 161 adev->driver_data = pdata; 162 pdev = acpi_create_platform_device(adev, dev_desc->properties); 163 if (!IS_ERR_OR_NULL(pdev)) 164 return 1; 165 166 ret = PTR_ERR(pdev); 167 adev->driver_data = NULL; 168 169 err_out: 170 kfree(pdata); 171 return ret; 172} 173 174static const struct acpi_device_id acpi_apd_device_ids[] = { 175 /* Generic apd devices */ 176#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE 177 { "AMD0010", APD_ADDR(cz_i2c_desc) }, 178 { "AMDI0010", APD_ADDR(wt_i2c_desc) }, 179 { "AMD0020", APD_ADDR(cz_uart_desc) }, 180 { "AMDI0020", APD_ADDR(cz_uart_desc) }, 181 { "AMD0030", }, 182#endif 183#ifdef CONFIG_ARM64 184 { "APMC0D0F", APD_ADDR(xgene_i2c_desc) }, 185 { "BRCM900D", APD_ADDR(vulcan_spi_desc) }, 186 { "CAV900D", APD_ADDR(vulcan_spi_desc) }, 187 { "CAV9007", APD_ADDR(thunderx2_i2c_desc) }, 188 { "HISI02A1", APD_ADDR(hip07_i2c_desc) }, 189 { "HISI02A2", APD_ADDR(hip08_i2c_desc) }, 190#endif 191 { } 192}; 193 194static struct acpi_scan_handler apd_handler = { 195 .ids = acpi_apd_device_ids, 196 .attach = acpi_apd_create_device, 197}; 198 199void __init acpi_apd_init(void) 200{ 201 acpi_scan_add_handler(&apd_handler); 202}