Browse Source

Merge branch 'acpi-lpss'

* acpi-lpss:
  ACPI / LPSS: override SDIO private register space size from ACPI tables
  ACPI / LPSS: mask the UART TX completion interrupt
  ACPI / LPSS: add support for Intel BayTrail

Conflicts:
	drivers/acpi/acpi_lpss.c (with commit b9e95fc)
Rafael J. Wysocki 12 years ago
parent
commit
f4c9f40238
2 changed files with 116 additions and 13 deletions
  1. 115 10
      drivers/acpi/acpi_lpss.c
  2. 1 3
      drivers/clk/x86/clk-lpt.c

+ 115 - 10
drivers/acpi/acpi_lpss.c

@@ -32,12 +32,26 @@ ACPI_MODULE_NAME("acpi_lpss");
 #define LPSS_GENERAL_LTR_MODE_SW	BIT(2)
 #define LPSS_SW_LTR			0x10
 #define LPSS_AUTO_LTR			0x14
+#define LPSS_TX_INT			0x20
+#define LPSS_TX_INT_MASK		BIT(1)
+
+struct lpss_shared_clock {
+	const char *name;
+	unsigned long rate;
+	struct clk *clk;
+};
+
+struct lpss_private_data;
 
 struct lpss_device_desc {
 	bool clk_required;
 	const char *clkdev_name;
 	bool ltr_required;
 	unsigned int prv_offset;
+	size_t prv_size_override;
+	bool clk_gate;
+	struct lpss_shared_clock *shared_clock;
+	void (*setup)(struct lpss_private_data *pdata);
 };
 
 static struct lpss_device_desc lpss_dma_desc = {
@@ -52,17 +66,76 @@ struct lpss_private_data {
 	const struct lpss_device_desc *dev_desc;
 };
 
+static void lpss_uart_setup(struct lpss_private_data *pdata)
+{
+	unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
+	u32 reg;
+
+	reg = readl(pdata->mmio_base + tx_int_offset);
+	writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset);
+}
+
 static struct lpss_device_desc lpt_dev_desc = {
 	.clk_required = true,
 	.prv_offset = 0x800,
 	.ltr_required = true,
+	.clk_gate = true,
+};
+
+static struct lpss_device_desc lpt_uart_dev_desc = {
+	.clk_required = true,
+	.prv_offset = 0x800,
+	.ltr_required = true,
+	.clk_gate = true,
+	.setup = lpss_uart_setup,
 };
 
 static struct lpss_device_desc lpt_sdio_dev_desc = {
 	.prv_offset = 0x1000,
+	.prv_size_override = 0x1018,
 	.ltr_required = true,
 };
 
+static struct lpss_shared_clock uart_clock = {
+	.name = "uart_clk",
+	.rate = 44236800,
+};
+
+static struct lpss_device_desc byt_uart_dev_desc = {
+	.clk_required = true,
+	.prv_offset = 0x800,
+	.clk_gate = true,
+	.shared_clock = &uart_clock,
+	.setup = lpss_uart_setup,
+};
+
+static struct lpss_shared_clock spi_clock = {
+	.name = "spi_clk",
+	.rate = 50000000,
+};
+
+static struct lpss_device_desc byt_spi_dev_desc = {
+	.clk_required = true,
+	.prv_offset = 0x400,
+	.clk_gate = true,
+	.shared_clock = &spi_clock,
+};
+
+static struct lpss_device_desc byt_sdio_dev_desc = {
+	.clk_required = true,
+};
+
+static struct lpss_shared_clock i2c_clock = {
+	.name = "i2c_clk",
+	.rate = 100000000,
+};
+
+static struct lpss_device_desc byt_i2c_dev_desc = {
+	.clk_required = true,
+	.prv_offset = 0x800,
+	.shared_clock = &i2c_clock,
+};
+
 static const struct acpi_device_id acpi_lpss_device_ids[] = {
 	/* Generic LPSS devices */
 	{ "INTL9C60", (unsigned long)&lpss_dma_desc },
@@ -72,11 +145,18 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
 	{ "INT33C1", (unsigned long)&lpt_dev_desc },
 	{ "INT33C2", (unsigned long)&lpt_dev_desc },
 	{ "INT33C3", (unsigned long)&lpt_dev_desc },
-	{ "INT33C4", (unsigned long)&lpt_dev_desc },
-	{ "INT33C5", (unsigned long)&lpt_dev_desc },
+	{ "INT33C4", (unsigned long)&lpt_uart_dev_desc },
+	{ "INT33C5", (unsigned long)&lpt_uart_dev_desc },
 	{ "INT33C6", (unsigned long)&lpt_sdio_dev_desc },
 	{ "INT33C7", },
 
+	/* BayTrail LPSS devices */
+	{ "80860F0A", (unsigned long)&byt_uart_dev_desc },
+	{ "80860F0E", (unsigned long)&byt_spi_dev_desc },
+	{ "80860F14", (unsigned long)&byt_sdio_dev_desc },
+	{ "80860F41", (unsigned long)&byt_i2c_dev_desc },
+	{ "INT33B2", },
+
 	{ }
 };
 
