Loading drivers/acpi/acpi_lpss.c +58 −109 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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) }, Loading @@ -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) }, { } }; Loading @@ -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; Loading @@ -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) Loading @@ -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); Loading @@ -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); Loading Loading @@ -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. */ Loading @@ -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)) { Loading Loading @@ -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; Loading @@ -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) Loading Loading
drivers/acpi/acpi_lpss.c +58 −109 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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) }, Loading @@ -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) }, { } }; Loading @@ -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; Loading @@ -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) Loading @@ -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); Loading @@ -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); Loading Loading @@ -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. */ Loading @@ -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)) { Loading Loading @@ -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; Loading @@ -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) Loading