diff options
Diffstat (limited to 'drivers/acpi/acpi_lpss.c')
-rw-r--r-- | drivers/acpi/acpi_lpss.c | 232 |
1 files changed, 202 insertions, 30 deletions
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 0e9c0d38b85c..db362a96c38e 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/platform_data/clk-lpss.h> | 20 | #include <linux/platform_data/clk-lpss.h> |
21 | #include <linux/pm_runtime.h> | 21 | #include <linux/pm_runtime.h> |
22 | #include <linux/delay.h> | ||
22 | 23 | ||
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | 25 | ||
@@ -28,6 +29,7 @@ ACPI_MODULE_NAME("acpi_lpss"); | |||
28 | #define LPSS_LTR_SIZE 0x18 | 29 | #define LPSS_LTR_SIZE 0x18 |
29 | 30 | ||
30 | /* Offsets relative to LPSS_PRIVATE_OFFSET */ | 31 | /* Offsets relative to LPSS_PRIVATE_OFFSET */ |
32 | #define LPSS_CLK_DIVIDER_DEF_MASK (BIT(1) | BIT(16)) | ||
31 | #define LPSS_GENERAL 0x08 | 33 | #define LPSS_GENERAL 0x08 |
32 | #define LPSS_GENERAL_LTR_MODE_SW BIT(2) | 34 | #define LPSS_GENERAL_LTR_MODE_SW BIT(2) |
33 | #define LPSS_GENERAL_UART_RTS_OVRD BIT(3) | 35 | #define LPSS_GENERAL_UART_RTS_OVRD BIT(3) |
@@ -43,6 +45,8 @@ ACPI_MODULE_NAME("acpi_lpss"); | |||
43 | #define LPSS_TX_INT 0x20 | 45 | #define LPSS_TX_INT 0x20 |
44 | #define LPSS_TX_INT_MASK BIT(1) | 46 | #define LPSS_TX_INT_MASK BIT(1) |
45 | 47 | ||
48 | #define LPSS_PRV_REG_COUNT 9 | ||
49 | |||
46 | struct lpss_shared_clock { | 50 | struct lpss_shared_clock { |
47 | const char *name; | 51 | const char *name; |
48 | unsigned long rate; | 52 | unsigned long rate; |
@@ -57,7 +61,9 @@ struct lpss_device_desc { | |||
57 | bool ltr_required; | 61 | bool ltr_required; |
58 | unsigned int prv_offset; | 62 | unsigned int prv_offset; |
59 | size_t prv_size_override; | 63 | size_t prv_size_override; |
64 | bool clk_divider; | ||
60 | bool clk_gate; | 65 | bool clk_gate; |
66 | bool save_ctx; | ||
61 | struct lpss_shared_clock *shared_clock; | 67 | struct lpss_shared_clock *shared_clock; |
62 | void (*setup)(struct lpss_private_data *pdata); | 68 | void (*setup)(struct lpss_private_data *pdata); |
63 | }; | 69 | }; |
@@ -72,6 +78,7 @@ struct lpss_private_data { | |||
72 | resource_size_t mmio_size; | 78 | resource_size_t mmio_size; |
73 | struct clk *clk; | 79 | struct clk *clk; |
74 | const struct lpss_device_desc *dev_desc; | 80 | const struct lpss_device_desc *dev_desc; |
81 | u32 prv_reg_ctx[LPSS_PRV_REG_COUNT]; | ||
75 | }; | 82 | }; |
76 | 83 | ||
77 | static void lpss_uart_setup(struct lpss_private_data *pdata) | 84 | static void lpss_uart_setup(struct lpss_private_data *pdata) |
@@ -92,6 +99,14 @@ static struct lpss_device_desc lpt_dev_desc = { | |||
92 | .clk_required = true, | 99 | .clk_required = true, |
93 | .prv_offset = 0x800, | 100 | .prv_offset = 0x800, |
94 | .ltr_required = true, | 101 | .ltr_required = true, |
102 | .clk_divider = true, | ||
103 | .clk_gate = true, | ||
104 | }; | ||
105 | |||
106 | static struct lpss_device_desc lpt_i2c_dev_desc = { | ||
107 | .clk_required = true, | ||
108 | .prv_offset = 0x800, | ||
109 | .ltr_required = true, | ||
95 | .clk_gate = true, | 110 | .clk_gate = true, |
96 | }; | 111 | }; |
97 | 112 | ||
@@ -99,6 +114,7 @@ static struct lpss_device_desc lpt_uart_dev_desc = { | |||
99 | .clk_required = true, | 114 | .clk_required = true, |
100 | .prv_offset = 0x800, | 115 | .prv_offset = 0x800, |
101 | .ltr_required = true, | 116 | .ltr_required = true, |
117 | .clk_divider = true, | ||
102 | .clk_gate = true, | 118 | .clk_gate = true, |
103 | .setup = lpss_uart_setup, | 119 | .setup = lpss_uart_setup, |
104 | }; | 120 | }; |
@@ -116,32 +132,25 @@ static struct lpss_shared_clock pwm_clock = { | |||
116 | 132 | ||
117 | static struct lpss_device_desc byt_pwm_dev_desc = { | 133 | static struct lpss_device_desc byt_pwm_dev_desc = { |
118 | .clk_required = true, | 134 | .clk_required = true, |
135 | .save_ctx = true, | ||
119 | .shared_clock = &pwm_clock, | 136 | .shared_clock = &pwm_clock, |
120 | }; | 137 | }; |
121 | 138 | ||
122 | static struct lpss_shared_clock uart_clock = { | ||
123 | .name = "uart_clk", | ||
124 | .rate = 44236800, | ||
125 | }; | ||
126 | |||
127 | static struct lpss_device_desc byt_uart_dev_desc = { | 139 | static struct lpss_device_desc byt_uart_dev_desc = { |
128 | .clk_required = true, | 140 | .clk_required = true, |
129 | .prv_offset = 0x800, | 141 | .prv_offset = 0x800, |
142 | .clk_divider = true, | ||
130 | .clk_gate = true, | 143 | .clk_gate = true, |
131 | .shared_clock = &uart_clock, | 144 | .save_ctx = true, |
132 | .setup = lpss_uart_setup, | 145 | .setup = lpss_uart_setup, |
133 | }; | 146 | }; |
134 | 147 | ||
135 | static struct lpss_shared_clock spi_clock = { | ||
136 | .name = "spi_clk", | ||
137 | .rate = 50000000, | ||
138 | }; | ||
139 | |||
140 | static struct lpss_device_desc byt_spi_dev_desc = { | 148 | static struct lpss_device_desc byt_spi_dev_desc = { |
141 | .clk_required = true, | 149 | .clk_required = true, |
142 | .prv_offset = 0x400, | 150 | .prv_offset = 0x400, |
151 | .clk_divider = true, | ||
143 | .clk_gate = true, | 152 | .clk_gate = true, |
144 | .shared_clock = &spi_clock, | 153 | .save_ctx = true, |
145 | }; | 154 | }; |
146 | 155 | ||
147 | static struct lpss_device_desc byt_sdio_dev_desc = { | 156 | static struct lpss_device_desc byt_sdio_dev_desc = { |
@@ -156,6 +165,7 @@ static struct lpss_shared_clock i2c_clock = { | |||
156 | static struct lpss_device_desc byt_i2c_dev_desc = { | 165 | static struct lpss_device_desc byt_i2c_dev_desc = { |
157 | .clk_required = true, | 166 | .clk_required = true, |
158 | .prv_offset = 0x800, | 167 | .prv_offset = 0x800, |
168 | .save_ctx = true, | ||
159 | .shared_clock = &i2c_clock, | 169 | .shared_clock = &i2c_clock, |
160 | }; | 170 | }; |
161 | 171 | ||
@@ -166,8 +176,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { | |||
166 | /* Lynxpoint LPSS devices */ | 176 | /* Lynxpoint LPSS devices */ |
167 | { "INT33C0", (unsigned long)&lpt_dev_desc }, | 177 | { "INT33C0", (unsigned long)&lpt_dev_desc }, |
168 | { "INT33C1", (unsigned long)&lpt_dev_desc }, | 178 | { "INT33C1", (unsigned long)&lpt_dev_desc }, |
169 | { "INT33C2", (unsigned long)&lpt_dev_desc }, | 179 | { "INT33C2", (unsigned long)&lpt_i2c_dev_desc }, |
170 | { "INT33C3", (unsigned long)&lpt_dev_desc }, | 180 | { "INT33C3", (unsigned long)&lpt_i2c_dev_desc }, |
171 | { "INT33C4", (unsigned long)&lpt_uart_dev_desc }, | 181 | { "INT33C4", (unsigned long)&lpt_uart_dev_desc }, |
172 | { "INT33C5", (unsigned long)&lpt_uart_dev_desc }, | 182 | { "INT33C5", (unsigned long)&lpt_uart_dev_desc }, |
173 | { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, | 183 | { "INT33C6", (unsigned long)&lpt_sdio_dev_desc }, |
@@ -183,8 +193,8 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { | |||
183 | 193 | ||
184 | { "INT3430", (unsigned long)&lpt_dev_desc }, | 194 | { "INT3430", (unsigned long)&lpt_dev_desc }, |
185 | { "INT3431", (unsigned long)&lpt_dev_desc }, | 195 | { "INT3431", (unsigned long)&lpt_dev_desc }, |
186 | { "INT3432", (unsigned long)&lpt_dev_desc }, | 196 | { "INT3432", (unsigned long)&lpt_i2c_dev_desc }, |
187 | { "INT3433", (unsigned long)&lpt_dev_desc }, | 197 | { "INT3433", (unsigned long)&lpt_i2c_dev_desc }, |
188 | { "INT3434", (unsigned long)&lpt_uart_dev_desc }, | 198 | { "INT3434", (unsigned long)&lpt_uart_dev_desc }, |
189 | { "INT3435", (unsigned long)&lpt_uart_dev_desc }, | 199 | { "INT3435", (unsigned long)&lpt_uart_dev_desc }, |
190 | { "INT3436", (unsigned long)&lpt_sdio_dev_desc }, | 200 | { "INT3436", (unsigned long)&lpt_sdio_dev_desc }, |
@@ -212,9 +222,11 @@ static int register_device_clock(struct acpi_device *adev, | |||
212 | { | 222 | { |
213 | const struct lpss_device_desc *dev_desc = pdata->dev_desc; | 223 | const struct lpss_device_desc *dev_desc = pdata->dev_desc; |
214 | struct lpss_shared_clock *shared_clock = dev_desc->shared_clock; | 224 | struct lpss_shared_clock *shared_clock = dev_desc->shared_clock; |
225 | const char *devname = dev_name(&adev->dev); | ||
215 | struct clk *clk = ERR_PTR(-ENODEV); | 226 | struct clk *clk = ERR_PTR(-ENODEV); |
216 | struct lpss_clk_data *clk_data; | 227 | struct lpss_clk_data *clk_data; |
217 | const char *parent; | 228 | const char *parent, *clk_name; |
229 | void __iomem *prv_base; | ||
218 | 230 | ||
219 | if (!lpss_clk_dev) | 231 | if (!lpss_clk_dev) |
220 | lpt_register_clock_device(); | 232 | lpt_register_clock_device(); |
@@ -225,7 +237,7 @@ static int register_device_clock(struct acpi_device *adev, | |||
225 | 237 | ||
226 | if (dev_desc->clkdev_name) { | 238 | if (dev_desc->clkdev_name) { |
227 | clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name, | 239 | clk_register_clkdev(clk_data->clk, dev_desc->clkdev_name, |
228 | dev_name(&adev->dev)); | 240 | devname); |
229 | return 0; | 241 | return 0; |
230 | } | 242 | } |
231 | 243 | ||
@@ -234,6 +246,7 @@ static int register_device_clock(struct acpi_device *adev, | |||
234 | return -ENODATA; | 246 | return -ENODATA; |
235 | 247 | ||
236 | parent = clk_data->name; | 248 | parent = clk_data->name; |
249 | prv_base = pdata->mmio_base + dev_desc->prv_offset; | ||
237 | 250 | ||
238 | if (shared_clock) { | 251 | if (shared_clock) { |
239 | clk = shared_clock->clk; | 252 | clk = shared_clock->clk; |
@@ -247,16 +260,41 @@ static int register_device_clock(struct acpi_device *adev, | |||
247 | } | 260 | } |
248 | 261 | ||
249 | if (dev_desc->clk_gate) { | 262 | if (dev_desc->clk_gate) { |
250 | clk = clk_register_gate(NULL, dev_name(&adev->dev), parent, 0, | 263 | clk = clk_register_gate(NULL, devname, parent, 0, |
251 | pdata->mmio_base + dev_desc->prv_offset, | 264 | prv_base, 0, 0, NULL); |
252 | 0, 0, NULL); | 265 | parent = devname; |
253 | pdata->clk = clk; | 266 | } |
267 | |||
268 | if (dev_desc->clk_divider) { | ||
269 | /* Prevent division by zero */ | ||
270 | if (!readl(prv_base)) | ||
271 | writel(LPSS_CLK_DIVIDER_DEF_MASK, prv_base); | ||
272 | |||
273 | clk_name = kasprintf(GFP_KERNEL, "%s-div", devname); | ||
274 | if (!clk_name) | ||
275 | return -ENOMEM; | ||
276 | clk = clk_register_fractional_divider(NULL, clk_name, parent, | ||
277 | 0, prv_base, | ||
278 | 1, 15, 16, 15, 0, NULL); | ||
279 | parent = clk_name; | ||
280 | |||
281 | clk_name = kasprintf(GFP_KERNEL, "%s-update", devname); | ||
282 | if (!clk_name) { | ||
283 | kfree(parent); | ||
284 | return -ENOMEM; | ||
285 | } | ||
286 | clk = clk_register_gate(NULL, clk_name, parent, | ||
287 | CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, | ||
288 | prv_base, 31, 0, NULL); | ||
289 | kfree(parent); | ||
290 | kfree(clk_name); | ||
254 | } | 291 | } |
255 | 292 | ||
256 | if (IS_ERR(clk)) | 293 | if (IS_ERR(clk)) |
257 | return PTR_ERR(clk); | 294 | return PTR_ERR(clk); |
258 | 295 | ||
259 | clk_register_clkdev(clk, NULL, dev_name(&adev->dev)); | 296 | pdata->clk = clk; |
297 | clk_register_clkdev(clk, NULL, devname); | ||
260 | return 0; | 298 | return 0; |
261 | } | 299 | } |
262 | 300 | ||
@@ -454,6 +492,126 @@ static void acpi_lpss_set_ltr(struct device *dev, s32 val) | |||
454 | } | 492 | } |
455 | } | 493 | } |
456 | 494 | ||
495 | #ifdef CONFIG_PM | ||
496 | /** | ||
497 | * acpi_lpss_save_ctx() - Save the private registers of LPSS device | ||
498 | * @dev: LPSS device | ||
499 | * | ||
500 | * Most LPSS devices have private registers which may loose their context when | ||
501 | * the device is powered down. acpi_lpss_save_ctx() saves those registers into | ||
502 | * prv_reg_ctx array. | ||
503 | */ | ||
504 | static void acpi_lpss_save_ctx(struct device *dev) | ||
505 | { | ||
506 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
507 | unsigned int i; | ||
508 | |||
509 | for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { | ||
510 | unsigned long offset = i * sizeof(u32); | ||
511 | |||
512 | pdata->prv_reg_ctx[i] = __lpss_reg_read(pdata, offset); | ||
513 | dev_dbg(dev, "saving 0x%08x from LPSS reg at offset 0x%02lx\n", | ||
514 | pdata->prv_reg_ctx[i], offset); | ||
515 | } | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * acpi_lpss_restore_ctx() - Restore the private registers of LPSS device | ||
520 | * @dev: LPSS device | ||
521 | * | ||
522 | * Restores the registers that were previously stored with acpi_lpss_save_ctx(). | ||
523 | */ | ||
524 | static void acpi_lpss_restore_ctx(struct device *dev) | ||
525 | { | ||
526 | struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev)); | ||
527 | unsigned int i; | ||
528 | |||
529 | /* | ||
530 | * The following delay is needed or the subsequent write operations may | ||
531 | * fail. The LPSS devices are actually PCI devices and the PCI spec | ||
532 | * expects 10ms delay before the device can be accessed after D3 to D0 | ||
533 | * transition. | ||
534 | */ | ||
535 | msleep(10); | ||
536 | |||
537 | for (i = 0; i < LPSS_PRV_REG_COUNT; i++) { | ||
538 | unsigned long offset = i * sizeof(u32); | ||
539 | |||
540 | __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset); | ||
541 | dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n", | ||
542 | pdata->prv_reg_ctx[i], offset); | ||
543 | } | ||
544 | } | ||
545 | |||
546 | #ifdef CONFIG_PM_SLEEP | ||
547 | static int acpi_lpss_suspend_late(struct device *dev) | ||
548 | { | ||
549 | int ret = pm_generic_suspend_late(dev); | ||
550 | |||
551 | if (ret) | ||
552 | return ret; | ||
553 | |||
554 | acpi_lpss_save_ctx(dev); | ||
555 | return acpi_dev_suspend_late(dev); | ||
556 | } | ||
557 | |||
558 | static int acpi_lpss_restore_early(struct device *dev) | ||
559 | { | ||
560 | int ret = acpi_dev_resume_early(dev); | ||
561 | |||
562 | if (ret) | ||
563 | return ret; | ||
564 | |||
565 | acpi_lpss_restore_ctx(dev); | ||
566 | return pm_generic_resume_early(dev); | ||
567 | } | ||
568 | #endif /* CONFIG_PM_SLEEP */ | ||
569 | |||
570 | #ifdef CONFIG_PM_RUNTIME | ||
571 | static int acpi_lpss_runtime_suspend(struct device *dev) | ||
572 | { | ||
573 | int ret = pm_generic_runtime_suspend(dev); | ||
574 | |||
575 | if (ret) | ||
576 | return ret; | ||
577 | |||
578 | acpi_lpss_save_ctx(dev); | ||
579 | return acpi_dev_runtime_suspend(dev); | ||
580 | } | ||
581 | |||
582 | static int acpi_lpss_runtime_resume(struct device *dev) | ||
583 | { | ||
584 | int ret = acpi_dev_runtime_resume(dev); | ||
585 | |||
586 | if (ret) | ||
587 | return ret; | ||
588 | |||
589 | acpi_lpss_restore_ctx(dev); | ||
590 | return pm_generic_runtime_resume(dev); | ||
591 | } | ||
592 | #endif /* CONFIG_PM_RUNTIME */ | ||
593 | #endif /* CONFIG_PM */ | ||
594 | |||
595 | static struct dev_pm_domain acpi_lpss_pm_domain = { | ||
596 | .ops = { | ||
597 | #ifdef CONFIG_PM_SLEEP | ||
598 | .suspend_late = acpi_lpss_suspend_late, | ||
599 | .restore_early = acpi_lpss_restore_early, | ||
600 | .prepare = acpi_subsys_prepare, | ||
601 | .complete = acpi_subsys_complete, | ||
602 | .suspend = acpi_subsys_suspend, | ||
603 | .resume_early = acpi_subsys_resume_early, | ||
604 | .freeze = acpi_subsys_freeze, | ||
605 | .poweroff = acpi_subsys_suspend, | ||
606 | .poweroff_late = acpi_subsys_suspend_late, | ||
607 | #endif | ||
608 | #ifdef CONFIG_PM_RUNTIME | ||
609 | .runtime_suspend = acpi_lpss_runtime_suspend, | ||
610 | .runtime_resume = acpi_lpss_runtime_resume, | ||
611 | #endif | ||
612 | }, | ||
613 | }; | ||
614 | |||
457 | static int acpi_lpss_platform_notify(struct notifier_block *nb, | 615 | static int acpi_lpss_platform_notify(struct notifier_block *nb, |
458 | unsigned long action, void *data) | 616 | unsigned long action, void *data) |
459 | { | 617 | { |
@@ -461,7 +619,6 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, | |||
461 | struct lpss_private_data *pdata; | 619 | struct lpss_private_data *pdata; |
462 | struct acpi_device *adev; | 620 | struct acpi_device *adev; |
463 | const struct acpi_device_id *id; | 621 | const struct acpi_device_id *id; |
464 | int ret = 0; | ||
465 | 622 | ||
466 | id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev); | 623 | id = acpi_match_device(acpi_lpss_device_ids, &pdev->dev); |
467 | if (!id || !id->driver_data) | 624 | if (!id || !id->driver_data) |
@@ -471,7 +628,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, | |||
471 | return 0; | 628 | return 0; |
472 | 629 | ||
473 | pdata = acpi_driver_data(adev); | 630 | pdata = acpi_driver_data(adev); |
474 | if (!pdata || !pdata->mmio_base || !pdata->dev_desc->ltr_required) | 631 | if (!pdata || !pdata->mmio_base) |
475 | return 0; | 632 | return 0; |
476 | 633 | ||
477 | if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { | 634 | if (pdata->mmio_size < pdata->dev_desc->prv_offset + LPSS_LTR_SIZE) { |
@@ -479,12 +636,27 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, | |||
479 | return 0; | 636 | return 0; |
480 | } | 637 | } |
481 | 638 | ||
482 | if (action == BUS_NOTIFY_ADD_DEVICE) | 639 | switch (action) { |
483 | ret = sysfs_create_group(&pdev->dev.kobj, &lpss_attr_group); | 640 | case BUS_NOTIFY_BOUND_DRIVER: |
484 | else if (action == BUS_NOTIFY_DEL_DEVICE) | 641 | if (pdata->dev_desc->save_ctx) |
485 | sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); | 642 | pdev->dev.pm_domain = &acpi_lpss_pm_domain; |
643 | break; | ||
644 | case BUS_NOTIFY_UNBOUND_DRIVER: | ||
645 | if (pdata->dev_desc->save_ctx) | ||
646 | pdev->dev.pm_domain = NULL; | ||
647 | break; | ||
648 | case BUS_NOTIFY_ADD_DEVICE: | ||
649 | if (pdata->dev_desc->ltr_required) | ||
650 | return sysfs_create_group(&pdev->dev.kobj, | ||
651 | &lpss_attr_group); | ||
652 | case BUS_NOTIFY_DEL_DEVICE: | ||
653 | if (pdata->dev_desc->ltr_required) | ||
654 | sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group); | ||
655 | default: | ||
656 | break; | ||
657 | } | ||
486 | 658 | ||
487 | return ret; | 659 | return 0; |
488 | } | 660 | } |
489 | 661 | ||
490 | static struct notifier_block acpi_lpss_nb = { | 662 | static struct notifier_block acpi_lpss_nb = { |