xref: /openbmc/linux/drivers/mfd/intel-lpss-pci.c (revision ff0a04a699b9ea9b795208baff2ae727a6a3085a)
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