14b45efe8SAndy Shevchenko /* 24b45efe8SAndy Shevchenko * Intel LPSS PCI support. 34b45efe8SAndy Shevchenko * 44b45efe8SAndy Shevchenko * Copyright (C) 2015, Intel Corporation 54b45efe8SAndy Shevchenko * 64b45efe8SAndy Shevchenko * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> 74b45efe8SAndy Shevchenko * Mika Westerberg <mika.westerberg@linux.intel.com> 84b45efe8SAndy Shevchenko * 94b45efe8SAndy Shevchenko * This program is free software; you can redistribute it and/or modify 104b45efe8SAndy Shevchenko * it under the terms of the GNU General Public License version 2 as 114b45efe8SAndy Shevchenko * published by the Free Software Foundation. 124b45efe8SAndy Shevchenko */ 134b45efe8SAndy Shevchenko 144b45efe8SAndy Shevchenko #include <linux/ioport.h> 154b45efe8SAndy Shevchenko #include <linux/kernel.h> 164b45efe8SAndy Shevchenko #include <linux/module.h> 174b45efe8SAndy Shevchenko #include <linux/pci.h> 184b45efe8SAndy Shevchenko #include <linux/pm.h> 194b45efe8SAndy Shevchenko #include <linux/pm_runtime.h> 204b45efe8SAndy Shevchenko 214b45efe8SAndy Shevchenko #include "intel-lpss.h" 224b45efe8SAndy Shevchenko 234b45efe8SAndy Shevchenko static int intel_lpss_pci_probe(struct pci_dev *pdev, 244b45efe8SAndy Shevchenko const struct pci_device_id *id) 254b45efe8SAndy Shevchenko { 264b45efe8SAndy Shevchenko struct intel_lpss_platform_info *info; 274b45efe8SAndy Shevchenko int ret; 284b45efe8SAndy Shevchenko 294b45efe8SAndy Shevchenko ret = pcim_enable_device(pdev); 304b45efe8SAndy Shevchenko if (ret) 314b45efe8SAndy Shevchenko return ret; 324b45efe8SAndy Shevchenko 334b45efe8SAndy Shevchenko info = devm_kmemdup(&pdev->dev, (void *)id->driver_data, sizeof(*info), 344b45efe8SAndy Shevchenko GFP_KERNEL); 354b45efe8SAndy Shevchenko if (!info) 364b45efe8SAndy Shevchenko return -ENOMEM; 374b45efe8SAndy Shevchenko 384b45efe8SAndy Shevchenko info->mem = &pdev->resource[0]; 394b45efe8SAndy Shevchenko info->irq = pdev->irq; 404b45efe8SAndy Shevchenko 414b45efe8SAndy Shevchenko /* Probably it is enough to set this for iDMA capable devices only */ 424b45efe8SAndy Shevchenko pci_set_master(pdev); 434b45efe8SAndy Shevchenko 444b45efe8SAndy Shevchenko ret = intel_lpss_probe(&pdev->dev, info); 454b45efe8SAndy Shevchenko if (ret) 464b45efe8SAndy Shevchenko return ret; 474b45efe8SAndy Shevchenko 484b45efe8SAndy Shevchenko pm_runtime_put(&pdev->dev); 494b45efe8SAndy Shevchenko pm_runtime_allow(&pdev->dev); 504b45efe8SAndy Shevchenko 514b45efe8SAndy Shevchenko return 0; 524b45efe8SAndy Shevchenko } 534b45efe8SAndy Shevchenko 544b45efe8SAndy Shevchenko static void intel_lpss_pci_remove(struct pci_dev *pdev) 554b45efe8SAndy Shevchenko { 564b45efe8SAndy Shevchenko pm_runtime_forbid(&pdev->dev); 574b45efe8SAndy Shevchenko pm_runtime_get_sync(&pdev->dev); 584b45efe8SAndy Shevchenko 594b45efe8SAndy Shevchenko intel_lpss_remove(&pdev->dev); 604b45efe8SAndy Shevchenko } 614b45efe8SAndy Shevchenko 624b45efe8SAndy Shevchenko static INTEL_LPSS_PM_OPS(intel_lpss_pci_pm_ops); 634b45efe8SAndy Shevchenko 644b45efe8SAndy Shevchenko static const struct intel_lpss_platform_info spt_info = { 654b45efe8SAndy Shevchenko .clk_rate = 120000000, 664b45efe8SAndy Shevchenko }; 674b45efe8SAndy Shevchenko 684b45efe8SAndy Shevchenko static const struct intel_lpss_platform_info spt_uart_info = { 694b45efe8SAndy Shevchenko .clk_rate = 120000000, 704b45efe8SAndy Shevchenko .clk_con_id = "baudclk", 714b45efe8SAndy Shevchenko }; 724b45efe8SAndy Shevchenko 73*ff0a04a6SAndy Shevchenko static const struct intel_lpss_platform_info bxt_info = { 74*ff0a04a6SAndy Shevchenko .clk_rate = 100000000, 75*ff0a04a6SAndy Shevchenko }; 76*ff0a04a6SAndy Shevchenko 77*ff0a04a6SAndy Shevchenko static const struct intel_lpss_platform_info bxt_uart_info = { 78*ff0a04a6SAndy Shevchenko .clk_rate = 100000000, 79*ff0a04a6SAndy Shevchenko .clk_con_id = "baudclk", 80*ff0a04a6SAndy Shevchenko }; 81*ff0a04a6SAndy Shevchenko 82*ff0a04a6SAndy Shevchenko static const struct intel_lpss_platform_info bxt_i2c_info = { 83*ff0a04a6SAndy Shevchenko .clk_rate = 133000000, 84*ff0a04a6SAndy Shevchenko }; 85*ff0a04a6SAndy Shevchenko 864b45efe8SAndy Shevchenko static const struct pci_device_id intel_lpss_pci_ids[] = { 87*ff0a04a6SAndy Shevchenko /* BXT */ 88*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info }, 89*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0aae), (kernel_ulong_t)&bxt_i2c_info }, 90*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ab0), (kernel_ulong_t)&bxt_i2c_info }, 91*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ab2), (kernel_ulong_t)&bxt_i2c_info }, 92*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ab4), (kernel_ulong_t)&bxt_i2c_info }, 93*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ab6), (kernel_ulong_t)&bxt_i2c_info }, 94*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ab8), (kernel_ulong_t)&bxt_i2c_info }, 95*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0aba), (kernel_ulong_t)&bxt_i2c_info }, 96*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0abc), (kernel_ulong_t)&bxt_uart_info }, 97*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0abe), (kernel_ulong_t)&bxt_uart_info }, 98*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ac0), (kernel_ulong_t)&bxt_uart_info }, 99*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ac2), (kernel_ulong_t)&bxt_info }, 100*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ac4), (kernel_ulong_t)&bxt_info }, 101*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0ac6), (kernel_ulong_t)&bxt_info }, 102*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x0aee), (kernel_ulong_t)&bxt_uart_info }, 103*ff0a04a6SAndy Shevchenko /* APL */ 104*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5aac), (kernel_ulong_t)&bxt_i2c_info }, 105*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5aae), (kernel_ulong_t)&bxt_i2c_info }, 106*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ab0), (kernel_ulong_t)&bxt_i2c_info }, 107*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ab2), (kernel_ulong_t)&bxt_i2c_info }, 108*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ab4), (kernel_ulong_t)&bxt_i2c_info }, 109*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ab6), (kernel_ulong_t)&bxt_i2c_info }, 110*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ab8), (kernel_ulong_t)&bxt_i2c_info }, 111*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5aba), (kernel_ulong_t)&bxt_i2c_info }, 112*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5abc), (kernel_ulong_t)&bxt_uart_info }, 113*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5abe), (kernel_ulong_t)&bxt_uart_info }, 114*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ac0), (kernel_ulong_t)&bxt_uart_info }, 115*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ac2), (kernel_ulong_t)&bxt_info }, 116*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ac4), (kernel_ulong_t)&bxt_info }, 117*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5ac6), (kernel_ulong_t)&bxt_info }, 118*ff0a04a6SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x5aee), (kernel_ulong_t)&bxt_uart_info }, 1194b45efe8SAndy Shevchenko /* SPT-LP */ 1204b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d27), (kernel_ulong_t)&spt_uart_info }, 1214b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info }, 1224b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d29), (kernel_ulong_t)&spt_info }, 1234b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d2a), (kernel_ulong_t)&spt_info }, 1244b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d60), (kernel_ulong_t)&spt_info }, 1254b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d61), (kernel_ulong_t)&spt_info }, 1264b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d62), (kernel_ulong_t)&spt_info }, 1274b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d63), (kernel_ulong_t)&spt_info }, 1284b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d64), (kernel_ulong_t)&spt_info }, 1294b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d65), (kernel_ulong_t)&spt_info }, 1304b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0x9d66), (kernel_ulong_t)&spt_uart_info }, 1314b45efe8SAndy Shevchenko /* SPT-H */ 1324b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info }, 1334b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info }, 1344b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0xa129), (kernel_ulong_t)&spt_info }, 1354b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0xa12a), (kernel_ulong_t)&spt_info }, 1364b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_info }, 1374b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_info }, 1384b45efe8SAndy Shevchenko { PCI_VDEVICE(INTEL, 0xa166), (kernel_ulong_t)&spt_uart_info }, 1394b45efe8SAndy Shevchenko { } 1404b45efe8SAndy Shevchenko }; 1414b45efe8SAndy Shevchenko MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids); 1424b45efe8SAndy Shevchenko 1434b45efe8SAndy Shevchenko static struct pci_driver intel_lpss_pci_driver = { 1444b45efe8SAndy Shevchenko .name = "intel-lpss", 1454b45efe8SAndy Shevchenko .id_table = intel_lpss_pci_ids, 1464b45efe8SAndy Shevchenko .probe = intel_lpss_pci_probe, 1474b45efe8SAndy Shevchenko .remove = intel_lpss_pci_remove, 1484b45efe8SAndy Shevchenko .driver = { 1494b45efe8SAndy Shevchenko .pm = &intel_lpss_pci_pm_ops, 1504b45efe8SAndy Shevchenko }, 1514b45efe8SAndy Shevchenko }; 1524b45efe8SAndy Shevchenko 1534b45efe8SAndy Shevchenko module_pci_driver(intel_lpss_pci_driver); 1544b45efe8SAndy Shevchenko 1554b45efe8SAndy Shevchenko MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); 1564b45efe8SAndy Shevchenko MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); 1574b45efe8SAndy Shevchenko MODULE_DESCRIPTION("Intel LPSS PCI driver"); 1584b45efe8SAndy Shevchenko MODULE_LICENSE("GPL v2"); 159