Commit a13f4531 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'acpi-lpss'

* acpi-lpss:
  ACPI / LPSS: not using UART RTS override with Auto Flow Control
  ACPI / LPSS: remove struct lpss_shared_clock
  ACPI / LPSS: support for 133MHz I2C source clock on Baytrail
  ACPI / LPSS: drop clkdev_name member from lpss_device_desc
  ACPI / LPSS: introduce flags
parents 354f1dbe 3f9ae379
Loading
Loading
Loading
Loading
+58 −109
Original line number Diff line number Diff line
@@ -54,55 +54,58 @@ ACPI_MODULE_NAME("acpi_lpss");

#define LPSS_PRV_REG_COUNT		9

struct lpss_shared_clock {
	const char *name;
	unsigned long rate;
	struct clk *clk;
};
/* LPSS Flags */
#define LPSS_CLK			BIT(0)
#define LPSS_CLK_GATE			BIT(1)
#define LPSS_CLK_DIVIDER		BIT(2)
#define LPSS_LTR			BIT(3)
#define LPSS_SAVE_CTX			BIT(4)

struct lpss_private_data;

struct lpss_device_desc {
	bool clk_required;
	const char *clkdev_name;
	bool ltr_required;
	unsigned int flags;
	unsigned int prv_offset;
	size_t prv_size_override;
	bool clk_divider;
	bool clk_gate;
	bool save_ctx;
	struct lpss_shared_clock *shared_clock;
	void (*setup)(struct lpss_private_data *pdata);
};

static struct lpss_device_desc lpss_dma_desc = {
	.clk_required = true,
	.clkdev_name = "hclk",
	.flags = LPSS_CLK,
};

struct lpss_private_data {
	void __iomem *mmio_base;
	resource_size_t mmio_size;
	unsigned int fixed_clk_rate;
	struct clk *clk;
	const struct lpss_device_desc *dev_desc;
	u32 prv_reg_ctx[LPSS_PRV_REG_COUNT];
};

/* UART Component Parameter Register */
#define LPSS_UART_CPR			0xF4
#define LPSS_UART_CPR_AFCE		BIT(4)

static void lpss_uart_setup(struct lpss_private_data *pdata)
{
	unsigned int offset;
	u32 reg;
	u32 val;

	offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
	reg = readl(pdata->mmio_base + offset);
	writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset);
	val = readl(pdata->mmio_base + offset);
	writel(val | LPSS_TX_INT_MASK, pdata->mmio_base + offset);

	val = readl(pdata->mmio_base + LPSS_UART_CPR);
	if (!(val & LPSS_UART_CPR_AFCE)) {
		offset = pdata->dev_desc->prv_offset + LPSS_GENERAL;
	reg = readl(pdata->mmio_base + offset);
	writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset);
		val = readl(pdata->mmio_base + offset);
		val |= LPSS_GENERAL_UART_RTS_OVRD;
		writel(val, pdata->mmio_base + offset);
	}
}

static void lpss_i2c_setup(struct lpss_private_data *pdata)
static void byt_i2c_setup(struct lpss_private_data *pdata)
{
	unsigned int offset;
	u32 val;
@@ -111,100 +114,56 @@ static void lpss_i2c_setup(struct lpss_private_data *pdata)
	val = readl(pdata->mmio_base + offset);
	val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC;
	writel(val, pdata->mmio_base + offset);
}

static struct lpss_device_desc wpt_dev_desc = {
	.clk_required = true,
	.prv_offset = 0x800,
	.ltr_required = true,
	.clk_divider = true,
	.clk_gate = true,
};
	if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset))
		pdata->fixed_clk_rate = 133000000;
}

static struct lpss_device_desc lpt_dev_desc = {
	.clk_required = true,
	.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR,
	.prv_offset = 0x800,
	.ltr_required = true,
	.clk_divider = true,
	.clk_gate = true,
};

static struct lpss_device_desc lpt_i2c_dev_desc = {
	.clk_required = true,
	.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR,
	.prv_offset = 0x800,
	.ltr_required = true,
	.clk_gate = true,
};

static struct lpss_device_desc lpt_uart_dev_desc = {
	.clk_required = true,
	.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_LTR,
	.prv_offset = 0x800,
	.ltr_required = true,
	.clk_divider = true,
	.clk_gate = true,
	.setup = lpss_uart_setup,
};

static struct lpss_device_desc lpt_sdio_dev_desc = {
	.flags = LPSS_LTR,
	.prv_offset = 0x1000,
	.prv_size_override = 0x1018,
	.ltr_required = true,
};

static struct lpss_shared_clock pwm_clock = {
	.name = "pwm_clk",
	.rate = 25000000,
};

static struct lpss_device_desc byt_pwm_dev_desc = {
	.clk_required = true,
	.save_ctx = true,
	.shared_clock = &pwm_clock,
	.flags = LPSS_SAVE_CTX,
};

static struct lpss_device_desc byt_uart_dev_desc = {
	.clk_required = true,
	.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
	.prv_offset = 0x800,
	.clk_divider = true,
	.clk_gate = true,
	.save_ctx = true,
	.setup = lpss_uart_setup,
};

