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