1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 24b45efe8SAndy Shevchenko /* 34b45efe8SAndy Shevchenko * Intel LPSS ACPI support. 44b45efe8SAndy Shevchenko * 54b45efe8SAndy Shevchenko * Copyright (C) 2015, Intel Corporation 64b45efe8SAndy Shevchenko * 74b45efe8SAndy Shevchenko * Authors: Andy Shevchenko <andriy.shevchenko@linux.intel.com> 84b45efe8SAndy Shevchenko * Mika Westerberg <mika.westerberg@linux.intel.com> 94b45efe8SAndy Shevchenko */ 104b45efe8SAndy Shevchenko 114b45efe8SAndy Shevchenko #include <linux/acpi.h> 124b45efe8SAndy Shevchenko #include <linux/ioport.h> 134b45efe8SAndy Shevchenko #include <linux/kernel.h> 144b45efe8SAndy Shevchenko #include <linux/module.h> 154b45efe8SAndy Shevchenko #include <linux/pm_runtime.h> 164b45efe8SAndy Shevchenko #include <linux/platform_device.h> 17028af594SMika Westerberg #include <linux/property.h> 18*5a2d27c2SAndy Shevchenko #include <linux/pxa2xx_ssp.h> 194b45efe8SAndy Shevchenko 204b45efe8SAndy Shevchenko #include "intel-lpss.h" 214b45efe8SAndy Shevchenko 22*5a2d27c2SAndy Shevchenko static const struct property_entry spt_spi_properties[] = { 23*5a2d27c2SAndy Shevchenko PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_SPT_SSP), 24*5a2d27c2SAndy Shevchenko { } 25*5a2d27c2SAndy Shevchenko }; 26*5a2d27c2SAndy Shevchenko 27*5a2d27c2SAndy Shevchenko static const struct software_node spt_spi_node = { 28*5a2d27c2SAndy Shevchenko .properties = spt_spi_properties, 29*5a2d27c2SAndy Shevchenko }; 30*5a2d27c2SAndy Shevchenko 31c5b90cb2SAndy Shevchenko static const struct intel_lpss_platform_info spt_info = { 32c5b90cb2SAndy Shevchenko .clk_rate = 120000000, 33*5a2d27c2SAndy Shevchenko .swnode = &spt_spi_node, 34c5b90cb2SAndy Shevchenko }; 35c5b90cb2SAndy Shevchenko 369677e6f7SAndy Shevchenko static const struct property_entry spt_i2c_properties[] = { 37028af594SMika Westerberg PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 230), 38028af594SMika Westerberg { }, 39028af594SMika Westerberg }; 40028af594SMika Westerberg 4103152e35SHeikki Krogerus static const struct software_node spt_i2c_node = { 4203152e35SHeikki Krogerus .properties = spt_i2c_properties, 4303152e35SHeikki Krogerus }; 4403152e35SHeikki Krogerus 45028af594SMika Westerberg static const struct intel_lpss_platform_info spt_i2c_info = { 46028af594SMika Westerberg .clk_rate = 120000000, 4703152e35SHeikki Krogerus .swnode = &spt_i2c_node, 48028af594SMika Westerberg }; 49028af594SMika Westerberg 509677e6f7SAndy Shevchenko static const struct property_entry uart_properties[] = { 51c5b90cb2SAndy Shevchenko PROPERTY_ENTRY_U32("reg-io-width", 4), 52c5b90cb2SAndy Shevchenko PROPERTY_ENTRY_U32("reg-shift", 2), 53c5b90cb2SAndy Shevchenko PROPERTY_ENTRY_BOOL("snps,uart-16550-compatible"), 54c5b90cb2SAndy Shevchenko { }, 55c5b90cb2SAndy Shevchenko }; 56c5b90cb2SAndy Shevchenko 5703152e35SHeikki Krogerus static const struct software_node uart_node = { 5803152e35SHeikki Krogerus .properties = uart_properties, 5903152e35SHeikki Krogerus }; 6003152e35SHeikki Krogerus 61c5b90cb2SAndy Shevchenko static const struct intel_lpss_platform_info spt_uart_info = { 62c5b90cb2SAndy Shevchenko .clk_rate = 120000000, 63c5b90cb2SAndy Shevchenko .clk_con_id = "baudclk", 6403152e35SHeikki Krogerus .swnode = &uart_node, 65c5b90cb2SAndy Shevchenko }; 66c5b90cb2SAndy Shevchenko 67*5a2d27c2SAndy Shevchenko static const struct property_entry bxt_spi_properties[] = { 68*5a2d27c2SAndy Shevchenko PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BXT_SSP), 69*5a2d27c2SAndy Shevchenko { } 70*5a2d27c2SAndy Shevchenko }; 71*5a2d27c2SAndy Shevchenko 72*5a2d27c2SAndy Shevchenko static const struct software_node bxt_spi_node = { 73*5a2d27c2SAndy Shevchenko .properties = bxt_spi_properties, 74*5a2d27c2SAndy Shevchenko }; 75*5a2d27c2SAndy Shevchenko 766a636ec0SMika Westerberg static const struct intel_lpss_platform_info bxt_info = { 776a636ec0SMika Westerberg .clk_rate = 100000000, 78*5a2d27c2SAndy Shevchenko .swnode = &bxt_spi_node, 796a636ec0SMika Westerberg }; 806a636ec0SMika Westerberg 819677e6f7SAndy Shevchenko static const struct property_entry bxt_i2c_properties[] = { 820343b2f4SMika Westerberg PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 42), 830343b2f4SMika Westerberg PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171), 840343b2f4SMika Westerberg PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 208), 850343b2f4SMika Westerberg { }, 860343b2f4SMika Westerberg }; 870343b2f4SMika Westerberg 8803152e35SHeikki Krogerus static const struct software_node bxt_i2c_node = { 8903152e35SHeikki Krogerus .properties = bxt_i2c_properties, 9003152e35SHeikki Krogerus }; 9103152e35SHeikki Krogerus 926a636ec0SMika Westerberg static const struct intel_lpss_platform_info bxt_i2c_info = { 936a636ec0SMika Westerberg .clk_rate = 133000000, 9403152e35SHeikki Krogerus .swnode = &bxt_i2c_node, 956a636ec0SMika Westerberg }; 966a636ec0SMika Westerberg 979677e6f7SAndy Shevchenko static const struct property_entry apl_i2c_properties[] = { 98c50cdd62SJarkko Nikula PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 207), 99c50cdd62SJarkko Nikula PROPERTY_ENTRY_U32("i2c-sda-falling-time-ns", 171), 100c50cdd62SJarkko Nikula PROPERTY_ENTRY_U32("i2c-scl-falling-time-ns", 208), 101c50cdd62SJarkko Nikula { }, 102c50cdd62SJarkko Nikula }; 103c50cdd62SJarkko Nikula 10403152e35SHeikki Krogerus static const struct software_node apl_i2c_node = { 10503152e35SHeikki Krogerus .properties = apl_i2c_properties, 10603152e35SHeikki Krogerus }; 10703152e35SHeikki Krogerus 108c50cdd62SJarkko Nikula static const struct intel_lpss_platform_info apl_i2c_info = { 109c50cdd62SJarkko Nikula .clk_rate = 133000000, 11003152e35SHeikki Krogerus .swnode = &apl_i2c_node, 111c50cdd62SJarkko Nikula }; 112c50cdd62SJarkko Nikula 113*5a2d27c2SAndy Shevchenko static const struct property_entry cnl_spi_properties[] = { 114*5a2d27c2SAndy Shevchenko PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_CNL_SSP), 115*5a2d27c2SAndy Shevchenko { } 116*5a2d27c2SAndy Shevchenko }; 117*5a2d27c2SAndy Shevchenko 118*5a2d27c2SAndy Shevchenko static const struct software_node cnl_spi_node = { 119*5a2d27c2SAndy Shevchenko .properties = cnl_spi_properties, 120*5a2d27c2SAndy Shevchenko }; 121*5a2d27c2SAndy Shevchenko 122*5a2d27c2SAndy Shevchenko static const struct intel_lpss_platform_info cnl_info = { 123*5a2d27c2SAndy Shevchenko .clk_rate = 120000000, 124*5a2d27c2SAndy Shevchenko .swnode = &cnl_spi_node, 125*5a2d27c2SAndy Shevchenko }; 126*5a2d27c2SAndy Shevchenko 12732979fcfSAndy Shevchenko static const struct intel_lpss_platform_info cnl_i2c_info = { 12832979fcfSAndy Shevchenko .clk_rate = 216000000, 12932979fcfSAndy Shevchenko .swnode = &spt_i2c_node, 13032979fcfSAndy Shevchenko }; 13132979fcfSAndy Shevchenko 1324b45efe8SAndy Shevchenko static const struct acpi_device_id intel_lpss_acpi_ids[] = { 1334b45efe8SAndy Shevchenko /* SPT */ 134c5b90cb2SAndy Shevchenko { "INT3440", (kernel_ulong_t)&spt_info }, 135c5b90cb2SAndy Shevchenko { "INT3441", (kernel_ulong_t)&spt_info }, 136c5b90cb2SAndy Shevchenko { "INT3442", (kernel_ulong_t)&spt_i2c_info }, 137c5b90cb2SAndy Shevchenko { "INT3443", (kernel_ulong_t)&spt_i2c_info }, 138c5b90cb2SAndy Shevchenko { "INT3444", (kernel_ulong_t)&spt_i2c_info }, 139c5b90cb2SAndy Shevchenko { "INT3445", (kernel_ulong_t)&spt_i2c_info }, 140028af594SMika Westerberg { "INT3446", (kernel_ulong_t)&spt_i2c_info }, 141028af594SMika Westerberg { "INT3447", (kernel_ulong_t)&spt_i2c_info }, 142c5b90cb2SAndy Shevchenko { "INT3448", (kernel_ulong_t)&spt_uart_info }, 143c5b90cb2SAndy Shevchenko { "INT3449", (kernel_ulong_t)&spt_uart_info }, 144c5b90cb2SAndy Shevchenko { "INT344A", (kernel_ulong_t)&spt_uart_info }, 14532979fcfSAndy Shevchenko /* CNL */ 146*5a2d27c2SAndy Shevchenko { "INT34B0", (kernel_ulong_t)&cnl_info }, 147*5a2d27c2SAndy Shevchenko { "INT34B1", (kernel_ulong_t)&cnl_info }, 14832979fcfSAndy Shevchenko { "INT34B2", (kernel_ulong_t)&cnl_i2c_info }, 14932979fcfSAndy Shevchenko { "INT34B3", (kernel_ulong_t)&cnl_i2c_info }, 15032979fcfSAndy Shevchenko { "INT34B4", (kernel_ulong_t)&cnl_i2c_info }, 15132979fcfSAndy Shevchenko { "INT34B5", (kernel_ulong_t)&cnl_i2c_info }, 15232979fcfSAndy Shevchenko { "INT34B6", (kernel_ulong_t)&cnl_i2c_info }, 15332979fcfSAndy Shevchenko { "INT34B7", (kernel_ulong_t)&cnl_i2c_info }, 15432979fcfSAndy Shevchenko { "INT34B8", (kernel_ulong_t)&spt_uart_info }, 15532979fcfSAndy Shevchenko { "INT34B9", (kernel_ulong_t)&spt_uart_info }, 15632979fcfSAndy Shevchenko { "INT34BA", (kernel_ulong_t)&spt_uart_info }, 157*5a2d27c2SAndy Shevchenko { "INT34BC", (kernel_ulong_t)&cnl_info }, 1586a636ec0SMika Westerberg /* BXT */ 1596a636ec0SMika Westerberg { "80860AAC", (kernel_ulong_t)&bxt_i2c_info }, 1606a636ec0SMika Westerberg { "80860ABC", (kernel_ulong_t)&bxt_info }, 1616a636ec0SMika Westerberg { "80860AC2", (kernel_ulong_t)&bxt_info }, 1626a636ec0SMika Westerberg /* APL */ 163c50cdd62SJarkko Nikula { "80865AAC", (kernel_ulong_t)&apl_i2c_info }, 1646a636ec0SMika Westerberg { "80865ABC", (kernel_ulong_t)&bxt_info }, 1656a636ec0SMika Westerberg { "80865AC2", (kernel_ulong_t)&bxt_info }, 1664b45efe8SAndy Shevchenko { } 1674b45efe8SAndy Shevchenko }; 1684b45efe8SAndy Shevchenko MODULE_DEVICE_TABLE(acpi, intel_lpss_acpi_ids); 1694b45efe8SAndy Shevchenko 1704b45efe8SAndy Shevchenko static int intel_lpss_acpi_probe(struct platform_device *pdev) 1714b45efe8SAndy Shevchenko { 1724b45efe8SAndy Shevchenko struct intel_lpss_platform_info *info; 1734b45efe8SAndy Shevchenko const struct acpi_device_id *id; 174c9e14308SAndy Shevchenko int ret; 1754b45efe8SAndy Shevchenko 1764b45efe8SAndy Shevchenko id = acpi_match_device(intel_lpss_acpi_ids, &pdev->dev); 1774b45efe8SAndy Shevchenko if (!id) 1784b45efe8SAndy Shevchenko return -ENODEV; 1794b45efe8SAndy Shevchenko 1804b45efe8SAndy Shevchenko info = devm_kmemdup(&pdev->dev, (void *)id->driver_data, sizeof(*info), 1814b45efe8SAndy Shevchenko GFP_KERNEL); 1824b45efe8SAndy Shevchenko if (!info) 1834b45efe8SAndy Shevchenko return -ENOMEM; 1844b45efe8SAndy Shevchenko 1854b45efe8SAndy Shevchenko info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1864b45efe8SAndy Shevchenko info->irq = platform_get_irq(pdev, 0); 1874b45efe8SAndy Shevchenko 188c9e14308SAndy Shevchenko ret = intel_lpss_probe(&pdev->dev, info); 189c9e14308SAndy Shevchenko if (ret) 190c9e14308SAndy Shevchenko return ret; 191c9e14308SAndy Shevchenko 1924b45efe8SAndy Shevchenko pm_runtime_set_active(&pdev->dev); 1934b45efe8SAndy Shevchenko pm_runtime_enable(&pdev->dev); 1944b45efe8SAndy Shevchenko 195c9e14308SAndy Shevchenko return 0; 1964b45efe8SAndy Shevchenko } 1974b45efe8SAndy Shevchenko 1984b45efe8SAndy Shevchenko static int intel_lpss_acpi_remove(struct platform_device *pdev) 1994b45efe8SAndy Shevchenko { 2004b45efe8SAndy Shevchenko intel_lpss_remove(&pdev->dev); 2014b45efe8SAndy Shevchenko pm_runtime_disable(&pdev->dev); 2024b45efe8SAndy Shevchenko 2034b45efe8SAndy Shevchenko return 0; 2044b45efe8SAndy Shevchenko } 2054b45efe8SAndy Shevchenko 2064b45efe8SAndy Shevchenko static INTEL_LPSS_PM_OPS(intel_lpss_acpi_pm_ops); 2074b45efe8SAndy Shevchenko 2084b45efe8SAndy Shevchenko static struct platform_driver intel_lpss_acpi_driver = { 2094b45efe8SAndy Shevchenko .probe = intel_lpss_acpi_probe, 2104b45efe8SAndy Shevchenko .remove = intel_lpss_acpi_remove, 2114b45efe8SAndy Shevchenko .driver = { 2124b45efe8SAndy Shevchenko .name = "intel-lpss", 2134b45efe8SAndy Shevchenko .acpi_match_table = intel_lpss_acpi_ids, 2144b45efe8SAndy Shevchenko .pm = &intel_lpss_acpi_pm_ops, 2154b45efe8SAndy Shevchenko }, 2164b45efe8SAndy Shevchenko }; 2174b45efe8SAndy Shevchenko 2184b45efe8SAndy Shevchenko module_platform_driver(intel_lpss_acpi_driver); 2194b45efe8SAndy Shevchenko 2204b45efe8SAndy Shevchenko MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); 2214b45efe8SAndy Shevchenko MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>"); 2224b45efe8SAndy Shevchenko MODULE_DESCRIPTION("Intel LPSS ACPI driver"); 2234b45efe8SAndy Shevchenko MODULE_LICENSE("GPL v2"); 224