static struct lpss_device_desc byt_spi_dev_desc = {
	.clk_required = true,
	.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
	.prv_offset = 0x400,
	.clk_divider = true,
	.clk_gate = true,
	.save_ctx = true,
};

static struct lpss_device_desc byt_sdio_dev_desc = {
	.clk_required = true,
};

static struct lpss_shared_clock i2c_clock = {
	.name = "i2c_clk",
	.rate = 100000000,
	.flags = LPSS_CLK,
};

static struct lpss_device_desc byt_i2c_dev_desc = {
	.clk_required = true,
	.flags = LPSS_CLK | LPSS_SAVE_CTX,
	.prv_offset = 0x800,
	.save_ctx = true,
	.shared_clock = &i2c_clock,
	.setup = lpss_i2c_setup,
};

static struct lpss_shared_clock bsw_pwm_clock = {
	.name = "pwm_clk",
	.rate = 19200000,
};

static struct lpss_device_desc bsw_pwm_dev_desc = {
	.clk_required = true,
	.save_ctx = true,
	.shared_clock = &bsw_pwm_clock,
	.setup = byt_i2c_setup,
};

#else
@@ -237,7 +196,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
	{ "INT33FC", },

	/* Braswell LPSS devices */
	{ "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
	{ "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
	{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
	{ "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
	{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
@@ -251,7 +210,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
	{ "INT3436", LPSS_ADDR(lpt_sdio_dev_desc) },
	{ "INT3437", },

	{ "INT3438", LPSS_ADDR(wpt_dev_desc) },
	/* Wildcat Point LPSS devices */
	{ "INT3438", LPSS_ADDR(lpt_dev_desc) },

	{ }
};
@@ -276,7 +236,6 @@ 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;
	const char *devname = dev_name(&adev->dev);
	struct clk *clk = ERR_PTR(-ENODEV);
	struct lpss_clk_data *clk_data;
@@ -289,12 +248,7 @@ static int register_device_clock(struct acpi_device *adev,
	clk_data = platform_get_drvdata(lpss_clk_dev);
	if (!clk_data)
		return -ENODEV;

	if (dev_desc->clkdev_name) {
		clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name,
				    devname);
		return 0;
	}
	clk = clk_data->clk;

	if (!pdata->mmio_base
	    || pdata->mmio_size < dev_desc->prv_offset + LPSS_CLK_SIZE)
@@ -303,24 +257,19 @@ static int register_device_clock(struct acpi_device *adev,
	parent = clk_data->name;
	prv_base = pdata->mmio_base + dev_desc->prv_offset;

	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 (pdata->fixed_clk_rate) {
		clk = clk_register_fixed_rate(NULL, devname, parent, 0,
					      pdata->fixed_clk_rate);
		goto out;
	}

	if (dev_desc->clk_gate) {
	if (dev_desc->flags & LPSS_CLK_GATE) {
		clk = clk_register_gate(NULL, devname, parent, 0,
					prv_base, 0, 0, NULL);
		parent = devname;
	}

	if (dev_desc->clk_divider) {
	if (dev_desc->flags & LPSS_CLK_DIVIDER) {
		/* Prevent division by zero */
		if (!readl(prv_base))
			writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base);
@@ -344,7 +293,7 @@ static int register_device_clock(struct acpi_device *adev,
		kfree(parent);
		kfree(clk_name);
	}

out:
	if (IS_ERR(clk))
		return PTR_ERR(clk);

@@ -392,7 +341,10 @@ static int acpi_lpss_create_device(struct acpi_device *adev,

	pdata->dev_desc = dev_desc;

	if (dev_desc->clk_required) {
	if (dev_desc->setup)
		dev_desc->setup(pdata);

	if (dev_desc->flags & LPSS_CLK) {
		ret = register_device_clock(adev, pdata);
		if (ret) {
			/* Skip the device, but continue the namespace scan. */
@@ -413,9 +365,6 @@ 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;
	pdev = acpi_create_platform_device(adev);
	if (!IS_ERR_OR_NULL(pdev)) {
@@ -692,19 +641,19 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,

	switch (action) {
	case BUS_NOTIFY_BOUND_DRIVER:
		if (pdata->dev_desc->save_ctx)
		if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
			pdev->dev.pm_domain = &acpi_lpss_pm_domain;
		break;
	case BUS_NOTIFY_UNBOUND_DRIVER:
		if (pdata->dev_desc->save_ctx)
		if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
			pdev->dev.pm_domain = NULL;
		break;
	case BUS_NOTIFY_ADD_DEVICE:
		if (pdata->dev_desc->ltr_required)
		if (pdata->dev_desc->flags & LPSS_LTR)
			return sysfs_create_group(&pdev->dev.kobj,
						  &lpss_attr_group);
	case BUS_NOTIFY_DEL_DEVICE:
		if (pdata->dev_desc->ltr_required)
		if (pdata->dev_desc->flags & LPSS_LTR)
			sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
	default:
		break;
@@ -721,7 +670,7 @@ static void acpi_lpss_bind(struct device *dev)
{
	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));

	if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required)
	if (!pdata || !pdata->mmio_base || !(pdata->dev_desc->flags & LPSS_LTR))
		return;

	if (pdata->mmio_size >= pdata->dev_desc->prv_offset + LPSS_LTR_SIZE)