Merge back earlier 'acpi-lpss' material for v3.18.
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 29 Sep 2014 13:29:18 +0000 (15:29 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 29 Sep 2014 13:29:18 +0000 (15:29 +0200)
drivers/acpi/acpi_lpss.c

index b0ea767..93d1606 100644 (file)
@@ -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);
-
-       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);
+       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;
+               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)