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