1 /* 2 * sst_acpi.c - SST (LPE) driver init file for ACPI enumeration. 3 * 4 * Copyright (c) 2013, Intel Corporation. 5 * 6 * Authors: Ramesh Babu K V <Ramesh.Babu@intel.com> 7 * Authors: Omair Mohammed Abdullah <omair.m.abdullah@intel.com> 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms and conditions of the GNU General Public License, 11 * version 2, as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 16 * more details. 17 * 18 * 19 */ 20 21 #include <linux/module.h> 22 #include <linux/fs.h> 23 #include <linux/interrupt.h> 24 #include <linux/slab.h> 25 #include <linux/io.h> 26 #include <linux/miscdevice.h> 27 #include <linux/platform_device.h> 28 #include <linux/firmware.h> 29 #include <linux/pm_runtime.h> 30 #include <linux/pm_qos.h> 31 #include <linux/acpi.h> 32 #include <asm/platform_sst_audio.h> 33 #include <sound/core.h> 34 #include <sound/soc.h> 35 #include <sound/compress_driver.h> 36 #include <acpi/acbuffer.h> 37 #include <acpi/platform/acenv.h> 38 #include <acpi/platform/aclinux.h> 39 #include <acpi/actypes.h> 40 #include <acpi/acpi_bus.h> 41 #include "../sst-mfld-platform.h" 42 #include "../../common/sst-dsp.h" 43 #include "../../common/sst-acpi.h" 44 #include "sst.h" 45 46 /* LPE viewpoint addresses */ 47 #define SST_BYT_IRAM_PHY_START 0xff2c0000 48 #define SST_BYT_IRAM_PHY_END 0xff2d4000 49 #define SST_BYT_DRAM_PHY_START 0xff300000 50 #define SST_BYT_DRAM_PHY_END 0xff320000 51 #define SST_BYT_IMR_VIRT_START 0xc0000000 /* virtual addr in LPE */ 52 #define SST_BYT_IMR_VIRT_END 0xc01fffff 53 #define SST_BYT_SHIM_PHY_ADDR 0xff340000 54 #define SST_BYT_MBOX_PHY_ADDR 0xff344000 55 #define SST_BYT_DMA0_PHY_ADDR 0xff298000 56 #define SST_BYT_DMA1_PHY_ADDR 0xff29c000 57 #define SST_BYT_SSP0_PHY_ADDR 0xff2a0000 58 #define SST_BYT_SSP2_PHY_ADDR 0xff2a2000 59 60 #define BYT_FW_MOD_TABLE_OFFSET 0x80000 61 #define BYT_FW_MOD_TABLE_SIZE 0x100 62 #define BYT_FW_MOD_OFFSET (BYT_FW_MOD_TABLE_OFFSET + BYT_FW_MOD_TABLE_SIZE) 63 64 static const struct sst_info byt_fwparse_info = { 65 .use_elf = false, 66 .max_streams = 25, 67 .iram_start = SST_BYT_IRAM_PHY_START, 68 .iram_end = SST_BYT_IRAM_PHY_END, 69 .iram_use = true, 70 .dram_start = SST_BYT_DRAM_PHY_START, 71 .dram_end = SST_BYT_DRAM_PHY_END, 72 .dram_use = true, 73 .imr_start = SST_BYT_IMR_VIRT_START, 74 .imr_end = SST_BYT_IMR_VIRT_END, 75 .imr_use = true, 76 .mailbox_start = SST_BYT_MBOX_PHY_ADDR, 77 .num_probes = 0, 78 .lpe_viewpt_rqd = true, 79 }; 80 81 static const struct sst_ipc_info byt_ipc_info = { 82 .ipc_offset = 0, 83 .mbox_recv_off = 0x400, 84 }; 85 86 static const struct sst_lib_dnld_info byt_lib_dnld_info = { 87 .mod_base = SST_BYT_IMR_VIRT_START, 88 .mod_end = SST_BYT_IMR_VIRT_END, 89 .mod_table_offset = BYT_FW_MOD_TABLE_OFFSET, 90 .mod_table_size = BYT_FW_MOD_TABLE_SIZE, 91 .mod_ddr_dnld = false, 92 }; 93 94 static const struct sst_res_info byt_rvp_res_info = { 95 .shim_offset = 0x140000, 96 .shim_size = 0x000100, 97 .shim_phy_addr = SST_BYT_SHIM_PHY_ADDR, 98 .ssp0_offset = 0xa0000, 99 .ssp0_size = 0x1000, 100 .dma0_offset = 0x98000, 101 .dma0_size = 0x4000, 102 .dma1_offset = 0x9c000, 103 .dma1_size = 0x4000, 104 .iram_offset = 0x0c0000, 105 .iram_size = 0x14000, 106 .dram_offset = 0x100000, 107 .dram_size = 0x28000, 108 .mbox_offset = 0x144000, 109 .mbox_size = 0x1000, 110 .acpi_lpe_res_index = 0, 111 .acpi_ddr_index = 2, 112 .acpi_ipc_irq_index = 5, 113 }; 114 115 static struct sst_platform_info byt_rvp_platform_data = { 116 .probe_data = &byt_fwparse_info, 117 .ipc_info = &byt_ipc_info, 118 .lib_info = &byt_lib_dnld_info, 119 .res_info = &byt_rvp_res_info, 120 .platform = "sst-mfld-platform", 121 }; 122 123 /* Cherryview (Cherrytrail and Braswell) uses same mrfld dpcm fw as Baytrail, 124 * so pdata is same as Baytrail. 125 */ 126 static struct sst_platform_info chv_platform_data = { 127 .probe_data = &byt_fwparse_info, 128 .ipc_info = &byt_ipc_info, 129 .lib_info = &byt_lib_dnld_info, 130 .res_info = &byt_rvp_res_info, 131 .platform = "sst-mfld-platform", 132 }; 133 134 static int sst_platform_get_resources(struct intel_sst_drv *ctx) 135 { 136 struct resource *rsrc; 137 struct platform_device *pdev = to_platform_device(ctx->dev); 138 139 /* All ACPI resource request here */ 140 /* Get Shim addr */ 141 rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 142 ctx->pdata->res_info->acpi_lpe_res_index); 143 if (!rsrc) { 144 dev_err(ctx->dev, "Invalid SHIM base from IFWI"); 145 return -EIO; 146 } 147 dev_info(ctx->dev, "LPE base: %#x size:%#x", (unsigned int) rsrc->start, 148 (unsigned int)resource_size(rsrc)); 149 150 ctx->iram_base = rsrc->start + ctx->pdata->res_info->iram_offset; 151 ctx->iram_end = ctx->iram_base + ctx->pdata->res_info->iram_size - 1; 152 dev_info(ctx->dev, "IRAM base: %#x", ctx->iram_base); 153 ctx->iram = devm_ioremap_nocache(ctx->dev, ctx->iram_base, 154 ctx->pdata->res_info->iram_size); 155 if (!ctx->iram) { 156 dev_err(ctx->dev, "unable to map IRAM"); 157 return -EIO; 158 } 159 160 ctx->dram_base = rsrc->start + ctx->pdata->res_info->dram_offset; 161 ctx->dram_end = ctx->dram_base + ctx->pdata->res_info->dram_size - 1; 162 dev_info(ctx->dev, "DRAM base: %#x", ctx->dram_base); 163 ctx->dram = devm_ioremap_nocache(ctx->dev, ctx->dram_base, 164 ctx->pdata->res_info->dram_size); 165 if (!ctx->dram) { 166 dev_err(ctx->dev, "unable to map DRAM"); 167 return -EIO; 168 } 169 170 ctx->shim_phy_add = rsrc->start + ctx->pdata->res_info->shim_offset; 171 dev_info(ctx->dev, "SHIM base: %#x", ctx->shim_phy_add); 172 ctx->shim = devm_ioremap_nocache(ctx->dev, ctx->shim_phy_add, 173 ctx->pdata->res_info->shim_size); 174 if (!ctx->shim) { 175 dev_err(ctx->dev, "unable to map SHIM"); 176 return -EIO; 177 } 178 179 /* reassign physical address to LPE viewpoint address */ 180 ctx->shim_phy_add = ctx->pdata->res_info->shim_phy_addr; 181 182 /* Get mailbox addr */ 183 ctx->mailbox_add = rsrc->start + ctx->pdata->res_info->mbox_offset; 184 dev_info(ctx->dev, "Mailbox base: %#x", ctx->mailbox_add); 185 ctx->mailbox = devm_ioremap_nocache(ctx->dev, ctx->mailbox_add, 186 ctx->pdata->res_info->mbox_size); 187 if (!ctx->mailbox) { 188 dev_err(ctx->dev, "unable to map mailbox"); 189 return -EIO; 190 } 191 192 /* reassign physical address to LPE viewpoint address */ 193 ctx->mailbox_add = ctx->info.mailbox_start; 194 195 rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 196 ctx->pdata->res_info->acpi_ddr_index); 197 if (!rsrc) { 198 dev_err(ctx->dev, "Invalid DDR base from IFWI"); 199 return -EIO; 200 } 201 ctx->ddr_base = rsrc->start; 202 ctx->ddr_end = rsrc->end; 203 dev_info(ctx->dev, "DDR base: %#x", ctx->ddr_base); 204 ctx->ddr = devm_ioremap_nocache(ctx->dev, ctx->ddr_base, 205 resource_size(rsrc)); 206 if (!ctx->ddr) { 207 dev_err(ctx->dev, "unable to map DDR"); 208 return -EIO; 209 } 210 211 /* Find the IRQ */ 212 ctx->irq_num = platform_get_irq(pdev, 213 ctx->pdata->res_info->acpi_ipc_irq_index); 214 return 0; 215 } 216 217 static int sst_acpi_probe(struct platform_device *pdev) 218 { 219 struct device *dev = &pdev->dev; 220 int ret = 0; 221 struct intel_sst_drv *ctx; 222 const struct acpi_device_id *id; 223 struct sst_acpi_mach *mach; 224 struct platform_device *mdev; 225 struct platform_device *plat_dev; 226 struct sst_platform_info *pdata; 227 unsigned int dev_id; 228 229 id = acpi_match_device(dev->driver->acpi_match_table, dev); 230 if (!id) 231 return -ENODEV; 232 dev_dbg(dev, "for %s", id->id); 233 234 mach = (struct sst_acpi_mach *)id->driver_data; 235 mach = sst_acpi_find_machine(mach); 236 if (mach == NULL) { 237 dev_err(dev, "No matching machine driver found\n"); 238 return -ENODEV; 239 } 240 pdata = mach->pdata; 241 242 ret = kstrtouint(id->id, 16, &dev_id); 243 if (ret < 0) { 244 dev_err(dev, "Unique device id conversion error: %d\n", ret); 245 return ret; 246 } 247 248 dev_dbg(dev, "ACPI device id: %x\n", dev_id); 249 250 plat_dev = platform_device_register_data(dev, pdata->platform, -1, 251 NULL, 0); 252 if (IS_ERR(plat_dev)) { 253 dev_err(dev, "Failed to create machine device: %s\n", 254 pdata->platform); 255 return PTR_ERR(plat_dev); 256 } 257 258 /* 259 * Create platform device for sst machine driver, 260 * pass machine info as pdata 261 */ 262 mdev = platform_device_register_data(dev, mach->drv_name, -1, 263 (const void *)mach, sizeof(*mach)); 264 if (IS_ERR(mdev)) { 265 dev_err(dev, "Failed to create machine device: %s\n", 266 mach->drv_name); 267 return PTR_ERR(mdev); 268 } 269 270 ret = sst_alloc_drv_context(&ctx, dev, dev_id); 271 if (ret < 0) 272 return ret; 273 274 /* Fill sst platform data */ 275 ctx->pdata = pdata; 276 strcpy(ctx->firmware_name, mach->fw_filename); 277 278 ret = sst_platform_get_resources(ctx); 279 if (ret) 280 return ret; 281 282 ret = sst_context_init(ctx); 283 if (ret < 0) 284 return ret; 285 286 /* need to save shim registers in BYT */ 287 ctx->shim_regs64 = devm_kzalloc(ctx->dev, sizeof(*ctx->shim_regs64), 288 GFP_KERNEL); 289 if (!ctx->shim_regs64) { 290 ret = -ENOMEM; 291 goto do_sst_cleanup; 292 } 293 294 sst_configure_runtime_pm(ctx); 295 platform_set_drvdata(pdev, ctx); 296 return ret; 297 298 do_sst_cleanup: 299 sst_context_cleanup(ctx); 300 platform_set_drvdata(pdev, NULL); 301 dev_err(ctx->dev, "failed with %d\n", ret); 302 return ret; 303 } 304 305 /** 306 * intel_sst_remove - remove function 307 * 308 * @pdev: platform device structure 309 * 310 * This function is called by OS when a device is unloaded 311 * This frees the interrupt etc 312 */ 313 static int sst_acpi_remove(struct platform_device *pdev) 314 { 315 struct intel_sst_drv *ctx; 316 317 ctx = platform_get_drvdata(pdev); 318 sst_context_cleanup(ctx); 319 platform_set_drvdata(pdev, NULL); 320 return 0; 321 } 322 323 static struct sst_acpi_mach sst_acpi_bytcr[] = { 324 {"10EC5640", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, 325 &byt_rvp_platform_data }, 326 {"10EC5642", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, 327 &byt_rvp_platform_data }, 328 {"INTCCFFD", "bytcr_rt5640", "intel/fw_sst_0f28.bin", "bytcr_rt5640", NULL, 329 &byt_rvp_platform_data }, 330 {"10EC5651", "bytcr_rt5651", "intel/fw_sst_0f28.bin", "bytcr_rt5651", NULL, 331 &byt_rvp_platform_data }, 332 {}, 333 }; 334 335 /* Cherryview-based platforms: CherryTrail and Braswell */ 336 static struct sst_acpi_mach sst_acpi_chv[] = { 337 {"10EC5670", "cht-bsw-rt5672", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, 338 &chv_platform_data }, 339 {"10EC5645", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, 340 &chv_platform_data }, 341 {"10EC5650", "cht-bsw-rt5645", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, 342 &chv_platform_data }, 343 {"193C9890", "cht-bsw-max98090", "intel/fw_sst_22a8.bin", "cht-bsw", NULL, 344 &chv_platform_data }, 345 /* some CHT-T platforms rely on RT5640, use Baytrail machine driver */ 346 {"10EC5640", "bytcr_rt5640", "intel/fw_sst_22a8.bin", "bytcr_rt5640", NULL, 347 &chv_platform_data }, 348 349 {}, 350 }; 351 352 static const struct acpi_device_id sst_acpi_ids[] = { 353 { "80860F28", (unsigned long)&sst_acpi_bytcr}, 354 { "808622A8", (unsigned long) &sst_acpi_chv}, 355 { }, 356 }; 357 358 MODULE_DEVICE_TABLE(acpi, sst_acpi_ids); 359 360 static struct platform_driver sst_acpi_driver = { 361 .driver = { 362 .name = "intel_sst_acpi", 363 .acpi_match_table = ACPI_PTR(sst_acpi_ids), 364 .pm = &intel_sst_pm, 365 }, 366 .probe = sst_acpi_probe, 367 .remove = sst_acpi_remove, 368 }; 369 370 module_platform_driver(sst_acpi_driver); 371 372 MODULE_DESCRIPTION("Intel (R) SST(R) Audio Engine ACPI Driver"); 373 MODULE_AUTHOR("Ramesh Babu K V"); 374 MODULE_AUTHOR("Omair Mohammed Abdullah"); 375 MODULE_LICENSE("GPL v2"); 376 MODULE_ALIAS("sst"); 377