@@ -98,7 +178,10 @@ static int register_device_clock(struct acpi_device *adev,
 				 struct lpss_private_data *pdata)
 {
 	const struct lpss_device_desc *dev_desc = pdata->dev_desc;
+	struct lpss_shared_clock *shared_clock = dev_desc->shared_clock;
+	struct clk *clk = ERR_PTR(-ENODEV);
 	struct lpss_clk_data *clk_data;
+	const char *parent;
 
 	if (!lpss_clk_dev)
 		lpt_register_clock_device();
@@ -117,14 +200,30 @@ static int register_device_clock(struct acpi_device *adev,
 	    || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE)
 		return -ENODATA;
 
-	pdata->clk = clk_register_gate(NULL, dev_name(&adev->dev),
-				       clk_data->name, 0,
-				       pdata->mmio_base + dev_desc->prv_offset,
-				       0, 0, NULL);
-	if (IS_ERR(pdata->clk))
-		return PTR_ERR(pdata->clk);
+	parent = clk_data->name;
+
+	if (shared_clock) {
+		clk = shared_clock->clk;
+		if (!clk) {
+			clk = clk_register_fixed_rate(NULL, shared_clock->name,
+						      "lpss_clk", 0,
+						      shared_clock->rate);
+			shared_clock->clk = clk;
+		}
+		parent = shared_clock->name;
+	}
+
+	if (dev_desc->clk_gate) {
+		clk = clk_register_gate(NULL, dev_name(&adev->dev), parent, 0,
+					pdata->mmio_base + dev_desc->prv_offset,
+					0, 0, NULL);
+		pdata->clk = clk;
+	}
 
-	clk_register_clkdev(pdata->clk, NULL, dev_name(&adev->dev));
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	clk_register_clkdev(clk, NULL, dev_name(&adev->dev));
 	return 0;
 }
 
@@ -152,7 +251,10 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
 
 	list_for_each_entry(rentry, &resource_list, node)
 		if (resource_type(&rentry->res) == IORESOURCE_MEM) {
-			pdata->mmio_size = resource_size(&rentry->res);
+			if (dev_desc->prv_size_override)
+				pdata->mmio_size = dev_desc->prv_size_override;
+			else
+				pdata->mmio_size = resource_size(&rentry->res);
 			pdata->mmio_base = ioremap(rentry->res.start,
 						   pdata->mmio_size);
 			pdata->dev_desc = dev_desc;
@@ -182,6 +284,9 @@ static int acpi_lpss_create_device(struct acpi_device *adev,
 		goto err_out;
 	}
 
+	if (dev_desc->setup)
+		dev_desc->setup(pdata);
+
 	adev->driver_data = pdata;
 	ret = acpi_create_platform_device(adev, id);
 	if (ret > 0)

+ 1 - 3
drivers/clk/x86/clk-lpt.c

@@ -1,5 +1,5 @@
 /*
- * Intel Lynxpoint LPSS clocks.
+ * Intel Low Power Subsystem clocks.
  *
  * Copyright (C) 2013, Intel Corporation
  * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
@@ -18,8 +18,6 @@
 #include <linux/platform_data/clk-lpss.h>
 #include <linux/platform_device.h>
 
-#define PRV_CLOCK_PARAMS 0x800
-
 static int lpt_clk_probe(struct platform_device *pdev)
 {
 	struct lpss_clk_data *drvdata;